diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 239 | ||||
-rw-r--r-- | drivers/usb/gadget/Kconfig | 14 | ||||
-rw-r--r-- | drivers/usb/gadget/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/mv_udc.h | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/mv_udc_core.c | 188 | ||||
-rw-r--r-- | drivers/usb/gadget/s3c-hsudc.c | 117 | ||||
-rw-r--r-- | drivers/usb/host/Kconfig | 9 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mv.c | 391 | ||||
-rw-r--r-- | drivers/usb/otg/Kconfig | 12 | ||||
-rw-r--r-- | drivers/usb/otg/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/otg/mv_otg.c | 957 | ||||
-rw-r--r-- | drivers/usb/otg/mv_otg.h | 165 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_host.c | 3 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.c | 3 |
16 files changed, 1847 insertions, 263 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 7367e5cb9831..4c6bedad51fd 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -65,6 +65,22 @@ void dwc3_map_buffer_to_dma(struct dwc3_request *req) | |||
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | 67 | ||
68 | if (req->request.num_sgs) { | ||
69 | int mapped; | ||
70 | |||
71 | mapped = dma_map_sg(dwc->dev, req->request.sg, | ||
72 | req->request.num_sgs, | ||
73 | req->direction ? DMA_TO_DEVICE | ||
74 | : DMA_FROM_DEVICE); | ||
75 | if (mapped < 0) { | ||
76 | dev_err(dwc->dev, "failed to map SGs\n"); | ||
77 | return; | ||
78 | } | ||
79 | |||
80 | req->request.num_mapped_sgs = mapped; | ||
81 | return; | ||
82 | } | ||
83 | |||
68 | if (req->request.dma == DMA_ADDR_INVALID) { | 84 | if (req->request.dma == DMA_ADDR_INVALID) { |
69 | req->request.dma = dma_map_single(dwc->dev, req->request.buf, | 85 | req->request.dma = dma_map_single(dwc->dev, req->request.buf, |
70 | req->request.length, req->direction | 86 | req->request.length, req->direction |
@@ -82,6 +98,17 @@ void dwc3_unmap_buffer_from_dma(struct dwc3_request *req) | |||
82 | return; | 98 | return; |
83 | } | 99 | } |
84 | 100 | ||
101 | if (req->request.num_mapped_sgs) { | ||
102 | req->request.dma = DMA_ADDR_INVALID; | ||
103 | dma_unmap_sg(dwc->dev, req->request.sg, | ||
104 | req->request.num_sgs, | ||
105 | req->direction ? DMA_TO_DEVICE | ||
106 | : DMA_FROM_DEVICE); | ||
107 | |||
108 | req->request.num_mapped_sgs = 0; | ||
109 | return; | ||
110 | } | ||
111 | |||
85 | if (req->mapped) { | 112 | if (req->mapped) { |
86 | dma_unmap_single(dwc->dev, req->request.dma, | 113 | dma_unmap_single(dwc->dev, req->request.dma, |
87 | req->request.length, req->direction | 114 | req->request.length, req->direction |
@@ -97,7 +124,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | |||
97 | struct dwc3 *dwc = dep->dwc; | 124 | struct dwc3 *dwc = dep->dwc; |
98 | 125 | ||
99 | if (req->queued) { | 126 | if (req->queued) { |
100 | dep->busy_slot++; | 127 | if (req->request.num_mapped_sgs) |
128 | dep->busy_slot += req->request.num_mapped_sgs; | ||
129 | else | ||
130 | dep->busy_slot++; | ||
131 | |||
101 | /* | 132 | /* |
102 | * Skip LINK TRB. We can't use req->trb and check for | 133 | * Skip LINK TRB. We can't use req->trb and check for |
103 | * DWC3_TRBCTL_LINK_TRB because it points the TRB we just | 134 | * DWC3_TRBCTL_LINK_TRB because it points the TRB we just |
@@ -108,6 +139,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | |||
108 | dep->busy_slot++; | 139 | dep->busy_slot++; |
109 | } | 140 | } |
110 | list_del(&req->list); | 141 | list_del(&req->list); |
142 | req->trb = NULL; | ||
111 | 143 | ||
112 | if (req->request.status == -EINPROGRESS) | 144 | if (req->request.status == -EINPROGRESS) |
113 | req->request.status = status; | 145 | req->request.status = status; |
@@ -544,6 +576,85 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, | |||
544 | kfree(req); | 576 | kfree(req); |
545 | } | 577 | } |
546 | 578 | ||
579 | /** | ||
580 | * dwc3_prepare_one_trb - setup one TRB from one request | ||
581 | * @dep: endpoint for which this request is prepared | ||
582 | * @req: dwc3_request pointer | ||
583 | */ | ||
584 | static void dwc3_prepare_one_trb(struct dwc3_ep *dep, | ||
585 | struct dwc3_request *req, dma_addr_t dma, | ||
586 | unsigned length, unsigned last, unsigned chain) | ||
587 | { | ||
588 | struct dwc3 *dwc = dep->dwc; | ||
589 | struct dwc3_trb_hw *trb_hw; | ||
590 | struct dwc3_trb trb; | ||
591 | |||
592 | unsigned int cur_slot; | ||
593 | |||
594 | dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n", | ||
595 | dep->name, req, (unsigned long long) dma, | ||
596 | length, last ? " last" : "", | ||
597 | chain ? " chain" : ""); | ||
598 | |||
599 | trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; | ||
600 | cur_slot = dep->free_slot; | ||
601 | dep->free_slot++; | ||
602 | |||
603 | /* Skip the LINK-TRB on ISOC */ | ||
604 | if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | ||
605 | usb_endpoint_xfer_isoc(dep->desc)) | ||
606 | return; | ||
607 | |||
608 | memset(&trb, 0, sizeof(trb)); | ||
609 | if (!req->trb) { | ||
610 | dwc3_gadget_move_request_queued(req); | ||
611 | req->trb = trb_hw; | ||
612 | req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); | ||
613 | } | ||
614 | |||
615 | if (usb_endpoint_xfer_isoc(dep->desc)) { | ||
616 | trb.isp_imi = true; | ||
617 | trb.csp = true; | ||
618 | } else { | ||
619 | trb.chn = chain; | ||
620 | trb.lst = last; | ||
621 | } | ||
622 | |||
623 | if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | ||
624 | trb.sid_sofn = req->request.stream_id; | ||
625 | |||
626 | switch (usb_endpoint_type(dep->desc)) { | ||
627 | case USB_ENDPOINT_XFER_CONTROL: | ||
628 | trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | ||
629 | break; | ||
630 | |||
631 | case USB_ENDPOINT_XFER_ISOC: | ||
632 | trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; | ||
633 | |||
634 | /* IOC every DWC3_TRB_NUM / 4 so we can refill */ | ||
635 | if (!(cur_slot % (DWC3_TRB_NUM / 4))) | ||
636 | trb.ioc = last; | ||
637 | break; | ||
638 | |||
639 | case USB_ENDPOINT_XFER_BULK: | ||
640 | case USB_ENDPOINT_XFER_INT: | ||
641 | trb.trbctl = DWC3_TRBCTL_NORMAL; | ||
642 | break; | ||
643 | default: | ||
644 | /* | ||
645 | * This is only possible with faulty memory because we | ||
646 | * checked it already :) | ||
647 | */ | ||
648 | BUG(); | ||
649 | } | ||
650 | |||
651 | trb.length = length; | ||
652 | trb.bplh = dma; | ||
653 | trb.hwo = true; | ||
654 | |||
655 | dwc3_trb_to_hw(&trb, trb_hw); | ||
656 | } | ||
657 | |||
547 | /* | 658 | /* |
548 | * dwc3_prepare_trbs - setup TRBs from requests | 659 | * dwc3_prepare_trbs - setup TRBs from requests |
549 | * @dep: endpoint for which requests are being prepared | 660 | * @dep: endpoint for which requests are being prepared |
@@ -553,18 +664,17 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, | |||
553 | * transfers. The functions returns once there are not more TRBs available or | 664 | * transfers. The functions returns once there are not more TRBs available or |
554 | * it run out of requests. | 665 | * it run out of requests. |
555 | */ | 666 | */ |
556 | static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | 667 | static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) |
557 | bool starting) | ||
558 | { | 668 | { |
559 | struct dwc3_request *req, *n, *ret = NULL; | 669 | struct dwc3_request *req, *n; |
560 | struct dwc3_trb_hw *trb_hw; | ||
561 | struct dwc3_trb trb; | ||
562 | u32 trbs_left; | 670 | u32 trbs_left; |
671 | unsigned int last_one = 0; | ||
563 | 672 | ||
564 | BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); | 673 | BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); |
565 | 674 | ||
566 | /* the first request must not be queued */ | 675 | /* the first request must not be queued */ |
567 | trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; | 676 | trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; |
677 | |||
568 | /* | 678 | /* |
569 | * if busy & slot are equal than it is either full or empty. If we are | 679 | * if busy & slot are equal than it is either full or empty. If we are |
570 | * starting to proceed requests then we are empty. Otherwise we ar | 680 | * starting to proceed requests then we are empty. Otherwise we ar |
@@ -572,7 +682,7 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | |||
572 | */ | 682 | */ |
573 | if (!trbs_left) { | 683 | if (!trbs_left) { |
574 | if (!starting) | 684 | if (!starting) |
575 | return NULL; | 685 | return; |
576 | trbs_left = DWC3_TRB_NUM; | 686 | trbs_left = DWC3_TRB_NUM; |
577 | /* | 687 | /* |
578 | * In case we start from scratch, we queue the ISOC requests | 688 | * In case we start from scratch, we queue the ISOC requests |
@@ -596,94 +706,62 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | |||
596 | 706 | ||
597 | /* The last TRB is a link TRB, not used for xfer */ | 707 | /* The last TRB is a link TRB, not used for xfer */ |
598 | if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc)) | 708 | if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc)) |
599 | return NULL; | 709 | return; |
600 | 710 | ||
601 | list_for_each_entry_safe(req, n, &dep->request_list, list) { | 711 | list_for_each_entry_safe(req, n, &dep->request_list, list) { |
602 | unsigned int last_one = 0; | 712 | unsigned length; |
603 | unsigned int cur_slot; | 713 | dma_addr_t dma; |
604 | 714 | ||
605 | trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; | 715 | if (req->request.num_mapped_sgs > 0) { |
606 | cur_slot = dep->free_slot; | 716 | struct usb_request *request = &req->request; |
607 | dep->free_slot++; | 717 | struct scatterlist *sg = request->sg; |
718 | struct scatterlist *s; | ||
719 | int i; | ||
608 | 720 | ||
609 | /* Skip the LINK-TRB on ISOC */ | 721 | for_each_sg(sg, s, request->num_mapped_sgs, i) { |
610 | if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | 722 | unsigned chain = true; |
611 | usb_endpoint_xfer_isoc(dep->desc)) | ||
612 | continue; | ||
613 | 723 | ||
614 | dwc3_gadget_move_request_queued(req); | 724 | length = sg_dma_len(s); |
615 | memset(&trb, 0, sizeof(trb)); | 725 | dma = sg_dma_address(s); |
616 | trbs_left--; | ||
617 | 726 | ||
618 | /* Is our TRB pool empty? */ | 727 | if (i == (request->num_mapped_sgs - 1) |
619 | if (!trbs_left) | 728 | || sg_is_last(s)) { |
620 | last_one = 1; | 729 | last_one = true; |
621 | /* Is this the last request? */ | 730 | chain = false; |
622 | if (list_empty(&dep->request_list)) | 731 | } |
623 | last_one = 1; | ||
624 | 732 | ||
625 | /* | 733 | trbs_left--; |
626 | * FIXME we shouldn't need to set LST bit always but we are | 734 | if (!trbs_left) |
627 | * facing some weird problem with the Hardware where it doesn't | 735 | last_one = true; |
628 | * complete even though it has been previously started. | ||
629 | * | ||
630 | * While we're debugging the problem, as a workaround to | ||
631 | * multiple TRBs handling, use only one TRB at a time. | ||
632 | */ | ||
633 | last_one = 1; | ||
634 | 736 | ||
635 | req->trb = trb_hw; | 737 | if (last_one) |
636 | if (!ret) | 738 | chain = false; |
637 | ret = req; | ||
638 | 739 | ||
639 | trb.bplh = req->request.dma; | 740 | dwc3_prepare_one_trb(dep, req, dma, length, |
741 | last_one, chain); | ||
640 | 742 | ||
641 | if (usb_endpoint_xfer_isoc(dep->desc)) { | 743 | if (last_one) |
642 | trb.isp_imi = true; | 744 | break; |
643 | trb.csp = true; | 745 | } |
644 | } else { | 746 | } else { |
645 | trb.lst = last_one; | 747 | dma = req->request.dma; |
646 | } | 748 | length = req->request.length; |
749 | trbs_left--; | ||
647 | 750 | ||
648 | if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | 751 | if (!trbs_left) |
649 | trb.sid_sofn = req->request.stream_id; | 752 | last_one = 1; |
650 | 753 | ||
651 | switch (usb_endpoint_type(dep->desc)) { | 754 | /* Is this the last request? */ |
652 | case USB_ENDPOINT_XFER_CONTROL: | 755 | if (list_is_last(&req->list, &dep->request_list)) |
653 | trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | 756 | last_one = 1; |
654 | break; | ||
655 | 757 | ||
656 | case USB_ENDPOINT_XFER_ISOC: | 758 | dwc3_prepare_one_trb(dep, req, dma, length, |
657 | trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; | 759 | last_one, false); |
658 | 760 | ||
659 | /* IOC every DWC3_TRB_NUM / 4 so we can refill */ | 761 | if (last_one) |
660 | if (!(cur_slot % (DWC3_TRB_NUM / 4))) | 762 | break; |
661 | trb.ioc = last_one; | ||
662 | break; | ||
663 | |||
664 | case USB_ENDPOINT_XFER_BULK: | ||
665 | case USB_ENDPOINT_XFER_INT: | ||
666 | trb.trbctl = DWC3_TRBCTL_NORMAL; | ||
667 | break; | ||
668 | default: | ||
669 | /* | ||
670 | * This is only possible with faulty memory because we | ||
671 | * checked it already :) | ||
672 | */ | ||
673 | BUG(); | ||
674 | } | 763 | } |
675 | |||
676 | trb.length = req->request.length; | ||
677 | trb.hwo = true; | ||
678 | |||
679 | dwc3_trb_to_hw(&trb, trb_hw); | ||
680 | req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); | ||
681 | |||
682 | if (last_one) | ||
683 | break; | ||
684 | } | 764 | } |
685 | |||
686 | return ret; | ||
687 | } | 765 | } |
688 | 766 | ||
689 | static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, | 767 | static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, |
@@ -712,11 +790,13 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, | |||
712 | /* req points to the first request which will be sent */ | 790 | /* req points to the first request which will be sent */ |
713 | req = next_request(&dep->req_queued); | 791 | req = next_request(&dep->req_queued); |
714 | } else { | 792 | } else { |
793 | dwc3_prepare_trbs(dep, start_new); | ||
794 | |||
715 | /* | 795 | /* |
716 | * req points to the first request where HWO changed | 796 | * req points to the first request where HWO changed |
717 | * from 0 to 1 | 797 | * from 0 to 1 |
718 | */ | 798 | */ |
719 | req = dwc3_prepare_trbs(dep, start_new); | 799 | req = next_request(&dep->req_queued); |
720 | } | 800 | } |
721 | if (!req) { | 801 | if (!req) { |
722 | dep->flags |= DWC3_EP_PENDING_REQUEST; | 802 | dep->flags |= DWC3_EP_PENDING_REQUEST; |
@@ -2093,6 +2173,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) | |||
2093 | dwc->gadget.max_speed = USB_SPEED_SUPER; | 2173 | dwc->gadget.max_speed = USB_SPEED_SUPER; |
2094 | dwc->gadget.speed = USB_SPEED_UNKNOWN; | 2174 | dwc->gadget.speed = USB_SPEED_UNKNOWN; |
2095 | dwc->gadget.dev.parent = dwc->dev; | 2175 | dwc->gadget.dev.parent = dwc->dev; |
2176 | dwc->gadget.sg_supported = true; | ||
2096 | 2177 | ||
2097 | dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); | 2178 | dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); |
2098 | 2179 | ||
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 93f6c808f570..1fe87aafa087 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -125,7 +125,6 @@ config USB_GADGET_STORAGE_NUM_BUFFERS | |||
125 | # | 125 | # |
126 | choice | 126 | choice |
127 | prompt "USB Peripheral Controller" | 127 | prompt "USB Peripheral Controller" |
128 | depends on USB_GADGET | ||
129 | help | 128 | help |
130 | A USB device uses a controller to talk to its host. | 129 | A USB device uses a controller to talk to its host. |
131 | Systems should have only one such upstream link. | 130 | Systems should have only one such upstream link. |
@@ -310,13 +309,13 @@ config USB_S3C_HSUDC | |||
310 | 309 | ||
311 | This driver has been tested on S3C2416 and S3C2450 processors. | 310 | This driver has been tested on S3C2416 and S3C2450 processors. |
312 | 311 | ||
313 | config USB_PXA_U2O | 312 | config USB_MV_UDC |
314 | tristate "PXA9xx Processor USB2.0 controller" | 313 | tristate "Marvell USB2.0 Device Controller" |
315 | depends on ARCH_MMP | ||
316 | select USB_GADGET_DUALSPEED | 314 | select USB_GADGET_DUALSPEED |
317 | help | 315 | help |
318 | PXA9xx Processor series include a high speed USB2.0 device | 316 | Marvell Socs (including PXA and MMP series) include a high speed |
319 | controller, which support high speed and full speed USB peripheral. | 317 | USB2.0 OTG controller, which can be configured as high speed or |
318 | full speed USB peripheral. | ||
320 | 319 | ||
321 | # | 320 | # |
322 | # Controllers available in both integrated and discrete versions | 321 | # Controllers available in both integrated and discrete versions |
@@ -532,12 +531,10 @@ endchoice | |||
532 | # Selected by UDC drivers that support high-speed operation. | 531 | # Selected by UDC drivers that support high-speed operation. |
533 | config USB_GADGET_DUALSPEED | 532 | config USB_GADGET_DUALSPEED |
534 | bool | 533 | bool |
535 | depends on USB_GADGET | ||
536 | 534 | ||
537 | # Selected by UDC drivers that support super-speed opperation | 535 | # Selected by UDC drivers that support super-speed opperation |
538 | config USB_GADGET_SUPERSPEED | 536 | config USB_GADGET_SUPERSPEED |
539 | bool | 537 | bool |
540 | depends on USB_GADGET | ||
541 | depends on USB_GADGET_DUALSPEED | 538 | depends on USB_GADGET_DUALSPEED |
542 | 539 | ||
543 | # | 540 | # |
@@ -545,7 +542,6 @@ config USB_GADGET_SUPERSPEED | |||
545 | # | 542 | # |
546 | choice | 543 | choice |
547 | tristate "USB Gadget Drivers" | 544 | tristate "USB Gadget Drivers" |
548 | depends on USB_GADGET | ||
549 | default USB_ETH | 545 | default USB_ETH |
550 | help | 546 | help |
551 | A Linux "Gadget Driver" talks to the USB Peripheral Controller | 547 | A Linux "Gadget Driver" talks to the USB Peripheral Controller |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index b54ac6190890..b7f6eefc3927 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -27,7 +27,7 @@ obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o | |||
27 | obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o | 27 | obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o |
28 | obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o | 28 | obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o |
29 | obj-$(CONFIG_USB_EG20T) += pch_udc.o | 29 | obj-$(CONFIG_USB_EG20T) += pch_udc.o |
30 | obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o | 30 | obj-$(CONFIG_USB_MV_UDC) += mv_udc.o |
31 | mv_udc-y := mv_udc_core.o | 31 | mv_udc-y := mv_udc_core.o |
32 | obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o | 32 | obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o |
33 | obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o | 33 | obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o |
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index 3d8404484613..34aadfae723d 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h | |||
@@ -180,7 +180,7 @@ struct mv_udc { | |||
180 | 180 | ||
181 | struct mv_cap_regs __iomem *cap_regs; | 181 | struct mv_cap_regs __iomem *cap_regs; |
182 | struct mv_op_regs __iomem *op_regs; | 182 | struct mv_op_regs __iomem *op_regs; |
183 | unsigned int phy_regs; | 183 | void __iomem *phy_regs; |
184 | unsigned int max_eps; | 184 | unsigned int max_eps; |
185 | struct mv_dqh *ep_dqh; | 185 | struct mv_dqh *ep_dqh; |
186 | size_t ep_dqh_size; | 186 | size_t ep_dqh_size; |
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 142a67f06638..f97e737d26f7 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c | |||
@@ -276,11 +276,12 @@ static void done(struct mv_ep *ep, struct mv_req *req, int status) | |||
276 | 276 | ||
277 | static int queue_dtd(struct mv_ep *ep, struct mv_req *req) | 277 | static int queue_dtd(struct mv_ep *ep, struct mv_req *req) |
278 | { | 278 | { |
279 | u32 tmp, epstatus, bit_pos, direction; | ||
280 | struct mv_udc *udc; | 279 | struct mv_udc *udc; |
281 | struct mv_dqh *dqh; | 280 | struct mv_dqh *dqh; |
281 | u32 bit_pos, direction; | ||
282 | u32 usbcmd, epstatus; | ||
282 | unsigned int loops; | 283 | unsigned int loops; |
283 | int readsafe, retval = 0; | 284 | int retval = 0; |
284 | 285 | ||
285 | udc = ep->udc; | 286 | udc = ep->udc; |
286 | direction = ep_dir(ep); | 287 | direction = ep_dir(ep); |
@@ -293,30 +294,18 @@ static int queue_dtd(struct mv_ep *ep, struct mv_req *req) | |||
293 | lastreq = list_entry(ep->queue.prev, struct mv_req, queue); | 294 | lastreq = list_entry(ep->queue.prev, struct mv_req, queue); |
294 | lastreq->tail->dtd_next = | 295 | lastreq->tail->dtd_next = |
295 | req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK; | 296 | req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK; |
296 | if (readl(&udc->op_regs->epprime) & bit_pos) { | 297 | |
297 | loops = LOOPS(PRIME_TIMEOUT); | 298 | wmb(); |
298 | while (readl(&udc->op_regs->epprime) & bit_pos) { | 299 | |
299 | if (loops == 0) { | 300 | if (readl(&udc->op_regs->epprime) & bit_pos) |
300 | retval = -ETIME; | 301 | goto done; |
301 | goto done; | 302 | |
302 | } | ||
303 | udelay(LOOPS_USEC); | ||
304 | loops--; | ||
305 | } | ||
306 | if (readl(&udc->op_regs->epstatus) & bit_pos) | ||
307 | goto done; | ||
308 | } | ||
309 | readsafe = 0; | ||
310 | loops = LOOPS(READSAFE_TIMEOUT); | 303 | loops = LOOPS(READSAFE_TIMEOUT); |
311 | while (readsafe == 0) { | 304 | while (1) { |
312 | if (loops == 0) { | ||
313 | retval = -ETIME; | ||
314 | goto done; | ||
315 | } | ||
316 | /* start with setting the semaphores */ | 305 | /* start with setting the semaphores */ |
317 | tmp = readl(&udc->op_regs->usbcmd); | 306 | usbcmd = readl(&udc->op_regs->usbcmd); |
318 | tmp |= USBCMD_ATDTW_TRIPWIRE_SET; | 307 | usbcmd |= USBCMD_ATDTW_TRIPWIRE_SET; |
319 | writel(tmp, &udc->op_regs->usbcmd); | 308 | writel(usbcmd, &udc->op_regs->usbcmd); |
320 | 309 | ||
321 | /* read the endpoint status */ | 310 | /* read the endpoint status */ |
322 | epstatus = readl(&udc->op_regs->epstatus) & bit_pos; | 311 | epstatus = readl(&udc->op_regs->epstatus) & bit_pos; |
@@ -329,98 +318,46 @@ static int queue_dtd(struct mv_ep *ep, struct mv_req *req) | |||
329 | * primed. | 318 | * primed. |
330 | */ | 319 | */ |
331 | if (readl(&udc->op_regs->usbcmd) | 320 | if (readl(&udc->op_regs->usbcmd) |
332 | & USBCMD_ATDTW_TRIPWIRE_SET) { | 321 | & USBCMD_ATDTW_TRIPWIRE_SET) |
333 | readsafe = 1; | 322 | break; |
334 | } | 323 | |
335 | loops--; | 324 | loops--; |
325 | if (loops == 0) { | ||
326 | dev_err(&udc->dev->dev, | ||
327 | "Timeout for ATDTW_TRIPWIRE...\n"); | ||
328 | retval = -ETIME; | ||
329 | goto done; | ||
330 | } | ||
336 | udelay(LOOPS_USEC); | 331 | udelay(LOOPS_USEC); |
337 | } | 332 | } |
338 | 333 | ||
339 | /* Clear the semaphore */ | 334 | /* Clear the semaphore */ |
340 | tmp = readl(&udc->op_regs->usbcmd); | 335 | usbcmd = readl(&udc->op_regs->usbcmd); |
341 | tmp &= USBCMD_ATDTW_TRIPWIRE_CLEAR; | 336 | usbcmd &= USBCMD_ATDTW_TRIPWIRE_CLEAR; |
342 | writel(tmp, &udc->op_regs->usbcmd); | 337 | writel(usbcmd, &udc->op_regs->usbcmd); |
343 | |||
344 | /* If endpoint is not active, we activate it now. */ | ||
345 | if (!epstatus) { | ||
346 | if (direction == EP_DIR_IN) { | ||
347 | struct mv_dtd *curr_dtd = dma_to_virt( | ||
348 | &udc->dev->dev, dqh->curr_dtd_ptr); | ||
349 | |||
350 | loops = LOOPS(DTD_TIMEOUT); | ||
351 | while (curr_dtd->size_ioc_sts | ||
352 | & DTD_STATUS_ACTIVE) { | ||
353 | if (loops == 0) { | ||
354 | retval = -ETIME; | ||
355 | goto done; | ||
356 | } | ||
357 | loops--; | ||
358 | udelay(LOOPS_USEC); | ||
359 | } | ||
360 | } | ||
361 | /* No other transfers on the queue */ | ||
362 | 338 | ||
363 | /* Write dQH next pointer and terminate bit to 0 */ | 339 | if (epstatus) |
364 | dqh->next_dtd_ptr = req->head->td_dma | 340 | goto done; |
365 | & EP_QUEUE_HEAD_NEXT_POINTER_MASK; | 341 | } |
366 | dqh->size_ioc_int_sts = 0; | ||
367 | 342 | ||
368 | /* | 343 | /* Write dQH next pointer and terminate bit to 0 */ |
369 | * Ensure that updates to the QH will | 344 | dqh->next_dtd_ptr = req->head->td_dma |
370 | * occur before priming. | 345 | & EP_QUEUE_HEAD_NEXT_POINTER_MASK; |
371 | */ | ||
372 | wmb(); | ||
373 | 346 | ||
374 | /* Prime the Endpoint */ | 347 | /* clear active and halt bit, in case set from a previous error */ |
375 | writel(bit_pos, &udc->op_regs->epprime); | 348 | dqh->size_ioc_int_sts &= ~(DTD_STATUS_ACTIVE | DTD_STATUS_HALTED); |
376 | } | ||
377 | } else { | ||
378 | /* Write dQH next pointer and terminate bit to 0 */ | ||
379 | dqh->next_dtd_ptr = req->head->td_dma | ||
380 | & EP_QUEUE_HEAD_NEXT_POINTER_MASK; | ||
381 | dqh->size_ioc_int_sts = 0; | ||
382 | 349 | ||
383 | /* Ensure that updates to the QH will occur before priming. */ | 350 | /* Ensure that updates to the QH will occure before priming. */ |
384 | wmb(); | 351 | wmb(); |
385 | 352 | ||
386 | /* Prime the Endpoint */ | 353 | /* Prime the Endpoint */ |
387 | writel(bit_pos, &udc->op_regs->epprime); | 354 | writel(bit_pos, &udc->op_regs->epprime); |
388 | 355 | ||
389 | if (direction == EP_DIR_IN) { | ||
390 | /* FIXME add status check after prime the IN ep */ | ||
391 | int prime_again; | ||
392 | u32 curr_dtd_ptr = dqh->curr_dtd_ptr; | ||
393 | |||
394 | loops = LOOPS(DTD_TIMEOUT); | ||
395 | prime_again = 0; | ||
396 | while ((curr_dtd_ptr != req->head->td_dma)) { | ||
397 | curr_dtd_ptr = dqh->curr_dtd_ptr; | ||
398 | if (loops == 0) { | ||
399 | dev_err(&udc->dev->dev, | ||
400 | "failed to prime %s\n", | ||
401 | ep->name); | ||
402 | retval = -ETIME; | ||
403 | goto done; | ||
404 | } | ||
405 | loops--; | ||
406 | udelay(LOOPS_USEC); | ||
407 | |||
408 | if (loops == (LOOPS(DTD_TIMEOUT) >> 2)) { | ||
409 | if (prime_again) | ||
410 | goto done; | ||
411 | dev_info(&udc->dev->dev, | ||
412 | "prime again\n"); | ||
413 | writel(bit_pos, | ||
414 | &udc->op_regs->epprime); | ||
415 | prime_again = 1; | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | done: | 356 | done: |
421 | return retval; | 357 | return retval; |
422 | } | 358 | } |
423 | 359 | ||
360 | |||
424 | static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length, | 361 | static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length, |
425 | dma_addr_t *dma, int *is_last) | 362 | dma_addr_t *dma, int *is_last) |
426 | { | 363 | { |
@@ -841,6 +778,27 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) | |||
841 | return 0; | 778 | return 0; |
842 | } | 779 | } |
843 | 780 | ||
781 | static void mv_prime_ep(struct mv_ep *ep, struct mv_req *req) | ||
782 | { | ||
783 | struct mv_dqh *dqh = ep->dqh; | ||
784 | u32 bit_pos; | ||
785 | |||
786 | /* Write dQH next pointer and terminate bit to 0 */ | ||
787 | dqh->next_dtd_ptr = req->head->td_dma | ||
788 | & EP_QUEUE_HEAD_NEXT_POINTER_MASK; | ||
789 | |||
790 | /* clear active and halt bit, in case set from a previous error */ | ||
791 | dqh->size_ioc_int_sts &= ~(DTD_STATUS_ACTIVE | DTD_STATUS_HALTED); | ||
792 | |||
793 | /* Ensure that updates to the QH will occure before priming. */ | ||
794 | wmb(); | ||
795 | |||
796 | bit_pos = 1 << (((ep_dir(ep) == EP_DIR_OUT) ? 0 : 16) + ep->ep_num); | ||
797 | |||
798 | /* Prime the Endpoint */ | ||
799 | writel(bit_pos, &ep->udc->op_regs->epprime); | ||
800 | } | ||
801 | |||
844 | /* dequeues (cancels, unlinks) an I/O request from an endpoint */ | 802 | /* dequeues (cancels, unlinks) an I/O request from an endpoint */ |
845 | static int mv_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) | 803 | static int mv_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) |
846 | { | 804 | { |
@@ -883,15 +841,13 @@ static int mv_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) | |||
883 | 841 | ||
884 | /* The request isn't the last request in this ep queue */ | 842 | /* The request isn't the last request in this ep queue */ |
885 | if (req->queue.next != &ep->queue) { | 843 | if (req->queue.next != &ep->queue) { |
886 | struct mv_dqh *qh; | ||
887 | struct mv_req *next_req; | 844 | struct mv_req *next_req; |
888 | 845 | ||
889 | qh = ep->dqh; | 846 | next_req = list_entry(req->queue.next, |
890 | next_req = list_entry(req->queue.next, struct mv_req, | 847 | struct mv_req, queue); |
891 | queue); | ||
892 | 848 | ||
893 | /* Point the QH to the first TD of next request */ | 849 | /* Point the QH to the first TD of next request */ |
894 | writel((u32) next_req->head, &qh->curr_dtd_ptr); | 850 | mv_prime_ep(ep, next_req); |
895 | } else { | 851 | } else { |
896 | struct mv_dqh *qh; | 852 | struct mv_dqh *qh; |
897 | 853 | ||
@@ -1196,7 +1152,7 @@ static int mv_udc_get_frame(struct usb_gadget *gadget) | |||
1196 | 1152 | ||
1197 | udc = container_of(gadget, struct mv_udc, gadget); | 1153 | udc = container_of(gadget, struct mv_udc, gadget); |
1198 | 1154 | ||
1199 | retval = readl(udc->op_regs->frindex) & USB_FRINDEX_MASKS; | 1155 | retval = readl(&udc->op_regs->frindex) & USB_FRINDEX_MASKS; |
1200 | 1156 | ||
1201 | return retval; | 1157 | return retval; |
1202 | } | 1158 | } |
@@ -2172,11 +2128,9 @@ static int __devexit mv_udc_remove(struct platform_device *dev) | |||
2172 | 2128 | ||
2173 | if (udc->cap_regs) | 2129 | if (udc->cap_regs) |
2174 | iounmap(udc->cap_regs); | 2130 | iounmap(udc->cap_regs); |
2175 | udc->cap_regs = NULL; | ||
2176 | 2131 | ||
2177 | if (udc->phy_regs) | 2132 | if (udc->phy_regs) |
2178 | iounmap((void *)udc->phy_regs); | 2133 | iounmap(udc->phy_regs); |
2179 | udc->phy_regs = 0; | ||
2180 | 2134 | ||
2181 | if (udc->status_req) { | 2135 | if (udc->status_req) { |
2182 | kfree(udc->status_req->req.buf); | 2136 | kfree(udc->status_req->req.buf); |
@@ -2261,8 +2215,8 @@ static int __devinit mv_udc_probe(struct platform_device *dev) | |||
2261 | goto err_iounmap_capreg; | 2215 | goto err_iounmap_capreg; |
2262 | } | 2216 | } |
2263 | 2217 | ||
2264 | udc->phy_regs = (unsigned int)ioremap(r->start, resource_size(r)); | 2218 | udc->phy_regs = ioremap(r->start, resource_size(r)); |
2265 | if (udc->phy_regs == 0) { | 2219 | if (udc->phy_regs == NULL) { |
2266 | dev_err(&dev->dev, "failed to map phy I/O memory\n"); | 2220 | dev_err(&dev->dev, "failed to map phy I/O memory\n"); |
2267 | retval = -EBUSY; | 2221 | retval = -EBUSY; |
2268 | goto err_iounmap_capreg; | 2222 | goto err_iounmap_capreg; |
@@ -2273,7 +2227,8 @@ static int __devinit mv_udc_probe(struct platform_device *dev) | |||
2273 | if (retval) | 2227 | if (retval) |
2274 | goto err_iounmap_phyreg; | 2228 | goto err_iounmap_phyreg; |
2275 | 2229 | ||
2276 | udc->op_regs = (struct mv_op_regs __iomem *)((u32)udc->cap_regs | 2230 | udc->op_regs = |
2231 | (struct mv_op_regs __iomem *)((unsigned long)udc->cap_regs | ||
2277 | + (readl(&udc->cap_regs->caplength_hciversion) | 2232 | + (readl(&udc->cap_regs->caplength_hciversion) |
2278 | & CAPLENGTH_MASK)); | 2233 | & CAPLENGTH_MASK)); |
2279 | udc->max_eps = readl(&udc->cap_regs->dccparams) & DCCPARAMS_DEN_MASK; | 2234 | udc->max_eps = readl(&udc->cap_regs->dccparams) & DCCPARAMS_DEN_MASK; |
@@ -2433,7 +2388,7 @@ err_free_dma: | |||
2433 | err_disable_clock: | 2388 | err_disable_clock: |
2434 | mv_udc_disable_internal(udc); | 2389 | mv_udc_disable_internal(udc); |
2435 | err_iounmap_phyreg: | 2390 | err_iounmap_phyreg: |
2436 | iounmap((void *)udc->phy_regs); | 2391 | iounmap(udc->phy_regs); |
2437 | err_iounmap_capreg: | 2392 | err_iounmap_capreg: |
2438 | iounmap(udc->cap_regs); | 2393 | iounmap(udc->cap_regs); |
2439 | err_put_clk: | 2394 | err_put_clk: |
@@ -2524,7 +2479,7 @@ static struct platform_driver udc_driver = { | |||
2524 | .shutdown = mv_udc_shutdown, | 2479 | .shutdown = mv_udc_shutdown, |
2525 | .driver = { | 2480 | .driver = { |
2526 | .owner = THIS_MODULE, | 2481 | .owner = THIS_MODULE, |
2527 | .name = "pxa-u2o", | 2482 | .name = "mv-udc", |
2528 | #ifdef CONFIG_PM | 2483 | #ifdef CONFIG_PM |
2529 | .pm = &mv_udc_pm_ops, | 2484 | .pm = &mv_udc_pm_ops, |
2530 | #endif | 2485 | #endif |
@@ -2532,9 +2487,8 @@ static struct platform_driver udc_driver = { | |||
2532 | }; | 2487 | }; |
2533 | 2488 | ||
2534 | module_platform_driver(udc_driver); | 2489 | module_platform_driver(udc_driver); |
2535 | 2490 | MODULE_ALIAS("platform:mv-udc"); | |
2536 | MODULE_DESCRIPTION(DRIVER_DESC); | 2491 | MODULE_DESCRIPTION(DRIVER_DESC); |
2537 | MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>"); | 2492 | MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>"); |
2538 | MODULE_VERSION(DRIVER_VERSION); | 2493 | MODULE_VERSION(DRIVER_VERSION); |
2539 | MODULE_LICENSE("GPL"); | 2494 | MODULE_LICENSE("GPL"); |
2540 | MODULE_ALIAS("platform:pxa-u2o"); | ||
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 6f2a0419350d..df8661d266cb 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c | |||
@@ -28,9 +28,10 @@ | |||
28 | #include <linux/usb/gadget.h> | 28 | #include <linux/usb/gadget.h> |
29 | #include <linux/usb/otg.h> | 29 | #include <linux/usb/otg.h> |
30 | #include <linux/prefetch.h> | 30 | #include <linux/prefetch.h> |
31 | #include <linux/platform_data/s3c-hsudc.h> | ||
32 | #include <linux/regulator/consumer.h> | ||
31 | 33 | ||
32 | #include <mach/regs-s3c2443-clock.h> | 34 | #include <mach/regs-s3c2443-clock.h> |
33 | #include <plat/udc.h> | ||
34 | 35 | ||
35 | #define S3C_HSUDC_REG(x) (x) | 36 | #define S3C_HSUDC_REG(x) (x) |
36 | 37 | ||
@@ -87,6 +88,12 @@ | |||
87 | #define DATA_STATE_XMIT (1) | 88 | #define DATA_STATE_XMIT (1) |
88 | #define DATA_STATE_RECV (2) | 89 | #define DATA_STATE_RECV (2) |
89 | 90 | ||
91 | static const char * const s3c_hsudc_supply_names[] = { | ||
92 | "vdda", /* analog phy supply, 3.3V */ | ||
93 | "vddi", /* digital phy supply, 1.2V */ | ||
94 | "vddosc", /* oscillator supply, 1.8V - 3.3V */ | ||
95 | }; | ||
96 | |||
90 | /** | 97 | /** |
91 | * struct s3c_hsudc_ep - Endpoint representation used by driver. | 98 | * struct s3c_hsudc_ep - Endpoint representation used by driver. |
92 | * @ep: USB gadget layer representation of device endpoint. | 99 | * @ep: USB gadget layer representation of device endpoint. |
@@ -139,6 +146,7 @@ struct s3c_hsudc { | |||
139 | struct device *dev; | 146 | struct device *dev; |
140 | struct s3c24xx_hsudc_platdata *pd; | 147 | struct s3c24xx_hsudc_platdata *pd; |
141 | struct otg_transceiver *transceiver; | 148 | struct otg_transceiver *transceiver; |
149 | struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)]; | ||
142 | spinlock_t lock; | 150 | spinlock_t lock; |
143 | void __iomem *regs; | 151 | void __iomem *regs; |
144 | struct resource *mem_rsrc; | 152 | struct resource *mem_rsrc; |
@@ -153,7 +161,6 @@ struct s3c_hsudc { | |||
153 | #define ep_index(_ep) ((_ep)->bEndpointAddress & \ | 161 | #define ep_index(_ep) ((_ep)->bEndpointAddress & \ |
154 | USB_ENDPOINT_NUMBER_MASK) | 162 | USB_ENDPOINT_NUMBER_MASK) |
155 | 163 | ||
156 | static struct s3c_hsudc *the_controller; | ||
157 | static const char driver_name[] = "s3c-udc"; | 164 | static const char driver_name[] = "s3c-udc"; |
158 | static const char ep0name[] = "ep0-control"; | 165 | static const char ep0name[] = "ep0-control"; |
159 | 166 | ||
@@ -282,8 +289,7 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status) | |||
282 | * All the endpoints are stopped and any pending transfer requests if any on | 289 | * All the endpoints are stopped and any pending transfer requests if any on |
283 | * the endpoint are terminated. | 290 | * the endpoint are terminated. |
284 | */ | 291 | */ |
285 | static void s3c_hsudc_stop_activity(struct s3c_hsudc *hsudc, | 292 | static void s3c_hsudc_stop_activity(struct s3c_hsudc *hsudc) |
286 | struct usb_gadget_driver *driver) | ||
287 | { | 293 | { |
288 | struct s3c_hsudc_ep *hsep; | 294 | struct s3c_hsudc_ep *hsep; |
289 | int epnum; | 295 | int epnum; |
@@ -295,10 +301,6 @@ static void s3c_hsudc_stop_activity(struct s3c_hsudc *hsudc, | |||
295 | hsep->stopped = 1; | 301 | hsep->stopped = 1; |
296 | s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN); | 302 | s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN); |
297 | } | 303 | } |
298 | |||
299 | spin_unlock(&hsudc->lock); | ||
300 | driver->disconnect(&hsudc->gadget); | ||
301 | spin_lock(&hsudc->lock); | ||
302 | } | 304 | } |
303 | 305 | ||
304 | /** | 306 | /** |
@@ -1135,16 +1137,15 @@ static irqreturn_t s3c_hsudc_irq(int irq, void *_dev) | |||
1135 | return IRQ_HANDLED; | 1137 | return IRQ_HANDLED; |
1136 | } | 1138 | } |
1137 | 1139 | ||
1138 | static int s3c_hsudc_start(struct usb_gadget_driver *driver, | 1140 | static int s3c_hsudc_start(struct usb_gadget *gadget, |
1139 | int (*bind)(struct usb_gadget *)) | 1141 | struct usb_gadget_driver *driver) |
1140 | { | 1142 | { |
1141 | struct s3c_hsudc *hsudc = the_controller; | 1143 | struct s3c_hsudc *hsudc = to_hsudc(gadget); |
1142 | int ret; | 1144 | int ret; |
1143 | 1145 | ||
1144 | if (!driver | 1146 | if (!driver |
1145 | || driver->max_speed < USB_SPEED_FULL | 1147 | || driver->max_speed < USB_SPEED_FULL |
1146 | || !bind | 1148 | || !driver->setup) |
1147 | || !driver->unbind || !driver->disconnect || !driver->setup) | ||
1148 | return -EINVAL; | 1149 | return -EINVAL; |
1149 | 1150 | ||
1150 | if (!hsudc) | 1151 | if (!hsudc) |
@@ -1155,21 +1156,12 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver, | |||
1155 | 1156 | ||
1156 | hsudc->driver = driver; | 1157 | hsudc->driver = driver; |
1157 | hsudc->gadget.dev.driver = &driver->driver; | 1158 | hsudc->gadget.dev.driver = &driver->driver; |
1158 | hsudc->gadget.speed = USB_SPEED_UNKNOWN; | ||
1159 | ret = device_add(&hsudc->gadget.dev); | ||
1160 | if (ret) { | ||
1161 | dev_err(hsudc->dev, "failed to probe gadget device"); | ||
1162 | return ret; | ||
1163 | } | ||
1164 | |||
1165 | ret = bind(&hsudc->gadget); | ||
1166 | if (ret) { | ||
1167 | dev_err(hsudc->dev, "%s: bind failed\n", hsudc->gadget.name); | ||
1168 | device_del(&hsudc->gadget.dev); | ||
1169 | 1159 | ||
1170 | hsudc->driver = NULL; | 1160 | ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies), |
1171 | hsudc->gadget.dev.driver = NULL; | 1161 | hsudc->supplies); |
1172 | return ret; | 1162 | if (ret != 0) { |
1163 | dev_err(hsudc->dev, "failed to enable supplies: %d\n", ret); | ||
1164 | goto err_supplies; | ||
1173 | } | 1165 | } |
1174 | 1166 | ||
1175 | /* connect to bus through transceiver */ | 1167 | /* connect to bus through transceiver */ |
@@ -1178,13 +1170,7 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver, | |||
1178 | if (ret) { | 1170 | if (ret) { |
1179 | dev_err(hsudc->dev, "%s: can't bind to transceiver\n", | 1171 | dev_err(hsudc->dev, "%s: can't bind to transceiver\n", |
1180 | hsudc->gadget.name); | 1172 | hsudc->gadget.name); |
1181 | driver->unbind(&hsudc->gadget); | 1173 | goto err_otg; |
1182 | |||
1183 | device_del(&hsudc->gadget.dev); | ||
1184 | |||
1185 | hsudc->driver = NULL; | ||
1186 | hsudc->gadget.dev.driver = NULL; | ||
1187 | return ret; | ||
1188 | } | 1174 | } |
1189 | } | 1175 | } |
1190 | 1176 | ||
@@ -1197,34 +1183,43 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver, | |||
1197 | hsudc->pd->gpio_init(); | 1183 | hsudc->pd->gpio_init(); |
1198 | 1184 | ||
1199 | return 0; | 1185 | return 0; |
1186 | err_otg: | ||
1187 | regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); | ||
1188 | err_supplies: | ||
1189 | hsudc->driver = NULL; | ||
1190 | hsudc->gadget.dev.driver = NULL; | ||
1191 | return ret; | ||
1200 | } | 1192 | } |
1201 | 1193 | ||
1202 | static int s3c_hsudc_stop(struct usb_gadget_driver *driver) | 1194 | static int s3c_hsudc_stop(struct usb_gadget *gadget, |
1195 | struct usb_gadget_driver *driver) | ||
1203 | { | 1196 | { |
1204 | struct s3c_hsudc *hsudc = the_controller; | 1197 | struct s3c_hsudc *hsudc = to_hsudc(gadget); |
1205 | unsigned long flags; | 1198 | unsigned long flags; |
1206 | 1199 | ||
1207 | if (!hsudc) | 1200 | if (!hsudc) |
1208 | return -ENODEV; | 1201 | return -ENODEV; |
1209 | 1202 | ||
1210 | if (!driver || driver != hsudc->driver || !driver->unbind) | 1203 | if (!driver || driver != hsudc->driver) |
1211 | return -EINVAL; | 1204 | return -EINVAL; |
1212 | 1205 | ||
1213 | spin_lock_irqsave(&hsudc->lock, flags); | 1206 | spin_lock_irqsave(&hsudc->lock, flags); |
1214 | hsudc->driver = 0; | 1207 | hsudc->driver = NULL; |
1208 | hsudc->gadget.dev.driver = NULL; | ||
1209 | hsudc->gadget.speed = USB_SPEED_UNKNOWN; | ||
1215 | s3c_hsudc_uninit_phy(); | 1210 | s3c_hsudc_uninit_phy(); |
1216 | if (hsudc->pd->gpio_uninit) | 1211 | if (hsudc->pd->gpio_uninit) |
1217 | hsudc->pd->gpio_uninit(); | 1212 | hsudc->pd->gpio_uninit(); |
1218 | s3c_hsudc_stop_activity(hsudc, driver); | 1213 | s3c_hsudc_stop_activity(hsudc); |
1219 | spin_unlock_irqrestore(&hsudc->lock, flags); | 1214 | spin_unlock_irqrestore(&hsudc->lock, flags); |
1220 | 1215 | ||
1221 | if (hsudc->transceiver) | 1216 | if (hsudc->transceiver) |
1222 | (void) otg_set_peripheral(hsudc->transceiver, NULL); | 1217 | (void) otg_set_peripheral(hsudc->transceiver, NULL); |
1223 | 1218 | ||
1224 | driver->unbind(&hsudc->gadget); | ||
1225 | device_del(&hsudc->gadget.dev); | ||
1226 | disable_irq(hsudc->irq); | 1219 | disable_irq(hsudc->irq); |
1227 | 1220 | ||
1221 | regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); | ||
1222 | |||
1228 | dev_info(hsudc->dev, "unregistered gadget driver '%s'\n", | 1223 | dev_info(hsudc->dev, "unregistered gadget driver '%s'\n", |
1229 | driver->driver.name); | 1224 | driver->driver.name); |
1230 | return 0; | 1225 | return 0; |
@@ -1242,7 +1237,7 @@ static int s3c_hsudc_gadget_getframe(struct usb_gadget *gadget) | |||
1242 | 1237 | ||
1243 | static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA) | 1238 | static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA) |
1244 | { | 1239 | { |
1245 | struct s3c_hsudc *hsudc = the_controller; | 1240 | struct s3c_hsudc *hsudc = to_hsudc(gadget); |
1246 | 1241 | ||
1247 | if (!hsudc) | 1242 | if (!hsudc) |
1248 | return -ENODEV; | 1243 | return -ENODEV; |
@@ -1255,18 +1250,18 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA) | |||
1255 | 1250 | ||
1256 | static struct usb_gadget_ops s3c_hsudc_gadget_ops = { | 1251 | static struct usb_gadget_ops s3c_hsudc_gadget_ops = { |
1257 | .get_frame = s3c_hsudc_gadget_getframe, | 1252 | .get_frame = s3c_hsudc_gadget_getframe, |
1258 | .start = s3c_hsudc_start, | 1253 | .udc_start = s3c_hsudc_start, |
1259 | .stop = s3c_hsudc_stop, | 1254 | .udc_stop = s3c_hsudc_stop, |
1260 | .vbus_draw = s3c_hsudc_vbus_draw, | 1255 | .vbus_draw = s3c_hsudc_vbus_draw, |
1261 | }; | 1256 | }; |
1262 | 1257 | ||
1263 | static int s3c_hsudc_probe(struct platform_device *pdev) | 1258 | static int __devinit s3c_hsudc_probe(struct platform_device *pdev) |
1264 | { | 1259 | { |
1265 | struct device *dev = &pdev->dev; | 1260 | struct device *dev = &pdev->dev; |
1266 | struct resource *res; | 1261 | struct resource *res; |
1267 | struct s3c_hsudc *hsudc; | 1262 | struct s3c_hsudc *hsudc; |
1268 | struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data; | 1263 | struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data; |
1269 | int ret; | 1264 | int ret, i; |
1270 | 1265 | ||
1271 | hsudc = kzalloc(sizeof(struct s3c_hsudc) + | 1266 | hsudc = kzalloc(sizeof(struct s3c_hsudc) + |
1272 | sizeof(struct s3c_hsudc_ep) * pd->epnum, | 1267 | sizeof(struct s3c_hsudc_ep) * pd->epnum, |
@@ -1276,13 +1271,22 @@ static int s3c_hsudc_probe(struct platform_device *pdev) | |||
1276 | return -ENOMEM; | 1271 | return -ENOMEM; |
1277 | } | 1272 | } |
1278 | 1273 | ||
1279 | the_controller = hsudc; | ||
1280 | platform_set_drvdata(pdev, dev); | 1274 | platform_set_drvdata(pdev, dev); |
1281 | hsudc->dev = dev; | 1275 | hsudc->dev = dev; |
1282 | hsudc->pd = pdev->dev.platform_data; | 1276 | hsudc->pd = pdev->dev.platform_data; |
1283 | 1277 | ||
1284 | hsudc->transceiver = otg_get_transceiver(); | 1278 | hsudc->transceiver = otg_get_transceiver(); |
1285 | 1279 | ||
1280 | for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++) | ||
1281 | hsudc->supplies[i].supply = s3c_hsudc_supply_names[i]; | ||
1282 | |||
1283 | ret = regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies), | ||
1284 | hsudc->supplies); | ||
1285 | if (ret != 0) { | ||
1286 | dev_err(dev, "failed to request supplies: %d\n", ret); | ||
1287 | goto err_supplies; | ||
1288 | } | ||
1289 | |||
1286 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1290 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1287 | if (!res) { | 1291 | if (!res) { |
1288 | dev_err(dev, "unable to obtain driver resource data\n"); | 1292 | dev_err(dev, "unable to obtain driver resource data\n"); |
@@ -1307,7 +1311,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev) | |||
1307 | 1311 | ||
1308 | spin_lock_init(&hsudc->lock); | 1312 | spin_lock_init(&hsudc->lock); |
1309 | 1313 | ||
1310 | device_initialize(&hsudc->gadget.dev); | ||
1311 | dev_set_name(&hsudc->gadget.dev, "gadget"); | 1314 | dev_set_name(&hsudc->gadget.dev, "gadget"); |
1312 | 1315 | ||
1313 | hsudc->gadget.max_speed = USB_SPEED_HIGH; | 1316 | hsudc->gadget.max_speed = USB_SPEED_HIGH; |
@@ -1319,6 +1322,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev) | |||
1319 | 1322 | ||
1320 | hsudc->gadget.is_otg = 0; | 1323 | hsudc->gadget.is_otg = 0; |
1321 | hsudc->gadget.is_a_peripheral = 0; | 1324 | hsudc->gadget.is_a_peripheral = 0; |
1325 | hsudc->gadget.speed = USB_SPEED_UNKNOWN; | ||
1322 | 1326 | ||
1323 | s3c_hsudc_setup_ep(hsudc); | 1327 | s3c_hsudc_setup_ep(hsudc); |
1324 | 1328 | ||
@@ -1348,12 +1352,20 @@ static int s3c_hsudc_probe(struct platform_device *pdev) | |||
1348 | disable_irq(hsudc->irq); | 1352 | disable_irq(hsudc->irq); |
1349 | local_irq_enable(); | 1353 | local_irq_enable(); |
1350 | 1354 | ||
1355 | ret = device_register(&hsudc->gadget.dev); | ||
1356 | if (ret) { | ||
1357 | put_device(&hsudc->gadget.dev); | ||
1358 | goto err_add_device; | ||
1359 | } | ||
1360 | |||
1351 | ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget); | 1361 | ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget); |
1352 | if (ret) | 1362 | if (ret) |
1353 | goto err_add_udc; | 1363 | goto err_add_udc; |
1354 | 1364 | ||
1355 | return 0; | 1365 | return 0; |
1356 | err_add_udc: | 1366 | err_add_udc: |
1367 | device_unregister(&hsudc->gadget.dev); | ||
1368 | err_add_device: | ||
1357 | clk_disable(hsudc->uclk); | 1369 | clk_disable(hsudc->uclk); |
1358 | clk_put(hsudc->uclk); | 1370 | clk_put(hsudc->uclk); |
1359 | err_clk: | 1371 | err_clk: |
@@ -1362,10 +1374,13 @@ err_irq: | |||
1362 | iounmap(hsudc->regs); | 1374 | iounmap(hsudc->regs); |
1363 | 1375 | ||
1364 | err_remap: | 1376 | err_remap: |
1365 | release_resource(hsudc->mem_rsrc); | 1377 | release_mem_region(res->start, resource_size(res)); |
1366 | kfree(hsudc->mem_rsrc); | ||
1367 | |||
1368 | err_res: | 1378 | err_res: |
1379 | if (hsudc->transceiver) | ||
1380 | otg_put_transceiver(hsudc->transceiver); | ||
1381 | |||
1382 | regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); | ||
1383 | err_supplies: | ||
1369 | kfree(hsudc); | 1384 | kfree(hsudc); |
1370 | return ret; | 1385 | return ret; |
1371 | } | 1386 | } |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 060e0e2b1ae6..a52769b5c904 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -194,6 +194,15 @@ config USB_EHCI_S5P | |||
194 | help | 194 | help |
195 | Enable support for the S5P SOC's on-chip EHCI controller. | 195 | Enable support for the S5P SOC's on-chip EHCI controller. |
196 | 196 | ||
197 | config USB_EHCI_MV | ||
198 | bool "EHCI support for Marvell on-chip controller" | ||
199 | depends on USB_EHCI_HCD | ||
200 | select USB_EHCI_ROOT_HUB_TT | ||
201 | ---help--- | ||
202 | Enables support for Marvell (including PXA and MMP series) on-chip | ||
203 | USB SPH and OTG controller. SPH is a single port host, and it can | ||
204 | only be EHCI host. OTG is controller that can switch to host mode. | ||
205 | |||
197 | config USB_W90X900_EHCI | 206 | config USB_W90X900_EHCI |
198 | bool "W90X900(W90P910) EHCI support" | 207 | bool "W90X900(W90P910) EHCI support" |
199 | depends on USB_EHCI_HCD && ARCH_W90X900 | 208 | depends on USB_EHCI_HCD && ARCH_W90X900 |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c4c76ab204c1..e311a511529b 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1371,6 +1371,11 @@ MODULE_LICENSE ("GPL"); | |||
1371 | #define PLATFORM_DRIVER ehci_xls_driver | 1371 | #define PLATFORM_DRIVER ehci_xls_driver |
1372 | #endif | 1372 | #endif |
1373 | 1373 | ||
1374 | #ifdef CONFIG_USB_EHCI_MV | ||
1375 | #include "ehci-mv.c" | ||
1376 | #define PLATFORM_DRIVER ehci_mv_driver | ||
1377 | #endif | ||
1378 | |||
1374 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | 1379 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ |
1375 | !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ | 1380 | !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ |
1376 | !defined(XILINX_OF_PLATFORM_DRIVER) | 1381 | !defined(XILINX_OF_PLATFORM_DRIVER) |
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c new file mode 100644 index 000000000000..52a604fb9321 --- /dev/null +++ b/drivers/usb/host/ehci-mv.c | |||
@@ -0,0 +1,391 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Marvell International Ltd. All rights reserved. | ||
3 | * Author: Chao Xie <chao.xie@marvell.com> | ||
4 | * Neil Zhang <zhangwm@marvell.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/usb/otg.h> | ||
17 | #include <linux/platform_data/mv_usb.h> | ||
18 | |||
19 | #define CAPLENGTH_MASK (0xff) | ||
20 | |||
21 | struct ehci_hcd_mv { | ||
22 | struct usb_hcd *hcd; | ||
23 | |||
24 | /* Which mode does this ehci running OTG/Host ? */ | ||
25 | int mode; | ||
26 | |||
27 | void __iomem *phy_regs; | ||
28 | void __iomem *cap_regs; | ||
29 | void __iomem *op_regs; | ||
30 | |||
31 | struct otg_transceiver *otg; | ||
32 | |||
33 | struct mv_usb_platform_data *pdata; | ||
34 | |||
35 | /* clock source and total clock number */ | ||
36 | unsigned int clknum; | ||
37 | struct clk *clk[0]; | ||
38 | }; | ||
39 | |||
40 | static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv) | ||
41 | { | ||
42 | unsigned int i; | ||
43 | |||
44 | for (i = 0; i < ehci_mv->clknum; i++) | ||
45 | clk_enable(ehci_mv->clk[i]); | ||
46 | } | ||
47 | |||
48 | static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) | ||
49 | { | ||
50 | unsigned int i; | ||
51 | |||
52 | for (i = 0; i < ehci_mv->clknum; i++) | ||
53 | clk_disable(ehci_mv->clk[i]); | ||
54 | } | ||
55 | |||
56 | static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) | ||
57 | { | ||
58 | int retval; | ||
59 | |||
60 | ehci_clock_enable(ehci_mv); | ||
61 | if (ehci_mv->pdata->phy_init) { | ||
62 | retval = ehci_mv->pdata->phy_init(ehci_mv->phy_regs); | ||
63 | if (retval) | ||
64 | return retval; | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv) | ||
71 | { | ||
72 | if (ehci_mv->pdata->phy_deinit) | ||
73 | ehci_mv->pdata->phy_deinit(ehci_mv->phy_regs); | ||
74 | ehci_clock_disable(ehci_mv); | ||
75 | } | ||
76 | |||
77 | static int mv_ehci_reset(struct usb_hcd *hcd) | ||
78 | { | ||
79 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
80 | struct device *dev = hcd->self.controller; | ||
81 | struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev); | ||
82 | int retval; | ||
83 | |||
84 | if (ehci_mv == NULL) { | ||
85 | dev_err(dev, "Can not find private ehci data\n"); | ||
86 | return -ENODEV; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * data structure init | ||
91 | */ | ||
92 | retval = ehci_init(hcd); | ||
93 | if (retval) { | ||
94 | dev_err(dev, "ehci_init failed %d\n", retval); | ||
95 | return retval; | ||
96 | } | ||
97 | |||
98 | hcd->has_tt = 1; | ||
99 | ehci->sbrn = 0x20; | ||
100 | |||
101 | retval = ehci_reset(ehci); | ||
102 | if (retval) { | ||
103 | dev_err(dev, "ehci_reset failed %d\n", retval); | ||
104 | return retval; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static const struct hc_driver mv_ehci_hc_driver = { | ||
111 | .description = hcd_name, | ||
112 | .product_desc = "Marvell EHCI", | ||
113 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
114 | |||
115 | /* | ||
116 | * generic hardware linkage | ||
117 | */ | ||
118 | .irq = ehci_irq, | ||
119 | .flags = HCD_MEMORY | HCD_USB2, | ||
120 | |||
121 | /* | ||
122 | * basic lifecycle operations | ||
123 | */ | ||
124 | .reset = mv_ehci_reset, | ||
125 | .start = ehci_run, | ||
126 | .stop = ehci_stop, | ||
127 | .shutdown = ehci_shutdown, | ||
128 | |||
129 | /* | ||
130 | * managing i/o requests and associated device resources | ||
131 | */ | ||
132 | .urb_enqueue = ehci_urb_enqueue, | ||
133 | .urb_dequeue = ehci_urb_dequeue, | ||
134 | .endpoint_disable = ehci_endpoint_disable, | ||
135 | .endpoint_reset = ehci_endpoint_reset, | ||
136 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
137 | |||
138 | /* | ||
139 | * scheduling support | ||
140 | */ | ||
141 | .get_frame_number = ehci_get_frame, | ||
142 | |||
143 | /* | ||
144 | * root hub support | ||
145 | */ | ||
146 | .hub_status_data = ehci_hub_status_data, | ||
147 | .hub_control = ehci_hub_control, | ||
148 | .bus_suspend = ehci_bus_suspend, | ||
149 | .bus_resume = ehci_bus_resume, | ||
150 | }; | ||
151 | |||
152 | static int mv_ehci_probe(struct platform_device *pdev) | ||
153 | { | ||
154 | struct mv_usb_platform_data *pdata = pdev->dev.platform_data; | ||
155 | struct usb_hcd *hcd; | ||
156 | struct ehci_hcd *ehci; | ||
157 | struct ehci_hcd_mv *ehci_mv; | ||
158 | struct resource *r; | ||
159 | int clk_i, retval = -ENODEV; | ||
160 | u32 offset; | ||
161 | size_t size; | ||
162 | |||
163 | if (!pdata) { | ||
164 | dev_err(&pdev->dev, "missing platform_data\n"); | ||
165 | return -ENODEV; | ||
166 | } | ||
167 | |||
168 | if (usb_disabled()) | ||
169 | return -ENODEV; | ||
170 | |||
171 | hcd = usb_create_hcd(&mv_ehci_hc_driver, &pdev->dev, "mv ehci"); | ||
172 | if (!hcd) | ||
173 | return -ENOMEM; | ||
174 | |||
175 | size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum; | ||
176 | ehci_mv = kzalloc(size, GFP_KERNEL); | ||
177 | if (ehci_mv == NULL) { | ||
178 | dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n"); | ||
179 | retval = -ENOMEM; | ||
180 | goto err_put_hcd; | ||
181 | } | ||
182 | |||
183 | platform_set_drvdata(pdev, ehci_mv); | ||
184 | ehci_mv->pdata = pdata; | ||
185 | ehci_mv->hcd = hcd; | ||
186 | |||
187 | ehci_mv->clknum = pdata->clknum; | ||
188 | for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) { | ||
189 | ehci_mv->clk[clk_i] = | ||
190 | clk_get(&pdev->dev, pdata->clkname[clk_i]); | ||
191 | if (IS_ERR(ehci_mv->clk[clk_i])) { | ||
192 | dev_err(&pdev->dev, "error get clck \"%s\"\n", | ||
193 | pdata->clkname[clk_i]); | ||
194 | retval = PTR_ERR(ehci_mv->clk[clk_i]); | ||
195 | goto err_put_clk; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs"); | ||
200 | if (r == NULL) { | ||
201 | dev_err(&pdev->dev, "no phy I/O memory resource defined\n"); | ||
202 | retval = -ENODEV; | ||
203 | goto err_put_clk; | ||
204 | } | ||
205 | |||
206 | ehci_mv->phy_regs = ioremap(r->start, resource_size(r)); | ||
207 | if (ehci_mv->phy_regs == 0) { | ||
208 | dev_err(&pdev->dev, "failed to map phy I/O memory\n"); | ||
209 | retval = -EFAULT; | ||
210 | goto err_put_clk; | ||
211 | } | ||
212 | |||
213 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "capregs"); | ||
214 | if (!r) { | ||
215 | dev_err(&pdev->dev, "no I/O memory resource defined\n"); | ||
216 | retval = -ENODEV; | ||
217 | goto err_iounmap_phyreg; | ||
218 | } | ||
219 | |||
220 | ehci_mv->cap_regs = ioremap(r->start, resource_size(r)); | ||
221 | if (ehci_mv->cap_regs == NULL) { | ||
222 | dev_err(&pdev->dev, "failed to map I/O memory\n"); | ||
223 | retval = -EFAULT; | ||
224 | goto err_iounmap_phyreg; | ||
225 | } | ||
226 | |||
227 | retval = mv_ehci_enable(ehci_mv); | ||
228 | if (retval) { | ||
229 | dev_err(&pdev->dev, "init phy error %d\n", retval); | ||
230 | goto err_iounmap_capreg; | ||
231 | } | ||
232 | |||
233 | offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK; | ||
234 | ehci_mv->op_regs = | ||
235 | (void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset); | ||
236 | |||
237 | hcd->rsrc_start = r->start; | ||
238 | hcd->rsrc_len = r->end - r->start + 1; | ||
239 | hcd->regs = ehci_mv->op_regs; | ||
240 | |||
241 | hcd->irq = platform_get_irq(pdev, 0); | ||
242 | if (!hcd->irq) { | ||
243 | dev_err(&pdev->dev, "Cannot get irq."); | ||
244 | retval = -ENODEV; | ||
245 | goto err_disable_clk; | ||
246 | } | ||
247 | |||
248 | ehci = hcd_to_ehci(hcd); | ||
249 | ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs; | ||
250 | ehci->regs = (struct ehci_regs *) ehci_mv->op_regs; | ||
251 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
252 | |||
253 | ehci_mv->mode = pdata->mode; | ||
254 | if (ehci_mv->mode == MV_USB_MODE_OTG) { | ||
255 | #ifdef CONFIG_USB_OTG_UTILS | ||
256 | ehci_mv->otg = otg_get_transceiver(); | ||
257 | if (!ehci_mv->otg) { | ||
258 | dev_err(&pdev->dev, | ||
259 | "unable to find transceiver\n"); | ||
260 | retval = -ENODEV; | ||
261 | goto err_disable_clk; | ||
262 | } | ||
263 | |||
264 | retval = otg_set_host(ehci_mv->otg, &hcd->self); | ||
265 | if (retval < 0) { | ||
266 | dev_err(&pdev->dev, | ||
267 | "unable to register with transceiver\n"); | ||
268 | retval = -ENODEV; | ||
269 | goto err_put_transceiver; | ||
270 | } | ||
271 | /* otg will enable clock before use as host */ | ||
272 | mv_ehci_disable(ehci_mv); | ||
273 | #else | ||
274 | dev_info(&pdev->dev, "MV_USB_MODE_OTG " | ||
275 | "must have CONFIG_USB_OTG_UTILS enabled\n"); | ||
276 | goto err_disable_clk; | ||
277 | #endif | ||
278 | } else { | ||
279 | if (pdata->set_vbus) | ||
280 | pdata->set_vbus(1); | ||
281 | |||
282 | retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); | ||
283 | if (retval) { | ||
284 | dev_err(&pdev->dev, | ||
285 | "failed to add hcd with err %d\n", retval); | ||
286 | goto err_set_vbus; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | if (pdata->private_init) | ||
291 | pdata->private_init(ehci_mv->op_regs, ehci_mv->phy_regs); | ||
292 | |||
293 | dev_info(&pdev->dev, | ||
294 | "successful find EHCI device with regs 0x%p irq %d" | ||
295 | " working in %s mode\n", hcd->regs, hcd->irq, | ||
296 | ehci_mv->mode == MV_USB_MODE_OTG ? "OTG" : "Host"); | ||
297 | |||
298 | return 0; | ||
299 | |||
300 | err_set_vbus: | ||
301 | if (pdata->set_vbus) | ||
302 | pdata->set_vbus(0); | ||
303 | #ifdef CONFIG_USB_OTG_UTILS | ||
304 | err_put_transceiver: | ||
305 | if (ehci_mv->otg) | ||
306 | otg_put_transceiver(ehci_mv->otg); | ||
307 | #endif | ||
308 | err_disable_clk: | ||
309 | mv_ehci_disable(ehci_mv); | ||
310 | err_iounmap_capreg: | ||
311 | iounmap(ehci_mv->cap_regs); | ||
312 | err_iounmap_phyreg: | ||
313 | iounmap(ehci_mv->phy_regs); | ||
314 | err_put_clk: | ||
315 | for (clk_i--; clk_i >= 0; clk_i--) | ||
316 | clk_put(ehci_mv->clk[clk_i]); | ||
317 | platform_set_drvdata(pdev, NULL); | ||
318 | kfree(ehci_mv); | ||
319 | err_put_hcd: | ||
320 | usb_put_hcd(hcd); | ||
321 | |||
322 | return retval; | ||
323 | } | ||
324 | |||
325 | static int mv_ehci_remove(struct platform_device *pdev) | ||
326 | { | ||
327 | struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev); | ||
328 | struct usb_hcd *hcd = ehci_mv->hcd; | ||
329 | int clk_i; | ||
330 | |||
331 | if (hcd->rh_registered) | ||
332 | usb_remove_hcd(hcd); | ||
333 | |||
334 | if (ehci_mv->otg) { | ||
335 | otg_set_host(ehci_mv->otg, NULL); | ||
336 | otg_put_transceiver(ehci_mv->otg); | ||
337 | } | ||
338 | |||
339 | if (ehci_mv->mode == MV_USB_MODE_HOST) { | ||
340 | if (ehci_mv->pdata->set_vbus) | ||
341 | ehci_mv->pdata->set_vbus(0); | ||
342 | |||
343 | mv_ehci_disable(ehci_mv); | ||
344 | } | ||
345 | |||
346 | iounmap(ehci_mv->cap_regs); | ||
347 | iounmap(ehci_mv->phy_regs); | ||
348 | |||
349 | for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) | ||
350 | clk_put(ehci_mv->clk[clk_i]); | ||
351 | |||
352 | platform_set_drvdata(pdev, NULL); | ||
353 | |||
354 | kfree(ehci_mv); | ||
355 | usb_put_hcd(hcd); | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | MODULE_ALIAS("mv-ehci"); | ||
361 | |||
362 | static const struct platform_device_id ehci_id_table[] = { | ||
363 | {"pxa-u2oehci", PXA_U2OEHCI}, | ||
364 | {"pxa-sph", PXA_SPH}, | ||
365 | {"mmp3-hsic", MMP3_HSIC}, | ||
366 | {"mmp3-fsic", MMP3_FSIC}, | ||
367 | {}, | ||
368 | }; | ||
369 | |||
370 | static void mv_ehci_shutdown(struct platform_device *pdev) | ||
371 | { | ||
372 | struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev); | ||
373 | struct usb_hcd *hcd = ehci_mv->hcd; | ||
374 | |||
375 | if (!hcd->rh_registered) | ||
376 | return; | ||
377 | |||
378 | if (hcd->driver->shutdown) | ||
379 | hcd->driver->shutdown(hcd); | ||
380 | } | ||
381 | |||
382 | static struct platform_driver ehci_mv_driver = { | ||
383 | .probe = mv_ehci_probe, | ||
384 | .remove = mv_ehci_remove, | ||
385 | .shutdown = mv_ehci_shutdown, | ||
386 | .driver = { | ||
387 | .name = "mv-ehci", | ||
388 | .bus = &platform_bus_type, | ||
389 | }, | ||
390 | .id_table = ehci_id_table, | ||
391 | }; | ||
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 5e913d72cdab..2a25955881fc 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -130,4 +130,16 @@ config FSL_USB2_OTG | |||
130 | help | 130 | help |
131 | Enable this to support Freescale USB OTG transceiver. | 131 | Enable this to support Freescale USB OTG transceiver. |
132 | 132 | ||
133 | config USB_MV_OTG | ||
134 | tristate "Marvell USB OTG support" | ||
135 | depends on USB_MV_UDC | ||
136 | select USB_OTG | ||
137 | select USB_OTG_UTILS | ||
138 | help | ||
139 | Say Y here if you want to build Marvell USB OTG transciever | ||
140 | driver in kernel (including PXA and MMP series). This driver | ||
141 | implements role switch between EHCI host driver and gadget driver. | ||
142 | |||
143 | To compile this driver as a module, choose M here. | ||
144 | |||
133 | endif # USB || OTG | 145 | endif # USB || OTG |
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 566655c53331..b2c5a9598637 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile | |||
@@ -21,3 +21,4 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o | |||
21 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o | 21 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o |
22 | fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o | 22 | fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o |
23 | obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o | 23 | obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o |
24 | obj-$(CONFIG_USB_MV_OTG) += mv_otg.o | ||
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c new file mode 100644 index 000000000000..db0d4fcdc8e2 --- /dev/null +++ b/drivers/usb/otg/mv_otg.c | |||
@@ -0,0 +1,957 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Marvell International Ltd. All rights reserved. | ||
3 | * Author: Chao Xie <chao.xie@marvell.com> | ||
4 | * Neil Zhang <zhangwm@marvell.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/uaccess.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/proc_fs.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/workqueue.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include <linux/usb.h> | ||
24 | #include <linux/usb/ch9.h> | ||
25 | #include <linux/usb/otg.h> | ||
26 | #include <linux/usb/gadget.h> | ||
27 | #include <linux/usb/hcd.h> | ||
28 | #include <linux/platform_data/mv_usb.h> | ||
29 | |||
30 | #include "mv_otg.h" | ||
31 | |||
32 | #define DRIVER_DESC "Marvell USB OTG transceiver driver" | ||
33 | #define DRIVER_VERSION "Jan 20, 2010" | ||
34 | |||
35 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
36 | MODULE_VERSION(DRIVER_VERSION); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | static const char driver_name[] = "mv-otg"; | ||
40 | |||
41 | static char *state_string[] = { | ||
42 | "undefined", | ||
43 | "b_idle", | ||
44 | "b_srp_init", | ||
45 | "b_peripheral", | ||
46 | "b_wait_acon", | ||
47 | "b_host", | ||
48 | "a_idle", | ||
49 | "a_wait_vrise", | ||
50 | "a_wait_bcon", | ||
51 | "a_host", | ||
52 | "a_suspend", | ||
53 | "a_peripheral", | ||
54 | "a_wait_vfall", | ||
55 | "a_vbus_err" | ||
56 | }; | ||
57 | |||
58 | static int mv_otg_set_vbus(struct otg_transceiver *otg, bool on) | ||
59 | { | ||
60 | struct mv_otg *mvotg = container_of(otg, struct mv_otg, otg); | ||
61 | if (mvotg->pdata->set_vbus == NULL) | ||
62 | return -ENODEV; | ||
63 | |||
64 | return mvotg->pdata->set_vbus(on); | ||
65 | } | ||
66 | |||
67 | static int mv_otg_set_host(struct otg_transceiver *otg, | ||
68 | struct usb_bus *host) | ||
69 | { | ||
70 | otg->host = host; | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int mv_otg_set_peripheral(struct otg_transceiver *otg, | ||
76 | struct usb_gadget *gadget) | ||
77 | { | ||
78 | otg->gadget = gadget; | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void mv_otg_run_state_machine(struct mv_otg *mvotg, | ||
84 | unsigned long delay) | ||
85 | { | ||
86 | dev_dbg(&mvotg->pdev->dev, "transceiver is updated\n"); | ||
87 | if (!mvotg->qwork) | ||
88 | return; | ||
89 | |||
90 | queue_delayed_work(mvotg->qwork, &mvotg->work, delay); | ||
91 | } | ||
92 | |||
93 | static void mv_otg_timer_await_bcon(unsigned long data) | ||
94 | { | ||
95 | struct mv_otg *mvotg = (struct mv_otg *) data; | ||
96 | |||
97 | mvotg->otg_ctrl.a_wait_bcon_timeout = 1; | ||
98 | |||
99 | dev_info(&mvotg->pdev->dev, "B Device No Response!\n"); | ||
100 | |||
101 | if (spin_trylock(&mvotg->wq_lock)) { | ||
102 | mv_otg_run_state_machine(mvotg, 0); | ||
103 | spin_unlock(&mvotg->wq_lock); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static int mv_otg_cancel_timer(struct mv_otg *mvotg, unsigned int id) | ||
108 | { | ||
109 | struct timer_list *timer; | ||
110 | |||
111 | if (id >= OTG_TIMER_NUM) | ||
112 | return -EINVAL; | ||
113 | |||
114 | timer = &mvotg->otg_ctrl.timer[id]; | ||
115 | |||
116 | if (timer_pending(timer)) | ||
117 | del_timer(timer); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int mv_otg_set_timer(struct mv_otg *mvotg, unsigned int id, | ||
123 | unsigned long interval, | ||
124 | void (*callback) (unsigned long)) | ||
125 | { | ||
126 | struct timer_list *timer; | ||
127 | |||
128 | if (id >= OTG_TIMER_NUM) | ||
129 | return -EINVAL; | ||
130 | |||
131 | timer = &mvotg->otg_ctrl.timer[id]; | ||
132 | if (timer_pending(timer)) { | ||
133 | dev_err(&mvotg->pdev->dev, "Timer%d is already running\n", id); | ||
134 | return -EBUSY; | ||
135 | } | ||
136 | |||
137 | init_timer(timer); | ||
138 | timer->data = (unsigned long) mvotg; | ||
139 | timer->function = callback; | ||
140 | timer->expires = jiffies + interval; | ||
141 | add_timer(timer); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static int mv_otg_reset(struct mv_otg *mvotg) | ||
147 | { | ||
148 | unsigned int loops; | ||
149 | u32 tmp; | ||
150 | |||
151 | /* Stop the controller */ | ||
152 | tmp = readl(&mvotg->op_regs->usbcmd); | ||
153 | tmp &= ~USBCMD_RUN_STOP; | ||
154 | writel(tmp, &mvotg->op_regs->usbcmd); | ||
155 | |||
156 | /* Reset the controller to get default values */ | ||
157 | writel(USBCMD_CTRL_RESET, &mvotg->op_regs->usbcmd); | ||
158 | |||
159 | loops = 500; | ||
160 | while (readl(&mvotg->op_regs->usbcmd) & USBCMD_CTRL_RESET) { | ||
161 | if (loops == 0) { | ||
162 | dev_err(&mvotg->pdev->dev, | ||
163 | "Wait for RESET completed TIMEOUT\n"); | ||
164 | return -ETIMEDOUT; | ||
165 | } | ||
166 | loops--; | ||
167 | udelay(20); | ||
168 | } | ||
169 | |||
170 | writel(0x0, &mvotg->op_regs->usbintr); | ||
171 | tmp = readl(&mvotg->op_regs->usbsts); | ||
172 | writel(tmp, &mvotg->op_regs->usbsts); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static void mv_otg_init_irq(struct mv_otg *mvotg) | ||
178 | { | ||
179 | u32 otgsc; | ||
180 | |||
181 | mvotg->irq_en = OTGSC_INTR_A_SESSION_VALID | ||
182 | | OTGSC_INTR_A_VBUS_VALID; | ||
183 | mvotg->irq_status = OTGSC_INTSTS_A_SESSION_VALID | ||
184 | | OTGSC_INTSTS_A_VBUS_VALID; | ||
185 | |||
186 | if (mvotg->pdata->vbus == NULL) { | ||
187 | mvotg->irq_en |= OTGSC_INTR_B_SESSION_VALID | ||
188 | | OTGSC_INTR_B_SESSION_END; | ||
189 | mvotg->irq_status |= OTGSC_INTSTS_B_SESSION_VALID | ||
190 | | OTGSC_INTSTS_B_SESSION_END; | ||
191 | } | ||
192 | |||
193 | if (mvotg->pdata->id == NULL) { | ||
194 | mvotg->irq_en |= OTGSC_INTR_USB_ID; | ||
195 | mvotg->irq_status |= OTGSC_INTSTS_USB_ID; | ||
196 | } | ||
197 | |||
198 | otgsc = readl(&mvotg->op_regs->otgsc); | ||
199 | otgsc |= mvotg->irq_en; | ||
200 | writel(otgsc, &mvotg->op_regs->otgsc); | ||
201 | } | ||
202 | |||
203 | static void mv_otg_start_host(struct mv_otg *mvotg, int on) | ||
204 | { | ||
205 | struct otg_transceiver *otg = &mvotg->otg; | ||
206 | struct usb_hcd *hcd; | ||
207 | |||
208 | if (!otg->host) | ||
209 | return; | ||
210 | |||
211 | dev_info(&mvotg->pdev->dev, "%s host\n", on ? "start" : "stop"); | ||
212 | |||
213 | hcd = bus_to_hcd(otg->host); | ||
214 | |||
215 | if (on) | ||
216 | usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); | ||
217 | else | ||
218 | usb_remove_hcd(hcd); | ||
219 | } | ||
220 | |||
221 | static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) | ||
222 | { | ||
223 | struct otg_transceiver *otg = &mvotg->otg; | ||
224 | |||
225 | if (!otg->gadget) | ||
226 | return; | ||
227 | |||
228 | dev_info(otg->dev, "gadget %s\n", on ? "on" : "off"); | ||
229 | |||
230 | if (on) | ||
231 | usb_gadget_vbus_connect(otg->gadget); | ||
232 | else | ||
233 | usb_gadget_vbus_disconnect(otg->gadget); | ||
234 | } | ||
235 | |||
236 | static void otg_clock_enable(struct mv_otg *mvotg) | ||
237 | { | ||
238 | unsigned int i; | ||
239 | |||
240 | for (i = 0; i < mvotg->clknum; i++) | ||
241 | clk_enable(mvotg->clk[i]); | ||
242 | } | ||
243 | |||
244 | static void otg_clock_disable(struct mv_otg *mvotg) | ||
245 | { | ||
246 | unsigned int i; | ||
247 | |||
248 | for (i = 0; i < mvotg->clknum; i++) | ||
249 | clk_disable(mvotg->clk[i]); | ||
250 | } | ||
251 | |||
252 | static int mv_otg_enable_internal(struct mv_otg *mvotg) | ||
253 | { | ||
254 | int retval = 0; | ||
255 | |||
256 | if (mvotg->active) | ||
257 | return 0; | ||
258 | |||
259 | dev_dbg(&mvotg->pdev->dev, "otg enabled\n"); | ||
260 | |||
261 | otg_clock_enable(mvotg); | ||
262 | if (mvotg->pdata->phy_init) { | ||
263 | retval = mvotg->pdata->phy_init(mvotg->phy_regs); | ||
264 | if (retval) { | ||
265 | dev_err(&mvotg->pdev->dev, | ||
266 | "init phy error %d\n", retval); | ||
267 | otg_clock_disable(mvotg); | ||
268 | return retval; | ||
269 | } | ||
270 | } | ||
271 | mvotg->active = 1; | ||
272 | |||
273 | return 0; | ||
274 | |||
275 | } | ||
276 | |||
277 | static int mv_otg_enable(struct mv_otg *mvotg) | ||
278 | { | ||
279 | if (mvotg->clock_gating) | ||
280 | return mv_otg_enable_internal(mvotg); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static void mv_otg_disable_internal(struct mv_otg *mvotg) | ||
286 | { | ||
287 | if (mvotg->active) { | ||
288 | dev_dbg(&mvotg->pdev->dev, "otg disabled\n"); | ||
289 | if (mvotg->pdata->phy_deinit) | ||
290 | mvotg->pdata->phy_deinit(mvotg->phy_regs); | ||
291 | otg_clock_disable(mvotg); | ||
292 | mvotg->active = 0; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static void mv_otg_disable(struct mv_otg *mvotg) | ||
297 | { | ||
298 | if (mvotg->clock_gating) | ||
299 | mv_otg_disable_internal(mvotg); | ||
300 | } | ||
301 | |||
302 | static void mv_otg_update_inputs(struct mv_otg *mvotg) | ||
303 | { | ||
304 | struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl; | ||
305 | u32 otgsc; | ||
306 | |||
307 | otgsc = readl(&mvotg->op_regs->otgsc); | ||
308 | |||
309 | if (mvotg->pdata->vbus) { | ||
310 | if (mvotg->pdata->vbus->poll() == VBUS_HIGH) { | ||
311 | otg_ctrl->b_sess_vld = 1; | ||
312 | otg_ctrl->b_sess_end = 0; | ||
313 | } else { | ||
314 | otg_ctrl->b_sess_vld = 0; | ||
315 | otg_ctrl->b_sess_end = 1; | ||
316 | } | ||
317 | } else { | ||
318 | otg_ctrl->b_sess_vld = !!(otgsc & OTGSC_STS_B_SESSION_VALID); | ||
319 | otg_ctrl->b_sess_end = !!(otgsc & OTGSC_STS_B_SESSION_END); | ||
320 | } | ||
321 | |||
322 | if (mvotg->pdata->id) | ||
323 | otg_ctrl->id = !!mvotg->pdata->id->poll(); | ||
324 | else | ||
325 | otg_ctrl->id = !!(otgsc & OTGSC_STS_USB_ID); | ||
326 | |||
327 | if (mvotg->pdata->otg_force_a_bus_req && !otg_ctrl->id) | ||
328 | otg_ctrl->a_bus_req = 1; | ||
329 | |||
330 | otg_ctrl->a_sess_vld = !!(otgsc & OTGSC_STS_A_SESSION_VALID); | ||
331 | otg_ctrl->a_vbus_vld = !!(otgsc & OTGSC_STS_A_VBUS_VALID); | ||
332 | |||
333 | dev_dbg(&mvotg->pdev->dev, "%s: ", __func__); | ||
334 | dev_dbg(&mvotg->pdev->dev, "id %d\n", otg_ctrl->id); | ||
335 | dev_dbg(&mvotg->pdev->dev, "b_sess_vld %d\n", otg_ctrl->b_sess_vld); | ||
336 | dev_dbg(&mvotg->pdev->dev, "b_sess_end %d\n", otg_ctrl->b_sess_end); | ||
337 | dev_dbg(&mvotg->pdev->dev, "a_vbus_vld %d\n", otg_ctrl->a_vbus_vld); | ||
338 | dev_dbg(&mvotg->pdev->dev, "a_sess_vld %d\n", otg_ctrl->a_sess_vld); | ||
339 | } | ||
340 | |||
341 | static void mv_otg_update_state(struct mv_otg *mvotg) | ||
342 | { | ||
343 | struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl; | ||
344 | struct otg_transceiver *otg = &mvotg->otg; | ||
345 | int old_state = otg->state; | ||
346 | |||
347 | switch (old_state) { | ||
348 | case OTG_STATE_UNDEFINED: | ||
349 | otg->state = OTG_STATE_B_IDLE; | ||
350 | /* FALL THROUGH */ | ||
351 | case OTG_STATE_B_IDLE: | ||
352 | if (otg_ctrl->id == 0) | ||
353 | otg->state = OTG_STATE_A_IDLE; | ||
354 | else if (otg_ctrl->b_sess_vld) | ||
355 | otg->state = OTG_STATE_B_PERIPHERAL; | ||
356 | break; | ||
357 | case OTG_STATE_B_PERIPHERAL: | ||
358 | if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0) | ||
359 | otg->state = OTG_STATE_B_IDLE; | ||
360 | break; | ||
361 | case OTG_STATE_A_IDLE: | ||
362 | if (otg_ctrl->id) | ||
363 | otg->state = OTG_STATE_B_IDLE; | ||
364 | else if (!(otg_ctrl->a_bus_drop) && | ||
365 | (otg_ctrl->a_bus_req || otg_ctrl->a_srp_det)) | ||
366 | otg->state = OTG_STATE_A_WAIT_VRISE; | ||
367 | break; | ||
368 | case OTG_STATE_A_WAIT_VRISE: | ||
369 | if (otg_ctrl->a_vbus_vld) | ||
370 | otg->state = OTG_STATE_A_WAIT_BCON; | ||
371 | break; | ||
372 | case OTG_STATE_A_WAIT_BCON: | ||
373 | if (otg_ctrl->id || otg_ctrl->a_bus_drop | ||
374 | || otg_ctrl->a_wait_bcon_timeout) { | ||
375 | mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); | ||
376 | mvotg->otg_ctrl.a_wait_bcon_timeout = 0; | ||
377 | otg->state = OTG_STATE_A_WAIT_VFALL; | ||
378 | otg_ctrl->a_bus_req = 0; | ||
379 | } else if (!otg_ctrl->a_vbus_vld) { | ||
380 | mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); | ||
381 | mvotg->otg_ctrl.a_wait_bcon_timeout = 0; | ||
382 | otg->state = OTG_STATE_A_VBUS_ERR; | ||
383 | } else if (otg_ctrl->b_conn) { | ||
384 | mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); | ||
385 | mvotg->otg_ctrl.a_wait_bcon_timeout = 0; | ||
386 | otg->state = OTG_STATE_A_HOST; | ||
387 | } | ||
388 | break; | ||
389 | case OTG_STATE_A_HOST: | ||
390 | if (otg_ctrl->id || !otg_ctrl->b_conn | ||
391 | || otg_ctrl->a_bus_drop) | ||
392 | otg->state = OTG_STATE_A_WAIT_BCON; | ||
393 | else if (!otg_ctrl->a_vbus_vld) | ||
394 | otg->state = OTG_STATE_A_VBUS_ERR; | ||
395 | break; | ||
396 | case OTG_STATE_A_WAIT_VFALL: | ||
397 | if (otg_ctrl->id | ||
398 | || (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld) | ||
399 | || otg_ctrl->a_bus_req) | ||
400 | otg->state = OTG_STATE_A_IDLE; | ||
401 | break; | ||
402 | case OTG_STATE_A_VBUS_ERR: | ||
403 | if (otg_ctrl->id || otg_ctrl->a_clr_err | ||
404 | || otg_ctrl->a_bus_drop) { | ||
405 | otg_ctrl->a_clr_err = 0; | ||
406 | otg->state = OTG_STATE_A_WAIT_VFALL; | ||
407 | } | ||
408 | break; | ||
409 | default: | ||
410 | break; | ||
411 | } | ||
412 | } | ||
413 | |||
414 | static void mv_otg_work(struct work_struct *work) | ||
415 | { | ||
416 | struct mv_otg *mvotg; | ||
417 | struct otg_transceiver *otg; | ||
418 | int old_state; | ||
419 | |||
420 | mvotg = container_of((struct delayed_work *)work, struct mv_otg, work); | ||
421 | |||
422 | run: | ||
423 | /* work queue is single thread, or we need spin_lock to protect */ | ||
424 | otg = &mvotg->otg; | ||
425 | old_state = otg->state; | ||
426 | |||
427 | if (!mvotg->active) | ||
428 | return; | ||
429 | |||
430 | mv_otg_update_inputs(mvotg); | ||
431 | mv_otg_update_state(mvotg); | ||
432 | |||
433 | if (old_state != otg->state) { | ||
434 | dev_info(&mvotg->pdev->dev, "change from state %s to %s\n", | ||
435 | state_string[old_state], | ||
436 | state_string[otg->state]); | ||
437 | |||
438 | switch (otg->state) { | ||
439 | case OTG_STATE_B_IDLE: | ||
440 | mvotg->otg.default_a = 0; | ||
441 | if (old_state == OTG_STATE_B_PERIPHERAL) | ||
442 | mv_otg_start_periphrals(mvotg, 0); | ||
443 | mv_otg_reset(mvotg); | ||
444 | mv_otg_disable(mvotg); | ||
445 | break; | ||
446 | case OTG_STATE_B_PERIPHERAL: | ||
447 | mv_otg_enable(mvotg); | ||
448 | mv_otg_start_periphrals(mvotg, 1); | ||
449 | break; | ||
450 | case OTG_STATE_A_IDLE: | ||
451 | mvotg->otg.default_a = 1; | ||
452 | mv_otg_enable(mvotg); | ||
453 | if (old_state == OTG_STATE_A_WAIT_VFALL) | ||
454 | mv_otg_start_host(mvotg, 0); | ||
455 | mv_otg_reset(mvotg); | ||
456 | break; | ||
457 | case OTG_STATE_A_WAIT_VRISE: | ||
458 | mv_otg_set_vbus(&mvotg->otg, 1); | ||
459 | break; | ||
460 | case OTG_STATE_A_WAIT_BCON: | ||
461 | if (old_state != OTG_STATE_A_HOST) | ||
462 | mv_otg_start_host(mvotg, 1); | ||
463 | mv_otg_set_timer(mvotg, A_WAIT_BCON_TIMER, | ||
464 | T_A_WAIT_BCON, | ||
465 | mv_otg_timer_await_bcon); | ||
466 | /* | ||
467 | * Now, we directly enter A_HOST. So set b_conn = 1 | ||
468 | * here. In fact, it need host driver to notify us. | ||
469 | */ | ||
470 | mvotg->otg_ctrl.b_conn = 1; | ||
471 | break; | ||
472 | case OTG_STATE_A_HOST: | ||
473 | break; | ||
474 | case OTG_STATE_A_WAIT_VFALL: | ||
475 | /* | ||
476 | * Now, we has exited A_HOST. So set b_conn = 0 | ||
477 | * here. In fact, it need host driver to notify us. | ||
478 | */ | ||
479 | mvotg->otg_ctrl.b_conn = 0; | ||
480 | mv_otg_set_vbus(&mvotg->otg, 0); | ||
481 | break; | ||
482 | case OTG_STATE_A_VBUS_ERR: | ||
483 | break; | ||
484 | default: | ||
485 | break; | ||
486 | } | ||
487 | goto run; | ||
488 | } | ||
489 | } | ||
490 | |||
491 | static irqreturn_t mv_otg_irq(int irq, void *dev) | ||
492 | { | ||
493 | struct mv_otg *mvotg = dev; | ||
494 | u32 otgsc; | ||
495 | |||
496 | otgsc = readl(&mvotg->op_regs->otgsc); | ||
497 | writel(otgsc, &mvotg->op_regs->otgsc); | ||
498 | |||
499 | /* | ||
500 | * if we have vbus, then the vbus detection for B-device | ||
501 | * will be done by mv_otg_inputs_irq(). | ||
502 | */ | ||
503 | if (mvotg->pdata->vbus) | ||
504 | if ((otgsc & OTGSC_STS_USB_ID) && | ||
505 | !(otgsc & OTGSC_INTSTS_USB_ID)) | ||
506 | return IRQ_NONE; | ||
507 | |||
508 | if ((otgsc & mvotg->irq_status) == 0) | ||
509 | return IRQ_NONE; | ||
510 | |||
511 | mv_otg_run_state_machine(mvotg, 0); | ||
512 | |||
513 | return IRQ_HANDLED; | ||
514 | } | ||
515 | |||
516 | static irqreturn_t mv_otg_inputs_irq(int irq, void *dev) | ||
517 | { | ||
518 | struct mv_otg *mvotg = dev; | ||
519 | |||
520 | /* The clock may disabled at this time */ | ||
521 | if (!mvotg->active) { | ||
522 | mv_otg_enable(mvotg); | ||
523 | mv_otg_init_irq(mvotg); | ||
524 | } | ||
525 | |||
526 | mv_otg_run_state_machine(mvotg, 0); | ||
527 | |||
528 | return IRQ_HANDLED; | ||
529 | } | ||
530 | |||
531 | static ssize_t | ||
532 | get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
533 | { | ||
534 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
535 | return scnprintf(buf, PAGE_SIZE, "%d\n", | ||
536 | mvotg->otg_ctrl.a_bus_req); | ||
537 | } | ||
538 | |||
539 | static ssize_t | ||
540 | set_a_bus_req(struct device *dev, struct device_attribute *attr, | ||
541 | const char *buf, size_t count) | ||
542 | { | ||
543 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
544 | |||
545 | if (count > 2) | ||
546 | return -1; | ||
547 | |||
548 | /* We will use this interface to change to A device */ | ||
549 | if (mvotg->otg.state != OTG_STATE_B_IDLE | ||
550 | && mvotg->otg.state != OTG_STATE_A_IDLE) | ||
551 | return -1; | ||
552 | |||
553 | /* The clock may disabled and we need to set irq for ID detected */ | ||
554 | mv_otg_enable(mvotg); | ||
555 | mv_otg_init_irq(mvotg); | ||
556 | |||
557 | if (buf[0] == '1') { | ||
558 | mvotg->otg_ctrl.a_bus_req = 1; | ||
559 | mvotg->otg_ctrl.a_bus_drop = 0; | ||
560 | dev_dbg(&mvotg->pdev->dev, | ||
561 | "User request: a_bus_req = 1\n"); | ||
562 | |||
563 | if (spin_trylock(&mvotg->wq_lock)) { | ||
564 | mv_otg_run_state_machine(mvotg, 0); | ||
565 | spin_unlock(&mvotg->wq_lock); | ||
566 | } | ||
567 | } | ||
568 | |||
569 | return count; | ||
570 | } | ||
571 | |||
572 | static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, | ||
573 | set_a_bus_req); | ||
574 | |||
575 | static ssize_t | ||
576 | set_a_clr_err(struct device *dev, struct device_attribute *attr, | ||
577 | const char *buf, size_t count) | ||
578 | { | ||
579 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
580 | if (!mvotg->otg.default_a) | ||
581 | return -1; | ||
582 | |||
583 | if (count > 2) | ||
584 | return -1; | ||
585 | |||
586 | if (buf[0] == '1') { | ||
587 | mvotg->otg_ctrl.a_clr_err = 1; | ||
588 | dev_dbg(&mvotg->pdev->dev, | ||
589 | "User request: a_clr_err = 1\n"); | ||
590 | } | ||
591 | |||
592 | if (spin_trylock(&mvotg->wq_lock)) { | ||
593 | mv_otg_run_state_machine(mvotg, 0); | ||
594 | spin_unlock(&mvotg->wq_lock); | ||
595 | } | ||
596 | |||
597 | return count; | ||
598 | } | ||
599 | |||
600 | static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err); | ||
601 | |||
602 | static ssize_t | ||
603 | get_a_bus_drop(struct device *dev, struct device_attribute *attr, | ||
604 | char *buf) | ||
605 | { | ||
606 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
607 | return scnprintf(buf, PAGE_SIZE, "%d\n", | ||
608 | mvotg->otg_ctrl.a_bus_drop); | ||
609 | } | ||
610 | |||
611 | static ssize_t | ||
612 | set_a_bus_drop(struct device *dev, struct device_attribute *attr, | ||
613 | const char *buf, size_t count) | ||
614 | { | ||
615 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
616 | if (!mvotg->otg.default_a) | ||
617 | return -1; | ||
618 | |||
619 | if (count > 2) | ||
620 | return -1; | ||
621 | |||
622 | if (buf[0] == '0') { | ||
623 | mvotg->otg_ctrl.a_bus_drop = 0; | ||
624 | dev_dbg(&mvotg->pdev->dev, | ||
625 | "User request: a_bus_drop = 0\n"); | ||
626 | } else if (buf[0] == '1') { | ||
627 | mvotg->otg_ctrl.a_bus_drop = 1; | ||
628 | mvotg->otg_ctrl.a_bus_req = 0; | ||
629 | dev_dbg(&mvotg->pdev->dev, | ||
630 | "User request: a_bus_drop = 1\n"); | ||
631 | dev_dbg(&mvotg->pdev->dev, | ||
632 | "User request: and a_bus_req = 0\n"); | ||
633 | } | ||
634 | |||
635 | if (spin_trylock(&mvotg->wq_lock)) { | ||
636 | mv_otg_run_state_machine(mvotg, 0); | ||
637 | spin_unlock(&mvotg->wq_lock); | ||
638 | } | ||
639 | |||
640 | return count; | ||
641 | } | ||
642 | |||
643 | static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, | ||
644 | get_a_bus_drop, set_a_bus_drop); | ||
645 | |||
646 | static struct attribute *inputs_attrs[] = { | ||
647 | &dev_attr_a_bus_req.attr, | ||
648 | &dev_attr_a_clr_err.attr, | ||
649 | &dev_attr_a_bus_drop.attr, | ||
650 | NULL, | ||
651 | }; | ||
652 | |||
653 | static struct attribute_group inputs_attr_group = { | ||
654 | .name = "inputs", | ||
655 | .attrs = inputs_attrs, | ||
656 | }; | ||
657 | |||
658 | int mv_otg_remove(struct platform_device *pdev) | ||
659 | { | ||
660 | struct mv_otg *mvotg = platform_get_drvdata(pdev); | ||
661 | int clk_i; | ||
662 | |||
663 | sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group); | ||
664 | |||
665 | if (mvotg->irq) | ||
666 | free_irq(mvotg->irq, mvotg); | ||
667 | |||
668 | if (mvotg->pdata->vbus) | ||
669 | free_irq(mvotg->pdata->vbus->irq, mvotg); | ||
670 | if (mvotg->pdata->id) | ||
671 | free_irq(mvotg->pdata->id->irq, mvotg); | ||
672 | |||
673 | if (mvotg->qwork) { | ||
674 | flush_workqueue(mvotg->qwork); | ||
675 | destroy_workqueue(mvotg->qwork); | ||
676 | } | ||
677 | |||
678 | mv_otg_disable(mvotg); | ||
679 | |||
680 | if (mvotg->cap_regs) | ||
681 | iounmap(mvotg->cap_regs); | ||
682 | |||
683 | if (mvotg->phy_regs) | ||
684 | iounmap(mvotg->phy_regs); | ||
685 | |||
686 | for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++) | ||
687 | clk_put(mvotg->clk[clk_i]); | ||
688 | |||
689 | otg_set_transceiver(NULL); | ||
690 | platform_set_drvdata(pdev, NULL); | ||
691 | |||
692 | kfree(mvotg); | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static int mv_otg_probe(struct platform_device *pdev) | ||
698 | { | ||
699 | struct mv_usb_platform_data *pdata = pdev->dev.platform_data; | ||
700 | struct mv_otg *mvotg; | ||
701 | struct resource *r; | ||
702 | int retval = 0, clk_i, i; | ||
703 | size_t size; | ||
704 | |||
705 | if (pdata == NULL) { | ||
706 | dev_err(&pdev->dev, "failed to get platform data\n"); | ||
707 | return -ENODEV; | ||
708 | } | ||
709 | |||
710 | size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum; | ||
711 | mvotg = kzalloc(size, GFP_KERNEL); | ||
712 | if (!mvotg) { | ||
713 | dev_err(&pdev->dev, "failed to allocate memory!\n"); | ||
714 | return -ENOMEM; | ||
715 | } | ||
716 | |||
717 | platform_set_drvdata(pdev, mvotg); | ||
718 | |||
719 | mvotg->pdev = pdev; | ||
720 | mvotg->pdata = pdata; | ||
721 | |||
722 | mvotg->clknum = pdata->clknum; | ||
723 | for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) { | ||
724 | mvotg->clk[clk_i] = clk_get(&pdev->dev, pdata->clkname[clk_i]); | ||
725 | if (IS_ERR(mvotg->clk[clk_i])) { | ||
726 | retval = PTR_ERR(mvotg->clk[clk_i]); | ||
727 | goto err_put_clk; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | mvotg->qwork = create_singlethread_workqueue("mv_otg_queue"); | ||
732 | if (!mvotg->qwork) { | ||
733 | dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n"); | ||
734 | retval = -ENOMEM; | ||
735 | goto err_put_clk; | ||
736 | } | ||
737 | |||
738 | INIT_DELAYED_WORK(&mvotg->work, mv_otg_work); | ||
739 | |||
740 | /* OTG common part */ | ||
741 | mvotg->pdev = pdev; | ||
742 | mvotg->otg.dev = &pdev->dev; | ||
743 | mvotg->otg.label = driver_name; | ||
744 | mvotg->otg.set_host = mv_otg_set_host; | ||
745 | mvotg->otg.set_peripheral = mv_otg_set_peripheral; | ||
746 | mvotg->otg.set_vbus = mv_otg_set_vbus; | ||
747 | mvotg->otg.state = OTG_STATE_UNDEFINED; | ||
748 | |||
749 | for (i = 0; i < OTG_TIMER_NUM; i++) | ||
750 | init_timer(&mvotg->otg_ctrl.timer[i]); | ||
751 | |||
752 | r = platform_get_resource_byname(mvotg->pdev, | ||
753 | IORESOURCE_MEM, "phyregs"); | ||
754 | if (r == NULL) { | ||
755 | dev_err(&pdev->dev, "no phy I/O memory resource defined\n"); | ||
756 | retval = -ENODEV; | ||
757 | goto err_destroy_workqueue; | ||
758 | } | ||
759 | |||
760 | mvotg->phy_regs = ioremap(r->start, resource_size(r)); | ||
761 | if (mvotg->phy_regs == NULL) { | ||
762 | dev_err(&pdev->dev, "failed to map phy I/O memory\n"); | ||
763 | retval = -EFAULT; | ||
764 | goto err_destroy_workqueue; | ||
765 | } | ||
766 | |||
767 | r = platform_get_resource_byname(mvotg->pdev, | ||
768 | IORESOURCE_MEM, "capregs"); | ||
769 | if (r == NULL) { | ||
770 | dev_err(&pdev->dev, "no I/O memory resource defined\n"); | ||
771 | retval = -ENODEV; | ||
772 | goto err_unmap_phyreg; | ||
773 | } | ||
774 | |||
775 | mvotg->cap_regs = ioremap(r->start, resource_size(r)); | ||
776 | if (mvotg->cap_regs == NULL) { | ||
777 | dev_err(&pdev->dev, "failed to map I/O memory\n"); | ||
778 | retval = -EFAULT; | ||
779 | goto err_unmap_phyreg; | ||
780 | } | ||
781 | |||
782 | /* we will acces controller register, so enable the udc controller */ | ||
783 | retval = mv_otg_enable_internal(mvotg); | ||
784 | if (retval) { | ||
785 | dev_err(&pdev->dev, "mv otg enable error %d\n", retval); | ||
786 | goto err_unmap_capreg; | ||
787 | } | ||
788 | |||
789 | mvotg->op_regs = | ||
790 | (struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs | ||
791 | + (readl(mvotg->cap_regs) & CAPLENGTH_MASK)); | ||
792 | |||
793 | if (pdata->id) { | ||
794 | retval = request_threaded_irq(pdata->id->irq, NULL, | ||
795 | mv_otg_inputs_irq, | ||
796 | IRQF_ONESHOT, "id", mvotg); | ||
797 | if (retval) { | ||
798 | dev_info(&pdev->dev, | ||
799 | "Failed to request irq for ID\n"); | ||
800 | pdata->id = NULL; | ||
801 | } | ||
802 | } | ||
803 | |||
804 | if (pdata->vbus) { | ||
805 | mvotg->clock_gating = 1; | ||
806 | retval = request_threaded_irq(pdata->vbus->irq, NULL, | ||
807 | mv_otg_inputs_irq, | ||
808 | IRQF_ONESHOT, "vbus", mvotg); | ||
809 | if (retval) { | ||
810 | dev_info(&pdev->dev, | ||
811 | "Failed to request irq for VBUS, " | ||
812 | "disable clock gating\n"); | ||
813 | mvotg->clock_gating = 0; | ||
814 | pdata->vbus = NULL; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | if (pdata->disable_otg_clock_gating) | ||
819 | mvotg->clock_gating = 0; | ||
820 | |||
821 | mv_otg_reset(mvotg); | ||
822 | mv_otg_init_irq(mvotg); | ||
823 | |||
824 | r = platform_get_resource(mvotg->pdev, IORESOURCE_IRQ, 0); | ||
825 | if (r == NULL) { | ||
826 | dev_err(&pdev->dev, "no IRQ resource defined\n"); | ||
827 | retval = -ENODEV; | ||
828 | goto err_disable_clk; | ||
829 | } | ||
830 | |||
831 | mvotg->irq = r->start; | ||
832 | if (request_irq(mvotg->irq, mv_otg_irq, IRQF_SHARED, | ||
833 | driver_name, mvotg)) { | ||
834 | dev_err(&pdev->dev, "Request irq %d for OTG failed\n", | ||
835 | mvotg->irq); | ||
836 | mvotg->irq = 0; | ||
837 | retval = -ENODEV; | ||
838 | goto err_disable_clk; | ||
839 | } | ||
840 | |||
841 | retval = otg_set_transceiver(&mvotg->otg); | ||
842 | if (retval < 0) { | ||
843 | dev_err(&pdev->dev, "can't register transceiver, %d\n", | ||
844 | retval); | ||
845 | goto err_free_irq; | ||
846 | } | ||
847 | |||
848 | retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group); | ||
849 | if (retval < 0) { | ||
850 | dev_dbg(&pdev->dev, | ||
851 | "Can't register sysfs attr group: %d\n", retval); | ||
852 | goto err_set_transceiver; | ||
853 | } | ||
854 | |||
855 | spin_lock_init(&mvotg->wq_lock); | ||
856 | if (spin_trylock(&mvotg->wq_lock)) { | ||
857 | mv_otg_run_state_machine(mvotg, 2 * HZ); | ||
858 | spin_unlock(&mvotg->wq_lock); | ||
859 | } | ||
860 | |||
861 | dev_info(&pdev->dev, | ||
862 | "successful probe OTG device %s clock gating.\n", | ||
863 | mvotg->clock_gating ? "with" : "without"); | ||
864 | |||
865 | return 0; | ||
866 | |||
867 | err_set_transceiver: | ||
868 | otg_set_transceiver(NULL); | ||
869 | err_free_irq: | ||
870 | free_irq(mvotg->irq, mvotg); | ||
871 | err_disable_clk: | ||
872 | if (pdata->vbus) | ||
873 | free_irq(pdata->vbus->irq, mvotg); | ||
874 | if (pdata->id) | ||
875 | free_irq(pdata->id->irq, mvotg); | ||
876 | mv_otg_disable_internal(mvotg); | ||
877 | err_unmap_capreg: | ||
878 | iounmap(mvotg->cap_regs); | ||
879 | err_unmap_phyreg: | ||
880 | iounmap(mvotg->phy_regs); | ||
881 | err_destroy_workqueue: | ||
882 | flush_workqueue(mvotg->qwork); | ||
883 | destroy_workqueue(mvotg->qwork); | ||
884 | err_put_clk: | ||
885 | for (clk_i--; clk_i >= 0; clk_i--) | ||
886 | clk_put(mvotg->clk[clk_i]); | ||
887 | |||
888 | platform_set_drvdata(pdev, NULL); | ||
889 | kfree(mvotg); | ||
890 | |||
891 | return retval; | ||
892 | } | ||
893 | |||
894 | #ifdef CONFIG_PM | ||
895 | static int mv_otg_suspend(struct platform_device *pdev, pm_message_t state) | ||
896 | { | ||
897 | struct mv_otg *mvotg = platform_get_drvdata(pdev); | ||
898 | |||
899 | if (mvotg->otg.state != OTG_STATE_B_IDLE) { | ||
900 | dev_info(&pdev->dev, | ||
901 | "OTG state is not B_IDLE, it is %d!\n", | ||
902 | mvotg->otg.state); | ||
903 | return -EAGAIN; | ||
904 | } | ||
905 | |||
906 | if (!mvotg->clock_gating) | ||
907 | mv_otg_disable_internal(mvotg); | ||
908 | |||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | static int mv_otg_resume(struct platform_device *pdev) | ||
913 | { | ||
914 | struct mv_otg *mvotg = platform_get_drvdata(pdev); | ||
915 | u32 otgsc; | ||
916 | |||
917 | if (!mvotg->clock_gating) { | ||
918 | mv_otg_enable_internal(mvotg); | ||
919 | |||
920 | otgsc = readl(&mvotg->op_regs->otgsc); | ||
921 | otgsc |= mvotg->irq_en; | ||
922 | writel(otgsc, &mvotg->op_regs->otgsc); | ||
923 | |||
924 | if (spin_trylock(&mvotg->wq_lock)) { | ||
925 | mv_otg_run_state_machine(mvotg, 0); | ||
926 | spin_unlock(&mvotg->wq_lock); | ||
927 | } | ||
928 | } | ||
929 | return 0; | ||
930 | } | ||
931 | #endif | ||
932 | |||
933 | static struct platform_driver mv_otg_driver = { | ||
934 | .probe = mv_otg_probe, | ||
935 | .remove = __exit_p(mv_otg_remove), | ||
936 | .driver = { | ||
937 | .owner = THIS_MODULE, | ||
938 | .name = driver_name, | ||
939 | }, | ||
940 | #ifdef CONFIG_PM | ||
941 | .suspend = mv_otg_suspend, | ||
942 | .resume = mv_otg_resume, | ||
943 | #endif | ||
944 | }; | ||
945 | |||
946 | static int __init mv_otg_init(void) | ||
947 | { | ||
948 | return platform_driver_register(&mv_otg_driver); | ||
949 | } | ||
950 | |||
951 | static void __exit mv_otg_exit(void) | ||
952 | { | ||
953 | platform_driver_unregister(&mv_otg_driver); | ||
954 | } | ||
955 | |||
956 | module_init(mv_otg_init); | ||
957 | module_exit(mv_otg_exit); | ||
diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/otg/mv_otg.h new file mode 100644 index 000000000000..be6ca1437645 --- /dev/null +++ b/drivers/usb/otg/mv_otg.h | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Marvell International Ltd. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef __MV_USB_OTG_CONTROLLER__ | ||
11 | #define __MV_USB_OTG_CONTROLLER__ | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | |||
15 | /* Command Register Bit Masks */ | ||
16 | #define USBCMD_RUN_STOP (0x00000001) | ||
17 | #define USBCMD_CTRL_RESET (0x00000002) | ||
18 | |||
19 | /* otgsc Register Bit Masks */ | ||
20 | #define OTGSC_CTRL_VUSB_DISCHARGE 0x00000001 | ||
21 | #define OTGSC_CTRL_VUSB_CHARGE 0x00000002 | ||
22 | #define OTGSC_CTRL_OTG_TERM 0x00000008 | ||
23 | #define OTGSC_CTRL_DATA_PULSING 0x00000010 | ||
24 | #define OTGSC_STS_USB_ID 0x00000100 | ||
25 | #define OTGSC_STS_A_VBUS_VALID 0x00000200 | ||
26 | #define OTGSC_STS_A_SESSION_VALID 0x00000400 | ||
27 | #define OTGSC_STS_B_SESSION_VALID 0x00000800 | ||
28 | #define OTGSC_STS_B_SESSION_END 0x00001000 | ||
29 | #define OTGSC_STS_1MS_TOGGLE 0x00002000 | ||
30 | #define OTGSC_STS_DATA_PULSING 0x00004000 | ||
31 | #define OTGSC_INTSTS_USB_ID 0x00010000 | ||
32 | #define OTGSC_INTSTS_A_VBUS_VALID 0x00020000 | ||
33 | #define OTGSC_INTSTS_A_SESSION_VALID 0x00040000 | ||
34 | #define OTGSC_INTSTS_B_SESSION_VALID 0x00080000 | ||
35 | #define OTGSC_INTSTS_B_SESSION_END 0x00100000 | ||
36 | #define OTGSC_INTSTS_1MS 0x00200000 | ||
37 | #define OTGSC_INTSTS_DATA_PULSING 0x00400000 | ||
38 | #define OTGSC_INTR_USB_ID 0x01000000 | ||
39 | #define OTGSC_INTR_A_VBUS_VALID 0x02000000 | ||
40 | #define OTGSC_INTR_A_SESSION_VALID 0x04000000 | ||
41 | #define OTGSC_INTR_B_SESSION_VALID 0x08000000 | ||
42 | #define OTGSC_INTR_B_SESSION_END 0x10000000 | ||
43 | #define OTGSC_INTR_1MS_TIMER 0x20000000 | ||
44 | #define OTGSC_INTR_DATA_PULSING 0x40000000 | ||
45 | |||
46 | #define CAPLENGTH_MASK (0xff) | ||
47 | |||
48 | /* Timer's interval, unit 10ms */ | ||
49 | #define T_A_WAIT_VRISE 100 | ||
50 | #define T_A_WAIT_BCON 2000 | ||
51 | #define T_A_AIDL_BDIS 100 | ||
52 | #define T_A_BIDL_ADIS 20 | ||
53 | #define T_B_ASE0_BRST 400 | ||
54 | #define T_B_SE0_SRP 300 | ||
55 | #define T_B_SRP_FAIL 2000 | ||
56 | #define T_B_DATA_PLS 10 | ||
57 | #define T_B_SRP_INIT 100 | ||
58 | #define T_A_SRP_RSPNS 10 | ||
59 | #define T_A_DRV_RSM 5 | ||
60 | |||
61 | enum otg_function { | ||
62 | OTG_B_DEVICE = 0, | ||
63 | OTG_A_DEVICE | ||
64 | }; | ||
65 | |||
66 | enum mv_otg_timer { | ||
67 | A_WAIT_BCON_TIMER = 0, | ||
68 | OTG_TIMER_NUM | ||
69 | }; | ||
70 | |||
71 | /* PXA OTG state machine */ | ||
72 | struct mv_otg_ctrl { | ||
73 | /* internal variables */ | ||
74 | u8 a_set_b_hnp_en; /* A-Device set b_hnp_en */ | ||
75 | u8 b_srp_done; | ||
76 | u8 b_hnp_en; | ||
77 | |||
78 | /* OTG inputs */ | ||
79 | u8 a_bus_drop; | ||
80 | u8 a_bus_req; | ||
81 | u8 a_clr_err; | ||
82 | u8 a_bus_resume; | ||
83 | u8 a_bus_suspend; | ||
84 | u8 a_conn; | ||
85 | u8 a_sess_vld; | ||
86 | u8 a_srp_det; | ||
87 | u8 a_vbus_vld; | ||
88 | u8 b_bus_req; /* B-Device Require Bus */ | ||
89 | u8 b_bus_resume; | ||
90 | u8 b_bus_suspend; | ||
91 | u8 b_conn; | ||
92 | u8 b_se0_srp; | ||
93 | u8 b_sess_end; | ||
94 | u8 b_sess_vld; | ||
95 | u8 id; | ||
96 | u8 a_suspend_req; | ||
97 | |||
98 | /*Timer event */ | ||
99 | u8 a_aidl_bdis_timeout; | ||
100 | u8 b_ase0_brst_timeout; | ||
101 | u8 a_bidl_adis_timeout; | ||
102 | u8 a_wait_bcon_timeout; | ||
103 | |||
104 | struct timer_list timer[OTG_TIMER_NUM]; | ||
105 | }; | ||
106 | |||
107 | #define VUSBHS_MAX_PORTS 8 | ||
108 | |||
109 | struct mv_otg_regs { | ||
110 | u32 usbcmd; /* Command register */ | ||
111 | u32 usbsts; /* Status register */ | ||
112 | u32 usbintr; /* Interrupt enable */ | ||
113 | u32 frindex; /* Frame index */ | ||
114 | u32 reserved1[1]; | ||
115 | u32 deviceaddr; /* Device Address */ | ||
116 | u32 eplistaddr; /* Endpoint List Address */ | ||
117 | u32 ttctrl; /* HOST TT status and control */ | ||
118 | u32 burstsize; /* Programmable Burst Size */ | ||
119 | u32 txfilltuning; /* Host Transmit Pre-Buffer Packet Tuning */ | ||
120 | u32 reserved[4]; | ||
121 | u32 epnak; /* Endpoint NAK */ | ||
122 | u32 epnaken; /* Endpoint NAK Enable */ | ||
123 | u32 configflag; /* Configured Flag register */ | ||
124 | u32 portsc[VUSBHS_MAX_PORTS]; /* Port Status/Control x, x = 1..8 */ | ||
125 | u32 otgsc; | ||
126 | u32 usbmode; /* USB Host/Device mode */ | ||
127 | u32 epsetupstat; /* Endpoint Setup Status */ | ||
128 | u32 epprime; /* Endpoint Initialize */ | ||
129 | u32 epflush; /* Endpoint De-initialize */ | ||
130 | u32 epstatus; /* Endpoint Status */ | ||
131 | u32 epcomplete; /* Endpoint Interrupt On Complete */ | ||
132 | u32 epctrlx[16]; /* Endpoint Control, where x = 0.. 15 */ | ||
133 | u32 mcr; /* Mux Control */ | ||
134 | u32 isr; /* Interrupt Status */ | ||
135 | u32 ier; /* Interrupt Enable */ | ||
136 | }; | ||
137 | |||
138 | struct mv_otg { | ||
139 | struct otg_transceiver otg; | ||
140 | struct mv_otg_ctrl otg_ctrl; | ||
141 | |||
142 | /* base address */ | ||
143 | void __iomem *phy_regs; | ||
144 | void __iomem *cap_regs; | ||
145 | struct mv_otg_regs __iomem *op_regs; | ||
146 | |||
147 | struct platform_device *pdev; | ||
148 | int irq; | ||
149 | u32 irq_status; | ||
150 | u32 irq_en; | ||
151 | |||
152 | struct delayed_work work; | ||
153 | struct workqueue_struct *qwork; | ||
154 | |||
155 | spinlock_t wq_lock; | ||
156 | |||
157 | struct mv_usb_platform_data *pdata; | ||
158 | |||
159 | unsigned int active; | ||
160 | unsigned int clock_gating; | ||
161 | unsigned int clknum; | ||
162 | struct clk *clk[0]; | ||
163 | }; | ||
164 | |||
165 | #endif | ||
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index db2a1c6a0866..528691d5f3e2 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -185,7 +185,7 @@ static int usbhsg_dma_map(struct device *dev, | |||
185 | } | 185 | } |
186 | 186 | ||
187 | if (dma_mapping_error(dev, pkt->dma)) { | 187 | if (dma_mapping_error(dev, pkt->dma)) { |
188 | dev_err(dev, "dma mapping error %x\n", pkt->dma); | 188 | dev_err(dev, "dma mapping error %llx\n", (u64)pkt->dma); |
189 | return -EIO; | 189 | return -EIO; |
190 | } | 190 | } |
191 | 191 | ||
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index aa50eaaffcb6..df8363d252a5 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c | |||
@@ -633,7 +633,6 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) | |||
633 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | 633 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); |
634 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); | 634 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); |
635 | struct urb *urb = ureq->urb; | 635 | struct urb *urb = ureq->urb; |
636 | struct usbhsh_ep *uep = usbhsh_ep_to_uep(urb->ep); | ||
637 | struct device *dev = usbhs_priv_to_dev(priv); | 636 | struct device *dev = usbhs_priv_to_dev(priv); |
638 | int status = 0; | 637 | int status = 0; |
639 | 638 | ||
@@ -651,7 +650,7 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) | |||
651 | usbhsh_ureq_free(hpriv, ureq); | 650 | usbhsh_ureq_free(hpriv, ureq); |
652 | 651 | ||
653 | usbhsh_endpoint_sequence_save(hpriv, urb, pkt); | 652 | usbhsh_endpoint_sequence_save(hpriv, urb, pkt); |
654 | usbhsh_pipe_detach(hpriv, uep); | 653 | usbhsh_pipe_detach(hpriv, usbhsh_ep_to_uep(urb->ep)); |
655 | 654 | ||
656 | usb_hcd_unlink_urb_from_ep(hcd, urb); | 655 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
657 | usb_hcd_giveback_urb(hcd, urb, status); | 656 | usb_hcd_giveback_urb(hcd, urb, status); |
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index c2559e80d41f..feb06d6d2814 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c | |||
@@ -330,8 +330,7 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, | |||
330 | if (dir_in) | 330 | if (dir_in) |
331 | usbhsp_flags_set(pipe, IS_DIR_HOST); | 331 | usbhsp_flags_set(pipe, IS_DIR_HOST); |
332 | 332 | ||
333 | if ((is_host && !dir_in) || | 333 | if (!!is_host ^ !!dir_in) |
334 | (!is_host && dir_in)) | ||
335 | dir |= DIR_OUT; | 334 | dir |= DIR_OUT; |
336 | 335 | ||
337 | if (!dir) | 336 | if (!dir) |