brcm2708: update to v3.18
[openwrt/staging/wigyori.git] / target / linux / brcm2708 / patches-3.18 / 0025-Add-FIQ-patch-to-dwc_otg-driver.-Enable-with-dwc_otg.patch
1 From a29a51d9320d44124fe13457c45663d3051a9452 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 025/114] Add FIQ patch to dwc_otg driver. Enable with
5 dwc_otg.fiq_fix_enable=1. Should give about 10% more ARM performance. Thanks
6 to Gordon and Costas
7
8 Avoid dynamic memory allocation for channel lock in USB driver. Thanks ddv2005.
9
10 Add NAK holdoff scheme. Enabled by default, disable with dwc_otg.nak_holdoff_enable=0. Thanks gsh
11
12 Make sure we wait for the reset to finish
13
14 dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent kernel
15 memory corruption, escalating to OOPS under high USB load.
16
17 dwc_otg: Fix unsafe access of QTD during URB enqueue
18
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.
25
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).
28
29 dwc_otg: Fix incorrect URB allocation error handling
30
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.
34
35 dwc_otg: fix potential use-after-free case in interrupt handler
36
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
43 0x00.
44
45 dwc_otg: add handling of SPLIT transaction data toggle errors
46
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).
52
53 dwc_otg: implement tasklet for returning URBs to usbcore hcd layer
54
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.
62
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.
67
68 dwc_otg: fix NAK holdoff and allow on split transactions only
69
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.
75
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.
80
81 dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held in completion handler
82
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).
86
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
89 before doing so.
90
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
95 eliminated.
96
97 USB fix using a FIQ to implement split transactions
98
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
102
103 dwc_otg: fix device attributes and avoid kernel warnings on boot
104
105 dcw_otg: avoid logging function that can cause panics
106
107 See: https://github.com/raspberrypi/firmware/issues/21
108 Thanks to cleverca22 for fix
109
110 dwc_otg: mask correct interrupts after transaction error recovery
111
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.
116
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.
121
122 dwc_otg: fiq: prevent FIQ thrash and incorrect state passing to IRQ
123
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.
131
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.
138
139 Fix function tracing
140
141 dwc_otg: whitespace cleanup in dwc_otg_urb_enqueue
142
143 dwc_otg: prevent OOPSes during device disconnects
144
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.
152
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
155 critical section.
156
157 dwc_otg: prevent BUG() in TT allocation if hub address is > 16
158
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.
162
163 This was hit if a hub was plugged in which enumerated as addr > 16,
164 due to previous device resets or unplugs.
165
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.
169
170 dwc_otg: make channel halts with unknown state less damaging
171
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.
175
176 Add catchall handling to treat as a transaction error and retry.
177
178 dwc_otg: fiq_split: use TTs with more granularity
179
180 This fixes certain issues with split transaction scheduling.
181
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
187 transaction buffers
188
189 This commit will mainly affect USB audio playback.
190
191 dwc_otg: fix potential sleep while atomic during urb enqueue
192
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
196 critical section.
197
198 dwc_otg: make fiq_split_enable imply fiq_fix_enable
199
200 Failing to set up the FIQ correctly would result in
201 "IRQ 32: nobody cared" errors in dmesg.
202
203 dwc_otg: prevent crashes on host port disconnects
204
205 Fix several issues resulting in crashes or inconsistent state
206 if a Model A root port was disconnected.
207
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
211 using freed memory
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)
221
222 dwc_otg: prevent leaking URBs during enqueue
223
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.
226
227 dwc_otg: Enable NAK holdoff for control split transactions
228
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.
234
235 In certain circumstances, usually while booting, this interrupt
236 storm could cause SD card timeouts.
237
238 dwc_otg: Fix for occasional lockup on boot when doing a USB reset
239
240 dwc_otg: Don't issue traffic to LS devices in FS mode
241
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.
245
246 Fix ARM architecture issue with local_irq_restore()
247
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.
250
251 Fixup arch_local_irq_restore to avoid trampling the F bit in CPSR.
252
253 Also fix some of the hacks previously implemented for previous dwc_otg
254 incarnations.
255 ---
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 | 153 ++---
262 .../usb/host/dwc_common_port/dwc_common_linux.c | 11 +
263 drivers/usb/host/dwc_common_port/dwc_list.h | 14 +-
264 drivers/usb/host/dwc_common_port/dwc_os.h | 2 +
265 drivers/usb/host/dwc_otg/Makefile | 1 +
266 drivers/usb/host/dwc_otg/dwc_otg_attr.c | 14 +-
267 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 47 +-
268 drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 1 +
269 drivers/usb/host/dwc_otg/dwc_otg_driver.c | 52 +-
270 drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 303 +++++++--
271 drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 37 +-
272 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 3 +-
273 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 5 +
274 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 705 ++++++++++++++++++++-
275 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 159 +++--
276 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 53 +-
277 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c | 113 ++++
278 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h | 48 ++
279 drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 3 +
280 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 2 +-
281 25 files changed, 1544 insertions(+), 251 deletions(-)
282 create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
283 create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
284
285 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
286 index 6283d7d..ba9c18e 100644
287 --- a/arch/arm/Kconfig
288 +++ b/arch/arm/Kconfig
289 @@ -395,6 +395,7 @@ config ARCH_BCM2708
290 select ARM_ERRATA_411920
291 select MACH_BCM2708
292 select VC4
293 + select FIQ
294 help
295 This enables support for Broadcom BCM2708 boards.
296
297 diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
298 index 3b763d6..5770408 100644
299 --- a/arch/arm/include/asm/irqflags.h
300 +++ b/arch/arm/include/asm/irqflags.h
301 @@ -145,12 +145,22 @@ static inline unsigned long arch_local_save_flags(void)
302 }
303
304 /*
305 - * restore saved IRQ & FIQ state
306 + * restore saved IRQ state
307 */
308 static inline void arch_local_irq_restore(unsigned long flags)
309 {
310 - asm volatile(
311 - " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
312 + unsigned long temp = 0;
313 + flags &= ~(1 << 6);
314 + asm volatile (
315 + " mrs %0, cpsr"
316 + : "=r" (temp)
317 + :
318 + : "memory", "cc");
319 + /* Preserve FIQ bit */
320 + temp &= (1 << 6);
321 + flags = flags | temp;
322 + asm volatile (
323 + " msr cpsr_c, %0 @ local_irq_restore"
324 :
325 : "r" (flags)
326 : "memory", "cc");
327 diff --git a/arch/arm/kernel/fiqasm.S b/arch/arm/kernel/fiqasm.S
328 index 8dd26e1..eef4847 100644
329 --- a/arch/arm/kernel/fiqasm.S
330 +++ b/arch/arm/kernel/fiqasm.S
331 @@ -47,3 +47,7 @@ ENTRY(__get_fiq_regs)
332 mov r0, r0 @ avoid hazard prior to ARMv4
333 ret lr
334 ENDPROC(__get_fiq_regs)
335 +
336 +ENTRY(__FIQ_Branch)
337 + mov pc, r8
338 +ENDPROC(__FIQ_Branch)
339 diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c
340 index ef1c8d5..96fa9b9 100644
341 --- a/arch/arm/mach-bcm2708/armctrl.c
342 +++ b/arch/arm/mach-bcm2708/armctrl.c
343 @@ -52,8 +52,12 @@ static void armctrl_mask_irq(struct irq_data *d)
344 0
345 };
346
347 - unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
348 - writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
349 + if (d->irq >= FIQ_START) {
350 + writel(0, __io_address(ARM_IRQ_FAST));
351 + } else {
352 + unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
353 + writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
354 + }
355 }
356
357 static void armctrl_unmask_irq(struct irq_data *d)
358 @@ -65,8 +69,14 @@ static void armctrl_unmask_irq(struct irq_data *d)
359 0
360 };
361
362 - unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
363 - writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
364 + if (d->irq >= FIQ_START) {
365 + unsigned int data =
366 + (unsigned int)irq_get_chip_data(d->irq) - FIQ_START;
367 + writel(0x80 | data, __io_address(ARM_IRQ_FAST));
368 + } else {
369 + unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
370 + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
371 + }
372 }
373
374 #if defined(CONFIG_PM)
375 @@ -204,5 +214,6 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start,
376 }
377
378 armctrl_pm_register(base, irq_start, resume_sources);
379 + init_FIQ(FIQ_START);
380 return 0;
381 }
382 diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c
383 index 7dd89a7f..dc59a6b 100644
384 --- a/arch/arm/mach-bcm2708/bcm2708.c
385 +++ b/arch/arm/mach-bcm2708/bcm2708.c
386 @@ -321,12 +321,32 @@ static struct resource bcm2708_usb_resources[] = {
387 .flags = IORESOURCE_MEM,
388 },
389 [1] = {
390 - .start = IRQ_USB,
391 - .end = IRQ_USB,
392 + .start = MPHI_BASE,
393 + .end = MPHI_BASE + SZ_4K - 1,
394 + .flags = IORESOURCE_MEM,
395 + },
396 + [2] = {
397 + .start = IRQ_HOSTPORT,
398 + .end = IRQ_HOSTPORT,
399 .flags = IORESOURCE_IRQ,
400 },
401 };
402
403 +bool fiq_fix_enable = true;
404 +
405 +static struct resource bcm2708_usb_resources_no_fiq_fix[] = {
406 + [0] = {
407 + .start = USB_BASE,
408 + .end = USB_BASE + SZ_128K - 1,
409 + .flags = IORESOURCE_MEM,
410 + },
411 + [1] = {
412 + .start = IRQ_USB,
413 + .end = IRQ_USB,
414 + .flags = IORESOURCE_IRQ,
415 + },
416 +};
417 +
418 static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
419
420 static struct platform_device bcm2708_usb_device = {
421 @@ -681,6 +701,11 @@ void __init bcm2708_init(void)
422 #endif
423 bcm_register_device(&bcm2708_systemtimer_device);
424 bcm_register_device(&bcm2708_fb_device);
425 + if (!fiq_fix_enable)
426 + {
427 + bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix;
428 + bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix);
429 + }
430 bcm_register_device(&bcm2708_usb_device);
431 bcm_register_device(&bcm2708_uart1_device);
432 bcm_register_device(&bcm2708_powerman_device);
433 diff --git a/arch/arm/mach-bcm2708/include/mach/irqs.h b/arch/arm/mach-bcm2708/include/mach/irqs.h
434 index 3a88a1a..45152ed 100644
435 --- a/arch/arm/mach-bcm2708/include/mach/irqs.h
436 +++ b/arch/arm/mach-bcm2708/include/mach/irqs.h
437 @@ -106,87 +106,90 @@
438 #define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1)
439 #define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2)
440
441 +#define FIQ_START HARD_IRQS
442 +
443 /*
444 * FIQ interrupts definitions are the same as the INT definitions.
445 */
446 -#define FIQ_TIMER0 INT_TIMER0
447 -#define FIQ_TIMER1 INT_TIMER1
448 -#define FIQ_TIMER2 INT_TIMER2
449 -#define FIQ_TIMER3 INT_TIMER3
450 -#define FIQ_CODEC0 INT_CODEC0
451 -#define FIQ_CODEC1 INT_CODEC1
452 -#define FIQ_CODEC2 INT_CODEC2
453 -#define FIQ_JPEG INT_JPEG
454 -#define FIQ_ISP INT_ISP
455 -#define FIQ_USB INT_USB
456 -#define FIQ_3D INT_3D
457 -#define FIQ_TRANSPOSER INT_TRANSPOSER
458 -#define FIQ_MULTICORESYNC0 INT_MULTICORESYNC0
459 -#define FIQ_MULTICORESYNC1 INT_MULTICORESYNC1
460 -#define FIQ_MULTICORESYNC2 INT_MULTICORESYNC2
461 -#define FIQ_MULTICORESYNC3 INT_MULTICORESYNC3
462 -#define FIQ_DMA0 INT_DMA0
463 -#define FIQ_DMA1 INT_DMA1
464 -#define FIQ_DMA2 INT_DMA2
465 -#define FIQ_DMA3 INT_DMA3
466 -#define FIQ_DMA4 INT_DMA4
467 -#define FIQ_DMA5 INT_DMA5
468 -#define FIQ_DMA6 INT_DMA6
469 -#define FIQ_DMA7 INT_DMA7
470 -#define FIQ_DMA8 INT_DMA8
471 -#define FIQ_DMA9 INT_DMA9
472 -#define FIQ_DMA10 INT_DMA10
473 -#define FIQ_DMA11 INT_DMA11
474 -#define FIQ_DMA12 INT_DMA12
475 -#define FIQ_AUX INT_AUX
476 -#define FIQ_ARM INT_ARM
477 -#define FIQ_VPUDMA INT_VPUDMA
478 -#define FIQ_HOSTPORT INT_HOSTPORT
479 -#define FIQ_VIDEOSCALER INT_VIDEOSCALER
480 -#define FIQ_CCP2TX INT_CCP2TX
481 -#define FIQ_SDC INT_SDC
482 -#define FIQ_DSI0 INT_DSI0
483 -#define FIQ_AVE INT_AVE
484 -#define FIQ_CAM0 INT_CAM0
485 -#define FIQ_CAM1 INT_CAM1
486 -#define FIQ_HDMI0 INT_HDMI0
487 -#define FIQ_HDMI1 INT_HDMI1
488 -#define FIQ_PIXELVALVE1 INT_PIXELVALVE1
489 -#define FIQ_I2CSPISLV INT_I2CSPISLV
490 -#define FIQ_DSI1 INT_DSI1
491 -#define FIQ_PWA0 INT_PWA0
492 -#define FIQ_PWA1 INT_PWA1
493 -#define FIQ_CPR INT_CPR
494 -#define FIQ_SMI INT_SMI
495 -#define FIQ_GPIO0 INT_GPIO0
496 -#define FIQ_GPIO1 INT_GPIO1
497 -#define FIQ_GPIO2 INT_GPIO2
498 -#define FIQ_GPIO3 INT_GPIO3
499 -#define FIQ_I2C INT_I2C
500 -#define FIQ_SPI INT_SPI
501 -#define FIQ_I2SPCM INT_I2SPCM
502 -#define FIQ_SDIO INT_SDIO
503 -#define FIQ_UART INT_UART
504 -#define FIQ_SLIMBUS INT_SLIMBUS
505 -#define FIQ_VEC INT_VEC
506 -#define FIQ_CPG INT_CPG
507 -#define FIQ_RNG INT_RNG
508 -#define FIQ_ARASANSDIO INT_ARASANSDIO
509 -#define FIQ_AVSPMON INT_AVSPMON
510 +#define FIQ_TIMER0 (FIQ_START+INTERRUPT_TIMER0)
511 +#define FIQ_TIMER1 (FIQ_START+INTERRUPT_TIMER1)
512 +#define FIQ_TIMER2 (FIQ_START+INTERRUPT_TIMER2)
513 +#define FIQ_TIMER3 (FIQ_START+INTERRUPT_TIMER3)
514 +#define FIQ_CODEC0 (FIQ_START+INTERRUPT_CODEC0)
515 +#define FIQ_CODEC1 (FIQ_START+INTERRUPT_CODEC1)
516 +#define FIQ_CODEC2 (FIQ_START+INTERRUPT_CODEC2)
517 +#define FIQ_JPEG (FIQ_START+INTERRUPT_JPEG)
518 +#define FIQ_ISP (FIQ_START+INTERRUPT_ISP)
519 +#define FIQ_USB (FIQ_START+INTERRUPT_USB)
520 +#define FIQ_3D (FIQ_START+INTERRUPT_3D)
521 +#define FIQ_TRANSPOSER (FIQ_START+INTERRUPT_TRANSPOSER)
522 +#define FIQ_MULTICORESYNC0 (FIQ_START+INTERRUPT_MULTICORESYNC0)
523 +#define FIQ_MULTICORESYNC1 (FIQ_START+INTERRUPT_MULTICORESYNC1)
524 +#define FIQ_MULTICORESYNC2 (FIQ_START+INTERRUPT_MULTICORESYNC2)
525 +#define FIQ_MULTICORESYNC3 (FIQ_START+INTERRUPT_MULTICORESYNC3)
526 +#define FIQ_DMA0 (FIQ_START+INTERRUPT_DMA0)
527 +#define FIQ_DMA1 (FIQ_START+INTERRUPT_DMA1)
528 +#define FIQ_DMA2 (FIQ_START+INTERRUPT_DMA2)
529 +#define FIQ_DMA3 (FIQ_START+INTERRUPT_DMA3)
530 +#define FIQ_DMA4 (FIQ_START+INTERRUPT_DMA4)
531 +#define FIQ_DMA5 (FIQ_START+INTERRUPT_DMA5)
532 +#define FIQ_DMA6 (FIQ_START+INTERRUPT_DMA6)
533 +#define FIQ_DMA7 (FIQ_START+INTERRUPT_DMA7)
534 +#define FIQ_DMA8 (FIQ_START+INTERRUPT_DMA8)
535 +#define FIQ_DMA9 (FIQ_START+INTERRUPT_DMA9)
536 +#define FIQ_DMA10 (FIQ_START+INTERRUPT_DMA10)
537 +#define FIQ_DMA11 (FIQ_START+INTERRUPT_DMA11)
538 +#define FIQ_DMA12 (FIQ_START+INTERRUPT_DMA12)
539 +#define FIQ_AUX (FIQ_START+INTERRUPT_AUX)
540 +#define FIQ_ARM (FIQ_START+INTERRUPT_ARM)
541 +#define FIQ_VPUDMA (FIQ_START+INTERRUPT_VPUDMA)
542 +#define FIQ_HOSTPORT (FIQ_START+INTERRUPT_HOSTPORT)
543 +#define FIQ_VIDEOSCALER (FIQ_START+INTERRUPT_VIDEOSCALER)
544 +#define FIQ_CCP2TX (FIQ_START+INTERRUPT_CCP2TX)
545 +#define FIQ_SDC (FIQ_START+INTERRUPT_SDC)
546 +#define FIQ_DSI0 (FIQ_START+INTERRUPT_DSI0)
547 +#define FIQ_AVE (FIQ_START+INTERRUPT_AVE)
548 +#define FIQ_CAM0 (FIQ_START+INTERRUPT_CAM0)
549 +#define FIQ_CAM1 (FIQ_START+INTERRUPT_CAM1)
550 +#define FIQ_HDMI0 (FIQ_START+INTERRUPT_HDMI0)
551 +#define FIQ_HDMI1 (FIQ_START+INTERRUPT_HDMI1)
552 +#define FIQ_PIXELVALVE1 (FIQ_START+INTERRUPT_PIXELVALVE1)
553 +#define FIQ_I2CSPISLV (FIQ_START+INTERRUPT_I2CSPISLV)
554 +#define FIQ_DSI1 (FIQ_START+INTERRUPT_DSI1)
555 +#define FIQ_PWA0 (FIQ_START+INTERRUPT_PWA0)
556 +#define FIQ_PWA1 (FIQ_START+INTERRUPT_PWA1)
557 +#define FIQ_CPR (FIQ_START+INTERRUPT_CPR)
558 +#define FIQ_SMI (FIQ_START+INTERRUPT_SMI)
559 +#define FIQ_GPIO0 (FIQ_START+INTERRUPT_GPIO0)
560 +#define FIQ_GPIO1 (FIQ_START+INTERRUPT_GPIO1)
561 +#define FIQ_GPIO2 (FIQ_START+INTERRUPT_GPIO2)
562 +#define FIQ_GPIO3 (FIQ_START+INTERRUPT_GPIO3)
563 +#define FIQ_I2C (FIQ_START+INTERRUPT_I2C)
564 +#define FIQ_SPI (FIQ_START+INTERRUPT_SPI)
565 +#define FIQ_I2SPCM (FIQ_START+INTERRUPT_I2SPCM)
566 +#define FIQ_SDIO (FIQ_START+INTERRUPT_SDIO)
567 +#define FIQ_UART (FIQ_START+INTERRUPT_UART)
568 +#define FIQ_SLIMBUS (FIQ_START+INTERRUPT_SLIMBUS)
569 +#define FIQ_VEC (FIQ_START+INTERRUPT_VEC)
570 +#define FIQ_CPG (FIQ_START+INTERRUPT_CPG)
571 +#define FIQ_RNG (FIQ_START+INTERRUPT_RNG)
572 +#define FIQ_ARASANSDIO (FIQ_START+INTERRUPT_ARASANSDIO)
573 +#define FIQ_AVSPMON (FIQ_START+INTERRUPT_AVSPMON)
574
575 -#define FIQ_ARM_TIMER INT_ARM_TIMER
576 -#define FIQ_ARM_MAILBOX INT_ARM_MAILBOX
577 -#define FIQ_ARM_DOORBELL_0 INT_ARM_DOORBELL_0
578 -#define FIQ_ARM_DOORBELL_1 INT_ARM_DOORBELL_1
579 -#define FIQ_VPU0_HALTED INT_VPU0_HALTED
580 -#define FIQ_VPU1_HALTED INT_VPU1_HALTED
581 -#define FIQ_ILLEGAL_TYPE0 INT_ILLEGAL_TYPE0
582 -#define FIQ_ILLEGAL_TYPE1 INT_ILLEGAL_TYPE1
583 -#define FIQ_PENDING1 INT_PENDING1
584 -#define FIQ_PENDING2 INT_PENDING2
585 +#define FIQ_ARM_TIMER (FIQ_START+INTERRUPT_ARM_TIMER)
586 +#define FIQ_ARM_MAILBOX (FIQ_START+INTERRUPT_ARM_MAILBOX)
587 +#define FIQ_ARM_DOORBELL_0 (FIQ_START+INTERRUPT_ARM_DOORBELL_0)
588 +#define FIQ_ARM_DOORBELL_1 (FIQ_START+INTERRUPT_ARM_DOORBELL_1)
589 +#define FIQ_VPU0_HALTED (FIQ_START+INTERRUPT_VPU0_HALTED)
590 +#define FIQ_VPU1_HALTED (FIQ_START+INTERRUPT_VPU1_HALTED)
591 +#define FIQ_ILLEGAL_TYPE0 (FIQ_START+INTERRUPT_ILLEGAL_TYPE0)
592 +#define FIQ_ILLEGAL_TYPE1 (FIQ_START+INTERRUPT_ILLEGAL_TYPE1)
593 +#define FIQ_PENDING1 (FIQ_START+INTERRUPT_PENDING1)
594 +#define FIQ_PENDING2 (FIQ_START+INTERRUPT_PENDING2)
595
596 #define HARD_IRQS (64 + 21)
597 -#define GPIO_IRQ_START (HARD_IRQS)
598 +#define FIQ_IRQS (64 + 21)
599 +#define GPIO_IRQ_START (HARD_IRQS + FIQ_IRQS)
600 #define GPIO_IRQS (32*5)
601 #define SPARE_ALLOC_IRQS 64
602 #define BCM2708_ALLOC_IRQS (HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_ALLOC_IRQS)
603 diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
604 index 1668f10..5c50a8b 100644
605 --- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c
606 +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
607 @@ -580,7 +580,13 @@ void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
608
609 void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
610 {
611 + unsigned long flags;
612 +
613 + local_irq_save(flags);
614 + local_fiq_disable();
615 writel((readl(reg) & ~clear_mask) | set_mask, reg);
616 + local_fiq_enable();
617 + local_irq_restore(flags);
618 }
619
620 #if 0
621 @@ -995,6 +1001,11 @@ void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
622 tasklet_schedule(&task->t);
623 }
624
625 +void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task)
626 +{
627 + tasklet_hi_schedule(&task->t);
628 +}
629 +
630
631 /* workqueues
632 - run in process context (can sleep)
633 diff --git a/drivers/usb/host/dwc_common_port/dwc_list.h b/drivers/usb/host/dwc_common_port/dwc_list.h
634 index 89cc325..4ce560d 100644
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))
643
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))
651
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))
659
660 /*
661 * Tail queue functions.
662 diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h
663 index 8117731..a2bbe23 100644
664 --- a/drivers/usb/host/dwc_common_port/dwc_os.h
665 +++ b/drivers/usb/host/dwc_common_port/dwc_os.h
666 @@ -982,6 +982,8 @@ extern void DWC_TASK_FREE(dwc_tasklet_t *task);
667 extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
668 #define dwc_task_schedule DWC_TASK_SCHEDULE
669
670 +extern void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task);
671 +#define dwc_task_hi_schedule DWC_TASK_HI_SCHEDULE
672
673 /** @name Timer
674 *
675 diff --git a/drivers/usb/host/dwc_otg/Makefile b/drivers/usb/host/dwc_otg/Makefile
676 index 236c47c..a56f193 100644
677 --- a/drivers/usb/host/dwc_otg/Makefile
678 +++ b/drivers/usb/host/dwc_otg/Makefile
679 @@ -36,6 +36,7 @@ dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o
680 dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o
681 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
682 dwc_otg-objs += dwc_otg_adp.o
683 +dwc_otg-objs += dwc_otg_mphi_fix.o
684 ifneq ($(CFI),)
685 dwc_otg-objs += dwc_otg_cfi.o
686 endif
687 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
688 index fab2961..9da0c92 100644
689 --- a/drivers/usb/host/dwc_otg/dwc_otg_attr.c
690 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
691 @@ -909,7 +909,7 @@ static ssize_t regdump_show(struct device *_dev,
692 return sprintf(buf, "Register Dump\n");
693 }
694
695 -DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0);
696 +DEVICE_ATTR(regdump, S_IRUGO, regdump_show, 0);
697
698 /**
699 * Dump global registers and either host or device registers (depending on the
700 @@ -920,12 +920,12 @@ static ssize_t spramdump_show(struct device *_dev,
701 {
702 dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
703
704 - dwc_otg_dump_spram(otg_dev->core_if);
705 + //dwc_otg_dump_spram(otg_dev->core_if);
706
707 return sprintf(buf, "SPRAM Dump\n");
708 }
709
710 -DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0);
711 +DEVICE_ATTR(spramdump, S_IRUGO, spramdump_show, 0);
712
713 /**
714 * Dump the current hcd state.
715 @@ -940,7 +940,7 @@ static ssize_t hcddump_show(struct device *_dev,
716 return sprintf(buf, "HCD Dump\n");
717 }
718
719 -DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0);
720 +DEVICE_ATTR(hcddump, S_IRUGO, hcddump_show, 0);
721
722 /**
723 * Dump the average frame remaining at SOF. This can be used to
724 @@ -958,7 +958,7 @@ static ssize_t hcd_frrem_show(struct device *_dev,
725 return sprintf(buf, "HCD Dump Frame Remaining\n");
726 }
727
728 -DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0);
729 +DEVICE_ATTR(hcd_frrem, S_IRUGO, hcd_frrem_show, 0);
730
731 /**
732 * Displays the time required to read the GNPTXFSIZ register many times (the
733 @@ -986,7 +986,7 @@ static ssize_t rd_reg_test_show(struct device *_dev,
734 RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
735 }
736
737 -DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0);
738 +DEVICE_ATTR(rd_reg_test, S_IRUGO, rd_reg_test_show, 0);
739
740 /**
741 * Displays the time required to write the GNPTXFSIZ register many times (the
742 @@ -1014,7 +1014,7 @@ static ssize_t wr_reg_test_show(struct device *_dev,
743 RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
744 }
745
746 -DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0);
747 +DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0);
748
749 #ifdef CONFIG_USB_DWC_OTG_LPM
750
751 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
752 index 59fc862..2f8b3bd 100644
753 --- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
754 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
755 @@ -45,6 +45,7 @@
756 #include "dwc_otg_driver.h"
757 #include "dwc_otg_pcd.h"
758 #include "dwc_otg_hcd.h"
759 +#include "dwc_otg_mphi_fix.h"
760
761 #ifdef DEBUG
762 inline const char *op_state_str(dwc_otg_core_if_t * core_if)
763 @@ -1318,7 +1319,7 @@ static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
764 /**
765 * This function returns the Core Interrupt register.
766 */
767 -static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
768 +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk)
769 {
770 gahbcfg_data_t gahbcfg = {.d32 = 0 };
771 gintsts_data_t gintsts;
772 @@ -1335,26 +1336,45 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
773 gintmsk_common.b.lpmtranrcvd = 1;
774 #endif
775 gintmsk_common.b.restoredone = 1;
776 - /** @todo: The port interrupt occurs while in device
777 - * mode. Added code to CIL to clear the interrupt for now!
778 - */
779 - gintmsk_common.b.portintr = 1;
780 -
781 + if(dwc_otg_is_device_mode(core_if))
782 + {
783 + /** @todo: The port interrupt occurs while in device
784 + * mode. Added code to CIL to clear the interrupt for now!
785 + */
786 + gintmsk_common.b.portintr = 1;
787 + }
788 gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
789 gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
790 + {
791 + unsigned long flags;
792 +
793 + // Re-enable the saved interrupts
794 + local_irq_save(flags);
795 + local_fiq_disable();
796 + gintmsk.d32 |= gintmsk_common.d32;
797 + gintsts_saved.d32 &= ~gintmsk_common.d32;
798 + reenable_gintmsk->d32 = gintmsk.d32;
799 + local_irq_restore(flags);
800 + }
801 +
802 gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
803
804 #ifdef DEBUG
805 /* if any common interrupts set */
806 if (gintsts.d32 & gintmsk_common.d32) {
807 - DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n",
808 + DWC_DEBUGPL(DBG_ANY, "common_intr: gintsts=%08x gintmsk=%08x\n",
809 gintsts.d32, gintmsk.d32);
810 }
811 #endif
812 - if (gahbcfg.b.glblintrmsk)
813 + if (!fiq_fix_enable){
814 + if (gahbcfg.b.glblintrmsk)
815 + return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
816 + else
817 + return 0;
818 + }
819 + else {
820 return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
821 - else
822 - return 0;
823 + }
824
825 }
826
827 @@ -1386,6 +1406,7 @@ int32_t dwc_otg_handle_common_intr(void *dev)
828 {
829 int retval = 0;
830 gintsts_data_t gintsts;
831 + gintmsk_data_t reenable_gintmsk;
832 gpwrdn_data_t gpwrdn = {.d32 = 0 };
833 dwc_otg_device_t *otg_dev = dev;
834 dwc_otg_core_if_t *core_if = otg_dev->core_if;
835 @@ -1407,7 +1428,7 @@ int32_t dwc_otg_handle_common_intr(void *dev)
836 }
837
838 if (core_if->hibernation_suspend <= 0) {
839 - gintsts.d32 = dwc_otg_read_common_intr(core_if);
840 + gintsts.d32 = dwc_otg_read_common_intr(core_if, &reenable_gintmsk);
841
842 if (gintsts.b.modemismatch) {
843 retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
844 @@ -1504,8 +1525,12 @@ int32_t dwc_otg_handle_common_intr(void *dev)
845 gintsts.b.portintr = 1;
846 DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
847 retval |= 1;
848 + reenable_gintmsk.b.portintr = 1;
849
850 }
851 +
852 + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, reenable_gintmsk.d32);
853 +
854 } else {
855 DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
856
857 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
858 index 8900318..ccc24e0 100644
859 --- a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
860 +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
861 @@ -49,6 +49,7 @@ static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)
862 return old;
863 }
864
865 +#define DBG_USER (0x1)
866 /** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
867 #define DBG_CIL (0x2)
868 /** When debug level has the DBG_CILV bit set, display CIL Verbose debug
869 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
870 index ac2c846..f06c3d22 100644
871 --- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
872 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
873 @@ -64,6 +64,8 @@ bool microframe_schedule=true;
874
875 static const char dwc_driver_name[] = "dwc_otg";
876
877 +extern void* dummy_send;
878 +
879 extern int pcd_init(
880 #ifdef LM_INTERFACE
881 struct lm_device *_dev
882 @@ -238,6 +240,14 @@ static struct dwc_otg_driver_module_params dwc_otg_module_params = {
883 .adp_enable = -1,
884 };
885
886 +//Global variable to switch the fiq fix on or off (declared in bcm2708.c)
887 +extern bool fiq_fix_enable;
888 +// Global variable to enable the split transaction fix
889 +bool fiq_split_enable = true;
890 +//Global variable to switch the nak holdoff on or off
891 +bool nak_holdoff_enable = true;
892 +
893 +
894 /**
895 * This function shows the Driver Version.
896 */
897 @@ -779,17 +789,33 @@ static int dwc_otg_driver_probe(
898 _dev->resource->start,
899 _dev->resource->end - _dev->resource->start + 1);
900 #if 1
901 - if (!request_mem_region(_dev->resource->start,
902 - _dev->resource->end - _dev->resource->start + 1,
903 + if (!request_mem_region(_dev->resource[0].start,
904 + _dev->resource[0].end - _dev->resource[0].start + 1,
905 "dwc_otg")) {
906 dev_dbg(&_dev->dev, "error reserving mapped memory\n");
907 retval = -EFAULT;
908 goto fail;
909 }
910
911 - dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
912 - _dev->resource->end -
913 - _dev->resource->start+1);
914 + dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start,
915 + _dev->resource[0].end -
916 + _dev->resource[0].start+1);
917 + if (fiq_fix_enable)
918 + {
919 + if (!request_mem_region(_dev->resource[1].start,
920 + _dev->resource[1].end - _dev->resource[1].start + 1,
921 + "dwc_otg")) {
922 + dev_dbg(&_dev->dev, "error reserving mapped memory\n");
923 + retval = -EFAULT;
924 + goto fail;
925 + }
926 +
927 + dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
928 + _dev->resource[1].end -
929 + _dev->resource[1].start + 1);
930 + dummy_send = (void *) kmalloc(16, GFP_ATOMIC);
931 + }
932 +
933 #else
934 {
935 struct map_desc desc = {
936 @@ -1044,6 +1070,12 @@ static int __init dwc_otg_driver_init(void)
937 int retval = 0;
938 int error;
939 struct device_driver *drv;
940 +
941 + if(fiq_split_enable && !fiq_fix_enable) {
942 + printk(KERN_WARNING "dwc_otg: fiq_split_enable was set without fiq_fix_enable! Correcting.\n");
943 + fiq_fix_enable = 1;
944 + }
945 +
946 printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
947 DWC_DRIVER_VERSION,
948 #ifdef LM_INTERFACE
949 @@ -1063,6 +1095,9 @@ static int __init dwc_otg_driver_init(void)
950 printk(KERN_ERR "%s retval=%d\n", __func__, retval);
951 return retval;
952 }
953 + printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");
954 + printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled");
955 + printk(KERN_DEBUG "dwc_otg: FIQ split fix %s\n", fiq_split_enable ? "enabled":"disabled");
956
957 error = driver_create_file(drv, &driver_attr_version);
958 #ifdef DEBUG
959 @@ -1343,6 +1378,13 @@ MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");
960 module_param(microframe_schedule, bool, 0444);
961 MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
962
963 +module_param(fiq_fix_enable, bool, 0444);
964 +MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");
965 +module_param(nak_holdoff_enable, bool, 0444);
966 +MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff");
967 +module_param(fiq_split_enable, bool, 0444);
968 +MODULE_PARM_DESC(fiq_split_enable, "Enable the FIQ fix on split transactions");
969 +
970 /** @page "Module Parameters"
971 *
972 * The following parameters may be specified when starting the module.
973 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
974 index 1e89549..986d361 100644
975 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
976 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
977 @@ -40,10 +40,14 @@
978 * header file.
979 */
980
981 +#include <linux/usb.h>
982 +#include <linux/usb/hcd.h>
983 +
984 #include "dwc_otg_hcd.h"
985 #include "dwc_otg_regs.h"
986 +#include "dwc_otg_mphi_fix.h"
987
988 -extern bool microframe_schedule;
989 +extern bool microframe_schedule, nak_holdoff_enable;
990
991 //#define DEBUG_HOST_CHANNELS
992 #ifdef DEBUG_HOST_CHANNELS
993 @@ -53,6 +57,13 @@ static int last_sel_trans_num_avail_hc_at_start = 0;
994 static int last_sel_trans_num_avail_hc_at_end = 0;
995 #endif /* DEBUG_HOST_CHANNELS */
996
997 +extern int g_next_sched_frame, g_np_count, g_np_sent;
998 +
999 +extern haint_data_t haint_saved;
1000 +extern hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
1001 +extern hcint_data_t hcint_saved[MAX_EPS_CHANNELS];
1002 +extern gintsts_data_t ginsts_saved;
1003 +
1004 dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
1005 {
1006 return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
1007 @@ -162,31 +173,43 @@ static void del_timers(dwc_otg_hcd_t * hcd)
1008
1009 /**
1010 * Processes all the URBs in a single list of QHs. Completes them with
1011 - * -ETIMEDOUT and frees the QTD.
1012 + * -ESHUTDOWN and frees the QTD.
1013 */
1014 static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
1015 {
1016 - dwc_list_link_t *qh_item;
1017 + dwc_list_link_t *qh_item, *qh_tmp;
1018 dwc_otg_qh_t *qh;
1019 dwc_otg_qtd_t *qtd, *qtd_tmp;
1020
1021 - DWC_LIST_FOREACH(qh_item, qh_list) {
1022 + DWC_LIST_FOREACH_SAFE(qh_item, qh_tmp, qh_list) {
1023 qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
1024 DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
1025 &qh->qtd_list, qtd_list_entry) {
1026 qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
1027 if (qtd->urb != NULL) {
1028 hcd->fops->complete(hcd, qtd->urb->priv,
1029 - qtd->urb, -DWC_E_TIMEOUT);
1030 + qtd->urb, -DWC_E_SHUTDOWN);
1031 dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
1032 }
1033
1034 }
1035 + if(qh->channel) {
1036 + /* Using hcchar.chen == 1 is not a reliable test.
1037 + * It is possible that the channel has already halted
1038 + * but not yet been through the IRQ handler.
1039 + */
1040 + dwc_otg_hc_halt(hcd->core_if, qh->channel,
1041 + DWC_OTG_HC_XFER_URB_DEQUEUE);
1042 + if(microframe_schedule)
1043 + hcd->available_host_channels++;
1044 + qh->channel = NULL;
1045 + }
1046 + dwc_otg_hcd_qh_remove(hcd, qh);
1047 }
1048 }
1049
1050 /**
1051 - * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
1052 + * Responds with an error status of ESHUTDOWN to all URBs in the non-periodic
1053 * and periodic schedules. The QTD associated with each URB is removed from
1054 * the schedule and freed. This function may be called when a disconnect is
1055 * detected or when the HCD is being stopped.
1056 @@ -272,7 +295,8 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p)
1057 */
1058 dwc_otg_hcd->flags.b.port_connect_status_change = 1;
1059 dwc_otg_hcd->flags.b.port_connect_status = 0;
1060 -
1061 + if(fiq_fix_enable)
1062 + local_fiq_disable();
1063 /*
1064 * Shutdown any transfers in process by clearing the Tx FIFO Empty
1065 * interrupt mask and status bits and disabling subsequent host
1066 @@ -368,8 +392,22 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p)
1067 channel->qh = NULL;
1068 }
1069 }
1070 + if(fiq_split_enable) {
1071 + for(i=0; i < 128; i++) {
1072 + dwc_otg_hcd->hub_port[i] = 0;
1073 + }
1074 + haint_saved.d32 = 0;
1075 + for(i=0; i < MAX_EPS_CHANNELS; i++) {
1076 + hcint_saved[i].d32 = 0;
1077 + hcintmsk_saved[i].d32 = 0;
1078 + }
1079 + }
1080 +
1081 }
1082
1083 + if(fiq_fix_enable)
1084 + local_fiq_enable();
1085 +
1086 if (dwc_otg_hcd->fops->disconnect) {
1087 dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
1088 }
1089 @@ -407,6 +445,7 @@ static int dwc_otg_hcd_sleep_cb(void *p)
1090 }
1091 #endif
1092
1093 +
1094 /**
1095 * HCD Callback function for Remote Wakeup.
1096 *
1097 @@ -457,10 +496,12 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
1098 dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
1099 int atomic_alloc)
1100 {
1101 - dwc_irqflags_t flags;
1102 int retval = 0;
1103 + uint8_t needs_scheduling = 0;
1104 + dwc_otg_transaction_type_e tr_type;
1105 dwc_otg_qtd_t *qtd;
1106 gintmsk_data_t intr_mask = {.d32 = 0 };
1107 + hprt0_data_t hprt0 = { .d32 = 0 };
1108
1109 #ifdef DEBUG /* integrity checks (Broadcom) */
1110 if (NULL == hcd->core_if) {
1111 @@ -475,6 +516,16 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
1112 return -DWC_E_NO_DEVICE;
1113 }
1114
1115 + /* Some core configurations cannot support LS traffic on a FS root port */
1116 + if ((hcd->fops->speed(hcd, dwc_otg_urb->priv) == USB_SPEED_LOW) &&
1117 + (hcd->core_if->hwcfg2.b.fs_phy_type == 1) &&
1118 + (hcd->core_if->hwcfg2.b.hs_phy_type == 1)) {
1119 + hprt0.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
1120 + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_FULL_SPEED) {
1121 + return -DWC_E_NO_DEVICE;
1122 + }
1123 + }
1124 +
1125 qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
1126 if (qtd == NULL) {
1127 DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
1128 @@ -490,32 +541,27 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
1129 return -DWC_E_NO_MEMORY;
1130 }
1131 #endif
1132 - retval =
1133 - dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
1134 + intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
1135 + if(!intr_mask.b.sofintr) needs_scheduling = 1;
1136 + if((((dwc_otg_qh_t *)ep_handle)->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP))
1137 + /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
1138 + needs_scheduling = 0;
1139 +
1140 + retval = dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
1141 // creates a new queue in ep_handle if it doesn't exist already
1142 if (retval < 0) {
1143 DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
1144 "Error status %d\n", retval);
1145 dwc_otg_hcd_qtd_free(qtd);
1146 - } else {
1147 - qtd->qh = *ep_handle;
1148 + return retval;
1149 }
1150 - intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
1151 - if (!intr_mask.b.sofintr && retval == 0) {
1152 - dwc_otg_transaction_type_e tr_type;
1153 - if ((qtd->qh->ep_type == UE_BULK)
1154 - && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
1155 - /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
1156 - return 0;
1157 - }
1158 - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
1159 +
1160 + if(needs_scheduling) {
1161 tr_type = dwc_otg_hcd_select_transactions(hcd);
1162 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
1163 dwc_otg_hcd_queue_transactions(hcd, tr_type);
1164 }
1165 - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
1166 }
1167 -
1168 return retval;
1169 }
1170
1171 @@ -524,6 +570,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
1172 {
1173 dwc_otg_qh_t *qh;
1174 dwc_otg_qtd_t *urb_qtd;
1175 + BUG_ON(!hcd);
1176 + BUG_ON(!dwc_otg_urb);
1177
1178 #ifdef DEBUG /* integrity checks (Broadcom) */
1179
1180 @@ -540,14 +588,17 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
1181 return -DWC_E_INVALID;
1182 }
1183 urb_qtd = dwc_otg_urb->qtd;
1184 + BUG_ON(!urb_qtd);
1185 if (urb_qtd->qh == NULL) {
1186 DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
1187 return -DWC_E_INVALID;
1188 }
1189 #else
1190 urb_qtd = dwc_otg_urb->qtd;
1191 + BUG_ON(!urb_qtd);
1192 #endif
1193 qh = urb_qtd->qh;
1194 + BUG_ON(!qh);
1195 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
1196 if (urb_qtd->in_process) {
1197 dump_channel_info(hcd, qh);
1198 @@ -571,6 +622,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
1199 */
1200 dwc_otg_hc_halt(hcd->core_if, qh->channel,
1201 DWC_OTG_HC_XFER_URB_DEQUEUE);
1202 +
1203 + dwc_otg_hcd_release_port(hcd, qh);
1204 }
1205 }
1206
1207 @@ -687,6 +740,33 @@ static void reset_tasklet_func(void *data)
1208 dwc_otg_hcd->flags.b.port_reset_change = 1;
1209 }
1210
1211 +static void completion_tasklet_func(void *ptr)
1212 +{
1213 + dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) ptr;
1214 + struct urb *urb;
1215 + urb_tq_entry_t *item;
1216 + dwc_irqflags_t flags;
1217 +
1218 + /* This could just be spin_lock_irq */
1219 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
1220 + while (!DWC_TAILQ_EMPTY(&hcd->completed_urb_list)) {
1221 + item = DWC_TAILQ_FIRST(&hcd->completed_urb_list);
1222 + urb = item->urb;
1223 + DWC_TAILQ_REMOVE(&hcd->completed_urb_list, item,
1224 + urb_tq_entries);
1225 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
1226 + DWC_FREE(item);
1227 +
1228 + usb_hcd_giveback_urb(hcd->priv, urb, urb->status);
1229 +
1230 + fiq_print(FIQDBG_PORTHUB, "COMPLETE");
1231 +
1232 + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
1233 + }
1234 + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
1235 + return;
1236 +}
1237 +
1238 static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
1239 {
1240 dwc_list_link_t *item;
1241 @@ -819,12 +899,14 @@ static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
1242 } else if (dwc_otg_hcd->status_buf != NULL) {
1243 DWC_FREE(dwc_otg_hcd->status_buf);
1244 }
1245 + DWC_SPINLOCK_FREE(dwc_otg_hcd->channel_lock);
1246 DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
1247 /* Set core_if's lock pointer to NULL */
1248 dwc_otg_hcd->core_if->lock = NULL;
1249
1250 DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
1251 DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
1252 + DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
1253
1254 #ifdef DWC_DEV_SRPCAP
1255 if (dwc_otg_hcd->core_if->power_down == 2 &&
1256 @@ -874,7 +956,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
1257 DWC_LIST_INIT(&hcd->periodic_sched_ready);
1258 DWC_LIST_INIT(&hcd->periodic_sched_assigned);
1259 DWC_LIST_INIT(&hcd->periodic_sched_queued);
1260 -
1261 + DWC_TAILQ_INIT(&hcd->completed_urb_list);
1262 /*
1263 * Create a host channel descriptor for each host channel implemented
1264 * in the controller. Initialize the channel descriptor array.
1265 @@ -912,6 +994,9 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
1266
1267 /* Initialize reset tasklet. */
1268 hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
1269 +
1270 + hcd->completion_tasklet = DWC_TASK_ALLOC("completion_tasklet",
1271 + completion_tasklet_func, hcd);
1272 #ifdef DWC_DEV_SRPCAP
1273 if (hcd->core_if->power_down == 2) {
1274 /* Initialize Power on timer for Host power up in case hibernation */
1275 @@ -944,6 +1029,12 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
1276 hcd->frame_list = NULL;
1277 hcd->frame_list_dma = 0;
1278 hcd->periodic_qh_count = 0;
1279 +
1280 + DWC_MEMSET(hcd->hub_port, 0, sizeof(hcd->hub_port));
1281 +#ifdef FIQ_DEBUG
1282 + DWC_MEMSET(hcd->hub_port_alloc, -1, sizeof(hcd->hub_port_alloc));
1283 +#endif
1284 +
1285 out:
1286 return retval;
1287 }
1288 @@ -1089,7 +1180,12 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
1289 uint32_t hub_addr, port_addr;
1290 hc->do_split = 1;
1291 hc->xact_pos = qtd->isoc_split_pos;
1292 - hc->complete_split = qtd->complete_split;
1293 + /* We don't need to do complete splits anymore */
1294 + if(fiq_split_enable)
1295 + hc->complete_split = qtd->complete_split = 0;
1296 + else
1297 + hc->complete_split = qtd->complete_split;
1298 +
1299 hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
1300 hc->hub_addr = (uint8_t) hub_addr;
1301 hc->port_addr = (uint8_t) port_addr;
1302 @@ -1236,6 +1332,65 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
1303 hc->qh = qh;
1304 }
1305
1306 +/*
1307 +** Check the transaction to see if the port / hub has already been assigned for
1308 +** a split transaction
1309 +**
1310 +** Return 0 - Port is already in use
1311 +*/
1312 +int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
1313 +{
1314 + uint32_t hub_addr, port_addr;
1315 +
1316 + if(!fiq_split_enable)
1317 + return 0;
1318 +
1319 + hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
1320 +
1321 + if(hcd->hub_port[hub_addr] & (1 << port_addr))
1322 + {
1323 + fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count);
1324 +
1325 + qh->skip_count++;
1326 +
1327 + if(qh->skip_count > 40000)
1328 + {
1329 + printk_once(KERN_ERR "Error: Having to skip port allocation");
1330 + local_fiq_disable();
1331 + BUG();
1332 + return 0;
1333 + }
1334 + return 1;
1335 + }
1336 + else
1337 + {
1338 + qh->skip_count = 0;
1339 + hcd->hub_port[hub_addr] |= 1 << port_addr;
1340 + fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
1341 +#ifdef FIQ_DEBUG
1342 + hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd);
1343 +#endif
1344 + return 0;
1345 + }
1346 +}
1347 +void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
1348 +{
1349 + uint32_t hub_addr, port_addr;
1350 +
1351 + if(!fiq_split_enable)
1352 + return;
1353 +
1354 + hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
1355 +
1356 + hcd->hub_port[hub_addr] &= ~(1 << port_addr);
1357 +#ifdef FIQ_DEBUG
1358 + hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1;
1359 +#endif
1360 + fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
1361 +
1362 +}
1363 +
1364 +
1365 /**
1366 * This function selects transactions from the HCD transfer schedule and
1367 * assigns them to available host channels. It is called from HCD interrupt
1368 @@ -1249,9 +1404,10 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
1369 {
1370 dwc_list_link_t *qh_ptr;
1371 dwc_otg_qh_t *qh;
1372 + dwc_otg_qtd_t *qtd;
1373 int num_channels;
1374 dwc_irqflags_t flags;
1375 - dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
1376 + dwc_spinlock_t *channel_lock = hcd->channel_lock;
1377 dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
1378
1379 #ifdef DEBUG_SOF
1380 @@ -1269,11 +1425,29 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
1381
1382 while (qh_ptr != &hcd->periodic_sched_ready &&
1383 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1384 +
1385 + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1386 +
1387 + if(qh->do_split) {
1388 + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
1389 + if(!(qh->ep_type == UE_ISOCHRONOUS &&
1390 + (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
1391 + qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END))) {
1392 + if(dwc_otg_hcd_allocate_port(hcd, qh))
1393 + {
1394 + qh_ptr = DWC_LIST_NEXT(qh_ptr);
1395 + g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
1396 + continue;
1397 + }
1398 + }
1399 + }
1400 +
1401 if (microframe_schedule) {
1402 // Make sure we leave one channel for non periodic transactions.
1403 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
1404 if (hcd->available_host_channels <= 1) {
1405 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
1406 + if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh);
1407 break;
1408 }
1409 hcd->available_host_channels--;
1410 @@ -1294,8 +1468,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
1411 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
1412 &qh->qh_list_entry);
1413 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
1414 -
1415 - ret_val = DWC_OTG_TRANSACTION_PERIODIC;
1416 }
1417
1418 /*
1419 @@ -1310,6 +1482,31 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
1420 num_channels - hcd->periodic_channels) &&
1421 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1422
1423 + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1424 +
1425 + /*
1426 + * Check to see if this is a NAK'd retransmit, in which case ignore for retransmission
1427 + * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed
1428 + * cheeky devices that just hold off using NAKs
1429 + */
1430 + if (nak_holdoff_enable && qh->do_split) {
1431 + if (qh->nak_frame != 0xffff &&
1432 + dwc_full_frame_num(qh->nak_frame) ==
1433 + dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
1434 + /*
1435 + * Revisit: Need to avoid trampling on periodic scheduling.
1436 + * Currently we are safe because g_np_count != g_np_sent whenever we hit this,
1437 + * but if this behaviour is changed then periodic endpoints will get a slower
1438 + * polling rate.
1439 + */
1440 + g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
1441 + qh_ptr = DWC_LIST_NEXT(qh_ptr);
1442 + continue;
1443 + } else {
1444 + qh->nak_frame = 0xffff;
1445 + }
1446 + }
1447 +
1448 if (microframe_schedule) {
1449 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
1450 if (hcd->available_host_channels < 1) {
1451 @@ -1322,7 +1519,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
1452 last_sel_trans_num_nonper_scheduled++;
1453 #endif /* DEBUG_HOST_CHANNELS */
1454 }
1455 - qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1456
1457 assign_and_init_hc(hcd, qh);
1458
1459 @@ -1336,21 +1532,22 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
1460 &qh->qh_list_entry);
1461 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
1462
1463 - if (ret_val == DWC_OTG_TRANSACTION_NONE) {
1464 - ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
1465 - } else {
1466 - ret_val = DWC_OTG_TRANSACTION_ALL;
1467 - }
1468 + g_np_sent++;
1469
1470 if (!microframe_schedule)
1471 hcd->non_periodic_channels++;
1472 }
1473
1474 + if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned))
1475 + ret_val |= DWC_OTG_TRANSACTION_PERIODIC;
1476 +
1477 + if(!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active))
1478 + ret_val |= DWC_OTG_TRANSACTION_NON_PERIODIC;
1479 +
1480 +
1481 #ifdef DEBUG_HOST_CHANNELS
1482 last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
1483 #endif /* DEBUG_HOST_CHANNELS */
1484 -
1485 - DWC_SPINLOCK_FREE(channel_lock);
1486 return ret_val;
1487 }
1488
1489 @@ -1464,6 +1661,15 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd)
1490
1491 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1492
1493 + // Do not send a split start transaction any later than frame .6
1494 + // Note, we have to schedule a periodic in .5 to make it go in .6
1495 + if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
1496 + {
1497 + qh_ptr = qh_ptr->next;
1498 + g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
1499 + continue;
1500 + }
1501 +
1502 /*
1503 * Set a flag if we're queuing high-bandwidth in slave mode.
1504 * The flag prevents any halts to get into the request queue in
1505 @@ -1593,6 +1799,15 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
1506
1507 qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
1508 qh_list_entry);
1509 +
1510 + // Do not send a split start transaction any later than frame .5
1511 + // non periodic transactions will start immediately in this uframe
1512 + if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
1513 + {
1514 + g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
1515 + break;
1516 + }
1517 +
1518 status =
1519 queue_transaction(hcd, qh->channel,
1520 tx_status.b.nptxfspcavail);
1521 @@ -3118,17 +3333,13 @@ dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
1522 else
1523 dwc_otg_urb = DWC_ALLOC(size);
1524
1525 - if (NULL != dwc_otg_urb)
1526 - dwc_otg_urb->packet_count = iso_desc_count;
1527 + if (dwc_otg_urb)
1528 + dwc_otg_urb->packet_count = iso_desc_count;
1529 else {
1530 - dwc_otg_urb->packet_count = 0;
1531 - if (size != 0) {
1532 - DWC_ERROR("**** DWC OTG HCD URB alloc - "
1533 - "%salloc of %db failed\n",
1534 - atomic_alloc?"atomic ":"", size);
1535 - }
1536 - }
1537 -
1538 + DWC_ERROR("**** DWC OTG HCD URB alloc - "
1539 + "%salloc of %db failed\n",
1540 + atomic_alloc?"atomic ":"", size);
1541 + }
1542 return dwc_otg_urb;
1543 }
1544
1545 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
1546 index bb4f67a..0007fa1 100644
1547 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
1548 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
1549 @@ -168,10 +168,10 @@ typedef enum dwc_otg_control_phase {
1550
1551 /** Transaction types. */
1552 typedef enum dwc_otg_transaction_type {
1553 - DWC_OTG_TRANSACTION_NONE,
1554 - DWC_OTG_TRANSACTION_PERIODIC,
1555 - DWC_OTG_TRANSACTION_NON_PERIODIC,
1556 - DWC_OTG_TRANSACTION_ALL
1557 + DWC_OTG_TRANSACTION_NONE = 0,
1558 + DWC_OTG_TRANSACTION_PERIODIC = 1,
1559 + DWC_OTG_TRANSACTION_NON_PERIODIC = 2,
1560 + DWC_OTG_TRANSACTION_ALL = DWC_OTG_TRANSACTION_PERIODIC + DWC_OTG_TRANSACTION_NON_PERIODIC
1561 } dwc_otg_transaction_type_e;
1562
1563 struct dwc_otg_qh;
1564 @@ -321,6 +321,11 @@ typedef struct dwc_otg_qh {
1565 */
1566 uint16_t sched_frame;
1567
1568 + /*
1569 + ** Frame a NAK was received on this queue head, used to minimise NAK retransmission
1570 + */
1571 + uint16_t nak_frame;
1572 +
1573 /** (micro)frame at which last start split was initialized. */
1574 uint16_t start_split_frame;
1575
1576 @@ -365,10 +370,19 @@ typedef struct dwc_otg_qh {
1577
1578 uint16_t speed;
1579 uint16_t frame_usecs[8];
1580 +
1581 + uint32_t skip_count;
1582 } dwc_otg_qh_t;
1583
1584 DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
1585
1586 +typedef struct urb_tq_entry {
1587 + struct urb *urb;
1588 + DWC_TAILQ_ENTRY(urb_tq_entry) urb_tq_entries;
1589 +} urb_tq_entry_t;
1590 +
1591 +DWC_TAILQ_HEAD(urb_list, urb_tq_entry);
1592 +
1593 /**
1594 * This structure holds the state of the HCD, including the non-periodic and
1595 * periodic schedules.
1596 @@ -546,9 +560,12 @@ struct dwc_otg_hcd {
1597 /* Tasket to do a reset */
1598 dwc_tasklet_t *reset_tasklet;
1599
1600 + dwc_tasklet_t *completion_tasklet;
1601 + struct urb_list completed_urb_list;
1602 +
1603 /* */
1604 dwc_spinlock_t *lock;
1605 -
1606 + dwc_spinlock_t *channel_lock;
1607 /**
1608 * Private data that could be used by OS wrapper.
1609 */
1610 @@ -559,6 +576,12 @@ struct dwc_otg_hcd {
1611 /** Frame List */
1612 uint32_t *frame_list;
1613
1614 + /** Hub - Port assignment */
1615 + int hub_port[128];
1616 +#ifdef FIQ_DEBUG
1617 + int hub_port_alloc[2048];
1618 +#endif
1619 +
1620 /** Frame List DMA address */
1621 dma_addr_t frame_list_dma;
1622
1623 @@ -589,6 +612,10 @@ extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
1624 extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
1625 dwc_otg_transaction_type_e tr_type);
1626
1627 +int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh);
1628 +void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh);
1629 +
1630 +
1631 /** @} */
1632
1633 /** @name Interrupt Handler Functions */
1634 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
1635 index 274967b..ee920c4 100644
1636 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
1637 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
1638 @@ -276,7 +276,7 @@ void dump_frame_list(dwc_otg_hcd_t * hcd)
1639 static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
1640 {
1641 dwc_irqflags_t flags;
1642 - dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
1643 + dwc_spinlock_t *channel_lock = hcd->channel_lock;
1644
1645 dwc_hc_t *hc = qh->channel;
1646 if (dwc_qh_is_non_per(qh)) {
1647 @@ -306,7 +306,6 @@ static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
1648 dwc_memset(qh->desc_list, 0x00,
1649 sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
1650 }
1651 - DWC_SPINLOCK_FREE(channel_lock);
1652 }
1653
1654 /**
1655 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
1656 index 4823167..fb57db0 100644
1657 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
1658 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
1659 @@ -113,6 +113,11 @@ extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);
1660 */
1661 extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
1662
1663 +/** This function is used to handle the fast interrupt
1664 + *
1665 + */
1666 +extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void);
1667 +
1668 /**
1669 * Returns private data set by
1670 * dwc_otg_hcd_set_priv_data function.
1671 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
1672 index b41e164..64d33a5 100644
1673 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
1674 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
1675 @@ -34,6 +34,12 @@
1676
1677 #include "dwc_otg_hcd.h"
1678 #include "dwc_otg_regs.h"
1679 +#include "dwc_otg_mphi_fix.h"
1680 +
1681 +#include <linux/jiffies.h>
1682 +#include <mach/hardware.h>
1683 +#include <asm/fiq.h>
1684 +
1685
1686 extern bool microframe_schedule;
1687
1688 @@ -41,38 +47,487 @@ extern bool microframe_schedule;
1689 * This file contains the implementation of the HCD Interrupt handlers.
1690 */
1691
1692 +/*
1693 + * Some globals to communicate between the FIQ and INTERRUPT
1694 + */
1695 +
1696 +void * dummy_send;
1697 +mphi_regs_t c_mphi_regs;
1698 +volatile void *dwc_regs_base;
1699 +int fiq_done, int_done;
1700 +
1701 +gintsts_data_t gintsts_saved = {.d32 = 0};
1702 +hcint_data_t hcint_saved[MAX_EPS_CHANNELS];
1703 +hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
1704 +int split_out_xfersize[MAX_EPS_CHANNELS];
1705 +haint_data_t haint_saved;
1706 +
1707 +int g_next_sched_frame, g_np_count, g_np_sent;
1708 +static int mphi_int_count = 0 ;
1709 +
1710 +hcchar_data_t nak_hcchar;
1711 +hctsiz_data_t nak_hctsiz;
1712 +hcsplt_data_t nak_hcsplt;
1713 +int nak_count;
1714 +
1715 +int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
1716 +int split_start_frame[MAX_EPS_CHANNELS];
1717 +int queued_port[MAX_EPS_CHANNELS];
1718 +
1719 +#ifdef FIQ_DEBUG
1720 +char buffer[1000*16];
1721 +int wptr;
1722 +void notrace _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...)
1723 +{
1724 + FIQDBG_T dbg_lvl_req = FIQDBG_PORTHUB;
1725 + va_list args;
1726 + char text[17];
1727 + hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) };
1728 + unsigned long flags;
1729 +
1730 + local_irq_save(flags);
1731 + local_fiq_disable();
1732 + if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR)
1733 + {
1734 + snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937);
1735 + va_start(args, fmt);
1736 + vsnprintf(text+8, 9, fmt, args);
1737 + va_end(args);
1738 +
1739 + memcpy(buffer + wptr, text, 16);
1740 + wptr = (wptr + 16) % sizeof(buffer);
1741 + }
1742 + local_irq_restore(flags);
1743 +}
1744 +#endif
1745 +
1746 +void notrace fiq_queue_request(int channel, int odd_frame)
1747 +{
1748 + hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };
1749 + hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };
1750 + hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10) };
1751 +
1752 + if(hcsplt.b.spltena == 0)
1753 + {
1754 + fiq_print(FIQDBG_ERR, "SPLTENA ");
1755 + BUG();
1756 + }
1757 +
1758 + if(hcchar.b.epdir == 1)
1759 + {
1760 + fiq_print(FIQDBG_SCHED, "IN Ch %d", channel);
1761 + }
1762 + else
1763 + {
1764 + hctsiz.b.xfersize = 0;
1765 + fiq_print(FIQDBG_SCHED, "OUT Ch %d", channel);
1766 + }
1767 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x10), hctsiz.d32);
1768 +
1769 + hcsplt.b.compsplt = 1;
1770 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x4), hcsplt.d32);
1771 +
1772 + // Send the Split complete
1773 + hcchar.b.chen = 1;
1774 + hcchar.b.oddfrm = odd_frame ? 1 : 0;
1775 +
1776 + // Post this for transmit on the next frame for periodic or this frame for non-periodic
1777 + fiq_print(FIQDBG_SCHED, "SND_%s", odd_frame ? "ODD " : "EVEN");
1778 +
1779 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x0), hcchar.d32);
1780 +}
1781 +
1782 +static int last_sof = -1;
1783 +
1784 +/*
1785 +** Function to handle the start of frame interrupt, choose whether we need to do anything and
1786 +** therefore trigger the main interrupt
1787 +**
1788 +** returns int != 0 - interrupt has been handled
1789 +*/
1790 +int diff;
1791 +
1792 +int notrace fiq_sof_handle(hfnum_data_t hfnum)
1793 +{
1794 + int handled = 0;
1795 + int i;
1796 +
1797 + // Just check that once we're running we don't miss a SOF
1798 + /*if(last_sof != -1 && (hfnum.b.frnum != ((last_sof + 1) & 0x3fff)))
1799 + {
1800 + fiq_print(FIQDBG_ERR, "LASTSOF ");
1801 + fiq_print(FIQDBG_ERR, "%4d%d ", last_sof / 8, last_sof & 7);
1802 + fiq_print(FIQDBG_ERR, "%4d%d ", hfnum.b.frnum / 8, hfnum.b.frnum & 7);
1803 + BUG();
1804 + }*/
1805 +
1806 + // Only start remembering the last sof when the interrupt has been
1807 + // enabled (we don't check the mask to come in here...)
1808 + if(last_sof != -1 || FIQ_READ(dwc_regs_base + 0x18) & (1<<3))
1809 + last_sof = hfnum.b.frnum;
1810 +
1811 + for(i = 0; i < MAX_EPS_CHANNELS; i++)
1812 + {
1813 + if(complete_sched[i] != -1)
1814 + {
1815 + if(complete_sched[i] <= hfnum.b.frnum || (complete_sched[i] > 0x3f00 && hfnum.b.frnum < 0xf0))
1816 + {
1817 + fiq_queue_request(i, hfnum.b.frnum & 1);
1818 + complete_sched[i] = -1;
1819 + }
1820 + }
1821 +
1822 + if(complete_sched[i] != -1)
1823 + {
1824 + // This is because we've seen a split complete occur with no start...
1825 + // most likely because missed the complete 0x3fff frames ago!
1826 +
1827 + diff = (hfnum.b.frnum + 0x3fff - complete_sched[i]) & 0x3fff ;
1828 + if(diff > 32 && diff < 0x3f00)
1829 + {
1830 + fiq_print(FIQDBG_ERR, "SPLTMISS");
1831 + BUG();
1832 + }
1833 + }
1834 + }
1835 +
1836 + if(g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
1837 + {
1838 + /*
1839 + * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet
1840 + * g_next_sched_frame is the next frame we have periodic packets for
1841 + *
1842 + * if neither of these are required for this frame then just clear the interrupt
1843 + */
1844 + handled = 1;
1845 +
1846 + }
1847 +
1848 + return handled;
1849 +}
1850 +
1851 +int notrace port_id(hcsplt_data_t hcsplt)
1852 +{
1853 + return hcsplt.b.prtaddr + (hcsplt.b.hubaddr << 8);
1854 +}
1855 +
1856 +int notrace fiq_hcintr_handle(int channel, hfnum_data_t hfnum)
1857 +{
1858 + hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };
1859 + hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };
1860 + hcint_data_t hcint = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x8) };
1861 + hcintmsk_data_t hcintmsk = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0xc) };
1862 + hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10)};
1863 +
1864 + hcint_saved[channel].d32 |= hcint.d32;
1865 + hcintmsk_saved[channel].d32 = hcintmsk.d32;
1866 +
1867 + if(hcsplt.b.spltena)
1868 + {
1869 + fiq_print(FIQDBG_PORTHUB, "ph: %4x", port_id(hcsplt));
1870 + if(hcint.b.chhltd)
1871 + {
1872 + fiq_print(FIQDBG_SCHED, "CH HLT %d", channel);
1873 + fiq_print(FIQDBG_SCHED, "%08x", hcint_saved[channel]);
1874 + }
1875 + if(hcint.b.stall || hcint.b.xacterr || hcint.b.bblerr || hcint.b.frmovrun || hcint.b.datatglerr)
1876 + {
1877 + queued_port[channel] = 0;
1878 + fiq_print(FIQDBG_ERR, "CHAN ERR");
1879 + }
1880 + if(hcint.b.xfercomp)
1881 + {
1882 + // Clear the port allocation and transmit anything also on this port
1883 + queued_port[channel] = 0;
1884 + fiq_print(FIQDBG_SCHED, "XFERCOMP");
1885 + }
1886 + if(hcint.b.nak)
1887 + {
1888 + queued_port[channel] = 0;
1889 + fiq_print(FIQDBG_SCHED, "NAK");
1890 + }
1891 + if(hcint.b.ack && !hcsplt.b.compsplt)
1892 + {
1893 + int i;
1894 +
1895 + // Do not complete isochronous out transactions
1896 + if(hcchar.b.eptype == 1 && hcchar.b.epdir == 0)
1897 + {
1898 + queued_port[channel] = 0;
1899 + fiq_print(FIQDBG_SCHED, "ISOC_OUT");
1900 + }
1901 + else
1902 + {
1903 + // Make sure we check the port / hub combination that we sent this split on.
1904 + // Do not queue a second request to the same port
1905 + for(i = 0; i < MAX_EPS_CHANNELS; i++)
1906 + {
1907 + if(port_id(hcsplt) == queued_port[i])
1908 + {
1909 + fiq_print(FIQDBG_ERR, "PORTERR ");
1910 + //BUG();
1911 + }
1912 + }
1913 +
1914 + split_start_frame[channel] = (hfnum.b.frnum + 1) & ~7;
1915 +
1916 + // Note, the size of an OUT is in the start split phase, not
1917 + // the complete split
1918 + split_out_xfersize[channel] = hctsiz.b.xfersize;
1919 +
1920 + hcint_saved[channel].b.chhltd = 0;
1921 + hcint_saved[channel].b.ack = 0;
1922 +
1923 + queued_port[channel] = port_id(hcsplt);
1924 +
1925 + if(hcchar.b.eptype & 1)
1926 + {
1927 + // Send the periodic complete in the same oddness frame as the ACK went...
1928 + fiq_queue_request(channel, !(hfnum.b.frnum & 1));
1929 + // complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
1930 + }
1931 + else
1932 + {
1933 + // Schedule the split complete to occur later
1934 + complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 2);
1935 + fiq_print(FIQDBG_SCHED, "ACK%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
1936 + }
1937 + }
1938 + }
1939 + if(hcint.b.nyet)
1940 + {
1941 + fiq_print(FIQDBG_ERR, "NYETERR1");
1942 + //BUG();
1943 + // Can transmit a split complete up to uframe .0 of the next frame
1944 + if(hfnum.b.frnum <= dwc_frame_num_inc(split_start_frame[channel], 8))
1945 + {
1946 + // Send it next frame
1947 + if(hcchar.b.eptype & 1) // type 1 & 3 are interrupt & isoc
1948 + {
1949 + fiq_print(FIQDBG_SCHED, "NYT:SEND");
1950 + fiq_queue_request(channel, !(hfnum.b.frnum & 1));
1951 + }
1952 + else
1953 + {
1954 + // Schedule non-periodic access for next frame (the odd-even bit doesn't effect NP)
1955 + complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
1956 + fiq_print(FIQDBG_SCHED, "NYT%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
1957 + }
1958 + hcint_saved[channel].b.chhltd = 0;
1959 + hcint_saved[channel].b.nyet = 0;
1960 + }
1961 + else
1962 + {
1963 + queued_port[channel] = 0;
1964 + fiq_print(FIQDBG_ERR, "NYETERR2");
1965 + //BUG();
1966 + }
1967 + }
1968 + }
1969 + else
1970 + {
1971 + /*
1972 + * If we have any of NAK, ACK, Datatlgerr active on a
1973 + * non-split channel, the sole reason is to reset error
1974 + * counts for a previously broken transaction. The FIQ
1975 + * will thrash on NAK IN and ACK OUT in particular so
1976 + * handle it "once" and allow the IRQ to do the rest.
1977 + */
1978 + hcint.d32 &= hcintmsk.d32;
1979 + if(hcint.b.nak)
1980 + {
1981 + hcintmsk.b.nak = 0;
1982 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);
1983 + }
1984 + if (hcint.b.ack)
1985 + {
1986 + hcintmsk.b.ack = 0;
1987 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);
1988 + }
1989 + }
1990 +
1991 + // Clear the interrupt, this will also clear the HAINT bit
1992 + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32);
1993 + return hcint_saved[channel].d32 == 0;
1994 +}
1995 +
1996 +gintsts_data_t gintsts;
1997 +gintmsk_data_t gintmsk;
1998 +// triggered: The set of interrupts that were triggered
1999 +// handled: The set of interrupts that have been handled (no IRQ is
2000 +// required)
2001 +// keep: The set of interrupts we want to keep unmasked even though we
2002 +// want to trigger an IRQ to handle it (SOF and HCINTR)
2003 +gintsts_data_t triggered, handled, keep;
2004 +hfnum_data_t hfnum;
2005 +
2006 +void __attribute__ ((naked)) notrace dwc_otg_hcd_handle_fiq(void)
2007 +{
2008 +
2009 + /* entry takes care to store registers we will be treading on here */
2010 + asm __volatile__ (
2011 + "mov ip, sp ;"
2012 + /* stash FIQ and normal regs */
2013 + "stmdb sp!, {r0-r12, lr};"
2014 + /* !! THIS SETS THE FRAME, adjust to > sizeof locals */
2015 + "sub fp, ip, #512 ;"
2016 + );
2017 +
2018 + // Cannot put local variables at the beginning of the function
2019 + // because otherwise 'C' will play with the stack pointer. any locals
2020 + // need to be inside the following block
2021 + do
2022 + {
2023 + fiq_done++;
2024 + gintsts.d32 = FIQ_READ(dwc_regs_base + 0x14);
2025 + gintmsk.d32 = FIQ_READ(dwc_regs_base + 0x18);
2026 + hfnum.d32 = FIQ_READ(dwc_regs_base + 0x408);
2027 + triggered.d32 = gintsts.d32 & gintmsk.d32;
2028 + handled.d32 = 0;
2029 + keep.d32 = 0;
2030 + fiq_print(FIQDBG_INT, "FIQ ");
2031 + fiq_print(FIQDBG_INT, "%08x", gintsts.d32);
2032 + fiq_print(FIQDBG_INT, "%08x", gintmsk.d32);
2033 + if(gintsts.d32)
2034 + {
2035 + // If port enabled
2036 + if((FIQ_READ(dwc_regs_base + 0x440) & 0xf) == 0x5)
2037 + {
2038 + if(gintsts.b.sofintr)
2039 + {
2040 + if(fiq_sof_handle(hfnum))
2041 + {
2042 + handled.b.sofintr = 1; /* Handled in FIQ */
2043 + }
2044 + else
2045 + {
2046 + /* Keer interrupt unmasked */
2047 + keep.b.sofintr = 1;
2048 + }
2049 + {
2050 + // Need to make sure the read and clearing of the SOF interrupt is as close as possible to avoid the possibility of missing
2051 + // a start of frame interrupt
2052 + gintsts_data_t gintsts = { .b.sofintr = 1 };
2053 + FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
2054 + }
2055 + }
2056 +
2057 + if(fiq_split_enable && gintsts.b.hcintr)
2058 + {
2059 + int i;
2060 + haint_data_t haint;
2061 + haintmsk_data_t haintmsk;
2062 +
2063 + haint.d32 = FIQ_READ(dwc_regs_base + 0x414);
2064 + haintmsk.d32 = FIQ_READ(dwc_regs_base + 0x418);
2065 + haint.d32 &= haintmsk.d32;
2066 + haint_saved.d32 |= haint.d32;
2067 +
2068 + fiq_print(FIQDBG_INT, "hcintr");
2069 + fiq_print(FIQDBG_INT, "%08x", FIQ_READ(dwc_regs_base + 0x414));
2070 +
2071 + // Go through each channel that has an enabled interrupt
2072 + for(i = 0; i < 16; i++)
2073 + if((haint.d32 >> i) & 1)
2074 + if(fiq_hcintr_handle(i, hfnum))
2075 + haint_saved.d32 &= ~(1 << i); /* this was handled */
2076 +
2077 + /* If we've handled all host channel interrupts then don't trigger the interrupt */
2078 + if(haint_saved.d32 == 0)
2079 + {
2080 + handled.b.hcintr = 1;
2081 + }
2082 + else
2083 + {
2084 + /* Make sure we keep the channel interrupt unmasked when triggering the IRQ */
2085 + keep.b.hcintr = 1;
2086 + }
2087 +
2088 + {
2089 + gintsts_data_t gintsts = { .b.hcintr = 1 };
2090 +
2091 + // Always clear the channel interrupt
2092 + FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
2093 + }
2094 + }
2095 + }
2096 + else
2097 + {
2098 + last_sof = -1;
2099 + }
2100 + }
2101 +
2102 + // Mask out the interrupts triggered - those handled - don't mask out the ones we want to keep
2103 + gintmsk.d32 = keep.d32 | (gintmsk.d32 & ~(triggered.d32 & ~handled.d32));
2104 + // Save those that were triggered but not handled
2105 + gintsts_saved.d32 |= triggered.d32 & ~handled.d32;
2106 + FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
2107 +
2108 + // Clear and save any unhandled interrupts and trigger the interrupt
2109 + if(gintsts_saved.d32)
2110 + {
2111 + /* To enable the MPHI interrupt (INT 32)
2112 + */
2113 + FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send);
2114 + FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
2115 +
2116 + mphi_int_count++;
2117 + }
2118 + }
2119 + while(0);
2120 +
2121 + mb();
2122 +
2123 + /* exit back to normal mode restoring everything */
2124 + asm __volatile__ (
2125 + /* return FIQ regs back to pristine state
2126 + * and get normal regs back
2127 + */
2128 + "ldmia sp!, {r0-r12, lr};"
2129 +
2130 + /* return */
2131 + "subs pc, lr, #4;"
2132 + );
2133 +}
2134 +
2135 /** This function handles interrupts for the HCD. */
2136 int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
2137 {
2138 int retval = 0;
2139 + static int last_time;
2140
2141 dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
2142 gintsts_data_t gintsts;
2143 + gintmsk_data_t gintmsk;
2144 + hfnum_data_t hfnum;
2145 +
2146 #ifdef DEBUG
2147 dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
2148
2149 - //GRAYG: debugging
2150 - if (NULL == global_regs) {
2151 - DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
2152 - "core_if=%p\n",
2153 - dwc_otg_hcd, global_regs);
2154 - return retval;
2155 - }
2156 #endif
2157
2158 + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
2159 + gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
2160 +
2161 /* Exit from ISR if core is hibernated */
2162 if (core_if->hibernation_suspend == 1) {
2163 - return retval;
2164 + goto exit_handler_routine;
2165 }
2166 DWC_SPINLOCK(dwc_otg_hcd->lock);
2167 /* Check if HOST Mode */
2168 if (dwc_otg_is_host_mode(core_if)) {
2169 - gintsts.d32 = dwc_otg_read_core_intr(core_if);
2170 + local_fiq_disable();
2171 + gintmsk.d32 |= gintsts_saved.d32;
2172 + gintsts.d32 |= gintsts_saved.d32;
2173 + gintsts_saved.d32 = 0;
2174 + local_fiq_enable();
2175 if (!gintsts.d32) {
2176 - DWC_SPINUNLOCK(dwc_otg_hcd->lock);
2177 - return 0;
2178 + goto exit_handler_routine;
2179 }
2180 + gintsts.d32 &= gintmsk.d32;
2181 +
2182 #ifdef DEBUG
2183 + // We should be OK doing this because the common interrupts should already have been serviced
2184 /* Don't print debug message in the interrupt handler on SOF */
2185 #ifndef DEBUG_SOF
2186 if (gintsts.d32 != DWC_SOF_INTR_MASK)
2187 @@ -88,10 +543,16 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
2188 "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
2189 gintsts.d32, core_if);
2190 #endif
2191 -
2192 - if (gintsts.b.sofintr) {
2193 + hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum);
2194 + if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
2195 + {
2196 + /* Note, we should never get here if the FIQ is doing it's job properly*/
2197 retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
2198 }
2199 + else if (gintsts.b.sofintr) {
2200 + retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
2201 + }
2202 +
2203 if (gintsts.b.rxstsqlvl) {
2204 retval |=
2205 dwc_otg_hcd_handle_rx_status_q_level_intr
2206 @@ -106,7 +567,10 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
2207 /** @todo Implement i2cintr handler. */
2208 }
2209 if (gintsts.b.portintr) {
2210 +
2211 + gintmsk_data_t gintmsk = { .b.portintr = 1};
2212 retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
2213 + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
2214 }
2215 if (gintsts.b.hcintr) {
2216 retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
2217 @@ -138,11 +602,48 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
2218 #endif
2219
2220 }
2221 +
2222 +exit_handler_routine:
2223 +
2224 + if (fiq_fix_enable)
2225 + {
2226 + local_fiq_disable();
2227 + // Make sure that we don't clear the interrupt if we've still got pending work to do
2228 + if(gintsts_saved.d32 == 0)
2229 + {
2230 + /* Clear the MPHI interrupt */
2231 + DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));
2232 + if (mphi_int_count >= 60)
2233 + {
2234 + DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));
2235 + while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17)))
2236 + ;
2237 + DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
2238 + mphi_int_count = 0;
2239 + }
2240 + int_done++;
2241 + }
2242 +
2243 + // Unmask handled interrupts
2244 + FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
2245 + //DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);
2246 +
2247 + local_fiq_enable();
2248 +
2249 + if((jiffies / HZ) > last_time)
2250 + {
2251 + /* Once a second output the fiq and irq numbers, useful for debug */
2252 + last_time = jiffies / HZ;
2253 + DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done);
2254 + }
2255 + }
2256 +
2257 DWC_SPINUNLOCK(dwc_otg_hcd->lock);
2258 return retval;
2259 }
2260
2261 #ifdef DWC_TRACK_MISSED_SOFS
2262 +
2263 #warning Compiling code to track missed SOFs
2264 #define FRAME_NUM_ARRAY_SIZE 1000
2265 /**
2266 @@ -188,7 +689,8 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
2267 dwc_list_link_t *qh_entry;
2268 dwc_otg_qh_t *qh;
2269 dwc_otg_transaction_type_e tr_type;
2270 - gintsts_data_t gintsts = {.d32 = 0 };
2271 + int did_something = 0;
2272 + int32_t next_sched_frame = -1;
2273
2274 hfnum.d32 =
2275 DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
2276 @@ -212,17 +714,31 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
2277 qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
2278 qh_entry = qh_entry->next;
2279 if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
2280 +
2281 /*
2282 * Move QH to the ready list to be executed next
2283 * (micro)frame.
2284 */
2285 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
2286 &qh->qh_list_entry);
2287 +
2288 + did_something = 1;
2289 + }
2290 + else
2291 + {
2292 + if(next_sched_frame < 0 || dwc_frame_num_le(qh->sched_frame, next_sched_frame))
2293 + {
2294 + next_sched_frame = qh->sched_frame;
2295 + }
2296 }
2297 }
2298 +
2299 + g_next_sched_frame = next_sched_frame;
2300 +
2301 tr_type = dwc_otg_hcd_select_transactions(hcd);
2302 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
2303 dwc_otg_hcd_queue_transactions(hcd, tr_type);
2304 + did_something = 1;
2305 }
2306
2307 /* Clear interrupt */
2308 @@ -511,6 +1027,15 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
2309
2310 haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
2311
2312 + // Overwrite with saved interrupts from fiq handler
2313 + if(fiq_split_enable)
2314 + {
2315 + local_fiq_disable();
2316 + haint.d32 = haint_saved.d32;
2317 + haint_saved.d32 = 0;
2318 + local_fiq_enable();
2319 + }
2320 +
2321 for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
2322 if (haint.b2.chint & (1 << i)) {
2323 retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
2324 @@ -551,7 +1076,10 @@ static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
2325 *short_read = (hctsiz.b.xfersize != 0);
2326 }
2327 } else if (hc->qh->do_split) {
2328 - length = qtd->ssplit_out_xfer_count;
2329 + if(fiq_split_enable)
2330 + length = split_out_xfersize[hc->hc_num];
2331 + else
2332 + length = qtd->ssplit_out_xfer_count;
2333 } else {
2334 length = hc->xfer_len;
2335 }
2336 @@ -595,7 +1123,6 @@ static int update_urb_state_xfer_comp(dwc_hc_t * hc,
2337 DWC_OTG_HC_XFER_COMPLETE,
2338 &short_read);
2339
2340 -
2341 /* non DWORD-aligned buffer case handling. */
2342 if (hc->align_buff && xfer_length && hc->ep_is_in) {
2343 dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
2344 @@ -797,11 +1324,24 @@ static void release_channel(dwc_otg_hcd_t * hcd,
2345 dwc_otg_transaction_type_e tr_type;
2346 int free_qtd;
2347 dwc_irqflags_t flags;
2348 - dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
2349 + dwc_spinlock_t *channel_lock = hcd->channel_lock;
2350 +#ifdef FIQ_DEBUG
2351 + int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0;
2352 +#endif
2353 + int hog_port = 0;
2354
2355 DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n",
2356 __func__, hc->hc_num, halt_status, hc->xfer_len);
2357
2358 + if(fiq_split_enable && hc->do_split) {
2359 + if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) {
2360 + if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID ||
2361 + hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) {
2362 + hog_port = 1;
2363 + }
2364 + }
2365 + }
2366 +
2367 switch (halt_status) {
2368 case DWC_OTG_HC_XFER_URB_COMPLETE:
2369 free_qtd = 1;
2370 @@ -876,15 +1416,32 @@ cleanup:
2371
2372 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
2373 hcd->available_host_channels++;
2374 + fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels);
2375 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
2376 }
2377
2378 + if(fiq_split_enable && hc->do_split)
2379 + {
2380 + if(!(hcd->hub_port[hc->hub_addr] & (1 << hc->port_addr)))
2381 + {
2382 + fiq_print(FIQDBG_ERR, "PRTNOTAL");
2383 + //BUG();
2384 + }
2385 + if(!hog_port && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC ||
2386 + hc->ep_type == DWC_OTG_EP_TYPE_INTR)) {
2387 + hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);
2388 +#ifdef FIQ_DEBUG
2389 + hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;
2390 +#endif
2391 + fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);
2392 + }
2393 + }
2394 +
2395 /* Try to queue more transfers now that there's a free channel. */
2396 tr_type = dwc_otg_hcd_select_transactions(hcd);
2397 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
2398 dwc_otg_hcd_queue_transactions(hcd, tr_type);
2399 }
2400 - DWC_SPINLOCK_FREE(channel_lock);
2401 }
2402
2403 /**
2404 @@ -1295,6 +1852,17 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
2405 "NAK Received--\n", hc->hc_num);
2406
2407 /*
2408 + * When we get bulk NAKs then remember this so we holdoff on this qh until
2409 + * the beginning of the next frame
2410 + */
2411 + switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
2412 + case UE_BULK:
2413 + case UE_CONTROL:
2414 + if (nak_holdoff_enable)
2415 + hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd);
2416 + }
2417 +
2418 + /*
2419 * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
2420 * interrupt. Re-start the SSPLIT transfer.
2421 */
2422 @@ -1316,7 +1884,11 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
2423 * transfers in DMA mode for the sole purpose of
2424 * resetting the error count after a transaction error
2425 * occurs. The core will continue transferring data.
2426 + * Disable other interrupts unmasked for the same
2427 + * reason.
2428 */
2429 + disable_hc_int(hc_regs, datatglerr);
2430 + disable_hc_int(hc_regs, ack);
2431 qtd->error_count = 0;
2432 goto handle_nak_done;
2433 }
2434 @@ -1428,6 +2000,15 @@ static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
2435 halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
2436 }
2437 } else {
2438 + /*
2439 + * An unmasked ACK on a non-split DMA transaction is
2440 + * for the sole purpose of resetting error counts. Disable other
2441 + * interrupts unmasked for the same reason.
2442 + */
2443 + if(hcd->core_if->dma_enable) {
2444 + disable_hc_int(hc_regs, datatglerr);
2445 + disable_hc_int(hc_regs, nak);
2446 + }
2447 qtd->error_count = 0;
2448
2449 if (hc->qh->ping_state) {
2450 @@ -1490,8 +2071,10 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
2451 hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
2452 int frnum = dwc_otg_hcd_get_frame_number(hcd);
2453
2454 + // With the FIQ running we only ever see the failed NYET
2455 if (dwc_full_frame_num(frnum) !=
2456 - dwc_full_frame_num(hc->qh->sched_frame)) {
2457 + dwc_full_frame_num(hc->qh->sched_frame) ||
2458 + fiq_split_enable) {
2459 /*
2460 * No longer in the same full speed frame.
2461 * Treat this as a transaction error.
2462 @@ -1778,13 +2361,28 @@ static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
2463 dwc_otg_qtd_t * qtd)
2464 {
2465 DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
2466 - "Data Toggle Error--\n", hc->hc_num);
2467 + "Data Toggle Error on %s transfer--\n",
2468 + hc->hc_num, (hc->ep_is_in ? "IN" : "OUT"));
2469
2470 - if (hc->ep_is_in) {
2471 + /* Data toggles on split transactions cause the hc to halt.
2472 + * restart transfer */
2473 + if(hc->qh->do_split)
2474 + {
2475 + qtd->error_count++;
2476 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2477 + update_urb_state_xfer_intr(hc, hc_regs,
2478 + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2479 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2480 + } else if (hc->ep_is_in) {
2481 + /* An unmasked data toggle error on a non-split DMA transaction is
2482 + * for the sole purpose of resetting error counts. Disable other
2483 + * interrupts unmasked for the same reason.
2484 + */
2485 + if(hcd->core_if->dma_enable) {
2486 + disable_hc_int(hc_regs, ack);
2487 + disable_hc_int(hc_regs, nak);
2488 + }
2489 qtd->error_count = 0;
2490 - } else {
2491 - DWC_ERROR("Data Toggle Error on OUT transfer,"
2492 - "channel %d\n", hc->hc_num);
2493 }
2494
2495 disable_hc_int(hc_regs, datatglerr);
2496 @@ -1862,10 +2460,10 @@ static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
2497 static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
2498 dwc_hc_t * hc,
2499 dwc_otg_hc_regs_t * hc_regs,
2500 - dwc_otg_qtd_t * qtd)
2501 + dwc_otg_qtd_t * qtd,
2502 + hcint_data_t hcint,
2503 + hcintmsk_data_t hcintmsk)
2504 {
2505 - hcint_data_t hcint;
2506 - hcintmsk_data_t hcintmsk;
2507 int out_nak_enh = 0;
2508
2509 /* For core with OUT NAK enhancement, the flow for high-
2510 @@ -1897,8 +2495,11 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
2511 }
2512
2513 /* Read the HCINTn register to determine the cause for the halt. */
2514 - hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2515 - hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
2516 + if(!fiq_split_enable)
2517 + {
2518 + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2519 + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
2520 + }
2521
2522 if (hcint.b.xfercomp) {
2523 /** @todo This is here because of a possible hardware bug. Spec
2524 @@ -1937,6 +2538,8 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
2525 handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
2526 } else if (hcint.b.frmovrun) {
2527 handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
2528 + } else if (hcint.b.datatglerr) {
2529 + handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd);
2530 } else if (!out_nak_enh) {
2531 if (hcint.b.nyet) {
2532 /*
2533 @@ -1986,12 +2589,24 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
2534 DWC_READ_REG32(&hcd->
2535 core_if->core_global_regs->
2536 gintsts));
2537 + /* Failthrough: use 3-strikes rule */
2538 + qtd->error_count++;
2539 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2540 + update_urb_state_xfer_intr(hc, hc_regs,
2541 + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2542 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2543 }
2544
2545 }
2546 } else {
2547 DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
2548 hcint.d32);
2549 + /* Failthrough: use 3-strikes rule */
2550 + qtd->error_count++;
2551 + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2552 + update_urb_state_xfer_intr(hc, hc_regs,
2553 + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2554 + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2555 }
2556 }
2557
2558 @@ -2009,13 +2624,15 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
2559 static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
2560 dwc_hc_t * hc,
2561 dwc_otg_hc_regs_t * hc_regs,
2562 - dwc_otg_qtd_t * qtd)
2563 + dwc_otg_qtd_t * qtd,
2564 + hcint_data_t hcint,
2565 + hcintmsk_data_t hcintmsk)
2566 {
2567 DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
2568 "Channel Halted--\n", hc->hc_num);
2569
2570 if (hcd->core_if->dma_enable) {
2571 - handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
2572 + handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd, hcint, hcintmsk);
2573 } else {
2574 #ifdef DEBUG
2575 if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
2576 @@ -2032,7 +2649,7 @@ static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
2577 int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
2578 {
2579 int retval = 0;
2580 - hcint_data_t hcint;
2581 + hcint_data_t hcint, hcint_orig;
2582 hcintmsk_data_t hcintmsk;
2583 dwc_hc_t *hc;
2584 dwc_otg_hc_regs_t *hc_regs;
2585 @@ -2042,15 +2659,33 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
2586
2587 hc = dwc_otg_hcd->hc_ptr_array[num];
2588 hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
2589 + if(hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
2590 + /* We are responding to a channel disable. Driver
2591 + * state is cleared - our qtd has gone away.
2592 + */
2593 + release_channel(dwc_otg_hcd, hc, NULL, hc->halt_status);
2594 + return 1;
2595 + }
2596 qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
2597
2598 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2599 + hcint_orig = hcint;
2600 hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
2601 DWC_DEBUGPL(DBG_HCDV,
2602 " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
2603 hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
2604 hcint.d32 = hcint.d32 & hcintmsk.d32;
2605
2606 + if(fiq_split_enable)
2607 + {
2608 + // replace with the saved interrupts from the fiq handler
2609 + local_fiq_disable();
2610 + hcint_orig.d32 = hcint_saved[num].d32;
2611 + hcint.d32 = hcint_orig.d32 & hcintmsk_saved[num].d32;
2612 + hcint_saved[num].d32 = 0;
2613 + local_fiq_enable();
2614 + }
2615 +
2616 if (!dwc_otg_hcd->core_if->dma_enable) {
2617 if (hcint.b.chhltd && hcint.d32 != 0x2) {
2618 hcint.b.chhltd = 0;
2619 @@ -2068,7 +2703,7 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
2620 hcint.b.nyet = 0;
2621 }
2622 if (hcint.b.chhltd) {
2623 - retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2624 + retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd, hcint_orig, hcintmsk_saved[num]);
2625 }
2626 if (hcint.b.ahberr) {
2627 retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2628 @@ -2080,7 +2715,8 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
2629 retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2630 }
2631 if (hcint.b.ack) {
2632 - retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2633 + if(!hcint.b.chhltd)
2634 + retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2635 }
2636 if (hcint.b.nyet) {
2637 retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2638 @@ -2102,5 +2738,4 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
2639
2640 return retval;
2641 }
2642 -
2643 #endif /* DWC_DEVICE_ONLY */
2644 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
2645 index e4787f5..ee8eec9 100644
2646 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
2647 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
2648 @@ -1,3 +1,4 @@
2649 +
2650 /* ==========================================================================
2651 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
2652 * $Revision: #20 $
2653 @@ -50,6 +51,7 @@
2654 #include <linux/dma-mapping.h>
2655 #include <linux/version.h>
2656 #include <asm/io.h>
2657 +#include <asm/fiq.h>
2658 #include <linux/usb.h>
2659 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
2660 #include <../drivers/usb/core/hcd.h>
2661 @@ -67,6 +69,8 @@
2662 #include "dwc_otg_dbg.h"
2663 #include "dwc_otg_driver.h"
2664 #include "dwc_otg_hcd.h"
2665 +#include "dwc_otg_mphi_fix.h"
2666 +
2667 /**
2668 * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
2669 * qualified with its direction (possible 32 endpoints per device).
2670 @@ -76,6 +80,8 @@
2671
2672 static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
2673
2674 +extern bool fiq_fix_enable;
2675 +
2676 /** @name Linux HC Driver API Functions */
2677 /** @{ */
2678 /* manage i/o requests, device state */
2679 @@ -259,13 +265,15 @@ static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
2680
2681 /**
2682 * Sets the final status of an URB and returns it to the device driver. Any
2683 - * required cleanup of the URB is performed.
2684 + * required cleanup of the URB is performed. The HCD lock should be held on
2685 + * entry.
2686 */
2687 static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
2688 dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
2689 {
2690 struct urb *urb = (struct urb *)urb_handle;
2691 -
2692 + urb_tq_entry_t *new_entry;
2693 + int rc = 0;
2694 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
2695 DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
2696 __func__, urb, usb_pipedevice(urb->pipe),
2697 @@ -279,7 +287,7 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
2698 }
2699 }
2700 }
2701 -
2702 + new_entry = DWC_ALLOC_ATOMIC(sizeof(urb_tq_entry_t));
2703 urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
2704 /* Convert status value. */
2705 switch (status) {
2706 @@ -301,6 +309,9 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
2707 case -DWC_E_OVERFLOW:
2708 status = -EOVERFLOW;
2709 break;
2710 + case -DWC_E_SHUTDOWN:
2711 + status = -ESHUTDOWN;
2712 + break;
2713 default:
2714 if (status) {
2715 DWC_PRINTF("Uknown urb status %d\n", status);
2716 @@ -342,18 +353,33 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
2717 }
2718
2719 DWC_FREE(dwc_otg_urb);
2720 -
2721 + if (!new_entry) {
2722 + DWC_ERROR("dwc_otg_hcd: complete: cannot allocate URB TQ entry\n");
2723 + urb->status = -EPROTO;
2724 + /* don't schedule the tasklet -
2725 + * directly return the packet here with error. */
2726 #if USB_URB_EP_LINKING
2727 - usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
2728 + usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
2729 #endif
2730 - DWC_SPINUNLOCK(hcd->lock);
2731 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
2732 - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
2733 + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
2734 #else
2735 - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
2736 + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
2737 #endif
2738 - DWC_SPINLOCK(hcd->lock);
2739 -
2740 + } else {
2741 + new_entry->urb = urb;
2742 +#if USB_URB_EP_LINKING
2743 + rc = usb_hcd_check_unlink_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
2744 + if(0 == rc) {
2745 + usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
2746 + }
2747 +#endif
2748 + if(0 == rc) {
2749 + DWC_TAILQ_INSERT_TAIL(&hcd->completed_urb_list, new_entry,
2750 + urb_tq_entries);
2751 + DWC_TASK_HI_SCHEDULE(hcd->completion_tasklet);
2752 + }
2753 + }
2754 return 0;
2755 }
2756
2757 @@ -366,6 +392,16 @@ static struct dwc_otg_hcd_function_ops hcd_fops = {
2758 .get_b_hnp_enable = _get_b_hnp_enable,
2759 };
2760
2761 +static struct fiq_handler fh = {
2762 + .name = "usb_fiq",
2763 +};
2764 +struct fiq_stack_s {
2765 + int magic1;
2766 + uint8_t stack[2048];
2767 + int magic2;
2768 +} fiq_stack;
2769 +
2770 +extern mphi_regs_t c_mphi_regs;
2771 /**
2772 * Initializes the HCD. This function allocates memory for and initializes the
2773 * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
2774 @@ -379,6 +415,7 @@ int hcd_init(dwc_bus_dev_t *_dev)
2775 dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
2776 int retval = 0;
2777 u64 dmamask;
2778 + struct pt_regs regs;
2779
2780 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
2781
2782 @@ -396,6 +433,20 @@ int hcd_init(dwc_bus_dev_t *_dev)
2783 pci_set_consistent_dma_mask(_dev, dmamask);
2784 #endif
2785
2786 + if (fiq_fix_enable)
2787 + {
2788 + // Set up fiq
2789 + claim_fiq(&fh);
2790 + set_fiq_handler(__FIQ_Branch, 4);
2791 + memset(&regs,0,sizeof(regs));
2792 + regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq;
2793 + regs.ARM_r9 = (long)0;
2794 + regs.ARM_sp = (long)fiq_stack.stack + sizeof(fiq_stack.stack) - 4;
2795 + set_fiq_regs(&regs);
2796 + fiq_stack.magic1 = 0xdeadbeef;
2797 + fiq_stack.magic2 = 0xaa995566;
2798 + }
2799 +
2800 /*
2801 * Allocate memory for the base HCD plus the DWC OTG HCD.
2802 * Initialize the base HCD.
2803 @@ -415,6 +466,30 @@ int hcd_init(dwc_bus_dev_t *_dev)
2804
2805 hcd->regs = otg_dev->os_dep.base;
2806
2807 + if (fiq_fix_enable)
2808 + {
2809 + volatile extern void *dwc_regs_base;
2810 +
2811 + //Set the mphi periph to the required registers
2812 + c_mphi_regs.base = otg_dev->os_dep.mphi_base;
2813 + c_mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
2814 + c_mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
2815 + c_mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
2816 + c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
2817 +
2818 + dwc_regs_base = otg_dev->os_dep.base;
2819 +
2820 + //Enable mphi peripheral
2821 + writel((1<<31),c_mphi_regs.ctrl);
2822 +#ifdef DEBUG
2823 + if (readl(c_mphi_regs.ctrl) & 0x80000000)
2824 + DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n");
2825 + else
2826 + DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n");
2827 +#endif
2828 + // Enable FIQ interrupt from USB peripheral
2829 + enable_fiq(INTERRUPT_VC_USB);
2830 + }
2831 /* Initialize the DWC OTG HCD. */
2832 dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
2833 if (!dwc_otg_hcd) {
2834 @@ -607,9 +682,7 @@ static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
2835 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
2836 struct usb_host_endpoint *ep = urb->ep;
2837 #endif
2838 -#if USB_URB_EP_LINKING
2839 dwc_irqflags_t irqflags;
2840 -#endif
2841 void **ref_ep_hcpriv = &ep->hcpriv;
2842 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
2843 dwc_otg_hcd_urb_t *dwc_otg_urb;
2844 @@ -661,9 +734,8 @@ static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
2845 if(dwc_otg_urb == NULL)
2846 return -ENOMEM;
2847
2848 - urb->hcpriv = dwc_otg_urb;
2849 - if (!dwc_otg_urb && urb->number_of_packets)
2850 - return -ENOMEM;
2851 + if (!dwc_otg_urb && urb->number_of_packets)
2852 + return -ENOMEM;
2853
2854 dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
2855 usb_pipeendpoint(urb->pipe), ep_type,
2856 @@ -703,37 +775,42 @@ static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
2857 iso_frame_desc[i].length);
2858 }
2859
2860 + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
2861 + urb->hcpriv = dwc_otg_urb;
2862 #if USB_URB_EP_LINKING
2863 - DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
2864 retval = usb_hcd_link_urb_to_ep(hcd, urb);
2865 - DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
2866 if (0 == retval)
2867 #endif
2868 - {
2869 - retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
2870 - /*(dwc_otg_qh_t **)*/
2871 - ref_ep_hcpriv,
2872 - mem_flags == GFP_ATOMIC ? 1 : 0);
2873 - if (0 == retval) {
2874 - if (alloc_bandwidth) {
2875 - allocate_bus_bandwidth(hcd,
2876 - dwc_otg_hcd_get_ep_bandwidth(
2877 - dwc_otg_hcd, *ref_ep_hcpriv),
2878 - urb);
2879 - }
2880 - } else {
2881 + {
2882 + retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
2883 + /*(dwc_otg_qh_t **)*/
2884 + ref_ep_hcpriv, 1);
2885 + if (0 == retval) {
2886 + if (alloc_bandwidth) {
2887 + allocate_bus_bandwidth(hcd,
2888 + dwc_otg_hcd_get_ep_bandwidth(
2889 + dwc_otg_hcd, *ref_ep_hcpriv),
2890 + urb);
2891 + }
2892 + } else {
2893 + DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
2894 #if USB_URB_EP_LINKING
2895 - dwc_irqflags_t irqflags;
2896 - DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
2897 - DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
2898 - usb_hcd_unlink_urb_from_ep(hcd, urb);
2899 - DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
2900 + usb_hcd_unlink_urb_from_ep(hcd, urb);
2901 #endif
2902 - if (retval == -DWC_E_NO_DEVICE) {
2903 - retval = -ENODEV;
2904 - }
2905 - }
2906 - }
2907 + DWC_FREE(dwc_otg_urb);
2908 + urb->hcpriv = NULL;
2909 + if (retval == -DWC_E_NO_DEVICE)
2910 + retval = -ENODEV;
2911 + }
2912 + }
2913 +#if USB_URB_EP_LINKING
2914 + else
2915 + {
2916 + DWC_FREE(dwc_otg_urb);
2917 + urb->hcpriv = NULL;
2918 + }
2919 +#endif
2920 + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
2921 return retval;
2922 }
2923
2924 @@ -777,6 +854,8 @@ static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
2925 usb_hcd_unlink_urb_from_ep(hcd, urb);
2926 #endif
2927 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
2928 +
2929 +
2930 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
2931 usb_hcd_giveback_urb(hcd, urb);
2932 #else
2933 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
2934 index 0a1cbb7..5c22b6c 100644
2935 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
2936 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
2937 @@ -41,6 +41,7 @@
2938
2939 #include "dwc_otg_hcd.h"
2940 #include "dwc_otg_regs.h"
2941 +#include "dwc_otg_mphi_fix.h"
2942
2943 extern bool microframe_schedule;
2944
2945 @@ -182,6 +183,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
2946 if (microframe_schedule)
2947 qh->speed = dev_speed;
2948
2949 + qh->nak_frame = 0xffff;
2950
2951 if (((dev_speed == USB_SPEED_LOW) ||
2952 (dev_speed == USB_SPEED_FULL)) &&
2953 @@ -191,6 +193,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
2954 dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
2955 hub_port);
2956 qh->do_split = 1;
2957 + qh->skip_count = 0;
2958 }
2959
2960 if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
2961 @@ -573,6 +576,9 @@ static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
2962 return status;
2963 }
2964
2965 +
2966 +extern int g_next_sched_frame, g_np_count, g_np_sent;
2967 +
2968 /**
2969 * Schedules an interrupt or isochronous transfer in the periodic schedule.
2970 *
2971 @@ -631,8 +637,13 @@ static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
2972 DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
2973 }
2974 else {
2975 - /* Always start in the inactive schedule. */
2976 - DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
2977 + if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame))
2978 + {
2979 + g_next_sched_frame = qh->sched_frame;
2980 +
2981 + }
2982 + /* Always start in the inactive schedule. */
2983 + DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
2984 }
2985
2986 if (!microframe_schedule) {
2987 @@ -646,6 +657,7 @@ static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
2988 return status;
2989 }
2990
2991 +
2992 /**
2993 * This function adds a QH to either the non periodic or periodic schedule if
2994 * it is not already in the schedule. If the QH is already in the schedule, no
2995 @@ -668,6 +680,7 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
2996 /* Always start in the inactive schedule. */
2997 DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
2998 &qh->qh_list_entry);
2999 + g_np_count++;
3000 } else {
3001 status = schedule_periodic(hcd, qh);
3002 if ( !hcd->periodic_qh_count ) {
3003 @@ -727,6 +740,9 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
3004 hcd->non_periodic_qh_ptr->next;
3005 }
3006 DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
3007 +
3008 + // If we've removed the last non-periodic entry then there are none left!
3009 + g_np_count = g_np_sent;
3010 } else {
3011 deschedule_periodic(hcd, qh);
3012 hcd->periodic_qh_count--;
3013 @@ -755,6 +771,24 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
3014 int sched_next_periodic_split)
3015 {
3016 if (dwc_qh_is_non_per(qh)) {
3017 +
3018 + dwc_otg_qh_t *qh_tmp;
3019 + dwc_list_link_t *qh_list;
3020 + DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive)
3021 + {
3022 + qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry);
3023 + if(qh_tmp == qh)
3024 + {
3025 + /*
3026 + * FIQ is being disabled because this one nevers gets a np_count increment
3027 + * This is still not absolutely correct, but it should fix itself with
3028 + * just an unnecessary extra interrupt
3029 + */
3030 + g_np_sent = g_np_count;
3031 + }
3032 + }
3033 +
3034 +
3035 dwc_otg_hcd_qh_remove(hcd, qh);
3036 if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
3037 /* Add back to inactive non-periodic schedule. */
3038 @@ -768,6 +802,7 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
3039 if (sched_next_periodic_split) {
3040
3041 qh->sched_frame = frame_number;
3042 +
3043 if (dwc_frame_num_le(frame_number,
3044 dwc_frame_num_inc
3045 (qh->start_split_frame,
3046 @@ -816,6 +851,11 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
3047 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
3048 &qh->qh_list_entry);
3049 } else {
3050 + if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame))
3051 + {
3052 + g_next_sched_frame = qh->sched_frame;
3053 + }
3054 +
3055 DWC_LIST_MOVE_HEAD
3056 (&hcd->periodic_sched_inactive,
3057 &qh->qh_list_entry);
3058 @@ -880,6 +920,7 @@ void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb)
3059 * QH to place the QTD into. If it does not find a QH, then it will create a
3060 * new QH. If the QH to which the QTD is added is not currently scheduled, it
3061 * is placed into the proper schedule based on its EP type.
3062 + * HCD lock must be held and interrupts must be disabled on entry
3063 *
3064 * @param[in] qtd The QTD to add
3065 * @param[in] hcd The DWC HCD structure
3066 @@ -892,8 +933,6 @@ int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,
3067 dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)
3068 {
3069 int retval = 0;
3070 - dwc_irqflags_t flags;
3071 -
3072 dwc_otg_hcd_urb_t *urb = qtd->urb;
3073
3074 /*
3075 @@ -903,18 +942,16 @@ int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,
3076 if (*qh == NULL) {
3077 *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);
3078 if (*qh == NULL) {
3079 - retval = -1;
3080 + retval = -DWC_E_NO_MEMORY;
3081 goto done;
3082 }
3083 }
3084 - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
3085 retval = dwc_otg_hcd_qh_add(hcd, *qh);
3086 if (retval == 0) {
3087 DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
3088 qtd_list_entry);
3089 + qtd->qh = *qh;
3090 }
3091 - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
3092 -
3093 done:
3094
3095 return retval;
3096 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
3097 new file mode 100755
3098 index 0000000..50b94a8
3099 --- /dev/null
3100 +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
3101 @@ -0,0 +1,113 @@
3102 +#include "dwc_otg_regs.h"
3103 +#include "dwc_otg_dbg.h"
3104 +
3105 +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name)
3106 +{
3107 + DWC_DEBUGPL(DBG_USER, "*** Debugging from within the %s function: ***\n"
3108 + "curmode: %1i Modemismatch: %1i otgintr: %1i sofintr: %1i\n"
3109 + "rxstsqlvl: %1i nptxfempty : %1i ginnakeff: %1i goutnakeff: %1i\n"
3110 + "ulpickint: %1i i2cintr: %1i erlysuspend:%1i usbsuspend: %1i\n"
3111 + "usbreset: %1i enumdone: %1i isooutdrop: %1i eopframe: %1i\n"
3112 + "restoredone: %1i epmismatch: %1i inepint: %1i outepintr: %1i\n"
3113 + "incomplisoin:%1i incomplisoout:%1i fetsusp: %1i resetdet: %1i\n"
3114 + "portintr: %1i hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i\n"
3115 + "conidstschng:%1i disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
3116 + function_name,
3117 + gintsts.b.curmode,
3118 + gintsts.b.modemismatch,
3119 + gintsts.b.otgintr,
3120 + gintsts.b.sofintr,
3121 + gintsts.b.rxstsqlvl,
3122 + gintsts.b.nptxfempty,
3123 + gintsts.b.ginnakeff,
3124 + gintsts.b.goutnakeff,
3125 + gintsts.b.ulpickint,
3126 + gintsts.b.i2cintr,
3127 + gintsts.b.erlysuspend,
3128 + gintsts.b.usbsuspend,
3129 + gintsts.b.usbreset,
3130 + gintsts.b.enumdone,
3131 + gintsts.b.isooutdrop,
3132 + gintsts.b.eopframe,
3133 + gintsts.b.restoredone,
3134 + gintsts.b.epmismatch,
3135 + gintsts.b.inepint,
3136 + gintsts.b.outepintr,
3137 + gintsts.b.incomplisoin,
3138 + gintsts.b.incomplisoout,
3139 + gintsts.b.fetsusp,
3140 + gintsts.b.resetdet,
3141 + gintsts.b.portintr,
3142 + gintsts.b.hcintr,
3143 + gintsts.b.ptxfempty,
3144 + gintsts.b.lpmtranrcvd,
3145 + gintsts.b.conidstschng,
3146 + gintsts.b.disconnect,
3147 + gintsts.b.sessreqintr,
3148 + gintsts.b.wkupintr);
3149 + return;
3150 +}
3151 +
3152 +void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name)
3153 +{
3154 + DWC_DEBUGPL(DBG_USER, "Interrupt Mask status (called from %s) :\n"
3155 + "modemismatch: %1i otgintr: %1i sofintr: %1i rxstsqlvl: %1i\n"
3156 + "nptxfempty: %1i ginnakeff: %1i goutnakeff: %1i ulpickint: %1i\n"
3157 + "i2cintr: %1i erlysuspend:%1i usbsuspend: %1i usbreset: %1i\n"
3158 + "enumdone: %1i isooutdrop: %1i eopframe: %1i restoredone: %1i\n"
3159 + "epmismatch: %1i inepintr: %1i outepintr: %1i incomplisoin:%1i\n"
3160 + "incomplisoout:%1i fetsusp: %1i resetdet: %1i portintr: %1i\n"
3161 + "hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i conidstschng:%1i\n"
3162 + "disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
3163 + function_name,
3164 + gintmsk.b.modemismatch,
3165 + gintmsk.b.otgintr,
3166 + gintmsk.b.sofintr,
3167 + gintmsk.b.rxstsqlvl,
3168 + gintmsk.b.nptxfempty,
3169 + gintmsk.b.ginnakeff,
3170 + gintmsk.b.goutnakeff,
3171 + gintmsk.b.ulpickint,
3172 + gintmsk.b.i2cintr,
3173 + gintmsk.b.erlysuspend,
3174 + gintmsk.b.usbsuspend,
3175 + gintmsk.b.usbreset,
3176 + gintmsk.b.enumdone,
3177 + gintmsk.b.isooutdrop,
3178 + gintmsk.b.eopframe,
3179 + gintmsk.b.restoredone,
3180 + gintmsk.b.epmismatch,
3181 + gintmsk.b.inepintr,
3182 + gintmsk.b.outepintr,
3183 + gintmsk.b.incomplisoin,
3184 + gintmsk.b.incomplisoout,
3185 + gintmsk.b.fetsusp,
3186 + gintmsk.b.resetdet,
3187 + gintmsk.b.portintr,
3188 + gintmsk.b.hcintr,
3189 + gintmsk.b.ptxfempty,
3190 + gintmsk.b.lpmtranrcvd,
3191 + gintmsk.b.conidstschng,
3192 + gintmsk.b.disconnect,
3193 + gintmsk.b.sessreqintr,
3194 + gintmsk.b.wkupintr);
3195 + return;
3196 +}
3197 +
3198 +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name)
3199 +{
3200 + DWC_DEBUGPL(DBG_USER, "otg int register (from %s function):\n"
3201 + "sesenddet:%1i sesreqsucstschung:%2i hstnegsucstschng:%1i\n"
3202 + "hstnegdet:%1i adevtoutchng: %2i debdone: %1i\n"
3203 + "mvic: %1i\n",
3204 + function_name,
3205 + gotgint.b.sesenddet,
3206 + gotgint.b.sesreqsucstschng,
3207 + gotgint.b.hstnegsucstschng,
3208 + gotgint.b.hstnegdet,
3209 + gotgint.b.adevtoutchng,
3210 + gotgint.b.debdone,
3211 + gotgint.b.mvic);
3212 +
3213 + return;
3214 +}
3215 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
3216 new file mode 100755
3217 index 0000000..ca17379
3218 --- /dev/null
3219 +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
3220 @@ -0,0 +1,48 @@
3221 +#ifndef __DWC_OTG_MPHI_FIX_H__
3222 +#define __DWC_OTG_MPHI_FIX_H__
3223 +#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_))
3224 +#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_))
3225 +
3226 +typedef struct {
3227 + volatile void* base;
3228 + volatile void* ctrl;
3229 + volatile void* outdda;
3230 + volatile void* outddb;
3231 + volatile void* intstat;
3232 +} mphi_regs_t;
3233 +
3234 +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name);
3235 +void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name);
3236 +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);
3237 +
3238 +extern gintsts_data_t gintsts_saved;
3239 +
3240 +#ifdef DEBUG
3241 +#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__)
3242 +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__)
3243 +#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__)
3244 +
3245 +#else
3246 +#define DWC_DBG_PRINT_CORE_INT(_arg_)
3247 +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_)
3248 +#define DWC_DBG_PRINT_OTG_INT(_arg_)
3249 +
3250 +#endif
3251 +
3252 +typedef enum {
3253 + FIQDBG_SCHED = (1 << 0),
3254 + FIQDBG_INT = (1 << 1),
3255 + FIQDBG_ERR = (1 << 2),
3256 + FIQDBG_PORTHUB = (1 << 3),
3257 +} FIQDBG_T;
3258 +
3259 +void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...);
3260 +#ifdef FIQ_DEBUG
3261 +#define fiq_print _fiq_print
3262 +#else
3263 +#define fiq_print(x, y, ...)
3264 +#endif
3265 +
3266 +extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable;
3267 +
3268 +#endif
3269 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
3270 index e46d9bb..6b2c7d0 100644
3271 --- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
3272 +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
3273 @@ -97,6 +97,9 @@ typedef struct os_dependent {
3274 /** Register offset for Diagnostic API */
3275 uint32_t reg_offset;
3276
3277 + /** Base address for MPHI peripheral */
3278 + void *mphi_base;
3279 +
3280 #ifdef LM_INTERFACE
3281 struct lm_device *lmdev;
3282 #elif defined(PCI_INTERFACE)
3283 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
3284 index 1b1f83c..c8590b5 100644
3285 --- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
3286 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
3287 @@ -4276,7 +4276,7 @@ do { \
3288 && (pcd->ep0state == EP0_OUT_DATA_PHASE))
3289 status.d32 = core_if->dev_if->out_desc_addr->status.d32;
3290 if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
3291 - status.d32 = status.d32 = core_if->dev_if->
3292 + status.d32 = core_if->dev_if->
3293 out_desc_addr->status.d32;
3294
3295 if (status.b.sr) {
3296 --
3297 1.8.3.2
3298