brcm2708: update against latest rpi-3.10.y branch
[openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0027-Add-FIQ-patch-to-dwc_otg-driver.-Enable-with-dwc_otg.patch
diff --git a/target/linux/brcm2708/patches-3.10/0027-Add-FIQ-patch-to-dwc_otg-driver.-Enable-with-dwc_otg.patch b/target/linux/brcm2708/patches-3.10/0027-Add-FIQ-patch-to-dwc_otg-driver.-Enable-with-dwc_otg.patch
new file mode 100644 (file)
index 0000000..8fe0f67
--- /dev/null
@@ -0,0 +1,1116 @@
+From c80392fbbb9a09f035f66a7d2a9fed2469373210 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Wed, 3 Jul 2013 00:46:42 +0100
+Subject: [PATCH 027/174] Add FIQ patch to dwc_otg driver. Enable with
+ dwc_otg.fiq_fix_enable=1. Should give about 10% more ARM performance. Thanks
+ to Gordon and Costas
+
+---
+ arch/arm/Kconfig                              |   1 +
+ arch/arm/include/asm/fiq.h                    |   1 +
+ arch/arm/kernel/fiq.c                         |   1 +
+ arch/arm/kernel/fiqasm.S                      |   7 ++
+ arch/arm/mach-bcm2708/armctrl.c               |  19 ++-
+ arch/arm/mach-bcm2708/bcm2708.c               |  29 ++++-
+ arch/arm/mach-bcm2708/include/mach/irqs.h     | 159 +++++++++++++-------------
+ arch/arm/mach-bcm2708/include/mach/platform.h |   2 +
+ drivers/usb/host/dwc_otg/Makefile             |   1 +
+ drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c   |  14 ++-
+ drivers/usb/host/dwc_otg/dwc_otg_dbg.h        |   1 +
+ drivers/usb/host/dwc_otg/dwc_otg_driver.c     |  37 +++++-
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c        |   5 +
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.h        |   2 +-
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h     |   5 +
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c   | 154 ++++++++++++++++++++++---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c  |  45 ++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c  |  20 +++-
+ drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c   | 113 ++++++++++++++++++
+ drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h   |  36 ++++++
+ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h     |   3 +
+ 21 files changed, 545 insertions(+), 110 deletions(-)
+ create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
+ create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
+
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -373,6 +373,7 @@ config ARCH_BCM2708
+       select ARM_ERRATA_411920
+       select MACH_BCM2708
+       select VC4
++      select FIQ
+       help
+         This enables support for Broadcom BCM2708 boards.
+--- a/arch/arm/include/asm/fiq.h
++++ b/arch/arm/include/asm/fiq.h
+@@ -42,6 +42,7 @@ extern void disable_fiq(int fiq);
+ /* helpers defined in fiqasm.S: */
+ extern void __set_fiq_regs(unsigned long const *regs);
+ extern void __get_fiq_regs(unsigned long *regs);
++extern void __FIQ_Branch(unsigned long *regs);
+ static inline void set_fiq_regs(struct pt_regs const *regs)
+ {
+--- a/arch/arm/kernel/fiq.c
++++ b/arch/arm/kernel/fiq.c
+@@ -141,6 +141,7 @@ void disable_fiq(int fiq)
+ EXPORT_SYMBOL(set_fiq_handler);
+ EXPORT_SYMBOL(__set_fiq_regs);        /* defined in fiqasm.S */
+ EXPORT_SYMBOL(__get_fiq_regs);        /* defined in fiqasm.S */
++EXPORT_SYMBOL(__FIQ_Branch);  /* defined in fiqasm.S */
+ EXPORT_SYMBOL(claim_fiq);
+ EXPORT_SYMBOL(release_fiq);
+ EXPORT_SYMBOL(enable_fiq);
+--- a/arch/arm/kernel/fiqasm.S
++++ b/arch/arm/kernel/fiqasm.S
+@@ -25,6 +25,9 @@
+ ENTRY(__set_fiq_regs)
+       mov     r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE
+       mrs     r1, cpsr
++@@@@@@@@@@@@@@@ hack: enable the fiq here to keep usb driver happy
++      and     r1, #~PSR_F_BIT
++@@@@@@@@@@@@@@@ endhack: (need to find better place for this to happen)
+       msr     cpsr_c, r2      @ select FIQ mode
+       mov     r0, r0          @ avoid hazard prior to ARMv4
+       ldmia   r0!, {r8 - r12}
+@@ -47,3 +50,7 @@ ENTRY(__get_fiq_regs)
+       mov     r0, r0          @ avoid hazard prior to ARMv4
+       mov     pc, lr
+ ENDPROC(__get_fiq_regs)
++
++ENTRY(__FIQ_Branch)
++      mov pc, r8
++ENDPROC(__FIQ_Branch)
+--- a/arch/arm/mach-bcm2708/armctrl.c
++++ b/arch/arm/mach-bcm2708/armctrl.c
+@@ -52,8 +52,12 @@ static void armctrl_mask_irq(struct irq_
+               0
+       };
+-      unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
+-      writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
++      if (d->irq >= FIQ_START) {
++              writel(0, __io_address(ARM_IRQ_FAST));
++      } else {
++              unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
++              writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
++      }
+ }
+ static void armctrl_unmask_irq(struct irq_data *d)
+@@ -65,8 +69,14 @@ static void armctrl_unmask_irq(struct ir
+               0
+       };
+-      unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
+-      writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
++      if (d->irq >= FIQ_START) {
++              unsigned int data =
++                  (unsigned int)irq_get_chip_data(d->irq) - FIQ_START;
++              writel(0x80 | data, __io_address(ARM_IRQ_FAST));
++      } else {
++              unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
++              writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
++      }
+ }
+ #if defined(CONFIG_PM)
+@@ -204,5 +214,6 @@ int __init armctrl_init(void __iomem * b
+       }
+       armctrl_pm_register(base, irq_start, resume_sources);
++      init_FIQ(FIQ_START);
+       return 0;
+ }
+--- a/arch/arm/mach-bcm2708/bcm2708.c
++++ b/arch/arm/mach-bcm2708/bcm2708.c
+@@ -309,12 +309,32 @@ static struct resource bcm2708_usb_resou
+              .flags = IORESOURCE_MEM,
+              },
+       [1] = {
+-             .start = IRQ_USB,
+-             .end = IRQ_USB,
++              .start = MPHI_BASE,
++              .end = MPHI_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++            },
++      [2] = {
++             .start = IRQ_HOSTPORT,
++             .end = IRQ_HOSTPORT,
+              .flags = IORESOURCE_IRQ,
+              },
+ };
++bool fiq_fix_enable = true;
++
++static struct resource bcm2708_usb_resources_no_fiq_fix[] = {
++      [0] = {
++              .start = USB_BASE,
++              .end = USB_BASE + SZ_128K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      [1] = {
++              .start = IRQ_USB,
++              .end = IRQ_USB,
++              .flags = IORESOURCE_IRQ,
++              },
++};
++
+ static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+ static struct platform_device bcm2708_usb_device = {
+@@ -642,6 +662,11 @@ void __init bcm2708_init(void)
+ #endif
+       bcm_register_device(&bcm2708_systemtimer_device);
+       bcm_register_device(&bcm2708_fb_device);
++      if (!fiq_fix_enable)
++      {
++              bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix;
++              bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix);
++      }
+       bcm_register_device(&bcm2708_usb_device);
+       bcm_register_device(&bcm2708_uart1_device);
+       bcm_register_device(&bcm2708_powerman_device);
+--- a/arch/arm/mach-bcm2708/include/mach/irqs.h
++++ b/arch/arm/mach-bcm2708/include/mach/irqs.h
+@@ -106,91 +106,94 @@
+ #define IRQ_PENDING1          (IRQ_ARMCTRL_START + INTERRUPT_PENDING1)
+ #define IRQ_PENDING2          (IRQ_ARMCTRL_START + INTERRUPT_PENDING2)
++#define FIQ_START             HARD_IRQS
++
+ /*
+  *  FIQ interrupts definitions are the same as the INT definitions.
+  */
+-#define FIQ_TIMER0            INT_TIMER0
+-#define FIQ_TIMER1            INT_TIMER1
+-#define FIQ_TIMER2            INT_TIMER2
+-#define FIQ_TIMER3            INT_TIMER3
+-#define FIQ_CODEC0            INT_CODEC0
+-#define FIQ_CODEC1            INT_CODEC1
+-#define FIQ_CODEC2            INT_CODEC2
+-#define FIQ_JPEG              INT_JPEG
+-#define FIQ_ISP               INT_ISP
+-#define FIQ_USB               INT_USB
+-#define FIQ_3D                INT_3D
+-#define FIQ_TRANSPOSER        INT_TRANSPOSER
+-#define FIQ_MULTICORESYNC0    INT_MULTICORESYNC0
+-#define FIQ_MULTICORESYNC1    INT_MULTICORESYNC1
+-#define FIQ_MULTICORESYNC2    INT_MULTICORESYNC2
+-#define FIQ_MULTICORESYNC3    INT_MULTICORESYNC3
+-#define FIQ_DMA0              INT_DMA0
+-#define FIQ_DMA1              INT_DMA1
+-#define FIQ_DMA2              INT_DMA2
+-#define FIQ_DMA3              INT_DMA3
+-#define FIQ_DMA4              INT_DMA4
+-#define FIQ_DMA5              INT_DMA5
+-#define FIQ_DMA6              INT_DMA6
+-#define FIQ_DMA7              INT_DMA7
+-#define FIQ_DMA8              INT_DMA8
+-#define FIQ_DMA9              INT_DMA9
+-#define FIQ_DMA10             INT_DMA10
+-#define FIQ_DMA11             INT_DMA11
+-#define FIQ_DMA12             INT_DMA12
+-#define FIQ_AUX               INT_AUX
+-#define FIQ_ARM               INT_ARM
+-#define FIQ_VPUDMA            INT_VPUDMA
+-#define FIQ_HOSTPORT          INT_HOSTPORT
+-#define FIQ_VIDEOSCALER       INT_VIDEOSCALER
+-#define FIQ_CCP2TX            INT_CCP2TX
+-#define FIQ_SDC               INT_SDC
+-#define FIQ_DSI0              INT_DSI0
+-#define FIQ_AVE               INT_AVE
+-#define FIQ_CAM0              INT_CAM0
+-#define FIQ_CAM1              INT_CAM1
+-#define FIQ_HDMI0             INT_HDMI0
+-#define FIQ_HDMI1             INT_HDMI1
+-#define FIQ_PIXELVALVE1       INT_PIXELVALVE1
+-#define FIQ_I2CSPISLV         INT_I2CSPISLV
+-#define FIQ_DSI1              INT_DSI1
+-#define FIQ_PWA0              INT_PWA0
+-#define FIQ_PWA1              INT_PWA1
+-#define FIQ_CPR               INT_CPR
+-#define FIQ_SMI               INT_SMI
+-#define FIQ_GPIO0             INT_GPIO0
+-#define FIQ_GPIO1             INT_GPIO1
+-#define FIQ_GPIO2             INT_GPIO2
+-#define FIQ_GPIO3             INT_GPIO3
+-#define FIQ_I2C               INT_I2C
+-#define FIQ_SPI               INT_SPI
+-#define FIQ_I2SPCM            INT_I2SPCM
+-#define FIQ_SDIO              INT_SDIO
+-#define FIQ_UART              INT_UART
+-#define FIQ_SLIMBUS           INT_SLIMBUS
+-#define FIQ_VEC               INT_VEC
+-#define FIQ_CPG               INT_CPG
+-#define FIQ_RNG               INT_RNG
+-#define FIQ_ARASANSDIO        INT_ARASANSDIO
+-#define FIQ_AVSPMON           INT_AVSPMON
+-
+-#define FIQ_ARM_TIMER         INT_ARM_TIMER
+-#define FIQ_ARM_MAILBOX       INT_ARM_MAILBOX
+-#define FIQ_ARM_DOORBELL_0    INT_ARM_DOORBELL_0
+-#define FIQ_ARM_DOORBELL_1    INT_ARM_DOORBELL_1
+-#define FIQ_VPU0_HALTED       INT_VPU0_HALTED
+-#define FIQ_VPU1_HALTED       INT_VPU1_HALTED
+-#define FIQ_ILLEGAL_TYPE0     INT_ILLEGAL_TYPE0
+-#define FIQ_ILLEGAL_TYPE1     INT_ILLEGAL_TYPE1
+-#define FIQ_PENDING1          INT_PENDING1
+-#define FIQ_PENDING2          INT_PENDING2
++#define FIQ_TIMER0            (FIQ_START+INTERRUPT_TIMER0)
++#define FIQ_TIMER1            (FIQ_START+INTERRUPT_TIMER1)
++#define FIQ_TIMER2            (FIQ_START+INTERRUPT_TIMER2)
++#define FIQ_TIMER3            (FIQ_START+INTERRUPT_TIMER3)
++#define FIQ_CODEC0            (FIQ_START+INTERRUPT_CODEC0)
++#define FIQ_CODEC1            (FIQ_START+INTERRUPT_CODEC1)
++#define FIQ_CODEC2            (FIQ_START+INTERRUPT_CODEC2)
++#define FIQ_JPEG              (FIQ_START+INTERRUPT_JPEG)
++#define FIQ_ISP               (FIQ_START+INTERRUPT_ISP)
++#define FIQ_USB               (FIQ_START+INTERRUPT_USB)
++#define FIQ_3D                (FIQ_START+INTERRUPT_3D)
++#define FIQ_TRANSPOSER        (FIQ_START+INTERRUPT_TRANSPOSER)
++#define FIQ_MULTICORESYNC0    (FIQ_START+INTERRUPT_MULTICORESYNC0)
++#define FIQ_MULTICORESYNC1    (FIQ_START+INTERRUPT_MULTICORESYNC1)
++#define FIQ_MULTICORESYNC2    (FIQ_START+INTERRUPT_MULTICORESYNC2)
++#define FIQ_MULTICORESYNC3    (FIQ_START+INTERRUPT_MULTICORESYNC3)
++#define FIQ_DMA0              (FIQ_START+INTERRUPT_DMA0)
++#define FIQ_DMA1              (FIQ_START+INTERRUPT_DMA1)
++#define FIQ_DMA2              (FIQ_START+INTERRUPT_DMA2)
++#define FIQ_DMA3              (FIQ_START+INTERRUPT_DMA3)
++#define FIQ_DMA4              (FIQ_START+INTERRUPT_DMA4)
++#define FIQ_DMA5              (FIQ_START+INTERRUPT_DMA5)
++#define FIQ_DMA6              (FIQ_START+INTERRUPT_DMA6)
++#define FIQ_DMA7              (FIQ_START+INTERRUPT_DMA7)
++#define FIQ_DMA8              (FIQ_START+INTERRUPT_DMA8)
++#define FIQ_DMA9              (FIQ_START+INTERRUPT_DMA9)
++#define FIQ_DMA10             (FIQ_START+INTERRUPT_DMA10)
++#define FIQ_DMA11             (FIQ_START+INTERRUPT_DMA11)
++#define FIQ_DMA12             (FIQ_START+INTERRUPT_DMA12)
++#define FIQ_AUX               (FIQ_START+INTERRUPT_AUX)
++#define FIQ_ARM               (FIQ_START+INTERRUPT_ARM)
++#define FIQ_VPUDMA            (FIQ_START+INTERRUPT_VPUDMA)
++#define FIQ_HOSTPORT          (FIQ_START+INTERRUPT_HOSTPORT)
++#define FIQ_VIDEOSCALER       (FIQ_START+INTERRUPT_VIDEOSCALER)
++#define FIQ_CCP2TX            (FIQ_START+INTERRUPT_CCP2TX)
++#define FIQ_SDC               (FIQ_START+INTERRUPT_SDC)
++#define FIQ_DSI0              (FIQ_START+INTERRUPT_DSI0)
++#define FIQ_AVE               (FIQ_START+INTERRUPT_AVE)
++#define FIQ_CAM0              (FIQ_START+INTERRUPT_CAM0)
++#define FIQ_CAM1              (FIQ_START+INTERRUPT_CAM1)
++#define FIQ_HDMI0             (FIQ_START+INTERRUPT_HDMI0)
++#define FIQ_HDMI1             (FIQ_START+INTERRUPT_HDMI1)
++#define FIQ_PIXELVALVE1       (FIQ_START+INTERRUPT_PIXELVALVE1)
++#define FIQ_I2CSPISLV         (FIQ_START+INTERRUPT_I2CSPISLV)
++#define FIQ_DSI1              (FIQ_START+INTERRUPT_DSI1)
++#define FIQ_PWA0              (FIQ_START+INTERRUPT_PWA0)
++#define FIQ_PWA1              (FIQ_START+INTERRUPT_PWA1)
++#define FIQ_CPR               (FIQ_START+INTERRUPT_CPR)
++#define FIQ_SMI               (FIQ_START+INTERRUPT_SMI)
++#define FIQ_GPIO0             (FIQ_START+INTERRUPT_GPIO0)
++#define FIQ_GPIO1             (FIQ_START+INTERRUPT_GPIO1)
++#define FIQ_GPIO2             (FIQ_START+INTERRUPT_GPIO2)
++#define FIQ_GPIO3             (FIQ_START+INTERRUPT_GPIO3)
++#define FIQ_I2C               (FIQ_START+INTERRUPT_I2C)
++#define FIQ_SPI               (FIQ_START+INTERRUPT_SPI)
++#define FIQ_I2SPCM            (FIQ_START+INTERRUPT_I2SPCM)
++#define FIQ_SDIO              (FIQ_START+INTERRUPT_SDIO)
++#define FIQ_UART              (FIQ_START+INTERRUPT_UART)
++#define FIQ_SLIMBUS           (FIQ_START+INTERRUPT_SLIMBUS)
++#define FIQ_VEC               (FIQ_START+INTERRUPT_VEC)
++#define FIQ_CPG               (FIQ_START+INTERRUPT_CPG)
++#define FIQ_RNG               (FIQ_START+INTERRUPT_RNG)
++#define FIQ_ARASANSDIO        (FIQ_START+INTERRUPT_ARASANSDIO)
++#define FIQ_AVSPMON           (FIQ_START+INTERRUPT_AVSPMON)
++
++#define FIQ_ARM_TIMER         (FIQ_START+INTERRUPT_ARM_TIMER)
++#define FIQ_ARM_MAILBOX       (FIQ_START+INTERRUPT_ARM_MAILBOX)
++#define FIQ_ARM_DOORBELL_0    (FIQ_START+INTERRUPT_ARM_DOORBELL_0)
++#define FIQ_ARM_DOORBELL_1    (FIQ_START+INTERRUPT_ARM_DOORBELL_1)
++#define FIQ_VPU0_HALTED       (FIQ_START+INTERRUPT_VPU0_HALTED)
++#define FIQ_VPU1_HALTED       (FIQ_START+INTERRUPT_VPU1_HALTED)
++#define FIQ_ILLEGAL_TYPE0     (FIQ_START+INTERRUPT_ILLEGAL_TYPE0)
++#define FIQ_ILLEGAL_TYPE1     (FIQ_START+INTERRUPT_ILLEGAL_TYPE1)
++#define FIQ_PENDING1          (FIQ_START+INTERRUPT_PENDING1)
++#define FIQ_PENDING2          (FIQ_START+INTERRUPT_PENDING2)
+-#define HARD_IRQS           (64 + 21)
+-#define GPIO_IRQ_START              HARD_IRQS
++#define GPIO_IRQ_START              (HARD_IRQS + FIQ_IRQS)
+-#define GPIO_IRQS           32*5
++#define HARD_IRQS           (64 + 21)
++#define FIQ_IRQS              (64 + 21)
++#define GPIO_IRQS           (32*5)
+-#define NR_IRQS                     HARD_IRQS+GPIO_IRQS
++#define NR_IRQS                     HARD_IRQS+FIQ_IRQS+GPIO_IRQS
+ #endif /* _BCM2708_IRQS_H_ */
+--- a/arch/arm/mach-bcm2708/include/mach/platform.h
++++ b/arch/arm/mach-bcm2708/include/mach/platform.h
+@@ -56,7 +56,9 @@
+  */
+ #define BCM2708_PERI_BASE        0x20000000
++#define IC0_BASE                 (BCM2708_PERI_BASE + 0x2000)
+ #define ST_BASE                  (BCM2708_PERI_BASE + 0x3000)   /* System Timer */
++#define MPHI_BASE              (BCM2708_PERI_BASE + 0x6000)   /* Message -based Parallel Host Interface */
+ #define DMA_BASE               (BCM2708_PERI_BASE + 0x7000)   /* DMA controller */
+ #define ARM_BASE                 (BCM2708_PERI_BASE + 0xB000)  /* BCM2708 ARM control block */
+ #define PM_BASE                        (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */
+--- a/drivers/usb/host/dwc_otg/Makefile
++++ b/drivers/usb/host/dwc_otg/Makefile
+@@ -36,6 +36,7 @@ dwc_otg-objs += dwc_otg_cil.o dwc_otg_ci
+ dwc_otg-objs  += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o 
+ 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
+ dwc_otg-objs  += dwc_otg_adp.o
++dwc_otg-objs  += dwc_otg_mphi_fix.o
+ ifneq ($(CFI),)
+ dwc_otg-objs  += dwc_otg_cfi.o
+ endif
+--- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
+@@ -45,6 +45,9 @@
+ #include "dwc_otg_driver.h"
+ #include "dwc_otg_pcd.h"
+ #include "dwc_otg_hcd.h"
++#include "dwc_otg_mphi_fix.h"
++
++extern bool fiq_fix_enable;
+ #ifdef DEBUG
+ inline const char *op_state_str(dwc_otg_core_if_t * core_if)
+@@ -1351,10 +1354,15 @@ static inline uint32_t dwc_otg_read_comm
+                           gintsts.d32, gintmsk.d32);
+       }
+ #endif
+-      if (gahbcfg.b.glblintrmsk)      
++      if (!fiq_fix_enable){
++              if (gahbcfg.b.glblintrmsk)
++                      return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
++              else
++                      return 0;
++      }
++      else {
+               return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
+-      else
+-              return 0;
++      }
+ }
+--- a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
+@@ -49,6 +49,7 @@ static inline uint32_t SET_DEBUG_LEVEL(c
+       return old;
+ }
++#define DBG_USER      (0x1)
+ /** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
+ #define DBG_CIL               (0x2)
+ /** When debug level has the DBG_CILV bit set, display CIL Verbose debug
+--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+@@ -64,6 +64,8 @@ bool microframe_schedule=true;
+ static const char dwc_driver_name[] = "dwc_otg";
++extern void* dummy_send;
++
+ extern int pcd_init(
+ #ifdef LM_INTERFACE
+                          struct lm_device *_dev
+@@ -238,6 +240,10 @@ static struct dwc_otg_driver_module_para
+       .adp_enable = -1,
+ };
++//Global variable to switch the fiq fix on or off (declared in bcm2708.c)
++extern bool fiq_fix_enable;
++
++
+ /**
+  * This function shows the Driver Version.
+  */
+@@ -779,17 +785,33 @@ static int dwc_otg_driver_probe(
+                     _dev->resource->start,
+                     _dev->resource->end - _dev->resource->start + 1);
+ #if 1
+-        if (!request_mem_region(_dev->resource->start,
+-                                _dev->resource->end - _dev->resource->start + 1,
++        if (!request_mem_region(_dev->resource[0].start,
++                                _dev->resource[0].end - _dev->resource[0].start + 1,
+                                 "dwc_otg")) {
+           dev_dbg(&_dev->dev, "error reserving mapped memory\n");
+           retval = -EFAULT;
+           goto fail;
+         }
+-      dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
+-                                                      _dev->resource->end -
+-                                                      _dev->resource->start+1);
++      dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start,
++                                                      _dev->resource[0].end -
++                                                      _dev->resource[0].start+1);
++      if (fiq_fix_enable)
++      {
++              if (!request_mem_region(_dev->resource[1].start,
++                                      _dev->resource[1].end - _dev->resource[1].start + 1,
++                                      "dwc_otg")) {
++                dev_dbg(&_dev->dev, "error reserving mapped memory\n");
++                retval = -EFAULT;
++                goto fail;
++      }
++
++              dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
++                                                          _dev->resource[1].end -
++                                                          _dev->resource[1].start + 1);
++              dummy_send = (void *) kmalloc(16, GFP_ATOMIC);
++      }
++
+ #else
+         {
+                 struct map_desc desc = {
+@@ -1063,6 +1085,7 @@ static int __init dwc_otg_driver_init(vo
+               printk(KERN_ERR "%s retval=%d\n", __func__, retval);
+               return retval;
+       }
++      printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");
+       error = driver_create_file(drv, &driver_attr_version);
+ #ifdef DEBUG
+@@ -1343,6 +1366,10 @@ MODULE_PARM_DESC(otg_ver, "OTG revision
+ module_param(microframe_schedule, bool, 0444);
+ MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
++
++module_param(fiq_fix_enable, bool, 0444);
++MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");
++
+ /** @page "Module Parameters"
+  *
+  * The following parameters may be specified when starting the module.
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -53,6 +53,8 @@ static int last_sel_trans_num_avail_hc_a
+ static int last_sel_trans_num_avail_hc_at_end = 0;
+ #endif /* DEBUG_HOST_CHANNELS */
++extern int g_next_sched_frame, g_np_count, g_np_sent;
++
+ dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
+ {
+       return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
+@@ -407,6 +409,7 @@ static int dwc_otg_hcd_sleep_cb(void *p)
+ }
+ #endif
++
+ /**
+  * HCD Callback function for Remote Wakeup.
+  *
+@@ -1330,6 +1333,8 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
+                                  &qh->qh_list_entry);
+               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
++              g_np_sent++;
++
+               if (ret_val == DWC_OTG_TRANSACTION_NONE) {
+                       ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
+               } else {
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
+@@ -594,7 +594,7 @@ extern void dwc_otg_hcd_queue_transactio
+ /** @name Interrupt Handler Functions */
+ /** @{ */
+ extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
+-extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
++extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd, int32_t);
+ extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
+                                                        dwc_otg_hcd);
+ extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
+@@ -113,6 +113,11 @@ extern void dwc_otg_hcd_remove(dwc_otg_h
+  */
+ extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
++/** This function is used to handle the fast interrupt
++ *
++ */
++extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void);
++
+ /**
+  * Returns private data set by
+  * dwc_otg_hcd_set_priv_data function.
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+@@ -34,6 +34,11 @@
+ #include "dwc_otg_hcd.h"
+ #include "dwc_otg_regs.h"
++#include "dwc_otg_mphi_fix.h"
++
++#include <linux/jiffies.h>
++#include <mach/hardware.h>
++
+ extern bool microframe_schedule;
+@@ -41,36 +46,105 @@ extern bool microframe_schedule;
+  * This file contains the implementation of the HCD Interrupt handlers.
+  */
++/*
++ * Some globals to communicate between the FIQ and INTERRUPT
++ */
++
++void * dummy_send;
++mphi_regs_t c_mphi_regs;
++int fiq_done, int_done;
++int g_next_sched_frame, g_np_count, g_np_sent, g_work_expected;
++static int mphi_int_count = 0 ;
++
++extern bool fiq_fix_enable;
++
++void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void)
++{
++      gintsts_data_t gintsts;
++      hfnum_data_t hfnum;
++
++      /* entry takes care to store registers we will be treading on here */
++      asm __volatile__ (
++              "mov     ip, sp ;"
++              /* stash FIQ and normal regs */
++              "stmdb  sp!, {r0-r12,  lr};"
++              /* !! THIS SETS THE FRAME, adjust to > sizeof locals */
++              "sub     fp, ip, #256 ;"
++              );
++
++      fiq_done++;
++      gintsts.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x14) & FIQ_READ_IO_ADDRESS(USB_BASE + 0x18);
++      hfnum.d32 =   FIQ_READ_IO_ADDRESS(USB_BASE + 0x408);
++
++      if(gintsts.d32)
++      {
++              if(gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
++              {
++                      /*
++                       * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet
++                       * g_next_sched_frame is the next frame we have periodic packets for
++                       *
++                       * if neither of these are required for this frame then just clear the interrupt
++                       */
++                      gintsts.d32 = 0;
++                      gintsts.b.sofintr = 1;
++                      FIQ_WRITE_IO_ADDRESS((USB_BASE + 0x14), gintsts.d32);
++
++                      g_work_expected = 0;
++              }
++              else
++              {
++                      g_work_expected = 1;
++                      /* To enable the MPHI interrupt  (INT 32)
++                       */
++                      FIQ_WRITE(  c_mphi_regs.outdda, (int) dummy_send);
++                      FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
++
++                      mphi_int_count++;
++                      /* Clear the USB global interrupt so we don't just sit in the FIQ */
++                      FIQ_MODIFY_IO_ADDRESS((USB_BASE + 0x8),1,0);
++
++              }
++      }
++      mb();
++
++      /* exit back to normal mode restoring everything */
++      asm __volatile__ (
++              /* return FIQ regs back to pristine state
++               * and get normal regs back
++               */
++              "ldmia  sp!, {r0-r12, lr};"
++
++              /* return */
++              "subs   pc, lr, #4;"
++      );
++}
++
+ /** This function handles interrupts for the HCD. */
+ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
+ {
+       int retval = 0;
++      static int last_time;
+       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
+       gintsts_data_t gintsts;
++      hfnum_data_t hfnum;
++
+ #ifdef DEBUG
+       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+-        //GRAYG: debugging
+-        if (NULL == global_regs) {
+-                DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
+-                            "core_if=%p\n",
+-                            dwc_otg_hcd, global_regs);
+-                return retval;
+-        }
+ #endif
+       /* Exit from ISR if core is hibernated */
+       if (core_if->hibernation_suspend == 1) {
+-              return retval;
++              goto exit_handler_routine;
+       }
+       DWC_SPINLOCK(dwc_otg_hcd->lock);
+       /* Check if HOST Mode */
+       if (dwc_otg_is_host_mode(core_if)) {
+               gintsts.d32 = dwc_otg_read_core_intr(core_if);
+               if (!gintsts.d32) {
+-                      DWC_SPINUNLOCK(dwc_otg_hcd->lock);
+-                      return 0;
++                      goto exit_handler_routine;
+               }
+ #ifdef DEBUG
+               /* Don't print debug message in the interrupt handler on SOF */
+@@ -88,9 +162,14 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
+                                   "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
+                                   gintsts.d32, core_if);
+ #endif
+-
+-              if (gintsts.b.sofintr) {
+-                      retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
++              hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum);
++              if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
++              {
++                      /* Note, we should never get here if the FIQ is doing it's job properly*/
++                      retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected);
++              }
++              else if (gintsts.b.sofintr) {
++                      retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected);
+               }
+               if (gintsts.b.rxstsqlvl) {
+                       retval |=
+@@ -138,11 +217,37 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
+ #endif
+       }
++
++exit_handler_routine:
++
++      if (fiq_fix_enable)
++      {
++              /* Clear the MPHI interrupt */
++              DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));
++              if (mphi_int_count >= 60)
++              {
++                      DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));
++                      DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
++                      mphi_int_count = 0;
++              }
++                      int_done++;
++              if((jiffies / HZ) > last_time)
++              {
++                      /* Once a second output the fiq and irq numbers, useful for debug */
++                      last_time = jiffies / HZ;
++                      DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done);
++              }
++
++              /* Re-Enable FIQ interrupt from USB peripheral */
++              DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);
++      }
++
+       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
+       return retval;
+ }
+ #ifdef DWC_TRACK_MISSED_SOFS
++
+ #warning Compiling code to track missed SOFs
+ #define FRAME_NUM_ARRAY_SIZE 1000
+ /**
+@@ -182,13 +287,15 @@ static inline void track_missed_sofs(uin
+  * (micro)frame. Periodic transactions may be queued to the controller for the
+  * next (micro)frame.
+  */
+-int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
++int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected)
+ {
+       hfnum_data_t hfnum;
+       dwc_list_link_t *qh_entry;
+       dwc_otg_qh_t *qh;
+       dwc_otg_transaction_type_e tr_type;
+       gintsts_data_t gintsts = {.d32 = 0 };
++      int did_something = 0;
++      int32_t next_sched_frame = -1;
+       hfnum.d32 =
+           DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
+@@ -218,12 +325,30 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_
+                        */
+                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
+                                          &qh->qh_list_entry);
++
++                      did_something = 1;
++              }
++              else
++              {
++                      if(next_sched_frame < 0 || dwc_frame_num_le(qh->sched_frame, next_sched_frame))
++                      {
++                              next_sched_frame = qh->sched_frame;
++                      }
+               }
+       }
++
++      g_next_sched_frame = next_sched_frame;
++
+       tr_type = dwc_otg_hcd_select_transactions(hcd);
+       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
+               dwc_otg_hcd_queue_transactions(hcd, tr_type);
++              did_something = 1;
+       }
++      if(work_expected && !did_something)
++              DWC_DEBUGPL(DBG_USER, "Nothing to do !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame);
++      if(!work_expected && did_something)
++              DWC_DEBUGPL(DBG_USER, "Unexpected work done !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame);
++
+       /* Clear interrupt */
+       gintsts.b.sofintr = 1;
+@@ -2102,5 +2227,4 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
+       return retval;
+ }
+-
+ #endif /* DWC_DEVICE_ONLY */
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -1,3 +1,4 @@
++
+ /* ==========================================================================
+  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
+  * $Revision: #20 $
+@@ -50,6 +51,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/version.h>
+ #include <asm/io.h>
++#include <asm/fiq.h>
+ #include <linux/usb.h>
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+ #include <../drivers/usb/core/hcd.h>
+@@ -67,6 +69,8 @@
+ #include "dwc_otg_dbg.h"
+ #include "dwc_otg_driver.h"
+ #include "dwc_otg_hcd.h"
++#include "dwc_otg_mphi_fix.h"
++
+ /**
+  * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
+  * qualified with its direction (possible 32 endpoints per device).
+@@ -76,6 +80,8 @@
+ static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
++extern bool fiq_fix_enable;
++
+ /** @name Linux HC Driver API Functions */
+ /** @{ */
+ /* manage i/o requests, device state */
+@@ -366,6 +372,12 @@ static struct dwc_otg_hcd_function_ops h
+       .get_b_hnp_enable = _get_b_hnp_enable,
+ };
++static struct fiq_handler fh = {
++  .name = "usb_fiq",
++};
++static uint8_t fiqStack[1024];
++
++extern mphi_regs_t c_mphi_regs;
+ /**
+  * Initializes the HCD. This function allocates memory for and initializes the
+  * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
+@@ -379,6 +391,7 @@ int hcd_init(dwc_bus_dev_t *_dev)
+       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
+       int retval = 0;
+         u64 dmamask;
++      struct pt_regs regs;
+       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
+@@ -396,6 +409,18 @@ int hcd_init(dwc_bus_dev_t *_dev)
+         pci_set_consistent_dma_mask(_dev, dmamask);
+ #endif
++      if (fiq_fix_enable)
++      {
++              // Set up fiq
++              claim_fiq(&fh);
++              set_fiq_handler(__FIQ_Branch, 4);
++              memset(&regs,0,sizeof(regs));
++              regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq;
++              regs.ARM_r9 = (long)0;
++              regs.ARM_sp = (long)fiqStack + sizeof(fiqStack) - 4;
++              set_fiq_regs(&regs);
++              }
++
+       /*
+        * Allocate memory for the base HCD plus the DWC OTG HCD.
+        * Initialize the base HCD.
+@@ -415,6 +440,26 @@ int hcd_init(dwc_bus_dev_t *_dev)
+       hcd->regs = otg_dev->os_dep.base;
++      if (fiq_fix_enable)
++      {
++              //Set the mphi periph to  the required registers
++              c_mphi_regs.base    = otg_dev->os_dep.mphi_base;
++              c_mphi_regs.ctrl    = otg_dev->os_dep.mphi_base + 0x4c;
++              c_mphi_regs.outdda  = otg_dev->os_dep.mphi_base + 0x28;
++              c_mphi_regs.outddb  = otg_dev->os_dep.mphi_base + 0x2c;
++              c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
++
++              //Enable mphi peripheral
++              writel((1<<31),c_mphi_regs.ctrl);
++#ifdef DEBUG
++              if (readl(c_mphi_regs.ctrl) & 0x80000000)
++                      DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n");
++              else
++                      DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n");
++#endif
++              // Enable FIQ interrupt from USB peripheral
++              enable_fiq(INTERRUPT_VC_USB);
++      }
+       /* Initialize the DWC OTG HCD. */
+       dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
+       if (!dwc_otg_hcd) {
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
+@@ -572,6 +572,9 @@ static int check_max_xfer_size(dwc_otg_h
+       return status;
+ }
++
++extern int g_next_sched_frame, g_np_count, g_np_sent;
++
+ /**
+  * Schedules an interrupt or isochronous transfer in the periodic schedule.
+  *
+@@ -630,8 +633,13 @@ static int schedule_periodic(dwc_otg_hcd
+               DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
+       }
+       else {
+-      /* Always start in the inactive schedule. */
+-      DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
++              if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame))
++              {
++                      g_next_sched_frame = qh->sched_frame;
++
++              }
++              /* Always start in the inactive schedule. */
++              DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
+       }
+       if (!microframe_schedule) {
+@@ -645,6 +653,7 @@ static int schedule_periodic(dwc_otg_hcd
+       return status;
+ }
++
+ /**
+  * This function adds a QH to either the non periodic or periodic schedule if
+  * it is not already in the schedule. If the QH is already in the schedule, no
+@@ -667,6 +676,7 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * h
+               /* Always start in the inactive schedule. */
+               DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
+                                    &qh->qh_list_entry);
++              g_np_count++;
+       } else {
+               status = schedule_periodic(hcd, qh);
+               if ( !hcd->periodic_qh_count ) {
+@@ -767,6 +777,7 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_h
+                       if (sched_next_periodic_split) {
+                               qh->sched_frame = frame_number;
++
+                               if (dwc_frame_num_le(frame_number,
+                                                    dwc_frame_num_inc
+                                                    (qh->start_split_frame,
+@@ -815,6 +826,11 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_h
+                               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
+                                                  &qh->qh_list_entry);
+                       } else {
++                              if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame))
++                              {
++                                      g_next_sched_frame = qh->sched_frame;
++                              }
++
+                               DWC_LIST_MOVE_HEAD
+                                   (&hcd->periodic_sched_inactive,
+                                    &qh->qh_list_entry);
+--- /dev/null
++++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
+@@ -0,0 +1,113 @@
++#include "dwc_otg_regs.h"
++#include "dwc_otg_dbg.h"
++
++void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name)
++{
++      DWC_DEBUGPL(DBG_USER,   "*** Debugging from within the %s  function: ***\n"
++                              "curmode:     %1i    Modemismatch: %1i    otgintr:    %1i    sofintr:    %1i\n"
++                              "rxstsqlvl:   %1i    nptxfempty  : %1i    ginnakeff:  %1i    goutnakeff: %1i\n"
++                              "ulpickint:   %1i    i2cintr:      %1i    erlysuspend:%1i    usbsuspend: %1i\n"
++                              "usbreset:    %1i    enumdone:     %1i    isooutdrop: %1i    eopframe:   %1i\n"
++                              "restoredone: %1i    epmismatch:   %1i    inepint:    %1i    outepintr:  %1i\n"
++                              "incomplisoin:%1i    incomplisoout:%1i    fetsusp:    %1i    resetdet:   %1i\n"
++                              "portintr:    %1i    hcintr:       %1i    ptxfempty:  %1i    lpmtranrcvd:%1i\n"
++                              "conidstschng:%1i    disconnect:   %1i    sessreqintr:%1i    wkupintr:   %1i\n",
++                              function_name,
++                              gintsts.b.curmode,
++                              gintsts.b.modemismatch,
++                              gintsts.b.otgintr,
++                              gintsts.b.sofintr,
++                              gintsts.b.rxstsqlvl,
++                              gintsts.b.nptxfempty,
++                              gintsts.b.ginnakeff,
++                              gintsts.b.goutnakeff,
++                              gintsts.b.ulpickint,
++                              gintsts.b.i2cintr,
++                              gintsts.b.erlysuspend,
++                              gintsts.b.usbsuspend,
++                              gintsts.b.usbreset,
++                              gintsts.b.enumdone,
++                              gintsts.b.isooutdrop,
++                              gintsts.b.eopframe,
++                              gintsts.b.restoredone,
++                              gintsts.b.epmismatch,
++                              gintsts.b.inepint,
++                              gintsts.b.outepintr,
++                              gintsts.b.incomplisoin,
++                              gintsts.b.incomplisoout,
++                              gintsts.b.fetsusp,
++                              gintsts.b.resetdet,
++                              gintsts.b.portintr,
++                              gintsts.b.hcintr,
++                              gintsts.b.ptxfempty,
++                              gintsts.b.lpmtranrcvd,
++                              gintsts.b.conidstschng,
++                              gintsts.b.disconnect,
++                              gintsts.b.sessreqintr,
++                              gintsts.b.wkupintr);
++      return;
++}
++
++void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name)
++{
++      DWC_DEBUGPL(DBG_USER,   "Interrupt Mask status (called from %s) :\n"
++                              "modemismatch: %1i     otgintr:    %1i    sofintr:    %1i    rxstsqlvl:   %1i\n"
++                              "nptxfempty:   %1i     ginnakeff:  %1i    goutnakeff: %1i    ulpickint:   %1i\n"
++                              "i2cintr:      %1i     erlysuspend:%1i    usbsuspend: %1i    usbreset:    %1i\n"
++                              "enumdone:     %1i     isooutdrop: %1i    eopframe:   %1i    restoredone: %1i\n"
++                              "epmismatch:   %1i     inepintr:   %1i    outepintr:  %1i    incomplisoin:%1i\n"
++                              "incomplisoout:%1i     fetsusp:    %1i    resetdet:   %1i    portintr:    %1i\n"
++                              "hcintr:       %1i     ptxfempty:  %1i    lpmtranrcvd:%1i    conidstschng:%1i\n"
++                              "disconnect:   %1i     sessreqintr:%1i    wkupintr:   %1i\n",
++                              function_name,
++                              gintmsk.b.modemismatch,
++                              gintmsk.b.otgintr,
++                              gintmsk.b.sofintr,
++                              gintmsk.b.rxstsqlvl,
++                              gintmsk.b.nptxfempty,
++                              gintmsk.b.ginnakeff,
++                              gintmsk.b.goutnakeff,
++                              gintmsk.b.ulpickint,
++                              gintmsk.b.i2cintr,
++                              gintmsk.b.erlysuspend,
++                              gintmsk.b.usbsuspend,
++                              gintmsk.b.usbreset,
++                              gintmsk.b.enumdone,
++                              gintmsk.b.isooutdrop,
++                              gintmsk.b.eopframe,
++                              gintmsk.b.restoredone,
++                              gintmsk.b.epmismatch,
++                              gintmsk.b.inepintr,
++                              gintmsk.b.outepintr,
++                              gintmsk.b.incomplisoin,
++                              gintmsk.b.incomplisoout,
++                              gintmsk.b.fetsusp,
++                              gintmsk.b.resetdet,
++                              gintmsk.b.portintr,
++                              gintmsk.b.hcintr,
++                              gintmsk.b.ptxfempty,
++                              gintmsk.b.lpmtranrcvd,
++                              gintmsk.b.conidstschng,
++                              gintmsk.b.disconnect,
++                              gintmsk.b.sessreqintr,
++                              gintmsk.b.wkupintr);
++      return;
++}
++ 
++void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name)
++{
++      DWC_DEBUGPL(DBG_USER,   "otg int register (from %s function):\n"
++                              "sesenddet:%1i    sesreqsucstschung:%2i    hstnegsucstschng:%1i\n"
++                              "hstnegdet:%1i    adevtoutchng:     %2i    debdone:         %1i\n"
++                              "mvic:     %1i\n",
++                              function_name,
++                              gotgint.b.sesenddet,
++                              gotgint.b.sesreqsucstschng,
++                              gotgint.b.hstnegsucstschng,
++                              gotgint.b.hstnegdet,
++                              gotgint.b.adevtoutchng,
++                              gotgint.b.debdone,
++                              gotgint.b.mvic);
++
++      return;
++}
+--- /dev/null
++++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
+@@ -0,0 +1,36 @@
++#ifndef __DWC_OTG_MPHI_FIX_H__
++#define __DWC_OTG_MPHI_FIX_H__
++
++#define FIQ_WRITE_IO_ADDRESS(_addr_,_data_) *(volatile uint32_t *) IO_ADDRESS(_addr_) = _data_
++#define FIQ_READ_IO_ADDRESS(_addr_) *(volatile uint32_t *) IO_ADDRESS(_addr_) 
++#define FIQ_MODIFY_IO_ADDRESS(_addr_,_clear_,_set_) FIQ_WRITE_IO_ADDRESS(_addr_ , (FIQ_READ_IO_ADDRESS(_addr_)&~_clear_)|_set_)
++#define FIQ_WRITE(_addr_,_data_) *(volatile uint32_t *) _addr_ = _data_
++
++typedef struct {
++      volatile void* base;
++      volatile void* ctrl;
++      volatile void* outdda;
++      volatile void* outddb;
++      volatile void* intstat;
++} mphi_regs_t; 
++
++void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name);
++void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name);
++void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);
++
++
++
++#ifdef DEBUG
++#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__)
++#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__)
++#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__)
++
++#else
++#define DWC_DBG_PRINT_CORE_INT(_arg_)
++#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_)
++#define DWC_DBG_PRINT_OTG_INT(_arg_)
++
++
++#endif
++
++#endif
+--- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+@@ -97,6 +97,9 @@ typedef struct os_dependent {
+       /** Register offset for Diagnostic API */
+       uint32_t reg_offset;
++      /** Base address for MPHI peripheral */
++      void *mphi_base;
++
+ #ifdef LM_INTERFACE
+       struct lm_device *lmdev;
+ #elif  defined(PCI_INTERFACE)