blob: 564d1c965dd84966aff9c7df5a4469a068614611 [file] [log] [blame]
Channagoud Kadabi8bc768e2015-01-27 11:40:51 -08001/* Copyright (c) 2013-2015, 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
Channagoud Kadabi700c0682014-06-05 19:15:02 -0700214 memset(dev, 0, sizeof(dwc_dev_t));
Amol Jadif3d5a892013-07-23 16:09:44 -0700215
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];
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +0800459 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -0700460
461 DBG("\n RESET on EP = %d while state = %s", ep_index,
462 ep_state_lookup[ep->state]);
463
464 if ((ep->state == EP_STATE_START_TRANSFER) ||
465 (ep->state == EP_STATE_XFER_IN_PROG))
466 {
467 DBG("\n NEED to do end transfer");
468
469 dwc_ep_cmd_end_transfer(dev, ep->phy_num);
470 }
471 }
472
473 /* inform client that device is offline */
474 if (dev->notify)
475 {
476 DBG("\n calling Notify for OFFLINE event.\n");
477 dev->notify(dev->notify_context, DWC_NOTIFY_EVENT_OFFLINE);
478 }
479}
480
481/* handle control endpoint specific events:
482 * implements the control transfer programming model as described
483 * in snps chapter 8.4, figure 8-2.
484 */
485void dwc_event_handler_ep_ctrl(dwc_dev_t *dev, uint32_t *event)
486{
487#ifdef DEBUG_USB
488 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
489 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
490 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
491 uint16_t event_param = DWC_EVENT_EP_EVENT_PARAM(*event);
492
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +0800493 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -0700494 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gaoe2568e52014-07-24 15:23:18 +0800495 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -0700496
497 DBG("\n\n\n++EP_EVENT: %s in ctrl_state: %s ep_state[%d]: %s",
498 event_lookup_ep[event_id],
499 dev_ctrl_state_lookup[dev->ctrl_state],
500 ep_phy_num,
501 ep_state_lookup[ep->state]);
502
503 DBG("\n ep_phy_num = %d param = 0x%x status = 0x%x", ep_phy_num,
504 event_param,
505 event_status);
Lijuan Gaoe2568e52014-07-24 15:23:18 +0800506#endif
Amol Jadif3d5a892013-07-23 16:09:44 -0700507
508 /* call the handler for the current control state */
509 switch (dev->ctrl_state)
510 {
511 case EP_FSM_SETUP:
512 {
513 dwc_event_handler_ep_ctrl_state_setup(dev, event);
514 }
515 break;
516 case EP_FSM_CTRL_DATA:
517 {
518 dwc_event_handler_ep_ctrl_state_data(dev, event);
519 }
520 break;
521 case EP_FSM_WAIT_FOR_HOST_2:
522 {
523 dwc_event_handler_ep_ctrl_state_wait_for_host_2(dev, event);
524 }
525 break;
526 case EP_FSM_WAIT_FOR_HOST_3:
527 {
528 dwc_event_handler_ep_ctrl_state_wait_for_host_3(dev, event);
529 }
530 break;
531 case EP_FSM_STATUS_2:
532 {
533 dwc_event_handler_ep_ctrl_state_status_2(dev, event);
534 }
535 break;
536 case EP_FSM_STATUS_3:
537 {
538 dwc_event_handler_ep_ctrl_state_status_3(dev, event);
539 }
540 break;
541 case EP_FSM_STALL:
542 {
543 dwc_event_handler_ep_ctrl_state_stall(dev, event);
544 }
545 break;
546
547 default:
Amol Jadi1133a302013-10-01 14:45:38 -0700548 ERR("Invalid ctrl_state = %d\n", dev->ctrl_state);
549 dwc_print_ep_event_details(dev, event);
550 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -0700551 ASSERT(0);
552 }
553
Lijuan Gaoe2568e52014-07-24 15:23:18 +0800554#ifdef DEBUG_USB
Amol Jadif3d5a892013-07-23 16:09:44 -0700555 DBG("\n--EP_EVENT: %s in ctrl_state: %s ep_state[%d]: %s",
556 event_lookup_ep[event_id],
557 dev_ctrl_state_lookup[dev->ctrl_state],
558 ep_phy_num,
559 ep_state_lookup[ep->state]);
Lijuan Gaoe2568e52014-07-24 15:23:18 +0800560#endif
Amol Jadif3d5a892013-07-23 16:09:44 -0700561}
562
563/* check status of transfer:
564 * returns TRB status: non-zero value indicates failure to complete transfer.
565 * Also updates the "bytes_in_buf". This field indicates the number of bytes
566 * still remaining to be transferred. This field will be zero when all the
567 * requested data is transferred.
568 */
569uint8_t dwc_event_check_trb_status(dwc_dev_t *dev,
570 uint32_t *event,
571 uint8_t index,
572 uint32_t *bytes_in_buf)
573{
574 uint8_t status = 0;
575 uint8_t trb_updated = 0;
576 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +0800577
578 ASSERT(index < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -0700579 dwc_ep_t *ep = &dev->ep[index];
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +0800580 ASSERT(ep != NULL);
581
Amol Jadif3d5a892013-07-23 16:09:44 -0700582 dwc_trb_t *trb = ep->trb;
583 uint32_t num_of_trb = ep->trb_queued;
584 uint32_t bytes_remaining = 0;
585
586 /* sanity ck. */
587 ASSERT(num_of_trb);
588
589 /* invalidate trb data before reading */
590 arch_invalidate_cache_range((addr_t) trb, sizeof(dwc_trb_t)*num_of_trb);
591
592 while (num_of_trb)
593 {
594 bytes_remaining += REG_READ_FIELD_LOCAL(&trb->f3, TRB_F3, BUFSIZ);
595
Amol Jadif3d5a892013-07-23 16:09:44 -0700596 /* The first non-zero status indicates the transfer status. Update
597 * "status" only once but still go through all the TRBs to find out
598 * the bytes still remaining to be transferred.
599 */
600 if (!status)
601 {
602 status = REG_READ_FIELD_LOCAL(&trb->f3, TRB_F3, TRBSTS);
603 }
604
605 if ((event_status & DWC_XFER_COMPLETE_EVT_STATUS_SHORT_PKT) &&
606 (REG_READ_FIELD_LOCAL(&trb->f4, TRB_F4, HWO)))
607 {
608 /* This TRB needs to be reclaimed since transfer completed due to
609 * reception of a short pkt.
610 * "fast-forward" condition as described in snps 8.2.3.2.
611 */
612 DBG("\n TRB needs to be reclaimed by sw. trb = 0x%x\n", (uint32_t) trb);
613 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, HWO, 0x0);
614 trb_updated = 1;
615 }
Channagoud Kadabic075a6f2014-02-18 12:10:30 -0800616
617 /* point to next trb */
618 trb++;
619
620 /* decrement trb count */
621 num_of_trb--;
Amol Jadif3d5a892013-07-23 16:09:44 -0700622 }
623
624 /* flush out any updates to trb before continuing */
625 if (trb_updated)
626 {
627 arch_clean_invalidate_cache_range((addr_t) ep->trb,
628 sizeof(dwc_trb_t)*ep->trb_queued);
629 }
630
631 /* reset the EP's queued trb count */
632 ep->trb_queued = 0;
633
634 *bytes_in_buf = bytes_remaining;
635
636 DBG("\n trb_status: %d total buf size = 0x%x \n", status, *bytes_in_buf);
637
638 return status;
639}
640
641/* handle all events occurring in Control-Setup state */
642static void dwc_event_handler_ep_ctrl_state_setup(dwc_dev_t *dev,
643 uint32_t *event)
644{
645 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
646 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
647 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
648
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +0800649 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -0700650 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gaoe2568e52014-07-24 15:23:18 +0800651 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -0700652
653 switch (event_id)
654 {
655 case DWC_EVENT_EP_CMD_COMPLETE:
656 {
657 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
658
659 if (cmd == DEPCMD_CMD_START_TRANSFER)
660 {
661 ASSERT(ep->state == EP_STATE_START_TRANSFER);
662
663 ASSERT(event_status == 0);
664
665 /* save the resource id assigned to this ep. */
666 ep->state = EP_STATE_XFER_IN_PROG;
667 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
668 }
669 else
670 {
671 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
672 }
673 }
674 break;
675
676 case DWC_EVENT_EP_XFER_NOT_READY:
677 {
678 /* attempting to start data/status before setup. snps 8.4.2 #2 */
679 DBG("\nattempting to start data/status before setup. stalling..\n");
680
681 dwc_ep_cmd_stall(dev, ep_phy_num);
682
683 /* new state is stall */
684 dev->ctrl_state = EP_FSM_STALL;
685 }
686 break;
687
688 case DWC_EVENT_EP_XFER_COMPLETE:
689 {
690 uint32_t bytes_remaining = 0;
691 uint8_t status = 0;
692
693 /* cannot happen on any other ep */
694 ASSERT(ep_phy_num == 0);
695
696 /* Assert if ep state is not xfer_in_prog. fatal error. */
697 ASSERT(ep->state == EP_STATE_XFER_IN_PROG);
698
699 /* update ep state to inactive. */
700 ep->state = EP_STATE_INACTIVE;
701
702 /* check transfer status. */
703 status = dwc_event_check_trb_status(dev,
704 event,
705 DWC_EP_PHY_TO_INDEX(ep_phy_num),
706 &bytes_remaining);
707
708 if (status || bytes_remaining)
709 {
710 /* transfer failed. queue another transfer. */
711 dwc_ep_ctrl_state_setup_enter(dev);
712 }
713 else
714 {
715 int ret;
716 uint8_t *data = dev->setup_pkt; /* setup pkt data */
717
718 /* invalidate any cached setup data before reading */
719 arch_invalidate_cache_range((addr_t) data, DWC_SETUP_PKT_LEN);
720
721 /* call setup handler */
722 ret = dev->setup_handler(dev->setup_context, data);
723
724 if (ret == DWC_SETUP_2_STAGE)
725 {
726 /* this is a 2 stage setup. */
727 dev->ctrl_state = EP_FSM_WAIT_FOR_HOST_2;
728 }
729 else if (ret == DWC_SETUP_3_STAGE)
730 {
731 /* this is a 3 stage setup. */
732 dev->ctrl_state = EP_FSM_CTRL_DATA;
733 }
734 else
735 {
736 /* bad setup bytes. stall */
737 dwc_ep_cmd_stall(dev, ep_phy_num);
738
739 /* new state is stall */
740 dev->ctrl_state = EP_FSM_STALL;
741 }
742 }
743 }
744 break;
745 case DWC_EVENT_EP_XFER_IN_PROGRESS:
746 default:
747 /* event is not expected in this state */
Channagoud Kadabi9ac72462014-04-15 15:29:41 -0700748 ERR("\n Ignore the unexpected EP event: %s\n", event_lookup_ep[event_id]);
Amol Jadi1133a302013-10-01 14:45:38 -0700749 dwc_print_ep_event_details(dev, event);
750 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -0700751 }
752}
753
Amol Jadi1133a302013-10-01 14:45:38 -0700754
Amol Jadif3d5a892013-07-23 16:09:44 -0700755/* handle all events occurring in Control-Data state */
756static void dwc_event_handler_ep_ctrl_state_data(dwc_dev_t *dev,
757 uint32_t *event)
758{
759 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
760 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
761 uint8_t event_ctrl_stage = DWC_EVENT_EP_EVENT_CTRL_STAGE(*event);
762 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
763
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +0800764 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -0700765 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gaoe2568e52014-07-24 15:23:18 +0800766 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -0700767
768 switch (event_id)
769 {
770 case DWC_EVENT_EP_CMD_COMPLETE:
771 {
772 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
773
774 if (cmd == DEPCMD_CMD_START_TRANSFER)
775 {
776 ASSERT(ep->state == EP_STATE_START_TRANSFER);
777
778 ASSERT(event_status == 0);
779
780 /* save the resource id assigned to this ep. */
781 ep->state = EP_STATE_XFER_IN_PROG;
782 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
783 }
784 else
785 {
786 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
787 }
788 }
789 break;
790
791 case DWC_EVENT_EP_XFER_NOT_READY:
792 {
793 /* confirm that this is control data request.
794 * control_status_request is invalid event in this state.
795 * assert if it ever occurs.
796 * something must be wrong in fsm implementation.
797 */
798 ASSERT(event_ctrl_stage == CONTROL_DATA_REQUEST);
799
800 /* In this state, the ep must be in transfer state.
801 * otherwise this came on an ep that we are not expecting any data.
802 */
803 if((ep->state == EP_STATE_START_TRANSFER) ||
804 (ep->state == EP_STATE_XFER_IN_PROG))
805 {
806 DBG("\n Host requested data on ep_phy_num = %d."
807 "Transfer already started. No action....", ep_phy_num);
808 }
809 else
810 {
811 /* host attempting to move data in wrong direction.
812 * end transfer for the direction that we started and stall.
813 */
814 uint8_t end_ep_phy_num;
815
816 /* end the other ep */
817 end_ep_phy_num = (ep_phy_num == 0) ? 1 : 0;
818
819 DBG("\nAttempting to move data in wrong direction. stalling. ");
820
821 dwc_ep_cmd_end_transfer(dev, end_ep_phy_num);
822
823 /* stall */
824 dwc_ep_cmd_stall(dev, end_ep_phy_num);
825
826 /* move to stall state. */
827 dev->ctrl_state = EP_FSM_STALL;
828 }
829 }
830 break;
831 case DWC_EVENT_EP_XFER_COMPLETE:
832 {
833 uint32_t bytes_remaining;
834 uint8_t status;
835
836 /* should never happen in any other state.
837 * something wrong in fsm implementation.
838 */
839 ASSERT(ep->state == EP_STATE_XFER_IN_PROG);
840
841 /* transfer is complete */
842 ep->state = EP_STATE_INACTIVE;
843
844 /* check transfer status */
845 status = dwc_event_check_trb_status(dev,
846 event,
847 DWC_EP_PHY_TO_INDEX(ep_phy_num),
848 &bytes_remaining);
849
850 if (status || bytes_remaining)
851 {
852 DBG("\n\n ********DATA TRANSFER FAILED ************* "
853 "status = %d bytes_remaining = %d\n\n",
854 status, bytes_remaining);
855 }
856
857 /* wait for host to request status */
858 dev->ctrl_state = EP_FSM_WAIT_FOR_HOST_3;
859 }
860 break;
861 case DWC_EVENT_EP_XFER_IN_PROGRESS:
862 default:
863 /* event is not expected in this state */
Channagoud Kadabi9ac72462014-04-15 15:29:41 -0700864 ERR("\n Ignore the unexpected EP event: %s\n", event_lookup_ep[event_id]);
Amol Jadi1133a302013-10-01 14:45:38 -0700865 dwc_print_ep_event_details(dev, event);
866 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -0700867 }
868}
869
870/* handle all events occurring in Wait-for-Host-2 state */
871static void dwc_event_handler_ep_ctrl_state_wait_for_host_2(dwc_dev_t *dev,
872 uint32_t *event)
873{
874 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
875 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
876 uint8_t event_ctrl_stage = DWC_EVENT_EP_EVENT_CTRL_STAGE(*event);
877
878 switch (event_id)
879 {
Channagoud Kadabi49c82bf2014-02-12 17:08:42 -0800880 case DWC_EVENT_EP_CMD_COMPLETE:
881 {
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800882 DBG("\n cmd = %s has no action. ignored.",
883 cmd_lookup[DWC_EVENT_EP_EVENT_CMD_TYPE(*event)]);
Channagoud Kadabi49c82bf2014-02-12 17:08:42 -0800884 }
885 break;
Amol Jadif3d5a892013-07-23 16:09:44 -0700886 case DWC_EVENT_EP_XFER_NOT_READY:
887 {
888 if (event_ctrl_stage == CONTROL_DATA_REQUEST)
889 {
890 DBG("\n\n attempting to start data when setup did not indicate"
891 "data stage. stall...\n\n");
892
893 dwc_ep_cmd_stall(dev, ep_phy_num);
894
895 /* move to stall state. */
896 dev->ctrl_state = EP_FSM_STALL;
897 }
898 else if (event_ctrl_stage == CONTROL_STATUS_REQUEST)
899 {
900 /* status cannot happen on phy = 0 */
901 ASSERT(ep_phy_num == 1);
902
903 dwc_request_t req;
904
905 req.callback = 0x0;
906 req.context = 0x0;
907 req.data = 0x0;
908 req.len = 0x0;
909 req.trbctl = TRBCTL_CONTROL_STATUS_2;
910
911 dwc_request_queue(dev, ep_phy_num, &req);
912
913 dev->ctrl_state = EP_FSM_STATUS_2;
914 }
915 else
916 {
917 ASSERT(0);
918 }
919 }
920 break;
921 case DWC_EVENT_EP_XFER_IN_PROGRESS:
922 case DWC_EVENT_EP_XFER_COMPLETE:
923 default:
924 /* event not expected in this state. */
Channagoud Kadabi9ac72462014-04-15 15:29:41 -0700925 ERR("\n Ignore the unexpected EP event: %s\n", event_lookup_ep[event_id]);
Amol Jadi1133a302013-10-01 14:45:38 -0700926 dwc_print_ep_event_details(dev, event);
927 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -0700928 }
929}
930
931/* handle all events occurring in Wait-for-Host-3 state */
932static void dwc_event_handler_ep_ctrl_state_wait_for_host_3(dwc_dev_t *dev,
933 uint32_t *event)
934{
935 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
936 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
937 uint8_t event_ctrl_stage = DWC_EVENT_EP_EVENT_CTRL_STAGE(*event);
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +0800938
939 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Matthew Qin365014b2014-09-04 19:26:57 +0800940 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
941 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -0700942
943 switch (event_id)
944 {
Channagoud Kadabi49c82bf2014-02-12 17:08:42 -0800945 case DWC_EVENT_EP_CMD_COMPLETE:
946 {
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800947 DBG("\n cmd = %s has no action. ignored.",
948 cmd_lookup[DWC_EVENT_EP_EVENT_CMD_TYPE(*event)]);
Channagoud Kadabi49c82bf2014-02-12 17:08:42 -0800949 }
950 break;
Amol Jadif3d5a892013-07-23 16:09:44 -0700951 case DWC_EVENT_EP_XFER_NOT_READY:
952 {
953 if (event_ctrl_stage == CONTROL_DATA_REQUEST)/* data request */
954 {
Matthew Qin365014b2014-09-04 19:26:57 +0800955 if (ep->state == EP_STATE_START_TRANSFER ||
956 ep->state == EP_STATE_XFER_IN_PROG) {
957 /*
958 * special case handling when data stage transfer length
959 * was exact multiple of max_pkt_size.
960 * Need to setup a TRB to complete data stage with a zero
961 * length pkt transfer.
962 */
963
964 dwc_request_t req;
965
966 req.callback = 0x0;
967 req.context = 0x0;
968 req.data = 0x0;
969 req.len = 0x0;
970 req.trbctl = TRBCTL_CONTROL_DATA;
971
972 DBG("\n Sending the elp to host as the end of xfer\n");
973 dwc_request_queue(dev, ep_phy_num, &req);
974 dev->ctrl_state = EP_FSM_CTRL_DATA;
975 } else {
976 DBG("\n attempting to start data when setup did not indicate"
977 "data stage. stall...\n\n");
978 dwc_ep_cmd_stall(dev, ep_phy_num);
979 dev->ctrl_state = EP_FSM_STALL;
980 }
Amol Jadif3d5a892013-07-23 16:09:44 -0700981 }
982 else if (event_ctrl_stage == CONTROL_STATUS_REQUEST)/* stat req */
983 {
984 dwc_request_t req;
985
986 req.callback = 0x0;
987 req.context = 0x0;
988 req.data = 0x0;
989 req.len = 0x0;
990 req.trbctl = TRBCTL_CONTROL_STATUS_3;
991
992 dwc_request_queue(dev, ep_phy_num, &req);
993
994 dev->ctrl_state = EP_FSM_STATUS_3;
995 }
996 else
997 {
998 ASSERT(0);
999 }
1000 }
1001 break;
1002 case DWC_EVENT_EP_XFER_IN_PROGRESS:
1003 case DWC_EVENT_EP_XFER_COMPLETE:
1004 default:
1005 /* event is not expected in this state */
Channagoud Kadabi9ac72462014-04-15 15:29:41 -07001006 ERR("\n Ignore the unexpected EP event: %s\n", event_lookup_ep[event_id]);
Amol Jadi1133a302013-10-01 14:45:38 -07001007 dwc_print_ep_event_details(dev, event);
1008 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -07001009 }
1010}
1011
1012
1013/* handle all events occurring in Status-2 state */
1014static void dwc_event_handler_ep_ctrl_state_status_2(dwc_dev_t *dev,
1015 uint32_t *event)
1016{
1017 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1018 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1019 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
1020
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001021 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001022 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001023 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -07001024
1025 switch (event_id)
1026 {
1027 case DWC_EVENT_EP_CMD_COMPLETE:
1028 {
1029 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
1030
1031 if (cmd == DEPCMD_CMD_START_TRANSFER)
1032 {
1033 ASSERT(ep->state == EP_STATE_START_TRANSFER);
1034
1035 ASSERT(event_status == 0);
1036
1037 /* save the resource id assigned to this ep. */
1038 ep->state = EP_STATE_XFER_IN_PROG;
1039 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
1040 }
1041 else
1042 {
1043 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
1044 }
1045 }
1046 break;
1047 case DWC_EVENT_EP_XFER_COMPLETE:
1048 {
1049 uint32_t bytes_remaining;
1050 uint8_t status;
1051
1052 /* cannot happen on ep 0 */
1053 ASSERT(ep_phy_num == 1);
1054
1055 /* should never happen in any other state.
1056 * something wrong in fsm implementation.
1057 */
1058 ASSERT(ep->state == EP_STATE_XFER_IN_PROG);
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001059 if (dev->is_test_mode)
1060 {
1061 /* Write DCTL register with test mode value */
1062 dwc_device_enter_test_mode(dev);
1063 dprintf(INFO, "Device entered test mode, please reset the device once testing is finished\n");
1064 break;
1065 }
Amol Jadif3d5a892013-07-23 16:09:44 -07001066
1067 ep->state = EP_STATE_INACTIVE;
1068
1069 /* check transfer status */
1070 status = dwc_event_check_trb_status(dev,
1071 event,
1072 DWC_EP_PHY_TO_INDEX(ep_phy_num),
1073 &bytes_remaining);
1074
1075 if (status || bytes_remaining)
1076 {
1077 DBG("\n\n ******** TRANSFER FAILED ************* status ="
1078 " %d bytes_remaining = %d\n\n", status, bytes_remaining);
1079 }
1080
1081 dwc_ep_ctrl_state_setup_enter(dev);
1082 }
1083 break;
1084 case DWC_EVENT_EP_XFER_NOT_READY:
1085 case DWC_EVENT_EP_XFER_IN_PROGRESS:
1086 default:
1087 /* event is not expected in this state */
Channagoud Kadabi9ac72462014-04-15 15:29:41 -07001088 ERR("\n Ignore the unexpected EP event: %s\n", event_lookup_ep[event_id]);
Amol Jadi1133a302013-10-01 14:45:38 -07001089 dwc_print_ep_event_details(dev, event);
1090 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -07001091 }
1092}
1093
1094/* handle all events occurring in Status-3 state */
1095static void dwc_event_handler_ep_ctrl_state_status_3(dwc_dev_t *dev,
1096 uint32_t *event)
1097{
1098 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1099 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1100 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
1101
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001102 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001103 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001104 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -07001105
1106 switch (event_id)
1107 {
1108 case DWC_EVENT_EP_CMD_COMPLETE:
1109 {
1110 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
1111
1112 if (cmd == DEPCMD_CMD_START_TRANSFER)
1113 {
1114 /* something wrong with fsm. cannot happen in any other ep state.*/
1115 ASSERT(ep->state == EP_STATE_START_TRANSFER);
1116
1117 ASSERT(event_status == 0);
1118
1119 /* save the resource id assigned to this ep. */
1120 ep->state = EP_STATE_XFER_IN_PROG;
1121 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
1122 }
1123 else
1124 {
1125 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
1126 }
1127 }
1128 break;
1129 case DWC_EVENT_EP_XFER_COMPLETE:
1130 {
1131 uint32_t bytes_remaining;
1132 uint8_t status;
1133
1134 /* should never happen in any other state.
1135 * something wrong in fsm implementation.
1136 */
1137 ASSERT(ep->state == EP_STATE_XFER_IN_PROG);
1138
1139 ep->state = EP_STATE_INACTIVE;
1140
1141 /* check transfer status */
1142 status = dwc_event_check_trb_status(dev,
1143 event,
1144 DWC_EP_PHY_TO_INDEX(ep_phy_num),
1145 &bytes_remaining);
1146
1147 if (status || bytes_remaining)
1148 {
1149 DBG("\n\n ******** TRANSFER FAILED ************* status ="
1150 " %d bytes_remaining = %d\n\n", status, bytes_remaining);
1151
1152 /* data stage failed. */
1153 dwc_ep_cmd_stall(dev, ep_phy_num);
1154
1155 /* move to stall state. */
1156 dev->ctrl_state = EP_FSM_STALL;
1157 }
1158 else
1159 {
1160 dwc_ep_ctrl_state_setup_enter(dev);
1161 }
1162 }
1163 break;
1164 case DWC_EVENT_EP_XFER_NOT_READY:
1165 case DWC_EVENT_EP_XFER_IN_PROGRESS:
1166 default:
1167 /* event is not expected in this state */
Channagoud Kadabi9ac72462014-04-15 15:29:41 -07001168 ERR("\n Ignore the unexpected EP event: %s\n", event_lookup_ep[event_id]);
Amol Jadi1133a302013-10-01 14:45:38 -07001169 dwc_print_ep_event_details(dev, event);
1170 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -07001171 }
1172}
1173
1174/* handle all events occurring in stall state */
1175static void dwc_event_handler_ep_ctrl_state_stall(dwc_dev_t *dev,
1176 uint32_t *event)
1177{
1178 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1179 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1180
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001181 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001182 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001183 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -07001184
1185 switch (event_id)
1186 {
1187 case DWC_EVENT_EP_CMD_COMPLETE:
1188 {
1189 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
1190
1191 if (cmd == DEPCMD_CMD_SET_STALL)
1192 {
1193 /* stall complete. go back to setup state. */
1194 dwc_ep_ctrl_state_setup_enter(dev);
1195 }
1196 else if (cmd == DEPCMD_CMD_END_TRANSFER)
1197 {
1198 /* reset state and resource index */
1199 ep->state = EP_STATE_INACTIVE;
1200 ep->resource_idx = 0;
1201 }
1202 else
1203 {
1204 DBG("\n cmd = %s has no action. ignored.", cmd_lookup[cmd]);
1205 }
1206 }
1207 break;
1208 default:
1209 DBG("\n\n ********No Action defined for this event. ignored. \n\n");
1210 break;
1211 }
1212}
1213
1214/* event handler for INACTIVE state of bulk endpoint */
1215static void dwc_event_handler_ep_bulk_state_inactive(dwc_dev_t *dev,
1216 uint32_t *event)
1217{
Amol Jadif3d5a892013-07-23 16:09:44 -07001218 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
Channagoud Kadabi42f54da2015-06-24 12:53:30 -07001219#ifdef DEBUG_USB
1220 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1221#endif
Amol Jadif3d5a892013-07-23 16:09:44 -07001222
1223 switch (event_id)
1224 {
1225 case DWC_EVENT_EP_CMD_COMPLETE:
1226 {
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -08001227 DBG("\n cmd = %s has no action. ignored.",
1228 cmd_lookup[DWC_EVENT_EP_EVENT_CMD_TYPE(*event)]);
Amol Jadif3d5a892013-07-23 16:09:44 -07001229 }
1230 break;
1231 case DWC_EVENT_EP_XFER_NOT_READY:
1232 {
1233 /* This is a valid scenario where host is requesting data and
1234 * our client has not queued the request yet.
1235 */
1236 DBG("\n Host requested data on ep_phy_num = %d. "
1237 "No action. ignored.", ep_phy_num);
1238 }
1239 break;
1240 case DWC_EVENT_EP_XFER_IN_PROGRESS:
1241 case DWC_EVENT_EP_XFER_COMPLETE:
1242 default:
1243 /* event is not expected in this state */
Channagoud Kadabi9ac72462014-04-15 15:29:41 -07001244 ERR("\n Ignore the unexpected EP event: %s\n", event_lookup_ep[event_id]);
Amol Jadi1133a302013-10-01 14:45:38 -07001245 dwc_print_ep_event_details(dev, event);
1246 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -07001247 }
1248}
1249
1250/* event handler for START_TRANSFER state of bulk endpoint */
1251static void dwc_event_handler_ep_bulk_state_start_transfer(dwc_dev_t *dev,
1252 uint32_t *event)
1253{
1254 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1255 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1256 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
1257
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001258 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001259 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001260 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -07001261
1262 switch (event_id)
1263 {
1264 case DWC_EVENT_EP_CMD_COMPLETE:
1265 {
1266 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
1267
1268 if (cmd == DEPCMD_CMD_START_TRANSFER)
1269 {
1270 if (event_status == 0)
1271 {
1272 /* save the resource id assigned to this ep. */
1273 ep->state = EP_STATE_XFER_IN_PROG;
1274 ep->resource_idx = DWC_EVENT_EP_EVENT_XFER_RES_IDX(*event);
1275 }
1276 else
1277 {
1278 /* start transfer failed. inform client */
1279 if (ep->req.callback)
1280 {
1281 ep->req.callback(ep->req.context, 0, -1);
1282 }
1283
1284 /* back to inactive state */
1285 dwc_ep_bulk_state_inactive_enter(dev, ep_phy_num);
1286 }
1287 }
1288 else
1289 {
1290 DBG("\n cmd = %s has no action. ignored.\n", cmd_lookup[cmd]);
1291 }
1292 }
1293 break;
1294 default:
Channagoud Kadabi9ac72462014-04-15 15:29:41 -07001295 ERR("\n Ignore the unexpected EP event: %s\n", event_lookup_ep[event_id]);
Amol Jadi1133a302013-10-01 14:45:38 -07001296 dwc_print_ep_event_details(dev, event);
1297 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -07001298 }
1299}
1300
1301/* event handler for TRANSFER_IN_PROGRESS state of bulk endpoint */
1302static void dwc_event_handler_ep_bulk_state_xfer_in_prog(dwc_dev_t *dev,
1303 uint32_t *event)
1304{
1305 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1306 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1307
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001308 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001309 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001310 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -07001311
1312 switch (event_id)
1313 {
1314 case DWC_EVENT_EP_CMD_COMPLETE:
1315 {
1316 dwc_dep_cmd_id_t cmd = DWC_EVENT_EP_EVENT_CMD_TYPE(*event);
1317
1318 if (cmd == DEPCMD_CMD_END_TRANSFER)
1319 {
1320 /* transfer was cancelled for some reason. */
1321 DBG("\n transfer was cancelled on ep_phy_num = %d\n", ep_phy_num);
1322
1323 /* inform client that transfer failed. */
1324 if (ep->req.callback)
1325 {
1326 ep->req.callback(ep->req.context, 0, -1);
1327 }
1328
1329 /* back to inactive state */
1330 dwc_ep_bulk_state_inactive_enter(dev, ep_phy_num);
1331 }
1332 else
1333 {
1334 DBG("\n cmd = %s has no action. ignored.\n", cmd_lookup[cmd]);
1335 }
1336 }
1337 break;
1338 case DWC_EVENT_EP_XFER_NOT_READY:
1339 {
1340 /* This is a valid scenario where host is requesting data and
1341 * we have not yet moved to start transfer state.
1342 */
1343 DBG("\n Host requested data on ep_phy_num = %d."
1344 "No action. ignored.", ep_phy_num);
1345 }
1346 break;
1347 case DWC_EVENT_EP_XFER_COMPLETE:
1348 {
1349 uint32_t bytes_remaining;
1350 uint8_t status;
1351
1352 /* Check how many TRBs were processed and how much data got
1353 * transferred. If there are bytes_remaining, it does not
1354 * necessarily mean failed xfer. We could have queued a 512 byte
1355 * read and receive say 13 bytes of data which is a valid scenario.
1356 */
1357 status = dwc_event_check_trb_status(dev,
1358 event,
1359 DWC_EP_PHY_TO_INDEX(ep_phy_num),
1360 &bytes_remaining);
1361
1362 DBG("\n\n ******DATA TRANSFER COMPLETED (ep_phy_num = %d) ********"
1363 "bytes_remaining = %d\n\n", ep_phy_num, bytes_remaining);
1364
1365 if (ep->req.callback)
1366 {
1367 ep->req.callback(ep->req.context,
1368 ep->bytes_queued - bytes_remaining,
1369 status ? -1 : 0);
1370 }
1371
1372 dwc_ep_bulk_state_inactive_enter(dev, ep_phy_num);
1373 }
1374 break;
1375 default:
Channagoud Kadabi9ac72462014-04-15 15:29:41 -07001376 ERR("\n Ignore the unexpected EP event: %s\n", event_lookup_ep[event_id]);
Amol Jadi1133a302013-10-01 14:45:38 -07001377 dwc_print_ep_event_details(dev, event);
1378 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -07001379 }
1380}
1381
1382/* bulk endpoint event handler */
1383void dwc_event_handler_ep_bulk(dwc_dev_t *dev, uint32_t *event)
1384{
1385 uint8_t ep_phy_num = DWC_EVENT_EP_EVENT_EP_NUM(*event);
1386#ifdef DEBUG_USB
1387 dwc_event_ep_event_id_t event_id = DWC_EVENT_EP_EVENT_ID(*event);
1388 uint8_t event_status = DWC_EVENT_EP_EVENT_STATUS(*event);
1389 uint16_t event_param = DWC_EVENT_EP_EVENT_PARAM(*event);
1390#endif
1391
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001392 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001393 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001394 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -07001395
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001396#ifdef DEBUG_USB
Amol Jadif3d5a892013-07-23 16:09:44 -07001397 DBG("\n\n\n++EP_EVENT: %s in ctrl_state: %s ep_state[%d]: %s",
1398 event_lookup_ep[event_id],
1399 dev_ctrl_state_lookup[dev->ctrl_state],
1400 ep_phy_num,
1401 ep_state_lookup[ep->state]);
1402
1403 DBG("\n ep_phy_num = %d param = 0x%x status = 0x%x",
1404 ep_phy_num, event_param, event_status);
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001405#endif
Amol Jadif3d5a892013-07-23 16:09:44 -07001406
1407 switch (ep->state)
1408 {
1409 case EP_STATE_INACTIVE:
1410 {
1411 dwc_event_handler_ep_bulk_state_inactive(dev, event);
1412 }
1413 break;
1414 case EP_STATE_START_TRANSFER:
1415 {
1416 dwc_event_handler_ep_bulk_state_start_transfer(dev, event);
1417 }
1418 break;
1419 case EP_STATE_XFER_IN_PROG:
1420 {
1421 dwc_event_handler_ep_bulk_state_xfer_in_prog(dev, event);
1422 }
1423 break;
1424 default:
Amol Jadi1133a302013-10-01 14:45:38 -07001425 ERR("\n EP state is invalid. Asserting...\n");
1426 dwc_print_ep_event_details(dev, event);
1427 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -07001428 ASSERT(0);
1429 }
1430
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001431#ifdef DEBUG_USB
Amol Jadif3d5a892013-07-23 16:09:44 -07001432 DBG("\n--EP_EVENT: %s in ctrl_state: %s ep_state[%d]: %s",
1433 event_lookup_ep[event_id],
1434 dev_ctrl_state_lookup[dev->ctrl_state],
1435 ep_phy_num,
1436 ep_state_lookup[ep->state]);
Lijuan Gaoe2568e52014-07-24 15:23:18 +08001437#endif
Amol Jadif3d5a892013-07-23 16:09:44 -07001438}
1439
1440
1441
1442
1443/******************** Endpoint related APIs **********************************/
1444
1445/* Initialize and enable EP:
1446 * - set the initial configuration for an endpoint
1447 * - set transfer resources
1448 * - enable the endpoint
1449 */
1450static void dwc_ep_config_init_enable(dwc_dev_t *dev, uint8_t index)
1451{
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001452 ASSERT(index < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001453 uint8_t ep_phy_num = dev->ep[index].phy_num;
1454
1455 dwc_ep_cmd_set_config(dev, index, SET_CONFIG_ACTION_INIT);
1456
1457 dev->ep[index].state = EP_STATE_INACTIVE;
1458
1459 /* Set transfer resource configs for the end points */
1460 dwc_ep_cmd_set_transfer_resource(dev, ep_phy_num);
1461
1462 /* enable endpoint */
1463 dwc_ep_enable(dev, ep_phy_num);
1464}
1465
1466/* Initialize control EPs:
1467 * Do the one time initialization of control EPs
1468 */
1469static void dwc_ep_ctrl_init(dwc_dev_t *dev)
1470{
1471 uint8_t index;
1472
1473 /* Control OUT */
1474 index = DWC_EP_INDEX(0, DWC_EP_DIRECTION_OUT);
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001475 ASSERT(index < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001476
1477 dev->ep[index].number = 0;
1478 dev->ep[index].dir = DWC_EP_DIRECTION_OUT;
1479 dev->ep[index].phy_num = 0;
1480 dev->ep[index].type = EP_TYPE_CONTROL;
1481 dev->ep[index].state = EP_STATE_INIT;
1482 dev->ep[index].max_pkt_size = 512;
1483 dev->ep[index].burst_size = 0;
1484 dev->ep[index].tx_fifo_num = 0;
1485 dev->ep[index].zlp = 0;
1486 dev->ep[index].trb_count = 1;
1487 /* TRB must be aligned to 16 */
1488 dev->ep[index].trb = memalign(lcm(CACHE_LINE, 16),
1489 ROUNDUP(dev->ep[index].trb_count*sizeof(dwc_trb_t), CACHE_LINE));
1490 ASSERT(dev->ep[index].trb);
1491 dev->ep[index].trb_queued = 0;
1492 dev->ep[index].bytes_queued = 0;
1493
1494 /* Control IN */
Channagoud Kadabi50a17d02013-10-24 16:55:39 -07001495 index = DWC_EP_INDEX(0, DWC_EP_DIRECTION_IN);
Amol Jadif3d5a892013-07-23 16:09:44 -07001496
1497 dev->ep[index].number = 0;
1498 dev->ep[index].dir = DWC_EP_DIRECTION_IN;
1499 dev->ep[index].phy_num = 1;
1500 dev->ep[index].type = EP_TYPE_CONTROL;
1501 dev->ep[index].state = EP_STATE_INIT;
1502 dev->ep[index].max_pkt_size = 512;
1503 dev->ep[index].burst_size = 0;
1504 dev->ep[index].tx_fifo_num = 0;
1505 dev->ep[index].zlp = 0;
1506 dev->ep[index].trb_count = 1;
1507 /* TRB must be aligned to 16 */
1508 dev->ep[index].trb = memalign(lcm(CACHE_LINE, 16),
1509 ROUNDUP(dev->ep[index].trb_count*sizeof(dwc_trb_t), CACHE_LINE));
1510 ASSERT(dev->ep[index].trb);
1511 dev->ep[index].trb_queued = 0;
1512 dev->ep[index].bytes_queued = 0;
1513
1514 /* configure and enable the endpoints */
1515 dwc_ep_config_init_enable(dev, 0);
1516 dwc_ep_config_init_enable(dev, 1);
1517}
1518
1519
1520/* entry function into setup state for control fsm */
1521static void dwc_ep_ctrl_state_setup_enter(dwc_dev_t *dev)
1522{
1523 dwc_request_t req;
1524
1525 /* queue request to receive the first setup pkt from host */
1526 memset(dev->setup_pkt, 0, DWC_SETUP_PKT_LEN);
1527
1528 /* flush data */
1529 arch_clean_invalidate_cache_range((addr_t) dev->setup_pkt, DWC_SETUP_PKT_LEN);
1530
1531 req.data = dev->setup_pkt;
1532 req.len = DWC_SETUP_PKT_LEN;
1533 req.trbctl = TRBCTL_CONTROL_SETUP;
1534 req.callback = NULL;
1535 req.context = NULL;
1536
1537 dwc_request_queue(dev, 0, &req);
1538
1539 /* reset control ep state to "setup" state */
1540 dev->ctrl_state = EP_FSM_SETUP;
1541}
1542
1543/* entry function into inactive state for data transfer fsm */
1544static void dwc_ep_bulk_state_inactive_enter(dwc_dev_t *dev, uint8_t ep_phy_num)
1545{
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001546 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001547 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001548 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -07001549
1550 /* queue request to receive the first setup pkt from host */
1551 ep->req.data = NULL;
1552 ep->req.len = 0;
1553 ep->req.trbctl = 0;
1554 ep->req.callback = NULL;
1555 ep->req.context = NULL;
1556
1557 /* inactive state */
1558 ep->state = EP_STATE_INACTIVE;
1559
1560 /* reset the resource index, trb and bytes queued */
1561 ep->resource_idx = 0;
1562 ep->trb_queued = 0;
1563 ep->bytes_queued = 0;
1564}
1565
1566/*************************** External APIs ************************************/
1567
1568/* Initialize controller for device mode operation.
1569 * Implements sequence as described in HPG.
1570 * Numbers indicate the step # in HPG.
1571 */
1572void dwc_device_init(dwc_dev_t *dev)
1573{
1574 /* 15. reset device ctrl. */
1575 dwc_device_reset(dev);
1576
1577 /* 16. initialize global control reg for device mode operation */
1578 dwc_gctl_init(dev);
1579
1580 /* 17. AXI master config */
1581 dwc_axi_master_config(dev);
1582
1583 /* 18. */
1584 /* a. tx fifo config */
1585 /* reset value is good. */
1586 /* b. rx fifo config */
1587 /* reset value is good. */
1588
1589 /* 18.c */
1590 dwc_event_init(dev);
1591
1592 /* 18.d */
1593 /* enable device event generation */
1594 dwc_event_device_enable(dev, BIT(DWC_EVENT_DEVICE_EVENT_ID_DISCONNECT) |
1595 BIT(DWC_EVENT_DEVICE_EVENT_ID_USB_RESET) |
Channagoud Kadabi8bc768e2015-01-27 11:40:51 -08001596 BIT(DWC_EVENT_DEVICE_EVENT_ID_SUSPEND_ENTRY) |
Amol Jadif3d5a892013-07-23 16:09:44 -07001597 BIT(DWC_EVENT_DEVICE_EVENT_ID_CONNECT_DONE));
1598
1599 /* 18.e initialize control end point
1600 * start new config on end point 0. only needed for ep0.
1601 * resource index must be set to 0.
1602 */
1603 dwc_ep_cmd_start_new_config(dev, 0, 0);
1604
1605 /* steps described in snps 8.1 */
1606 dwc_ep_ctrl_init(dev);
1607
1608 /* Unmask interrupts */
1609 unmask_interrupt(USB30_EE1_IRQ);
1610
1611 /* start the control ep fsm */
1612 dwc_ep_ctrl_state_setup_enter(dev);
1613}
1614
1615/* add a new non-control endpoint belonging to the selected USB configuration.
1616 * This is called when "set config" setup is received from host.
1617 * udc layer first adds the endpoints which are part of the selected
1618 * configuration by calling this api.
1619 * Then it calls dwc_device_set_configuration() to enable that configuration.
1620 * TODO: need better api to manage this. possibly a single api to do both.
1621 * also, currently this only works as long as same configuration is selected
1622 * every time. The cleanup during usb reset is not cleanly removing the
1623 * endpoints added during a set config. This works fine for our usecase.
1624 */
Sundarajan Srinivasan1c421912014-03-31 17:55:31 -07001625void dwc_device_add_ep(dwc_dev_t *dev, dwc_ep_t *new_ep)
Amol Jadif3d5a892013-07-23 16:09:44 -07001626{
Sundarajan Srinivasan1c421912014-03-31 17:55:31 -07001627 uint8_t index = DWC_EP_INDEX(new_ep->number, new_ep->dir);
Amol Jadif3d5a892013-07-23 16:09:44 -07001628
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001629 ASSERT(index < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001630 dwc_ep_t *ep = &dev->ep[index];
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001631 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -07001632
1633 memset(ep, 0, sizeof(ep));
1634
1635 /* copy client specified params */
1636
Sundarajan Srinivasan1c421912014-03-31 17:55:31 -07001637 ep->number = new_ep->number;
1638 ep->dir = new_ep->dir;
1639 ep->type = new_ep->type;
1640 ep->max_pkt_size = new_ep->max_pkt_size;
1641 ep->burst_size = new_ep->burst_size;
1642 ep->zlp = new_ep->zlp;
1643 ep->trb_count = new_ep->trb_count;
1644 ep->trb = new_ep->trb;
Amol Jadif3d5a892013-07-23 16:09:44 -07001645
1646 ASSERT(ep->trb);
1647
1648 /* clear out trb memory space. */
1649 memset(ep->trb, 0, (ep->trb_count)*sizeof(ep->trb));
1650 arch_clean_invalidate_cache_range((addr_t) ep->trb,
1651 (ep->trb_count)*sizeof(ep->trb));
1652
1653 /* initialize dwc specified params */
1654
1655 /* map this usb ep to the next available phy ep.
1656 * we assume non-flexible endpoint mapping.
1657 * so the physical ep number is same as the index into our EP array.
1658 */
1659 ep->phy_num = index;
1660
1661 if (ep->dir == DWC_EP_DIRECTION_IN)
1662 {
1663 /* TODO: this works only as long as we just one IN EP (non-control).
1664 * Need to increment this for every new IN ep added.
1665 */
1666 ep->tx_fifo_num = 1;
1667 }
1668 else
1669 {
1670 ep->tx_fifo_num = 0; /* tx fifo num must be 0 for OUT ep */
1671 }
1672
1673 ep->trb_queued = 0;
1674 ep->bytes_queued = 0;
1675 ep->resource_idx = 0;
1676 ep->state = EP_STATE_INIT;
1677}
1678
1679/* Configure and enable non-control endpoints:
1680 * This is called when "set config" setup is received from host.
1681 * Implements sequence as described in snps databook 8.1.5.
1682 */
1683void dwc_device_set_configuration(dwc_dev_t *dev)
1684{
1685 /* disable every ep other than control EPs */
1686 dwc_ep_disable_non_control(dev);
1687
1688 /* re-initialize TX FIFO by sending set config cmd to ep-1 */
1689 dwc_ep_cmd_set_config(dev, 1, SET_CONFIG_ACTION_MODIFY);
1690
1691 /* re-initialize transfer resource allocation:
1692 * only needed for ep0.
1693 * resource index must be set to 2 when doing set config
1694 */
1695 dwc_ep_cmd_start_new_config(dev, 0, 2);
1696
1697 /* Initialize config for each non-control EP in the new configuration */
1698 for (uint8_t ep_index = 2; ep_index < DWC_MAX_NUM_OF_EP; ep_index++)
1699 {
1700 /* non-zero phy ep num indicates that this ep data is initialized
1701 * and ready for use.
1702 */
1703 if (dev->ep[ep_index].phy_num)
1704 {
1705 dwc_ep_config_init_enable(dev, ep_index);
1706 }
1707 }
1708
1709 /* optional: re-initialize tx FIFO : GTXFIFOSIZn*/
1710}
1711
1712/* Enqueue new data transfer request on an endpoint. */
1713static int dwc_request_queue(dwc_dev_t *dev,
1714 uint8_t ep_phy_num,
1715 dwc_request_t *req)
1716{
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001717 ASSERT(DWC_EP_PHY_TO_INDEX(ep_phy_num) < DWC_MAX_NUM_OF_EP);
Amol Jadif3d5a892013-07-23 16:09:44 -07001718 dwc_ep_t *ep = &dev->ep[DWC_EP_PHY_TO_INDEX(ep_phy_num)];
Lijuan Gao4e0ddbe2014-09-24 15:41:05 +08001719 ASSERT(ep != NULL);
Amol Jadif3d5a892013-07-23 16:09:44 -07001720
1721 dwc_trb_t *trb = ep->trb;
1722 uint8_t *data_ptr = req->data;
1723 uint32_t transfer_len = req->len;
1724 dwc_trb_trbctl_t trbctl = req->trbctl;
1725
1726 uint32_t pad_len;
1727
1728 if(ep->state != EP_STATE_INACTIVE)
1729 {
1730 DBG("\n EP must be in INACTIVE state to start queue transfer. ep_phy_num = %d current state = %s",
1731 ep_phy_num, ep_state_lookup[ep->state]);
1732 return -1;
1733 }
1734
1735 /* trb queued must be 0 at this time. */
1736 ASSERT(ep->trb_queued == 0);
1737
1738 /* save the original request for this ep */
1739 ep->req = *req;
1740
1741 ep->bytes_queued = 0;
1742
Channagoud Kadabi5f8f1c42015-03-25 14:35:05 -07001743 if (ep->type == EP_TYPE_CONTROL || ep->type == EP_TYPE_INTERRUPT)
Amol Jadif3d5a892013-07-23 16:09:44 -07001744 {
1745 memset(trb, 0, sizeof(dwc_trb_t));
1746
1747 REG_WRITE_FIELD_LOCAL(&trb->f1, TRB_F1, PTR_LOW, (uint32_t) data_ptr);
1748 REG_WRITE_FIELD_LOCAL(&trb->f2, TRB_F2, PTR_HIGH, 0x0);
1749 REG_WRITE_FIELD_LOCAL(&trb->f3, TRB_F3, BUFSIZ, transfer_len);
1750 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, LST, 0x1);
1751 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CHN, 0x0);
1752 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CSP, 0x0);
1753 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, TRBCTL, trbctl);
1754 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, IOC, 0x1);
1755 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, HWO, 0x1);
1756
1757 /* increment the queued trb count */
1758 ep->trb_queued++;
1759 ep->bytes_queued += transfer_len;
1760 data_ptr += transfer_len;
1761 }
1762 else if (ep->type == EP_TYPE_BULK)
1763 {
1764 /* reserve 1 trb for pad/zero-length pkt */
1765 uint32_t trb_available = ep->trb_count - 1;
1766 uint32_t max_bytes_per_trb;
1767 uint32_t offset;
1768 uint32_t trb_len = 0;
1769
1770 /* snps 7.2 table 7-1. applies only to older versions of the controller:
1771 * - data_ptr in first TRB can be aligned to byte
1772 * - but the following TRBs should point to data that is aligned
1773 * to master bus data width.
1774 */
1775
1776 /* align default MAX_BYTES_PER_TRB to DWC_MASTER_BUS_WIDTH */
1777 max_bytes_per_trb = ROUNDDOWN(DWC_MAX_BYTES_PER_TRB, DWC_MASTER_BUS_WIDTH);
1778
1779 while (trb_available && transfer_len)
1780 {
1781 /* clear out trb fields */
1782 memset(trb, 0, sizeof(dwc_trb_t));
1783
1784 if (ep->trb_queued == 0)
1785 {
1786 /* first trb: limit the transfer length in this TRB such that
1787 * the next trb data_ptr will be aligned to master bus width.
1788 */
1789 offset = ((uint32_t) data_ptr) & (DWC_MASTER_BUS_WIDTH - 1);
1790 trb_len = (transfer_len <= max_bytes_per_trb) ?
1791 transfer_len : (max_bytes_per_trb - offset);
1792 }
1793 else
1794 {
1795 trb_len = (transfer_len <= max_bytes_per_trb) ?
1796 transfer_len : max_bytes_per_trb;
1797 }
1798
1799 REG_WRITE_FIELD_LOCAL(&trb->f1, TRB_F1, PTR_LOW, (uint32_t) data_ptr);
1800 REG_WRITE_FIELD_LOCAL(&trb->f2, TRB_F2, PTR_HIGH, 0x0);
1801 REG_WRITE_FIELD_LOCAL(&trb->f3, TRB_F3, BUFSIZ, trb_len);
1802 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, LST, 0x0);
1803 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CHN, 0x1);
1804 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CSP, 0x0);
1805 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, TRBCTL, trbctl);
1806 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, IOC, 0x0);
1807 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, HWO, 0x1);
1808
1809 /* increment the queued trb count */
1810 ep->trb_queued++;
1811 ep->bytes_queued += trb_len;
1812 data_ptr += trb_len;
1813
1814 /* remaining transfer len */
1815 transfer_len -= trb_len;
1816
1817 /* remaining trb */
1818 trb_available--;
1819
1820 /* point to the next trb */
1821 trb++;
1822 }
1823
1824 if (transfer_len)
1825 {
1826 /* TRBs not available to queue the entire request.
1827 * If more data is expected in each request, increase the number
1828 * of TRBs allocated for this EP.
1829 */
1830 ERR("\n ERROR: Enough TRBs are not available to setup transfer\n");
1831 ERR("\n ERROR: Increase TRB chain for the ep.\n");
1832 ERR("\n ERROR: phy_ep_num = %d xfer len = %d\n", ep_phy_num, req->len);
1833 ASSERT(0);
1834 }
1835
1836 /* snps 8.2.3.3:
1837 * For an OUT ep:
1838 * (a) The "buffer descriptor" must be exact multiple of max_pkt_size
1839 * "buffer descriptor" consists of one or more TRBs upto the TRB
1840 * with CHN (chain) flag is not set.
1841 * Add a TRB to pad the len if it is not exact multiple.
1842 *
1843 * (b) If the expected amount of data is exact multiple of max_pkt_size:
1844 * add a max_pkt_size trb to sink in zero-length pkt, only if
1845 * the EP expects it.
1846 */
1847 uint32_t roundup = req->len % ep->max_pkt_size;
1848
1849 if ( (ep->dir == DWC_EP_DIRECTION_OUT) &&
1850 (roundup || ep->zlp))
1851 {
1852 if(roundup)
1853 {
1854 /* add a TRB to make it exact multiple of max_pkt_size */
1855 pad_len = ep->max_pkt_size - roundup;
1856 }
1857 else
1858 {
1859 /* "buffer descriptor" is exact multiple of max_pkt_size and
1860 * ep expects a zero-length pkt.
1861 * Add a TRB to sink in the zero-length pkt.
1862 */
1863 pad_len = ep->max_pkt_size;
1864 }
1865
1866 memset(trb, 0, sizeof(dwc_trb_t));
1867 memset(ep->zlp_buf, 0, DWC_ZLP_BUF_SIZE);
1868
1869 REG_WRITE_FIELD_LOCAL(&trb->f1, TRB_F1, PTR_LOW, (uint32_t) ep->zlp_buf);
1870 REG_WRITE_FIELD_LOCAL(&trb->f2, TRB_F2, PTR_HIGH, 0x0);
1871 REG_WRITE_FIELD_LOCAL(&trb->f3, TRB_F3, BUFSIZ, pad_len);
1872 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, LST, 0x1);
1873 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CHN, 0x0);
1874 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CSP, 0x0);
1875 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, TRBCTL, trbctl);
1876 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, IOC, 0x1);
1877 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, HWO, 0x1);
1878
1879 /* increment the queued trb count */
1880 ep->trb_queued++;
1881 ep->bytes_queued += pad_len;
1882 }
1883 else /* pad trb not needed. */
1884 {
1885 /* point trb to the last programmed trb */
1886 trb--;
1887
1888 /* setup params for last TRB */
1889 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, CHN, 0x0);
1890 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, LST, 0x1);
1891 REG_WRITE_FIELD_LOCAL(&trb->f4, TRB_F4, IOC, 0x1);
1892 }
1893 }
1894 else
1895 {
1896 /* invalid EP type */
1897 ASSERT(0);
1898 }
1899
1900 /* flush the trb data to main memory */
1901 arch_clean_invalidate_cache_range((addr_t) ep->trb,
1902 sizeof(dwc_trb_t)*ep->trb_queued);
1903
1904 DBG("\n Starting new xfer on ep_phy_num = %d TRB_QUEUED = %d \n",
1905 ep_phy_num, ep->trb_queued);
1906
1907 /* dwc_request_queue could be triggered from app and thus
1908 * outside of interrupt context. Use critical section to make sure all
1909 * states are updated properly before we handle other interrupts.
1910 */
1911 enter_critical_section();
1912
1913 if(ep->state == EP_STATE_INACTIVE)
1914 {
1915 dwc_ep_cmd_start_transfer(dev, ep_phy_num);
1916
1917 if(dwc_device_run_status(dev))
1918 {
1919 ep->state = EP_STATE_START_TRANSFER;
1920 }
1921 else
1922 {
1923 /* no interrupt expected on completion of start transfer.
1924 * directly move to xfer in prog state.
1925 */
1926 ep->state = EP_STATE_XFER_IN_PROG;
1927 }
1928 }
1929 else
1930 {
Amol Jadi1133a302013-10-01 14:45:38 -07001931 ERR("\n Attempting START_TRANSFER in invalid state: %s. .......\n",
Amol Jadif3d5a892013-07-23 16:09:44 -07001932 ep_state_lookup[ep->state]);
Amol Jadi1133a302013-10-01 14:45:38 -07001933 dwc_print_current_state(dev);
Amol Jadif3d5a892013-07-23 16:09:44 -07001934 ASSERT(0);
1935 }
1936
1937 exit_critical_section();
1938
1939 return 0;
1940}
1941
1942/* data transfer request:
1943 * NOTE: Assumes that the data to be transferred is already in main memory.
1944 * Any cache management must be done by caller .
1945 * For received data, cache mgmt must be done in callback function.
1946 */
1947int dwc_transfer_request(dwc_dev_t *dwc,
1948 uint8_t usb_ep,
1949 dwc_ep_direction_t dir,
1950 void *buf,
1951 uint32_t len,
1952 dwc_transfer_callback_t callback,
1953 void *callback_context)
1954{
1955 uint8_t ep_phy_num;
1956 dwc_request_t req;
1957
1958 /* map usb ep to physical ep */
1959 ep_phy_num = DWC_EP_PHY_NUM(usb_ep, dir);
1960
1961 req.data = buf;
1962 req.len = len;
1963 req.callback = callback;
1964 req.context = callback_context;
1965
1966 if (usb_ep == 0)
1967 {
1968 /* control EP always has CONTROL_DATA trb */
1969 req.trbctl = TRBCTL_CONTROL_DATA;
1970 }
1971 else
1972 {
1973 req.trbctl = TRBCTL_NORMAL;
1974 }
1975
1976 return dwc_request_queue(dwc, ep_phy_num, &req);
1977}