blob: 1347bd8bcb4ce018af3765b7bd0d21135886d4c4 [file] [log] [blame]
Amol Jadif3d5a892013-07-23 16:09:44 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/* This code implements the DesignWare Cores USB 3.0 driver. This file only
30 * implements the state machine and higher level logic as described in the
31 * SNPS DesignWare Cores SS USB3.0 Controller databook.
32 * Another file (dwc_hw.c) file implements the functions to interact with
33 * the dwc hardware registers directly.
34 */
35
36#include <debug.h>
37#include <reg.h>
38#include <bits.h>
39#include <string.h>
40#include <malloc.h>
41#include <stdlib.h>
42#include <arch/defines.h>
43#include <platform/timer.h>
44#include <platform/interrupts.h>
45#include <platform/irqs.h>
46#include <kernel/event.h>
47#include <usb30_dwc.h>
48#include <usb30_dwc_hw.h>
49#include <usb30_dwc_hwio.h>
50
51//#define DEBUG_USB
52
53#ifdef DEBUG_USB
54#define DBG(...) dprintf(ALWAYS, __VA_ARGS__)
55#else
56#define DBG(...)
57#endif
58
59#define ERR(...) dprintf(ALWAYS, __VA_ARGS__)
60
61/* debug only: enum string lookup for debug purpose */
62char* ss_link_state_lookup[20];
63char* hs_link_state_lookup[20];
64char* event_lookup_device[20];
65char* event_lookup_ep[20];
66char* dev_ctrl_state_lookup[20];
67char* ep_state_lookup[20];
68char* speed_lookup[20];
69char* cmd_lookup[20];
70
71/* debug only: initialize the enum lookup */
72void dwc_debug_lookup_init(void)
73{
74 /* EP event */
75 event_lookup_ep[DWC_EVENT_EP_CMD_COMPLETE] = "DWC_EVENT_EP_CMD_COMPLETE ";
76 event_lookup_ep[DWC_EVENT_EP_XFER_NOT_READY] = "DWC_EVENT_EP_XFER_NOT_READY ";
77 event_lookup_ep[DWC_EVENT_EP_XFER_IN_PROGRESS] = "DWC_EVENT_EP_XFER_IN_PROGRESS";
78 event_lookup_ep[DWC_EVENT_EP_XFER_COMPLETE] = "DWC_EVENT_EP_XFER_COMPLETE ";
79
80 /* Device event */
81 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_VENDOR_DEVICE_TEST_LMP] = "DWC_EVENT_DEVICE_EVENT_ID_VENDOR_DEVICE_TEST_LMP";
82 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_BUFFER_OVERFLOW] = "DWC_EVENT_DEVICE_EVENT_ID_BUFFER_OVERFLOW ";
83 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_GENERIC_CMD_COMPLETE] = "DWC_EVENT_DEVICE_EVENT_ID_GENERIC_CMD_COMPLETE ";
84 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_ERRATIC_ERROR] = "DWC_EVENT_DEVICE_EVENT_ID_ERRATIC_ERROR ";
85 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_SOF] = "DWC_EVENT_DEVICE_EVENT_ID_SOF ";
86 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_SUSPEND_ENTRY] = "DWC_EVENT_DEVICE_EVENT_ID_SUSPEND_ENTRY ";
87 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_HIBER] = "DWC_EVENT_DEVICE_EVENT_ID_HIBER ";
88 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_WAKEUP] = "DWC_EVENT_DEVICE_EVENT_ID_WAKEUP ";
89 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_USB_LINK_STATUS_CHANGE] = "DWC_EVENT_DEVICE_EVENT_ID_USB_LINK_STATUS_CHANGE";
90 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_CONNECT_DONE] = "DWC_EVENT_DEVICE_EVENT_ID_CONNECT_DONE ";
91 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_USB_RESET] = "DWC_EVENT_DEVICE_EVENT_ID_USB_RESET ";
92 event_lookup_device[DWC_EVENT_DEVICE_EVENT_ID_DISCONNECT] = "DWC_EVENT_DEVICE_EVENT_ID_DISCONNECT ";
93
94 /* Control state */
95 dev_ctrl_state_lookup[EP_FSM_INIT] = "EP_FSM_INIT ";
96 dev_ctrl_state_lookup[EP_FSM_SETUP] = "EP_FSM_SETUP ";
97 dev_ctrl_state_lookup[EP_FSM_CTRL_DATA] = "EP_FSM_CTRL_DATA ";
98 dev_ctrl_state_lookup[EP_FSM_WAIT_FOR_HOST_2] = "EP_FSM_WAIT_FOR_HOST_2";
99 dev_ctrl_state_lookup[EP_FSM_WAIT_FOR_HOST_3] = "EP_FSM_WAIT_FOR_HOST_3";
100 dev_ctrl_state_lookup[EP_FSM_STATUS_2] = "EP_FSM_STATUS_2 ";
101 dev_ctrl_state_lookup[EP_FSM_STATUS_3] = "EP_FSM_STATUS_3 ";
102 dev_ctrl_state_lookup[EP_FSM_STALL] = "EP_FSM_STALL ";
103
104 /* EP state */
105 ep_state_lookup[EP_STATE_INIT] = "EP_STATE_INIT";
106 ep_state_lookup[EP_STATE_INACTIVE] = "EP_STATE_INACTIVE";
107 ep_state_lookup[EP_STATE_START_TRANSFER] = "EP_STATE_START_TRANSFER";
108 ep_state_lookup[EP_STATE_XFER_IN_PROG] = "EP_STATE_XFER_IN_PROG";
109
110 /* HS link status */
111 hs_link_state_lookup[ON] = "ON ";
112 hs_link_state_lookup[L1] = "L1 ";
113 hs_link_state_lookup[L2] = "L2 ";
114 hs_link_state_lookup[DISCONNECTED] = "DISCONNECTED ";
115 hs_link_state_lookup[EARLY_SUSPEND] = "EARLY_SUSPEND";
116 hs_link_state_lookup[RESET] = "RESET ";
117 hs_link_state_lookup[RESUME] = "RESUME ";
118
119 /* SS link status */
120 ss_link_state_lookup[U0] = "U0 ";
121 ss_link_state_lookup[U1] = "U1 ";
122 ss_link_state_lookup[U2] = "U2 ";
123 ss_link_state_lookup[U3] = "U3 ";
124 ss_link_state_lookup[SS_DIS] = "SS_DIS ";
125 ss_link_state_lookup[RX_DET] = "RX_DET ";
126 ss_link_state_lookup[SS_INACT] = "SS_INACT ";
127 ss_link_state_lookup[POLL] = "POLL ";
128 ss_link_state_lookup[RECOV] = "RECOV ";
129 ss_link_state_lookup[HRESET] = "HRESET ";
130 ss_link_state_lookup[CMPLY] = "CMPLY ";
131 ss_link_state_lookup[LPBK] = "LPBK ";
132 ss_link_state_lookup[RESUME_RESET] = "RESUME_RESET";
133
134 /* connection speed */
135 speed_lookup[DSTS_CONNECTSPD_HS] = "DSTS_CONNECTSPD_HS ";
136 speed_lookup[DSTS_CONNECTSPD_FS1] = "DSTS_CONNECTSPD_FS1";
137 speed_lookup[DSTS_CONNECTSPD_LS] = "DSTS_CONNECTSPD_LS ";
138 speed_lookup[DSTS_CONNECTSPD_FS2] = "DSTS_CONNECTSPD_FS1";
139 speed_lookup[DSTS_CONNECTSPD_SS] = "DSTS_CONNECTSPD_SS ";
140
141 /* dwc command */
142 cmd_lookup[DEPCMD_CMD_SET_EP_CONF] = "DEPCMD_CMD_SET_EP_CONF ";
143 cmd_lookup[DEPCMD_CMD_SET_TR_CONF] = "DEPCMD_CMD_SET_TR_CONF ";
144 cmd_lookup[DEPCMD_CMD_GET_EP_STATE] = "DEPCMD_CMD_GET_EP_STATE ";
145 cmd_lookup[DEPCMD_CMD_SET_STALL] = "DEPCMD_CMD_SET_STALL ";
146 cmd_lookup[DEPCMD_CMD_CLEAR_STALL] = "DEPCMD_CMD_CLEAR_STALL ";
147 cmd_lookup[DEPCMD_CMD_START_TRANSFER] = "DEPCMD_CMD_START_TRANSFER ";
148 cmd_lookup[DEPCMD_CMD_UPDATE_TRANSFER] = "DEPCMD_CMD_UPDATE_TRANSFER";
149 cmd_lookup[DEPCMD_CMD_END_TRANSFER] = "DEPCMD_CMD_END_TRANSFER ";
150 cmd_lookup[DEPCMD_CMD_START_NEW_CONF] = "DEPCMD_CMD_START_NEW_CONF ";
151}
152
153
154/******************************** DWC global **********************************/
155/* Initialize DWC driver. */
156dwc_dev_t* dwc_init(dwc_config_t *config)
157{
158 dwc_dev_t *dev = (dwc_dev_t*) malloc(sizeof(dwc_dev_t));
159 ASSERT(dev);
160
161 memset(dev, 0, sizeof(dev));
162
163 /* save config info */
164 dev->base = config->base;
165 dev->event_buf.buf = config->event_buf;
166 dev->event_buf.buf_size = config->event_buf_size;
167 dev->event_buf.index = 0;
168 dev->event_buf.max_index = (config->event_buf_size)/4 - 1; /* (max num of 4 byte events) - 1 */
169
170 dev->notify_context = config->notify_context;
171 dev->notify = config->notify;
172
173 /* allocate buffer for receiving setup packet */
174 dev->setup_pkt = memalign(CACHE_LINE, ROUNDUP(DWC_SETUP_PKT_LEN, CACHE_LINE));
175 ASSERT(dev->setup_pkt);
176
177 /* callback function to handler setup packet */
178 dev->setup_context = config->setup_context;
179 dev->setup_handler = config->setup_handler;
180
181 /* read core version from h/w */
182 dev->core_id = dwc_coreid(dev);
183
184 /* register for interrupt */
185 register_int_handler(USB30_EE1_IRQ, dwc_irq_handler_ee1, dev);
186
187#ifdef DEBUG_USB
188 /* note: only for debug */
189 dwc_debug_lookup_init();
190#endif
191
192 return dev;
193}
194
195/* interrupt handler */
196static enum handler_return dwc_irq_handler_ee1(void* context)
197{
198 dwc_dev_t *dev;
199 uint16_t event_size; /* number of bytes used by the event */
200 uint32_t event[3] = {0x0, 0x0, 0x0};
201
202 /* get the device on which this interrupt occurred */
203 dev = (dwc_dev_t *) context;
204
205 /* while there are events to be processed */
206 while((event_size = dwc_event_get_next(dev, event)))
207 {
208 /* device event? */
209 if(DWC_EVENT_IS_DEVICE_EVENT(*event))
210 {
211 /* handle device events */
212 dwc_event_handler_device(dev, event);
213 }
214 else
215 {
216 /* endpoint event */
217 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
218
219 if ((ep_phy_num == 0) ||
220 (ep_phy_num == 1))
221 {
222 /* handle control ep event */
223 dwc_event_handler_ep_ctrl(dev, event);
224 }
225 else
226 {
227 /* handle non-control ep event. only bulk ep is supported.*/
228 dwc_event_handler_ep_bulk(dev, event);
229 }
230 }
231
232 /* update number of bytes processed */
233 dwc_event_processed(dev, event_size);
234 }
235
236 return INT_NO_RESCHEDULE;
237}
238
239/*====================== DWC Event configuration/handling functions========== */
240
241/* handles all device specific events */
242void dwc_event_handler_device(dwc_dev_t *dev, uint32_t *event)
243{
244 dwc_event_device_event_id_t event_id = DWC_EVENT_DEVICE_EVENT_ID(*event);
245
246 DBG("\nDEVICE_EVENT: %s in %s \n", event_lookup_device[event_id],
247 dev_ctrl_state_lookup[dev->ctrl_state]);
248
249 switch (event_id)
250 {
251 case DWC_EVENT_DEVICE_EVENT_ID_VENDOR_DEVICE_TEST_LMP:
252 case DWC_EVENT_DEVICE_EVENT_ID_BUFFER_OVERFLOW:
253 case DWC_EVENT_DEVICE_EVENT_ID_GENERIC_CMD_COMPLETE:
254 case DWC_EVENT_DEVICE_EVENT_ID_ERRATIC_ERROR:
255 case DWC_EVENT_DEVICE_EVENT_ID_SOF:
256 case DWC_EVENT_DEVICE_EVENT_ID_SUSPEND_ENTRY:
257 case DWC_EVENT_DEVICE_EVENT_ID_HIBER:
258 case DWC_EVENT_DEVICE_EVENT_ID_WAKEUP:
259 break;
260 case DWC_EVENT_DEVICE_EVENT_ID_USB_LINK_STATUS_CHANGE:
261 {
262 dwc_event_device_link_status_change(dev, event);
263 }
264 break;
265 case DWC_EVENT_DEVICE_EVENT_ID_CONNECT_DONE:
266 {
267 dwc_event_device_connect_done(dev);
268 }
269 break;
270 case DWC_EVENT_DEVICE_EVENT_ID_USB_RESET:
271 {
272 dwc_event_device_reset(dev);
273 }
274 break;
275 case DWC_EVENT_DEVICE_EVENT_ID_DISCONNECT:
276 {
277 dwc_event_device_disconnect(dev);
278 }
279 break;
280
281 default:
282 ASSERT(0);
283 }
284}
285
286/* handle link status change event: does nothing for now.
287 * only for debug purpose.
288 */
289static void dwc_event_device_link_status_change(dwc_dev_t *dev, uint32_t *event)
290{
291#ifdef DEBUG_USB
292 uint8_t event_info = DWC_EVENT_DEVICE_EVENT_INFO(*event);
293 uint8_t ss_event = DWC_EVENT_DEVICE_EVENT_INFO_SS_EVENT(*event);
294 uint8_t link_state = DWC_EVENT_DEVICE_EVENT_INFO_LINK_STATE(event_info);
295
296 if(ss_event)
297 {
298 DBG("\n SS link state = %s (%d)\n", ss_link_state_lookup[link_state], link_state);
299 }
300 else
301 {
302 DBG("\n HS link state = %s (%d)\n", hs_link_state_lookup[link_state], link_state);
303 }
304#endif
305}
306
307/* handle disconnect event */
308static void dwc_event_device_disconnect(dwc_dev_t *dev)
309{
310 /* inform client that device is disconnected */
311 if (dev->notify)
312 dev->notify(dev->notify_context, DWC_NOTIFY_EVENT_DISCONNECTED);
313}
314
315/* handle connect event: snps 8.1.3 */
316static void dwc_event_device_connect_done(dwc_dev_t *dev)
317{
318 uint8_t speed;
319 uint16_t max_pkt_size = 0;
320 dwc_notify_event_t dwc_event = DWC_NOTIFY_EVENT_DISCONNECTED;
321
322 /* get connection speed */
323 speed = dwc_connectspeed(dev);
324
325 switch (speed)
326 {
327 case DSTS_CONNECTSPD_SS:
328 {
329 max_pkt_size = 512;
330 dwc_event = DWC_NOTIFY_EVENT_CONNECTED_SS;
331 }
332 break;
333 case DSTS_CONNECTSPD_HS:
334 {
335 max_pkt_size = 64;
336 dwc_event = DWC_NOTIFY_EVENT_CONNECTED_HS;
337 }
338 break;
339 case DSTS_CONNECTSPD_FS1:
340 case DSTS_CONNECTSPD_FS2:
341 {
342 max_pkt_size = 64;
343 dwc_event = DWC_NOTIFY_EVENT_CONNECTED_FS;
344 }
345 break;
346 case DSTS_CONNECTSPD_LS:
347 {
348 max_pkt_size = 8;
349 dwc_event = DWC_NOTIFY_EVENT_CONNECTED_LS;
350 }
351 break;
352 default:
353 ASSERT(0);
354 }
355
356 DBG("\nspeed = %d : %s max_pkt_size %d \n", speed,
357 speed_lookup[speed],
358 max_pkt_size);
359
360
361 /* save max pkt size for control endpoints */
362 dev->ep[0].max_pkt_size = max_pkt_size;
363 dev->ep[1].max_pkt_size = max_pkt_size;
364
365 /* Issue a DEPCFG command (with Config Action set to "Modify") for
366 * physical endpoints 0 & 1 using the same endpoint characteristics from
367 * Power-On Reset, but set
368 * MaxPacketSize to 512 (SuperSpeed), 64 (High-Speed),
369 * 8/16/32/64 (Full-Speed), or 8 (Low-Speed).
370 */
371 dwc_ep_cmd_set_config(dev, 0, SET_CONFIG_ACTION_MODIFY);
372 dwc_ep_cmd_set_config(dev, 1, SET_CONFIG_ACTION_MODIFY);
373
374 /* TODO: future optimization:
375 * GUSB2CFG/GUSB3PIPECTL
376 * Depending on the connected speed, write to the other PHY's control
377 * register to suspend it.
378 * GTXFIFOSIZn (optional) Based on the new MaxPacketSize of IN endpoint 0,
379 * software may choose to re-allocate
380 * the TX FIFO sizes by writing to these registers.
381 */
382
383 /* inform client that device is connected */
384 if (dev->notify)
385 dev->notify(dev->notify_context, dwc_event);
386}
387
388/* handle usb reset event:
389 * snps 8.1.2:
390 * Set DevAddr to 0
391 * end transfer for any active transfers (except for the default control EP)
392 */
393void dwc_event_device_reset(dwc_dev_t *dev)
394{
395 /* set dev address to 0 */
396 dwc_device_set_addr(dev, 0x0);
397
398 /* Send "stop transfer" on any non-control ep
399 * which has a transfer in progress: snps 8.2.5
400 */
401 for (uint8_t ep_index = 2; ep_index < DWC_MAX_NUM_OF_EP; ep_index++)
402 {
403 dwc_ep_t *ep = &dev->ep[ep_index];
404
405 DBG("\n RESET on EP = %d while state = %s", ep_index,
406 ep_state_lookup[ep->state]);
407
408 if ((ep->state == EP_STATE_START_TRANSFER) ||
409 (ep->state == EP_STATE_XFER_IN_PROG))
410 {
411 DBG("\n NEED to do end transfer");
412
413 dwc_ep_cmd_end_transfer(dev, ep->phy_num);
414 }
415 }
416
417 /* inform client that device is offline */
418 if (dev->notify)
419 {
420 DBG("\n calling Notify for OFFLINE event.\n");
421 dev->notify(dev->notify_context, DWC_NOTIFY_EVENT_OFFLINE);
422 }
423}
424
425/* handle control endpoint specific events:
426 * implements the control transfer programming model as described
427 * in snps chapter 8.4, figure 8-2.
428 */
429void dwc_event_handler_ep_ctrl(dwc_dev_t *dev, uint32_t *event)
430{
431#ifdef DEBUG_USB
432 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
433 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
434 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
435 uint16_t event_param = DWC_EVENT_EP_EVENT_PARAM(*event);
436
437 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
438#endif
439
440 DBG("\n\n\n++EP_EVENT: %s in ctrl_state: %s ep_state[%d]: %s",
441 event_lookup_ep[event_id],
442 dev_ctrl_state_lookup[dev->ctrl_state],
443 ep_phy_num,
444 ep_state_lookup[ep->state]);
445
446 DBG("\n ep_phy_num = %d param = 0x%x status = 0x%x", ep_phy_num,
447 event_param,
448 event_status);
449
450
451 /* call the handler for the current control state */
452 switch (dev->ctrl_state)
453 {
454 case EP_FSM_SETUP:
455 {
456 dwc_event_handler_ep_ctrl_state_setup(dev, event);
457 }
458 break;
459 case EP_FSM_CTRL_DATA:
460 {
461 dwc_event_handler_ep_ctrl_state_data(dev, event);
462 }
463 break;
464 case EP_FSM_WAIT_FOR_HOST_2:
465 {
466 dwc_event_handler_ep_ctrl_state_wait_for_host_2(dev, event);
467 }
468 break;
469 case EP_FSM_WAIT_FOR_HOST_3:
470 {
471 dwc_event_handler_ep_ctrl_state_wait_for_host_3(dev, event);
472 }
473 break;
474 case EP_FSM_STATUS_2:
475 {
476 dwc_event_handler_ep_ctrl_state_status_2(dev, event);
477 }
478 break;
479 case EP_FSM_STATUS_3:
480 {
481 dwc_event_handler_ep_ctrl_state_status_3(dev, event);
482 }
483 break;
484 case EP_FSM_STALL:
485 {
486 dwc_event_handler_ep_ctrl_state_stall(dev, event);
487 }
488 break;
489
490 default:
491 ASSERT(0);
492 }
493
494 DBG("\n--EP_EVENT: %s in ctrl_state: %s ep_state[%d]: %s",
495 event_lookup_ep[event_id],
496 dev_ctrl_state_lookup[dev->ctrl_state],
497 ep_phy_num,
498 ep_state_lookup[ep->state]);
499}
500
501/* check status of transfer:
502 * returns TRB status: non-zero value indicates failure to complete transfer.
503 * Also updates the "bytes_in_buf". This field indicates the number of bytes
504 * still remaining to be transferred. This field will be zero when all the
505 * requested data is transferred.
506 */
507uint8_t dwc_event_check_trb_status(dwc_dev_t *dev,
508 uint32_t *event,
509 uint8_t index,
510 uint32_t *bytes_in_buf)
511{
512 uint8_t status = 0;
513 uint8_t trb_updated = 0;
514 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
515 dwc_ep_t *ep = &dev->ep[index];
516 dwc_trb_t *trb = ep->trb;
517 uint32_t num_of_trb = ep->trb_queued;
518 uint32_t bytes_remaining = 0;
519
520 /* sanity ck. */
521 ASSERT(num_of_trb);
522
523 /* invalidate trb data before reading */
524 arch_invalidate_cache_range((addr_t) trb, sizeof(dwc_trb_t)*num_of_trb);
525
526 while (num_of_trb)
527 {
528 bytes_remaining += REG_READ_FIELD_LOCAL(&trb->f3, TRB_F3, BUFSIZ);
529
530 /* point to next trb */
531 trb++;
532
533 /* decrement trb count */
534 num_of_trb--;
535
536 /* The first non-zero status indicates the transfer status. Update
537 * "status" only once but still go through all the TRBs to find out
538 * the bytes still remaining to be transferred.
539 */
540 if (!status)
541 {
542 status = REG_READ_FIELD_LOCAL(&trb->f3, TRB_F3, TRBSTS);
543 }
544
545 if ((event_status & DWC_XFER_COMPLETE_EVT_STATUS_SHORT_PKT) &&
546 (REG_READ_FIELD_LOCAL(&trb->f4, TRB_F4, HWO)))
547 {
548 /* This TRB needs to be reclaimed since transfer completed due to
549 * reception of a short pkt.
550 * "fast-forward" condition as described in snps 8.2.3.2.
551 */
552 DBG("\n TRB needs to be reclaimed by sw. trb = 0x%x\n", (uint32_t) trb);
553 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, HWO, 0x0);
554 trb_updated = 1;
555 }
556 }
557
558 /* flush out any updates to trb before continuing */
559 if (trb_updated)
560 {
561 arch_clean_invalidate_cache_range((addr_t) ep->trb,
562 sizeof(dwc_trb_t)*ep->trb_queued);
563 }
564
565 /* reset the EP's queued trb count */
566 ep->trb_queued = 0;
567
568 *bytes_in_buf = bytes_remaining;
569
570 DBG("\n trb_status: %d total buf size = 0x%x \n", status, *bytes_in_buf);
571
572 return status;
573}
574
575/* handle all events occurring in Control-Setup state */
576static void dwc_event_handler_ep_ctrl_state_setup(dwc_dev_t *dev,
577 uint32_t *event)
578{
579 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
580 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
581 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
582
583 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
584
585 switch (event_id)
586 {
587 case DWC_EVENT_EP_CMD_COMPLETE:
588 {
589 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
590
591 if (cmd == DEPCMD_CMD_START_TRANSFER)
592 {
593 ASSERT(ep->state == EP_STATE_START_TRANSFER);
594
595 ASSERT(event_status == 0);
596
597 /* save the resource id assigned to this ep. */
598 ep->state = EP_STATE_XFER_IN_PROG;
599 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
600 }
601 else
602 {
603 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
604 }
605 }
606 break;
607
608 case DWC_EVENT_EP_XFER_NOT_READY:
609 {
610 /* attempting to start data/status before setup. snps 8.4.2 #2 */
611 DBG("\nattempting to start data/status before setup. stalling..\n");
612
613 dwc_ep_cmd_stall(dev, ep_phy_num);
614
615 /* new state is stall */
616 dev->ctrl_state = EP_FSM_STALL;
617 }
618 break;
619
620 case DWC_EVENT_EP_XFER_COMPLETE:
621 {
622 uint32_t bytes_remaining = 0;
623 uint8_t status = 0;
624
625 /* cannot happen on any other ep */
626 ASSERT(ep_phy_num == 0);
627
628 /* Assert if ep state is not xfer_in_prog. fatal error. */
629 ASSERT(ep->state == EP_STATE_XFER_IN_PROG);
630
631 /* update ep state to inactive. */
632 ep->state = EP_STATE_INACTIVE;
633
634 /* check transfer status. */
635 status = dwc_event_check_trb_status(dev,
636 event,
637 DWC_EP_PHY_TO_INDEX(ep_phy_num),
638 &bytes_remaining);
639
640 if (status || bytes_remaining)
641 {
642 /* transfer failed. queue another transfer. */
643 dwc_ep_ctrl_state_setup_enter(dev);
644 }
645 else
646 {
647 int ret;
648 uint8_t *data = dev->setup_pkt; /* setup pkt data */
649
650 /* invalidate any cached setup data before reading */
651 arch_invalidate_cache_range((addr_t) data, DWC_SETUP_PKT_LEN);
652
653 /* call setup handler */
654 ret = dev->setup_handler(dev->setup_context, data);
655
656 if (ret == DWC_SETUP_2_STAGE)
657 {
658 /* this is a 2 stage setup. */
659 dev->ctrl_state = EP_FSM_WAIT_FOR_HOST_2;
660 }
661 else if (ret == DWC_SETUP_3_STAGE)
662 {
663 /* this is a 3 stage setup. */
664 dev->ctrl_state = EP_FSM_CTRL_DATA;
665 }
666 else
667 {
668 /* bad setup bytes. stall */
669 dwc_ep_cmd_stall(dev, ep_phy_num);
670
671 /* new state is stall */
672 dev->ctrl_state = EP_FSM_STALL;
673 }
674 }
675 }
676 break;
677 case DWC_EVENT_EP_XFER_IN_PROGRESS:
678 default:
679 /* event is not expected in this state */
680 ERR("\n unhandled event_id = %d \n", event_id);
681 ASSERT(0);
682 }
683}
684
685/* handle all events occurring in Control-Data state */
686static void dwc_event_handler_ep_ctrl_state_data(dwc_dev_t *dev,
687 uint32_t *event)
688{
689 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
690 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
691 uint8_t event_ctrl_stage = DWC_EVENT_EP_EVENT_CTRL_STAGE(*event);
692 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
693
694 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
695
696 switch (event_id)
697 {
698 case DWC_EVENT_EP_CMD_COMPLETE:
699 {
700 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
701
702 if (cmd == DEPCMD_CMD_START_TRANSFER)
703 {
704 ASSERT(ep->state == EP_STATE_START_TRANSFER);
705
706 ASSERT(event_status == 0);
707
708 /* save the resource id assigned to this ep. */
709 ep->state = EP_STATE_XFER_IN_PROG;
710 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
711 }
712 else
713 {
714 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
715 }
716 }
717 break;
718
719 case DWC_EVENT_EP_XFER_NOT_READY:
720 {
721 /* confirm that this is control data request.
722 * control_status_request is invalid event in this state.
723 * assert if it ever occurs.
724 * something must be wrong in fsm implementation.
725 */
726 ASSERT(event_ctrl_stage == CONTROL_DATA_REQUEST);
727
728 /* In this state, the ep must be in transfer state.
729 * otherwise this came on an ep that we are not expecting any data.
730 */
731 if((ep->state == EP_STATE_START_TRANSFER) ||
732 (ep->state == EP_STATE_XFER_IN_PROG))
733 {
734 DBG("\n Host requested data on ep_phy_num = %d."
735 "Transfer already started. No action....", ep_phy_num);
736 }
737 else
738 {
739 /* host attempting to move data in wrong direction.
740 * end transfer for the direction that we started and stall.
741 */
742 uint8_t end_ep_phy_num;
743
744 /* end the other ep */
745 end_ep_phy_num = (ep_phy_num == 0) ? 1 : 0;
746
747 DBG("\nAttempting to move data in wrong direction. stalling. ");
748
749 dwc_ep_cmd_end_transfer(dev, end_ep_phy_num);
750
751 /* stall */
752 dwc_ep_cmd_stall(dev, end_ep_phy_num);
753
754 /* move to stall state. */
755 dev->ctrl_state = EP_FSM_STALL;
756 }
757 }
758 break;
759 case DWC_EVENT_EP_XFER_COMPLETE:
760 {
761 uint32_t bytes_remaining;
762 uint8_t status;
763
764 /* should never happen in any other state.
765 * something wrong in fsm implementation.
766 */
767 ASSERT(ep->state == EP_STATE_XFER_IN_PROG);
768
769 /* transfer is complete */
770 ep->state = EP_STATE_INACTIVE;
771
772 /* check transfer status */
773 status = dwc_event_check_trb_status(dev,
774 event,
775 DWC_EP_PHY_TO_INDEX(ep_phy_num),
776 &bytes_remaining);
777
778 if (status || bytes_remaining)
779 {
780 DBG("\n\n ********DATA TRANSFER FAILED ************* "
781 "status = %d bytes_remaining = %d\n\n",
782 status, bytes_remaining);
783 }
784
785 /* wait for host to request status */
786 dev->ctrl_state = EP_FSM_WAIT_FOR_HOST_3;
787 }
788 break;
789 case DWC_EVENT_EP_XFER_IN_PROGRESS:
790 default:
791 /* event is not expected in this state */
792 ASSERT(0);
793 }
794}
795
796/* handle all events occurring in Wait-for-Host-2 state */
797static void dwc_event_handler_ep_ctrl_state_wait_for_host_2(dwc_dev_t *dev,
798 uint32_t *event)
799{
800 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
801 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
802 uint8_t event_ctrl_stage = DWC_EVENT_EP_EVENT_CTRL_STAGE(*event);
803
804 switch (event_id)
805 {
806 case DWC_EVENT_EP_XFER_NOT_READY:
807 {
808 if (event_ctrl_stage == CONTROL_DATA_REQUEST)
809 {
810 DBG("\n\n attempting to start data when setup did not indicate"
811 "data stage. stall...\n\n");
812
813 dwc_ep_cmd_stall(dev, ep_phy_num);
814
815 /* move to stall state. */
816 dev->ctrl_state = EP_FSM_STALL;
817 }
818 else if (event_ctrl_stage == CONTROL_STATUS_REQUEST)
819 {
820 /* status cannot happen on phy = 0 */
821 ASSERT(ep_phy_num == 1);
822
823 dwc_request_t req;
824
825 req.callback = 0x0;
826 req.context = 0x0;
827 req.data = 0x0;
828 req.len = 0x0;
829 req.trbctl = TRBCTL_CONTROL_STATUS_2;
830
831 dwc_request_queue(dev, ep_phy_num, &req);
832
833 dev->ctrl_state = EP_FSM_STATUS_2;
834 }
835 else
836 {
837 ASSERT(0);
838 }
839 }
840 break;
841 case DWC_EVENT_EP_XFER_IN_PROGRESS:
842 case DWC_EVENT_EP_XFER_COMPLETE:
843 default:
844 /* event not expected in this state. */
845 ASSERT(0);
846 }
847}
848
849/* handle all events occurring in Wait-for-Host-3 state */
850static void dwc_event_handler_ep_ctrl_state_wait_for_host_3(dwc_dev_t *dev,
851 uint32_t *event)
852{
853 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
854 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
855 uint8_t event_ctrl_stage = DWC_EVENT_EP_EVENT_CTRL_STAGE(*event);
856
857 switch (event_id)
858 {
859 case DWC_EVENT_EP_XFER_NOT_READY:
860 {
861 if (event_ctrl_stage == CONTROL_DATA_REQUEST)/* data request */
862 {
863 /* TODO:
864 * special case handling when data stage transfer length
865 * was exact multiple of max_pkt_size.
866 * Need to setup a TRB to complete data stage with a zero
867 * length pkt transfer.
868 * Not implemented currently since all data during enumeration
869 * is less then max_pkt_size.
870 */
871 ASSERT(0);
872 }
873 else if (event_ctrl_stage == CONTROL_STATUS_REQUEST)/* stat req */
874 {
875 dwc_request_t req;
876
877 req.callback = 0x0;
878 req.context = 0x0;
879 req.data = 0x0;
880 req.len = 0x0;
881 req.trbctl = TRBCTL_CONTROL_STATUS_3;
882
883 dwc_request_queue(dev, ep_phy_num, &req);
884
885 dev->ctrl_state = EP_FSM_STATUS_3;
886 }
887 else
888 {
889 ASSERT(0);
890 }
891 }
892 break;
893 case DWC_EVENT_EP_XFER_IN_PROGRESS:
894 case DWC_EVENT_EP_XFER_COMPLETE:
895 default:
896 /* event is not expected in this state */
897 ASSERT(0);
898 }
899}
900
901
902/* handle all events occurring in Status-2 state */
903static void dwc_event_handler_ep_ctrl_state_status_2(dwc_dev_t *dev,
904 uint32_t *event)
905{
906 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
907 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
908 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
909
910 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
911
912 switch (event_id)
913 {
914 case DWC_EVENT_EP_CMD_COMPLETE:
915 {
916 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
917
918 if (cmd == DEPCMD_CMD_START_TRANSFER)
919 {
920 ASSERT(ep->state == EP_STATE_START_TRANSFER);
921
922 ASSERT(event_status == 0);
923
924 /* save the resource id assigned to this ep. */
925 ep->state = EP_STATE_XFER_IN_PROG;
926 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
927 }
928 else
929 {
930 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
931 }
932 }
933 break;
934 case DWC_EVENT_EP_XFER_COMPLETE:
935 {
936 uint32_t bytes_remaining;
937 uint8_t status;
938
939 /* cannot happen on ep 0 */
940 ASSERT(ep_phy_num == 1);
941
942 /* should never happen in any other state.
943 * something wrong in fsm implementation.
944 */
945 ASSERT(ep->state == EP_STATE_XFER_IN_PROG);
946
947 ep->state = EP_STATE_INACTIVE;
948
949 /* check transfer status */
950 status = dwc_event_check_trb_status(dev,
951 event,
952 DWC_EP_PHY_TO_INDEX(ep_phy_num),
953 &bytes_remaining);
954
955 if (status || bytes_remaining)
956 {
957 DBG("\n\n ******** TRANSFER FAILED ************* status ="
958 " %d bytes_remaining = %d\n\n", status, bytes_remaining);
959 }
960
961 dwc_ep_ctrl_state_setup_enter(dev);
962 }
963 break;
964 case DWC_EVENT_EP_XFER_NOT_READY:
965 case DWC_EVENT_EP_XFER_IN_PROGRESS:
966 default:
967 /* event is not expected in this state */
968 ASSERT(0);
969 }
970}
971
972/* handle all events occurring in Status-3 state */
973static void dwc_event_handler_ep_ctrl_state_status_3(dwc_dev_t *dev,
974 uint32_t *event)
975{
976 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
977 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
978 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
979
980 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
981
982 switch (event_id)
983 {
984 case DWC_EVENT_EP_CMD_COMPLETE:
985 {
986 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
987
988 if (cmd == DEPCMD_CMD_START_TRANSFER)
989 {
990 /* something wrong with fsm. cannot happen in any other ep state.*/
991 ASSERT(ep->state == EP_STATE_START_TRANSFER);
992
993 ASSERT(event_status == 0);
994
995 /* save the resource id assigned to this ep. */
996 ep->state = EP_STATE_XFER_IN_PROG;
997 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
998 }
999 else
1000 {
1001 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
1002 }
1003 }
1004 break;
1005 case DWC_EVENT_EP_XFER_COMPLETE:
1006 {
1007 uint32_t bytes_remaining;
1008 uint8_t status;
1009
1010 /* should never happen in any other state.
1011 * something wrong in fsm implementation.
1012 */
1013 ASSERT(ep->state == EP_STATE_XFER_IN_PROG);
1014
1015 ep->state = EP_STATE_INACTIVE;
1016
1017 /* check transfer status */
1018 status = dwc_event_check_trb_status(dev,
1019 event,
1020 DWC_EP_PHY_TO_INDEX(ep_phy_num),
1021 &bytes_remaining);
1022
1023 if (status || bytes_remaining)
1024 {
1025 DBG("\n\n ******** TRANSFER FAILED ************* status ="
1026 " %d bytes_remaining = %d\n\n", status, bytes_remaining);
1027
1028 /* data stage failed. */
1029 dwc_ep_cmd_stall(dev, ep_phy_num);
1030
1031 /* move to stall state. */
1032 dev->ctrl_state = EP_FSM_STALL;
1033 }
1034 else
1035 {
1036 dwc_ep_ctrl_state_setup_enter(dev);
1037 }
1038 }
1039 break;
1040 case DWC_EVENT_EP_XFER_NOT_READY:
1041 case DWC_EVENT_EP_XFER_IN_PROGRESS:
1042 default:
1043 /* event is not expected in this state */
1044 ASSERT(0);
1045 }
1046}
1047
1048/* handle all events occurring in stall state */
1049static void dwc_event_handler_ep_ctrl_state_stall(dwc_dev_t *dev,
1050 uint32_t *event)
1051{
1052 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1053 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1054
1055 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
1056
1057 switch (event_id)
1058 {
1059 case DWC_EVENT_EP_CMD_COMPLETE:
1060 {
1061 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
1062
1063 if (cmd == DEPCMD_CMD_SET_STALL)
1064 {
1065 /* stall complete. go back to setup state. */
1066 dwc_ep_ctrl_state_setup_enter(dev);
1067 }
1068 else if (cmd == DEPCMD_CMD_END_TRANSFER)
1069 {
1070 /* reset state and resource index */
1071 ep->state = EP_STATE_INACTIVE;
1072 ep->resource_idx = 0;
1073 }
1074 else
1075 {
1076 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
1077 }
1078 }
1079 break;
1080 default:
1081 DBG("\n\n ********No Action defined for this event. ignored. \n\n");
1082 break;
1083 }
1084}
1085
1086/* event handler for INACTIVE state of bulk endpoint */
1087static void dwc_event_handler_ep_bulk_state_inactive(dwc_dev_t *dev,
1088 uint32_t *event)
1089{
1090#ifdef DEBUG_USB
1091 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1092 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
1093#endif
1094 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1095
1096 switch (event_id)
1097 {
1098 case DWC_EVENT_EP_CMD_COMPLETE:
1099 {
1100 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
1101 }
1102 break;
1103 case DWC_EVENT_EP_XFER_NOT_READY:
1104 {
1105 /* This is a valid scenario where host is requesting data and
1106 * our client has not queued the request yet.
1107 */
1108 DBG("\n Host requested data on ep_phy_num = %d. "
1109 "No action. ignored.", ep_phy_num);
1110 }
1111 break;
1112 case DWC_EVENT_EP_XFER_IN_PROGRESS:
1113 case DWC_EVENT_EP_XFER_COMPLETE:
1114 default:
1115 /* event is not expected in this state */
1116 ASSERT(0);
1117 }
1118}
1119
1120/* event handler for START_TRANSFER state of bulk endpoint */
1121static void dwc_event_handler_ep_bulk_state_start_transfer(dwc_dev_t *dev,
1122 uint32_t *event)
1123{
1124 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1125 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1126 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
1127
1128 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
1129
1130 switch (event_id)
1131 {
1132 case DWC_EVENT_EP_CMD_COMPLETE:
1133 {
1134 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
1135
1136 if (cmd == DEPCMD_CMD_START_TRANSFER)
1137 {
1138 if (event_status == 0)
1139 {
1140 /* save the resource id assigned to this ep. */
1141 ep->state = EP_STATE_XFER_IN_PROG;
1142 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
1143 }
1144 else
1145 {
1146 /* start transfer failed. inform client */
1147 if (ep->req.callback)
1148 {
1149 ep->req.callback(ep->req.context, 0, -1);
1150 }
1151
1152 /* back to inactive state */
1153 dwc_ep_bulk_state_inactive_enter(dev, ep_phy_num);
1154 }
1155 }
1156 else
1157 {
1158 DBG("\n cmd = %s has no action. ignored.\n", cmd_lookup[cmd]);
1159 }
1160 }
1161 break;
1162 default:
1163 ASSERT(0);
1164 }
1165}
1166
1167/* event handler for TRANSFER_IN_PROGRESS state of bulk endpoint */
1168static void dwc_event_handler_ep_bulk_state_xfer_in_prog(dwc_dev_t *dev,
1169 uint32_t *event)
1170{
1171 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1172 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1173
1174 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
1175
1176 switch (event_id)
1177 {
1178 case DWC_EVENT_EP_CMD_COMPLETE:
1179 {
1180 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
1181
1182 if (cmd == DEPCMD_CMD_END_TRANSFER)
1183 {
1184 /* transfer was cancelled for some reason. */
1185 DBG("\n transfer was cancelled on ep_phy_num = %d\n", ep_phy_num);
1186
1187 /* inform client that transfer failed. */
1188 if (ep->req.callback)
1189 {
1190 ep->req.callback(ep->req.context, 0, -1);
1191 }
1192
1193 /* back to inactive state */
1194 dwc_ep_bulk_state_inactive_enter(dev, ep_phy_num);
1195 }
1196 else
1197 {
1198 DBG("\n cmd = %s has no action. ignored.\n", cmd_lookup[cmd]);
1199 }
1200 }
1201 break;
1202 case DWC_EVENT_EP_XFER_NOT_READY:
1203 {
1204 /* This is a valid scenario where host is requesting data and
1205 * we have not yet moved to start transfer state.
1206 */
1207 DBG("\n Host requested data on ep_phy_num = %d."
1208 "No action. ignored.", ep_phy_num);
1209 }
1210 break;
1211 case DWC_EVENT_EP_XFER_COMPLETE:
1212 {
1213 uint32_t bytes_remaining;
1214 uint8_t status;
1215
1216 /* Check how many TRBs were processed and how much data got
1217 * transferred. If there are bytes_remaining, it does not
1218 * necessarily mean failed xfer. We could have queued a 512 byte
1219 * read and receive say 13 bytes of data which is a valid scenario.
1220 */
1221 status = dwc_event_check_trb_status(dev,
1222 event,
1223 DWC_EP_PHY_TO_INDEX(ep_phy_num),
1224 &bytes_remaining);
1225
1226 DBG("\n\n ******DATA TRANSFER COMPLETED (ep_phy_num = %d) ********"
1227 "bytes_remaining = %d\n\n", ep_phy_num, bytes_remaining);
1228
1229 if (ep->req.callback)
1230 {
1231 ep->req.callback(ep->req.context,
1232 ep->bytes_queued - bytes_remaining,
1233 status ? -1 : 0);
1234 }
1235
1236 dwc_ep_bulk_state_inactive_enter(dev, ep_phy_num);
1237 }
1238 break;
1239 default:
1240 ASSERT(0);
1241 }
1242}
1243
1244/* bulk endpoint event handler */
1245void dwc_event_handler_ep_bulk(dwc_dev_t *dev, uint32_t *event)
1246{
1247 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1248#ifdef DEBUG_USB
1249 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1250 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
1251 uint16_t event_param = DWC_EVENT_EP_EVENT_PARAM(*event);
1252#endif
1253
1254
1255 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
1256
1257 DBG("\n\n\n++EP_EVENT: %s in ctrl_state: %s ep_state[%d]: %s",
1258 event_lookup_ep[event_id],
1259 dev_ctrl_state_lookup[dev->ctrl_state],
1260 ep_phy_num,
1261 ep_state_lookup[ep->state]);
1262
1263 DBG("\n ep_phy_num = %d param = 0x%x status = 0x%x",
1264 ep_phy_num, event_param, event_status);
1265
1266 switch (ep->state)
1267 {
1268 case EP_STATE_INACTIVE:
1269 {
1270 dwc_event_handler_ep_bulk_state_inactive(dev, event);
1271 }
1272 break;
1273 case EP_STATE_START_TRANSFER:
1274 {
1275 dwc_event_handler_ep_bulk_state_start_transfer(dev, event);
1276 }
1277 break;
1278 case EP_STATE_XFER_IN_PROG:
1279 {
1280 dwc_event_handler_ep_bulk_state_xfer_in_prog(dev, event);
1281 }
1282 break;
1283 default:
1284 DBG("\n EP state is invalid. Asserting...\n");
1285 ASSERT(0);
1286 }
1287
1288 DBG("\n--EP_EVENT: %s in ctrl_state: %s ep_state[%d]: %s",
1289 event_lookup_ep[event_id],
1290 dev_ctrl_state_lookup[dev->ctrl_state],
1291 ep_phy_num,
1292 ep_state_lookup[ep->state]);
1293}
1294
1295
1296
1297
1298/******************** Endpoint related APIs **********************************/
1299
1300/* Initialize and enable EP:
1301 * - set the initial configuration for an endpoint
1302 * - set transfer resources
1303 * - enable the endpoint
1304 */
1305static void dwc_ep_config_init_enable(dwc_dev_t *dev, uint8_t index)
1306{
1307 uint8_t ep_phy_num = dev->ep[index].phy_num;
1308
1309 dwc_ep_cmd_set_config(dev, index, SET_CONFIG_ACTION_INIT);
1310
1311 dev->ep[index].state = EP_STATE_INACTIVE;
1312
1313 /* Set transfer resource configs for the end points */
1314 dwc_ep_cmd_set_transfer_resource(dev, ep_phy_num);
1315
1316 /* enable endpoint */
1317 dwc_ep_enable(dev, ep_phy_num);
1318}
1319
1320/* Initialize control EPs:
1321 * Do the one time initialization of control EPs
1322 */
1323static void dwc_ep_ctrl_init(dwc_dev_t *dev)
1324{
1325 uint8_t index;
1326
1327 /* Control OUT */
1328 index = DWC_EP_INDEX(0, DWC_EP_DIRECTION_OUT);
1329
1330 dev->ep[index].number = 0;
1331 dev->ep[index].dir = DWC_EP_DIRECTION_OUT;
1332 dev->ep[index].phy_num = 0;
1333 dev->ep[index].type = EP_TYPE_CONTROL;
1334 dev->ep[index].state = EP_STATE_INIT;
1335 dev->ep[index].max_pkt_size = 512;
1336 dev->ep[index].burst_size = 0;
1337 dev->ep[index].tx_fifo_num = 0;
1338 dev->ep[index].zlp = 0;
1339 dev->ep[index].trb_count = 1;
1340 /* TRB must be aligned to 16 */
1341 dev->ep[index].trb = memalign(lcm(CACHE_LINE, 16),
1342 ROUNDUP(dev->ep[index].trb_count*sizeof(dwc_trb_t), CACHE_LINE));
1343 ASSERT(dev->ep[index].trb);
1344 dev->ep[index].trb_queued = 0;
1345 dev->ep[index].bytes_queued = 0;
1346
1347 /* Control IN */
1348 index = DWC_EP_INDEX(0, DWC_EP_DIRECTION_OUT);
1349
1350 dev->ep[index].number = 0;
1351 dev->ep[index].dir = DWC_EP_DIRECTION_IN;
1352 dev->ep[index].phy_num = 1;
1353 dev->ep[index].type = EP_TYPE_CONTROL;
1354 dev->ep[index].state = EP_STATE_INIT;
1355 dev->ep[index].max_pkt_size = 512;
1356 dev->ep[index].burst_size = 0;
1357 dev->ep[index].tx_fifo_num = 0;
1358 dev->ep[index].zlp = 0;
1359 dev->ep[index].trb_count = 1;
1360 /* TRB must be aligned to 16 */
1361 dev->ep[index].trb = memalign(lcm(CACHE_LINE, 16),
1362 ROUNDUP(dev->ep[index].trb_count*sizeof(dwc_trb_t), CACHE_LINE));
1363 ASSERT(dev->ep[index].trb);
1364 dev->ep[index].trb_queued = 0;
1365 dev->ep[index].bytes_queued = 0;
1366
1367 /* configure and enable the endpoints */
1368 dwc_ep_config_init_enable(dev, 0);
1369 dwc_ep_config_init_enable(dev, 1);
1370}
1371
1372
1373/* entry function into setup state for control fsm */
1374static void dwc_ep_ctrl_state_setup_enter(dwc_dev_t *dev)
1375{
1376 dwc_request_t req;
1377
1378 /* queue request to receive the first setup pkt from host */
1379 memset(dev->setup_pkt, 0, DWC_SETUP_PKT_LEN);
1380
1381 /* flush data */
1382 arch_clean_invalidate_cache_range((addr_t) dev->setup_pkt, DWC_SETUP_PKT_LEN);
1383
1384 req.data = dev->setup_pkt;
1385 req.len = DWC_SETUP_PKT_LEN;
1386 req.trbctl = TRBCTL_CONTROL_SETUP;
1387 req.callback = NULL;
1388 req.context = NULL;
1389
1390 dwc_request_queue(dev, 0, &req);
1391
1392 /* reset control ep state to "setup" state */
1393 dev->ctrl_state = EP_FSM_SETUP;
1394}
1395
1396/* entry function into inactive state for data transfer fsm */
1397static void dwc_ep_bulk_state_inactive_enter(dwc_dev_t *dev, uint8_t ep_phy_num)
1398{
1399 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
1400
1401 /* queue request to receive the first setup pkt from host */
1402 ep->req.data = NULL;
1403 ep->req.len = 0;
1404 ep->req.trbctl = 0;
1405 ep->req.callback = NULL;
1406 ep->req.context = NULL;
1407
1408 /* inactive state */
1409 ep->state = EP_STATE_INACTIVE;
1410
1411 /* reset the resource index, trb and bytes queued */
1412 ep->resource_idx = 0;
1413 ep->trb_queued = 0;
1414 ep->bytes_queued = 0;
1415}
1416
1417/*************************** External APIs ************************************/
1418
1419/* Initialize controller for device mode operation.
1420 * Implements sequence as described in HPG.
1421 * Numbers indicate the step # in HPG.
1422 */
1423void dwc_device_init(dwc_dev_t *dev)
1424{
1425 /* 15. reset device ctrl. */
1426 dwc_device_reset(dev);
1427
1428 /* 16. initialize global control reg for device mode operation */
1429 dwc_gctl_init(dev);
1430
1431 /* 17. AXI master config */
1432 dwc_axi_master_config(dev);
1433
1434 /* 18. */
1435 /* a. tx fifo config */
1436 /* reset value is good. */
1437 /* b. rx fifo config */
1438 /* reset value is good. */
1439
1440 /* 18.c */
1441 dwc_event_init(dev);
1442
1443 /* 18.d */
1444 /* enable device event generation */
1445 dwc_event_device_enable(dev, BIT(DWC_EVENT_DEVICE_EVENT_ID_DISCONNECT) |
1446 BIT(DWC_EVENT_DEVICE_EVENT_ID_USB_RESET) |
1447 BIT(DWC_EVENT_DEVICE_EVENT_ID_CONNECT_DONE));
1448
1449 /* 18.e initialize control end point
1450 * start new config on end point 0. only needed for ep0.
1451 * resource index must be set to 0.
1452 */
1453 dwc_ep_cmd_start_new_config(dev, 0, 0);
1454
1455 /* steps described in snps 8.1 */
1456 dwc_ep_ctrl_init(dev);
1457
1458 /* Unmask interrupts */
1459 unmask_interrupt(USB30_EE1_IRQ);
1460
1461 /* start the control ep fsm */
1462 dwc_ep_ctrl_state_setup_enter(dev);
1463}
1464
1465/* add a new non-control endpoint belonging to the selected USB configuration.
1466 * This is called when "set config" setup is received from host.
1467 * udc layer first adds the endpoints which are part of the selected
1468 * configuration by calling this api.
1469 * Then it calls dwc_device_set_configuration() to enable that configuration.
1470 * TODO: need better api to manage this. possibly a single api to do both.
1471 * also, currently this only works as long as same configuration is selected
1472 * every time. The cleanup during usb reset is not cleanly removing the
1473 * endpoints added during a set config. This works fine for our usecase.
1474 */
1475void dwc_device_add_ep(dwc_dev_t *dev, dwc_ep_t new_ep)
1476{
1477 uint8_t index = DWC_EP_INDEX(new_ep.number, new_ep.dir);
1478
1479 dwc_ep_t *ep = &dev->ep[index];
1480
1481 memset(ep, 0, sizeof(ep));
1482
1483 /* copy client specified params */
1484
1485 ep->number = new_ep.number;
1486 ep->dir = new_ep.dir;
1487 ep->type = new_ep.type;
1488 ep->max_pkt_size = new_ep.max_pkt_size;
1489 ep->burst_size = new_ep.burst_size;
1490 ep->zlp = new_ep.zlp;
1491 ep->trb_count = new_ep.trb_count;
1492 ep->trb = new_ep.trb;
1493
1494 ASSERT(ep->trb);
1495
1496 /* clear out trb memory space. */
1497 memset(ep->trb, 0, (ep->trb_count)*sizeof(ep->trb));
1498 arch_clean_invalidate_cache_range((addr_t) ep->trb,
1499 (ep->trb_count)*sizeof(ep->trb));
1500
1501 /* initialize dwc specified params */
1502
1503 /* map this usb ep to the next available phy ep.
1504 * we assume non-flexible endpoint mapping.
1505 * so the physical ep number is same as the index into our EP array.
1506 */
1507 ep->phy_num = index;
1508
1509 if (ep->dir == DWC_EP_DIRECTION_IN)
1510 {
1511 /* TODO: this works only as long as we just one IN EP (non-control).
1512 * Need to increment this for every new IN ep added.
1513 */
1514 ep->tx_fifo_num = 1;
1515 }
1516 else
1517 {
1518 ep->tx_fifo_num = 0; /* tx fifo num must be 0 for OUT ep */
1519 }
1520
1521 ep->trb_queued = 0;
1522 ep->bytes_queued = 0;
1523 ep->resource_idx = 0;
1524 ep->state = EP_STATE_INIT;
1525}
1526
1527/* Configure and enable non-control endpoints:
1528 * This is called when "set config" setup is received from host.
1529 * Implements sequence as described in snps databook 8.1.5.
1530 */
1531void dwc_device_set_configuration(dwc_dev_t *dev)
1532{
1533 /* disable every ep other than control EPs */
1534 dwc_ep_disable_non_control(dev);
1535
1536 /* re-initialize TX FIFO by sending set config cmd to ep-1 */
1537 dwc_ep_cmd_set_config(dev, 1, SET_CONFIG_ACTION_MODIFY);
1538
1539 /* re-initialize transfer resource allocation:
1540 * only needed for ep0.
1541 * resource index must be set to 2 when doing set config
1542 */
1543 dwc_ep_cmd_start_new_config(dev, 0, 2);
1544
1545 /* Initialize config for each non-control EP in the new configuration */
1546 for (uint8_t ep_index = 2; ep_index < DWC_MAX_NUM_OF_EP; ep_index++)
1547 {
1548 /* non-zero phy ep num indicates that this ep data is initialized
1549 * and ready for use.
1550 */
1551 if (dev->ep[ep_index].phy_num)
1552 {
1553 dwc_ep_config_init_enable(dev, ep_index);
1554 }
1555 }
1556
1557 /* optional: re-initialize tx FIFO : GTXFIFOSIZn*/
1558}
1559
1560/* Enqueue new data transfer request on an endpoint. */
1561static int dwc_request_queue(dwc_dev_t *dev,
1562 uint8_t ep_phy_num,
1563 dwc_request_t *req)
1564{
1565 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
1566
1567 dwc_trb_t *trb = ep->trb;
1568 uint8_t *data_ptr = req->data;
1569 uint32_t transfer_len = req->len;
1570 dwc_trb_trbctl_t trbctl = req->trbctl;
1571
1572 uint32_t pad_len;
1573
1574 if(ep->state != EP_STATE_INACTIVE)
1575 {
1576 DBG("\n EP must be in INACTIVE state to start queue transfer. ep_phy_num = %d current state = %s",
1577 ep_phy_num, ep_state_lookup[ep->state]);
1578 return -1;
1579 }
1580
1581 /* trb queued must be 0 at this time. */
1582 ASSERT(ep->trb_queued == 0);
1583
1584 /* save the original request for this ep */
1585 ep->req = *req;
1586
1587 ep->bytes_queued = 0;
1588
1589 if (ep->type == EP_TYPE_CONTROL)
1590 {
1591 memset(trb, 0, sizeof(dwc_trb_t));
1592
1593 REG_WRITE_FIELD_LOCAL(&trb->f1, TRB_F1, PTR_LOW, (uint32_t) data_ptr);
1594 REG_WRITE_FIELD_LOCAL(&trb->f2, TRB_F2, PTR_HIGH, 0x0);
1595 REG_WRITE_FIELD_LOCAL(&trb->f3, TRB_F3, BUFSIZ, transfer_len);
1596 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, LST, 0x1);
1597 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CHN, 0x0);
1598 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CSP, 0x0);
1599 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, TRBCTL, trbctl);
1600 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, IOC, 0x1);
1601 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, HWO, 0x1);
1602
1603 /* increment the queued trb count */
1604 ep->trb_queued++;
1605 ep->bytes_queued += transfer_len;
1606 data_ptr += transfer_len;
1607 }
1608 else if (ep->type == EP_TYPE_BULK)
1609 {
1610 /* reserve 1 trb for pad/zero-length pkt */
1611 uint32_t trb_available = ep->trb_count - 1;
1612 uint32_t max_bytes_per_trb;
1613 uint32_t offset;
1614 uint32_t trb_len = 0;
1615
1616 /* snps 7.2 table 7-1. applies only to older versions of the controller:
1617 * - data_ptr in first TRB can be aligned to byte
1618 * - but the following TRBs should point to data that is aligned
1619 * to master bus data width.
1620 */
1621
1622 /* align default MAX_BYTES_PER_TRB to DWC_MASTER_BUS_WIDTH */
1623 max_bytes_per_trb = ROUNDDOWN(DWC_MAX_BYTES_PER_TRB, DWC_MASTER_BUS_WIDTH);
1624
1625 while (trb_available && transfer_len)
1626 {
1627 /* clear out trb fields */
1628 memset(trb, 0, sizeof(dwc_trb_t));
1629
1630 if (ep->trb_queued == 0)
1631 {
1632 /* first trb: limit the transfer length in this TRB such that
1633 * the next trb data_ptr will be aligned to master bus width.
1634 */
1635 offset = ((uint32_t) data_ptr) & (DWC_MASTER_BUS_WIDTH - 1);
1636 trb_len = (transfer_len <= max_bytes_per_trb) ?
1637 transfer_len : (max_bytes_per_trb - offset);
1638 }
1639 else
1640 {
1641 trb_len = (transfer_len <= max_bytes_per_trb) ?
1642 transfer_len : max_bytes_per_trb;
1643 }
1644
1645 REG_WRITE_FIELD_LOCAL(&trb->f1, TRB_F1, PTR_LOW, (uint32_t) data_ptr);
1646 REG_WRITE_FIELD_LOCAL(&trb->f2, TRB_F2, PTR_HIGH, 0x0);
1647 REG_WRITE_FIELD_LOCAL(&trb->f3, TRB_F3, BUFSIZ, trb_len);
1648 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, LST, 0x0);
1649 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CHN, 0x1);
1650 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CSP, 0x0);
1651 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, TRBCTL, trbctl);
1652 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, IOC, 0x0);
1653 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, HWO, 0x1);
1654
1655 /* increment the queued trb count */
1656 ep->trb_queued++;
1657 ep->bytes_queued += trb_len;
1658 data_ptr += trb_len;
1659
1660 /* remaining transfer len */
1661 transfer_len -= trb_len;
1662
1663 /* remaining trb */
1664 trb_available--;
1665
1666 /* point to the next trb */
1667 trb++;
1668 }
1669
1670 if (transfer_len)
1671 {
1672 /* TRBs not available to queue the entire request.
1673 * If more data is expected in each request, increase the number
1674 * of TRBs allocated for this EP.
1675 */
1676 ERR("\n ERROR: Enough TRBs are not available to setup transfer\n");
1677 ERR("\n ERROR: Increase TRB chain for the ep.\n");
1678 ERR("\n ERROR: phy_ep_num = %d xfer len = %d\n", ep_phy_num, req->len);
1679 ASSERT(0);
1680 }
1681
1682 /* snps 8.2.3.3:
1683 * For an OUT ep:
1684 * (a) The "buffer descriptor" must be exact multiple of max_pkt_size
1685 * "buffer descriptor" consists of one or more TRBs upto the TRB
1686 * with CHN (chain) flag is not set.
1687 * Add a TRB to pad the len if it is not exact multiple.
1688 *
1689 * (b) If the expected amount of data is exact multiple of max_pkt_size:
1690 * add a max_pkt_size trb to sink in zero-length pkt, only if
1691 * the EP expects it.
1692 */
1693 uint32_t roundup = req->len % ep->max_pkt_size;
1694
1695 if ( (ep->dir == DWC_EP_DIRECTION_OUT) &&
1696 (roundup || ep->zlp))
1697 {
1698 if(roundup)
1699 {
1700 /* add a TRB to make it exact multiple of max_pkt_size */
1701 pad_len = ep->max_pkt_size - roundup;
1702 }
1703 else
1704 {
1705 /* "buffer descriptor" is exact multiple of max_pkt_size and
1706 * ep expects a zero-length pkt.
1707 * Add a TRB to sink in the zero-length pkt.
1708 */
1709 pad_len = ep->max_pkt_size;
1710 }
1711
1712 memset(trb, 0, sizeof(dwc_trb_t));
1713 memset(ep->zlp_buf, 0, DWC_ZLP_BUF_SIZE);
1714
1715 REG_WRITE_FIELD_LOCAL(&trb->f1, TRB_F1, PTR_LOW, (uint32_t) ep->zlp_buf);
1716 REG_WRITE_FIELD_LOCAL(&trb->f2, TRB_F2, PTR_HIGH, 0x0);
1717 REG_WRITE_FIELD_LOCAL(&trb->f3, TRB_F3, BUFSIZ, pad_len);
1718 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, LST, 0x1);
1719 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CHN, 0x0);
1720 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CSP, 0x0);
1721 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, TRBCTL, trbctl);
1722 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, IOC, 0x1);
1723 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, HWO, 0x1);
1724
1725 /* increment the queued trb count */
1726 ep->trb_queued++;
1727 ep->bytes_queued += pad_len;
1728 }
1729 else /* pad trb not needed. */
1730 {
1731 /* point trb to the last programmed trb */
1732 trb--;
1733
1734 /* setup params for last TRB */
1735 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CHN, 0x0);
1736 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, LST, 0x1);
1737 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, IOC, 0x1);
1738 }
1739 }
1740 else
1741 {
1742 /* invalid EP type */
1743 ASSERT(0);
1744 }
1745
1746 /* flush the trb data to main memory */
1747 arch_clean_invalidate_cache_range((addr_t) ep->trb,
1748 sizeof(dwc_trb_t)*ep->trb_queued);
1749
1750 DBG("\n Starting new xfer on ep_phy_num = %d TRB_QUEUED = %d \n",
1751 ep_phy_num, ep->trb_queued);
1752
1753 /* dwc_request_queue could be triggered from app and thus
1754 * outside of interrupt context. Use critical section to make sure all
1755 * states are updated properly before we handle other interrupts.
1756 */
1757 enter_critical_section();
1758
1759 if(ep->state == EP_STATE_INACTIVE)
1760 {
1761 dwc_ep_cmd_start_transfer(dev, ep_phy_num);
1762
1763 if(dwc_device_run_status(dev))
1764 {
1765 ep->state = EP_STATE_START_TRANSFER;
1766 }
1767 else
1768 {
1769 /* no interrupt expected on completion of start transfer.
1770 * directly move to xfer in prog state.
1771 */
1772 ep->state = EP_STATE_XFER_IN_PROG;
1773 }
1774 }
1775 else
1776 {
1777 DBG("\n Attempting START_TRANSFER in invalid state: %s. .......\n",
1778 ep_state_lookup[ep->state]);
1779 ASSERT(0);
1780 }
1781
1782 exit_critical_section();
1783
1784 return 0;
1785}
1786
1787/* data transfer request:
1788 * NOTE: Assumes that the data to be transferred is already in main memory.
1789 * Any cache management must be done by caller .
1790 * For received data, cache mgmt must be done in callback function.
1791 */
1792int dwc_transfer_request(dwc_dev_t *dwc,
1793 uint8_t usb_ep,
1794 dwc_ep_direction_t dir,
1795 void *buf,
1796 uint32_t len,
1797 dwc_transfer_callback_t callback,
1798 void *callback_context)
1799{
1800 uint8_t ep_phy_num;
1801 dwc_request_t req;
1802
1803 /* map usb ep to physical ep */
1804 ep_phy_num = DWC_EP_PHY_NUM(usb_ep, dir);
1805
1806 req.data = buf;
1807 req.len = len;
1808 req.callback = callback;
1809 req.context = callback_context;
1810
1811 if (usb_ep == 0)
1812 {
1813 /* control EP always has CONTROL_DATA trb */
1814 req.trbctl = TRBCTL_CONTROL_DATA;
1815 }
1816 else
1817 {
1818 req.trbctl = TRBCTL_NORMAL;
1819 }
1820
1821 return dwc_request_queue(dwc, ep_phy_num, &req);
1822}