aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.10/0027-Add-FIQ-patch-to-dwc_otg-driver.-Enable-with-dwc_otg.patch
blob: 8fe0f6756be2542a6e5ab36c7d1a9367e5909226 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
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)