brcm2708: update 3.10 patches with raspberrypi/rpi-3.10.y of 27 Apr. 2014
[openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0027-Add-FIQ-patch-to-dwc_otg-driver.-Enable-with-dwc_otg.patch
1 From 5e4c6e64d0c5fd6adc6c68cc1366f0f7c0ad84ba 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 027/196] 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 ---
9  arch/arm/Kconfig                              |   1 +
10  arch/arm/include/asm/fiq.h                    |   1 +
11  arch/arm/kernel/fiq.c                         |   1 +
12  arch/arm/kernel/fiqasm.S                      |   7 ++
13  arch/arm/mach-bcm2708/armctrl.c               |  19 ++-
14  arch/arm/mach-bcm2708/bcm2708.c               |  29 ++++-
15  arch/arm/mach-bcm2708/include/mach/irqs.h     | 159 +++++++++++++-------------
16  arch/arm/mach-bcm2708/include/mach/platform.h |   2 +
17  drivers/usb/host/dwc_otg/Makefile             |   1 +
18  drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c   |  14 ++-
19  drivers/usb/host/dwc_otg/dwc_otg_dbg.h        |   1 +
20  drivers/usb/host/dwc_otg/dwc_otg_driver.c     |  37 +++++-
21  drivers/usb/host/dwc_otg/dwc_otg_hcd.c        |   5 +
22  drivers/usb/host/dwc_otg/dwc_otg_hcd.h        |   2 +-
23  drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h     |   5 +
24  drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c   | 154 ++++++++++++++++++++++---
25  drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c  |  45 ++++++++
26  drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c  |  20 +++-
27  drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c   | 113 ++++++++++++++++++
28  drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h   |  36 ++++++
29  drivers/usb/host/dwc_otg/dwc_otg_os_dep.h     |   3 +
30  21 files changed, 545 insertions(+), 110 deletions(-)
31  create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
32  create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
33
34 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
35 index eb291c7..5468f1f 100644
36 --- a/arch/arm/Kconfig
37 +++ b/arch/arm/Kconfig
38 @@ -373,6 +373,7 @@ config ARCH_BCM2708
39         select ARM_ERRATA_411920
40         select MACH_BCM2708
41         select VC4
42 +       select FIQ
43         help
44           This enables support for Broadcom BCM2708 boards.
45  
46 diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h
47 index d493d0b..f1a131b 100644
48 --- a/arch/arm/include/asm/fiq.h
49 +++ b/arch/arm/include/asm/fiq.h
50 @@ -42,6 +42,7 @@ extern void disable_fiq(int fiq);
51  /* helpers defined in fiqasm.S: */
52  extern void __set_fiq_regs(unsigned long const *regs);
53  extern void __get_fiq_regs(unsigned long *regs);
54 +extern void __FIQ_Branch(unsigned long *regs);
55  
56  static inline void set_fiq_regs(struct pt_regs const *regs)
57  {
58 diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
59 index 25442f4..74ff4ba 100644
60 --- a/arch/arm/kernel/fiq.c
61 +++ b/arch/arm/kernel/fiq.c
62 @@ -145,6 +145,7 @@ void disable_fiq(int fiq)
63  EXPORT_SYMBOL(set_fiq_handler);
64  EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */
65  EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */
66 +EXPORT_SYMBOL(__FIQ_Branch);   /* defined in fiqasm.S */
67  EXPORT_SYMBOL(claim_fiq);
68  EXPORT_SYMBOL(release_fiq);
69  EXPORT_SYMBOL(enable_fiq);
70 diff --git a/arch/arm/kernel/fiqasm.S b/arch/arm/kernel/fiqasm.S
71 index 207f9d6..93eddfe 100644
72 --- a/arch/arm/kernel/fiqasm.S
73 +++ b/arch/arm/kernel/fiqasm.S
74 @@ -25,6 +25,9 @@
75  ENTRY(__set_fiq_regs)
76         mov     r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE
77         mrs     r1, cpsr
78 +@@@@@@@@@@@@@@@ hack: enable the fiq here to keep usb driver happy
79 +       and     r1, #~PSR_F_BIT
80 +@@@@@@@@@@@@@@@ endhack: (need to find better place for this to happen)
81         msr     cpsr_c, r2      @ select FIQ mode
82         mov     r0, r0          @ avoid hazard prior to ARMv4
83         ldmia   r0!, {r8 - r12}
84 @@ -47,3 +50,7 @@ ENTRY(__get_fiq_regs)
85         mov     r0, r0          @ avoid hazard prior to ARMv4
86         mov     pc, lr
87  ENDPROC(__get_fiq_regs)
88 +
89 +ENTRY(__FIQ_Branch)
90 +       mov pc, r8
91 +ENDPROC(__FIQ_Branch)
92 diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c
93 index da18725..274aa30 100644
94 --- a/arch/arm/mach-bcm2708/armctrl.c
95 +++ b/arch/arm/mach-bcm2708/armctrl.c
96 @@ -52,8 +52,12 @@ static void armctrl_mask_irq(struct irq_data *d)
97                 0
98         };
99  
100 -       unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
101 -       writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
102 +       if (d->irq >= FIQ_START) {
103 +               writel(0, __io_address(ARM_IRQ_FAST));
104 +       } else {
105 +               unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
106 +               writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
107 +       }
108  }
109  
110  static void armctrl_unmask_irq(struct irq_data *d)
111 @@ -65,8 +69,14 @@ static void armctrl_unmask_irq(struct irq_data *d)
112                 0
113         };
114  
115 -       unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
116 -       writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
117 +       if (d->irq >= FIQ_START) {
118 +               unsigned int data =
119 +                   (unsigned int)irq_get_chip_data(d->irq) - FIQ_START;
120 +               writel(0x80 | data, __io_address(ARM_IRQ_FAST));
121 +       } else {
122 +               unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
123 +               writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
124 +       }
125  }
126  
127  #if defined(CONFIG_PM)
128 @@ -204,5 +214,6 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start,
129         }
130  
131         armctrl_pm_register(base, irq_start, resume_sources);
132 +       init_FIQ(FIQ_START);
133         return 0;
134  }
135 diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c
136 index 18f7ede..b9aa2de 100644
137 --- a/arch/arm/mach-bcm2708/bcm2708.c
138 +++ b/arch/arm/mach-bcm2708/bcm2708.c
139 @@ -309,12 +309,32 @@ static struct resource bcm2708_usb_resources[] = {
140                .flags = IORESOURCE_MEM,
141                },
142         [1] = {
143 -              .start = IRQ_USB,
144 -              .end = IRQ_USB,
145 +               .start = MPHI_BASE,
146 +               .end = MPHI_BASE + SZ_4K - 1,
147 +               .flags = IORESOURCE_MEM,
148 +             },
149 +       [2] = {
150 +              .start = IRQ_HOSTPORT,
151 +              .end = IRQ_HOSTPORT,
152                .flags = IORESOURCE_IRQ,
153                },
154  };
155  
156 +bool fiq_fix_enable = true;
157 +
158 +static struct resource bcm2708_usb_resources_no_fiq_fix[] = {
159 +       [0] = {
160 +               .start = USB_BASE,
161 +               .end = USB_BASE + SZ_128K - 1,
162 +               .flags = IORESOURCE_MEM,
163 +               },
164 +       [1] = {
165 +               .start = IRQ_USB,
166 +               .end = IRQ_USB,
167 +               .flags = IORESOURCE_IRQ,
168 +               },
169 +};
170 +
171  static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
172  
173  static struct platform_device bcm2708_usb_device = {
174 @@ -642,6 +662,11 @@ void __init bcm2708_init(void)
175  #endif
176         bcm_register_device(&bcm2708_systemtimer_device);
177         bcm_register_device(&bcm2708_fb_device);
178 +       if (!fiq_fix_enable)
179 +       {
180 +               bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix;
181 +               bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix);
182 +       }
183         bcm_register_device(&bcm2708_usb_device);
184         bcm_register_device(&bcm2708_uart1_device);
185         bcm_register_device(&bcm2708_powerman_device);
186 diff --git a/arch/arm/mach-bcm2708/include/mach/irqs.h b/arch/arm/mach-bcm2708/include/mach/irqs.h
187 index e8bb068..9aaedf1 100644
188 --- a/arch/arm/mach-bcm2708/include/mach/irqs.h
189 +++ b/arch/arm/mach-bcm2708/include/mach/irqs.h
190 @@ -106,91 +106,94 @@
191  #define IRQ_PENDING1          (IRQ_ARMCTRL_START + INTERRUPT_PENDING1)
192  #define IRQ_PENDING2          (IRQ_ARMCTRL_START + INTERRUPT_PENDING2)
193  
194 +#define FIQ_START             HARD_IRQS
195 +
196  /*
197   *  FIQ interrupts definitions are the same as the INT definitions.
198   */
199 -#define FIQ_TIMER0            INT_TIMER0
200 -#define FIQ_TIMER1            INT_TIMER1
201 -#define FIQ_TIMER2            INT_TIMER2
202 -#define FIQ_TIMER3            INT_TIMER3
203 -#define FIQ_CODEC0            INT_CODEC0
204 -#define FIQ_CODEC1            INT_CODEC1
205 -#define FIQ_CODEC2            INT_CODEC2
206 -#define FIQ_JPEG              INT_JPEG
207 -#define FIQ_ISP               INT_ISP
208 -#define FIQ_USB               INT_USB
209 -#define FIQ_3D                INT_3D
210 -#define FIQ_TRANSPOSER        INT_TRANSPOSER
211 -#define FIQ_MULTICORESYNC0    INT_MULTICORESYNC0
212 -#define FIQ_MULTICORESYNC1    INT_MULTICORESYNC1
213 -#define FIQ_MULTICORESYNC2    INT_MULTICORESYNC2
214 -#define FIQ_MULTICORESYNC3    INT_MULTICORESYNC3
215 -#define FIQ_DMA0              INT_DMA0
216 -#define FIQ_DMA1              INT_DMA1
217 -#define FIQ_DMA2              INT_DMA2
218 -#define FIQ_DMA3              INT_DMA3
219 -#define FIQ_DMA4              INT_DMA4
220 -#define FIQ_DMA5              INT_DMA5
221 -#define FIQ_DMA6              INT_DMA6
222 -#define FIQ_DMA7              INT_DMA7
223 -#define FIQ_DMA8              INT_DMA8
224 -#define FIQ_DMA9              INT_DMA9
225 -#define FIQ_DMA10             INT_DMA10
226 -#define FIQ_DMA11             INT_DMA11
227 -#define FIQ_DMA12             INT_DMA12
228 -#define FIQ_AUX               INT_AUX
229 -#define FIQ_ARM               INT_ARM
230 -#define FIQ_VPUDMA            INT_VPUDMA
231 -#define FIQ_HOSTPORT          INT_HOSTPORT
232 -#define FIQ_VIDEOSCALER       INT_VIDEOSCALER
233 -#define FIQ_CCP2TX            INT_CCP2TX
234 -#define FIQ_SDC               INT_SDC
235 -#define FIQ_DSI0              INT_DSI0
236 -#define FIQ_AVE               INT_AVE
237 -#define FIQ_CAM0              INT_CAM0
238 -#define FIQ_CAM1              INT_CAM1
239 -#define FIQ_HDMI0             INT_HDMI0
240 -#define FIQ_HDMI1             INT_HDMI1
241 -#define FIQ_PIXELVALVE1       INT_PIXELVALVE1
242 -#define FIQ_I2CSPISLV         INT_I2CSPISLV
243 -#define FIQ_DSI1              INT_DSI1
244 -#define FIQ_PWA0              INT_PWA0
245 -#define FIQ_PWA1              INT_PWA1
246 -#define FIQ_CPR               INT_CPR
247 -#define FIQ_SMI               INT_SMI
248 -#define FIQ_GPIO0             INT_GPIO0
249 -#define FIQ_GPIO1             INT_GPIO1
250 -#define FIQ_GPIO2             INT_GPIO2
251 -#define FIQ_GPIO3             INT_GPIO3
252 -#define FIQ_I2C               INT_I2C
253 -#define FIQ_SPI               INT_SPI
254 -#define FIQ_I2SPCM            INT_I2SPCM
255 -#define FIQ_SDIO              INT_SDIO
256 -#define FIQ_UART              INT_UART
257 -#define FIQ_SLIMBUS           INT_SLIMBUS
258 -#define FIQ_VEC               INT_VEC
259 -#define FIQ_CPG               INT_CPG
260 -#define FIQ_RNG               INT_RNG
261 -#define FIQ_ARASANSDIO        INT_ARASANSDIO
262 -#define FIQ_AVSPMON           INT_AVSPMON
263 +#define FIQ_TIMER0            (FIQ_START+INTERRUPT_TIMER0)
264 +#define FIQ_TIMER1            (FIQ_START+INTERRUPT_TIMER1)
265 +#define FIQ_TIMER2            (FIQ_START+INTERRUPT_TIMER2)
266 +#define FIQ_TIMER3            (FIQ_START+INTERRUPT_TIMER3)
267 +#define FIQ_CODEC0            (FIQ_START+INTERRUPT_CODEC0)
268 +#define FIQ_CODEC1            (FIQ_START+INTERRUPT_CODEC1)
269 +#define FIQ_CODEC2            (FIQ_START+INTERRUPT_CODEC2)
270 +#define FIQ_JPEG              (FIQ_START+INTERRUPT_JPEG)
271 +#define FIQ_ISP               (FIQ_START+INTERRUPT_ISP)
272 +#define FIQ_USB               (FIQ_START+INTERRUPT_USB)
273 +#define FIQ_3D                (FIQ_START+INTERRUPT_3D)
274 +#define FIQ_TRANSPOSER        (FIQ_START+INTERRUPT_TRANSPOSER)
275 +#define FIQ_MULTICORESYNC0    (FIQ_START+INTERRUPT_MULTICORESYNC0)
276 +#define FIQ_MULTICORESYNC1    (FIQ_START+INTERRUPT_MULTICORESYNC1)
277 +#define FIQ_MULTICORESYNC2    (FIQ_START+INTERRUPT_MULTICORESYNC2)
278 +#define FIQ_MULTICORESYNC3    (FIQ_START+INTERRUPT_MULTICORESYNC3)
279 +#define FIQ_DMA0              (FIQ_START+INTERRUPT_DMA0)
280 +#define FIQ_DMA1              (FIQ_START+INTERRUPT_DMA1)
281 +#define FIQ_DMA2              (FIQ_START+INTERRUPT_DMA2)
282 +#define FIQ_DMA3              (FIQ_START+INTERRUPT_DMA3)
283 +#define FIQ_DMA4              (FIQ_START+INTERRUPT_DMA4)
284 +#define FIQ_DMA5              (FIQ_START+INTERRUPT_DMA5)
285 +#define FIQ_DMA6              (FIQ_START+INTERRUPT_DMA6)
286 +#define FIQ_DMA7              (FIQ_START+INTERRUPT_DMA7)
287 +#define FIQ_DMA8              (FIQ_START+INTERRUPT_DMA8)
288 +#define FIQ_DMA9              (FIQ_START+INTERRUPT_DMA9)
289 +#define FIQ_DMA10             (FIQ_START+INTERRUPT_DMA10)
290 +#define FIQ_DMA11             (FIQ_START+INTERRUPT_DMA11)
291 +#define FIQ_DMA12             (FIQ_START+INTERRUPT_DMA12)
292 +#define FIQ_AUX               (FIQ_START+INTERRUPT_AUX)
293 +#define FIQ_ARM               (FIQ_START+INTERRUPT_ARM)
294 +#define FIQ_VPUDMA            (FIQ_START+INTERRUPT_VPUDMA)
295 +#define FIQ_HOSTPORT          (FIQ_START+INTERRUPT_HOSTPORT)
296 +#define FIQ_VIDEOSCALER       (FIQ_START+INTERRUPT_VIDEOSCALER)
297 +#define FIQ_CCP2TX            (FIQ_START+INTERRUPT_CCP2TX)
298 +#define FIQ_SDC               (FIQ_START+INTERRUPT_SDC)
299 +#define FIQ_DSI0              (FIQ_START+INTERRUPT_DSI0)
300 +#define FIQ_AVE               (FIQ_START+INTERRUPT_AVE)
301 +#define FIQ_CAM0              (FIQ_START+INTERRUPT_CAM0)
302 +#define FIQ_CAM1              (FIQ_START+INTERRUPT_CAM1)
303 +#define FIQ_HDMI0             (FIQ_START+INTERRUPT_HDMI0)
304 +#define FIQ_HDMI1             (FIQ_START+INTERRUPT_HDMI1)
305 +#define FIQ_PIXELVALVE1       (FIQ_START+INTERRUPT_PIXELVALVE1)
306 +#define FIQ_I2CSPISLV         (FIQ_START+INTERRUPT_I2CSPISLV)
307 +#define FIQ_DSI1              (FIQ_START+INTERRUPT_DSI1)
308 +#define FIQ_PWA0              (FIQ_START+INTERRUPT_PWA0)
309 +#define FIQ_PWA1              (FIQ_START+INTERRUPT_PWA1)
310 +#define FIQ_CPR               (FIQ_START+INTERRUPT_CPR)
311 +#define FIQ_SMI               (FIQ_START+INTERRUPT_SMI)
312 +#define FIQ_GPIO0             (FIQ_START+INTERRUPT_GPIO0)
313 +#define FIQ_GPIO1             (FIQ_START+INTERRUPT_GPIO1)
314 +#define FIQ_GPIO2             (FIQ_START+INTERRUPT_GPIO2)
315 +#define FIQ_GPIO3             (FIQ_START+INTERRUPT_GPIO3)
316 +#define FIQ_I2C               (FIQ_START+INTERRUPT_I2C)
317 +#define FIQ_SPI               (FIQ_START+INTERRUPT_SPI)
318 +#define FIQ_I2SPCM            (FIQ_START+INTERRUPT_I2SPCM)
319 +#define FIQ_SDIO              (FIQ_START+INTERRUPT_SDIO)
320 +#define FIQ_UART              (FIQ_START+INTERRUPT_UART)
321 +#define FIQ_SLIMBUS           (FIQ_START+INTERRUPT_SLIMBUS)
322 +#define FIQ_VEC               (FIQ_START+INTERRUPT_VEC)
323 +#define FIQ_CPG               (FIQ_START+INTERRUPT_CPG)
324 +#define FIQ_RNG               (FIQ_START+INTERRUPT_RNG)
325 +#define FIQ_ARASANSDIO        (FIQ_START+INTERRUPT_ARASANSDIO)
326 +#define FIQ_AVSPMON           (FIQ_START+INTERRUPT_AVSPMON)
327  
328 -#define FIQ_ARM_TIMER         INT_ARM_TIMER
329 -#define FIQ_ARM_MAILBOX       INT_ARM_MAILBOX
330 -#define FIQ_ARM_DOORBELL_0    INT_ARM_DOORBELL_0
331 -#define FIQ_ARM_DOORBELL_1    INT_ARM_DOORBELL_1
332 -#define FIQ_VPU0_HALTED       INT_VPU0_HALTED
333 -#define FIQ_VPU1_HALTED       INT_VPU1_HALTED
334 -#define FIQ_ILLEGAL_TYPE0     INT_ILLEGAL_TYPE0
335 -#define FIQ_ILLEGAL_TYPE1     INT_ILLEGAL_TYPE1
336 -#define FIQ_PENDING1          INT_PENDING1
337 -#define FIQ_PENDING2          INT_PENDING2
338 +#define FIQ_ARM_TIMER         (FIQ_START+INTERRUPT_ARM_TIMER)
339 +#define FIQ_ARM_MAILBOX       (FIQ_START+INTERRUPT_ARM_MAILBOX)
340 +#define FIQ_ARM_DOORBELL_0    (FIQ_START+INTERRUPT_ARM_DOORBELL_0)
341 +#define FIQ_ARM_DOORBELL_1    (FIQ_START+INTERRUPT_ARM_DOORBELL_1)
342 +#define FIQ_VPU0_HALTED       (FIQ_START+INTERRUPT_VPU0_HALTED)
343 +#define FIQ_VPU1_HALTED       (FIQ_START+INTERRUPT_VPU1_HALTED)
344 +#define FIQ_ILLEGAL_TYPE0     (FIQ_START+INTERRUPT_ILLEGAL_TYPE0)
345 +#define FIQ_ILLEGAL_TYPE1     (FIQ_START+INTERRUPT_ILLEGAL_TYPE1)
346 +#define FIQ_PENDING1          (FIQ_START+INTERRUPT_PENDING1)
347 +#define FIQ_PENDING2          (FIQ_START+INTERRUPT_PENDING2)
348  
349 -#define HARD_IRQS            (64 + 21)
350 -#define GPIO_IRQ_START       HARD_IRQS
351 +#define GPIO_IRQ_START       (HARD_IRQS + FIQ_IRQS)
352  
353 -#define GPIO_IRQS            32*5
354 +#define HARD_IRQS            (64 + 21)
355 +#define FIQ_IRQS              (64 + 21)
356 +#define GPIO_IRQS            (32*5)
357  
358 -#define NR_IRQS                      HARD_IRQS+GPIO_IRQS
359 +#define NR_IRQS                      HARD_IRQS+FIQ_IRQS+GPIO_IRQS
360  
361  
362  #endif /* _BCM2708_IRQS_H_ */
363 diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h
364 index 4d3c15d..89e72d1 100644
365 --- a/arch/arm/mach-bcm2708/include/mach/platform.h
366 +++ b/arch/arm/mach-bcm2708/include/mach/platform.h
367 @@ -56,7 +56,9 @@
368   */
369  
370  #define BCM2708_PERI_BASE        0x20000000
371 +#define IC0_BASE                 (BCM2708_PERI_BASE + 0x2000)
372  #define ST_BASE                  (BCM2708_PERI_BASE + 0x3000)   /* System Timer */
373 +#define MPHI_BASE               (BCM2708_PERI_BASE + 0x6000)   /* Message -based Parallel Host Interface */
374  #define DMA_BASE                (BCM2708_PERI_BASE + 0x7000)   /* DMA controller */
375  #define ARM_BASE                 (BCM2708_PERI_BASE + 0xB000)   /* BCM2708 ARM control block */
376  #define PM_BASE                         (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */
377 diff --git a/drivers/usb/host/dwc_otg/Makefile b/drivers/usb/host/dwc_otg/Makefile
378 index c4c6e4e..6bd6a2e 100644
379 --- a/drivers/usb/host/dwc_otg/Makefile
380 +++ b/drivers/usb/host/dwc_otg/Makefile
381 @@ -36,6 +36,7 @@ dwc_otg-objs  += dwc_otg_cil.o dwc_otg_cil_intr.o
382  dwc_otg-objs   += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o 
383  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
384  dwc_otg-objs   += dwc_otg_adp.o
385 +dwc_otg-objs   += dwc_otg_mphi_fix.o
386  ifneq ($(CFI),)
387  dwc_otg-objs   += dwc_otg_cfi.o
388  endif
389 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
390 index 21804c4..b861b55 100644
391 --- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
392 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
393 @@ -45,6 +45,9 @@
394  #include "dwc_otg_driver.h"
395  #include "dwc_otg_pcd.h"
396  #include "dwc_otg_hcd.h"
397 +#include "dwc_otg_mphi_fix.h"
398 +
399 +extern bool fiq_fix_enable;
400  
401  #ifdef DEBUG
402  inline const char *op_state_str(dwc_otg_core_if_t * core_if)
403 @@ -1351,10 +1354,15 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
404                             gintsts.d32, gintmsk.d32);
405         }
406  #endif
407 -       if (gahbcfg.b.glblintrmsk)      
408 +       if (!fiq_fix_enable){
409 +               if (gahbcfg.b.glblintrmsk)
410 +                       return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
411 +               else
412 +                       return 0;
413 +       }
414 +       else {
415                 return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
416 -       else
417 -               return 0;
418 +       }
419  
420  }
421  
422 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
423 index 8681aa9..2ff1532 100644
424 --- a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
425 +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
426 @@ -49,6 +49,7 @@ static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)
427         return old;
428  }
429  
430 +#define DBG_USER       (0x1)
431  /** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
432  #define DBG_CIL                (0x2)
433  /** When debug level has the DBG_CILV bit set, display CIL Verbose debug
434 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
435 index e7f99e1..3ac720b 100644
436 --- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
437 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
438 @@ -64,6 +64,8 @@ bool microframe_schedule=true;
439  
440  static const char dwc_driver_name[] = "dwc_otg";
441  
442 +extern void* dummy_send;
443 +
444  extern int pcd_init(
445  #ifdef LM_INTERFACE
446                            struct lm_device *_dev
447 @@ -238,6 +240,10 @@ static struct dwc_otg_driver_module_params dwc_otg_module_params = {
448         .adp_enable = -1,
449  };
450  
451 +//Global variable to switch the fiq fix on or off (declared in bcm2708.c)
452 +extern bool fiq_fix_enable;
453 +
454 +
455  /**
456   * This function shows the Driver Version.
457   */
458 @@ -779,17 +785,33 @@ static int dwc_otg_driver_probe(
459                      _dev->resource->start,
460                      _dev->resource->end - _dev->resource->start + 1);
461  #if 1
462 -        if (!request_mem_region(_dev->resource->start,
463 -                                _dev->resource->end - _dev->resource->start + 1,
464 +        if (!request_mem_region(_dev->resource[0].start,
465 +                                _dev->resource[0].end - _dev->resource[0].start + 1,
466                                  "dwc_otg")) {
467            dev_dbg(&_dev->dev, "error reserving mapped memory\n");
468            retval = -EFAULT;
469            goto fail;
470          }
471  
472 -       dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
473 -                                                      _dev->resource->end -
474 -                                                      _dev->resource->start+1);
475 +       dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start,
476 +                                                      _dev->resource[0].end -
477 +                                                      _dev->resource[0].start+1);
478 +       if (fiq_fix_enable)
479 +       {
480 +               if (!request_mem_region(_dev->resource[1].start,
481 +                                       _dev->resource[1].end - _dev->resource[1].start + 1,
482 +                                       "dwc_otg")) {
483 +                 dev_dbg(&_dev->dev, "error reserving mapped memory\n");
484 +                 retval = -EFAULT;
485 +                 goto fail;
486 +       }
487 +
488 +               dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
489 +                                                           _dev->resource[1].end -
490 +                                                           _dev->resource[1].start + 1);
491 +               dummy_send = (void *) kmalloc(16, GFP_ATOMIC);
492 +       }
493 +
494  #else
495          {
496                  struct map_desc desc = {
497 @@ -1063,6 +1085,7 @@ static int __init dwc_otg_driver_init(void)
498                 printk(KERN_ERR "%s retval=%d\n", __func__, retval);
499                 return retval;
500         }
501 +       printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");
502  
503         error = driver_create_file(drv, &driver_attr_version);
504  #ifdef DEBUG
505 @@ -1343,6 +1366,10 @@ MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");
506  module_param(microframe_schedule, bool, 0444);
507  MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
508  
509 +
510 +module_param(fiq_fix_enable, bool, 0444);
511 +MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");
512 +
513  /** @page "Module Parameters"
514   *
515   * The following parameters may be specified when starting the module.
516 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
517 index 434d0c4..20f989e 100644
518 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
519 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
520 @@ -53,6 +53,8 @@ static int last_sel_trans_num_avail_hc_at_start = 0;
521  static int last_sel_trans_num_avail_hc_at_end = 0;
522  #endif /* DEBUG_HOST_CHANNELS */
523  
524 +extern int g_next_sched_frame, g_np_count, g_np_sent;
525 +
526  dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
527  {
528         return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
529 @@ -407,6 +409,7 @@ static int dwc_otg_hcd_sleep_cb(void *p)
530  }
531  #endif
532  
533 +
534  /**
535   * HCD Callback function for Remote Wakeup.
536   *
537 @@ -1330,6 +1333,8 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
538                                    &qh->qh_list_entry);
539                 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
540  
541 +               g_np_sent++;
542 +
543                 if (ret_val == DWC_OTG_TRANSACTION_NONE) {
544                         ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
545                 } else {
546 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
547 index 8075595..dd30f47 100644
548 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
549 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
550 @@ -594,7 +594,7 @@ extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
551  /** @name Interrupt Handler Functions */
552  /** @{ */
553  extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
554 -extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
555 +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd, int32_t);
556  extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
557                                                          dwc_otg_hcd);
558  extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
559 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
560 index b3dc806..04ca4c2 100644
561 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
562 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
563 @@ -113,6 +113,11 @@ extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);
564   */
565  extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
566  
567 +/** This function is used to handle the fast interrupt
568 + *
569 + */
570 +extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void);
571 +
572  /**
573   * Returns private data set by
574   * dwc_otg_hcd_set_priv_data function.
575 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
576 index 63c1b55..f1658fa 100644
577 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
578 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
579 @@ -34,6 +34,11 @@
580  
581  #include "dwc_otg_hcd.h"
582  #include "dwc_otg_regs.h"
583 +#include "dwc_otg_mphi_fix.h"
584 +
585 +#include <linux/jiffies.h>
586 +#include <mach/hardware.h>
587 +
588  
589  extern bool microframe_schedule;
590  
591 @@ -41,36 +46,105 @@ extern bool microframe_schedule;
592   * This file contains the implementation of the HCD Interrupt handlers.
593   */
594  
595 +/*
596 + * Some globals to communicate between the FIQ and INTERRUPT
597 + */
598 +
599 +void * dummy_send;
600 +mphi_regs_t c_mphi_regs;
601 +int fiq_done, int_done;
602 +int g_next_sched_frame, g_np_count, g_np_sent, g_work_expected;
603 +static int mphi_int_count = 0 ;
604 +
605 +extern bool fiq_fix_enable;
606 +
607 +void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void)
608 +{
609 +       gintsts_data_t gintsts;
610 +       hfnum_data_t hfnum;
611 +
612 +       /* entry takes care to store registers we will be treading on here */
613 +       asm __volatile__ (
614 +               "mov     ip, sp ;"
615 +               /* stash FIQ and normal regs */
616 +               "stmdb  sp!, {r0-r12,  lr};"
617 +               /* !! THIS SETS THE FRAME, adjust to > sizeof locals */
618 +               "sub     fp, ip, #256 ;"
619 +               );
620 +
621 +       fiq_done++;
622 +       gintsts.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x14) & FIQ_READ_IO_ADDRESS(USB_BASE + 0x18);
623 +       hfnum.d32 =   FIQ_READ_IO_ADDRESS(USB_BASE + 0x408);
624 +
625 +       if(gintsts.d32)
626 +       {
627 +               if(gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
628 +               {
629 +                       /*
630 +                        * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet
631 +                        * g_next_sched_frame is the next frame we have periodic packets for
632 +                        *
633 +                        * if neither of these are required for this frame then just clear the interrupt
634 +                        */
635 +                       gintsts.d32 = 0;
636 +                       gintsts.b.sofintr = 1;
637 +                       FIQ_WRITE_IO_ADDRESS((USB_BASE + 0x14), gintsts.d32);
638 +
639 +                       g_work_expected = 0;
640 +               }
641 +               else
642 +               {
643 +                       g_work_expected = 1;
644 +                       /* To enable the MPHI interrupt  (INT 32)
645 +                        */
646 +                       FIQ_WRITE(  c_mphi_regs.outdda, (int) dummy_send);
647 +                       FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
648 +
649 +                       mphi_int_count++;
650 +                       /* Clear the USB global interrupt so we don't just sit in the FIQ */
651 +                       FIQ_MODIFY_IO_ADDRESS((USB_BASE + 0x8),1,0);
652 +
653 +               }
654 +       }
655 +       mb();
656 +
657 +       /* exit back to normal mode restoring everything */
658 +       asm __volatile__ (
659 +               /* return FIQ regs back to pristine state
660 +                * and get normal regs back
661 +                */
662 +               "ldmia  sp!, {r0-r12, lr};"
663 +
664 +               /* return */
665 +               "subs   pc, lr, #4;"
666 +       );
667 +}
668 +
669  /** This function handles interrupts for the HCD. */
670  int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
671  {
672         int retval = 0;
673 +       static int last_time;
674  
675         dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
676         gintsts_data_t gintsts;
677 +       hfnum_data_t hfnum;
678 +
679  #ifdef DEBUG
680         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
681  
682 -        //GRAYG: debugging
683 -        if (NULL == global_regs) {
684 -                DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
685 -                            "core_if=%p\n",
686 -                            dwc_otg_hcd, global_regs);
687 -                return retval;
688 -        }
689  #endif
690  
691         /* Exit from ISR if core is hibernated */
692         if (core_if->hibernation_suspend == 1) {
693 -               return retval;
694 +               goto exit_handler_routine;
695         }
696         DWC_SPINLOCK(dwc_otg_hcd->lock);
697         /* Check if HOST Mode */
698         if (dwc_otg_is_host_mode(core_if)) {
699                 gintsts.d32 = dwc_otg_read_core_intr(core_if);
700                 if (!gintsts.d32) {
701 -                       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
702 -                       return 0;
703 +                       goto exit_handler_routine;
704                 }
705  #ifdef DEBUG
706                 /* Don't print debug message in the interrupt handler on SOF */
707 @@ -88,9 +162,14 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
708                                     "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
709                                     gintsts.d32, core_if);
710  #endif
711 -
712 -               if (gintsts.b.sofintr) {
713 -                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
714 +               hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum);
715 +               if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
716 +               {
717 +                       /* Note, we should never get here if the FIQ is doing it's job properly*/
718 +                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected);
719 +               }
720 +               else if (gintsts.b.sofintr) {
721 +                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected);
722                 }
723                 if (gintsts.b.rxstsqlvl) {
724                         retval |=
725 @@ -138,11 +217,37 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
726  #endif
727  
728         }
729 +
730 +exit_handler_routine:
731 +
732 +       if (fiq_fix_enable)
733 +       {
734 +               /* Clear the MPHI interrupt */
735 +               DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));
736 +               if (mphi_int_count >= 60)
737 +               {
738 +                       DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));
739 +                       DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
740 +                       mphi_int_count = 0;
741 +               }
742 +                       int_done++;
743 +               if((jiffies / HZ) > last_time)
744 +               {
745 +                       /* Once a second output the fiq and irq numbers, useful for debug */
746 +                       last_time = jiffies / HZ;
747 +                       DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done);
748 +               }
749 +
750 +               /* Re-Enable FIQ interrupt from USB peripheral */
751 +               DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);
752 +       }
753 +
754         DWC_SPINUNLOCK(dwc_otg_hcd->lock);
755         return retval;
756  }
757  
758  #ifdef DWC_TRACK_MISSED_SOFS
759 +
760  #warning Compiling code to track missed SOFs
761  #define FRAME_NUM_ARRAY_SIZE 1000
762  /**
763 @@ -182,13 +287,15 @@ static inline void track_missed_sofs(uint16_t curr_frame_number)
764   * (micro)frame. Periodic transactions may be queued to the controller for the
765   * next (micro)frame.
766   */
767 -int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
768 +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected)
769  {
770         hfnum_data_t hfnum;
771         dwc_list_link_t *qh_entry;
772         dwc_otg_qh_t *qh;
773         dwc_otg_transaction_type_e tr_type;
774         gintsts_data_t gintsts = {.d32 = 0 };
775 +       int did_something = 0;
776 +       int32_t next_sched_frame = -1;
777  
778         hfnum.d32 =
779             DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
780 @@ -218,12 +325,30 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
781                          */
782                         DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
783                                            &qh->qh_list_entry);
784 +
785 +                       did_something = 1;
786 +               }
787 +               else
788 +               {
789 +                       if(next_sched_frame < 0 || dwc_frame_num_le(qh->sched_frame, next_sched_frame))
790 +                       {
791 +                               next_sched_frame = qh->sched_frame;
792 +                       }
793                 }
794         }
795 +
796 +       g_next_sched_frame = next_sched_frame;
797 +
798         tr_type = dwc_otg_hcd_select_transactions(hcd);
799         if (tr_type != DWC_OTG_TRANSACTION_NONE) {
800                 dwc_otg_hcd_queue_transactions(hcd, tr_type);
801 +               did_something = 1;
802         }
803 +       if(work_expected && !did_something)
804 +               DWC_DEBUGPL(DBG_USER, "Nothing to do !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame);
805 +       if(!work_expected && did_something)
806 +               DWC_DEBUGPL(DBG_USER, "Unexpected work done !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame);
807 +
808  
809         /* Clear interrupt */
810         gintsts.b.sofintr = 1;
811 @@ -2102,5 +2227,4 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
812  
813         return retval;
814  }
815 -
816  #endif /* DWC_DEVICE_ONLY */
817 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
818 index 4a985a6..9702f81 100644
819 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
820 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
821 @@ -1,3 +1,4 @@
822 +
823  /* ==========================================================================
824   * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
825   * $Revision: #20 $
826 @@ -50,6 +51,7 @@
827  #include <linux/dma-mapping.h>
828  #include <linux/version.h>
829  #include <asm/io.h>
830 +#include <asm/fiq.h>
831  #include <linux/usb.h>
832  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
833  #include <../drivers/usb/core/hcd.h>
834 @@ -67,6 +69,8 @@
835  #include "dwc_otg_dbg.h"
836  #include "dwc_otg_driver.h"
837  #include "dwc_otg_hcd.h"
838 +#include "dwc_otg_mphi_fix.h"
839 +
840  /**
841   * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
842   * qualified with its direction (possible 32 endpoints per device).
843 @@ -76,6 +80,8 @@
844  
845  static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
846  
847 +extern bool fiq_fix_enable;
848 +
849  /** @name Linux HC Driver API Functions */
850  /** @{ */
851  /* manage i/o requests, device state */
852 @@ -366,6 +372,12 @@ static struct dwc_otg_hcd_function_ops hcd_fops = {
853         .get_b_hnp_enable = _get_b_hnp_enable,
854  };
855  
856 +static struct fiq_handler fh = {
857 +  .name = "usb_fiq",
858 +};
859 +static uint8_t fiqStack[1024];
860 +
861 +extern mphi_regs_t c_mphi_regs;
862  /**
863   * Initializes the HCD. This function allocates memory for and initializes the
864   * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
865 @@ -379,6 +391,7 @@ int hcd_init(dwc_bus_dev_t *_dev)
866         dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
867         int retval = 0;
868          u64 dmamask;
869 +       struct pt_regs regs;
870  
871         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
872  
873 @@ -396,6 +409,18 @@ int hcd_init(dwc_bus_dev_t *_dev)
874          pci_set_consistent_dma_mask(_dev, dmamask);
875  #endif
876  
877 +       if (fiq_fix_enable)
878 +       {
879 +               // Set up fiq
880 +               claim_fiq(&fh);
881 +               set_fiq_handler(__FIQ_Branch, 4);
882 +               memset(&regs,0,sizeof(regs));
883 +               regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq;
884 +               regs.ARM_r9 = (long)0;
885 +               regs.ARM_sp = (long)fiqStack + sizeof(fiqStack) - 4;
886 +               set_fiq_regs(&regs);
887 +               }
888 +
889         /*
890          * Allocate memory for the base HCD plus the DWC OTG HCD.
891          * Initialize the base HCD.
892 @@ -415,6 +440,26 @@ int hcd_init(dwc_bus_dev_t *_dev)
893  
894         hcd->regs = otg_dev->os_dep.base;
895  
896 +       if (fiq_fix_enable)
897 +       {
898 +               //Set the mphi periph to  the required registers
899 +               c_mphi_regs.base    = otg_dev->os_dep.mphi_base;
900 +               c_mphi_regs.ctrl    = otg_dev->os_dep.mphi_base + 0x4c;
901 +               c_mphi_regs.outdda  = otg_dev->os_dep.mphi_base + 0x28;
902 +               c_mphi_regs.outddb  = otg_dev->os_dep.mphi_base + 0x2c;
903 +               c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
904 +
905 +               //Enable mphi peripheral
906 +               writel((1<<31),c_mphi_regs.ctrl);
907 +#ifdef DEBUG
908 +               if (readl(c_mphi_regs.ctrl) & 0x80000000)
909 +                       DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n");
910 +               else
911 +                       DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n");
912 +#endif
913 +               // Enable FIQ interrupt from USB peripheral
914 +               enable_fiq(INTERRUPT_VC_USB);
915 +       }
916         /* Initialize the DWC OTG HCD. */
917         dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
918         if (!dwc_otg_hcd) {
919 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
920 index 08c1669..ac10323 100644
921 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
922 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
923 @@ -572,6 +572,9 @@ static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
924         return status;
925  }
926  
927 +
928 +extern int g_next_sched_frame, g_np_count, g_np_sent;
929 +
930  /**
931   * Schedules an interrupt or isochronous transfer in the periodic schedule.
932   *
933 @@ -630,8 +633,13 @@ static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
934                 DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
935         }
936         else {
937 -       /* Always start in the inactive schedule. */
938 -       DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
939 +               if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame))
940 +               {
941 +                       g_next_sched_frame = qh->sched_frame;
942 +
943 +               }
944 +               /* Always start in the inactive schedule. */
945 +               DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
946         }
947  
948         if (!microframe_schedule) {
949 @@ -645,6 +653,7 @@ static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
950         return status;
951  }
952  
953 +
954  /**
955   * This function adds a QH to either the non periodic or periodic schedule if
956   * it is not already in the schedule. If the QH is already in the schedule, no
957 @@ -667,6 +676,7 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
958                 /* Always start in the inactive schedule. */
959                 DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
960                                      &qh->qh_list_entry);
961 +               g_np_count++;
962         } else {
963                 status = schedule_periodic(hcd, qh);
964                 if ( !hcd->periodic_qh_count ) {
965 @@ -767,6 +777,7 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
966                         if (sched_next_periodic_split) {
967  
968                                 qh->sched_frame = frame_number;
969 +
970                                 if (dwc_frame_num_le(frame_number,
971                                                      dwc_frame_num_inc
972                                                      (qh->start_split_frame,
973 @@ -815,6 +826,11 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
974                                 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
975                                                    &qh->qh_list_entry);
976                         } else {
977 +                               if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame))
978 +                               {
979 +                                       g_next_sched_frame = qh->sched_frame;
980 +                               }
981 +
982                                 DWC_LIST_MOVE_HEAD
983                                     (&hcd->periodic_sched_inactive,
984                                      &qh->qh_list_entry);
985 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
986 new file mode 100755
987 index 0000000..b70ca68
988 --- /dev/null
989 +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
990 @@ -0,0 +1,113 @@
991 +#include "dwc_otg_regs.h"
992 +#include "dwc_otg_dbg.h"
993 +
994 +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name)
995 +{
996 +       DWC_DEBUGPL(DBG_USER,   "*** Debugging from within the %s  function: ***\n"
997 +                               "curmode:     %1i    Modemismatch: %1i    otgintr:    %1i    sofintr:    %1i\n"
998 +                               "rxstsqlvl:   %1i    nptxfempty  : %1i    ginnakeff:  %1i    goutnakeff: %1i\n"
999 +                               "ulpickint:   %1i    i2cintr:      %1i    erlysuspend:%1i    usbsuspend: %1i\n"
1000 +                               "usbreset:    %1i    enumdone:     %1i    isooutdrop: %1i    eopframe:   %1i\n"
1001 +                               "restoredone: %1i    epmismatch:   %1i    inepint:    %1i    outepintr:  %1i\n"
1002 +                               "incomplisoin:%1i    incomplisoout:%1i    fetsusp:    %1i    resetdet:   %1i\n"
1003 +                               "portintr:    %1i    hcintr:       %1i    ptxfempty:  %1i    lpmtranrcvd:%1i\n"
1004 +                               "conidstschng:%1i    disconnect:   %1i    sessreqintr:%1i    wkupintr:   %1i\n",
1005 +                               function_name,
1006 +                               gintsts.b.curmode,
1007 +                               gintsts.b.modemismatch,
1008 +                               gintsts.b.otgintr,
1009 +                               gintsts.b.sofintr,
1010 +                               gintsts.b.rxstsqlvl,
1011 +                               gintsts.b.nptxfempty,
1012 +                               gintsts.b.ginnakeff,
1013 +                               gintsts.b.goutnakeff,
1014 +                               gintsts.b.ulpickint,
1015 +                               gintsts.b.i2cintr,
1016 +                               gintsts.b.erlysuspend,
1017 +                               gintsts.b.usbsuspend,
1018 +                               gintsts.b.usbreset,
1019 +                               gintsts.b.enumdone,
1020 +                               gintsts.b.isooutdrop,
1021 +                               gintsts.b.eopframe,
1022 +                               gintsts.b.restoredone,
1023 +                               gintsts.b.epmismatch,
1024 +                               gintsts.b.inepint,
1025 +                               gintsts.b.outepintr,
1026 +                               gintsts.b.incomplisoin,
1027 +                               gintsts.b.incomplisoout,
1028 +                               gintsts.b.fetsusp,
1029 +                               gintsts.b.resetdet,
1030 +                               gintsts.b.portintr,
1031 +                               gintsts.b.hcintr,
1032 +                               gintsts.b.ptxfempty,
1033 +                               gintsts.b.lpmtranrcvd,
1034 +                               gintsts.b.conidstschng,
1035 +                               gintsts.b.disconnect,
1036 +                               gintsts.b.sessreqintr,
1037 +                               gintsts.b.wkupintr);
1038 +       return;
1039 +}
1040 +
1041 +void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name)
1042 +{
1043 +       DWC_DEBUGPL(DBG_USER,   "Interrupt Mask status (called from %s) :\n"
1044 +                               "modemismatch: %1i     otgintr:    %1i    sofintr:    %1i    rxstsqlvl:   %1i\n"
1045 +                               "nptxfempty:   %1i     ginnakeff:  %1i    goutnakeff: %1i    ulpickint:   %1i\n"
1046 +                               "i2cintr:      %1i     erlysuspend:%1i    usbsuspend: %1i    usbreset:    %1i\n"
1047 +                               "enumdone:     %1i     isooutdrop: %1i    eopframe:   %1i    restoredone: %1i\n"
1048 +                               "epmismatch:   %1i     inepintr:   %1i    outepintr:  %1i    incomplisoin:%1i\n"
1049 +                               "incomplisoout:%1i     fetsusp:    %1i    resetdet:   %1i    portintr:    %1i\n"
1050 +                               "hcintr:       %1i     ptxfempty:  %1i    lpmtranrcvd:%1i    conidstschng:%1i\n"
1051 +                               "disconnect:   %1i     sessreqintr:%1i    wkupintr:   %1i\n",
1052 +                               function_name,
1053 +                               gintmsk.b.modemismatch,
1054 +                               gintmsk.b.otgintr,
1055 +                               gintmsk.b.sofintr,
1056 +                               gintmsk.b.rxstsqlvl,
1057 +                               gintmsk.b.nptxfempty,
1058 +                               gintmsk.b.ginnakeff,
1059 +                               gintmsk.b.goutnakeff,
1060 +                               gintmsk.b.ulpickint,
1061 +                               gintmsk.b.i2cintr,
1062 +                               gintmsk.b.erlysuspend,
1063 +                               gintmsk.b.usbsuspend,
1064 +                               gintmsk.b.usbreset,
1065 +                               gintmsk.b.enumdone,
1066 +                               gintmsk.b.isooutdrop,
1067 +                               gintmsk.b.eopframe,
1068 +                               gintmsk.b.restoredone,
1069 +                               gintmsk.b.epmismatch,
1070 +                               gintmsk.b.inepintr,
1071 +                               gintmsk.b.outepintr,
1072 +                               gintmsk.b.incomplisoin,
1073 +                               gintmsk.b.incomplisoout,
1074 +                               gintmsk.b.fetsusp,
1075 +                               gintmsk.b.resetdet,
1076 +                               gintmsk.b.portintr,
1077 +                               gintmsk.b.hcintr,
1078 +                               gintmsk.b.ptxfempty,
1079 +                               gintmsk.b.lpmtranrcvd,
1080 +                               gintmsk.b.conidstschng,
1081 +                               gintmsk.b.disconnect,
1082 +                               gintmsk.b.sessreqintr,
1083 +                               gintmsk.b.wkupintr);
1084 +       return;
1085 +}
1086
1087 +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name)
1088 +{
1089 +       DWC_DEBUGPL(DBG_USER,   "otg int register (from %s function):\n"
1090 +                               "sesenddet:%1i    sesreqsucstschung:%2i    hstnegsucstschng:%1i\n"
1091 +                               "hstnegdet:%1i    adevtoutchng:     %2i    debdone:         %1i\n"
1092 +                               "mvic:     %1i\n",
1093 +                               function_name,
1094 +                               gotgint.b.sesenddet,
1095 +                               gotgint.b.sesreqsucstschng,
1096 +                               gotgint.b.hstnegsucstschng,
1097 +                               gotgint.b.hstnegdet,
1098 +                               gotgint.b.adevtoutchng,
1099 +                               gotgint.b.debdone,
1100 +                               gotgint.b.mvic);
1101 +
1102 +       return;
1103 +}
1104 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
1105 new file mode 100755
1106 index 0000000..22f28e1
1107 --- /dev/null
1108 +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
1109 @@ -0,0 +1,36 @@
1110 +#ifndef __DWC_OTG_MPHI_FIX_H__
1111 +#define __DWC_OTG_MPHI_FIX_H__
1112 +
1113 +#define FIQ_WRITE_IO_ADDRESS(_addr_,_data_) *(volatile uint32_t *) IO_ADDRESS(_addr_) = _data_
1114 +#define FIQ_READ_IO_ADDRESS(_addr_) *(volatile uint32_t *) IO_ADDRESS(_addr_) 
1115 +#define FIQ_MODIFY_IO_ADDRESS(_addr_,_clear_,_set_) FIQ_WRITE_IO_ADDRESS(_addr_ , (FIQ_READ_IO_ADDRESS(_addr_)&~_clear_)|_set_)
1116 +#define FIQ_WRITE(_addr_,_data_) *(volatile uint32_t *) _addr_ = _data_
1117 +
1118 +typedef struct {
1119 +       volatile void* base;
1120 +       volatile void* ctrl;
1121 +       volatile void* outdda;
1122 +       volatile void* outddb;
1123 +       volatile void* intstat;
1124 +} mphi_regs_t; 
1125 +
1126 +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name);
1127 +void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name);
1128 +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);
1129 +
1130 +
1131 +
1132 +#ifdef DEBUG
1133 +#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__)
1134 +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__)
1135 +#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__)
1136 +
1137 +#else
1138 +#define DWC_DBG_PRINT_CORE_INT(_arg_)
1139 +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_)
1140 +#define DWC_DBG_PRINT_OTG_INT(_arg_)
1141 +
1142 +
1143 +#endif
1144 +
1145 +#endif
1146 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
1147 index a7e9076..bb1c42d 100644
1148 --- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
1149 +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
1150 @@ -97,6 +97,9 @@ typedef struct os_dependent {
1151         /** Register offset for Diagnostic API */
1152         uint32_t reg_offset;
1153  
1154 +       /** Base address for MPHI peripheral */
1155 +       void *mphi_base;
1156 +
1157  #ifdef LM_INTERFACE
1158         struct lm_device *lmdev;
1159  #elif  defined(PCI_INTERFACE)
1160 -- 
1161 1.9.1
1162