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