1 /* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
4 * $Date: 2008-11-21 05:39:15 $
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.
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.
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
32 * ========================================================================== */
34 #include <linux/interrupt.h>
35 #include <linux/dma-mapping.h>
36 #include <linux/version.h>
38 #include "dwc_otg_driver.h"
39 #include "dwc_otg_pcd.h"
44 /* request functions defined in "dwc_otg_pcd.c" */
47 * This file contains the implementation of the PCD Interrupt handlers.
49 * The PCD handles the device interrupts. Many conditions can cause a
50 * device interrupt. When an interrupt occurs, the device interrupt
51 * service routine determines the cause of the interrupt and
52 * dispatches handling to the appropriate function. These interrupt
53 * handling functions are described below.
54 * All interrupt registers are processed from LSB to MSB.
59 * This function prints the ep0 state for debug purposes.
61 static inline void print_ep0_state(dwc_otg_pcd_t
*pcd
)
66 switch (pcd
->ep0state
) {
68 strcpy(str
, "EP0_DISCONNECT");
71 strcpy(str
, "EP0_IDLE");
73 case EP0_IN_DATA_PHASE
:
74 strcpy(str
, "EP0_IN_DATA_PHASE");
76 case EP0_OUT_DATA_PHASE
:
77 strcpy(str
, "EP0_OUT_DATA_PHASE");
79 case EP0_IN_STATUS_PHASE
:
80 strcpy(str
,"EP0_IN_STATUS_PHASE");
82 case EP0_OUT_STATUS_PHASE
:
83 strcpy(str
,"EP0_OUT_STATUS_PHASE");
86 strcpy(str
,"EP0_STALL");
89 strcpy(str
,"EP0_INVALID");
92 DWC_DEBUGPL(DBG_ANY
, "%s(%d)\n", str
, pcd
->ep0state
);
97 * This function returns pointer to in ep struct with number ep_num
99 static inline dwc_otg_pcd_ep_t
* get_in_ep(dwc_otg_pcd_t
*pcd
, uint32_t ep_num
)
102 int num_in_eps
= GET_CORE_IF(pcd
)->dev_if
->num_in_eps
;
107 for(i
= 0; i
< num_in_eps
; ++i
)
109 if(pcd
->in_ep
[i
].dwc_ep
.num
== ep_num
)
110 return &pcd
->in_ep
[i
];
116 * This function returns pointer to out ep struct with number ep_num
118 static inline dwc_otg_pcd_ep_t
* get_out_ep(dwc_otg_pcd_t
*pcd
, uint32_t ep_num
)
121 int num_out_eps
= GET_CORE_IF(pcd
)->dev_if
->num_out_eps
;
126 for(i
= 0; i
< num_out_eps
; ++i
)
128 if(pcd
->out_ep
[i
].dwc_ep
.num
== ep_num
)
129 return &pcd
->out_ep
[i
];
135 * This functions gets a pointer to an EP from the wIndex address
136 * value of the control request.
138 static dwc_otg_pcd_ep_t
*get_ep_by_addr (dwc_otg_pcd_t
*pcd
, u16 wIndex
)
140 dwc_otg_pcd_ep_t
*ep
;
142 if ((wIndex
& USB_ENDPOINT_NUMBER_MASK
) == 0)
144 list_for_each_entry(ep
, &pcd
->gadget
.ep_list
, ep
.ep_list
)
151 bEndpointAddress
= ep
->desc
->bEndpointAddress
;
152 if((wIndex
& (USB_DIR_IN
| USB_ENDPOINT_NUMBER_MASK
))
153 == (bEndpointAddress
& (USB_DIR_IN
| USB_ENDPOINT_NUMBER_MASK
)))
160 * This function checks the EP request queue, if the queue is not
161 * empty the next request is started.
163 void start_next_request(dwc_otg_pcd_ep_t
*ep
)
165 dwc_otg_pcd_request_t
*req
= 0;
166 uint32_t max_transfer
= GET_CORE_IF(ep
->pcd
)->core_params
->max_transfer_size
;
168 if (!list_empty(&ep
->queue
)) {
169 req
= list_entry(ep
->queue
.next
,
170 dwc_otg_pcd_request_t
, queue
);
172 /* Setup and start the Transfer */
173 ep
->dwc_ep
.dma_addr
= req
->req
.dma
;
174 ep
->dwc_ep
.start_xfer_buff
= req
->req
.buf
;
175 ep
->dwc_ep
.xfer_buff
= req
->req
.buf
;
176 ep
->dwc_ep
.sent_zlp
= 0;
177 ep
->dwc_ep
.total_len
= req
->req
.length
;
178 ep
->dwc_ep
.xfer_len
= 0;
179 ep
->dwc_ep
.xfer_count
= 0;
181 if(max_transfer
> MAX_TRANSFER_SIZE
) {
182 ep
->dwc_ep
.maxxfer
= max_transfer
- (max_transfer
% ep
->dwc_ep
.maxpacket
);
184 ep
->dwc_ep
.maxxfer
= max_transfer
;
188 if((ep
->dwc_ep
.total_len
% ep
->dwc_ep
.maxpacket
== 0)
189 && (ep
->dwc_ep
.total_len
!= 0)) {
190 ep
->dwc_ep
.sent_zlp
= 1;
195 dwc_otg_ep_start_transfer(GET_CORE_IF(ep
->pcd
), &ep
->dwc_ep
);
200 * This function handles the SOF Interrupts. At this time the SOF
201 * Interrupt is disabled.
203 int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t
*pcd
)
205 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
207 gintsts_data_t gintsts
;
209 DWC_DEBUGPL(DBG_PCD
, "SOF\n");
211 /* Clear interrupt */
213 gintsts
.b
.sofintr
= 1;
214 dwc_write_reg32 (&core_if
->core_global_regs
->gintsts
, gintsts
.d32
);
221 * This function handles the Rx Status Queue Level Interrupt, which
222 * indicates that there is a least one packet in the Rx FIFO. The
223 * packets are moved from the FIFO to memory, where they will be
224 * processed when the Endpoint Interrupt Register indicates Transfer
225 * Complete or SETUP Phase Done.
227 * Repeat the following until the Rx Status Queue is empty:
228 * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
230 * -# If Receive FIFO is empty then skip to step Clear the interrupt
232 * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
233 * SETUP data to the buffer
234 * -# If OUT Data Packet call dwc_otg_read_packet to copy the data
235 * to the destination buffer
237 int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t
*pcd
)
239 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
240 dwc_otg_core_global_regs_t
*global_regs
= core_if
->core_global_regs
;
241 gintmsk_data_t gintmask
= {.d32
=0};
242 device_grxsts_data_t status
;
243 dwc_otg_pcd_ep_t
*ep
;
244 gintsts_data_t gintsts
;
246 static char *dpid_str
[] ={ "D0", "D2", "D1", "MDATA" };
249 //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
250 /* Disable the Rx Status Queue Level interrupt */
251 gintmask
.b
.rxstsqlvl
= 1;
252 dwc_modify_reg32(&global_regs
->gintmsk
, gintmask
.d32
, 0);
254 /* Get the Status from the top of the FIFO */
255 status
.d32
= dwc_read_reg32(&global_regs
->grxstsp
);
257 DWC_DEBUGPL(DBG_PCD
, "EP:%d BCnt:%d DPID:%s "
258 "pktsts:%x Frame:%d(0x%0x)\n",
259 status
.b
.epnum
, status
.b
.bcnt
,
260 dpid_str
[status
.b
.dpid
],
261 status
.b
.pktsts
, status
.b
.fn
, status
.b
.fn
);
262 /* Get pointer to EP structure */
263 ep
= get_out_ep(pcd
, status
.b
.epnum
);
265 switch (status
.b
.pktsts
) {
266 case DWC_DSTS_GOUT_NAK
:
267 DWC_DEBUGPL(DBG_PCDV
, "Global OUT NAK\n");
269 case DWC_STS_DATA_UPDT
:
270 DWC_DEBUGPL(DBG_PCDV
, "OUT Data Packet\n");
271 if (status
.b
.bcnt
&& ep
->dwc_ep
.xfer_buff
) {
272 /** @todo NGS Check for buffer overflow? */
273 dwc_otg_read_packet(core_if
,
274 ep
->dwc_ep
.xfer_buff
,
276 ep
->dwc_ep
.xfer_count
+= status
.b
.bcnt
;
277 ep
->dwc_ep
.xfer_buff
+= status
.b
.bcnt
;
280 case DWC_STS_XFER_COMP
:
281 DWC_DEBUGPL(DBG_PCDV
, "OUT Complete\n");
283 case DWC_DSTS_SETUP_COMP
:
285 DWC_DEBUGPL(DBG_PCDV
, "Setup Complete\n");
288 case DWC_DSTS_SETUP_UPDT
:
289 dwc_otg_read_setup_packet(core_if
, pcd
->setup_pkt
->d32
);
292 "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
293 pcd
->setup_pkt
->req
.bRequestType
,
294 pcd
->setup_pkt
->req
.bRequest
,
295 pcd
->setup_pkt
->req
.wValue
,
296 pcd
->setup_pkt
->req
.wIndex
,
297 pcd
->setup_pkt
->req
.wLength
);
299 ep
->dwc_ep
.xfer_count
+= status
.b
.bcnt
;
302 DWC_DEBUGPL(DBG_PCDV
, "Invalid Packet Status (0x%0x)\n",
307 /* Enable the Rx Status Queue Level interrupt */
308 dwc_modify_reg32(&global_regs
->gintmsk
, 0, gintmask
.d32
);
309 /* Clear interrupt */
311 gintsts
.b
.rxstsqlvl
= 1;
312 dwc_write_reg32 (&global_regs
->gintsts
, gintsts
.d32
);
314 //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
318 * This function examines the Device IN Token Learning Queue to
319 * determine the EP number of the last IN token received. This
320 * implementation is for the Mass Storage device where there are only
321 * 2 IN EPs (Control-IN and BULK-IN).
323 * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
324 * are 8 EP Numbers in each of the other possible DTKNQ Registers.
326 * @param core_if Programming view of DWC_otg controller.
329 static inline int get_ep_of_last_in_token(dwc_otg_core_if_t
*core_if
)
331 dwc_otg_device_global_regs_t
*dev_global_regs
=
332 core_if
->dev_if
->dev_global_regs
;
333 const uint32_t TOKEN_Q_DEPTH
= core_if
->hwcfg2
.b
.dev_token_q_depth
;
334 /* Number of Token Queue Registers */
335 const int DTKNQ_REG_CNT
= (TOKEN_Q_DEPTH
+ 7) / 8;
336 dtknq1_data_t dtknqr1
;
337 uint32_t in_tkn_epnums
[4];
340 volatile uint32_t *addr
= &dev_global_regs
->dtknqr1
;
343 //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
346 /* Read the DTKNQ Registers */
347 for (i
= 0; i
< DTKNQ_REG_CNT
; i
++)
349 in_tkn_epnums
[ i
] = dwc_read_reg32(addr
);
350 DWC_DEBUGPL(DBG_PCDV
, "DTKNQR%d=0x%08x\n", i
+1,
352 if (addr
== &dev_global_regs
->dvbusdis
) {
353 addr
= &dev_global_regs
->dtknqr3_dthrctl
;
361 /* Copy the DTKNQR1 data to the bit field. */
362 dtknqr1
.d32
= in_tkn_epnums
[0];
363 /* Get the EP numbers */
364 in_tkn_epnums
[0] = dtknqr1
.b
.epnums0_5
;
365 ndx
= dtknqr1
.b
.intknwptr
- 1;
367 //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
369 /** @todo Find a simpler way to calculate the max
371 int cnt
= TOKEN_Q_DEPTH
;
372 if (TOKEN_Q_DEPTH
<= 6) {
373 cnt
= TOKEN_Q_DEPTH
- 1;
375 else if (TOKEN_Q_DEPTH
<= 14) {
376 cnt
= TOKEN_Q_DEPTH
- 7;
378 else if (TOKEN_Q_DEPTH
<= 22) {
379 cnt
= TOKEN_Q_DEPTH
- 15;
382 cnt
= TOKEN_Q_DEPTH
- 23;
384 epnum
= (in_tkn_epnums
[ DTKNQ_REG_CNT
- 1 ] >> (cnt
* 4)) & 0xF;
388 epnum
= (in_tkn_epnums
[0] >> (ndx
* 4)) & 0xF;
390 else if (ndx
<= 13) {
392 epnum
= (in_tkn_epnums
[1] >> (ndx
* 4)) & 0xF;
394 else if (ndx
<= 21) {
396 epnum
= (in_tkn_epnums
[2] >> (ndx
* 4)) & 0xF;
398 else if (ndx
<= 29) {
400 epnum
= (in_tkn_epnums
[3] >> (ndx
* 4)) & 0xF;
403 //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
408 * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
409 * The active request is checked for the next packet to be loaded into
410 * the non-periodic Tx FIFO.
412 int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t
*pcd
)
414 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
415 dwc_otg_core_global_regs_t
*global_regs
=
416 core_if
->core_global_regs
;
417 dwc_otg_dev_in_ep_regs_t
*ep_regs
;
418 gnptxsts_data_t txstatus
= {.d32
= 0};
419 gintsts_data_t gintsts
;
422 dwc_otg_pcd_ep_t
*ep
= 0;
426 /* Get the epnum from the IN Token Learning Queue. */
427 epnum
= get_ep_of_last_in_token(core_if
);
428 ep
= get_in_ep(pcd
, epnum
);
430 DWC_DEBUGPL(DBG_PCD
, "NP TxFifo Empty: %s(%d) \n", ep
->ep
.name
, epnum
);
431 ep_regs
= core_if
->dev_if
->in_ep_regs
[epnum
];
433 len
= ep
->dwc_ep
.xfer_len
- ep
->dwc_ep
.xfer_count
;
434 if (len
> ep
->dwc_ep
.maxpacket
) {
435 len
= ep
->dwc_ep
.maxpacket
;
437 dwords
= (len
+ 3)/4;
440 /* While there is space in the queue and space in the FIFO and
441 * More data to tranfer, Write packets to the Tx FIFO */
442 txstatus
.d32
= dwc_read_reg32(&global_regs
->gnptxsts
);
443 DWC_DEBUGPL(DBG_PCDV
, "b4 GNPTXSTS=0x%08x\n",txstatus
.d32
);
445 while (txstatus
.b
.nptxqspcavail
> 0 &&
446 txstatus
.b
.nptxfspcavail
> dwords
&&
447 ep
->dwc_ep
.xfer_count
< ep
->dwc_ep
.xfer_len
) {
449 dwc_otg_ep_write_packet(core_if
, &ep
->dwc_ep
, 0);
450 len
= ep
->dwc_ep
.xfer_len
- ep
->dwc_ep
.xfer_count
;
452 if (len
> ep
->dwc_ep
.maxpacket
) {
453 len
= ep
->dwc_ep
.maxpacket
;
456 dwords
= (len
+ 3)/4;
457 txstatus
.d32
= dwc_read_reg32(&global_regs
->gnptxsts
);
458 DWC_DEBUGPL(DBG_PCDV
,"GNPTXSTS=0x%08x\n",txstatus
.d32
);
461 DWC_DEBUGPL(DBG_PCDV
, "GNPTXSTS=0x%08x\n",
462 dwc_read_reg32(&global_regs
->gnptxsts
));
464 /* Clear interrupt */
466 gintsts
.b
.nptxfempty
= 1;
467 dwc_write_reg32 (&global_regs
->gintsts
, gintsts
.d32
);
473 * This function is called when dedicated Tx FIFO Empty interrupt occurs.
474 * The active request is checked for the next packet to be loaded into
475 * apropriate Tx FIFO.
477 static int32_t write_empty_tx_fifo(dwc_otg_pcd_t
*pcd
, uint32_t epnum
)
479 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
480 dwc_otg_dev_if_t
* dev_if
= core_if
->dev_if
;
481 dwc_otg_dev_in_ep_regs_t
*ep_regs
;
482 dtxfsts_data_t txstatus
= {.d32
= 0};
483 dwc_otg_pcd_ep_t
*ep
= 0;
487 ep
= get_in_ep(pcd
, epnum
);
489 DWC_DEBUGPL(DBG_PCD
, "Dedicated TxFifo Empty: %s(%d) \n", ep
->ep
.name
, epnum
);
491 ep_regs
= core_if
->dev_if
->in_ep_regs
[epnum
];
493 len
= ep
->dwc_ep
.xfer_len
- ep
->dwc_ep
.xfer_count
;
495 if (len
> ep
->dwc_ep
.maxpacket
) {
496 len
= ep
->dwc_ep
.maxpacket
;
499 dwords
= (len
+ 3)/4;
501 /* While there is space in the queue and space in the FIFO and
502 * More data to tranfer, Write packets to the Tx FIFO */
503 txstatus
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[epnum
]->dtxfsts
);
504 DWC_DEBUGPL(DBG_PCDV
, "b4 dtxfsts[%d]=0x%08x\n",epnum
,txstatus
.d32
);
506 while (txstatus
.b
.txfspcavail
> dwords
&&
507 ep
->dwc_ep
.xfer_count
< ep
->dwc_ep
.xfer_len
&&
508 ep
->dwc_ep
.xfer_len
!= 0) {
510 dwc_otg_ep_write_packet(core_if
, &ep
->dwc_ep
, 0);
512 len
= ep
->dwc_ep
.xfer_len
- ep
->dwc_ep
.xfer_count
;
513 if (len
> ep
->dwc_ep
.maxpacket
) {
514 len
= ep
->dwc_ep
.maxpacket
;
517 dwords
= (len
+ 3)/4;
518 txstatus
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[epnum
]->dtxfsts
);
519 DWC_DEBUGPL(DBG_PCDV
,"dtxfsts[%d]=0x%08x\n", epnum
, txstatus
.d32
);
522 DWC_DEBUGPL(DBG_PCDV
, "b4 dtxfsts[%d]=0x%08x\n",epnum
,dwc_read_reg32(&dev_if
->in_ep_regs
[epnum
]->dtxfsts
));
529 * This function is called when the Device is disconnected. It stops
530 * any active requests and informs the Gadget driver of the
533 void dwc_otg_pcd_stop(dwc_otg_pcd_t
*pcd
)
535 int i
, num_in_eps
, num_out_eps
;
536 dwc_otg_pcd_ep_t
*ep
;
538 gintmsk_data_t intr_mask
= {.d32
= 0};
540 num_in_eps
= GET_CORE_IF(pcd
)->dev_if
->num_in_eps
;
541 num_out_eps
= GET_CORE_IF(pcd
)->dev_if
->num_out_eps
;
543 DWC_DEBUGPL(DBG_PCDV
, "%s() \n", __func__
);
544 /* don't disconnect drivers more than once */
545 if (pcd
->ep0state
== EP0_DISCONNECT
) {
546 DWC_DEBUGPL(DBG_ANY
, "%s() Already Disconnected\n", __func__
);
549 pcd
->ep0state
= EP0_DISCONNECT
;
551 /* Reset the OTG state. */
552 dwc_otg_pcd_update_otg(pcd
, 1);
554 /* Disable the NP Tx Fifo Empty Interrupt. */
555 intr_mask
.b
.nptxfempty
= 1;
556 dwc_modify_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintmsk
,
559 /* Flush the FIFOs */
560 /**@todo NGS Flush Periodic FIFOs */
561 dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd
), 0x10);
562 dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd
));
564 /* prevent new request submissions, kill any outstanding requests */
566 dwc_otg_request_nuke(ep
);
567 /* prevent new request submissions, kill any outstanding requests */
568 for (i
= 0; i
< num_in_eps
; i
++)
570 dwc_otg_pcd_ep_t
*ep
= &pcd
->in_ep
[i
];
571 dwc_otg_request_nuke(ep
);
573 /* prevent new request submissions, kill any outstanding requests */
574 for (i
= 0; i
< num_out_eps
; i
++)
576 dwc_otg_pcd_ep_t
*ep
= &pcd
->out_ep
[i
];
577 dwc_otg_request_nuke(ep
);
580 /* report disconnect; the driver is already quiesced */
581 if (pcd
->driver
&& pcd
->driver
->disconnect
) {
582 SPIN_UNLOCK(&pcd
->lock
);
583 pcd
->driver
->disconnect(&pcd
->gadget
);
584 SPIN_LOCK(&pcd
->lock
);
589 * This interrupt indicates that ...
591 int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t
*pcd
)
593 gintmsk_data_t intr_mask
= { .d32
= 0};
594 gintsts_data_t gintsts
;
596 DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "i2cintr");
597 intr_mask
.b
.i2cintr
= 1;
598 dwc_modify_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintmsk
,
601 /* Clear interrupt */
603 gintsts
.b
.i2cintr
= 1;
604 dwc_write_reg32 (&GET_CORE_IF(pcd
)->core_global_regs
->gintsts
,
611 * This interrupt indicates that ...
613 int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t
*pcd
)
615 gintsts_data_t gintsts
;
617 DWC_PRINT("Early Suspend Detected\n");
619 /* Clear interrupt */
621 gintsts
.b
.erlysuspend
= 1;
622 dwc_write_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintsts
,
628 * This function configures EPO to receive SETUP packets.
630 * @todo NGS: Update the comments from the HW FS.
632 * -# Program the following fields in the endpoint specific registers
633 * for Control OUT EP 0, in order to receive a setup packet
634 * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
636 * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
637 * to back setup packets)
638 * - In DMA mode, DOEPDMA0 Register with a memory address to
639 * store any setup packets received
641 * @param core_if Programming view of DWC_otg controller.
642 * @param pcd Programming view of the PCD.
644 static inline void ep0_out_start(dwc_otg_core_if_t
*core_if
, dwc_otg_pcd_t
*pcd
)
646 dwc_otg_dev_if_t
*dev_if
= core_if
->dev_if
;
647 deptsiz0_data_t doeptsize0
= { .d32
= 0};
648 dwc_otg_dma_desc_t
* dma_desc
;
649 depctl_data_t doepctl
= { .d32
= 0 };
652 DWC_DEBUGPL(DBG_PCDV
,"%s() doepctl0=%0x\n", __func__
,
653 dwc_read_reg32(&dev_if
->out_ep_regs
[0]->doepctl
));
656 doeptsize0
.b
.supcnt
= 3;
657 doeptsize0
.b
.pktcnt
= 1;
658 doeptsize0
.b
.xfersize
= 8*3;
661 if (core_if
->dma_enable
) {
662 if (!core_if
->dma_desc_enable
) {
663 /** put here as for Hermes mode deptisz register should not be written */
664 dwc_write_reg32(&dev_if
->out_ep_regs
[0]->doeptsiz
,
667 /** @todo dma needs to handle multiple setup packets (up to 3) */
668 dwc_write_reg32(&dev_if
->out_ep_regs
[0]->doepdma
,
669 pcd
->setup_pkt_dma_handle
);
671 dev_if
->setup_desc_index
= (dev_if
->setup_desc_index
+ 1) & 1;
672 dma_desc
= dev_if
->setup_desc_addr
[dev_if
->setup_desc_index
];
674 /** DMA Descriptor Setup */
675 dma_desc
->status
.b
.bs
= BS_HOST_BUSY
;
676 dma_desc
->status
.b
.l
= 1;
677 dma_desc
->status
.b
.ioc
= 1;
678 dma_desc
->status
.b
.bytes
= pcd
->ep0
.dwc_ep
.maxpacket
;
679 dma_desc
->buf
= pcd
->setup_pkt_dma_handle
;
680 dma_desc
->status
.b
.bs
= BS_HOST_READY
;
682 /** DOEPDMA0 Register write */
683 dwc_write_reg32(&dev_if
->out_ep_regs
[0]->doepdma
, dev_if
->dma_setup_desc_addr
[dev_if
->setup_desc_index
]);
687 /** put here as for Hermes mode deptisz register should not be written */
688 dwc_write_reg32(&dev_if
->out_ep_regs
[0]->doeptsiz
,
692 /** DOEPCTL0 Register write */
695 dwc_write_reg32(&dev_if
->out_ep_regs
[0]->doepctl
, doepctl
.d32
);
698 DWC_DEBUGPL(DBG_PCDV
,"doepctl0=%0x\n",
699 dwc_read_reg32(&dev_if
->out_ep_regs
[0]->doepctl
));
700 DWC_DEBUGPL(DBG_PCDV
,"diepctl0=%0x\n",
701 dwc_read_reg32(&dev_if
->in_ep_regs
[0]->diepctl
));
707 * This interrupt occurs when a USB Reset is detected. When the USB
708 * Reset Interrupt occurs the device state is set to DEFAULT and the
709 * EP0 state is set to IDLE.
710 * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
711 * -# Unmask the following interrupt bits
712 * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
713 * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
714 * - DOEPMSK.SETUP = 1
715 * - DOEPMSK.XferCompl = 1
716 * - DIEPMSK.XferCompl = 1
717 * - DIEPMSK.TimeOut = 1
718 * -# Program the following fields in the endpoint specific registers
719 * for Control OUT EP 0, in order to receive a setup packet
720 * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
722 * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
723 * to back setup packets)
724 * - In DMA mode, DOEPDMA0 Register with a memory address to
725 * store any setup packets received
726 * At this point, all the required initialization, except for enabling
727 * the control 0 OUT endpoint is done, for receiving SETUP packets.
729 int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t
* pcd
)
731 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
732 dwc_otg_dev_if_t
*dev_if
= core_if
->dev_if
;
733 depctl_data_t doepctl
= { .d32
= 0};
735 daint_data_t daintmsk
= { .d32
= 0};
736 doepmsk_data_t doepmsk
= { .d32
= 0};
737 diepmsk_data_t diepmsk
= { .d32
= 0};
739 dcfg_data_t dcfg
= { .d32
=0 };
740 grstctl_t resetctl
= { .d32
=0 };
741 dctl_data_t dctl
= {.d32
=0};
743 gintsts_data_t gintsts
;
745 DWC_PRINT("USB RESET\n");
747 for(i
= 1;i
< 16; ++i
)
749 dwc_otg_pcd_ep_t
*ep
;
751 ep
= get_in_ep(pcd
,i
);
753 dwc_ep
= &ep
->dwc_ep
;
754 dwc_ep
->next_frame
= 0xffffffff;
757 #endif /* DWC_EN_ISOC */
759 /* reset the HNP settings */
760 dwc_otg_pcd_update_otg(pcd
, 1);
762 /* Clear the Remote Wakeup Signalling */
763 dctl
.b
.rmtwkupsig
= 1;
764 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->dctl
,
767 /* Set NAK for all OUT EPs */
769 for (i
=0; i
<= dev_if
->num_out_eps
; i
++)
771 dwc_write_reg32(&dev_if
->out_ep_regs
[i
]->doepctl
,
775 /* Flush the NP Tx FIFO */
776 dwc_otg_flush_tx_fifo(core_if
, 0x10);
777 /* Flush the Learning Queue */
778 resetctl
.b
.intknqflsh
= 1;
779 dwc_write_reg32(&core_if
->core_global_regs
->grstctl
, resetctl
.d32
);
781 if(core_if
->multiproc_int_enable
) {
782 daintmsk
.b
.inep0
= 1;
783 daintmsk
.b
.outep0
= 1;
784 dwc_write_reg32(&dev_if
->dev_global_regs
->deachintmsk
, daintmsk
.d32
);
787 doepmsk
.b
.xfercompl
= 1;
788 doepmsk
.b
.ahberr
= 1;
789 doepmsk
.b
.epdisabled
= 1;
791 if(core_if
->dma_desc_enable
) {
792 doepmsk
.b
.stsphsercvd
= 1;
796 doepmsk.b.babble = 1;
799 if(core_if->dma_enable) {
803 dwc_write_reg32(&dev_if
->dev_global_regs
->doepeachintmsk
[0], doepmsk
.d32
);
805 diepmsk
.b
.xfercompl
= 1;
806 diepmsk
.b
.timeout
= 1;
807 diepmsk
.b
.epdisabled
= 1;
808 diepmsk
.b
.ahberr
= 1;
809 diepmsk
.b
.intknepmis
= 1;
811 if(core_if
->dma_desc_enable
) {
815 if(core_if->dma_enable) {
819 dwc_write_reg32(&dev_if
->dev_global_regs
->diepeachintmsk
[0], diepmsk
.d32
);
821 daintmsk
.b
.inep0
= 1;
822 daintmsk
.b
.outep0
= 1;
823 dwc_write_reg32(&dev_if
->dev_global_regs
->daintmsk
, daintmsk
.d32
);
826 doepmsk
.b
.xfercompl
= 1;
827 doepmsk
.b
.ahberr
= 1;
828 doepmsk
.b
.epdisabled
= 1;
830 if(core_if
->dma_desc_enable
) {
831 doepmsk
.b
.stsphsercvd
= 1;
835 doepmsk.b.babble = 1;
839 dwc_write_reg32(&dev_if
->dev_global_regs
->doepmsk
, doepmsk
.d32
);
841 diepmsk
.b
.xfercompl
= 1;
842 diepmsk
.b
.timeout
= 1;
843 diepmsk
.b
.epdisabled
= 1;
844 diepmsk
.b
.ahberr
= 1;
845 diepmsk
.b
.intknepmis
= 1;
847 if(core_if
->dma_desc_enable
) {
851 // diepmsk.b.nak = 1;
853 dwc_write_reg32(&dev_if
->dev_global_regs
->diepmsk
, diepmsk
.d32
);
856 /* Reset Device Address */
857 dcfg
.d32
= dwc_read_reg32(&dev_if
->dev_global_regs
->dcfg
);
859 dwc_write_reg32(&dev_if
->dev_global_regs
->dcfg
, dcfg
.d32
);
861 /* setup EP0 to receive SETUP packets */
862 ep0_out_start(core_if
, pcd
);
864 /* Clear interrupt */
866 gintsts
.b
.usbreset
= 1;
867 dwc_write_reg32 (&core_if
->core_global_regs
->gintsts
, gintsts
.d32
);
873 * Get the device speed from the device status register and convert it
874 * to USB speed constant.
876 * @param core_if Programming view of DWC_otg controller.
878 static int get_device_speed(dwc_otg_core_if_t
*core_if
)
881 enum usb_device_speed speed
= USB_SPEED_UNKNOWN
;
882 dsts
.d32
= dwc_read_reg32(&core_if
->dev_if
->dev_global_regs
->dsts
);
884 switch (dsts
.b
.enumspd
) {
885 case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ
:
886 speed
= USB_SPEED_HIGH
;
888 case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ
:
889 case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ
:
890 speed
= USB_SPEED_FULL
;
893 case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ
:
894 speed
= USB_SPEED_LOW
;
902 * Read the device status register and set the device speed in the
904 * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
906 int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t
*pcd
)
908 dwc_otg_pcd_ep_t
*ep0
= &pcd
->ep0
;
909 gintsts_data_t gintsts
;
910 gusbcfg_data_t gusbcfg
;
911 dwc_otg_core_global_regs_t
*global_regs
=
912 GET_CORE_IF(pcd
)->core_global_regs
;
913 uint8_t utmi16b
, utmi8b
;
914 DWC_DEBUGPL(DBG_PCD
, "SPEED ENUM\n");
916 if (GET_CORE_IF(pcd
)->snpsid
>= 0x4F54260A) {
923 dwc_otg_ep0_activate(GET_CORE_IF(pcd
), &ep0
->dwc_ep
);
926 print_ep0_state(pcd
);
929 if (pcd
->ep0state
== EP0_DISCONNECT
) {
930 pcd
->ep0state
= EP0_IDLE
;
932 else if (pcd
->ep0state
== EP0_STALL
) {
933 pcd
->ep0state
= EP0_IDLE
;
936 pcd
->ep0state
= EP0_IDLE
;
940 pcd
->gadget
.speed
= get_device_speed(GET_CORE_IF(pcd
));
942 /* Set USB turnaround time based on device speed and PHY interface. */
943 gusbcfg
.d32
= dwc_read_reg32(&global_regs
->gusbcfg
);
944 if (pcd
->gadget
.speed
== USB_SPEED_HIGH
) {
945 if (GET_CORE_IF(pcd
)->hwcfg2
.b
.hs_phy_type
== DWC_HWCFG2_HS_PHY_TYPE_ULPI
) {
947 gusbcfg
.b
.usbtrdtim
= 9;
949 if (GET_CORE_IF(pcd
)->hwcfg2
.b
.hs_phy_type
== DWC_HWCFG2_HS_PHY_TYPE_UTMI
) {
950 /* UTMI+ interface */
951 if (GET_CORE_IF(pcd
)->hwcfg4
.b
.utmi_phy_data_width
== 0) {
952 gusbcfg
.b
.usbtrdtim
= utmi8b
;
954 else if (GET_CORE_IF(pcd
)->hwcfg4
.b
.utmi_phy_data_width
== 1) {
955 gusbcfg
.b
.usbtrdtim
= utmi16b
;
957 else if (GET_CORE_IF(pcd
)->core_params
->phy_utmi_width
== 8) {
958 gusbcfg
.b
.usbtrdtim
= utmi8b
;
961 gusbcfg
.b
.usbtrdtim
= utmi16b
;
964 if (GET_CORE_IF(pcd
)->hwcfg2
.b
.hs_phy_type
== DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI
) {
965 /* UTMI+ OR ULPI interface */
966 if (gusbcfg
.b
.ulpi_utmi_sel
== 1) {
968 gusbcfg
.b
.usbtrdtim
= 9;
971 /* UTMI+ interface */
972 if (GET_CORE_IF(pcd
)->core_params
->phy_utmi_width
== 16) {
973 gusbcfg
.b
.usbtrdtim
= utmi16b
;
976 gusbcfg
.b
.usbtrdtim
= utmi8b
;
982 /* Full or low speed */
983 gusbcfg
.b
.usbtrdtim
= 9;
985 dwc_write_reg32(&global_regs
->gusbcfg
, gusbcfg
.d32
);
987 /* Clear interrupt */
989 gintsts
.b
.enumdone
= 1;
990 dwc_write_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintsts
,
996 * This interrupt indicates that the ISO OUT Packet was dropped due to
997 * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs
998 * read all the data from the Rx FIFO.
1000 int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t
*pcd
)
1002 gintmsk_data_t intr_mask
= { .d32
= 0};
1003 gintsts_data_t gintsts
;
1005 DWC_PRINT("INTERRUPT Handler not implemented for %s\n",
1006 "ISOC Out Dropped");
1008 intr_mask
.b
.isooutdrop
= 1;
1009 dwc_modify_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintmsk
,
1012 /* Clear interrupt */
1015 gintsts
.b
.isooutdrop
= 1;
1016 dwc_write_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintsts
,
1023 * This interrupt indicates the end of the portion of the micro-frame
1024 * for periodic transactions. If there is a periodic transaction for
1025 * the next frame, load the packets into the EP periodic Tx FIFO.
1027 int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t
*pcd
)
1029 gintmsk_data_t intr_mask
= { .d32
= 0};
1030 gintsts_data_t gintsts
;
1031 DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "EOP");
1033 intr_mask
.b
.eopframe
= 1;
1034 dwc_modify_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintmsk
,
1037 /* Clear interrupt */
1039 gintsts
.b
.eopframe
= 1;
1040 dwc_write_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintsts
, gintsts
.d32
);
1046 * This interrupt indicates that EP of the packet on the top of the
1047 * non-periodic Tx FIFO does not match EP of the IN Token received.
1049 * The "Device IN Token Queue" Registers are read to determine the
1050 * order the IN Tokens have been received. The non-periodic Tx FIFO
1051 * is flushed, so it can be reloaded in the order seen in the IN Token
1054 int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_core_if_t
*core_if
)
1056 gintsts_data_t gintsts
;
1057 DWC_DEBUGPL(DBG_PCDV
, "%s(%p)\n", __func__
, core_if
);
1059 /* Clear interrupt */
1061 gintsts
.b
.epmismatch
= 1;
1062 dwc_write_reg32 (&core_if
->core_global_regs
->gintsts
, gintsts
.d32
);
1068 * This funcion stalls EP0.
1070 static inline void ep0_do_stall(dwc_otg_pcd_t
*pcd
, const int err_val
)
1072 dwc_otg_pcd_ep_t
*ep0
= &pcd
->ep0
;
1073 struct usb_ctrlrequest
*ctrl
= &pcd
->setup_pkt
->req
;
1074 DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
1075 ctrl
->bRequestType
, ctrl
->bRequest
, err_val
);
1077 ep0
->dwc_ep
.is_in
= 1;
1078 dwc_otg_ep_set_stall(pcd
->otg_dev
->core_if
, &ep0
->dwc_ep
);
1079 pcd
->ep0
.stopped
= 1;
1080 pcd
->ep0state
= EP0_IDLE
;
1081 ep0_out_start(GET_CORE_IF(pcd
), pcd
);
1085 * This functions delegates the setup command to the gadget driver.
1087 static inline void do_gadget_setup(dwc_otg_pcd_t
*pcd
,
1088 struct usb_ctrlrequest
* ctrl
)
1091 if (pcd
->driver
&& pcd
->driver
->setup
) {
1092 SPIN_UNLOCK(&pcd
->lock
);
1093 ret
= pcd
->driver
->setup(&pcd
->gadget
, ctrl
);
1094 SPIN_LOCK(&pcd
->lock
);
1096 ep0_do_stall(pcd
, ret
);
1099 /** @todo This is a g_file_storage gadget driver specific
1100 * workaround: a DELAYED_STATUS result from the fsg_setup
1101 * routine will result in the gadget queueing a EP0 IN status
1102 * phase for a two-stage control transfer. Exactly the same as
1103 * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
1104 * specific request. Need a generic way to know when the gadget
1105 * driver will queue the status phase. Can we assume when we
1106 * call the gadget driver setup() function that it will always
1107 * queue and require the following flag? Need to look into
1111 if (ret
== 256 + 999) {
1112 pcd
->request_config
= 1;
1118 * This function starts the Zero-Length Packet for the IN status phase
1119 * of a 2 stage control transfer.
1121 static inline void do_setup_in_status_phase(dwc_otg_pcd_t
*pcd
)
1123 dwc_otg_pcd_ep_t
*ep0
= &pcd
->ep0
;
1124 if (pcd
->ep0state
== EP0_STALL
) {
1128 pcd
->ep0state
= EP0_IN_STATUS_PHASE
;
1130 /* Prepare for more SETUP Packets */
1131 DWC_DEBUGPL(DBG_PCD
, "EP0 IN ZLP\n");
1132 ep0
->dwc_ep
.xfer_len
= 0;
1133 ep0
->dwc_ep
.xfer_count
= 0;
1134 ep0
->dwc_ep
.is_in
= 1;
1135 ep0
->dwc_ep
.dma_addr
= pcd
->setup_pkt_dma_handle
;
1136 dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd
), &ep0
->dwc_ep
);
1138 /* Prepare for more SETUP Packets */
1139 // if(GET_CORE_IF(pcd)->dma_enable == 0) ep0_out_start(GET_CORE_IF(pcd), pcd);
1143 * This function starts the Zero-Length Packet for the OUT status phase
1144 * of a 2 stage control transfer.
1146 static inline void do_setup_out_status_phase(dwc_otg_pcd_t
*pcd
)
1148 dwc_otg_pcd_ep_t
*ep0
= &pcd
->ep0
;
1149 if (pcd
->ep0state
== EP0_STALL
) {
1150 DWC_DEBUGPL(DBG_PCD
, "EP0 STALLED\n");
1153 pcd
->ep0state
= EP0_OUT_STATUS_PHASE
;
1155 DWC_DEBUGPL(DBG_PCD
, "EP0 OUT ZLP\n");
1156 ep0
->dwc_ep
.xfer_len
= 0;
1157 ep0
->dwc_ep
.xfer_count
= 0;
1158 ep0
->dwc_ep
.is_in
= 0;
1159 ep0
->dwc_ep
.dma_addr
= pcd
->setup_pkt_dma_handle
;
1160 dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd
), &ep0
->dwc_ep
);
1162 /* Prepare for more SETUP Packets */
1163 if(GET_CORE_IF(pcd
)->dma_enable
== 0) {
1164 ep0_out_start(GET_CORE_IF(pcd
), pcd
);
1169 * Clear the EP halt (STALL) and if pending requests start the
1172 static inline void pcd_clear_halt(dwc_otg_pcd_t
*pcd
, dwc_otg_pcd_ep_t
*ep
)
1174 if(ep
->dwc_ep
.stall_clear_flag
== 0)
1175 dwc_otg_ep_clear_stall(GET_CORE_IF(pcd
), &ep
->dwc_ep
);
1177 /* Reactive the EP */
1178 dwc_otg_ep_activate(GET_CORE_IF(pcd
), &ep
->dwc_ep
);
1181 /* If there is a request in the EP queue start it */
1183 /** @todo FIXME: this causes an EP mismatch in DMA mode.
1184 * epmismatch not yet implemented. */
1187 * Above fixme is solved by implmenting a tasklet to call the
1188 * start_next_request(), outside of interrupt context at some
1189 * time after the current time, after a clear-halt setup packet.
1190 * Still need to implement ep mismatch in the future if a gadget
1191 * ever uses more than one endpoint at once
1194 tasklet_schedule (pcd
->start_xfer_tasklet
);
1196 /* Start Control Status Phase */
1197 do_setup_in_status_phase(pcd
);
1201 * This function is called when the SET_FEATURE TEST_MODE Setup packet
1202 * is sent from the host. The Device Control register is written with
1203 * the Test Mode bits set to the specified Test Mode. This is done as
1204 * a tasklet so that the "Status" phase of the control transfer
1205 * completes before transmitting the TEST packets.
1207 * @todo This has not been tested since the tasklet struct was put
1208 * into the PCD struct!
1211 static void do_test_mode(unsigned long data
)
1214 dwc_otg_pcd_t
*pcd
= (dwc_otg_pcd_t
*)data
;
1215 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
1216 int test_mode
= pcd
->test_mode
;
1219 // DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
1221 dctl
.d32
= dwc_read_reg32(&core_if
->dev_if
->dev_global_regs
->dctl
);
1222 switch (test_mode
) {
1231 case 3: // TEST_SE0_NAK
1235 case 4: // TEST_PACKET
1239 case 5: // TEST_FORCE_ENABLE
1243 dwc_write_reg32(&core_if
->dev_if
->dev_global_regs
->dctl
, dctl
.d32
);
1247 * This function process the GET_STATUS Setup Commands.
1249 static inline void do_get_status(dwc_otg_pcd_t
*pcd
)
1251 struct usb_ctrlrequest ctrl
= pcd
->setup_pkt
->req
;
1252 dwc_otg_pcd_ep_t
*ep
;
1253 dwc_otg_pcd_ep_t
*ep0
= &pcd
->ep0
;
1254 uint16_t *status
= pcd
->status_buf
;
1257 DWC_DEBUGPL(DBG_PCD
,
1258 "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
1259 ctrl
.bRequestType
, ctrl
.bRequest
,
1260 ctrl
.wValue
, ctrl
.wIndex
, ctrl
.wLength
);
1263 switch (ctrl
.bRequestType
& USB_RECIP_MASK
) {
1264 case USB_RECIP_DEVICE
:
1265 *status
= 0x1; /* Self powered */
1266 *status
|= pcd
->remote_wakeup_enable
<< 1;
1269 case USB_RECIP_INTERFACE
:
1273 case USB_RECIP_ENDPOINT
:
1274 ep
= get_ep_by_addr(pcd
, ctrl
.wIndex
);
1275 if (ep
== 0 || ctrl
.wLength
> 2) {
1276 ep0_do_stall(pcd
, -EOPNOTSUPP
);
1279 /** @todo check for EP stall */
1280 *status
= ep
->stopped
;
1283 pcd
->ep0_pending
= 1;
1284 ep0
->dwc_ep
.start_xfer_buff
= (uint8_t *)status
;
1285 ep0
->dwc_ep
.xfer_buff
= (uint8_t *)status
;
1286 ep0
->dwc_ep
.dma_addr
= pcd
->status_buf_dma_handle
;
1287 ep0
->dwc_ep
.xfer_len
= 2;
1288 ep0
->dwc_ep
.xfer_count
= 0;
1289 ep0
->dwc_ep
.total_len
= ep0
->dwc_ep
.xfer_len
;
1290 dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd
), &ep0
->dwc_ep
);
1293 * This function process the SET_FEATURE Setup Commands.
1295 static inline void do_set_feature(dwc_otg_pcd_t
*pcd
)
1297 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
1298 dwc_otg_core_global_regs_t
*global_regs
=
1299 core_if
->core_global_regs
;
1300 struct usb_ctrlrequest ctrl
= pcd
->setup_pkt
->req
;
1301 dwc_otg_pcd_ep_t
*ep
= 0;
1302 int32_t otg_cap_param
= core_if
->core_params
->otg_cap
;
1303 gotgctl_data_t gotgctl
= { .d32
= 0 };
1305 DWC_DEBUGPL(DBG_PCD
, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
1306 ctrl
.bRequestType
, ctrl
.bRequest
,
1307 ctrl
.wValue
, ctrl
.wIndex
, ctrl
.wLength
);
1308 DWC_DEBUGPL(DBG_PCD
,"otg_cap=%d\n", otg_cap_param
);
1311 switch (ctrl
.bRequestType
& USB_RECIP_MASK
) {
1312 case USB_RECIP_DEVICE
:
1313 switch (ctrl
.wValue
) {
1314 case USB_DEVICE_REMOTE_WAKEUP
:
1315 pcd
->remote_wakeup_enable
= 1;
1318 case USB_DEVICE_TEST_MODE
:
1319 /* Setup the Test Mode tasklet to do the Test
1320 * Packet generation after the SETUP Status
1321 * phase has completed. */
1323 /** @todo This has not been tested since the
1324 * tasklet struct was put into the PCD
1326 pcd
->test_mode_tasklet
.next
= 0;
1327 pcd
->test_mode_tasklet
.state
= 0;
1328 atomic_set(&pcd
->test_mode_tasklet
.count
, 0);
1329 pcd
->test_mode_tasklet
.func
= do_test_mode
;
1330 pcd
->test_mode_tasklet
.data
= (unsigned long)pcd
;
1331 pcd
->test_mode
= ctrl
.wIndex
>> 8;
1332 tasklet_schedule(&pcd
->test_mode_tasklet
);
1335 case USB_DEVICE_B_HNP_ENABLE
:
1336 DWC_DEBUGPL(DBG_PCDV
, "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
1338 /* dev may initiate HNP */
1339 if (otg_cap_param
== DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
) {
1340 pcd
->b_hnp_enable
= 1;
1341 dwc_otg_pcd_update_otg(pcd
, 0);
1342 DWC_DEBUGPL(DBG_PCD
, "Request B HNP\n");
1343 /**@todo Is the gotgctl.devhnpen cleared
1344 * by a USB Reset? */
1345 gotgctl
.b
.devhnpen
= 1;
1346 gotgctl
.b
.hnpreq
= 1;
1347 dwc_write_reg32(&global_regs
->gotgctl
, gotgctl
.d32
);
1350 ep0_do_stall(pcd
, -EOPNOTSUPP
);
1354 case USB_DEVICE_A_HNP_SUPPORT
:
1355 /* RH port supports HNP */
1356 DWC_DEBUGPL(DBG_PCDV
, "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
1357 if (otg_cap_param
== DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
) {
1358 pcd
->a_hnp_support
= 1;
1359 dwc_otg_pcd_update_otg(pcd
, 0);
1362 ep0_do_stall(pcd
, -EOPNOTSUPP
);
1366 case USB_DEVICE_A_ALT_HNP_SUPPORT
:
1367 /* other RH port does */
1368 DWC_DEBUGPL(DBG_PCDV
, "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
1369 if (otg_cap_param
== DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
) {
1370 pcd
->a_alt_hnp_support
= 1;
1371 dwc_otg_pcd_update_otg(pcd
, 0);
1374 ep0_do_stall(pcd
, -EOPNOTSUPP
);
1378 do_setup_in_status_phase(pcd
);
1381 case USB_RECIP_INTERFACE
:
1382 do_gadget_setup(pcd
, &ctrl
);
1385 case USB_RECIP_ENDPOINT
:
1386 if (ctrl
.wValue
== USB_ENDPOINT_HALT
) {
1387 ep
= get_ep_by_addr(pcd
, ctrl
.wIndex
);
1389 ep0_do_stall(pcd
, -EOPNOTSUPP
);
1393 dwc_otg_ep_set_stall(core_if
, &ep
->dwc_ep
);
1395 do_setup_in_status_phase(pcd
);
1401 * This function process the CLEAR_FEATURE Setup Commands.
1403 static inline void do_clear_feature(dwc_otg_pcd_t
*pcd
)
1405 struct usb_ctrlrequest ctrl
= pcd
->setup_pkt
->req
;
1406 dwc_otg_pcd_ep_t
*ep
= 0;
1408 DWC_DEBUGPL(DBG_PCD
,
1409 "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
1410 ctrl
.bRequestType
, ctrl
.bRequest
,
1411 ctrl
.wValue
, ctrl
.wIndex
, ctrl
.wLength
);
1413 switch (ctrl
.bRequestType
& USB_RECIP_MASK
) {
1414 case USB_RECIP_DEVICE
:
1415 switch (ctrl
.wValue
) {
1416 case USB_DEVICE_REMOTE_WAKEUP
:
1417 pcd
->remote_wakeup_enable
= 0;
1420 case USB_DEVICE_TEST_MODE
:
1421 /** @todo Add CLEAR_FEATURE for TEST modes. */
1424 do_setup_in_status_phase(pcd
);
1427 case USB_RECIP_ENDPOINT
:
1428 ep
= get_ep_by_addr(pcd
, ctrl
.wIndex
);
1430 ep0_do_stall(pcd
, -EOPNOTSUPP
);
1434 pcd_clear_halt(pcd
, ep
);
1441 * This function process the SET_ADDRESS Setup Commands.
1443 static inline void do_set_address(dwc_otg_pcd_t
*pcd
)
1445 dwc_otg_dev_if_t
*dev_if
= GET_CORE_IF(pcd
)->dev_if
;
1446 struct usb_ctrlrequest ctrl
= pcd
->setup_pkt
->req
;
1448 if (ctrl
.bRequestType
== USB_RECIP_DEVICE
) {
1449 dcfg_data_t dcfg
= {.d32
=0};
1452 // DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
1454 dcfg
.b
.devaddr
= ctrl
.wValue
;
1455 dwc_modify_reg32(&dev_if
->dev_global_regs
->dcfg
, 0, dcfg
.d32
);
1456 do_setup_in_status_phase(pcd
);
1461 * This function processes SETUP commands. In Linux, the USB Command
1462 * processing is done in two places - the first being the PCD and the
1463 * second in the Gadget Driver (for example, the File-Backed Storage
1467 * <tr><td>Command </td><td>Driver </td><td>Description</td></tr>
1469 * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
1470 * defined in chapter 9 of the USB 2.0 Specification chapter 9
1473 * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
1474 * requests are the ENDPOINT_HALT feature is procesed, all others the
1475 * interface requests are ignored.</td></tr>
1477 * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
1478 * requests are processed by the PCD. Interface requests are passed
1479 * to the Gadget Driver.</td></tr>
1481 * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
1482 * with device address received </td></tr>
1484 * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
1485 * requested descriptor</td></tr>
1487 * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
1488 * not implemented by any of the existing Gadget Drivers.</td></tr>
1490 * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
1491 * all EPs and enable EPs for new configuration.</td></tr>
1493 * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
1494 * the current configuration</td></tr>
1496 * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
1497 * EPs and enable EPs for new configuration.</td></tr>
1499 * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
1500 * current interface.</td></tr>
1502 * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
1503 * message.</td></tr>
1506 * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
1507 * processed by pcd_setup. Calling the Function Driver's setup function from
1508 * pcd_setup processes the gadget SETUP commands.
1510 static inline void pcd_setup(dwc_otg_pcd_t
*pcd
)
1512 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
1513 dwc_otg_dev_if_t
*dev_if
= core_if
->dev_if
;
1514 struct usb_ctrlrequest ctrl
= pcd
->setup_pkt
->req
;
1515 dwc_otg_pcd_ep_t
*ep0
= &pcd
->ep0
;
1517 deptsiz0_data_t doeptsize0
= { .d32
= 0};
1520 DWC_DEBUGPL(DBG_PCD
, "SETUP %02x.%02x v%04x i%04x l%04x\n",
1521 ctrl
.bRequestType
, ctrl
.bRequest
,
1522 ctrl
.wValue
, ctrl
.wIndex
, ctrl
.wLength
);
1525 doeptsize0
.d32
= dwc_read_reg32(&dev_if
->out_ep_regs
[0]->doeptsiz
);
1527 /** @todo handle > 1 setup packet , assert error for now */
1529 if (core_if
->dma_enable
&& core_if
->dma_desc_enable
== 0 && (doeptsize0
.b
.supcnt
< 2)) {
1530 DWC_ERROR ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n");
1533 /* Clean up the request queue */
1534 dwc_otg_request_nuke(ep0
);
1537 if (ctrl
.bRequestType
& USB_DIR_IN
) {
1538 ep0
->dwc_ep
.is_in
= 1;
1539 pcd
->ep0state
= EP0_IN_DATA_PHASE
;
1542 ep0
->dwc_ep
.is_in
= 0;
1543 pcd
->ep0state
= EP0_OUT_DATA_PHASE
;
1546 if(ctrl
.wLength
== 0) {
1547 ep0
->dwc_ep
.is_in
= 1;
1548 pcd
->ep0state
= EP0_IN_STATUS_PHASE
;
1551 if ((ctrl
.bRequestType
& USB_TYPE_MASK
) != USB_TYPE_STANDARD
) {
1552 /* handle non-standard (class/vendor) requests in the gadget driver */
1553 do_gadget_setup(pcd
, &ctrl
);
1557 /** @todo NGS: Handle bad setup packet? */
1559 ///////////////////////////////////////////
1560 //// --- Standard Request handling --- ////
1562 switch (ctrl
.bRequest
) {
1563 case USB_REQ_GET_STATUS
:
1567 case USB_REQ_CLEAR_FEATURE
:
1568 do_clear_feature(pcd
);
1571 case USB_REQ_SET_FEATURE
:
1572 do_set_feature(pcd
);
1575 case USB_REQ_SET_ADDRESS
:
1576 do_set_address(pcd
);
1579 case USB_REQ_SET_INTERFACE
:
1580 case USB_REQ_SET_CONFIGURATION
:
1581 // _pcd->request_config = 1; /* Configuration changed */
1582 do_gadget_setup(pcd
, &ctrl
);
1585 case USB_REQ_SYNCH_FRAME
:
1586 do_gadget_setup(pcd
, &ctrl
);
1590 /* Call the Gadget Driver's setup functions */
1591 do_gadget_setup(pcd
, &ctrl
);
1597 * This function completes the ep0 control transfer.
1599 static int32_t ep0_complete_request(dwc_otg_pcd_ep_t
*ep
)
1601 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(ep
->pcd
);
1602 dwc_otg_dev_if_t
*dev_if
= core_if
->dev_if
;
1603 dwc_otg_dev_in_ep_regs_t
*in_ep_regs
=
1604 dev_if
->in_ep_regs
[ep
->dwc_ep
.num
];
1606 dwc_otg_dev_out_ep_regs_t
*out_ep_regs
=
1607 dev_if
->out_ep_regs
[ep
->dwc_ep
.num
];
1609 deptsiz0_data_t deptsiz
;
1610 desc_sts_data_t desc_sts
;
1611 dwc_otg_pcd_request_t
*req
;
1613 dwc_otg_pcd_t
*pcd
= ep
->pcd
;
1615 //DWC_DEBUGPL(DBG_PCDV, "%s() %s\n", __func__, _ep->ep.name);
1617 if (pcd
->ep0_pending
&& list_empty(&ep
->queue
)) {
1618 if (ep
->dwc_ep
.is_in
) {
1620 DWC_DEBUGPL(DBG_PCDV
, "Do setup OUT status phase\n");
1622 do_setup_out_status_phase(pcd
);
1626 DWC_DEBUGPL(DBG_PCDV
, "Do setup IN status phase\n");
1628 do_setup_in_status_phase(pcd
);
1630 pcd
->ep0_pending
= 0;
1634 if (list_empty(&ep
->queue
)) {
1637 req
= list_entry(ep
->queue
.next
, dwc_otg_pcd_request_t
, queue
);
1640 if (pcd
->ep0state
== EP0_OUT_STATUS_PHASE
|| pcd
->ep0state
== EP0_IN_STATUS_PHASE
) {
1643 else if (ep
->dwc_ep
.is_in
) {
1644 deptsiz
.d32
= dwc_read_reg32(&in_ep_regs
->dieptsiz
);
1645 if(core_if
->dma_desc_enable
!= 0)
1646 desc_sts
.d32
= readl(dev_if
->in_desc_addr
);
1648 DWC_DEBUGPL(DBG_PCDV
, "%s len=%d xfersize=%d pktcnt=%d\n",
1649 ep
->ep
.name
, ep
->dwc_ep
.xfer_len
,
1650 deptsiz
.b
.xfersize
, deptsiz
.b
.pktcnt
);
1653 if (((core_if
->dma_desc_enable
== 0) && (deptsiz
.b
.xfersize
== 0)) ||
1654 ((core_if
->dma_desc_enable
!= 0) && (desc_sts
.b
.bytes
== 0))) {
1655 req
->req
.actual
= ep
->dwc_ep
.xfer_count
;
1656 /* Is a Zero Len Packet needed? */
1657 if (req
->req
.zero
) {
1659 DWC_DEBUGPL(DBG_PCD
, "Setup Rx ZLP\n");
1663 do_setup_out_status_phase(pcd
);
1669 deptsiz
.d32
= dwc_read_reg32(&out_ep_regs
->doeptsiz
);
1670 DWC_DEBUGPL(DBG_PCDV
, "%s len=%d xsize=%d pktcnt=%d\n",
1671 ep
->ep
.name
, ep
->dwc_ep
.xfer_len
,
1675 req
->req
.actual
= ep
->dwc_ep
.xfer_count
;
1676 /* Is a Zero Len Packet needed? */
1677 if (req
->req
.zero
) {
1679 DWC_DEBUGPL(DBG_PCDV
, "Setup Tx ZLP\n");
1683 if(core_if
->dma_desc_enable
== 0)
1684 do_setup_in_status_phase(pcd
);
1687 /* Complete the request */
1689 dwc_otg_request_done(ep
, req
, 0);
1690 ep
->dwc_ep
.start_xfer_buff
= 0;
1691 ep
->dwc_ep
.xfer_buff
= 0;
1692 ep
->dwc_ep
.xfer_len
= 0;
1699 * This function completes the request for the EP. If there are
1700 * additional requests for the EP in the queue they will be started.
1702 static void complete_ep(dwc_otg_pcd_ep_t
*ep
)
1704 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(ep
->pcd
);
1705 dwc_otg_dev_if_t
*dev_if
= core_if
->dev_if
;
1706 dwc_otg_dev_in_ep_regs_t
*in_ep_regs
=
1707 dev_if
->in_ep_regs
[ep
->dwc_ep
.num
];
1708 deptsiz_data_t deptsiz
;
1709 desc_sts_data_t desc_sts
;
1710 dwc_otg_pcd_request_t
*req
= 0;
1711 dwc_otg_dma_desc_t
* dma_desc
;
1712 uint32_t byte_count
= 0;
1716 DWC_DEBUGPL(DBG_PCDV
,"%s() %s-%s\n", __func__
, ep
->ep
.name
,
1717 (ep
->dwc_ep
.is_in
?"IN":"OUT"));
1719 /* Get any pending requests */
1720 if (!list_empty(&ep
->queue
)) {
1721 req
= list_entry(ep
->queue
.next
, dwc_otg_pcd_request_t
,
1724 printk("complete_ep 0x%p, req = NULL!\n", ep
);
1729 printk("complete_ep 0x%p, ep->queue empty!\n", ep
);
1732 DWC_DEBUGPL(DBG_PCD
, "Requests %d\n", ep
->pcd
->request_pending
);
1734 if (ep
->dwc_ep
.is_in
) {
1735 deptsiz
.d32
= dwc_read_reg32(&in_ep_regs
->dieptsiz
);
1737 if (core_if
->dma_enable
) {
1738 if(core_if
->dma_desc_enable
== 0) {
1739 if (deptsiz
.b
.xfersize
== 0 && deptsiz
.b
.pktcnt
== 0) {
1740 byte_count
= ep
->dwc_ep
.xfer_len
- ep
->dwc_ep
.xfer_count
;
1742 ep
->dwc_ep
.xfer_buff
+= byte_count
;
1743 ep
->dwc_ep
.dma_addr
+= byte_count
;
1744 ep
->dwc_ep
.xfer_count
+= byte_count
;
1746 DWC_DEBUGPL(DBG_PCDV
, "%s len=%d xfersize=%d pktcnt=%d\n",
1747 ep
->ep
.name
, ep
->dwc_ep
.xfer_len
,
1748 deptsiz
.b
.xfersize
, deptsiz
.b
.pktcnt
);
1751 if(ep
->dwc_ep
.xfer_len
< ep
->dwc_ep
.total_len
) {
1752 dwc_otg_ep_start_transfer(core_if
, &ep
->dwc_ep
);
1753 } else if(ep
->dwc_ep
.sent_zlp
) {
1755 * This fragment of code should initiate 0
1756 * length trasfer in case if it is queued
1757 * a trasfer with size divisible to EPs max
1758 * packet size and with usb_request zero field
1759 * is set, which means that after data is transfered,
1760 * it is also should be transfered
1761 * a 0 length packet at the end. For Slave and
1762 * Buffer DMA modes in this case SW has
1763 * to initiate 2 transfers one with transfer size,
1764 * and the second with 0 size. For Desriptor
1765 * DMA mode SW is able to initiate a transfer,
1766 * which will handle all the packets including
1769 ep
->dwc_ep
.sent_zlp
= 0;
1770 dwc_otg_ep_start_zl_transfer(core_if
, &ep
->dwc_ep
);
1775 DWC_WARN("Incomplete transfer (%s-%s [siz=%d pkt=%d])\n",
1776 ep
->ep
.name
, (ep
->dwc_ep
.is_in
?"IN":"OUT"),
1777 deptsiz
.b
.xfersize
, deptsiz
.b
.pktcnt
);
1780 dma_desc
= ep
->dwc_ep
.desc_addr
;
1782 ep
->dwc_ep
.sent_zlp
= 0;
1784 for(i
= 0; i
< ep
->dwc_ep
.desc_cnt
; ++i
) {
1785 desc_sts
.d32
= readl(dma_desc
);
1786 byte_count
+= desc_sts
.b
.bytes
;
1790 if(byte_count
== 0) {
1791 ep
->dwc_ep
.xfer_count
= ep
->dwc_ep
.total_len
;
1794 DWC_WARN("Incomplete transfer\n");
1798 if (deptsiz
.b
.xfersize
== 0 && deptsiz
.b
.pktcnt
== 0) {
1799 /* Check if the whole transfer was completed,
1800 * if no, setup transfer for next portion of data
1802 DWC_DEBUGPL(DBG_PCDV
, "%s len=%d xfersize=%d pktcnt=%d\n",
1803 ep
->ep
.name
, ep
->dwc_ep
.xfer_len
,
1804 deptsiz
.b
.xfersize
, deptsiz
.b
.pktcnt
);
1805 if(ep
->dwc_ep
.xfer_len
< ep
->dwc_ep
.total_len
) {
1806 dwc_otg_ep_start_transfer(core_if
, &ep
->dwc_ep
);
1807 } else if(ep
->dwc_ep
.sent_zlp
) {
1809 * This fragment of code should initiate 0
1810 * length trasfer in case if it is queued
1811 * a trasfer with size divisible to EPs max
1812 * packet size and with usb_request zero field
1813 * is set, which means that after data is transfered,
1814 * it is also should be transfered
1815 * a 0 length packet at the end. For Slave and
1816 * Buffer DMA modes in this case SW has
1817 * to initiate 2 transfers one with transfer size,
1818 * and the second with 0 size. For Desriptor
1819 * DMA mode SW is able to initiate a transfer,
1820 * which will handle all the packets including
1823 ep
->dwc_ep
.sent_zlp
= 0;
1824 dwc_otg_ep_start_zl_transfer(core_if
, &ep
->dwc_ep
);
1830 DWC_WARN("Incomplete transfer (%s-%s [siz=%d pkt=%d])\n",
1831 ep
->ep
.name
, (ep
->dwc_ep
.is_in
?"IN":"OUT"),
1832 deptsiz
.b
.xfersize
, deptsiz
.b
.pktcnt
);
1836 dwc_otg_dev_out_ep_regs_t
*out_ep_regs
=
1837 dev_if
->out_ep_regs
[ep
->dwc_ep
.num
];
1839 if(core_if
->dma_enable
) {
1840 if(core_if
->dma_desc_enable
) {
1841 dma_desc
= ep
->dwc_ep
.desc_addr
;
1843 ep
->dwc_ep
.sent_zlp
= 0;
1844 for(i
= 0; i
< ep
->dwc_ep
.desc_cnt
; ++i
) {
1845 desc_sts
.d32
= readl(dma_desc
);
1846 byte_count
+= desc_sts
.b
.bytes
;
1850 ep
->dwc_ep
.xfer_count
= ep
->dwc_ep
.total_len
1851 - byte_count
+ ((4 - (ep
->dwc_ep
.total_len
& 0x3)) & 0x3);
1855 deptsiz
.d32
= dwc_read_reg32(&out_ep_regs
->doeptsiz
);
1857 byte_count
= (ep
->dwc_ep
.xfer_len
-
1858 ep
->dwc_ep
.xfer_count
- deptsiz
.b
.xfersize
);
1859 ep
->dwc_ep
.xfer_buff
+= byte_count
;
1860 ep
->dwc_ep
.dma_addr
+= byte_count
;
1861 ep
->dwc_ep
.xfer_count
+= byte_count
;
1863 /* Check if the whole transfer was completed,
1864 * if no, setup transfer for next portion of data
1866 if(ep
->dwc_ep
.xfer_len
< ep
->dwc_ep
.total_len
) {
1867 dwc_otg_ep_start_transfer(core_if
, &ep
->dwc_ep
);
1869 else if(ep
->dwc_ep
.sent_zlp
) {
1871 * This fragment of code should initiate 0
1872 * length trasfer in case if it is queued
1873 * a trasfer with size divisible to EPs max
1874 * packet size and with usb_request zero field
1875 * is set, which means that after data is transfered,
1876 * it is also should be transfered
1877 * a 0 length packet at the end. For Slave and
1878 * Buffer DMA modes in this case SW has
1879 * to initiate 2 transfers one with transfer size,
1880 * and the second with 0 size. For Desriptor
1881 * DMA mode SW is able to initiate a transfer,
1882 * which will handle all the packets including
1885 ep
->dwc_ep
.sent_zlp
= 0;
1886 dwc_otg_ep_start_zl_transfer(core_if
, &ep
->dwc_ep
);
1892 /* Check if the whole transfer was completed,
1893 * if no, setup transfer for next portion of data
1895 if(ep
->dwc_ep
.xfer_len
< ep
->dwc_ep
.total_len
) {
1896 dwc_otg_ep_start_transfer(core_if
, &ep
->dwc_ep
);
1898 else if(ep
->dwc_ep
.sent_zlp
) {
1900 * This fragment of code should initiate 0
1901 * length trasfer in case if it is queued
1902 * a trasfer with size divisible to EPs max
1903 * packet size and with usb_request zero field
1904 * is set, which means that after data is transfered,
1905 * it is also should be transfered
1906 * a 0 length packet at the end. For Slave and
1907 * Buffer DMA modes in this case SW has
1908 * to initiate 2 transfers one with transfer size,
1909 * and the second with 0 size. For Desriptor
1910 * DMA mode SW is able to initiate a transfer,
1911 * which will handle all the packets including
1914 ep
->dwc_ep
.sent_zlp
= 0;
1915 dwc_otg_ep_start_zl_transfer(core_if
, &ep
->dwc_ep
);
1923 DWC_DEBUGPL(DBG_PCDV
, "addr %p, %s len=%d cnt=%d xsize=%d pktcnt=%d\n",
1924 &out_ep_regs
->doeptsiz
, ep
->ep
.name
, ep
->dwc_ep
.xfer_len
,
1925 ep
->dwc_ep
.xfer_count
,
1931 /* Complete the request */
1933 req
->req
.actual
= ep
->dwc_ep
.xfer_count
;
1935 dwc_otg_request_done(ep
, req
, 0);
1937 ep
->dwc_ep
.start_xfer_buff
= 0;
1938 ep
->dwc_ep
.xfer_buff
= 0;
1939 ep
->dwc_ep
.xfer_len
= 0;
1941 /* If there is a request in the queue start it.*/
1942 start_next_request(ep
);
1950 * This function BNA interrupt for Isochronous EPs
1953 static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t
*ep
)
1955 dwc_ep_t
*dwc_ep
= &ep
->dwc_ep
;
1956 volatile uint32_t *addr
;
1957 depctl_data_t depctl
= {.d32
= 0};
1958 dwc_otg_pcd_t
*pcd
= ep
->pcd
;
1959 dwc_otg_dma_desc_t
*dma_desc
;
1962 dma_desc
= dwc_ep
->iso_desc_addr
+ dwc_ep
->desc_cnt
* (dwc_ep
->proc_buf_num
);
1965 desc_sts_data_t sts
= {.d32
= 0};
1966 for(i
= 0;i
< dwc_ep
->desc_cnt
; ++i
, ++dma_desc
)
1968 sts
.d32
= readl(&dma_desc
->status
);
1969 sts
.b_iso_in
.bs
= BS_HOST_READY
;
1970 writel(sts
.d32
,&dma_desc
->status
);
1974 desc_sts_data_t sts
= {.d32
= 0};
1975 for(i
= 0;i
< dwc_ep
->desc_cnt
; ++i
, ++dma_desc
)
1977 sts
.d32
= readl(&dma_desc
->status
);
1978 sts
.b_iso_out
.bs
= BS_HOST_READY
;
1979 writel(sts
.d32
,&dma_desc
->status
);
1983 if(dwc_ep
->is_in
== 0){
1984 addr
= &GET_CORE_IF(pcd
)->dev_if
->out_ep_regs
[dwc_ep
->num
]->doepctl
;
1987 addr
= &GET_CORE_IF(pcd
)->dev_if
->in_ep_regs
[dwc_ep
->num
]->diepctl
;
1990 dwc_modify_reg32(addr
,depctl
.d32
,depctl
.d32
);
1994 * This function sets latest iso packet information(non-PTI mode)
1996 * @param core_if Programming view of DWC_otg controller.
1997 * @param ep The EP to start the transfer on.
2000 void set_current_pkt_info(dwc_otg_core_if_t
*core_if
, dwc_ep_t
*ep
)
2002 deptsiz_data_t deptsiz
= { .d32
= 0 };
2003 dma_addr_t dma_addr
;
2006 if(ep
->proc_buf_num
)
2007 dma_addr
= ep
->dma_addr1
;
2009 dma_addr
= ep
->dma_addr0
;
2013 deptsiz
.d32
= dwc_read_reg32(&core_if
->dev_if
->in_ep_regs
[ep
->num
]->dieptsiz
);
2014 offset
= ep
->data_per_frame
;
2016 deptsiz
.d32
= dwc_read_reg32(&core_if
->dev_if
->out_ep_regs
[ep
->num
]->doeptsiz
);
2017 offset
= ep
->data_per_frame
+ (0x4 & (0x4 - (ep
->data_per_frame
& 0x3)));
2020 if(!deptsiz
.b
.xfersize
) {
2021 ep
->pkt_info
[ep
->cur_pkt
].length
= ep
->data_per_frame
;
2022 ep
->pkt_info
[ep
->cur_pkt
].offset
= ep
->cur_pkt_dma_addr
- dma_addr
;
2023 ep
->pkt_info
[ep
->cur_pkt
].status
= 0;
2025 ep
->pkt_info
[ep
->cur_pkt
].length
= ep
->data_per_frame
;
2026 ep
->pkt_info
[ep
->cur_pkt
].offset
= ep
->cur_pkt_dma_addr
- dma_addr
;
2027 ep
->pkt_info
[ep
->cur_pkt
].status
= -ENODATA
;
2029 ep
->cur_pkt_addr
+= offset
;
2030 ep
->cur_pkt_dma_addr
+= offset
;
2035 * This function sets latest iso packet information(DDMA mode)
2037 * @param core_if Programming view of DWC_otg controller.
2038 * @param dwc_ep The EP to start the transfer on.
2041 static void set_ddma_iso_pkts_info(dwc_otg_core_if_t
*core_if
, dwc_ep_t
*dwc_ep
)
2043 dwc_otg_dma_desc_t
* dma_desc
;
2044 desc_sts_data_t sts
= {.d32
= 0};
2045 iso_pkt_info_t
*iso_packet
;
2046 uint32_t data_per_desc
;
2050 iso_packet
= dwc_ep
->pkt_info
;
2052 /** Reinit closed DMA Descriptors*/
2054 if(dwc_ep
->is_in
== 0) {
2055 dma_desc
= dwc_ep
->iso_desc_addr
+ dwc_ep
->desc_cnt
* dwc_ep
->proc_buf_num
;
2058 for(i
= 0; i
< dwc_ep
->desc_cnt
- dwc_ep
->pkt_per_frm
; i
+= dwc_ep
->pkt_per_frm
)
2060 for(j
= 0; j
< dwc_ep
->pkt_per_frm
; ++j
)
2062 data_per_desc
= ((j
+ 1) * dwc_ep
->maxpacket
> dwc_ep
->data_per_frame
) ?
2063 dwc_ep
->data_per_frame
- j
* dwc_ep
->maxpacket
: dwc_ep
->maxpacket
;
2064 data_per_desc
+= (data_per_desc
% 4) ? (4 - data_per_desc
% 4):0;
2066 sts
.d32
= readl(&dma_desc
->status
);
2068 /* Write status in iso_packet_decsriptor */
2069 iso_packet
->status
= sts
.b_iso_out
.rxsts
+ (sts
.b_iso_out
.bs
^BS_DMA_DONE
);
2070 if(iso_packet
->status
) {
2071 iso_packet
->status
= -ENODATA
;
2074 /* Received data length */
2075 if(!sts
.b_iso_out
.rxbytes
){
2076 iso_packet
->length
= data_per_desc
- sts
.b_iso_out
.rxbytes
;
2078 iso_packet
->length
= data_per_desc
- sts
.b_iso_out
.rxbytes
+
2079 (4 - dwc_ep
->data_per_frame
% 4);
2082 iso_packet
->offset
= offset
;
2084 offset
+= data_per_desc
;
2090 for(j
= 0; j
< dwc_ep
->pkt_per_frm
- 1; ++j
)
2092 data_per_desc
= ((j
+ 1) * dwc_ep
->maxpacket
> dwc_ep
->data_per_frame
) ?
2093 dwc_ep
->data_per_frame
- j
* dwc_ep
->maxpacket
: dwc_ep
->maxpacket
;
2094 data_per_desc
+= (data_per_desc
% 4) ? (4 - data_per_desc
% 4):0;
2096 sts
.d32
= readl(&dma_desc
->status
);
2098 /* Write status in iso_packet_decsriptor */
2099 iso_packet
->status
= sts
.b_iso_out
.rxsts
+ (sts
.b_iso_out
.bs
^BS_DMA_DONE
);
2100 if(iso_packet
->status
) {
2101 iso_packet
->status
= -ENODATA
;
2104 /* Received data length */
2105 iso_packet
->length
= dwc_ep
->data_per_frame
- sts
.b_iso_out
.rxbytes
;
2107 iso_packet
->offset
= offset
;
2109 offset
+= data_per_desc
;
2114 sts
.d32
= readl(&dma_desc
->status
);
2116 /* Write status in iso_packet_decsriptor */
2117 iso_packet
->status
= sts
.b_iso_out
.rxsts
+ (sts
.b_iso_out
.bs
^BS_DMA_DONE
);
2118 if(iso_packet
->status
) {
2119 iso_packet
->status
= -ENODATA
;
2121 /* Received data length */
2122 if(!sts
.b_iso_out
.rxbytes
){
2123 iso_packet
->length
= dwc_ep
->data_per_frame
- sts
.b_iso_out
.rxbytes
;
2125 iso_packet
->length
= dwc_ep
->data_per_frame
- sts
.b_iso_out
.rxbytes
+
2126 (4 - dwc_ep
->data_per_frame
% 4);
2129 iso_packet
->offset
= offset
;
2131 else /** ISO IN EP */
2133 dma_desc
= dwc_ep
->iso_desc_addr
+ dwc_ep
->desc_cnt
* dwc_ep
->proc_buf_num
;
2135 for(i
= 0; i
< dwc_ep
->desc_cnt
- 1; i
++)
2137 sts
.d32
= readl(&dma_desc
->status
);
2139 /* Write status in iso packet descriptor */
2140 iso_packet
->status
= sts
.b_iso_in
.txsts
+ (sts
.b_iso_in
.bs
^BS_DMA_DONE
);
2141 if(iso_packet
->status
!= 0) {
2142 iso_packet
->status
= -ENODATA
;
2145 /* Bytes has been transfered */
2146 iso_packet
->length
= dwc_ep
->data_per_frame
- sts
.b_iso_in
.txbytes
;
2152 sts
.d32
= readl(&dma_desc
->status
);
2153 while(sts
.b_iso_in
.bs
== BS_DMA_BUSY
) {
2154 sts
.d32
= readl(&dma_desc
->status
);
2157 /* Write status in iso packet descriptor ??? do be done with ERROR codes*/
2158 iso_packet
->status
= sts
.b_iso_in
.txsts
+ (sts
.b_iso_in
.bs
^BS_DMA_DONE
);
2159 if(iso_packet
->status
!= 0) {
2160 iso_packet
->status
= -ENODATA
;
2163 /* Bytes has been transfered */
2164 iso_packet
->length
= dwc_ep
->data_per_frame
- sts
.b_iso_in
.txbytes
;
2169 * This function reinitialize DMA Descriptors for Isochronous transfer
2171 * @param core_if Programming view of DWC_otg controller.
2172 * @param dwc_ep The EP to start the transfer on.
2175 static void reinit_ddma_iso_xfer(dwc_otg_core_if_t
*core_if
, dwc_ep_t
*dwc_ep
)
2178 dwc_otg_dma_desc_t
* dma_desc
;
2180 volatile uint32_t *addr
;
2181 desc_sts_data_t sts
= { .d32
=0 };
2182 uint32_t data_per_desc
;
2184 if(dwc_ep
->is_in
== 0) {
2185 addr
= &core_if
->dev_if
->out_ep_regs
[dwc_ep
->num
]->doepctl
;
2188 addr
= &core_if
->dev_if
->in_ep_regs
[dwc_ep
->num
]->diepctl
;
2192 if(dwc_ep
->proc_buf_num
== 0) {
2193 /** Buffer 0 descriptors setup */
2194 dma_ad
= dwc_ep
->dma_addr0
;
2197 /** Buffer 1 descriptors setup */
2198 dma_ad
= dwc_ep
->dma_addr1
;
2202 /** Reinit closed DMA Descriptors*/
2204 if(dwc_ep
->is_in
== 0) {
2205 dma_desc
= dwc_ep
->iso_desc_addr
+ dwc_ep
->desc_cnt
* dwc_ep
->proc_buf_num
;
2207 sts
.b_iso_out
.bs
= BS_HOST_READY
;
2208 sts
.b_iso_out
.rxsts
= 0;
2209 sts
.b_iso_out
.l
= 0;
2210 sts
.b_iso_out
.sp
= 0;
2211 sts
.b_iso_out
.ioc
= 0;
2212 sts
.b_iso_out
.pid
= 0;
2213 sts
.b_iso_out
.framenum
= 0;
2215 for(i
= 0; i
< dwc_ep
->desc_cnt
- dwc_ep
->pkt_per_frm
; i
+= dwc_ep
->pkt_per_frm
)
2217 for(j
= 0; j
< dwc_ep
->pkt_per_frm
; ++j
)
2219 data_per_desc
= ((j
+ 1) * dwc_ep
->maxpacket
> dwc_ep
->data_per_frame
) ?
2220 dwc_ep
->data_per_frame
- j
* dwc_ep
->maxpacket
: dwc_ep
->maxpacket
;
2221 data_per_desc
+= (data_per_desc
% 4) ? (4 - data_per_desc
% 4):0;
2222 sts
.b_iso_out
.rxbytes
= data_per_desc
;
2223 writel((uint32_t)dma_ad
, &dma_desc
->buf
);
2224 writel(sts
.d32
, &dma_desc
->status
);
2226 (uint32_t)dma_ad
+= data_per_desc
;
2231 for(j
= 0; j
< dwc_ep
->pkt_per_frm
- 1; ++j
)
2234 data_per_desc
= ((j
+ 1) * dwc_ep
->maxpacket
> dwc_ep
->data_per_frame
) ?
2235 dwc_ep
->data_per_frame
- j
* dwc_ep
->maxpacket
: dwc_ep
->maxpacket
;
2236 data_per_desc
+= (data_per_desc
% 4) ? (4 - data_per_desc
% 4):0;
2237 sts
.b_iso_out
.rxbytes
= data_per_desc
;
2239 writel((uint32_t)dma_ad
, &dma_desc
->buf
);
2240 writel(sts
.d32
, &dma_desc
->status
);
2243 (uint32_t)dma_ad
+= data_per_desc
;
2246 sts
.b_iso_out
.ioc
= 1;
2247 sts
.b_iso_out
.l
= dwc_ep
->proc_buf_num
;
2249 data_per_desc
= ((j
+ 1) * dwc_ep
->maxpacket
> dwc_ep
->data_per_frame
) ?
2250 dwc_ep
->data_per_frame
- j
* dwc_ep
->maxpacket
: dwc_ep
->maxpacket
;
2251 data_per_desc
+= (data_per_desc
% 4) ? (4 - data_per_desc
% 4):0;
2252 sts
.b_iso_out
.rxbytes
= data_per_desc
;
2254 writel((uint32_t)dma_ad
, &dma_desc
->buf
);
2255 writel(sts
.d32
, &dma_desc
->status
);
2257 else /** ISO IN EP */
2259 dma_desc
= dwc_ep
->iso_desc_addr
+ dwc_ep
->desc_cnt
* dwc_ep
->proc_buf_num
;
2261 sts
.b_iso_in
.bs
= BS_HOST_READY
;
2262 sts
.b_iso_in
.txsts
= 0;
2263 sts
.b_iso_in
.sp
= 0;
2264 sts
.b_iso_in
.ioc
= 0;
2265 sts
.b_iso_in
.pid
= dwc_ep
->pkt_per_frm
;
2266 sts
.b_iso_in
.framenum
= dwc_ep
->next_frame
;
2267 sts
.b_iso_in
.txbytes
= dwc_ep
->data_per_frame
;
2270 for(i
= 0; i
< dwc_ep
->desc_cnt
- 1; i
++)
2272 writel((uint32_t)dma_ad
, &dma_desc
->buf
);
2273 writel(sts
.d32
, &dma_desc
->status
);
2275 sts
.b_iso_in
.framenum
+= dwc_ep
->bInterval
;
2276 (uint32_t)dma_ad
+= dwc_ep
->data_per_frame
;
2280 sts
.b_iso_in
.ioc
= 1;
2281 sts
.b_iso_in
.l
= dwc_ep
->proc_buf_num
;
2283 writel((uint32_t)dma_ad
, &dma_desc
->buf
);
2284 writel(sts
.d32
, &dma_desc
->status
);
2286 dwc_ep
->next_frame
= sts
.b_iso_in
.framenum
+ dwc_ep
->bInterval
* 1;
2288 dwc_ep
->proc_buf_num
= (dwc_ep
->proc_buf_num
^ 1) & 0x1;
2293 * This function is to handle Iso EP transfer complete interrupt
2294 * in case Iso out packet was dropped
2296 * @param core_if Programming view of DWC_otg controller.
2297 * @param dwc_ep The EP for wihich transfer complete was asserted
2300 static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t
*core_if
, dwc_ep_t
*dwc_ep
)
2304 uint32_t drp_pkt_cnt
;
2305 deptsiz_data_t deptsiz
= { .d32
= 0 };
2306 depctl_data_t depctl
= { .d32
= 0 };
2309 deptsiz
.d32
= dwc_read_reg32(&core_if
->dev_if
->out_ep_regs
[dwc_ep
->num
]->doeptsiz
);
2311 drp_pkt
= dwc_ep
->pkt_cnt
- deptsiz
.b
.pktcnt
;
2312 drp_pkt_cnt
= dwc_ep
->pkt_per_frm
- (drp_pkt
% dwc_ep
->pkt_per_frm
);
2314 /* Setting dropped packets status */
2315 for(i
= 0; i
< drp_pkt_cnt
; ++i
) {
2316 dwc_ep
->pkt_info
[drp_pkt
].status
= -ENODATA
;
2322 if(deptsiz
.b
.pktcnt
> 0) {
2323 deptsiz
.b
.xfersize
= dwc_ep
->xfer_len
- (dwc_ep
->pkt_cnt
- deptsiz
.b
.pktcnt
) * dwc_ep
->maxpacket
;
2325 deptsiz
.b
.xfersize
= 0;
2326 deptsiz
.b
.pktcnt
= 0;
2329 dwc_write_reg32(&core_if
->dev_if
->out_ep_regs
[dwc_ep
->num
]->doeptsiz
, deptsiz
.d32
);
2331 if(deptsiz
.b
.pktcnt
> 0) {
2332 if(dwc_ep
->proc_buf_num
) {
2333 dma_addr
= dwc_ep
->dma_addr1
+ dwc_ep
->xfer_len
- deptsiz
.b
.xfersize
;
2335 dma_addr
= dwc_ep
->dma_addr0
+ dwc_ep
->xfer_len
- deptsiz
.b
.xfersize
;;
2338 dwc_write_reg32(&core_if
->dev_if
->out_ep_regs
[dwc_ep
->num
]->doepdma
, dma_addr
);
2340 /** Re-enable endpoint, clear nak */
2345 dwc_modify_reg32(&core_if
->dev_if
->out_ep_regs
[dwc_ep
->num
]->doepctl
,
2346 depctl
.d32
,depctl
.d32
);
2354 * This function sets iso packets information(PTI mode)
2356 * @param core_if Programming view of DWC_otg controller.
2357 * @param ep The EP to start the transfer on.
2360 static uint32_t set_iso_pkts_info(dwc_otg_core_if_t
*core_if
, dwc_ep_t
*ep
)
2364 iso_pkt_info_t
*packet_info
= ep
->pkt_info
;
2366 uint32_t frame_data
;
2367 deptsiz_data_t deptsiz
;
2369 if(ep
->proc_buf_num
== 0) {
2370 /** Buffer 0 descriptors setup */
2371 dma_ad
= ep
->dma_addr0
;
2374 /** Buffer 1 descriptors setup */
2375 dma_ad
= ep
->dma_addr1
;
2380 deptsiz
.d32
= dwc_read_reg32(&core_if
->dev_if
->in_ep_regs
[ep
->num
]->dieptsiz
);
2382 deptsiz
.d32
= dwc_read_reg32(&core_if
->dev_if
->out_ep_regs
[ep
->num
]->doeptsiz
);
2385 if(!deptsiz
.b
.xfersize
) {
2387 for(i
= 0; i
< ep
->pkt_cnt
; i
+= ep
->pkt_per_frm
)
2389 frame_data
= ep
->data_per_frame
;
2390 for(j
= 0; j
< ep
->pkt_per_frm
; ++j
) {
2392 /* Packet status - is not set as initially
2393 * it is set to 0 and if packet was sent
2394 successfully, status field will remain 0*/
2397 /* Bytes has been transfered */
2398 packet_info
->length
= (ep
->maxpacket
< frame_data
) ?
2399 ep
->maxpacket
: frame_data
;
2401 /* Received packet offset */
2402 packet_info
->offset
= offset
;
2403 offset
+= packet_info
->length
;
2404 frame_data
-= packet_info
->length
;
2411 /* This is a workaround for in case of Transfer Complete with
2412 * PktDrpSts interrupts merging - in this case Transfer complete
2413 * interrupt for Isoc Out Endpoint is asserted without PktDrpSts
2414 * set and with DOEPTSIZ register non zero. Investigations showed,
2415 * that this happens when Out packet is dropped, but because of
2416 * interrupts merging during first interrupt handling PktDrpSts
2417 * bit is cleared and for next merged interrupts it is not reset.
2418 * In this case SW hadles the interrupt as if PktDrpSts bit is set.
2423 return handle_iso_out_pkt_dropped(core_if
, ep
);
2429 * This function is to handle Iso EP transfer complete interrupt
2431 * @param ep The EP for which transfer complete was asserted
2434 static void complete_iso_ep(dwc_otg_pcd_ep_t
*ep
)
2436 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(ep
->pcd
);
2437 dwc_ep_t
*dwc_ep
= &ep
->dwc_ep
;
2438 uint8_t is_last
= 0;
2440 if(core_if
->dma_enable
) {
2441 if(core_if
->dma_desc_enable
) {
2442 set_ddma_iso_pkts_info(core_if
, dwc_ep
);
2443 reinit_ddma_iso_xfer(core_if
, dwc_ep
);
2446 if(core_if
->pti_enh_enable
) {
2447 if(set_iso_pkts_info(core_if
, dwc_ep
)) {
2448 dwc_ep
->proc_buf_num
= (dwc_ep
->proc_buf_num
^ 1) & 0x1;
2449 dwc_otg_iso_ep_start_buf_transfer(core_if
, dwc_ep
);
2453 set_current_pkt_info(core_if
, dwc_ep
);
2454 if(dwc_ep
->cur_pkt
>= dwc_ep
->pkt_cnt
) {
2456 dwc_ep
->cur_pkt
= 0;
2457 dwc_ep
->proc_buf_num
= (dwc_ep
->proc_buf_num
^ 1) & 0x1;
2458 if(dwc_ep
->proc_buf_num
) {
2459 dwc_ep
->cur_pkt_addr
= dwc_ep
->xfer_buff1
;
2460 dwc_ep
->cur_pkt_dma_addr
= dwc_ep
->dma_addr1
;
2462 dwc_ep
->cur_pkt_addr
= dwc_ep
->xfer_buff0
;
2463 dwc_ep
->cur_pkt_dma_addr
= dwc_ep
->dma_addr0
;
2467 dwc_otg_iso_ep_start_frm_transfer(core_if
, dwc_ep
);
2471 set_current_pkt_info(core_if
, dwc_ep
);
2472 if(dwc_ep
->cur_pkt
>= dwc_ep
->pkt_cnt
) {
2474 dwc_ep
->cur_pkt
= 0;
2475 dwc_ep
->proc_buf_num
= (dwc_ep
->proc_buf_num
^ 1) & 0x1;
2476 if(dwc_ep
->proc_buf_num
) {
2477 dwc_ep
->cur_pkt_addr
= dwc_ep
->xfer_buff1
;
2478 dwc_ep
->cur_pkt_dma_addr
= dwc_ep
->dma_addr1
;
2480 dwc_ep
->cur_pkt_addr
= dwc_ep
->xfer_buff0
;
2481 dwc_ep
->cur_pkt_dma_addr
= dwc_ep
->dma_addr0
;
2485 dwc_otg_iso_ep_start_frm_transfer(core_if
, dwc_ep
);
2488 dwc_otg_iso_buffer_done(ep
, ep
->iso_req
);
2491 #endif //DWC_EN_ISOC
2495 * This function handles EP0 Control transfers.
2497 * The state of the control tranfers are tracked in
2498 * <code>ep0state</code>.
2500 static void handle_ep0(dwc_otg_pcd_t
*pcd
)
2502 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
2503 dwc_otg_pcd_ep_t
*ep0
= &pcd
->ep0
;
2504 desc_sts_data_t desc_sts
;
2505 deptsiz0_data_t deptsiz
;
2506 uint32_t byte_count
;
2509 DWC_DEBUGPL(DBG_PCDV
, "%s()\n", __func__
);
2510 print_ep0_state(pcd
);
2513 switch (pcd
->ep0state
) {
2514 case EP0_DISCONNECT
:
2518 pcd
->request_config
= 0;
2523 case EP0_IN_DATA_PHASE
:
2525 DWC_DEBUGPL(DBG_PCD
, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
2526 ep0
->dwc_ep
.num
, (ep0
->dwc_ep
.is_in
?"IN":"OUT"),
2527 ep0
->dwc_ep
.type
, ep0
->dwc_ep
.maxpacket
);
2530 if (core_if
->dma_enable
!= 0) {
2532 * For EP0 we can only program 1 packet at a time so we
2533 * need to do the make calculations after each complete.
2534 * Call write_packet to make the calculations, as in
2535 * slave mode, and use those values to determine if we
2538 if(core_if
->dma_desc_enable
== 0) {
2539 deptsiz
.d32
= dwc_read_reg32(&core_if
->dev_if
->in_ep_regs
[0]->dieptsiz
);
2540 byte_count
= ep0
->dwc_ep
.xfer_len
- deptsiz
.b
.xfersize
;
2543 desc_sts
.d32
= readl(core_if
->dev_if
->in_desc_addr
);
2544 byte_count
= ep0
->dwc_ep
.xfer_len
- desc_sts
.b
.bytes
;
2546 ep0
->dwc_ep
.xfer_count
+= byte_count
;
2547 ep0
->dwc_ep
.xfer_buff
+= byte_count
;
2548 ep0
->dwc_ep
.dma_addr
+= byte_count
;
2550 if (ep0
->dwc_ep
.xfer_count
< ep0
->dwc_ep
.total_len
) {
2551 dwc_otg_ep0_continue_transfer (GET_CORE_IF(pcd
), &ep0
->dwc_ep
);
2552 DWC_DEBUGPL(DBG_PCD
, "CONTINUE TRANSFER\n");
2554 else if(ep0
->dwc_ep
.sent_zlp
) {
2555 dwc_otg_ep0_continue_transfer (GET_CORE_IF(pcd
), &ep0
->dwc_ep
);
2556 ep0
->dwc_ep
.sent_zlp
= 0;
2557 DWC_DEBUGPL(DBG_PCD
, "CONTINUE TRANSFER\n");
2560 ep0_complete_request(ep0
);
2561 DWC_DEBUGPL(DBG_PCD
, "COMPLETE TRANSFER\n");
2564 case EP0_OUT_DATA_PHASE
:
2566 DWC_DEBUGPL(DBG_PCD
, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
2567 ep0
->dwc_ep
.num
, (ep0
->dwc_ep
.is_in
?"IN":"OUT"),
2568 ep0
->dwc_ep
.type
, ep0
->dwc_ep
.maxpacket
);
2570 if (core_if
->dma_enable
!= 0) {
2571 if(core_if
->dma_desc_enable
== 0) {
2572 deptsiz
.d32
= dwc_read_reg32(&core_if
->dev_if
->out_ep_regs
[0]->doeptsiz
);
2573 byte_count
= ep0
->dwc_ep
.maxpacket
- deptsiz
.b
.xfersize
;
2576 desc_sts
.d32
= readl(core_if
->dev_if
->out_desc_addr
);
2577 byte_count
= ep0
->dwc_ep
.maxpacket
- desc_sts
.b
.bytes
;
2579 ep0
->dwc_ep
.xfer_count
+= byte_count
;
2580 ep0
->dwc_ep
.xfer_buff
+= byte_count
;
2581 ep0
->dwc_ep
.dma_addr
+= byte_count
;
2583 if (ep0
->dwc_ep
.xfer_count
< ep0
->dwc_ep
.total_len
) {
2584 dwc_otg_ep0_continue_transfer (GET_CORE_IF(pcd
), &ep0
->dwc_ep
);
2585 DWC_DEBUGPL(DBG_PCD
, "CONTINUE TRANSFER\n");
2587 else if(ep0
->dwc_ep
.sent_zlp
) {
2588 dwc_otg_ep0_continue_transfer (GET_CORE_IF(pcd
), &ep0
->dwc_ep
);
2589 ep0
->dwc_ep
.sent_zlp
= 0;
2590 DWC_DEBUGPL(DBG_PCD
, "CONTINUE TRANSFER\n");
2593 ep0_complete_request(ep0
);
2594 DWC_DEBUGPL(DBG_PCD
, "COMPLETE TRANSFER\n");
2599 case EP0_IN_STATUS_PHASE
:
2600 case EP0_OUT_STATUS_PHASE
:
2601 DWC_DEBUGPL(DBG_PCD
, "CASE: EP0_STATUS\n");
2602 ep0_complete_request(ep0
);
2603 pcd
->ep0state
= EP0_IDLE
;
2605 ep0
->dwc_ep
.is_in
= 0; /* OUT for next SETUP */
2607 /* Prepare for more SETUP Packets */
2608 if(core_if
->dma_enable
) {
2609 ep0_out_start(core_if
, pcd
);
2614 DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
2618 print_ep0_state(pcd
);
2626 static void restart_transfer(dwc_otg_pcd_t
*pcd
, const uint32_t epnum
)
2628 dwc_otg_core_if_t
*core_if
;
2629 dwc_otg_dev_if_t
*dev_if
;
2630 deptsiz_data_t dieptsiz
= {.d32
=0};
2631 dwc_otg_pcd_ep_t
*ep
;
2633 ep
= get_in_ep(pcd
, epnum
);
2636 if(ep
->dwc_ep
.type
== DWC_OTG_EP_TYPE_ISOC
) {
2639 #endif /* DWC_EN_ISOC */
2641 core_if
= GET_CORE_IF(pcd
);
2642 dev_if
= core_if
->dev_if
;
2644 dieptsiz
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[epnum
]->dieptsiz
);
2646 DWC_DEBUGPL(DBG_PCD
,"xfer_buff=%p xfer_count=%0x xfer_len=%0x"
2647 " stopped=%d\n", ep
->dwc_ep
.xfer_buff
,
2648 ep
->dwc_ep
.xfer_count
, ep
->dwc_ep
.xfer_len
,
2651 * If xfersize is 0 and pktcnt in not 0, resend the last packet.
2653 if (dieptsiz
.b
.pktcnt
&& dieptsiz
.b
.xfersize
== 0 &&
2654 ep
->dwc_ep
.start_xfer_buff
!= 0) {
2655 if (ep
->dwc_ep
.total_len
<= ep
->dwc_ep
.maxpacket
) {
2656 ep
->dwc_ep
.xfer_count
= 0;
2657 ep
->dwc_ep
.xfer_buff
= ep
->dwc_ep
.start_xfer_buff
;
2658 ep
->dwc_ep
.xfer_len
= ep
->dwc_ep
.xfer_count
;
2661 ep
->dwc_ep
.xfer_count
-= ep
->dwc_ep
.maxpacket
;
2662 /* convert packet size to dwords. */
2663 ep
->dwc_ep
.xfer_buff
-= ep
->dwc_ep
.maxpacket
;
2664 ep
->dwc_ep
.xfer_len
= ep
->dwc_ep
.xfer_count
;
2667 DWC_DEBUGPL(DBG_PCD
,"xfer_buff=%p xfer_count=%0x "
2668 "xfer_len=%0x stopped=%d\n",
2669 ep
->dwc_ep
.xfer_buff
,
2670 ep
->dwc_ep
.xfer_count
, ep
->dwc_ep
.xfer_len
,
2674 dwc_otg_ep0_start_transfer(core_if
, &ep
->dwc_ep
);
2677 dwc_otg_ep_start_transfer(core_if
, &ep
->dwc_ep
);
2684 * handle the IN EP disable interrupt.
2686 static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t
*pcd
,
2687 const uint32_t epnum
)
2689 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
2690 dwc_otg_dev_if_t
*dev_if
= core_if
->dev_if
;
2691 deptsiz_data_t dieptsiz
= {.d32
=0};
2692 dctl_data_t dctl
= {.d32
=0};
2693 dwc_otg_pcd_ep_t
*ep
;
2696 ep
= get_in_ep(pcd
, epnum
);
2697 dwc_ep
= &ep
->dwc_ep
;
2699 if(dwc_ep
->type
== DWC_OTG_EP_TYPE_ISOC
) {
2700 dwc_otg_flush_tx_fifo(core_if
, dwc_ep
->tx_fifo_num
);
2704 DWC_DEBUGPL(DBG_PCD
,"diepctl%d=%0x\n", epnum
,
2705 dwc_read_reg32(&dev_if
->in_ep_regs
[epnum
]->diepctl
));
2706 dieptsiz
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[epnum
]->dieptsiz
);
2708 DWC_DEBUGPL(DBG_ANY
, "pktcnt=%d size=%d\n",
2710 dieptsiz
.b
.xfersize
);
2713 /* Flush the Tx FIFO */
2714 dwc_otg_flush_tx_fifo(core_if
, dwc_ep
->tx_fifo_num
);
2715 /* Clear the Global IN NP NAK */
2717 dctl
.b
.cgnpinnak
= 1;
2718 dwc_modify_reg32(&dev_if
->dev_global_regs
->dctl
,
2720 /* Restart the transaction */
2721 if (dieptsiz
.b
.pktcnt
!= 0 ||
2722 dieptsiz
.b
.xfersize
!= 0) {
2723 restart_transfer(pcd
, epnum
);
2727 /* Restart the transaction */
2728 if (dieptsiz
.b
.pktcnt
!= 0 ||
2729 dieptsiz
.b
.xfersize
!= 0) {
2730 restart_transfer(pcd
, epnum
);
2732 DWC_DEBUGPL(DBG_ANY
, "STOPPED!!!\n");
2737 * Handler for the IN EP timeout handshake interrupt.
2739 static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t
*pcd
,
2740 const uint32_t epnum
)
2742 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
2743 dwc_otg_dev_if_t
*dev_if
= core_if
->dev_if
;
2746 deptsiz_data_t dieptsiz
= {.d32
=0};
2749 dctl_data_t dctl
= {.d32
=0};
2750 dwc_otg_pcd_ep_t
*ep
;
2752 gintmsk_data_t intr_mask
= {.d32
= 0};
2754 ep
= get_in_ep(pcd
, epnum
);
2756 /* Disable the NP Tx Fifo Empty Interrrupt */
2757 if (!core_if
->dma_enable
) {
2758 intr_mask
.b
.nptxfempty
= 1;
2759 dwc_modify_reg32(&core_if
->core_global_regs
->gintmsk
, intr_mask
.d32
, 0);
2761 /** @todo NGS Check EP type.
2762 * Implement for Periodic EPs */
2766 /* Enable the Global IN NAK Effective Interrupt */
2767 intr_mask
.b
.ginnakeff
= 1;
2768 dwc_modify_reg32(&core_if
->core_global_regs
->gintmsk
,
2771 /* Set Global IN NAK */
2772 dctl
.b
.sgnpinnak
= 1;
2773 dwc_modify_reg32(&dev_if
->dev_global_regs
->dctl
,
2774 dctl
.d32
, dctl
.d32
);
2779 dieptsiz
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[num
]->dieptsiz
);
2780 DWC_DEBUGPL(DBG_ANY
, "pktcnt=%d size=%d\n",
2782 dieptsiz
.b
.xfersize
);
2785 #ifdef DISABLE_PERIODIC_EP
2787 * Set the NAK bit for this EP to
2788 * start the disable process.
2792 dwc_modify_reg32(&dev_if
->in_ep_regs
[num
]->diepctl
, diepctl
.d32
, diepctl
.d32
);
2799 * Handler for the IN EP NAK interrupt.
2801 static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t
*pcd
,
2802 const uint32_t epnum
)
2804 /** @todo implement ISR */
2805 dwc_otg_core_if_t
* core_if
;
2806 diepmsk_data_t intr_mask
= { .d32
= 0};
2808 DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
2809 core_if
= GET_CORE_IF(pcd
);
2810 intr_mask
.b
.nak
= 1;
2812 if(core_if
->multiproc_int_enable
) {
2813 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->diepeachintmsk
[epnum
],
2816 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->diepmsk
,
2824 * Handler for the OUT EP Babble interrupt.
2826 static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t
*pcd
,
2827 const uint32_t epnum
)
2829 /** @todo implement ISR */
2830 dwc_otg_core_if_t
* core_if
;
2831 doepmsk_data_t intr_mask
= { .d32
= 0};
2833 DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "OUT EP Babble");
2834 core_if
= GET_CORE_IF(pcd
);
2835 intr_mask
.b
.babble
= 1;
2837 if(core_if
->multiproc_int_enable
) {
2838 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->doepeachintmsk
[epnum
],
2841 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->doepmsk
,
2849 * Handler for the OUT EP NAK interrupt.
2851 static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t
*pcd
,
2852 const uint32_t epnum
)
2854 /** @todo implement ISR */
2855 dwc_otg_core_if_t
* core_if
;
2856 doepmsk_data_t intr_mask
= { .d32
= 0};
2858 DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
2859 core_if
= GET_CORE_IF(pcd
);
2860 intr_mask
.b
.nak
= 1;
2862 if(core_if
->multiproc_int_enable
) {
2863 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->doepeachintmsk
[epnum
],
2866 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->doepmsk
,
2874 * Handler for the OUT EP NYET interrupt.
2876 static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t
*pcd
,
2877 const uint32_t epnum
)
2879 /** @todo implement ISR */
2880 dwc_otg_core_if_t
* core_if
;
2881 doepmsk_data_t intr_mask
= { .d32
= 0};
2883 DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
2884 core_if
= GET_CORE_IF(pcd
);
2885 intr_mask
.b
.nyet
= 1;
2887 if(core_if
->multiproc_int_enable
) {
2888 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->doepeachintmsk
[epnum
],
2891 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->doepmsk
,
2899 * This interrupt indicates that an IN EP has a pending Interrupt.
2900 * The sequence for handling the IN EP interrupt is shown below:
2901 * -# Read the Device All Endpoint Interrupt register
2902 * -# Repeat the following for each IN EP interrupt bit set (from
2904 * -# Read the Device Endpoint Interrupt (DIEPINTn) register
2905 * -# If "Transfer Complete" call the request complete function
2906 * -# If "Endpoint Disabled" complete the EP disable procedure.
2907 * -# If "AHB Error Interrupt" log error
2908 * -# If "Time-out Handshake" log error
2909 * -# If "IN Token Received when TxFIFO Empty" write packet to Tx
2911 * -# If "IN Token EP Mismatch" (disable, this is handled by EP
2912 * Mismatch Interrupt)
2914 static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t
*pcd
)
2916 #define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
2918 diepint_data_t diepint = {.d32=0}; \
2919 diepint.b.__intr = 1; \
2920 dwc_write_reg32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
2924 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
2925 dwc_otg_dev_if_t
*dev_if
= core_if
->dev_if
;
2926 diepint_data_t diepint
= {.d32
=0};
2927 dctl_data_t dctl
= {.d32
=0};
2928 depctl_data_t depctl
= {.d32
=0};
2931 dwc_otg_pcd_ep_t
*ep
;
2933 gintmsk_data_t intr_mask
= {.d32
= 0};
2937 DWC_DEBUGPL(DBG_PCDV
, "%s(%p)\n", __func__
, pcd
);
2939 /* Read in the device interrupt bits */
2940 ep_intr
= dwc_otg_read_dev_all_in_ep_intr(core_if
);
2942 /* Service the Device IN interrupts for each endpoint */
2946 /* Get EP pointer */
2947 ep
= get_in_ep(pcd
, epnum
);
2948 dwc_ep
= &ep
->dwc_ep
;
2950 depctl
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[epnum
]->diepctl
);
2951 empty_msk
= dwc_read_reg32(&dev_if
->dev_global_regs
->dtknqr4_fifoemptymsk
);
2953 DWC_DEBUGPL(DBG_PCDV
,
2954 "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n",
2959 DWC_DEBUGPL(DBG_PCD
,
2960 "EP%d-%s: type=%d, mps=%d\n",
2961 dwc_ep
->num
, (dwc_ep
->is_in
?"IN":"OUT"),
2962 dwc_ep
->type
, dwc_ep
->maxpacket
);
2964 diepint
.d32
= dwc_otg_read_dev_in_ep_intr(core_if
, dwc_ep
);
2966 DWC_DEBUGPL(DBG_PCDV
, "EP %d Interrupt Register - 0x%x\n", epnum
, diepint
.d32
);
2967 /* Transfer complete */
2968 if (diepint
.b
.xfercompl
) {
2969 /* Disable the NP Tx FIFO Empty
2971 if(core_if
->en_multiple_tx_fifo
== 0) {
2972 intr_mask
.b
.nptxfempty
= 1;
2973 dwc_modify_reg32(&core_if
->core_global_regs
->gintmsk
, intr_mask
.d32
, 0);
2976 /* Disable the Tx FIFO Empty Interrupt for this EP */
2977 uint32_t fifoemptymsk
= 0x1 << dwc_ep
->num
;
2978 dwc_modify_reg32(&core_if
->dev_if
->dev_global_regs
->dtknqr4_fifoemptymsk
,
2981 /* Clear the bit in DIEPINTn for this interrupt */
2982 CLEAR_IN_EP_INTR(core_if
,epnum
,xfercompl
);
2984 /* Complete the transfer */
2989 else if(dwc_ep
->type
== DWC_OTG_EP_TYPE_ISOC
) {
2991 complete_iso_ep(ep
);
2993 #endif //DWC_EN_ISOC
2999 /* Endpoint disable */
3000 if (diepint
.b
.epdisabled
) {
3001 DWC_DEBUGPL(DBG_ANY
,"EP%d IN disabled\n", epnum
);
3002 handle_in_ep_disable_intr(pcd
, epnum
);
3004 /* Clear the bit in DIEPINTn for this interrupt */
3005 CLEAR_IN_EP_INTR(core_if
,epnum
,epdisabled
);
3008 if (diepint
.b
.ahberr
) {
3009 DWC_DEBUGPL(DBG_ANY
,"EP%d IN AHB Error\n", epnum
);
3010 /* Clear the bit in DIEPINTn for this interrupt */
3011 CLEAR_IN_EP_INTR(core_if
,epnum
,ahberr
);
3013 /* TimeOUT Handshake (non-ISOC IN EPs) */
3014 if (diepint
.b
.timeout
) {
3015 DWC_DEBUGPL(DBG_ANY
,"EP%d IN Time-out\n", epnum
);
3016 handle_in_ep_timeout_intr(pcd
, epnum
);
3018 CLEAR_IN_EP_INTR(core_if
,epnum
,timeout
);
3020 /** IN Token received with TxF Empty */
3021 if (diepint
.b
.intktxfemp
) {
3022 DWC_DEBUGPL(DBG_ANY
,"EP%d IN TKN TxFifo Empty\n",
3024 if (!ep
->stopped
&& epnum
!= 0) {
3026 diepmsk_data_t diepmsk
= { .d32
= 0};
3027 diepmsk
.b
.intktxfemp
= 1;
3029 if(core_if
->multiproc_int_enable
) {
3030 dwc_modify_reg32(&dev_if
->dev_global_regs
->diepeachintmsk
[epnum
],
3033 dwc_modify_reg32(&dev_if
->dev_global_regs
->diepmsk
, diepmsk
.d32
, 0);
3035 start_next_request(ep
);
3037 else if(core_if
->dma_desc_enable
&& epnum
== 0 &&
3038 pcd
->ep0state
== EP0_OUT_STATUS_PHASE
) {
3040 depctl
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[epnum
]->diepctl
);
3042 /* set the disable and stall bits */
3043 if (depctl
.b
.epena
) {
3047 dwc_write_reg32(&dev_if
->in_ep_regs
[epnum
]->diepctl
, depctl
.d32
);
3049 CLEAR_IN_EP_INTR(core_if
,epnum
,intktxfemp
);
3051 /** IN Token Received with EP mismatch */
3052 if (diepint
.b
.intknepmis
) {
3053 DWC_DEBUGPL(DBG_ANY
,"EP%d IN TKN EP Mismatch\n", epnum
);
3054 CLEAR_IN_EP_INTR(core_if
,epnum
,intknepmis
);
3056 /** IN Endpoint NAK Effective */
3057 if (diepint
.b
.inepnakeff
) {
3058 DWC_DEBUGPL(DBG_ANY
,"EP%d IN EP NAK Effective\n", epnum
);
3060 if (ep
->disabling
) {
3064 dwc_modify_reg32(&dev_if
->in_ep_regs
[epnum
]->diepctl
, depctl
.d32
, depctl
.d32
);
3066 CLEAR_IN_EP_INTR(core_if
,epnum
,inepnakeff
);
3070 /** IN EP Tx FIFO Empty Intr */
3071 if (diepint
.b
.emptyintr
) {
3072 DWC_DEBUGPL(DBG_ANY
,"EP%d Tx FIFO Empty Intr \n", epnum
);
3073 write_empty_tx_fifo(pcd
, epnum
);
3075 CLEAR_IN_EP_INTR(core_if
,epnum
,emptyintr
);
3079 /** IN EP BNA Intr */
3080 if (diepint
.b
.bna
) {
3081 CLEAR_IN_EP_INTR(core_if
,epnum
,bna
);
3082 if(core_if
->dma_desc_enable
) {
3084 if(dwc_ep
->type
== DWC_OTG_EP_TYPE_ISOC
) {
3086 * This checking is performed to prevent first "false" BNA
3087 * handling occuring right after reconnect
3089 if(dwc_ep
->next_frame
!= 0xffffffff)
3090 dwc_otg_pcd_handle_iso_bna(ep
);
3093 #endif //DWC_EN_ISOC
3095 dctl
.d32
= dwc_read_reg32(&dev_if
->dev_global_regs
->dctl
);
3097 /* If Global Continue on BNA is disabled - disable EP */
3098 if(!dctl
.b
.gcontbna
) {
3102 dwc_modify_reg32(&dev_if
->in_ep_regs
[epnum
]->diepctl
, depctl
.d32
, depctl
.d32
);
3104 start_next_request(ep
);
3110 if (diepint
.b
.nak
) {
3111 DWC_DEBUGPL(DBG_ANY
,"EP%d IN NAK Interrupt\n", epnum
);
3112 handle_in_ep_nak_intr(pcd
, epnum
);
3114 CLEAR_IN_EP_INTR(core_if
,epnum
,nak
);
3122 #undef CLEAR_IN_EP_INTR
3126 * This interrupt indicates that an OUT EP has a pending Interrupt.
3127 * The sequence for handling the OUT EP interrupt is shown below:
3128 * -# Read the Device All Endpoint Interrupt register
3129 * -# Repeat the following for each OUT EP interrupt bit set (from
3131 * -# Read the Device Endpoint Interrupt (DOEPINTn) register
3132 * -# If "Transfer Complete" call the request complete function
3133 * -# If "Endpoint Disabled" complete the EP disable procedure.
3134 * -# If "AHB Error Interrupt" log error
3135 * -# If "Setup Phase Done" process Setup Packet (See Standard USB
3136 * Command Processing)
3138 static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t
*pcd
)
3140 #define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
3142 doepint_data_t doepint = {.d32=0}; \
3143 doepint.b.__intr = 1; \
3144 dwc_write_reg32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
3148 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
3149 dwc_otg_dev_if_t
*dev_if
= core_if
->dev_if
;
3151 doepint_data_t doepint
= {.d32
=0};
3152 dctl_data_t dctl
= {.d32
=0};
3153 depctl_data_t doepctl
= {.d32
=0};
3155 dwc_otg_pcd_ep_t
*ep
;
3158 DWC_DEBUGPL(DBG_PCDV
, "%s()\n", __func__
);
3160 /* Read in the device interrupt bits */
3161 ep_intr
= dwc_otg_read_dev_all_out_ep_intr(core_if
);
3165 /* Get EP pointer */
3166 ep
= get_out_ep(pcd
, epnum
);
3167 dwc_ep
= &ep
->dwc_ep
;
3170 DWC_DEBUGPL(DBG_PCDV
,
3171 "EP%d-%s: type=%d, mps=%d\n",
3172 dwc_ep
->num
, (dwc_ep
->is_in
?"IN":"OUT"),
3173 dwc_ep
->type
, dwc_ep
->maxpacket
);
3175 doepint
.d32
= dwc_otg_read_dev_out_ep_intr(core_if
, dwc_ep
);
3177 /* Transfer complete */
3178 if (doepint
.b
.xfercompl
) {
3181 /* Clear the bit in DOEPINTn for this interrupt */
3182 CLEAR_OUT_EP_INTR(core_if
,epnum
,xfercompl
);
3183 if(core_if
->dma_desc_enable
== 0 || pcd
->ep0state
!= EP0_IDLE
)
3186 } else if(dwc_ep
->type
== DWC_OTG_EP_TYPE_ISOC
) {
3187 if (doepint
.b
.pktdrpsts
== 0) {
3188 /* Clear the bit in DOEPINTn for this interrupt */
3189 CLEAR_OUT_EP_INTR(core_if
,epnum
,xfercompl
);
3190 complete_iso_ep(ep
);
3193 doepint_data_t doepint
= {.d32
=0};
3194 doepint
.b
.xfercompl
= 1;
3195 doepint
.b
.pktdrpsts
= 1;
3196 dwc_write_reg32(&core_if
->dev_if
->out_ep_regs
[epnum
]->doepint
,
3198 if(handle_iso_out_pkt_dropped(core_if
,dwc_ep
)) {
3199 complete_iso_ep(ep
);
3202 #endif //DWC_EN_ISOC
3204 /* Clear the bit in DOEPINTn for this interrupt */
3205 CLEAR_OUT_EP_INTR(core_if
,epnum
,xfercompl
);
3211 /* Endpoint disable */
3212 if (doepint
.b
.epdisabled
) {
3214 /* Clear the bit in DOEPINTn for this interrupt */
3215 CLEAR_OUT_EP_INTR(core_if
,epnum
,epdisabled
);
3218 if (doepint
.b
.ahberr
) {
3219 DWC_DEBUGPL(DBG_PCD
,"EP%d OUT AHB Error\n", epnum
);
3220 DWC_DEBUGPL(DBG_PCD
,"EP DMA REG %d \n", core_if
->dev_if
->out_ep_regs
[epnum
]->doepdma
);
3221 CLEAR_OUT_EP_INTR(core_if
,epnum
,ahberr
);
3223 /* Setup Phase Done (contorl EPs) */
3224 if (doepint
.b
.setup
) {
3226 DWC_DEBUGPL(DBG_PCD
,"EP%d SETUP Done\n",
3229 CLEAR_OUT_EP_INTR(core_if
,epnum
,setup
);
3234 /** OUT EP BNA Intr */
3235 if (doepint
.b
.bna
) {
3236 CLEAR_OUT_EP_INTR(core_if
,epnum
,bna
);
3237 if(core_if
->dma_desc_enable
) {
3239 if(dwc_ep
->type
== DWC_OTG_EP_TYPE_ISOC
) {
3241 * This checking is performed to prevent first "false" BNA
3242 * handling occuring right after reconnect
3244 if(dwc_ep
->next_frame
!= 0xffffffff)
3245 dwc_otg_pcd_handle_iso_bna(ep
);
3248 #endif //DWC_EN_ISOC
3250 dctl
.d32
= dwc_read_reg32(&dev_if
->dev_global_regs
->dctl
);
3252 /* If Global Continue on BNA is disabled - disable EP*/
3253 if(!dctl
.b
.gcontbna
) {
3256 doepctl
.b
.epdis
= 1;
3257 dwc_modify_reg32(&dev_if
->out_ep_regs
[epnum
]->doepctl
, doepctl
.d32
, doepctl
.d32
);
3259 start_next_request(ep
);
3264 if (doepint
.b
.stsphsercvd
) {
3265 CLEAR_OUT_EP_INTR(core_if
,epnum
,stsphsercvd
);
3266 if(core_if
->dma_desc_enable
) {
3267 do_setup_in_status_phase(pcd
);
3270 /* Babble Interrutp */
3271 if (doepint
.b
.babble
) {
3272 DWC_DEBUGPL(DBG_ANY
,"EP%d OUT Babble\n", epnum
);
3273 handle_out_ep_babble_intr(pcd
, epnum
);
3275 CLEAR_OUT_EP_INTR(core_if
,epnum
,babble
);
3278 if (doepint
.b
.nak
) {
3279 DWC_DEBUGPL(DBG_ANY
,"EP%d OUT NAK\n", epnum
);
3280 handle_out_ep_nak_intr(pcd
, epnum
);
3282 CLEAR_OUT_EP_INTR(core_if
,epnum
,nak
);
3284 /* NYET Interrutp */
3285 if (doepint
.b
.nyet
) {
3286 DWC_DEBUGPL(DBG_ANY
,"EP%d OUT NYET\n", epnum
);
3287 handle_out_ep_nyet_intr(pcd
, epnum
);
3289 CLEAR_OUT_EP_INTR(core_if
,epnum
,nyet
);
3299 #undef CLEAR_OUT_EP_INTR
3304 * Incomplete ISO IN Transfer Interrupt.
3305 * This interrupt indicates one of the following conditions occurred
3306 * while transmitting an ISOC transaction.
3307 * - Corrupted IN Token for ISOC EP.
3308 * - Packet not complete in FIFO.
3309 * The follow actions will be taken:
3310 * -# Determine the EP
3311 * -# Set incomplete flag in dwc_ep structure
3312 * -# Disable EP; when "Endpoint Disabled" interrupt is received
3315 int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t
*pcd
)
3317 gintsts_data_t gintsts
;
3321 dwc_otg_dev_if_t
*dev_if
;
3322 deptsiz_data_t deptsiz
= { .d32
= 0};
3323 depctl_data_t depctl
= { .d32
= 0};
3324 dsts_data_t dsts
= { .d32
= 0};
3328 dev_if
= GET_CORE_IF(pcd
)->dev_if
;
3330 for(i
= 1; i
<= dev_if
->num_in_eps
; ++i
) {
3331 dwc_ep
= &pcd
->in_ep
[i
].dwc_ep
;
3332 if(dwc_ep
->active
&&
3333 dwc_ep
->type
== USB_ENDPOINT_XFER_ISOC
)
3335 deptsiz
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[i
]->dieptsiz
);
3336 depctl
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[i
]->diepctl
);
3338 if(depctl
.b
.epdis
&& deptsiz
.d32
) {
3339 set_current_pkt_info(GET_CORE_IF(pcd
), dwc_ep
);
3340 if(dwc_ep
->cur_pkt
>= dwc_ep
->pkt_cnt
) {
3341 dwc_ep
->cur_pkt
= 0;
3342 dwc_ep
->proc_buf_num
= (dwc_ep
->proc_buf_num
^ 1) & 0x1;
3344 if(dwc_ep
->proc_buf_num
) {
3345 dwc_ep
->cur_pkt_addr
= dwc_ep
->xfer_buff1
;
3346 dwc_ep
->cur_pkt_dma_addr
= dwc_ep
->dma_addr1
;
3348 dwc_ep
->cur_pkt_addr
= dwc_ep
->xfer_buff0
;
3349 dwc_ep
->cur_pkt_dma_addr
= dwc_ep
->dma_addr0
;
3354 dsts
.d32
= dwc_read_reg32(&GET_CORE_IF(pcd
)->dev_if
->dev_global_regs
->dsts
);
3355 dwc_ep
->next_frame
= dsts
.b
.soffn
;
3357 dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF(pcd
), dwc_ep
);
3363 gintmsk_data_t intr_mask
= { .d32
= 0};
3364 DWC_PRINT("INTERRUPT Handler not implemented for %s\n",
3365 "IN ISOC Incomplete");
3367 intr_mask
.b
.incomplisoin
= 1;
3368 dwc_modify_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintmsk
,
3370 #endif //DWC_EN_ISOC
3372 /* Clear interrupt */
3374 gintsts
.b
.incomplisoin
= 1;
3375 dwc_write_reg32 (&GET_CORE_IF(pcd
)->core_global_regs
->gintsts
,
3382 * Incomplete ISO OUT Transfer Interrupt.
3384 * This interrupt indicates that the core has dropped an ISO OUT
3385 * packet. The following conditions can be the cause:
3386 * - FIFO Full, the entire packet would not fit in the FIFO.
3389 * The follow actions will be taken:
3390 * -# Determine the EP
3391 * -# Set incomplete flag in dwc_ep structure
3392 * -# Read any data from the FIFO
3393 * -# Disable EP. when "Endpoint Disabled" interrupt is received
3396 int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t
*pcd
)
3398 /* @todo implement ISR */
3399 gintsts_data_t gintsts
;
3402 dwc_otg_dev_if_t
*dev_if
;
3403 deptsiz_data_t deptsiz
= { .d32
= 0};
3404 depctl_data_t depctl
= { .d32
= 0};
3405 dsts_data_t dsts
= { .d32
= 0};
3409 dev_if
= GET_CORE_IF(pcd
)->dev_if
;
3411 for(i
= 1; i
<= dev_if
->num_out_eps
; ++i
) {
3412 dwc_ep
= &pcd
->in_ep
[i
].dwc_ep
;
3413 if(pcd
->out_ep
[i
].dwc_ep
.active
&&
3414 pcd
->out_ep
[i
].dwc_ep
.type
== USB_ENDPOINT_XFER_ISOC
)
3416 deptsiz
.d32
= dwc_read_reg32(&dev_if
->out_ep_regs
[i
]->doeptsiz
);
3417 depctl
.d32
= dwc_read_reg32(&dev_if
->out_ep_regs
[i
]->doepctl
);
3419 if(depctl
.b
.epdis
&& deptsiz
.d32
) {
3420 set_current_pkt_info(GET_CORE_IF(pcd
), &pcd
->out_ep
[i
].dwc_ep
);
3421 if(dwc_ep
->cur_pkt
>= dwc_ep
->pkt_cnt
) {
3422 dwc_ep
->cur_pkt
= 0;
3423 dwc_ep
->proc_buf_num
= (dwc_ep
->proc_buf_num
^ 1) & 0x1;
3425 if(dwc_ep
->proc_buf_num
) {
3426 dwc_ep
->cur_pkt_addr
= dwc_ep
->xfer_buff1
;
3427 dwc_ep
->cur_pkt_dma_addr
= dwc_ep
->dma_addr1
;
3429 dwc_ep
->cur_pkt_addr
= dwc_ep
->xfer_buff0
;
3430 dwc_ep
->cur_pkt_dma_addr
= dwc_ep
->dma_addr0
;
3435 dsts
.d32
= dwc_read_reg32(&GET_CORE_IF(pcd
)->dev_if
->dev_global_regs
->dsts
);
3436 dwc_ep
->next_frame
= dsts
.b
.soffn
;
3438 dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF(pcd
), dwc_ep
);
3443 /** @todo implement ISR */
3444 gintmsk_data_t intr_mask
= { .d32
= 0};
3446 DWC_PRINT("INTERRUPT Handler not implemented for %s\n",
3447 "OUT ISOC Incomplete");
3449 intr_mask
.b
.incomplisoout
= 1;
3450 dwc_modify_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintmsk
,
3453 #endif // DWC_EN_ISOC
3455 /* Clear interrupt */
3457 gintsts
.b
.incomplisoout
= 1;
3458 dwc_write_reg32 (&GET_CORE_IF(pcd
)->core_global_regs
->gintsts
,
3465 * This function handles the Global IN NAK Effective interrupt.
3468 int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t
*pcd
)
3470 dwc_otg_dev_if_t
*dev_if
= GET_CORE_IF(pcd
)->dev_if
;
3471 depctl_data_t diepctl
= { .d32
= 0};
3472 depctl_data_t diepctl_rd
= { .d32
= 0};
3473 gintmsk_data_t intr_mask
= { .d32
= 0};
3474 gintsts_data_t gintsts
;
3477 DWC_DEBUGPL(DBG_PCD
, "Global IN NAK Effective\n");
3479 /* Disable all active IN EPs */
3480 diepctl
.b
.epdis
= 1;
3483 for (i
=0; i
<= dev_if
->num_in_eps
; i
++)
3485 diepctl_rd
.d32
= dwc_read_reg32(&dev_if
->in_ep_regs
[i
]->diepctl
);
3486 if (diepctl_rd
.b
.epena
) {
3487 dwc_write_reg32(&dev_if
->in_ep_regs
[i
]->diepctl
,
3491 /* Disable the Global IN NAK Effective Interrupt */
3492 intr_mask
.b
.ginnakeff
= 1;
3493 dwc_modify_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintmsk
,
3496 /* Clear interrupt */
3498 gintsts
.b
.ginnakeff
= 1;
3499 dwc_write_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintsts
,
3506 * OUT NAK Effective.
3509 int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t
*pcd
)
3511 gintmsk_data_t intr_mask
= { .d32
= 0};
3512 gintsts_data_t gintsts
;
3514 DWC_PRINT("INTERRUPT Handler not implemented for %s\n",
3515 "Global IN NAK Effective\n");
3516 /* Disable the Global IN NAK Effective Interrupt */
3517 intr_mask
.b
.goutnakeff
= 1;
3518 dwc_modify_reg32(&GET_CORE_IF(pcd
)->core_global_regs
->gintmsk
,
3521 /* Clear interrupt */
3523 gintsts
.b
.goutnakeff
= 1;
3524 dwc_write_reg32 (&GET_CORE_IF(pcd
)->core_global_regs
->gintsts
,
3532 * PCD interrupt handler.
3534 * The PCD handles the device interrupts. Many conditions can cause a
3535 * device interrupt. When an interrupt occurs, the device interrupt
3536 * service routine determines the cause of the interrupt and
3537 * dispatches handling to the appropriate function. These interrupt
3538 * handling functions are described below.
3540 * All interrupt registers are processed from LSB to MSB.
3543 int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t
*pcd
)
3545 dwc_otg_core_if_t
*core_if
= GET_CORE_IF(pcd
);
3547 dwc_otg_core_global_regs_t
*global_regs
=
3548 core_if
->core_global_regs
;
3550 gintsts_data_t gintr_status
;
3555 DWC_DEBUGPL(DBG_ANY
, "%s() gintsts=%08x gintmsk=%08x\n",
3557 dwc_read_reg32(&global_regs
->gintsts
),
3558 dwc_read_reg32(&global_regs
->gintmsk
));
3561 if (dwc_otg_is_device_mode(core_if
)) {
3562 SPIN_LOCK(&pcd
->lock
);
3564 DWC_DEBUGPL(DBG_PCDV
, "%s() gintsts=%08x gintmsk=%08x\n",
3566 dwc_read_reg32(&global_regs
->gintsts
),
3567 dwc_read_reg32(&global_regs
->gintmsk
));
3570 gintr_status
.d32
= dwc_otg_read_core_intr(core_if
);
3573 if (!gintr_status.d32) {
3574 SPIN_UNLOCK(&pcd->lock);
3578 DWC_DEBUGPL(DBG_PCDV
, "%s: gintsts&gintmsk=%08x\n",
3579 __func__
, gintr_status
.d32
);
3581 if (gintr_status
.b
.sofintr
) {
3582 retval
|= dwc_otg_pcd_handle_sof_intr(pcd
);
3584 if (gintr_status
.b
.rxstsqlvl
) {
3585 retval
|= dwc_otg_pcd_handle_rx_status_q_level_intr(pcd
);
3587 if (gintr_status
.b
.nptxfempty
) {
3588 retval
|= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd
);
3590 if (gintr_status
.b
.ginnakeff
) {
3591 retval
|= dwc_otg_pcd_handle_in_nak_effective(pcd
);
3593 if (gintr_status
.b
.goutnakeff
) {
3594 retval
|= dwc_otg_pcd_handle_out_nak_effective(pcd
);
3596 if (gintr_status
.b
.i2cintr
) {
3597 retval
|= dwc_otg_pcd_handle_i2c_intr(pcd
);
3599 if (gintr_status
.b
.erlysuspend
) {
3600 retval
|= dwc_otg_pcd_handle_early_suspend_intr(pcd
);
3602 if (gintr_status
.b
.usbreset
) {
3603 retval
|= dwc_otg_pcd_handle_usb_reset_intr(pcd
);
3605 if (gintr_status
.b
.enumdone
) {
3606 retval
|= dwc_otg_pcd_handle_enum_done_intr(pcd
);
3608 if (gintr_status
.b
.isooutdrop
) {
3609 retval
|= dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(pcd
);
3611 if (gintr_status
.b
.eopframe
) {
3612 retval
|= dwc_otg_pcd_handle_end_periodic_frame_intr(pcd
);
3614 if (gintr_status
.b
.epmismatch
) {
3615 retval
|= dwc_otg_pcd_handle_ep_mismatch_intr(core_if
);
3617 if (gintr_status
.b
.inepint
) {
3618 if(!core_if
->multiproc_int_enable
) {
3619 retval
|= dwc_otg_pcd_handle_in_ep_intr(pcd
);
3622 if (gintr_status
.b
.outepintr
) {
3623 if(!core_if
->multiproc_int_enable
) {
3624 retval
|= dwc_otg_pcd_handle_out_ep_intr(pcd
);
3627 if (gintr_status
.b
.incomplisoin
) {
3628 retval
|= dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd
);
3630 if (gintr_status
.b
.incomplisoout
) {
3631 retval
|= dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd
);
3634 /* In MPI mode De vice Endpoints intterrupts are asserted
3635 * without setting outepintr and inepint bits set, so these
3636 * Interrupt handlers are called without checking these bit-fields
3638 if(core_if
->multiproc_int_enable
) {
3639 retval
|= dwc_otg_pcd_handle_in_ep_intr(pcd
);
3640 retval
|= dwc_otg_pcd_handle_out_ep_intr(pcd
);
3643 DWC_DEBUGPL(DBG_PCDV
, "%s() gintsts=%0x\n", __func__
,
3644 dwc_read_reg32(&global_regs
->gintsts
));
3646 SPIN_UNLOCK(&pcd
->lock
);
3649 S3C2410X_CLEAR_EINTPEND();
3654 #endif /* DWC_HOST_ONLY */