blob: a950bc802f404d0b56524245bb7819275752d50f [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2 *
3 * (C)Copyright 2013 - 2014 Marvell. All Rights Reserved.
4 *
5 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
6 * The copyright notice above does not evidence any actual or intended
7 * publication of such source code.
8 * This Module contains Proprietary Information of Marvell and should be
9 * treated as Confidential.
10 * The information in this file is provided for the exclusive use of the
11 * licensees of Marvell.
12 * Such users have the right to use, modify, and incorporate this code into
13 * products for purposes authorized by the license agreement provided they
14 * include this notice and the associated copyright notice with any such
15 * product.
16 * The information in this file is provided "AS IS" without warranty.
17 *
18 ******************************************************************************/
19
20
21#include "Typedef.h"
22#include "misc.h"
23#include "timer.h"
24#include "usb_descriptors.h"
25#include "usbapi.h"
26#include "usb2_main.h"
27#include "usb2_memory.h"
28#include "usb2_enumeration.h"
29#include "ProtocolManager.h"
30//#include "USB2.h"
31#include "snps_usb.h"
32
33#define CIU_REG_CHIPID (0xD4282C00)
34
35#define USB_ENABLE_DEBUG 1
36#ifdef USB_ENABLE_DEBUG
37#define NR_LOGGING_ARRAY (32)
38#define USB_CMD_PASS (0)
39#define USB_CMD_FAIL1 (1)
40#define USB_CMD_FAIL2 (2)
41#define USB_CMD_FAIL3 (3)
42#define USB_CMD_FAIL4 (4)
43#define USB_CMD_FAIL5 (5)
44//32*32 =1024
45struct usb_cmd_params usbcmd_logging_array[NR_LOGGING_ARRAY];
46int usbcmd_logging_ptr = 0;
47//char usbsend_len_table[NR_LOGGING_ARRAY];
48//int usbsend_len_ptr = 0;
49USHORT usbrecv_len_table[NR_LOGGING_ARRAY];
50int usbrecv_len_ptr = 0;
51struct usb_trb_params usbep0_trb_table[NR_LOGGING_ARRAY];
52int usbep0_trb_ptr = 0;
53struct usb_trb_params usbep1_trb_table[NR_LOGGING_ARRAY];
54int usbep1_trb_ptr = 0;
55char usbep0_nrdy_table[NR_LOGGING_ARRAY];
56int usbep0_nrdy_ptr = 0;
57short usbcmd_cur_cmd_result = 0;
58short usbep1_data_count = 0;
59short usbcmd_setlink_count = 0;
60short usbcmd_setlink_fail_count = 0;
61short usbep0_nrdy_fail_count = 0;
62short usbep0_data_nrdy_count = 0;
63#endif
64
65static int IS_PTRB_OK(UINT_T ptrb)
66{
67 if (ptrb >= 0x000000 && ptrb < 0xc0000000)
68 return 1;
69 else
70 return 0;
71}
72
73int DWC3_SET_LINK_STATE(enum dwc3_link_state state)
74{
75 int retries = 10000;
76 UINT reg;
77
78 /*
79 * Wait until device controller is ready. Only applies to 1.94a and
80 * later RTL.
81 */
82 while (--retries) {
83 reg = DWC3_REG_READ(DWC3_DSTS);
84 bbu_printf("%s: DWC3_DSTS: 0x%x\n\r", __func__, reg);
85 if (!(reg & DWC3_DSTS_DCNRD))
86 break;
87 Delay(5);
88 }
89
90 if (retries <= 0)
91 return -1;
92
93 reg = DWC3_REG_READ(DWC3_DCTL);
94 reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
95
96 /* set requested state */
97 reg |= DWC3_DCTL_ULSTCHNGREQ(state);
98 DWC3_REG_WRITE(DWC3_DCTL, reg);
99
100 bbu_printf("%s: retries: %d DWC3_DCTL: 0x%x\n\r", __func__, retries, reg);
101 return 0;
102}
103
104static int DO_DWC3_GADGET_WAKEUP(void)
105{
106 int retries;
107 int ret;
108 UINT reg;
109 UINT link_state;
110
111 reg = DWC3_REG_READ(DWC3_DSTS);
112 bbu_printf("%s: DWC3_DSTS: 0x%x\n\r", __func__, reg);
113 link_state = DWC3_DSTS_USBLNKST(reg);
114
115 switch (link_state) {
116 case DWC3_LINK_STATE_RESET:
117 case DWC3_LINK_STATE_RX_DET: /* in HS, means Early Suspend */
118 case DWC3_LINK_STATE_U3: /* in HS, means SUSPEND */
119 case DWC3_LINK_STATE_RESUME:
120 break;
121 default:
122 return -1;
123 }
124
125 ret = DWC3_SET_LINK_STATE(DWC3_LINK_STATE_RECOV);
126 if (ret < 0) {
127 bbu_printf("failed to put link in Recovery\n\r");
128 return ret;
129 }
130
131#ifdef USB_ENABLE_DEBUG
132 usbcmd_setlink_count++;
133#endif
134
135 /* poll until Link State changes to ON */
136 retries = 10000;
137 while (retries--) {
138 reg = DWC3_REG_READ(DWC3_DSTS);
139
140 /* in HS, means ON */
141 if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0)
142 break;
143 Delay(5);
144 }
145
146 if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) {
147#ifdef USB_ENABLE_DEBUG
148 usbcmd_setlink_fail_count++;
149#endif
150 bbu_printf("failed to send remote wakeup\n\r");
151 return -1;
152 }
153
154 bbu_printf("%s: DWC3_DSTS: 0x%x\n\r", __func__, reg);
155 return 0;
156}
157
158int DWC3_SEND_EP_CMD(P_DC_Properties_T pDCProps, UINT cmd,
159 struct dwc3_gadget_ep_cmd_params *params, UINT ep_num)
160{
161 UINT timeout = 100000;
162 UINT reg;
163 UINT link_state;
164 int cmd_status = 0;
165 int ret = 0;
166 int needs_wakeup;
167#ifdef USB_ENABLE_DEBUG
168 struct dwc3_trb * ptrb;
169#endif
170
171 reg = DWC3_REG_READ(DWC3_DSTS);
172 link_state = DWC3_DSTS_USBLNKST(reg);
173 bbu_printf("%s: DWC3_DSTS: 0x%x\n\r", __func__, reg);
174
175 if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
176 needs_wakeup = (link_state == DWC3_LINK_STATE_U1 ||
177 link_state == DWC3_LINK_STATE_U2 ||
178 link_state == DWC3_LINK_STATE_U3);
179
180 if (needs_wakeup) {
181 bbu_printf("%s:do wakeup\n\r", __func__);
182 DO_DWC3_GADGET_WAKEUP();
183 }
184 }
185
186#ifdef USB_ENABLE_DEBUG
187 usbcmd_logging_array[usbcmd_logging_ptr%NR_LOGGING_ARRAY].param0 = params->param0;
188 usbcmd_logging_array[usbcmd_logging_ptr%NR_LOGGING_ARRAY].param1 = params->param1;
189 usbcmd_logging_array[usbcmd_logging_ptr%NR_LOGGING_ARRAY].param2 = params->param2;
190 usbcmd_logging_array[usbcmd_logging_ptr%NR_LOGGING_ARRAY].cmd
191 = ((pDCProps->link_state << 16) | ((reg & DWC3_DSTS_CONNECTSPD) << 12)
192 | (link_state << 8) | (ep_num << 4) | cmd);
193 ptrb = params->param1;
194 if ((cmd == DWC3_DEPCMD_STARTTRANSFER) && IS_PTRB_OK((UINT_T)ptrb)) {
195 usbcmd_logging_array[usbcmd_logging_ptr%NR_LOGGING_ARRAY].param0 = ptrb->size;
196 usbcmd_logging_array[usbcmd_logging_ptr%NR_LOGGING_ARRAY].param2 = ptrb->ctrl;
197 }
198 usbcmd_logging_ptr++;
199 usbcmd_cur_cmd_result = USB_CMD_FAIL1;
200#endif
201
202 DWC3_REG_WRITE((DWC3_DEP_BASE(ep_num)+DWC3_DEPCMDPAR0), params->param0);
203 DWC3_REG_WRITE((DWC3_DEP_BASE(ep_num)+DWC3_DEPCMDPAR1), params->param1);
204 DWC3_REG_WRITE((DWC3_DEP_BASE(ep_num)+DWC3_DEPCMDPAR2), params->param2);
205 cmd |= DWC3_DEPCMD_CMDACT;
206 __asm__ __volatile__("dsb" : : : "memory");
207
208 DWC3_REG_WRITE((DWC3_DEP_BASE(ep_num)+DWC3_DEPCMD), cmd);
209
210 bbu_printf("%s:param0: 0x%x\n\r", __func__, params->param0);
211 bbu_printf("%s:param1: 0x%x\n\r", __func__, params->param1);
212 bbu_printf("%s:param2: 0x%x\n\r", __func__, params->param2);
213 bbu_printf("%s:cmd: 0x%x\n\r", __func__, cmd);
214 do {
215 reg = DWC3_REG_READ((DWC3_DEP_BASE(ep_num)+DWC3_DEPCMD));
216 if (!(reg & DWC3_DEPCMD_CMDACT)) {
217 cmd_status = DWC3_DEPCMD_STATUS(reg);
218
219 switch (cmd_status) {
220 case 0:
221 ret = 0;
222 break;
223 case DEPEVT_TRANSFER_NO_RESOURCE:
224 case DEPEVT_TRANSFER_BUS_EXPIRY:
225 default:
226 ret = -cmd_status;
227 break;
228 }
229 break;
230 }
231 } while (--timeout);
232
233 if (timeout == 0) {
234 ret = -1;
235 bbu_printf("%s: cmd 0x%x timeout: %d, cmd_status: 0x%x\n\r", __func__, cmd, timeout, cmd_status);
236 }
237
238#ifdef USB_ENABLE_DEBUG
239 usbcmd_cur_cmd_result = ret;
240#endif
241 if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
242 reg = DWC3_REG_READ((DWC3_DEP_BASE(ep_num)+DWC3_DEPCMD));
243 pDCProps->ep0to3_resource_idx[ep_num] = DWC3_DEPCMD_GET_RSC_IDX(reg);
244 }
245
246 return ret;
247}
248
249static void DWC3_STOP_ACTIVE_XFER(P_DC_Properties_T pDCProps, UINT ep_num, UCHAR resource_idx)
250{
251 struct dwc3_gadget_ep_cmd_params params;
252 UINT cmd;
253
254 if (resource_idx == 0)
255 return;
256
257 cmd = DWC3_DEPCMD_ENDTRANSFER;
258 cmd |= DWC3_DEPCMD_HIPRI_FORCERM;
259 cmd |= DWC3_DEPCMD_PARAM(resource_idx);
260 memset(&params, 0, sizeof(params));
261 DWC3_SEND_EP_CMD(pDCProps, cmd, &params, ep_num);
262 Delay(100);
263 pDCProps->ep0to3_resource_idx[ep_num] = 0x0;
264}
265
266void DWC3_EP0_OUT_START(P_DC_Properties_T pDCProps)
267{
268 bbu_printf("%s: buffer: 0x%x\n\r", __func__, pDCProps->ep0_out_buffer);
269 USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, USB_OUT,
270 pDCProps->ep0_out_buffer, 0x8, DWC3_TRBCTL_CONTROL_SETUP);
271}
272
273void DWC3_EP0_STALL_AND_RESTART(P_DC_Properties_T pDCProps)
274{
275 struct dwc3_gadget_ep_cmd_params params;
276 int ret;
277
278 memset(&params, 0x00, sizeof(params));
279 ret = DWC3_SEND_EP_CMD(pDCProps, DWC3_DEPCMD_SETSTALL, &params, 0);
280 if (ret) {
281 bbu_printf("failed to set STALL on ep0\n\r");
282 return;
283 }
284
285 pDCProps->ep0state = EP0_SETUP_PHASE;
286 DWC3_EP0_OUT_START(pDCProps);
287}
288
289static void DWC3_EP0_HANDLE_SETUP(P_DC_Properties_T pDCProps,
290 struct dwc3_event_depevt *event)
291{
292 UCHAR epnum;
293 P_dQH_T pQH;
294 XLLP_USB_SETUP_DATA_T *usb_ctrl_p;
295
296 epnum = event->endpoint_number;
297 if (epnum > 1)
298 return;
299
300 pQH = &pDCProps->pdQHHead[epnum];
301
302 ReleasetrbChain((struct dwc3_trb *)(pQH->initial_trb));
303 pQH->initial_trb = NULL;
304
305 usb_ctrl_p = pDCProps->ep0_out_buffer;
306 if (usb_ctrl_p->wLength == 0) {
307 pDCProps->ctrl_direction = USB_IN;
308 pDCProps->ctrl_stages = 2;
309 pDCProps->ep0_next_event = DWC3_EP0_NRDY_STATUS;
310 pDCProps->ep0_expect_in = 0x0;
311 } else {
312 pDCProps->ctrl_direction = !(usb_ctrl_p->bmRequestType & 0x80);
313 pDCProps->ctrl_stages = 3;
314 pDCProps->ep0_next_event = DWC3_EP0_NRDY_DATA;
315 pDCProps->ep0_expect_in = !(pDCProps->ctrl_direction);
316 }
317
318 USB2D_EnumerationHandler(pDCProps, (XLLP_USB_SETUP_DATA_T *)pDCProps->ep0_out_buffer);
319}
320
321static void DWC3_EP0_COMPLETE_DATA(P_DC_Properties_T pDCProps,
322 struct dwc3_event_depevt *event)
323{
324
325 UCHAR epnum;
326 UINT count;
327 struct dwc3_trb * ptrb;
328 P_dQH_T pQH;
329
330 epnum = event->endpoint_number;
331 if (epnum > 1)
332 return;
333
334 pDCProps->ep0_next_event = DWC3_EP0_NRDY_STATUS;
335
336 pQH = &pDCProps->pdQHHead[epnum];
337 ptrb = pQH->initial_trb;
338 //remaining bytes
339 count = ptrb->size & DWC3_TRB_SIZE_MASK;
340
341 bbu_printf("%s: ptrb->ctrl: 0x%x, event->status 0x%x\n\r",
342 __func__, ptrb->ctrl, event->status);
343
344 //update size counter for the last packet being a short packet
345 pQH->tot_size -= count;
346
347 ReleasetrbChain((struct dwc3_trb *)(pQH->initial_trb));
348 pQH->initial_trb = NULL;
349 //OUT EP
350 if ((epnum & 0x1) == 0) {
351 memcpy(pQH->buffer, pDCProps->ep0_out_buffer, pQH->tot_size);
352 //TODO: invoke callback to handle buffer
353 }
354}
355
356static void DWC3_EP0_COMPLETE_STATUS(P_DC_Properties_T pDCProps,
357 struct dwc3_event_depevt *event)
358{
359 UCHAR epnum;
360 P_dQH_T pQH;
361
362 epnum = event->endpoint_number;
363 if (epnum > 1)
364 return;
365
366 pQH = &pDCProps->pdQHHead[epnum];
367
368 pDCProps->ep0state = EP0_SETUP_PHASE;
369 ReleasetrbChain((struct dwc3_trb *)(pQH->initial_trb));
370 pQH->initial_trb = NULL;
371
372 bbu_printf("%s\n\r", __func__);
373 DWC3_EP0_OUT_START(pDCProps);
374}
375
376
377static void DWC3_EP0_XFERNOTREADY(P_DC_Properties_T pDCProps,
378 struct dwc3_event_depevt *event)
379{
380 UINT ep_num;
381
382 if (event->endpoint_number > 1) {
383 bbu_printf("%s ep_num: %d\n\r", __func__, event->endpoint_number);
384 return;
385 }
386
387 ep_num = !!event->endpoint_number;
388
389 switch (event->status) {
390 case DEPEVT_STATUS_CONTROL_DATA:
391 //do noting
392 bbu_printf("DEPEVT_STATUS_CONTROL_DATA nothing\n\r");
393 if (pDCProps->ep0_expect_in != event->endpoint_number) {
394 usbep0_data_nrdy_count++;
395 }
396 break;
397
398 case DEPEVT_STATUS_CONTROL_STATUS:
399 bbu_printf("DEPEVT_STATUS_CONTROL_STATUS\n\r");
400
401 if (pDCProps->ep0_next_event != DWC3_EP0_NRDY_STATUS) {
402 bbu_printf("DEPEVT_STATUS_CONTROL_STATUS nothing\n\r");
403#ifdef USB_ENABLE_DEBUG
404 usbep0_nrdy_fail_count++;
405#endif
406 return;
407 }
408
409 //STATUS BASED ON STAGE/DIRECTION
410 if (pDCProps->ctrl_stages == 2)
411 USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0,
412 /*pDCProps->ctrl_direction*/ep_num,
413 pDCProps->BufferSpace2, 0, DWC3_TRBCTL_CONTROL_STATUS2);
414 else
415 USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0,
416 /*pDCProps->ctrl_direction*/ep_num,
417 pDCProps->BufferSpace2, 0, DWC3_TRBCTL_CONTROL_STATUS3);
418#ifdef USB_ENABLE_DEBUG
419 if (pDCProps->ctrl_stages == 2)
420 usbep0_nrdy_table[usbep0_nrdy_ptr%NR_LOGGING_ARRAY] = DWC3_TRBCTL_CONTROL_STATUS2 | ep_num;
421 else
422 usbep0_nrdy_table[usbep0_nrdy_ptr%NR_LOGGING_ARRAY] = DWC3_TRBCTL_CONTROL_STATUS3 | ep_num;
423 usbep0_nrdy_ptr++;
424#endif
425 break;
426 default:
427 break;
428 }
429}
430
431static void DWC3_EP0_XFER_COMPLETE(P_DC_Properties_T pDCProps,
432 struct dwc3_event_depevt *event)
433{
434 UCHAR epnum;
435 struct dwc3_trb * ptrb;
436
437 epnum = event->endpoint_number;
438 if (epnum > 1)
439 return;
440 pDCProps->ep0to3_resource_idx[epnum] = 0x0;
441#ifdef USB_ENABLE_DEBUG
442 ptrb = pDCProps->pdQHHead[(epnum & 0x1)].initial_trb;
443 if (IS_PTRB_OK((UINT_T)ptrb)) {
444 usbep0_trb_table[usbep0_trb_ptr%NR_LOGGING_ARRAY].size = ptrb->size;
445 usbep0_trb_table[usbep0_trb_ptr%NR_LOGGING_ARRAY].ctrl= (ptrb->ctrl | (epnum << 16));
446 } else {
447 usbep0_trb_table[usbep0_trb_ptr%NR_LOGGING_ARRAY].size = 0;
448 usbep0_trb_table[usbep0_trb_ptr%NR_LOGGING_ARRAY].ctrl= (epnum << 16);
449 }
450 usbep0_trb_ptr++;
451#endif
452
453 switch (pDCProps->ep0state) {
454 case EP0_SETUP_PHASE:
455 bbu_printf("%s: setup\n\r", __func__);
456 DWC3_EP0_HANDLE_SETUP(pDCProps, event);
457 break;
458
459 case EP0_DATA_PHASE:
460 bbu_printf("%s: data\n\r", __func__);
461 DWC3_EP0_COMPLETE_DATA(pDCProps, event);
462#ifndef DWC3_ENABLE_XFERNOTREADY
463 //STATUS BASED ON STAGE/DIRECTION
464 //2stage xfer status is handled in out pkt
465 if (pDCProps->ctrl_stages == 2)
466 USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, pDCProps->ctrl_direction,
467 pDCProps->BufferSpace2, 0, DWC3_TRBCTL_CONTROL_STATUS2);
468 else
469 USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, pDCProps->ctrl_direction,
470 pDCProps->BufferSpace2, 0, DWC3_TRBCTL_CONTROL_STATUS3);
471#endif
472 break;
473
474 case EP0_STATUS_PHASE:
475 bbu_printf("%s: status\n\r", __func__);
476 DWC3_EP0_COMPLETE_STATUS(pDCProps, event);
477 break;
478 default:
479 break;
480 }
481}
482
483void DWC3_EP0_INT(P_DC_Properties_T pDCProps, struct dwc3_event_depevt *event)
484{
485 switch (event->endpoint_event) {
486 case DWC3_DEPEVT_XFERCOMPLETE:
487 bbu_printf("DWC3_DEPEVT_XFERCOMPLETE\n\r");
488 DWC3_EP0_XFER_COMPLETE(pDCProps, event);
489 break;
490
491 case DWC3_DEPEVT_XFERNOTREADY:
492 bbu_printf("DWC3_DEPEVT_XFERNOTREADY ep%d\n\r", event->endpoint_number);
493 DWC3_EP0_XFERNOTREADY(pDCProps, event);
494 break;
495
496 case DWC3_DEPEVT_XFERINPROGRESS:
497 case DWC3_DEPEVT_RXTXFIFOEVT:
498 case DWC3_DEPEVT_STREAMEVT:
499 break;
500 case DWC3_DEPEVT_EPCMDCMPLT:
501 break;
502 }
503}
504
505int DWC3_GET_CONN_SPEED(void)
506{
507 UINT reg;
508 UCHAR speed;
509
510 reg = DWC3_REG_READ(DWC3_DSTS);
511 speed = reg & DWC3_DSTS_CONNECTSPD;
512 switch (speed) {
513 case DWC3_DSTS_HIGHSPEED:
514 return USB_MODE_HS;
515 case DWC3_DSTS_FULLSPEED:
516 return USB_MODE_FS;
517 /*case DWC3_DSTS_SUPERSPEED:
518 return USB_MODE_SS;
519 case DWC3_DSTS_SUPERSPEED_PLUS:
520 return USB_MODE_SS_PLUS;
521 case DWC3_DSTS_LOWSPEED:
522 return USB_MODE_LS;*/
523 default:
524 return USB_MODE_HS;
525 }
526}
527
528static int DWC3_EP_SET_XFER_RESOURCE(P_DC_Properties_T pDCProps, UINT ep_num)
529{
530 struct dwc3_gadget_ep_cmd_params params;
531 UINT cmd;
532 int ret;
533
534 //prepare cmd parameters
535 params.param1 = 0x0;
536 params.param2 = 0x0;
537 params.param0 = DWC3_DEPXFERCFG_NUM_XFER_RES(1);
538 cmd = DWC3_DEPCMD_SETTRANSFRESOURCE;
539
540 ret = DWC3_SEND_EP_CMD(pDCProps, cmd, &params, ep_num);
541 return ret;
542}
543
544static int DWC3_EP_START_CFG(P_DC_Properties_T pDCProps, UINT ep_num)
545{
546 struct dwc3_gadget_ep_cmd_params params;
547 UINT cmd;
548 int ret;
549
550 //prepare cmd parameters
551 params.param0 = 0x0;
552 params.param1 = 0x0;
553 params.param2 = 0x0;
554 cmd = DWC3_DEPCMD_DEPSTARTCFG;
555
556 ret = DWC3_SEND_EP_CMD(pDCProps, cmd, &params, ep_num);
557 return ret;
558}
559
560static int DWC3_EP_SET_CFG(P_DC_Properties_T pDCProps, UINT ep_num, UINT modify)
561{
562 struct dwc3_gadget_ep_cmd_params params;
563 UINT cmd;
564 int ret, usb_speed_mode;
565
566 usb_speed_mode = DWC3_GET_CONN_SPEED();
567 //prepare cmd parameters
568 params.param0 = 0x0;
569 params.param1 = 0x0;
570 params.param2 = 0x0;
571
572 if (ep_num == 0 || ep_num == 1)
573 {
574 //CONTROL EP AND MAXPACKET SIZE
575 params.param0 = DWC3_DEPCFG_EP_TYPE(USB_CNTRL)
576 | DWC3_DEPCFG_MAX_PACKET_SIZE(USB_MPS_CNTRL_64);
577 } else {
578 if(usb_speed_mode == USB_MODE_FS)
579 //CONTROL EP AND MAXPACKET SIZE
580 params.param0 = DWC3_DEPCFG_EP_TYPE(USB_BULK)
581 | DWC3_DEPCFG_MAX_PACKET_SIZE(USB_MPS_BULK_64);
582 else
583 params.param0 = DWC3_DEPCFG_EP_TYPE(USB_BULK)
584 | DWC3_DEPCFG_MAX_PACKET_SIZE(USB_MPS_BULK_512);
585 }
586
587 if (modify) {
588 params.param0 |= DWC3_DEPCFG_ACTION_MODIFY;
589 } else {
590 params.param0 |= DWC3_DEPCFG_ACTION_INIT;
591 }
592 params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN;
593
594#ifdef DWC3_ENABLE_XFERNOTREADY
595 if (ep_num <= 1)
596 params.param1 |= DWC3_DEPCFG_XFER_NOT_READY_EN;
597#endif
598
599 /*
600 * We are doing 1:1 mapping for endpoints, meaning
601 * Physical Endpoints 2 maps to Logical Endpoint 2 and
602 * so on. We consider the direction bit as part of the physical
603 * endpoint number. So USB endpoint 0x81 is 0x03.
604 */
605 params.param1 |= DWC3_DEPCFG_EP_NUMBER(ep_num);
606
607 /*
608 * We must use the lower 16 TX FIFOs even though
609 * HW might have more
610 */
611 if (ep_num & 0x1)
612 params.param0 |= DWC3_DEPCFG_FIFO_NUMBER((ep_num >> 1));
613
614 cmd = DWC3_DEPCMD_SETEPCONFIG;
615 ret = DWC3_SEND_EP_CMD(pDCProps, cmd, &params, ep_num);
616 return ret;
617}
618
619UINT_T USB2D_Initialize(UINT base_address, UINT int_number, int param)
620{
621 P_DC_Properties_T pDCProps;
622 UINT_T regval;
623
624 //Try and get a new USB 2 'Object'
625 pDCProps = Allocate_USB2_Device(int_number);
626 //Check for error
627 if(pDCProps == NULL) {
628 bbu_printf("%s:line:%d\n\r", __func__, __LINE__);
629 return NotFoundError; //mdb make new error code
630 }
631
632 //reset and restore the controller
633 DWC3_Controller_Setup(pDCProps, param);
634
635 //setup EP 0
636 USB2D_Endpoint_Setup(pDCProps, USB_ENDPOINT_0, USB_OUT, USB_CNTRL);
637 USB2D_Endpoint_Setup(pDCProps, USB_ENDPOINT_0, USB_IN, USB_CNTRL);
638
639 pDCProps->link_state = DWC3_LINK_STATE_SS_DIS;
640
641 /* begin to receive SETUP packets */
642 pDCProps->ep0state = EP0_SETUP_PHASE;
643 DWC3_EP0_OUT_START(pDCProps);
644 __asm__ __volatile__("dsb" : : : "memory");
645
646 //ENABLE USB RUN BIT
647 bbu_printf("%s start usb now\n\r", __func__);
648 regval = DWC3_REG_READ(DWC3_DCTL);
649 regval |= DWC3_DCTL_RUN_STOP;
650 DWC3_REG_WRITE(DWC3_DCTL, regval);
651 bbu_printf("%s start usb done\n\r", __func__);
652 return NoError;
653}
654
655void USB2D_Shutdown(UINT intnum)
656{
657 UINT32 regval, count;
658 P_DC_Properties_T pDCProps = Get_DC_Properties(intnum);
659
660 if (pDCProps == NULL)
661 return;
662
663 //First wait a short time for the last transfers to complete
664 Delay((30 * 1000));
665
666 DWC3_STOP_ACTIVE_XFER(pDCProps, 3, pDCProps->ep0to3_resource_idx[3]);
667 DWC3_STOP_ACTIVE_XFER(pDCProps, 2, pDCProps->ep0to3_resource_idx[2]);
668 DWC3_STOP_ACTIVE_XFER(pDCProps, 1, pDCProps->ep0to3_resource_idx[1]);
669
670 //Disable all EVENTS
671 DWC3_REG_WRITE(DWC3_DEVTEN, 0x0);
672 __asm__ __volatile__("dsb" : : : "memory");
673
674 //Clear any pending events
675 count = DWC3_REG_READ(DWC3_GEVNTCOUNT(0));
676 count &= 0xFFFF;
677 DWC3_REG_WRITE(DWC3_GEVNTCOUNT(0), count);
678 __asm__ __volatile__("dsb" : : : "memory");
679
680 //lastly, shut off the controller
681 regval = DWC3_REG_READ(DWC3_DCTL);
682 regval &= ~DWC3_DCTL_RUN_STOP;
683 DWC3_REG_WRITE(DWC3_DCTL, regval);
684 Delay(50);
685}
686
687static void DWC3_DISCONNECT_INT(P_DC_Properties_T pDCProps)
688{
689 UINT reg;
690
691 bbu_printf("%s\n\r", __func__);
692 reg = DWC3_REG_READ(DWC3_DCTL);
693 reg &= ~DWC3_DCTL_INITU1ENA;
694 reg &= ~DWC3_DCTL_INITU2ENA;
695 DWC3_REG_WRITE(DWC3_DCTL, reg);
696 pDCProps->dev_state = USB_STATE_NOTATTACHED;
697}
698
699static void DWC3_RESET_INT(P_DC_Properties_T pDCProps)
700{
701 UINT reg;
702
703 bbu_printf("%s\n\r", __func__);
704 reg = DWC3_REG_READ(DWC3_DCTL);
705 reg &= ~DWC3_DCTL_TSTCTRL_MASK;
706 DWC3_REG_WRITE(DWC3_DCTL, reg);
707
708 //stop any pending transfers
709 DWC3_STOP_ACTIVE_XFER(pDCProps, 3, pDCProps->ep0to3_resource_idx[3]);
710 DWC3_STOP_ACTIVE_XFER(pDCProps, 2, pDCProps->ep0to3_resource_idx[2]);
711
712 /* Reset device address to zero */
713 reg = DWC3_REG_READ(DWC3_DCFG);
714 reg &= ~(DWC3_DCFG_DEVADDR_MASK);
715 DWC3_REG_WRITE(DWC3_DCFG, reg);
716}
717
718static void DWC3_CONNDONE_INT(P_DC_Properties_T pDCProps)
719{
720 UINT reg;
721 UCHAR speed;
722 INT usb_real_speed_mode;
723
724 reg = DWC3_REG_READ(DWC3_DSTS);
725 speed = reg & DWC3_DSTS_CONNECTSPD;
726 bbu_printf("%s:DWC3_DSTS = 0x%x\n\r", __func__, reg);
727
728 usb_real_speed_mode = DWC3_GET_CONN_SPEED();
729 /*
730 * real speed != pre-set speed
731 * need to care about second time link
732 */
733 if ((get_usb_speed_mode() == USB_MODE_HS)
734 && (usb_real_speed_mode != get_usb_speed_mode())) {
735 //update EP config
736 //update USB DESC
737 UpdateUSBDeviceConfigDesc(usb_real_speed_mode);
738 DWC3_EP_SET_CFG(pDCProps, 0, 1);
739 DWC3_EP_SET_CFG(pDCProps, 1, 1);
740 }
741
742 reg = DWC3_REG_READ(DWC3_DCFG);
743 reg |= DWC3_DCFG_LPM_CAP;
744 DWC3_REG_WRITE(DWC3_DCFG, reg);
745
746 reg = DWC3_REG_READ(DWC3_DCTL);
747 reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
748 DWC3_REG_WRITE(DWC3_DCTL, reg);
749}
750
751static void DWC3_WAKEUP_INT(P_DC_Properties_T pDCProps)
752{
753 bbu_printf("%s\n\r", __func__);
754}
755
756static void DWC3_LINKSTS_CHANGE_INT(P_DC_Properties_T pDCProps,
757 unsigned int evtinfo)
758{
759 bbu_printf("%s\n\r", __func__);
760 pDCProps->link_state = evtinfo & DWC3_LINK_STATE_MASK;
761}
762
763static void DWC3_SUSPEND_INT(P_DC_Properties_T pDCProps,
764 unsigned int evtinfo)
765{
766 bbu_printf("%s\n\r", __func__);
767 pDCProps->link_state = evtinfo & DWC3_LINK_STATE_MASK;
768}
769
770static void DWC3_DEV_INT(P_DC_Properties_T pDCProps,
771 struct dwc3_event_devt *event)
772{
773 bbu_printf("%s\n\r", __func__);
774 switch (event->type) {
775 case DWC3_DEVICE_EVENT_DISCONNECT:
776 DWC3_DISCONNECT_INT(pDCProps);
777 break;
778 case DWC3_DEVICE_EVENT_RESET:
779 DWC3_RESET_INT(pDCProps);
780 break;
781 case DWC3_DEVICE_EVENT_CONNECT_DONE:
782 DWC3_CONNDONE_INT(pDCProps);
783 break;
784 case DWC3_DEVICE_EVENT_WAKEUP:
785 DWC3_WAKEUP_INT(pDCProps);
786 break;
787 case DWC3_DEVICE_EVENT_HIBER_REQ:
788 //do nothing
789 break;
790 case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
791 DWC3_LINKSTS_CHANGE_INT(pDCProps, event->event_info);
792 break;
793 case DWC3_DEVICE_EVENT_EOPF:
794 if (pDCProps->dev_state >= USB_STATE_CONFIGURED)
795 DWC3_SUSPEND_INT(pDCProps, event->event_info);
796 break;
797 case DWC3_DEVICE_EVENT_SOF:
798 case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
799 case DWC3_DEVICE_EVENT_CMD_CMPL:
800 case DWC3_DEVICE_EVENT_OVERFLOW:
801 break;
802 default:
803 break;
804 }
805}
806
807//endpoint complete interrupt handler - means a trb finish (IOC bit)
808void DWC3_Complete_Int(P_DC_Properties_T pDCProps, UINT ep_num, struct dwc3_event_depevt *event)
809{
810 UINT count, s_pkt;
811 struct dwc3_trb * ptrb;
812 P_dQH_T pQH;
813
814 pDCProps->ep0to3_resource_idx[ep_num] = 0x0;
815 pQH = &pDCProps->pdQHHead[ep_num];
816 ptrb = pQH->initial_trb;
817 //remaining bytes
818 count = ptrb->size & DWC3_TRB_SIZE_MASK;
819
820#ifdef USB_ENABLE_DEBUG
821 if (IS_PTRB_OK((UINT_T)ptrb)) {
822 usbep1_trb_table[usbep1_trb_ptr%NR_LOGGING_ARRAY].size = ptrb->size;
823 usbep1_trb_table[usbep1_trb_ptr%NR_LOGGING_ARRAY].ctrl= (ptrb->ctrl | (ep_num << 16));
824 } else {
825 usbep1_trb_table[usbep1_trb_ptr%NR_LOGGING_ARRAY].size = 0;
826 usbep1_trb_table[usbep1_trb_ptr%NR_LOGGING_ARRAY].ctrl= (ep_num << 16);
827 }
828 usbep1_trb_ptr++;
829#endif
830
831 bbu_printf("%s: --ptrb->ctrl: 0x%x, event->status 0x%x ep %d, cn: %d\n\r",
832 __func__, ptrb->ctrl, event->status, ep_num, count);
833
834 //OUT EP
835 if ((ep_num & 0x1) == 0) {
836 if (count && (event->status & DEPEVT_STATUS_SHORT))
837 s_pkt = 1;
838 }
839
840 if (s_pkt)
841 goto giveback;
842
843 if ((event->status & DEPEVT_STATUS_LST) &&
844 (ptrb->ctrl & (DWC3_TRB_CTRL_LST |
845 DWC3_TRB_CTRL_HWO)))
846 goto giveback;
847
848 if ((event->status & DEPEVT_STATUS_IOC) &&
849 (ptrb->ctrl & DWC3_TRB_CTRL_IOC))
850 goto giveback;
851
852 //TODO:
853 return;
854
855giveback:
856#ifdef USB_ENABLE_DEBUG
857 usbep1_data_count++;
858#endif
859 ReleasetrbChain((struct dwc3_trb *)(pQH->initial_trb));
860 pQH->initial_trb = NULL;
861 //update size counter for the last packet being a short packet
862 pQH->tot_size -= count;
863 bbu_printf("%s: tot_size: %d\n\r", __func__, pQH->tot_size);
864 //Endpoint 2 RX serve call here
865 if(ep_num == 2) {
866 USB2D_PM_Call(pDCProps);
867 }
868}
869
870static void DWC3_EP_INT(P_DC_Properties_T pDCProps, struct dwc3_event_depevt *event)
871{
872 UCHAR epnum = event->endpoint_number;
873
874 if (epnum == 0 || epnum == 1) {
875 DWC3_EP0_INT(pDCProps, event);
876 return;
877 }
878
879 //TODO: only 4 eps in bootrom
880 if (epnum > 3)
881 return;
882
883 switch (event->endpoint_event) {
884 case DWC3_DEPEVT_XFERCOMPLETE:
885 DWC3_Complete_Int(pDCProps, epnum, event);
886 break;
887 case DWC3_DEPEVT_XFERINPROGRESS:
888 break;
889 case DWC3_DEPEVT_XFERNOTREADY:
890 break;
891 case DWC3_DEPEVT_STREAMEVT:
892 case DWC3_DEPEVT_EPCMDCMPLT:
893 case DWC3_DEPEVT_RXTXFIFOEVT:
894 break;
895 default:
896 break;
897 }
898}
899
900static void DWC3_PROCESS_EVENT_ENTRY(P_DC_Properties_T pDCProps,
901 union dwc3_event *event)
902{
903 if (!event->type.is_devspec)
904 DWC3_EP_INT(pDCProps, &event->depevt);
905 else if (event->type.type == DWC3_EVENT_TYPE_DEV)
906 DWC3_DEV_INT(pDCProps, &event->devt);
907}
908
909void USB2D_ISR(UINT intnum)
910{
911 UINT count;
912 UINT reg;
913 int left;
914 union dwc3_event event;
915
916 P_DC_Properties_T pDCProps = Get_DC_Properties(intnum);
917
918 //bogus input. caller screwed up. return
919 if (pDCProps == NULL) {
920 bbu_printf("%s:line:%d pDCProps = NULL\n\r", __func__, __LINE__);
921 return;
922 }
923 count = DWC3_REG_READ(DWC3_GEVNTCOUNT(0));
924 count &= DWC3_GEVNTCOUNT_MASK;
925 if (!count) {
926 return;
927 }
928
929 /* Mask interrupt */
930 reg = DWC3_REG_READ(DWC3_GEVNTSIZ(0));
931 reg |= DWC3_GEVNTSIZ_INTMASK;
932 DWC3_REG_WRITE(DWC3_GEVNTSIZ(0), reg);
933 bbu_printf("%s event count: %d, pos: %d\n\r", __func__, count, pDCProps->evt_pos);
934#if 0
935 amount = MIN(count, pDCProps->evt_length - pDCProps->evt_pos);
936 memcpy(pDCProps->event_buff_cache + pDCProps->evt_pos,
937 pDCProps->event_buff + pDCProps->evt_pos, amount);
938
939 if (amount < count)
940 memcpy(pDCProps->event_buff_cache, pDCProps->event_buff, count - amount);
941
942 DWC3_REG_WRITE(DWC3_GEVNTCOUNT(0), count);
943#endif
944
945 left = (int)count;
946 while (left > 0) {
947#if 0
948 event.raw = *(UINT *) (pDCProps->event_buff_cache + pDCProps->evt_pos);
949#endif
950 event.raw = *(UINT *) (pDCProps->event_buff + pDCProps->evt_pos);
951 bbu_printf("==>handle pos: %d event: 0x%x\n\r", pDCProps->evt_pos, event.raw);
952 DWC3_PROCESS_EVENT_ENTRY(pDCProps, &event);
953
954 pDCProps->evt_pos = (pDCProps->evt_pos + 4) % pDCProps->evt_length;
955 left -= 4;
956 }
957
958#if 1
959 //clear the event count
960 DWC3_REG_WRITE(DWC3_GEVNTCOUNT(0), count);
961#endif
962
963 bbu_printf("####last pos: %d\n\r", pDCProps->evt_pos);
964 /* Unmask interrupt */
965 reg = DWC3_REG_READ(DWC3_GEVNTSIZ(0));
966 reg &= ~DWC3_GEVNTSIZ_INTMASK;
967 DWC3_REG_WRITE(DWC3_GEVNTSIZ(0), reg);
968}
969
970
971void DWC3_Controller_Setup(P_DC_Properties_T pDCProps, int param)
972{
973 UINT regval, chipid = 0x1901;
974 int usb_speed_mode;
975 UINT32 timeout;
976
977 usb_speed_mode = get_usb_speed_mode();
978
979 //SOFT RESET CONTROLLER
980 regval = DWC3_REG_READ(DWC3_DCTL);
981 regval |= DWC3_DCTL_CSFTRST;
982 DWC3_REG_WRITE(DWC3_DCTL, regval);
983 //worst case: delay 200ms to align with code in linux
984 timeout = 50000;
985 do {
986 regval = DWC3_REG_READ(DWC3_DCTL);
987 if (!(regval & DWC3_DCTL_CSFTRST))
988 break;
989 Delay(4);
990 } while (--timeout);
991 //make sure 3 phy clk delay before accessing phy
992 Delay(5);
993 bbu_printf("%s: timeout: 0x%x\n\r", __func__, timeout);
994
995 //use mac2_clk as mac3_clk
996 regval = DWC3_REG_READ(DWC3_GUCTL1);
997 regval |= BIT(26);
998 //regval = 0x0104198a;
999 DWC3_REG_WRITE(DWC3_GUCTL1, regval);
1000
1001 //TODO: 16bits phy on FPGA, 8bits PHY for silicon chip
1002 //SET USB2PHYCFG0, use 8bits utim phy
1003 //on FPGA the chipid[26:24] is force to 0x1
1004 //FPGA-1, ZEBU-2, silicon-0
1005 chipid = BU_REG_READ(CIU_REG_CHIPID);
1006 if (((chipid >> 24) & 0x7) == 0x1)
1007 regval = (0x40002407|(1<<3));
1008 else
1009 regval = 0x40002407;
1010 DWC3_REG_WRITE(DWC3_GUSB2PHYCFG(0), regval);
1011
1012 //dwc3_core_setup_global_control
1013 //BIT[13:12]-10: SET AS DEVICE MODE
1014 regval = (1625<<19)|(0x2204);
1015 //regval = 0x32c92004;
1016 DWC3_REG_WRITE(DWC3_GCTL, regval);
1017
1018 //Program DCFG
1019 //bit0~2 0->HS 1->FS 4->SS
1020 //regval = 0x480804;//(regval & (~(0x3<<0))) | (0<<0); //SS mode
1021 regval = DWC3_REG_READ(DWC3_DCFG);
1022 if (usb_speed_mode == USB_MODE_FS)
1023 regval = 0x480801;//(regval & (~(0x3<<0))) | (0<<0); //FS mode
1024 else if (usb_speed_mode == USB_MODE_HS)
1025 regval = 0x480800;//(regval & (~(0x3<<0))) | (0<<0); //HS mode
1026 else
1027 regval = 0x480801;//(regval & (~(0x3<<0))) | (0<<0); //FS mode
1028 DWC3_REG_WRITE(DWC3_DCFG, regval);
1029
1030 //CONFIG EVENT BUFFERS
1031 pDCProps->evt_pos = 0;
1032 DWC3_REG_WRITE(DWC3_GEVNTADRLO(0), pDCProps->event_buff);
1033 DWC3_REG_WRITE(DWC3_GEVNTADRHI(0), 0x0);
1034 DWC3_REG_WRITE(DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_SIZE(pDCProps->evt_length));
1035 DWC3_REG_WRITE(DWC3_GEVNTCOUNT(0), 0);
1036 bbu_printf("event buffer: 0x%x\n\r", pDCProps->event_buff);
1037
1038 //bbu_printf("event buffer cache: 0x%x\n\r", pDCProps->event_buff_cache);
1039 //dwc3_gadget_enable_irq
1040 //#define DWC3_DEVTEN_WKUPEVTEN BIT(4)
1041 //#define DWC3_DEVTEN_ULSTCNGEN BIT(3)
1042 //#define DWC3_DEVTEN_CONNECTDONEEN BIT(2)
1043 //#define DWC3_DEVTEN_USBRSTEN BIT(1)
1044 //#define DWC3_DEVTEN_DISCONNEVTEN BIT(0)
1045 regval = DWC3_REG_READ(DWC3_DEVTEN);
1046 regval |= 0x1f;
1047 DWC3_REG_WRITE(DWC3_DEVTEN, regval);
1048
1049 return;
1050}
1051
1052
1053//Configures an endpoint
1054void USB2D_Endpoint_Setup(P_DC_Properties_T pDCProps, XLLP_USB_ENDPOINT_ID_T ep_num, XLLP_USB_EP_DIR_T direction, XLLP_USB_EP_TYPE_T type)
1055{
1056 UINT hw_ep_num, reg;
1057
1058 hw_ep_num = ep_num*2+direction;
1059
1060 //TODO: IS THERE ANY SEQUENCE ISSUE?
1061 if (hw_ep_num == 0) {
1062 DWC3_EP_START_CFG(pDCProps, hw_ep_num);
1063#if 1
1064 //only 4 eps are used in bootrom
1065 DWC3_EP_SET_XFER_RESOURCE(pDCProps, 0);
1066 DWC3_EP_SET_XFER_RESOURCE(pDCProps, 1);
1067 DWC3_EP_SET_XFER_RESOURCE(pDCProps, 2);
1068 DWC3_EP_SET_XFER_RESOURCE(pDCProps, 3);
1069#endif
1070 }
1071
1072 DWC3_EP_SET_CFG(pDCProps, hw_ep_num, 0);
1073
1074 reg = DWC3_REG_READ(DWC3_DALEPENA);
1075 reg |= DWC3_DALEPENA_EP(hw_ep_num);
1076 DWC3_REG_WRITE(DWC3_DALEPENA, reg);
1077}
1078
1079void USB2D_PM_Call(P_DC_Properties_T pDCProps)
1080{
1081 UINT bytes, buffer;
1082 P_USBAPI_T pUsbApi;
1083
1084 //grab info from the last RECEIVE operation
1085 pUsbApi = GetUSBAPIhandle_InterruptNum(pDCProps->InterruptNum);
1086 if (pUsbApi != NULL)
1087 {
1088 bytes = pDCProps->pdQHHead[USB_ENDPOINT_A*2].tot_size;
1089 buffer = pDCProps->pdQHHead[USB_ENDPOINT_A*2].buffer;
1090
1091 //call into Protocol Manager
1092 PM_ISR(pUsbApi, bytes, (UINT*)buffer);
1093 }
1094}
1095
1096void USB2D_SendWrapper(UINT *buffer, UINT size, void * pUSBAPI)
1097{
1098 P_DC_Properties_T pDCProps;
1099
1100 //get the correct structure
1101 pDCProps = Get_DC_Properties(((P_USBAPI_T)pUSBAPI)->interruptNum);
1102 if (pDCProps != NULL)
1103 {
1104#ifdef USB_ENABLE_DEBUG
1105 //usbsend_len_table[usbsend_len_ptr%NR_LOGGING_ARRAY] = size;
1106 //usbsend_len_ptr++;
1107 //usbsend_buff_table[usbsend_buff_ptr%NR_LOGGING_ARRAY] = buffer;
1108 //usbsend_buff_ptr++;
1109#endif
1110 //call the trasmit routine
1111 USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_A, USB_IN, (UINT)(buffer), size);
1112 }
1113 return;
1114}
1115
1116void USB2D_RecieveWrapper(UINT *buffer, UINT size, void * pUSBAPI)
1117{
1118 P_DC_Properties_T pDCProps;
1119
1120 //get the correct structure
1121 pDCProps = Get_DC_Properties(((P_USBAPI_T)pUSBAPI)->interruptNum);
1122 if (pDCProps != NULL)
1123 {
1124#ifdef USB_ENABLE_DEBUG
1125 usbrecv_len_table[usbrecv_len_ptr%NR_LOGGING_ARRAY] = size;
1126 usbrecv_len_ptr++;
1127 //usbrecv_buff_table[usbrecv_buff_ptr%NR_LOGGING_ARRAY] = buffer;
1128 //usbrecv_buff_ptr++;
1129#endif
1130 //round up the size to mutiples of 512 for hs mode, N *64 for FS mode
1131 //should be round up to mutiples of 1024 for usb3
1132 if (USB_MODE_FS == DWC3_GET_CONN_SPEED())
1133 size = (((size + 63) >> 6) << 6);
1134 else
1135 size = (((size + 511) >> 9) << 9);
1136 //call the trasmit routine
1137#ifdef USB_ENABLE_DEBUG
1138 //usbrecv_rdlen_table[usbrecv_rdlogging_ptr%NR_LOGGING_ARRAY] = size;
1139 //usbrecv_rdlogging_ptr++;
1140#endif
1141 USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_A, USB_OUT, (UINT)(buffer), size);
1142 }
1143 return;
1144}
1145
1146void USB2D_Endpoint0Transmit(P_DC_Properties_T pDCProps, XLLP_USB_ENDPOINT_ID_T ep_num, XLLP_USB_EP_DIR_T direction, UINT buffer, UINT size, UINT type)
1147{
1148 UINT qh_index, cmd;
1149 struct dwc3_trb * ptrb, *ptrb_first;
1150 struct dwc3_gadget_ep_cmd_params params;
1151 INT ret = 0;
1152
1153 //calculate which Queue Head to service
1154 qh_index = ep_num*2+direction;
1155
1156 //grab an initial trb
1157 ptrb_first = ptrb = get_trb_ep0();
1158
1159 //check for memory shortage
1160 if(ptrb == NULL) {
1161 bbu_printf("---%s: trb is NULL\n\r",__func__);
1162 return;
1163 }
1164#ifdef USB_ENABLE_DEBUG
1165 //usbtrb0_table[usbtrb0_logging_ptr%NR_LOGGING_ARRAY] = ptrb;
1166 //usbtrb0_logging_ptr++;
1167#endif
1168 bbu_printf("====%s: trb: 0x%x buffer: 0x%x size: 0x%x\n\r",__func__, ptrb, buffer, size);
1169 //save off info for software cleanup later on
1170 pDCProps->pdQHHead[qh_index].initial_trb = (UINT)(ptrb_first);
1171 pDCProps->pdQHHead[qh_index].buffer = (UINT)buffer;
1172 pDCProps->pdQHHead[qh_index].tot_size = size;
1173
1174 //parepare data trb
1175 ptrb->size = size;
1176 //USE the fixed buffer to OUT DATA
1177 if ((type == DWC3_TRBCTL_CONTROL_DATA) && (USB_OUT == direction))
1178 ptrb->bpl = pDCProps->ep0_out_buffer;
1179 else
1180 ptrb->bpl = buffer;
1181 ptrb->bph = 0x0;
1182 ptrb->ctrl = type;
1183
1184 //data phase
1185 if (type == DWC3_TRBCTL_CONTROL_DATA)
1186 pDCProps->ep0state = EP0_DATA_PHASE;
1187
1188 if ((type == DWC3_TRBCTL_CONTROL_STATUS3) ||
1189 type == DWC3_TRBCTL_CONTROL_STATUS2)
1190 pDCProps->ep0state = EP0_STATUS_PHASE;
1191
1192 /*
1193 * Enable ISP on OUT packet
1194 */
1195 ptrb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
1196 ptrb->ctrl |= DWC3_TRB_CTRL_IOC;
1197 ptrb->ctrl |= DWC3_TRB_CTRL_HWO;
1198 ptrb->ctrl |= DWC3_TRB_CTRL_LST;
1199
1200 //store the last trb pointer to allow us to monitor completion
1201 pDCProps->pdQHHead[qh_index].last_trb = (UINT)(ptrb);
1202
1203 //prepare cmd parameters
1204 params.param0 = 0x0;
1205 params.param1 = ptrb;
1206 params.param2 = 0x0;
1207 cmd = DWC3_DEPCMD_STARTTRANSFER |
1208 DWC3_DEPCMD_PARAM(0x0);
1209
1210 ret = DWC3_SEND_EP_CMD(pDCProps, cmd, &params, qh_index);
1211 pDCProps->ep0_next_event = DWC3_EP0_COMPLETE;
1212}
1213
1214void USB2D_EndpointTransmit(P_DC_Properties_T pDCProps, XLLP_USB_ENDPOINT_ID_T ep_num, XLLP_USB_EP_DIR_T direction, UINT buffer, UINT size)
1215{
1216 UINT qh_index, cmd;
1217 struct dwc3_trb * ptrb, *ptrb_first;
1218 struct dwc3_gadget_ep_cmd_params params;
1219 INT ret = 0;
1220
1221 //calculate which Queue Head to service
1222 qh_index = ep_num*2+direction;
1223
1224 //grab an initial trb
1225 ptrb_first = ptrb = get_trb();
1226
1227 //check for memory shortage
1228 if(ptrb == NULL) {
1229 return;
1230 }
1231#ifdef USB_ENABLE_DEBUG
1232 //usbtrb_table[usbtrb_logging_ptr%NR_LOGGING_ARRAY] = ptrb;
1233 //usbtrb_logging_ptr++;
1234#endif
1235 bbu_printf("===%s: trb: 0x%x buffer: 0x%x size: 0x%x\n\r",__func__, ptrb, buffer, size);
1236 //save off info for software cleanup later on
1237 pDCProps->pdQHHead[qh_index].initial_trb = (UINT)(ptrb_first);
1238 pDCProps->pdQHHead[qh_index].buffer = (UINT)buffer;
1239 pDCProps->pdQHHead[qh_index].tot_size = size;
1240
1241 //parepare data trb
1242 ptrb->size = size;
1243 ptrb->bpl = buffer;
1244
1245 ptrb->bph = 0x0;
1246 ptrb->ctrl = DWC3_TRBCTL_NORMAL;
1247 /*
1248 * Enable ISP on OUT packet
1249 */
1250 if (USB_OUT == direction) {
1251 ptrb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
1252 }
1253 ptrb->ctrl |= DWC3_TRB_CTRL_IOC;
1254 ptrb->ctrl |= DWC3_TRB_CTRL_HWO;
1255 ptrb->ctrl |= DWC3_TRB_CTRL_LST;
1256
1257 //store the last trb pointer to allow us to monitor completion
1258 pDCProps->pdQHHead[qh_index].last_trb = (UINT)(ptrb);
1259
1260 //prepare cmd parameters
1261 params.param0 = 0x0;
1262 params.param1 = ptrb;
1263 params.param2 = 0x0;
1264 cmd = DWC3_DEPCMD_STARTTRANSFER |
1265 DWC3_DEPCMD_PARAM(0x0);
1266
1267 ret = DWC3_SEND_EP_CMD(pDCProps, cmd, &params, qh_index);
1268}
1269
1270