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