brcm2708: update 3.10 patches with raspberrypi/rpi-3.10.y of 27 Apr. 2014
[openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0072-USB-fix-using-a-FIQ-to-implement-split-transactions.patch
1 From 0b8275da8346466af37b50d5ba687a386df9b0f4 Mon Sep 17 00:00:00 2001
2 From: Gordon Hollingworth <gordon@holliweb.co.uk>
3 Date: Thu, 4 Apr 2013 11:05:21 +0100
4 Subject: [PATCH 072/196] USB fix using a FIQ to implement split transactions
5
6 This commit adds a FIQ implementaion that schedules
7 the split transactions using a FIQ so we don't get
8 held off by the interrupt latency of Linux
9 ---
10  .../usb/host/dwc_common_port/dwc_common_linux.c    |   7 +-
11  drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c        |  37 +-
12  drivers/usb/host/dwc_otg/dwc_otg_driver.c          |   6 +-
13  drivers/usb/host/dwc_otg/dwc_otg_hcd.c             | 125 ++++-
14  drivers/usb/host/dwc_otg/dwc_otg_hcd.h             |  20 +-
15  drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c        | 538 ++++++++++++++++++---
16  drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c       |  18 +-
17  drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c       |  31 +-
18  drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h        |  26 +-
19  drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c        |   2 +-
20  10 files changed, 696 insertions(+), 114 deletions(-)
21
22 diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
23 index 6814e51..0812d3a 100644
24 --- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c
25 +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
26 @@ -580,7 +580,12 @@ void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
27  
28  void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
29  {
30 +       unsigned long flags;
31 +
32 +       local_irq_save(flags);
33 +       local_fiq_disable();
34         writel((readl(reg) & ~clear_mask) | set_mask, reg);
35 +       local_irq_restore(flags);
36  }
37  
38  #if 0
39 @@ -1301,7 +1306,7 @@ EXPORT_SYMBOL(DWC_EXCEPTION);
40  EXPORT_SYMBOL(__DWC_DEBUG);
41  #endif
42  
43 -EXPORT_SYMBOL(__DWC_DMA_ALLOC);\r
44 +EXPORT_SYMBOL(__DWC_DMA_ALLOC);
45  EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);
46  EXPORT_SYMBOL(__DWC_DMA_FREE);
47  EXPORT_SYMBOL(__DWC_ALLOC);
48 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
49 index b861b55..b5a007d 100644
50 --- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
51 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
52 @@ -47,8 +47,6 @@
53  #include "dwc_otg_hcd.h"
54  #include "dwc_otg_mphi_fix.h"
55  
56 -extern bool fiq_fix_enable;
57 -
58  #ifdef DEBUG
59  inline const char *op_state_str(dwc_otg_core_if_t * core_if)
60  {
61 @@ -1321,7 +1319,7 @@ static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
62  /**
63   * This function returns the Core Interrupt register.
64   */
65 -static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
66 +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk)
67  {
68         gahbcfg_data_t gahbcfg = {.d32 = 0 };
69         gintsts_data_t gintsts;
70 @@ -1338,19 +1336,33 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
71         gintmsk_common.b.lpmtranrcvd = 1;
72  #endif
73         gintmsk_common.b.restoredone = 1;
74 -       /** @todo: The port interrupt occurs while in device
75 -         * mode. Added code to CIL to clear the interrupt for now!
76 -         */
77 -       gintmsk_common.b.portintr = 1;
78 -
79 +       if(dwc_otg_is_device_mode(core_if))
80 +       {
81 +               /** @todo: The port interrupt occurs while in device
82 +                * mode. Added code to CIL to clear the interrupt for now!
83 +                */
84 +               gintmsk_common.b.portintr = 1;
85 +       }
86         gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
87         gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
88 +       {
89 +               unsigned long flags;
90 +
91 +               // Re-enable the saved interrupts
92 +               local_irq_save(flags);
93 +               local_fiq_disable();
94 +               gintmsk.d32 |= gintmsk_common.d32;
95 +               gintsts_saved.d32 &= ~gintmsk_common.d32;
96 +               reenable_gintmsk->d32 = gintmsk.d32;
97 +               local_irq_restore(flags);
98 +       }
99 +
100         gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
101  
102  #ifdef DEBUG
103         /* if any common interrupts set */
104         if (gintsts.d32 & gintmsk_common.d32) {
105 -               DWC_DEBUGPL(DBG_ANY, "gintsts=%08x  gintmsk=%08x\n",
106 +               DWC_DEBUGPL(DBG_ANY, "common_intr: gintsts=%08x  gintmsk=%08x\n",
107                             gintsts.d32, gintmsk.d32);
108         }
109  #endif
110 @@ -1394,6 +1406,7 @@ int32_t dwc_otg_handle_common_intr(void *dev)
111  {
112         int retval = 0;
113         gintsts_data_t gintsts;
114 +       gintmsk_data_t reenable_gintmsk;
115         gpwrdn_data_t gpwrdn = {.d32 = 0 };
116         dwc_otg_device_t *otg_dev = dev;
117         dwc_otg_core_if_t *core_if = otg_dev->core_if;
118 @@ -1415,7 +1428,7 @@ int32_t dwc_otg_handle_common_intr(void *dev)
119         }
120  
121         if (core_if->hibernation_suspend <= 0) {
122 -               gintsts.d32 = dwc_otg_read_common_intr(core_if);
123 +               gintsts.d32 = dwc_otg_read_common_intr(core_if, &reenable_gintmsk);
124  
125                 if (gintsts.b.modemismatch) {
126                         retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
127 @@ -1512,8 +1525,12 @@ int32_t dwc_otg_handle_common_intr(void *dev)
128                         gintsts.b.portintr = 1;
129                         DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
130                         retval |= 1;
131 +                       reenable_gintmsk.b.portintr = 1;
132  
133                 }
134 +
135 +               DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, reenable_gintmsk.d32);
136 +
137         } else {
138                 DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
139  
140 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
141 index cea8fcb..6c89a69 100644
142 --- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
143 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
144 @@ -242,7 +242,8 @@ static struct dwc_otg_driver_module_params dwc_otg_module_params = {
145  
146  //Global variable to switch the fiq fix on or off (declared in bcm2708.c)
147  extern bool fiq_fix_enable;
148 -
149 +// Global variable to enable the split transaction fix
150 +bool fiq_split_enable = true;
151  //Global variable to switch the nak holdoff on or off
152  bool nak_holdoff_enable = true;
153  
154 @@ -1090,6 +1091,7 @@ static int __init dwc_otg_driver_init(void)
155         }
156         printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");
157         printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled");
158 +       printk(KERN_DEBUG "dwc_otg: FIQ split fix %s\n", fiq_split_enable ? "enabled":"disabled");
159  
160         error = driver_create_file(drv, &driver_attr_version);
161  #ifdef DEBUG
162 @@ -1374,6 +1376,8 @@ module_param(fiq_fix_enable, bool, 0444);
163  MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");
164  module_param(nak_holdoff_enable, bool, 0444);
165  MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff");
166 +module_param(fiq_split_enable, bool, 0444);
167 +MODULE_PARM_DESC(fiq_split_enable, "Enable the FIQ fix on split transactions");
168  
169  /** @page "Module Parameters"
170   *
171 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
172 index 9c2e71a..af9108c 100644
173 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
174 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
175 @@ -45,6 +45,7 @@
176  
177  #include "dwc_otg_hcd.h"
178  #include "dwc_otg_regs.h"
179 +#include "dwc_otg_mphi_fix.h"
180  
181  extern bool microframe_schedule, nak_holdoff_enable;
182  
183 @@ -581,6 +582,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
184                          */
185                         dwc_otg_hc_halt(hcd->core_if, qh->channel,
186                                         DWC_OTG_HC_XFER_URB_DEQUEUE);
187 +
188 +                       dwc_otg_hcd_release_port(hcd, qh);
189                 }
190         }
191  
192 @@ -716,6 +719,8 @@ static void completion_tasklet_func(void *ptr)
193  
194                 usb_hcd_giveback_urb(hcd->priv, urb, urb->status);
195  
196 +               fiq_print(FIQDBG_PORTHUB, "COMPLETE");
197 +
198                 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
199         }
200         DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
201 @@ -979,6 +984,10 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
202         hcd->frame_list = NULL;
203         hcd->frame_list_dma = 0;
204         hcd->periodic_qh_count = 0;
205 +
206 +       DWC_MEMSET(hcd->hub_port, 0, sizeof(hcd->hub_port));
207 +       DWC_MEMSET(hcd->hub_port_alloc, -1, sizeof(hcd->hub_port_alloc));
208 +
209  out:
210         return retval;
211  }
212 @@ -1124,7 +1133,12 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
213                 uint32_t hub_addr, port_addr;
214                 hc->do_split = 1;
215                 hc->xact_pos = qtd->isoc_split_pos;
216 -               hc->complete_split = qtd->complete_split;
217 +               /* We don't need to do complete splits anymore */
218 +               if(fiq_split_enable)
219 +                       hc->complete_split = qtd->complete_split = 0;
220 +               else
221 +                       hc->complete_split = qtd->complete_split;
222 +
223                 hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
224                 hc->hub_addr = (uint8_t) hub_addr;
225                 hc->port_addr = (uint8_t) port_addr;
226 @@ -1271,6 +1285,62 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
227         hc->qh = qh;
228  }
229  
230 +/*
231 +** Check the transaction to see if the port / hub has already been assigned for
232 +** a split transaction
233 +**
234 +** Return 0 - Port is already in use
235 +*/
236 +int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
237 +{
238 +       uint32_t hub_addr, port_addr;
239 +
240 +       if(!fiq_split_enable)
241 +               return 0;
242 +
243 +       hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
244 +
245 +       if(hcd->hub_port[hub_addr] & (1 << port_addr))
246 +       {
247 +               fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count);
248 +
249 +               qh->skip_count++;
250 +
251 +               if(qh->skip_count > 40000)
252 +               {
253 +                       printk_once(KERN_ERR "Error: Having to skip port allocation");
254 +                       local_fiq_disable();
255 +                       BUG();
256 +                       return 0;
257 +               }
258 +               return 1;
259 +       }
260 +       else
261 +       {
262 +               qh->skip_count = 0;
263 +               hcd->hub_port[hub_addr] |= 1 << port_addr;
264 +               fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
265 +               hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd);
266 +               return 0;
267 +       }
268 +}
269 +void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
270 +{
271 +       uint32_t hub_addr, port_addr;
272 +
273 +       if(!fiq_split_enable)
274 +               return;
275 +
276 +       hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
277 +
278 +       hcd->hub_port[hub_addr] &= ~(1 << port_addr);
279 +       hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1;
280 +
281 +       fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
282 +
283 +}
284 +
285 +
286  /**
287   * This function selects transactions from the HCD transfer schedule and
288   * assigns them to available host channels. It is called from HCD interrupt
289 @@ -1304,11 +1374,22 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
290  
291         while (qh_ptr != &hcd->periodic_sched_ready &&
292                !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
293 +
294 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
295 +
296 +               if(qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh))
297 +               {
298 +                       qh_ptr = DWC_LIST_NEXT(qh_ptr);
299 +                       g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
300 +                       continue;
301 +               }
302 +
303                 if (microframe_schedule) {
304                         // Make sure we leave one channel for non periodic transactions.
305                         DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
306                         if (hcd->available_host_channels <= 1) {
307                                 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
308 +                               if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh);
309                                 break;
310                         }
311                         hcd->available_host_channels--;
312 @@ -1329,8 +1410,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
313                 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
314                                    &qh->qh_list_entry);
315                 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
316 -
317 -               ret_val = DWC_OTG_TRANSACTION_PERIODIC;
318         }
319  
320         /*
321 @@ -1369,10 +1448,19 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
322                                 qh->nak_frame = 0xffff;
323                         }
324                 }
325 +
326 +               if (qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh))
327 +               {
328 +                       g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
329 +                       qh_ptr = DWC_LIST_NEXT(qh_ptr);
330 +                       continue;
331 +               }
332 +
333                 if (microframe_schedule) {
334                                 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
335                                 if (hcd->available_host_channels < 1) {
336                                         DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
337 +                                       if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh);
338                                         break;
339                                 }
340                                 hcd->available_host_channels--;
341 @@ -1396,16 +1484,17 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
342  
343                 g_np_sent++;
344  
345 -               if (ret_val == DWC_OTG_TRANSACTION_NONE) {
346 -                       ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
347 -               } else {
348 -                       ret_val = DWC_OTG_TRANSACTION_ALL;
349 -               }
350 -
351                 if (!microframe_schedule)
352                         hcd->non_periodic_channels++;
353         }
354  
355 +       if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned))
356 +               ret_val |= DWC_OTG_TRANSACTION_PERIODIC;
357 +
358 +       if(!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active))
359 +               ret_val |= DWC_OTG_TRANSACTION_NON_PERIODIC;
360 +
361 +
362  #ifdef DEBUG_HOST_CHANNELS
363         last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
364  #endif /* DEBUG_HOST_CHANNELS */
365 @@ -1522,6 +1611,15 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd)
366  
367                 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
368  
369 +               // Do not send a split start transaction any later than frame .6
370 +               // Note, we have to schedule a periodic in .5 to make it go in .6
371 +               if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
372 +               {
373 +                       qh_ptr = qh_ptr->next;
374 +                       g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
375 +                       continue;
376 +               }
377 +
378                 /*
379                  * Set a flag if we're queuing high-bandwidth in slave mode.
380                  * The flag prevents any halts to get into the request queue in
381 @@ -1651,6 +1749,15 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
382  
383                 qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
384                                     qh_list_entry);
385 +
386 +               // Do not send a split start transaction any later than frame .5
387 +               // non periodic transactions will start immediately in this uframe
388 +               if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
389 +               {
390 +                       g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
391 +                       break;
392 +               }
393 +
394                 status =
395                     queue_transaction(hcd, qh->channel,
396                                       tx_status.b.nptxfspcavail);
397 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
398 index 0493dbf..d3d6e997 100644
399 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
400 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
401 @@ -168,10 +168,10 @@ typedef enum dwc_otg_control_phase {
402  
403  /** Transaction types. */
404  typedef enum dwc_otg_transaction_type {
405 -       DWC_OTG_TRANSACTION_NONE,
406 -       DWC_OTG_TRANSACTION_PERIODIC,
407 -       DWC_OTG_TRANSACTION_NON_PERIODIC,
408 -       DWC_OTG_TRANSACTION_ALL
409 +       DWC_OTG_TRANSACTION_NONE          = 0,
410 +       DWC_OTG_TRANSACTION_PERIODIC      = 1,
411 +       DWC_OTG_TRANSACTION_NON_PERIODIC  = 2,
412 +       DWC_OTG_TRANSACTION_ALL           = DWC_OTG_TRANSACTION_PERIODIC + DWC_OTG_TRANSACTION_NON_PERIODIC
413  } dwc_otg_transaction_type_e;
414  
415  struct dwc_otg_qh;
416 @@ -370,6 +370,8 @@ typedef struct dwc_otg_qh {
417  
418         uint16_t speed;
419         uint16_t frame_usecs[8];
420 +
421 +       uint32_t skip_count;
422  } dwc_otg_qh_t;
423  
424  DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
425 @@ -574,6 +576,10 @@ struct dwc_otg_hcd {
426         /** Frame List */
427         uint32_t *frame_list;
428  
429 +       /** Hub - Port assignment */
430 +       int hub_port[16];
431 +       int hub_port_alloc[256];
432 +
433         /** Frame List DMA address */
434         dma_addr_t frame_list_dma;
435  
436 @@ -604,12 +610,16 @@ extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
437  extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
438                                            dwc_otg_transaction_type_e tr_type);
439  
440 +int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh);
441 +void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh);
442 +
443 +
444  /** @} */
445  
446  /** @name Interrupt Handler Functions */
447  /** @{ */
448  extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
449 -extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd, int32_t);
450 +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
451  extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
452                                                          dwc_otg_hcd);
453  extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
454 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
455 index 16e8c6c..e8b4d35 100644
456 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
457 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
458 @@ -38,6 +38,7 @@
459  
460  #include <linux/jiffies.h>
461  #include <mach/hardware.h>
462 +#include <asm/fiq.h>
463  
464  
465  extern bool microframe_schedule;
466 @@ -52,21 +53,295 @@ extern bool microframe_schedule;
467  
468  void * dummy_send;
469  mphi_regs_t c_mphi_regs;
470 +volatile void *dwc_regs_base;
471  int fiq_done, int_done;
472 -int g_next_sched_frame, g_np_count, g_np_sent, g_work_expected;
473 -static int mphi_int_count = 0 ;
474  
475 -extern bool fiq_fix_enable, nak_holdoff_enable;
476 +gintsts_data_t  gintsts_saved = {.d32 = 0};
477 +hcint_data_t    hcint_saved[MAX_EPS_CHANNELS];
478 +hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
479 +int             split_out_xfersize[MAX_EPS_CHANNELS];
480 +haint_data_t    haint_saved;
481 +
482 +int g_next_sched_frame, g_np_count, g_np_sent;
483 +static int mphi_int_count = 0 ;
484  
485  hcchar_data_t nak_hcchar;
486  hctsiz_data_t nak_hctsiz;
487  hcsplt_data_t nak_hcsplt;
488  int nak_count;
489  
490 +int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
491 +int split_start_frame[MAX_EPS_CHANNELS];
492 +int queued_port[MAX_EPS_CHANNELS];
493 +
494 +#ifdef FIQ_DEBUG
495 +char buffer[1000*16];
496 +int wptr;
497 +void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...)
498 +{
499 +       FIQDBG_T dbg_lvl_req = FIQDBG_PORTHUB;
500 +       va_list args;
501 +       char text[17];
502 +       hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) };
503 +       unsigned long flags;
504 +
505 +       local_irq_save(flags);
506 +       local_fiq_disable();
507 +       if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR)
508 +       {
509 +               snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937);
510 +               va_start(args, fmt);
511 +               vsnprintf(text+8, 9, fmt, args);
512 +               va_end(args);
513 +
514 +               memcpy(buffer + wptr, text, 16);
515 +               wptr = (wptr + 16) % sizeof(buffer);
516 +       }
517 +       local_irq_restore(flags);
518 +}
519 +#endif
520 +
521 +void fiq_queue_request(int channel, int odd_frame)
522 +{
523 +       hcchar_data_t   hcchar   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0)  };
524 +       hcsplt_data_t   hcsplt   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4)  };
525 +       hctsiz_data_t   hctsiz   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10) };
526 +
527 +       if(hcsplt.b.spltena     == 0)
528 +       {
529 +               fiq_print(FIQDBG_ERR, "SPLTENA ");
530 +               BUG();
531 +       }
532 +
533 +       if(hcchar.b.epdir == 1)
534 +       {
535 +               fiq_print(FIQDBG_SCHED, "IN  Ch %d", channel);
536 +       }
537 +       else
538 +       {
539 +               hctsiz.b.xfersize = 0;
540 +               fiq_print(FIQDBG_SCHED, "OUT Ch %d", channel);
541 +       }
542 +       FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x10), hctsiz.d32);
543 +
544 +       hcsplt.b.compsplt = 1;
545 +       FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x4), hcsplt.d32);
546 +
547 +       // Send the Split complete
548 +       hcchar.b.chen = 1;
549 +       hcchar.b.oddfrm = odd_frame ? 1 : 0;
550 +
551 +       // Post this for transmit on the next frame for periodic or this frame for non-periodic
552 +       fiq_print(FIQDBG_SCHED, "SND_%s", odd_frame ? "ODD " : "EVEN");
553 +
554 +       FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x0), hcchar.d32);
555 +}
556 +
557 +static int last_sof = -1;
558 +
559 +/*
560 +** Function to handle the start of frame interrupt, choose whether we need to do anything and
561 +** therefore trigger the main interrupt
562 +**
563 +** returns int != 0 - interrupt has been handled
564 +*/
565 +int diff;
566 +
567 +int fiq_sof_handle(hfnum_data_t hfnum)
568 +{
569 +       int handled = 0;
570 +       int i;
571 +
572 +       // Just check that once we're running we don't miss a SOF
573 +       /*if(last_sof != -1 && (hfnum.b.frnum != ((last_sof + 1) & 0x3fff)))
574 +       {
575 +               fiq_print(FIQDBG_ERR, "LASTSOF ");
576 +               fiq_print(FIQDBG_ERR, "%4d%d   ", last_sof / 8, last_sof & 7);
577 +               fiq_print(FIQDBG_ERR, "%4d%d   ", hfnum.b.frnum / 8, hfnum.b.frnum & 7);
578 +               BUG();
579 +       }*/
580 +
581 +       // Only start remembering the last sof when the interrupt has been
582 +       // enabled (we don't check the mask to come in here...)
583 +       if(last_sof != -1 || FIQ_READ(dwc_regs_base + 0x18) & (1<<3))
584 +               last_sof = hfnum.b.frnum;
585 +
586 +       for(i = 0; i < MAX_EPS_CHANNELS; i++)
587 +       {
588 +               if(complete_sched[i] != -1)
589 +               {
590 +                       if(complete_sched[i] <= hfnum.b.frnum || (complete_sched[i] > 0x3f00 && hfnum.b.frnum < 0xf0))
591 +                       {
592 +                               fiq_queue_request(i, hfnum.b.frnum & 1);
593 +                               complete_sched[i] = -1;
594 +                       }
595 +               }
596 +
597 +               if(complete_sched[i] != -1)
598 +               {
599 +                       // This is because we've seen a split complete occur with no start...
600 +                       // most likely because missed the complete 0x3fff frames ago!
601 +
602 +                       diff = (hfnum.b.frnum + 0x3fff - complete_sched[i]) & 0x3fff ;
603 +                       if(diff > 32 && diff < 0x3f00)
604 +                       {
605 +                               fiq_print(FIQDBG_ERR, "SPLTMISS");
606 +                               BUG();
607 +                       }
608 +               }
609 +       }
610 +
611 +       if(g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
612 +       {
613 +               /*
614 +                * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet
615 +                * g_next_sched_frame is the next frame we have periodic packets for
616 +                *
617 +                * if neither of these are required for this frame then just clear the interrupt
618 +                */
619 +               handled = 1;
620 +
621 +       }
622 +
623 +       return handled;
624 +}
625 +
626 +int port_id(hcsplt_data_t hcsplt)
627 +{
628 +       return hcsplt.b.prtaddr + (hcsplt.b.hubaddr << 8);
629 +}
630 +
631 +int fiq_hcintr_handle(int channel, hfnum_data_t hfnum)
632 +{
633 +       hcchar_data_t   hcchar   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };
634 +       hcsplt_data_t   hcsplt   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };
635 +       hcint_data_t    hcint    = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x8) };
636 +       hcintmsk_data_t hcintmsk = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0xc) };
637 +       hctsiz_data_t   hctsiz   = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10)};
638 +
639 +       hcint_saved[channel].d32 |= hcint.d32;
640 +       hcintmsk_saved[channel].d32 =  hcintmsk.d32;
641 +
642 +       if(hcsplt.b.spltena)
643 +       {
644 +               fiq_print(FIQDBG_PORTHUB, "ph: %4x", port_id(hcsplt));
645 +               if(hcint.b.chhltd)
646 +               {
647 +                       fiq_print(FIQDBG_SCHED, "CH HLT %d", channel);
648 +                       fiq_print(FIQDBG_SCHED, "%08x", hcint_saved[channel]);
649 +               }
650 +               if(hcint.b.stall || hcint.b.xacterr || hcint.b.bblerr || hcint.b.frmovrun || hcint.b.datatglerr)
651 +               {
652 +                       queued_port[channel] = 0;
653 +                       fiq_print(FIQDBG_ERR, "CHAN ERR");
654 +               }
655 +               if(hcint.b.xfercomp)
656 +               {
657 +                       // Clear the port allocation and transmit anything also on this port
658 +                       queued_port[channel] = 0;
659 +                       fiq_print(FIQDBG_SCHED, "XFERCOMP");
660 +               }
661 +               if(hcint.b.nak)
662 +               {
663 +                       queued_port[channel] = 0;
664 +                       fiq_print(FIQDBG_SCHED, "NAK");
665 +               }
666 +               if(hcint.b.ack && !hcsplt.b.compsplt)
667 +               {
668 +                       int i;
669 +
670 +                       // Do not complete isochronous out transactions
671 +                       if(hcchar.b.eptype == 1 && hcchar.b.epdir == 0)
672 +                       {
673 +                               queued_port[channel] = 0;
674 +                               fiq_print(FIQDBG_SCHED, "ISOC_OUT");
675 +                       }
676 +                       else
677 +                       {
678 +                               // Make sure we check the port / hub combination that we sent this split on.
679 +                               // Do not queue a second request to the same port
680 +                               for(i = 0; i < MAX_EPS_CHANNELS; i++)
681 +                               {
682 +                                       if(port_id(hcsplt) == queued_port[i])
683 +                                       {
684 +                                               fiq_print(FIQDBG_ERR, "PORTERR ");
685 +                                               //BUG();
686 +                                       }
687 +                               }
688 +
689 +                               split_start_frame[channel] = (hfnum.b.frnum + 1) & ~7;
690 +
691 +                               // Note, the size of an OUT is in the start split phase, not
692 +                               // the complete split
693 +                               split_out_xfersize[channel] = hctsiz.b.xfersize;
694 +
695 +                               hcint_saved[channel].b.chhltd = 0;
696 +                               hcint_saved[channel].b.ack = 0;
697 +
698 +                               queued_port[channel] = port_id(hcsplt);
699 +
700 +                               if(hcchar.b.eptype & 1)
701 +                               {
702 +                                       // Send the periodic complete in the same oddness frame as the ACK went...
703 +                                       fiq_queue_request(channel, !(hfnum.b.frnum & 1));
704 +       //                              complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
705 +                               }
706 +                               else
707 +                               {
708 +                                       // Schedule the split complete to occur later
709 +                                       complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 2);
710 +                                       fiq_print(FIQDBG_SCHED, "ACK%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
711 +                               }
712 +                       }
713 +               }
714 +               if(hcint.b.nyet)
715 +               {
716 +                       fiq_print(FIQDBG_ERR, "NYETERR1");
717 +                       //BUG();
718 +                       // Can transmit a split complete up to uframe .0 of the next frame
719 +                       if(hfnum.b.frnum <= dwc_frame_num_inc(split_start_frame[channel], 8))
720 +                       {
721 +                               // Send it next frame
722 +                               if(hcchar.b.eptype & 1) // type 1 & 3 are interrupt & isoc
723 +                               {
724 +                                       fiq_print(FIQDBG_SCHED, "NYT:SEND");
725 +                                       fiq_queue_request(channel, !(hfnum.b.frnum & 1));
726 +                               }
727 +                               else
728 +                               {
729 +                                       // Schedule non-periodic access for next frame (the odd-even bit doesn't effect NP)
730 +                                       complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
731 +                                       fiq_print(FIQDBG_SCHED, "NYT%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
732 +                               }
733 +                               hcint_saved[channel].b.chhltd = 0;
734 +                               hcint_saved[channel].b.nyet = 0;
735 +                       }
736 +                       else
737 +                       {
738 +                               queued_port[channel] = 0;
739 +                               fiq_print(FIQDBG_ERR, "NYETERR2");
740 +                               //BUG();
741 +                       }
742 +               }
743 +       }
744 +
745 +       // Clear the interrupt, this will also clear the HAINT bit
746 +       FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32);
747 +       return hcint_saved[channel].d32 == 0;
748 +}
749 +
750 +gintsts_data_t gintsts;
751 +gintmsk_data_t gintmsk;
752 +// triggered: The set of interrupts that were triggered
753 +// handled:   The set of interrupts that have been handled (no IRQ is
754 +//            required)
755 +// keep:      The set of interrupts we want to keep unmasked even though we
756 +//            want to trigger an IRQ to handle it (SOF and HCINTR)
757 +gintsts_data_t triggered, handled, keep;
758 +hfnum_data_t hfnum;
759 +
760  void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void)
761  {
762 -       gintsts_data_t gintsts;
763 -       hfnum_data_t hfnum;
764  
765         /* entry takes care to store registers we will be treading on here */
766         asm __volatile__ (
767 @@ -74,43 +349,112 @@ void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void)
768                 /* stash FIQ and normal regs */
769                 "stmdb  sp!, {r0-r12,  lr};"
770                 /* !! THIS SETS THE FRAME, adjust to > sizeof locals */
771 -               "sub     fp, ip, #256 ;"
772 +               "sub     fp, ip, #512 ;"
773                 );
774  
775 -       fiq_done++;
776 -       gintsts.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x14) & FIQ_READ_IO_ADDRESS(USB_BASE + 0x18);
777 -       hfnum.d32 =   FIQ_READ_IO_ADDRESS(USB_BASE + 0x408);
778 -
779 -       if(gintsts.d32)
780 +       // Cannot put local variables at the beginning of the function
781 +       // because otherwise 'C' will play with the stack pointer. any locals
782 +       // need to be inside the following block
783 +       do
784         {
785 -               if(gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
786 +               fiq_done++;
787 +               gintsts.d32 = FIQ_READ(dwc_regs_base + 0x14);
788 +               gintmsk.d32 = FIQ_READ(dwc_regs_base + 0x18);
789 +               hfnum.d32 =   FIQ_READ(dwc_regs_base + 0x408);
790 +               triggered.d32 = gintsts.d32 & gintmsk.d32;
791 +               handled.d32 = 0;
792 +               keep.d32 = 0;
793 +               fiq_print(FIQDBG_INT, "FIQ     ");
794 +               fiq_print(FIQDBG_INT, "%08x", gintsts.d32);
795 +               fiq_print(FIQDBG_INT, "%08x", gintmsk.d32);
796 +               if(gintsts.d32)
797                 {
798 -                       /*
799 -                        * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet
800 -                        * g_next_sched_frame is the next frame we have periodic packets for
801 -                        *
802 -                        * if neither of these are required for this frame then just clear the interrupt
803 -                        */
804 -                       gintsts.d32 = 0;
805 -                       gintsts.b.sofintr = 1;
806 -                       FIQ_WRITE_IO_ADDRESS((USB_BASE + 0x14), gintsts.d32);
807 +                       // If port enabled
808 +                       if((FIQ_READ(dwc_regs_base + 0x440) & 0xf) == 0x5)
809 +                       {
810 +                               if(gintsts.b.sofintr)
811 +                               {
812 +                                       if(fiq_sof_handle(hfnum))
813 +                                       {
814 +                                               handled.b.sofintr = 1; /* Handled in FIQ */
815 +                                       }
816 +                                       else
817 +                                       {
818 +                                               /* Keer interrupt unmasked */
819 +                                               keep.b.sofintr = 1;
820 +                                       }
821 +                                       {
822 +                                               // Need to make sure the read and clearing of the SOF interrupt is as close as possible to avoid the possibility of missing
823 +                                               // a start of frame interrupt
824 +                                               gintsts_data_t gintsts = { .b.sofintr = 1 };
825 +                                               FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
826 +                                       }
827 +                               }
828 +
829 +                               if(fiq_split_enable && gintsts.b.hcintr)
830 +                               {
831 +                                       int i;
832 +                                       haint_data_t    haint;
833 +                                       haintmsk_data_t haintmsk;
834 +
835 +                                       haint.d32 = FIQ_READ(dwc_regs_base + 0x414);
836 +                                       haintmsk.d32 = FIQ_READ(dwc_regs_base + 0x418);
837 +                                       haint.d32 &= haintmsk.d32;
838 +                                       haint_saved.d32 |= haint.d32;
839 +
840 +                                       fiq_print(FIQDBG_INT, "hcintr");
841 +                                       fiq_print(FIQDBG_INT, "%08x", FIQ_READ(dwc_regs_base + 0x414));
842 +
843 +                                       // Go through each channel that has an enabled interrupt
844 +                                       for(i = 0; i < 16; i++)
845 +                                               if((haint.d32 >> i) & 1)
846 +                                                       if(fiq_hcintr_handle(i, hfnum))
847 +                                                               haint_saved.d32 &= ~(1 << i); /* this was handled */
848 +
849 +                                       /* If we've handled all host channel interrupts then don't trigger the interrupt */
850 +                                       if(haint_saved.d32 == 0)
851 +                                       {
852 +                                               handled.b.hcintr = 1;
853 +                                       }
854 +                                       else
855 +                                       {
856 +                                               /* Make sure we keep the channel interrupt unmasked when triggering the IRQ */
857 +                                               keep.b.hcintr = 1;
858 +                                       }
859  
860 -                       g_work_expected = 0;
861 +                                       {
862 +                                               gintsts_data_t gintsts = { .b.hcintr = 1 };
863 +
864 +                                               // Always clear the channel interrupt
865 +                                               FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
866 +                                       }
867 +                               }
868 +                       }
869 +                       else
870 +                       {
871 +                               last_sof = -1;
872 +                       }
873                 }
874 -               else
875 +
876 +               // Mask out the interrupts triggered - those handled - don't mask out the ones we want to keep
877 +               gintmsk.d32 = keep.d32 | (gintmsk.d32 & ~(triggered.d32 & ~handled.d32));
878 +               // Save those that were triggered but not handled
879 +               gintsts_saved.d32 |= triggered.d32 & ~handled.d32;
880 +               FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
881 +
882 +               // Clear and save any unhandled interrupts and trigger the interrupt
883 +               if(gintsts_saved.d32)
884                 {
885 -                       g_work_expected = 1;
886                         /* To enable the MPHI interrupt  (INT 32)
887                          */
888 -                       FIQ_WRITE(  c_mphi_regs.outdda, (int) dummy_send);
889 +                       FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send);
890                         FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
891  
892                         mphi_int_count++;
893 -                       /* Clear the USB global interrupt so we don't just sit in the FIQ */
894 -                       FIQ_MODIFY_IO_ADDRESS((USB_BASE + 0x8),1,0);
895 -
896                 }
897         }
898 +       while(0);
899 +
900         mb();
901  
902         /* exit back to normal mode restoring everything */
903 @@ -133,6 +477,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
904  
905         dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
906         gintsts_data_t gintsts;
907 +       gintmsk_data_t gintmsk;
908         hfnum_data_t hfnum;
909  
910  #ifdef DEBUG
911 @@ -140,6 +485,9 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
912  
913  #endif
914  
915 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
916 +       gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
917 +
918         /* Exit from ISR if core is hibernated */
919         if (core_if->hibernation_suspend == 1) {
920                 goto exit_handler_routine;
921 @@ -147,11 +495,18 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
922         DWC_SPINLOCK(dwc_otg_hcd->lock);
923         /* Check if HOST Mode */
924         if (dwc_otg_is_host_mode(core_if)) {
925 -               gintsts.d32 = dwc_otg_read_core_intr(core_if);
926 +               local_fiq_disable();
927 +               gintmsk.d32 |= gintsts_saved.d32;
928 +               gintsts.d32 |= gintsts_saved.d32;
929 +               gintsts_saved.d32 = 0;
930 +               local_fiq_enable();
931                 if (!gintsts.d32) {
932                         goto exit_handler_routine;
933                 }
934 +               gintsts.d32 &= gintmsk.d32;
935 +
936  #ifdef DEBUG
937 +               // We should be OK doing this because the common interrupts should already have been serviced
938                 /* Don't print debug message in the interrupt handler on SOF */
939  #ifndef DEBUG_SOF
940                 if (gintsts.d32 != DWC_SOF_INTR_MASK)
941 @@ -171,11 +526,12 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
942                 if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
943                 {
944                         /* Note, we should never get here if the FIQ is doing it's job properly*/
945 -                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected);
946 +                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
947                 }
948                 else if (gintsts.b.sofintr) {
949 -                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected);
950 +                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
951                 }
952 +
953                 if (gintsts.b.rxstsqlvl) {
954                         retval |=
955                             dwc_otg_hcd_handle_rx_status_q_level_intr
956 @@ -190,7 +546,10 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
957                         /** @todo Implement i2cintr handler. */
958                 }
959                 if (gintsts.b.portintr) {
960 +
961 +                       gintmsk_data_t gintmsk = { .b.portintr = 1};
962                         retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
963 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
964                 }
965                 if (gintsts.b.hcintr) {
966                         retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
967 @@ -227,26 +586,35 @@ exit_handler_routine:
968  
969         if (fiq_fix_enable)
970         {
971 -               /* Clear the MPHI interrupt */
972 -               DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));
973 -               if (mphi_int_count >= 60)
974 +               local_fiq_disable();
975 +               // Make sure that we don't clear the interrupt if we've still got pending work to do
976 +               if(gintsts_saved.d32 == 0)
977                 {
978 -                       DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));
979 -                       while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17)))
980 -                               ;
981 -                       DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
982 -                       mphi_int_count = 0;
983 +                       /* Clear the MPHI interrupt */
984 +                       DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));
985 +                       if (mphi_int_count >= 60)
986 +                       {
987 +                               DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));
988 +                               while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17)))
989 +                                       ;
990 +                               DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
991 +                               mphi_int_count = 0;
992 +                       }
993 +                       int_done++;
994                 }
995 -               int_done++;
996 +
997 +               // Unmask handled interrupts
998 +               FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
999 +               //DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);
1000 +
1001 +               local_fiq_enable();
1002 +
1003                 if((jiffies / HZ) > last_time)
1004                 {
1005                         /* Once a second output the fiq and irq numbers, useful for debug */
1006                         last_time = jiffies / HZ;
1007                         DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done);
1008                 }
1009 -
1010 -               /* Re-Enable FIQ interrupt from USB peripheral */
1011 -               DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);
1012         }
1013  
1014         DWC_SPINUNLOCK(dwc_otg_hcd->lock);
1015 @@ -294,13 +662,12 @@ static inline void track_missed_sofs(uint16_t curr_frame_number)
1016   * (micro)frame. Periodic transactions may be queued to the controller for the
1017   * next (micro)frame.
1018   */
1019 -int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected)
1020 +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
1021  {
1022         hfnum_data_t hfnum;
1023         dwc_list_link_t *qh_entry;
1024         dwc_otg_qh_t *qh;
1025         dwc_otg_transaction_type_e tr_type;
1026 -       gintsts_data_t gintsts = {.d32 = 0 };
1027         int did_something = 0;
1028         int32_t next_sched_frame = -1;
1029  
1030 @@ -326,6 +693,7 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected)
1031                 qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
1032                 qh_entry = qh_entry->next;
1033                 if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
1034 +
1035                         /*
1036                          * Move QH to the ready list to be executed next
1037                          * (micro)frame.
1038 @@ -351,15 +719,10 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected)
1039                 dwc_otg_hcd_queue_transactions(hcd, tr_type);
1040                 did_something = 1;
1041         }
1042 -       if(work_expected && !did_something)
1043 -               DWC_DEBUGPL(DBG_USER, "Nothing to do !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame);
1044 -       if(!work_expected && did_something)
1045 -               DWC_DEBUGPL(DBG_USER, "Unexpected work done !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame);
1046 -
1047  
1048         /* Clear interrupt */
1049 -       gintsts.b.sofintr = 1;
1050 -       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
1051 +       //gintsts.b.sofintr = 1;
1052 +       //DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
1053  
1054         return 1;
1055  }
1056 @@ -643,6 +1006,15 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
1057  
1058         haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
1059  
1060 +       // Overwrite with saved interrupts from fiq handler
1061 +       if(fiq_split_enable)
1062 +       {
1063 +               local_fiq_disable();
1064 +               haint.d32 = haint_saved.d32;
1065 +               haint_saved.d32 = 0;
1066 +               local_fiq_enable();
1067 +       }
1068 +
1069         for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
1070                 if (haint.b2.chint & (1 << i)) {
1071                         retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
1072 @@ -683,7 +1055,10 @@ static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
1073                                 *short_read = (hctsiz.b.xfersize != 0);
1074                         }
1075                 } else if (hc->qh->do_split) {
1076 -                       length = qtd->ssplit_out_xfer_count;
1077 +                       if(fiq_split_enable)
1078 +                               length = split_out_xfersize[hc->hc_num];
1079 +                       else
1080 +                               length = qtd->ssplit_out_xfer_count;
1081                 } else {
1082                         length = hc->xfer_len;
1083                 }
1084 @@ -727,7 +1102,6 @@ static int update_urb_state_xfer_comp(dwc_hc_t * hc,
1085                                              DWC_OTG_HC_XFER_COMPLETE,
1086                                              &short_read);
1087  
1088 -
1089         /* non DWORD-aligned buffer case handling. */
1090         if (hc->align_buff && xfer_length && hc->ep_is_in) {
1091                 dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
1092 @@ -930,6 +1304,9 @@ static void release_channel(dwc_otg_hcd_t * hcd,
1093         int free_qtd;
1094         dwc_irqflags_t flags;
1095         dwc_spinlock_t *channel_lock = hcd->channel_lock;
1096 +#ifdef FIQ_DEBUG
1097 +       int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0;
1098 +#endif
1099  
1100         DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d, xfer_len %d\n",
1101                     __func__, hc->hc_num, halt_status, hc->xfer_len);
1102 @@ -1008,9 +1385,24 @@ cleanup:
1103  
1104                 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
1105                 hcd->available_host_channels++;
1106 +               fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels);
1107                 DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
1108         }
1109  
1110 +       if(fiq_split_enable && hc->do_split)
1111 +       {
1112 +               if(!(hcd->hub_port[hc->hub_addr] & (1 << hc->port_addr)))
1113 +               {
1114 +                       fiq_print(FIQDBG_ERR, "PRTNOTAL");
1115 +                       //BUG();
1116 +               }
1117 +
1118 +               hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);
1119 +               hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;
1120 +
1121 +               fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);
1122 +       }
1123 +
1124         /* Try to queue more transfers now that there's a free channel. */
1125         tr_type = dwc_otg_hcd_select_transactions(hcd);
1126         if (tr_type != DWC_OTG_TRANSACTION_NONE) {
1127 @@ -1633,8 +2025,10 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
1128                     hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
1129                         int frnum = dwc_otg_hcd_get_frame_number(hcd);
1130  
1131 +                       // With the FIQ running we only ever see the failed NYET
1132                         if (dwc_full_frame_num(frnum) !=
1133 -                           dwc_full_frame_num(hc->qh->sched_frame)) {
1134 +                           dwc_full_frame_num(hc->qh->sched_frame) ||
1135 +                           fiq_split_enable) {
1136                                 /*
1137                                  * No longer in the same full speed frame.
1138                                  * Treat this as a transaction error.
1139 @@ -2012,10 +2406,10 @@ static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
1140  static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
1141                                       dwc_hc_t * hc,
1142                                       dwc_otg_hc_regs_t * hc_regs,
1143 -                                     dwc_otg_qtd_t * qtd)
1144 +                                     dwc_otg_qtd_t * qtd,
1145 +                                     hcint_data_t hcint,
1146 +                                     hcintmsk_data_t hcintmsk)
1147  {
1148 -       hcint_data_t hcint;
1149 -       hcintmsk_data_t hcintmsk;
1150         int out_nak_enh = 0;
1151  
1152         /* For core with OUT NAK enhancement, the flow for high-
1153 @@ -2047,8 +2441,11 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
1154         }
1155  
1156         /* Read the HCINTn register to determine the cause for the halt. */
1157 -       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1158 -       hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
1159 +       if(!fiq_split_enable)
1160 +       {
1161 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1162 +               hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
1163 +       }
1164  
1165         if (hcint.b.xfercomp) {
1166                 /** @todo This is here because of a possible hardware bug.  Spec
1167 @@ -2161,13 +2558,15 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
1168  static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
1169                                      dwc_hc_t * hc,
1170                                      dwc_otg_hc_regs_t * hc_regs,
1171 -                                    dwc_otg_qtd_t * qtd)
1172 +                                    dwc_otg_qtd_t * qtd,
1173 +                                    hcint_data_t hcint,
1174 +                                    hcintmsk_data_t hcintmsk)
1175  {
1176         DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1177                     "Channel Halted--\n", hc->hc_num);
1178  
1179         if (hcd->core_if->dma_enable) {
1180 -               handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
1181 +               handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd, hcint, hcintmsk);
1182         } else {
1183  #ifdef DEBUG
1184                 if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
1185 @@ -2184,7 +2583,7 @@ static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
1186  int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
1187  {
1188         int retval = 0;
1189 -       hcint_data_t hcint;
1190 +       hcint_data_t hcint, hcint_orig;
1191         hcintmsk_data_t hcintmsk;
1192         dwc_hc_t *hc;
1193         dwc_otg_hc_regs_t *hc_regs;
1194 @@ -2197,12 +2596,23 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
1195         qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
1196  
1197         hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1198 +       hcint_orig = hcint;
1199         hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
1200         DWC_DEBUGPL(DBG_HCDV,
1201                     "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
1202                     hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
1203         hcint.d32 = hcint.d32 & hcintmsk.d32;
1204  
1205 +       if(fiq_split_enable)
1206 +       {
1207 +               // replace with the saved interrupts from the fiq handler
1208 +               local_fiq_disable();
1209 +               hcint_orig.d32 = hcint_saved[num].d32;
1210 +               hcint.d32 = hcint_orig.d32 & hcintmsk_saved[num].d32;
1211 +               hcint_saved[num].d32 = 0;
1212 +               local_fiq_enable();
1213 +       }
1214 +
1215         if (!dwc_otg_hcd->core_if->dma_enable) {
1216                 if (hcint.b.chhltd && hcint.d32 != 0x2) {
1217                         hcint.b.chhltd = 0;
1218 @@ -2220,7 +2630,7 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
1219                 hcint.b.nyet = 0;
1220         }
1221         if (hcint.b.chhltd) {
1222 -               retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
1223 +               retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd, hcint_orig, hcintmsk_saved[num]);
1224         }
1225         if (hcint.b.ahberr) {
1226                 retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
1227 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
1228 index fef557d..0d6f5f4 100644
1229 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
1230 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
1231 @@ -392,7 +392,11 @@ static struct dwc_otg_hcd_function_ops hcd_fops = {
1232  static struct fiq_handler fh = {
1233    .name = "usb_fiq",
1234  };
1235 -static uint8_t fiqStack[1024];
1236 +struct fiq_stack_s {
1237 +       int magic1;
1238 +       uint8_t stack[2048];
1239 +       int magic2;
1240 +} fiq_stack;
1241  
1242  extern mphi_regs_t c_mphi_regs;
1243  /**
1244 @@ -434,9 +438,11 @@ int hcd_init(dwc_bus_dev_t *_dev)
1245                 memset(&regs,0,sizeof(regs));
1246                 regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq;
1247                 regs.ARM_r9 = (long)0;
1248 -               regs.ARM_sp = (long)fiqStack + sizeof(fiqStack) - 4;
1249 +               regs.ARM_sp = (long)fiq_stack.stack + sizeof(fiq_stack.stack) - 4;
1250                 set_fiq_regs(&regs);
1251 -               }
1252 +               fiq_stack.magic1 = 0xdeadbeef;
1253 +               fiq_stack.magic2 = 0xaa995566;
1254 +       }
1255  
1256         /*
1257          * Allocate memory for the base HCD plus the DWC OTG HCD.
1258 @@ -459,6 +465,8 @@ int hcd_init(dwc_bus_dev_t *_dev)
1259  
1260         if (fiq_fix_enable)
1261         {
1262 +               volatile extern void *dwc_regs_base;
1263 +
1264                 //Set the mphi periph to  the required registers
1265                 c_mphi_regs.base    = otg_dev->os_dep.mphi_base;
1266                 c_mphi_regs.ctrl    = otg_dev->os_dep.mphi_base + 0x4c;
1267 @@ -466,6 +474,8 @@ int hcd_init(dwc_bus_dev_t *_dev)
1268                 c_mphi_regs.outddb  = otg_dev->os_dep.mphi_base + 0x2c;
1269                 c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
1270  
1271 +               dwc_regs_base = otg_dev->os_dep.base;
1272 +
1273                 //Enable mphi peripheral
1274                 writel((1<<31),c_mphi_regs.ctrl);
1275  #ifdef DEBUG
1276 @@ -839,6 +849,8 @@ static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
1277                  usb_hcd_unlink_urb_from_ep(hcd, urb);
1278  #endif
1279                 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
1280 +
1281 +
1282  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
1283                  usb_hcd_giveback_urb(hcd, urb);
1284  #else
1285 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
1286 index b3e6e52..8125307 100644
1287 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
1288 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
1289 @@ -41,6 +41,7 @@
1290  
1291  #include "dwc_otg_hcd.h"
1292  #include "dwc_otg_regs.h"
1293 +#include "dwc_otg_mphi_fix.h"
1294  
1295  extern bool microframe_schedule;
1296  
1297 @@ -191,6 +192,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
1298                             dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
1299                             hub_port);
1300                 qh->do_split = 1;
1301 +               qh->skip_count = 0;
1302         }
1303  
1304         if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
1305 @@ -737,6 +739,9 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
1306                             hcd->non_periodic_qh_ptr->next;
1307                 }
1308                 DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
1309 +
1310 +               // If we've removed the last non-periodic entry then there are none left!
1311 +               g_np_count = g_np_sent;
1312         } else {
1313                 deschedule_periodic(hcd, qh);
1314                 hcd->periodic_qh_count--;
1315 @@ -766,21 +771,21 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
1316  {      
1317         if (dwc_qh_is_non_per(qh)) {
1318  
1319 -       dwc_otg_qh_t *qh_tmp;
1320 -       dwc_list_link_t *qh_list;
1321 -       DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive)
1322 -       {
1323 -               qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry);
1324 -               if(qh_tmp == qh)
1325 +               dwc_otg_qh_t *qh_tmp;
1326 +               dwc_list_link_t *qh_list;
1327 +               DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive)
1328                 {
1329 -                       /*
1330 -                        *  FIQ is being disabled because this one nevers gets a np_count increment
1331 -                        *  This is still not absolutely correct, but it should fix itself with
1332 -                        *  just an unnecessary extra interrupt
1333 -                        */
1334 -                       g_np_sent = g_np_count;
1335 +                       qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry);
1336 +                       if(qh_tmp == qh)
1337 +                       {
1338 +                               /*
1339 +                                *  FIQ is being disabled because this one nevers gets a np_count increment
1340 +                                *  This is still not absolutely correct, but it should fix itself with
1341 +                                *  just an unnecessary extra interrupt
1342 +                                */
1343 +                               g_np_sent = g_np_count;
1344 +                       }
1345                 }
1346 -       }
1347  
1348  
1349                 dwc_otg_hcd_qh_remove(hcd, qh);
1350 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
1351 index 22f28e1..ca17379 100755
1352 --- a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
1353 +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
1354 @@ -1,10 +1,7 @@
1355  #ifndef __DWC_OTG_MPHI_FIX_H__
1356  #define __DWC_OTG_MPHI_FIX_H__
1357 -
1358 -#define FIQ_WRITE_IO_ADDRESS(_addr_,_data_) *(volatile uint32_t *) IO_ADDRESS(_addr_) = _data_
1359 -#define FIQ_READ_IO_ADDRESS(_addr_) *(volatile uint32_t *) IO_ADDRESS(_addr_) 
1360 -#define FIQ_MODIFY_IO_ADDRESS(_addr_,_clear_,_set_) FIQ_WRITE_IO_ADDRESS(_addr_ , (FIQ_READ_IO_ADDRESS(_addr_)&~_clear_)|_set_)
1361 -#define FIQ_WRITE(_addr_,_data_) *(volatile uint32_t *) _addr_ = _data_
1362 +#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_))
1363 +#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_))
1364  
1365  typedef struct {
1366         volatile void* base;
1367 @@ -12,13 +9,13 @@ typedef struct {
1368         volatile void* outdda;
1369         volatile void* outddb;
1370         volatile void* intstat;
1371 -} mphi_regs_t; 
1372 +} mphi_regs_t;
1373  
1374  void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name);
1375  void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name);
1376  void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);
1377  
1378 -
1379 +extern gintsts_data_t gintsts_saved;
1380  
1381  #ifdef DEBUG
1382  #define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__)
1383 @@ -30,7 +27,22 @@ void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);
1384  #define DWC_DBG_PRINT_CORE_INT_MASK(_arg_)
1385  #define DWC_DBG_PRINT_OTG_INT(_arg_)
1386  
1387 +#endif
1388 +
1389 +typedef enum {
1390 +       FIQDBG_SCHED = (1 << 0),
1391 +       FIQDBG_INT   = (1 << 1),
1392 +       FIQDBG_ERR   = (1 << 2),
1393 +       FIQDBG_PORTHUB = (1 << 3),
1394 +} FIQDBG_T;
1395  
1396 +void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...);
1397 +#ifdef FIQ_DEBUG
1398 +#define fiq_print _fiq_print
1399 +#else
1400 +#define fiq_print(x, y, ...)
1401  #endif
1402  
1403 +extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable;
1404 +
1405  #endif
1406 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
1407 index 27061d3..9720937 100644
1408 --- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
1409 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
1410 @@ -4276,7 +4276,7 @@ do { \
1411                                                                         && (pcd->ep0state == EP0_OUT_DATA_PHASE))
1412                                                                         status.d32 = core_if->dev_if->out_desc_addr->status.d32;
1413                                                                 if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
1414 -                                                                       status.d32 = status.d32 = core_if->dev_if->
1415 +                                                                       status.d32 = core_if->dev_if->
1416                                                                         out_desc_addr->status.d32;
1417  
1418                                                                 if (status.b.sr) {
1419 -- 
1420 1.9.1
1421