Branch data Line data Source code
1 : : /* ==========================================================================
2 : : * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
3 : : * $Revision: #116 $
4 : : * $Date: 2012/08/10 $
5 : : * $Change: 2047372 $
6 : : *
7 : : * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8 : : * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9 : : * otherwise expressly agreed to in writing between Synopsys and you.
10 : : *
11 : : * The Software IS NOT an item of Licensed Software or Licensed Product under
12 : : * any End User Software License Agreement or Agreement for Licensed Product
13 : : * with Synopsys or any supplement thereto. You are permitted to use and
14 : : * redistribute this Software in source and binary forms, with or without
15 : : * modification, provided that redistributions of source code must retain this
16 : : * notice. You may not view, use, disclose, copy or distribute this file or
17 : : * any information contained herein except pursuant to this license grant from
18 : : * Synopsys. If you do not agree with this notice, including the disclaimer
19 : : * below, then you are not authorized to use the Software.
20 : : *
21 : : * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22 : : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : : * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25 : : * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 : : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 : : * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 : : * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 : : * DAMAGE.
32 : : * ========================================================================== */
33 : : #ifndef DWC_HOST_ONLY
34 : :
35 : : #include "dwc_otg_pcd.h"
36 : :
37 : : #ifdef DWC_UTE_CFI
38 : : #include "dwc_otg_cfi.h"
39 : : #endif
40 : :
41 : : #ifdef DWC_UTE_PER_IO
42 : : extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep);
43 : : #endif
44 : : //#define PRINT_CFI_DMA_DESCS
45 : :
46 : : #define DEBUG_EP0
47 : :
48 : : /**
49 : : * This function updates OTG.
50 : : */
51 : : static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)
52 : : {
53 : :
54 : : if (reset) {
55 : 0 : pcd->b_hnp_enable = 0;
56 : 0 : pcd->a_hnp_support = 0;
57 : 0 : pcd->a_alt_hnp_support = 0;
58 : : }
59 : :
60 : 0 : if (pcd->fops->hnp_changed) {
61 : 0 : pcd->fops->hnp_changed(pcd);
62 : : }
63 : : }
64 : :
65 : : /** @file
66 : : * This file contains the implementation of the PCD Interrupt handlers.
67 : : *
68 : : * The PCD handles the device interrupts. Many conditions can cause a
69 : : * device interrupt. When an interrupt occurs, the device interrupt
70 : : * service routine determines the cause of the interrupt and
71 : : * dispatches handling to the appropriate function. These interrupt
72 : : * handling functions are described below.
73 : : * All interrupt registers are processed from LSB to MSB.
74 : : */
75 : :
76 : : /**
77 : : * This function prints the ep0 state for debug purposes.
78 : : */
79 : : static inline void print_ep0_state(dwc_otg_pcd_t * pcd)
80 : : {
81 : : #ifdef DEBUG
82 : : char str[40];
83 : :
84 : : switch (pcd->ep0state) {
85 : : case EP0_DISCONNECT:
86 : : dwc_strcpy(str, "EP0_DISCONNECT");
87 : : break;
88 : : case EP0_IDLE:
89 : : dwc_strcpy(str, "EP0_IDLE");
90 : : break;
91 : : case EP0_IN_DATA_PHASE:
92 : : dwc_strcpy(str, "EP0_IN_DATA_PHASE");
93 : : break;
94 : : case EP0_OUT_DATA_PHASE:
95 : : dwc_strcpy(str, "EP0_OUT_DATA_PHASE");
96 : : break;
97 : : case EP0_IN_STATUS_PHASE:
98 : : dwc_strcpy(str, "EP0_IN_STATUS_PHASE");
99 : : break;
100 : : case EP0_OUT_STATUS_PHASE:
101 : : dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");
102 : : break;
103 : : case EP0_STALL:
104 : : dwc_strcpy(str, "EP0_STALL");
105 : : break;
106 : : default:
107 : : dwc_strcpy(str, "EP0_INVALID");
108 : : }
109 : :
110 : : DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);
111 : : #endif
112 : : }
113 : :
114 : : /**
115 : : * This function calculate the size of the payload in the memory
116 : : * for out endpoints and prints size for debug purposes(used in
117 : : * 2.93a DevOutNak feature).
118 : : */
119 : : static inline void print_memory_payload(dwc_otg_pcd_t * pcd, dwc_ep_t * ep)
120 : : {
121 : : #ifdef DEBUG
122 : : deptsiz_data_t deptsiz_init = {.d32 = 0 };
123 : : deptsiz_data_t deptsiz_updt = {.d32 = 0 };
124 : : int pack_num;
125 : : unsigned payload;
126 : :
127 : : deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num];
128 : : deptsiz_updt.d32 =
129 : : DWC_READ_REG32(&pcd->core_if->dev_if->
130 : : out_ep_regs[ep->num]->doeptsiz);
131 : : /* Payload will be */
132 : : payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize;
133 : : /* Packet count is decremented every time a packet
134 : : * is written to the RxFIFO not in to the external memory
135 : : * So, if payload == 0, then it means no packet was sent to ext memory*/
136 : : pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt);
137 : : DWC_DEBUGPL(DBG_PCDV,
138 : : "Payload for EP%d-%s\n",
139 : : ep->num, (ep->is_in ? "IN" : "OUT"));
140 : : DWC_DEBUGPL(DBG_PCDV,
141 : : "Number of transfered bytes = 0x%08x\n", payload);
142 : : DWC_DEBUGPL(DBG_PCDV,
143 : : "Number of transfered packets = %d\n", pack_num);
144 : : #endif
145 : : }
146 : :
147 : :
148 : : #ifdef DWC_UTE_CFI
149 : : static inline void print_desc(struct dwc_otg_dma_desc *ddesc,
150 : : const uint8_t * epname, int descnum)
151 : : {
152 : : CFI_INFO
153 : : ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",
154 : : epname, descnum, ddesc->buf, ddesc->status.b.bytes,
155 : : ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,
156 : : ddesc->status.b.bs);
157 : : }
158 : : #endif
159 : :
160 : : /**
161 : : * This function returns pointer to in ep struct with number ep_num
162 : : */
163 : : static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
164 : : {
165 : : int i;
166 : 0 : int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
167 : 0 : if (ep_num == 0) {
168 : 0 : return &pcd->ep0;
169 : : } else {
170 : 0 : for (i = 0; i < num_in_eps; ++i) {
171 : 0 : if (pcd->in_ep[i].dwc_ep.num == ep_num)
172 : 0 : return &pcd->in_ep[i];
173 : : }
174 : : return 0;
175 : : }
176 : : }
177 : :
178 : : /**
179 : : * This function returns pointer to out ep struct with number ep_num
180 : : */
181 : : static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
182 : : {
183 : : int i;
184 : 0 : int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
185 : 0 : if (ep_num == 0) {
186 : 0 : return &pcd->ep0;
187 : : } else {
188 : 0 : for (i = 0; i < num_out_eps; ++i) {
189 : 0 : if (pcd->out_ep[i].dwc_ep.num == ep_num)
190 : 0 : return &pcd->out_ep[i];
191 : : }
192 : : return 0;
193 : : }
194 : : }
195 : :
196 : : /**
197 : : * This functions gets a pointer to an EP from the wIndex address
198 : : * value of the control request.
199 : : */
200 : 0 : dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)
201 : : {
202 : : dwc_otg_pcd_ep_t *ep;
203 : 0 : uint32_t ep_num = UE_GET_ADDR(wIndex);
204 : :
205 : 0 : if (ep_num == 0) {
206 : 0 : ep = &pcd->ep0;
207 : 0 : } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) { /* in ep */
208 : 0 : ep = &pcd->in_ep[ep_num - 1];
209 : : } else {
210 : 0 : ep = &pcd->out_ep[ep_num - 1];
211 : : }
212 : :
213 : 0 : return ep;
214 : : }
215 : :
216 : : /**
217 : : * This function checks the EP request queue, if the queue is not
218 : : * empty the next request is started.
219 : : */
220 : 0 : void start_next_request(dwc_otg_pcd_ep_t * ep)
221 : : {
222 : : dwc_otg_pcd_request_t *req = 0;
223 : 0 : uint32_t max_transfer =
224 : 0 : GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;
225 : :
226 : : #ifdef DWC_UTE_CFI
227 : : struct dwc_otg_pcd *pcd;
228 : : pcd = ep->pcd;
229 : : #endif
230 : :
231 : 0 : if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
232 : : req = DWC_CIRCLEQ_FIRST(&ep->queue);
233 : :
234 : : #ifdef DWC_UTE_CFI
235 : : if (ep->dwc_ep.buff_mode != BM_STANDARD) {
236 : : ep->dwc_ep.cfi_req_len = req->length;
237 : : pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);
238 : : } else {
239 : : #endif
240 : : /* Setup and start the Transfer */
241 : 0 : if (req->dw_align_buf) {
242 : 0 : ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
243 : 0 : ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
244 : 0 : ep->dwc_ep.xfer_buff = req->dw_align_buf;
245 : : } else {
246 : 0 : ep->dwc_ep.dma_addr = req->dma;
247 : 0 : ep->dwc_ep.start_xfer_buff = req->buf;
248 : 0 : ep->dwc_ep.xfer_buff = req->buf;
249 : : }
250 : 0 : ep->dwc_ep.sent_zlp = 0;
251 : 0 : ep->dwc_ep.total_len = req->length;
252 : 0 : ep->dwc_ep.xfer_len = 0;
253 : 0 : ep->dwc_ep.xfer_count = 0;
254 : :
255 : 0 : ep->dwc_ep.maxxfer = max_transfer;
256 : 0 : if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {
257 : : uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE
258 : : - (DDMA_MAX_TRANSFER_SIZE % 4);
259 : 0 : if (ep->dwc_ep.is_in) {
260 : 0 : if (ep->dwc_ep.maxxfer >
261 : : DDMA_MAX_TRANSFER_SIZE) {
262 : 0 : ep->dwc_ep.maxxfer =
263 : : DDMA_MAX_TRANSFER_SIZE;
264 : : }
265 : : } else {
266 : 0 : if (ep->dwc_ep.maxxfer > out_max_xfer) {
267 : 0 : ep->dwc_ep.maxxfer =
268 : : out_max_xfer;
269 : : }
270 : : }
271 : : }
272 : 0 : if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
273 : 0 : ep->dwc_ep.maxxfer -=
274 : 0 : (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);
275 : : }
276 : 0 : if (req->sent_zlp) {
277 : 0 : if ((ep->dwc_ep.total_len %
278 : 0 : ep->dwc_ep.maxpacket == 0)
279 : 0 : && (ep->dwc_ep.total_len != 0)) {
280 : 0 : ep->dwc_ep.sent_zlp = 1;
281 : : }
282 : :
283 : : }
284 : : #ifdef DWC_UTE_CFI
285 : : }
286 : : #endif
287 : 0 : dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
288 : 0 : } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
289 : 0 : DWC_PRINTF("There are no more ISOC requests \n");
290 : 0 : ep->dwc_ep.frame_num = 0xFFFFFFFF;
291 : : }
292 : 0 : }
293 : :
294 : : /**
295 : : * This function handles the SOF Interrupts. At this time the SOF
296 : : * Interrupt is disabled.
297 : : */
298 : 0 : int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)
299 : : {
300 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
301 : :
302 : : gintsts_data_t gintsts;
303 : :
304 : : DWC_DEBUGPL(DBG_PCD, "SOF\n");
305 : :
306 : : /* Clear interrupt */
307 : 0 : gintsts.d32 = 0;
308 : 0 : gintsts.b.sofintr = 1;
309 : 0 : DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
310 : :
311 : 0 : return 1;
312 : : }
313 : :
314 : : /**
315 : : * This function handles the Rx Status Queue Level Interrupt, which
316 : : * indicates that there is a least one packet in the Rx FIFO. The
317 : : * packets are moved from the FIFO to memory, where they will be
318 : : * processed when the Endpoint Interrupt Register indicates Transfer
319 : : * Complete or SETUP Phase Done.
320 : : *
321 : : * Repeat the following until the Rx Status Queue is empty:
322 : : * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
323 : : * info
324 : : * -# If Receive FIFO is empty then skip to step Clear the interrupt
325 : : * and exit
326 : : * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
327 : : * SETUP data to the buffer
328 : : * -# If OUT Data Packet call dwc_otg_read_packet to copy the data
329 : : * to the destination buffer
330 : : */
331 : 0 : int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
332 : : {
333 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
334 : 0 : dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
335 : 0 : gintmsk_data_t gintmask = {.d32 = 0 };
336 : : device_grxsts_data_t status;
337 : : dwc_otg_pcd_ep_t *ep;
338 : : gintsts_data_t gintsts;
339 : : #ifdef DEBUG
340 : : static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };
341 : : #endif
342 : :
343 : : //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
344 : : /* Disable the Rx Status Queue Level interrupt */
345 : 0 : gintmask.b.rxstsqlvl = 1;
346 : 0 : DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);
347 : :
348 : : /* Get the Status from the top of the FIFO */
349 : 0 : status.d32 = DWC_READ_REG32(&global_regs->grxstsp);
350 : :
351 : : DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "
352 : : "pktsts:%x Frame:%d(0x%0x)\n",
353 : : status.b.epnum, status.b.bcnt,
354 : : dpid_str[status.b.dpid],
355 : : status.b.pktsts, status.b.fn, status.b.fn);
356 : : /* Get pointer to EP structure */
357 : 0 : ep = get_out_ep(pcd, status.b.epnum);
358 : :
359 : 0 : switch (status.b.pktsts) {
360 : : case DWC_DSTS_GOUT_NAK:
361 : : DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
362 : : break;
363 : : case DWC_STS_DATA_UPDT:
364 : : DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
365 : 0 : if (status.b.bcnt && ep->dwc_ep.xfer_buff) {
366 : : /** @todo NGS Check for buffer overflow? */
367 : 0 : dwc_otg_read_packet(core_if,
368 : : ep->dwc_ep.xfer_buff,
369 : 0 : status.b.bcnt);
370 : 0 : ep->dwc_ep.xfer_count += status.b.bcnt;
371 : 0 : ep->dwc_ep.xfer_buff += status.b.bcnt;
372 : : }
373 : : break;
374 : : case DWC_STS_XFER_COMP:
375 : : DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
376 : : break;
377 : : case DWC_DSTS_SETUP_COMP:
378 : : #ifdef DEBUG_EP0
379 : : DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
380 : : #endif
381 : : break;
382 : : case DWC_DSTS_SETUP_UPDT:
383 : 0 : dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
384 : : #ifdef DEBUG_EP0
385 : : DWC_DEBUGPL(DBG_PCD,
386 : : "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
387 : : pcd->setup_pkt->req.bmRequestType,
388 : : pcd->setup_pkt->req.bRequest,
389 : : UGETW(pcd->setup_pkt->req.wValue),
390 : : UGETW(pcd->setup_pkt->req.wIndex),
391 : : UGETW(pcd->setup_pkt->req.wLength));
392 : : #endif
393 : 0 : ep->dwc_ep.xfer_count += status.b.bcnt;
394 : 0 : break;
395 : : default:
396 : : DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",
397 : : status.b.pktsts);
398 : : break;
399 : : }
400 : :
401 : : /* Enable the Rx Status Queue Level interrupt */
402 : 0 : DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);
403 : : /* Clear interrupt */
404 : 0 : gintsts.d32 = 0;
405 : 0 : gintsts.b.rxstsqlvl = 1;
406 : 0 : DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
407 : :
408 : : //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
409 : 0 : return 1;
410 : : }
411 : :
412 : : /**
413 : : * This function examines the Device IN Token Learning Queue to
414 : : * determine the EP number of the last IN token received. This
415 : : * implementation is for the Mass Storage device where there are only
416 : : * 2 IN EPs (Control-IN and BULK-IN).
417 : : *
418 : : * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
419 : : * are 8 EP Numbers in each of the other possible DTKNQ Registers.
420 : : *
421 : : * @param core_if Programming view of DWC_otg controller.
422 : : *
423 : : */
424 : 0 : static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)
425 : : {
426 : 0 : dwc_otg_device_global_regs_t *dev_global_regs =
427 : 0 : core_if->dev_if->dev_global_regs;
428 : 0 : const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
429 : : /* Number of Token Queue Registers */
430 : 0 : const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
431 : : dtknq1_data_t dtknqr1;
432 : : uint32_t in_tkn_epnums[4];
433 : : int ndx = 0;
434 : : int i = 0;
435 : 0 : volatile uint32_t *addr = &dev_global_regs->dtknqr1;
436 : : int epnum = 0;
437 : :
438 : : //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
439 : :
440 : : /* Read the DTKNQ Registers */
441 : 0 : for (i = 0; i < DTKNQ_REG_CNT; i++) {
442 : 0 : in_tkn_epnums[i] = DWC_READ_REG32(addr);
443 : : DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
444 : : in_tkn_epnums[i]);
445 : 0 : if (addr == &dev_global_regs->dvbusdis) {
446 : 0 : addr = &dev_global_regs->dtknqr3_dthrctl;
447 : : } else {
448 : 0 : ++addr;
449 : : }
450 : :
451 : : }
452 : :
453 : : /* Copy the DTKNQR1 data to the bit field. */
454 : 0 : dtknqr1.d32 = in_tkn_epnums[0];
455 : : /* Get the EP numbers */
456 : 0 : in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
457 : 0 : ndx = dtknqr1.b.intknwptr - 1;
458 : :
459 : : //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
460 : 0 : if (ndx == -1) {
461 : : /** @todo Find a simpler way to calculate the max
462 : : * queue position.*/
463 : : int cnt = TOKEN_Q_DEPTH;
464 : 0 : if (TOKEN_Q_DEPTH <= 6) {
465 : 0 : cnt = TOKEN_Q_DEPTH - 1;
466 : 0 : } else if (TOKEN_Q_DEPTH <= 14) {
467 : 0 : cnt = TOKEN_Q_DEPTH - 7;
468 : 0 : } else if (TOKEN_Q_DEPTH <= 22) {
469 : 0 : cnt = TOKEN_Q_DEPTH - 15;
470 : : } else {
471 : 0 : cnt = TOKEN_Q_DEPTH - 23;
472 : : }
473 : 0 : epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
474 : : } else {
475 : 0 : if (ndx <= 5) {
476 : 0 : epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
477 : 0 : } else if (ndx <= 13) {
478 : 0 : ndx -= 6;
479 : 0 : epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
480 : 0 : } else if (ndx <= 21) {
481 : 0 : ndx -= 14;
482 : 0 : epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
483 : 0 : } else if (ndx <= 29) {
484 : 0 : ndx -= 22;
485 : 0 : epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
486 : : }
487 : : }
488 : : //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
489 : 0 : return epnum;
490 : : }
491 : :
492 : : /**
493 : : * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
494 : : * The active request is checked for the next packet to be loaded into
495 : : * the non-periodic Tx FIFO.
496 : : */
497 : 0 : int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)
498 : : {
499 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
500 : 0 : dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
501 : : dwc_otg_dev_in_ep_regs_t *ep_regs;
502 : : gnptxsts_data_t txstatus = {.d32 = 0 };
503 : : gintsts_data_t gintsts;
504 : :
505 : : int epnum = 0;
506 : : dwc_otg_pcd_ep_t *ep = 0;
507 : : uint32_t len = 0;
508 : : int dwords;
509 : :
510 : : /* Get the epnum from the IN Token Learning Queue. */
511 : 0 : epnum = get_ep_of_last_in_token(core_if);
512 : 0 : ep = get_in_ep(pcd, epnum);
513 : :
514 : : DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);
515 : :
516 : : ep_regs = core_if->dev_if->in_ep_regs[epnum];
517 : :
518 : 0 : len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
519 : 0 : if (len > ep->dwc_ep.maxpacket) {
520 : : len = ep->dwc_ep.maxpacket;
521 : : }
522 : 0 : dwords = (len + 3) / 4;
523 : :
524 : : /* While there is space in the queue and space in the FIFO and
525 : : * More data to tranfer, Write packets to the Tx FIFO */
526 : 0 : txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
527 : : DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);
528 : :
529 : 0 : while (txstatus.b.nptxqspcavail > 0 &&
530 : 0 : txstatus.b.nptxfspcavail > dwords &&
531 : 0 : ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
532 : : /* Write the FIFO */
533 : 0 : dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
534 : 0 : len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
535 : :
536 : 0 : if (len > ep->dwc_ep.maxpacket) {
537 : : len = ep->dwc_ep.maxpacket;
538 : : }
539 : :
540 : 0 : dwords = (len + 3) / 4;
541 : 0 : txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
542 : : DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);
543 : : }
544 : :
545 : : DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
546 : : DWC_READ_REG32(&global_regs->gnptxsts));
547 : :
548 : : /* Clear interrupt */
549 : 0 : gintsts.d32 = 0;
550 : 0 : gintsts.b.nptxfempty = 1;
551 : 0 : DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
552 : :
553 : 0 : return 1;
554 : : }
555 : :
556 : : /**
557 : : * This function is called when dedicated Tx FIFO Empty interrupt occurs.
558 : : * The active request is checked for the next packet to be loaded into
559 : : * apropriate Tx FIFO.
560 : : */
561 : 0 : static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
562 : : {
563 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
564 : 0 : dwc_otg_dev_if_t *dev_if = core_if->dev_if;
565 : : dwc_otg_dev_in_ep_regs_t *ep_regs;
566 : : dtxfsts_data_t txstatus = {.d32 = 0 };
567 : : dwc_otg_pcd_ep_t *ep = 0;
568 : : uint32_t len = 0;
569 : : int dwords;
570 : :
571 : : ep = get_in_ep(pcd, epnum);
572 : :
573 : : DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
574 : :
575 : : ep_regs = core_if->dev_if->in_ep_regs[epnum];
576 : :
577 : 0 : len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
578 : :
579 : 0 : if (len > ep->dwc_ep.maxpacket) {
580 : : len = ep->dwc_ep.maxpacket;
581 : : }
582 : :
583 : 0 : dwords = (len + 3) / 4;
584 : :
585 : : /* While there is space in the queue and space in the FIFO and
586 : : * More data to tranfer, Write packets to the Tx FIFO */
587 : 0 : txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
588 : : DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
589 : :
590 : 0 : while (txstatus.b.txfspcavail > dwords &&
591 : 0 : ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
592 : 0 : ep->dwc_ep.xfer_len != 0) {
593 : : /* Write the FIFO */
594 : 0 : dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
595 : :
596 : 0 : len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
597 : 0 : if (len > ep->dwc_ep.maxpacket) {
598 : : len = ep->dwc_ep.maxpacket;
599 : : }
600 : :
601 : 0 : dwords = (len + 3) / 4;
602 : 0 : txstatus.d32 =
603 : 0 : DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
604 : : DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
605 : : txstatus.d32);
606 : : }
607 : :
608 : : DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
609 : : DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
610 : :
611 : 0 : return 1;
612 : : }
613 : :
614 : : /**
615 : : * This function is called when the Device is disconnected. It stops
616 : : * any active requests and informs the Gadget driver of the
617 : : * disconnect.
618 : : */
619 : 0 : void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)
620 : : {
621 : : int i, num_in_eps, num_out_eps;
622 : : dwc_otg_pcd_ep_t *ep;
623 : :
624 : 0 : gintmsk_data_t intr_mask = {.d32 = 0 };
625 : :
626 : 0 : DWC_SPINLOCK(pcd->lock);
627 : :
628 : 0 : num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
629 : 0 : num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
630 : :
631 : : DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);
632 : : /* don't disconnect drivers more than once */
633 : 0 : if (pcd->ep0state == EP0_DISCONNECT) {
634 : : DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);
635 : 0 : DWC_SPINUNLOCK(pcd->lock);
636 : 0 : return;
637 : : }
638 : 0 : pcd->ep0state = EP0_DISCONNECT;
639 : :
640 : : /* Reset the OTG state. */
641 : : dwc_otg_pcd_update_otg(pcd, 1);
642 : :
643 : : /* Disable the NP Tx Fifo Empty Interrupt. */
644 : 0 : intr_mask.b.nptxfempty = 1;
645 : 0 : DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
646 : : intr_mask.d32, 0);
647 : :
648 : : /* Flush the FIFOs */
649 : : /**@todo NGS Flush Periodic FIFOs */
650 : 0 : dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);
651 : 0 : dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
652 : :
653 : : /* prevent new request submissions, kill any outstanding requests */
654 : 0 : ep = &pcd->ep0;
655 : 0 : dwc_otg_request_nuke(ep);
656 : : /* prevent new request submissions, kill any outstanding requests */
657 : 0 : for (i = 0; i < num_in_eps; i++) {
658 : 0 : dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];
659 : 0 : dwc_otg_request_nuke(ep);
660 : : }
661 : : /* prevent new request submissions, kill any outstanding requests */
662 : 0 : for (i = 0; i < num_out_eps; i++) {
663 : 0 : dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];
664 : 0 : dwc_otg_request_nuke(ep);
665 : : }
666 : :
667 : : /* report disconnect; the driver is already quiesced */
668 : 0 : if (pcd->fops->disconnect) {
669 : 0 : DWC_SPINUNLOCK(pcd->lock);
670 : 0 : pcd->fops->disconnect(pcd);
671 : 0 : DWC_SPINLOCK(pcd->lock);
672 : : }
673 : 0 : DWC_SPINUNLOCK(pcd->lock);
674 : : }
675 : :
676 : : /**
677 : : * This interrupt indicates that ...
678 : : */
679 : 0 : int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)
680 : : {
681 : 0 : gintmsk_data_t intr_mask = {.d32 = 0 };
682 : : gintsts_data_t gintsts;
683 : :
684 : 0 : DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");
685 : 0 : intr_mask.b.i2cintr = 1;
686 : 0 : DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
687 : : intr_mask.d32, 0);
688 : :
689 : : /* Clear interrupt */
690 : 0 : gintsts.d32 = 0;
691 : 0 : gintsts.b.i2cintr = 1;
692 : 0 : DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
693 : : gintsts.d32);
694 : 0 : return 1;
695 : : }
696 : :
697 : : /**
698 : : * This interrupt indicates that ...
699 : : */
700 : 0 : int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)
701 : : {
702 : : gintsts_data_t gintsts;
703 : : #if defined(VERBOSE)
704 : : DWC_PRINTF("Early Suspend Detected\n");
705 : : #endif
706 : :
707 : : /* Clear interrupt */
708 : 0 : gintsts.d32 = 0;
709 : 0 : gintsts.b.erlysuspend = 1;
710 : 0 : DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
711 : : gintsts.d32);
712 : 0 : return 1;
713 : : }
714 : :
715 : : /**
716 : : * This function configures EPO to receive SETUP packets.
717 : : *
718 : : * @todo NGS: Update the comments from the HW FS.
719 : : *
720 : : * -# Program the following fields in the endpoint specific registers
721 : : * for Control OUT EP 0, in order to receive a setup packet
722 : : * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
723 : : * setup packets)
724 : : * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
725 : : * to back setup packets)
726 : : * - In DMA mode, DOEPDMA0 Register with a memory address to
727 : : * store any setup packets received
728 : : *
729 : : * @param core_if Programming view of DWC_otg controller.
730 : : * @param pcd Programming view of the PCD.
731 : : */
732 : 0 : static inline void ep0_out_start(dwc_otg_core_if_t * core_if,
733 : : dwc_otg_pcd_t * pcd)
734 : : {
735 : 0 : dwc_otg_dev_if_t *dev_if = core_if->dev_if;
736 : 0 : deptsiz0_data_t doeptsize0 = {.d32 = 0 };
737 : : dwc_otg_dev_dma_desc_t *dma_desc;
738 : : depctl_data_t doepctl = {.d32 = 0 };
739 : :
740 : : #ifdef VERBOSE
741 : : DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,
742 : : DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
743 : : #endif
744 : 0 : if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
745 : 0 : doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
746 : 0 : if (doepctl.b.epena) {
747 : 0 : return;
748 : : }
749 : : }
750 : :
751 : 0 : doeptsize0.b.supcnt = 3;
752 : 0 : doeptsize0.b.pktcnt = 1;
753 : 0 : doeptsize0.b.xfersize = 8 * 3;
754 : :
755 : 0 : if (core_if->dma_enable) {
756 : 0 : if (!core_if->dma_desc_enable) {
757 : : /** put here as for Hermes mode deptisz register should not be written */
758 : 0 : DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
759 : : doeptsize0.d32);
760 : :
761 : : /** @todo dma needs to handle multiple setup packets (up to 3) */
762 : 0 : DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
763 : : pcd->setup_pkt_dma_handle);
764 : : } else {
765 : 0 : dev_if->setup_desc_index =
766 : 0 : (dev_if->setup_desc_index + 1) & 1;
767 : 0 : dma_desc =
768 : : dev_if->setup_desc_addr[dev_if->setup_desc_index];
769 : :
770 : : /** DMA Descriptor Setup */
771 : 0 : dma_desc->status.b.bs = BS_HOST_BUSY;
772 : 0 : if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
773 : 0 : dma_desc->status.b.sr = 0;
774 : 0 : dma_desc->status.b.mtrf = 0;
775 : : }
776 : 0 : dma_desc->status.b.l = 1;
777 : 0 : dma_desc->status.b.ioc = 1;
778 : 0 : dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
779 : 0 : dma_desc->buf = pcd->setup_pkt_dma_handle;
780 : 0 : dma_desc->status.b.sts = 0;
781 : 0 : dma_desc->status.b.bs = BS_HOST_READY;
782 : :
783 : : /** DOEPDMA0 Register write */
784 : 0 : DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
785 : : dev_if->dma_setup_desc_addr
786 : 0 : [dev_if->setup_desc_index]);
787 : : }
788 : :
789 : : } else {
790 : : /** put here as for Hermes mode deptisz register should not be written */
791 : 0 : DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
792 : : doeptsize0.d32);
793 : : }
794 : :
795 : : /** DOEPCTL0 Register write cnak will be set after setup interrupt */
796 : 0 : doepctl.d32 = 0;
797 : 0 : doepctl.b.epena = 1;
798 : 0 : if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
799 : 0 : doepctl.b.cnak = 1;
800 : 0 : DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
801 : : } else {
802 : 0 : DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);
803 : : }
804 : :
805 : : #ifdef VERBOSE
806 : : DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
807 : : DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
808 : : DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
809 : : DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
810 : : #endif
811 : : }
812 : :
813 : : /**
814 : : * This interrupt occurs when a USB Reset is detected. When the USB
815 : : * Reset Interrupt occurs the device state is set to DEFAULT and the
816 : : * EP0 state is set to IDLE.
817 : : * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
818 : : * -# Unmask the following interrupt bits
819 : : * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
820 : : * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
821 : : * - DOEPMSK.SETUP = 1
822 : : * - DOEPMSK.XferCompl = 1
823 : : * - DIEPMSK.XferCompl = 1
824 : : * - DIEPMSK.TimeOut = 1
825 : : * -# Program the following fields in the endpoint specific registers
826 : : * for Control OUT EP 0, in order to receive a setup packet
827 : : * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
828 : : * setup packets)
829 : : * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
830 : : * to back setup packets)
831 : : * - In DMA mode, DOEPDMA0 Register with a memory address to
832 : : * store any setup packets received
833 : : * At this point, all the required initialization, except for enabling
834 : : * the control 0 OUT endpoint is done, for receiving SETUP packets.
835 : : */
836 : 0 : int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
837 : : {
838 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
839 : 0 : dwc_otg_dev_if_t *dev_if = core_if->dev_if;
840 : 0 : depctl_data_t doepctl = {.d32 = 0 };
841 : : depctl_data_t diepctl = {.d32 = 0 };
842 : 0 : daint_data_t daintmsk = {.d32 = 0 };
843 : 0 : doepmsk_data_t doepmsk = {.d32 = 0 };
844 : 0 : diepmsk_data_t diepmsk = {.d32 = 0 };
845 : : dcfg_data_t dcfg = {.d32 = 0 };
846 : 0 : grstctl_t resetctl = {.d32 = 0 };
847 : 0 : dctl_data_t dctl = {.d32 = 0 };
848 : : int i = 0;
849 : : gintsts_data_t gintsts;
850 : : pcgcctl_data_t power = {.d32 = 0 };
851 : :
852 : 0 : power.d32 = DWC_READ_REG32(core_if->pcgcctl);
853 : 0 : if (power.b.stoppclk) {
854 : 0 : power.d32 = 0;
855 : 0 : power.b.stoppclk = 1;
856 : 0 : DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
857 : :
858 : 0 : power.b.pwrclmp = 1;
859 : 0 : DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
860 : :
861 : 0 : power.b.rstpdwnmodule = 1;
862 : 0 : DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
863 : : }
864 : :
865 : 0 : core_if->lx_state = DWC_OTG_L0;
866 : :
867 : 0 : DWC_PRINTF("USB RESET\n");
868 : : #ifdef DWC_EN_ISOC
869 : : for (i = 1; i < 16; ++i) {
870 : : dwc_otg_pcd_ep_t *ep;
871 : : dwc_ep_t *dwc_ep;
872 : : ep = get_in_ep(pcd, i);
873 : : if (ep != 0) {
874 : : dwc_ep = &ep->dwc_ep;
875 : : dwc_ep->next_frame = 0xffffffff;
876 : : }
877 : : }
878 : : #endif /* DWC_EN_ISOC */
879 : :
880 : : /* reset the HNP settings */
881 : : dwc_otg_pcd_update_otg(pcd, 1);
882 : :
883 : : /* Clear the Remote Wakeup Signalling */
884 : 0 : dctl.b.rmtwkupsig = 1;
885 : 0 : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
886 : :
887 : : /* Set NAK for all OUT EPs */
888 : 0 : doepctl.b.snak = 1;
889 : 0 : for (i = 0; i <= dev_if->num_out_eps; i++) {
890 : 0 : DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
891 : : }
892 : :
893 : : /* Flush the NP Tx FIFO */
894 : 0 : dwc_otg_flush_tx_fifo(core_if, 0x10);
895 : : /* Flush the Learning Queue */
896 : 0 : resetctl.b.intknqflsh = 1;
897 : 0 : DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
898 : :
899 : 0 : if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
900 : 0 : core_if->start_predict = 0;
901 : 0 : for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
902 : 0 : core_if->nextep_seq[i] = 0xff; // 0xff - EP not active
903 : : }
904 : 0 : core_if->nextep_seq[0] = 0;
905 : 0 : core_if->first_in_nextep_seq = 0;
906 : 0 : diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
907 : 0 : diepctl.b.nextep = 0;
908 : 0 : DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
909 : :
910 : : /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
911 : 0 : dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
912 : 0 : dcfg.b.epmscnt = 2;
913 : 0 : DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
914 : :
915 : : DWC_DEBUGPL(DBG_PCDV,
916 : : "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
917 : : __func__, core_if->first_in_nextep_seq);
918 : 0 : for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
919 : : DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
920 : : }
921 : : }
922 : :
923 : 0 : if (core_if->multiproc_int_enable) {
924 : 0 : daintmsk.b.inep0 = 1;
925 : 0 : daintmsk.b.outep0 = 1;
926 : 0 : DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk,
927 : : daintmsk.d32);
928 : :
929 : 0 : doepmsk.b.setup = 1;
930 : 0 : doepmsk.b.xfercompl = 1;
931 : 0 : doepmsk.b.ahberr = 1;
932 : 0 : doepmsk.b.epdisabled = 1;
933 : :
934 : 0 : if ((core_if->dma_desc_enable) ||
935 : 0 : (core_if->dma_enable
936 : 0 : && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
937 : 0 : doepmsk.b.stsphsercvd = 1;
938 : : }
939 : 0 : if (core_if->dma_desc_enable)
940 : 0 : doepmsk.b.bna = 1;
941 : : /*
942 : : doepmsk.b.babble = 1;
943 : : doepmsk.b.nyet = 1;
944 : :
945 : : if (core_if->dma_enable) {
946 : : doepmsk.b.nak = 1;
947 : : }
948 : : */
949 : 0 : DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0],
950 : : doepmsk.d32);
951 : :
952 : 0 : diepmsk.b.xfercompl = 1;
953 : 0 : diepmsk.b.timeout = 1;
954 : 0 : diepmsk.b.epdisabled = 1;
955 : 0 : diepmsk.b.ahberr = 1;
956 : 0 : diepmsk.b.intknepmis = 1;
957 : 0 : if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
958 : 0 : diepmsk.b.intknepmis = 0;
959 : :
960 : : /* if (core_if->dma_desc_enable) {
961 : : diepmsk.b.bna = 1;
962 : : }
963 : : */
964 : : /*
965 : : if (core_if->dma_enable) {
966 : : diepmsk.b.nak = 1;
967 : : }
968 : : */
969 : 0 : DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0],
970 : : diepmsk.d32);
971 : : } else {
972 : 0 : daintmsk.b.inep0 = 1;
973 : 0 : daintmsk.b.outep0 = 1;
974 : 0 : DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,
975 : : daintmsk.d32);
976 : :
977 : 0 : doepmsk.b.setup = 1;
978 : 0 : doepmsk.b.xfercompl = 1;
979 : 0 : doepmsk.b.ahberr = 1;
980 : 0 : doepmsk.b.epdisabled = 1;
981 : :
982 : 0 : if ((core_if->dma_desc_enable) ||
983 : 0 : (core_if->dma_enable
984 : 0 : && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
985 : 0 : doepmsk.b.stsphsercvd = 1;
986 : : }
987 : 0 : if (core_if->dma_desc_enable)
988 : 0 : doepmsk.b.bna = 1;
989 : 0 : DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
990 : :
991 : 0 : diepmsk.b.xfercompl = 1;
992 : 0 : diepmsk.b.timeout = 1;
993 : 0 : diepmsk.b.epdisabled = 1;
994 : 0 : diepmsk.b.ahberr = 1;
995 : 0 : if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
996 : 0 : diepmsk.b.intknepmis = 0;
997 : : /*
998 : : if (core_if->dma_desc_enable) {
999 : : diepmsk.b.bna = 1;
1000 : : }
1001 : : */
1002 : :
1003 : 0 : DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
1004 : : }
1005 : :
1006 : : /* Reset Device Address */
1007 : 0 : dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
1008 : 0 : dcfg.b.devaddr = 0;
1009 : 0 : DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
1010 : :
1011 : : /* setup EP0 to receive SETUP packets */
1012 : 0 : if (core_if->snpsid <= OTG_CORE_REV_2_94a)
1013 : 0 : ep0_out_start(core_if, pcd);
1014 : :
1015 : : /* Clear interrupt */
1016 : 0 : gintsts.d32 = 0;
1017 : 0 : gintsts.b.usbreset = 1;
1018 : 0 : DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
1019 : :
1020 : 0 : return 1;
1021 : : }
1022 : :
1023 : : /**
1024 : : * Get the device speed from the device status register and convert it
1025 : : * to USB speed constant.
1026 : : *
1027 : : * @param core_if Programming view of DWC_otg controller.
1028 : : */
1029 : 0 : static int get_device_speed(dwc_otg_core_if_t * core_if)
1030 : : {
1031 : : dsts_data_t dsts;
1032 : : int speed = 0;
1033 : 0 : dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
1034 : :
1035 : 0 : switch (dsts.b.enumspd) {
1036 : : case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
1037 : : speed = USB_SPEED_HIGH;
1038 : : break;
1039 : : case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
1040 : : case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
1041 : : speed = USB_SPEED_FULL;
1042 : 0 : break;
1043 : :
1044 : : case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
1045 : : speed = USB_SPEED_LOW;
1046 : 0 : break;
1047 : : }
1048 : :
1049 : 0 : return speed;
1050 : : }
1051 : :
1052 : : /**
1053 : : * Read the device status register and set the device speed in the
1054 : : * data structure.
1055 : : * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
1056 : : */
1057 : 0 : int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
1058 : : {
1059 : : dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
1060 : : gintsts_data_t gintsts;
1061 : : gusbcfg_data_t gusbcfg;
1062 : 0 : dwc_otg_core_global_regs_t *global_regs =
1063 : 0 : GET_CORE_IF(pcd)->core_global_regs;
1064 : : uint8_t utmi16b, utmi8b;
1065 : : int speed;
1066 : : DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
1067 : :
1068 : 0 : if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
1069 : : utmi16b = 6; //vahrama old value was 6;
1070 : : utmi8b = 9;
1071 : : } else {
1072 : : utmi16b = 4;
1073 : : utmi8b = 8;
1074 : : }
1075 : 0 : dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
1076 : 0 : if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) {
1077 : 0 : ep0_out_start(GET_CORE_IF(pcd), pcd);
1078 : : }
1079 : :
1080 : : #ifdef DEBUG_EP0
1081 : : print_ep0_state(pcd);
1082 : : #endif
1083 : :
1084 : 0 : if (pcd->ep0state == EP0_DISCONNECT) {
1085 : 0 : pcd->ep0state = EP0_IDLE;
1086 : 0 : } else if (pcd->ep0state == EP0_STALL) {
1087 : 0 : pcd->ep0state = EP0_IDLE;
1088 : : }
1089 : :
1090 : 0 : pcd->ep0state = EP0_IDLE;
1091 : :
1092 : 0 : ep0->stopped = 0;
1093 : :
1094 : 0 : speed = get_device_speed(GET_CORE_IF(pcd));
1095 : 0 : pcd->fops->connect(pcd, speed);
1096 : :
1097 : : /* Set USB turnaround time based on device speed and PHY interface. */
1098 : 0 : gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
1099 : 0 : if (speed == USB_SPEED_HIGH) {
1100 : 0 : if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
1101 : : DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
1102 : : /* ULPI interface */
1103 : 0 : gusbcfg.b.usbtrdtim = 9;
1104 : : }
1105 : 0 : if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
1106 : : DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
1107 : : /* UTMI+ interface */
1108 : 0 : if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {
1109 : 0 : gusbcfg.b.usbtrdtim = utmi8b;
1110 : 0 : } else if (GET_CORE_IF(pcd)->hwcfg4.
1111 : : b.utmi_phy_data_width == 1) {
1112 : 0 : gusbcfg.b.usbtrdtim = utmi16b;
1113 : 0 : } else if (GET_CORE_IF(pcd)->
1114 : 0 : core_params->phy_utmi_width == 8) {
1115 : 0 : gusbcfg.b.usbtrdtim = utmi8b;
1116 : : } else {
1117 : 0 : gusbcfg.b.usbtrdtim = utmi16b;
1118 : : }
1119 : : }
1120 : 0 : if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
1121 : : DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
1122 : : /* UTMI+ OR ULPI interface */
1123 : 0 : if (gusbcfg.b.ulpi_utmi_sel == 1) {
1124 : : /* ULPI interface */
1125 : 0 : gusbcfg.b.usbtrdtim = 9;
1126 : : } else {
1127 : : /* UTMI+ interface */
1128 : 0 : if (GET_CORE_IF(pcd)->
1129 : 0 : core_params->phy_utmi_width == 16) {
1130 : 0 : gusbcfg.b.usbtrdtim = utmi16b;
1131 : : } else {
1132 : 0 : gusbcfg.b.usbtrdtim = utmi8b;
1133 : : }
1134 : : }
1135 : : }
1136 : : } else {
1137 : : /* Full or low speed */
1138 : 0 : gusbcfg.b.usbtrdtim = 9;
1139 : : }
1140 : 0 : DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);
1141 : :
1142 : : /* Clear interrupt */
1143 : 0 : gintsts.d32 = 0;
1144 : 0 : gintsts.b.enumdone = 1;
1145 : 0 : DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
1146 : : gintsts.d32);
1147 : 0 : return 1;
1148 : : }
1149 : :
1150 : : /**
1151 : : * This interrupt indicates that the ISO OUT Packet was dropped due to
1152 : : * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs
1153 : : * read all the data from the Rx FIFO.
1154 : : */
1155 : 0 : int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)
1156 : : {
1157 : 0 : gintmsk_data_t intr_mask = {.d32 = 0 };
1158 : : gintsts_data_t gintsts;
1159 : :
1160 : 0 : DWC_WARN("INTERRUPT Handler not implemented for %s\n",
1161 : : "ISOC Out Dropped");
1162 : :
1163 : 0 : intr_mask.b.isooutdrop = 1;
1164 : 0 : DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
1165 : : intr_mask.d32, 0);
1166 : :
1167 : : /* Clear interrupt */
1168 : 0 : gintsts.d32 = 0;
1169 : 0 : gintsts.b.isooutdrop = 1;
1170 : 0 : DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
1171 : : gintsts.d32);
1172 : :
1173 : 0 : return 1;
1174 : : }
1175 : :
1176 : : /**
1177 : : * This interrupt indicates the end of the portion of the micro-frame
1178 : : * for periodic transactions. If there is a periodic transaction for
1179 : : * the next frame, load the packets into the EP periodic Tx FIFO.
1180 : : */
1181 : 0 : int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)
1182 : : {
1183 : 0 : gintmsk_data_t intr_mask = {.d32 = 0 };
1184 : : gintsts_data_t gintsts;
1185 : 0 : DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");
1186 : :
1187 : 0 : intr_mask.b.eopframe = 1;
1188 : 0 : DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
1189 : : intr_mask.d32, 0);
1190 : :
1191 : : /* Clear interrupt */
1192 : 0 : gintsts.d32 = 0;
1193 : 0 : gintsts.b.eopframe = 1;
1194 : 0 : DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
1195 : : gintsts.d32);
1196 : :
1197 : 0 : return 1;
1198 : : }
1199 : :
1200 : : /**
1201 : : * This interrupt indicates that EP of the packet on the top of the
1202 : : * non-periodic Tx FIFO does not match EP of the IN Token received.
1203 : : *
1204 : : * The "Device IN Token Queue" Registers are read to determine the
1205 : : * order the IN Tokens have been received. The non-periodic Tx FIFO
1206 : : * is flushed, so it can be reloaded in the order seen in the IN Token
1207 : : * Queue.
1208 : : */
1209 : 0 : int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd)
1210 : : {
1211 : : gintsts_data_t gintsts;
1212 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
1213 : : dctl_data_t dctl;
1214 : 0 : gintmsk_data_t intr_mask = {.d32 = 0 };
1215 : :
1216 : 0 : if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) {
1217 : 0 : core_if->start_predict = 1;
1218 : :
1219 : : DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
1220 : :
1221 : 0 : gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
1222 : 0 : if (!gintsts.b.ginnakeff) {
1223 : : /* Disable EP Mismatch interrupt */
1224 : : intr_mask.d32 = 0;
1225 : 0 : intr_mask.b.epmismatch = 1;
1226 : 0 : DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
1227 : : /* Enable the Global IN NAK Effective Interrupt */
1228 : 0 : intr_mask.d32 = 0;
1229 : 0 : intr_mask.b.ginnakeff = 1;
1230 : 0 : DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
1231 : : /* Set the global non-periodic IN NAK handshake */
1232 : 0 : dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
1233 : 0 : dctl.b.sgnpinnak = 1;
1234 : 0 : DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
1235 : : } else {
1236 : 0 : DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n");
1237 : : }
1238 : : /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective()
1239 : : * handler after Global IN NAK Effective interrupt will be asserted */
1240 : : }
1241 : : /* Clear interrupt */
1242 : 0 : gintsts.d32 = 0;
1243 : 0 : gintsts.b.epmismatch = 1;
1244 : 0 : DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
1245 : :
1246 : 0 : return 1;
1247 : : }
1248 : :
1249 : : /**
1250 : : * This interrupt is valid only in DMA mode. This interrupt indicates that the
1251 : : * core has stopped fetching data for IN endpoints due to the unavailability of
1252 : : * TxFIFO space or Request Queue space. This interrupt is used by the
1253 : : * application for an endpoint mismatch algorithm.
1254 : : *
1255 : : * @param pcd The PCD
1256 : : */
1257 : 0 : int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd)
1258 : : {
1259 : : gintsts_data_t gintsts;
1260 : : gintmsk_data_t gintmsk_data;
1261 : : dctl_data_t dctl;
1262 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
1263 : : DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
1264 : :
1265 : : /* Clear the global non-periodic IN NAK handshake */
1266 : 0 : dctl.d32 = 0;
1267 : 0 : dctl.b.cgnpinnak = 1;
1268 : 0 : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
1269 : :
1270 : : /* Mask GINTSTS.FETSUSP interrupt */
1271 : 0 : gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
1272 : 0 : gintmsk_data.b.fetsusp = 0;
1273 : 0 : DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32);
1274 : :
1275 : : /* Clear interrupt */
1276 : 0 : gintsts.d32 = 0;
1277 : 0 : gintsts.b.fetsusp = 1;
1278 : 0 : DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
1279 : :
1280 : 0 : return 1;
1281 : : }
1282 : : /**
1283 : : * This funcion stalls EP0.
1284 : : */
1285 : 0 : static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
1286 : : {
1287 : : dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
1288 : 0 : usb_device_request_t *ctrl = &pcd->setup_pkt->req;
1289 : 0 : DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
1290 : : ctrl->bmRequestType, ctrl->bRequest, err_val);
1291 : :
1292 : 0 : ep0->dwc_ep.is_in = 1;
1293 : 0 : dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
1294 : 0 : pcd->ep0.stopped = 1;
1295 : 0 : pcd->ep0state = EP0_IDLE;
1296 : 0 : ep0_out_start(GET_CORE_IF(pcd), pcd);
1297 : 0 : }
1298 : :
1299 : : /**
1300 : : * This functions delegates the setup command to the gadget driver.
1301 : : */
1302 : 0 : static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,
1303 : : usb_device_request_t * ctrl)
1304 : : {
1305 : : int ret = 0;
1306 : 0 : DWC_SPINUNLOCK(pcd->lock);
1307 : 0 : ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);
1308 : 0 : DWC_SPINLOCK(pcd->lock);
1309 : 0 : if (ret < 0) {
1310 : 0 : ep0_do_stall(pcd, ret);
1311 : : }
1312 : :
1313 : : /** @todo This is a g_file_storage gadget driver specific
1314 : : * workaround: a DELAYED_STATUS result from the fsg_setup
1315 : : * routine will result in the gadget queueing a EP0 IN status
1316 : : * phase for a two-stage control transfer. Exactly the same as
1317 : : * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
1318 : : * specific request. Need a generic way to know when the gadget
1319 : : * driver will queue the status phase. Can we assume when we
1320 : : * call the gadget driver setup() function that it will always
1321 : : * queue and require the following flag? Need to look into
1322 : : * this.
1323 : : */
1324 : :
1325 : 0 : if (ret == 256 + 999) {
1326 : 0 : pcd->request_config = 1;
1327 : : }
1328 : 0 : }
1329 : :
1330 : : #ifdef DWC_UTE_CFI
1331 : : /**
1332 : : * This functions delegates the CFI setup commands to the gadget driver.
1333 : : * This function will return a negative value to indicate a failure.
1334 : : */
1335 : : static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,
1336 : : struct cfi_usb_ctrlrequest *ctrl_req)
1337 : : {
1338 : : int ret = 0;
1339 : :
1340 : : if (pcd->fops && pcd->fops->cfi_setup) {
1341 : : DWC_SPINUNLOCK(pcd->lock);
1342 : : ret = pcd->fops->cfi_setup(pcd, ctrl_req);
1343 : : DWC_SPINLOCK(pcd->lock);
1344 : : if (ret < 0) {
1345 : : ep0_do_stall(pcd, ret);
1346 : : return ret;
1347 : : }
1348 : : }
1349 : :
1350 : : return ret;
1351 : : }
1352 : : #endif
1353 : :
1354 : : /**
1355 : : * This function starts the Zero-Length Packet for the IN status phase
1356 : : * of a 2 stage control transfer.
1357 : : */
1358 : 0 : static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)
1359 : : {
1360 : : dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
1361 : 0 : if (pcd->ep0state == EP0_STALL) {
1362 : 0 : return;
1363 : : }
1364 : :
1365 : 0 : pcd->ep0state = EP0_IN_STATUS_PHASE;
1366 : :
1367 : : /* Prepare for more SETUP Packets */
1368 : : DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
1369 : 0 : if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a)
1370 : 0 : && (pcd->core_if->dma_desc_enable)
1371 : 0 : && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) {
1372 : : DWC_DEBUGPL(DBG_PCDV,
1373 : : "Data terminated wait next packet in out_desc_addr\n");
1374 : 0 : pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr);
1375 : 0 : pcd->data_terminated = 1;
1376 : : }
1377 : 0 : ep0->dwc_ep.xfer_len = 0;
1378 : 0 : ep0->dwc_ep.xfer_count = 0;
1379 : 0 : ep0->dwc_ep.is_in = 1;
1380 : 0 : ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
1381 : 0 : dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
1382 : :
1383 : : /* Prepare for more SETUP Packets */
1384 : : //ep0_out_start(GET_CORE_IF(pcd), pcd);
1385 : : }
1386 : :
1387 : : /**
1388 : : * This function starts the Zero-Length Packet for the OUT status phase
1389 : : * of a 2 stage control transfer.
1390 : : */
1391 : 0 : static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)
1392 : : {
1393 : : dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
1394 : 0 : if (pcd->ep0state == EP0_STALL) {
1395 : : DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
1396 : 0 : return;
1397 : : }
1398 : 0 : pcd->ep0state = EP0_OUT_STATUS_PHASE;
1399 : :
1400 : : DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
1401 : 0 : ep0->dwc_ep.xfer_len = 0;
1402 : 0 : ep0->dwc_ep.xfer_count = 0;
1403 : 0 : ep0->dwc_ep.is_in = 0;
1404 : 0 : ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
1405 : 0 : dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
1406 : :
1407 : : /* Prepare for more SETUP Packets */
1408 : 0 : if (GET_CORE_IF(pcd)->dma_enable == 0) {
1409 : 0 : ep0_out_start(GET_CORE_IF(pcd), pcd);
1410 : : }
1411 : : }
1412 : :
1413 : : /**
1414 : : * Clear the EP halt (STALL) and if pending requests start the
1415 : : * transfer.
1416 : : */
1417 : 0 : static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
1418 : : {
1419 : 0 : if (ep->dwc_ep.stall_clear_flag == 0)
1420 : 0 : dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
1421 : :
1422 : : /* Reactive the EP */
1423 : 0 : dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
1424 : 0 : if (ep->stopped) {
1425 : 0 : ep->stopped = 0;
1426 : : /* If there is a request in the EP queue start it */
1427 : :
1428 : : /** @todo FIXME: this causes an EP mismatch in DMA mode.
1429 : : * epmismatch not yet implemented. */
1430 : :
1431 : : /*
1432 : : * Above fixme is solved by implmenting a tasklet to call the
1433 : : * start_next_request(), outside of interrupt context at some
1434 : : * time after the current time, after a clear-halt setup packet.
1435 : : * Still need to implement ep mismatch in the future if a gadget
1436 : : * ever uses more than one endpoint at once
1437 : : */
1438 : 0 : ep->queue_sof = 1;
1439 : 0 : DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);
1440 : : }
1441 : : /* Start Control Status Phase */
1442 : 0 : do_setup_in_status_phase(pcd);
1443 : 0 : }
1444 : :
1445 : : /**
1446 : : * This function is called when the SET_FEATURE TEST_MODE Setup packet
1447 : : * is sent from the host. The Device Control register is written with
1448 : : * the Test Mode bits set to the specified Test Mode. This is done as
1449 : : * a tasklet so that the "Status" phase of the control transfer
1450 : : * completes before transmitting the TEST packets.
1451 : : *
1452 : : * @todo This has not been tested since the tasklet struct was put
1453 : : * into the PCD struct!
1454 : : *
1455 : : */
1456 : 0 : void do_test_mode(void *data)
1457 : : {
1458 : : dctl_data_t dctl;
1459 : : dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
1460 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
1461 : 0 : int test_mode = pcd->test_mode;
1462 : :
1463 : : // DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
1464 : :
1465 : 0 : dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
1466 : 0 : switch (test_mode) {
1467 : : case 1: // TEST_J
1468 : 0 : dctl.b.tstctl = 1;
1469 : 0 : break;
1470 : :
1471 : : case 2: // TEST_K
1472 : 0 : dctl.b.tstctl = 2;
1473 : 0 : break;
1474 : :
1475 : : case 3: // TEST_SE0_NAK
1476 : 0 : dctl.b.tstctl = 3;
1477 : 0 : break;
1478 : :
1479 : : case 4: // TEST_PACKET
1480 : 0 : dctl.b.tstctl = 4;
1481 : 0 : break;
1482 : :
1483 : : case 5: // TEST_FORCE_ENABLE
1484 : 0 : dctl.b.tstctl = 5;
1485 : 0 : break;
1486 : : }
1487 : 0 : DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
1488 : 0 : }
1489 : :
1490 : : /**
1491 : : * This function process the GET_STATUS Setup Commands.
1492 : : */
1493 : 0 : static inline void do_get_status(dwc_otg_pcd_t * pcd)
1494 : : {
1495 : 0 : usb_device_request_t ctrl = pcd->setup_pkt->req;
1496 : : dwc_otg_pcd_ep_t *ep;
1497 : : dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
1498 : 0 : uint16_t *status = pcd->status_buf;
1499 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
1500 : :
1501 : : #ifdef DEBUG_EP0
1502 : : DWC_DEBUGPL(DBG_PCD,
1503 : : "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
1504 : : ctrl.bmRequestType, ctrl.bRequest,
1505 : : UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
1506 : : UGETW(ctrl.wLength));
1507 : : #endif
1508 : :
1509 : 0 : switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
1510 : : case UT_DEVICE:
1511 : 0 : if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */
1512 : 0 : DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex));
1513 : 0 : DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver);
1514 : 0 : DWC_PRINTF("OTG CAP - %d, %d\n",
1515 : 0 : core_if->core_params->otg_cap,
1516 : : DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
1517 : 0 : if (core_if->otg_ver == 1
1518 : 0 : && core_if->core_params->otg_cap ==
1519 : : DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
1520 : 0 : uint8_t *otgsts = (uint8_t*)pcd->status_buf;
1521 : 0 : *otgsts = (core_if->otg_sts & 0x1);
1522 : 0 : pcd->ep0_pending = 1;
1523 : 0 : ep0->dwc_ep.start_xfer_buff =
1524 : : (uint8_t *) otgsts;
1525 : 0 : ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts;
1526 : 0 : ep0->dwc_ep.dma_addr =
1527 : 0 : pcd->status_buf_dma_handle;
1528 : 0 : ep0->dwc_ep.xfer_len = 1;
1529 : 0 : ep0->dwc_ep.xfer_count = 0;
1530 : 0 : ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
1531 : 0 : dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
1532 : : &ep0->dwc_ep);
1533 : 0 : return;
1534 : : } else {
1535 : 0 : ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
1536 : 0 : return;
1537 : : }
1538 : : break;
1539 : : } else {
1540 : 0 : *status = 0x1; /* Self powered */
1541 : 0 : *status |= pcd->remote_wakeup_enable << 1;
1542 : 0 : break;
1543 : : }
1544 : : case UT_INTERFACE:
1545 : 0 : *status = 0;
1546 : 0 : break;
1547 : :
1548 : : case UT_ENDPOINT:
1549 : 0 : ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
1550 : 0 : if (ep == 0 || UGETW(ctrl.wLength) > 2) {
1551 : 0 : ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
1552 : 0 : return;
1553 : : }
1554 : : /** @todo check for EP stall */
1555 : 0 : *status = ep->stopped;
1556 : 0 : break;
1557 : : }
1558 : 0 : pcd->ep0_pending = 1;
1559 : 0 : ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
1560 : 0 : ep0->dwc_ep.xfer_buff = (uint8_t *) status;
1561 : 0 : ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
1562 : 0 : ep0->dwc_ep.xfer_len = 2;
1563 : 0 : ep0->dwc_ep.xfer_count = 0;
1564 : 0 : ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
1565 : 0 : dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
1566 : : }
1567 : :
1568 : : /**
1569 : : * This function process the SET_FEATURE Setup Commands.
1570 : : */
1571 : 0 : static inline void do_set_feature(dwc_otg_pcd_t * pcd)
1572 : : {
1573 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
1574 : 0 : dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
1575 : 0 : usb_device_request_t ctrl = pcd->setup_pkt->req;
1576 : : dwc_otg_pcd_ep_t *ep = 0;
1577 : 0 : int32_t otg_cap_param = core_if->core_params->otg_cap;
1578 : 0 : gotgctl_data_t gotgctl = {.d32 = 0 };
1579 : :
1580 : : DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
1581 : : ctrl.bmRequestType, ctrl.bRequest,
1582 : : UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
1583 : : UGETW(ctrl.wLength));
1584 : : DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);
1585 : :
1586 : 0 : switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
1587 : : case UT_DEVICE:
1588 : 0 : switch (UGETW(ctrl.wValue)) {
1589 : : case UF_DEVICE_REMOTE_WAKEUP:
1590 : 0 : pcd->remote_wakeup_enable = 1;
1591 : 0 : break;
1592 : :
1593 : : case UF_TEST_MODE:
1594 : : /* Setup the Test Mode tasklet to do the Test
1595 : : * Packet generation after the SETUP Status
1596 : : * phase has completed. */
1597 : :
1598 : : /** @todo This has not been tested since the
1599 : : * tasklet struct was put into the PCD
1600 : : * struct! */
1601 : 0 : pcd->test_mode = UGETW(ctrl.wIndex) >> 8;
1602 : 0 : DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);
1603 : 0 : break;
1604 : :
1605 : : case UF_DEVICE_B_HNP_ENABLE:
1606 : : DWC_DEBUGPL(DBG_PCDV,
1607 : : "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
1608 : :
1609 : : /* dev may initiate HNP */
1610 : 0 : if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
1611 : 0 : pcd->b_hnp_enable = 1;
1612 : : dwc_otg_pcd_update_otg(pcd, 0);
1613 : : DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
1614 : : /**@todo Is the gotgctl.devhnpen cleared
1615 : : * by a USB Reset? */
1616 : 0 : gotgctl.b.devhnpen = 1;
1617 : 0 : gotgctl.b.hnpreq = 1;
1618 : 0 : DWC_WRITE_REG32(&global_regs->gotgctl,
1619 : : gotgctl.d32);
1620 : : } else {
1621 : 0 : ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
1622 : 0 : return;
1623 : : }
1624 : 0 : break;
1625 : :
1626 : : case UF_DEVICE_A_HNP_SUPPORT:
1627 : : /* RH port supports HNP */
1628 : : DWC_DEBUGPL(DBG_PCDV,
1629 : : "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
1630 : 0 : if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
1631 : 0 : pcd->a_hnp_support = 1;
1632 : : dwc_otg_pcd_update_otg(pcd, 0);
1633 : : } else {
1634 : 0 : ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
1635 : 0 : return;
1636 : : }
1637 : : break;
1638 : :
1639 : : case UF_DEVICE_A_ALT_HNP_SUPPORT:
1640 : : /* other RH port does */
1641 : : DWC_DEBUGPL(DBG_PCDV,
1642 : : "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
1643 : 0 : if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
1644 : 0 : pcd->a_alt_hnp_support = 1;
1645 : : dwc_otg_pcd_update_otg(pcd, 0);
1646 : : } else {
1647 : 0 : ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
1648 : 0 : return;
1649 : : }
1650 : : break;
1651 : :
1652 : : default:
1653 : 0 : ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
1654 : 0 : return;
1655 : :
1656 : : }
1657 : 0 : do_setup_in_status_phase(pcd);
1658 : 0 : break;
1659 : :
1660 : : case UT_INTERFACE:
1661 : 0 : do_gadget_setup(pcd, &ctrl);
1662 : 0 : break;
1663 : :
1664 : : case UT_ENDPOINT:
1665 : 0 : if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {
1666 : 0 : ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
1667 : 0 : if (ep == 0) {
1668 : 0 : ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
1669 : 0 : return;
1670 : : }
1671 : 0 : ep->stopped = 1;
1672 : 0 : dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
1673 : : }
1674 : 0 : do_setup_in_status_phase(pcd);
1675 : 0 : break;
1676 : : }
1677 : : }
1678 : :
1679 : : /**
1680 : : * This function process the CLEAR_FEATURE Setup Commands.
1681 : : */
1682 : 0 : static inline void do_clear_feature(dwc_otg_pcd_t * pcd)
1683 : : {
1684 : 0 : usb_device_request_t ctrl = pcd->setup_pkt->req;
1685 : : dwc_otg_pcd_ep_t *ep = 0;
1686 : :
1687 : : DWC_DEBUGPL(DBG_PCD,
1688 : : "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
1689 : : ctrl.bmRequestType, ctrl.bRequest,
1690 : : UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
1691 : : UGETW(ctrl.wLength));
1692 : :
1693 : 0 : switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
1694 : : case UT_DEVICE:
1695 : 0 : switch (UGETW(ctrl.wValue)) {
1696 : : case UF_DEVICE_REMOTE_WAKEUP:
1697 : 0 : pcd->remote_wakeup_enable = 0;
1698 : 0 : break;
1699 : :
1700 : : case UF_TEST_MODE:
1701 : : /** @todo Add CLEAR_FEATURE for TEST modes. */
1702 : : break;
1703 : :
1704 : : default:
1705 : 0 : ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
1706 : 0 : return;
1707 : : }
1708 : 0 : do_setup_in_status_phase(pcd);
1709 : 0 : break;
1710 : :
1711 : : case UT_ENDPOINT:
1712 : 0 : ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
1713 : 0 : if (ep == 0) {
1714 : 0 : ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
1715 : 0 : return;
1716 : : }
1717 : :
1718 : 0 : pcd_clear_halt(pcd, ep);
1719 : :
1720 : 0 : break;
1721 : : }
1722 : : }
1723 : :
1724 : : /**
1725 : : * This function process the SET_ADDRESS Setup Commands.
1726 : : */
1727 : 0 : static inline void do_set_address(dwc_otg_pcd_t * pcd)
1728 : : {
1729 : 0 : dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
1730 : 0 : usb_device_request_t ctrl = pcd->setup_pkt->req;
1731 : :
1732 : 0 : if (ctrl.bmRequestType == UT_DEVICE) {
1733 : 0 : dcfg_data_t dcfg = {.d32 = 0 };
1734 : :
1735 : : #ifdef DEBUG_EP0
1736 : : // DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
1737 : : #endif
1738 : 0 : dcfg.b.devaddr = UGETW(ctrl.wValue);
1739 : 0 : DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
1740 : 0 : do_setup_in_status_phase(pcd);
1741 : : }
1742 : 0 : }
1743 : :
1744 : : /**
1745 : : * This function processes SETUP commands. In Linux, the USB Command
1746 : : * processing is done in two places - the first being the PCD and the
1747 : : * second in the Gadget Driver (for example, the File-Backed Storage
1748 : : * Gadget Driver).
1749 : : *
1750 : : * <table>
1751 : : * <tr><td>Command </td><td>Driver </td><td>Description</td></tr>
1752 : : *
1753 : : * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
1754 : : * defined in chapter 9 of the USB 2.0 Specification chapter 9
1755 : : * </td></tr>
1756 : : *
1757 : : * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
1758 : : * requests are the ENDPOINT_HALT feature is procesed, all others the
1759 : : * interface requests are ignored.</td></tr>
1760 : : *
1761 : : * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
1762 : : * requests are processed by the PCD. Interface requests are passed
1763 : : * to the Gadget Driver.</td></tr>
1764 : : *
1765 : : * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
1766 : : * with device address received </td></tr>
1767 : : *
1768 : : * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
1769 : : * requested descriptor</td></tr>
1770 : : *
1771 : : * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
1772 : : * not implemented by any of the existing Gadget Drivers.</td></tr>
1773 : : *
1774 : : * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
1775 : : * all EPs and enable EPs for new configuration.</td></tr>
1776 : : *
1777 : : * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
1778 : : * the current configuration</td></tr>
1779 : : *
1780 : : * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
1781 : : * EPs and enable EPs for new configuration.</td></tr>
1782 : : *
1783 : : * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
1784 : : * current interface.</td></tr>
1785 : : *
1786 : : * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
1787 : : * message.</td></tr>
1788 : : * </table>
1789 : : *
1790 : : * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
1791 : : * processed by pcd_setup. Calling the Function Driver's setup function from
1792 : : * pcd_setup processes the gadget SETUP commands.
1793 : : */
1794 : 0 : static inline void pcd_setup(dwc_otg_pcd_t * pcd)
1795 : : {
1796 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
1797 : 0 : dwc_otg_dev_if_t *dev_if = core_if->dev_if;
1798 : 0 : usb_device_request_t ctrl = pcd->setup_pkt->req;
1799 : 0 : dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
1800 : :
1801 : : deptsiz0_data_t doeptsize0 = {.d32 = 0 };
1802 : :
1803 : : #ifdef DWC_UTE_CFI
1804 : : int retval = 0;
1805 : : struct cfi_usb_ctrlrequest cfi_req;
1806 : : #endif
1807 : :
1808 : 0 : doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz);
1809 : :
1810 : : /** In BDMA more then 1 setup packet is not supported till 3.00a */
1811 : 0 : if (core_if->dma_enable && core_if->dma_desc_enable == 0
1812 : 0 : && (doeptsize0.b.supcnt < 2)
1813 : 0 : && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
1814 : 0 : DWC_ERROR
1815 : : ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n");
1816 : : }
1817 : 0 : if ((core_if->snpsid >= OTG_CORE_REV_3_00a)
1818 : 0 : && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) {
1819 : 0 : ctrl =
1820 : 0 : (pcd->setup_pkt +
1821 : 0 : (3 - doeptsize0.b.supcnt - 1 +
1822 : 0 : ep0->dwc_ep.stp_rollover))->req;
1823 : : }
1824 : : #ifdef DEBUG_EP0
1825 : : DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
1826 : : ctrl.bmRequestType, ctrl.bRequest,
1827 : : UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
1828 : : UGETW(ctrl.wLength));
1829 : : #endif
1830 : :
1831 : : /* Clean up the request queue */
1832 : 0 : dwc_otg_request_nuke(ep0);
1833 : 0 : ep0->stopped = 0;
1834 : :
1835 : 0 : if (ctrl.bmRequestType & UE_DIR_IN) {
1836 : 0 : ep0->dwc_ep.is_in = 1;
1837 : 0 : pcd->ep0state = EP0_IN_DATA_PHASE;
1838 : : } else {
1839 : 0 : ep0->dwc_ep.is_in = 0;
1840 : 0 : pcd->ep0state = EP0_OUT_DATA_PHASE;
1841 : : }
1842 : :
1843 : 0 : if (UGETW(ctrl.wLength) == 0) {
1844 : 0 : ep0->dwc_ep.is_in = 1;
1845 : 0 : pcd->ep0state = EP0_IN_STATUS_PHASE;
1846 : : }
1847 : :
1848 : 0 : if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {
1849 : :
1850 : : #ifdef DWC_UTE_CFI
1851 : : DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
1852 : :
1853 : : //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n",
1854 : : ctrl.bRequestType, ctrl.bRequest);
1855 : : if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
1856 : : if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
1857 : : retval = cfi_setup(pcd, &cfi_req);
1858 : : if (retval < 0) {
1859 : : ep0_do_stall(pcd, retval);
1860 : : pcd->ep0_pending = 0;
1861 : : return;
1862 : : }
1863 : :
1864 : : /* if need gadget setup then call it and check the retval */
1865 : : if (pcd->cfi->need_gadget_att) {
1866 : : retval =
1867 : : cfi_gadget_setup(pcd,
1868 : : &pcd->
1869 : : cfi->ctrl_req);
1870 : : if (retval < 0) {
1871 : : pcd->ep0_pending = 0;
1872 : : return;
1873 : : }
1874 : : }
1875 : :
1876 : : if (pcd->cfi->need_status_in_complete) {
1877 : : do_setup_in_status_phase(pcd);
1878 : : }
1879 : : return;
1880 : : }
1881 : : }
1882 : : #endif
1883 : :
1884 : : /* handle non-standard (class/vendor) requests in the gadget driver */
1885 : 0 : do_gadget_setup(pcd, &ctrl);
1886 : 0 : return;
1887 : : }
1888 : :
1889 : : /** @todo NGS: Handle bad setup packet? */
1890 : :
1891 : : ///////////////////////////////////////////
1892 : : //// --- Standard Request handling --- ////
1893 : :
1894 : 0 : switch (ctrl.bRequest) {
1895 : : case UR_GET_STATUS:
1896 : 0 : do_get_status(pcd);
1897 : 0 : break;
1898 : :
1899 : : case UR_CLEAR_FEATURE:
1900 : 0 : do_clear_feature(pcd);
1901 : 0 : break;
1902 : :
1903 : : case UR_SET_FEATURE:
1904 : 0 : do_set_feature(pcd);
1905 : 0 : break;
1906 : :
1907 : : case UR_SET_ADDRESS:
1908 : 0 : do_set_address(pcd);
1909 : 0 : break;
1910 : :
1911 : : case UR_SET_INTERFACE:
1912 : : case UR_SET_CONFIG:
1913 : : // _pcd->request_config = 1; /* Configuration changed */
1914 : 0 : do_gadget_setup(pcd, &ctrl);
1915 : 0 : break;
1916 : :
1917 : : case UR_SYNCH_FRAME:
1918 : 0 : do_gadget_setup(pcd, &ctrl);
1919 : 0 : break;
1920 : :
1921 : : default:
1922 : : /* Call the Gadget Driver's setup functions */
1923 : 0 : do_gadget_setup(pcd, &ctrl);
1924 : 0 : break;
1925 : : }
1926 : : }
1927 : :
1928 : : /**
1929 : : * This function completes the ep0 control transfer.
1930 : : */
1931 : 0 : static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
1932 : : {
1933 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
1934 : 0 : dwc_otg_dev_if_t *dev_if = core_if->dev_if;
1935 : 0 : dwc_otg_dev_in_ep_regs_t *in_ep_regs =
1936 : 0 : dev_if->in_ep_regs[ep->dwc_ep.num];
1937 : : #ifdef DEBUG_EP0
1938 : 0 : dwc_otg_dev_out_ep_regs_t *out_ep_regs =
1939 : : dev_if->out_ep_regs[ep->dwc_ep.num];
1940 : : #endif
1941 : : deptsiz0_data_t deptsiz;
1942 : : dev_dma_desc_sts_t desc_sts;
1943 : : dwc_otg_pcd_request_t *req;
1944 : : int is_last = 0;
1945 : : dwc_otg_pcd_t *pcd = ep->pcd;
1946 : :
1947 : : #ifdef DWC_UTE_CFI
1948 : : struct cfi_usb_ctrlrequest *ctrlreq;
1949 : : int retval = -DWC_E_NOT_SUPPORTED;
1950 : : #endif
1951 : :
1952 : : desc_sts.b.bytes = 0;
1953 : :
1954 : 0 : if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {
1955 : 0 : if (ep->dwc_ep.is_in) {
1956 : : #ifdef DEBUG_EP0
1957 : : DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
1958 : : #endif
1959 : 0 : do_setup_out_status_phase(pcd);
1960 : : } else {
1961 : : #ifdef DEBUG_EP0
1962 : : DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
1963 : : #endif
1964 : :
1965 : : #ifdef DWC_UTE_CFI
1966 : : ctrlreq = &pcd->cfi->ctrl_req;
1967 : :
1968 : : if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {
1969 : : if (ctrlreq->bRequest > 0xB0
1970 : : && ctrlreq->bRequest < 0xBF) {
1971 : :
1972 : : /* Return if the PCD failed to handle the request */
1973 : : if ((retval =
1974 : : pcd->cfi->ops.
1975 : : ctrl_write_complete(pcd->cfi,
1976 : : pcd)) < 0) {
1977 : : CFI_INFO
1978 : : ("ERROR setting a new value in the PCD(%d)\n",
1979 : : retval);
1980 : : ep0_do_stall(pcd, retval);
1981 : : pcd->ep0_pending = 0;
1982 : : return 0;
1983 : : }
1984 : :
1985 : : /* If the gadget needs to be notified on the request */
1986 : : if (pcd->cfi->need_gadget_att == 1) {
1987 : : //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);
1988 : : retval =
1989 : : cfi_gadget_setup(pcd,
1990 : : &pcd->cfi->
1991 : : ctrl_req);
1992 : :
1993 : : /* Return from the function if the gadget failed to process
1994 : : * the request properly - this should never happen !!!
1995 : : */
1996 : : if (retval < 0) {
1997 : : CFI_INFO
1998 : : ("ERROR setting a new value in the gadget(%d)\n",
1999 : : retval);
2000 : : pcd->ep0_pending = 0;
2001 : : return 0;
2002 : : }
2003 : : }
2004 : :
2005 : : CFI_INFO("%s: RETVAL=%d\n", __func__,
2006 : : retval);
2007 : : /* If we hit here then the PCD and the gadget has properly
2008 : : * handled the request - so send the ZLP IN to the host.
2009 : : */
2010 : : /* @todo: MAS - decide whether we need to start the setup
2011 : : * stage based on the need_setup value of the cfi object
2012 : : */
2013 : : do_setup_in_status_phase(pcd);
2014 : : pcd->ep0_pending = 0;
2015 : : return 1;
2016 : : }
2017 : : }
2018 : : #endif
2019 : :
2020 : 0 : do_setup_in_status_phase(pcd);
2021 : : }
2022 : 0 : pcd->ep0_pending = 0;
2023 : 0 : return 1;
2024 : : }
2025 : :
2026 : 0 : if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
2027 : : return 0;
2028 : : }
2029 : : req = DWC_CIRCLEQ_FIRST(&ep->queue);
2030 : :
2031 : 0 : if (pcd->ep0state == EP0_OUT_STATUS_PHASE
2032 : 0 : || pcd->ep0state == EP0_IN_STATUS_PHASE) {
2033 : : is_last = 1;
2034 : 0 : } else if (ep->dwc_ep.is_in) {
2035 : 0 : deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
2036 : 0 : if (core_if->dma_desc_enable != 0)
2037 : 0 : desc_sts = dev_if->in_desc_addr->status;
2038 : : #ifdef DEBUG_EP0
2039 : : DWC_DEBUGPL(DBG_PCDV, "%d len=%d xfersize=%d pktcnt=%d\n",
2040 : : ep->dwc_ep.num, ep->dwc_ep.xfer_len,
2041 : : deptsiz.b.xfersize, deptsiz.b.pktcnt);
2042 : : #endif
2043 : :
2044 : 0 : if (((core_if->dma_desc_enable == 0)
2045 : 0 : && (deptsiz.b.xfersize == 0))
2046 : 0 : || ((core_if->dma_desc_enable != 0)
2047 : 0 : && (desc_sts.b.bytes == 0))) {
2048 : 0 : req->actual = ep->dwc_ep.xfer_count;
2049 : : /* Is a Zero Len Packet needed? */
2050 : 0 : if (req->sent_zlp) {
2051 : : #ifdef DEBUG_EP0
2052 : : DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
2053 : : #endif
2054 : 0 : req->sent_zlp = 0;
2055 : : }
2056 : 0 : do_setup_out_status_phase(pcd);
2057 : : }
2058 : : } else {
2059 : : /* ep0-OUT */
2060 : : #ifdef DEBUG_EP0
2061 : 0 : deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);
2062 : : DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",
2063 : : ep->dwc_ep.num, ep->dwc_ep.xfer_len,
2064 : : deptsiz.b.xfersize, deptsiz.b.pktcnt);
2065 : : #endif
2066 : 0 : req->actual = ep->dwc_ep.xfer_count;
2067 : :
2068 : : /* Is a Zero Len Packet needed? */
2069 : 0 : if (req->sent_zlp) {
2070 : : #ifdef DEBUG_EP0
2071 : : DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
2072 : : #endif
2073 : 0 : req->sent_zlp = 0;
2074 : : }
2075 : : /* For older cores do setup in status phase in Slave/BDMA modes,
2076 : : * starting from 3.00 do that only in slave, and for DMA modes
2077 : : * just re-enable ep 0 OUT here*/
2078 : 0 : if (core_if->dma_enable == 0
2079 : 0 : || (core_if->dma_desc_enable == 0
2080 : 0 : && core_if->snpsid <= OTG_CORE_REV_2_94a)) {
2081 : 0 : do_setup_in_status_phase(pcd);
2082 : 0 : } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
2083 : : DWC_DEBUGPL(DBG_PCDV,
2084 : : "Enable out ep before in status phase\n");
2085 : 0 : ep0_out_start(core_if, pcd);
2086 : : }
2087 : : }
2088 : :
2089 : : /* Complete the request */
2090 : 0 : if (is_last) {
2091 : 0 : dwc_otg_request_done(ep, req, 0);
2092 : 0 : ep->dwc_ep.start_xfer_buff = 0;
2093 : 0 : ep->dwc_ep.xfer_buff = 0;
2094 : 0 : ep->dwc_ep.xfer_len = 0;
2095 : 0 : return 1;
2096 : : }
2097 : : return 0;
2098 : : }
2099 : :
2100 : : #ifdef DWC_UTE_CFI
2101 : : /**
2102 : : * This function calculates traverses all the CFI DMA descriptors and
2103 : : * and accumulates the bytes that are left to be transfered.
2104 : : *
2105 : : * @return The total bytes left to transfered, or a negative value as failure
2106 : : */
2107 : : static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)
2108 : : {
2109 : : int32_t ret = 0;
2110 : : int i;
2111 : : struct dwc_otg_dma_desc *ddesc = NULL;
2112 : : struct cfi_ep *cfiep;
2113 : :
2114 : : /* See if the pcd_ep has its respective cfi_ep mapped */
2115 : : cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);
2116 : : if (!cfiep) {
2117 : : CFI_INFO("%s: Failed to find ep\n", __func__);
2118 : : return -1;
2119 : : }
2120 : :
2121 : : ddesc = ep->dwc_ep.descs;
2122 : :
2123 : : for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {
2124 : :
2125 : : #if defined(PRINT_CFI_DMA_DESCS)
2126 : : print_desc(ddesc, ep->ep.name, i);
2127 : : #endif
2128 : : ret += ddesc->status.b.bytes;
2129 : : ddesc++;
2130 : : }
2131 : :
2132 : : if (ret)
2133 : : CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,
2134 : : ret);
2135 : :
2136 : : return ret;
2137 : : }
2138 : : #endif
2139 : :
2140 : : /**
2141 : : * This function completes the request for the EP. If there are
2142 : : * additional requests for the EP in the queue they will be started.
2143 : : */
2144 : 0 : static void complete_ep(dwc_otg_pcd_ep_t * ep)
2145 : : {
2146 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
2147 : : struct device *dev = dwc_otg_pcd_to_dev(ep->pcd);
2148 : 0 : dwc_otg_dev_if_t *dev_if = core_if->dev_if;
2149 : 0 : dwc_otg_dev_in_ep_regs_t *in_ep_regs =
2150 : 0 : dev_if->in_ep_regs[ep->dwc_ep.num];
2151 : : deptsiz_data_t deptsiz;
2152 : : dev_dma_desc_sts_t desc_sts;
2153 : : dwc_otg_pcd_request_t *req = 0;
2154 : : dwc_otg_dev_dma_desc_t *dma_desc;
2155 : : uint32_t byte_count = 0;
2156 : : int is_last = 0;
2157 : : int i;
2158 : :
2159 : : DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,
2160 : : (ep->dwc_ep.is_in ? "IN" : "OUT"));
2161 : :
2162 : : /* Get any pending requests */
2163 : 0 : if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
2164 : : req = DWC_CIRCLEQ_FIRST(&ep->queue);
2165 : 0 : if (!req) {
2166 : 0 : DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
2167 : 0 : return;
2168 : : }
2169 : : } else {
2170 : 0 : DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
2171 : 0 : return;
2172 : : }
2173 : :
2174 : : DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);
2175 : :
2176 : 0 : if (ep->dwc_ep.is_in) {
2177 : 0 : deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
2178 : :
2179 : 0 : if (core_if->dma_enable) {
2180 : 0 : if (core_if->dma_desc_enable == 0) {
2181 : 0 : if (deptsiz.b.xfersize == 0
2182 : 0 : && deptsiz.b.pktcnt == 0) {
2183 : 0 : byte_count =
2184 : 0 : ep->dwc_ep.xfer_len -
2185 : 0 : ep->dwc_ep.xfer_count;
2186 : :
2187 : 0 : ep->dwc_ep.xfer_buff += byte_count;
2188 : 0 : ep->dwc_ep.dma_addr += byte_count;
2189 : 0 : ep->dwc_ep.xfer_count += byte_count;
2190 : :
2191 : : DWC_DEBUGPL(DBG_PCDV,
2192 : : "%d-%s len=%d xfersize=%d pktcnt=%d\n",
2193 : : ep->dwc_ep.num,
2194 : : (ep->dwc_ep.
2195 : : is_in ? "IN" : "OUT"),
2196 : : ep->dwc_ep.xfer_len,
2197 : : deptsiz.b.xfersize,
2198 : : deptsiz.b.pktcnt);
2199 : :
2200 : 0 : if (ep->dwc_ep.xfer_len <
2201 : 0 : ep->dwc_ep.total_len) {
2202 : 0 : dwc_otg_ep_start_transfer
2203 : : (core_if, &ep->dwc_ep);
2204 : 0 : } else if (ep->dwc_ep.sent_zlp) {
2205 : : /*
2206 : : * This fragment of code should initiate 0
2207 : : * length transfer in case if it is queued
2208 : : * a transfer with size divisible to EPs max
2209 : : * packet size and with usb_request zero field
2210 : : * is set, which means that after data is transfered,
2211 : : * it is also should be transfered
2212 : : * a 0 length packet at the end. For Slave and
2213 : : * Buffer DMA modes in this case SW has
2214 : : * to initiate 2 transfers one with transfer size,
2215 : : * and the second with 0 size. For Descriptor
2216 : : * DMA mode SW is able to initiate a transfer,
2217 : : * which will handle all the packets including
2218 : : * the last 0 length.
2219 : : */
2220 : 0 : ep->dwc_ep.sent_zlp = 0;
2221 : 0 : dwc_otg_ep_start_zl_transfer
2222 : : (core_if, &ep->dwc_ep);
2223 : : } else {
2224 : : is_last = 1;
2225 : : }
2226 : : } else {
2227 : 0 : if (ep->dwc_ep.type ==
2228 : : DWC_OTG_EP_TYPE_ISOC) {
2229 : 0 : req->actual = 0;
2230 : 0 : dwc_otg_request_done(ep, req, 0);
2231 : :
2232 : 0 : ep->dwc_ep.start_xfer_buff = 0;
2233 : 0 : ep->dwc_ep.xfer_buff = 0;
2234 : 0 : ep->dwc_ep.xfer_len = 0;
2235 : :
2236 : : /* If there is a request in the queue start it. */
2237 : 0 : start_next_request(ep);
2238 : : } else
2239 : 0 : DWC_WARN
2240 : : ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
2241 : : ep->dwc_ep.num,
2242 : : (ep->dwc_ep.is_in ? "IN" : "OUT"),
2243 : : deptsiz.b.xfersize,
2244 : : deptsiz.b.pktcnt);
2245 : : }
2246 : : } else {
2247 : 0 : dma_desc = ep->dwc_ep.desc_addr;
2248 : : byte_count = 0;
2249 : 0 : ep->dwc_ep.sent_zlp = 0;
2250 : :
2251 : : #ifdef DWC_UTE_CFI
2252 : : CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
2253 : : ep->dwc_ep.buff_mode);
2254 : : if (ep->dwc_ep.buff_mode != BM_STANDARD) {
2255 : : int residue;
2256 : :
2257 : : residue = cfi_calc_desc_residue(ep);
2258 : : if (residue < 0)
2259 : : return;
2260 : :
2261 : : byte_count = residue;
2262 : : } else {
2263 : : #endif
2264 : 0 : for (i = 0; i < ep->dwc_ep.desc_cnt;
2265 : 0 : ++i) {
2266 : 0 : desc_sts = dma_desc->status;
2267 : 0 : byte_count += desc_sts.b.bytes;
2268 : 0 : dma_desc++;
2269 : : }
2270 : : #ifdef DWC_UTE_CFI
2271 : : }
2272 : : #endif
2273 : 0 : if (byte_count == 0) {
2274 : 0 : ep->dwc_ep.xfer_count =
2275 : 0 : ep->dwc_ep.total_len;
2276 : : is_last = 1;
2277 : : } else {
2278 : 0 : DWC_WARN("Incomplete transfer\n");
2279 : : }
2280 : : }
2281 : : } else {
2282 : 0 : if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {
2283 : : DWC_DEBUGPL(DBG_PCDV,
2284 : : "%d-%s len=%d xfersize=%d pktcnt=%d\n",
2285 : : ep->dwc_ep.num,
2286 : : ep->dwc_ep.is_in ? "IN" : "OUT",
2287 : : ep->dwc_ep.xfer_len,
2288 : : deptsiz.b.xfersize,
2289 : : deptsiz.b.pktcnt);
2290 : :
2291 : : /* Check if the whole transfer was completed,
2292 : : * if no, setup transfer for next portion of data
2293 : : */
2294 : 0 : if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
2295 : 0 : dwc_otg_ep_start_transfer(core_if,
2296 : : &ep->dwc_ep);
2297 : 0 : } else if (ep->dwc_ep.sent_zlp) {
2298 : : /*
2299 : : * This fragment of code should initiate 0
2300 : : * length trasfer in case if it is queued
2301 : : * a trasfer with size divisible to EPs max
2302 : : * packet size and with usb_request zero field
2303 : : * is set, which means that after data is transfered,
2304 : : * it is also should be transfered
2305 : : * a 0 length packet at the end. For Slave and
2306 : : * Buffer DMA modes in this case SW has
2307 : : * to initiate 2 transfers one with transfer size,
2308 : : * and the second with 0 size. For Desriptor
2309 : : * DMA mode SW is able to initiate a transfer,
2310 : : * which will handle all the packets including
2311 : : * the last 0 legth.
2312 : : */
2313 : 0 : ep->dwc_ep.sent_zlp = 0;
2314 : 0 : dwc_otg_ep_start_zl_transfer(core_if,
2315 : : &ep->dwc_ep);
2316 : : } else {
2317 : : is_last = 1;
2318 : : }
2319 : : } else {
2320 : 0 : DWC_WARN
2321 : : ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",
2322 : : ep->dwc_ep.num,
2323 : : (ep->dwc_ep.is_in ? "IN" : "OUT"),
2324 : : deptsiz.b.xfersize, deptsiz.b.pktcnt);
2325 : : }
2326 : : }
2327 : : } else {
2328 : 0 : dwc_otg_dev_out_ep_regs_t *out_ep_regs =
2329 : : dev_if->out_ep_regs[ep->dwc_ep.num];
2330 : : desc_sts.d32 = 0;
2331 : 0 : if (core_if->dma_enable) {
2332 : 0 : if (core_if->dma_desc_enable) {
2333 : 0 : dma_desc = ep->dwc_ep.desc_addr;
2334 : : byte_count = 0;
2335 : 0 : ep->dwc_ep.sent_zlp = 0;
2336 : :
2337 : : #ifdef DWC_UTE_CFI
2338 : : CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
2339 : : ep->dwc_ep.buff_mode);
2340 : : if (ep->dwc_ep.buff_mode != BM_STANDARD) {
2341 : : int residue;
2342 : : residue = cfi_calc_desc_residue(ep);
2343 : : if (residue < 0)
2344 : : return;
2345 : : byte_count = residue;
2346 : : } else {
2347 : : #endif
2348 : :
2349 : 0 : for (i = 0; i < ep->dwc_ep.desc_cnt;
2350 : 0 : ++i) {
2351 : 0 : desc_sts = dma_desc->status;
2352 : 0 : byte_count += desc_sts.b.bytes;
2353 : 0 : dma_desc++;
2354 : : }
2355 : :
2356 : : #ifdef DWC_UTE_CFI
2357 : : }
2358 : : #endif
2359 : : /* Checking for interrupt Out transfers with not
2360 : : * dword aligned mps sizes
2361 : : */
2362 : 0 : if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR &&
2363 : 0 : (ep->dwc_ep.maxpacket%4)) {
2364 : 0 : ep->dwc_ep.xfer_count =
2365 : 0 : ep->dwc_ep.total_len - byte_count;
2366 : 0 : if ((ep->dwc_ep.xfer_len %
2367 : : ep->dwc_ep.maxpacket)
2368 : 0 : && (ep->dwc_ep.xfer_len /
2369 : : ep->dwc_ep.maxpacket <
2370 : : MAX_DMA_DESC_CNT))
2371 : 0 : ep->dwc_ep.xfer_len -=
2372 : 0 : (ep->dwc_ep.desc_cnt -
2373 : 0 : 1) * ep->dwc_ep.maxpacket +
2374 : : ep->dwc_ep.xfer_len %
2375 : : ep->dwc_ep.maxpacket;
2376 : : else
2377 : 0 : ep->dwc_ep.xfer_len -=
2378 : 0 : ep->dwc_ep.desc_cnt *
2379 : : ep->dwc_ep.maxpacket;
2380 : 0 : if (ep->dwc_ep.xfer_len > 0) {
2381 : 0 : dwc_otg_ep_start_transfer
2382 : : (core_if, &ep->dwc_ep);
2383 : : } else {
2384 : : is_last = 1;
2385 : : }
2386 : : } else {
2387 : 0 : ep->dwc_ep.xfer_count =
2388 : 0 : ep->dwc_ep.total_len - byte_count +
2389 : : ((4 -
2390 : : (ep->dwc_ep.
2391 : : total_len & 0x3)) & 0x3);
2392 : : is_last = 1;
2393 : : }
2394 : : } else {
2395 : : deptsiz.d32 = 0;
2396 : 0 : deptsiz.d32 =
2397 : 0 : DWC_READ_REG32(&out_ep_regs->doeptsiz);
2398 : :
2399 : 0 : byte_count = (ep->dwc_ep.xfer_len -
2400 : 0 : ep->dwc_ep.xfer_count -
2401 : 0 : deptsiz.b.xfersize);
2402 : 0 : ep->dwc_ep.xfer_buff += byte_count;
2403 : 0 : ep->dwc_ep.dma_addr += byte_count;
2404 : 0 : ep->dwc_ep.xfer_count += byte_count;
2405 : :
2406 : : /* Check if the whole transfer was completed,
2407 : : * if no, setup transfer for next portion of data
2408 : : */
2409 : 0 : if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
2410 : 0 : dwc_otg_ep_start_transfer(core_if,
2411 : : &ep->dwc_ep);
2412 : 0 : } else if (ep->dwc_ep.sent_zlp) {
2413 : : /*
2414 : : * This fragment of code should initiate 0
2415 : : * length trasfer in case if it is queued
2416 : : * a trasfer with size divisible to EPs max
2417 : : * packet size and with usb_request zero field
2418 : : * is set, which means that after data is transfered,
2419 : : * it is also should be transfered
2420 : : * a 0 length packet at the end. For Slave and
2421 : : * Buffer DMA modes in this case SW has
2422 : : * to initiate 2 transfers one with transfer size,
2423 : : * and the second with 0 size. For Desriptor
2424 : : * DMA mode SW is able to initiate a transfer,
2425 : : * which will handle all the packets including
2426 : : * the last 0 legth.
2427 : : */
2428 : 0 : ep->dwc_ep.sent_zlp = 0;
2429 : 0 : dwc_otg_ep_start_zl_transfer(core_if,
2430 : : &ep->dwc_ep);
2431 : : } else {
2432 : : is_last = 1;
2433 : : }
2434 : : }
2435 : : } else {
2436 : : /* Check if the whole transfer was completed,
2437 : : * if no, setup transfer for next portion of data
2438 : : */
2439 : 0 : if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
2440 : 0 : dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
2441 : 0 : } else if (ep->dwc_ep.sent_zlp) {
2442 : : /*
2443 : : * This fragment of code should initiate 0
2444 : : * length transfer in case if it is queued
2445 : : * a transfer with size divisible to EPs max
2446 : : * packet size and with usb_request zero field
2447 : : * is set, which means that after data is transfered,
2448 : : * it is also should be transfered
2449 : : * a 0 length packet at the end. For Slave and
2450 : : * Buffer DMA modes in this case SW has
2451 : : * to initiate 2 transfers one with transfer size,
2452 : : * and the second with 0 size. For Descriptor
2453 : : * DMA mode SW is able to initiate a transfer,
2454 : : * which will handle all the packets including
2455 : : * the last 0 length.
2456 : : */
2457 : 0 : ep->dwc_ep.sent_zlp = 0;
2458 : 0 : dwc_otg_ep_start_zl_transfer(core_if,
2459 : : &ep->dwc_ep);
2460 : : } else {
2461 : : is_last = 1;
2462 : : }
2463 : : }
2464 : :
2465 : : DWC_DEBUGPL(DBG_PCDV,
2466 : : "addr %p, %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",
2467 : : &out_ep_regs->doeptsiz, ep->dwc_ep.num,
2468 : : ep->dwc_ep.is_in ? "IN" : "OUT",
2469 : : ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,
2470 : : deptsiz.b.xfersize, deptsiz.b.pktcnt);
2471 : : }
2472 : :
2473 : : /* Complete the request */
2474 : 0 : if (is_last) {
2475 : : #ifdef DWC_UTE_CFI
2476 : : if (ep->dwc_ep.buff_mode != BM_STANDARD) {
2477 : : req->actual = ep->dwc_ep.cfi_req_len - byte_count;
2478 : : } else {
2479 : : #endif
2480 : 0 : req->actual = ep->dwc_ep.xfer_count;
2481 : : #ifdef DWC_UTE_CFI
2482 : : }
2483 : : #endif
2484 : 0 : if (req->dw_align_buf) {
2485 : 0 : if (!ep->dwc_ep.is_in) {
2486 : 0 : dwc_memcpy(req->buf, req->dw_align_buf, req->length);
2487 : : }
2488 : 0 : DWC_DMA_FREE(dev, req->length, req->dw_align_buf,
2489 : : req->dw_align_buf_dma);
2490 : : }
2491 : :
2492 : 0 : dwc_otg_request_done(ep, req, 0);
2493 : :
2494 : 0 : ep->dwc_ep.start_xfer_buff = 0;
2495 : 0 : ep->dwc_ep.xfer_buff = 0;
2496 : 0 : ep->dwc_ep.xfer_len = 0;
2497 : :
2498 : : /* If there is a request in the queue start it. */
2499 : 0 : start_next_request(ep);
2500 : : }
2501 : : }
2502 : :
2503 : : #ifdef DWC_EN_ISOC
2504 : :
2505 : : /**
2506 : : * This function BNA interrupt for Isochronous EPs
2507 : : *
2508 : : */
2509 : : static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)
2510 : : {
2511 : : dwc_ep_t *dwc_ep = &ep->dwc_ep;
2512 : : volatile uint32_t *addr;
2513 : : depctl_data_t depctl = {.d32 = 0 };
2514 : : dwc_otg_pcd_t *pcd = ep->pcd;
2515 : : dwc_otg_dev_dma_desc_t *dma_desc;
2516 : : int i;
2517 : :
2518 : : dma_desc =
2519 : : dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);
2520 : :
2521 : : if (dwc_ep->is_in) {
2522 : : dev_dma_desc_sts_t sts = {.d32 = 0 };
2523 : : for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
2524 : : sts.d32 = dma_desc->status.d32;
2525 : : sts.b_iso_in.bs = BS_HOST_READY;
2526 : : dma_desc->status.d32 = sts.d32;
2527 : : }
2528 : : } else {
2529 : : dev_dma_desc_sts_t sts = {.d32 = 0 };
2530 : : for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
2531 : : sts.d32 = dma_desc->status.d32;
2532 : : sts.b_iso_out.bs = BS_HOST_READY;
2533 : : dma_desc->status.d32 = sts.d32;
2534 : : }
2535 : : }
2536 : :
2537 : : if (dwc_ep->is_in == 0) {
2538 : : addr =
2539 : : &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->
2540 : : num]->doepctl;
2541 : : } else {
2542 : : addr =
2543 : : &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
2544 : : }
2545 : : depctl.b.epena = 1;
2546 : : DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
2547 : : }
2548 : :
2549 : : /**
2550 : : * This function sets latest iso packet information(non-PTI mode)
2551 : : *
2552 : : * @param core_if Programming view of DWC_otg controller.
2553 : : * @param ep The EP to start the transfer on.
2554 : : *
2555 : : */
2556 : : void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
2557 : : {
2558 : : deptsiz_data_t deptsiz = {.d32 = 0 };
2559 : : dma_addr_t dma_addr;
2560 : : uint32_t offset;
2561 : :
2562 : : if (ep->proc_buf_num)
2563 : : dma_addr = ep->dma_addr1;
2564 : : else
2565 : : dma_addr = ep->dma_addr0;
2566 : :
2567 : : if (ep->is_in) {
2568 : : deptsiz.d32 =
2569 : : DWC_READ_REG32(&core_if->dev_if->
2570 : : in_ep_regs[ep->num]->dieptsiz);
2571 : : offset = ep->data_per_frame;
2572 : : } else {
2573 : : deptsiz.d32 =
2574 : : DWC_READ_REG32(&core_if->dev_if->
2575 : : out_ep_regs[ep->num]->doeptsiz);
2576 : : offset =
2577 : : ep->data_per_frame +
2578 : : (0x4 & (0x4 - (ep->data_per_frame & 0x3)));
2579 : : }
2580 : :
2581 : : if (!deptsiz.b.xfersize) {
2582 : : ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
2583 : : ep->pkt_info[ep->cur_pkt].offset =
2584 : : ep->cur_pkt_dma_addr - dma_addr;
2585 : : ep->pkt_info[ep->cur_pkt].status = 0;
2586 : : } else {
2587 : : ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
2588 : : ep->pkt_info[ep->cur_pkt].offset =
2589 : : ep->cur_pkt_dma_addr - dma_addr;
2590 : : ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;
2591 : : }
2592 : : ep->cur_pkt_addr += offset;
2593 : : ep->cur_pkt_dma_addr += offset;
2594 : : ep->cur_pkt++;
2595 : : }
2596 : :
2597 : : /**
2598 : : * This function sets latest iso packet information(DDMA mode)
2599 : : *
2600 : : * @param core_if Programming view of DWC_otg controller.
2601 : : * @param dwc_ep The EP to start the transfer on.
2602 : : *
2603 : : */
2604 : : static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,
2605 : : dwc_ep_t * dwc_ep)
2606 : : {
2607 : : dwc_otg_dev_dma_desc_t *dma_desc;
2608 : : dev_dma_desc_sts_t sts = {.d32 = 0 };
2609 : : iso_pkt_info_t *iso_packet;
2610 : : uint32_t data_per_desc;
2611 : : uint32_t offset;
2612 : : int i, j;
2613 : :
2614 : : iso_packet = dwc_ep->pkt_info;
2615 : :
2616 : : /** Reinit closed DMA Descriptors*/
2617 : : /** ISO OUT EP */
2618 : : if (dwc_ep->is_in == 0) {
2619 : : dma_desc =
2620 : : dwc_ep->iso_desc_addr +
2621 : : dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
2622 : : offset = 0;
2623 : :
2624 : : for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
2625 : : i += dwc_ep->pkt_per_frm) {
2626 : : for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
2627 : : data_per_desc =
2628 : : ((j + 1) * dwc_ep->maxpacket >
2629 : : dwc_ep->
2630 : : data_per_frame) ? dwc_ep->data_per_frame -
2631 : : j * dwc_ep->maxpacket : dwc_ep->maxpacket;
2632 : : data_per_desc +=
2633 : : (data_per_desc % 4) ? (4 -
2634 : : data_per_desc %
2635 : : 4) : 0;
2636 : :
2637 : : sts.d32 = dma_desc->status.d32;
2638 : :
2639 : : /* Write status in iso_packet_decsriptor */
2640 : : iso_packet->status =
2641 : : sts.b_iso_out.rxsts +
2642 : : (sts.b_iso_out.bs ^ BS_DMA_DONE);
2643 : : if (iso_packet->status) {
2644 : : iso_packet->status = -DWC_E_NO_DATA;
2645 : : }
2646 : :
2647 : : /* Received data length */
2648 : : if (!sts.b_iso_out.rxbytes) {
2649 : : iso_packet->length =
2650 : : data_per_desc -
2651 : : sts.b_iso_out.rxbytes;
2652 : : } else {
2653 : : iso_packet->length =
2654 : : data_per_desc -
2655 : : sts.b_iso_out.rxbytes + (4 -
2656 : : dwc_ep->data_per_frame
2657 : : % 4);
2658 : : }
2659 : :
2660 : : iso_packet->offset = offset;
2661 : :
2662 : : offset += data_per_desc;
2663 : : dma_desc++;
2664 : : iso_packet++;
2665 : : }
2666 : : }
2667 : :
2668 : : for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
2669 : : data_per_desc =
2670 : : ((j + 1) * dwc_ep->maxpacket >
2671 : : dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
2672 : : j * dwc_ep->maxpacket : dwc_ep->maxpacket;
2673 : : data_per_desc +=
2674 : : (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
2675 : :
2676 : : sts.d32 = dma_desc->status.d32;
2677 : :
2678 : : /* Write status in iso_packet_decsriptor */
2679 : : iso_packet->status =
2680 : : sts.b_iso_out.rxsts +
2681 : : (sts.b_iso_out.bs ^ BS_DMA_DONE);
2682 : : if (iso_packet->status) {
2683 : : iso_packet->status = -DWC_E_NO_DATA;
2684 : : }
2685 : :
2686 : : /* Received data length */
2687 : : iso_packet->length =
2688 : : dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
2689 : :
2690 : : iso_packet->offset = offset;
2691 : :
2692 : : offset += data_per_desc;
2693 : : iso_packet++;
2694 : : dma_desc++;
2695 : : }
2696 : :
2697 : : sts.d32 = dma_desc->status.d32;
2698 : :
2699 : : /* Write status in iso_packet_decsriptor */
2700 : : iso_packet->status =
2701 : : sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);
2702 : : if (iso_packet->status) {
2703 : : iso_packet->status = -DWC_E_NO_DATA;
2704 : : }
2705 : : /* Received data length */
2706 : : if (!sts.b_iso_out.rxbytes) {
2707 : : iso_packet->length =
2708 : : dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
2709 : : } else {
2710 : : iso_packet->length =
2711 : : dwc_ep->data_per_frame - sts.b_iso_out.rxbytes +
2712 : : (4 - dwc_ep->data_per_frame % 4);
2713 : : }
2714 : :
2715 : : iso_packet->offset = offset;
2716 : : } else {
2717 : : /** ISO IN EP */
2718 : :
2719 : : dma_desc =
2720 : : dwc_ep->iso_desc_addr +
2721 : : dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
2722 : :
2723 : : for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
2724 : : sts.d32 = dma_desc->status.d32;
2725 : :
2726 : : /* Write status in iso packet descriptor */
2727 : : iso_packet->status =
2728 : : sts.b_iso_in.txsts +
2729 : : (sts.b_iso_in.bs ^ BS_DMA_DONE);
2730 : : if (iso_packet->status != 0) {
2731 : : iso_packet->status = -DWC_E_NO_DATA;
2732 : :
2733 : : }
2734 : : /* Bytes has been transfered */
2735 : : iso_packet->length =
2736 : : dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
2737 : :
2738 : : dma_desc++;
2739 : : iso_packet++;
2740 : : }
2741 : :
2742 : : sts.d32 = dma_desc->status.d32;
2743 : : while (sts.b_iso_in.bs == BS_DMA_BUSY) {
2744 : : sts.d32 = dma_desc->status.d32;
2745 : : }
2746 : :
2747 : : /* Write status in iso packet descriptor ??? do be done with ERROR codes */
2748 : : iso_packet->status =
2749 : : sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);
2750 : : if (iso_packet->status != 0) {
2751 : : iso_packet->status = -DWC_E_NO_DATA;
2752 : : }
2753 : :
2754 : : /* Bytes has been transfered */
2755 : : iso_packet->length =
2756 : : dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
2757 : : }
2758 : : }
2759 : :
2760 : : /**
2761 : : * This function reinitialize DMA Descriptors for Isochronous transfer
2762 : : *
2763 : : * @param core_if Programming view of DWC_otg controller.
2764 : : * @param dwc_ep The EP to start the transfer on.
2765 : : *
2766 : : */
2767 : : static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
2768 : : {
2769 : : int i, j;
2770 : : dwc_otg_dev_dma_desc_t *dma_desc;
2771 : : dma_addr_t dma_ad;
2772 : : volatile uint32_t *addr;
2773 : : dev_dma_desc_sts_t sts = {.d32 = 0 };
2774 : : uint32_t data_per_desc;
2775 : :
2776 : : if (dwc_ep->is_in == 0) {
2777 : : addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
2778 : : } else {
2779 : : addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
2780 : : }
2781 : :
2782 : : if (dwc_ep->proc_buf_num == 0) {
2783 : : /** Buffer 0 descriptors setup */
2784 : : dma_ad = dwc_ep->dma_addr0;
2785 : : } else {
2786 : : /** Buffer 1 descriptors setup */
2787 : : dma_ad = dwc_ep->dma_addr1;
2788 : : }
2789 : :
2790 : : /** Reinit closed DMA Descriptors*/
2791 : : /** ISO OUT EP */
2792 : : if (dwc_ep->is_in == 0) {
2793 : : dma_desc =
2794 : : dwc_ep->iso_desc_addr +
2795 : : dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
2796 : :
2797 : : sts.b_iso_out.bs = BS_HOST_READY;
2798 : : sts.b_iso_out.rxsts = 0;
2799 : : sts.b_iso_out.l = 0;
2800 : : sts.b_iso_out.sp = 0;
2801 : : sts.b_iso_out.ioc = 0;
2802 : : sts.b_iso_out.pid = 0;
2803 : : sts.b_iso_out.framenum = 0;
2804 : :
2805 : : for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
2806 : : i += dwc_ep->pkt_per_frm) {
2807 : : for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
2808 : : data_per_desc =
2809 : : ((j + 1) * dwc_ep->maxpacket >
2810 : : dwc_ep->
2811 : : data_per_frame) ? dwc_ep->data_per_frame -
2812 : : j * dwc_ep->maxpacket : dwc_ep->maxpacket;
2813 : : data_per_desc +=
2814 : : (data_per_desc % 4) ? (4 -
2815 : : data_per_desc %
2816 : : 4) : 0;
2817 : : sts.b_iso_out.rxbytes = data_per_desc;
2818 : : dma_desc->buf = dma_ad;
2819 : : dma_desc->status.d32 = sts.d32;
2820 : :
2821 : : dma_ad += data_per_desc;
2822 : : dma_desc++;
2823 : : }
2824 : : }
2825 : :
2826 : : for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
2827 : :
2828 : : data_per_desc =
2829 : : ((j + 1) * dwc_ep->maxpacket >
2830 : : dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
2831 : : j * dwc_ep->maxpacket : dwc_ep->maxpacket;
2832 : : data_per_desc +=
2833 : : (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
2834 : : sts.b_iso_out.rxbytes = data_per_desc;
2835 : :
2836 : : dma_desc->buf = dma_ad;
2837 : : dma_desc->status.d32 = sts.d32;
2838 : :
2839 : : dma_desc++;
2840 : : dma_ad += data_per_desc;
2841 : : }
2842 : :
2843 : : sts.b_iso_out.ioc = 1;
2844 : : sts.b_iso_out.l = dwc_ep->proc_buf_num;
2845 : :
2846 : : data_per_desc =
2847 : : ((j + 1) * dwc_ep->maxpacket >
2848 : : dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
2849 : : j * dwc_ep->maxpacket : dwc_ep->maxpacket;
2850 : : data_per_desc +=
2851 : : (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
2852 : : sts.b_iso_out.rxbytes = data_per_desc;
2853 : :
2854 : : dma_desc->buf = dma_ad;
2855 : : dma_desc->status.d32 = sts.d32;
2856 : : } else {
2857 : : /** ISO IN EP */
2858 : :
2859 : : dma_desc =
2860 : : dwc_ep->iso_desc_addr +
2861 : : dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
2862 : :
2863 : : sts.b_iso_in.bs = BS_HOST_READY;
2864 : : sts.b_iso_in.txsts = 0;
2865 : : sts.b_iso_in.sp = 0;
2866 : : sts.b_iso_in.ioc = 0;
2867 : : sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
2868 : : sts.b_iso_in.framenum = dwc_ep->next_frame;
2869 : : sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
2870 : : sts.b_iso_in.l = 0;
2871 : :
2872 : : for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
2873 : : dma_desc->buf = dma_ad;
2874 : : dma_desc->status.d32 = sts.d32;
2875 : :
2876 : : sts.b_iso_in.framenum += dwc_ep->bInterval;
2877 : : dma_ad += dwc_ep->data_per_frame;
2878 : : dma_desc++;
2879 : : }
2880 : :
2881 : : sts.b_iso_in.ioc = 1;
2882 : : sts.b_iso_in.l = dwc_ep->proc_buf_num;
2883 : :
2884 : : dma_desc->buf = dma_ad;
2885 : : dma_desc->status.d32 = sts.d32;
2886 : :
2887 : : dwc_ep->next_frame =
2888 : : sts.b_iso_in.framenum + dwc_ep->bInterval * 1;
2889 : : }
2890 : : dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
2891 : : }
2892 : :
2893 : : /**
2894 : : * This function is to handle Iso EP transfer complete interrupt
2895 : : * in case Iso out packet was dropped
2896 : : *
2897 : : * @param core_if Programming view of DWC_otg controller.
2898 : : * @param dwc_ep The EP for wihich transfer complete was asserted
2899 : : *
2900 : : */
2901 : : static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,
2902 : : dwc_ep_t * dwc_ep)
2903 : : {
2904 : : uint32_t dma_addr;
2905 : : uint32_t drp_pkt;
2906 : : uint32_t drp_pkt_cnt;
2907 : : deptsiz_data_t deptsiz = {.d32 = 0 };
2908 : : depctl_data_t depctl = {.d32 = 0 };
2909 : : int i;
2910 : :
2911 : : deptsiz.d32 =
2912 : : DWC_READ_REG32(&core_if->dev_if->
2913 : : out_ep_regs[dwc_ep->num]->doeptsiz);
2914 : :
2915 : : drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;
2916 : : drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);
2917 : :
2918 : : /* Setting dropped packets status */
2919 : : for (i = 0; i < drp_pkt_cnt; ++i) {
2920 : : dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;
2921 : : drp_pkt++;
2922 : : deptsiz.b.pktcnt--;
2923 : : }
2924 : :
2925 : : if (deptsiz.b.pktcnt > 0) {
2926 : : deptsiz.b.xfersize =
2927 : : dwc_ep->xfer_len - (dwc_ep->pkt_cnt -
2928 : : deptsiz.b.pktcnt) * dwc_ep->maxpacket;
2929 : : } else {
2930 : : deptsiz.b.xfersize = 0;
2931 : : deptsiz.b.pktcnt = 0;
2932 : : }
2933 : :
2934 : : DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,
2935 : : deptsiz.d32);
2936 : :
2937 : : if (deptsiz.b.pktcnt > 0) {
2938 : : if (dwc_ep->proc_buf_num) {
2939 : : dma_addr =
2940 : : dwc_ep->dma_addr1 + dwc_ep->xfer_len -
2941 : : deptsiz.b.xfersize;
2942 : : } else {
2943 : : dma_addr =
2944 : : dwc_ep->dma_addr0 + dwc_ep->xfer_len -
2945 : : deptsiz.b.xfersize;;
2946 : : }
2947 : :
2948 : : DWC_WRITE_REG32(&core_if->dev_if->
2949 : : out_ep_regs[dwc_ep->num]->doepdma, dma_addr);
2950 : :
2951 : : /** Re-enable endpoint, clear nak */
2952 : : depctl.d32 = 0;
2953 : : depctl.b.epena = 1;
2954 : : depctl.b.cnak = 1;
2955 : :
2956 : : DWC_MODIFY_REG32(&core_if->dev_if->
2957 : : out_ep_regs[dwc_ep->num]->doepctl, depctl.d32,
2958 : : depctl.d32);
2959 : : return 0;
2960 : : } else {
2961 : : return 1;
2962 : : }
2963 : : }
2964 : :
2965 : : /**
2966 : : * This function sets iso packets information(PTI mode)
2967 : : *
2968 : : * @param core_if Programming view of DWC_otg controller.
2969 : : * @param ep The EP to start the transfer on.
2970 : : *
2971 : : */
2972 : : static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
2973 : : {
2974 : : int i, j;
2975 : : dma_addr_t dma_ad;
2976 : : iso_pkt_info_t *packet_info = ep->pkt_info;
2977 : : uint32_t offset;
2978 : : uint32_t frame_data;
2979 : : deptsiz_data_t deptsiz;
2980 : :
2981 : : if (ep->proc_buf_num == 0) {
2982 : : /** Buffer 0 descriptors setup */
2983 : : dma_ad = ep->dma_addr0;
2984 : : } else {
2985 : : /** Buffer 1 descriptors setup */
2986 : : dma_ad = ep->dma_addr1;
2987 : : }
2988 : :
2989 : : if (ep->is_in) {
2990 : : deptsiz.d32 =
2991 : : DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
2992 : : dieptsiz);
2993 : : } else {
2994 : : deptsiz.d32 =
2995 : : DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
2996 : : doeptsiz);
2997 : : }
2998 : :
2999 : : if (!deptsiz.b.xfersize) {
3000 : : offset = 0;
3001 : : for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {
3002 : : frame_data = ep->data_per_frame;
3003 : : for (j = 0; j < ep->pkt_per_frm; ++j) {
3004 : :
3005 : : /* Packet status - is not set as initially
3006 : : * it is set to 0 and if packet was sent
3007 : : successfully, status field will remain 0*/
3008 : :
3009 : : /* Bytes has been transfered */
3010 : : packet_info->length =
3011 : : (ep->maxpacket <
3012 : : frame_data) ? ep->maxpacket : frame_data;
3013 : :
3014 : : /* Received packet offset */
3015 : : packet_info->offset = offset;
3016 : : offset += packet_info->length;
3017 : : frame_data -= packet_info->length;
3018 : :
3019 : : packet_info++;
3020 : : }
3021 : : }
3022 : : return 1;
3023 : : } else {
3024 : : /* This is a workaround for in case of Transfer Complete with
3025 : : * PktDrpSts interrupts merging - in this case Transfer complete
3026 : : * interrupt for Isoc Out Endpoint is asserted without PktDrpSts
3027 : : * set and with DOEPTSIZ register non zero. Investigations showed,
3028 : : * that this happens when Out packet is dropped, but because of
3029 : : * interrupts merging during first interrupt handling PktDrpSts
3030 : : * bit is cleared and for next merged interrupts it is not reset.
3031 : : * In this case SW hadles the interrupt as if PktDrpSts bit is set.
3032 : : */
3033 : : if (ep->is_in) {
3034 : : return 1;
3035 : : } else {
3036 : : return handle_iso_out_pkt_dropped(core_if, ep);
3037 : : }
3038 : : }
3039 : : }
3040 : :
3041 : : /**
3042 : : * This function is to handle Iso EP transfer complete interrupt
3043 : : *
3044 : : * @param pcd The PCD
3045 : : * @param ep The EP for which transfer complete was asserted
3046 : : *
3047 : : */
3048 : : static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
3049 : : {
3050 : : dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
3051 : : dwc_ep_t *dwc_ep = &ep->dwc_ep;
3052 : : uint8_t is_last = 0;
3053 : :
3054 : : if (ep->dwc_ep.next_frame == 0xffffffff) {
3055 : : DWC_WARN("Next frame is not set!\n");
3056 : : return;
3057 : : }
3058 : :
3059 : : if (core_if->dma_enable) {
3060 : : if (core_if->dma_desc_enable) {
3061 : : set_ddma_iso_pkts_info(core_if, dwc_ep);
3062 : : reinit_ddma_iso_xfer(core_if, dwc_ep);
3063 : : is_last = 1;
3064 : : } else {
3065 : : if (core_if->pti_enh_enable) {
3066 : : if (set_iso_pkts_info(core_if, dwc_ep)) {
3067 : : dwc_ep->proc_buf_num =
3068 : : (dwc_ep->proc_buf_num ^ 1) & 0x1;
3069 : : dwc_otg_iso_ep_start_buf_transfer
3070 : : (core_if, dwc_ep);
3071 : : is_last = 1;
3072 : : }
3073 : : } else {
3074 : : set_current_pkt_info(core_if, dwc_ep);
3075 : : if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
3076 : : is_last = 1;
3077 : : dwc_ep->cur_pkt = 0;
3078 : : dwc_ep->proc_buf_num =
3079 : : (dwc_ep->proc_buf_num ^ 1) & 0x1;
3080 : : if (dwc_ep->proc_buf_num) {
3081 : : dwc_ep->cur_pkt_addr =
3082 : : dwc_ep->xfer_buff1;
3083 : : dwc_ep->cur_pkt_dma_addr =
3084 : : dwc_ep->dma_addr1;
3085 : : } else {
3086 : : dwc_ep->cur_pkt_addr =
3087 : : dwc_ep->xfer_buff0;
3088 : : dwc_ep->cur_pkt_dma_addr =
3089 : : dwc_ep->dma_addr0;
3090 : : }
3091 : :
3092 : : }
3093 : : dwc_otg_iso_ep_start_frm_transfer(core_if,
3094 : : dwc_ep);
3095 : : }
3096 : : }
3097 : : } else {
3098 : : set_current_pkt_info(core_if, dwc_ep);
3099 : : if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
3100 : : is_last = 1;
3101 : : dwc_ep->cur_pkt = 0;
3102 : : dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
3103 : : if (dwc_ep->proc_buf_num) {
3104 : : dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;
3105 : : dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;
3106 : : } else {
3107 : : dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;
3108 : : dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;
3109 : : }
3110 : :
3111 : : }
3112 : : dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);
3113 : : }
3114 : : if (is_last)
3115 : : dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);
3116 : : }
3117 : : #endif /* DWC_EN_ISOC */
3118 : :
3119 : : /**
3120 : : * This function handle BNA interrupt for Non Isochronous EPs
3121 : : *
3122 : : */
3123 : 0 : static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep)
3124 : : {
3125 : : dwc_ep_t *dwc_ep = &ep->dwc_ep;
3126 : : volatile uint32_t *addr;
3127 : 0 : depctl_data_t depctl = {.d32 = 0 };
3128 : 0 : dwc_otg_pcd_t *pcd = ep->pcd;
3129 : : dwc_otg_dev_dma_desc_t *dma_desc;
3130 : : dev_dma_desc_sts_t sts = {.d32 = 0 };
3131 : 0 : dwc_otg_core_if_t *core_if = ep->pcd->core_if;
3132 : : int i, start;
3133 : :
3134 : 0 : if (!dwc_ep->desc_cnt)
3135 : 0 : DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num,
3136 : : (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt);
3137 : :
3138 : 0 : if (core_if->core_params->cont_on_bna && !dwc_ep->is_in
3139 : 0 : && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) {
3140 : : uint32_t doepdma;
3141 : 0 : dwc_otg_dev_out_ep_regs_t *out_regs =
3142 : 0 : core_if->dev_if->out_ep_regs[dwc_ep->num];
3143 : 0 : doepdma = DWC_READ_REG32(&(out_regs->doepdma));
3144 : 0 : start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t);
3145 : 0 : dma_desc = &(dwc_ep->desc_addr[start]);
3146 : : } else {
3147 : : start = 0;
3148 : 0 : dma_desc = dwc_ep->desc_addr;
3149 : : }
3150 : :
3151 : :
3152 : 0 : for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
3153 : 0 : sts.d32 = dma_desc->status.d32;
3154 : 0 : sts.b.bs = BS_HOST_READY;
3155 : 0 : dma_desc->status.d32 = sts.d32;
3156 : : }
3157 : :
3158 : 0 : if (dwc_ep->is_in == 0) {
3159 : 0 : addr =
3160 : 0 : &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->
3161 : : doepctl;
3162 : : } else {
3163 : 0 : addr =
3164 : 0 : &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
3165 : : }
3166 : 0 : depctl.b.epena = 1;
3167 : 0 : depctl.b.cnak = 1;
3168 : 0 : DWC_MODIFY_REG32(addr, 0, depctl.d32);
3169 : 0 : }
3170 : :
3171 : : /**
3172 : : * This function handles EP0 Control transfers.
3173 : : *
3174 : : * The state of the control transfers are tracked in
3175 : : * <code>ep0state</code>.
3176 : : */
3177 : 0 : static void handle_ep0(dwc_otg_pcd_t * pcd)
3178 : : {
3179 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
3180 : 0 : dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
3181 : : dev_dma_desc_sts_t desc_sts;
3182 : : deptsiz0_data_t deptsiz;
3183 : : uint32_t byte_count;
3184 : :
3185 : : #ifdef DEBUG_EP0
3186 : : DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
3187 : : print_ep0_state(pcd);
3188 : : #endif
3189 : :
3190 : : // DWC_PRINTF("HANDLE EP0\n");
3191 : :
3192 : 0 : switch (pcd->ep0state) {
3193 : : case EP0_DISCONNECT:
3194 : : break;
3195 : :
3196 : : case EP0_IDLE:
3197 : 0 : pcd->request_config = 0;
3198 : :
3199 : 0 : pcd_setup(pcd);
3200 : 0 : break;
3201 : :
3202 : : case EP0_IN_DATA_PHASE:
3203 : : #ifdef DEBUG_EP0
3204 : : DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
3205 : : ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
3206 : : ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
3207 : : #endif
3208 : :
3209 : 0 : if (core_if->dma_enable != 0) {
3210 : : /*
3211 : : * For EP0 we can only program 1 packet at a time so we
3212 : : * need to do the make calculations after each complete.
3213 : : * Call write_packet to make the calculations, as in
3214 : : * slave mode, and use those values to determine if we
3215 : : * can complete.
3216 : : */
3217 : 0 : if (core_if->dma_desc_enable == 0) {
3218 : 0 : deptsiz.d32 =
3219 : 0 : DWC_READ_REG32(&core_if->
3220 : 0 : dev_if->in_ep_regs[0]->
3221 : : dieptsiz);
3222 : 0 : byte_count =
3223 : 0 : ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
3224 : : } else {
3225 : 0 : desc_sts =
3226 : 0 : core_if->dev_if->in_desc_addr->status;
3227 : 0 : byte_count =
3228 : 0 : ep0->dwc_ep.xfer_len - desc_sts.b.bytes;
3229 : : }
3230 : 0 : ep0->dwc_ep.xfer_count += byte_count;
3231 : 0 : ep0->dwc_ep.xfer_buff += byte_count;
3232 : 0 : ep0->dwc_ep.dma_addr += byte_count;
3233 : : }
3234 : 0 : if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
3235 : 0 : dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
3236 : : &ep0->dwc_ep);
3237 : : DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
3238 : 0 : } else if (ep0->dwc_ep.sent_zlp) {
3239 : 0 : dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
3240 : : &ep0->dwc_ep);
3241 : 0 : ep0->dwc_ep.sent_zlp = 0;
3242 : : DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
3243 : : } else {
3244 : 0 : ep0_complete_request(ep0);
3245 : : DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
3246 : : }
3247 : : break;
3248 : : case EP0_OUT_DATA_PHASE:
3249 : : #ifdef DEBUG_EP0
3250 : : DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
3251 : : ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
3252 : : ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
3253 : : #endif
3254 : 0 : if (core_if->dma_enable != 0) {
3255 : 0 : if (core_if->dma_desc_enable == 0) {
3256 : 0 : deptsiz.d32 =
3257 : 0 : DWC_READ_REG32(&core_if->
3258 : 0 : dev_if->out_ep_regs[0]->
3259 : : doeptsiz);
3260 : 0 : byte_count =
3261 : 0 : ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;
3262 : : } else {
3263 : 0 : desc_sts =
3264 : 0 : core_if->dev_if->out_desc_addr->status;
3265 : 0 : byte_count =
3266 : 0 : ep0->dwc_ep.maxpacket - desc_sts.b.bytes;
3267 : : }
3268 : 0 : ep0->dwc_ep.xfer_count += byte_count;
3269 : 0 : ep0->dwc_ep.xfer_buff += byte_count;
3270 : 0 : ep0->dwc_ep.dma_addr += byte_count;
3271 : : }
3272 : 0 : if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
3273 : 0 : dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
3274 : : &ep0->dwc_ep);
3275 : : DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
3276 : 0 : } else if (ep0->dwc_ep.sent_zlp) {
3277 : 0 : dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
3278 : : &ep0->dwc_ep);
3279 : 0 : ep0->dwc_ep.sent_zlp = 0;
3280 : : DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
3281 : : } else {
3282 : 0 : ep0_complete_request(ep0);
3283 : : DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
3284 : : }
3285 : : break;
3286 : :
3287 : : case EP0_IN_STATUS_PHASE:
3288 : : case EP0_OUT_STATUS_PHASE:
3289 : : DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");
3290 : 0 : ep0_complete_request(ep0);
3291 : 0 : pcd->ep0state = EP0_IDLE;
3292 : 0 : ep0->stopped = 1;
3293 : 0 : ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */
3294 : :
3295 : : /* Prepare for more SETUP Packets */
3296 : 0 : if (core_if->dma_enable) {
3297 : 0 : ep0_out_start(core_if, pcd);
3298 : : }
3299 : : break;
3300 : :
3301 : : case EP0_STALL:
3302 : 0 : DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
3303 : 0 : break;
3304 : : }
3305 : : #ifdef DEBUG_EP0
3306 : : print_ep0_state(pcd);
3307 : : #endif
3308 : 0 : }
3309 : :
3310 : : /**
3311 : : * Restart transfer
3312 : : */
3313 : 0 : static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)
3314 : : {
3315 : : dwc_otg_core_if_t *core_if;
3316 : : dwc_otg_dev_if_t *dev_if;
3317 : : deptsiz_data_t dieptsiz = {.d32 = 0 };
3318 : : dwc_otg_pcd_ep_t *ep;
3319 : :
3320 : : ep = get_in_ep(pcd, epnum);
3321 : :
3322 : : #ifdef DWC_EN_ISOC
3323 : : if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
3324 : : return;
3325 : : }
3326 : : #endif /* DWC_EN_ISOC */
3327 : :
3328 : : core_if = GET_CORE_IF(pcd);
3329 : : dev_if = core_if->dev_if;
3330 : :
3331 : 0 : dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
3332 : :
3333 : : DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"
3334 : : " stopped=%d\n", ep->dwc_ep.xfer_buff,
3335 : : ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);
3336 : : /*
3337 : : * If xfersize is 0 and pktcnt in not 0, resend the last packet.
3338 : : */
3339 : 0 : if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
3340 : 0 : ep->dwc_ep.start_xfer_buff != 0) {
3341 : 0 : if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {
3342 : 0 : ep->dwc_ep.xfer_count = 0;
3343 : 0 : ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
3344 : 0 : ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
3345 : : } else {
3346 : 0 : ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
3347 : : /* convert packet size to dwords. */
3348 : 0 : ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
3349 : 0 : ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
3350 : : }
3351 : 0 : ep->stopped = 0;
3352 : : DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "
3353 : : "xfer_len=%0x stopped=%d\n",
3354 : : ep->dwc_ep.xfer_buff,
3355 : : ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,
3356 : : ep->stopped);
3357 : 0 : if (epnum == 0) {
3358 : 0 : dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
3359 : : } else {
3360 : 0 : dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
3361 : : }
3362 : : }
3363 : 0 : }
3364 : :
3365 : : /*
3366 : : * This function create new nextep sequnce based on Learn Queue.
3367 : : *
3368 : : * @param core_if Programming view of DWC_otg controller
3369 : : */
3370 : 0 : void predict_nextep_seq( dwc_otg_core_if_t * core_if)
3371 : : {
3372 : 0 : dwc_otg_device_global_regs_t *dev_global_regs =
3373 : 0 : core_if->dev_if->dev_global_regs;
3374 : 0 : const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
3375 : : /* Number of Token Queue Registers */
3376 : 0 : const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
3377 : : dtknq1_data_t dtknqr1;
3378 : : uint32_t in_tkn_epnums[4];
3379 : : uint8_t seqnum[MAX_EPS_CHANNELS];
3380 : 0 : uint8_t intkn_seq[TOKEN_Q_DEPTH];
3381 : : grstctl_t resetctl = {.d32 = 0 };
3382 : : uint8_t temp;
3383 : : int ndx = 0;
3384 : : int start = 0;
3385 : : int end = 0;
3386 : : int sort_done = 0;
3387 : : int i = 0;
3388 : 0 : volatile uint32_t *addr = &dev_global_regs->dtknqr1;
3389 : :
3390 : :
3391 : : DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
3392 : :
3393 : : /* Read the DTKNQ Registers */
3394 : 0 : for (i = 0; i < DTKNQ_REG_CNT; i++) {
3395 : 0 : in_tkn_epnums[i] = DWC_READ_REG32(addr);
3396 : : DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
3397 : : in_tkn_epnums[i]);
3398 : 0 : if (addr == &dev_global_regs->dvbusdis) {
3399 : 0 : addr = &dev_global_regs->dtknqr3_dthrctl;
3400 : : } else {
3401 : 0 : ++addr;
3402 : : }
3403 : :
3404 : : }
3405 : :
3406 : : /* Copy the DTKNQR1 data to the bit field. */
3407 : 0 : dtknqr1.d32 = in_tkn_epnums[0];
3408 : 0 : if (dtknqr1.b.wrap_bit) {
3409 : 0 : ndx = dtknqr1.b.intknwptr;
3410 : : end = ndx -1;
3411 : : if (end < 0)
3412 : : end = TOKEN_Q_DEPTH -1;
3413 : : } else {
3414 : : ndx = 0;
3415 : : end = dtknqr1.b.intknwptr -1;
3416 : : if (end < 0)
3417 : : end = 0;
3418 : : }
3419 : : start = ndx;
3420 : :
3421 : : /* Fill seqnum[] by initial values: EP number + 31 */
3422 : 0 : for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
3423 : 0 : seqnum[i] = i +31;
3424 : : }
3425 : :
3426 : : /* Fill intkn_seq[] from in_tkn_epnums[0] */
3427 : 0 : for (i=0; i < 6; i++)
3428 : 0 : intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf;
3429 : :
3430 : 0 : if (TOKEN_Q_DEPTH > 6) {
3431 : : /* Fill intkn_seq[] from in_tkn_epnums[1] */
3432 : 0 : for (i=6; i < 14; i++)
3433 : 0 : intkn_seq[i] =
3434 : 0 : (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf;
3435 : : }
3436 : :
3437 : 0 : if (TOKEN_Q_DEPTH > 14) {
3438 : : /* Fill intkn_seq[] from in_tkn_epnums[1] */
3439 : 0 : for (i=14; i < 22; i++)
3440 : 0 : intkn_seq[i] =
3441 : 0 : (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf;
3442 : : }
3443 : :
3444 : 0 : if (TOKEN_Q_DEPTH > 22) {
3445 : : /* Fill intkn_seq[] from in_tkn_epnums[1] */
3446 : 0 : for (i=22; i < 30; i++)
3447 : 0 : intkn_seq[i] =
3448 : 0 : (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf;
3449 : : }
3450 : :
3451 : : DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__,
3452 : : start, end);
3453 : : for (i=0; i<TOKEN_Q_DEPTH; i++)
3454 : : DWC_DEBUGPL(DBG_PCDV,"%d\n", intkn_seq[i]);
3455 : :
3456 : : /* Update seqnum based on intkn_seq[] */
3457 : : i = 0;
3458 : : do {
3459 : 0 : seqnum[intkn_seq[ndx]] = i;
3460 : 0 : ndx++;
3461 : 0 : i++;
3462 : 0 : if (ndx == TOKEN_Q_DEPTH)
3463 : : ndx = 0;
3464 : 0 : } while ( i < TOKEN_Q_DEPTH );
3465 : :
3466 : : /* Mark non active EP's in seqnum[] by 0xff */
3467 : 0 : for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
3468 : 0 : if (core_if->nextep_seq[i] == 0xff )
3469 : 0 : seqnum[i] = 0xff;
3470 : : }
3471 : :
3472 : : /* Sort seqnum[] */
3473 : : sort_done = 0;
3474 : 0 : while (!sort_done) {
3475 : : sort_done = 1;
3476 : 0 : for (i=0; i<core_if->dev_if->num_in_eps; i++) {
3477 : 0 : if (seqnum[i] > seqnum[i+1]) {
3478 : : temp = seqnum[i];
3479 : 0 : seqnum[i] = seqnum[i+1];
3480 : 0 : seqnum[i+1] = temp;
3481 : : sort_done = 0;
3482 : : }
3483 : : }
3484 : : }
3485 : :
3486 : 0 : ndx = start + seqnum[0];
3487 : 0 : if (ndx >= TOKEN_Q_DEPTH)
3488 : 0 : ndx = ndx % TOKEN_Q_DEPTH;
3489 : 0 : core_if->first_in_nextep_seq = intkn_seq[ndx];
3490 : :
3491 : : /* Update seqnum[] by EP numbers */
3492 : 0 : for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
3493 : : ndx = start + i;
3494 : 0 : if (seqnum[i] < 31) {
3495 : 0 : ndx = start + seqnum[i];
3496 : 0 : if (ndx >= TOKEN_Q_DEPTH)
3497 : 0 : ndx = ndx % TOKEN_Q_DEPTH;
3498 : 0 : seqnum[i] = intkn_seq[ndx];
3499 : : } else {
3500 : 0 : if (seqnum[i] < 0xff) {
3501 : 0 : seqnum[i] = seqnum[i] - 31;
3502 : : } else {
3503 : : break;
3504 : : }
3505 : : }
3506 : : }
3507 : :
3508 : : /* Update nextep_seq[] based on seqnum[] */
3509 : 0 : for (i=0; i<core_if->dev_if->num_in_eps; i++) {
3510 : 0 : if (seqnum[i] != 0xff) {
3511 : 0 : if (seqnum[i+1] != 0xff) {
3512 : 0 : core_if->nextep_seq[seqnum[i]] = seqnum[i+1];
3513 : : } else {
3514 : 0 : core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq;
3515 : 0 : break;
3516 : : }
3517 : : } else {
3518 : : break;
3519 : : }
3520 : : }
3521 : :
3522 : : DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
3523 : : __func__, core_if->first_in_nextep_seq);
3524 : 0 : for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
3525 : : DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]);
3526 : : }
3527 : :
3528 : : /* Flush the Learning Queue */
3529 : 0 : resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl);
3530 : 0 : resetctl.b.intknqflsh = 1;
3531 : 0 : DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
3532 : :
3533 : :
3534 : 0 : }
3535 : :
3536 : : /**
3537 : : * handle the IN EP disable interrupt.
3538 : : */
3539 : 0 : static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,
3540 : : const uint32_t epnum)
3541 : : {
3542 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
3543 : 0 : dwc_otg_dev_if_t *dev_if = core_if->dev_if;
3544 : : deptsiz_data_t dieptsiz = {.d32 = 0 };
3545 : 0 : dctl_data_t dctl = {.d32 = 0 };
3546 : : dwc_otg_pcd_ep_t *ep;
3547 : : dwc_ep_t *dwc_ep;
3548 : : gintmsk_data_t gintmsk_data;
3549 : : depctl_data_t depctl;
3550 : : uint32_t diepdma;
3551 : : uint32_t remain_to_transfer = 0;
3552 : : uint8_t i;
3553 : : uint32_t xfer_size;
3554 : :
3555 : : ep = get_in_ep(pcd, epnum);
3556 : : dwc_ep = &ep->dwc_ep;
3557 : :
3558 : 0 : if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
3559 : 0 : dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
3560 : 0 : complete_ep(ep);
3561 : 0 : return;
3562 : : }
3563 : :
3564 : : DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,
3565 : : DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl));
3566 : 0 : dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
3567 : 0 : depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
3568 : :
3569 : : DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
3570 : : dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
3571 : :
3572 : 0 : if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) {
3573 : 0 : if (ep->stopped) {
3574 : 0 : if (core_if->en_multiple_tx_fifo)
3575 : : /* Flush the Tx FIFO */
3576 : 0 : dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
3577 : : /* Clear the Global IN NP NAK */
3578 : : dctl.d32 = 0;
3579 : 0 : dctl.b.cgnpinnak = 1;
3580 : 0 : DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
3581 : : /* Restart the transaction */
3582 : 0 : if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
3583 : 0 : restart_transfer(pcd, epnum);
3584 : : }
3585 : : } else {
3586 : : /* Restart the transaction */
3587 : 0 : if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
3588 : 0 : restart_transfer(pcd, epnum);
3589 : : }
3590 : : DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
3591 : : }
3592 : : return;
3593 : : }
3594 : :
3595 : 0 : if (core_if->start_predict > 2) { // NP IN EP
3596 : 0 : core_if->start_predict--;
3597 : 0 : return;
3598 : : }
3599 : :
3600 : 0 : core_if->start_predict--;
3601 : :
3602 : 0 : if (core_if->start_predict == 1) { // All NP IN Ep's disabled now
3603 : :
3604 : 0 : predict_nextep_seq(core_if);
3605 : :
3606 : : /* Update all active IN EP's NextEP field based of nextep_seq[] */
3607 : 0 : for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) {
3608 : 0 : depctl.d32 =
3609 : 0 : DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
3610 : 0 : if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP
3611 : 0 : depctl.b.nextep = core_if->nextep_seq[i];
3612 : 0 : DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
3613 : : }
3614 : : }
3615 : : /* Flush Shared NP TxFIFO */
3616 : 0 : dwc_otg_flush_tx_fifo(core_if, 0);
3617 : : /* Rewind buffers */
3618 : 0 : if (!core_if->dma_desc_enable) {
3619 : 0 : i = core_if->first_in_nextep_seq;
3620 : : do {
3621 : 0 : ep = get_in_ep(pcd, i);
3622 : 0 : dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
3623 : 0 : xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count;
3624 : 0 : if (xfer_size > ep->dwc_ep.maxxfer)
3625 : : xfer_size = ep->dwc_ep.maxxfer;
3626 : 0 : depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
3627 : 0 : if (dieptsiz.b.pktcnt != 0) {
3628 : 0 : if (xfer_size == 0) {
3629 : : remain_to_transfer = 0;
3630 : : } else {
3631 : 0 : if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {
3632 : 0 : remain_to_transfer =
3633 : 0 : dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;
3634 : : } else {
3635 : 0 : remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket)
3636 : 0 : + (xfer_size % ep->dwc_ep.maxpacket);
3637 : : }
3638 : : }
3639 : 0 : diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma);
3640 : 0 : dieptsiz.b.xfersize = remain_to_transfer;
3641 : 0 : DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32);
3642 : 0 : diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer);
3643 : 0 : DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma);
3644 : : }
3645 : 0 : i = core_if->nextep_seq[i];
3646 : 0 : } while (i != core_if->first_in_nextep_seq);
3647 : : } else { // dma_desc_enable
3648 : 0 : DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__);
3649 : : }
3650 : :
3651 : : /* Restart transfers in predicted sequences */
3652 : 0 : i = core_if->first_in_nextep_seq;
3653 : : do {
3654 : 0 : dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
3655 : 0 : depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
3656 : 0 : if (dieptsiz.b.pktcnt != 0) {
3657 : 0 : depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
3658 : 0 : depctl.b.epena = 1;
3659 : 0 : depctl.b.cnak = 1;
3660 : 0 : DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
3661 : : }
3662 : 0 : i = core_if->nextep_seq[i];
3663 : 0 : } while (i != core_if->first_in_nextep_seq);
3664 : :
3665 : : /* Clear the global non-periodic IN NAK handshake */
3666 : 0 : dctl.d32 = 0;
3667 : 0 : dctl.b.cgnpinnak = 1;
3668 : 0 : DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
3669 : :
3670 : : /* Unmask EP Mismatch interrupt */
3671 : 0 : gintmsk_data.d32 = 0;
3672 : 0 : gintmsk_data.b.epmismatch = 1;
3673 : 0 : DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32);
3674 : :
3675 : 0 : core_if->start_predict = 0;
3676 : :
3677 : : }
3678 : : }
3679 : :
3680 : : /**
3681 : : * Handler for the IN EP timeout handshake interrupt.
3682 : : */
3683 : 0 : static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,
3684 : : const uint32_t epnum)
3685 : : {
3686 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
3687 : 0 : dwc_otg_dev_if_t *dev_if = core_if->dev_if;
3688 : :
3689 : : #ifdef DEBUG
3690 : : deptsiz_data_t dieptsiz = {.d32 = 0 };
3691 : : uint32_t num = 0;
3692 : : #endif
3693 : 0 : dctl_data_t dctl = {.d32 = 0 };
3694 : : dwc_otg_pcd_ep_t *ep;
3695 : :
3696 : 0 : gintmsk_data_t intr_mask = {.d32 = 0 };
3697 : :
3698 : : ep = get_in_ep(pcd, epnum);
3699 : :
3700 : : /* Disable the NP Tx Fifo Empty Interrrupt */
3701 : 0 : if (!core_if->dma_enable) {
3702 : 0 : intr_mask.b.nptxfempty = 1;
3703 : 0 : DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
3704 : : intr_mask.d32, 0);
3705 : : }
3706 : : /** @todo NGS Check EP type.
3707 : : * Implement for Periodic EPs */
3708 : : /*
3709 : : * Non-periodic EP
3710 : : */
3711 : : /* Enable the Global IN NAK Effective Interrupt */
3712 : 0 : intr_mask.b.ginnakeff = 1;
3713 : 0 : DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
3714 : :
3715 : : /* Set Global IN NAK */
3716 : 0 : dctl.b.sgnpinnak = 1;
3717 : 0 : DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
3718 : :
3719 : 0 : ep->stopped = 1;
3720 : :
3721 : : #ifdef DEBUG
3722 : : dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz);
3723 : : DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
3724 : : dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
3725 : : #endif
3726 : :
3727 : : #ifdef DISABLE_PERIODIC_EP
3728 : : /*
3729 : : * Set the NAK bit for this EP to
3730 : : * start the disable process.
3731 : : */
3732 : : diepctl.d32 = 0;
3733 : : diepctl.b.snak = 1;
3734 : : DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,
3735 : : diepctl.d32);
3736 : : ep->disabling = 1;
3737 : : ep->stopped = 1;
3738 : : #endif
3739 : 0 : }
3740 : :
3741 : : /**
3742 : : * Handler for the IN EP NAK interrupt.
3743 : : */
3744 : : static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,
3745 : : const uint32_t epnum)
3746 : : {
3747 : : /** @todo implement ISR */
3748 : : dwc_otg_core_if_t *core_if;
3749 : : diepmsk_data_t intr_mask = {.d32 = 0 };
3750 : :
3751 : : DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
3752 : : core_if = GET_CORE_IF(pcd);
3753 : : intr_mask.b.nak = 1;
3754 : :
3755 : : if (core_if->multiproc_int_enable) {
3756 : : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
3757 : : diepeachintmsk[epnum], intr_mask.d32, 0);
3758 : : } else {
3759 : : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk,
3760 : : intr_mask.d32, 0);
3761 : : }
3762 : :
3763 : : return 1;
3764 : : }
3765 : :
3766 : : /**
3767 : : * Handler for the OUT EP Babble interrupt.
3768 : : */
3769 : 0 : static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,
3770 : : const uint32_t epnum)
3771 : : {
3772 : : /** @todo implement ISR */
3773 : : dwc_otg_core_if_t *core_if;
3774 : 0 : doepmsk_data_t intr_mask = {.d32 = 0 };
3775 : :
3776 : 0 : DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
3777 : : "OUT EP Babble");
3778 : 0 : core_if = GET_CORE_IF(pcd);
3779 : 0 : intr_mask.b.babble = 1;
3780 : :
3781 : 0 : if (core_if->multiproc_int_enable) {
3782 : 0 : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
3783 : : doepeachintmsk[epnum], intr_mask.d32, 0);
3784 : : } else {
3785 : 0 : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
3786 : : intr_mask.d32, 0);
3787 : : }
3788 : :
3789 : 0 : return 1;
3790 : : }
3791 : :
3792 : : /**
3793 : : * Handler for the OUT EP NAK interrupt.
3794 : : */
3795 : 0 : static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
3796 : : const uint32_t epnum)
3797 : : {
3798 : : /** @todo implement ISR */
3799 : : dwc_otg_core_if_t *core_if;
3800 : 0 : doepmsk_data_t intr_mask = {.d32 = 0 };
3801 : :
3802 : : DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
3803 : 0 : core_if = GET_CORE_IF(pcd);
3804 : 0 : intr_mask.b.nak = 1;
3805 : :
3806 : 0 : if (core_if->multiproc_int_enable) {
3807 : 0 : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
3808 : : doepeachintmsk[epnum], intr_mask.d32, 0);
3809 : : } else {
3810 : 0 : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
3811 : : intr_mask.d32, 0);
3812 : : }
3813 : :
3814 : 0 : return 1;
3815 : : }
3816 : :
3817 : : /**
3818 : : * Handler for the OUT EP NYET interrupt.
3819 : : */
3820 : 0 : static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
3821 : : const uint32_t epnum)
3822 : : {
3823 : : /** @todo implement ISR */
3824 : : dwc_otg_core_if_t *core_if;
3825 : 0 : doepmsk_data_t intr_mask = {.d32 = 0 };
3826 : :
3827 : 0 : DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
3828 : 0 : core_if = GET_CORE_IF(pcd);
3829 : 0 : intr_mask.b.nyet = 1;
3830 : :
3831 : 0 : if (core_if->multiproc_int_enable) {
3832 : 0 : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
3833 : : doepeachintmsk[epnum], intr_mask.d32, 0);
3834 : : } else {
3835 : 0 : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
3836 : : intr_mask.d32, 0);
3837 : : }
3838 : :
3839 : 0 : return 1;
3840 : : }
3841 : :
3842 : : /**
3843 : : * This interrupt indicates that an IN EP has a pending Interrupt.
3844 : : * The sequence for handling the IN EP interrupt is shown below:
3845 : : * -# Read the Device All Endpoint Interrupt register
3846 : : * -# Repeat the following for each IN EP interrupt bit set (from
3847 : : * LSB to MSB).
3848 : : * -# Read the Device Endpoint Interrupt (DIEPINTn) register
3849 : : * -# If "Transfer Complete" call the request complete function
3850 : : * -# If "Endpoint Disabled" complete the EP disable procedure.
3851 : : * -# If "AHB Error Interrupt" log error
3852 : : * -# If "Time-out Handshake" log error
3853 : : * -# If "IN Token Received when TxFIFO Empty" write packet to Tx
3854 : : * FIFO.
3855 : : * -# If "IN Token EP Mismatch" (disable, this is handled by EP
3856 : : * Mismatch Interrupt)
3857 : : */
3858 : 0 : static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
3859 : : {
3860 : : #define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
3861 : : do { \
3862 : : diepint_data_t diepint = {.d32=0}; \
3863 : : diepint.b.__intr = 1; \
3864 : : DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
3865 : : diepint.d32); \
3866 : : } while (0)
3867 : :
3868 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
3869 : 0 : dwc_otg_dev_if_t *dev_if = core_if->dev_if;
3870 : : diepint_data_t diepint = {.d32 = 0 };
3871 : : depctl_data_t depctl = {.d32 = 0 };
3872 : : uint32_t ep_intr;
3873 : : uint32_t epnum = 0;
3874 : : dwc_otg_pcd_ep_t *ep;
3875 : : dwc_ep_t *dwc_ep;
3876 : 0 : gintmsk_data_t intr_mask = {.d32 = 0 };
3877 : :
3878 : : DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);
3879 : :
3880 : : /* Read in the device interrupt bits */
3881 : 0 : ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
3882 : :
3883 : : /* Service the Device IN interrupts for each endpoint */
3884 : 0 : while (ep_intr) {
3885 : 0 : if (ep_intr & 0x1) {
3886 : : uint32_t empty_msk;
3887 : : /* Get EP pointer */
3888 : : ep = get_in_ep(pcd, epnum);
3889 : 0 : dwc_ep = &ep->dwc_ep;
3890 : :
3891 : : depctl.d32 =
3892 : 0 : DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
3893 : 0 : empty_msk =
3894 : 0 : DWC_READ_REG32(&dev_if->
3895 : : dev_global_regs->dtknqr4_fifoemptymsk);
3896 : :
3897 : : DWC_DEBUGPL(DBG_PCDV,
3898 : : "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n",
3899 : : epnum, empty_msk, depctl.d32);
3900 : :
3901 : : DWC_DEBUGPL(DBG_PCD,
3902 : : "EP%d-%s: type=%d, mps=%d\n",
3903 : : dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
3904 : : dwc_ep->type, dwc_ep->maxpacket);
3905 : :
3906 : : diepint.d32 =
3907 : 0 : dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
3908 : :
3909 : : DWC_DEBUGPL(DBG_PCDV,
3910 : : "EP %d Interrupt Register - 0x%x\n", epnum,
3911 : : diepint.d32);
3912 : : /* Transfer complete */
3913 : 0 : if (diepint.b.xfercompl) {
3914 : : /* Disable the NP Tx FIFO Empty
3915 : : * Interrupt */
3916 : 0 : if (core_if->en_multiple_tx_fifo == 0) {
3917 : 0 : intr_mask.b.nptxfempty = 1;
3918 : 0 : DWC_MODIFY_REG32
3919 : 0 : (&core_if->core_global_regs->gintmsk,
3920 : : intr_mask.d32, 0);
3921 : : } else {
3922 : : /* Disable the Tx FIFO Empty Interrupt for this EP */
3923 : 0 : uint32_t fifoemptymsk =
3924 : 0 : 0x1 << dwc_ep->num;
3925 : 0 : DWC_MODIFY_REG32(&core_if->
3926 : 0 : dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
3927 : : fifoemptymsk, 0);
3928 : : }
3929 : : /* Clear the bit in DIEPINTn for this interrupt */
3930 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
3931 : :
3932 : : /* Complete the transfer */
3933 : 0 : if (epnum == 0) {
3934 : 0 : handle_ep0(pcd);
3935 : : }
3936 : : #ifdef DWC_EN_ISOC
3937 : : else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
3938 : : if (!ep->stopped)
3939 : : complete_iso_ep(pcd, ep);
3940 : : }
3941 : : #endif /* DWC_EN_ISOC */
3942 : : #ifdef DWC_UTE_PER_IO
3943 : : else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
3944 : : if (!ep->stopped)
3945 : : complete_xiso_ep(ep);
3946 : : }
3947 : : #endif /* DWC_UTE_PER_IO */
3948 : : else {
3949 : 0 : if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC &&
3950 : 0 : dwc_ep->bInterval > 1) {
3951 : 0 : dwc_ep->frame_num += dwc_ep->bInterval;
3952 : 0 : if (dwc_ep->frame_num > 0x3FFF)
3953 : : {
3954 : 0 : dwc_ep->frm_overrun = 1;
3955 : 0 : dwc_ep->frame_num &= 0x3FFF;
3956 : : } else
3957 : 0 : dwc_ep->frm_overrun = 0;
3958 : : }
3959 : 0 : complete_ep(ep);
3960 : 0 : if(diepint.b.nak)
3961 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, nak);
3962 : : }
3963 : : }
3964 : : /* Endpoint disable */
3965 : 0 : if (diepint.b.epdisabled) {
3966 : : DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",
3967 : : epnum);
3968 : 0 : handle_in_ep_disable_intr(pcd, epnum);
3969 : :
3970 : : /* Clear the bit in DIEPINTn for this interrupt */
3971 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
3972 : : }
3973 : : /* AHB Error */
3974 : 0 : if (diepint.b.ahberr) {
3975 : 0 : DWC_ERROR("EP%d IN AHB Error\n", epnum);
3976 : : /* Clear the bit in DIEPINTn for this interrupt */
3977 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, ahberr);
3978 : : }
3979 : : /* TimeOUT Handshake (non-ISOC IN EPs) */
3980 : 0 : if (diepint.b.timeout) {
3981 : 0 : DWC_ERROR("EP%d IN Time-out\n", epnum);
3982 : 0 : handle_in_ep_timeout_intr(pcd, epnum);
3983 : :
3984 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, timeout);
3985 : : }
3986 : : /** IN Token received with TxF Empty */
3987 : 0 : if (diepint.b.intktxfemp) {
3988 : : DWC_DEBUGPL(DBG_ANY,
3989 : : "EP%d IN TKN TxFifo Empty\n",
3990 : : epnum);
3991 : 0 : if (!ep->stopped && epnum != 0) {
3992 : :
3993 : 0 : diepmsk_data_t diepmsk = {.d32 = 0 };
3994 : 0 : diepmsk.b.intktxfemp = 1;
3995 : :
3996 : 0 : if (core_if->multiproc_int_enable) {
3997 : 0 : DWC_MODIFY_REG32
3998 : 0 : (&dev_if->dev_global_regs->diepeachintmsk
3999 : : [epnum], diepmsk.d32, 0);
4000 : : } else {
4001 : 0 : DWC_MODIFY_REG32
4002 : 0 : (&dev_if->dev_global_regs->diepmsk,
4003 : : diepmsk.d32, 0);
4004 : : }
4005 : 0 : } else if (core_if->dma_desc_enable
4006 : 0 : && epnum == 0
4007 : 0 : && pcd->ep0state ==
4008 : : EP0_OUT_STATUS_PHASE) {
4009 : : // EP0 IN set STALL
4010 : 0 : depctl.d32 =
4011 : 0 : DWC_READ_REG32(&dev_if->in_ep_regs
4012 : 0 : [epnum]->diepctl);
4013 : :
4014 : : /* set the disable and stall bits */
4015 : 0 : if (depctl.b.epena) {
4016 : 0 : depctl.b.epdis = 1;
4017 : : }
4018 : 0 : depctl.b.stall = 1;
4019 : 0 : DWC_WRITE_REG32(&dev_if->in_ep_regs
4020 : 0 : [epnum]->diepctl,
4021 : : depctl.d32);
4022 : : }
4023 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
4024 : : }
4025 : : /** IN Token Received with EP mismatch */
4026 : 0 : if (diepint.b.intknepmis) {
4027 : : DWC_DEBUGPL(DBG_ANY,
4028 : : "EP%d IN TKN EP Mismatch\n", epnum);
4029 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);
4030 : : }
4031 : : /** IN Endpoint NAK Effective */
4032 : 0 : if (diepint.b.inepnakeff) {
4033 : : DWC_DEBUGPL(DBG_ANY,
4034 : : "EP%d IN EP NAK Effective\n",
4035 : : epnum);
4036 : : /* Periodic EP */
4037 : 0 : if (ep->disabling) {
4038 : 0 : depctl.d32 = 0;
4039 : 0 : depctl.b.snak = 1;
4040 : 0 : depctl.b.epdis = 1;
4041 : 0 : DWC_MODIFY_REG32(&dev_if->in_ep_regs
4042 : 0 : [epnum]->diepctl,
4043 : : depctl.d32,
4044 : : depctl.d32);
4045 : : }
4046 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
4047 : :
4048 : : }
4049 : :
4050 : : /** IN EP Tx FIFO Empty Intr */
4051 : 0 : if (diepint.b.emptyintr) {
4052 : : DWC_DEBUGPL(DBG_ANY,
4053 : : "EP%d Tx FIFO Empty Intr \n",
4054 : : epnum);
4055 : 0 : write_empty_tx_fifo(pcd, epnum);
4056 : :
4057 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
4058 : :
4059 : : }
4060 : :
4061 : : /** IN EP BNA Intr */
4062 : 0 : if (diepint.b.bna) {
4063 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, bna);
4064 : 0 : if (core_if->dma_desc_enable) {
4065 : : #ifdef DWC_EN_ISOC
4066 : : if (dwc_ep->type ==
4067 : : DWC_OTG_EP_TYPE_ISOC) {
4068 : : /*
4069 : : * This checking is performed to prevent first "false" BNA
4070 : : * handling occuring right after reconnect
4071 : : */
4072 : : if (dwc_ep->next_frame !=
4073 : : 0xffffffff)
4074 : : dwc_otg_pcd_handle_iso_bna(ep);
4075 : : } else
4076 : : #endif /* DWC_EN_ISOC */
4077 : : {
4078 : 0 : dwc_otg_pcd_handle_noniso_bna(ep);
4079 : : }
4080 : : }
4081 : : }
4082 : : /* NAK Interrutp */
4083 : 0 : if (diepint.b.nak) {
4084 : : DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
4085 : : epnum);
4086 : 0 : if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
4087 : : depctl_data_t depctl;
4088 : 0 : if (ep->dwc_ep.frame_num == 0xFFFFFFFF) {
4089 : 0 : ep->dwc_ep.frame_num = core_if->frame_num;
4090 : 0 : if (ep->dwc_ep.bInterval > 1) {
4091 : : depctl.d32 = 0;
4092 : 0 : depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
4093 : 0 : if (ep->dwc_ep.frame_num & 0x1) {
4094 : 0 : depctl.b.setd1pid = 1;
4095 : 0 : depctl.b.setd0pid = 0;
4096 : : } else {
4097 : 0 : depctl.b.setd0pid = 1;
4098 : 0 : depctl.b.setd1pid = 0;
4099 : : }
4100 : 0 : DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32);
4101 : : }
4102 : 0 : start_next_request(ep);
4103 : : }
4104 : 0 : ep->dwc_ep.frame_num += ep->dwc_ep.bInterval;
4105 : 0 : if (dwc_ep->frame_num > 0x3FFF) {
4106 : 0 : dwc_ep->frm_overrun = 1;
4107 : 0 : dwc_ep->frame_num &= 0x3FFF;
4108 : : } else
4109 : 0 : dwc_ep->frm_overrun = 0;
4110 : : }
4111 : :
4112 : 0 : CLEAR_IN_EP_INTR(core_if, epnum, nak);
4113 : : }
4114 : : }
4115 : 0 : epnum++;
4116 : 0 : ep_intr >>= 1;
4117 : : }
4118 : :
4119 : 0 : return 1;
4120 : : #undef CLEAR_IN_EP_INTR
4121 : : }
4122 : :
4123 : : /**
4124 : : * This interrupt indicates that an OUT EP has a pending Interrupt.
4125 : : * The sequence for handling the OUT EP interrupt is shown below:
4126 : : * -# Read the Device All Endpoint Interrupt register
4127 : : * -# Repeat the following for each OUT EP interrupt bit set (from
4128 : : * LSB to MSB).
4129 : : * -# Read the Device Endpoint Interrupt (DOEPINTn) register
4130 : : * -# If "Transfer Complete" call the request complete function
4131 : : * -# If "Endpoint Disabled" complete the EP disable procedure.
4132 : : * -# If "AHB Error Interrupt" log error
4133 : : * -# If "Setup Phase Done" process Setup Packet (See Standard USB
4134 : : * Command Processing)
4135 : : */
4136 : 0 : static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
4137 : : {
4138 : : #define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
4139 : : do { \
4140 : : doepint_data_t doepint = {.d32=0}; \
4141 : : doepint.b.__intr = 1; \
4142 : : DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
4143 : : doepint.d32); \
4144 : : } while (0)
4145 : :
4146 : 0 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
4147 : : uint32_t ep_intr;
4148 : : doepint_data_t doepint = {.d32 = 0 };
4149 : : uint32_t epnum = 0;
4150 : : dwc_otg_pcd_ep_t *ep;
4151 : : dwc_ep_t *dwc_ep;
4152 : : dctl_data_t dctl = {.d32 = 0 };
4153 : 0 : gintmsk_data_t gintmsk = {.d32 = 0 };
4154 : :
4155 : :
4156 : : DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
4157 : :
4158 : : /* Read in the device interrupt bits */
4159 : 0 : ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
4160 : :
4161 : 0 : while (ep_intr) {
4162 : 0 : if (ep_intr & 0x1) {
4163 : : /* Get EP pointer */
4164 : : ep = get_out_ep(pcd, epnum);
4165 : 0 : dwc_ep = &ep->dwc_ep;
4166 : :
4167 : : #ifdef VERBOSE
4168 : : DWC_DEBUGPL(DBG_PCDV,
4169 : : "EP%d-%s: type=%d, mps=%d\n",
4170 : : dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
4171 : : dwc_ep->type, dwc_ep->maxpacket);
4172 : : #endif
4173 : 0 : doepint.d32 =
4174 : 0 : dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
4175 : : /* Moved this interrupt upper due to core deffect of asserting
4176 : : * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */
4177 : 0 : if (doepint.b.stsphsercvd) {
4178 : : deptsiz0_data_t deptsiz;
4179 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);
4180 : : deptsiz.d32 =
4181 : 0 : DWC_READ_REG32(&core_if->dev_if->
4182 : 0 : out_ep_regs[0]->doeptsiz);
4183 : 0 : if (core_if->snpsid >= OTG_CORE_REV_3_00a
4184 : 0 : && core_if->dma_enable
4185 : 0 : && core_if->dma_desc_enable == 0
4186 : 0 : && doepint.b.xfercompl
4187 : 0 : && deptsiz.b.xfersize == 24) {
4188 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum,
4189 : : xfercompl);
4190 : 0 : doepint.b.xfercompl = 0;
4191 : 0 : ep0_out_start(core_if, pcd);
4192 : : }
4193 : 0 : if ((core_if->dma_desc_enable) ||
4194 : 0 : (core_if->dma_enable
4195 : 0 : && core_if->snpsid >=
4196 : : OTG_CORE_REV_3_00a)) {
4197 : 0 : do_setup_in_status_phase(pcd);
4198 : : }
4199 : : }
4200 : : /* Transfer complete */
4201 : 0 : if (doepint.b.xfercompl) {
4202 : :
4203 : 0 : if (epnum == 0) {
4204 : : /* Clear the bit in DOEPINTn for this interrupt */
4205 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
4206 : 0 : if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
4207 : : DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
4208 : : DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint),
4209 : : doepint.d32);
4210 : : DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n",
4211 : : DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl));
4212 : :
4213 : 0 : if (core_if->snpsid >= OTG_CORE_REV_3_00a
4214 : 0 : && core_if->dma_enable == 0) {
4215 : : doepint_data_t doepint;
4216 : 0 : doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
4217 : 0 : out_ep_regs[0]->doepint);
4218 : 0 : if (pcd->ep0state == EP0_IDLE && doepint.b.sr) {
4219 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, sr);
4220 : : goto exit_xfercompl;
4221 : : }
4222 : : }
4223 : : /* In case of DDMA look at SR bit to go to the Data Stage */
4224 : 0 : if (core_if->dma_desc_enable) {
4225 : : dev_dma_desc_sts_t status = {.d32 = 0};
4226 : 0 : if (pcd->ep0state == EP0_IDLE) {
4227 : 0 : status.d32 = core_if->dev_if->setup_desc_addr[core_if->
4228 : 0 : dev_if->setup_desc_index]->status.d32;
4229 : 0 : if(pcd->data_terminated) {
4230 : 0 : pcd->data_terminated = 0;
4231 : 0 : status.d32 = core_if->dev_if->out_desc_addr->status.d32;
4232 : 0 : dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8);
4233 : : }
4234 : 0 : if (status.b.sr) {
4235 : 0 : if (doepint.b.setup) {
4236 : : DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n");
4237 : : /* Already started data stage, clear setup */
4238 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, setup);
4239 : 0 : doepint.b.setup = 0;
4240 : 0 : handle_ep0(pcd);
4241 : : /* Prepare for more setup packets */
4242 : 0 : if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
4243 : : pcd->ep0state == EP0_IN_DATA_PHASE) {
4244 : 0 : ep0_out_start(core_if, pcd);
4245 : : }
4246 : :
4247 : : goto exit_xfercompl;
4248 : : } else {
4249 : : /* Prepare for more setup packets */
4250 : : DWC_DEBUGPL(DBG_PCDV,
4251 : : "EP0_IDLE SR=1 setup=0 new setup comes\n");
4252 : 0 : ep0_out_start(core_if, pcd);
4253 : : }
4254 : : }
4255 : : } else {
4256 : : dwc_otg_pcd_request_t *req;
4257 : : dev_dma_desc_sts_t status = {.d32 = 0};
4258 : : diepint_data_t diepint0;
4259 : 0 : diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
4260 : 0 : in_ep_regs[0]->diepint);
4261 : :
4262 : 0 : if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) {
4263 : 0 : DWC_ERROR("EP0 is stalled/disconnected\n");
4264 : : }
4265 : :
4266 : : /* Clear IN xfercompl if set */
4267 : 0 : if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE
4268 : 0 : || pcd->ep0state == EP0_IN_DATA_PHASE)) {
4269 : 0 : DWC_WRITE_REG32(&core_if->dev_if->
4270 : 0 : in_ep_regs[0]->diepint, diepint0.d32);
4271 : : }
4272 : :
4273 : 0 : status.d32 = core_if->dev_if->setup_desc_addr[core_if->
4274 : 0 : dev_if->setup_desc_index]->status.d32;
4275 : :
4276 : 0 : if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len
4277 : 0 : && (pcd->ep0state == EP0_OUT_DATA_PHASE))
4278 : 0 : status.d32 = core_if->dev_if->out_desc_addr->status.d32;
4279 : 0 : if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
4280 : 0 : status.d32 = core_if->dev_if->
4281 : 0 : out_desc_addr->status.d32;
4282 : :
4283 : 0 : if (status.b.sr) {
4284 : 0 : if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
4285 : : DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
4286 : : } else {
4287 : : DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
4288 : : req = DWC_CIRCLEQ_FIRST(&ep->queue);
4289 : 0 : if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
4290 : : pcd->ep0state == EP0_OUT_DATA_PHASE) {
4291 : : /* Read arrived setup packet from req->buf */
4292 : 0 : dwc_memcpy(&pcd->setup_pkt->req,
4293 : 0 : req->buf + ep->dwc_ep.xfer_count, 8);
4294 : : }
4295 : 0 : req->actual = ep->dwc_ep.xfer_count;
4296 : 0 : dwc_otg_request_done(ep, req, -ECONNRESET);
4297 : 0 : ep->dwc_ep.start_xfer_buff = 0;
4298 : 0 : ep->dwc_ep.xfer_buff = 0;
4299 : 0 : ep->dwc_ep.xfer_len = 0;
4300 : : }
4301 : 0 : pcd->ep0state = EP0_IDLE;
4302 : 0 : if (doepint.b.setup) {
4303 : : DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
4304 : : /* Data stage started, clear setup */
4305 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, setup);
4306 : 0 : doepint.b.setup = 0;
4307 : 0 : handle_ep0(pcd);
4308 : : /* Prepare for setup packets if ep0in was enabled*/
4309 : 0 : if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
4310 : 0 : ep0_out_start(core_if, pcd);
4311 : : }
4312 : :
4313 : : goto exit_xfercompl;
4314 : : } else {
4315 : : /* Prepare for more setup packets */
4316 : : DWC_DEBUGPL(DBG_PCDV,
4317 : : "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
4318 : 0 : ep0_out_start(core_if, pcd);
4319 : : }
4320 : : }
4321 : : }
4322 : : }
4323 : 0 : if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable
4324 : 0 : && core_if->dma_desc_enable == 0) {
4325 : : doepint_data_t doepint_temp = {.d32 = 0};
4326 : : deptsiz0_data_t doeptsize0 = {.d32 = 0 };
4327 : 0 : doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
4328 : 0 : out_ep_regs[ep->dwc_ep.num]->doepint);
4329 : 0 : doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if->
4330 : 0 : out_ep_regs[ep->dwc_ep.num]->doeptsiz);
4331 : 0 : if (pcd->ep0state == EP0_IDLE) {
4332 : 0 : if (doepint_temp.b.sr) {
4333 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, sr);
4334 : : }
4335 : 0 : doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
4336 : 0 : out_ep_regs[0]->doepint);
4337 : 0 : if (doeptsize0.b.supcnt == 3) {
4338 : : DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n");
4339 : 0 : ep->dwc_ep.stp_rollover = 1;
4340 : : }
4341 : 0 : if (doepint.b.setup) {
4342 : : retry:
4343 : : /* Already started data stage, clear setup */
4344 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, setup);
4345 : 0 : doepint.b.setup = 0;
4346 : 0 : handle_ep0(pcd);
4347 : 0 : ep->dwc_ep.stp_rollover = 0;
4348 : : /* Prepare for more setup packets */
4349 : 0 : if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
4350 : : pcd->ep0state == EP0_IN_DATA_PHASE) {
4351 : 0 : ep0_out_start(core_if, pcd);
4352 : : }
4353 : 0 : goto exit_xfercompl;
4354 : : } else {
4355 : : /* Prepare for more setup packets */
4356 : : DWC_DEBUGPL(DBG_ANY,
4357 : : "EP0_IDLE SR=1 setup=0 new setup comes\n");
4358 : 0 : doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
4359 : 0 : out_ep_regs[0]->doepint);
4360 : 0 : if(doepint.b.setup)
4361 : : goto retry;
4362 : 0 : ep0_out_start(core_if, pcd);
4363 : : }
4364 : : } else {
4365 : : dwc_otg_pcd_request_t *req;
4366 : : diepint_data_t diepint0 = {.d32 = 0};
4367 : : doepint_data_t doepint_temp = {.d32 = 0};
4368 : : depctl_data_t diepctl0;
4369 : 0 : diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
4370 : 0 : in_ep_regs[0]->diepint);
4371 : 0 : diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if->
4372 : 0 : in_ep_regs[0]->diepctl);
4373 : :
4374 : 0 : if (pcd->ep0state == EP0_IN_DATA_PHASE
4375 : 0 : || pcd->ep0state == EP0_IN_STATUS_PHASE) {
4376 : 0 : if (diepint0.b.xfercompl) {
4377 : 0 : DWC_WRITE_REG32(&core_if->dev_if->
4378 : 0 : in_ep_regs[0]->diepint, diepint0.d32);
4379 : : }
4380 : 0 : if (diepctl0.b.epena) {
4381 : : diepint_data_t diepint = {.d32 = 0};
4382 : 0 : diepctl0.b.snak = 1;
4383 : 0 : DWC_WRITE_REG32(&core_if->dev_if->
4384 : 0 : in_ep_regs[0]->diepctl, diepctl0.d32);
4385 : : do {
4386 : 0 : dwc_udelay(10);
4387 : 0 : diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
4388 : 0 : in_ep_regs[0]->diepint);
4389 : 0 : } while (!diepint.b.inepnakeff);
4390 : 0 : diepint.b.inepnakeff = 1;
4391 : 0 : DWC_WRITE_REG32(&core_if->dev_if->
4392 : 0 : in_ep_regs[0]->diepint, diepint.d32);
4393 : 0 : diepctl0.d32 = 0;
4394 : 0 : diepctl0.b.epdis = 1;
4395 : 0 : DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl,
4396 : : diepctl0.d32);
4397 : : do {
4398 : 0 : dwc_udelay(10);
4399 : 0 : diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
4400 : 0 : in_ep_regs[0]->diepint);
4401 : 0 : } while (!diepint.b.epdisabled);
4402 : 0 : diepint.b.epdisabled = 1;
4403 : 0 : DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint,
4404 : : diepint.d32);
4405 : : }
4406 : : }
4407 : 0 : doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
4408 : 0 : out_ep_regs[ep->dwc_ep.num]->doepint);
4409 : 0 : if (doepint_temp.b.sr) {
4410 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, sr);
4411 : 0 : if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
4412 : : DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
4413 : : } else {
4414 : : DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
4415 : : req = DWC_CIRCLEQ_FIRST(&ep->queue);
4416 : 0 : if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
4417 : 0 : pcd->ep0state == EP0_OUT_DATA_PHASE) {
4418 : : /* Read arrived setup packet from req->buf */
4419 : 0 : dwc_memcpy(&pcd->setup_pkt->req,
4420 : 0 : req->buf + ep->dwc_ep.xfer_count, 8);
4421 : : }
4422 : 0 : req->actual = ep->dwc_ep.xfer_count;
4423 : 0 : dwc_otg_request_done(ep, req, -ECONNRESET);
4424 : 0 : ep->dwc_ep.start_xfer_buff = 0;
4425 : 0 : ep->dwc_ep.xfer_buff = 0;
4426 : 0 : ep->dwc_ep.xfer_len = 0;
4427 : : }
4428 : 0 : pcd->ep0state = EP0_IDLE;
4429 : 0 : if (doepint.b.setup) {
4430 : : DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
4431 : : /* Data stage started, clear setup */
4432 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, setup);
4433 : 0 : doepint.b.setup = 0;
4434 : 0 : handle_ep0(pcd);
4435 : : /* Prepare for setup packets if ep0in was enabled*/
4436 : 0 : if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
4437 : 0 : ep0_out_start(core_if, pcd);
4438 : : }
4439 : 0 : goto exit_xfercompl;
4440 : : } else {
4441 : : /* Prepare for more setup packets */
4442 : : DWC_DEBUGPL(DBG_PCDV,
4443 : : "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
4444 : 0 : ep0_out_start(core_if, pcd);
4445 : : }
4446 : : }
4447 : : }
4448 : : }
4449 : 0 : if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE)
4450 : 0 : handle_ep0(pcd);
4451 : : exit_xfercompl:
4452 : : DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
4453 : : dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32);
4454 : : } else {
4455 : 0 : if (core_if->dma_desc_enable == 0
4456 : 0 : || pcd->ep0state != EP0_IDLE)
4457 : 0 : handle_ep0(pcd);
4458 : : }
4459 : : #ifdef DWC_EN_ISOC
4460 : : } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
4461 : : if (doepint.b.pktdrpsts == 0) {
4462 : : /* Clear the bit in DOEPINTn for this interrupt */
4463 : : CLEAR_OUT_EP_INTR(core_if,
4464 : : epnum,
4465 : : xfercompl);
4466 : : complete_iso_ep(pcd, ep);
4467 : : } else {
4468 : :
4469 : : doepint_data_t doepint = {.d32 = 0 };
4470 : : doepint.b.xfercompl = 1;
4471 : : doepint.b.pktdrpsts = 1;
4472 : : DWC_WRITE_REG32
4473 : : (&core_if->dev_if->out_ep_regs
4474 : : [epnum]->doepint,
4475 : : doepint.d32);
4476 : : if (handle_iso_out_pkt_dropped
4477 : : (core_if, dwc_ep)) {
4478 : : complete_iso_ep(pcd,
4479 : : ep);
4480 : : }
4481 : : }
4482 : : #endif /* DWC_EN_ISOC */
4483 : : #ifdef DWC_UTE_PER_IO
4484 : : } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
4485 : : CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
4486 : : if (!ep->stopped)
4487 : : complete_xiso_ep(ep);
4488 : : #endif /* DWC_UTE_PER_IO */
4489 : : } else {
4490 : : /* Clear the bit in DOEPINTn for this interrupt */
4491 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum,
4492 : : xfercompl);
4493 : :
4494 : 0 : if (core_if->core_params->dev_out_nak) {
4495 : 0 : DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]);
4496 : 0 : pcd->core_if->ep_xfer_info[epnum].state = 0;
4497 : : #ifdef DEBUG
4498 : : print_memory_payload(pcd, dwc_ep);
4499 : : #endif
4500 : : }
4501 : 0 : complete_ep(ep);
4502 : : }
4503 : :
4504 : : }
4505 : :
4506 : : /* Endpoint disable */
4507 : 0 : if (doepint.b.epdisabled) {
4508 : :
4509 : : /* Clear the bit in DOEPINTn for this interrupt */
4510 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
4511 : 0 : if (core_if->core_params->dev_out_nak) {
4512 : : #ifdef DEBUG
4513 : : print_memory_payload(pcd, dwc_ep);
4514 : : #endif
4515 : : /* In case of timeout condition */
4516 : 0 : if (core_if->ep_xfer_info[epnum].state == 2) {
4517 : 0 : dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
4518 : : dev_global_regs->dctl);
4519 : 0 : dctl.b.cgoutnak = 1;
4520 : 0 : DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
4521 : : dctl.d32);
4522 : : /* Unmask goutnakeff interrupt which was masked
4523 : : * during handle nak out interrupt */
4524 : 0 : gintmsk.b.goutnakeff = 1;
4525 : 0 : DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
4526 : : 0, gintmsk.d32);
4527 : :
4528 : 0 : complete_ep(ep);
4529 : : }
4530 : : }
4531 : 0 : if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
4532 : : {
4533 : : dctl_data_t dctl;
4534 : : gintmsk_data_t intr_mask = {.d32 = 0};
4535 : : dwc_otg_pcd_request_t *req = 0;
4536 : :
4537 : 0 : dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
4538 : : dev_global_regs->dctl);
4539 : 0 : dctl.b.cgoutnak = 1;
4540 : 0 : DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
4541 : : dctl.d32);
4542 : :
4543 : : intr_mask.d32 = 0;
4544 : : intr_mask.b.incomplisoout = 1;
4545 : :
4546 : : /* Get any pending requests */
4547 : 0 : if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
4548 : : req = DWC_CIRCLEQ_FIRST(&ep->queue);
4549 : 0 : if (!req) {
4550 : 0 : DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
4551 : : } else {
4552 : 0 : dwc_otg_request_done(ep, req, 0);
4553 : 0 : start_next_request(ep);
4554 : : }
4555 : : } else {
4556 : 0 : DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
4557 : : }
4558 : : }
4559 : : }
4560 : : /* AHB Error */
4561 : 0 : if (doepint.b.ahberr) {
4562 : 0 : DWC_ERROR("EP%d OUT AHB Error\n", epnum);
4563 : 0 : DWC_ERROR("EP%d DEPDMA=0x%08x \n",
4564 : : epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma);
4565 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);
4566 : : }
4567 : : /* Setup Phase Done (contorl EPs) */
4568 : 0 : if (doepint.b.setup) {
4569 : : #ifdef DEBUG_EP0
4570 : : DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum);
4571 : : #endif
4572 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, setup);
4573 : :
4574 : 0 : handle_ep0(pcd);
4575 : : }
4576 : :
4577 : : /** OUT EP BNA Intr */
4578 : 0 : if (doepint.b.bna) {
4579 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, bna);
4580 : 0 : if (core_if->dma_desc_enable) {
4581 : : #ifdef DWC_EN_ISOC
4582 : : if (dwc_ep->type ==
4583 : : DWC_OTG_EP_TYPE_ISOC) {
4584 : : /*
4585 : : * This checking is performed to prevent first "false" BNA
4586 : : * handling occuring right after reconnect
4587 : : */
4588 : : if (dwc_ep->next_frame !=
4589 : : 0xffffffff)
4590 : : dwc_otg_pcd_handle_iso_bna(ep);
4591 : : } else
4592 : : #endif /* DWC_EN_ISOC */
4593 : : {
4594 : 0 : dwc_otg_pcd_handle_noniso_bna(ep);
4595 : : }
4596 : : }
4597 : : }
4598 : : /* Babble Interrupt */
4599 : 0 : if (doepint.b.babble) {
4600 : : DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",
4601 : : epnum);
4602 : 0 : handle_out_ep_babble_intr(pcd, epnum);
4603 : :
4604 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, babble);
4605 : : }
4606 : 0 : if (doepint.b.outtknepdis) {
4607 : : DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \
4608 : : disabled\n",epnum);
4609 : 0 : if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
4610 : 0 : doepmsk_data_t doepmsk = {.d32 = 0};
4611 : 0 : ep->dwc_ep.frame_num = core_if->frame_num;
4612 : 0 : if (ep->dwc_ep.bInterval > 1) {
4613 : : depctl_data_t depctl;
4614 : 0 : depctl.d32 = DWC_READ_REG32(&core_if->dev_if->
4615 : 0 : out_ep_regs[epnum]->doepctl);
4616 : 0 : if (ep->dwc_ep.frame_num & 0x1) {
4617 : 0 : depctl.b.setd1pid = 1;
4618 : 0 : depctl.b.setd0pid = 0;
4619 : : } else {
4620 : 0 : depctl.b.setd0pid = 1;
4621 : 0 : depctl.b.setd1pid = 0;
4622 : : }
4623 : 0 : DWC_WRITE_REG32(&core_if->dev_if->
4624 : 0 : out_ep_regs[epnum]->doepctl, depctl.d32);
4625 : : }
4626 : 0 : start_next_request(ep);
4627 : 0 : doepmsk.b.outtknepdis = 1;
4628 : 0 : DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
4629 : : doepmsk.d32, 0);
4630 : : }
4631 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
4632 : : }
4633 : :
4634 : : /* NAK Interrutp */
4635 : 0 : if (doepint.b.nak) {
4636 : : DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
4637 : 0 : handle_out_ep_nak_intr(pcd, epnum);
4638 : :
4639 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, nak);
4640 : : }
4641 : : /* NYET Interrutp */
4642 : 0 : if (doepint.b.nyet) {
4643 : : DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);
4644 : 0 : handle_out_ep_nyet_intr(pcd, epnum);
4645 : :
4646 : 0 : CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
4647 : : }
4648 : : }
4649 : :
4650 : 0 : epnum++;
4651 : 0 : ep_intr >>= 1;
4652 : : }
4653 : :
4654 : 0 : return 1;
4655 : :
4656 : : #undef CLEAR_OUT_EP_INTR
4657 : : }
4658 : : static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun)
4659 : : {
4660 : : int retval = 0;
4661 : 0 : if(!frm_overrun && curr_fr >= trgt_fr)
4662 : : retval = 1;
4663 : 0 : else if (frm_overrun
4664 : 0 : && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2)))
4665 : : retval = 1;
4666 : : return retval;
4667 : : }
4668 : : /**
4669 : : * Incomplete ISO IN Transfer Interrupt.
4670 : : * This interrupt indicates one of the following conditions occurred
4671 : : * while transmitting an ISOC transaction.
4672 : : * - Corrupted IN Token for ISOC EP.
4673 : : * - Packet not complete in FIFO.
4674 : : * The follow actions will be taken:
4675 : : * -# Determine the EP
4676 : : * -# Set incomplete flag in dwc_ep structure
4677 : : * -# Disable EP; when "Endpoint Disabled" interrupt is received
4678 : : * Flush FIFO
4679 : : */
4680 : 0 : int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)
4681 : : {
4682 : : gintsts_data_t gintsts;
4683 : :
4684 : : #ifdef DWC_EN_ISOC
4685 : : dwc_otg_dev_if_t *dev_if;
4686 : : deptsiz_data_t deptsiz = {.d32 = 0 };
4687 : : depctl_data_t depctl = {.d32 = 0 };
4688 : : dsts_data_t dsts = {.d32 = 0 };
4689 : : dwc_ep_t *dwc_ep;
4690 : : int i;
4691 : :
4692 : : dev_if = GET_CORE_IF(pcd)->dev_if;
4693 : :
4694 : : for (i = 1; i <= dev_if->num_in_eps; ++i) {
4695 : : dwc_ep = &pcd->in_ep[i].dwc_ep;
4696 : : if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
4697 : : deptsiz.d32 =
4698 : : DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
4699 : : depctl.d32 =
4700 : : DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
4701 : :
4702 : : if (depctl.b.epdis && deptsiz.d32) {
4703 : : set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);
4704 : : if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
4705 : : dwc_ep->cur_pkt = 0;
4706 : : dwc_ep->proc_buf_num =
4707 : : (dwc_ep->proc_buf_num ^ 1) & 0x1;
4708 : :
4709 : : if (dwc_ep->proc_buf_num) {
4710 : : dwc_ep->cur_pkt_addr =
4711 : : dwc_ep->xfer_buff1;
4712 : : dwc_ep->cur_pkt_dma_addr =
4713 : : dwc_ep->dma_addr1;
4714 : : } else {
4715 : : dwc_ep->cur_pkt_addr =
4716 : : dwc_ep->xfer_buff0;
4717 : : dwc_ep->cur_pkt_dma_addr =
4718 : : dwc_ep->dma_addr0;
4719 : : }
4720 : :
4721 : : }
4722 : :
4723 : : dsts.d32 =
4724 : : DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
4725 : : dev_global_regs->dsts);
4726 : : dwc_ep->next_frame = dsts.b.soffn;
4727 : :
4728 : : dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
4729 : : (pcd),
4730 : : dwc_ep);
4731 : : }
4732 : : }
4733 : : }
4734 : :
4735 : : #else
4736 : : depctl_data_t depctl = {.d32 = 0 };
4737 : : dwc_ep_t *dwc_ep;
4738 : : dwc_otg_dev_if_t *dev_if;
4739 : : int i;
4740 : 0 : dev_if = GET_CORE_IF(pcd)->dev_if;
4741 : :
4742 : : DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n");
4743 : :
4744 : 0 : for (i = 1; i <= dev_if->num_in_eps; ++i) {
4745 : 0 : dwc_ep = &pcd->in_ep[i-1].dwc_ep;
4746 : 0 : depctl.d32 =
4747 : 0 : DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
4748 : 0 : if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
4749 : 0 : if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num,
4750 : : dwc_ep->frm_overrun))
4751 : : {
4752 : 0 : depctl.d32 =
4753 : 0 : DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
4754 : 0 : depctl.b.snak = 1;
4755 : 0 : depctl.b.epdis = 1;
4756 : 0 : DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32);
4757 : : }
4758 : : }
4759 : : }
4760 : :
4761 : : /*intr_mask.b.incomplisoin = 1;
4762 : : DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
4763 : : intr_mask.d32, 0); */
4764 : : #endif //DWC_EN_ISOC
4765 : :
4766 : : /* Clear interrupt */
4767 : 0 : gintsts.d32 = 0;
4768 : 0 : gintsts.b.incomplisoin = 1;
4769 : 0 : DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
4770 : : gintsts.d32);
4771 : :
4772 : 0 : return 1;
4773 : : }
4774 : :
4775 : : /**
4776 : : * Incomplete ISO OUT Transfer Interrupt.
4777 : : *
4778 : : * This interrupt indicates that the core has dropped an ISO OUT
4779 : : * packet. The following conditions can be the cause:
4780 : : * - FIFO Full, the entire packet would not fit in the FIFO.
4781 : : * - CRC Error
4782 : : * - Corrupted Token
4783 : : * The follow actions will be taken:
4784 : : * -# Determine the EP
4785 : : * -# Set incomplete flag in dwc_ep structure
4786 : : * -# Read any data from the FIFO
4787 : : * -# Disable EP. When "Endpoint Disabled" interrupt is received
4788 : : * re-enable EP.
4789 : : */
4790 : 0 : int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)
4791 : : {
4792 : :
4793 : : gintsts_data_t gintsts;
4794 : :
4795 : : #ifdef DWC_EN_ISOC
4796 : : dwc_otg_dev_if_t *dev_if;
4797 : : deptsiz_data_t deptsiz = {.d32 = 0 };
4798 : : depctl_data_t depctl = {.d32 = 0 };
4799 : : dsts_data_t dsts = {.d32 = 0 };
4800 : : dwc_ep_t *dwc_ep;
4801 : : int i;
4802 : :
4803 : : dev_if = GET_CORE_IF(pcd)->dev_if;
4804 : :
4805 : : for (i = 1; i <= dev_if->num_out_eps; ++i) {
4806 : : dwc_ep = &pcd->in_ep[i].dwc_ep;
4807 : : if (pcd->out_ep[i].dwc_ep.active &&
4808 : : pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
4809 : : deptsiz.d32 =
4810 : : DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz);
4811 : : depctl.d32 =
4812 : : DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
4813 : :
4814 : : if (depctl.b.epdis && deptsiz.d32) {
4815 : : set_current_pkt_info(GET_CORE_IF(pcd),
4816 : : &pcd->out_ep[i].dwc_ep);
4817 : : if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
4818 : : dwc_ep->cur_pkt = 0;
4819 : : dwc_ep->proc_buf_num =
4820 : : (dwc_ep->proc_buf_num ^ 1) & 0x1;
4821 : :
4822 : : if (dwc_ep->proc_buf_num) {
4823 : : dwc_ep->cur_pkt_addr =
4824 : : dwc_ep->xfer_buff1;
4825 : : dwc_ep->cur_pkt_dma_addr =
4826 : : dwc_ep->dma_addr1;
4827 : : } else {
4828 : : dwc_ep->cur_pkt_addr =
4829 : : dwc_ep->xfer_buff0;
4830 : : dwc_ep->cur_pkt_dma_addr =
4831 : : dwc_ep->dma_addr0;
4832 : : }
4833 : :
4834 : : }
4835 : :
4836 : : dsts.d32 =
4837 : : DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
4838 : : dev_global_regs->dsts);
4839 : : dwc_ep->next_frame = dsts.b.soffn;
4840 : :
4841 : : dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
4842 : : (pcd),
4843 : : dwc_ep);
4844 : : }
4845 : : }
4846 : : }
4847 : : #else
4848 : : /** @todo implement ISR */
4849 : : gintmsk_data_t intr_mask = {.d32 = 0 };
4850 : : dwc_otg_core_if_t *core_if;
4851 : : deptsiz_data_t deptsiz = {.d32 = 0 };
4852 : : depctl_data_t depctl = {.d32 = 0 };
4853 : : dctl_data_t dctl = {.d32 = 0 };
4854 : : dwc_ep_t *dwc_ep = NULL;
4855 : : int i;
4856 : 0 : core_if = GET_CORE_IF(pcd);
4857 : :
4858 : 0 : for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
4859 : 0 : dwc_ep = &pcd->out_ep[i].dwc_ep;
4860 : 0 : depctl.d32 =
4861 : 0 : DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
4862 : 0 : if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) {
4863 : 0 : core_if->dev_if->isoc_ep = dwc_ep;
4864 : : deptsiz.d32 =
4865 : 0 : DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz);
4866 : 0 : break;
4867 : : }
4868 : : }
4869 : 0 : dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
4870 : 0 : gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
4871 : 0 : intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
4872 : :
4873 : 0 : if (!intr_mask.b.goutnakeff) {
4874 : : /* Unmask it */
4875 : 0 : intr_mask.b.goutnakeff = 1;
4876 : 0 : DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32);
4877 : : }
4878 : 0 : if (!gintsts.b.goutnakeff) {
4879 : 0 : dctl.b.sgoutnak = 1;
4880 : : }
4881 : 0 : DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
4882 : :
4883 : 0 : depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
4884 : 0 : if (depctl.b.epena) {
4885 : 0 : depctl.b.epdis = 1;
4886 : 0 : depctl.b.snak = 1;
4887 : : }
4888 : 0 : DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32);
4889 : :
4890 : : intr_mask.d32 = 0;
4891 : : intr_mask.b.incomplisoout = 1;
4892 : :
4893 : : #endif /* DWC_EN_ISOC */
4894 : :
4895 : : /* Clear interrupt */
4896 : 0 : gintsts.d32 = 0;
4897 : 0 : gintsts.b.incomplisoout = 1;
4898 : 0 : DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
4899 : : gintsts.d32);
4900 : :
4901 : 0 : return 1;
4902 : : }
4903 : :
4904 : : /**
4905 : : * This function handles the Global IN NAK Effective interrupt.
4906 : : *
4907 : : */
4908 : 0 : int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)
4909 : : {
4910 : 0 : dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
4911 : : depctl_data_t diepctl = {.d32 = 0 };
4912 : 0 : gintmsk_data_t intr_mask = {.d32 = 0 };
4913 : : gintsts_data_t gintsts;
4914 : : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
4915 : : int i;
4916 : :
4917 : : DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
4918 : :
4919 : : /* Disable all active IN EPs */
4920 : 0 : for (i = 0; i <= dev_if->num_in_eps; i++) {
4921 : 0 : diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
4922 : 0 : if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {
4923 : 0 : if (core_if->start_predict > 0)
4924 : 0 : core_if->start_predict++;
4925 : 0 : diepctl.b.epdis = 1;
4926 : 0 : diepctl.b.snak = 1;
4927 : 0 : DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32);
4928 : : }
4929 : : }
4930 : :
4931 : :
4932 : : /* Disable the Global IN NAK Effective Interrupt */
4933 : 0 : intr_mask.b.ginnakeff = 1;
4934 : 0 : DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
4935 : : intr_mask.d32, 0);
4936 : :
4937 : : /* Clear interrupt */
4938 : 0 : gintsts.d32 = 0;
4939 : 0 : gintsts.b.ginnakeff = 1;
4940 : 0 : DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
4941 : : gintsts.d32);
4942 : :
4943 : 0 : return 1;
4944 : : }
4945 : :
4946 : : /**
4947 : : * OUT NAK Effective.
4948 : : *
4949 : : */
4950 : 0 : int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)
4951 : : {
4952 : 0 : dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
4953 : 0 : gintmsk_data_t intr_mask = {.d32 = 0 };
4954 : : gintsts_data_t gintsts;
4955 : : depctl_data_t doepctl;
4956 : : int i;
4957 : :
4958 : : /* Disable the Global OUT NAK Effective Interrupt */
4959 : 0 : intr_mask.b.goutnakeff = 1;
4960 : 0 : DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
4961 : : intr_mask.d32, 0);
4962 : :
4963 : : /* If DEV OUT NAK enabled*/
4964 : 0 : if (pcd->core_if->core_params->dev_out_nak) {
4965 : : /* Run over all out endpoints to determine the ep number on
4966 : : * which the timeout has happened
4967 : : */
4968 : 0 : for (i = 0; i <= dev_if->num_out_eps; i++) {
4969 : 0 : if ( pcd->core_if->ep_xfer_info[i].state == 2 )
4970 : : break;
4971 : : }
4972 : 0 : if (i > dev_if->num_out_eps) {
4973 : : dctl_data_t dctl;
4974 : 0 : dctl.d32 =
4975 : 0 : DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
4976 : 0 : dctl.b.cgoutnak = 1;
4977 : 0 : DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl,
4978 : : dctl.d32);
4979 : : goto out;
4980 : : }
4981 : :
4982 : : /* Disable the endpoint */
4983 : 0 : doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
4984 : 0 : if (doepctl.b.epena) {
4985 : 0 : doepctl.b.epdis = 1;
4986 : 0 : doepctl.b.snak = 1;
4987 : : }
4988 : 0 : DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
4989 : 0 : return 1;
4990 : : }
4991 : : /* We come here from Incomplete ISO OUT handler */
4992 : 0 : if (dev_if->isoc_ep) {
4993 : : dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep;
4994 : 0 : uint32_t epnum = dwc_ep->num;
4995 : : doepint_data_t doepint;
4996 : : doepint.d32 =
4997 : 0 : DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint);
4998 : 0 : dev_if->isoc_ep = NULL;
4999 : 0 : doepctl.d32 =
5000 : 0 : DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl);
5001 : 0 : DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32);
5002 : 0 : if (doepctl.b.epena) {
5003 : 0 : doepctl.b.epdis = 1;
5004 : 0 : doepctl.b.snak = 1;
5005 : : }
5006 : 0 : DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl,
5007 : : doepctl.d32);
5008 : : return 1;
5009 : : } else
5010 : 0 : DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
5011 : : "Global OUT NAK Effective\n");
5012 : :
5013 : : out:
5014 : : /* Clear interrupt */
5015 : 0 : gintsts.d32 = 0;
5016 : 0 : gintsts.b.goutnakeff = 1;
5017 : 0 : DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
5018 : : gintsts.d32);
5019 : :
5020 : 0 : return 1;
5021 : : }
5022 : :
5023 : : /**
5024 : : * PCD interrupt handler.
5025 : : *
5026 : : * The PCD handles the device interrupts. Many conditions can cause a
5027 : : * device interrupt. When an interrupt occurs, the device interrupt
5028 : : * service routine determines the cause of the interrupt and
5029 : : * dispatches handling to the appropriate function. These interrupt
5030 : : * handling functions are described below.
5031 : : *
5032 : : * All interrupt registers are processed from LSB to MSB.
5033 : : *
5034 : : */
5035 : 3 : int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
5036 : : {
5037 : 3 : dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
5038 : : #ifdef VERBOSE
5039 : : dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
5040 : : #endif
5041 : : gintsts_data_t gintr_status;
5042 : : int32_t retval = 0;
5043 : :
5044 : : /* Exit from ISR if core is hibernated */
5045 : 3 : if (core_if->hibernation_suspend == 1) {
5046 : : return retval;
5047 : : }
5048 : : #ifdef VERBOSE
5049 : : DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n",
5050 : : __func__,
5051 : : DWC_READ_REG32(&global_regs->gintsts),
5052 : : DWC_READ_REG32(&global_regs->gintmsk));
5053 : : #endif
5054 : :
5055 : 3 : if (dwc_otg_is_device_mode(core_if)) {
5056 : 0 : DWC_SPINLOCK(pcd->lock);
5057 : : #ifdef VERBOSE
5058 : : DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n",
5059 : : __func__,
5060 : : DWC_READ_REG32(&global_regs->gintsts),
5061 : : DWC_READ_REG32(&global_regs->gintmsk));
5062 : : #endif
5063 : :
5064 : 0 : gintr_status.d32 = dwc_otg_read_core_intr(core_if);
5065 : :
5066 : : DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
5067 : : __func__, gintr_status.d32);
5068 : :
5069 : 0 : if (gintr_status.b.sofintr) {
5070 : : retval |= dwc_otg_pcd_handle_sof_intr(pcd);
5071 : : }
5072 : 0 : if (gintr_status.b.rxstsqlvl) {
5073 : 0 : retval |=
5074 : 0 : dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
5075 : : }
5076 : 0 : if (gintr_status.b.nptxfempty) {
5077 : 0 : retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
5078 : : }
5079 : 0 : if (gintr_status.b.goutnakeff) {
5080 : 0 : retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);
5081 : : }
5082 : 0 : if (gintr_status.b.i2cintr) {
5083 : 0 : retval |= dwc_otg_pcd_handle_i2c_intr(pcd);
5084 : : }
5085 : 0 : if (gintr_status.b.erlysuspend) {
5086 : 0 : retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
5087 : : }
5088 : 0 : if (gintr_status.b.usbreset) {
5089 : 0 : retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
5090 : : }
5091 : 0 : if (gintr_status.b.enumdone) {
5092 : 0 : retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
5093 : : }
5094 : 0 : if (gintr_status.b.isooutdrop) {
5095 : 0 : retval |=
5096 : 0 : dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
5097 : : (pcd);
5098 : : }
5099 : 0 : if (gintr_status.b.eopframe) {
5100 : 0 : retval |=
5101 : 0 : dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
5102 : : }
5103 : 0 : if (gintr_status.b.inepint) {
5104 : 0 : if (!core_if->multiproc_int_enable) {
5105 : 0 : retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
5106 : : }
5107 : : }
5108 : 0 : if (gintr_status.b.outepintr) {
5109 : 0 : if (!core_if->multiproc_int_enable) {
5110 : 0 : retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
5111 : : }
5112 : : }
5113 : 0 : if (gintr_status.b.epmismatch) {
5114 : 0 : retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd);
5115 : : }
5116 : 0 : if (gintr_status.b.fetsusp) {
5117 : 0 : retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd);
5118 : : }
5119 : 0 : if (gintr_status.b.ginnakeff) {
5120 : 0 : retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);
5121 : : }
5122 : 0 : if (gintr_status.b.incomplisoin) {
5123 : 0 : retval |=
5124 : 0 : dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
5125 : : }
5126 : 0 : if (gintr_status.b.incomplisoout) {
5127 : 0 : retval |=
5128 : 0 : dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
5129 : : }
5130 : :
5131 : : /* In MPI mode Device Endpoints interrupts are asserted
5132 : : * without setting outepintr and inepint bits set, so these
5133 : : * Interrupt handlers are called without checking these bit-fields
5134 : : */
5135 : 0 : if (core_if->multiproc_int_enable) {
5136 : 0 : retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
5137 : 0 : retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
5138 : : }
5139 : : #ifdef VERBOSE
5140 : : DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
5141 : : DWC_READ_REG32(&global_regs->gintsts));
5142 : : #endif
5143 : 0 : DWC_SPINUNLOCK(pcd->lock);
5144 : : }
5145 : 3 : return retval;
5146 : : }
5147 : :
5148 : : #endif /* DWC_HOST_ONLY */
|