diff options
author | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2009-03-27 11:14:38 -0400 |
---|---|---|
committer | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2009-03-27 11:14:38 -0400 |
commit | b92efa9abffc4a634cd2e7a0f81f8aa6310d67c9 (patch) | |
tree | 9847508d9b8d4e585f90db4a453bfbc3700c997e /drivers/usb/host | |
parent | a16fffdd8eb95ebab7dc22414896fe6493951e0e (diff) | |
parent | be0ea69674ed95e1e98cb3687a241badc756d228 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into avr32-arch
Diffstat (limited to 'drivers/usb/host')
40 files changed, 4300 insertions, 162 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2b476b6b3d4d..845479f7c707 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -24,10 +24,7 @@ config USB_EHCI_HCD | |||
24 | The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 | 24 | The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 |
25 | "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. | 25 | "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. |
26 | If your USB host controller supports USB 2.0, you will likely want to | 26 | If your USB host controller supports USB 2.0, you will likely want to |
27 | configure this Host Controller Driver. At the time of this writing, | 27 | configure this Host Controller Driver. |
28 | the primary implementation of EHCI is a chip from NEC, widely available | ||
29 | in add-on PCI cards, but implementations are in the works from other | ||
30 | vendors including Intel and Philips. Motherboard support is appearing. | ||
31 | 28 | ||
32 | EHCI controllers are packaged with "companion" host controllers (OHCI | 29 | EHCI controllers are packaged with "companion" host controllers (OHCI |
33 | or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports | 30 | or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports |
@@ -123,7 +120,7 @@ config USB_ISP116X_HCD | |||
123 | 120 | ||
124 | config USB_ISP1760_HCD | 121 | config USB_ISP1760_HCD |
125 | tristate "ISP 1760 HCD support" | 122 | tristate "ISP 1760 HCD support" |
126 | depends on USB && EXPERIMENTAL && (PCI || PPC_OF) | 123 | depends on USB && EXPERIMENTAL |
127 | ---help--- | 124 | ---help--- |
128 | The ISP1760 chip is a USB 2.0 host controller. | 125 | The ISP1760 chip is a USB 2.0 host controller. |
129 | 126 | ||
@@ -140,6 +137,7 @@ config USB_OHCI_HCD | |||
140 | tristate "OHCI HCD support" | 137 | tristate "OHCI HCD support" |
141 | depends on USB && USB_ARCH_HAS_OHCI | 138 | depends on USB && USB_ARCH_HAS_OHCI |
142 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 | 139 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 |
140 | select USB_OTG_UTILS if ARCH_OMAP | ||
143 | ---help--- | 141 | ---help--- |
144 | The Open Host Controller Interface (OHCI) is a standard for accessing | 142 | The Open Host Controller Interface (OHCI) is a standard for accessing |
145 | USB 1.1 host controller hardware. It does more in hardware than Intel's | 143 | USB 1.1 host controller hardware. It does more in hardware than Intel's |
@@ -238,6 +236,23 @@ config USB_UHCI_HCD | |||
238 | To compile this driver as a module, choose M here: the | 236 | To compile this driver as a module, choose M here: the |
239 | module will be called uhci-hcd. | 237 | module will be called uhci-hcd. |
240 | 238 | ||
239 | config USB_FHCI_HCD | ||
240 | tristate "Freescale QE USB Host Controller support" | ||
241 | depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE | ||
242 | select FSL_GTM | ||
243 | select QE_USB | ||
244 | help | ||
245 | This driver enables support for Freescale QE USB Host Controller | ||
246 | (as found on MPC8360 and MPC8323 processors), the driver supports | ||
247 | Full and Low Speed USB. | ||
248 | |||
249 | config FHCI_DEBUG | ||
250 | bool "Freescale QE USB Host Controller debug support" | ||
251 | depends on USB_FHCI_HCD && DEBUG_FS | ||
252 | help | ||
253 | Say "y" to see some FHCI debug information and statistics | ||
254 | throught debugfs. | ||
255 | |||
241 | config USB_U132_HCD | 256 | config USB_U132_HCD |
242 | tristate "Elan U132 Adapter Host Controller" | 257 | tristate "Elan U132 Adapter Host Controller" |
243 | depends on USB && USB_FTDI_ELAN | 258 | depends on USB && USB_FTDI_ELAN |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index e5f3f20787e4..f163571e33d8 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -7,6 +7,11 @@ ifeq ($(CONFIG_USB_DEBUG),y) | |||
7 | endif | 7 | endif |
8 | 8 | ||
9 | isp1760-objs := isp1760-hcd.o isp1760-if.o | 9 | isp1760-objs := isp1760-hcd.o isp1760-if.o |
10 | fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \ | ||
11 | fhci-tds.o fhci-sched.o | ||
12 | ifeq ($(CONFIG_FHCI_DEBUG),y) | ||
13 | fhci-objs += fhci-dbg.o | ||
14 | endif | ||
10 | 15 | ||
11 | obj-$(CONFIG_USB_WHCI_HCD) += whci/ | 16 | obj-$(CONFIG_USB_WHCI_HCD) += whci/ |
12 | 17 | ||
@@ -17,6 +22,7 @@ obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o | |||
17 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | 22 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o |
18 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o | 23 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o |
19 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o | 24 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o |
25 | obj-$(CONFIG_USB_FHCI_HCD) += fhci.o | ||
20 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o | 26 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o |
21 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o | 27 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o |
22 | obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o | 28 | obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 4725d15d096f..f2618d17710d 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -110,6 +110,42 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); | |||
110 | 110 | ||
111 | /*-------------------------------------------------------------------------*/ | 111 | /*-------------------------------------------------------------------------*/ |
112 | 112 | ||
113 | static void | ||
114 | timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action) | ||
115 | { | ||
116 | /* Don't override timeouts which shrink or (later) disable | ||
117 | * the async ring; just the I/O watchdog. Note that if a | ||
118 | * SHRINK were pending, OFF would never be requested. | ||
119 | */ | ||
120 | if (timer_pending(&ehci->watchdog) | ||
121 | && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) | ||
122 | & ehci->actions)) | ||
123 | return; | ||
124 | |||
125 | if (!test_and_set_bit(action, &ehci->actions)) { | ||
126 | unsigned long t; | ||
127 | |||
128 | switch (action) { | ||
129 | case TIMER_IO_WATCHDOG: | ||
130 | t = EHCI_IO_JIFFIES; | ||
131 | break; | ||
132 | case TIMER_ASYNC_OFF: | ||
133 | t = EHCI_ASYNC_JIFFIES; | ||
134 | break; | ||
135 | /* case TIMER_ASYNC_SHRINK: */ | ||
136 | default: | ||
137 | /* add a jiffie since we synch against the | ||
138 | * 8 KHz uframe counter. | ||
139 | */ | ||
140 | t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; | ||
141 | break; | ||
142 | } | ||
143 | mod_timer(&ehci->watchdog, t + jiffies); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | /*-------------------------------------------------------------------------*/ | ||
148 | |||
113 | /* | 149 | /* |
114 | * handshake - spin reading hc until handshake completes or fails | 150 | * handshake - spin reading hc until handshake completes or fails |
115 | * @ptr: address of hc register to be read | 151 | * @ptr: address of hc register to be read |
@@ -485,6 +521,7 @@ static int ehci_init(struct usb_hcd *hcd) | |||
485 | * periodic_size can shrink by USBCMD update if hcc_params allows. | 521 | * periodic_size can shrink by USBCMD update if hcc_params allows. |
486 | */ | 522 | */ |
487 | ehci->periodic_size = DEFAULT_I_TDPS; | 523 | ehci->periodic_size = DEFAULT_I_TDPS; |
524 | INIT_LIST_HEAD(&ehci->cached_itd_list); | ||
488 | if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) | 525 | if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) |
489 | return retval; | 526 | return retval; |
490 | 527 | ||
@@ -497,6 +534,7 @@ static int ehci_init(struct usb_hcd *hcd) | |||
497 | 534 | ||
498 | ehci->reclaim = NULL; | 535 | ehci->reclaim = NULL; |
499 | ehci->next_uframe = -1; | 536 | ehci->next_uframe = -1; |
537 | ehci->clock_frame = -1; | ||
500 | 538 | ||
501 | /* | 539 | /* |
502 | * dedicate a qh for the async ring head, since we couldn't unlink | 540 | * dedicate a qh for the async ring head, since we couldn't unlink |
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 0431397836f6..10d52919abbb 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c | |||
@@ -128,6 +128,7 @@ static inline void qh_put (struct ehci_qh *qh) | |||
128 | 128 | ||
129 | static void ehci_mem_cleanup (struct ehci_hcd *ehci) | 129 | static void ehci_mem_cleanup (struct ehci_hcd *ehci) |
130 | { | 130 | { |
131 | free_cached_itd_list(ehci); | ||
131 | if (ehci->async) | 132 | if (ehci->async) |
132 | qh_put (ehci->async); | 133 | qh_put (ehci->async); |
133 | ehci->async = NULL; | 134 | ehci->async = NULL; |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index bdc6e86e1f8b..abb9a7706ec7 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -230,7 +230,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
230 | pci_read_config_word(pdev, 0x62, &port_wake); | 230 | pci_read_config_word(pdev, 0x62, &port_wake); |
231 | if (port_wake & 0x0001) { | 231 | if (port_wake & 0x0001) { |
232 | dev_warn(&pdev->dev, "Enabling legacy PCI PM\n"); | 232 | dev_warn(&pdev->dev, "Enabling legacy PCI PM\n"); |
233 | device_init_wakeup(&pdev->dev, 1); | 233 | device_set_wakeup_capable(&pdev->dev, 1); |
234 | } | 234 | } |
235 | } | 235 | } |
236 | 236 | ||
@@ -432,8 +432,6 @@ static struct pci_driver ehci_pci_driver = { | |||
432 | 432 | ||
433 | #ifdef CONFIG_PM | 433 | #ifdef CONFIG_PM |
434 | .suspend = usb_hcd_pci_suspend, | 434 | .suspend = usb_hcd_pci_suspend, |
435 | .suspend_late = usb_hcd_pci_suspend_late, | ||
436 | .resume_early = usb_hcd_pci_resume_early, | ||
437 | .resume = usb_hcd_pci_resume, | 435 | .resume = usb_hcd_pci_resume, |
438 | #endif | 436 | #endif |
439 | .shutdown = usb_hcd_pci_shutdown, | 437 | .shutdown = usb_hcd_pci_shutdown, |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3712b925b315..1976b1b3778c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -333,12 +333,40 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
333 | token = hc32_to_cpu(ehci, qtd->hw_token); | 333 | token = hc32_to_cpu(ehci, qtd->hw_token); |
334 | 334 | ||
335 | /* always clean up qtds the hc de-activated */ | 335 | /* always clean up qtds the hc de-activated */ |
336 | retry_xacterr: | ||
336 | if ((token & QTD_STS_ACTIVE) == 0) { | 337 | if ((token & QTD_STS_ACTIVE) == 0) { |
337 | 338 | ||
338 | /* on STALL, error, and short reads this urb must | 339 | /* on STALL, error, and short reads this urb must |
339 | * complete and all its qtds must be recycled. | 340 | * complete and all its qtds must be recycled. |
340 | */ | 341 | */ |
341 | if ((token & QTD_STS_HALT) != 0) { | 342 | if ((token & QTD_STS_HALT) != 0) { |
343 | |||
344 | /* retry transaction errors until we | ||
345 | * reach the software xacterr limit | ||
346 | */ | ||
347 | if ((token & QTD_STS_XACT) && | ||
348 | QTD_CERR(token) == 0 && | ||
349 | --qh->xacterrs > 0 && | ||
350 | !urb->unlinked) { | ||
351 | ehci_dbg(ehci, | ||
352 | "detected XactErr len %zu/%zu retry %d\n", | ||
353 | qtd->length - QTD_LENGTH(token), qtd->length, | ||
354 | QH_XACTERR_MAX - qh->xacterrs); | ||
355 | |||
356 | /* reset the token in the qtd and the | ||
357 | * qh overlay (which still contains | ||
358 | * the qtd) so that we pick up from | ||
359 | * where we left off | ||
360 | */ | ||
361 | token &= ~QTD_STS_HALT; | ||
362 | token |= QTD_STS_ACTIVE | | ||
363 | (EHCI_TUNE_CERR << 10); | ||
364 | qtd->hw_token = cpu_to_hc32(ehci, | ||
365 | token); | ||
366 | wmb(); | ||
367 | qh->hw_token = cpu_to_hc32(ehci, token); | ||
368 | goto retry_xacterr; | ||
369 | } | ||
342 | stopped = 1; | 370 | stopped = 1; |
343 | 371 | ||
344 | /* magic dummy for some short reads; qh won't advance. | 372 | /* magic dummy for some short reads; qh won't advance. |
@@ -421,6 +449,9 @@ halt: | |||
421 | /* remove qtd; it's recycled after possible urb completion */ | 449 | /* remove qtd; it's recycled after possible urb completion */ |
422 | list_del (&qtd->qtd_list); | 450 | list_del (&qtd->qtd_list); |
423 | last = qtd; | 451 | last = qtd; |
452 | |||
453 | /* reinit the xacterr counter for the next qtd */ | ||
454 | qh->xacterrs = QH_XACTERR_MAX; | ||
424 | } | 455 | } |
425 | 456 | ||
426 | /* last urb's completion might still need calling */ | 457 | /* last urb's completion might still need calling */ |
@@ -862,6 +893,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
862 | head->qh_next.qh = qh; | 893 | head->qh_next.qh = qh; |
863 | head->hw_next = dma; | 894 | head->hw_next = dma; |
864 | 895 | ||
896 | qh->xacterrs = QH_XACTERR_MAX; | ||
865 | qh->qh_state = QH_STATE_LINKED; | 897 | qh->qh_state = QH_STATE_LINKED; |
866 | /* qtd completions reported later by interrupt */ | 898 | /* qtd completions reported later by interrupt */ |
867 | } | 899 | } |
@@ -1095,7 +1127,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1095 | prev->qh_next = qh->qh_next; | 1127 | prev->qh_next = qh->qh_next; |
1096 | wmb (); | 1128 | wmb (); |
1097 | 1129 | ||
1098 | if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) { | 1130 | /* If the controller isn't running, we don't have to wait for it */ |
1131 | if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) { | ||
1099 | /* if (unlikely (qh->reclaim != 0)) | 1132 | /* if (unlikely (qh->reclaim != 0)) |
1100 | * this will recurse, probably not much | 1133 | * this will recurse, probably not much |
1101 | */ | 1134 | */ |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index a081ee65bde6..ada5d2ba297b 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -563,7 +563,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
563 | // and this qh is active in the current uframe | 563 | // and this qh is active in the current uframe |
564 | // (and overlay token SplitXstate is false?) | 564 | // (and overlay token SplitXstate is false?) |
565 | // THEN | 565 | // THEN |
566 | // qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */); | 566 | // qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */); |
567 | 567 | ||
568 | /* high bandwidth, or otherwise part of every microframe */ | 568 | /* high bandwidth, or otherwise part of every microframe */ |
569 | if ((period = qh->period) == 0) | 569 | if ((period = qh->period) == 0) |
@@ -1004,7 +1004,8 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) | |||
1004 | 1004 | ||
1005 | is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0; | 1005 | is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0; |
1006 | stream->bEndpointAddress &= 0x0f; | 1006 | stream->bEndpointAddress &= 0x0f; |
1007 | stream->ep->hcpriv = NULL; | 1007 | if (stream->ep) |
1008 | stream->ep->hcpriv = NULL; | ||
1008 | 1009 | ||
1009 | if (stream->rescheduled) { | 1010 | if (stream->rescheduled) { |
1010 | ehci_info (ehci, "ep%d%s-iso rescheduled " | 1011 | ehci_info (ehci, "ep%d%s-iso rescheduled " |
@@ -1535,7 +1536,7 @@ itd_link_urb ( | |||
1535 | struct ehci_itd, itd_list); | 1536 | struct ehci_itd, itd_list); |
1536 | list_move_tail (&itd->itd_list, &stream->td_list); | 1537 | list_move_tail (&itd->itd_list, &stream->td_list); |
1537 | itd->stream = iso_stream_get (stream); | 1538 | itd->stream = iso_stream_get (stream); |
1538 | itd->urb = usb_get_urb (urb); | 1539 | itd->urb = urb; |
1539 | itd_init (ehci, stream, itd); | 1540 | itd_init (ehci, stream, itd); |
1540 | } | 1541 | } |
1541 | 1542 | ||
@@ -1644,7 +1645,7 @@ itd_complete ( | |||
1644 | (void) disable_periodic(ehci); | 1645 | (void) disable_periodic(ehci); |
1645 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | 1646 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; |
1646 | 1647 | ||
1647 | if (unlikely (list_empty (&stream->td_list))) { | 1648 | if (unlikely(list_is_singular(&stream->td_list))) { |
1648 | ehci_to_hcd(ehci)->self.bandwidth_allocated | 1649 | ehci_to_hcd(ehci)->self.bandwidth_allocated |
1649 | -= stream->bandwidth; | 1650 | -= stream->bandwidth; |
1650 | ehci_vdbg (ehci, | 1651 | ehci_vdbg (ehci, |
@@ -1653,14 +1654,27 @@ itd_complete ( | |||
1653 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); | 1654 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
1654 | } | 1655 | } |
1655 | iso_stream_put (ehci, stream); | 1656 | iso_stream_put (ehci, stream); |
1656 | /* OK to recycle this ITD now that its completion callback ran. */ | 1657 | |
1657 | done: | 1658 | done: |
1658 | usb_put_urb(urb); | ||
1659 | itd->urb = NULL; | 1659 | itd->urb = NULL; |
1660 | itd->stream = NULL; | 1660 | if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { |
1661 | list_move(&itd->itd_list, &stream->free_list); | 1661 | /* OK to recycle this ITD now. */ |
1662 | iso_stream_put(ehci, stream); | 1662 | itd->stream = NULL; |
1663 | 1663 | list_move(&itd->itd_list, &stream->free_list); | |
1664 | iso_stream_put(ehci, stream); | ||
1665 | } else { | ||
1666 | /* HW might remember this ITD, so we can't recycle it yet. | ||
1667 | * Move it to a safe place until a new frame starts. | ||
1668 | */ | ||
1669 | list_move(&itd->itd_list, &ehci->cached_itd_list); | ||
1670 | if (stream->refcount == 2) { | ||
1671 | /* If iso_stream_put() were called here, stream | ||
1672 | * would be freed. Instead, just prevent reuse. | ||
1673 | */ | ||
1674 | stream->ep->hcpriv = NULL; | ||
1675 | stream->ep = NULL; | ||
1676 | } | ||
1677 | } | ||
1664 | return retval; | 1678 | return retval; |
1665 | } | 1679 | } |
1666 | 1680 | ||
@@ -1934,7 +1948,7 @@ sitd_link_urb ( | |||
1934 | struct ehci_sitd, sitd_list); | 1948 | struct ehci_sitd, sitd_list); |
1935 | list_move_tail (&sitd->sitd_list, &stream->td_list); | 1949 | list_move_tail (&sitd->sitd_list, &stream->td_list); |
1936 | sitd->stream = iso_stream_get (stream); | 1950 | sitd->stream = iso_stream_get (stream); |
1937 | sitd->urb = usb_get_urb (urb); | 1951 | sitd->urb = urb; |
1938 | 1952 | ||
1939 | sitd_patch(ehci, stream, sitd, sched, packet); | 1953 | sitd_patch(ehci, stream, sitd, sched, packet); |
1940 | sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, | 1954 | sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, |
@@ -2019,7 +2033,7 @@ sitd_complete ( | |||
2019 | (void) disable_periodic(ehci); | 2033 | (void) disable_periodic(ehci); |
2020 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | 2034 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; |
2021 | 2035 | ||
2022 | if (list_empty (&stream->td_list)) { | 2036 | if (list_is_singular(&stream->td_list)) { |
2023 | ehci_to_hcd(ehci)->self.bandwidth_allocated | 2037 | ehci_to_hcd(ehci)->self.bandwidth_allocated |
2024 | -= stream->bandwidth; | 2038 | -= stream->bandwidth; |
2025 | ehci_vdbg (ehci, | 2039 | ehci_vdbg (ehci, |
@@ -2030,7 +2044,6 @@ sitd_complete ( | |||
2030 | iso_stream_put (ehci, stream); | 2044 | iso_stream_put (ehci, stream); |
2031 | /* OK to recycle this SITD now that its completion callback ran. */ | 2045 | /* OK to recycle this SITD now that its completion callback ran. */ |
2032 | done: | 2046 | done: |
2033 | usb_put_urb(urb); | ||
2034 | sitd->urb = NULL; | 2047 | sitd->urb = NULL; |
2035 | sitd->stream = NULL; | 2048 | sitd->stream = NULL; |
2036 | list_move(&sitd->sitd_list, &stream->free_list); | 2049 | list_move(&sitd->sitd_list, &stream->free_list); |
@@ -2101,6 +2114,20 @@ done: | |||
2101 | 2114 | ||
2102 | /*-------------------------------------------------------------------------*/ | 2115 | /*-------------------------------------------------------------------------*/ |
2103 | 2116 | ||
2117 | static void free_cached_itd_list(struct ehci_hcd *ehci) | ||
2118 | { | ||
2119 | struct ehci_itd *itd, *n; | ||
2120 | |||
2121 | list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) { | ||
2122 | struct ehci_iso_stream *stream = itd->stream; | ||
2123 | itd->stream = NULL; | ||
2124 | list_move(&itd->itd_list, &stream->free_list); | ||
2125 | iso_stream_put(ehci, stream); | ||
2126 | } | ||
2127 | } | ||
2128 | |||
2129 | /*-------------------------------------------------------------------------*/ | ||
2130 | |||
2104 | static void | 2131 | static void |
2105 | scan_periodic (struct ehci_hcd *ehci) | 2132 | scan_periodic (struct ehci_hcd *ehci) |
2106 | { | 2133 | { |
@@ -2115,10 +2142,17 @@ scan_periodic (struct ehci_hcd *ehci) | |||
2115 | * Touches as few pages as possible: cache-friendly. | 2142 | * Touches as few pages as possible: cache-friendly. |
2116 | */ | 2143 | */ |
2117 | now_uframe = ehci->next_uframe; | 2144 | now_uframe = ehci->next_uframe; |
2118 | if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | 2145 | if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { |
2119 | clock = ehci_readl(ehci, &ehci->regs->frame_index); | 2146 | clock = ehci_readl(ehci, &ehci->regs->frame_index); |
2120 | else | 2147 | clock_frame = (clock >> 3) % ehci->periodic_size; |
2148 | } else { | ||
2121 | clock = now_uframe + mod - 1; | 2149 | clock = now_uframe + mod - 1; |
2150 | clock_frame = -1; | ||
2151 | } | ||
2152 | if (ehci->clock_frame != clock_frame) { | ||
2153 | free_cached_itd_list(ehci); | ||
2154 | ehci->clock_frame = clock_frame; | ||
2155 | } | ||
2122 | clock %= mod; | 2156 | clock %= mod; |
2123 | clock_frame = clock >> 3; | 2157 | clock_frame = clock >> 3; |
2124 | 2158 | ||
@@ -2277,6 +2311,10 @@ restart: | |||
2277 | /* rescan the rest of this frame, then ... */ | 2311 | /* rescan the rest of this frame, then ... */ |
2278 | clock = now; | 2312 | clock = now; |
2279 | clock_frame = clock >> 3; | 2313 | clock_frame = clock >> 3; |
2314 | if (ehci->clock_frame != clock_frame) { | ||
2315 | free_cached_itd_list(ehci); | ||
2316 | ehci->clock_frame = clock_frame; | ||
2317 | } | ||
2280 | } else { | 2318 | } else { |
2281 | now_uframe++; | 2319 | now_uframe++; |
2282 | now_uframe %= mod; | 2320 | now_uframe %= mod; |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index fb7054ccf4fc..6cff195e1a36 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -87,6 +87,10 @@ struct ehci_hcd { /* one per controller */ | |||
87 | int next_uframe; /* scan periodic, start here */ | 87 | int next_uframe; /* scan periodic, start here */ |
88 | unsigned periodic_sched; /* periodic activity count */ | 88 | unsigned periodic_sched; /* periodic activity count */ |
89 | 89 | ||
90 | /* list of itds completed while clock_frame was still active */ | ||
91 | struct list_head cached_itd_list; | ||
92 | unsigned clock_frame; | ||
93 | |||
90 | /* per root hub port */ | 94 | /* per root hub port */ |
91 | unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; | 95 | unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; |
92 | 96 | ||
@@ -186,39 +190,7 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) | |||
186 | clear_bit (action, &ehci->actions); | 190 | clear_bit (action, &ehci->actions); |
187 | } | 191 | } |
188 | 192 | ||
189 | static inline void | 193 | static void free_cached_itd_list(struct ehci_hcd *ehci); |
190 | timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) | ||
191 | { | ||
192 | /* Don't override timeouts which shrink or (later) disable | ||
193 | * the async ring; just the I/O watchdog. Note that if a | ||
194 | * SHRINK were pending, OFF would never be requested. | ||
195 | */ | ||
196 | if (timer_pending(&ehci->watchdog) | ||
197 | && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) | ||
198 | & ehci->actions)) | ||
199 | return; | ||
200 | |||
201 | if (!test_and_set_bit (action, &ehci->actions)) { | ||
202 | unsigned long t; | ||
203 | |||
204 | switch (action) { | ||
205 | case TIMER_IO_WATCHDOG: | ||
206 | t = EHCI_IO_JIFFIES; | ||
207 | break; | ||
208 | case TIMER_ASYNC_OFF: | ||
209 | t = EHCI_ASYNC_JIFFIES; | ||
210 | break; | ||
211 | // case TIMER_ASYNC_SHRINK: | ||
212 | default: | ||
213 | /* add a jiffie since we synch against the | ||
214 | * 8 KHz uframe counter. | ||
215 | */ | ||
216 | t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; | ||
217 | break; | ||
218 | } | ||
219 | mod_timer(&ehci->watchdog, t + jiffies); | ||
220 | } | ||
221 | } | ||
222 | 194 | ||
223 | /*-------------------------------------------------------------------------*/ | 195 | /*-------------------------------------------------------------------------*/ |
224 | 196 | ||
@@ -281,7 +253,7 @@ struct ehci_qtd { | |||
281 | 253 | ||
282 | /* | 254 | /* |
283 | * Now the following defines are not converted using the | 255 | * Now the following defines are not converted using the |
284 | * __constant_cpu_to_le32() macro anymore, since we have to support | 256 | * cpu_to_le32() macro anymore, since we have to support |
285 | * "dynamic" switching between be and le support, so that the driver | 257 | * "dynamic" switching between be and le support, so that the driver |
286 | * can be used on one system with SoC EHCI controller using big-endian | 258 | * can be used on one system with SoC EHCI controller using big-endian |
287 | * descriptors as well as a normal little-endian PCI EHCI controller. | 259 | * descriptors as well as a normal little-endian PCI EHCI controller. |
@@ -370,6 +342,9 @@ struct ehci_qh { | |||
370 | #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ | 342 | #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ |
371 | #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ | 343 | #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ |
372 | 344 | ||
345 | u8 xacterrs; /* XactErr retry counter */ | ||
346 | #define QH_XACTERR_MAX 32 /* XactErr retry limit */ | ||
347 | |||
373 | /* periodic schedule info */ | 348 | /* periodic schedule info */ |
374 | u8 usecs; /* intr bandwidth */ | 349 | u8 usecs; /* intr bandwidth */ |
375 | u8 gap_uf; /* uframes split/csplit gap */ | 350 | u8 gap_uf; /* uframes split/csplit gap */ |
diff --git a/drivers/usb/host/fhci-dbg.c b/drivers/usb/host/fhci-dbg.c new file mode 100644 index 000000000000..ea8a4255c5da --- /dev/null +++ b/drivers/usb/host/fhci-dbg.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Freescale QUICC Engine USB Host Controller Driver | ||
3 | * | ||
4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
5 | * Shlomi Gridish <gridish@freescale.com> | ||
6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
8 | * Peter Barada <peterb@logicpd.com> | ||
9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/debugfs.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/usb.h> | ||
23 | #include "../core/hcd.h" | ||
24 | #include "fhci.h" | ||
25 | |||
26 | void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er) | ||
27 | { | ||
28 | int i; | ||
29 | |||
30 | if (usb_er == -1) { | ||
31 | fhci->usb_irq_stat[12]++; | ||
32 | return; | ||
33 | } | ||
34 | |||
35 | for (i = 0; i < 12; ++i) { | ||
36 | if (usb_er & (1 << i)) | ||
37 | fhci->usb_irq_stat[i]++; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | static int fhci_dfs_regs_show(struct seq_file *s, void *v) | ||
42 | { | ||
43 | struct fhci_hcd *fhci = s->private; | ||
44 | struct fhci_regs __iomem *regs = fhci->regs; | ||
45 | |||
46 | seq_printf(s, | ||
47 | "mode: 0x%x\n" "addr: 0x%x\n" | ||
48 | "command: 0x%x\n" "ep0: 0x%x\n" | ||
49 | "event: 0x%x\n" "mask: 0x%x\n" | ||
50 | "status: 0x%x\n" "SOF timer: %d\n" | ||
51 | "frame number: %d\n" | ||
52 | "lines status: 0x%x\n", | ||
53 | in_8(®s->usb_mod), in_8(®s->usb_addr), | ||
54 | in_8(®s->usb_comm), in_be16(®s->usb_ep[0]), | ||
55 | in_be16(®s->usb_event), in_be16(®s->usb_mask), | ||
56 | in_8(®s->usb_status), in_be16(®s->usb_sof_tmr), | ||
57 | in_be16(®s->usb_frame_num), | ||
58 | fhci_ioports_check_bus_state(fhci)); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int fhci_dfs_irq_stat_show(struct seq_file *s, void *v) | ||
64 | { | ||
65 | struct fhci_hcd *fhci = s->private; | ||
66 | int *usb_irq_stat = fhci->usb_irq_stat; | ||
67 | |||
68 | seq_printf(s, | ||
69 | "RXB: %d\n" "TXB: %d\n" "BSY: %d\n" | ||
70 | "SOF: %d\n" "TXE0: %d\n" "TXE1: %d\n" | ||
71 | "TXE2: %d\n" "TXE3: %d\n" "IDLE: %d\n" | ||
72 | "RESET: %d\n" "SFT: %d\n" "MSF: %d\n" | ||
73 | "IDLE_ONLY: %d\n", | ||
74 | usb_irq_stat[0], usb_irq_stat[1], usb_irq_stat[2], | ||
75 | usb_irq_stat[3], usb_irq_stat[4], usb_irq_stat[5], | ||
76 | usb_irq_stat[6], usb_irq_stat[7], usb_irq_stat[8], | ||
77 | usb_irq_stat[9], usb_irq_stat[10], usb_irq_stat[11], | ||
78 | usb_irq_stat[12]); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int fhci_dfs_regs_open(struct inode *inode, struct file *file) | ||
84 | { | ||
85 | return single_open(file, fhci_dfs_regs_show, inode->i_private); | ||
86 | } | ||
87 | |||
88 | static int fhci_dfs_irq_stat_open(struct inode *inode, struct file *file) | ||
89 | { | ||
90 | return single_open(file, fhci_dfs_irq_stat_show, inode->i_private); | ||
91 | } | ||
92 | |||
93 | static const struct file_operations fhci_dfs_regs_fops = { | ||
94 | .open = fhci_dfs_regs_open, | ||
95 | .read = seq_read, | ||
96 | .llseek = seq_lseek, | ||
97 | .release = single_release, | ||
98 | }; | ||
99 | |||
100 | static const struct file_operations fhci_dfs_irq_stat_fops = { | ||
101 | .open = fhci_dfs_irq_stat_open, | ||
102 | .read = seq_read, | ||
103 | .llseek = seq_lseek, | ||
104 | .release = single_release, | ||
105 | }; | ||
106 | |||
107 | void fhci_dfs_create(struct fhci_hcd *fhci) | ||
108 | { | ||
109 | struct device *dev = fhci_to_hcd(fhci)->self.controller; | ||
110 | |||
111 | fhci->dfs_root = debugfs_create_dir(dev_name(dev), NULL); | ||
112 | if (!fhci->dfs_root) { | ||
113 | WARN_ON(1); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | fhci->dfs_regs = debugfs_create_file("regs", S_IFREG | S_IRUGO, | ||
118 | fhci->dfs_root, fhci, &fhci_dfs_regs_fops); | ||
119 | |||
120 | fhci->dfs_irq_stat = debugfs_create_file("irq_stat", | ||
121 | S_IFREG | S_IRUGO, fhci->dfs_root, fhci, | ||
122 | &fhci_dfs_irq_stat_fops); | ||
123 | |||
124 | WARN_ON(!fhci->dfs_regs || !fhci->dfs_irq_stat); | ||
125 | } | ||
126 | |||
127 | void fhci_dfs_destroy(struct fhci_hcd *fhci) | ||
128 | { | ||
129 | if (!fhci->dfs_root) | ||
130 | return; | ||
131 | |||
132 | if (fhci->dfs_irq_stat) | ||
133 | debugfs_remove(fhci->dfs_irq_stat); | ||
134 | |||
135 | if (fhci->dfs_regs) | ||
136 | debugfs_remove(fhci->dfs_regs); | ||
137 | |||
138 | debugfs_remove(fhci->dfs_root); | ||
139 | } | ||
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c new file mode 100644 index 000000000000..0951818ef93b --- /dev/null +++ b/drivers/usb/host/fhci-hcd.c | |||
@@ -0,0 +1,836 @@ | |||
1 | /* | ||
2 | * Freescale QUICC Engine USB Host Controller Driver | ||
3 | * | ||
4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
5 | * Shlomi Gridish <gridish@freescale.com> | ||
6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
8 | * Peter Barada <peterb@logicpd.com> | ||
9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/list.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/usb.h> | ||
28 | #include <linux/of_platform.h> | ||
29 | #include <linux/of_gpio.h> | ||
30 | #include <asm/qe.h> | ||
31 | #include <asm/fsl_gtm.h> | ||
32 | #include "../core/hcd.h" | ||
33 | #include "fhci.h" | ||
34 | |||
35 | void fhci_start_sof_timer(struct fhci_hcd *fhci) | ||
36 | { | ||
37 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
38 | |||
39 | /* clear frame_n */ | ||
40 | out_be16(&fhci->pram->frame_num, 0); | ||
41 | |||
42 | out_be16(&fhci->regs->usb_sof_tmr, 0); | ||
43 | setbits8(&fhci->regs->usb_mod, USB_MODE_SFTE); | ||
44 | |||
45 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
46 | } | ||
47 | |||
48 | void fhci_stop_sof_timer(struct fhci_hcd *fhci) | ||
49 | { | ||
50 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
51 | |||
52 | clrbits8(&fhci->regs->usb_mod, USB_MODE_SFTE); | ||
53 | gtm_stop_timer16(fhci->timer); | ||
54 | |||
55 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
56 | } | ||
57 | |||
58 | u16 fhci_get_sof_timer_count(struct fhci_usb *usb) | ||
59 | { | ||
60 | return be16_to_cpu(in_be16(&usb->fhci->regs->usb_sof_tmr) / 12); | ||
61 | } | ||
62 | |||
63 | /* initialize the endpoint zero */ | ||
64 | static u32 endpoint_zero_init(struct fhci_usb *usb, | ||
65 | enum fhci_mem_alloc data_mem, | ||
66 | u32 ring_len) | ||
67 | { | ||
68 | u32 rc; | ||
69 | |||
70 | rc = fhci_create_ep(usb, data_mem, ring_len); | ||
71 | if (rc) | ||
72 | return rc; | ||
73 | |||
74 | /* inilialize endpoint registers */ | ||
75 | fhci_init_ep_registers(usb, usb->ep0, data_mem); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | /* enable the USB interrupts */ | ||
81 | void fhci_usb_enable_interrupt(struct fhci_usb *usb) | ||
82 | { | ||
83 | struct fhci_hcd *fhci = usb->fhci; | ||
84 | |||
85 | if (usb->intr_nesting_cnt == 1) { | ||
86 | /* initialize the USB interrupt */ | ||
87 | enable_irq(fhci_to_hcd(fhci)->irq); | ||
88 | |||
89 | /* initialize the event register and mask register */ | ||
90 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
91 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
92 | |||
93 | /* enable the timer interrupts */ | ||
94 | enable_irq(fhci->timer->irq); | ||
95 | } else if (usb->intr_nesting_cnt > 1) | ||
96 | fhci_info(fhci, "unbalanced USB interrupts nesting\n"); | ||
97 | usb->intr_nesting_cnt--; | ||
98 | } | ||
99 | |||
100 | /* diable the usb interrupt */ | ||
101 | void fhci_usb_disable_interrupt(struct fhci_usb *usb) | ||
102 | { | ||
103 | struct fhci_hcd *fhci = usb->fhci; | ||
104 | |||
105 | if (usb->intr_nesting_cnt == 0) { | ||
106 | /* diable the timer interrupt */ | ||
107 | disable_irq_nosync(fhci->timer->irq); | ||
108 | |||
109 | /* disable the usb interrupt */ | ||
110 | disable_irq_nosync(fhci_to_hcd(fhci)->irq); | ||
111 | out_be16(&usb->fhci->regs->usb_mask, 0); | ||
112 | } | ||
113 | usb->intr_nesting_cnt++; | ||
114 | } | ||
115 | |||
116 | /* enable the USB controller */ | ||
117 | static u32 fhci_usb_enable(struct fhci_hcd *fhci) | ||
118 | { | ||
119 | struct fhci_usb *usb = fhci->usb_lld; | ||
120 | |||
121 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
122 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
123 | setbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN); | ||
124 | |||
125 | mdelay(100); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /* disable the USB controller */ | ||
131 | static u32 fhci_usb_disable(struct fhci_hcd *fhci) | ||
132 | { | ||
133 | struct fhci_usb *usb = fhci->usb_lld; | ||
134 | |||
135 | fhci_usb_disable_interrupt(usb); | ||
136 | fhci_port_disable(fhci); | ||
137 | |||
138 | /* disable the usb controller */ | ||
139 | if (usb->port_status == FHCI_PORT_FULL || | ||
140 | usb->port_status == FHCI_PORT_LOW) | ||
141 | fhci_device_disconnected_interrupt(fhci); | ||
142 | |||
143 | clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /* check the bus state by polling the QE bit on the IO ports */ | ||
149 | int fhci_ioports_check_bus_state(struct fhci_hcd *fhci) | ||
150 | { | ||
151 | u8 bits = 0; | ||
152 | |||
153 | /* check USBOE,if transmitting,exit */ | ||
154 | if (!gpio_get_value(fhci->gpios[GPIO_USBOE])) | ||
155 | return -1; | ||
156 | |||
157 | /* check USBRP */ | ||
158 | if (gpio_get_value(fhci->gpios[GPIO_USBRP])) | ||
159 | bits |= 0x2; | ||
160 | |||
161 | /* check USBRN */ | ||
162 | if (gpio_get_value(fhci->gpios[GPIO_USBRN])) | ||
163 | bits |= 0x1; | ||
164 | |||
165 | return bits; | ||
166 | } | ||
167 | |||
168 | static void fhci_mem_free(struct fhci_hcd *fhci) | ||
169 | { | ||
170 | struct ed *ed; | ||
171 | struct ed *next_ed; | ||
172 | struct td *td; | ||
173 | struct td *next_td; | ||
174 | |||
175 | list_for_each_entry_safe(ed, next_ed, &fhci->empty_eds, node) { | ||
176 | list_del(&ed->node); | ||
177 | kfree(ed); | ||
178 | } | ||
179 | |||
180 | list_for_each_entry_safe(td, next_td, &fhci->empty_tds, node) { | ||
181 | list_del(&td->node); | ||
182 | kfree(td); | ||
183 | } | ||
184 | |||
185 | kfree(fhci->vroot_hub); | ||
186 | fhci->vroot_hub = NULL; | ||
187 | |||
188 | kfree(fhci->hc_list); | ||
189 | fhci->hc_list = NULL; | ||
190 | } | ||
191 | |||
192 | static int fhci_mem_init(struct fhci_hcd *fhci) | ||
193 | { | ||
194 | int i; | ||
195 | |||
196 | fhci->hc_list = kzalloc(sizeof(*fhci->hc_list), GFP_KERNEL); | ||
197 | if (!fhci->hc_list) | ||
198 | goto err; | ||
199 | |||
200 | INIT_LIST_HEAD(&fhci->hc_list->ctrl_list); | ||
201 | INIT_LIST_HEAD(&fhci->hc_list->bulk_list); | ||
202 | INIT_LIST_HEAD(&fhci->hc_list->iso_list); | ||
203 | INIT_LIST_HEAD(&fhci->hc_list->intr_list); | ||
204 | INIT_LIST_HEAD(&fhci->hc_list->done_list); | ||
205 | |||
206 | fhci->vroot_hub = kzalloc(sizeof(*fhci->vroot_hub), GFP_KERNEL); | ||
207 | if (!fhci->vroot_hub) | ||
208 | goto err; | ||
209 | |||
210 | INIT_LIST_HEAD(&fhci->empty_eds); | ||
211 | INIT_LIST_HEAD(&fhci->empty_tds); | ||
212 | |||
213 | /* initialize work queue to handle done list */ | ||
214 | fhci_tasklet.data = (unsigned long)fhci; | ||
215 | fhci->process_done_task = &fhci_tasklet; | ||
216 | |||
217 | for (i = 0; i < MAX_TDS; i++) { | ||
218 | struct td *td; | ||
219 | |||
220 | td = kmalloc(sizeof(*td), GFP_KERNEL); | ||
221 | if (!td) | ||
222 | goto err; | ||
223 | fhci_recycle_empty_td(fhci, td); | ||
224 | } | ||
225 | for (i = 0; i < MAX_EDS; i++) { | ||
226 | struct ed *ed; | ||
227 | |||
228 | ed = kmalloc(sizeof(*ed), GFP_KERNEL); | ||
229 | if (!ed) | ||
230 | goto err; | ||
231 | fhci_recycle_empty_ed(fhci, ed); | ||
232 | } | ||
233 | |||
234 | fhci->active_urbs = 0; | ||
235 | return 0; | ||
236 | err: | ||
237 | fhci_mem_free(fhci); | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | |||
241 | /* destroy the fhci_usb structure */ | ||
242 | static void fhci_usb_free(void *lld) | ||
243 | { | ||
244 | struct fhci_usb *usb = lld; | ||
245 | struct fhci_hcd *fhci = usb->fhci; | ||
246 | |||
247 | if (usb) { | ||
248 | fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF); | ||
249 | fhci_ep0_free(usb); | ||
250 | kfree(usb->actual_frame); | ||
251 | kfree(usb); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | /* initialize the USB */ | ||
256 | static int fhci_usb_init(struct fhci_hcd *fhci) | ||
257 | { | ||
258 | struct fhci_usb *usb = fhci->usb_lld; | ||
259 | |||
260 | memset_io(usb->fhci->pram, 0, FHCI_PRAM_SIZE); | ||
261 | |||
262 | usb->port_status = FHCI_PORT_DISABLED; | ||
263 | usb->max_frame_usage = FRAME_TIME_USAGE; | ||
264 | usb->sw_transaction_time = SW_FIX_TIME_BETWEEN_TRANSACTION; | ||
265 | |||
266 | usb->actual_frame = kzalloc(sizeof(*usb->actual_frame), GFP_KERNEL); | ||
267 | if (!usb->actual_frame) { | ||
268 | fhci_usb_free(usb); | ||
269 | return -ENOMEM; | ||
270 | } | ||
271 | |||
272 | INIT_LIST_HEAD(&usb->actual_frame->tds_list); | ||
273 | |||
274 | /* initializing registers on chip, clear frame number */ | ||
275 | out_be16(&fhci->pram->frame_num, 0); | ||
276 | |||
277 | /* clear rx state */ | ||
278 | out_be32(&fhci->pram->rx_state, 0); | ||
279 | |||
280 | /* set mask register */ | ||
281 | usb->saved_msk = (USB_E_TXB_MASK | | ||
282 | USB_E_TXE1_MASK | | ||
283 | USB_E_IDLE_MASK | | ||
284 | USB_E_RESET_MASK | USB_E_SFT_MASK | USB_E_MSF_MASK); | ||
285 | |||
286 | out_8(&usb->fhci->regs->usb_mod, USB_MODE_HOST | USB_MODE_EN); | ||
287 | |||
288 | /* clearing the mask register */ | ||
289 | out_be16(&usb->fhci->regs->usb_mask, 0); | ||
290 | |||
291 | /* initialing the event register */ | ||
292 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
293 | |||
294 | if (endpoint_zero_init(usb, DEFAULT_DATA_MEM, DEFAULT_RING_LEN) != 0) { | ||
295 | fhci_usb_free(usb); | ||
296 | return -EINVAL; | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | /* initialize the fhci_usb struct and the corresponding data staruct */ | ||
303 | static struct fhci_usb *fhci_create_lld(struct fhci_hcd *fhci) | ||
304 | { | ||
305 | struct fhci_usb *usb; | ||
306 | |||
307 | /* allocate memory for SCC data structure */ | ||
308 | usb = kzalloc(sizeof(*usb), GFP_KERNEL); | ||
309 | if (!usb) { | ||
310 | fhci_err(fhci, "no memory for SCC data struct\n"); | ||
311 | return NULL; | ||
312 | } | ||
313 | |||
314 | usb->fhci = fhci; | ||
315 | usb->hc_list = fhci->hc_list; | ||
316 | usb->vroot_hub = fhci->vroot_hub; | ||
317 | |||
318 | usb->transfer_confirm = fhci_transfer_confirm_callback; | ||
319 | |||
320 | return usb; | ||
321 | } | ||
322 | |||
323 | static int fhci_start(struct usb_hcd *hcd) | ||
324 | { | ||
325 | int ret; | ||
326 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
327 | |||
328 | ret = fhci_mem_init(fhci); | ||
329 | if (ret) { | ||
330 | fhci_err(fhci, "failed to allocate memory\n"); | ||
331 | goto err; | ||
332 | } | ||
333 | |||
334 | fhci->usb_lld = fhci_create_lld(fhci); | ||
335 | if (!fhci->usb_lld) { | ||
336 | fhci_err(fhci, "low level driver config failed\n"); | ||
337 | ret = -ENOMEM; | ||
338 | goto err; | ||
339 | } | ||
340 | |||
341 | ret = fhci_usb_init(fhci); | ||
342 | if (ret) { | ||
343 | fhci_err(fhci, "low level driver initialize failed\n"); | ||
344 | goto err; | ||
345 | } | ||
346 | |||
347 | spin_lock_init(&fhci->lock); | ||
348 | |||
349 | /* connect the virtual root hub */ | ||
350 | fhci->vroot_hub->dev_num = 1; /* this field may be needed to fix */ | ||
351 | fhci->vroot_hub->hub.wHubStatus = 0; | ||
352 | fhci->vroot_hub->hub.wHubChange = 0; | ||
353 | fhci->vroot_hub->port.wPortStatus = 0; | ||
354 | fhci->vroot_hub->port.wPortChange = 0; | ||
355 | |||
356 | hcd->state = HC_STATE_RUNNING; | ||
357 | |||
358 | /* | ||
359 | * From here on, khubd concurrently accesses the root | ||
360 | * hub; drivers will be talking to enumerated devices. | ||
361 | * (On restart paths, khubd already knows about the root | ||
362 | * hub and could find work as soon as we wrote FLAG_CF.) | ||
363 | * | ||
364 | * Before this point the HC was idle/ready. After, khubd | ||
365 | * and device drivers may start it running. | ||
366 | */ | ||
367 | fhci_usb_enable(fhci); | ||
368 | return 0; | ||
369 | err: | ||
370 | fhci_mem_free(fhci); | ||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | static void fhci_stop(struct usb_hcd *hcd) | ||
375 | { | ||
376 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
377 | |||
378 | fhci_usb_disable_interrupt(fhci->usb_lld); | ||
379 | fhci_usb_disable(fhci); | ||
380 | |||
381 | fhci_usb_free(fhci->usb_lld); | ||
382 | fhci->usb_lld = NULL; | ||
383 | fhci_mem_free(fhci); | ||
384 | } | ||
385 | |||
386 | static int fhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, | ||
387 | gfp_t mem_flags) | ||
388 | { | ||
389 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
390 | u32 pipe = urb->pipe; | ||
391 | int ret; | ||
392 | int i; | ||
393 | int size = 0; | ||
394 | struct urb_priv *urb_priv; | ||
395 | unsigned long flags; | ||
396 | |||
397 | switch (usb_pipetype(pipe)) { | ||
398 | case PIPE_CONTROL: | ||
399 | /* 1 td fro setup,1 for ack */ | ||
400 | size = 2; | ||
401 | case PIPE_BULK: | ||
402 | /* one td for every 4096 bytes(can be upto 8k) */ | ||
403 | size += urb->transfer_buffer_length / 4096; | ||
404 | /* ...add for any remaining bytes... */ | ||
405 | if ((urb->transfer_buffer_length % 4096) != 0) | ||
406 | size++; | ||
407 | /* ..and maybe a zero length packet to wrap it up */ | ||
408 | if (size == 0) | ||
409 | size++; | ||
410 | else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 | ||
411 | && (urb->transfer_buffer_length | ||
412 | % usb_maxpacket(urb->dev, pipe, | ||
413 | usb_pipeout(pipe))) != 0) | ||
414 | size++; | ||
415 | break; | ||
416 | case PIPE_ISOCHRONOUS: | ||
417 | size = urb->number_of_packets; | ||
418 | if (size <= 0) | ||
419 | return -EINVAL; | ||
420 | for (i = 0; i < urb->number_of_packets; i++) { | ||
421 | urb->iso_frame_desc[i].actual_length = 0; | ||
422 | urb->iso_frame_desc[i].status = (u32) (-EXDEV); | ||
423 | } | ||
424 | break; | ||
425 | case PIPE_INTERRUPT: | ||
426 | size = 1; | ||
427 | } | ||
428 | |||
429 | /* allocate the private part of the URB */ | ||
430 | urb_priv = kzalloc(sizeof(*urb_priv), mem_flags); | ||
431 | if (!urb_priv) | ||
432 | return -ENOMEM; | ||
433 | |||
434 | /* allocate the private part of the URB */ | ||
435 | urb_priv->tds = kzalloc(size * sizeof(struct td), mem_flags); | ||
436 | if (!urb_priv->tds) { | ||
437 | kfree(urb_priv); | ||
438 | return -ENOMEM; | ||
439 | } | ||
440 | |||
441 | spin_lock_irqsave(&fhci->lock, flags); | ||
442 | |||
443 | ret = usb_hcd_link_urb_to_ep(hcd, urb); | ||
444 | if (ret) | ||
445 | goto err; | ||
446 | |||
447 | /* fill the private part of the URB */ | ||
448 | urb_priv->num_of_tds = size; | ||
449 | |||
450 | urb->status = -EINPROGRESS; | ||
451 | urb->actual_length = 0; | ||
452 | urb->error_count = 0; | ||
453 | urb->hcpriv = urb_priv; | ||
454 | |||
455 | fhci_queue_urb(fhci, urb); | ||
456 | err: | ||
457 | if (ret) { | ||
458 | kfree(urb_priv->tds); | ||
459 | kfree(urb_priv); | ||
460 | } | ||
461 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | /* dequeue FHCI URB */ | ||
466 | static int fhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | ||
467 | { | ||
468 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
469 | struct fhci_usb *usb = fhci->usb_lld; | ||
470 | int ret = -EINVAL; | ||
471 | unsigned long flags; | ||
472 | |||
473 | if (!urb || !urb->dev || !urb->dev->bus) | ||
474 | goto out; | ||
475 | |||
476 | spin_lock_irqsave(&fhci->lock, flags); | ||
477 | |||
478 | ret = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
479 | if (ret) | ||
480 | goto out2; | ||
481 | |||
482 | if (usb->port_status != FHCI_PORT_DISABLED) { | ||
483 | struct urb_priv *urb_priv; | ||
484 | |||
485 | /* | ||
486 | * flag the urb's data for deletion in some upcoming | ||
487 | * SF interrupt's delete list processing | ||
488 | */ | ||
489 | urb_priv = urb->hcpriv; | ||
490 | |||
491 | if (!urb_priv || (urb_priv->state == URB_DEL)) | ||
492 | goto out2; | ||
493 | |||
494 | urb_priv->state = URB_DEL; | ||
495 | |||
496 | /* already pending? */ | ||
497 | urb_priv->ed->state = FHCI_ED_URB_DEL; | ||
498 | } else { | ||
499 | fhci_urb_complete_free(fhci, urb); | ||
500 | } | ||
501 | |||
502 | out2: | ||
503 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
504 | out: | ||
505 | return ret; | ||
506 | } | ||
507 | |||
508 | static void fhci_endpoint_disable(struct usb_hcd *hcd, | ||
509 | struct usb_host_endpoint *ep) | ||
510 | { | ||
511 | struct fhci_hcd *fhci; | ||
512 | struct ed *ed; | ||
513 | unsigned long flags; | ||
514 | |||
515 | fhci = hcd_to_fhci(hcd); | ||
516 | spin_lock_irqsave(&fhci->lock, flags); | ||
517 | ed = ep->hcpriv; | ||
518 | if (ed) { | ||
519 | while (ed->td_head != NULL) { | ||
520 | struct td *td = fhci_remove_td_from_ed(ed); | ||
521 | fhci_urb_complete_free(fhci, td->urb); | ||
522 | } | ||
523 | fhci_recycle_empty_ed(fhci, ed); | ||
524 | ep->hcpriv = NULL; | ||
525 | } | ||
526 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
527 | } | ||
528 | |||
529 | static int fhci_get_frame_number(struct usb_hcd *hcd) | ||
530 | { | ||
531 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
532 | |||
533 | return get_frame_num(fhci); | ||
534 | } | ||
535 | |||
536 | static const struct hc_driver fhci_driver = { | ||
537 | .description = "fsl,usb-fhci", | ||
538 | .product_desc = "FHCI HOST Controller", | ||
539 | .hcd_priv_size = sizeof(struct fhci_hcd), | ||
540 | |||
541 | /* generic hardware linkage */ | ||
542 | .irq = fhci_irq, | ||
543 | .flags = HCD_USB11 | HCD_MEMORY, | ||
544 | |||
545 | /* basic lifecycle operation */ | ||
546 | .start = fhci_start, | ||
547 | .stop = fhci_stop, | ||
548 | |||
549 | /* managing i/o requests and associated device resources */ | ||
550 | .urb_enqueue = fhci_urb_enqueue, | ||
551 | .urb_dequeue = fhci_urb_dequeue, | ||
552 | .endpoint_disable = fhci_endpoint_disable, | ||
553 | |||
554 | /* scheduling support */ | ||
555 | .get_frame_number = fhci_get_frame_number, | ||
556 | |||
557 | /* root hub support */ | ||
558 | .hub_status_data = fhci_hub_status_data, | ||
559 | .hub_control = fhci_hub_control, | ||
560 | }; | ||
561 | |||
562 | static int __devinit of_fhci_probe(struct of_device *ofdev, | ||
563 | const struct of_device_id *ofid) | ||
564 | { | ||
565 | struct device *dev = &ofdev->dev; | ||
566 | struct device_node *node = ofdev->node; | ||
567 | struct usb_hcd *hcd; | ||
568 | struct fhci_hcd *fhci; | ||
569 | struct resource usb_regs; | ||
570 | unsigned long pram_addr; | ||
571 | unsigned int usb_irq; | ||
572 | const char *sprop; | ||
573 | const u32 *iprop; | ||
574 | int size; | ||
575 | int ret; | ||
576 | int i; | ||
577 | int j; | ||
578 | |||
579 | if (usb_disabled()) | ||
580 | return -ENODEV; | ||
581 | |||
582 | sprop = of_get_property(node, "mode", NULL); | ||
583 | if (sprop && strcmp(sprop, "host")) | ||
584 | return -ENODEV; | ||
585 | |||
586 | hcd = usb_create_hcd(&fhci_driver, dev, dev_name(dev)); | ||
587 | if (!hcd) { | ||
588 | dev_err(dev, "could not create hcd\n"); | ||
589 | return -ENOMEM; | ||
590 | } | ||
591 | |||
592 | fhci = hcd_to_fhci(hcd); | ||
593 | hcd->self.controller = dev; | ||
594 | dev_set_drvdata(dev, hcd); | ||
595 | |||
596 | iprop = of_get_property(node, "hub-power-budget", &size); | ||
597 | if (iprop && size == sizeof(*iprop)) | ||
598 | hcd->power_budget = *iprop; | ||
599 | |||
600 | /* FHCI registers. */ | ||
601 | ret = of_address_to_resource(node, 0, &usb_regs); | ||
602 | if (ret) { | ||
603 | dev_err(dev, "could not get regs\n"); | ||
604 | goto err_regs; | ||
605 | } | ||
606 | |||
607 | hcd->regs = ioremap(usb_regs.start, usb_regs.end - usb_regs.start + 1); | ||
608 | if (!hcd->regs) { | ||
609 | dev_err(dev, "could not ioremap regs\n"); | ||
610 | ret = -ENOMEM; | ||
611 | goto err_regs; | ||
612 | } | ||
613 | fhci->regs = hcd->regs; | ||
614 | |||
615 | /* Parameter RAM. */ | ||
616 | iprop = of_get_property(node, "reg", &size); | ||
617 | if (!iprop || size < sizeof(*iprop) * 4) { | ||
618 | dev_err(dev, "can't get pram offset\n"); | ||
619 | ret = -EINVAL; | ||
620 | goto err_pram; | ||
621 | } | ||
622 | |||
623 | pram_addr = cpm_muram_alloc_fixed(iprop[2], FHCI_PRAM_SIZE); | ||
624 | if (IS_ERR_VALUE(pram_addr)) { | ||
625 | dev_err(dev, "failed to allocate usb pram\n"); | ||
626 | ret = -ENOMEM; | ||
627 | goto err_pram; | ||
628 | } | ||
629 | fhci->pram = cpm_muram_addr(pram_addr); | ||
630 | |||
631 | /* GPIOs and pins */ | ||
632 | for (i = 0; i < NUM_GPIOS; i++) { | ||
633 | int gpio; | ||
634 | enum of_gpio_flags flags; | ||
635 | |||
636 | gpio = of_get_gpio_flags(node, i, &flags); | ||
637 | fhci->gpios[i] = gpio; | ||
638 | fhci->alow_gpios[i] = flags & OF_GPIO_ACTIVE_LOW; | ||
639 | |||
640 | if (!gpio_is_valid(gpio)) { | ||
641 | if (i < GPIO_SPEED) { | ||
642 | dev_err(dev, "incorrect GPIO%d: %d\n", | ||
643 | i, gpio); | ||
644 | goto err_gpios; | ||
645 | } else { | ||
646 | dev_info(dev, "assuming board doesn't have " | ||
647 | "%s gpio\n", i == GPIO_SPEED ? | ||
648 | "speed" : "power"); | ||
649 | continue; | ||
650 | } | ||
651 | } | ||
652 | |||
653 | ret = gpio_request(gpio, dev_name(dev)); | ||
654 | if (ret) { | ||
655 | dev_err(dev, "failed to request gpio %d", i); | ||
656 | goto err_gpios; | ||
657 | } | ||
658 | |||
659 | if (i >= GPIO_SPEED) { | ||
660 | ret = gpio_direction_output(gpio, 0); | ||
661 | if (ret) { | ||
662 | dev_err(dev, "failed to set gpio %d as " | ||
663 | "an output\n", i); | ||
664 | i++; | ||
665 | goto err_gpios; | ||
666 | } | ||
667 | } | ||
668 | } | ||
669 | |||
670 | for (j = 0; j < NUM_PINS; j++) { | ||
671 | fhci->pins[j] = qe_pin_request(ofdev->node, j); | ||
672 | if (IS_ERR(fhci->pins[j])) { | ||
673 | ret = PTR_ERR(fhci->pins[j]); | ||
674 | dev_err(dev, "can't get pin %d: %d\n", j, ret); | ||
675 | goto err_pins; | ||
676 | } | ||
677 | } | ||
678 | |||
679 | /* Frame limit timer and its interrupt. */ | ||
680 | fhci->timer = gtm_get_timer16(); | ||
681 | if (IS_ERR(fhci->timer)) { | ||
682 | ret = PTR_ERR(fhci->timer); | ||
683 | dev_err(dev, "failed to request qe timer: %i", ret); | ||
684 | goto err_get_timer; | ||
685 | } | ||
686 | |||
687 | ret = request_irq(fhci->timer->irq, fhci_frame_limit_timer_irq, | ||
688 | IRQF_DISABLED, "qe timer (usb)", hcd); | ||
689 | if (ret) { | ||
690 | dev_err(dev, "failed to request timer irq"); | ||
691 | goto err_timer_irq; | ||
692 | } | ||
693 | |||
694 | /* USB Host interrupt. */ | ||
695 | usb_irq = irq_of_parse_and_map(node, 0); | ||
696 | if (usb_irq == NO_IRQ) { | ||
697 | dev_err(dev, "could not get usb irq\n"); | ||
698 | ret = -EINVAL; | ||
699 | goto err_usb_irq; | ||
700 | } | ||
701 | |||
702 | /* Clocks. */ | ||
703 | sprop = of_get_property(node, "fsl,fullspeed-clock", NULL); | ||
704 | if (sprop) { | ||
705 | fhci->fullspeed_clk = qe_clock_source(sprop); | ||
706 | if (fhci->fullspeed_clk == QE_CLK_DUMMY) { | ||
707 | dev_err(dev, "wrong fullspeed-clock\n"); | ||
708 | ret = -EINVAL; | ||
709 | goto err_clocks; | ||
710 | } | ||
711 | } | ||
712 | |||
713 | sprop = of_get_property(node, "fsl,lowspeed-clock", NULL); | ||
714 | if (sprop) { | ||
715 | fhci->lowspeed_clk = qe_clock_source(sprop); | ||
716 | if (fhci->lowspeed_clk == QE_CLK_DUMMY) { | ||
717 | dev_err(dev, "wrong lowspeed-clock\n"); | ||
718 | ret = -EINVAL; | ||
719 | goto err_clocks; | ||
720 | } | ||
721 | } | ||
722 | |||
723 | if (fhci->fullspeed_clk == QE_CLK_NONE && | ||
724 | fhci->lowspeed_clk == QE_CLK_NONE) { | ||
725 | dev_err(dev, "no clocks specified\n"); | ||
726 | ret = -EINVAL; | ||
727 | goto err_clocks; | ||
728 | } | ||
729 | |||
730 | dev_info(dev, "at 0x%p, irq %d\n", hcd->regs, usb_irq); | ||
731 | |||
732 | fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF); | ||
733 | |||
734 | /* Start with full-speed, if possible. */ | ||
735 | if (fhci->fullspeed_clk != QE_CLK_NONE) { | ||
736 | fhci_config_transceiver(fhci, FHCI_PORT_FULL); | ||
737 | qe_usb_clock_set(fhci->fullspeed_clk, USB_CLOCK); | ||
738 | } else { | ||
739 | fhci_config_transceiver(fhci, FHCI_PORT_LOW); | ||
740 | qe_usb_clock_set(fhci->lowspeed_clk, USB_CLOCK >> 3); | ||
741 | } | ||
742 | |||
743 | /* Clear and disable any pending interrupts. */ | ||
744 | out_be16(&fhci->regs->usb_event, 0xffff); | ||
745 | out_be16(&fhci->regs->usb_mask, 0); | ||
746 | |||
747 | ret = usb_add_hcd(hcd, usb_irq, IRQF_DISABLED); | ||
748 | if (ret < 0) | ||
749 | goto err_add_hcd; | ||
750 | |||
751 | fhci_dfs_create(fhci); | ||
752 | |||
753 | return 0; | ||
754 | |||
755 | err_add_hcd: | ||
756 | err_clocks: | ||
757 | irq_dispose_mapping(usb_irq); | ||
758 | err_usb_irq: | ||
759 | free_irq(fhci->timer->irq, hcd); | ||
760 | err_timer_irq: | ||
761 | gtm_put_timer16(fhci->timer); | ||
762 | err_get_timer: | ||
763 | err_pins: | ||
764 | while (--j >= 0) | ||
765 | qe_pin_free(fhci->pins[j]); | ||
766 | err_gpios: | ||
767 | while (--i >= 0) { | ||
768 | if (gpio_is_valid(fhci->gpios[i])) | ||
769 | gpio_free(fhci->gpios[i]); | ||
770 | } | ||
771 | cpm_muram_free(pram_addr); | ||
772 | err_pram: | ||
773 | iounmap(hcd->regs); | ||
774 | err_regs: | ||
775 | usb_put_hcd(hcd); | ||
776 | return ret; | ||
777 | } | ||
778 | |||
779 | static int __devexit fhci_remove(struct device *dev) | ||
780 | { | ||
781 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
782 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
783 | int i; | ||
784 | int j; | ||
785 | |||
786 | usb_remove_hcd(hcd); | ||
787 | free_irq(fhci->timer->irq, hcd); | ||
788 | gtm_put_timer16(fhci->timer); | ||
789 | cpm_muram_free(cpm_muram_offset(fhci->pram)); | ||
790 | for (i = 0; i < NUM_GPIOS; i++) { | ||
791 | if (!gpio_is_valid(fhci->gpios[i])) | ||
792 | continue; | ||
793 | gpio_free(fhci->gpios[i]); | ||
794 | } | ||
795 | for (j = 0; j < NUM_PINS; j++) | ||
796 | qe_pin_free(fhci->pins[j]); | ||
797 | fhci_dfs_destroy(fhci); | ||
798 | usb_put_hcd(hcd); | ||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | static int __devexit of_fhci_remove(struct of_device *ofdev) | ||
803 | { | ||
804 | return fhci_remove(&ofdev->dev); | ||
805 | } | ||
806 | |||
807 | static struct of_device_id of_fhci_match[] = { | ||
808 | { .compatible = "fsl,mpc8323-qe-usb", }, | ||
809 | {}, | ||
810 | }; | ||
811 | MODULE_DEVICE_TABLE(of, of_fhci_match); | ||
812 | |||
813 | static struct of_platform_driver of_fhci_driver = { | ||
814 | .name = "fsl,usb-fhci", | ||
815 | .match_table = of_fhci_match, | ||
816 | .probe = of_fhci_probe, | ||
817 | .remove = __devexit_p(of_fhci_remove), | ||
818 | }; | ||
819 | |||
820 | static int __init fhci_module_init(void) | ||
821 | { | ||
822 | return of_register_platform_driver(&of_fhci_driver); | ||
823 | } | ||
824 | module_init(fhci_module_init); | ||
825 | |||
826 | static void __exit fhci_module_exit(void) | ||
827 | { | ||
828 | of_unregister_platform_driver(&of_fhci_driver); | ||
829 | } | ||
830 | module_exit(fhci_module_exit); | ||
831 | |||
832 | MODULE_DESCRIPTION("USB Freescale Host Controller Interface Driver"); | ||
833 | MODULE_AUTHOR("Shlomi Gridish <gridish@freescale.com>, " | ||
834 | "Jerry Huang <Chang-Ming.Huang@freescale.com>, " | ||
835 | "Anton Vorontsov <avorontsov@ru.mvista.com>"); | ||
836 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/host/fhci-hub.c b/drivers/usb/host/fhci-hub.c new file mode 100644 index 000000000000..0cfaedc3e124 --- /dev/null +++ b/drivers/usb/host/fhci-hub.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * Freescale QUICC Engine USB Host Controller Driver | ||
3 | * | ||
4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
5 | * Shlomi Gridish <gridish@freescale.com> | ||
6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
8 | * Peter Barada <peterb@logicpd.com> | ||
9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/usb.h> | ||
25 | #include <linux/gpio.h> | ||
26 | #include <asm/qe.h> | ||
27 | #include "../core/hcd.h" | ||
28 | #include "fhci.h" | ||
29 | |||
30 | /* virtual root hub specific descriptor */ | ||
31 | static u8 root_hub_des[] = { | ||
32 | 0x09, /* blength */ | ||
33 | 0x29, /* bDescriptorType;hub-descriptor */ | ||
34 | 0x01, /* bNbrPorts */ | ||
35 | 0x00, /* wHubCharacteristics */ | ||
36 | 0x00, | ||
37 | 0x01, /* bPwrOn2pwrGood;2ms */ | ||
38 | 0x00, /* bHubContrCurrent;0mA */ | ||
39 | 0x00, /* DeviceRemoveable */ | ||
40 | 0xff, /* PortPwrCtrlMask */ | ||
41 | }; | ||
42 | |||
43 | static void fhci_gpio_set_value(struct fhci_hcd *fhci, int gpio_nr, bool on) | ||
44 | { | ||
45 | int gpio = fhci->gpios[gpio_nr]; | ||
46 | bool alow = fhci->alow_gpios[gpio_nr]; | ||
47 | |||
48 | if (!gpio_is_valid(gpio)) | ||
49 | return; | ||
50 | |||
51 | gpio_set_value(gpio, on ^ alow); | ||
52 | mdelay(5); | ||
53 | } | ||
54 | |||
55 | void fhci_config_transceiver(struct fhci_hcd *fhci, | ||
56 | enum fhci_port_status status) | ||
57 | { | ||
58 | fhci_dbg(fhci, "-> %s: %d\n", __func__, status); | ||
59 | |||
60 | switch (status) { | ||
61 | case FHCI_PORT_POWER_OFF: | ||
62 | fhci_gpio_set_value(fhci, GPIO_POWER, false); | ||
63 | break; | ||
64 | case FHCI_PORT_DISABLED: | ||
65 | case FHCI_PORT_WAITING: | ||
66 | fhci_gpio_set_value(fhci, GPIO_POWER, true); | ||
67 | break; | ||
68 | case FHCI_PORT_LOW: | ||
69 | fhci_gpio_set_value(fhci, GPIO_SPEED, false); | ||
70 | break; | ||
71 | case FHCI_PORT_FULL: | ||
72 | fhci_gpio_set_value(fhci, GPIO_SPEED, true); | ||
73 | break; | ||
74 | default: | ||
75 | WARN_ON(1); | ||
76 | break; | ||
77 | } | ||
78 | |||
79 | fhci_dbg(fhci, "<- %s: %d\n", __func__, status); | ||
80 | } | ||
81 | |||
82 | /* disable the USB port by clearing the EN bit in the USBMOD register */ | ||
83 | void fhci_port_disable(struct fhci_hcd *fhci) | ||
84 | { | ||
85 | struct fhci_usb *usb = (struct fhci_usb *)fhci->usb_lld; | ||
86 | enum fhci_port_status port_status; | ||
87 | |||
88 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
89 | |||
90 | fhci_stop_sof_timer(fhci); | ||
91 | |||
92 | fhci_flush_all_transmissions(usb); | ||
93 | |||
94 | fhci_usb_disable_interrupt((struct fhci_usb *)fhci->usb_lld); | ||
95 | port_status = usb->port_status; | ||
96 | usb->port_status = FHCI_PORT_DISABLED; | ||
97 | |||
98 | /* Enable IDLE since we want to know if something comes along */ | ||
99 | usb->saved_msk |= USB_E_IDLE_MASK; | ||
100 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
101 | |||
102 | /* check if during the disconnection process attached new device */ | ||
103 | if (port_status == FHCI_PORT_WAITING) | ||
104 | fhci_device_connected_interrupt(fhci); | ||
105 | usb->vroot_hub->port.wPortStatus &= ~USB_PORT_STAT_ENABLE; | ||
106 | usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_ENABLE; | ||
107 | fhci_usb_enable_interrupt((struct fhci_usb *)fhci->usb_lld); | ||
108 | |||
109 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
110 | } | ||
111 | |||
112 | /* enable the USB port by setting the EN bit in the USBMOD register */ | ||
113 | void fhci_port_enable(void *lld) | ||
114 | { | ||
115 | struct fhci_usb *usb = (struct fhci_usb *)lld; | ||
116 | struct fhci_hcd *fhci = usb->fhci; | ||
117 | |||
118 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
119 | |||
120 | fhci_config_transceiver(fhci, usb->port_status); | ||
121 | |||
122 | if ((usb->port_status != FHCI_PORT_FULL) && | ||
123 | (usb->port_status != FHCI_PORT_LOW)) | ||
124 | fhci_start_sof_timer(fhci); | ||
125 | |||
126 | usb->vroot_hub->port.wPortStatus |= USB_PORT_STAT_ENABLE; | ||
127 | usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_ENABLE; | ||
128 | |||
129 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
130 | } | ||
131 | |||
132 | void fhci_io_port_generate_reset(struct fhci_hcd *fhci) | ||
133 | { | ||
134 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
135 | |||
136 | gpio_direction_output(fhci->gpios[GPIO_USBOE], 0); | ||
137 | gpio_direction_output(fhci->gpios[GPIO_USBTP], 0); | ||
138 | gpio_direction_output(fhci->gpios[GPIO_USBTN], 0); | ||
139 | |||
140 | mdelay(5); | ||
141 | |||
142 | qe_pin_set_dedicated(fhci->pins[PIN_USBOE]); | ||
143 | qe_pin_set_dedicated(fhci->pins[PIN_USBTP]); | ||
144 | qe_pin_set_dedicated(fhci->pins[PIN_USBTN]); | ||
145 | |||
146 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
147 | } | ||
148 | |||
149 | /* generate the RESET condition on the bus */ | ||
150 | void fhci_port_reset(void *lld) | ||
151 | { | ||
152 | struct fhci_usb *usb = (struct fhci_usb *)lld; | ||
153 | struct fhci_hcd *fhci = usb->fhci; | ||
154 | u8 mode; | ||
155 | u16 mask; | ||
156 | |||
157 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
158 | |||
159 | fhci_stop_sof_timer(fhci); | ||
160 | /* disable the USB controller */ | ||
161 | mode = in_8(&fhci->regs->usb_mod); | ||
162 | out_8(&fhci->regs->usb_mod, mode & (~USB_MODE_EN)); | ||
163 | |||
164 | /* disable idle interrupts */ | ||
165 | mask = in_be16(&fhci->regs->usb_mask); | ||
166 | out_be16(&fhci->regs->usb_mask, mask & (~USB_E_IDLE_MASK)); | ||
167 | |||
168 | fhci_io_port_generate_reset(fhci); | ||
169 | |||
170 | /* enable interrupt on this endpoint */ | ||
171 | out_be16(&fhci->regs->usb_mask, mask); | ||
172 | |||
173 | /* enable the USB controller */ | ||
174 | mode = in_8(&fhci->regs->usb_mod); | ||
175 | out_8(&fhci->regs->usb_mod, mode | USB_MODE_EN); | ||
176 | fhci_start_sof_timer(fhci); | ||
177 | |||
178 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
179 | } | ||
180 | |||
181 | int fhci_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
182 | { | ||
183 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
184 | int ret = 0; | ||
185 | unsigned long flags; | ||
186 | |||
187 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
188 | |||
189 | spin_lock_irqsave(&fhci->lock, flags); | ||
190 | |||
191 | if (fhci->vroot_hub->port.wPortChange & (USB_PORT_STAT_C_CONNECTION | | ||
192 | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_SUSPEND | | ||
193 | USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_OVERCURRENT)) { | ||
194 | *buf = 1 << 1; | ||
195 | ret = 1; | ||
196 | fhci_dbg(fhci, "-- %s\n", __func__); | ||
197 | } | ||
198 | |||
199 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
200 | |||
201 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
202 | |||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | int fhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | ||
207 | u16 wIndex, char *buf, u16 wLength) | ||
208 | { | ||
209 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
210 | int retval = 0; | ||
211 | int len = 0; | ||
212 | struct usb_hub_status *hub_status; | ||
213 | struct usb_port_status *port_status; | ||
214 | unsigned long flags; | ||
215 | |||
216 | spin_lock_irqsave(&fhci->lock, flags); | ||
217 | |||
218 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
219 | |||
220 | switch (typeReq) { | ||
221 | case ClearHubFeature: | ||
222 | switch (wValue) { | ||
223 | case C_HUB_LOCAL_POWER: | ||
224 | case C_HUB_OVER_CURRENT: | ||
225 | break; | ||
226 | default: | ||
227 | goto error; | ||
228 | } | ||
229 | break; | ||
230 | case ClearPortFeature: | ||
231 | fhci->vroot_hub->feature &= (1 << wValue); | ||
232 | |||
233 | switch (wValue) { | ||
234 | case USB_PORT_FEAT_ENABLE: | ||
235 | fhci->vroot_hub->port.wPortStatus &= | ||
236 | ~USB_PORT_STAT_ENABLE; | ||
237 | fhci_port_disable(fhci); | ||
238 | break; | ||
239 | case USB_PORT_FEAT_C_ENABLE: | ||
240 | fhci->vroot_hub->port.wPortChange &= | ||
241 | ~USB_PORT_STAT_C_ENABLE; | ||
242 | break; | ||
243 | case USB_PORT_FEAT_SUSPEND: | ||
244 | fhci->vroot_hub->port.wPortStatus &= | ||
245 | ~USB_PORT_STAT_SUSPEND; | ||
246 | fhci_stop_sof_timer(fhci); | ||
247 | break; | ||
248 | case USB_PORT_FEAT_C_SUSPEND: | ||
249 | fhci->vroot_hub->port.wPortChange &= | ||
250 | ~USB_PORT_STAT_C_SUSPEND; | ||
251 | break; | ||
252 | case USB_PORT_FEAT_POWER: | ||
253 | fhci->vroot_hub->port.wPortStatus &= | ||
254 | ~USB_PORT_STAT_POWER; | ||
255 | fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF); | ||
256 | break; | ||
257 | case USB_PORT_FEAT_C_CONNECTION: | ||
258 | fhci->vroot_hub->port.wPortChange &= | ||
259 | ~USB_PORT_STAT_C_CONNECTION; | ||
260 | break; | ||
261 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
262 | fhci->vroot_hub->port.wPortChange &= | ||
263 | ~USB_PORT_STAT_C_OVERCURRENT; | ||
264 | break; | ||
265 | case USB_PORT_FEAT_C_RESET: | ||
266 | fhci->vroot_hub->port.wPortChange &= | ||
267 | ~USB_PORT_STAT_C_RESET; | ||
268 | break; | ||
269 | default: | ||
270 | goto error; | ||
271 | } | ||
272 | break; | ||
273 | case GetHubDescriptor: | ||
274 | memcpy(buf, root_hub_des, sizeof(root_hub_des)); | ||
275 | buf[3] = 0x11; /* per-port power, no ovrcrnt */ | ||
276 | len = (buf[0] < wLength) ? buf[0] : wLength; | ||
277 | break; | ||
278 | case GetHubStatus: | ||
279 | hub_status = (struct usb_hub_status *)buf; | ||
280 | hub_status->wHubStatus = | ||
281 | cpu_to_le16(fhci->vroot_hub->hub.wHubStatus); | ||
282 | hub_status->wHubChange = | ||
283 | cpu_to_le16(fhci->vroot_hub->hub.wHubChange); | ||
284 | len = 4; | ||
285 | break; | ||
286 | case GetPortStatus: | ||
287 | port_status = (struct usb_port_status *)buf; | ||
288 | port_status->wPortStatus = | ||
289 | cpu_to_le16(fhci->vroot_hub->port.wPortStatus); | ||
290 | port_status->wPortChange = | ||
291 | cpu_to_le16(fhci->vroot_hub->port.wPortChange); | ||
292 | len = 4; | ||
293 | break; | ||
294 | case SetHubFeature: | ||
295 | switch (wValue) { | ||
296 | case C_HUB_OVER_CURRENT: | ||
297 | case C_HUB_LOCAL_POWER: | ||
298 | break; | ||
299 | default: | ||
300 | goto error; | ||
301 | } | ||
302 | break; | ||
303 | case SetPortFeature: | ||
304 | fhci->vroot_hub->feature |= (1 << wValue); | ||
305 | |||
306 | switch (wValue) { | ||
307 | case USB_PORT_FEAT_ENABLE: | ||
308 | fhci->vroot_hub->port.wPortStatus |= | ||
309 | USB_PORT_STAT_ENABLE; | ||
310 | fhci_port_enable(fhci->usb_lld); | ||
311 | break; | ||
312 | case USB_PORT_FEAT_SUSPEND: | ||
313 | fhci->vroot_hub->port.wPortStatus |= | ||
314 | USB_PORT_STAT_SUSPEND; | ||
315 | fhci_stop_sof_timer(fhci); | ||
316 | break; | ||
317 | case USB_PORT_FEAT_RESET: | ||
318 | fhci->vroot_hub->port.wPortStatus |= | ||
319 | USB_PORT_STAT_RESET; | ||
320 | fhci_port_reset(fhci->usb_lld); | ||
321 | fhci->vroot_hub->port.wPortStatus |= | ||
322 | USB_PORT_STAT_ENABLE; | ||
323 | fhci->vroot_hub->port.wPortStatus &= | ||
324 | ~USB_PORT_STAT_RESET; | ||
325 | break; | ||
326 | case USB_PORT_FEAT_POWER: | ||
327 | fhci->vroot_hub->port.wPortStatus |= | ||
328 | USB_PORT_STAT_POWER; | ||
329 | fhci_config_transceiver(fhci, FHCI_PORT_WAITING); | ||
330 | break; | ||
331 | default: | ||
332 | goto error; | ||
333 | } | ||
334 | break; | ||
335 | default: | ||
336 | error: | ||
337 | retval = -EPIPE; | ||
338 | } | ||
339 | |||
340 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
341 | |||
342 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
343 | |||
344 | return retval; | ||
345 | } | ||
diff --git a/drivers/usb/host/fhci-mem.c b/drivers/usb/host/fhci-mem.c new file mode 100644 index 000000000000..2c0736c99712 --- /dev/null +++ b/drivers/usb/host/fhci-mem.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Freescale QUICC Engine USB Host Controller Driver | ||
3 | * | ||
4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
5 | * Shlomi Gridish <gridish@freescale.com> | ||
6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
8 | * Peter Barada <peterb@logicpd.com> | ||
9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/usb.h> | ||
23 | #include "../core/hcd.h" | ||
24 | #include "fhci.h" | ||
25 | |||
26 | static void init_td(struct td *td) | ||
27 | { | ||
28 | memset(td, 0, sizeof(*td)); | ||
29 | INIT_LIST_HEAD(&td->node); | ||
30 | INIT_LIST_HEAD(&td->frame_lh); | ||
31 | } | ||
32 | |||
33 | static void init_ed(struct ed *ed) | ||
34 | { | ||
35 | memset(ed, 0, sizeof(*ed)); | ||
36 | INIT_LIST_HEAD(&ed->td_list); | ||
37 | INIT_LIST_HEAD(&ed->node); | ||
38 | } | ||
39 | |||
40 | static struct td *get_empty_td(struct fhci_hcd *fhci) | ||
41 | { | ||
42 | struct td *td; | ||
43 | |||
44 | if (!list_empty(&fhci->empty_tds)) { | ||
45 | td = list_entry(fhci->empty_tds.next, struct td, node); | ||
46 | list_del(fhci->empty_tds.next); | ||
47 | } else { | ||
48 | td = kmalloc(sizeof(*td), GFP_ATOMIC); | ||
49 | if (!td) | ||
50 | fhci_err(fhci, "No memory to allocate to TD\n"); | ||
51 | else | ||
52 | init_td(td); | ||
53 | } | ||
54 | |||
55 | return td; | ||
56 | } | ||
57 | |||
58 | void fhci_recycle_empty_td(struct fhci_hcd *fhci, struct td *td) | ||
59 | { | ||
60 | init_td(td); | ||
61 | list_add(&td->node, &fhci->empty_tds); | ||
62 | } | ||
63 | |||
64 | struct ed *fhci_get_empty_ed(struct fhci_hcd *fhci) | ||
65 | { | ||
66 | struct ed *ed; | ||
67 | |||
68 | if (!list_empty(&fhci->empty_eds)) { | ||
69 | ed = list_entry(fhci->empty_eds.next, struct ed, node); | ||
70 | list_del(fhci->empty_eds.next); | ||
71 | } else { | ||
72 | ed = kmalloc(sizeof(*ed), GFP_ATOMIC); | ||
73 | if (!ed) | ||
74 | fhci_err(fhci, "No memory to allocate to ED\n"); | ||
75 | else | ||
76 | init_ed(ed); | ||
77 | } | ||
78 | |||
79 | return ed; | ||
80 | } | ||
81 | |||
82 | void fhci_recycle_empty_ed(struct fhci_hcd *fhci, struct ed *ed) | ||
83 | { | ||
84 | init_ed(ed); | ||
85 | list_add(&ed->node, &fhci->empty_eds); | ||
86 | } | ||
87 | |||
88 | struct td *fhci_td_fill(struct fhci_hcd *fhci, struct urb *urb, | ||
89 | struct urb_priv *urb_priv, struct ed *ed, u16 index, | ||
90 | enum fhci_ta_type type, int toggle, u8 *data, u32 len, | ||
91 | u16 interval, u16 start_frame, bool ioc) | ||
92 | { | ||
93 | struct td *td = get_empty_td(fhci); | ||
94 | |||
95 | if (!td) | ||
96 | return NULL; | ||
97 | |||
98 | td->urb = urb; | ||
99 | td->ed = ed; | ||
100 | td->type = type; | ||
101 | td->toggle = toggle; | ||
102 | td->data = data; | ||
103 | td->len = len; | ||
104 | td->iso_index = index; | ||
105 | td->interval = interval; | ||
106 | td->start_frame = start_frame; | ||
107 | td->ioc = ioc; | ||
108 | td->status = USB_TD_OK; | ||
109 | |||
110 | urb_priv->tds[index] = td; | ||
111 | |||
112 | return td; | ||
113 | } | ||
diff --git a/drivers/usb/host/fhci-q.c b/drivers/usb/host/fhci-q.c new file mode 100644 index 000000000000..b0a1446ba292 --- /dev/null +++ b/drivers/usb/host/fhci-q.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Freescale QUICC Engine USB Host Controller Driver | ||
3 | * | ||
4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
5 | * Shlomi Gridish <gridish@freescale.com> | ||
6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
8 | * Peter Barada <peterb@logicpd.com> | ||
9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/list.h> | ||
23 | #include <linux/usb.h> | ||
24 | #include "../core/hcd.h" | ||
25 | #include "fhci.h" | ||
26 | |||
27 | /* maps the hardware error code to the USB error code */ | ||
28 | static int status_to_error(u32 status) | ||
29 | { | ||
30 | if (status == USB_TD_OK) | ||
31 | return 0; | ||
32 | else if (status & USB_TD_RX_ER_CRC) | ||
33 | return -EILSEQ; | ||
34 | else if (status & USB_TD_RX_ER_NONOCT) | ||
35 | return -EPROTO; | ||
36 | else if (status & USB_TD_RX_ER_OVERUN) | ||
37 | return -ECOMM; | ||
38 | else if (status & USB_TD_RX_ER_BITSTUFF) | ||
39 | return -EPROTO; | ||
40 | else if (status & USB_TD_RX_ER_PID) | ||
41 | return -EILSEQ; | ||
42 | else if (status & (USB_TD_TX_ER_NAK | USB_TD_TX_ER_TIMEOUT)) | ||
43 | return -ETIMEDOUT; | ||
44 | else if (status & USB_TD_TX_ER_STALL) | ||
45 | return -EPIPE; | ||
46 | else if (status & USB_TD_TX_ER_UNDERUN) | ||
47 | return -ENOSR; | ||
48 | else if (status & USB_TD_RX_DATA_UNDERUN) | ||
49 | return -EREMOTEIO; | ||
50 | else if (status & USB_TD_RX_DATA_OVERUN) | ||
51 | return -EOVERFLOW; | ||
52 | else | ||
53 | return -EINVAL; | ||
54 | } | ||
55 | |||
56 | void fhci_add_td_to_frame(struct fhci_time_frame *frame, struct td *td) | ||
57 | { | ||
58 | list_add_tail(&td->frame_lh, &frame->tds_list); | ||
59 | } | ||
60 | |||
61 | void fhci_add_tds_to_ed(struct ed *ed, struct td **td_list, int number) | ||
62 | { | ||
63 | int i; | ||
64 | |||
65 | for (i = 0; i < number; i++) { | ||
66 | struct td *td = td_list[i]; | ||
67 | list_add_tail(&td->node, &ed->td_list); | ||
68 | } | ||
69 | if (ed->td_head == NULL) | ||
70 | ed->td_head = td_list[0]; | ||
71 | } | ||
72 | |||
73 | static struct td *peek_td_from_ed(struct ed *ed) | ||
74 | { | ||
75 | struct td *td; | ||
76 | |||
77 | if (!list_empty(&ed->td_list)) | ||
78 | td = list_entry(ed->td_list.next, struct td, node); | ||
79 | else | ||
80 | td = NULL; | ||
81 | |||
82 | return td; | ||
83 | } | ||
84 | |||
85 | struct td *fhci_remove_td_from_frame(struct fhci_time_frame *frame) | ||
86 | { | ||
87 | struct td *td; | ||
88 | |||
89 | if (!list_empty(&frame->tds_list)) { | ||
90 | td = list_entry(frame->tds_list.next, struct td, frame_lh); | ||
91 | list_del_init(frame->tds_list.next); | ||
92 | } else | ||
93 | td = NULL; | ||
94 | |||
95 | return td; | ||
96 | } | ||
97 | |||
98 | struct td *fhci_peek_td_from_frame(struct fhci_time_frame *frame) | ||
99 | { | ||
100 | struct td *td; | ||
101 | |||
102 | if (!list_empty(&frame->tds_list)) | ||
103 | td = list_entry(frame->tds_list.next, struct td, frame_lh); | ||
104 | else | ||
105 | td = NULL; | ||
106 | |||
107 | return td; | ||
108 | } | ||
109 | |||
110 | struct td *fhci_remove_td_from_ed(struct ed *ed) | ||
111 | { | ||
112 | struct td *td; | ||
113 | |||
114 | if (!list_empty(&ed->td_list)) { | ||
115 | td = list_entry(ed->td_list.next, struct td, node); | ||
116 | list_del_init(ed->td_list.next); | ||
117 | |||
118 | /* if this TD was the ED's head, find next TD */ | ||
119 | if (!list_empty(&ed->td_list)) | ||
120 | ed->td_head = list_entry(ed->td_list.next, struct td, | ||
121 | node); | ||
122 | else | ||
123 | ed->td_head = NULL; | ||
124 | } else | ||
125 | td = NULL; | ||
126 | |||
127 | return td; | ||
128 | } | ||
129 | |||
130 | struct td *fhci_remove_td_from_done_list(struct fhci_controller_list *p_list) | ||
131 | { | ||
132 | struct td *td; | ||
133 | |||
134 | if (!list_empty(&p_list->done_list)) { | ||
135 | td = list_entry(p_list->done_list.next, struct td, node); | ||
136 | list_del_init(p_list->done_list.next); | ||
137 | } else | ||
138 | td = NULL; | ||
139 | |||
140 | return td; | ||
141 | } | ||
142 | |||
143 | void fhci_move_td_from_ed_to_done_list(struct fhci_usb *usb, struct ed *ed) | ||
144 | { | ||
145 | struct td *td; | ||
146 | |||
147 | td = ed->td_head; | ||
148 | list_del_init(&td->node); | ||
149 | |||
150 | /* If this TD was the ED's head,find next TD */ | ||
151 | if (!list_empty(&ed->td_list)) | ||
152 | ed->td_head = list_entry(ed->td_list.next, struct td, node); | ||
153 | else { | ||
154 | ed->td_head = NULL; | ||
155 | ed->state = FHCI_ED_SKIP; | ||
156 | } | ||
157 | ed->toggle_carry = td->toggle; | ||
158 | list_add_tail(&td->node, &usb->hc_list->done_list); | ||
159 | if (td->ioc) | ||
160 | usb->transfer_confirm(usb->fhci); | ||
161 | } | ||
162 | |||
163 | /* free done FHCI URB resource such as ED and TD */ | ||
164 | static void free_urb_priv(struct fhci_hcd *fhci, struct urb *urb) | ||
165 | { | ||
166 | int i; | ||
167 | struct urb_priv *urb_priv = urb->hcpriv; | ||
168 | struct ed *ed = urb_priv->ed; | ||
169 | |||
170 | for (i = 0; i < urb_priv->num_of_tds; i++) { | ||
171 | list_del_init(&urb_priv->tds[i]->node); | ||
172 | fhci_recycle_empty_td(fhci, urb_priv->tds[i]); | ||
173 | } | ||
174 | |||
175 | /* if this TD was the ED's head,find the next TD */ | ||
176 | if (!list_empty(&ed->td_list)) | ||
177 | ed->td_head = list_entry(ed->td_list.next, struct td, node); | ||
178 | else | ||
179 | ed->td_head = NULL; | ||
180 | |||
181 | kfree(urb_priv->tds); | ||
182 | kfree(urb_priv); | ||
183 | urb->hcpriv = NULL; | ||
184 | |||
185 | /* if this TD was the ED's head,find next TD */ | ||
186 | if (ed->td_head == NULL) | ||
187 | list_del_init(&ed->node); | ||
188 | fhci->active_urbs--; | ||
189 | } | ||
190 | |||
191 | /* this routine called to complete and free done URB */ | ||
192 | void fhci_urb_complete_free(struct fhci_hcd *fhci, struct urb *urb) | ||
193 | { | ||
194 | free_urb_priv(fhci, urb); | ||
195 | |||
196 | if (urb->status == -EINPROGRESS) { | ||
197 | if (urb->actual_length != urb->transfer_buffer_length && | ||
198 | urb->transfer_flags & URB_SHORT_NOT_OK) | ||
199 | urb->status = -EREMOTEIO; | ||
200 | else | ||
201 | urb->status = 0; | ||
202 | } | ||
203 | |||
204 | usb_hcd_unlink_urb_from_ep(fhci_to_hcd(fhci), urb); | ||
205 | |||
206 | spin_unlock(&fhci->lock); | ||
207 | |||
208 | usb_hcd_giveback_urb(fhci_to_hcd(fhci), urb, urb->status); | ||
209 | |||
210 | spin_lock(&fhci->lock); | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | * caculate transfer length/stats and update the urb | ||
215 | * Precondition: irqsafe(only for urb-?status locking) | ||
216 | */ | ||
217 | void fhci_done_td(struct urb *urb, struct td *td) | ||
218 | { | ||
219 | struct ed *ed = td->ed; | ||
220 | u32 cc = td->status; | ||
221 | |||
222 | /* ISO...drivers see per-TD length/status */ | ||
223 | if (ed->mode == FHCI_TF_ISO) { | ||
224 | u32 len; | ||
225 | if (!(urb->transfer_flags & URB_SHORT_NOT_OK && | ||
226 | cc == USB_TD_RX_DATA_UNDERUN)) | ||
227 | cc = USB_TD_OK; | ||
228 | |||
229 | if (usb_pipeout(urb->pipe)) | ||
230 | len = urb->iso_frame_desc[td->iso_index].length; | ||
231 | else | ||
232 | len = td->actual_len; | ||
233 | |||
234 | urb->actual_length += len; | ||
235 | urb->iso_frame_desc[td->iso_index].actual_length = len; | ||
236 | urb->iso_frame_desc[td->iso_index].status = | ||
237 | status_to_error(cc); | ||
238 | } | ||
239 | |||
240 | /* BULK,INT,CONTROL... drivers see aggregate length/status, | ||
241 | * except that "setup" bytes aren't counted and "short" transfers | ||
242 | * might not be reported as errors. | ||
243 | */ | ||
244 | else { | ||
245 | if (td->error_cnt >= 3) | ||
246 | urb->error_count = 3; | ||
247 | |||
248 | /* control endpoint only have soft stalls */ | ||
249 | |||
250 | /* update packet status if needed(short may be ok) */ | ||
251 | if (!(urb->transfer_flags & URB_SHORT_NOT_OK) && | ||
252 | cc == USB_TD_RX_DATA_UNDERUN) { | ||
253 | ed->state = FHCI_ED_OPER; | ||
254 | cc = USB_TD_OK; | ||
255 | } | ||
256 | if (cc != USB_TD_OK) { | ||
257 | if (urb->status == -EINPROGRESS) | ||
258 | urb->status = status_to_error(cc); | ||
259 | } | ||
260 | |||
261 | /* count all non-empty packets except control SETUP packet */ | ||
262 | if (td->type != FHCI_TA_SETUP || td->iso_index != 0) | ||
263 | urb->actual_length += td->actual_len; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | /* there are some pedning request to unlink */ | ||
268 | void fhci_del_ed_list(struct fhci_hcd *fhci, struct ed *ed) | ||
269 | { | ||
270 | struct td *td = peek_td_from_ed(ed); | ||
271 | struct urb *urb = td->urb; | ||
272 | struct urb_priv *urb_priv = urb->hcpriv; | ||
273 | |||
274 | if (urb_priv->state == URB_DEL) { | ||
275 | td = fhci_remove_td_from_ed(ed); | ||
276 | /* HC may have partly processed this TD */ | ||
277 | if (td->status != USB_TD_INPROGRESS) | ||
278 | fhci_done_td(urb, td); | ||
279 | |||
280 | /* URB is done;clean up */ | ||
281 | if (++(urb_priv->tds_cnt) == urb_priv->num_of_tds) | ||
282 | fhci_urb_complete_free(fhci, urb); | ||
283 | } | ||
284 | } | ||
diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c new file mode 100644 index 000000000000..bb63b68ddb77 --- /dev/null +++ b/drivers/usb/host/fhci-sched.c | |||
@@ -0,0 +1,888 @@ | |||
1 | /* | ||
2 | * Freescale QUICC Engine USB Host Controller Driver | ||
3 | * | ||
4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
5 | * Shlomi Gridish <gridish@freescale.com> | ||
6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
8 | * Peter Barada <peterb@logicpd.com> | ||
9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/usb.h> | ||
27 | #include <asm/qe.h> | ||
28 | #include <asm/fsl_gtm.h> | ||
29 | #include "../core/hcd.h" | ||
30 | #include "fhci.h" | ||
31 | |||
32 | static void recycle_frame(struct fhci_usb *usb, struct packet *pkt) | ||
33 | { | ||
34 | pkt->data = NULL; | ||
35 | pkt->len = 0; | ||
36 | pkt->status = USB_TD_OK; | ||
37 | pkt->info = 0; | ||
38 | pkt->priv_data = NULL; | ||
39 | |||
40 | cq_put(usb->ep0->empty_frame_Q, pkt); | ||
41 | } | ||
42 | |||
43 | /* confirm submitted packet */ | ||
44 | void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt) | ||
45 | { | ||
46 | struct td *td; | ||
47 | struct packet *td_pkt; | ||
48 | struct ed *ed; | ||
49 | u32 trans_len; | ||
50 | bool td_done = false; | ||
51 | |||
52 | td = fhci_remove_td_from_frame(usb->actual_frame); | ||
53 | td_pkt = td->pkt; | ||
54 | trans_len = pkt->len; | ||
55 | td->status = pkt->status; | ||
56 | if (td->type == FHCI_TA_IN && td_pkt->info & PKT_DUMMY_PACKET) { | ||
57 | if ((td->data + td->actual_len) && trans_len) | ||
58 | memcpy(td->data + td->actual_len, pkt->data, | ||
59 | trans_len); | ||
60 | cq_put(usb->ep0->dummy_packets_Q, pkt->data); | ||
61 | } | ||
62 | |||
63 | recycle_frame(usb, pkt); | ||
64 | |||
65 | ed = td->ed; | ||
66 | if (ed->mode == FHCI_TF_ISO) { | ||
67 | if (ed->td_list.next->next != &ed->td_list) { | ||
68 | struct td *td_next = | ||
69 | list_entry(ed->td_list.next->next, struct td, | ||
70 | node); | ||
71 | |||
72 | td_next->start_frame = usb->actual_frame->frame_num; | ||
73 | } | ||
74 | td->actual_len = trans_len; | ||
75 | td_done = true; | ||
76 | } else if ((td->status & USB_TD_ERROR) && | ||
77 | !(td->status & USB_TD_TX_ER_NAK)) { | ||
78 | /* | ||
79 | * There was an error on the transaction (but not NAK). | ||
80 | * If it is fatal error (data underrun, stall, bad pid or 3 | ||
81 | * errors exceeded), mark this TD as done. | ||
82 | */ | ||
83 | if ((td->status & USB_TD_RX_DATA_UNDERUN) || | ||
84 | (td->status & USB_TD_TX_ER_STALL) || | ||
85 | (td->status & USB_TD_RX_ER_PID) || | ||
86 | (++td->error_cnt >= 3)) { | ||
87 | ed->state = FHCI_ED_HALTED; | ||
88 | td_done = true; | ||
89 | |||
90 | if (td->status & USB_TD_RX_DATA_UNDERUN) { | ||
91 | fhci_dbg(usb->fhci, "td err fu\n"); | ||
92 | td->toggle = !td->toggle; | ||
93 | td->actual_len += trans_len; | ||
94 | } else { | ||
95 | fhci_dbg(usb->fhci, "td err f!u\n"); | ||
96 | } | ||
97 | } else { | ||
98 | fhci_dbg(usb->fhci, "td err !f\n"); | ||
99 | /* it is not a fatal error -retry this transaction */ | ||
100 | td->nak_cnt = 0; | ||
101 | td->error_cnt++; | ||
102 | td->status = USB_TD_OK; | ||
103 | } | ||
104 | } else if (td->status & USB_TD_TX_ER_NAK) { | ||
105 | /* there was a NAK response */ | ||
106 | fhci_vdbg(usb->fhci, "td nack\n"); | ||
107 | td->nak_cnt++; | ||
108 | td->error_cnt = 0; | ||
109 | td->status = USB_TD_OK; | ||
110 | } else { | ||
111 | /* there was no error on transaction */ | ||
112 | td->error_cnt = 0; | ||
113 | td->nak_cnt = 0; | ||
114 | td->toggle = !td->toggle; | ||
115 | td->actual_len += trans_len; | ||
116 | |||
117 | if (td->len == td->actual_len) | ||
118 | td_done = true; | ||
119 | } | ||
120 | |||
121 | if (td_done) | ||
122 | fhci_move_td_from_ed_to_done_list(usb, ed); | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * Flush all transmitted packets from BDs | ||
127 | * This routine is called when disabling the USB port to flush all | ||
128 | * transmissions that are allready scheduled in the BDs | ||
129 | */ | ||
130 | void fhci_flush_all_transmissions(struct fhci_usb *usb) | ||
131 | { | ||
132 | u8 mode; | ||
133 | struct td *td; | ||
134 | |||
135 | mode = in_8(&usb->fhci->regs->usb_mod); | ||
136 | clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN); | ||
137 | |||
138 | fhci_flush_bds(usb); | ||
139 | |||
140 | while ((td = fhci_peek_td_from_frame(usb->actual_frame)) != NULL) { | ||
141 | struct packet *pkt = td->pkt; | ||
142 | |||
143 | pkt->status = USB_TD_TX_ER_TIMEOUT; | ||
144 | fhci_transaction_confirm(usb, pkt); | ||
145 | } | ||
146 | |||
147 | usb->actual_frame->frame_status = FRAME_END_TRANSMISSION; | ||
148 | |||
149 | /* reset the event register */ | ||
150 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
151 | /* enable the USB controller */ | ||
152 | out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN); | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * This function forms the packet and transmit the packet. This function | ||
157 | * will handle all endpoint type:ISO,interrupt,control and bulk | ||
158 | */ | ||
159 | static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) | ||
160 | { | ||
161 | u32 fw_transaction_time, len = 0; | ||
162 | struct packet *pkt; | ||
163 | u8 *data = NULL; | ||
164 | |||
165 | /* calcalate data address,len and toggle and then add the transaction */ | ||
166 | if (td->toggle == USB_TD_TOGGLE_CARRY) | ||
167 | td->toggle = ed->toggle_carry; | ||
168 | |||
169 | switch (ed->mode) { | ||
170 | case FHCI_TF_ISO: | ||
171 | len = td->len; | ||
172 | if (td->type != FHCI_TA_IN) | ||
173 | data = td->data; | ||
174 | break; | ||
175 | case FHCI_TF_CTRL: | ||
176 | case FHCI_TF_BULK: | ||
177 | len = min(td->len - td->actual_len, ed->max_pkt_size); | ||
178 | if (!((td->type == FHCI_TA_IN) && | ||
179 | ((len + td->actual_len) == td->len))) | ||
180 | data = td->data + td->actual_len; | ||
181 | break; | ||
182 | case FHCI_TF_INTR: | ||
183 | len = min(td->len, ed->max_pkt_size); | ||
184 | if (!((td->type == FHCI_TA_IN) && | ||
185 | ((td->len + CRC_SIZE) >= ed->max_pkt_size))) | ||
186 | data = td->data; | ||
187 | break; | ||
188 | default: | ||
189 | break; | ||
190 | } | ||
191 | |||
192 | if (usb->port_status == FHCI_PORT_FULL) | ||
193 | fw_transaction_time = (((len + PROTOCOL_OVERHEAD) * 11) >> 4); | ||
194 | else | ||
195 | fw_transaction_time = ((len + PROTOCOL_OVERHEAD) * 6); | ||
196 | |||
197 | /* check if there's enough space in this frame to submit this TD */ | ||
198 | if (usb->actual_frame->total_bytes + len + PROTOCOL_OVERHEAD >= | ||
199 | usb->max_bytes_per_frame) { | ||
200 | fhci_vdbg(usb->fhci, "not enough space in this frame: " | ||
201 | "%d %d %d\n", usb->actual_frame->total_bytes, len, | ||
202 | usb->max_bytes_per_frame); | ||
203 | return -1; | ||
204 | } | ||
205 | |||
206 | /* check if there's enough time in this frame to submit this TD */ | ||
207 | if (usb->actual_frame->frame_status != FRAME_IS_PREPARED && | ||
208 | (usb->actual_frame->frame_status & FRAME_END_TRANSMISSION || | ||
209 | (fw_transaction_time + usb->sw_transaction_time >= | ||
210 | 1000 - fhci_get_sof_timer_count(usb)))) { | ||
211 | fhci_dbg(usb->fhci, "not enough time in this frame\n"); | ||
212 | return -1; | ||
213 | } | ||
214 | |||
215 | /* update frame object fields before transmitting */ | ||
216 | pkt = cq_get(usb->ep0->empty_frame_Q); | ||
217 | if (!pkt) { | ||
218 | fhci_dbg(usb->fhci, "there is no empty frame\n"); | ||
219 | return -1; | ||
220 | } | ||
221 | td->pkt = pkt; | ||
222 | |||
223 | pkt->info = 0; | ||
224 | if (data == NULL) { | ||
225 | data = cq_get(usb->ep0->dummy_packets_Q); | ||
226 | BUG_ON(!data); | ||
227 | pkt->info = PKT_DUMMY_PACKET; | ||
228 | } | ||
229 | pkt->data = data; | ||
230 | pkt->len = len; | ||
231 | pkt->status = USB_TD_OK; | ||
232 | /* update TD status field before transmitting */ | ||
233 | td->status = USB_TD_INPROGRESS; | ||
234 | /* update actual frame time object with the actual transmission */ | ||
235 | usb->actual_frame->total_bytes += (len + PROTOCOL_OVERHEAD); | ||
236 | fhci_add_td_to_frame(usb->actual_frame, td); | ||
237 | |||
238 | if (usb->port_status != FHCI_PORT_FULL && | ||
239 | usb->port_status != FHCI_PORT_LOW) { | ||
240 | pkt->status = USB_TD_TX_ER_TIMEOUT; | ||
241 | pkt->len = 0; | ||
242 | fhci_transaction_confirm(usb, pkt); | ||
243 | } else if (fhci_host_transaction(usb, pkt, td->type, ed->dev_addr, | ||
244 | ed->ep_addr, ed->mode, ed->speed, td->toggle)) { | ||
245 | /* remove TD from actual frame */ | ||
246 | list_del_init(&td->frame_lh); | ||
247 | td->status = USB_TD_OK; | ||
248 | if (pkt->info & PKT_DUMMY_PACKET) | ||
249 | cq_put(usb->ep0->dummy_packets_Q, pkt->data); | ||
250 | recycle_frame(usb, pkt); | ||
251 | usb->actual_frame->total_bytes -= (len + PROTOCOL_OVERHEAD); | ||
252 | fhci_err(usb->fhci, "host transaction failed\n"); | ||
253 | return -1; | ||
254 | } | ||
255 | |||
256 | return len; | ||
257 | } | ||
258 | |||
259 | static void move_head_to_tail(struct list_head *list) | ||
260 | { | ||
261 | struct list_head *node = list->next; | ||
262 | |||
263 | if (!list_empty(list)) { | ||
264 | list_del(node); | ||
265 | list_add_tail(node, list); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * This function goes through the endpoint list and schedules the | ||
271 | * transactions within this list | ||
272 | */ | ||
273 | static int scan_ed_list(struct fhci_usb *usb, | ||
274 | struct list_head *list, enum fhci_tf_mode list_type) | ||
275 | { | ||
276 | static const int frame_part[4] = { | ||
277 | [FHCI_TF_CTRL] = MAX_BYTES_PER_FRAME, | ||
278 | [FHCI_TF_ISO] = (MAX_BYTES_PER_FRAME * | ||
279 | MAX_PERIODIC_FRAME_USAGE) / 100, | ||
280 | [FHCI_TF_BULK] = MAX_BYTES_PER_FRAME, | ||
281 | [FHCI_TF_INTR] = (MAX_BYTES_PER_FRAME * | ||
282 | MAX_PERIODIC_FRAME_USAGE) / 100 | ||
283 | }; | ||
284 | struct ed *ed; | ||
285 | struct td *td; | ||
286 | int ans = 1; | ||
287 | u32 save_transaction_time = usb->sw_transaction_time; | ||
288 | |||
289 | list_for_each_entry(ed, list, node) { | ||
290 | td = ed->td_head; | ||
291 | |||
292 | if (!td || (td && td->status == USB_TD_INPROGRESS)) | ||
293 | continue; | ||
294 | |||
295 | if (ed->state != FHCI_ED_OPER) { | ||
296 | if (ed->state == FHCI_ED_URB_DEL) { | ||
297 | td->status = USB_TD_OK; | ||
298 | fhci_move_td_from_ed_to_done_list(usb, ed); | ||
299 | ed->state = FHCI_ED_SKIP; | ||
300 | } | ||
301 | continue; | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * if it isn't interrupt pipe or it is not iso pipe and the | ||
306 | * interval time passed | ||
307 | */ | ||
308 | if ((list_type == FHCI_TF_INTR || list_type == FHCI_TF_ISO) && | ||
309 | (((usb->actual_frame->frame_num - | ||
310 | td->start_frame) & 0x7ff) < td->interval)) | ||
311 | continue; | ||
312 | |||
313 | if (add_packet(usb, ed, td) < 0) | ||
314 | continue; | ||
315 | |||
316 | /* update time stamps in the TD */ | ||
317 | td->start_frame = usb->actual_frame->frame_num; | ||
318 | usb->sw_transaction_time += save_transaction_time; | ||
319 | |||
320 | if (usb->actual_frame->total_bytes >= | ||
321 | usb->max_bytes_per_frame) { | ||
322 | usb->actual_frame->frame_status = | ||
323 | FRAME_DATA_END_TRANSMISSION; | ||
324 | fhci_push_dummy_bd(usb->ep0); | ||
325 | ans = 0; | ||
326 | break; | ||
327 | } | ||
328 | |||
329 | if (usb->actual_frame->total_bytes >= frame_part[list_type]) | ||
330 | break; | ||
331 | } | ||
332 | |||
333 | /* be fair to each ED(move list head around) */ | ||
334 | move_head_to_tail(list); | ||
335 | usb->sw_transaction_time = save_transaction_time; | ||
336 | |||
337 | return ans; | ||
338 | } | ||
339 | |||
340 | static u32 rotate_frames(struct fhci_usb *usb) | ||
341 | { | ||
342 | struct fhci_hcd *fhci = usb->fhci; | ||
343 | |||
344 | if (!list_empty(&usb->actual_frame->tds_list)) { | ||
345 | if ((((in_be16(&fhci->pram->frame_num) & 0x07ff) - | ||
346 | usb->actual_frame->frame_num) & 0x7ff) > 5) | ||
347 | fhci_flush_actual_frame(usb); | ||
348 | else | ||
349 | return -EINVAL; | ||
350 | } | ||
351 | |||
352 | usb->actual_frame->frame_status = FRAME_IS_PREPARED; | ||
353 | usb->actual_frame->frame_num = in_be16(&fhci->pram->frame_num) & 0x7ff; | ||
354 | usb->actual_frame->total_bytes = 0; | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * This function schedule the USB transaction and will process the | ||
361 | * endpoint in the following order: iso, interrupt, control and bulk. | ||
362 | */ | ||
363 | void fhci_schedule_transactions(struct fhci_usb *usb) | ||
364 | { | ||
365 | int left = 1; | ||
366 | |||
367 | if (usb->actual_frame->frame_status & FRAME_END_TRANSMISSION) | ||
368 | if (rotate_frames(usb) != 0) | ||
369 | return; | ||
370 | |||
371 | if (usb->actual_frame->frame_status & FRAME_END_TRANSMISSION) | ||
372 | return; | ||
373 | |||
374 | if (usb->actual_frame->total_bytes == 0) { | ||
375 | /* | ||
376 | * schedule the next available ISO transfer | ||
377 | *or next stage of the ISO transfer | ||
378 | */ | ||
379 | scan_ed_list(usb, &usb->hc_list->iso_list, FHCI_TF_ISO); | ||
380 | |||
381 | /* | ||
382 | * schedule the next available interrupt transfer or | ||
383 | * the next stage of the interrupt transfer | ||
384 | */ | ||
385 | scan_ed_list(usb, &usb->hc_list->intr_list, FHCI_TF_INTR); | ||
386 | |||
387 | /* | ||
388 | * schedule the next available control transfer | ||
389 | * or the next stage of the control transfer | ||
390 | */ | ||
391 | left = scan_ed_list(usb, &usb->hc_list->ctrl_list, | ||
392 | FHCI_TF_CTRL); | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * schedule the next available bulk transfer or the next stage of the | ||
397 | * bulk transfer | ||
398 | */ | ||
399 | if (left > 0) | ||
400 | scan_ed_list(usb, &usb->hc_list->bulk_list, FHCI_TF_BULK); | ||
401 | } | ||
402 | |||
403 | /* Handles SOF interrupt */ | ||
404 | static void sof_interrupt(struct fhci_hcd *fhci) | ||
405 | { | ||
406 | struct fhci_usb *usb = fhci->usb_lld; | ||
407 | |||
408 | if ((usb->port_status == FHCI_PORT_DISABLED) && | ||
409 | (usb->vroot_hub->port.wPortStatus & USB_PORT_STAT_CONNECTION) && | ||
410 | !(usb->vroot_hub->port.wPortChange & USB_PORT_STAT_C_CONNECTION)) { | ||
411 | if (usb->vroot_hub->port.wPortStatus & USB_PORT_STAT_LOW_SPEED) | ||
412 | usb->port_status = FHCI_PORT_LOW; | ||
413 | else | ||
414 | usb->port_status = FHCI_PORT_FULL; | ||
415 | /* Disable IDLE */ | ||
416 | usb->saved_msk &= ~USB_E_IDLE_MASK; | ||
417 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
418 | } | ||
419 | |||
420 | gtm_set_exact_timer16(fhci->timer, usb->max_frame_usage, false); | ||
421 | |||
422 | fhci_host_transmit_actual_frame(usb); | ||
423 | usb->actual_frame->frame_status = FRAME_IS_TRANSMITTED; | ||
424 | |||
425 | fhci_schedule_transactions(usb); | ||
426 | } | ||
427 | |||
428 | /* Handles device disconnected interrupt on port */ | ||
429 | void fhci_device_disconnected_interrupt(struct fhci_hcd *fhci) | ||
430 | { | ||
431 | struct fhci_usb *usb = fhci->usb_lld; | ||
432 | |||
433 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
434 | |||
435 | fhci_usb_disable_interrupt(usb); | ||
436 | clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS); | ||
437 | usb->port_status = FHCI_PORT_DISABLED; | ||
438 | |||
439 | fhci_stop_sof_timer(fhci); | ||
440 | |||
441 | /* Enable IDLE since we want to know if something comes along */ | ||
442 | usb->saved_msk |= USB_E_IDLE_MASK; | ||
443 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
444 | |||
445 | usb->vroot_hub->port.wPortStatus &= ~USB_PORT_STAT_CONNECTION; | ||
446 | usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_CONNECTION; | ||
447 | usb->max_bytes_per_frame = 0; | ||
448 | fhci_usb_enable_interrupt(usb); | ||
449 | |||
450 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
451 | } | ||
452 | |||
453 | /* detect a new device connected on the USB port */ | ||
454 | void fhci_device_connected_interrupt(struct fhci_hcd *fhci) | ||
455 | { | ||
456 | |||
457 | struct fhci_usb *usb = fhci->usb_lld; | ||
458 | int state; | ||
459 | int ret; | ||
460 | |||
461 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
462 | |||
463 | fhci_usb_disable_interrupt(usb); | ||
464 | state = fhci_ioports_check_bus_state(fhci); | ||
465 | |||
466 | /* low-speed device was connected to the USB port */ | ||
467 | if (state == 1) { | ||
468 | ret = qe_usb_clock_set(fhci->lowspeed_clk, USB_CLOCK >> 3); | ||
469 | if (ret) { | ||
470 | fhci_warn(fhci, "Low-Speed device is not supported, " | ||
471 | "try use BRGx\n"); | ||
472 | goto out; | ||
473 | } | ||
474 | |||
475 | usb->port_status = FHCI_PORT_LOW; | ||
476 | setbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS); | ||
477 | usb->vroot_hub->port.wPortStatus |= | ||
478 | (USB_PORT_STAT_LOW_SPEED | | ||
479 | USB_PORT_STAT_CONNECTION); | ||
480 | usb->vroot_hub->port.wPortChange |= | ||
481 | USB_PORT_STAT_C_CONNECTION; | ||
482 | usb->max_bytes_per_frame = | ||
483 | (MAX_BYTES_PER_FRAME >> 3) - 7; | ||
484 | fhci_port_enable(usb); | ||
485 | } else if (state == 2) { | ||
486 | ret = qe_usb_clock_set(fhci->fullspeed_clk, USB_CLOCK); | ||
487 | if (ret) { | ||
488 | fhci_warn(fhci, "Full-Speed device is not supported, " | ||
489 | "try use CLKx\n"); | ||
490 | goto out; | ||
491 | } | ||
492 | |||
493 | usb->port_status = FHCI_PORT_FULL; | ||
494 | clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS); | ||
495 | usb->vroot_hub->port.wPortStatus &= | ||
496 | ~USB_PORT_STAT_LOW_SPEED; | ||
497 | usb->vroot_hub->port.wPortStatus |= | ||
498 | USB_PORT_STAT_CONNECTION; | ||
499 | usb->vroot_hub->port.wPortChange |= | ||
500 | USB_PORT_STAT_C_CONNECTION; | ||
501 | usb->max_bytes_per_frame = (MAX_BYTES_PER_FRAME - 15); | ||
502 | fhci_port_enable(usb); | ||
503 | } | ||
504 | out: | ||
505 | fhci_usb_enable_interrupt(usb); | ||
506 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
507 | } | ||
508 | |||
509 | irqreturn_t fhci_frame_limit_timer_irq(int irq, void *_hcd) | ||
510 | { | ||
511 | struct usb_hcd *hcd = _hcd; | ||
512 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
513 | struct fhci_usb *usb = fhci->usb_lld; | ||
514 | |||
515 | spin_lock(&fhci->lock); | ||
516 | |||
517 | gtm_set_exact_timer16(fhci->timer, 1000, false); | ||
518 | |||
519 | if (usb->actual_frame->frame_status == FRAME_IS_TRANSMITTED) { | ||
520 | usb->actual_frame->frame_status = FRAME_TIMER_END_TRANSMISSION; | ||
521 | fhci_push_dummy_bd(usb->ep0); | ||
522 | } | ||
523 | |||
524 | fhci_schedule_transactions(usb); | ||
525 | |||
526 | spin_unlock(&fhci->lock); | ||
527 | |||
528 | return IRQ_HANDLED; | ||
529 | } | ||
530 | |||
531 | /* Cancel transmission on the USB endpoint */ | ||
532 | static void abort_transmission(struct fhci_usb *usb) | ||
533 | { | ||
534 | fhci_dbg(usb->fhci, "-> %s\n", __func__); | ||
535 | /* issue stop Tx command */ | ||
536 | qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB, EP_ZERO, 0); | ||
537 | /* flush Tx FIFOs */ | ||
538 | out_8(&usb->fhci->regs->usb_comm, USB_CMD_FLUSH_FIFO | EP_ZERO); | ||
539 | udelay(1000); | ||
540 | /* reset Tx BDs */ | ||
541 | fhci_flush_bds(usb); | ||
542 | /* issue restart Tx command */ | ||
543 | qe_issue_cmd(QE_USB_RESTART_TX, QE_CR_SUBBLOCK_USB, EP_ZERO, 0); | ||
544 | fhci_dbg(usb->fhci, "<- %s\n", __func__); | ||
545 | } | ||
546 | |||
547 | irqreturn_t fhci_irq(struct usb_hcd *hcd) | ||
548 | { | ||
549 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
550 | struct fhci_usb *usb; | ||
551 | u16 usb_er = 0; | ||
552 | unsigned long flags; | ||
553 | |||
554 | spin_lock_irqsave(&fhci->lock, flags); | ||
555 | |||
556 | usb = fhci->usb_lld; | ||
557 | |||
558 | usb_er |= in_be16(&usb->fhci->regs->usb_event) & | ||
559 | in_be16(&usb->fhci->regs->usb_mask); | ||
560 | |||
561 | /* clear event bits for next time */ | ||
562 | out_be16(&usb->fhci->regs->usb_event, usb_er); | ||
563 | |||
564 | fhci_dbg_isr(fhci, usb_er); | ||
565 | |||
566 | if (usb_er & USB_E_RESET_MASK) { | ||
567 | if ((usb->port_status == FHCI_PORT_FULL) || | ||
568 | (usb->port_status == FHCI_PORT_LOW)) { | ||
569 | fhci_device_disconnected_interrupt(fhci); | ||
570 | usb_er &= ~USB_E_IDLE_MASK; | ||
571 | } else if (usb->port_status == FHCI_PORT_WAITING) { | ||
572 | usb->port_status = FHCI_PORT_DISCONNECTING; | ||
573 | |||
574 | /* Turn on IDLE since we want to disconnect */ | ||
575 | usb->saved_msk |= USB_E_IDLE_MASK; | ||
576 | out_be16(&usb->fhci->regs->usb_event, | ||
577 | usb->saved_msk); | ||
578 | } else if (usb->port_status == FHCI_PORT_DISABLED) { | ||
579 | if (fhci_ioports_check_bus_state(fhci) == 1 && | ||
580 | usb->port_status != FHCI_PORT_LOW && | ||
581 | usb->port_status != FHCI_PORT_FULL) | ||
582 | fhci_device_connected_interrupt(fhci); | ||
583 | } | ||
584 | usb_er &= ~USB_E_RESET_MASK; | ||
585 | } | ||
586 | |||
587 | if (usb_er & USB_E_MSF_MASK) { | ||
588 | abort_transmission(fhci->usb_lld); | ||
589 | usb_er &= ~USB_E_MSF_MASK; | ||
590 | } | ||
591 | |||
592 | if (usb_er & (USB_E_SOF_MASK | USB_E_SFT_MASK)) { | ||
593 | sof_interrupt(fhci); | ||
594 | usb_er &= ~(USB_E_SOF_MASK | USB_E_SFT_MASK); | ||
595 | } | ||
596 | |||
597 | if (usb_er & USB_E_TXB_MASK) { | ||
598 | fhci_tx_conf_interrupt(fhci->usb_lld); | ||
599 | usb_er &= ~USB_E_TXB_MASK; | ||
600 | } | ||
601 | |||
602 | if (usb_er & USB_E_TXE1_MASK) { | ||
603 | fhci_tx_conf_interrupt(fhci->usb_lld); | ||
604 | usb_er &= ~USB_E_TXE1_MASK; | ||
605 | } | ||
606 | |||
607 | if (usb_er & USB_E_IDLE_MASK) { | ||
608 | if (usb->port_status == FHCI_PORT_DISABLED && | ||
609 | usb->port_status != FHCI_PORT_LOW && | ||
610 | usb->port_status != FHCI_PORT_FULL) { | ||
611 | usb_er &= ~USB_E_RESET_MASK; | ||
612 | fhci_device_connected_interrupt(fhci); | ||
613 | } else if (usb->port_status == | ||
614 | FHCI_PORT_DISCONNECTING) { | ||
615 | /* XXX usb->port_status = FHCI_PORT_WAITING; */ | ||
616 | /* Disable IDLE */ | ||
617 | usb->saved_msk &= ~USB_E_IDLE_MASK; | ||
618 | out_be16(&usb->fhci->regs->usb_mask, | ||
619 | usb->saved_msk); | ||
620 | } else { | ||
621 | fhci_dbg_isr(fhci, -1); | ||
622 | } | ||
623 | |||
624 | usb_er &= ~USB_E_IDLE_MASK; | ||
625 | } | ||
626 | |||
627 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
628 | |||
629 | return IRQ_HANDLED; | ||
630 | } | ||
631 | |||
632 | |||
633 | /* | ||
634 | * Process normal completions(error or sucess) and clean the schedule. | ||
635 | * | ||
636 | * This is the main path for handing urbs back to drivers. The only other patth | ||
637 | * is process_del_list(),which unlinks URBs by scanning EDs,instead of scanning | ||
638 | * the (re-reversed) done list as this does. | ||
639 | */ | ||
640 | static void process_done_list(unsigned long data) | ||
641 | { | ||
642 | struct urb *urb; | ||
643 | struct ed *ed; | ||
644 | struct td *td; | ||
645 | struct urb_priv *urb_priv; | ||
646 | struct fhci_hcd *fhci = (struct fhci_hcd *)data; | ||
647 | |||
648 | disable_irq(fhci->timer->irq); | ||
649 | disable_irq(fhci_to_hcd(fhci)->irq); | ||
650 | spin_lock(&fhci->lock); | ||
651 | |||
652 | td = fhci_remove_td_from_done_list(fhci->hc_list); | ||
653 | while (td != NULL) { | ||
654 | urb = td->urb; | ||
655 | urb_priv = urb->hcpriv; | ||
656 | ed = td->ed; | ||
657 | |||
658 | /* update URB's length and status from TD */ | ||
659 | fhci_done_td(urb, td); | ||
660 | urb_priv->tds_cnt++; | ||
661 | |||
662 | /* | ||
663 | * if all this urb's TDs are done, call complete() | ||
664 | * Interrupt transfers are the onley special case: | ||
665 | * they are reissued,until "deleted" by usb_unlink_urb | ||
666 | * (real work done in a SOF intr, by process_del_list) | ||
667 | */ | ||
668 | if (urb_priv->tds_cnt == urb_priv->num_of_tds) { | ||
669 | fhci_urb_complete_free(fhci, urb); | ||
670 | } else if (urb_priv->state == URB_DEL && | ||
671 | ed->state == FHCI_ED_SKIP) { | ||
672 | fhci_del_ed_list(fhci, ed); | ||
673 | ed->state = FHCI_ED_OPER; | ||
674 | } else if (ed->state == FHCI_ED_HALTED) { | ||
675 | urb_priv->state = URB_DEL; | ||
676 | ed->state = FHCI_ED_URB_DEL; | ||
677 | fhci_del_ed_list(fhci, ed); | ||
678 | ed->state = FHCI_ED_OPER; | ||
679 | } | ||
680 | |||
681 | td = fhci_remove_td_from_done_list(fhci->hc_list); | ||
682 | } | ||
683 | |||
684 | spin_unlock(&fhci->lock); | ||
685 | enable_irq(fhci->timer->irq); | ||
686 | enable_irq(fhci_to_hcd(fhci)->irq); | ||
687 | } | ||
688 | |||
689 | DECLARE_TASKLET(fhci_tasklet, process_done_list, 0); | ||
690 | |||
691 | /* transfer complted callback */ | ||
692 | u32 fhci_transfer_confirm_callback(struct fhci_hcd *fhci) | ||
693 | { | ||
694 | if (!fhci->process_done_task->state) | ||
695 | tasklet_schedule(fhci->process_done_task); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | /* | ||
700 | * adds urb to the endpoint descriptor list | ||
701 | * arguments: | ||
702 | * fhci data structure for the Low level host controller | ||
703 | * ep USB Host endpoint data structure | ||
704 | * urb USB request block data structure | ||
705 | */ | ||
706 | void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) | ||
707 | { | ||
708 | struct ed *ed = urb->ep->hcpriv; | ||
709 | struct urb_priv *urb_priv = urb->hcpriv; | ||
710 | u32 data_len = urb->transfer_buffer_length; | ||
711 | int urb_state = 0; | ||
712 | int toggle = 0; | ||
713 | struct td *td; | ||
714 | u8 *data; | ||
715 | u16 cnt = 0; | ||
716 | |||
717 | if (ed == NULL) { | ||
718 | ed = fhci_get_empty_ed(fhci); | ||
719 | ed->dev_addr = usb_pipedevice(urb->pipe); | ||
720 | ed->ep_addr = usb_pipeendpoint(urb->pipe); | ||
721 | switch (usb_pipetype(urb->pipe)) { | ||
722 | case PIPE_CONTROL: | ||
723 | ed->mode = FHCI_TF_CTRL; | ||
724 | break; | ||
725 | case PIPE_BULK: | ||
726 | ed->mode = FHCI_TF_BULK; | ||
727 | break; | ||
728 | case PIPE_INTERRUPT: | ||
729 | ed->mode = FHCI_TF_INTR; | ||
730 | break; | ||
731 | case PIPE_ISOCHRONOUS: | ||
732 | ed->mode = FHCI_TF_ISO; | ||
733 | break; | ||
734 | default: | ||
735 | break; | ||
736 | } | ||
737 | ed->speed = (urb->dev->speed == USB_SPEED_LOW) ? | ||
738 | FHCI_LOW_SPEED : FHCI_FULL_SPEED; | ||
739 | ed->max_pkt_size = usb_maxpacket(urb->dev, | ||
740 | urb->pipe, usb_pipeout(urb->pipe)); | ||
741 | urb->ep->hcpriv = ed; | ||
742 | fhci_dbg(fhci, "new ep speed=%d max_pkt_size=%d\n", | ||
743 | ed->speed, ed->max_pkt_size); | ||
744 | } | ||
745 | |||
746 | /* for ISO transfer calculate start frame index */ | ||
747 | if (ed->mode == FHCI_TF_ISO && urb->transfer_flags & URB_ISO_ASAP) | ||
748 | urb->start_frame = ed->td_head ? ed->last_iso + 1 : | ||
749 | get_frame_num(fhci); | ||
750 | |||
751 | /* | ||
752 | * OHCI handles the DATA toggle itself,we just use the USB | ||
753 | * toggle bits | ||
754 | */ | ||
755 | if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
756 | usb_pipeout(urb->pipe))) | ||
757 | toggle = USB_TD_TOGGLE_CARRY; | ||
758 | else { | ||
759 | toggle = USB_TD_TOGGLE_DATA0; | ||
760 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
761 | usb_pipeout(urb->pipe), 1); | ||
762 | } | ||
763 | |||
764 | urb_priv->tds_cnt = 0; | ||
765 | urb_priv->ed = ed; | ||
766 | if (data_len > 0) | ||
767 | data = urb->transfer_buffer; | ||
768 | else | ||
769 | data = NULL; | ||
770 | |||
771 | switch (ed->mode) { | ||
772 | case FHCI_TF_BULK: | ||
773 | if (urb->transfer_flags & URB_ZERO_PACKET && | ||
774 | urb->transfer_buffer_length > 0 && | ||
775 | ((urb->transfer_buffer_length % | ||
776 | usb_maxpacket(urb->dev, urb->pipe, | ||
777 | usb_pipeout(urb->pipe))) == 0)) | ||
778 | urb_state = US_BULK0; | ||
779 | while (data_len > 4096) { | ||
780 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, | ||
781 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : | ||
782 | FHCI_TA_IN, | ||
783 | cnt ? USB_TD_TOGGLE_CARRY : | ||
784 | toggle, | ||
785 | data, 4096, 0, 0, true); | ||
786 | data += 4096; | ||
787 | data_len -= 4096; | ||
788 | cnt++; | ||
789 | } | ||
790 | |||
791 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, | ||
792 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, | ||
793 | cnt ? USB_TD_TOGGLE_CARRY : toggle, | ||
794 | data, data_len, 0, 0, true); | ||
795 | cnt++; | ||
796 | |||
797 | if (urb->transfer_flags & URB_ZERO_PACKET && | ||
798 | cnt < urb_priv->num_of_tds) { | ||
799 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, | ||
800 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : | ||
801 | FHCI_TA_IN, | ||
802 | USB_TD_TOGGLE_CARRY, NULL, 0, 0, 0, true); | ||
803 | cnt++; | ||
804 | } | ||
805 | break; | ||
806 | case FHCI_TF_INTR: | ||
807 | urb->start_frame = get_frame_num(fhci) + 1; | ||
808 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, | ||
809 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, | ||
810 | USB_TD_TOGGLE_DATA0, data, data_len, | ||
811 | urb->interval, urb->start_frame, true); | ||
812 | break; | ||
813 | case FHCI_TF_CTRL: | ||
814 | ed->dev_addr = usb_pipedevice(urb->pipe); | ||
815 | ed->max_pkt_size = usb_maxpacket(urb->dev, urb->pipe, | ||
816 | usb_pipeout(urb->pipe)); | ||
817 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP, | ||
818 | USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true); | ||
819 | |||
820 | if (data_len > 0) { | ||
821 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, | ||
822 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : | ||
823 | FHCI_TA_IN, | ||
824 | USB_TD_TOGGLE_DATA1, data, data_len, 0, 0, | ||
825 | true); | ||
826 | } | ||
827 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, | ||
828 | usb_pipeout(urb->pipe) ? FHCI_TA_IN : FHCI_TA_OUT, | ||
829 | USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true); | ||
830 | urb_state = US_CTRL_SETUP; | ||
831 | break; | ||
832 | case FHCI_TF_ISO: | ||
833 | for (cnt = 0; cnt < urb->number_of_packets; cnt++) { | ||
834 | u16 frame = urb->start_frame; | ||
835 | |||
836 | /* | ||
837 | * FIXME scheduling should handle frame counter | ||
838 | * roll-around ... exotic case (and OHCI has | ||
839 | * a 2^16 iso range, vs other HCs max of 2^10) | ||
840 | */ | ||
841 | frame += cnt * urb->interval; | ||
842 | frame &= 0x07ff; | ||
843 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, | ||
844 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : | ||
845 | FHCI_TA_IN, | ||
846 | USB_TD_TOGGLE_DATA0, | ||
847 | data + urb->iso_frame_desc[cnt].offset, | ||
848 | urb->iso_frame_desc[cnt].length, | ||
849 | urb->interval, frame, true); | ||
850 | } | ||
851 | break; | ||
852 | default: | ||
853 | break; | ||
854 | } | ||
855 | |||
856 | /* | ||
857 | * set the state of URB | ||
858 | * control pipe:3 states -- setup,data,status | ||
859 | * interrupt and bulk pipe:1 state -- data | ||
860 | */ | ||
861 | urb->pipe &= ~0x1f; | ||
862 | urb->pipe |= urb_state & 0x1f; | ||
863 | |||
864 | urb_priv->state = URB_INPROGRESS; | ||
865 | |||
866 | if (!ed->td_head) { | ||
867 | ed->state = FHCI_ED_OPER; | ||
868 | switch (ed->mode) { | ||
869 | case FHCI_TF_CTRL: | ||
870 | list_add(&ed->node, &fhci->hc_list->ctrl_list); | ||
871 | break; | ||
872 | case FHCI_TF_BULK: | ||
873 | list_add(&ed->node, &fhci->hc_list->bulk_list); | ||
874 | break; | ||
875 | case FHCI_TF_INTR: | ||
876 | list_add(&ed->node, &fhci->hc_list->intr_list); | ||
877 | break; | ||
878 | case FHCI_TF_ISO: | ||
879 | list_add(&ed->node, &fhci->hc_list->iso_list); | ||
880 | break; | ||
881 | default: | ||
882 | break; | ||
883 | } | ||
884 | } | ||
885 | |||
886 | fhci_add_tds_to_ed(ed, urb_priv->tds, urb_priv->num_of_tds); | ||
887 | fhci->active_urbs++; | ||
888 | } | ||
diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c new file mode 100644 index 000000000000..b40332290319 --- /dev/null +++ b/drivers/usb/host/fhci-tds.c | |||
@@ -0,0 +1,626 @@ | |||
1 | /* | ||
2 | * Freescale QUICC Engine USB Host Controller Driver | ||
3 | * | ||
4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
5 | * Shlomi Gridish <gridish@freescale.com> | ||
6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
8 | * Peter Barada <peterb@logicpd.com> | ||
9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/usb.h> | ||
24 | #include "../core/hcd.h" | ||
25 | #include "fhci.h" | ||
26 | |||
27 | #define DUMMY_BD_BUFFER 0xdeadbeef | ||
28 | #define DUMMY2_BD_BUFFER 0xbaadf00d | ||
29 | |||
30 | /* Transaction Descriptors bits */ | ||
31 | #define TD_R 0x8000 /* ready bit */ | ||
32 | #define TD_W 0x2000 /* wrap bit */ | ||
33 | #define TD_I 0x1000 /* interrupt on completion */ | ||
34 | #define TD_L 0x0800 /* last */ | ||
35 | #define TD_TC 0x0400 /* transmit CRC */ | ||
36 | #define TD_CNF 0x0200 /* CNF - Must be always 1 */ | ||
37 | #define TD_LSP 0x0100 /* Low-speed transaction */ | ||
38 | #define TD_PID 0x00c0 /* packet id */ | ||
39 | #define TD_RXER 0x0020 /* Rx error or not */ | ||
40 | |||
41 | #define TD_NAK 0x0010 /* No ack. */ | ||
42 | #define TD_STAL 0x0008 /* Stall recieved */ | ||
43 | #define TD_TO 0x0004 /* time out */ | ||
44 | #define TD_UN 0x0002 /* underrun */ | ||
45 | #define TD_NO 0x0010 /* Rx Non Octet Aligned Packet */ | ||
46 | #define TD_AB 0x0008 /* Frame Aborted */ | ||
47 | #define TD_CR 0x0004 /* CRC Error */ | ||
48 | #define TD_OV 0x0002 /* Overrun */ | ||
49 | #define TD_BOV 0x0001 /* Buffer Overrun */ | ||
50 | |||
51 | #define TD_ERRORS (TD_NAK | TD_STAL | TD_TO | TD_UN | \ | ||
52 | TD_NO | TD_AB | TD_CR | TD_OV | TD_BOV) | ||
53 | |||
54 | #define TD_PID_DATA0 0x0080 /* Data 0 toggle */ | ||
55 | #define TD_PID_DATA1 0x00c0 /* Data 1 toggle */ | ||
56 | #define TD_PID_TOGGLE 0x00c0 /* Data 0/1 toggle mask */ | ||
57 | |||
58 | #define TD_TOK_SETUP 0x0000 | ||
59 | #define TD_TOK_OUT 0x4000 | ||
60 | #define TD_TOK_IN 0x8000 | ||
61 | #define TD_ISO 0x1000 | ||
62 | #define TD_ENDP 0x0780 | ||
63 | #define TD_ADDR 0x007f | ||
64 | |||
65 | #define TD_ENDP_SHIFT 7 | ||
66 | |||
67 | struct usb_td { | ||
68 | __be16 status; | ||
69 | __be16 length; | ||
70 | __be32 buf_ptr; | ||
71 | __be16 extra; | ||
72 | __be16 reserved; | ||
73 | }; | ||
74 | |||
75 | static struct usb_td __iomem *next_bd(struct usb_td __iomem *base, | ||
76 | struct usb_td __iomem *td, | ||
77 | u16 status) | ||
78 | { | ||
79 | if (status & TD_W) | ||
80 | return base; | ||
81 | else | ||
82 | return ++td; | ||
83 | } | ||
84 | |||
85 | void fhci_push_dummy_bd(struct endpoint *ep) | ||
86 | { | ||
87 | if (ep->already_pushed_dummy_bd == false) { | ||
88 | u16 td_status = in_be16(&ep->empty_td->status); | ||
89 | |||
90 | out_be32(&ep->empty_td->buf_ptr, DUMMY_BD_BUFFER); | ||
91 | /* get the next TD in the ring */ | ||
92 | ep->empty_td = next_bd(ep->td_base, ep->empty_td, td_status); | ||
93 | ep->already_pushed_dummy_bd = true; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | /* destroy an USB endpoint */ | ||
98 | void fhci_ep0_free(struct fhci_usb *usb) | ||
99 | { | ||
100 | struct endpoint *ep; | ||
101 | int size; | ||
102 | |||
103 | ep = usb->ep0; | ||
104 | if (ep) { | ||
105 | if (ep->td_base) | ||
106 | cpm_muram_free(cpm_muram_offset(ep->td_base)); | ||
107 | |||
108 | if (ep->conf_frame_Q) { | ||
109 | size = cq_howmany(ep->conf_frame_Q); | ||
110 | for (; size; size--) { | ||
111 | struct packet *pkt = cq_get(ep->conf_frame_Q); | ||
112 | |||
113 | kfree(pkt); | ||
114 | } | ||
115 | cq_delete(ep->conf_frame_Q); | ||
116 | } | ||
117 | |||
118 | if (ep->empty_frame_Q) { | ||
119 | size = cq_howmany(ep->empty_frame_Q); | ||
120 | for (; size; size--) { | ||
121 | struct packet *pkt = cq_get(ep->empty_frame_Q); | ||
122 | |||
123 | kfree(pkt); | ||
124 | } | ||
125 | cq_delete(ep->empty_frame_Q); | ||
126 | } | ||
127 | |||
128 | if (ep->dummy_packets_Q) { | ||
129 | size = cq_howmany(ep->dummy_packets_Q); | ||
130 | for (; size; size--) { | ||
131 | u8 *buff = cq_get(ep->dummy_packets_Q); | ||
132 | |||
133 | kfree(buff); | ||
134 | } | ||
135 | cq_delete(ep->dummy_packets_Q); | ||
136 | } | ||
137 | |||
138 | kfree(ep); | ||
139 | usb->ep0 = NULL; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * create the endpoint structure | ||
145 | * | ||
146 | * arguments: | ||
147 | * usb A pointer to the data structure of the USB | ||
148 | * data_mem The data memory partition(BUS) | ||
149 | * ring_len TD ring length | ||
150 | */ | ||
151 | u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, | ||
152 | u32 ring_len) | ||
153 | { | ||
154 | struct endpoint *ep; | ||
155 | struct usb_td __iomem *td; | ||
156 | unsigned long ep_offset; | ||
157 | char *err_for = "enpoint PRAM"; | ||
158 | int ep_mem_size; | ||
159 | u32 i; | ||
160 | |||
161 | /* we need at least 3 TDs in the ring */ | ||
162 | if (!(ring_len > 2)) { | ||
163 | fhci_err(usb->fhci, "illegal TD ring length parameters\n"); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | ||
168 | if (!ep) | ||
169 | return -ENOMEM; | ||
170 | |||
171 | ep_mem_size = ring_len * sizeof(*td) + sizeof(struct fhci_ep_pram); | ||
172 | ep_offset = cpm_muram_alloc(ep_mem_size, 32); | ||
173 | if (IS_ERR_VALUE(ep_offset)) | ||
174 | goto err; | ||
175 | ep->td_base = cpm_muram_addr(ep_offset); | ||
176 | |||
177 | /* zero all queue pointers */ | ||
178 | ep->conf_frame_Q = cq_new(ring_len + 2); | ||
179 | ep->empty_frame_Q = cq_new(ring_len + 2); | ||
180 | ep->dummy_packets_Q = cq_new(ring_len + 2); | ||
181 | if (!ep->conf_frame_Q || !ep->empty_frame_Q || !ep->dummy_packets_Q) { | ||
182 | err_for = "frame_queues"; | ||
183 | goto err; | ||
184 | } | ||
185 | |||
186 | for (i = 0; i < (ring_len + 1); i++) { | ||
187 | struct packet *pkt; | ||
188 | u8 *buff; | ||
189 | |||
190 | pkt = kmalloc(sizeof(*pkt), GFP_KERNEL); | ||
191 | if (!pkt) { | ||
192 | err_for = "frame"; | ||
193 | goto err; | ||
194 | } | ||
195 | |||
196 | buff = kmalloc(1028 * sizeof(*buff), GFP_KERNEL); | ||
197 | if (!buff) { | ||
198 | kfree(pkt); | ||
199 | err_for = "buffer"; | ||
200 | goto err; | ||
201 | } | ||
202 | cq_put(ep->empty_frame_Q, pkt); | ||
203 | cq_put(ep->dummy_packets_Q, buff); | ||
204 | } | ||
205 | |||
206 | /* we put the endpoint parameter RAM right behind the TD ring */ | ||
207 | ep->ep_pram_ptr = (void __iomem *)ep->td_base + sizeof(*td) * ring_len; | ||
208 | |||
209 | ep->conf_td = ep->td_base; | ||
210 | ep->empty_td = ep->td_base; | ||
211 | |||
212 | ep->already_pushed_dummy_bd = false; | ||
213 | |||
214 | /* initialize tds */ | ||
215 | td = ep->td_base; | ||
216 | for (i = 0; i < ring_len; i++) { | ||
217 | out_be32(&td->buf_ptr, 0); | ||
218 | out_be16(&td->status, 0); | ||
219 | out_be16(&td->length, 0); | ||
220 | out_be16(&td->extra, 0); | ||
221 | td++; | ||
222 | } | ||
223 | td--; | ||
224 | out_be16(&td->status, TD_W); /* for last TD set Wrap bit */ | ||
225 | out_be16(&td->length, 0); | ||
226 | |||
227 | /* endpoint structure has been created */ | ||
228 | usb->ep0 = ep; | ||
229 | |||
230 | return 0; | ||
231 | err: | ||
232 | fhci_ep0_free(usb); | ||
233 | kfree(ep); | ||
234 | fhci_err(usb->fhci, "no memory for the %s\n", err_for); | ||
235 | return -ENOMEM; | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * initialize the endpoint register according to the given parameters | ||
240 | * | ||
241 | * artuments: | ||
242 | * usb A pointer to the data strucutre of the USB | ||
243 | * ep A pointer to the endpoint structre | ||
244 | * data_mem The data memory partition(BUS) | ||
245 | */ | ||
246 | void fhci_init_ep_registers(struct fhci_usb *usb, struct endpoint *ep, | ||
247 | enum fhci_mem_alloc data_mem) | ||
248 | { | ||
249 | u8 rt; | ||
250 | |||
251 | /* set the endpoint registers according to the endpoint */ | ||
252 | out_be16(&usb->fhci->regs->usb_ep[0], | ||
253 | USB_TRANS_CTR | USB_EP_MF | USB_EP_RTE); | ||
254 | out_be16(&usb->fhci->pram->ep_ptr[0], | ||
255 | cpm_muram_offset(ep->ep_pram_ptr)); | ||
256 | |||
257 | rt = (BUS_MODE_BO_BE | BUS_MODE_GBL); | ||
258 | #ifdef MULTI_DATA_BUS | ||
259 | if (data_mem == MEM_SECONDARY) | ||
260 | rt |= BUS_MODE_DTB; | ||
261 | #endif | ||
262 | out_8(&ep->ep_pram_ptr->rx_func_code, rt); | ||
263 | out_8(&ep->ep_pram_ptr->tx_func_code, rt); | ||
264 | out_be16(&ep->ep_pram_ptr->rx_buff_len, 1028); | ||
265 | out_be16(&ep->ep_pram_ptr->rx_base, 0); | ||
266 | out_be16(&ep->ep_pram_ptr->tx_base, cpm_muram_offset(ep->td_base)); | ||
267 | out_be16(&ep->ep_pram_ptr->rx_bd_ptr, 0); | ||
268 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, cpm_muram_offset(ep->td_base)); | ||
269 | out_be32(&ep->ep_pram_ptr->tx_state, 0); | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * Collect the submitted frames and inform the application about them | ||
274 | * It is also prepearing the TDs for new frames. If the Tx interrupts | ||
275 | * are diabled, the application should call that routine to get | ||
276 | * confirmation about the submitted frames. Otherwise, the routine is | ||
277 | * called frome the interrupt service routine during the Tx interrupt. | ||
278 | * In that case the application is informed by calling the application | ||
279 | * specific 'fhci_transaction_confirm' routine | ||
280 | */ | ||
281 | static void fhci_td_transaction_confirm(struct fhci_usb *usb) | ||
282 | { | ||
283 | struct endpoint *ep = usb->ep0; | ||
284 | struct packet *pkt; | ||
285 | struct usb_td __iomem *td; | ||
286 | u16 extra_data; | ||
287 | u16 td_status; | ||
288 | u16 td_length; | ||
289 | u32 buf; | ||
290 | |||
291 | /* | ||
292 | * collect transmitted BDs from the chip. The routine clears all BDs | ||
293 | * with R bit = 0 and the pointer to data buffer is not NULL, that is | ||
294 | * BDs which point to the transmitted data buffer | ||
295 | */ | ||
296 | while (1) { | ||
297 | td = ep->conf_td; | ||
298 | td_status = in_be16(&td->status); | ||
299 | td_length = in_be16(&td->length); | ||
300 | buf = in_be32(&td->buf_ptr); | ||
301 | extra_data = in_be16(&td->extra); | ||
302 | |||
303 | /* check if the TD is empty */ | ||
304 | if (!(!(td_status & TD_R) && ((td_status & ~TD_W) || buf))) | ||
305 | break; | ||
306 | /* check if it is a dummy buffer */ | ||
307 | else if ((buf == DUMMY_BD_BUFFER) && !(td_status & ~TD_W)) | ||
308 | break; | ||
309 | |||
310 | /* mark TD as empty */ | ||
311 | clrbits16(&td->status, ~TD_W); | ||
312 | out_be16(&td->length, 0); | ||
313 | out_be32(&td->buf_ptr, 0); | ||
314 | out_be16(&td->extra, 0); | ||
315 | /* advance the TD pointer */ | ||
316 | ep->conf_td = next_bd(ep->td_base, ep->conf_td, td_status); | ||
317 | |||
318 | /* check if it is a dummy buffer(type2) */ | ||
319 | if ((buf == DUMMY2_BD_BUFFER) && !(td_status & ~TD_W)) | ||
320 | continue; | ||
321 | |||
322 | pkt = cq_get(ep->conf_frame_Q); | ||
323 | if (!pkt) | ||
324 | fhci_err(usb->fhci, "no frame to confirm\n"); | ||
325 | |||
326 | if (td_status & TD_ERRORS) { | ||
327 | if (td_status & TD_RXER) { | ||
328 | if (td_status & TD_CR) | ||
329 | pkt->status = USB_TD_RX_ER_CRC; | ||
330 | else if (td_status & TD_AB) | ||
331 | pkt->status = USB_TD_RX_ER_BITSTUFF; | ||
332 | else if (td_status & TD_OV) | ||
333 | pkt->status = USB_TD_RX_ER_OVERUN; | ||
334 | else if (td_status & TD_BOV) | ||
335 | pkt->status = USB_TD_RX_DATA_OVERUN; | ||
336 | else if (td_status & TD_NO) | ||
337 | pkt->status = USB_TD_RX_ER_NONOCT; | ||
338 | else | ||
339 | fhci_err(usb->fhci, "illegal error " | ||
340 | "occured\n"); | ||
341 | } else if (td_status & TD_NAK) | ||
342 | pkt->status = USB_TD_TX_ER_NAK; | ||
343 | else if (td_status & TD_TO) | ||
344 | pkt->status = USB_TD_TX_ER_TIMEOUT; | ||
345 | else if (td_status & TD_UN) | ||
346 | pkt->status = USB_TD_TX_ER_UNDERUN; | ||
347 | else if (td_status & TD_STAL) | ||
348 | pkt->status = USB_TD_TX_ER_STALL; | ||
349 | else | ||
350 | fhci_err(usb->fhci, "illegal error occured\n"); | ||
351 | } else if ((extra_data & TD_TOK_IN) && | ||
352 | pkt->len > td_length - CRC_SIZE) { | ||
353 | pkt->status = USB_TD_RX_DATA_UNDERUN; | ||
354 | } | ||
355 | |||
356 | if (extra_data & TD_TOK_IN) | ||
357 | pkt->len = td_length - CRC_SIZE; | ||
358 | else if (pkt->info & PKT_ZLP) | ||
359 | pkt->len = 0; | ||
360 | else | ||
361 | pkt->len = td_length; | ||
362 | |||
363 | fhci_transaction_confirm(usb, pkt); | ||
364 | } | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | * Submitting a data frame to a specified endpoint of a USB device | ||
369 | * The frame is put in the driver's transmit queue for this endpoint | ||
370 | * | ||
371 | * Arguments: | ||
372 | * usb A pointer to the USB structure | ||
373 | * pkt A pointer to the user frame structure | ||
374 | * trans_type Transaction tyep - IN,OUT or SETUP | ||
375 | * dest_addr Device address - 0~127 | ||
376 | * dest_ep Endpoint number of the device - 0~16 | ||
377 | * trans_mode Pipe type - ISO,Interrupt,bulk or control | ||
378 | * dest_speed USB speed - Low speed or FULL speed | ||
379 | * data_toggle Data sequence toggle - 0 or 1 | ||
380 | */ | ||
381 | u32 fhci_host_transaction(struct fhci_usb *usb, | ||
382 | struct packet *pkt, | ||
383 | enum fhci_ta_type trans_type, | ||
384 | u8 dest_addr, | ||
385 | u8 dest_ep, | ||
386 | enum fhci_tf_mode trans_mode, | ||
387 | enum fhci_speed dest_speed, u8 data_toggle) | ||
388 | { | ||
389 | struct endpoint *ep = usb->ep0; | ||
390 | struct usb_td __iomem *td; | ||
391 | u16 extra_data; | ||
392 | u16 td_status; | ||
393 | |||
394 | fhci_usb_disable_interrupt(usb); | ||
395 | /* start from the next BD that should be filled */ | ||
396 | td = ep->empty_td; | ||
397 | td_status = in_be16(&td->status); | ||
398 | |||
399 | if (td_status & TD_R && in_be16(&td->length)) { | ||
400 | /* if the TD is not free */ | ||
401 | fhci_usb_enable_interrupt(usb); | ||
402 | return -1; | ||
403 | } | ||
404 | |||
405 | /* get the next TD in the ring */ | ||
406 | ep->empty_td = next_bd(ep->td_base, ep->empty_td, td_status); | ||
407 | fhci_usb_enable_interrupt(usb); | ||
408 | pkt->priv_data = td; | ||
409 | out_be32(&td->buf_ptr, virt_to_phys(pkt->data)); | ||
410 | /* sets up transaction parameters - addr,endp,dir,and type */ | ||
411 | extra_data = (dest_ep << TD_ENDP_SHIFT) | dest_addr; | ||
412 | switch (trans_type) { | ||
413 | case FHCI_TA_IN: | ||
414 | extra_data |= TD_TOK_IN; | ||
415 | break; | ||
416 | case FHCI_TA_OUT: | ||
417 | extra_data |= TD_TOK_OUT; | ||
418 | break; | ||
419 | case FHCI_TA_SETUP: | ||
420 | extra_data |= TD_TOK_SETUP; | ||
421 | break; | ||
422 | } | ||
423 | if (trans_mode == FHCI_TF_ISO) | ||
424 | extra_data |= TD_ISO; | ||
425 | out_be16(&td->extra, extra_data); | ||
426 | |||
427 | /* sets up the buffer descriptor */ | ||
428 | td_status = ((td_status & TD_W) | TD_R | TD_L | TD_I | TD_CNF); | ||
429 | if (!(pkt->info & PKT_NO_CRC)) | ||
430 | td_status |= TD_TC; | ||
431 | |||
432 | switch (trans_type) { | ||
433 | case FHCI_TA_IN: | ||
434 | if (data_toggle) | ||
435 | pkt->info |= PKT_PID_DATA1; | ||
436 | else | ||
437 | pkt->info |= PKT_PID_DATA0; | ||
438 | break; | ||
439 | default: | ||
440 | if (data_toggle) { | ||
441 | td_status |= TD_PID_DATA1; | ||
442 | pkt->info |= PKT_PID_DATA1; | ||
443 | } else { | ||
444 | td_status |= TD_PID_DATA0; | ||
445 | pkt->info |= PKT_PID_DATA0; | ||
446 | } | ||
447 | break; | ||
448 | } | ||
449 | |||
450 | if ((dest_speed == FHCI_LOW_SPEED) && | ||
451 | (usb->port_status == FHCI_PORT_FULL)) | ||
452 | td_status |= TD_LSP; | ||
453 | |||
454 | out_be16(&td->status, td_status); | ||
455 | |||
456 | /* set up buffer length */ | ||
457 | if (trans_type == FHCI_TA_IN) | ||
458 | out_be16(&td->length, pkt->len + CRC_SIZE); | ||
459 | else | ||
460 | out_be16(&td->length, pkt->len); | ||
461 | |||
462 | /* put the frame to the confirmation queue */ | ||
463 | cq_put(ep->conf_frame_Q, pkt); | ||
464 | |||
465 | if (cq_howmany(ep->conf_frame_Q) == 1) | ||
466 | out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | /* Reset the Tx BD ring */ | ||
472 | void fhci_flush_bds(struct fhci_usb *usb) | ||
473 | { | ||
474 | u16 extra_data; | ||
475 | u16 td_status; | ||
476 | u32 buf; | ||
477 | struct usb_td __iomem *td; | ||
478 | struct endpoint *ep = usb->ep0; | ||
479 | |||
480 | td = ep->td_base; | ||
481 | while (1) { | ||
482 | td_status = in_be16(&td->status); | ||
483 | buf = in_be32(&td->buf_ptr); | ||
484 | extra_data = in_be16(&td->extra); | ||
485 | |||
486 | /* if the TD is not empty - we'll confirm it as Timeout */ | ||
487 | if (td_status & TD_R) | ||
488 | out_be16(&td->status, (td_status & ~TD_R) | TD_TO); | ||
489 | /* if this TD is dummy - let's skip this TD */ | ||
490 | else if (in_be32(&td->buf_ptr) == DUMMY_BD_BUFFER) | ||
491 | out_be32(&td->buf_ptr, DUMMY2_BD_BUFFER); | ||
492 | /* if this is the last TD - break */ | ||
493 | if (td_status & TD_W) | ||
494 | break; | ||
495 | |||
496 | td++; | ||
497 | } | ||
498 | |||
499 | fhci_td_transaction_confirm(usb); | ||
500 | |||
501 | td = ep->td_base; | ||
502 | do { | ||
503 | out_be16(&td->status, 0); | ||
504 | out_be16(&td->length, 0); | ||
505 | out_be32(&td->buf_ptr, 0); | ||
506 | out_be16(&td->extra, 0); | ||
507 | td++; | ||
508 | } while (!(in_be16(&td->status) & TD_W)); | ||
509 | out_be16(&td->status, TD_W); /* for last TD set Wrap bit */ | ||
510 | out_be16(&td->length, 0); | ||
511 | out_be32(&td->buf_ptr, 0); | ||
512 | out_be16(&td->extra, 0); | ||
513 | |||
514 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, | ||
515 | in_be16(&ep->ep_pram_ptr->tx_base)); | ||
516 | out_be32(&ep->ep_pram_ptr->tx_state, 0); | ||
517 | out_be16(&ep->ep_pram_ptr->tx_cnt, 0); | ||
518 | ep->empty_td = ep->td_base; | ||
519 | ep->conf_td = ep->td_base; | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | * Flush all transmitted packets from TDs in the actual frame. | ||
524 | * This routine is called when something wrong with the controller and | ||
525 | * we want to get rid of the actual frame and start again next frame | ||
526 | */ | ||
527 | void fhci_flush_actual_frame(struct fhci_usb *usb) | ||
528 | { | ||
529 | u8 mode; | ||
530 | u16 tb_ptr; | ||
531 | u16 extra_data; | ||
532 | u16 td_status; | ||
533 | u32 buf_ptr; | ||
534 | struct usb_td __iomem *td; | ||
535 | struct endpoint *ep = usb->ep0; | ||
536 | |||
537 | /* disable the USB controller */ | ||
538 | mode = in_8(&usb->fhci->regs->usb_mod); | ||
539 | out_8(&usb->fhci->regs->usb_mod, mode & ~USB_MODE_EN); | ||
540 | |||
541 | tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr); | ||
542 | td = cpm_muram_addr(tb_ptr); | ||
543 | td_status = in_be16(&td->status); | ||
544 | buf_ptr = in_be32(&td->buf_ptr); | ||
545 | extra_data = in_be16(&td->extra); | ||
546 | do { | ||
547 | if (td_status & TD_R) { | ||
548 | out_be16(&td->status, (td_status & ~TD_R) | TD_TO); | ||
549 | } else { | ||
550 | out_be32(&td->buf_ptr, 0); | ||
551 | ep->already_pushed_dummy_bd = false; | ||
552 | break; | ||
553 | } | ||
554 | |||
555 | /* advance the TD pointer */ | ||
556 | td = next_bd(ep->td_base, td, td_status); | ||
557 | td_status = in_be16(&td->status); | ||
558 | buf_ptr = in_be32(&td->buf_ptr); | ||
559 | extra_data = in_be16(&td->extra); | ||
560 | } while ((td_status & TD_R) || buf_ptr); | ||
561 | |||
562 | fhci_td_transaction_confirm(usb); | ||
563 | |||
564 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, | ||
565 | in_be16(&ep->ep_pram_ptr->tx_base)); | ||
566 | out_be32(&ep->ep_pram_ptr->tx_state, 0); | ||
567 | out_be16(&ep->ep_pram_ptr->tx_cnt, 0); | ||
568 | ep->empty_td = ep->td_base; | ||
569 | ep->conf_td = ep->td_base; | ||
570 | |||
571 | usb->actual_frame->frame_status = FRAME_TIMER_END_TRANSMISSION; | ||
572 | |||
573 | /* reset the event register */ | ||
574 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
575 | /* enable the USB controller */ | ||
576 | out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN); | ||
577 | } | ||
578 | |||
579 | /* handles Tx confirm and Tx error interrupt */ | ||
580 | void fhci_tx_conf_interrupt(struct fhci_usb *usb) | ||
581 | { | ||
582 | fhci_td_transaction_confirm(usb); | ||
583 | |||
584 | /* | ||
585 | * Schedule another transaction to this frame only if we have | ||
586 | * already confirmed all transaction in the frame. | ||
587 | */ | ||
588 | if (((fhci_get_sof_timer_count(usb) < usb->max_frame_usage) || | ||
589 | (usb->actual_frame->frame_status & FRAME_END_TRANSMISSION)) && | ||
590 | (list_empty(&usb->actual_frame->tds_list))) | ||
591 | fhci_schedule_transactions(usb); | ||
592 | } | ||
593 | |||
594 | void fhci_host_transmit_actual_frame(struct fhci_usb *usb) | ||
595 | { | ||
596 | u16 tb_ptr; | ||
597 | u16 td_status; | ||
598 | struct usb_td __iomem *td; | ||
599 | struct endpoint *ep = usb->ep0; | ||
600 | |||
601 | tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr); | ||
602 | td = cpm_muram_addr(tb_ptr); | ||
603 | |||
604 | if (in_be32(&td->buf_ptr) == DUMMY_BD_BUFFER) { | ||
605 | struct usb_td __iomem *old_td = td; | ||
606 | |||
607 | ep->already_pushed_dummy_bd = false; | ||
608 | td_status = in_be16(&td->status); | ||
609 | /* gets the next TD in the ring */ | ||
610 | td = next_bd(ep->td_base, td, td_status); | ||
611 | tb_ptr = cpm_muram_offset(td); | ||
612 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, tb_ptr); | ||
613 | |||
614 | /* start transmit only if we have something in the TDs */ | ||
615 | if (in_be16(&td->status) & TD_R) | ||
616 | out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); | ||
617 | |||
618 | if (in_be32(&ep->conf_td->buf_ptr) == DUMMY_BD_BUFFER) { | ||
619 | out_be32(&old_td->buf_ptr, 0); | ||
620 | ep->conf_td = next_bd(ep->td_base, ep->conf_td, | ||
621 | td_status); | ||
622 | } else { | ||
623 | out_be32(&old_td->buf_ptr, DUMMY2_BD_BUFFER); | ||
624 | } | ||
625 | } | ||
626 | } | ||
diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h new file mode 100644 index 000000000000..7116284ed21a --- /dev/null +++ b/drivers/usb/host/fhci.h | |||
@@ -0,0 +1,607 @@ | |||
1 | /* | ||
2 | * Freescale QUICC Engine USB Host Controller Driver | ||
3 | * | ||
4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
5 | * Shlomi Gridish <gridish@freescale.com> | ||
6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
8 | * Peter Barada <peterb@logicpd.com> | ||
9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #ifndef __FHCI_H | ||
19 | #define __FHCI_H | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/kfifo.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/usb.h> | ||
28 | #include <asm/qe.h> | ||
29 | #include "../core/hcd.h" | ||
30 | |||
31 | #define USB_CLOCK 48000000 | ||
32 | |||
33 | #define FHCI_PRAM_SIZE 0x100 | ||
34 | |||
35 | #define MAX_EDS 32 | ||
36 | #define MAX_TDS 32 | ||
37 | |||
38 | |||
39 | /* CRC16 field size */ | ||
40 | #define CRC_SIZE 2 | ||
41 | |||
42 | /* USB protocol overhead for each frame transmitted from the host */ | ||
43 | #define PROTOCOL_OVERHEAD 7 | ||
44 | |||
45 | /* Packet structure, info field */ | ||
46 | #define PKT_PID_DATA0 0x80000000 /* PID - Data toggle zero */ | ||
47 | #define PKT_PID_DATA1 0x40000000 /* PID - Data toggle one */ | ||
48 | #define PKT_PID_SETUP 0x20000000 /* PID - Setup bit */ | ||
49 | #define PKT_SETUP_STATUS 0x10000000 /* Setup status bit */ | ||
50 | #define PKT_SETADDR_STATUS 0x08000000 /* Set address status bit */ | ||
51 | #define PKT_SET_HOST_LAST 0x04000000 /* Last data packet */ | ||
52 | #define PKT_HOST_DATA 0x02000000 /* Data packet */ | ||
53 | #define PKT_FIRST_IN_FRAME 0x01000000 /* First packet in the frame */ | ||
54 | #define PKT_TOKEN_FRAME 0x00800000 /* Token packet */ | ||
55 | #define PKT_ZLP 0x00400000 /* Zero length packet */ | ||
56 | #define PKT_IN_TOKEN_FRAME 0x00200000 /* IN token packet */ | ||
57 | #define PKT_OUT_TOKEN_FRAME 0x00100000 /* OUT token packet */ | ||
58 | #define PKT_SETUP_TOKEN_FRAME 0x00080000 /* SETUP token packet */ | ||
59 | #define PKT_STALL_FRAME 0x00040000 /* STALL packet */ | ||
60 | #define PKT_NACK_FRAME 0x00020000 /* NACK packet */ | ||
61 | #define PKT_NO_PID 0x00010000 /* No PID */ | ||
62 | #define PKT_NO_CRC 0x00008000 /* don't append CRC */ | ||
63 | #define PKT_HOST_COMMAND 0x00004000 /* Host command packet */ | ||
64 | #define PKT_DUMMY_PACKET 0x00002000 /* Dummy packet, used for mmm */ | ||
65 | #define PKT_LOW_SPEED_PACKET 0x00001000 /* Low-Speed packet */ | ||
66 | |||
67 | #define TRANS_OK (0) | ||
68 | #define TRANS_INPROGRESS (-1) | ||
69 | #define TRANS_DISCARD (-2) | ||
70 | #define TRANS_FAIL (-3) | ||
71 | |||
72 | #define PS_INT 0 | ||
73 | #define PS_DISCONNECTED 1 | ||
74 | #define PS_CONNECTED 2 | ||
75 | #define PS_READY 3 | ||
76 | #define PS_MISSING 4 | ||
77 | |||
78 | /* Transfer Descriptor status field */ | ||
79 | #define USB_TD_OK 0x00000000 /* TD transmited or received ok */ | ||
80 | #define USB_TD_INPROGRESS 0x80000000 /* TD is being transmitted */ | ||
81 | #define USB_TD_RX_ER_NONOCT 0x40000000 /* Tx Non Octet Aligned Packet */ | ||
82 | #define USB_TD_RX_ER_BITSTUFF 0x20000000 /* Frame Aborted-Received pkt */ | ||
83 | #define USB_TD_RX_ER_CRC 0x10000000 /* CRC error */ | ||
84 | #define USB_TD_RX_ER_OVERUN 0x08000000 /* Over - run occured */ | ||
85 | #define USB_TD_RX_ER_PID 0x04000000 /* wrong PID received */ | ||
86 | #define USB_TD_RX_DATA_UNDERUN 0x02000000 /* shorter than expected */ | ||
87 | #define USB_TD_RX_DATA_OVERUN 0x01000000 /* longer than expected */ | ||
88 | #define USB_TD_TX_ER_NAK 0x00800000 /* NAK handshake */ | ||
89 | #define USB_TD_TX_ER_STALL 0x00400000 /* STALL handshake */ | ||
90 | #define USB_TD_TX_ER_TIMEOUT 0x00200000 /* transmit time out */ | ||
91 | #define USB_TD_TX_ER_UNDERUN 0x00100000 /* transmit underrun */ | ||
92 | |||
93 | #define USB_TD_ERROR (USB_TD_RX_ER_NONOCT | USB_TD_RX_ER_BITSTUFF | \ | ||
94 | USB_TD_RX_ER_CRC | USB_TD_RX_ER_OVERUN | USB_TD_RX_ER_PID | \ | ||
95 | USB_TD_RX_DATA_UNDERUN | USB_TD_RX_DATA_OVERUN | \ | ||
96 | USB_TD_TX_ER_NAK | USB_TD_TX_ER_STALL | \ | ||
97 | USB_TD_TX_ER_TIMEOUT | USB_TD_TX_ER_UNDERUN) | ||
98 | |||
99 | /* Transfer Descriptor toggle field */ | ||
100 | #define USB_TD_TOGGLE_DATA0 0 | ||
101 | #define USB_TD_TOGGLE_DATA1 1 | ||
102 | #define USB_TD_TOGGLE_CARRY 2 | ||
103 | |||
104 | /* #define MULTI_DATA_BUS */ | ||
105 | |||
106 | /* Bus mode register RBMR/TBMR */ | ||
107 | #define BUS_MODE_GBL 0x20 /* Global snooping */ | ||
108 | #define BUS_MODE_BO 0x18 /* Byte ordering */ | ||
109 | #define BUS_MODE_BO_BE 0x10 /* Byte ordering - Big-endian */ | ||
110 | #define BUS_MODE_DTB 0x02 /* Data bus */ | ||
111 | |||
112 | /* FHCI QE USB Register Description */ | ||
113 | |||
114 | /* USB Mode Register bit define */ | ||
115 | #define USB_MODE_EN 0x01 | ||
116 | #define USB_MODE_HOST 0x02 | ||
117 | #define USB_MODE_TEST 0x04 | ||
118 | #define USB_MODE_SFTE 0x08 | ||
119 | #define USB_MODE_RESUME 0x40 | ||
120 | #define USB_MODE_LSS 0x80 | ||
121 | |||
122 | /* USB Slave Address Register Mask */ | ||
123 | #define USB_SLVADDR_MASK 0x7F | ||
124 | |||
125 | /* USB Endpoint register define */ | ||
126 | #define USB_EPNUM_MASK 0xF000 | ||
127 | #define USB_EPNUM_SHIFT 12 | ||
128 | |||
129 | #define USB_TRANS_MODE_SHIFT 8 | ||
130 | #define USB_TRANS_CTR 0x0000 | ||
131 | #define USB_TRANS_INT 0x0100 | ||
132 | #define USB_TRANS_BULK 0x0200 | ||
133 | #define USB_TRANS_ISO 0x0300 | ||
134 | |||
135 | #define USB_EP_MF 0x0020 | ||
136 | #define USB_EP_RTE 0x0010 | ||
137 | |||
138 | #define USB_THS_SHIFT 2 | ||
139 | #define USB_THS_MASK 0x000c | ||
140 | #define USB_THS_NORMAL 0x0 | ||
141 | #define USB_THS_IGNORE_IN 0x0004 | ||
142 | #define USB_THS_NACK 0x0008 | ||
143 | #define USB_THS_STALL 0x000c | ||
144 | |||
145 | #define USB_RHS_SHIFT 0 | ||
146 | #define USB_RHS_MASK 0x0003 | ||
147 | #define USB_RHS_NORMAL 0x0 | ||
148 | #define USB_RHS_IGNORE_OUT 0x0001 | ||
149 | #define USB_RHS_NACK 0x0002 | ||
150 | #define USB_RHS_STALL 0x0003 | ||
151 | |||
152 | #define USB_RTHS_MASK 0x000f | ||
153 | |||
154 | /* USB Command Register define */ | ||
155 | #define USB_CMD_STR_FIFO 0x80 | ||
156 | #define USB_CMD_FLUSH_FIFO 0x40 | ||
157 | #define USB_CMD_ISFT 0x20 | ||
158 | #define USB_CMD_DSFT 0x10 | ||
159 | #define USB_CMD_EP_MASK 0x03 | ||
160 | |||
161 | /* USB Event and Mask Register define */ | ||
162 | #define USB_E_MSF_MASK 0x0800 | ||
163 | #define USB_E_SFT_MASK 0x0400 | ||
164 | #define USB_E_RESET_MASK 0x0200 | ||
165 | #define USB_E_IDLE_MASK 0x0100 | ||
166 | #define USB_E_TXE4_MASK 0x0080 | ||
167 | #define USB_E_TXE3_MASK 0x0040 | ||
168 | #define USB_E_TXE2_MASK 0x0020 | ||
169 | #define USB_E_TXE1_MASK 0x0010 | ||
170 | #define USB_E_SOF_MASK 0x0008 | ||
171 | #define USB_E_BSY_MASK 0x0004 | ||
172 | #define USB_E_TXB_MASK 0x0002 | ||
173 | #define USB_E_RXB_MASK 0x0001 | ||
174 | |||
175 | /* Freescale USB Host controller registers */ | ||
176 | struct fhci_regs { | ||
177 | u8 usb_mod; /* mode register */ | ||
178 | u8 usb_addr; /* address register */ | ||
179 | u8 usb_comm; /* command register */ | ||
180 | u8 reserved1[1]; | ||
181 | __be16 usb_ep[4]; /* endpoint register */ | ||
182 | u8 reserved2[4]; | ||
183 | __be16 usb_event; /* event register */ | ||
184 | u8 reserved3[2]; | ||
185 | __be16 usb_mask; /* mask register */ | ||
186 | u8 reserved4[1]; | ||
187 | u8 usb_status; /* status register */ | ||
188 | __be16 usb_sof_tmr; /* Start Of Frame timer */ | ||
189 | u8 reserved5[2]; | ||
190 | __be16 usb_frame_num; /* frame number register */ | ||
191 | u8 reserved6[1]; | ||
192 | }; | ||
193 | |||
194 | /* Freescale USB HOST */ | ||
195 | struct fhci_pram { | ||
196 | __be16 ep_ptr[4]; /* Endpoint porter reg */ | ||
197 | __be32 rx_state; /* Rx internal state */ | ||
198 | __be32 rx_ptr; /* Rx internal data pointer */ | ||
199 | __be16 frame_num; /* Frame number */ | ||
200 | __be16 rx_cnt; /* Rx byte count */ | ||
201 | __be32 rx_temp; /* Rx temp */ | ||
202 | __be32 rx_data_temp; /* Rx data temp */ | ||
203 | __be16 rx_u_ptr; /* Rx microcode return address temp */ | ||
204 | u8 reserved1[2]; /* reserved area */ | ||
205 | __be32 sof_tbl; /* SOF lookup table pointer */ | ||
206 | u8 sof_u_crc_temp; /* SOF micorcode CRC5 temp reg */ | ||
207 | u8 reserved2[0xdb]; | ||
208 | }; | ||
209 | |||
210 | /* Freescale USB Endpoint*/ | ||
211 | struct fhci_ep_pram { | ||
212 | __be16 rx_base; /* Rx BD base address */ | ||
213 | __be16 tx_base; /* Tx BD base address */ | ||
214 | u8 rx_func_code; /* Rx function code */ | ||
215 | u8 tx_func_code; /* Tx function code */ | ||
216 | __be16 rx_buff_len; /* Rx buffer length */ | ||
217 | __be16 rx_bd_ptr; /* Rx BD pointer */ | ||
218 | __be16 tx_bd_ptr; /* Tx BD pointer */ | ||
219 | __be32 tx_state; /* Tx internal state */ | ||
220 | __be32 tx_ptr; /* Tx internal data pointer */ | ||
221 | __be16 tx_crc; /* temp transmit CRC */ | ||
222 | __be16 tx_cnt; /* Tx byte count */ | ||
223 | __be32 tx_temp; /* Tx temp */ | ||
224 | __be16 tx_u_ptr; /* Tx microcode return address temp */ | ||
225 | __be16 reserved; | ||
226 | }; | ||
227 | |||
228 | struct fhci_controller_list { | ||
229 | struct list_head ctrl_list; /* control endpoints */ | ||
230 | struct list_head bulk_list; /* bulk endpoints */ | ||
231 | struct list_head iso_list; /* isochronous endpoints */ | ||
232 | struct list_head intr_list; /* interruput endpoints */ | ||
233 | struct list_head done_list; /* done transfers */ | ||
234 | }; | ||
235 | |||
236 | struct virtual_root_hub { | ||
237 | int dev_num; /* USB address of the root hub */ | ||
238 | u32 feature; /* indicates what feature has been set */ | ||
239 | struct usb_hub_status hub; | ||
240 | struct usb_port_status port; | ||
241 | }; | ||
242 | |||
243 | enum fhci_gpios { | ||
244 | GPIO_USBOE = 0, | ||
245 | GPIO_USBTP, | ||
246 | GPIO_USBTN, | ||
247 | GPIO_USBRP, | ||
248 | GPIO_USBRN, | ||
249 | /* these are optional */ | ||
250 | GPIO_SPEED, | ||
251 | GPIO_POWER, | ||
252 | NUM_GPIOS, | ||
253 | }; | ||
254 | |||
255 | enum fhci_pins { | ||
256 | PIN_USBOE = 0, | ||
257 | PIN_USBTP, | ||
258 | PIN_USBTN, | ||
259 | NUM_PINS, | ||
260 | }; | ||
261 | |||
262 | struct fhci_hcd { | ||
263 | enum qe_clock fullspeed_clk; | ||
264 | enum qe_clock lowspeed_clk; | ||
265 | struct qe_pin *pins[NUM_PINS]; | ||
266 | int gpios[NUM_GPIOS]; | ||
267 | bool alow_gpios[NUM_GPIOS]; | ||
268 | |||
269 | struct fhci_regs __iomem *regs; /* I/O memory used to communicate */ | ||
270 | struct fhci_pram __iomem *pram; /* Parameter RAM */ | ||
271 | struct gtm_timer *timer; | ||
272 | |||
273 | spinlock_t lock; | ||
274 | struct fhci_usb *usb_lld; /* Low-level driver */ | ||
275 | struct virtual_root_hub *vroot_hub; /* the virtual root hub */ | ||
276 | int active_urbs; | ||
277 | struct fhci_controller_list *hc_list; | ||
278 | struct tasklet_struct *process_done_task; /* tasklet for done list */ | ||
279 | |||
280 | struct list_head empty_eds; | ||
281 | struct list_head empty_tds; | ||
282 | |||
283 | #ifdef CONFIG_FHCI_DEBUG | ||
284 | int usb_irq_stat[13]; | ||
285 | struct dentry *dfs_root; | ||
286 | struct dentry *dfs_regs; | ||
287 | struct dentry *dfs_irq_stat; | ||
288 | #endif | ||
289 | }; | ||
290 | |||
291 | #define USB_FRAME_USAGE 90 | ||
292 | #define FRAME_TIME_USAGE (USB_FRAME_USAGE*10) /* frame time usage */ | ||
293 | #define SW_FIX_TIME_BETWEEN_TRANSACTION 150 /* SW */ | ||
294 | #define MAX_BYTES_PER_FRAME (USB_FRAME_USAGE*15) | ||
295 | #define MAX_PERIODIC_FRAME_USAGE 90 | ||
296 | |||
297 | /* transaction type */ | ||
298 | enum fhci_ta_type { | ||
299 | FHCI_TA_IN = 0, /* input transaction */ | ||
300 | FHCI_TA_OUT, /* output transaction */ | ||
301 | FHCI_TA_SETUP, /* setup transaction */ | ||
302 | }; | ||
303 | |||
304 | /* transfer mode */ | ||
305 | enum fhci_tf_mode { | ||
306 | FHCI_TF_CTRL = 0, | ||
307 | FHCI_TF_ISO, | ||
308 | FHCI_TF_BULK, | ||
309 | FHCI_TF_INTR, | ||
310 | }; | ||
311 | |||
312 | enum fhci_speed { | ||
313 | FHCI_FULL_SPEED, | ||
314 | FHCI_LOW_SPEED, | ||
315 | }; | ||
316 | |||
317 | /* endpoint state */ | ||
318 | enum fhci_ed_state { | ||
319 | FHCI_ED_NEW = 0, /* pipe is new */ | ||
320 | FHCI_ED_OPER, /* pipe is operating */ | ||
321 | FHCI_ED_URB_DEL, /* pipe is in hold because urb is being deleted */ | ||
322 | FHCI_ED_SKIP, /* skip this pipe */ | ||
323 | FHCI_ED_HALTED, /* pipe is halted */ | ||
324 | }; | ||
325 | |||
326 | enum fhci_port_status { | ||
327 | FHCI_PORT_POWER_OFF = 0, | ||
328 | FHCI_PORT_DISABLED, | ||
329 | FHCI_PORT_DISCONNECTING, | ||
330 | FHCI_PORT_WAITING, /* waiting for connection */ | ||
331 | FHCI_PORT_FULL, /* full speed connected */ | ||
332 | FHCI_PORT_LOW, /* low speed connected */ | ||
333 | }; | ||
334 | |||
335 | enum fhci_mem_alloc { | ||
336 | MEM_CACHABLE_SYS = 0x00000001, /* primary DDR,cachable */ | ||
337 | MEM_NOCACHE_SYS = 0x00000004, /* primary DDR,non-cachable */ | ||
338 | MEM_SECONDARY = 0x00000002, /* either secondary DDR or SDRAM */ | ||
339 | MEM_PRAM = 0x00000008, /* multi-user RAM identifier */ | ||
340 | }; | ||
341 | |||
342 | /* USB default parameters*/ | ||
343 | #define DEFAULT_RING_LEN 8 | ||
344 | #define DEFAULT_DATA_MEM MEM_CACHABLE_SYS | ||
345 | |||
346 | struct ed { | ||
347 | u8 dev_addr; /* device address */ | ||
348 | u8 ep_addr; /* endpoint address */ | ||
349 | enum fhci_tf_mode mode; /* USB transfer mode */ | ||
350 | enum fhci_speed speed; | ||
351 | unsigned int max_pkt_size; | ||
352 | enum fhci_ed_state state; | ||
353 | struct list_head td_list; /* a list of all queued TD to this pipe */ | ||
354 | struct list_head node; | ||
355 | |||
356 | /* read only parameters, should be cleared upon initialization */ | ||
357 | u8 toggle_carry; /* toggle carry from the last TD submitted */ | ||
358 | u32 last_iso; /* time stamp of last queued ISO transfer */ | ||
359 | struct td *td_head; /* a pointer to the current TD handled */ | ||
360 | }; | ||
361 | |||
362 | struct td { | ||
363 | void *data; /* a pointer to the data buffer */ | ||
364 | unsigned int len; /* length of the data to be submitted */ | ||
365 | unsigned int actual_len; /* actual bytes transfered on this td */ | ||
366 | enum fhci_ta_type type; /* transaction type */ | ||
367 | u8 toggle; /* toggle for next trans. within this TD */ | ||
368 | u16 iso_index; /* ISO transaction index */ | ||
369 | u16 start_frame; /* start frame time stamp */ | ||
370 | u16 interval; /* interval between trans. (for ISO/Intr) */ | ||
371 | u32 status; /* status of the TD */ | ||
372 | struct ed *ed; /* a handle to the corresponding ED */ | ||
373 | struct urb *urb; /* a handle to the corresponding URB */ | ||
374 | bool ioc; /* Inform On Completion */ | ||
375 | struct list_head node; | ||
376 | |||
377 | /* read only parameters should be cleared upon initialization */ | ||
378 | struct packet *pkt; | ||
379 | int nak_cnt; | ||
380 | int error_cnt; | ||
381 | struct list_head frame_lh; | ||
382 | }; | ||
383 | |||
384 | struct packet { | ||
385 | u8 *data; /* packet data */ | ||
386 | u32 len; /* packet length */ | ||
387 | u32 status; /* status of the packet - equivalent to the status | ||
388 | * field for the corresponding structure td */ | ||
389 | u32 info; /* packet information */ | ||
390 | void __iomem *priv_data; /* private data of the driver (TDs or BDs) */ | ||
391 | }; | ||
392 | |||
393 | /* struct for each URB */ | ||
394 | #define URB_INPROGRESS 0 | ||
395 | #define URB_DEL 1 | ||
396 | |||
397 | /* URB states (state field) */ | ||
398 | #define US_BULK 0 | ||
399 | #define US_BULK0 1 | ||
400 | |||
401 | /* three setup states */ | ||
402 | #define US_CTRL_SETUP 2 | ||
403 | #define US_CTRL_DATA 1 | ||
404 | #define US_CTRL_ACK 0 | ||
405 | |||
406 | #define EP_ZERO 0 | ||
407 | |||
408 | struct urb_priv { | ||
409 | int num_of_tds; | ||
410 | int tds_cnt; | ||
411 | int state; | ||
412 | |||
413 | struct td **tds; | ||
414 | struct ed *ed; | ||
415 | struct timer_list time_out; | ||
416 | }; | ||
417 | |||
418 | struct endpoint { | ||
419 | /* Pointer to ep parameter RAM */ | ||
420 | struct fhci_ep_pram __iomem *ep_pram_ptr; | ||
421 | |||
422 | /* Host transactions */ | ||
423 | struct usb_td __iomem *td_base; /* first TD in the ring */ | ||
424 | struct usb_td __iomem *conf_td; /* next TD for confirm after transac */ | ||
425 | struct usb_td __iomem *empty_td;/* next TD for new transaction req. */ | ||
426 | struct kfifo *empty_frame_Q; /* Empty frames list to use */ | ||
427 | struct kfifo *conf_frame_Q; /* frames passed to TDs,waiting for tx */ | ||
428 | struct kfifo *dummy_packets_Q;/* dummy packets for the CRC overun */ | ||
429 | |||
430 | bool already_pushed_dummy_bd; | ||
431 | }; | ||
432 | |||
433 | /* struct for each 1mSec frame time */ | ||
434 | #define FRAME_IS_TRANSMITTED 0x00 | ||
435 | #define FRAME_TIMER_END_TRANSMISSION 0x01 | ||
436 | #define FRAME_DATA_END_TRANSMISSION 0x02 | ||
437 | #define FRAME_END_TRANSMISSION 0x03 | ||
438 | #define FRAME_IS_PREPARED 0x04 | ||
439 | |||
440 | struct fhci_time_frame { | ||
441 | u16 frame_num; /* frame number */ | ||
442 | u16 total_bytes; /* total bytes submitted within this frame */ | ||
443 | u8 frame_status; /* flag that indicates to stop fill this frame */ | ||
444 | struct list_head tds_list; /* all tds of this frame */ | ||
445 | }; | ||
446 | |||
447 | /* internal driver structure*/ | ||
448 | struct fhci_usb { | ||
449 | u16 saved_msk; /* saving of the USB mask register */ | ||
450 | struct endpoint *ep0; /* pointer for endpoint0 structure */ | ||
451 | int intr_nesting_cnt; /* interrupt nesting counter */ | ||
452 | u16 max_frame_usage; /* max frame time usage,in micro-sec */ | ||
453 | u16 max_bytes_per_frame; /* max byte can be tx in one time frame */ | ||
454 | u32 sw_transaction_time; /* sw complete trans time,in micro-sec */ | ||
455 | struct fhci_time_frame *actual_frame; | ||
456 | struct fhci_controller_list *hc_list; /* main structure for hc */ | ||
457 | struct virtual_root_hub *vroot_hub; | ||
458 | enum fhci_port_status port_status; /* v_rh port status */ | ||
459 | |||
460 | u32 (*transfer_confirm)(struct fhci_hcd *fhci); | ||
461 | |||
462 | struct fhci_hcd *fhci; | ||
463 | }; | ||
464 | |||
465 | /* | ||
466 | * Various helpers and prototypes below. | ||
467 | */ | ||
468 | |||
469 | static inline u16 get_frame_num(struct fhci_hcd *fhci) | ||
470 | { | ||
471 | return in_be16(&fhci->pram->frame_num) & 0x07ff; | ||
472 | } | ||
473 | |||
474 | #define fhci_dbg(fhci, fmt, args...) \ | ||
475 | dev_dbg(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
476 | #define fhci_vdbg(fhci, fmt, args...) \ | ||
477 | dev_vdbg(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
478 | #define fhci_err(fhci, fmt, args...) \ | ||
479 | dev_err(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
480 | #define fhci_info(fhci, fmt, args...) \ | ||
481 | dev_info(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
482 | #define fhci_warn(fhci, fmt, args...) \ | ||
483 | dev_warn(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
484 | |||
485 | static inline struct fhci_hcd *hcd_to_fhci(struct usb_hcd *hcd) | ||
486 | { | ||
487 | return (struct fhci_hcd *)hcd->hcd_priv; | ||
488 | } | ||
489 | |||
490 | static inline struct usb_hcd *fhci_to_hcd(struct fhci_hcd *fhci) | ||
491 | { | ||
492 | return container_of((void *)fhci, struct usb_hcd, hcd_priv); | ||
493 | } | ||
494 | |||
495 | /* fifo of pointers */ | ||
496 | static inline struct kfifo *cq_new(int size) | ||
497 | { | ||
498 | return kfifo_alloc(size * sizeof(void *), GFP_KERNEL, NULL); | ||
499 | } | ||
500 | |||
501 | static inline void cq_delete(struct kfifo *kfifo) | ||
502 | { | ||
503 | kfifo_free(kfifo); | ||
504 | } | ||
505 | |||
506 | static inline unsigned int cq_howmany(struct kfifo *kfifo) | ||
507 | { | ||
508 | return __kfifo_len(kfifo) / sizeof(void *); | ||
509 | } | ||
510 | |||
511 | static inline int cq_put(struct kfifo *kfifo, void *p) | ||
512 | { | ||
513 | return __kfifo_put(kfifo, (void *)&p, sizeof(p)); | ||
514 | } | ||
515 | |||
516 | static inline void *cq_get(struct kfifo *kfifo) | ||
517 | { | ||
518 | void *p = NULL; | ||
519 | |||
520 | __kfifo_get(kfifo, (void *)&p, sizeof(p)); | ||
521 | return p; | ||
522 | } | ||
523 | |||
524 | /* fhci-hcd.c */ | ||
525 | void fhci_start_sof_timer(struct fhci_hcd *fhci); | ||
526 | void fhci_stop_sof_timer(struct fhci_hcd *fhci); | ||
527 | u16 fhci_get_sof_timer_count(struct fhci_usb *usb); | ||
528 | void fhci_usb_enable_interrupt(struct fhci_usb *usb); | ||
529 | void fhci_usb_disable_interrupt(struct fhci_usb *usb); | ||
530 | int fhci_ioports_check_bus_state(struct fhci_hcd *fhci); | ||
531 | |||
532 | /* fhci-mem.c */ | ||
533 | void fhci_recycle_empty_td(struct fhci_hcd *fhci, struct td *td); | ||
534 | void fhci_recycle_empty_ed(struct fhci_hcd *fhci, struct ed *ed); | ||
535 | struct ed *fhci_get_empty_ed(struct fhci_hcd *fhci); | ||
536 | struct td *fhci_td_fill(struct fhci_hcd *fhci, struct urb *urb, | ||
537 | struct urb_priv *urb_priv, struct ed *ed, u16 index, | ||
538 | enum fhci_ta_type type, int toggle, u8 *data, u32 len, | ||
539 | u16 interval, u16 start_frame, bool ioc); | ||
540 | void fhci_add_tds_to_ed(struct ed *ed, struct td **td_list, int number); | ||
541 | |||
542 | /* fhci-hub.c */ | ||
543 | void fhci_config_transceiver(struct fhci_hcd *fhci, | ||
544 | enum fhci_port_status status); | ||
545 | void fhci_port_disable(struct fhci_hcd *fhci); | ||
546 | void fhci_port_enable(void *lld); | ||
547 | void fhci_io_port_generate_reset(struct fhci_hcd *fhci); | ||
548 | void fhci_port_reset(void *lld); | ||
549 | int fhci_hub_status_data(struct usb_hcd *hcd, char *buf); | ||
550 | int fhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | ||
551 | u16 wIndex, char *buf, u16 wLength); | ||
552 | |||
553 | /* fhci-tds.c */ | ||
554 | void fhci_flush_bds(struct fhci_usb *usb); | ||
555 | void fhci_flush_actual_frame(struct fhci_usb *usb); | ||
556 | u32 fhci_host_transaction(struct fhci_usb *usb, struct packet *pkt, | ||
557 | enum fhci_ta_type trans_type, u8 dest_addr, | ||
558 | u8 dest_ep, enum fhci_tf_mode trans_mode, | ||
559 | enum fhci_speed dest_speed, u8 data_toggle); | ||
560 | void fhci_host_transmit_actual_frame(struct fhci_usb *usb); | ||
561 | void fhci_tx_conf_interrupt(struct fhci_usb *usb); | ||
562 | void fhci_push_dummy_bd(struct endpoint *ep); | ||
563 | u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, | ||
564 | u32 ring_len); | ||
565 | void fhci_init_ep_registers(struct fhci_usb *usb, | ||
566 | struct endpoint *ep, | ||
567 | enum fhci_mem_alloc data_mem); | ||
568 | void fhci_ep0_free(struct fhci_usb *usb); | ||
569 | |||
570 | /* fhci-sched.c */ | ||
571 | extern struct tasklet_struct fhci_tasklet; | ||
572 | void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt); | ||
573 | void fhci_flush_all_transmissions(struct fhci_usb *usb); | ||
574 | void fhci_schedule_transactions(struct fhci_usb *usb); | ||
575 | void fhci_device_connected_interrupt(struct fhci_hcd *fhci); | ||
576 | void fhci_device_disconnected_interrupt(struct fhci_hcd *fhci); | ||
577 | void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb); | ||
578 | u32 fhci_transfer_confirm_callback(struct fhci_hcd *fhci); | ||
579 | irqreturn_t fhci_irq(struct usb_hcd *hcd); | ||
580 | irqreturn_t fhci_frame_limit_timer_irq(int irq, void *_hcd); | ||
581 | |||
582 | /* fhci-q.h */ | ||
583 | void fhci_urb_complete_free(struct fhci_hcd *fhci, struct urb *urb); | ||
584 | struct td *fhci_remove_td_from_ed(struct ed *ed); | ||
585 | struct td *fhci_remove_td_from_frame(struct fhci_time_frame *frame); | ||
586 | void fhci_move_td_from_ed_to_done_list(struct fhci_usb *usb, struct ed *ed); | ||
587 | struct td *fhci_peek_td_from_frame(struct fhci_time_frame *frame); | ||
588 | void fhci_add_td_to_frame(struct fhci_time_frame *frame, struct td *td); | ||
589 | struct td *fhci_remove_td_from_done_list(struct fhci_controller_list *p_list); | ||
590 | void fhci_done_td(struct urb *urb, struct td *td); | ||
591 | void fhci_del_ed_list(struct fhci_hcd *fhci, struct ed *ed); | ||
592 | |||
593 | #ifdef CONFIG_FHCI_DEBUG | ||
594 | |||
595 | void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er); | ||
596 | void fhci_dfs_destroy(struct fhci_hcd *fhci); | ||
597 | void fhci_dfs_create(struct fhci_hcd *fhci); | ||
598 | |||
599 | #else | ||
600 | |||
601 | static inline void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er) {} | ||
602 | static inline void fhci_dfs_destroy(struct fhci_hcd *fhci) {} | ||
603 | static inline void fhci_dfs_create(struct fhci_hcd *fhci) {} | ||
604 | |||
605 | #endif /* CONFIG_FHCI_DEBUG */ | ||
606 | |||
607 | #endif /* __FHCI_H */ | ||
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 8582236e4cad..cbf30e515f29 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c | |||
@@ -464,8 +464,7 @@ static int __hwahc_dev_set_key(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, | |||
464 | port_idx << 8 | iface_no, | 464 | port_idx << 8 | iface_no, |
465 | keyd, keyd_len, 1000 /* FIXME: arbitrary */); | 465 | keyd, keyd_len, 1000 /* FIXME: arbitrary */); |
466 | 466 | ||
467 | memset(keyd, 0, sizeof(*keyd)); /* clear keys etc. */ | 467 | kzfree(keyd); /* clear keys etc. */ |
468 | kfree(keyd); | ||
469 | return result; | 468 | return result; |
470 | } | 469 | } |
471 | 470 | ||
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 4dda31b26892..a2b305477afe 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -772,7 +772,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
772 | break; | 772 | break; |
773 | case PIPE_INTERRUPT: | 773 | case PIPE_INTERRUPT: |
774 | urb->interval = ep->period; | 774 | urb->interval = ep->period; |
775 | ep->length = min((int)ep->maxpacket, | 775 | ep->length = min_t(u32, ep->maxpacket, |
776 | urb->transfer_buffer_length); | 776 | urb->transfer_buffer_length); |
777 | 777 | ||
778 | /* urb submitted for already existing endpoint */ | 778 | /* urb submitted for already existing endpoint */ |
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index aa211bafcff9..12db961acdfb 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h | |||
@@ -563,7 +563,7 @@ static void urb_dbg(struct urb *urb, char *msg) | |||
563 | */ | 563 | */ |
564 | static inline void dump_ptd(struct ptd *ptd) | 564 | static inline void dump_ptd(struct ptd *ptd) |
565 | { | 565 | { |
566 | printk("td: %x %d%c%d %d,%d,%d %x %x%x%x\n", | 566 | printk(KERN_WARNING "td: %x %d%c%d %d,%d,%d %x %x%x%x\n", |
567 | PTD_GET_CC(ptd), PTD_GET_FA(ptd), | 567 | PTD_GET_CC(ptd), PTD_GET_FA(ptd), |
568 | PTD_DIR_STR(ptd), PTD_GET_EP(ptd), | 568 | PTD_DIR_STR(ptd), PTD_GET_EP(ptd), |
569 | PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), | 569 | PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), |
@@ -576,7 +576,7 @@ static inline void dump_ptd_out_data(struct ptd *ptd, u8 * buf) | |||
576 | int k; | 576 | int k; |
577 | 577 | ||
578 | if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) { | 578 | if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) { |
579 | printk("-> "); | 579 | printk(KERN_WARNING "-> "); |
580 | for (k = 0; k < PTD_GET_LEN(ptd); ++k) | 580 | for (k = 0; k < PTD_GET_LEN(ptd); ++k) |
581 | printk("%02x ", ((u8 *) buf)[k]); | 581 | printk("%02x ", ((u8 *) buf)[k]); |
582 | printk("\n"); | 582 | printk("\n"); |
@@ -588,13 +588,13 @@ static inline void dump_ptd_in_data(struct ptd *ptd, u8 * buf) | |||
588 | int k; | 588 | int k; |
589 | 589 | ||
590 | if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) { | 590 | if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) { |
591 | printk("<- "); | 591 | printk(KERN_WARNING "<- "); |
592 | for (k = 0; k < PTD_GET_COUNT(ptd); ++k) | 592 | for (k = 0; k < PTD_GET_COUNT(ptd); ++k) |
593 | printk("%02x ", ((u8 *) buf)[k]); | 593 | printk("%02x ", ((u8 *) buf)[k]); |
594 | printk("\n"); | 594 | printk("\n"); |
595 | } | 595 | } |
596 | if (PTD_GET_LAST(ptd)) | 596 | if (PTD_GET_LAST(ptd)) |
597 | printk("-\n"); | 597 | printk(KERN_WARNING "-\n"); |
598 | } | 598 | } |
599 | 599 | ||
600 | #else | 600 | #else |
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index b899f1a59c26..cd07ea3f0c63 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c | |||
@@ -644,7 +644,7 @@ static void transform_add_int(struct isp1760_hcd *priv, struct isp1760_qh *qh, | |||
644 | 644 | ||
645 | if (urb->dev->speed != USB_SPEED_HIGH) { | 645 | if (urb->dev->speed != USB_SPEED_HIGH) { |
646 | /* split */ | 646 | /* split */ |
647 | ptd->dw5 = __constant_cpu_to_le32(0x1c); | 647 | ptd->dw5 = cpu_to_le32(0x1c); |
648 | 648 | ||
649 | if (qh->period >= 32) | 649 | if (qh->period >= 32) |
650 | period = qh->period / 2; | 650 | period = qh->period / 2; |
@@ -819,6 +819,13 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, | |||
819 | u32 atl_regs, payload; | 819 | u32 atl_regs, payload; |
820 | u32 buffstatus; | 820 | u32 buffstatus; |
821 | 821 | ||
822 | /* | ||
823 | * When this function is called from the interrupt handler to enqueue | ||
824 | * a follow-up packet, the SKIP register gets written and read back | ||
825 | * almost immediately. With ISP1761, this register requires a delay of | ||
826 | * 195ns between a write and subsequent read (see section 15.1.1.3). | ||
827 | */ | ||
828 | ndelay(195); | ||
822 | skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG); | 829 | skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG); |
823 | 830 | ||
824 | BUG_ON(!skip_map); | 831 | BUG_ON(!skip_map); |
@@ -853,6 +860,13 @@ static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, | |||
853 | u32 int_regs, payload; | 860 | u32 int_regs, payload; |
854 | u32 buffstatus; | 861 | u32 buffstatus; |
855 | 862 | ||
863 | /* | ||
864 | * When this function is called from the interrupt handler to enqueue | ||
865 | * a follow-up packet, the SKIP register gets written and read back | ||
866 | * almost immediately. With ISP1761, this register requires a delay of | ||
867 | * 195ns between a write and subsequent read (see section 15.1.1.3). | ||
868 | */ | ||
869 | ndelay(195); | ||
856 | skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG); | 870 | skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG); |
857 | 871 | ||
858 | BUG_ON(!skip_map); | 872 | BUG_ON(!skip_map); |
@@ -1054,7 +1068,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) | |||
1054 | priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + | 1068 | priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + |
1055 | atl_regs, sizeof(ptd)); | 1069 | atl_regs, sizeof(ptd)); |
1056 | 1070 | ||
1057 | ptd.dw0 |= __constant_cpu_to_le32(PTD_VALID); | 1071 | ptd.dw0 |= cpu_to_le32(PTD_VALID); |
1058 | priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + | 1072 | priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + |
1059 | atl_regs, sizeof(ptd)); | 1073 | atl_regs, sizeof(ptd)); |
1060 | 1074 | ||
@@ -2235,9 +2249,10 @@ void deinit_kmem_cache(void) | |||
2235 | kmem_cache_destroy(qh_cachep); | 2249 | kmem_cache_destroy(qh_cachep); |
2236 | } | 2250 | } |
2237 | 2251 | ||
2238 | struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, | 2252 | struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, |
2239 | u64 irqflags, struct device *dev, const char *busname, | 2253 | int irq, unsigned long irqflags, |
2240 | unsigned int devflags) | 2254 | struct device *dev, const char *busname, |
2255 | unsigned int devflags) | ||
2241 | { | 2256 | { |
2242 | struct usb_hcd *hcd; | 2257 | struct usb_hcd *hcd; |
2243 | struct isp1760_hcd *priv; | 2258 | struct isp1760_hcd *priv; |
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index a9daea587962..462f4943cb1b 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h | |||
@@ -2,9 +2,10 @@ | |||
2 | #define _ISP1760_HCD_H_ | 2 | #define _ISP1760_HCD_H_ |
3 | 3 | ||
4 | /* exports for if */ | 4 | /* exports for if */ |
5 | struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, | 5 | struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, |
6 | u64 irqflags, struct device *dev, const char *busname, | 6 | int irq, unsigned long irqflags, |
7 | unsigned int devflags); | 7 | struct device *dev, const char *busname, |
8 | unsigned int devflags); | ||
8 | int init_kmem_once(void); | 9 | int init_kmem_once(void); |
9 | void deinit_kmem_cache(void); | 10 | void deinit_kmem_cache(void); |
10 | 11 | ||
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 4cf7ca428b33..3fa3a1702796 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/usb.h> | 11 | #include <linux/usb.h> |
12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
13 | #include <linux/platform_device.h> | ||
13 | 14 | ||
14 | #include "../core/hcd.h" | 15 | #include "../core/hcd.h" |
15 | #include "isp1760-hcd.h" | 16 | #include "isp1760-hcd.h" |
@@ -300,39 +301,101 @@ static struct pci_driver isp1761_pci_driver = { | |||
300 | }; | 301 | }; |
301 | #endif | 302 | #endif |
302 | 303 | ||
304 | static int __devinit isp1760_plat_probe(struct platform_device *pdev) | ||
305 | { | ||
306 | int ret = 0; | ||
307 | struct usb_hcd *hcd; | ||
308 | struct resource *mem_res; | ||
309 | struct resource *irq_res; | ||
310 | resource_size_t mem_size; | ||
311 | unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED; | ||
312 | |||
313 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
314 | if (!mem_res) { | ||
315 | pr_warning("isp1760: Memory resource not available\n"); | ||
316 | ret = -ENODEV; | ||
317 | goto out; | ||
318 | } | ||
319 | mem_size = resource_size(mem_res); | ||
320 | if (!request_mem_region(mem_res->start, mem_size, "isp1760")) { | ||
321 | pr_warning("isp1760: Cannot reserve the memory resource\n"); | ||
322 | ret = -EBUSY; | ||
323 | goto out; | ||
324 | } | ||
325 | |||
326 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
327 | if (!irq_res) { | ||
328 | pr_warning("isp1760: IRQ resource not available\n"); | ||
329 | return -ENODEV; | ||
330 | } | ||
331 | irqflags |= irq_res->flags & IRQF_TRIGGER_MASK; | ||
332 | |||
333 | hcd = isp1760_register(mem_res->start, mem_size, irq_res->start, | ||
334 | irqflags, &pdev->dev, dev_name(&pdev->dev), 0); | ||
335 | if (IS_ERR(hcd)) { | ||
336 | pr_warning("isp1760: Failed to register the HCD device\n"); | ||
337 | ret = -ENODEV; | ||
338 | goto cleanup; | ||
339 | } | ||
340 | |||
341 | pr_info("ISP1760 USB device initialised\n"); | ||
342 | return ret; | ||
343 | |||
344 | cleanup: | ||
345 | release_mem_region(mem_res->start, mem_size); | ||
346 | out: | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | static int __devexit isp1760_plat_remove(struct platform_device *pdev) | ||
351 | { | ||
352 | struct resource *mem_res; | ||
353 | resource_size_t mem_size; | ||
354 | |||
355 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
356 | mem_size = resource_size(mem_res); | ||
357 | release_mem_region(mem_res->start, mem_size); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static struct platform_driver isp1760_plat_driver = { | ||
363 | .probe = isp1760_plat_probe, | ||
364 | .remove = isp1760_plat_remove, | ||
365 | .driver = { | ||
366 | .name = "isp1760", | ||
367 | }, | ||
368 | }; | ||
369 | |||
303 | static int __init isp1760_init(void) | 370 | static int __init isp1760_init(void) |
304 | { | 371 | { |
305 | int ret; | 372 | int ret, any_ret = -ENODEV; |
306 | 373 | ||
307 | init_kmem_once(); | 374 | init_kmem_once(); |
308 | 375 | ||
376 | ret = platform_driver_register(&isp1760_plat_driver); | ||
377 | if (!ret) | ||
378 | any_ret = 0; | ||
309 | #ifdef CONFIG_PPC_OF | 379 | #ifdef CONFIG_PPC_OF |
310 | ret = of_register_platform_driver(&isp1760_of_driver); | 380 | ret = of_register_platform_driver(&isp1760_of_driver); |
311 | if (ret) { | 381 | if (!ret) |
312 | deinit_kmem_cache(); | 382 | any_ret = 0; |
313 | return ret; | ||
314 | } | ||
315 | #endif | 383 | #endif |
316 | #ifdef CONFIG_PCI | 384 | #ifdef CONFIG_PCI |
317 | ret = pci_register_driver(&isp1761_pci_driver); | 385 | ret = pci_register_driver(&isp1761_pci_driver); |
318 | if (ret) | 386 | if (!ret) |
319 | goto unreg_of; | 387 | any_ret = 0; |
320 | #endif | 388 | #endif |
321 | return ret; | ||
322 | 389 | ||
323 | #ifdef CONFIG_PCI | 390 | if (any_ret) |
324 | unreg_of: | 391 | deinit_kmem_cache(); |
325 | #endif | 392 | return any_ret; |
326 | #ifdef CONFIG_PPC_OF | ||
327 | of_unregister_platform_driver(&isp1760_of_driver); | ||
328 | #endif | ||
329 | deinit_kmem_cache(); | ||
330 | return ret; | ||
331 | } | 393 | } |
332 | module_init(isp1760_init); | 394 | module_init(isp1760_init); |
333 | 395 | ||
334 | static void __exit isp1760_exit(void) | 396 | static void __exit isp1760_exit(void) |
335 | { | 397 | { |
398 | platform_driver_unregister(&isp1760_plat_driver); | ||
336 | #ifdef CONFIG_PPC_OF | 399 | #ifdef CONFIG_PPC_OF |
337 | of_unregister_platform_driver(&isp1760_of_driver); | 400 | of_unregister_platform_driver(&isp1760_of_driver); |
338 | #endif | 401 | #endif |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 65a9609f4ad6..25db704f3a2a 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -593,12 +593,10 @@ static int ohci_run (struct ohci_hcd *ohci) | |||
593 | * to be checked in case boot firmware (BIOS/SMM/...) has set up | 593 | * to be checked in case boot firmware (BIOS/SMM/...) has set up |
594 | * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM). | 594 | * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM). |
595 | * If the bus glue detected wakeup capability then it should | 595 | * If the bus glue detected wakeup capability then it should |
596 | * already be enabled. Either way, if wakeup should be enabled | 596 | * already be enabled; if so we'll just enable it again. |
597 | * but isn't, we'll enable it now. | ||
598 | */ | 597 | */ |
599 | if ((ohci->hc_control & OHCI_CTRL_RWC) != 0 | 598 | if ((ohci->hc_control & OHCI_CTRL_RWC) != 0) |
600 | && !device_can_wakeup(hcd->self.controller)) | 599 | device_set_wakeup_capable(hcd->self.controller, 1); |
601 | device_init_wakeup(hcd->self.controller, 1); | ||
602 | 600 | ||
603 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { | 601 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { |
604 | case OHCI_USB_OPER: | 602 | case OHCI_USB_OPER: |
@@ -999,7 +997,7 @@ MODULE_LICENSE ("GPL"); | |||
999 | #define SA1111_DRIVER ohci_hcd_sa1111_driver | 997 | #define SA1111_DRIVER ohci_hcd_sa1111_driver |
1000 | #endif | 998 | #endif |
1001 | 999 | ||
1002 | #ifdef CONFIG_ARCH_S3C2410 | 1000 | #if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX) |
1003 | #include "ohci-s3c2410.c" | 1001 | #include "ohci-s3c2410.c" |
1004 | #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver | 1002 | #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver |
1005 | #endif | 1003 | #endif |
@@ -1051,7 +1049,8 @@ MODULE_LICENSE ("GPL"); | |||
1051 | 1049 | ||
1052 | #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 1050 | #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
1053 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | 1051 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
1054 | defined(CONFIG_CPU_SUBTYPE_SH7763) | 1052 | defined(CONFIG_CPU_SUBTYPE_SH7763) || \ |
1053 | defined(CONFIG_CPU_SUBTYPE_SH7786) | ||
1055 | #include "ohci-sh.c" | 1054 | #include "ohci-sh.c" |
1056 | #define PLATFORM_DRIVER ohci_hcd_sh_driver | 1055 | #define PLATFORM_DRIVER ohci_hcd_sh_driver |
1057 | #endif | 1056 | #endif |
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 4bbddb73abd9..f3aaba35e912 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c | |||
@@ -315,14 +315,14 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, | |||
315 | return -ENODEV; | 315 | return -ENODEV; |
316 | } | 316 | } |
317 | 317 | ||
318 | usb_host_ck = clk_get(0, "usb_hhc_ck"); | 318 | usb_host_ck = clk_get(&pdev->dev, "usb_hhc_ck"); |
319 | if (IS_ERR(usb_host_ck)) | 319 | if (IS_ERR(usb_host_ck)) |
320 | return PTR_ERR(usb_host_ck); | 320 | return PTR_ERR(usb_host_ck); |
321 | 321 | ||
322 | if (!cpu_is_omap15xx()) | 322 | if (!cpu_is_omap15xx()) |
323 | usb_dc_ck = clk_get(0, "usb_dc_ck"); | 323 | usb_dc_ck = clk_get(&pdev->dev, "usb_dc_ck"); |
324 | else | 324 | else |
325 | usb_dc_ck = clk_get(0, "lb_ck"); | 325 | usb_dc_ck = clk_get(&pdev->dev, "lb_ck"); |
326 | 326 | ||
327 | if (IS_ERR(usb_dc_ck)) { | 327 | if (IS_ERR(usb_dc_ck)) { |
328 | clk_put(usb_host_ck); | 328 | clk_put(usb_host_ck); |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 8b28ae7865ba..f9961b4c0da3 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -487,8 +487,6 @@ static struct pci_driver ohci_pci_driver = { | |||
487 | 487 | ||
488 | #ifdef CONFIG_PM | 488 | #ifdef CONFIG_PM |
489 | .suspend = usb_hcd_pci_suspend, | 489 | .suspend = usb_hcd_pci_suspend, |
490 | .suspend_late = usb_hcd_pci_suspend_late, | ||
491 | .resume_early = usb_hcd_pci_resume_early, | ||
492 | .resume = usb_hcd_pci_resume, | 490 | .resume = usb_hcd_pci_resume, |
493 | #endif | 491 | #endif |
494 | 492 | ||
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index f46af7a718d4..a68af2dd55ca 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c | |||
@@ -21,9 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | 24 | #include <plat/usb-control.h> | |
25 | #include <mach/hardware.h> | ||
26 | #include <mach/usb-control.h> | ||
27 | 25 | ||
28 | #define valid_port(idx) ((idx) == 1 || (idx) == 2) | 26 | #define valid_port(idx) ((idx) == 1 || (idx) == 2) |
29 | 27 | ||
@@ -372,7 +370,7 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, | |||
372 | 370 | ||
373 | usb_clk = clk_get(&dev->dev, "usb-bus-host"); | 371 | usb_clk = clk_get(&dev->dev, "usb-bus-host"); |
374 | if (IS_ERR(usb_clk)) { | 372 | if (IS_ERR(usb_clk)) { |
375 | dev_err(&dev->dev, "cannot get usb-host clock\n"); | 373 | dev_err(&dev->dev, "cannot get usb-bus-host clock\n"); |
376 | retval = -ENOENT; | 374 | retval = -ENOENT; |
377 | goto err_clk; | 375 | goto err_clk; |
378 | } | 376 | } |
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 75548f7c716b..5ac489ee3dab 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c | |||
@@ -845,14 +845,14 @@ static inline void qh_update(struct oxu_hcd *oxu, | |||
845 | is_out = !(qtd->hw_token & cpu_to_le32(1 << 8)); | 845 | is_out = !(qtd->hw_token & cpu_to_le32(1 << 8)); |
846 | epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f; | 846 | epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f; |
847 | if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) { | 847 | if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) { |
848 | qh->hw_token &= ~__constant_cpu_to_le32(QTD_TOGGLE); | 848 | qh->hw_token &= ~cpu_to_le32(QTD_TOGGLE); |
849 | usb_settoggle(qh->dev, epnum, is_out, 1); | 849 | usb_settoggle(qh->dev, epnum, is_out, 1); |
850 | } | 850 | } |
851 | } | 851 | } |
852 | 852 | ||
853 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ | 853 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ |
854 | wmb(); | 854 | wmb(); |
855 | qh->hw_token &= __constant_cpu_to_le32(QTD_TOGGLE | QTD_STS_PING); | 855 | qh->hw_token &= cpu_to_le32(QTD_TOGGLE | QTD_STS_PING); |
856 | } | 856 | } |
857 | 857 | ||
858 | /* If it weren't for a common silicon quirk (writing the dummy into the qh | 858 | /* If it weren't for a common silicon quirk (writing the dummy into the qh |
@@ -937,7 +937,7 @@ __acquires(oxu->lock) | |||
937 | struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; | 937 | struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; |
938 | 938 | ||
939 | /* S-mask in a QH means it's an interrupt urb */ | 939 | /* S-mask in a QH means it's an interrupt urb */ |
940 | if ((qh->hw_info2 & __constant_cpu_to_le32(QH_SMASK)) != 0) { | 940 | if ((qh->hw_info2 & cpu_to_le32(QH_SMASK)) != 0) { |
941 | 941 | ||
942 | /* ... update hc-wide periodic stats (for usbfs) */ | 942 | /* ... update hc-wide periodic stats (for usbfs) */ |
943 | oxu_to_hcd(oxu)->self.bandwidth_int_reqs--; | 943 | oxu_to_hcd(oxu)->self.bandwidth_int_reqs--; |
@@ -981,7 +981,7 @@ static void unlink_async(struct oxu_hcd *oxu, struct ehci_qh *qh); | |||
981 | static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh); | 981 | static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh); |
982 | static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh); | 982 | static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh); |
983 | 983 | ||
984 | #define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT) | 984 | #define HALT_BIT cpu_to_le32(QTD_STS_HALT) |
985 | 985 | ||
986 | /* Process and free completed qtds for a qh, returning URBs to drivers. | 986 | /* Process and free completed qtds for a qh, returning URBs to drivers. |
987 | * Chases up to qh->hw_current. Returns number of completions called, | 987 | * Chases up to qh->hw_current. Returns number of completions called, |
@@ -1160,7 +1160,7 @@ halt: | |||
1160 | /* should be rare for periodic transfers, | 1160 | /* should be rare for periodic transfers, |
1161 | * except maybe high bandwidth ... | 1161 | * except maybe high bandwidth ... |
1162 | */ | 1162 | */ |
1163 | if ((__constant_cpu_to_le32(QH_SMASK) | 1163 | if ((cpu_to_le32(QH_SMASK) |
1164 | & qh->hw_info2) != 0) { | 1164 | & qh->hw_info2) != 0) { |
1165 | intr_deschedule(oxu, qh); | 1165 | intr_deschedule(oxu, qh); |
1166 | (void) qh_schedule(oxu, qh); | 1166 | (void) qh_schedule(oxu, qh); |
@@ -1350,7 +1350,7 @@ static struct list_head *qh_urb_transaction(struct oxu_hcd *oxu, | |||
1350 | } | 1350 | } |
1351 | 1351 | ||
1352 | /* by default, enable interrupt on urb completion */ | 1352 | /* by default, enable interrupt on urb completion */ |
1353 | qtd->hw_token |= __constant_cpu_to_le32(QTD_IOC); | 1353 | qtd->hw_token |= cpu_to_le32(QTD_IOC); |
1354 | return head; | 1354 | return head; |
1355 | 1355 | ||
1356 | cleanup: | 1356 | cleanup: |
@@ -1539,7 +1539,7 @@ static void qh_link_async(struct oxu_hcd *oxu, struct ehci_qh *qh) | |||
1539 | /* qtd completions reported later by interrupt */ | 1539 | /* qtd completions reported later by interrupt */ |
1540 | } | 1540 | } |
1541 | 1541 | ||
1542 | #define QH_ADDR_MASK __constant_cpu_to_le32(0x7f) | 1542 | #define QH_ADDR_MASK cpu_to_le32(0x7f) |
1543 | 1543 | ||
1544 | /* | 1544 | /* |
1545 | * For control/bulk/interrupt, return QH with these TDs appended. | 1545 | * For control/bulk/interrupt, return QH with these TDs appended. |
@@ -2012,7 +2012,7 @@ static void qh_unlink_periodic(struct oxu_hcd *oxu, struct ehci_qh *qh) | |||
2012 | * and this qh is active in the current uframe | 2012 | * and this qh is active in the current uframe |
2013 | * (and overlay token SplitXstate is false?) | 2013 | * (and overlay token SplitXstate is false?) |
2014 | * THEN | 2014 | * THEN |
2015 | * qh->hw_info1 |= __constant_cpu_to_le32(1 << 7 "ignore"); | 2015 | * qh->hw_info1 |= cpu_to_le32(1 << 7 "ignore"); |
2016 | */ | 2016 | */ |
2017 | 2017 | ||
2018 | /* high bandwidth, or otherwise part of every microframe */ | 2018 | /* high bandwidth, or otherwise part of every microframe */ |
@@ -2057,7 +2057,7 @@ static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh) | |||
2057 | * active high speed queues may need bigger delays... | 2057 | * active high speed queues may need bigger delays... |
2058 | */ | 2058 | */ |
2059 | if (list_empty(&qh->qtd_list) | 2059 | if (list_empty(&qh->qtd_list) |
2060 | || (__constant_cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0) | 2060 | || (cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0) |
2061 | wait = 2; | 2061 | wait = 2; |
2062 | else | 2062 | else |
2063 | wait = 55; /* worst case: 3 * 1024 */ | 2063 | wait = 55; /* worst case: 3 * 1024 */ |
@@ -2183,10 +2183,10 @@ static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh) | |||
2183 | qh->start = frame; | 2183 | qh->start = frame; |
2184 | 2184 | ||
2185 | /* reset S-frame and (maybe) C-frame masks */ | 2185 | /* reset S-frame and (maybe) C-frame masks */ |
2186 | qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK)); | 2186 | qh->hw_info2 &= cpu_to_le32(~(QH_CMASK | QH_SMASK)); |
2187 | qh->hw_info2 |= qh->period | 2187 | qh->hw_info2 |= qh->period |
2188 | ? cpu_to_le32(1 << uframe) | 2188 | ? cpu_to_le32(1 << uframe) |
2189 | : __constant_cpu_to_le32(QH_SMASK); | 2189 | : cpu_to_le32(QH_SMASK); |
2190 | qh->hw_info2 |= c_mask; | 2190 | qh->hw_info2 |= c_mask; |
2191 | } else | 2191 | } else |
2192 | oxu_dbg(oxu, "reused qh %p schedule\n", qh); | 2192 | oxu_dbg(oxu, "reused qh %p schedule\n", qh); |
@@ -2684,7 +2684,7 @@ static int oxu_reset(struct usb_hcd *hcd) | |||
2684 | oxu->urb_len = 0; | 2684 | oxu->urb_len = 0; |
2685 | 2685 | ||
2686 | /* FIMXE */ | 2686 | /* FIMXE */ |
2687 | hcd->self.controller->dma_mask = 0UL; | 2687 | hcd->self.controller->dma_mask = NULL; |
2688 | 2688 | ||
2689 | if (oxu->is_otg) { | 2689 | if (oxu->is_otg) { |
2690 | oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET; | 2690 | oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET; |
diff --git a/drivers/usb/host/oxu210hp.h b/drivers/usb/host/oxu210hp.h index 8910e271cc7d..1c216ad9aad2 100644 --- a/drivers/usb/host/oxu210hp.h +++ b/drivers/usb/host/oxu210hp.h | |||
@@ -235,21 +235,21 @@ struct ehci_qtd { | |||
235 | } __attribute__ ((aligned(32))); | 235 | } __attribute__ ((aligned(32))); |
236 | 236 | ||
237 | /* mask NakCnt+T in qh->hw_alt_next */ | 237 | /* mask NakCnt+T in qh->hw_alt_next */ |
238 | #define QTD_MASK __constant_cpu_to_le32 (~0x1f) | 238 | #define QTD_MASK cpu_to_le32 (~0x1f) |
239 | 239 | ||
240 | #define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) | 240 | #define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) |
241 | 241 | ||
242 | /* Type tag from {qh, itd, sitd, fstn}->hw_next */ | 242 | /* Type tag from {qh, itd, sitd, fstn}->hw_next */ |
243 | #define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1)) | 243 | #define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1)) |
244 | 244 | ||
245 | /* values for that type tag */ | 245 | /* values for that type tag */ |
246 | #define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) | 246 | #define Q_TYPE_QH cpu_to_le32 (1 << 1) |
247 | 247 | ||
248 | /* next async queue entry, or pointer to interrupt/periodic QH */ | 248 | /* next async queue entry, or pointer to interrupt/periodic QH */ |
249 | #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) | 249 | #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) |
250 | 250 | ||
251 | /* for periodic/async schedules and qtd lists, mark end of list */ | 251 | /* for periodic/async schedules and qtd lists, mark end of list */ |
252 | #define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */ | 252 | #define EHCI_LIST_END cpu_to_le32(1) /* "null pointer" to hw */ |
253 | 253 | ||
254 | /* | 254 | /* |
255 | * Entries in periodic shadow table are pointers to one of four kinds | 255 | * Entries in periodic shadow table are pointers to one of four kinds |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 75b69847918e..033c2846ce59 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -234,7 +234,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | |||
234 | */ | 234 | */ |
235 | hcc_params = readl(base + EHCI_HCC_PARAMS); | 235 | hcc_params = readl(base + EHCI_HCC_PARAMS); |
236 | offset = (hcc_params >> 8) & 0xff; | 236 | offset = (hcc_params >> 8) & 0xff; |
237 | while (offset && count--) { | 237 | while (offset && --count) { |
238 | u32 cap; | 238 | u32 cap; |
239 | int msec; | 239 | int msec; |
240 | 240 | ||
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 319041205b57..f1626e58c141 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -660,9 +660,9 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, | |||
660 | u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; | 660 | u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; |
661 | 661 | ||
662 | memset(array, 0, sizeof(array)); | 662 | memset(array, 0, sizeof(array)); |
663 | switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | 663 | switch (usb_endpoint_type(ep)) { |
664 | case USB_ENDPOINT_XFER_BULK: | 664 | case USB_ENDPOINT_XFER_BULK: |
665 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 665 | if (usb_endpoint_dir_in(ep)) |
666 | array[i++] = 4; | 666 | array[i++] = 4; |
667 | else { | 667 | else { |
668 | array[i++] = 3; | 668 | array[i++] = 3; |
@@ -670,7 +670,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, | |||
670 | } | 670 | } |
671 | break; | 671 | break; |
672 | case USB_ENDPOINT_XFER_INT: | 672 | case USB_ENDPOINT_XFER_INT: |
673 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { | 673 | if (usb_endpoint_dir_in(ep)) { |
674 | array[i++] = 6; | 674 | array[i++] = 6; |
675 | array[i++] = 7; | 675 | array[i++] = 7; |
676 | array[i++] = 8; | 676 | array[i++] = 8; |
@@ -678,7 +678,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, | |||
678 | array[i++] = 9; | 678 | array[i++] = 9; |
679 | break; | 679 | break; |
680 | case USB_ENDPOINT_XFER_ISOC: | 680 | case USB_ENDPOINT_XFER_ISOC: |
681 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 681 | if (usb_endpoint_dir_in(ep)) |
682 | array[i++] = 2; | 682 | array[i++] = 2; |
683 | else | 683 | else |
684 | array[i++] = 1; | 684 | array[i++] = 1; |
@@ -928,10 +928,9 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, | |||
928 | 928 | ||
929 | info.pipenum = get_empty_pipenum(r8a66597, ep); | 929 | info.pipenum = get_empty_pipenum(r8a66597, ep); |
930 | info.address = get_urb_to_r8a66597_addr(r8a66597, urb); | 930 | info.address = get_urb_to_r8a66597_addr(r8a66597, urb); |
931 | info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 931 | info.epnum = usb_endpoint_num(ep); |
932 | info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); | 932 | info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); |
933 | info.type = get_r8a66597_type(ep->bmAttributes | 933 | info.type = get_r8a66597_type(usb_endpoint_type(ep)); |
934 | & USB_ENDPOINT_XFERTYPE_MASK); | ||
935 | info.bufnum = get_bufnum(info.pipenum); | 934 | info.bufnum = get_bufnum(info.pipenum); |
936 | info.buf_bsize = get_buf_bsize(info.pipenum); | 935 | info.buf_bsize = get_buf_bsize(info.pipenum); |
937 | if (info.type == R8A66597_BULK) { | 936 | if (info.type == R8A66597_BULK) { |
@@ -941,7 +940,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, | |||
941 | info.interval = get_interval(urb, ep->bInterval); | 940 | info.interval = get_interval(urb, ep->bInterval); |
942 | info.timer_interval = get_timer_interval(urb, ep->bInterval); | 941 | info.timer_interval = get_timer_interval(urb, ep->bInterval); |
943 | } | 942 | } |
944 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 943 | if (usb_endpoint_dir_in(ep)) |
945 | info.dir_in = 1; | 944 | info.dir_in = 1; |
946 | else | 945 | else |
947 | info.dir_in = 0; | 946 | info.dir_in = 0; |
@@ -1014,6 +1013,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, | |||
1014 | 1013 | ||
1015 | r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); | 1014 | r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); |
1016 | r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); | 1015 | r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); |
1016 | |||
1017 | if (r8a66597->bus_suspended) | ||
1018 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); | ||
1017 | } | 1019 | } |
1018 | 1020 | ||
1019 | /* this function must be called with interrupt disabled */ | 1021 | /* this function must be called with interrupt disabled */ |
@@ -1395,7 +1397,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) | |||
1395 | (int)urb->iso_frame_desc[td->iso_cnt].length); | 1397 | (int)urb->iso_frame_desc[td->iso_cnt].length); |
1396 | } else { | 1398 | } else { |
1397 | buf = (u16 *)(urb->transfer_buffer + urb->actual_length); | 1399 | buf = (u16 *)(urb->transfer_buffer + urb->actual_length); |
1398 | size = min((int)bufsize, | 1400 | size = min_t(u32, bufsize, |
1399 | urb->transfer_buffer_length - urb->actual_length); | 1401 | urb->transfer_buffer_length - urb->actual_length); |
1400 | } | 1402 | } |
1401 | 1403 | ||
@@ -1615,6 +1617,11 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) | |||
1615 | r8a66597_bclr(r8a66597, DTCHE, INTENB2); | 1617 | r8a66597_bclr(r8a66597, DTCHE, INTENB2); |
1616 | r8a66597_usb_disconnect(r8a66597, 1); | 1618 | r8a66597_usb_disconnect(r8a66597, 1); |
1617 | } | 1619 | } |
1620 | if (mask2 & BCHG) { | ||
1621 | r8a66597_write(r8a66597, ~BCHG, INTSTS2); | ||
1622 | r8a66597_bclr(r8a66597, BCHGE, INTENB2); | ||
1623 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); | ||
1624 | } | ||
1618 | } | 1625 | } |
1619 | 1626 | ||
1620 | if (mask1) { | 1627 | if (mask1) { |
@@ -1630,6 +1637,12 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) | |||
1630 | r8a66597_bclr(r8a66597, DTCHE, INTENB1); | 1637 | r8a66597_bclr(r8a66597, DTCHE, INTENB1); |
1631 | r8a66597_usb_disconnect(r8a66597, 0); | 1638 | r8a66597_usb_disconnect(r8a66597, 0); |
1632 | } | 1639 | } |
1640 | if (mask1 & BCHG) { | ||
1641 | r8a66597_write(r8a66597, ~BCHG, INTSTS1); | ||
1642 | r8a66597_bclr(r8a66597, BCHGE, INTENB1); | ||
1643 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); | ||
1644 | } | ||
1645 | |||
1633 | if (mask1 & SIGN) { | 1646 | if (mask1 & SIGN) { |
1634 | r8a66597_write(r8a66597, ~SIGN, INTSTS1); | 1647 | r8a66597_write(r8a66597, ~SIGN, INTSTS1); |
1635 | status = get_urb_error(r8a66597, 0); | 1648 | status = get_urb_error(r8a66597, 0); |
@@ -2141,7 +2154,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
2141 | 2154 | ||
2142 | switch (wValue) { | 2155 | switch (wValue) { |
2143 | case USB_PORT_FEAT_ENABLE: | 2156 | case USB_PORT_FEAT_ENABLE: |
2144 | rh->port &= (1 << USB_PORT_FEAT_POWER); | 2157 | rh->port &= ~(1 << USB_PORT_FEAT_POWER); |
2145 | break; | 2158 | break; |
2146 | case USB_PORT_FEAT_SUSPEND: | 2159 | case USB_PORT_FEAT_SUSPEND: |
2147 | break; | 2160 | break; |
@@ -2213,6 +2226,68 @@ error: | |||
2213 | return ret; | 2226 | return ret; |
2214 | } | 2227 | } |
2215 | 2228 | ||
2229 | #if defined(CONFIG_PM) | ||
2230 | static int r8a66597_bus_suspend(struct usb_hcd *hcd) | ||
2231 | { | ||
2232 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
2233 | int port; | ||
2234 | |||
2235 | dbg("%s", __func__); | ||
2236 | |||
2237 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { | ||
2238 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
2239 | unsigned long dvstctr_reg = get_dvstctr_reg(port); | ||
2240 | |||
2241 | if (!(rh->port & (1 << USB_PORT_FEAT_ENABLE))) | ||
2242 | continue; | ||
2243 | |||
2244 | dbg("suspend port = %d", port); | ||
2245 | r8a66597_bclr(r8a66597, UACT, dvstctr_reg); /* suspend */ | ||
2246 | rh->port |= 1 << USB_PORT_FEAT_SUSPEND; | ||
2247 | |||
2248 | if (rh->dev->udev->do_remote_wakeup) { | ||
2249 | msleep(3); /* waiting last SOF */ | ||
2250 | r8a66597_bset(r8a66597, RWUPE, dvstctr_reg); | ||
2251 | r8a66597_write(r8a66597, ~BCHG, get_intsts_reg(port)); | ||
2252 | r8a66597_bset(r8a66597, BCHGE, get_intenb_reg(port)); | ||
2253 | } | ||
2254 | } | ||
2255 | |||
2256 | r8a66597->bus_suspended = 1; | ||
2257 | |||
2258 | return 0; | ||
2259 | } | ||
2260 | |||
2261 | static int r8a66597_bus_resume(struct usb_hcd *hcd) | ||
2262 | { | ||
2263 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
2264 | int port; | ||
2265 | |||
2266 | dbg("%s", __func__); | ||
2267 | |||
2268 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { | ||
2269 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
2270 | unsigned long dvstctr_reg = get_dvstctr_reg(port); | ||
2271 | |||
2272 | if (!(rh->port & (1 << USB_PORT_FEAT_SUSPEND))) | ||
2273 | continue; | ||
2274 | |||
2275 | dbg("resume port = %d", port); | ||
2276 | rh->port &= ~(1 << USB_PORT_FEAT_SUSPEND); | ||
2277 | rh->port |= 1 << USB_PORT_FEAT_C_SUSPEND; | ||
2278 | r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg); | ||
2279 | msleep(50); | ||
2280 | r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg); | ||
2281 | } | ||
2282 | |||
2283 | return 0; | ||
2284 | |||
2285 | } | ||
2286 | #else | ||
2287 | #define r8a66597_bus_suspend NULL | ||
2288 | #define r8a66597_bus_resume NULL | ||
2289 | #endif | ||
2290 | |||
2216 | static struct hc_driver r8a66597_hc_driver = { | 2291 | static struct hc_driver r8a66597_hc_driver = { |
2217 | .description = hcd_name, | 2292 | .description = hcd_name, |
2218 | .hcd_priv_size = sizeof(struct r8a66597), | 2293 | .hcd_priv_size = sizeof(struct r8a66597), |
@@ -2243,16 +2318,39 @@ static struct hc_driver r8a66597_hc_driver = { | |||
2243 | */ | 2318 | */ |
2244 | .hub_status_data = r8a66597_hub_status_data, | 2319 | .hub_status_data = r8a66597_hub_status_data, |
2245 | .hub_control = r8a66597_hub_control, | 2320 | .hub_control = r8a66597_hub_control, |
2321 | .bus_suspend = r8a66597_bus_suspend, | ||
2322 | .bus_resume = r8a66597_bus_resume, | ||
2246 | }; | 2323 | }; |
2247 | 2324 | ||
2248 | #if defined(CONFIG_PM) | 2325 | #if defined(CONFIG_PM) |
2249 | static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state) | 2326 | static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state) |
2250 | { | 2327 | { |
2328 | struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); | ||
2329 | int port; | ||
2330 | |||
2331 | dbg("%s", __func__); | ||
2332 | |||
2333 | disable_controller(r8a66597); | ||
2334 | |||
2335 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { | ||
2336 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
2337 | |||
2338 | rh->port = 0x00000000; | ||
2339 | } | ||
2340 | |||
2251 | return 0; | 2341 | return 0; |
2252 | } | 2342 | } |
2253 | 2343 | ||
2254 | static int r8a66597_resume(struct platform_device *pdev) | 2344 | static int r8a66597_resume(struct platform_device *pdev) |
2255 | { | 2345 | { |
2346 | struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); | ||
2347 | struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); | ||
2348 | |||
2349 | dbg("%s", __func__); | ||
2350 | |||
2351 | enable_controller(r8a66597); | ||
2352 | usb_root_hub_lost_power(hcd->self.root_hub); | ||
2353 | |||
2256 | return 0; | 2354 | return 0; |
2257 | } | 2355 | } |
2258 | #else /* if defined(CONFIG_PM) */ | 2356 | #else /* if defined(CONFIG_PM) */ |
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index ecacde4d69b0..f49208f1bb74 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h | |||
@@ -504,6 +504,8 @@ struct r8a66597 { | |||
504 | 504 | ||
505 | struct list_head child_device; | 505 | struct list_head child_device; |
506 | unsigned long child_connect_map[4]; | 506 | unsigned long child_connect_map[4]; |
507 | |||
508 | unsigned bus_suspended:1; | ||
507 | }; | 509 | }; |
508 | 510 | ||
509 | static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd) | 511 | static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd) |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index e106e9d48d4a..a949259f18b9 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -230,7 +230,7 @@ static void in_packet( | |||
230 | writeb(usb_pipedevice(urb->pipe), data_reg); | 230 | writeb(usb_pipedevice(urb->pipe), data_reg); |
231 | 231 | ||
232 | sl811_write(sl811, bank + SL11H_HOSTCTLREG, control); | 232 | sl811_write(sl811, bank + SL11H_HOSTCTLREG, control); |
233 | ep->length = min((int)len, | 233 | ep->length = min_t(u32, len, |
234 | urb->transfer_buffer_length - urb->actual_length); | 234 | urb->transfer_buffer_length - urb->actual_length); |
235 | PACKET("IN%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "", | 235 | PACKET("IN%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "", |
236 | !!usb_gettoggle(urb->dev, ep->epnum, 0), ep, len); | 236 | !!usb_gettoggle(urb->dev, ep->epnum, 0), ep, len); |
@@ -255,7 +255,7 @@ static void out_packet( | |||
255 | buf = urb->transfer_buffer + urb->actual_length; | 255 | buf = urb->transfer_buffer + urb->actual_length; |
256 | prefetch(buf); | 256 | prefetch(buf); |
257 | 257 | ||
258 | len = min((int)ep->maxpacket, | 258 | len = min_t(u32, ep->maxpacket, |
259 | urb->transfer_buffer_length - urb->actual_length); | 259 | urb->transfer_buffer_length - urb->actual_length); |
260 | 260 | ||
261 | if (!(control & SL11H_HCTLMASK_ISOCH) | 261 | if (!(control & SL11H_HCTLMASK_ISOCH) |
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 20cc58b97807..e52b954dda47 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -118,7 +118,9 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) | |||
118 | } | 118 | } |
119 | 119 | ||
120 | out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); | 120 | out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); |
121 | out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); | 121 | out += sprintf(out, " Actlen=%d%s", urbp->urb->actual_length, |
122 | (urbp->qh->type == USB_ENDPOINT_XFER_CONTROL ? | ||
123 | "-8" : "")); | ||
122 | 124 | ||
123 | if (urbp->urb->unlinked) | 125 | if (urbp->urb->unlinked) |
124 | out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); | 126 | out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4e221060f58c..cf5e4cf7ea42 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -942,8 +942,6 @@ static struct pci_driver uhci_pci_driver = { | |||
942 | 942 | ||
943 | #ifdef CONFIG_PM | 943 | #ifdef CONFIG_PM |
944 | .suspend = usb_hcd_pci_suspend, | 944 | .suspend = usb_hcd_pci_suspend, |
945 | .suspend_late = usb_hcd_pci_suspend_late, | ||
946 | .resume_early = usb_hcd_pci_resume_early, | ||
947 | .resume = usb_hcd_pci_resume, | 945 | .resume = usb_hcd_pci_resume, |
948 | #endif /* PM */ | 946 | #endif /* PM */ |
949 | }; | 947 | }; |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 7d01c5677f92..26bd1b2bcbfc 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -73,11 +73,11 @@ | |||
73 | #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ | 73 | #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ |
74 | #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ | 74 | #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ |
75 | 75 | ||
76 | #define UHCI_PTR_BITS __constant_cpu_to_le32(0x000F) | 76 | #define UHCI_PTR_BITS cpu_to_le32(0x000F) |
77 | #define UHCI_PTR_TERM __constant_cpu_to_le32(0x0001) | 77 | #define UHCI_PTR_TERM cpu_to_le32(0x0001) |
78 | #define UHCI_PTR_QH __constant_cpu_to_le32(0x0002) | 78 | #define UHCI_PTR_QH cpu_to_le32(0x0002) |
79 | #define UHCI_PTR_DEPTH __constant_cpu_to_le32(0x0004) | 79 | #define UHCI_PTR_DEPTH cpu_to_le32(0x0004) |
80 | #define UHCI_PTR_BREADTH __constant_cpu_to_le32(0x0000) | 80 | #define UHCI_PTR_BREADTH cpu_to_le32(0x0000) |
81 | 81 | ||
82 | #define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ | 82 | #define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ |
83 | #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ | 83 | #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 5631d89c8730..3e5807d14ffb 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -402,7 +402,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) | |||
402 | /* Otherwise all the toggles in the URB have to be switched */ | 402 | /* Otherwise all the toggles in the URB have to be switched */ |
403 | } else { | 403 | } else { |
404 | list_for_each_entry(td, &urbp->td_list, list) { | 404 | list_for_each_entry(td, &urbp->td_list, list) { |
405 | td->token ^= __constant_cpu_to_le32( | 405 | td->token ^= cpu_to_le32( |
406 | TD_TOKEN_TOGGLE); | 406 | TD_TOKEN_TOGGLE); |
407 | toggle ^= 1; | 407 | toggle ^= 1; |
408 | } | 408 | } |
@@ -883,7 +883,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
883 | 883 | ||
884 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); | 884 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); |
885 | wmb(); | 885 | wmb(); |
886 | qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); | 886 | qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE); |
887 | qh->dummy_td = td; | 887 | qh->dummy_td = td; |
888 | 888 | ||
889 | /* Low-speed transfers get a different queue, and won't hog the bus. | 889 | /* Low-speed transfers get a different queue, and won't hog the bus. |
@@ -899,8 +899,6 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
899 | } | 899 | } |
900 | if (qh->state != QH_STATE_ACTIVE) | 900 | if (qh->state != QH_STATE_ACTIVE) |
901 | qh->skel = skel; | 901 | qh->skel = skel; |
902 | |||
903 | urb->actual_length = -8; /* Account for the SETUP packet */ | ||
904 | return 0; | 902 | return 0; |
905 | 903 | ||
906 | nomem: | 904 | nomem: |
@@ -1003,7 +1001,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
1003 | * fast side but not enough to justify delaying an interrupt | 1001 | * fast side but not enough to justify delaying an interrupt |
1004 | * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT | 1002 | * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT |
1005 | * flag setting. */ | 1003 | * flag setting. */ |
1006 | td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); | 1004 | td->status |= cpu_to_le32(TD_CTRL_IOC); |
1007 | 1005 | ||
1008 | /* | 1006 | /* |
1009 | * Build the new dummy TD and activate the old one | 1007 | * Build the new dummy TD and activate the old one |
@@ -1015,7 +1013,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
1015 | 1013 | ||
1016 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); | 1014 | uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); |
1017 | wmb(); | 1015 | wmb(); |
1018 | qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); | 1016 | qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE); |
1019 | qh->dummy_td = td; | 1017 | qh->dummy_td = td; |
1020 | 1018 | ||
1021 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | 1019 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), |
@@ -1317,7 +1315,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | |||
1317 | } | 1315 | } |
1318 | 1316 | ||
1319 | /* Set the interrupt-on-completion flag on the last packet. */ | 1317 | /* Set the interrupt-on-completion flag on the last packet. */ |
1320 | td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); | 1318 | td->status |= cpu_to_le32(TD_CTRL_IOC); |
1321 | 1319 | ||
1322 | /* Add the TDs to the frame list */ | 1320 | /* Add the TDs to the frame list */ |
1323 | frame = urb->start_frame; | 1321 | frame = urb->start_frame; |
@@ -1494,11 +1492,10 @@ __acquires(uhci->lock) | |||
1494 | 1492 | ||
1495 | if (qh->type == USB_ENDPOINT_XFER_CONTROL) { | 1493 | if (qh->type == USB_ENDPOINT_XFER_CONTROL) { |
1496 | 1494 | ||
1497 | /* urb->actual_length < 0 means the setup transaction didn't | 1495 | /* Subtract off the length of the SETUP packet from |
1498 | * complete successfully. Either it failed or the URB was | 1496 | * urb->actual_length. |
1499 | * unlinked first. Regardless, don't confuse people with a | 1497 | */ |
1500 | * negative length. */ | 1498 | urb->actual_length -= min_t(u32, 8, urb->actual_length); |
1501 | urb->actual_length = max(urb->actual_length, 0); | ||
1502 | } | 1499 | } |
1503 | 1500 | ||
1504 | /* When giving back the first URB in an Isochronous queue, | 1501 | /* When giving back the first URB in an Isochronous queue, |
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index 577c0d29849d..958751ccea43 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
@@ -170,12 +170,17 @@ void asl_stop(struct whc *whc) | |||
170 | void asl_update(struct whc *whc, uint32_t wusbcmd) | 170 | void asl_update(struct whc *whc, uint32_t wusbcmd) |
171 | { | 171 | { |
172 | struct wusbhc *wusbhc = &whc->wusbhc; | 172 | struct wusbhc *wusbhc = &whc->wusbhc; |
173 | long t; | ||
173 | 174 | ||
174 | mutex_lock(&wusbhc->mutex); | 175 | mutex_lock(&wusbhc->mutex); |
175 | if (wusbhc->active) { | 176 | if (wusbhc->active) { |
176 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 177 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); |
177 | wait_event(whc->async_list_wq, | 178 | t = wait_event_timeout( |
178 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0); | 179 | whc->async_list_wq, |
180 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0, | ||
181 | msecs_to_jiffies(1000)); | ||
182 | if (t == 0) | ||
183 | whc_hw_error(whc, "ASL update timeout"); | ||
179 | } | 184 | } |
180 | mutex_unlock(&wusbhc->mutex); | 185 | mutex_unlock(&wusbhc->mutex); |
181 | } | 186 | } |
@@ -222,13 +227,13 @@ void scan_async_work(struct work_struct *work) | |||
222 | * Now that the ASL is updated, complete the removal of any | 227 | * Now that the ASL is updated, complete the removal of any |
223 | * removed qsets. | 228 | * removed qsets. |
224 | */ | 229 | */ |
225 | spin_lock(&whc->lock); | 230 | spin_lock_irq(&whc->lock); |
226 | 231 | ||
227 | list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) { | 232 | list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) { |
228 | qset_remove_complete(whc, qset); | 233 | qset_remove_complete(whc, qset); |
229 | } | 234 | } |
230 | 235 | ||
231 | spin_unlock(&whc->lock); | 236 | spin_unlock_irq(&whc->lock); |
232 | } | 237 | } |
233 | 238 | ||
234 | /** | 239 | /** |
diff --git a/drivers/usb/host/whci/hw.c b/drivers/usb/host/whci/hw.c index d498e7203217..6afa2e379160 100644 --- a/drivers/usb/host/whci/hw.c +++ b/drivers/usb/host/whci/hw.c | |||
@@ -87,3 +87,18 @@ out: | |||
87 | 87 | ||
88 | return ret; | 88 | return ret; |
89 | } | 89 | } |
90 | |||
91 | /** | ||
92 | * whc_hw_error - recover from a hardware error | ||
93 | * @whc: the WHCI HC that broke. | ||
94 | * @reason: a description of the failure. | ||
95 | * | ||
96 | * Recover from broken hardware with a full reset. | ||
97 | */ | ||
98 | void whc_hw_error(struct whc *whc, const char *reason) | ||
99 | { | ||
100 | struct wusbhc *wusbhc = &whc->wusbhc; | ||
101 | |||
102 | dev_err(&whc->umc->dev, "hardware error: %s\n", reason); | ||
103 | wusbhc_reset_all(wusbhc); | ||
104 | } | ||
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index 2ae5abf69a6a..df8b85f07092 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c | |||
@@ -183,12 +183,17 @@ void pzl_stop(struct whc *whc) | |||
183 | void pzl_update(struct whc *whc, uint32_t wusbcmd) | 183 | void pzl_update(struct whc *whc, uint32_t wusbcmd) |
184 | { | 184 | { |
185 | struct wusbhc *wusbhc = &whc->wusbhc; | 185 | struct wusbhc *wusbhc = &whc->wusbhc; |
186 | long t; | ||
186 | 187 | ||
187 | mutex_lock(&wusbhc->mutex); | 188 | mutex_lock(&wusbhc->mutex); |
188 | if (wusbhc->active) { | 189 | if (wusbhc->active) { |
189 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 190 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); |
190 | wait_event(whc->periodic_list_wq, | 191 | t = wait_event_timeout( |
191 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0); | 192 | whc->periodic_list_wq, |
193 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0, | ||
194 | msecs_to_jiffies(1000)); | ||
195 | if (t == 0) | ||
196 | whc_hw_error(whc, "PZL update timeout"); | ||
192 | } | 197 | } |
193 | mutex_unlock(&wusbhc->mutex); | 198 | mutex_unlock(&wusbhc->mutex); |
194 | } | 199 | } |
@@ -250,13 +255,13 @@ void scan_periodic_work(struct work_struct *work) | |||
250 | * Now that the PZL is updated, complete the removal of any | 255 | * Now that the PZL is updated, complete the removal of any |
251 | * removed qsets. | 256 | * removed qsets. |
252 | */ | 257 | */ |
253 | spin_lock(&whc->lock); | 258 | spin_lock_irq(&whc->lock); |
254 | 259 | ||
255 | list_for_each_entry_safe(qset, t, &whc->periodic_removed_list, list_node) { | 260 | list_for_each_entry_safe(qset, t, &whc->periodic_removed_list, list_node) { |
256 | qset_remove_complete(whc, qset); | 261 | qset_remove_complete(whc, qset); |
257 | } | 262 | } |
258 | 263 | ||
259 | spin_unlock(&whc->lock); | 264 | spin_unlock_irq(&whc->lock); |
260 | } | 265 | } |
261 | 266 | ||
262 | /** | 267 | /** |
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index 0f3540f04f53..d3543a181dc9 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h | |||
@@ -137,6 +137,7 @@ void whc_clean_up(struct whc *whc); | |||
137 | /* hw.c */ | 137 | /* hw.c */ |
138 | void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); | 138 | void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); |
139 | int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); | 139 | int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); |
140 | void whc_hw_error(struct whc *whc, const char *reason); | ||
140 | 141 | ||
141 | /* wusb.c */ | 142 | /* wusb.c */ |
142 | int whc_wusbhc_start(struct wusbhc *wusbhc); | 143 | int whc_wusbhc_start(struct wusbhc *wusbhc); |