1 From 5128234c3c1c86a2587b5f0baf3bbd34445f5632 Mon Sep 17 00:00:00 2001
2 From: popcornmix <popcornmix@gmail.com>
3 Date: Wed, 3 Jul 2013 00:46:42 +0100
4 Subject: [PATCH 28/54] Add FIQ patch to dwc_otg driver. Enable with
5 dwc_otg.fiq_fix_enable=1. Should give about 10% more ARM performance. Thanks
8 Avoid dynamic memory allocation for channel lock in USB driver. Thanks ddv2005.
10 Add NAK holdoff scheme. Enabled by default, disable with dwc_otg.nak_holdoff_enable=0. Thanks gsh
12 Make sure we wait for the reset to finish
14 dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent kernel
15 memory corruption, escalating to OOPS under high USB load.
17 dwc_otg: Fix unsafe access of QTD during URB enqueue
19 In dwc_otg_hcd_urb_enqueue during qtd creation, it was possible that the
20 transaction could complete almost immediately after the qtd was assigned
21 to a host channel during URB enqueue, which meant the qtd pointer was no
22 longer valid having been completed and removed. Usually, this resulted in
23 an OOPS during URB submission. By predetermining whether transactions
24 need to be queued or not, this unsafe pointer access is avoided.
26 This bug was only evident on the Pi model A where a device was attached
27 that had no periodic endpoints (e.g. USB pendrive or some wlan devices).
29 dwc_otg: Fix incorrect URB allocation error handling
31 If the memory allocation for a dwc_otg_urb failed, the kernel would OOPS
32 because for some reason a member of the *unallocated* struct was set to
33 zero. Error handling changed to fail correctly.
35 dwc_otg: fix potential use-after-free case in interrupt handler
37 If a transaction had previously aborted, certain interrupts are
38 enabled to track error counts and reset where necessary. On IN
39 endpoints the host generates an ACK interrupt near-simultaneously
40 with completion of transfer. In the case where this transfer had
41 previously had an error, this results in a use-after-free on
42 the QTD memory space with a 1-byte length being overwritten to
45 dwc_otg: add handling of SPLIT transaction data toggle errors
47 Previously a data toggle error on packets from a USB1.1 device behind
48 a TT would result in the Pi locking up as the driver never handled
49 the associated interrupt. Patch adds basic retry mechanism and
50 interrupt acknowledgement to cater for either a chance toggle error or
51 for devices that have a broken initial toggle state (FT8U232/FT232BM).
53 dwc_otg: implement tasklet for returning URBs to usbcore hcd layer
55 The dwc_otg driver interrupt handler for transfer completion will spend
56 a very long time with interrupts disabled when a URB is completed -
57 this is because usb_hcd_giveback_urb is called from within the handler
58 which for a USB device driver with complicated processing (e.g. webcam)
59 will take an exorbitant amount of time to complete. This results in
60 missed completion interrupts for other USB packets which lead to them
61 being dropped due to microframe overruns.
63 This patch splits returning the URB to the usb hcd layer into a
64 high-priority tasklet. This will have most benefit for isochronous IN
65 transfers but will also have incidental benefit where multiple periodic
66 devices are active at once.
68 dwc_otg: fix NAK holdoff and allow on split transactions only
70 This corrects a bug where if a single active non-periodic endpoint
71 had at least one transaction in its qh, on frnum == MAX_FRNUM the qh
72 would get skipped and never get queued again. This would result in
73 a silent device until error detection (automatic or otherwise) would
74 either reset the device or flush and requeue the URBs.
76 Additionally the NAK holdoff was enabled for all transactions - this
77 would potentially stall a HS endpoint for 1ms if a previous error state
78 enabled this interrupt and the next response was a NAK. Fix so that
79 only split transactions get held off.
81 dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held in completion handler
83 usb_hcd_unlink_urb_from_ep must be called with the HCD lock held. Calling it
84 asynchronously in the tasklet was not safe (regression in
85 c4564d4a1a0a9b10d4419e48239f5d99e88d2667).
87 This change unlinks it from the endpoint prior to queueing it for handling in
88 the tasklet, and also adds a check to ensure the urb is OK to be unlinked
91 NULL pointer dereference kernel oopses had been observed in usb_hcd_giveback_urb
92 when a USB device was unplugged/replugged during data transfer. This effect
93 was reproduced using automated USB port power control, hundreds of replug
94 events were performed during active transfers to confirm that the problem was
97 USB fix using a FIQ to implement split transactions
99 This commit adds a FIQ implementaion that schedules
100 the split transactions using a FIQ so we don't get
101 held off by the interrupt latency of Linux
103 dwc_otg: fix device attributes and avoid kernel warnings on boot
105 dcw_otg: avoid logging function that can cause panics
107 See: https://github.com/raspberrypi/firmware/issues/21
108 Thanks to cleverca22 for fix
110 dwc_otg: mask correct interrupts after transaction error recovery
112 The dwc_otg driver will unmask certain interrupts on a transaction
113 that previously halted in the error state in order to reset the
114 QTD error count. The various fine-grained interrupt handlers do not
115 consider that other interrupts besides themselves were unmasked.
117 By disabling the two other interrupts only ever enabled in DMA mode
118 for this purpose, we can avoid unnecessary function calls in the
119 IRQ handler. This will also prevent an unneccesary FIQ interrupt
120 from being generated if the FIQ is enabled.
122 dwc_otg: fiq: prevent FIQ thrash and incorrect state passing to IRQ
124 In the case of a transaction to a device that had previously aborted
125 due to an error, several interrupts are enabled to reset the error
126 count when a device responds. This has the side-effect of making the
127 FIQ thrash because the hardware will generate multiple instances of
128 a NAK on an IN bulk/interrupt endpoint and multiple instances of ACK
129 on an OUT bulk/interrupt endpoint. Make the FIQ mask and clear the
130 associated interrupts.
132 Additionally, on non-split transactions make sure that only unmasked
133 interrupts are cleared. This caused a hard-to-trigger but serious
134 race condition when you had the combination of an endpoint awaiting
135 error recovery and a transaction completed on an endpoint - due to
136 the sequencing and timing of interrupts generated by the dwc_otg core,
137 it was possible to confuse the IRQ handler.
141 dwc_otg: whitespace cleanup in dwc_otg_urb_enqueue
143 dwc_otg: prevent OOPSes during device disconnects
145 The dwc_otg_urb_enqueue function is thread-unsafe. In particular the
146 access of urb->hcpriv, usb_hcd_link_urb_to_ep, dwc_otg_urb->qtd and
147 friends does not occur within a critical section and so if a device
148 was unplugged during activity there was a high chance that the
149 usbcore hub_thread would try to disable the endpoint with partially-
150 formed entries in the URB queue. This would result in BUG() or null
151 pointer dereferences.
153 Fix so that access of urb->hcpriv, enqueuing to the hardware and
154 adding to usbcore endpoint URB lists is contained within a single
157 dwc_otg: prevent BUG() in TT allocation if hub address is > 16
159 A fixed-size array is used to track TT allocation. This was
160 previously set to 16 which caused a crash because
161 dwc_otg_hcd_allocate_port would read past the end of the array.
163 This was hit if a hub was plugged in which enumerated as addr > 16,
164 due to previous device resets or unplugs.
166 Also add #ifdef FIQ_DEBUG around hcd->hub_port_alloc[], which grows
167 to a large size if 128 hub addresses are supported. This field is
168 for debug only for tracking which frame an allocate happened in.
170 dwc_otg: make channel halts with unknown state less damaging
172 If the IRQ received a channel halt interrupt through the FIQ
173 with no other bits set, the IRQ would not release the host
174 channel and never complete the URB.
176 Add catchall handling to treat as a transaction error and retry.
178 dwc_otg: fiq_split: use TTs with more granularity
180 This fixes certain issues with split transaction scheduling.
182 - Isochronous multi-packet OUT transactions now hog the TT until
183 they are completed - this prevents hubs aborting transactions
184 if they get a periodic start-split out-of-order
185 - Don't perform TT allocation on non-periodic endpoints - this
186 allows simultaneous use of the TT's bulk/control and periodic
189 This commit will mainly affect USB audio playback.
191 dwc_otg: fix potential sleep while atomic during urb enqueue
193 Fixes a regression introduced with eb1b482a. Kmalloc called from
194 dwc_otg_hcd_qtd_add / dwc_otg_hcd_qtd_create did not always have
195 the GPF_ATOMIC flag set. Force this flag when inside the larger
198 dwc_otg: make fiq_split_enable imply fiq_fix_enable
200 Failing to set up the FIQ correctly would result in
201 "IRQ 32: nobody cared" errors in dmesg.
203 dwc_otg: prevent crashes on host port disconnects
205 Fix several issues resulting in crashes or inconsistent state
206 if a Model A root port was disconnected.
208 - Clean up queue heads properly in kill_urbs_in_qh_list by
209 removing the empty QHs from the schedule lists
210 - Set the halt status properly to prevent IRQ handlers from
212 - Add fiq_split related cleanup for saved registers
213 - Make microframe scheduling reclaim host channels if
214 active during a disconnect
215 - Abort URBs with -ESHUTDOWN status response, informing
216 device drivers so they respond in a more correct fashion
217 and don't try to resubmit URBs
218 - Prevent IRQ handlers from attempting to handle channel
219 interrupts if the associated URB was dequeued (and the
220 driver state was cleared)
222 dwc_otg: prevent leaking URBs during enqueue
224 A dwc_otg_urb would get leaked if the HCD enqueue function
225 failed for any reason. Free the URB at the appropriate points.
227 dwc_otg: Enable NAK holdoff for control split transactions
229 Certain low-speed devices take a very long time to complete a
230 data or status stage of a control transaction, producing NAK
231 responses until they complete internal processing - the USB2.0
232 spec limit is up to 500mS. This causes the same type of interrupt
233 storm as seen with USB-serial dongles prior to c8edb238.
235 In certain circumstances, usually while booting, this interrupt
236 storm could cause SD card timeouts.
238 dwc_otg: Fix for occasional lockup on boot when doing a USB reset
240 dwc_otg: Don't issue traffic to LS devices in FS mode
242 Issuing low-speed packets when the root port is in full-speed mode
243 causes the root port to stop responding. Explicitly fail when
244 enqueuing URBs to a LS endpoint on a FS bus.
246 Fix ARM architecture issue with local_irq_restore()
248 If local_fiq_enable() is called before a local_irq_restore(flags) where
249 the flags variable has the F bit set, the FIQ will be erroneously disabled.
251 Fixup arch_local_irq_restore to avoid trampling the F bit in CPSR.
253 Also fix some of the hacks previously implemented for previous dwc_otg
256 arch/arm/Kconfig | 1 +
257 arch/arm/include/asm/irqflags.h | 16 +-
258 arch/arm/kernel/fiqasm.S | 4 +
259 arch/arm/mach-bcm2708/armctrl.c | 19 +-
260 arch/arm/mach-bcm2708/bcm2708.c | 29 +-
261 arch/arm/mach-bcm2708/include/mach/irqs.h | 155 ++---
262 arch/arm/mach-bcm2708/include/mach/platform.h | 2 +
263 .../usb/host/dwc_common_port/dwc_common_linux.c | 11 +
264 drivers/usb/host/dwc_common_port/dwc_list.h | 14 +-
265 drivers/usb/host/dwc_common_port/dwc_os.h | 2 +
266 drivers/usb/host/dwc_otg/Makefile | 1 +
267 drivers/usb/host/dwc_otg/dwc_otg_attr.c | 14 +-
268 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 47 +-
269 drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 1 +
270 drivers/usb/host/dwc_otg/dwc_otg_driver.c | 52 +-
271 drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 304 +++++++--
272 drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 37 +-
273 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 3 +-
274 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 5 +
275 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 705 ++++++++++++++++++++-
276 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 159 +++--
277 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 53 +-
278 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c | 113 ++++
279 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h | 48 ++
280 drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 3 +
281 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 2 +-
282 26 files changed, 1548 insertions(+), 252 deletions(-)
283 create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
284 create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
286 --- a/arch/arm/Kconfig
287 +++ b/arch/arm/Kconfig
288 @@ -394,6 +394,7 @@ config ARCH_BCM2708
289 select ARM_ERRATA_411920
294 This enables support for Broadcom BCM2708 boards.
296 --- a/arch/arm/include/asm/irqflags.h
297 +++ b/arch/arm/include/asm/irqflags.h
298 @@ -145,12 +145,22 @@ static inline unsigned long arch_local_s
302 - * restore saved IRQ & FIQ state
303 + * restore saved IRQ state
305 static inline void arch_local_irq_restore(unsigned long flags)
308 - " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
309 + unsigned long temp = 0;
310 + flags &= ~(1 << 6);
316 + /* Preserve FIQ bit */
318 + flags = flags | temp;
320 + " msr cpsr_c, %0 @ local_irq_restore"
324 --- a/arch/arm/kernel/fiqasm.S
325 +++ b/arch/arm/kernel/fiqasm.S
326 @@ -47,3 +47,7 @@ ENTRY(__get_fiq_regs)
327 mov r0, r0 @ avoid hazard prior to ARMv4
329 ENDPROC(__get_fiq_regs)
333 +ENDPROC(__FIQ_Branch)
334 --- a/arch/arm/mach-bcm2708/armctrl.c
335 +++ b/arch/arm/mach-bcm2708/armctrl.c
336 @@ -52,8 +52,12 @@ static void armctrl_mask_irq(struct irq_
340 - unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
341 - writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
342 + if (d->irq >= FIQ_START) {
343 + writel(0, __io_address(ARM_IRQ_FAST));
345 + unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
346 + writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
350 static void armctrl_unmask_irq(struct irq_data *d)
351 @@ -65,8 +69,14 @@ static void armctrl_unmask_irq(struct ir
355 - unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
356 - writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
357 + if (d->irq >= FIQ_START) {
358 + unsigned int data =
359 + (unsigned int)irq_get_chip_data(d->irq) - FIQ_START;
360 + writel(0x80 | data, __io_address(ARM_IRQ_FAST));
362 + unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
363 + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
367 #if defined(CONFIG_PM)
368 @@ -204,5 +214,6 @@ int __init armctrl_init(void __iomem * b
371 armctrl_pm_register(base, irq_start, resume_sources);
372 + init_FIQ(FIQ_START);
375 --- a/arch/arm/mach-bcm2708/bcm2708.c
376 +++ b/arch/arm/mach-bcm2708/bcm2708.c
377 @@ -321,12 +321,32 @@ static struct resource bcm2708_usb_resou
378 .flags = IORESOURCE_MEM,
383 + .start = MPHI_BASE,
384 + .end = MPHI_BASE + SZ_4K - 1,
385 + .flags = IORESOURCE_MEM,
388 + .start = IRQ_HOSTPORT,
389 + .end = IRQ_HOSTPORT,
390 .flags = IORESOURCE_IRQ,
394 +bool fiq_fix_enable = true;
396 +static struct resource bcm2708_usb_resources_no_fiq_fix[] = {
399 + .end = USB_BASE + SZ_128K - 1,
400 + .flags = IORESOURCE_MEM,
405 + .flags = IORESOURCE_IRQ,
409 static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
411 static struct platform_device bcm2708_usb_device = {
412 @@ -709,6 +729,11 @@ void __init bcm2708_init(void)
414 bcm_register_device(&bcm2708_systemtimer_device);
415 bcm_register_device(&bcm2708_fb_device);
416 + if (!fiq_fix_enable)
418 + bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix;
419 + bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix);
421 bcm_register_device(&bcm2708_usb_device);
422 bcm_register_device(&bcm2708_uart1_device);
423 bcm_register_device(&bcm2708_powerman_device);
424 --- a/arch/arm/mach-bcm2708/include/mach/irqs.h
425 +++ b/arch/arm/mach-bcm2708/include/mach/irqs.h
426 @@ -106,89 +106,92 @@
427 #define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1)
428 #define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2)
430 +#define FIQ_START HARD_IRQS
433 * FIQ interrupts definitions are the same as the INT definitions.
435 -#define FIQ_TIMER0 INT_TIMER0
436 -#define FIQ_TIMER1 INT_TIMER1
437 -#define FIQ_TIMER2 INT_TIMER2
438 -#define FIQ_TIMER3 INT_TIMER3
439 -#define FIQ_CODEC0 INT_CODEC0
440 -#define FIQ_CODEC1 INT_CODEC1
441 -#define FIQ_CODEC2 INT_CODEC2
442 -#define FIQ_JPEG INT_JPEG
443 -#define FIQ_ISP INT_ISP
444 -#define FIQ_USB INT_USB
445 -#define FIQ_3D INT_3D
446 -#define FIQ_TRANSPOSER INT_TRANSPOSER
447 -#define FIQ_MULTICORESYNC0 INT_MULTICORESYNC0
448 -#define FIQ_MULTICORESYNC1 INT_MULTICORESYNC1
449 -#define FIQ_MULTICORESYNC2 INT_MULTICORESYNC2
450 -#define FIQ_MULTICORESYNC3 INT_MULTICORESYNC3
451 -#define FIQ_DMA0 INT_DMA0
452 -#define FIQ_DMA1 INT_DMA1
453 -#define FIQ_DMA2 INT_DMA2
454 -#define FIQ_DMA3 INT_DMA3
455 -#define FIQ_DMA4 INT_DMA4
456 -#define FIQ_DMA5 INT_DMA5
457 -#define FIQ_DMA6 INT_DMA6
458 -#define FIQ_DMA7 INT_DMA7
459 -#define FIQ_DMA8 INT_DMA8
460 -#define FIQ_DMA9 INT_DMA9
461 -#define FIQ_DMA10 INT_DMA10
462 -#define FIQ_DMA11 INT_DMA11
463 -#define FIQ_DMA12 INT_DMA12
464 -#define FIQ_AUX INT_AUX
465 -#define FIQ_ARM INT_ARM
466 -#define FIQ_VPUDMA INT_VPUDMA
467 -#define FIQ_HOSTPORT INT_HOSTPORT
468 -#define FIQ_VIDEOSCALER INT_VIDEOSCALER
469 -#define FIQ_CCP2TX INT_CCP2TX
470 -#define FIQ_SDC INT_SDC
471 -#define FIQ_DSI0 INT_DSI0
472 -#define FIQ_AVE INT_AVE
473 -#define FIQ_CAM0 INT_CAM0
474 -#define FIQ_CAM1 INT_CAM1
475 -#define FIQ_HDMI0 INT_HDMI0
476 -#define FIQ_HDMI1 INT_HDMI1
477 -#define FIQ_PIXELVALVE1 INT_PIXELVALVE1
478 -#define FIQ_I2CSPISLV INT_I2CSPISLV
479 -#define FIQ_DSI1 INT_DSI1
480 -#define FIQ_PWA0 INT_PWA0
481 -#define FIQ_PWA1 INT_PWA1
482 -#define FIQ_CPR INT_CPR
483 -#define FIQ_SMI INT_SMI
484 -#define FIQ_GPIO0 INT_GPIO0
485 -#define FIQ_GPIO1 INT_GPIO1
486 -#define FIQ_GPIO2 INT_GPIO2
487 -#define FIQ_GPIO3 INT_GPIO3
488 -#define FIQ_I2C INT_I2C
489 -#define FIQ_SPI INT_SPI
490 -#define FIQ_I2SPCM INT_I2SPCM
491 -#define FIQ_SDIO INT_SDIO
492 -#define FIQ_UART INT_UART
493 -#define FIQ_SLIMBUS INT_SLIMBUS
494 -#define FIQ_VEC INT_VEC
495 -#define FIQ_CPG INT_CPG
496 -#define FIQ_RNG INT_RNG
497 -#define FIQ_ARASANSDIO INT_ARASANSDIO
498 -#define FIQ_AVSPMON INT_AVSPMON
499 +#define FIQ_TIMER0 (FIQ_START+INTERRUPT_TIMER0)
500 +#define FIQ_TIMER1 (FIQ_START+INTERRUPT_TIMER1)
501 +#define FIQ_TIMER2 (FIQ_START+INTERRUPT_TIMER2)
502 +#define FIQ_TIMER3 (FIQ_START+INTERRUPT_TIMER3)
503 +#define FIQ_CODEC0 (FIQ_START+INTERRUPT_CODEC0)
504 +#define FIQ_CODEC1 (FIQ_START+INTERRUPT_CODEC1)
505 +#define FIQ_CODEC2 (FIQ_START+INTERRUPT_CODEC2)
506 +#define FIQ_JPEG (FIQ_START+INTERRUPT_JPEG)
507 +#define FIQ_ISP (FIQ_START+INTERRUPT_ISP)
508 +#define FIQ_USB (FIQ_START+INTERRUPT_USB)
509 +#define FIQ_3D (FIQ_START+INTERRUPT_3D)
510 +#define FIQ_TRANSPOSER (FIQ_START+INTERRUPT_TRANSPOSER)
511 +#define FIQ_MULTICORESYNC0 (FIQ_START+INTERRUPT_MULTICORESYNC0)
512 +#define FIQ_MULTICORESYNC1 (FIQ_START+INTERRUPT_MULTICORESYNC1)
513 +#define FIQ_MULTICORESYNC2 (FIQ_START+INTERRUPT_MULTICORESYNC2)
514 +#define FIQ_MULTICORESYNC3 (FIQ_START+INTERRUPT_MULTICORESYNC3)
515 +#define FIQ_DMA0 (FIQ_START+INTERRUPT_DMA0)
516 +#define FIQ_DMA1 (FIQ_START+INTERRUPT_DMA1)
517 +#define FIQ_DMA2 (FIQ_START+INTERRUPT_DMA2)
518 +#define FIQ_DMA3 (FIQ_START+INTERRUPT_DMA3)
519 +#define FIQ_DMA4 (FIQ_START+INTERRUPT_DMA4)
520 +#define FIQ_DMA5 (FIQ_START+INTERRUPT_DMA5)
521 +#define FIQ_DMA6 (FIQ_START+INTERRUPT_DMA6)
522 +#define FIQ_DMA7 (FIQ_START+INTERRUPT_DMA7)
523 +#define FIQ_DMA8 (FIQ_START+INTERRUPT_DMA8)
524 +#define FIQ_DMA9 (FIQ_START+INTERRUPT_DMA9)
525 +#define FIQ_DMA10 (FIQ_START+INTERRUPT_DMA10)
526 +#define FIQ_DMA11 (FIQ_START+INTERRUPT_DMA11)
527 +#define FIQ_DMA12 (FIQ_START+INTERRUPT_DMA12)
528 +#define FIQ_AUX (FIQ_START+INTERRUPT_AUX)
529 +#define FIQ_ARM (FIQ_START+INTERRUPT_ARM)
530 +#define FIQ_VPUDMA (FIQ_START+INTERRUPT_VPUDMA)
531 +#define FIQ_HOSTPORT (FIQ_START+INTERRUPT_HOSTPORT)
532 +#define FIQ_VIDEOSCALER (FIQ_START+INTERRUPT_VIDEOSCALER)
533 +#define FIQ_CCP2TX (FIQ_START+INTERRUPT_CCP2TX)
534 +#define FIQ_SDC (FIQ_START+INTERRUPT_SDC)
535 +#define FIQ_DSI0 (FIQ_START+INTERRUPT_DSI0)
536 +#define FIQ_AVE (FIQ_START+INTERRUPT_AVE)
537 +#define FIQ_CAM0 (FIQ_START+INTERRUPT_CAM0)
538 +#define FIQ_CAM1 (FIQ_START+INTERRUPT_CAM1)
539 +#define FIQ_HDMI0 (FIQ_START+INTERRUPT_HDMI0)
540 +#define FIQ_HDMI1 (FIQ_START+INTERRUPT_HDMI1)
541 +#define FIQ_PIXELVALVE1 (FIQ_START+INTERRUPT_PIXELVALVE1)
542 +#define FIQ_I2CSPISLV (FIQ_START+INTERRUPT_I2CSPISLV)
543 +#define FIQ_DSI1 (FIQ_START+INTERRUPT_DSI1)
544 +#define FIQ_PWA0 (FIQ_START+INTERRUPT_PWA0)
545 +#define FIQ_PWA1 (FIQ_START+INTERRUPT_PWA1)
546 +#define FIQ_CPR (FIQ_START+INTERRUPT_CPR)
547 +#define FIQ_SMI (FIQ_START+INTERRUPT_SMI)
548 +#define FIQ_GPIO0 (FIQ_START+INTERRUPT_GPIO0)
549 +#define FIQ_GPIO1 (FIQ_START+INTERRUPT_GPIO1)
550 +#define FIQ_GPIO2 (FIQ_START+INTERRUPT_GPIO2)
551 +#define FIQ_GPIO3 (FIQ_START+INTERRUPT_GPIO3)
552 +#define FIQ_I2C (FIQ_START+INTERRUPT_I2C)
553 +#define FIQ_SPI (FIQ_START+INTERRUPT_SPI)
554 +#define FIQ_I2SPCM (FIQ_START+INTERRUPT_I2SPCM)
555 +#define FIQ_SDIO (FIQ_START+INTERRUPT_SDIO)
556 +#define FIQ_UART (FIQ_START+INTERRUPT_UART)
557 +#define FIQ_SLIMBUS (FIQ_START+INTERRUPT_SLIMBUS)
558 +#define FIQ_VEC (FIQ_START+INTERRUPT_VEC)
559 +#define FIQ_CPG (FIQ_START+INTERRUPT_CPG)
560 +#define FIQ_RNG (FIQ_START+INTERRUPT_RNG)
561 +#define FIQ_ARASANSDIO (FIQ_START+INTERRUPT_ARASANSDIO)
562 +#define FIQ_AVSPMON (FIQ_START+INTERRUPT_AVSPMON)
564 -#define FIQ_ARM_TIMER INT_ARM_TIMER
565 -#define FIQ_ARM_MAILBOX INT_ARM_MAILBOX
566 -#define FIQ_ARM_DOORBELL_0 INT_ARM_DOORBELL_0
567 -#define FIQ_ARM_DOORBELL_1 INT_ARM_DOORBELL_1
568 -#define FIQ_VPU0_HALTED INT_VPU0_HALTED
569 -#define FIQ_VPU1_HALTED INT_VPU1_HALTED
570 -#define FIQ_ILLEGAL_TYPE0 INT_ILLEGAL_TYPE0
571 -#define FIQ_ILLEGAL_TYPE1 INT_ILLEGAL_TYPE1
572 -#define FIQ_PENDING1 INT_PENDING1
573 -#define FIQ_PENDING2 INT_PENDING2
574 +#define FIQ_ARM_TIMER (FIQ_START+INTERRUPT_ARM_TIMER)
575 +#define FIQ_ARM_MAILBOX (FIQ_START+INTERRUPT_ARM_MAILBOX)
576 +#define FIQ_ARM_DOORBELL_0 (FIQ_START+INTERRUPT_ARM_DOORBELL_0)
577 +#define FIQ_ARM_DOORBELL_1 (FIQ_START+INTERRUPT_ARM_DOORBELL_1)
578 +#define FIQ_VPU0_HALTED (FIQ_START+INTERRUPT_VPU0_HALTED)
579 +#define FIQ_VPU1_HALTED (FIQ_START+INTERRUPT_VPU1_HALTED)
580 +#define FIQ_ILLEGAL_TYPE0 (FIQ_START+INTERRUPT_ILLEGAL_TYPE0)
581 +#define FIQ_ILLEGAL_TYPE1 (FIQ_START+INTERRUPT_ILLEGAL_TYPE1)
582 +#define FIQ_PENDING1 (FIQ_START+INTERRUPT_PENDING1)
583 +#define FIQ_PENDING2 (FIQ_START+INTERRUPT_PENDING2)
585 #define HARD_IRQS (64 + 21)
586 -#define GPIO_IRQ_START (HARD_IRQS)
587 +#define FIQ_IRQS (64 + 21)
588 +#define GPIO_IRQ_START (HARD_IRQS + FIQ_IRQS)
589 #define GPIO_IRQS (32*5)
590 #define SPARE_IRQS (64)
591 -#define NR_IRQS (HARD_IRQS+GPIO_IRQS+SPARE_IRQS)
592 +#define NR_IRQS (HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_IRQS)
594 #endif /* _BCM2708_IRQS_H_ */
595 --- a/arch/arm/mach-bcm2708/include/mach/platform.h
596 +++ b/arch/arm/mach-bcm2708/include/mach/platform.h
600 #define BCM2708_PERI_BASE 0x20000000
601 +#define IC0_BASE (BCM2708_PERI_BASE + 0x2000)
602 #define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */
603 +#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */
604 #define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */
605 #define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */
606 #define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */
607 --- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c
608 +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
609 @@ -580,7 +580,13 @@ void DWC_WRITE_REG64(uint64_t volatile *
611 void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
613 + unsigned long flags;
615 + local_irq_save(flags);
616 + local_fiq_disable();
617 writel((readl(reg) & ~clear_mask) | set_mask, reg);
618 + local_fiq_enable();
619 + local_irq_restore(flags);
623 @@ -991,6 +997,11 @@ void DWC_TASK_SCHEDULE(dwc_tasklet_t *ta
624 tasklet_schedule(&task->t);
627 +void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task)
629 + tasklet_hi_schedule(&task->t);
634 - run in process context (can sleep)
635 --- a/drivers/usb/host/dwc_common_port/dwc_list.h
636 +++ b/drivers/usb/host/dwc_common_port/dwc_list.h
637 @@ -384,17 +384,17 @@ struct { \
638 #define DWC_TAILQ_PREV(elm, headname, field) \
639 (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
640 #define DWC_TAILQ_EMPTY(head) \
641 - (TAILQ_FIRST(head) == TAILQ_END(head))
642 + (DWC_TAILQ_FIRST(head) == DWC_TAILQ_END(head))
644 #define DWC_TAILQ_FOREACH(var, head, field) \
645 - for((var) = TAILQ_FIRST(head); \
646 - (var) != TAILQ_END(head); \
647 - (var) = TAILQ_NEXT(var, field))
648 + for ((var) = DWC_TAILQ_FIRST(head); \
649 + (var) != DWC_TAILQ_END(head); \
650 + (var) = DWC_TAILQ_NEXT(var, field))
652 #define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
653 - for((var) = TAILQ_LAST(head, headname); \
654 - (var) != TAILQ_END(head); \
655 - (var) = TAILQ_PREV(var, headname, field))
656 + for ((var) = DWC_TAILQ_LAST(head, headname); \
657 + (var) != DWC_TAILQ_END(head); \
658 + (var) = DWC_TAILQ_PREV(var, headname, field))
661 * Tail queue functions.
662 --- a/drivers/usb/host/dwc_common_port/dwc_os.h
663 +++ b/drivers/usb/host/dwc_common_port/dwc_os.h
664 @@ -981,6 +981,8 @@ extern void DWC_TASK_FREE(dwc_tasklet_t
665 extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
666 #define dwc_task_schedule DWC_TASK_SCHEDULE
668 +extern void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task);
669 +#define dwc_task_hi_schedule DWC_TASK_HI_SCHEDULE
673 --- a/drivers/usb/host/dwc_otg/Makefile
674 +++ b/drivers/usb/host/dwc_otg/Makefile
675 @@ -36,6 +36,7 @@ dwc_otg-objs += dwc_otg_cil.o dwc_otg_ci
676 dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o
677 dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o
678 dwc_otg-objs += dwc_otg_adp.o
679 +dwc_otg-objs += dwc_otg_mphi_fix.o
681 dwc_otg-objs += dwc_otg_cfi.o
683 --- a/drivers/usb/host/dwc_otg/dwc_otg_attr.c
684 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
685 @@ -909,7 +909,7 @@ static ssize_t regdump_show(struct devic
686 return sprintf(buf, "Register Dump\n");
689 -DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0);
690 +DEVICE_ATTR(regdump, S_IRUGO, regdump_show, 0);
693 * Dump global registers and either host or device registers (depending on the
694 @@ -920,12 +920,12 @@ static ssize_t spramdump_show(struct dev
696 dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
698 - dwc_otg_dump_spram(otg_dev->core_if);
699 + //dwc_otg_dump_spram(otg_dev->core_if);
701 return sprintf(buf, "SPRAM Dump\n");
704 -DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0);
705 +DEVICE_ATTR(spramdump, S_IRUGO, spramdump_show, 0);
708 * Dump the current hcd state.
709 @@ -940,7 +940,7 @@ static ssize_t hcddump_show(struct devic
710 return sprintf(buf, "HCD Dump\n");
713 -DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0);
714 +DEVICE_ATTR(hcddump, S_IRUGO, hcddump_show, 0);
717 * Dump the average frame remaining at SOF. This can be used to
718 @@ -958,7 +958,7 @@ static ssize_t hcd_frrem_show(struct dev
719 return sprintf(buf, "HCD Dump Frame Remaining\n");
722 -DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0);
723 +DEVICE_ATTR(hcd_frrem, S_IRUGO, hcd_frrem_show, 0);
726 * Displays the time required to read the GNPTXFSIZ register many times (the
727 @@ -986,7 +986,7 @@ static ssize_t rd_reg_test_show(struct d
728 RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
731 -DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0);
732 +DEVICE_ATTR(rd_reg_test, S_IRUGO, rd_reg_test_show, 0);
735 * Displays the time required to write the GNPTXFSIZ register many times (the
736 @@ -1014,7 +1014,7 @@ static ssize_t wr_reg_test_show(struct d
737 RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
740 -DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0);
741 +DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0);
743 #ifdef CONFIG_USB_DWC_OTG_LPM
745 --- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
746 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
748 #include "dwc_otg_driver.h"
749 #include "dwc_otg_pcd.h"
750 #include "dwc_otg_hcd.h"
751 +#include "dwc_otg_mphi_fix.h"
754 inline const char *op_state_str(dwc_otg_core_if_t * core_if)
755 @@ -1318,7 +1319,7 @@ static int32_t dwc_otg_handle_lpm_intr(d
757 * This function returns the Core Interrupt register.
759 -static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
760 +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk)
762 gahbcfg_data_t gahbcfg = {.d32 = 0 };
763 gintsts_data_t gintsts;
764 @@ -1335,26 +1336,45 @@ static inline uint32_t dwc_otg_read_comm
765 gintmsk_common.b.lpmtranrcvd = 1;
767 gintmsk_common.b.restoredone = 1;
768 - /** @todo: The port interrupt occurs while in device
769 - * mode. Added code to CIL to clear the interrupt for now!
771 - gintmsk_common.b.portintr = 1;
773 + if(dwc_otg_is_device_mode(core_if))
775 + /** @todo: The port interrupt occurs while in device
776 + * mode. Added code to CIL to clear the interrupt for now!
778 + gintmsk_common.b.portintr = 1;
780 gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
781 gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
783 + unsigned long flags;
785 + // Re-enable the saved interrupts
786 + local_irq_save(flags);
787 + local_fiq_disable();
788 + gintmsk.d32 |= gintmsk_common.d32;
789 + gintsts_saved.d32 &= ~gintmsk_common.d32;
790 + reenable_gintmsk->d32 = gintmsk.d32;
791 + local_irq_restore(flags);
794 gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
797 /* if any common interrupts set */
798 if (gintsts.d32 & gintmsk_common.d32) {
799 - DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n",
800 + DWC_DEBUGPL(DBG_ANY, "common_intr: gintsts=%08x gintmsk=%08x\n",
801 gintsts.d32, gintmsk.d32);
804 - if (gahbcfg.b.glblintrmsk)
805 + if (!fiq_fix_enable){
806 + if (gahbcfg.b.glblintrmsk)
807 + return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
812 return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
819 @@ -1386,6 +1406,7 @@ int32_t dwc_otg_handle_common_intr(void
822 gintsts_data_t gintsts;
823 + gintmsk_data_t reenable_gintmsk;
824 gpwrdn_data_t gpwrdn = {.d32 = 0 };
825 dwc_otg_device_t *otg_dev = dev;
826 dwc_otg_core_if_t *core_if = otg_dev->core_if;
827 @@ -1407,7 +1428,7 @@ int32_t dwc_otg_handle_common_intr(void
830 if (core_if->hibernation_suspend <= 0) {
831 - gintsts.d32 = dwc_otg_read_common_intr(core_if);
832 + gintsts.d32 = dwc_otg_read_common_intr(core_if, &reenable_gintmsk);
834 if (gintsts.b.modemismatch) {
835 retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
836 @@ -1504,8 +1525,12 @@ int32_t dwc_otg_handle_common_intr(void
837 gintsts.b.portintr = 1;
838 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
840 + reenable_gintmsk.b.portintr = 1;
844 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, reenable_gintmsk.d32);
847 DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
849 --- a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
850 +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
851 @@ -49,6 +49,7 @@ static inline uint32_t SET_DEBUG_LEVEL(c
855 +#define DBG_USER (0x1)
856 /** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
857 #define DBG_CIL (0x2)
858 /** When debug level has the DBG_CILV bit set, display CIL Verbose debug
859 --- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
860 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
861 @@ -64,6 +64,8 @@ bool microframe_schedule=true;
863 static const char dwc_driver_name[] = "dwc_otg";
865 +extern void* dummy_send;
869 struct lm_device *_dev
870 @@ -238,6 +240,14 @@ static struct dwc_otg_driver_module_para
874 +//Global variable to switch the fiq fix on or off (declared in bcm2708.c)
875 +extern bool fiq_fix_enable;
876 +// Global variable to enable the split transaction fix
877 +bool fiq_split_enable = true;
878 +//Global variable to switch the nak holdoff on or off
879 +bool nak_holdoff_enable = true;
883 * This function shows the Driver Version.
885 @@ -779,17 +789,33 @@ static int dwc_otg_driver_probe(
886 _dev->resource->start,
887 _dev->resource->end - _dev->resource->start + 1);
889 - if (!request_mem_region(_dev->resource->start,
890 - _dev->resource->end - _dev->resource->start + 1,
891 + if (!request_mem_region(_dev->resource[0].start,
892 + _dev->resource[0].end - _dev->resource[0].start + 1,
894 dev_dbg(&_dev->dev, "error reserving mapped memory\n");
899 - dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
900 - _dev->resource->end -
901 - _dev->resource->start+1);
902 + dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start,
903 + _dev->resource[0].end -
904 + _dev->resource[0].start+1);
905 + if (fiq_fix_enable)
907 + if (!request_mem_region(_dev->resource[1].start,
908 + _dev->resource[1].end - _dev->resource[1].start + 1,
910 + dev_dbg(&_dev->dev, "error reserving mapped memory\n");
915 + dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
916 + _dev->resource[1].end -
917 + _dev->resource[1].start + 1);
918 + dummy_send = (void *) kmalloc(16, GFP_ATOMIC);
923 struct map_desc desc = {
924 @@ -1044,6 +1070,12 @@ static int __init dwc_otg_driver_init(vo
927 struct device_driver *drv;
929 + if(fiq_split_enable && !fiq_fix_enable) {
930 + printk(KERN_WARNING "dwc_otg: fiq_split_enable was set without fiq_fix_enable! Correcting.\n");
931 + fiq_fix_enable = 1;
934 printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
937 @@ -1063,6 +1095,9 @@ static int __init dwc_otg_driver_init(vo
938 printk(KERN_ERR "%s retval=%d\n", __func__, retval);
941 + printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");
942 + printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled");
943 + printk(KERN_DEBUG "dwc_otg: FIQ split fix %s\n", fiq_split_enable ? "enabled":"disabled");
945 error = driver_create_file(drv, &driver_attr_version);
947 @@ -1343,6 +1378,13 @@ MODULE_PARM_DESC(otg_ver, "OTG revision
948 module_param(microframe_schedule, bool, 0444);
949 MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
951 +module_param(fiq_fix_enable, bool, 0444);
952 +MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");
953 +module_param(nak_holdoff_enable, bool, 0444);
954 +MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff");
955 +module_param(fiq_split_enable, bool, 0444);
956 +MODULE_PARM_DESC(fiq_split_enable, "Enable the FIQ fix on split transactions");
958 /** @page "Module Parameters"
960 * The following parameters may be specified when starting the module.
961 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
962 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
967 +#include <linux/usb.h>
968 +#include <linux/usb/hcd.h>
970 #include "dwc_otg_hcd.h"
971 #include "dwc_otg_regs.h"
972 +#include "dwc_otg_mphi_fix.h"
974 -extern bool microframe_schedule;
975 +extern bool microframe_schedule, nak_holdoff_enable;
977 //#define DEBUG_HOST_CHANNELS
978 #ifdef DEBUG_HOST_CHANNELS
979 @@ -53,6 +57,13 @@ static int last_sel_trans_num_avail_hc_a
980 static int last_sel_trans_num_avail_hc_at_end = 0;
981 #endif /* DEBUG_HOST_CHANNELS */
983 +extern int g_next_sched_frame, g_np_count, g_np_sent;
985 +extern haint_data_t haint_saved;
986 +extern hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
987 +extern hcint_data_t hcint_saved[MAX_EPS_CHANNELS];
988 +extern gintsts_data_t ginsts_saved;
990 dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
992 return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
993 @@ -162,31 +173,43 @@ static void del_timers(dwc_otg_hcd_t * h
996 * Processes all the URBs in a single list of QHs. Completes them with
997 - * -ETIMEDOUT and frees the QTD.
998 + * -ESHUTDOWN and frees the QTD.
1000 static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
1002 - dwc_list_link_t *qh_item;
1003 + dwc_list_link_t *qh_item, *qh_tmp;
1005 dwc_otg_qtd_t *qtd, *qtd_tmp;
1007 - DWC_LIST_FOREACH(qh_item, qh_list) {
1008 + DWC_LIST_FOREACH_SAFE(qh_item, qh_tmp, qh_list) {
1009 qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
1010 DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
1011 &qh->qtd_list, qtd_list_entry) {
1012 qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
1013 if (qtd->urb != NULL) {
1014 hcd->fops->complete(hcd, qtd->urb->priv,
1015 - qtd->urb, -DWC_E_TIMEOUT);
1016 + qtd->urb, -DWC_E_SHUTDOWN);
1017 dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
1022 + /* Using hcchar.chen == 1 is not a reliable test.
1023 + * It is possible that the channel has already halted
1024 + * but not yet been through the IRQ handler.
1026 + dwc_otg_hc_halt(hcd->core_if, qh->channel,
1027 + DWC_OTG_HC_XFER_URB_DEQUEUE);
1028 + if(microframe_schedule)
1029 + hcd->available_host_channels++;
1030 + qh->channel = NULL;
1032 + dwc_otg_hcd_qh_remove(hcd, qh);
1037 - * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
1038 + * Responds with an error status of ESHUTDOWN to all URBs in the non-periodic
1039 * and periodic schedules. The QTD associated with each URB is removed from
1040 * the schedule and freed. This function may be called when a disconnect is
1041 * detected or when the HCD is being stopped.
1042 @@ -272,7 +295,8 @@ static int32_t dwc_otg_hcd_disconnect_cb
1044 dwc_otg_hcd->flags.b.port_connect_status_change = 1;
1045 dwc_otg_hcd->flags.b.port_connect_status = 0;
1047 + if(fiq_fix_enable)
1048 + local_fiq_disable();
1050 * Shutdown any transfers in process by clearing the Tx FIFO Empty
1051 * interrupt mask and status bits and disabling subsequent host
1052 @@ -368,8 +392,22 @@ static int32_t dwc_otg_hcd_disconnect_cb
1056 + if(fiq_split_enable) {
1057 + for(i=0; i < 128; i++) {
1058 + dwc_otg_hcd->hub_port[i] = 0;
1060 + haint_saved.d32 = 0;
1061 + for(i=0; i < MAX_EPS_CHANNELS; i++) {
1062 + hcint_saved[i].d32 = 0;
1063 + hcintmsk_saved[i].d32 = 0;
1069 + if(fiq_fix_enable)
1070 + local_fiq_enable();
1072 if (dwc_otg_hcd->fops->disconnect) {
1073 dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
1075 @@ -407,6 +445,7 @@ static int dwc_otg_hcd_sleep_cb(void *p)
1081 * HCD Callback function for Remote Wakeup.
1083 @@ -457,10 +496,12 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_
1084 dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
1087 - dwc_irqflags_t flags;
1089 + uint8_t needs_scheduling = 0;
1090 + dwc_otg_transaction_type_e tr_type;
1092 gintmsk_data_t intr_mask = {.d32 = 0 };
1093 + hprt0_data_t hprt0 = { .d32 = 0 };
1095 #ifdef DEBUG /* integrity checks (Broadcom) */
1096 if (NULL == hcd->core_if) {
1097 @@ -475,6 +516,16 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_
1098 return -DWC_E_NO_DEVICE;
1101 + /* Some core configurations cannot support LS traffic on a FS root port */
1102 + if ((hcd->fops->speed(hcd, dwc_otg_urb->priv) == USB_SPEED_LOW) &&
1103 + (hcd->core_if->hwcfg2.b.fs_phy_type == 1) &&
1104 + (hcd->core_if->hwcfg2.b.hs_phy_type == 1)) {
1105 + hprt0.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
1106 + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_FULL_SPEED) {
1107 + return -DWC_E_NO_DEVICE;
1111 qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
1113 DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
1114 @@ -490,32 +541,27 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_
1115 return -DWC_E_NO_MEMORY;
1119 - dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
1120 + intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
1121 + if(!intr_mask.b.sofintr) needs_scheduling = 1;
1122 + if((((dwc_otg_qh_t *)ep_handle)->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP))
1123 + /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
1124 + needs_scheduling = 0;
1126 + retval = dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
1127 // creates a new queue in ep_handle if it doesn't exist already
1129 DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
1130 "Error status %d\n", retval);
1131 dwc_otg_hcd_qtd_free(qtd);
1133 - qtd->qh = *ep_handle;
1136 - intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
1137 - if (!intr_mask.b.sofintr && retval == 0) {
1138 - dwc_otg_transaction_type_e tr_type;
1139 - if ((qtd->qh->ep_type == UE_BULK)
1140 - && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
1141 - /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
1144 - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
1146 + if(needs_scheduling) {
1147 tr_type = dwc_otg_hcd_select_transactions(hcd);
1148 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
1149 dwc_otg_hcd_queue_transactions(hcd, tr_type);
1151 - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
1157 @@ -524,6 +570,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_
1160 dwc_otg_qtd_t *urb_qtd;
1162 + BUG_ON(!dwc_otg_urb);
1164 #ifdef DEBUG /* integrity checks (Broadcom) */
1166 @@ -540,14 +588,17 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_
1167 return -DWC_E_INVALID;
1169 urb_qtd = dwc_otg_urb->qtd;
1171 if (urb_qtd->qh == NULL) {
1172 DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
1173 return -DWC_E_INVALID;
1176 urb_qtd = dwc_otg_urb->qtd;
1181 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
1182 if (urb_qtd->in_process) {
1183 dump_channel_info(hcd, qh);
1184 @@ -571,6 +622,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_
1186 dwc_otg_hc_halt(hcd->core_if, qh->channel,
1187 DWC_OTG_HC_XFER_URB_DEQUEUE);
1189 + dwc_otg_hcd_release_port(hcd, qh);
1193 @@ -687,6 +740,33 @@ static void reset_tasklet_func(void *dat
1194 dwc_otg_hcd->flags.b.port_reset_change = 1;
1197 +static void completion_tasklet_func(void *ptr)
1199 + dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) ptr;
1201 + urb_tq_entry_t *item;
1202 + dwc_irqflags_t flags;
1204 + /* This could just be spin_lock_irq */
1205 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
1206 + while (!DWC_TAILQ_EMPTY(&hcd->completed_urb_list)) {
1207 + item = DWC_TAILQ_FIRST(&hcd->completed_urb_list);
1209 + DWC_TAILQ_REMOVE(&hcd->completed_urb_list, item,
1211 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
1214 + usb_hcd_giveback_urb(hcd->priv, urb, urb->status);
1216 + fiq_print(FIQDBG_PORTHUB, "COMPLETE");
1218 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
1220 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
1224 static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
1226 dwc_list_link_t *item;
1227 @@ -819,12 +899,14 @@ static void dwc_otg_hcd_free(dwc_otg_hcd
1228 } else if (dwc_otg_hcd->status_buf != NULL) {
1229 DWC_FREE(dwc_otg_hcd->status_buf);
1231 + DWC_SPINLOCK_FREE(dwc_otg_hcd->channel_lock);
1232 DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
1233 /* Set core_if's lock pointer to NULL */
1234 dwc_otg_hcd->core_if->lock = NULL;
1236 DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
1237 DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
1238 + DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
1240 #ifdef DWC_DEV_SRPCAP
1241 if (dwc_otg_hcd->core_if->power_down == 2 &&
1242 @@ -845,6 +927,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
1245 hcd->lock = DWC_SPINLOCK_ALLOC();
1246 + hcd->channel_lock = DWC_SPINLOCK_ALLOC();
1247 DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",
1250 @@ -868,7 +951,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
1251 DWC_LIST_INIT(&hcd->periodic_sched_ready);
1252 DWC_LIST_INIT(&hcd->periodic_sched_assigned);
1253 DWC_LIST_INIT(&hcd->periodic_sched_queued);
1255 + DWC_TAILQ_INIT(&hcd->completed_urb_list);
1257 * Create a host channel descriptor for each host channel implemented
1258 * in the controller. Initialize the channel descriptor array.
1259 @@ -906,6 +989,9 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
1261 /* Initialize reset tasklet. */
1262 hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
1264 + hcd->completion_tasklet = DWC_TASK_ALLOC("completion_tasklet",
1265 + completion_tasklet_func, hcd);
1266 #ifdef DWC_DEV_SRPCAP
1267 if (hcd->core_if->power_down == 2) {
1268 /* Initialize Power on timer for Host power up in case hibernation */
1269 @@ -938,6 +1024,12 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
1270 hcd->frame_list = NULL;
1271 hcd->frame_list_dma = 0;
1272 hcd->periodic_qh_count = 0;
1274 + DWC_MEMSET(hcd->hub_port, 0, sizeof(hcd->hub_port));
1276 + DWC_MEMSET(hcd->hub_port_alloc, -1, sizeof(hcd->hub_port_alloc));
1282 @@ -1083,7 +1175,12 @@ static void assign_and_init_hc(dwc_otg_h
1283 uint32_t hub_addr, port_addr;
1285 hc->xact_pos = qtd->isoc_split_pos;
1286 - hc->complete_split = qtd->complete_split;
1287 + /* We don't need to do complete splits anymore */
1288 + if(fiq_split_enable)
1289 + hc->complete_split = qtd->complete_split = 0;
1291 + hc->complete_split = qtd->complete_split;
1293 hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
1294 hc->hub_addr = (uint8_t) hub_addr;
1295 hc->port_addr = (uint8_t) port_addr;
1296 @@ -1230,6 +1327,65 @@ static void assign_and_init_hc(dwc_otg_h
1301 +** Check the transaction to see if the port / hub has already been assigned for
1302 +** a split transaction
1304 +** Return 0 - Port is already in use
1306 +int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
1308 + uint32_t hub_addr, port_addr;
1310 + if(!fiq_split_enable)
1313 + hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
1315 + if(hcd->hub_port[hub_addr] & (1 << port_addr))
1317 + fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count);
1321 + if(qh->skip_count > 40000)
1323 + printk_once(KERN_ERR "Error: Having to skip port allocation");
1324 + local_fiq_disable();
1332 + qh->skip_count = 0;
1333 + hcd->hub_port[hub_addr] |= 1 << port_addr;
1334 + fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
1336 + hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd);
1341 +void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
1343 + uint32_t hub_addr, port_addr;
1345 + if(!fiq_split_enable)
1348 + hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
1350 + hcd->hub_port[hub_addr] &= ~(1 << port_addr);
1352 + hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1;
1354 + fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
1360 * This function selects transactions from the HCD transfer schedule and
1361 * assigns them to available host channels. It is called from HCD interrupt
1362 @@ -1243,9 +1399,10 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
1364 dwc_list_link_t *qh_ptr;
1366 + dwc_otg_qtd_t *qtd;
1368 dwc_irqflags_t flags;
1369 - dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
1370 + dwc_spinlock_t *channel_lock = hcd->channel_lock;
1371 dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
1374 @@ -1263,11 +1420,29 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
1376 while (qh_ptr != &hcd->periodic_sched_ready &&
1377 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1379 + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1381 + if(qh->do_split) {
1382 + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
1383 + if(!(qh->ep_type == UE_ISOCHRONOUS &&
1384 + (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
1385 + qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END))) {
1386 + if(dwc_otg_hcd_allocate_port(hcd, qh))
1388 + qh_ptr = DWC_LIST_NEXT(qh_ptr);
1389 + g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
1395 if (microframe_schedule) {
1396 // Make sure we leave one channel for non periodic transactions.
1397 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
1398 if (hcd->available_host_channels <= 1) {
1399 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
1400 + if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh);
1403 hcd->available_host_channels--;
1404 @@ -1288,8 +1463,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
1405 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
1406 &qh->qh_list_entry);
1407 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
1409 - ret_val = DWC_OTG_TRANSACTION_PERIODIC;
1413 @@ -1304,6 +1477,31 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
1414 num_channels - hcd->periodic_channels) &&
1415 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1417 + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1420 + * Check to see if this is a NAK'd retransmit, in which case ignore for retransmission
1421 + * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed
1422 + * cheeky devices that just hold off using NAKs
1424 + if (nak_holdoff_enable && qh->do_split) {
1425 + if (qh->nak_frame != 0xffff &&
1426 + dwc_full_frame_num(qh->nak_frame) ==
1427 + dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
1429 + * Revisit: Need to avoid trampling on periodic scheduling.
1430 + * Currently we are safe because g_np_count != g_np_sent whenever we hit this,
1431 + * but if this behaviour is changed then periodic endpoints will get a slower
1434 + g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
1435 + qh_ptr = DWC_LIST_NEXT(qh_ptr);
1438 + qh->nak_frame = 0xffff;
1442 if (microframe_schedule) {
1443 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
1444 if (hcd->available_host_channels < 1) {
1445 @@ -1316,7 +1514,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
1446 last_sel_trans_num_nonper_scheduled++;
1447 #endif /* DEBUG_HOST_CHANNELS */
1449 - qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1451 assign_and_init_hc(hcd, qh);
1453 @@ -1330,21 +1527,22 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
1454 &qh->qh_list_entry);
1455 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
1457 - if (ret_val == DWC_OTG_TRANSACTION_NONE) {
1458 - ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
1460 - ret_val = DWC_OTG_TRANSACTION_ALL;
1464 if (!microframe_schedule)
1465 hcd->non_periodic_channels++;
1468 + if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned))
1469 + ret_val |= DWC_OTG_TRANSACTION_PERIODIC;
1471 + if(!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active))
1472 + ret_val |= DWC_OTG_TRANSACTION_NON_PERIODIC;
1475 #ifdef DEBUG_HOST_CHANNELS
1476 last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
1477 #endif /* DEBUG_HOST_CHANNELS */
1479 - DWC_SPINLOCK_FREE(channel_lock);
1483 @@ -1458,6 +1656,15 @@ static void process_periodic_channels(dw
1485 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1487 + // Do not send a split start transaction any later than frame .6
1488 + // Note, we have to schedule a periodic in .5 to make it go in .6
1489 + if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
1491 + qh_ptr = qh_ptr->next;
1492 + g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
1497 * Set a flag if we're queuing high-bandwidth in slave mode.
1498 * The flag prevents any halts to get into the request queue in
1499 @@ -1587,6 +1794,15 @@ static void process_non_periodic_channel
1501 qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
1504 + // Do not send a split start transaction any later than frame .5
1505 + // non periodic transactions will start immediately in this uframe
1506 + if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
1508 + g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
1513 queue_transaction(hcd, qh->channel,
1514 tx_status.b.nptxfspcavail);
1515 @@ -3112,17 +3328,13 @@ dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc
1517 dwc_otg_urb = DWC_ALLOC(size);
1519 - if (NULL != dwc_otg_urb)
1520 - dwc_otg_urb->packet_count = iso_desc_count;
1522 + dwc_otg_urb->packet_count = iso_desc_count;
1524 - dwc_otg_urb->packet_count = 0;
1526 - DWC_ERROR("**** DWC OTG HCD URB alloc - "
1527 - "%salloc of %db failed\n",
1528 - atomic_alloc?"atomic ":"", size);
1532 + DWC_ERROR("**** DWC OTG HCD URB alloc - "
1533 + "%salloc of %db failed\n",
1534 + atomic_alloc?"atomic ":"", size);
1539 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
1540 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
1541 @@ -168,10 +168,10 @@ typedef enum dwc_otg_control_phase {
1543 /** Transaction types. */
1544 typedef enum dwc_otg_transaction_type {
1545 - DWC_OTG_TRANSACTION_NONE,
1546 - DWC_OTG_TRANSACTION_PERIODIC,
1547 - DWC_OTG_TRANSACTION_NON_PERIODIC,
1548 - DWC_OTG_TRANSACTION_ALL
1549 + DWC_OTG_TRANSACTION_NONE = 0,
1550 + DWC_OTG_TRANSACTION_PERIODIC = 1,
1551 + DWC_OTG_TRANSACTION_NON_PERIODIC = 2,
1552 + DWC_OTG_TRANSACTION_ALL = DWC_OTG_TRANSACTION_PERIODIC + DWC_OTG_TRANSACTION_NON_PERIODIC
1553 } dwc_otg_transaction_type_e;
1556 @@ -321,6 +321,11 @@ typedef struct dwc_otg_qh {
1558 uint16_t sched_frame;
1561 + ** Frame a NAK was received on this queue head, used to minimise NAK retransmission
1563 + uint16_t nak_frame;
1565 /** (micro)frame at which last start split was initialized. */
1566 uint16_t start_split_frame;
1568 @@ -365,10 +370,19 @@ typedef struct dwc_otg_qh {
1571 uint16_t frame_usecs[8];
1573 + uint32_t skip_count;
1576 DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
1578 +typedef struct urb_tq_entry {
1580 + DWC_TAILQ_ENTRY(urb_tq_entry) urb_tq_entries;
1583 +DWC_TAILQ_HEAD(urb_list, urb_tq_entry);
1586 * This structure holds the state of the HCD, including the non-periodic and
1587 * periodic schedules.
1588 @@ -546,9 +560,12 @@ struct dwc_otg_hcd {
1589 /* Tasket to do a reset */
1590 dwc_tasklet_t *reset_tasklet;
1592 + dwc_tasklet_t *completion_tasklet;
1593 + struct urb_list completed_urb_list;
1596 dwc_spinlock_t *lock;
1598 + dwc_spinlock_t *channel_lock;
1600 * Private data that could be used by OS wrapper.
1602 @@ -559,6 +576,12 @@ struct dwc_otg_hcd {
1604 uint32_t *frame_list;
1606 + /** Hub - Port assignment */
1607 + int hub_port[128];
1609 + int hub_port_alloc[2048];
1612 /** Frame List DMA address */
1613 dma_addr_t frame_list_dma;
1615 @@ -589,6 +612,10 @@ extern dwc_otg_transaction_type_e dwc_ot
1616 extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
1617 dwc_otg_transaction_type_e tr_type);
1619 +int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh);
1620 +void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh);
1625 /** @name Interrupt Handler Functions */
1626 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
1627 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
1628 @@ -276,7 +276,7 @@ void dump_frame_list(dwc_otg_hcd_t * hcd
1629 static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
1631 dwc_irqflags_t flags;
1632 - dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
1633 + dwc_spinlock_t *channel_lock = hcd->channel_lock;
1635 dwc_hc_t *hc = qh->channel;
1636 if (dwc_qh_is_non_per(qh)) {
1637 @@ -306,7 +306,6 @@ static void release_channel_ddma(dwc_otg
1638 dwc_memset(qh->desc_list, 0x00,
1639 sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
1641 - DWC_SPINLOCK_FREE(channel_lock);
1645 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
1646 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
1647 @@ -113,6 +113,11 @@ extern void dwc_otg_hcd_remove(dwc_otg_h
1649 extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
1651 +/** This function is used to handle the fast interrupt
1654 +extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void);
1657 * Returns private data set by
1658 * dwc_otg_hcd_set_priv_data function.
1659 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
1660 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
1663 #include "dwc_otg_hcd.h"
1664 #include "dwc_otg_regs.h"
1665 +#include "dwc_otg_mphi_fix.h"
1667 +#include <linux/jiffies.h>
1668 +#include <mach/hardware.h>
1669 +#include <asm/fiq.h>
1672 extern bool microframe_schedule;
1674 @@ -41,38 +47,487 @@ extern bool microframe_schedule;
1675 * This file contains the implementation of the HCD Interrupt handlers.
1679 + * Some globals to communicate between the FIQ and INTERRUPT
1683 +mphi_regs_t c_mphi_regs;
1684 +volatile void *dwc_regs_base;
1685 +int fiq_done, int_done;
1687 +gintsts_data_t gintsts_saved = {.d32 = 0};
1688 +hcint_data_t hcint_saved[MAX_EPS_CHANNELS];
1689 +hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
1690 +int split_out_xfersize[MAX_EPS_CHANNELS];
1691 +haint_data_t haint_saved;
1693 +int g_next_sched_frame, g_np_count, g_np_sent;
1694 +static int mphi_int_count = 0 ;
1696 +hcchar_data_t nak_hcchar;
1697 +hctsiz_data_t nak_hctsiz;
1698 +hcsplt_data_t nak_hcsplt;
1701 +int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
1702 +int split_start_frame[MAX_EPS_CHANNELS];
1703 +int queued_port[MAX_EPS_CHANNELS];
1706 +char buffer[1000*16];
1708 +void notrace _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...)
1710 + FIQDBG_T dbg_lvl_req = FIQDBG_PORTHUB;
1713 + hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) };
1714 + unsigned long flags;
1716 + local_irq_save(flags);
1717 + local_fiq_disable();
1718 + if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR)
1720 + snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937);
1721 + va_start(args, fmt);
1722 + vsnprintf(text+8, 9, fmt, args);
1725 + memcpy(buffer + wptr, text, 16);
1726 + wptr = (wptr + 16) % sizeof(buffer);
1728 + local_irq_restore(flags);
1732 +void notrace fiq_queue_request(int channel, int odd_frame)
1734 + hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };
1735 + hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };
1736 + hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10) };
1738 + if(hcsplt.b.spltena == 0)
1740 + fiq_print(FIQDBG_ERR, "SPLTENA ");
1744 + if(hcchar.b.epdir == 1)
1746 + fiq_print(FIQDBG_SCHED, "IN Ch %d", channel);
1750 + hctsiz.b.xfersize = 0;
1751 + fiq_print(FIQDBG_SCHED, "OUT Ch %d", channel);
1753 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x10), hctsiz.d32);
1755 + hcsplt.b.compsplt = 1;
1756 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x4), hcsplt.d32);
1758 + // Send the Split complete
1759 + hcchar.b.chen = 1;
1760 + hcchar.b.oddfrm = odd_frame ? 1 : 0;
1762 + // Post this for transmit on the next frame for periodic or this frame for non-periodic
1763 + fiq_print(FIQDBG_SCHED, "SND_%s", odd_frame ? "ODD " : "EVEN");
1765 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x0), hcchar.d32);
1768 +static int last_sof = -1;
1771 +** Function to handle the start of frame interrupt, choose whether we need to do anything and
1772 +** therefore trigger the main interrupt
1774 +** returns int != 0 - interrupt has been handled
1778 +int notrace fiq_sof_handle(hfnum_data_t hfnum)
1783 + // Just check that once we're running we don't miss a SOF
1784 + /*if(last_sof != -1 && (hfnum.b.frnum != ((last_sof + 1) & 0x3fff)))
1786 + fiq_print(FIQDBG_ERR, "LASTSOF ");
1787 + fiq_print(FIQDBG_ERR, "%4d%d ", last_sof / 8, last_sof & 7);
1788 + fiq_print(FIQDBG_ERR, "%4d%d ", hfnum.b.frnum / 8, hfnum.b.frnum & 7);
1792 + // Only start remembering the last sof when the interrupt has been
1793 + // enabled (we don't check the mask to come in here...)
1794 + if(last_sof != -1 || FIQ_READ(dwc_regs_base + 0x18) & (1<<3))
1795 + last_sof = hfnum.b.frnum;
1797 + for(i = 0; i < MAX_EPS_CHANNELS; i++)
1799 + if(complete_sched[i] != -1)
1801 + if(complete_sched[i] <= hfnum.b.frnum || (complete_sched[i] > 0x3f00 && hfnum.b.frnum < 0xf0))
1803 + fiq_queue_request(i, hfnum.b.frnum & 1);
1804 + complete_sched[i] = -1;
1808 + if(complete_sched[i] != -1)
1810 + // This is because we've seen a split complete occur with no start...
1811 + // most likely because missed the complete 0x3fff frames ago!
1813 + diff = (hfnum.b.frnum + 0x3fff - complete_sched[i]) & 0x3fff ;
1814 + if(diff > 32 && diff < 0x3f00)
1816 + fiq_print(FIQDBG_ERR, "SPLTMISS");
1822 + if(g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
1825 + * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet
1826 + * g_next_sched_frame is the next frame we have periodic packets for
1828 + * if neither of these are required for this frame then just clear the interrupt
1837 +int notrace port_id(hcsplt_data_t hcsplt)
1839 + return hcsplt.b.prtaddr + (hcsplt.b.hubaddr << 8);
1842 +int notrace fiq_hcintr_handle(int channel, hfnum_data_t hfnum)
1844 + hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };
1845 + hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };
1846 + hcint_data_t hcint = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x8) };
1847 + hcintmsk_data_t hcintmsk = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0xc) };
1848 + hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10)};
1850 + hcint_saved[channel].d32 |= hcint.d32;
1851 + hcintmsk_saved[channel].d32 = hcintmsk.d32;
1853 + if(hcsplt.b.spltena)
1855 + fiq_print(FIQDBG_PORTHUB, "ph: %4x", port_id(hcsplt));
1856 + if(hcint.b.chhltd)
1858 + fiq_print(FIQDBG_SCHED, "CH HLT %d", channel);
1859 + fiq_print(FIQDBG_SCHED, "%08x", hcint_saved[channel]);
1861 + if(hcint.b.stall || hcint.b.xacterr || hcint.b.bblerr || hcint.b.frmovrun || hcint.b.datatglerr)
1863 + queued_port[channel] = 0;
1864 + fiq_print(FIQDBG_ERR, "CHAN ERR");
1866 + if(hcint.b.xfercomp)
1868 + // Clear the port allocation and transmit anything also on this port
1869 + queued_port[channel] = 0;
1870 + fiq_print(FIQDBG_SCHED, "XFERCOMP");
1874 + queued_port[channel] = 0;
1875 + fiq_print(FIQDBG_SCHED, "NAK");
1877 + if(hcint.b.ack && !hcsplt.b.compsplt)
1881 + // Do not complete isochronous out transactions
1882 + if(hcchar.b.eptype == 1 && hcchar.b.epdir == 0)
1884 + queued_port[channel] = 0;
1885 + fiq_print(FIQDBG_SCHED, "ISOC_OUT");
1889 + // Make sure we check the port / hub combination that we sent this split on.
1890 + // Do not queue a second request to the same port
1891 + for(i = 0; i < MAX_EPS_CHANNELS; i++)
1893 + if(port_id(hcsplt) == queued_port[i])
1895 + fiq_print(FIQDBG_ERR, "PORTERR ");
1900 + split_start_frame[channel] = (hfnum.b.frnum + 1) & ~7;
1902 + // Note, the size of an OUT is in the start split phase, not
1903 + // the complete split
1904 + split_out_xfersize[channel] = hctsiz.b.xfersize;
1906 + hcint_saved[channel].b.chhltd = 0;
1907 + hcint_saved[channel].b.ack = 0;
1909 + queued_port[channel] = port_id(hcsplt);
1911 + if(hcchar.b.eptype & 1)
1913 + // Send the periodic complete in the same oddness frame as the ACK went...
1914 + fiq_queue_request(channel, !(hfnum.b.frnum & 1));
1915 + // complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
1919 + // Schedule the split complete to occur later
1920 + complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 2);
1921 + fiq_print(FIQDBG_SCHED, "ACK%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
1927 + fiq_print(FIQDBG_ERR, "NYETERR1");
1929 + // Can transmit a split complete up to uframe .0 of the next frame
1930 + if(hfnum.b.frnum <= dwc_frame_num_inc(split_start_frame[channel], 8))
1932 + // Send it next frame
1933 + if(hcchar.b.eptype & 1) // type 1 & 3 are interrupt & isoc
1935 + fiq_print(FIQDBG_SCHED, "NYT:SEND");
1936 + fiq_queue_request(channel, !(hfnum.b.frnum & 1));
1940 + // Schedule non-periodic access for next frame (the odd-even bit doesn't effect NP)
1941 + complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
1942 + fiq_print(FIQDBG_SCHED, "NYT%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
1944 + hcint_saved[channel].b.chhltd = 0;
1945 + hcint_saved[channel].b.nyet = 0;
1949 + queued_port[channel] = 0;
1950 + fiq_print(FIQDBG_ERR, "NYETERR2");
1958 + * If we have any of NAK, ACK, Datatlgerr active on a
1959 + * non-split channel, the sole reason is to reset error
1960 + * counts for a previously broken transaction. The FIQ
1961 + * will thrash on NAK IN and ACK OUT in particular so
1962 + * handle it "once" and allow the IRQ to do the rest.
1964 + hcint.d32 &= hcintmsk.d32;
1967 + hcintmsk.b.nak = 0;
1968 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);
1972 + hcintmsk.b.ack = 0;
1973 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);
1977 + // Clear the interrupt, this will also clear the HAINT bit
1978 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32);
1979 + return hcint_saved[channel].d32 == 0;
1982 +gintsts_data_t gintsts;
1983 +gintmsk_data_t gintmsk;
1984 +// triggered: The set of interrupts that were triggered
1985 +// handled: The set of interrupts that have been handled (no IRQ is
1987 +// keep: The set of interrupts we want to keep unmasked even though we
1988 +// want to trigger an IRQ to handle it (SOF and HCINTR)
1989 +gintsts_data_t triggered, handled, keep;
1990 +hfnum_data_t hfnum;
1992 +void __attribute__ ((naked)) notrace dwc_otg_hcd_handle_fiq(void)
1995 + /* entry takes care to store registers we will be treading on here */
1996 + asm __volatile__ (
1998 + /* stash FIQ and normal regs */
1999 + "stmdb sp!, {r0-r12, lr};"
2000 + /* !! THIS SETS THE FRAME, adjust to > sizeof locals */
2001 + "sub fp, ip, #512 ;"
2004 + // Cannot put local variables at the beginning of the function
2005 + // because otherwise 'C' will play with the stack pointer. any locals
2006 + // need to be inside the following block
2010 + gintsts.d32 = FIQ_READ(dwc_regs_base + 0x14);
2011 + gintmsk.d32 = FIQ_READ(dwc_regs_base + 0x18);
2012 + hfnum.d32 = FIQ_READ(dwc_regs_base + 0x408);
2013 + triggered.d32 = gintsts.d32 & gintmsk.d32;
2016 + fiq_print(FIQDBG_INT, "FIQ ");
2017 + fiq_print(FIQDBG_INT, "%08x", gintsts.d32);
2018 + fiq_print(FIQDBG_INT, "%08x", gintmsk.d32);
2021 + // If port enabled
2022 + if((FIQ_READ(dwc_regs_base + 0x440) & 0xf) == 0x5)
2024 + if(gintsts.b.sofintr)
2026 + if(fiq_sof_handle(hfnum))
2028 + handled.b.sofintr = 1; /* Handled in FIQ */
2032 + /* Keer interrupt unmasked */
2033 + keep.b.sofintr = 1;
2036 + // Need to make sure the read and clearing of the SOF interrupt is as close as possible to avoid the possibility of missing
2037 + // a start of frame interrupt
2038 + gintsts_data_t gintsts = { .b.sofintr = 1 };
2039 + FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
2043 + if(fiq_split_enable && gintsts.b.hcintr)
2046 + haint_data_t haint;
2047 + haintmsk_data_t haintmsk;
2049 + haint.d32 = FIQ_READ(dwc_regs_base + 0x414);
2050 + haintmsk.d32 = FIQ_READ(dwc_regs_base + 0x418);
2051 + haint.d32 &= haintmsk.d32;
2052 + haint_saved.d32 |= haint.d32;
2054 + fiq_print(FIQDBG_INT, "hcintr");
2055 + fiq_print(FIQDBG_INT, "%08x", FIQ_READ(dwc_regs_base + 0x414));
2057 + // Go through each channel that has an enabled interrupt
2058 + for(i = 0; i < 16; i++)
2059 + if((haint.d32 >> i) & 1)
2060 + if(fiq_hcintr_handle(i, hfnum))
2061 + haint_saved.d32 &= ~(1 << i); /* this was handled */
2063 + /* If we've handled all host channel interrupts then don't trigger the interrupt */
2064 + if(haint_saved.d32 == 0)
2066 + handled.b.hcintr = 1;
2070 + /* Make sure we keep the channel interrupt unmasked when triggering the IRQ */
2071 + keep.b.hcintr = 1;
2075 + gintsts_data_t gintsts = { .b.hcintr = 1 };
2077 + // Always clear the channel interrupt
2078 + FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
2088 + // Mask out the interrupts triggered - those handled - don't mask out the ones we want to keep
2089 + gintmsk.d32 = keep.d32 | (gintmsk.d32 & ~(triggered.d32 & ~handled.d32));
2090 + // Save those that were triggered but not handled
2091 + gintsts_saved.d32 |= triggered.d32 & ~handled.d32;
2092 + FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
2094 + // Clear and save any unhandled interrupts and trigger the interrupt
2095 + if(gintsts_saved.d32)
2097 + /* To enable the MPHI interrupt (INT 32)
2099 + FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send);
2100 + FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
2109 + /* exit back to normal mode restoring everything */
2110 + asm __volatile__ (
2111 + /* return FIQ regs back to pristine state
2112 + * and get normal regs back
2114 + "ldmia sp!, {r0-r12, lr};"
2117 + "subs pc, lr, #4;"
2121 /** This function handles interrupts for the HCD. */
2122 int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
2125 + static int last_time;
2127 dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
2128 gintsts_data_t gintsts;
2129 + gintmsk_data_t gintmsk;
2130 + hfnum_data_t hfnum;
2133 dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
2135 - //GRAYG: debugging
2136 - if (NULL == global_regs) {
2137 - DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
2139 - dwc_otg_hcd, global_regs);
2144 + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
2145 + gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
2147 /* Exit from ISR if core is hibernated */
2148 if (core_if->hibernation_suspend == 1) {
2150 + goto exit_handler_routine;
2152 DWC_SPINLOCK(dwc_otg_hcd->lock);
2153 /* Check if HOST Mode */
2154 if (dwc_otg_is_host_mode(core_if)) {
2155 - gintsts.d32 = dwc_otg_read_core_intr(core_if);
2156 + local_fiq_disable();
2157 + gintmsk.d32 |= gintsts_saved.d32;
2158 + gintsts.d32 |= gintsts_saved.d32;
2159 + gintsts_saved.d32 = 0;
2160 + local_fiq_enable();
2162 - DWC_SPINUNLOCK(dwc_otg_hcd->lock);
2164 + goto exit_handler_routine;
2166 + gintsts.d32 &= gintmsk.d32;
2169 + // We should be OK doing this because the common interrupts should already have been serviced
2170 /* Don't print debug message in the interrupt handler on SOF */
2172 if (gintsts.d32 != DWC_SOF_INTR_MASK)
2173 @@ -88,10 +543,16 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
2174 "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
2175 gintsts.d32, core_if);
2178 - if (gintsts.b.sofintr) {
2179 + hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum);
2180 + if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
2182 + /* Note, we should never get here if the FIQ is doing it's job properly*/
2183 retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
2185 + else if (gintsts.b.sofintr) {
2186 + retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
2189 if (gintsts.b.rxstsqlvl) {
2191 dwc_otg_hcd_handle_rx_status_q_level_intr
2192 @@ -106,7 +567,10 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
2193 /** @todo Implement i2cintr handler. */
2195 if (gintsts.b.portintr) {
2197 + gintmsk_data_t gintmsk = { .b.portintr = 1};
2198 retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
2199 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
2201 if (gintsts.b.hcintr) {
2202 retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
2203 @@ -138,11 +602,48 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
2208 +exit_handler_routine:
2210 + if (fiq_fix_enable)
2212 + local_fiq_disable();
2213 + // Make sure that we don't clear the interrupt if we've still got pending work to do
2214 + if(gintsts_saved.d32 == 0)
2216 + /* Clear the MPHI interrupt */
2217 + DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));
2218 + if (mphi_int_count >= 60)
2220 + DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));
2221 + while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17)))
2223 + DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
2224 + mphi_int_count = 0;
2229 + // Unmask handled interrupts
2230 + FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
2231 + //DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);
2233 + local_fiq_enable();
2235 + if((jiffies / HZ) > last_time)
2237 + /* Once a second output the fiq and irq numbers, useful for debug */
2238 + last_time = jiffies / HZ;
2239 + DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done);
2243 DWC_SPINUNLOCK(dwc_otg_hcd->lock);
2247 #ifdef DWC_TRACK_MISSED_SOFS
2249 #warning Compiling code to track missed SOFs
2250 #define FRAME_NUM_ARRAY_SIZE 1000
2252 @@ -188,7 +689,8 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_
2253 dwc_list_link_t *qh_entry;
2255 dwc_otg_transaction_type_e tr_type;
2256 - gintsts_data_t gintsts = {.d32 = 0 };
2257 + int did_something = 0;
2258 + int32_t next_sched_frame = -1;
2261 DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
2262 @@ -212,17 +714,31 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_
2263 qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
2264 qh_entry = qh_entry->next;
2265 if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
2268 * Move QH to the ready list to be executed next
2271 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
2272 &qh->qh_list_entry);
2274 + did_something = 1;
2278 + if(next_sched_frame < 0 || dwc_frame_num_le(qh->sched_frame, next_sched_frame))
2280 + next_sched_frame = qh->sched_frame;
2285 + g_next_sched_frame = next_sched_frame;
2287 tr_type = dwc_otg_hcd_select_transactions(hcd);
2288 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
2289 dwc_otg_hcd_queue_transactions(hcd, tr_type);
2290 + did_something = 1;
2293 /* Clear interrupt */
2294 @@ -511,6 +1027,15 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_o
2296 haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
2298 + // Overwrite with saved interrupts from fiq handler
2299 + if(fiq_split_enable)
2301 + local_fiq_disable();
2302 + haint.d32 = haint_saved.d32;
2303 + haint_saved.d32 = 0;
2304 + local_fiq_enable();
2307 for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
2308 if (haint.b2.chint & (1 << i)) {
2309 retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
2310 @@ -551,7 +1076,10 @@ static uint32_t get_actual_xfer_length(d
2311 *short_read = (hctsiz.b.xfersize != 0);
2313 } else if (hc->qh->do_split) {
2314 - length = qtd->ssplit_out_xfer_count;
2315 + if(fiq_split_enable)
2316 + length = split_out_xfersize[hc->hc_num];
2318 + length = qtd->ssplit_out_xfer_count;
2320 length = hc->xfer_len;
2322 @@ -595,7 +1123,6 @@ static int update_urb_state_xfer_comp(dw
2323 DWC_OTG_HC_XFER_COMPLETE,
2327 /* non DWORD-aligned buffer case handling. */
2328 if (hc->align_buff && xfer_length && hc->ep_is_in) {
2329 dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
2330 @@ -797,11 +1324,24 @@ static void release_channel(dwc_otg_hcd_
2331 dwc_otg_transaction_type_e tr_type;
2333 dwc_irqflags_t flags;
2334 - dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
2335 + dwc_spinlock_t *channel_lock = hcd->channel_lock;
2337 + int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0;
2341 DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n",
2342 __func__, hc->hc_num, halt_status, hc->xfer_len);
2344 + if(fiq_split_enable && hc->do_split) {
2345 + if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) {
2346 + if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID ||
2347 + hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) {
2353 switch (halt_status) {
2354 case DWC_OTG_HC_XFER_URB_COMPLETE:
2356 @@ -876,15 +1416,32 @@ cleanup:
2358 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
2359 hcd->available_host_channels++;
2360 + fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels);
2361 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
2364 + if(fiq_split_enable && hc->do_split)
2366 + if(!(hcd->hub_port[hc->hub_addr] & (1 << hc->port_addr)))
2368 + fiq_print(FIQDBG_ERR, "PRTNOTAL");
2371 + if(!hog_port && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC ||
2372 + hc->ep_type == DWC_OTG_EP_TYPE_INTR)) {
2373 + hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);
2375 + hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;
2377 + fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);
2381 /* Try to queue more transfers now that there's a free channel. */
2382 tr_type = dwc_otg_hcd_select_transactions(hcd);
2383 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
2384 dwc_otg_hcd_queue_transactions(hcd, tr_type);
2386 - DWC_SPINLOCK_FREE(channel_lock);
2390 @@ -1295,6 +1852,17 @@ static int32_t handle_hc_nak_intr(dwc_ot
2391 "NAK Received--\n", hc->hc_num);
2394 + * When we get bulk NAKs then remember this so we holdoff on this qh until
2395 + * the beginning of the next frame
2397 + switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
2400 + if (nak_holdoff_enable)
2401 + hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd);
2405 * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
2406 * interrupt. Re-start the SSPLIT transfer.
2408 @@ -1316,7 +1884,11 @@ static int32_t handle_hc_nak_intr(dwc_ot
2409 * transfers in DMA mode for the sole purpose of
2410 * resetting the error count after a transaction error
2411 * occurs. The core will continue transferring data.
2412 + * Disable other interrupts unmasked for the same
2415 + disable_hc_int(hc_regs, datatglerr);
2416 + disable_hc_int(hc_regs, ack);
2417 qtd->error_count = 0;
2418 goto handle_nak_done;
2420 @@ -1428,6 +2000,15 @@ static int32_t handle_hc_ack_intr(dwc_ot
2421 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
2425 + * An unmasked ACK on a non-split DMA transaction is
2426 + * for the sole purpose of resetting error counts. Disable other
2427 + * interrupts unmasked for the same reason.
2429 + if(hcd->core_if->dma_enable) {
2430 + disable_hc_int(hc_regs, datatglerr);
2431 + disable_hc_int(hc_regs, nak);
2433 qtd->error_count = 0;
2435 if (hc->qh->ping_state) {
2436 @@ -1490,8 +2071,10 @@ static int32_t handle_hc_nyet_intr(dwc_o
2437 hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
2438 int frnum = dwc_otg_hcd_get_frame_number(hcd);
2440 + // With the FIQ running we only ever see the failed NYET
2441 if (dwc_full_frame_num(frnum) !=
2442 - dwc_full_frame_num(hc->qh->sched_frame)) {
2443 + dwc_full_frame_num(hc->qh->sched_frame) ||
2444 + fiq_split_enable) {
2446 * No longer in the same full speed frame.
2447 * Treat this as a transaction error.
2448 @@ -1778,13 +2361,28 @@ static int32_t handle_hc_datatglerr_intr
2449 dwc_otg_qtd_t * qtd)
2451 DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
2452 - "Data Toggle Error--\n", hc->hc_num);
2453 + "Data Toggle Error on %s transfer--\n",
2454 + hc->hc_num, (hc->ep_is_in ? "IN" : "OUT"));
2456 - if (hc->ep_is_in) {
2457 + /* Data toggles on split transactions cause the hc to halt.
2458 + * restart transfer */
2459 + if(hc->qh->do_split)
2461 + qtd->error_count++;
2462 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2463 + update_urb_state_xfer_intr(hc, hc_regs,
2464 + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2465 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2466 + } else if (hc->ep_is_in) {
2467 + /* An unmasked data toggle error on a non-split DMA transaction is
2468 + * for the sole purpose of resetting error counts. Disable other
2469 + * interrupts unmasked for the same reason.
2471 + if(hcd->core_if->dma_enable) {
2472 + disable_hc_int(hc_regs, ack);
2473 + disable_hc_int(hc_regs, nak);
2475 qtd->error_count = 0;
2477 - DWC_ERROR("Data Toggle Error on OUT transfer,"
2478 - "channel %d\n", hc->hc_num);
2481 disable_hc_int(hc_regs, datatglerr);
2482 @@ -1862,10 +2460,10 @@ static inline int halt_status_ok(dwc_otg
2483 static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
2485 dwc_otg_hc_regs_t * hc_regs,
2486 - dwc_otg_qtd_t * qtd)
2487 + dwc_otg_qtd_t * qtd,
2488 + hcint_data_t hcint,
2489 + hcintmsk_data_t hcintmsk)
2491 - hcint_data_t hcint;
2492 - hcintmsk_data_t hcintmsk;
2493 int out_nak_enh = 0;
2495 /* For core with OUT NAK enhancement, the flow for high-
2496 @@ -1897,8 +2495,11 @@ static void handle_hc_chhltd_intr_dma(dw
2499 /* Read the HCINTn register to determine the cause for the halt. */
2500 - hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2501 - hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
2502 + if(!fiq_split_enable)
2504 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2505 + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
2508 if (hcint.b.xfercomp) {
2509 /** @todo This is here because of a possible hardware bug. Spec
2510 @@ -1937,6 +2538,8 @@ static void handle_hc_chhltd_intr_dma(dw
2511 handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
2512 } else if (hcint.b.frmovrun) {
2513 handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
2514 + } else if (hcint.b.datatglerr) {
2515 + handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd);
2516 } else if (!out_nak_enh) {
2519 @@ -1986,12 +2589,24 @@ static void handle_hc_chhltd_intr_dma(dw
2520 DWC_READ_REG32(&hcd->
2521 core_if->core_global_regs->
2523 + /* Failthrough: use 3-strikes rule */
2524 + qtd->error_count++;
2525 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2526 + update_urb_state_xfer_intr(hc, hc_regs,
2527 + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2528 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2533 DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
2535 + /* Failthrough: use 3-strikes rule */
2536 + qtd->error_count++;
2537 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2538 + update_urb_state_xfer_intr(hc, hc_regs,
2539 + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2540 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2544 @@ -2009,13 +2624,15 @@ static void handle_hc_chhltd_intr_dma(dw
2545 static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
2547 dwc_otg_hc_regs_t * hc_regs,
2548 - dwc_otg_qtd_t * qtd)
2549 + dwc_otg_qtd_t * qtd,
2550 + hcint_data_t hcint,
2551 + hcintmsk_data_t hcintmsk)
2553 DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
2554 "Channel Halted--\n", hc->hc_num);
2556 if (hcd->core_if->dma_enable) {
2557 - handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
2558 + handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd, hcint, hcintmsk);
2561 if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
2562 @@ -2032,7 +2649,7 @@ static int32_t handle_hc_chhltd_intr(dwc
2563 int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
2566 - hcint_data_t hcint;
2567 + hcint_data_t hcint, hcint_orig;
2568 hcintmsk_data_t hcintmsk;
2570 dwc_otg_hc_regs_t *hc_regs;
2571 @@ -2042,15 +2659,33 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
2573 hc = dwc_otg_hcd->hc_ptr_array[num];
2574 hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
2575 + if(hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
2576 + /* We are responding to a channel disable. Driver
2577 + * state is cleared - our qtd has gone away.
2579 + release_channel(dwc_otg_hcd, hc, NULL, hc->halt_status);
2582 qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
2584 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2585 + hcint_orig = hcint;
2586 hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
2587 DWC_DEBUGPL(DBG_HCDV,
2588 " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
2589 hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
2590 hcint.d32 = hcint.d32 & hcintmsk.d32;
2592 + if(fiq_split_enable)
2594 + // replace with the saved interrupts from the fiq handler
2595 + local_fiq_disable();
2596 + hcint_orig.d32 = hcint_saved[num].d32;
2597 + hcint.d32 = hcint_orig.d32 & hcintmsk_saved[num].d32;
2598 + hcint_saved[num].d32 = 0;
2599 + local_fiq_enable();
2602 if (!dwc_otg_hcd->core_if->dma_enable) {
2603 if (hcint.b.chhltd && hcint.d32 != 0x2) {
2605 @@ -2068,7 +2703,7 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
2608 if (hcint.b.chhltd) {
2609 - retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2610 + retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd, hcint_orig, hcintmsk_saved[num]);
2612 if (hcint.b.ahberr) {
2613 retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2614 @@ -2080,7 +2715,8 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
2615 retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2618 - retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2619 + if(!hcint.b.chhltd)
2620 + retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2623 retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2624 @@ -2102,5 +2738,4 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
2629 #endif /* DWC_DEVICE_ONLY */
2630 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
2631 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
2634 /* ==========================================================================
2635 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
2638 #include <linux/dma-mapping.h>
2639 #include <linux/version.h>
2641 +#include <asm/fiq.h>
2642 #include <linux/usb.h>
2643 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
2644 #include <../drivers/usb/core/hcd.h>
2646 #include "dwc_otg_dbg.h"
2647 #include "dwc_otg_driver.h"
2648 #include "dwc_otg_hcd.h"
2649 +#include "dwc_otg_mphi_fix.h"
2652 * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
2653 * qualified with its direction (possible 32 endpoints per device).
2656 static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
2658 +extern bool fiq_fix_enable;
2660 /** @name Linux HC Driver API Functions */
2662 /* manage i/o requests, device state */
2663 @@ -259,13 +265,15 @@ static void free_bus_bandwidth(struct us
2666 * Sets the final status of an URB and returns it to the device driver. Any
2667 - * required cleanup of the URB is performed.
2668 + * required cleanup of the URB is performed. The HCD lock should be held on
2671 static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
2672 dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
2674 struct urb *urb = (struct urb *)urb_handle;
2676 + urb_tq_entry_t *new_entry;
2678 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
2679 DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
2680 __func__, urb, usb_pipedevice(urb->pipe),
2681 @@ -279,7 +287,7 @@ static int _complete(dwc_otg_hcd_t * hcd
2686 + new_entry = DWC_ALLOC_ATOMIC(sizeof(urb_tq_entry_t));
2687 urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
2688 /* Convert status value. */
2690 @@ -301,6 +309,9 @@ static int _complete(dwc_otg_hcd_t * hcd
2691 case -DWC_E_OVERFLOW:
2692 status = -EOVERFLOW;
2694 + case -DWC_E_SHUTDOWN:
2695 + status = -ESHUTDOWN;
2699 DWC_PRINTF("Uknown urb status %d\n", status);
2700 @@ -342,18 +353,33 @@ static int _complete(dwc_otg_hcd_t * hcd
2703 DWC_FREE(dwc_otg_urb);
2706 + DWC_ERROR("dwc_otg_hcd: complete: cannot allocate URB TQ entry\n");
2707 + urb->status = -EPROTO;
2708 + /* don't schedule the tasklet -
2709 + * directly return the packet here with error. */
2710 #if USB_URB_EP_LINKING
2711 - usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
2712 + usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
2714 - DWC_SPINUNLOCK(hcd->lock);
2715 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
2716 - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
2717 + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
2719 - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
2720 + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
2722 - DWC_SPINLOCK(hcd->lock);
2725 + new_entry->urb = urb;
2726 +#if USB_URB_EP_LINKING
2727 + rc = usb_hcd_check_unlink_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
2729 + usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
2733 + DWC_TAILQ_INSERT_TAIL(&hcd->completed_urb_list, new_entry,
2735 + DWC_TASK_HI_SCHEDULE(hcd->completion_tasklet);
2741 @@ -366,6 +392,16 @@ static struct dwc_otg_hcd_function_ops h
2742 .get_b_hnp_enable = _get_b_hnp_enable,
2745 +static struct fiq_handler fh = {
2746 + .name = "usb_fiq",
2748 +struct fiq_stack_s {
2750 + uint8_t stack[2048];
2754 +extern mphi_regs_t c_mphi_regs;
2756 * Initializes the HCD. This function allocates memory for and initializes the
2757 * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
2758 @@ -379,6 +415,7 @@ int hcd_init(dwc_bus_dev_t *_dev)
2759 dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
2762 + struct pt_regs regs;
2764 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
2766 @@ -396,6 +433,20 @@ int hcd_init(dwc_bus_dev_t *_dev)
2767 pci_set_consistent_dma_mask(_dev, dmamask);
2770 + if (fiq_fix_enable)
2774 + set_fiq_handler(__FIQ_Branch, 4);
2775 + memset(®s,0,sizeof(regs));
2776 + regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq;
2777 + regs.ARM_r9 = (long)0;
2778 + regs.ARM_sp = (long)fiq_stack.stack + sizeof(fiq_stack.stack) - 4;
2779 + set_fiq_regs(®s);
2780 + fiq_stack.magic1 = 0xdeadbeef;
2781 + fiq_stack.magic2 = 0xaa995566;
2785 * Allocate memory for the base HCD plus the DWC OTG HCD.
2786 * Initialize the base HCD.
2787 @@ -415,6 +466,30 @@ int hcd_init(dwc_bus_dev_t *_dev)
2789 hcd->regs = otg_dev->os_dep.base;
2791 + if (fiq_fix_enable)
2793 + volatile extern void *dwc_regs_base;
2795 + //Set the mphi periph to the required registers
2796 + c_mphi_regs.base = otg_dev->os_dep.mphi_base;
2797 + c_mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
2798 + c_mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
2799 + c_mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
2800 + c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
2802 + dwc_regs_base = otg_dev->os_dep.base;
2804 + //Enable mphi peripheral
2805 + writel((1<<31),c_mphi_regs.ctrl);
2807 + if (readl(c_mphi_regs.ctrl) & 0x80000000)
2808 + DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n");
2810 + DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n");
2812 + // Enable FIQ interrupt from USB peripheral
2813 + enable_fiq(INTERRUPT_VC_USB);
2815 /* Initialize the DWC OTG HCD. */
2816 dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
2818 @@ -607,9 +682,7 @@ static int dwc_otg_urb_enqueue(struct us
2819 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
2820 struct usb_host_endpoint *ep = urb->ep;
2822 -#if USB_URB_EP_LINKING
2823 dwc_irqflags_t irqflags;
2825 void **ref_ep_hcpriv = &ep->hcpriv;
2826 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
2827 dwc_otg_hcd_urb_t *dwc_otg_urb;
2828 @@ -661,9 +734,8 @@ static int dwc_otg_urb_enqueue(struct us
2829 if(dwc_otg_urb == NULL)
2832 - urb->hcpriv = dwc_otg_urb;
2833 - if (!dwc_otg_urb && urb->number_of_packets)
2835 + if (!dwc_otg_urb && urb->number_of_packets)
2838 dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
2839 usb_pipeendpoint(urb->pipe), ep_type,
2840 @@ -703,37 +775,42 @@ static int dwc_otg_urb_enqueue(struct us
2841 iso_frame_desc[i].length);
2844 + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
2845 + urb->hcpriv = dwc_otg_urb;
2846 #if USB_URB_EP_LINKING
2847 - DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
2848 retval = usb_hcd_link_urb_to_ep(hcd, urb);
2849 - DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
2853 - retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
2854 - /*(dwc_otg_qh_t **)*/
2856 - mem_flags == GFP_ATOMIC ? 1 : 0);
2857 - if (0 == retval) {
2858 - if (alloc_bandwidth) {
2859 - allocate_bus_bandwidth(hcd,
2860 - dwc_otg_hcd_get_ep_bandwidth(
2861 - dwc_otg_hcd, *ref_ep_hcpriv),
2866 + retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
2867 + /*(dwc_otg_qh_t **)*/
2868 + ref_ep_hcpriv, 1);
2869 + if (0 == retval) {
2870 + if (alloc_bandwidth) {
2871 + allocate_bus_bandwidth(hcd,
2872 + dwc_otg_hcd_get_ep_bandwidth(
2873 + dwc_otg_hcd, *ref_ep_hcpriv),
2877 + DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
2878 #if USB_URB_EP_LINKING
2879 - dwc_irqflags_t irqflags;
2880 - DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
2881 - DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
2882 - usb_hcd_unlink_urb_from_ep(hcd, urb);
2883 - DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
2885 - if (retval == -DWC_E_NO_DEVICE) {
2890 + usb_hcd_unlink_urb_from_ep(hcd, urb);
2892 + DWC_FREE(dwc_otg_urb);
2893 + urb->hcpriv = NULL;
2894 + if (retval == -DWC_E_NO_DEVICE)
2898 +#if USB_URB_EP_LINKING
2901 + DWC_FREE(dwc_otg_urb);
2902 + urb->hcpriv = NULL;
2905 + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
2909 @@ -777,6 +854,8 @@ static int dwc_otg_urb_dequeue(struct us
2910 usb_hcd_unlink_urb_from_ep(hcd, urb);
2912 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
2915 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
2916 usb_hcd_giveback_urb(hcd, urb);
2918 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
2919 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
2922 #include "dwc_otg_hcd.h"
2923 #include "dwc_otg_regs.h"
2924 +#include "dwc_otg_mphi_fix.h"
2926 extern bool microframe_schedule;
2928 @@ -181,6 +182,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
2929 if (microframe_schedule)
2930 qh->speed = dev_speed;
2932 + qh->nak_frame = 0xffff;
2934 if (((dev_speed == USB_SPEED_LOW) ||
2935 (dev_speed == USB_SPEED_FULL)) &&
2936 @@ -190,6 +192,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
2937 dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
2940 + qh->skip_count = 0;
2943 if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
2944 @@ -572,6 +575,9 @@ static int check_max_xfer_size(dwc_otg_h
2949 +extern int g_next_sched_frame, g_np_count, g_np_sent;
2952 * Schedules an interrupt or isochronous transfer in the periodic schedule.
2954 @@ -630,8 +636,13 @@ static int schedule_periodic(dwc_otg_hcd
2955 DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
2958 - /* Always start in the inactive schedule. */
2959 - DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
2960 + if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame))
2962 + g_next_sched_frame = qh->sched_frame;
2965 + /* Always start in the inactive schedule. */
2966 + DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
2969 if (!microframe_schedule) {
2970 @@ -645,6 +656,7 @@ static int schedule_periodic(dwc_otg_hcd
2976 * This function adds a QH to either the non periodic or periodic schedule if
2977 * it is not already in the schedule. If the QH is already in the schedule, no
2978 @@ -667,6 +679,7 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * h
2979 /* Always start in the inactive schedule. */
2980 DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
2981 &qh->qh_list_entry);
2984 status = schedule_periodic(hcd, qh);
2985 if ( !hcd->periodic_qh_count ) {
2986 @@ -726,6 +739,9 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t
2987 hcd->non_periodic_qh_ptr->next;
2989 DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
2991 + // If we've removed the last non-periodic entry then there are none left!
2992 + g_np_count = g_np_sent;
2994 deschedule_periodic(hcd, qh);
2995 hcd->periodic_qh_count--;
2996 @@ -754,6 +770,24 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_h
2997 int sched_next_periodic_split)
2999 if (dwc_qh_is_non_per(qh)) {
3001 + dwc_otg_qh_t *qh_tmp;
3002 + dwc_list_link_t *qh_list;
3003 + DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive)
3005 + qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry);
3009 + * FIQ is being disabled because this one nevers gets a np_count increment
3010 + * This is still not absolutely correct, but it should fix itself with
3011 + * just an unnecessary extra interrupt
3013 + g_np_sent = g_np_count;
3018 dwc_otg_hcd_qh_remove(hcd, qh);
3019 if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
3020 /* Add back to inactive non-periodic schedule. */
3021 @@ -767,6 +801,7 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_h
3022 if (sched_next_periodic_split) {
3024 qh->sched_frame = frame_number;
3026 if (dwc_frame_num_le(frame_number,
3028 (qh->start_split_frame,
3029 @@ -815,6 +850,11 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_h
3030 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
3031 &qh->qh_list_entry);
3033 + if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame))
3035 + g_next_sched_frame = qh->sched_frame;
3039 (&hcd->periodic_sched_inactive,
3040 &qh->qh_list_entry);
3041 @@ -879,6 +919,7 @@ void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t
3042 * QH to place the QTD into. If it does not find a QH, then it will create a
3043 * new QH. If the QH to which the QTD is added is not currently scheduled, it
3044 * is placed into the proper schedule based on its EP type.
3045 + * HCD lock must be held and interrupts must be disabled on entry
3047 * @param[in] qtd The QTD to add
3048 * @param[in] hcd The DWC HCD structure
3049 @@ -891,8 +932,6 @@ int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t *
3050 dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)
3053 - dwc_irqflags_t flags;
3055 dwc_otg_hcd_urb_t *urb = qtd->urb;
3058 @@ -902,18 +941,16 @@ int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t *
3060 *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);
3063 + retval = -DWC_E_NO_MEMORY;
3067 - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
3068 retval = dwc_otg_hcd_qh_add(hcd, *qh);
3070 DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
3074 - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
3080 +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
3082 +#include "dwc_otg_regs.h"
3083 +#include "dwc_otg_dbg.h"
3085 +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name)
3087 + DWC_DEBUGPL(DBG_USER, "*** Debugging from within the %s function: ***\n"
3088 + "curmode: %1i Modemismatch: %1i otgintr: %1i sofintr: %1i\n"
3089 + "rxstsqlvl: %1i nptxfempty : %1i ginnakeff: %1i goutnakeff: %1i\n"
3090 + "ulpickint: %1i i2cintr: %1i erlysuspend:%1i usbsuspend: %1i\n"
3091 + "usbreset: %1i enumdone: %1i isooutdrop: %1i eopframe: %1i\n"
3092 + "restoredone: %1i epmismatch: %1i inepint: %1i outepintr: %1i\n"
3093 + "incomplisoin:%1i incomplisoout:%1i fetsusp: %1i resetdet: %1i\n"
3094 + "portintr: %1i hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i\n"
3095 + "conidstschng:%1i disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
3097 + gintsts.b.curmode,
3098 + gintsts.b.modemismatch,
3099 + gintsts.b.otgintr,
3100 + gintsts.b.sofintr,
3101 + gintsts.b.rxstsqlvl,
3102 + gintsts.b.nptxfempty,
3103 + gintsts.b.ginnakeff,
3104 + gintsts.b.goutnakeff,
3105 + gintsts.b.ulpickint,
3106 + gintsts.b.i2cintr,
3107 + gintsts.b.erlysuspend,
3108 + gintsts.b.usbsuspend,
3109 + gintsts.b.usbreset,
3110 + gintsts.b.enumdone,
3111 + gintsts.b.isooutdrop,
3112 + gintsts.b.eopframe,
3113 + gintsts.b.restoredone,
3114 + gintsts.b.epmismatch,
3115 + gintsts.b.inepint,
3116 + gintsts.b.outepintr,
3117 + gintsts.b.incomplisoin,
3118 + gintsts.b.incomplisoout,
3119 + gintsts.b.fetsusp,
3120 + gintsts.b.resetdet,
3121 + gintsts.b.portintr,
3123 + gintsts.b.ptxfempty,
3124 + gintsts.b.lpmtranrcvd,
3125 + gintsts.b.conidstschng,
3126 + gintsts.b.disconnect,
3127 + gintsts.b.sessreqintr,
3128 + gintsts.b.wkupintr);
3132 +void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name)
3134 + DWC_DEBUGPL(DBG_USER, "Interrupt Mask status (called from %s) :\n"
3135 + "modemismatch: %1i otgintr: %1i sofintr: %1i rxstsqlvl: %1i\n"
3136 + "nptxfempty: %1i ginnakeff: %1i goutnakeff: %1i ulpickint: %1i\n"
3137 + "i2cintr: %1i erlysuspend:%1i usbsuspend: %1i usbreset: %1i\n"
3138 + "enumdone: %1i isooutdrop: %1i eopframe: %1i restoredone: %1i\n"
3139 + "epmismatch: %1i inepintr: %1i outepintr: %1i incomplisoin:%1i\n"
3140 + "incomplisoout:%1i fetsusp: %1i resetdet: %1i portintr: %1i\n"
3141 + "hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i conidstschng:%1i\n"
3142 + "disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
3144 + gintmsk.b.modemismatch,
3145 + gintmsk.b.otgintr,
3146 + gintmsk.b.sofintr,
3147 + gintmsk.b.rxstsqlvl,
3148 + gintmsk.b.nptxfempty,
3149 + gintmsk.b.ginnakeff,
3150 + gintmsk.b.goutnakeff,
3151 + gintmsk.b.ulpickint,
3152 + gintmsk.b.i2cintr,
3153 + gintmsk.b.erlysuspend,
3154 + gintmsk.b.usbsuspend,
3155 + gintmsk.b.usbreset,
3156 + gintmsk.b.enumdone,
3157 + gintmsk.b.isooutdrop,
3158 + gintmsk.b.eopframe,
3159 + gintmsk.b.restoredone,
3160 + gintmsk.b.epmismatch,
3161 + gintmsk.b.inepintr,
3162 + gintmsk.b.outepintr,
3163 + gintmsk.b.incomplisoin,
3164 + gintmsk.b.incomplisoout,
3165 + gintmsk.b.fetsusp,
3166 + gintmsk.b.resetdet,
3167 + gintmsk.b.portintr,
3169 + gintmsk.b.ptxfempty,
3170 + gintmsk.b.lpmtranrcvd,
3171 + gintmsk.b.conidstschng,
3172 + gintmsk.b.disconnect,
3173 + gintmsk.b.sessreqintr,
3174 + gintmsk.b.wkupintr);
3178 +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name)
3180 + DWC_DEBUGPL(DBG_USER, "otg int register (from %s function):\n"
3181 + "sesenddet:%1i sesreqsucstschung:%2i hstnegsucstschng:%1i\n"
3182 + "hstnegdet:%1i adevtoutchng: %2i debdone: %1i\n"
3185 + gotgint.b.sesenddet,
3186 + gotgint.b.sesreqsucstschng,
3187 + gotgint.b.hstnegsucstschng,
3188 + gotgint.b.hstnegdet,
3189 + gotgint.b.adevtoutchng,
3190 + gotgint.b.debdone,
3196 +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
3198 +#ifndef __DWC_OTG_MPHI_FIX_H__
3199 +#define __DWC_OTG_MPHI_FIX_H__
3200 +#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_))
3201 +#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_))
3204 + volatile void* base;
3205 + volatile void* ctrl;
3206 + volatile void* outdda;
3207 + volatile void* outddb;
3208 + volatile void* intstat;
3211 +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name);
3212 +void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name);
3213 +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);
3215 +extern gintsts_data_t gintsts_saved;
3218 +#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__)
3219 +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__)
3220 +#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__)
3223 +#define DWC_DBG_PRINT_CORE_INT(_arg_)
3224 +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_)
3225 +#define DWC_DBG_PRINT_OTG_INT(_arg_)
3230 + FIQDBG_SCHED = (1 << 0),
3231 + FIQDBG_INT = (1 << 1),
3232 + FIQDBG_ERR = (1 << 2),
3233 + FIQDBG_PORTHUB = (1 << 3),
3236 +void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...);
3238 +#define fiq_print _fiq_print
3240 +#define fiq_print(x, y, ...)
3243 +extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable;
3246 --- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
3247 +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
3248 @@ -97,6 +97,9 @@ typedef struct os_dependent {
3249 /** Register offset for Diagnostic API */
3250 uint32_t reg_offset;
3252 + /** Base address for MPHI peripheral */
3256 struct lm_device *lmdev;
3257 #elif defined(PCI_INTERFACE)
3258 --- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
3259 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
3260 @@ -4276,7 +4276,7 @@ do { \
3261 && (pcd->ep0state == EP0_OUT_DATA_PHASE))
3262 status.d32 = core_if->dev_if->out_desc_addr->status.d32;
3263 if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
3264 - status.d32 = status.d32 = core_if->dev_if->
3265 + status.d32 = core_if->dev_if->
3266 out_desc_addr->status.d32;