hidg: support boot protocol
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg / dwc_otg_pcd_intr.c
1 /* ==========================================================================
2  * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_pcd_intr.c $
3  * $Revision: #18 $
4  * $Date: 2007/02/07 $
5  * $Change: 791271 $
6  *
7  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9  * otherwise expressly agreed to in writing between Synopsys and you.
10  * 
11  * The Software IS NOT an item of Licensed Software or Licensed Product under
12  * any End User Software License Agreement or Agreement for Licensed Product
13  * with Synopsys or any supplement thereto. You are permitted to use and
14  * redistribute this Software in source and binary forms, with or without
15  * modification, provided that redistributions of source code must retain this
16  * notice. You may not view, use, disclose, copy or distribute this file or
17  * any information contained herein except pursuant to this license grant from
18  * Synopsys. If you do not agree with this notice, including the disclaimer
19  * below, then you are not authorized to use the Software.
20  * 
21  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31  * DAMAGE.
32  * ========================================================================== */
33 #ifndef DWC_HOST_ONLY
34 #include <linux/interrupt.h>
35 #include <linux/dma-mapping.h>
36 #include "dwc_otg_driver.h"
37 #include "dwc_otg_pcd.h"
38
39
40 #define DEBUG_EP0
41
42 /* request functions defined in "dwc_otg_pcd.c" */
43 extern void request_done( dwc_otg_pcd_ep_t *_ep, dwc_otg_pcd_request_t *_req, 
44                                                                 int _status);
45 extern void request_nuke( dwc_otg_pcd_ep_t *_ep ); 
46 extern void dwc_otg_pcd_update_otg( dwc_otg_pcd_t *_pcd, 
47                                                                 const unsigned _reset );
48 /** @file 
49  * This file contains the implementation of the PCD Interrupt handlers.
50  *
51  * The PCD handles the device interrupts.  Many conditions can cause a
52  * device interrupt. When an interrupt occurs, the device interrupt
53  * service routine determines the cause of the interrupt and
54  * dispatches handling to the appropriate function. These interrupt
55  * handling functions are described below.
56  * All interrupt registers are processed from LSB to MSB.
57  */
58
59
60 /**
61  * This function prints the ep0 state for debug purposes.
62  */
63 static inline void print_ep0_state( dwc_otg_pcd_t *_pcd ) 
64 {
65 #ifdef DEBUG
66         char str[40];
67         
68         switch (_pcd->ep0state)
69         {
70         case EP0_DISCONNECT:
71                 strcpy(str, "EP0_DISCONNECT");
72                 break;
73         case EP0_IDLE:
74                 strcpy(str, "EP0_IDLE");
75                 break;
76         case EP0_IN_DATA_PHASE:
77                 strcpy(str, "EP0_IN_DATA_PHASE");
78                 break;
79         case EP0_OUT_DATA_PHASE:
80                 strcpy(str, "EP0_OUT_DATA_PHASE");
81                 break;
82         case EP0_STATUS:
83                 strcpy(str,"EP0_STATUS");
84                 break;
85         case EP0_STALL:
86                 strcpy(str,"EP0_STALL");
87                 break;
88         default:
89                 strcpy(str,"EP0_INVALID");                               
90         }
91         
92         DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, _pcd->ep0state);            
93 #endif
94 }
95
96 /**
97  * This function returns pointer to in ep struct with number ep_num
98  */
99 static inline dwc_otg_pcd_ep_t* get_in_ep( dwc_otg_pcd_t *_pcd, uint32_t ep_num) 
100 {
101         int i;
102         int num_in_eps = GET_CORE_IF(_pcd)->dev_if->num_in_eps;
103         if(ep_num == 0)
104         {
105                 return &_pcd->ep0;
106         }
107         else
108         {
109                 for(i = 0; i < num_in_eps; ++i)
110                 {
111                         if(_pcd->in_ep[i].dwc_ep.num == ep_num)
112                                 return &_pcd->in_ep[i];
113                 }
114                 return 0;
115         }
116 }
117 /**
118  * This function returns pointer to out ep struct with number ep_num
119  */
120 static inline dwc_otg_pcd_ep_t* get_out_ep( dwc_otg_pcd_t *_pcd, uint32_t ep_num) 
121 {
122         int i;
123         int num_out_eps = GET_CORE_IF(_pcd)->dev_if->num_out_eps;
124         if(ep_num == 0)
125         {
126                 return &_pcd->ep0;
127         }
128         else
129         {
130                 for(i = 0; i < num_out_eps; ++i)
131                 {
132                         if(_pcd->out_ep[i].dwc_ep.num == ep_num)
133                                 return &_pcd->out_ep[i];
134                 }
135                 return 0;
136         }
137 }
138 /**
139  * This functions gets a pointer to an EP from the wIndex address
140  * value of the control request.
141  */
142 static dwc_otg_pcd_ep_t *get_ep_by_addr (dwc_otg_pcd_t *_pcd, u16 _wIndex)
143 {
144         dwc_otg_pcd_ep_t        *ep;
145
146         if ((_wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
147                 return &_pcd->ep0;
148         list_for_each_entry( ep, &_pcd->gadget.ep_list, ep.ep_list) 
149         {
150                 u8      bEndpointAddress;
151
152                 if (!ep->desc)
153                         continue;
154                 bEndpointAddress = ep->desc->bEndpointAddress;
155                 if ((_wIndex ^ bEndpointAddress) & USB_DIR_IN)
156                         continue;
157                 if ((_wIndex & 0x0f) == (bEndpointAddress & 0x0f))
158                         return ep;
159         }
160         return NULL;
161 }
162
163 /**
164  * This function checks the EP request queue, if the queue is not
165  * empty the next request is started.
166  */
167 void start_next_request( dwc_otg_pcd_ep_t *_ep )
168 {
169         dwc_otg_pcd_request_t *req = 0;
170                 
171         if (!list_empty(&_ep->queue))
172         {
173                 req = list_entry(_ep->queue.next, 
174                            dwc_otg_pcd_request_t, queue);
175                         
176                 /* Setup and start the Transfer */
177                 _ep->dwc_ep.start_xfer_buff = req->req.buf;
178                 _ep->dwc_ep.xfer_buff = req->req.buf;
179                 _ep->dwc_ep.xfer_len = req->req.length;
180                 _ep->dwc_ep.xfer_count = 0;
181                 _ep->dwc_ep.dma_addr = req->req.dma;
182                 _ep->dwc_ep.sent_zlp = 0;
183                 _ep->dwc_ep.total_len = _ep->dwc_ep.xfer_len;
184         
185                 dwc_otg_ep_start_transfer( GET_CORE_IF(_ep->pcd), &_ep->dwc_ep );
186         }
187 }
188
189 /**
190  * This function handles the SOF Interrupts. At this time the SOF
191  * Interrupt is disabled.
192  */
193 int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t *_pcd)
194 {
195         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
196
197         gintsts_data_t gintsts;
198                 
199         //DWC_DEBUGPL(DBG_PCD, "SOF\n");
200
201         /* Clear interrupt */
202         gintsts.d32 = 0;
203         gintsts.b.sofintr = 1;
204         dwc_write_reg32 (&core_if->core_global_regs->gintsts, gintsts.d32);
205
206         return 1;
207 }
208
209
210 /**
211  * This function handles the Rx Status Queue Level Interrupt, which
212  * indicates that there is a least one packet in the Rx FIFO.  The
213  * packets are moved from the FIFO to memory, where they will be
214  * processed when the Endpoint Interrupt Register indicates Transfer
215  * Complete or SETUP Phase Done.
216  *
217  * Repeat the following until the Rx Status Queue is empty:
218  *       -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
219  *              info
220  *       -# If Receive FIFO is empty then skip to step Clear the interrupt
221  *              and exit
222  *       -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
223  *              SETUP data to the buffer
224  *       -# If OUT Data Packet call dwc_otg_read_packet to copy the data
225  *              to the destination buffer
226  */
227 int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t *_pcd)
228 {
229         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
230         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
231         gintmsk_data_t gintmask = {.d32=0};
232         device_grxsts_data_t status;
233         dwc_otg_pcd_ep_t *ep;
234         gintsts_data_t gintsts;
235 #ifdef DEBUG
236         static char *dpid_str[] ={ "D0", "D2", "D1", "MDATA" };
237 #endif
238                 
239         //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
240         /* Disable the Rx Status Queue Level interrupt */
241         gintmask.b.rxstsqlvl= 1;
242         dwc_modify_reg32( &global_regs->gintmsk, gintmask.d32, 0);
243
244         /* Get the Status from the top of the FIFO */
245         status.d32 = dwc_read_reg32( &global_regs->grxstsp );
246
247         DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s " 
248                                         "pktsts:%x Frame:%d(0x%0x)\n", 
249                                         status.b.epnum, status.b.bcnt,
250                                         dpid_str[status.b.dpid], 
251                                         status.b.pktsts, status.b.fn, status.b.fn);
252         /* Get pointer to EP structure */
253         ep = get_out_ep(_pcd, status.b.epnum);
254 //        ep = &_pcd->out_ep[ status.b.epnum - 1];
255                 
256         switch (status.b.pktsts) 
257         {
258         case DWC_DSTS_GOUT_NAK:
259                 DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
260                 break;
261         case DWC_STS_DATA_UPDT:
262                 DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
263                 if (status.b.bcnt && ep->dwc_ep.xfer_buff)
264                 {
265                         /** @todo NGS Check for buffer overflow? */
266                         dwc_otg_read_packet( core_if, 
267                                                                  ep->dwc_ep.xfer_buff,
268                                                                  status.b.bcnt);
269                         ep->dwc_ep.xfer_count += status.b.bcnt;
270                         ep->dwc_ep.xfer_buff += status.b.bcnt;
271                 }
272                 break;
273         case DWC_STS_XFER_COMP:
274                 DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
275                 break;
276         case DWC_DSTS_SETUP_COMP:
277 #ifdef DEBUG_EP0
278                 DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
279 #endif
280                 break;
281 case DWC_DSTS_SETUP_UPDT:
282                 dwc_otg_read_setup_packet( core_if, _pcd->setup_pkt->d32);
283 #ifdef DEBUG_EP0
284                 DWC_DEBUGPL(DBG_PCD, 
285                                         "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
286                                         _pcd->setup_pkt->req.bRequestType, 
287                                         _pcd->setup_pkt->req.bRequest,
288                                         _pcd->setup_pkt->req.wValue, 
289                                         _pcd->setup_pkt->req.wIndex, 
290                                         _pcd->setup_pkt->req.wLength);
291 #endif
292                 ep->dwc_ep.xfer_count += status.b.bcnt;
293                 break;
294         default:
295                 DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n", 
296                                                 status.b.pktsts);
297                 break;
298         }
299
300         /* Enable the Rx Status Queue Level interrupt */
301         dwc_modify_reg32( &global_regs->gintmsk, 0, gintmask.d32);
302         /* Clear interrupt */
303         gintsts.d32 = 0;
304         gintsts.b.rxstsqlvl = 1;
305         dwc_write_reg32 (&global_regs->gintsts, gintsts.d32);
306
307         //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
308         return 1;
309 }
310 /**
311  * This function examines the Device IN Token Learning Queue to
312  * determine the EP number of the last IN token received.  This
313  * implementation is for the Mass Storage device where there are only
314  * 2 IN EPs (Control-IN and BULK-IN).
315  *
316  * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
317  * are 8 EP Numbers in each of the other possible DTKNQ Registers.
318  *
319  * @param _core_if Programming view of DWC_otg controller.
320  *
321  */
322 static inline int get_ep_of_last_in_token(dwc_otg_core_if_t *_core_if)
323 {
324         dwc_otg_device_global_regs_t *dev_global_regs = 
325                         _core_if->dev_if->dev_global_regs;
326         const uint32_t TOKEN_Q_DEPTH = _core_if->hwcfg2.b.dev_token_q_depth;
327         /* Number of Token Queue Registers */
328         const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
329         dtknq1_data_t dtknqr1;
330         uint32_t in_tkn_epnums[4];
331         int ndx = 0;
332         int i = 0;
333         volatile uint32_t *addr = &dev_global_regs->dtknqr1;
334         int epnum = 0;
335
336         //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
337         
338         
339         /* Read the DTKNQ Registers */
340         for (i = 0; i < DTKNQ_REG_CNT; i++) 
341         {
342                 in_tkn_epnums[ i ] = dwc_read_reg32(addr);
343                 DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i+1, 
344                                         in_tkn_epnums[i]);
345                 if (addr == &dev_global_regs->dvbusdis) 
346                 {
347                         addr = &dev_global_regs->dtknqr3_dthrctl;
348                 } 
349                 else 
350                 {
351                         ++addr;
352                 }
353                                 
354                 }
355                 
356                 /* Copy the DTKNQR1 data to the bit field. */
357                 dtknqr1.d32 = in_tkn_epnums[0];
358                 /* Get the EP numbers */
359                 in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
360                 ndx = dtknqr1.b.intknwptr - 1;
361
362                 //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
363                 if (ndx == -1) 
364                 {
365                         /** @todo Find a simpler way to calculate the max
366                          * queue position.*/
367                         int cnt = TOKEN_Q_DEPTH;
368                         if (TOKEN_Q_DEPTH <= 6) 
369                         {
370                                 cnt = TOKEN_Q_DEPTH - 1;
371                         }
372                         else if (TOKEN_Q_DEPTH <= 14) 
373                         {
374                                 cnt = TOKEN_Q_DEPTH - 7;
375                         } 
376                         else if (TOKEN_Q_DEPTH <= 22) 
377                         {
378                                 cnt = TOKEN_Q_DEPTH - 15;
379                         } 
380                         else 
381                         {
382                                 cnt = TOKEN_Q_DEPTH - 23;
383                         }
384                         epnum = (in_tkn_epnums[ DTKNQ_REG_CNT - 1 ] >> (cnt * 4)) & 0xF;
385                 } 
386                 else 
387                 {
388                         if (ndx <= 5) 
389                         {
390                                 epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
391                         } 
392                         else if (ndx <= 13 ) 
393                         {
394                                 ndx -= 6;
395                                 epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
396                         } 
397                         else if (ndx <= 21 ) 
398                         {
399                                 ndx -= 14;
400                                 epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
401                         } 
402                         else if (ndx <= 29 ) 
403                         {
404                                 ndx -= 22;
405                                 epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
406                         }
407                 }
408                 //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
409                 return epnum;
410 }
411
412 /**
413  * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
414  * The active request is checked for the next packet to be loaded into
415  * the non-periodic Tx FIFO.
416  */
417 int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t *_pcd)
418 {
419         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
420         dwc_otg_core_global_regs_t *global_regs = 
421                         core_if->core_global_regs;
422         dwc_otg_dev_in_ep_regs_t *ep_regs;
423         gnptxsts_data_t txstatus = {.d32 = 0};
424         gintsts_data_t gintsts;
425         
426         int epnum = 0;
427         dwc_otg_pcd_ep_t *ep = 0;
428         uint32_t len = 0;
429         int dwords;
430
431         /* Get the epnum from the IN Token Learning Queue. */
432         epnum = get_ep_of_last_in_token(core_if);
433         ep = get_in_ep(_pcd, epnum);
434 /*      
435         if(epnum != 0)
436                 ep = &_pcd->in_ep[epnum-1];
437         else
438                 ep = &_pcd->ep0;
439 */
440         DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %s(%d) \n", ep->ep.name, epnum );
441
442         ep_regs = core_if->dev_if->in_ep_regs[epnum];
443         
444         len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
445         if (len > ep->dwc_ep.maxpacket) 
446         {
447                 len = ep->dwc_ep.maxpacket;
448         }
449         dwords = (len + 3)/4;
450                 
451                 
452         /* While there is space in the queue and space in the FIFO and
453         * More data to tranfer, Write packets to the Tx FIFO */
454         txstatus.d32 = dwc_read_reg32( &global_regs->gnptxsts );
455         DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n",txstatus.d32);
456         
457         while  (txstatus.b.nptxqspcavail > 0 &&
458                                 txstatus.b.nptxfspcavail > dwords &&
459                                 ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) 
460         {
461                 /* Write the FIFO */
462                 dwc_otg_ep_write_packet( core_if, &ep->dwc_ep, 0 );
463                 len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
464                 
465                 if (len > ep->dwc_ep.maxpacket) 
466                 {
467                         len = ep->dwc_ep.maxpacket;
468                 }
469                 
470                 dwords = (len + 3)/4;
471                 txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts);
472                 DWC_DEBUGPL(DBG_PCDV,"GNPTXSTS=0x%08x\n",txstatus.d32);
473         }       
474                                 
475         DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
476                                         dwc_read_reg32( &global_regs->gnptxsts));
477
478         /* Clear interrupt */
479         gintsts.d32 = 0;
480         gintsts.b.nptxfempty = 1;
481         dwc_write_reg32 (&global_regs->gintsts, gintsts.d32);
482
483         return 1;
484 }
485
486 /**
487  * This function is called when dedicated Tx FIFO Empty interrupt occurs.
488  * The active request is checked for the next packet to be loaded into
489  * apropriate Tx FIFO.
490  */
491 static int32_t write_empty_tx_fifo(dwc_otg_pcd_t *_pcd, uint32_t epnum)
492 {
493         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
494         dwc_otg_dev_if_t* dev_if = core_if->dev_if; 
495         dwc_otg_dev_in_ep_regs_t *ep_regs;
496         dtxfsts_data_t txstatus = {.d32 = 0};
497         dwc_otg_pcd_ep_t *ep = 0;
498         uint32_t len = 0;
499         int dwords;
500
501         ep = get_in_ep(_pcd, epnum);
502 /*
503         if(epnum != 0)
504                 ep = &_pcd->in_ep[epnum-1];
505         else
506                 ep = &_pcd->ep0;
507 */
508         DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %s(%d) \n", ep->ep.name, epnum );
509
510         ep_regs = core_if->dev_if->in_ep_regs[epnum];
511                 
512         len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
513
514         if (len > ep->dwc_ep.maxpacket) 
515         {
516                 len = ep->dwc_ep.maxpacket;
517         }
518         
519         dwords = (len + 3)/4;
520                 
521         /* While there is space in the queue and space in the FIFO and
522          * More data to tranfer, Write packets to the Tx FIFO */
523         txstatus.d32 = dwc_read_reg32( &dev_if->in_ep_regs[epnum]->dtxfsts);
524         DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n",epnum,txstatus.d32);
525
526         while  (txstatus.b.txfspcavail > dwords && 
527                         ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
528                         ep->dwc_ep.xfer_len != 0) 
529         {
530                 /* Write the FIFO */
531                 dwc_otg_ep_write_packet( core_if, &ep->dwc_ep, 0);
532
533                 len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
534                 if (len > ep->dwc_ep.maxpacket) 
535                 {
536                         len = ep->dwc_ep.maxpacket;
537                 }
538                                 
539                 dwords = (len + 3)/4;
540                 txstatus.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts);
541                 DWC_DEBUGPL(DBG_PCDV,"dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
542         }
543                                 
544         DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n",epnum,dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts));
545
546         return 1;
547 }
548
549  
550 /** 
551  * This function is called when the Device is disconnected.      It stops
552  * any active requests and informs the Gadget driver of the
553  * disconnect.
554  */
555 void dwc_otg_pcd_stop(dwc_otg_pcd_t *_pcd)
556 {
557         int i, num_in_eps, num_out_eps;
558         dwc_otg_pcd_ep_t *ep;
559         
560         gintmsk_data_t intr_mask = {.d32 = 0};
561     
562     SPIN_LOCK(&_pcd->lock);
563
564         num_in_eps = GET_CORE_IF(_pcd)->dev_if->num_in_eps;
565         num_out_eps = GET_CORE_IF(_pcd)->dev_if->num_out_eps;
566         
567         DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__ );
568         /* don't disconnect drivers more than once */
569         if (_pcd->ep0state == EP0_DISCONNECT) 
570         {
571                 SPIN_UNLOCK(&_pcd->lock);
572                 DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__ );
573                 return;            
574         }
575         _pcd->ep0state = EP0_DISCONNECT;
576
577         /* Reset the OTG state. */
578         dwc_otg_pcd_update_otg( _pcd, 1);
579                 
580         /* Disable the NP Tx Fifo Empty Interrupt. */
581         intr_mask.b.nptxfempty = 1;
582         dwc_modify_reg32(&GET_CORE_IF(_pcd)->core_global_regs->gintmsk, 
583                                          intr_mask.d32, 0);
584
585         /* Flush the FIFOs */
586         /**@todo NGS Flush Periodic FIFOs */
587         dwc_otg_flush_tx_fifo( GET_CORE_IF(_pcd), 0);
588         dwc_otg_flush_rx_fifo( GET_CORE_IF(_pcd) );
589
590         /* prevent new request submissions, kill any outstanding requests  */
591         ep = &_pcd->ep0;
592         request_nuke(ep);
593         /* prevent new request submissions, kill any outstanding requests  */
594         for (i = 0; i < num_in_eps; i++) 
595         {
596                 dwc_otg_pcd_ep_t *ep = &_pcd->in_ep[i];
597                 request_nuke(ep);
598         }
599         /* prevent new request submissions, kill any outstanding requests  */
600         for (i = 0; i < num_out_eps; i++) 
601         {
602                 dwc_otg_pcd_ep_t *ep = &_pcd->out_ep[i];
603                 request_nuke(ep);
604         }
605
606         /* report disconnect; the driver is already quiesced */
607         if (_pcd->driver && _pcd->driver->disconnect) 
608         {
609                 SPIN_UNLOCK(&_pcd->lock);
610                 _pcd->driver->disconnect(&_pcd->gadget);
611                 SPIN_LOCK(&_pcd->lock);
612         }
613                 SPIN_UNLOCK(&_pcd->lock);
614 }
615
616 /**
617  * This interrupt indicates that ...
618  */
619 int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t *_pcd)
620 {
621         gintmsk_data_t intr_mask = { .d32 = 0};
622         gintsts_data_t gintsts;
623
624         DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "i2cintr"); 
625         intr_mask.b.i2cintr = 1;
626         dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, 
627                                           intr_mask.d32, 0 );
628
629         /* Clear interrupt */
630         gintsts.d32 = 0;
631         gintsts.b.i2cintr = 1;
632         dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, 
633                                                  gintsts.d32);
634         return 1;
635 }
636
637
638 /**
639  * This interrupt indicates that ...
640  */
641 int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t *_pcd)
642 {
643         gintsts_data_t gintsts;
644 #if defined(VERBOSE)
645         DWC_PRINT("Early Suspend Detected\n");
646 #endif
647         /* Clear interrupt */
648         gintsts.d32 = 0;
649         gintsts.b.erlysuspend = 1;
650         dwc_write_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintsts, 
651                                                  gintsts.d32);
652         return 1;
653 }
654
655 /**
656  * This function configures EPO to receive SETUP packets.
657  *
658  * @todo NGS: Update the comments from the HW FS.
659  *
660  *      -# Program the following fields in the endpoint specific registers
661  *      for Control OUT EP 0, in order to receive a setup packet
662  *      - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
663  *        setup packets)
664  *      - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
665  *        to back setup packets)
666  *              - In DMA mode, DOEPDMA0 Register with a memory address to
667  *                store any setup packets received
668  *
669  * @param _core_if Programming view of DWC_otg controller.
670  * @param _pcd    Programming view of the PCD.
671  */
672 static inline void ep0_out_start( dwc_otg_core_if_t *_core_if, dwc_otg_pcd_t *_pcd )
673 {
674         dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
675         deptsiz0_data_t doeptsize0 = { .d32 = 0};
676
677 #ifdef VERBOSE
678         DWC_DEBUGPL(DBG_PCDV,"%s() doepctl0=%0x\n", __func__,
679                                 dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));
680 #endif
681
682         doeptsize0.b.supcnt = 3;        
683         doeptsize0.b.pktcnt = 1;
684         doeptsize0.b.xfersize = 8*3;
685         
686         dwc_write_reg32( &dev_if->out_ep_regs[0]->doeptsiz, 
687                                          doeptsize0.d32 );               
688
689         if (_core_if->dma_enable) 
690         {
691                 depctl_data_t doepctl = { .d32 = 0 };
692                 /** @todo dma needs to handle multiple setup packets (up to 3) */
693                 dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma, 
694                 _pcd->setup_pkt_dma_handle);
695                 // EP enable
696                 doepctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl);
697                 doepctl.b.epena = 1;
698
699                 doepctl.d32 = 0x80008000;
700                                 dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl,
701                                 doepctl.d32);
702         }
703 #ifdef VERBOSE
704                 DWC_DEBUGPL(DBG_PCDV,"doepctl0=%0x\n", 
705                                         dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));
706                 DWC_DEBUGPL(DBG_PCDV,"diepctl0=%0x\n", 
707                                         dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl));
708 #endif
709
710 }
711
712 /**
713  * This interrupt occurs when a USB Reset is detected.  When the USB
714  * Reset Interrupt occurs the device state is set to DEFAULT and the
715  * EP0 state is set to IDLE.
716  *      -#      Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
717  *      -#      Unmask the following interrupt bits
718  *              - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
719  *      - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
720  *      - DOEPMSK.SETUP = 1
721  *      - DOEPMSK.XferCompl = 1
722  *      - DIEPMSK.XferCompl = 1
723  *      - DIEPMSK.TimeOut = 1
724  *      -# Program the following fields in the endpoint specific registers
725  *      for Control OUT EP 0, in order to receive a setup packet
726  *      - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
727  *        setup packets)
728  *      - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
729  *        to back setup packets)
730  *              - In DMA mode, DOEPDMA0 Register with a memory address to
731  *                store any setup packets received
732  * At this point, all the required initialization, except for enabling
733  * the control 0 OUT endpoint is done, for receiving SETUP packets.
734  */
735 int32_t dwc_otg_pcd_handle_usb_reset_intr( dwc_otg_pcd_t * _pcd)
736 {
737         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
738         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
739         depctl_data_t doepctl = { .d32 = 0};
740         daint_data_t daintmsk = { .d32 = 0};
741         doepmsk_data_t doepmsk = { .d32 = 0};
742         diepmsk_data_t diepmsk = { .d32 = 0};
743         dcfg_data_t dcfg = { .d32=0 };
744         grstctl_t resetctl = { .d32=0 };
745         dctl_data_t dctl = {.d32=0};
746         int i = 0;
747         gintsts_data_t gintsts;
748                                                 
749         DWC_PRINT("USB RESET\n");
750
751         /* reset the HNP settings */
752         dwc_otg_pcd_update_otg( _pcd, 1);
753
754         /* Clear the Remote Wakeup Signalling */
755         dctl.b.rmtwkupsig = 1;
756         dwc_modify_reg32( &core_if->dev_if->dev_global_regs->dctl, 
757                                           dctl.d32, 0 );
758
759         /* Set NAK for all OUT EPs */
760         doepctl.b.snak = 1;
761         for (i=0; i <= dev_if->num_out_eps; i++) 
762         {
763                 dwc_write_reg32( &dev_if->out_ep_regs[i]->doepctl, 
764                                                  doepctl.d32 );
765         }
766
767         /* Flush the NP Tx FIFO , CHANGE 0x0 to 0x10 to flush all fifo. */
768         dwc_otg_flush_tx_fifo( core_if, 0x10 );
769         /* Flush the Learning Queue */
770         resetctl.b.intknqflsh = 1;
771         dwc_write_reg32( &core_if->core_global_regs->grstctl, resetctl.d32);
772
773         daintmsk.b.inep0 = 1;
774         daintmsk.b.outep0 = 1;
775         dwc_write_reg32( &dev_if->dev_global_regs->daintmsk, daintmsk.d32 );
776
777         doepmsk.b.setup = 1;
778         doepmsk.b.xfercompl = 1;
779         doepmsk.b.ahberr = 1;
780         doepmsk.b.epdisabled = 1;
781         dwc_write_reg32( &dev_if->dev_global_regs->doepmsk, doepmsk.d32 );
782
783         diepmsk.b.xfercompl = 1;
784         diepmsk.b.timeout = 1;
785         diepmsk.b.epdisabled = 1;
786         diepmsk.b.ahberr = 1;
787         diepmsk.b.intknepmis = 1;
788         dwc_write_reg32( &dev_if->dev_global_regs->diepmsk, diepmsk.d32 );               
789         /* Reset Device Address */
790         dcfg.d32 = dwc_read_reg32( &dev_if->dev_global_regs->dcfg);
791         dcfg.b.devaddr = 0;
792         dwc_write_reg32( &dev_if->dev_global_regs->dcfg, dcfg.d32);
793
794         /* setup EP0 to receive SETUP packets */
795         ep0_out_start( core_if, _pcd );
796                 
797         /* Clear interrupt */
798         gintsts.d32 = 0;
799         gintsts.b.usbreset = 1;
800         dwc_write_reg32 (&core_if->core_global_regs->gintsts, gintsts.d32);
801
802         return 1;
803 }
804
805 /**
806  * Get the device speed from the device status register and convert it
807  * to USB speed constant.
808  *
809  * @param _core_if Programming view of DWC_otg controller.
810  */
811 static int get_device_speed( dwc_otg_core_if_t *_core_if )
812 {
813         dsts_data_t dsts;
814         enum usb_device_speed speed = USB_SPEED_UNKNOWN;
815         dsts.d32 = dwc_read_reg32(&_core_if->dev_if->dev_global_regs->dsts);
816
817         switch (dsts.b.enumspd) 
818         {
819         case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
820                 speed = USB_SPEED_HIGH;
821                 break;
822         case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
823         case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
824                 speed = USB_SPEED_FULL;
825                 break;
826
827         case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
828                 speed = USB_SPEED_LOW;
829                 break;
830         }
831
832         return speed; 
833 }
834
835 /**
836  * Read the device status register and set the device speed in the
837  * data structure.      
838  * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
839  */
840 int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t *_pcd)
841 {
842         dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0;
843         gintsts_data_t gintsts;
844         gusbcfg_data_t gusbcfg;
845     volatile depctl_data_t depctl = {.d32 = 0};
846         dwc_otg_core_global_regs_t *global_regs =
847         GET_CORE_IF(_pcd)->core_global_regs;
848         uint32_t gsnpsid = global_regs->gsnpsid;
849         uint8_t utmi16b, utmi8b;
850         DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
851
852         if(gsnpsid >= (uint32_t)0x4f54260a)
853         {
854                 utmi16b = 5;
855                 utmi8b = 9;
856         }
857         else
858         {
859                 utmi16b = 4;
860                 utmi8b = 8;
861         }
862         dwc_otg_ep0_activate( GET_CORE_IF(_pcd), &ep0->dwc_ep );
863
864 #ifdef DEBUG_EP0
865         print_ep0_state(_pcd);
866 #endif
867                 
868         
869         _pcd->ep0state = EP0_IDLE;
870
871         ep0->stopped = 0;
872                 
873         _pcd->gadget.speed = get_device_speed(GET_CORE_IF(_pcd));
874
875         /* Set USB turnaround time based on device speed and PHY interface. */
876         gusbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
877         if (_pcd->gadget.speed == USB_SPEED_HIGH) 
878         {
879         depctl.b.mps = 0x200;
880                 if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_ULPI) 
881                 {
882                         /* ULPI interface */
883                         gusbcfg.b.usbtrdtim = 9;
884                 }
885                 if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI) 
886                 {
887 /////
888                         /* UTMI+ interface */
889                         if (GET_CORE_IF(_pcd)->hwcfg4.b.utmi_phy_data_width == 0) 
890                         {
891                                 gusbcfg.b.usbtrdtim = utmi8b;
892                         }
893                         else if (GET_CORE_IF(_pcd)->hwcfg4.b.utmi_phy_data_width == 1) 
894                         {
895                                 gusbcfg.b.usbtrdtim = utmi16b;
896                         }
897                         else if (GET_CORE_IF(_pcd)->core_params->phy_utmi_width == 8) 
898                         {
899                                 gusbcfg.b.usbtrdtim = utmi8b;
900                         } 
901                         else 
902                         {
903                                 gusbcfg.b.usbtrdtim = utmi16b;
904                         }
905                 }
906                 if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) 
907                 {
908                         /* UTMI+  OR  ULPI interface */
909                         if (gusbcfg.b.ulpi_utmi_sel == 1) 
910                         {
911                                 /* ULPI interface */
912                                 gusbcfg.b.usbtrdtim = 9;
913                         } 
914                         else 
915                         {
916                                 /* UTMI+ interface */
917                                 if (GET_CORE_IF(_pcd)->core_params->phy_utmi_width == 16) 
918                                 {
919                                         gusbcfg.b.usbtrdtim = utmi16b;
920                                 } 
921                                 else 
922                                 {
923                                         gusbcfg.b.usbtrdtim = utmi8b;
924                                 }
925                         }
926                 }
927         } 
928         else 
929         {
930         depctl.b.mps = 0x40;
931                 /* Full or low speed */
932                 gusbcfg.b.usbtrdtim = 9;
933         }
934         dwc_write_reg32(&global_regs->gusbcfg, gusbcfg.d32);
935
936         /* Clear interrupt */
937         gintsts.d32 = 0;
938         gintsts.b.enumdone = 1;
939         dwc_write_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintsts, 
940                                                  gintsts.d32 );
941         /* enable ep2out */
942         depctl.b.setd0pid = 1;
943     dwc_write_reg32( &GET_CORE_IF(_pcd)->dev_if->in_ep_regs[1]->diepctl, depctl.d32);
944         depctl.b.snak = 1;
945         depctl.b.txfnum = 2;
946         depctl.b.eptype = 2;
947     depctl.b.usbactep = 1;
948     dwc_write_reg32( &GET_CORE_IF(_pcd)->dev_if->out_ep_regs[2]->doepctl, depctl.d32 );
949     dwc_write_reg32( &GET_CORE_IF(_pcd)->dev_if->out_ep_regs[4]->doepctl, depctl.d32 );
950     dwc_write_reg32( &GET_CORE_IF(_pcd)->dev_if->out_ep_regs[6]->doepctl, depctl.d32 );
951     dwc_write_reg32( &GET_CORE_IF(_pcd)->dev_if->out_ep_regs[8]->doepctl, depctl.d32 );
952         return 1;
953 }
954
955 /**
956  * This interrupt indicates that the ISO OUT Packet was dropped due to
957  * Rx FIFO full or Rx Status Queue Full.  If this interrupt occurs
958  * read all the data from the Rx FIFO.
959  */
960 int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t *_pcd )
961 {
962         gintmsk_data_t intr_mask = { .d32 = 0};
963         gintsts_data_t gintsts;
964         
965         DWC_PRINT("INTERRUPT Handler not implemented for %s\n",
966                           "ISOC Out Dropped");
967
968         intr_mask.b.isooutdrop = 1;
969         dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, 
970                                           intr_mask.d32, 0 );
971
972         /* Clear interrupt */
973         gintsts.d32 = 0;
974         gintsts.b.isooutdrop = 1;
975         dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, 
976                                                  gintsts.d32);
977
978         return 1;
979 }
980
981 /**
982  * This interrupt indicates the end of the portion of the micro-frame
983  * for periodic transactions.  If there is a periodic transaction for
984  * the next frame, load the packets into the EP periodic Tx FIFO.
985  */
986 int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t *_pcd )
987 {
988         gintmsk_data_t intr_mask = { .d32 = 0};
989         gintsts_data_t gintsts;
990         DWC_PRINT("INTERRUPT Handler not implemented for %s\n",
991                           "EOP");
992
993         intr_mask.b.eopframe = 1;
994         dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, 
995                                           intr_mask.d32, 0 );
996
997         /* Clear interrupt */
998         gintsts.d32 = 0;
999         gintsts.b.eopframe = 1;
1000         dwc_write_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintsts, 
1001                                                  gintsts.d32);
1002
1003         return 1;
1004 }
1005
1006 /**
1007  * This interrupt indicates that EP of the packet on the top of the
1008  * non-periodic Tx FIFO does not match EP of the IN Token received.
1009  *
1010  * The "Device IN Token Queue" Registers are read to determine the
1011  * order the IN Tokens have been received.      The non-periodic Tx FIFO
1012  * is flushed, so it can be reloaded in the order seen in the IN Token
1013  * Queue.
1014  */
1015 int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_core_if_t *_core_if)
1016 {
1017         gintsts_data_t gintsts;
1018         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _core_if);
1019
1020         /* Clear interrupt */
1021         gintsts.d32 = 0;
1022         gintsts.b.epmismatch = 1;
1023         dwc_write_reg32 (&_core_if->core_global_regs->gintsts, gintsts.d32);
1024
1025         return 1;
1026 }
1027
1028 /**
1029  * This funcion stalls EP0.
1030  */
1031 static inline void ep0_do_stall( dwc_otg_pcd_t *_pcd, const int err_val ) 
1032 {
1033         dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0;
1034         struct usb_ctrlrequest  *ctrl = &_pcd->setup_pkt->req;
1035         DWC_WARN("req %02x.%02x v%04x i%04x l%04x protocol STALL; err %d\n",
1036                          ctrl->bRequestType, ctrl->bRequest,ctrl->wValue, ctrl->wIndex, ctrl->wLength, err_val);                
1037
1038         ep0->dwc_ep.is_in = 1;
1039         dwc_otg_ep_set_stall( _pcd->otg_dev->core_if, &ep0->dwc_ep );           
1040         _pcd->ep0.stopped = 1;
1041         _pcd->ep0state = EP0_IDLE;
1042         ep0_out_start( GET_CORE_IF(_pcd), _pcd );
1043 }
1044
1045 /**
1046  * This functions delegates the setup command to the gadget driver.
1047  */
1048 static inline void do_gadget_setup( dwc_otg_pcd_t *_pcd, 
1049                                                                         struct usb_ctrlrequest * _ctrl)
1050 {
1051         int ret = 0;
1052         if (_pcd->driver && _pcd->driver->setup) 
1053         {
1054                 SPIN_UNLOCK(&_pcd->lock);
1055                 ret = _pcd->driver->setup(&_pcd->gadget, _ctrl);
1056                 if(spin_is_locked(&_pcd->lock))
1057                     DWC_PRINT("%s warning: pcd->lock locked without unlock\n", __func__);
1058                 SPIN_LOCK(&_pcd->lock);
1059                 if (ret < 0) 
1060                 {
1061                         ep0_do_stall( _pcd, ret );
1062                 }
1063
1064                 /** @todo This is a g_file_storage gadget driver specific
1065                  * workaround: a DELAYED_STATUS result from the fsg_setup
1066                  * routine will result in the gadget queueing a EP0 IN status
1067                  * phase for a two-stage control transfer.      Exactly the same as
1068                  * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
1069                  * specific request.  Need a generic way to know when the gadget
1070                  * driver will queue the status phase.  Can we assume when we
1071                  * call the gadget driver setup() function that it will always
1072                  * queue and require the following flag?  Need to look into
1073                  * this.
1074                  */
1075
1076                 if (ret == 256 + 999) 
1077                 {
1078                         _pcd->request_config = 1;
1079                 }
1080         }
1081 }
1082
1083 /**
1084  * This function starts the Zero-Length Packet for the IN status phase
1085  * of a 2 stage control transfer. 
1086  */
1087 static inline void do_setup_in_status_phase( dwc_otg_pcd_t *_pcd)
1088 {
1089         dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0;
1090         if (_pcd->ep0state == EP0_STALL)
1091         {
1092                 return;
1093         }
1094                         
1095         _pcd->ep0state = EP0_STATUS;
1096                 
1097         /* Prepare for more SETUP Packets */
1098         DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
1099         ep0->dwc_ep.xfer_len = 0;
1100         ep0->dwc_ep.xfer_count = 0;
1101         ep0->dwc_ep.is_in = 1;
1102         ep0->dwc_ep.dma_addr = _pcd->setup_pkt_dma_handle;
1103
1104         dwc_otg_ep0_start_transfer( GET_CORE_IF(_pcd), &ep0->dwc_ep );
1105
1106         /* Prepare for more SETUP Packets */
1107         ep0_out_start( GET_CORE_IF(_pcd), _pcd );
1108
1109 }
1110
1111 /**
1112  * This function starts the Zero-Length Packet for the OUT status phase
1113  * of a 2 stage control transfer. 
1114  */
1115 static inline void do_setup_out_status_phase( dwc_otg_pcd_t *_pcd)
1116 {
1117         dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0;
1118         if (_pcd->ep0state == EP0_STALL)
1119         {
1120                 DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
1121                 return;
1122         }
1123         _pcd->ep0state = EP0_STATUS;
1124                 
1125         /* Prepare for more SETUP Packets */
1126         //ep0_out_start( GET_CORE_IF(_pcd), _pcd );
1127
1128         DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
1129         ep0->dwc_ep.xfer_len = 0;
1130         ep0->dwc_ep.xfer_count = 0;
1131         ep0->dwc_ep.is_in = 0;
1132         //ep0->dwc_ep.dma_addr = 0xffffffff;
1133         ep0->dwc_ep.dma_addr = _pcd->setup_pkt_dma_handle;
1134         dwc_otg_ep0_start_transfer( GET_CORE_IF(_pcd), &ep0->dwc_ep );
1135
1136         /* Prepare for more SETUP Packets */
1137         ep0_out_start( GET_CORE_IF(_pcd), _pcd );
1138
1139 }
1140
1141 /**
1142  * Clear the EP halt (STALL) and if pending requests start the
1143  * transfer.
1144  */
1145 static inline void pcd_clear_halt( dwc_otg_pcd_t *_pcd, dwc_otg_pcd_ep_t *_ep )
1146 {
1147         if(_ep->dwc_ep.stall_clear_flag == 0)
1148                 dwc_otg_ep_clear_stall( GET_CORE_IF(_pcd), &_ep->dwc_ep );
1149
1150         /* Reactive the EP */
1151         dwc_otg_ep_activate( GET_CORE_IF(_pcd), &_ep->dwc_ep );
1152         if (_ep->stopped) 
1153         {
1154                 _ep->stopped = 0;
1155                 /* If there is a request in the EP queue start it */ 
1156
1157                 /** @todo FIXME: this causes an EP mismatch in DMA mode.
1158                  * epmismatch not yet implemented. */
1159
1160                 /*
1161                  * Above fixme is solved by implmenting a tasklet to call the
1162                  * start_next_request(), outside of interrupt context at some
1163                  * time after the current time, after a clear-halt setup packet.
1164                  * Still need to implement ep mismatch in the future if a gadget
1165                  * ever uses more than one endpoint at once 
1166                  */
1167                 if (GET_CORE_IF(_pcd)->dma_enable) 
1168                 {
1169                         _ep->queue_sof = 1;
1170                         tasklet_schedule (_pcd->start_xfer_tasklet);
1171                 }
1172                 else 
1173                 {
1174 #if 0
1175                         _ep->queue_sof = 1;
1176                         DWC_ERROR("tasklet schedule\n");
1177                         tasklet_schedule (_pcd->start_xfer_tasklet);
1178                         if (GET_CORE_IF(_pcd)->core_params->opt) 
1179                         {
1180                                 start_next_request( _ep );
1181                         }
1182 #endif
1183                 }
1184         } 
1185         /* Start Control Status Phase */
1186         do_setup_in_status_phase( _pcd );
1187 }
1188
1189 /**
1190  * This function is called when the SET_FEATURE TEST_MODE Setup packet
1191  * is sent from the host.  The Device Control register is written with
1192  * the Test Mode bits set to the specified Test Mode.  This is done as
1193  * a tasklet so that the "Status" phase of the control transfer
1194  * completes before transmitting the TEST packets.
1195  *
1196  * @todo This has not been tested since the tasklet struct was put
1197  * into the PCD struct!
1198  *
1199  */
1200 static void do_test_mode( unsigned long _data )
1201 {
1202         dctl_data_t             dctl;
1203         dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)_data;
1204         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
1205         int test_mode = pcd->test_mode;
1206                 
1207
1208 //        DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);                
1209                                                 
1210         dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl);
1211         switch (test_mode) 
1212         {
1213         case 1: // TEST_J
1214                 dctl.b.tstctl = 1;
1215                 break;
1216
1217         case 2: // TEST_K       
1218                 dctl.b.tstctl = 2;
1219                 break;
1220
1221         case 3: // TEST_SE0_NAK
1222                 dctl.b.tstctl = 3;
1223                 break;
1224
1225         case 4: // TEST_PACKET
1226                 dctl.b.tstctl = 4;
1227                 break;
1228
1229         case 5: // TEST_FORCE_ENABLE
1230                 dctl.b.tstctl = 5;
1231                 break;
1232         }
1233         dwc_write_reg32(&core_if->dev_if->dev_global_regs->dctl,
1234                                                 dctl.d32);
1235 }
1236
1237
1238 /**
1239  * This function process the SET_FEATURE Setup Commands.
1240  */
1241 static inline void do_set_feature( dwc_otg_pcd_t *_pcd )
1242 {
1243         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
1244         dwc_otg_core_global_regs_t *global_regs = 
1245                         core_if->core_global_regs;
1246         struct usb_ctrlrequest  ctrl = _pcd->setup_pkt->req;
1247         dwc_otg_pcd_ep_t        *ep = 0;
1248         int32_t otg_cap_param = core_if->core_params->otg_cap;
1249         gotgctl_data_t gotgctl = { .d32 = 0 }; 
1250
1251         DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
1252                                         ctrl.bRequestType, ctrl.bRequest,
1253                                         ctrl.wValue, ctrl.wIndex, ctrl.wLength);
1254         DWC_DEBUGPL(DBG_PCD,"otg_cap=%d\n", otg_cap_param);
1255                 
1256
1257         switch (ctrl.bRequestType & USB_RECIP_MASK) 
1258         {
1259         case USB_RECIP_DEVICE:
1260                 switch (ctrl.wValue) 
1261                 {
1262                 case USB_DEVICE_REMOTE_WAKEUP:
1263                         _pcd->remote_wakeup_enable = 1;
1264                         break;
1265
1266                 case USB_DEVICE_TEST_MODE:
1267                         /* Setup the Test Mode tasklet to do the Test
1268                          * Packet generation after the SETUP Status
1269                          * phase has completed. */
1270
1271                         /** @todo This has not been tested since the
1272                          * tasklet struct was put into the PCD
1273                          * struct! */
1274                         _pcd->test_mode_tasklet.next = 0;
1275                         _pcd->test_mode_tasklet.state = 0;
1276                         atomic_set( &_pcd->test_mode_tasklet.count, 0);
1277                         _pcd->test_mode_tasklet.func = do_test_mode;
1278                         _pcd->test_mode_tasklet.data = (unsigned long)_pcd;
1279                         _pcd->test_mode = ctrl.wIndex >> 8; 
1280                         tasklet_schedule(&_pcd->test_mode_tasklet);
1281                         break;
1282
1283                 case USB_DEVICE_B_HNP_ENABLE:
1284                         DWC_DEBUGPL(DBG_PCDV, "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
1285                                                 
1286                         /* dev may initiate HNP */
1287                         if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) 
1288                         {
1289                                 _pcd->b_hnp_enable = 1;
1290                                 dwc_otg_pcd_update_otg( _pcd, 0 );
1291                                 DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
1292                                 /**@todo Is the gotgctl.devhnpen cleared
1293                                  * by a USB Reset? */
1294                                 gotgctl.b.devhnpen = 1;
1295                                 gotgctl.b.hnpreq = 1;
1296                                 dwc_write_reg32( &global_regs->gotgctl, gotgctl.d32 );
1297                         }
1298                         else 
1299                         {
1300                                 ep0_do_stall( _pcd, -EOPNOTSUPP);
1301                         }                                                
1302                         break;
1303
1304                 case USB_DEVICE_A_HNP_SUPPORT:
1305                         /* RH port supports HNP */
1306                         DWC_DEBUGPL(DBG_PCDV, "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
1307                         if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
1308                         {
1309                                 _pcd->a_hnp_support = 1;
1310                                 dwc_otg_pcd_update_otg( _pcd, 0 );
1311                         } 
1312                         else 
1313                         {
1314                                 ep0_do_stall( _pcd, -EOPNOTSUPP);
1315                         }                                                
1316                         break;
1317
1318                 case USB_DEVICE_A_ALT_HNP_SUPPORT:
1319                         /* other RH port does */
1320                         DWC_DEBUGPL(DBG_PCDV, "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
1321                         if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
1322                         {
1323                                 _pcd->a_alt_hnp_support = 1;
1324                                 dwc_otg_pcd_update_otg( _pcd, 0 );
1325                         } 
1326                         else 
1327                         {
1328                                 ep0_do_stall( _pcd, -EOPNOTSUPP);
1329                         }                                                
1330                         break;
1331                 }
1332                 do_setup_in_status_phase( _pcd );
1333                 break;
1334
1335         case USB_RECIP_INTERFACE:
1336                 do_gadget_setup(_pcd, &ctrl );
1337                 break;
1338
1339         case USB_RECIP_ENDPOINT:
1340                 if (ctrl.wValue == USB_ENDPOINT_HALT) 
1341                 {
1342                         ep = get_ep_by_addr(_pcd, ctrl.wIndex);
1343                         if (ep == 0) 
1344                         {
1345                                 ep0_do_stall(_pcd, -EOPNOTSUPP);
1346                                 return;
1347                         } 
1348                         ep->stopped = 1;
1349                         dwc_otg_ep_set_stall( core_if, &ep->dwc_ep );
1350                 }
1351                 do_setup_in_status_phase( _pcd );
1352                 break;
1353         }
1354 }
1355
1356 /**
1357  * This function process the CLEAR_FEATURE Setup Commands.
1358  */
1359 static inline void do_clear_feature( dwc_otg_pcd_t *_pcd )
1360 {
1361         struct usb_ctrlrequest  ctrl = _pcd->setup_pkt->req;
1362         dwc_otg_pcd_ep_t        *ep = 0;
1363
1364
1365         DWC_DEBUGPL(DBG_PCD, 
1366                                 "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
1367                                 ctrl.bRequestType, ctrl.bRequest,
1368                                 ctrl.wValue, ctrl.wIndex, ctrl.wLength);
1369
1370         switch (ctrl.bRequestType & USB_RECIP_MASK) 
1371         {
1372         case USB_RECIP_DEVICE:
1373                 switch (ctrl.wValue) 
1374                 {
1375                 case USB_DEVICE_REMOTE_WAKEUP:
1376                         _pcd->remote_wakeup_enable = 0;
1377                         break;
1378
1379                 case USB_DEVICE_TEST_MODE:
1380                         /** @todo Add CLEAR_FEATURE for TEST modes. */
1381                         break;
1382                 }
1383                 do_setup_in_status_phase( _pcd );
1384                 break;
1385
1386         case USB_RECIP_ENDPOINT:
1387                 ep = get_ep_by_addr(_pcd, ctrl.wIndex);
1388                 if (ep == 0) 
1389                 {
1390                         ep0_do_stall(_pcd, -EOPNOTSUPP);
1391                         return;
1392                 } 
1393
1394                 pcd_clear_halt(_pcd, ep );
1395
1396                 break;
1397         }
1398 }
1399
1400 /**
1401  *      This function processes SETUP commands.  In Linux, the USB Command
1402  *      processing is done in two places - the first being the PCD and the
1403  *      second in the Gadget Driver (for example, the File-Backed Storage
1404  *      Gadget Driver).
1405  *
1406  * <table>
1407  * <tr><td>Command      </td><td>Driver </td><td>Description</td></tr>
1408  *
1409  * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
1410  * defined in chapter 9 of the USB 2.0 Specification chapter 9
1411  * </td></tr>
1412  *
1413  * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
1414  * requests are the ENDPOINT_HALT feature is procesed, all others the
1415  * interface requests are ignored.</td></tr>
1416  *
1417  * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
1418  * requests are processed by the PCD.  Interface requests are passed
1419  * to the Gadget Driver.</td></tr>
1420  *
1421  * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
1422  * with device address received </td></tr>
1423  *
1424  * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
1425  * requested descriptor</td></tr>
1426  *
1427  * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
1428  * not implemented by any of the existing Gadget Drivers.</td></tr>
1429  *
1430  * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
1431  * all EPs and enable EPs for new configuration.</td></tr>
1432  *
1433  * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
1434  * the current configuration</td></tr>
1435  *
1436  * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
1437  * EPs and enable EPs for new configuration.</td></tr>
1438  *
1439  * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
1440  * current interface.</td></tr>
1441  *
1442  * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
1443  * message.</td></tr> 
1444  * </table>
1445  *
1446  * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
1447  * processed by pcd_setup. Calling the Function Driver's setup function from
1448  * pcd_setup processes the gadget SETUP commands.
1449  */
1450 static inline void pcd_setup( dwc_otg_pcd_t *_pcd )
1451 {
1452         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
1453         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
1454         struct usb_ctrlrequest  ctrl = _pcd->setup_pkt->req;
1455         dwc_otg_pcd_ep_t        *ep;
1456         dwc_otg_pcd_ep_t        *ep0 = &_pcd->ep0;
1457         uint16_t                                *status = _pcd->status_buf;
1458
1459         deptsiz0_data_t doeptsize0 = { .d32 = 0};
1460
1461 #ifdef DEBUG_EP0
1462         DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
1463                                         ctrl.bRequestType, ctrl.bRequest,
1464                                         ctrl.wValue, ctrl.wIndex, ctrl.wLength);
1465 #endif
1466
1467         doeptsize0.d32 = dwc_read_reg32( &dev_if->out_ep_regs[0]->doeptsiz );
1468
1469         /** @todo handle > 1 setup packet , assert error for now */
1470         if (core_if->dma_enable && (doeptsize0.b.supcnt < 2)) 
1471         {
1472                 DWC_ERROR ("\n\n-----------      CANNOT handle > 1 setup packet in DMA mode\n\n");
1473         }
1474
1475         /* Clean up the request queue */
1476         request_nuke( ep0 );
1477         ep0->stopped = 0;
1478
1479         if (ctrl.bRequestType & USB_DIR_IN) 
1480         {                
1481                 ep0->dwc_ep.is_in = 1;
1482                 _pcd->ep0state = EP0_IN_DATA_PHASE;
1483         } 
1484         else 
1485         {
1486                 ep0->dwc_ep.is_in = 0;
1487                 _pcd->ep0state = EP0_OUT_DATA_PHASE;
1488         }
1489     if (ctrl.wLength == 0) 
1490         {                
1491                 ep0->dwc_ep.is_in = 1;
1492                 _pcd->ep0state = EP0_STATUS;
1493         } 
1494         if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) 
1495         {
1496                 /* handle non-standard (class/vendor) requests in the gadget driver */
1497                 do_gadget_setup(_pcd, &ctrl );
1498                 return;
1499         }
1500
1501         /** @todo NGS: Handle bad setup packet? */
1502
1503         switch (ctrl.bRequest) 
1504         {
1505                 case USB_REQ_GET_STATUS:
1506 #ifdef DEBUG_EP0
1507                 DWC_DEBUGPL(DBG_PCD, 
1508                                                 "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
1509                                                 ctrl.bRequestType, ctrl.bRequest,
1510                                                 ctrl.wValue, ctrl.wIndex, ctrl.wLength);
1511 #endif
1512
1513                 switch (ctrl.bRequestType & USB_RECIP_MASK) 
1514                 {
1515                 case USB_RECIP_DEVICE:
1516                         *status = 0x1; /* Self powered */
1517                         *status |= _pcd->remote_wakeup_enable << 1; 
1518                         break;
1519
1520                 case USB_RECIP_INTERFACE:
1521                         *status = 0;
1522                         break;                                            
1523
1524                 case USB_RECIP_ENDPOINT:
1525                         ep = get_ep_by_addr(_pcd, ctrl.wIndex);
1526                         if ( ep == 0 || ctrl.wLength > 2) 
1527                         {
1528                                 ep0_do_stall(_pcd, -EOPNOTSUPP);
1529                                 return;
1530                         }
1531                         /** @todo check for EP stall */
1532                         *status = ep->stopped;
1533                         break;
1534                 }
1535                 _pcd->ep0_pending = 1;
1536
1537                 ep0->dwc_ep.start_xfer_buff = (uint8_t *)status;
1538                 ep0->dwc_ep.xfer_buff = (uint8_t *)status;
1539                 ep0->dwc_ep.dma_addr = _pcd->status_buf_dma_handle;
1540                 ep0->dwc_ep.xfer_len = 2;
1541                 ep0->dwc_ep.xfer_count = 0;
1542                 ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
1543                 dwc_otg_ep0_start_transfer( GET_CORE_IF(_pcd), &ep0->dwc_ep );
1544                 break;
1545
1546         case USB_REQ_CLEAR_FEATURE:
1547                 do_clear_feature( _pcd );
1548                 break;
1549
1550         case USB_REQ_SET_FEATURE:
1551                 do_set_feature( _pcd );
1552                 break;
1553                                 
1554         case USB_REQ_SET_ADDRESS:
1555                 if (ctrl.bRequestType == USB_RECIP_DEVICE) 
1556                 {
1557                         dcfg_data_t dcfg = {.d32=0};
1558                                                 
1559 #ifdef DEBUG_EP0
1560                         DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
1561 #endif
1562                         dcfg.b.devaddr = ctrl.wValue;
1563                         dwc_modify_reg32( &dev_if->dev_global_regs->dcfg, 
1564                                                                                   0, dcfg.d32);
1565                         do_setup_in_status_phase( _pcd );
1566                         return;
1567                 }
1568                 break;
1569
1570         case USB_REQ_SET_INTERFACE:
1571         case USB_REQ_SET_CONFIGURATION:
1572                         _pcd->request_config = 1;       /* Configuration changed */
1573                         do_gadget_setup(_pcd, &ctrl );
1574                         break;
1575                                 
1576         case USB_REQ_SYNCH_FRAME:
1577                         do_gadget_setup(_pcd, &ctrl );
1578                         break;
1579
1580         default:
1581                         /* Call the Gadget Driver's setup functions */            
1582                         do_gadget_setup(_pcd, &ctrl );
1583                 break;
1584         }
1585 }
1586
1587 /**
1588  * This function completes the ep0 control transfer.
1589  */
1590 static int32_t ep0_complete_request( dwc_otg_pcd_ep_t *_ep )
1591 {
1592         dwc_otg_core_if_t *core_if = GET_CORE_IF(_ep->pcd);
1593         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
1594         dwc_otg_dev_in_ep_regs_t *in_ep_regs = 
1595         dev_if->in_ep_regs[_ep->dwc_ep.num];
1596 #ifdef DEBUG_EP0
1597         dwc_otg_dev_out_ep_regs_t *out_ep_regs = 
1598                         dev_if->out_ep_regs[_ep->dwc_ep.num];
1599 #endif
1600         deptsiz0_data_t deptsiz;
1601         dwc_otg_pcd_request_t *req;
1602         int is_last = 0;
1603         dwc_otg_pcd_t *pcd = _ep->pcd;
1604                 
1605         DWC_DEBUGPL(DBG_PCDV, "%s() %s\n", __func__, _ep->ep.name);
1606
1607         if (pcd->ep0_pending && list_empty(&_ep->queue)) 
1608         {
1609                 if (_ep->dwc_ep.is_in) 
1610                 {
1611 #ifdef DEBUG_EP0
1612                         DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
1613 #endif
1614                         do_setup_out_status_phase(pcd);
1615                 } 
1616                 else 
1617                 {
1618 #ifdef DEBUG_EP0
1619                         DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
1620 #endif
1621                         do_setup_in_status_phase(pcd);
1622                 }
1623                 pcd->ep0_pending = 0;
1624                 pcd->ep0state = EP0_STATUS;
1625                 return 1;
1626         }
1627         
1628         if (list_empty(&_ep->queue)) 
1629         {
1630                 return 0;
1631         }
1632         req = list_entry(_ep->queue.next, dwc_otg_pcd_request_t, queue);
1633
1634
1635         if (pcd->ep0state == EP0_STATUS) 
1636         {
1637                 is_last = 1;                                            
1638         } 
1639 /*
1640         else if (req->req.zero) 
1641         {
1642                 DWC_PRINT("%s--------------------------------------------------\n",__func__);
1643                 req->req.actual = _ep->dwc_ep.xfer_count;
1644                 //do_setup_in_status_phase (pcd);
1645                 req->req.zero = 0;
1646                 _ep->dwc_ep.xfer_len = 0;
1647                 _ep->dwc_ep.xfer_count = 0;
1648                 _ep->dwc_ep.sent_zlp = 1;
1649                 dwc_otg_ep0_start_transfer( GET_CORE_IF(pcd), &_ep->dwc_ep );
1650                 return 1;
1651         }
1652 */
1653         else if (_ep->dwc_ep.is_in) 
1654         {
1655                 deptsiz.d32 = dwc_read_reg32( &in_ep_regs->dieptsiz);
1656 #ifdef DEBUG_EP0
1657                 DWC_DEBUGPL(DBG_PCDV, "%s len=%d  xfersize=%d pktcnt=%d\n", 
1658                                                 _ep->ep.name, _ep->dwc_ep.xfer_len,
1659                                                 deptsiz.b.xfersize, deptsiz.b.pktcnt);
1660 #endif                            
1661                 if (deptsiz.b.xfersize == 0) 
1662                 {
1663                         req->req.actual = _ep->dwc_ep.xfer_count;
1664                         /* Is a Zero Len Packet needed? */
1665                         //if (req->req.zero) {
1666 #ifdef DEBUG_EP0
1667                         DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
1668 #endif
1669                         do_setup_out_status_phase(pcd);
1670                 }
1671         } 
1672         else 
1673         {
1674                 /* ep0-OUT */
1675 #ifdef DEBUG_EP0
1676                 deptsiz.d32 = dwc_read_reg32( &out_ep_regs->doeptsiz);
1677                 DWC_DEBUGPL(DBG_PCDV, "%s len=%d xsize=%d pktcnt=%d\n",
1678                                                 _ep->ep.name, _ep->dwc_ep.xfer_len,
1679                                                 deptsiz.b.xfersize, 
1680                                                 deptsiz.b.pktcnt);
1681 #endif
1682                 req->req.actual = _ep->dwc_ep.xfer_count;
1683                 
1684                 /* Is a Zero Len Packet needed? */
1685                 //if (req->req.zero) {
1686 #ifdef DEBUG_EP0
1687                 DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
1688 #endif
1689                 do_setup_in_status_phase(pcd);
1690         }
1691                 
1692         /* Complete the request */
1693         if (is_last) 
1694         {
1695                 request_done(_ep, req, 0);
1696                 _ep->dwc_ep.start_xfer_buff = 0;
1697                 _ep->dwc_ep.xfer_buff = 0;
1698                 _ep->dwc_ep.xfer_len = 0;
1699                 return 1;
1700         }
1701         return 0;               
1702 }
1703
1704 /**
1705  * This function completes the request for the EP.      If there are
1706  * additional requests for the EP in the queue they will be started.
1707  */
1708 static void complete_ep( dwc_otg_pcd_ep_t *_ep )
1709 {
1710         dwc_otg_core_if_t *core_if = GET_CORE_IF(_ep->pcd);
1711         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
1712         dwc_otg_dev_in_ep_regs_t *in_ep_regs = 
1713         dev_if->in_ep_regs[_ep->dwc_ep.num];
1714         deptsiz_data_t deptsiz;
1715         dwc_otg_pcd_request_t *req = 0;
1716         int is_last = 0;
1717         
1718         DWC_DEBUGPL(DBG_PCDV,"%s() %s-%s\n", __func__, _ep->ep.name,
1719                                         (_ep->dwc_ep.is_in?"IN":"OUT"));
1720
1721         /* Get any pending requests */
1722         if (!list_empty(&_ep->queue)) 
1723         {
1724                 req = list_entry(_ep->queue.next, dwc_otg_pcd_request_t, 
1725                                                                  queue);
1726         }
1727         DWC_DEBUGPL(DBG_PCD, "Requests %d\n",_ep->pcd->request_pending);
1728
1729         if (_ep->dwc_ep.is_in) 
1730         {
1731                 deptsiz.d32 = dwc_read_reg32( &in_ep_regs->dieptsiz);
1732
1733                 if (core_if->dma_enable) 
1734                 {
1735                         if (deptsiz.b.xfersize == 0) 
1736                                 _ep->dwc_ep.xfer_count = _ep->dwc_ep.xfer_len;
1737                 }
1738
1739                 DWC_DEBUGPL(DBG_PCDV, "%s len=%d  xfersize=%d pktcnt=%d\n", 
1740                                                 _ep->ep.name, _ep->dwc_ep.xfer_len,
1741                                                 deptsiz.b.xfersize, deptsiz.b.pktcnt);
1742
1743                 if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0 &&
1744                                 _ep->dwc_ep.xfer_count == _ep->dwc_ep.xfer_len) 
1745                 {
1746                         is_last = 1;
1747                 } 
1748                 else 
1749                 {
1750                         DWC_WARN("Incomplete transfer (%s-%s [siz=%d pkt=%d])\n", 
1751                                          _ep->ep.name, (_ep->dwc_ep.is_in?"IN":"OUT"),
1752                                          deptsiz.b.xfersize, deptsiz.b.pktcnt);
1753                 }
1754         } 
1755         else 
1756         {
1757                 dwc_otg_dev_out_ep_regs_t *out_ep_regs = 
1758                                         dev_if->out_ep_regs[_ep->dwc_ep.num];
1759                 deptsiz.d32 = 0;
1760                 deptsiz.d32 = dwc_read_reg32( &out_ep_regs->doeptsiz);
1761
1762 #ifdef DEBUG
1763                         
1764                 DWC_DEBUGPL(DBG_PCDV, "addr %p,  %s len=%d cnt=%d xsize=%d pktcnt=%d\n",
1765                                                 &out_ep_regs->doeptsiz, _ep->ep.name, _ep->dwc_ep.xfer_len,
1766                                                 _ep->dwc_ep.xfer_count,
1767                                                 deptsiz.b.xfersize, 
1768                                                 deptsiz.b.pktcnt);
1769 #endif
1770                 is_last = 1;
1771         }
1772                 
1773         /* Complete the request */
1774         if (is_last) 
1775         {
1776
1777         /* HSL @RK,20090807 */
1778         if( req ) {
1779                         if (core_if->dma_enable) 
1780                         {
1781                                 req->req.actual = _ep->dwc_ep.xfer_len - deptsiz.b.xfersize;
1782                         }
1783                         else 
1784                         {
1785                                 req->req.actual = _ep->dwc_ep.xfer_count;
1786                         }
1787                         request_done(_ep, req, 0);
1788         } else {
1789             DWC_PRINT("\n++++++FIND NULL req,ep=%s++++++++++\n" , _ep->ep.name );
1790             _ep->pcd->request_pending = 0;
1791         }
1792                 _ep->dwc_ep.start_xfer_buff = 0;
1793                 _ep->dwc_ep.xfer_buff = 0;
1794                 _ep->dwc_ep.xfer_len = 0;
1795
1796                 /* If there is a request in the queue start it.*/
1797                 start_next_request( _ep );
1798         }
1799 }
1800
1801 /**
1802  * This function handles EP0 Control transfers.  
1803  *
1804  * The state of the control tranfers are tracked in
1805  * <code>ep0state</code>.
1806  */
1807 static void handle_ep0( dwc_otg_pcd_t *_pcd )
1808 {
1809         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
1810         dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0;
1811         deptsiz_data_t deptsiz;
1812
1813 #ifdef DEBUG_EP0
1814         DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
1815         print_ep0_state(_pcd);
1816 #endif
1817
1818         switch (_pcd->ep0state)
1819         {
1820         case EP0_DISCONNECT:
1821                 break;
1822                                 
1823         case EP0_IDLE:
1824                 _pcd->request_config = 0;
1825                                 
1826                 pcd_setup( _pcd );
1827                 break;
1828
1829         case EP0_IN_DATA_PHASE:
1830 #ifdef DEBUG_EP0
1831                 DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n", 
1832                                                 ep0->dwc_ep.num, (ep0->dwc_ep.is_in ?"IN":"OUT"),
1833                                                 ep0->dwc_ep.type, ep0->dwc_ep.maxpacket );
1834 #endif                            
1835                 if (core_if->dma_enable) 
1836                 {
1837                         /* 
1838                          * For EP0 we can only program 1 packet at a time so we
1839                          * need to do the make calculations after each complete.
1840                          * Call write_packet to make the calculations, as in
1841                          * slave mode, and use those values to determine if we
1842                          * can complete.
1843                          */
1844                         dwc_otg_ep_write_packet (core_if, &ep0->dwc_ep, 1);
1845                 }
1846                 if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) 
1847                 {
1848                         dwc_otg_ep0_continue_transfer ( GET_CORE_IF(_pcd), &ep0->dwc_ep );
1849                         DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); 
1850                 }else if (ep0->dwc_ep.sent_zlp) {
1851                         dwc_otg_ep0_continue_transfer(GET_CORE_IF(_pcd), &ep0->dwc_ep);
1852                         ep0->dwc_ep.sent_zlp = 0;
1853                         DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
1854                 }
1855                 else 
1856                 {               
1857                         ep0_complete_request( ep0 );
1858                         DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); 
1859                 }
1860                 break;
1861         case EP0_OUT_DATA_PHASE:
1862 #ifdef DEBUG_EP0
1863                 DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n", 
1864                                                 ep0->dwc_ep.num, (ep0->dwc_ep.is_in ?"IN":"OUT"),
1865                                                 ep0->dwc_ep.type, ep0->dwc_ep.maxpacket );
1866 #endif
1867         deptsiz.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[0]->dieptsiz);
1868         ep0->dwc_ep.xfer_count = ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
1869                 ep0_complete_request( ep0 );
1870                 break;
1871                                 
1872
1873         case EP0_STATUS:
1874                 DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n"); 
1875                                                 ep0_complete_request( ep0 );
1876                                                 _pcd->ep0state = EP0_IDLE;
1877                                                 ep0->stopped = 1;
1878                                                 ep0->dwc_ep.is_in = 0;  /* OUT for next SETUP */
1879
1880                 /* Prepare for more SETUP Packets */
1881                 if (core_if->dma_enable) 
1882                 {
1883                         ep0_out_start( core_if, _pcd );
1884                 }
1885
1886                 if (!GET_CORE_IF(_pcd)->dma_enable) 
1887                 {       
1888                         int i;
1889
1890                         depctl_data_t diepctl;
1891                         diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[0]->diepctl);
1892                         
1893                         if (_pcd->ep0.queue_sof) 
1894                         {
1895                                 _pcd->ep0.queue_sof = 0;
1896                                 start_next_request (&_pcd->ep0);
1897                         }
1898                         
1899                         diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[0]->diepctl);
1900                         
1901                         if (_pcd->ep0.queue_sof) 
1902                         {
1903                                 _pcd->ep0.queue_sof = 0;
1904                                 start_next_request (&_pcd->ep0);
1905                         }
1906                         for (i=0; i < core_if->dev_if->num_in_eps; i++) 
1907                         {
1908                                 diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[i+1]->diepctl);
1909                                 
1910                                 if (_pcd->in_ep[i].queue_sof) 
1911                                 {
1912                                         _pcd->in_ep[i].queue_sof = 0;
1913                                         start_next_request (&_pcd->in_ep[i]);
1914                                 }
1915                         }
1916                 }
1917                 break;
1918
1919         case EP0_STALL:
1920                 DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
1921                 break;
1922         }
1923 #ifdef DEBUG_EP0
1924         print_ep0_state(_pcd);
1925 #endif
1926 }
1927
1928 /**
1929  * Restart transfer
1930  */
1931 static void restart_transfer( dwc_otg_pcd_t *_pcd, const uint32_t _epnum)
1932 {
1933         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
1934         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
1935         deptsiz_data_t dieptsiz = {.d32=0};
1936         //depctl_data_t diepctl = {.d32=0};
1937         dwc_otg_pcd_ep_t *ep;
1938
1939         dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[_epnum]->dieptsiz);
1940
1941         ep = get_in_ep(_pcd, _epnum);
1942 /*
1943         if(_epnum != 0)
1944                 ep = &_pcd->in_ep[ _epnum - 1];    
1945         else
1946                 ep = &_pcd->ep0;
1947 */        
1948         DWC_DEBUGPL(DBG_PCD,"xfer_buff=%p xfer_count=%0x xfer_len=%0x" 
1949                                 " stopped=%d\n", ep->dwc_ep.xfer_buff,
1950                                 ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len ,
1951                                 ep->stopped);
1952         /*
1953          * If xfersize is 0 and pktcnt in not 0, resend the last packet.
1954          */
1955         if ( dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
1956                  ep->dwc_ep.start_xfer_buff != 0) 
1957         {
1958                 if ( ep->dwc_ep.xfer_len <= ep->dwc_ep.maxpacket ) 
1959                 {
1960                         ep->dwc_ep.xfer_count = 0;
1961                         ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
1962                 } 
1963                 else 
1964                 {
1965                         ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
1966                         /* convert packet size to dwords. */
1967                         ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
1968                 }
1969                 ep->stopped = 0;
1970                 DWC_DEBUGPL(DBG_PCD,"xfer_buff=%p xfer_count=%0x "
1971                                                 "xfer_len=%0x stopped=%d\n", 
1972                                                 ep->dwc_ep.xfer_buff,
1973                                                 ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len ,
1974                                                 ep->stopped
1975                                                 );
1976                 if (_epnum == 0) 
1977                 {
1978                         dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
1979                 } 
1980                 else 
1981                 {
1982                         dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
1983                 }
1984         }
1985 }
1986
1987
1988 /**
1989  * handle the IN EP disable interrupt.
1990  */
1991 static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t *_pcd, 
1992                                                                                          const uint32_t _epnum)
1993 {
1994         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
1995         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
1996         deptsiz_data_t dieptsiz = {.d32=0};
1997         dctl_data_t dctl = {.d32=0};
1998         dwc_otg_pcd_ep_t *ep;
1999         dwc_ep_t *dwc_ep;
2000
2001         ep = get_in_ep(_pcd, _epnum);
2002         dwc_ep = &ep->dwc_ep;
2003 /*
2004         if(_epnum != 0)
2005         {       
2006                 ep = &_pcd->in_ep[ _epnum - 1];
2007                 dwc_ep = &_pcd->in_ep[ _epnum - 1].dwc_ep;
2008         }
2009         else
2010         {
2011                 ep = &_pcd->ep0;
2012                 dwc_ep = &_pcd->ep0.dwc_ep;
2013         }
2014 */
2015         DWC_DEBUGPL(DBG_PCD,"diepctl%d=%0x\n", _epnum,
2016         dwc_read_reg32(&dev_if->in_ep_regs[_epnum]->diepctl));
2017         dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[_epnum]->dieptsiz);
2018
2019         DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
2020                                 dieptsiz.b.pktcnt, 
2021                                 dieptsiz.b.xfersize );
2022
2023         if (ep->stopped) 
2024         {
2025                 /* Flush the Tx FIFO */
2026                 /** @todo NGS: This is not the correct FIFO */
2027                          /* 20091009,HSL@RK,our dwc fifo work at dedicated mode, use 0x10 to flush all , not 0 */
2028                 dwc_otg_flush_tx_fifo( core_if, 0x10 );
2029                 
2030                 /* Clear the Global IN NP NAK */
2031                 dctl.d32 = 0;
2032                 dctl.b.cgnpinnak = 1;
2033                 dwc_modify_reg32(&dev_if->dev_global_regs->dctl, 
2034                                                  dctl.d32, 0);
2035                 /* Restart the transaction */
2036                 if (dieptsiz.b.pktcnt != 0 || 
2037                         dieptsiz.b.xfersize != 0) 
2038                 {
2039                         restart_transfer( _pcd, _epnum );
2040                 }
2041         } 
2042         else 
2043         {
2044                 /* Restart the transaction */
2045                 if (dieptsiz.b.pktcnt != 0 || 
2046                         dieptsiz.b.xfersize != 0) 
2047                 {
2048                         restart_transfer( _pcd, _epnum );
2049                 }
2050                 DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
2051         }                                                                
2052 }
2053
2054 /**
2055  * Handler for the IN EP timeout handshake interrupt. 
2056  */
2057 static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t *_pcd, 
2058                                                                                          const uint32_t _epnum)
2059 {
2060         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
2061         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
2062
2063 #ifdef DEBUG
2064         deptsiz_data_t dieptsiz = {.d32=0};
2065         uint32_t epnum = 0;
2066 #endif
2067         dctl_data_t dctl = {.d32=0};
2068         dwc_otg_pcd_ep_t *ep;
2069
2070         gintmsk_data_t intr_mask = {.d32 = 0};
2071
2072         ep = get_in_ep(_pcd, _epnum);
2073 /*
2074         if(_epnum != 0)
2075                 ep = &_pcd->in_ep[ _epnum - 1];
2076         else
2077                 ep = &_pcd->ep0;
2078 */              
2079
2080         /* Disable the NP Tx Fifo Empty Interrrupt */
2081         if (!core_if->dma_enable) 
2082         {
2083                 intr_mask.b.nptxfempty = 1;
2084                 dwc_modify_reg32( &core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
2085         }
2086         /** @todo NGS Check EP type.
2087          * Implement for Periodic EPs */
2088         /* 
2089          * Non-periodic EP 
2090          */
2091         /* Enable the Global IN NAK Effective Interrupt */
2092         intr_mask.d32 = 0;                      /* Bug fixed - clear mask b4 reusing */
2093         intr_mask.b.ginnakeff = 1;
2094         dwc_modify_reg32( &core_if->core_global_regs->gintmsk, 
2095                                           0, intr_mask.d32);
2096
2097         /* Set Global IN NAK */
2098         dctl.b.sgnpinnak = 1;
2099         dwc_modify_reg32(&dev_if->dev_global_regs->dctl,
2100                                          dctl.d32, dctl.d32);
2101
2102         ep->stopped = 1;
2103
2104 #ifdef DEBUG
2105         dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz);
2106         DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
2107                                 dieptsiz.b.pktcnt, 
2108                                 dieptsiz.b.xfersize );
2109 #endif
2110
2111 #ifdef DISABLE_PERIODIC_EP
2112         /*
2113          * Set the NAK bit for this EP to
2114          * start the disable process.
2115          */
2116         diepctl.d32 = 0;
2117         diepctl.b.snak = 1;
2118         dwc_modify_reg32(&dev_if->in_ep_regs[epnum]->diepctl, diepctl.d32, diepctl.d32);
2119         ep->disabling = 1;
2120         ep->stopped = 1;
2121 #endif
2122 }
2123
2124 /**
2125  * This interrupt indicates that an IN EP has a pending Interrupt.
2126  * The sequence for handling the IN EP interrupt is shown below:
2127  * -#   Read the Device All Endpoint Interrupt register
2128  * -#   Repeat the following for each IN EP interrupt bit set (from
2129  *              LSB to MSB).
2130  * -#   Read the Device Endpoint Interrupt (DIEPINTn) register
2131  * -#   If "Transfer Complete" call the request complete function
2132  * -#   If "Endpoint Disabled" complete the EP disable procedure.
2133  * -#   If "AHB Error Interrupt" log error
2134  * -#   If "Time-out Handshake" log error
2135  * -#   If "IN Token Received when TxFIFO Empty" write packet to Tx
2136  *              FIFO.
2137  * -#   If "IN Token EP Mismatch" (disable, this is handled by EP
2138  *              Mismatch Interrupt)
2139  */
2140 static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t *_pcd)
2141 {
2142 #define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
2143 do { \
2144                 diepint_data_t diepint = {.d32=0}; \
2145                 diepint.b.__intr = 1; \
2146                 dwc_write_reg32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
2147                 diepint.d32); \
2148 } while (0)
2149
2150         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
2151         dwc_otg_dev_if_t *dev_if = core_if->dev_if;
2152         diepint_data_t diepint = {.d32=0};
2153         depctl_data_t diepctl = {.d32=0};
2154         uint32_t ep_intr;
2155         uint32_t epnum = 0;
2156         dwc_otg_pcd_ep_t *ep;
2157         dwc_ep_t *dwc_ep;
2158         uint32_t _empty_msk, _diepctl;
2159         gintmsk_data_t intr_mask = {.d32 = 0};
2160
2161         
2162         
2163         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
2164
2165         /* Read in the device interrupt bits */
2166         ep_intr = dwc_otg_read_dev_all_in_ep_intr( core_if );
2167
2168         /* Service the Device IN interrupts for each endpoint */
2169         while( ep_intr ) 
2170         {
2171                 if (ep_intr&0x1) 
2172                 {
2173
2174                         
2175                         /* Get EP pointer */       
2176                         ep = get_in_ep(_pcd, epnum);
2177                         if(ep == NULL){
2178                 DWC_PRINT("%s epnum %d epintr %x\n", __func__, epnum, ep_intr);
2179                 break;
2180                         }
2181                         dwc_ep = &ep->dwc_ep;
2182
2183                         _diepctl = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl);
2184                         _empty_msk = dwc_read_reg32(&dev_if->dev_global_regs->dtknqr4_fifoemptymsk);
2185
2186                         DWC_DEBUGPL(DBG_PCDV, "IN EP INTERRUPT - %d\nepmty_msk - %8x  diepctl - %8x\n",epnum, _empty_msk, _diepctl);
2187
2188                         DWC_DEBUGPL(DBG_PCD, 
2189                                                 "EP%d-%s: type=%d, mps=%d\n", 
2190                                                 dwc_ep->num, (dwc_ep->is_in ?"IN":"OUT"),
2191                                                 dwc_ep->type, dwc_ep->maxpacket );
2192
2193                         diepint.d32 = dwc_otg_read_dev_in_ep_intr( core_if, dwc_ep );
2194                                                                                    
2195                         DWC_DEBUGPL(DBG_PCDV, "EP %d Interrupt Register - 0x%x\n", epnum, diepint.d32);
2196                         /* Transfer complete */
2197                         if ( diepint.b.xfercompl ) 
2198                         {
2199
2200                                 DWC_DEBUGPL(DBG_PCD,"EP%d IN Xfer Complete\n", epnum);
2201                                 
2202                                 /* Disable the NP Tx FIFO Empty
2203                                  * Interrrupt */
2204                                 if(core_if->en_multiple_tx_fifo == 0)
2205                                 {
2206                                         intr_mask.b.nptxfempty = 1;
2207                                         dwc_modify_reg32( &core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
2208                                 }
2209                                 else
2210                                 {                                               
2211                                         /* Disable the Tx FIFO Empty Interrupt for this EP */
2212                                         uint32_t fifoemptymsk = 0x1 << dwc_ep->num;
2213                                         dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
2214                                         fifoemptymsk, 0);
2215                                 }
2216                                 /* Clear the bit in DIEPINTn for this interrupt */
2217                                 CLEAR_IN_EP_INTR(core_if,epnum,xfercompl);
2218
2219                                 /* Complete the transfer */
2220                                 if (epnum == 0) 
2221                                 {
2222                                         handle_ep0( _pcd );
2223                                 }
2224                                 else 
2225                                 {
2226                                         complete_ep( ep );
2227                                 }
2228                         }
2229                         /* Endpoint disable      */
2230                         if ( diepint.b.epdisabled ) 
2231                         {
2232                                 DWC_DEBUGPL(DBG_ANY,"EP%d IN disabled\n", epnum);
2233                                 handle_in_ep_disable_intr( _pcd, epnum );
2234
2235                                 /* Clear the bit in DIEPINTn for this interrupt */
2236                                 CLEAR_IN_EP_INTR(core_if,epnum,epdisabled);
2237                         }
2238                         /* AHB Error */
2239                         if ( diepint.b.ahberr ) 
2240                         {
2241                                 DWC_DEBUGPL(DBG_ANY,"EP%d IN AHB Error\n", epnum);
2242                                 /* Clear the bit in DIEPINTn for this interrupt */
2243                                 CLEAR_IN_EP_INTR(core_if,epnum,ahberr);
2244                         }
2245                         /* TimeOUT Handshake (non-ISOC IN EPs) */
2246                         if ( diepint.b.timeout ) 
2247                         { 
2248                                 DWC_DEBUGPL(DBG_ANY,"EP%d IN Time-out\n", epnum);
2249                                 handle_in_ep_timeout_intr( _pcd, epnum );
2250
2251                                 CLEAR_IN_EP_INTR(core_if,epnum,timeout);
2252                         }
2253                         /** IN Token received with TxF Empty */
2254                         if (diepint.b.intktxfemp)
2255                         {
2256                                 DWC_DEBUGPL(DBG_ANY,"EP%d IN TKN TxFifo Empty\n",
2257                                                                 epnum);
2258                                 if (!ep->stopped && epnum != 0) 
2259                                 {
2260                                         diepmsk_data_t diepmsk = { .d32 = 0};
2261                                         diepmsk.b.intktxfemp = 1;
2262                                         dwc_modify_reg32( &dev_if->dev_global_regs->diepmsk, diepmsk.d32, 0 );           
2263                                         start_next_request(ep);
2264                                 }
2265                                 CLEAR_IN_EP_INTR(core_if,epnum,intktxfemp);
2266                         }                                       
2267                         /** IN Token Received with EP mismatch */
2268                         if (diepint.b.intknepmis)
2269                         {
2270                                 DWC_DEBUGPL(DBG_ANY,"EP%d IN TKN EP Mismatch\n", epnum);
2271                                 CLEAR_IN_EP_INTR(core_if,epnum,intknepmis);
2272                         }
2273                         /** IN Endpoint NAK Effective */
2274                         if (diepint.b.inepnakeff)
2275                         {
2276                                 DWC_DEBUGPL(DBG_ANY,"EP%d IN EP NAK Effective\n", epnum);
2277                                 /* Periodic EP */
2278                                 if (ep->disabling) 
2279                                 {
2280                                         diepctl.d32 = 0;
2281                                         diepctl.b.snak = 1;
2282                                         diepctl.b.epdis = 1;
2283                                         dwc_modify_reg32(&dev_if->in_ep_regs[epnum]->diepctl, diepctl.d32, diepctl.d32);
2284                                 }
2285                                 CLEAR_IN_EP_INTR(core_if,epnum,inepnakeff);
2286
2287                         }
2288                                         
2289                         /** IN EP Tx FIFO Empty Intr */
2290                         if (diepint.b.emptyintr)
2291                         {
2292                                 DWC_DEBUGPL(DBG_ANY,"EP%d Tx FIFO Empty Intr \n", epnum);
2293                                 write_empty_tx_fifo(_pcd, epnum);                                                                               
2294
2295                                 CLEAR_IN_EP_INTR(core_if,epnum,emptyintr);
2296                                                 
2297                         }
2298                 }
2299                 epnum++;
2300                 ep_intr >>=1;
2301         }
2302
2303         return 1;
2304 #undef CLEAR_IN_EP_INTR
2305 }
2306
2307 /**
2308  * This interrupt indicates that an OUT EP has a pending Interrupt.
2309  * The sequence for handling the OUT EP interrupt is shown below:
2310  * -#   Read the Device All Endpoint Interrupt register
2311  * -#   Repeat the following for each OUT EP interrupt bit set (from
2312  *              LSB to MSB).
2313  * -#   Read the Device Endpoint Interrupt (DOEPINTn) register
2314  * -#   If "Transfer Complete" call the request complete function
2315  * -#   If "Endpoint Disabled" complete the EP disable procedure.
2316  * -#   If "AHB Error Interrupt" log error
2317  * -#   If "Setup Phase Done" process Setup Packet (See Standard USB
2318  *              Command Processing)
2319  */
2320 static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t *_pcd)
2321 {
2322 #define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
2323 do { \
2324                 doepint_data_t doepint = {.d32=0}; \
2325                 doepint.b.__intr = 1; \
2326                 dwc_write_reg32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
2327                 doepint.d32); \
2328 } while (0)
2329
2330         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
2331         uint32_t ep_intr;
2332         doepint_data_t doepint = {.d32=0};
2333         uint32_t epnum = 0;
2334         dwc_ep_t *dwc_ep;
2335         
2336         DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
2337
2338         /* Read in the device interrupt bits */
2339         ep_intr = dwc_otg_read_dev_all_out_ep_intr( core_if );
2340 //      dwc_otg_dump_dev_registers(core_if);
2341
2342         while( ep_intr ) 
2343         {
2344                 if (ep_intr&0x1) 
2345                 {
2346                         /* Get EP pointer */       
2347                         dwc_ep = &((get_out_ep(_pcd, epnum))->dwc_ep);
2348 //                        dwc_ep = &_pcd->out_ep[ epnum - 1].dwc_ep;
2349 //#ifdef VERBOSE
2350 #if 1
2351                         DWC_DEBUGPL(DBG_PCDV, 
2352                                                         "EP%d-%s: type=%d, mps=%d\n", 
2353                                                         dwc_ep->num, (dwc_ep->is_in ?"IN":"OUT"),
2354                                                         dwc_ep->type, dwc_ep->maxpacket );
2355 #endif
2356                         doepint.d32 = dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
2357                                 
2358                         /* Transfer complete */
2359                         if ( doepint.b.xfercompl ) 
2360                         {
2361                                 DWC_DEBUGPL(DBG_PCD,"EP%d OUT Xfer Complete\n",
2362                                                                 epnum);
2363
2364                                 /* Clear the bit in DOEPINTn for this interrupt */
2365                                 CLEAR_OUT_EP_INTR(core_if,epnum,xfercompl);
2366
2367                                 if (epnum == 0) 
2368                                 {
2369                                         handle_ep0( _pcd );
2370                                 } 
2371                                 else 
2372                                 {
2373                                         complete_ep( get_out_ep(_pcd, epnum) );
2374 //                                              complete_ep( &_pcd->out_ep[ epnum - 1] );
2375                                 }
2376                         }
2377                         /* Endpoint disable      */
2378                         if ( doepint.b.epdisabled ) 
2379                         {
2380                                 DWC_DEBUGPL(DBG_PCD,"EP%d OUT disabled\n", epnum);
2381                                 /* Clear the bit in DOEPINTn for this interrupt */
2382                                 CLEAR_OUT_EP_INTR(core_if,epnum,epdisabled);
2383                         }
2384                         /* AHB Error */
2385                         if ( doepint.b.ahberr ) 
2386                         {
2387                                 DWC_DEBUGPL(DBG_PCD,"EP%d OUT AHB Error\n", epnum);
2388                                 DWC_DEBUGPL(DBG_PCD,"EP DMA REG  %d \n", core_if->dev_if->out_ep_regs[epnum]->doepdma);                                                                                                 
2389                                 CLEAR_OUT_EP_INTR(core_if,epnum,ahberr);
2390                         }
2391                         /* Setup Phase Done (contorl EPs) */
2392                         if ( doepint.b.setup ) 
2393                         {
2394 #ifdef DEBUG_EP0
2395                                 DWC_DEBUGPL(DBG_PCD,"EP%d SETUP Done\n", 
2396                                                         epnum);
2397 #endif
2398                                 handle_ep0( _pcd );
2399                                 CLEAR_OUT_EP_INTR(core_if,epnum,setup);
2400                         }
2401                 }
2402                 epnum++;
2403                 ep_intr >>=1;
2404         }
2405
2406         return 1;
2407
2408 #undef CLEAR_OUT_EP_INTR
2409 }
2410
2411 /**
2412  * Incomplete ISO IN Transfer Interrupt.
2413  * This interrupt indicates one of the following conditions occurred
2414  * while transmitting an ISOC transaction.
2415  * - Corrupted IN Token for ISOC EP.
2416  * - Packet not complete in FIFO.
2417  * The follow actions will be taken:
2418  *      -#      Determine the EP
2419  *      -#      Set incomplete flag in dwc_ep structure
2420  *      -#      Disable EP; when "Endpoint Disabled" interrupt is received
2421  *              Flush FIFO
2422  */
2423 int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t *_pcd)
2424 {
2425         gintmsk_data_t intr_mask = { .d32 = 0};
2426         gintsts_data_t gintsts;
2427         DWC_PRINT("INTERRUPT Handler not implemented for %s\n",
2428                           "IN ISOC Incomplete");
2429
2430         intr_mask.b.incomplisoin = 1;
2431         dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, 
2432                                           intr_mask.d32, 0 );
2433
2434         /* Clear interrupt */
2435         gintsts.d32 = 0;
2436         gintsts.b.incomplisoin = 1;
2437         dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, 
2438                                                  gintsts.d32);
2439
2440         return 1;
2441 }
2442
2443 /**
2444  * Incomplete ISO OUT Transfer Interrupt.  
2445  *
2446  * This interrupt indicates that the core has dropped an ISO OUT
2447  * packet.      The following conditions can be the cause:
2448  * - FIFO Full, the entire packet would not fit in the FIFO.
2449  * - CRC Error
2450  * - Corrupted Token
2451  * The follow actions will be taken:
2452  *      -#      Determine the EP
2453  *      -#      Set incomplete flag in dwc_ep structure
2454  *      -#      Read any data from the FIFO
2455  *      -#      Disable EP.      when "Endpoint Disabled" interrupt is received
2456  *              re-enable EP.
2457  */
2458 int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t *_pcd)
2459 {
2460         /** @todo implement ISR */
2461         gintmsk_data_t intr_mask = { .d32 = 0};
2462         gintsts_data_t gintsts;
2463         DWC_PRINT("INTERRUPT Handler not implemented for %s\n",
2464                           "OUT ISOC Incomplete");
2465
2466         intr_mask.b.incomplisoout = 1;
2467         dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, 
2468                                           intr_mask.d32, 0 );
2469
2470         /* Clear interrupt */
2471         gintsts.d32 = 0;
2472         gintsts.b.incomplisoout = 1;
2473         dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, 
2474                                                  gintsts.d32);
2475
2476         return 1;
2477 }
2478
2479 /**
2480  * This function handles the Global IN NAK Effective interrupt.
2481  *      
2482  */
2483 int32_t dwc_otg_pcd_handle_in_nak_effective( dwc_otg_pcd_t *_pcd )
2484 {
2485         dwc_otg_dev_if_t *dev_if = GET_CORE_IF(_pcd)->dev_if;
2486         depctl_data_t diepctl = { .d32 = 0};
2487         depctl_data_t diepctl_rd = { .d32 = 0};
2488         gintmsk_data_t intr_mask = { .d32 = 0};
2489         gintsts_data_t gintsts;
2490         int i;
2491
2492         DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
2493         
2494         /* Disable all active IN EPs */
2495         diepctl.b.epdis = 1;
2496         diepctl.b.snak = 1;
2497         
2498         for (i=0; i <= dev_if->num_in_eps; i++) 
2499         {
2500                 diepctl_rd.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl);
2501                 if (diepctl_rd.b.epena) 
2502                 {
2503                         dwc_write_reg32( &dev_if->in_ep_regs[i]->diepctl, 
2504                                                                 diepctl.d32 );  
2505                 }
2506         }
2507         /* Disable the Global IN NAK Effective Interrupt */
2508         intr_mask.b.ginnakeff = 1;
2509         dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, 
2510                                           intr_mask.d32, 0);
2511
2512         /* Clear interrupt */
2513         gintsts.d32 = 0;
2514         gintsts.b.ginnakeff = 1;
2515         dwc_write_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintsts, 
2516                                                  gintsts.d32);
2517
2518         return 1;
2519 }
2520
2521 /**
2522  * OUT NAK Effective.
2523  *
2524  */
2525 int32_t dwc_otg_pcd_handle_out_nak_effective( dwc_otg_pcd_t *_pcd )
2526 {
2527         gintmsk_data_t intr_mask = { .d32 = 0};
2528         gintsts_data_t gintsts;
2529
2530         DWC_PRINT("INTERRUPT Handler not implemented for %s\n", 
2531                           "Global IN NAK Effective\n");
2532         /* Disable the Global IN NAK Effective Interrupt */
2533         intr_mask.b.goutnakeff = 1;
2534         dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk, 
2535                                           intr_mask.d32, 0);
2536
2537         /* Clear interrupt */
2538         gintsts.d32 = 0;
2539         gintsts.b.goutnakeff = 1;
2540         dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts, 
2541                                                  gintsts.d32);
2542
2543         return 1;
2544 }
2545
2546
2547 /**
2548  * PCD interrupt handler.
2549  *
2550  * The PCD handles the device interrupts.  Many conditions can cause a
2551  * device interrupt. When an interrupt occurs, the device interrupt
2552  * service routine determines the cause of the interrupt and
2553  * dispatches handling to the appropriate function. These interrupt
2554  * handling functions are described below.
2555  *
2556  * All interrupt registers are processed from LSB to MSB.
2557  * 
2558  */
2559 int32_t dwc_otg_pcd_handle_intr( dwc_otg_pcd_t *_pcd )
2560 {
2561         dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
2562 #ifdef VERBOSE
2563         dwc_otg_core_global_regs_t *global_regs = 
2564                         core_if->core_global_regs;
2565 #endif
2566         gintsts_data_t gintr_status;
2567         int32_t retval = 0;
2568
2569 #ifdef VERBOSE
2570         DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x  gintmsk=%08x\n", 
2571                                 __func__,
2572                                 dwc_read_reg32( &global_regs->gintsts),
2573                                 dwc_read_reg32( &global_regs->gintmsk));
2574 #endif
2575
2576         if (dwc_otg_is_device_mode(core_if)) 
2577         {
2578                 SPIN_LOCK(&_pcd->lock);
2579 #ifdef VERBOSE
2580                 DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x  gintmsk=%08x\n", 
2581                                                 __func__,
2582                                                 dwc_read_reg32( &global_regs->gintsts),
2583                                                 dwc_read_reg32( &global_regs->gintmsk));                                
2584 #endif
2585                                 
2586                 gintr_status.d32 = dwc_otg_read_core_intr(core_if);
2587                 if (!gintr_status.d32) 
2588                 {
2589                         SPIN_UNLOCK(&_pcd->lock);
2590                         return 0;
2591                 }
2592                 DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
2593                                         __func__, gintr_status.d32 );
2594         
2595                 if (gintr_status.b.sofintr) 
2596                 {
2597                         retval |= dwc_otg_pcd_handle_sof_intr( _pcd );
2598                 }
2599                 if (gintr_status.b.rxstsqlvl) 
2600                 {
2601                         retval |= dwc_otg_pcd_handle_rx_status_q_level_intr( _pcd );
2602                 }
2603                 if (gintr_status.b.nptxfempty) 
2604                 {
2605                         retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr( _pcd );
2606                 }
2607                 if (gintr_status.b.ginnakeff) 
2608                 {
2609                         retval |= dwc_otg_pcd_handle_in_nak_effective( _pcd );
2610                 }
2611                 if (gintr_status.b.goutnakeff) 
2612                 {
2613                         retval |= dwc_otg_pcd_handle_out_nak_effective( _pcd );
2614                 }
2615                 if (gintr_status.b.i2cintr) 
2616                 {
2617                         retval |= dwc_otg_pcd_handle_i2c_intr( _pcd );
2618                 }
2619                 if (gintr_status.b.erlysuspend) 
2620                 {
2621                         retval |= dwc_otg_pcd_handle_early_suspend_intr( _pcd );
2622                 }
2623                 if (gintr_status.b.usbreset) 
2624                 {
2625                         retval |= dwc_otg_pcd_handle_usb_reset_intr( _pcd );
2626                         _pcd->conn_status = -1;
2627                 }
2628                 if (gintr_status.b.enumdone) 
2629                 {
2630                         retval |= dwc_otg_pcd_handle_enum_done_intr( _pcd );
2631                 }
2632                 if (gintr_status.b.isooutdrop) 
2633                 {
2634                         retval |= dwc_otg_pcd_handle_isoc_out_packet_dropped_intr( _pcd );
2635                 }
2636                 if (gintr_status.b.eopframe) 
2637                 {
2638                         retval |= dwc_otg_pcd_handle_end_periodic_frame_intr( _pcd );
2639                 }
2640                 if (gintr_status.b.epmismatch) 
2641                 {
2642                         retval |= dwc_otg_pcd_handle_ep_mismatch_intr( core_if );
2643                 }
2644                 if (gintr_status.b.inepint) 
2645                 {
2646                         retval |= dwc_otg_pcd_handle_in_ep_intr( _pcd );
2647                 }
2648                 if (gintr_status.b.outepintr) 
2649                 {
2650                         retval |= dwc_otg_pcd_handle_out_ep_intr( _pcd );
2651                 }
2652                 if (gintr_status.b.incomplisoin) 
2653                 {
2654                         retval |= dwc_otg_pcd_handle_incomplete_isoc_in_intr( _pcd );
2655                 }
2656                 if (gintr_status.b.incomplisoout) 
2657                 {
2658                         retval |= dwc_otg_pcd_handle_incomplete_isoc_out_intr( _pcd );
2659                 }
2660 #ifdef VERBOSE
2661                 DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
2662                                                 dwc_read_reg32( &global_regs->gintsts));
2663 #endif
2664                 SPIN_UNLOCK(&_pcd->lock);
2665         }
2666         return retval;
2667 }
2668
2669 #endif /* DWC_HOST_ONLY */