1 /*
2 * Copyright (c) 2021-2024 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 /*
8 * Copyright (c) 2024, sakumisu
9 *
10 * SPDX-License-Identifier: Apache-2.0
11 */
12 #include "usbd_core.h"
13 #include "usb_chipidea_reg.h"
14
15 #define USB_OTG_DEV ((CHIPIDEA_TypeDef *)g_usbdev_bus[busid].reg_base)
16
17 #define CHIPIDEA_BITSMASK(val, offset) ((uint32_t)(val) << (offset))
18 #define QTD_COUNT_EACH_ENDPOINT (8U)
19
20 #ifndef CONFIG_USBDEV_EP_NUM
21 #define CONFIG_USBDEV_EP_NUM 8
22 #endif
23
24 /* ENDPTCTRL */
25 enum {
26 ENDPTCTRL_STALL = CHIPIDEA_BITSMASK(1, 0),
27 ENDPTCTRL_TYPE = CHIPIDEA_BITSMASK(3, 2),
28 ENDPTCTRL_TOGGLE_INHIBIT = CHIPIDEA_BITSMASK(1, 5),
29 ENDPTCTRL_TOGGLE_RESET = CHIPIDEA_BITSMASK(1, 6),
30 ENDPTCTRL_ENABLE = CHIPIDEA_BITSMASK(1, 7),
31 };
32
33 /* USBSTS, USBINTR */
34 enum {
35 intr_usb = CHIPIDEA_BITSMASK(1, 0),
36 intr_error = CHIPIDEA_BITSMASK(1, 1),
37 intr_port_change = CHIPIDEA_BITSMASK(1, 2),
38 intr_reset = CHIPIDEA_BITSMASK(1, 6),
39 intr_sof = CHIPIDEA_BITSMASK(1, 7),
40 intr_suspend = CHIPIDEA_BITSMASK(1, 8),
41 intr_nak = CHIPIDEA_BITSMASK(1, 16)
42 };
43
44 /* Queue Transfer Descriptor */
45 typedef struct {
46 /* Word 0: Next QTD Pointer */
47 volatile uint32_t next; /* Next link pointer This field contains the physical memory address of the next dTD to be processed */
48
49 /* Word 1: qTQ Token */
50 volatile uint32_t : 3;
51 volatile uint32_t xact_err : 1;
52 volatile uint32_t : 1;
53 volatile uint32_t buffer_err : 1;
54 volatile uint32_t halted : 1;
55 volatile uint32_t active : 1;
56 volatile uint32_t : 2;
57 volatile uint32_t iso_mult_override : 2; /* This field can be used for transmit ISOs to override the MULT field in the dQH. This field must be zero for all packet types that are not transmit-ISO. */
58 volatile uint32_t : 3;
59 volatile uint32_t int_on_complete : 1;
60 volatile uint32_t total_bytes : 15;
61 volatile uint32_t : 0;
62
63 /* Word 2-6: Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page */
64 volatile uint32_t buffer[5];
65
66 /*------------- DCD Area -------------*/
67 volatile uint16_t expected_bytes;
68 volatile uint8_t reserved[2];
69 } dcd_qtd_t;
70
71 /* Queue Head */
72 typedef struct {
73 /* Word 0: Capabilities and Characteristics */
74
75 volatile uint32_t : 15; /* Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed. */
76 volatile uint32_t int_on_setup : 1; /* Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received. */
77 volatile uint32_t max_packet_size : 11; /* This directly corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize) */
78 volatile uint32_t : 2;
79 volatile uint32_t zero_length_termination : 1; /* This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length. */
80 volatile uint32_t iso_mult : 2;
81 volatile uint32_t : 0;
82
83 /* Word 1: Current qTD Pointer */
84 volatile uint32_t qtd_addr;
85
86 /* Word 2-9: Transfer Overlay */
87 volatile dcd_qtd_t qtd_overlay;
88
89 /* Word 10-11: Setup request (control OUT only) */
90 volatile struct usb_setup_packet setup_request;
91
92 /*--------------------------------------------------------------------
93 * Due to the fact QHD is 64 bytes aligned but occupies only 48 bytes
94 * thus there are 16 bytes padding free that we can make use of.
95 *--------------------------------------------------------------------
96 */
97 volatile uint8_t reserved[16];
98 } dcd_qhd_t;
99
100 typedef struct {
101 dcd_qhd_t qhd[CONFIG_USBDEV_EP_NUM * 2];
102 dcd_qtd_t qtd[CONFIG_USBDEV_EP_NUM * 2 * QTD_COUNT_EACH_ENDPOINT];
103 } dcd_data_t;
104
105 /* Endpoint state */
106 struct chipidea_ep_state {
107 uint16_t ep_mps; /* Endpoint max packet size */
108 uint8_t ep_type; /* Endpoint type */
109 uint8_t ep_stalled; /* Endpoint stall flag */
110 uint8_t ep_enable; /* Endpoint enable */
111 uint8_t *xfer_buf;
112 uint32_t xfer_len;
113 uint32_t actual_xfer_len;
114 };
115
116 /* Driver state */
117 struct chipidea_udc {
118 dcd_data_t *dcd_data;
119 bool is_suspend;
120 struct chipidea_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
121 struct chipidea_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
122 } g_chipidea_udc[CONFIG_USBDEV_MAX_BUS];
123
124 static USB_NOCACHE_RAM_SECTION __attribute__((aligned(2048))) dcd_data_t _dcd_data0;
125 #if CONFIG_USBDEV_MAX_BUS == 2
126 static USB_NOCACHE_RAM_SECTION __attribute__((aligned(2048))) dcd_data_t _dcd_data1;
127 #endif
128
129 static dcd_data_t *g_dcd_data[CONFIG_USBDEV_MAX_BUS] = {
130 &_dcd_data0,
131 #if CONFIG_USBDEV_MAX_BUS == 2
132 &_dcd_data1
133 #endif
134 };
135
136 /* Index to bit position in register */
ep_idx2bit(uint8_t ep_idx)137 static inline uint8_t ep_idx2bit(uint8_t ep_idx)
138 {
139 return ep_idx / 2 + ((ep_idx % 2) ? 16 : 0);
140 }
141
__chipidea_bus_reset(CHIPIDEA_TypeDef * ptr)142 static void __chipidea_bus_reset(CHIPIDEA_TypeDef *ptr)
143 {
144 /* The reset value for all endpoint types is the control endpoint. If one endpoint
145 * direction is enabled and the paired endpoint of opposite direction is disabled, then the
146 * endpoint type of the unused direction must be changed from the control type to any other
147 * type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior
148 * for the data PID tracking on the active endpoint.
149 */
150
151 for (uint32_t i = 1; i < CONFIG_USBDEV_EP_NUM; i++) {
152 ptr->ENDPTCTRL[i] = USB_ENDPTCTRL_TXT_SET(USB_ENDPOINT_TYPE_BULK) | USB_ENDPTCTRL_RXT_SET(USB_ENDPOINT_TYPE_BULK);
153 }
154
155 /* Clear All Registers */
156 ptr->ENDPTNAK = ptr->ENDPTNAK;
157 ptr->ENDPTNAKEN = 0;
158 ptr->USBSTS = ptr->USBSTS;
159 ptr->ENDPTSETUPSTAT = ptr->ENDPTSETUPSTAT;
160 ptr->ENDPTCOMPLETE = ptr->ENDPTCOMPLETE;
161
162 while (ptr->ENDPTPRIME) {
163 }
164 ptr->ENDPTFLUSH = 0xFFFFFFFF;
165 while (ptr->ENDPTFLUSH) {
166 }
167 }
168
chipidea_init(CHIPIDEA_TypeDef * ptr)169 static void chipidea_init(CHIPIDEA_TypeDef *ptr)
170 {
171 /* Reset controller */
172 ptr->USBCMD |= USB_USBCMD_RST_MASK;
173 while (USB_USBCMD_RST_GET(ptr->USBCMD)) {
174 }
175
176 /* Set mode to device, must be set immediately after reset */
177 ptr->USBMODE &= ~USB_USBMODE_CM_MASK;
178 ptr->USBMODE |= USB_USBMODE_CM_SET(2);
179
180 /* Disable setup lockout, please refer to "Control Endpoint Operation" section in RM. */
181 ptr->USBMODE &= ~USB_USBMODE_SLOM_MASK;
182
183 /* Set the endian */
184 ptr->USBMODE &= ~USB_USBMODE_ES_MASK;
185
186 /* Set parallel interface signal */
187 ptr->PORTSC1 &= ~USB_PORTSC1_STS_MASK;
188
189 /* Set parallel transceiver width */
190 ptr->PORTSC1 &= ~USB_PORTSC1_PTW_MASK;
191
192 /* Set usb forced to full speed mode */
193 //ptr->PORTSC1 |= USB_PORTSC1_PFSC_MASK;
194
195 /* Not use interrupt threshold. */
196 ptr->USBCMD &= ~USB_USBCMD_ITC_MASK;
197
198 /* Enable VBUS discharge */
199 ptr->OTGSC |= USB_OTGSC_VD_MASK;
200 }
201
chipidea_deinit(CHIPIDEA_TypeDef * ptr)202 static void chipidea_deinit(CHIPIDEA_TypeDef *ptr)
203 {
204 /* Stop */
205 ptr->USBCMD &= ~USB_USBCMD_RS_MASK;
206
207 /* Reset controller */
208 ptr->USBCMD |= USB_USBCMD_RST_MASK;
209 while (USB_USBCMD_RST_GET(ptr->USBCMD)) {
210 }
211
212 /* Reset endpoint list address register */
213 ptr->ENDPTLISTADDR = 0;
214
215 /* Reset status register */
216 ptr->USBSTS = ptr->USBSTS;
217
218 /* Reset interrupt enable register */
219 ptr->USBINTR = 0;
220 }
221
222 /*---------------------------------------------------------------------
223 * Endpoint API
224 *---------------------------------------------------------------------
225 */
__chipidea_edpt_open(CHIPIDEA_TypeDef * ptr,uint8_t ep_addr,uint8_t ep_type)226 static void __chipidea_edpt_open(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr, uint8_t ep_type)
227 {
228 uint8_t const epnum = ep_addr & 0x0f;
229 uint8_t const dir = (ep_addr & 0x80) >> 7;
230
231 /* Enable EP Control */
232 uint32_t temp = ptr->ENDPTCTRL[epnum];
233 temp &= ~((0x03 << 2) << (dir ? 16 : 0));
234 temp |= ((ep_type << 2) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET) << (dir ? 16 : 0);
235 ptr->ENDPTCTRL[epnum] = temp;
236 }
237
chipidea_edpt_xfer(CHIPIDEA_TypeDef * ptr,uint8_t ep_idx)238 static void chipidea_edpt_xfer(CHIPIDEA_TypeDef *ptr, uint8_t ep_idx)
239 {
240 uint32_t offset = ep_idx / 2 + ((ep_idx % 2) ? 16 : 0);
241
242 /* Start transfer */
243 ptr->ENDPTPRIME = 1 << offset;
244 }
245
chipidea_edpt_stall(CHIPIDEA_TypeDef * ptr,uint8_t ep_addr)246 static void chipidea_edpt_stall(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr)
247 {
248 uint8_t const epnum = ep_addr & 0x0f;
249 uint8_t const dir = (ep_addr & 0x80) >> 7;
250
251 ptr->ENDPTCTRL[epnum] |= ENDPTCTRL_STALL << (dir ? 16 : 0);
252 }
253
chipidea_edpt_clear_stall(CHIPIDEA_TypeDef * ptr,uint8_t ep_addr)254 static void chipidea_edpt_clear_stall(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr)
255 {
256 uint8_t const epnum = ep_addr & 0x0f;
257 uint8_t const dir = (ep_addr & 0x80) >> 7;
258
259 /* data toggle also need to be reset */
260 ptr->ENDPTCTRL[epnum] |= ENDPTCTRL_TOGGLE_RESET << (dir ? 16 : 0);
261 ptr->ENDPTCTRL[epnum] &= ~(ENDPTCTRL_STALL << (dir ? 16 : 0));
262 }
263
chipidea_edpt_check_stall(CHIPIDEA_TypeDef * ptr,uint8_t ep_addr)264 static bool chipidea_edpt_check_stall(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr)
265 {
266 uint8_t const epnum = ep_addr & 0x0f;
267 uint8_t const dir = (ep_addr & 0x80) >> 7;
268
269 return (ptr->ENDPTCTRL[epnum] & (ENDPTCTRL_STALL << (dir ? 16 : 0))) ? true : false;
270 }
271
chipidea_edpt_close(CHIPIDEA_TypeDef * ptr,uint8_t ep_addr)272 static void chipidea_edpt_close(CHIPIDEA_TypeDef *ptr, uint8_t ep_addr)
273 {
274 uint8_t const epnum = ep_addr & 0x0f;
275 uint8_t const dir = (ep_addr & 0x80) >> 7;
276
277 uint32_t primebit = CHIPIDEA_BITSMASK(1, epnum) << (dir ? 16 : 0);
278
279 /* Flush the endpoint to stop a transfer. */
280 do {
281 /* Set the corresponding bit(s) in the ENDPTFLUSH register */
282 ptr->ENDPTFLUSH |= primebit;
283
284 /* Wait until all bits in the ENDPTFLUSH register are cleared. */
285 while (0U != (ptr->ENDPTFLUSH & primebit)) {
286 }
287 /*
288 * Read the ENDPTSTAT register to ensure that for all endpoints
289 * commanded to be flushed, that the corresponding bits
290 * are now cleared.
291 */
292 } while (0U != (ptr->ENDPTSTAT & primebit));
293
294 /* Disable the endpoint */
295 ptr->ENDPTCTRL[epnum] &= ~((ENDPTCTRL_TYPE | ENDPTCTRL_ENABLE | ENDPTCTRL_STALL) << (dir ? 16 : 0));
296 ptr->ENDPTCTRL[epnum] |= (USB_ENDPOINT_TYPE_BULK << 2) << (dir ? 16 : 0);
297 }
298
299 /* Initialize qtd */
usb_qtd_init(dcd_qtd_t * p_qtd,void * data_ptr,uint16_t total_bytes)300 static void usb_qtd_init(dcd_qtd_t *p_qtd, void *data_ptr, uint16_t total_bytes)
301 {
302 memset(p_qtd, 0, sizeof(dcd_qtd_t));
303
304 p_qtd->next = 1;
305 p_qtd->active = 1;
306 p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
307
308 if (data_ptr != NULL) {
309 p_qtd->buffer[0] = (uint32_t)data_ptr;
310 for (uint8_t i = 1; i < 5; i++) {
311 p_qtd->buffer[i] = ((p_qtd->buffer[i - 1]) & 0xFFFFF000UL) + 4096U;
312 }
313 }
314 }
315
chipidea_qhd_get(uint8_t busid,uint8_t ep_idx)316 static dcd_qhd_t *chipidea_qhd_get(uint8_t busid, uint8_t ep_idx)
317 {
318 dcd_data_t *dcd_data;
319
320 dcd_data = g_chipidea_udc[busid].dcd_data;
321 return &dcd_data->qhd[ep_idx];
322 }
323
chipidea_qtd_get(uint8_t busid,uint8_t ep_idx)324 static dcd_qtd_t *chipidea_qtd_get(uint8_t busid, uint8_t ep_idx)
325 {
326 dcd_data_t *dcd_data;
327
328 dcd_data = g_chipidea_udc[busid].dcd_data;
329 return &dcd_data->qtd[ep_idx * QTD_COUNT_EACH_ENDPOINT];
330 }
331
chipidea_bus_reset(uint8_t busid,uint16_t ep0_max_packet_size)332 static void chipidea_bus_reset(uint8_t busid, uint16_t ep0_max_packet_size)
333 {
334 dcd_data_t *dcd_data;
335
336 dcd_data = g_chipidea_udc[busid].dcd_data;
337 __chipidea_bus_reset(USB_OTG_DEV);
338
339 /* Queue Head & Queue TD */
340 memset(dcd_data, 0, sizeof(dcd_data_t));
341
342 /* Set up Control Endpoints (0 OUT, 1 IN) */
343 dcd_data->qhd[0].zero_length_termination = dcd_data->qhd[1].zero_length_termination = 1;
344 dcd_data->qhd[0].max_packet_size = dcd_data->qhd[1].max_packet_size = ep0_max_packet_size;
345 dcd_data->qhd[0].qtd_overlay.next = dcd_data->qhd[1].qtd_overlay.next = 1;
346
347 /* OUT only */
348 dcd_data->qhd[0].int_on_setup = 1;
349 }
350
chipidea_edpt_open(uint8_t busid,uint8_t ep_addr,uint8_t ep_type,uint16_t ep_mps)351 static void chipidea_edpt_open(uint8_t busid, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
352 {
353 uint8_t const epnum = ep_addr & 0x0f;
354 uint8_t const dir = (ep_addr & 0x80) >> 7;
355 uint8_t const ep_idx = 2 * epnum + dir;
356 dcd_data_t *dcd_data;
357 dcd_qhd_t *p_qhd;
358
359 /* Prepare Queue Head */
360 dcd_data = g_chipidea_udc[busid].dcd_data;
361 p_qhd = &dcd_data->qhd[ep_idx];
362 memset(p_qhd, 0, sizeof(dcd_qhd_t));
363
364 p_qhd->zero_length_termination = 1;
365 p_qhd->max_packet_size = ep_mps & 0x7FFu;
366 p_qhd->qtd_overlay.next = 1;
367 if (ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
368 p_qhd->iso_mult = ((ep_mps >> 11u) & 0x3u) + 1u;
369 }
370
371 __chipidea_edpt_open(USB_OTG_DEV, ep_addr, ep_type);
372 }
373
chipidea_start_xfer(uint8_t busid,uint8_t ep_addr,uint8_t * buffer,uint32_t total_bytes)374 static bool chipidea_start_xfer(uint8_t busid, uint8_t ep_addr, uint8_t *buffer, uint32_t total_bytes)
375 {
376 uint8_t const epnum = ep_addr & 0x0f;
377 uint8_t const dir = (ep_addr & 0x80) >> 7;
378 uint8_t const ep_idx = 2 * epnum + dir;
379 uint8_t qtd_num;
380 uint8_t i;
381 uint32_t xfer_len;
382 dcd_qhd_t *p_qhd;
383 dcd_qtd_t *p_qtd;
384 dcd_qtd_t *first_p_qtd = NULL;
385 dcd_qtd_t *prev_p_qtd = NULL;
386 dcd_data_t *dcd_data;
387
388 dcd_data = g_chipidea_udc[busid].dcd_data;
389
390 if (epnum == 0) {
391 /* follows UM Setup packet handling using setup lockout mechanism
392 * wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out
393 */
394 while (USB_OTG_DEV->ENDPTSETUPSTAT & CHIPIDEA_BITSMASK(1, 0)) {
395 }
396 }
397
398 qtd_num = (total_bytes + 0x3fff) / 0x4000;
399 if (qtd_num > QTD_COUNT_EACH_ENDPOINT) {
400 return false;
401 }
402
403 if (buffer != NULL) {
404 buffer = (uint8_t *)buffer;
405 }
406 p_qhd = &dcd_data->qhd[ep_idx];
407 i = 0;
408 do {
409 p_qtd = &dcd_data->qtd[ep_idx * QTD_COUNT_EACH_ENDPOINT + i];
410 i++;
411
412 if (total_bytes > 0x4000) {
413 xfer_len = 0x4000;
414 total_bytes -= 0x4000;
415 } else {
416 xfer_len = total_bytes;
417 total_bytes = 0;
418 }
419
420 usb_qtd_init(p_qtd, (void *)buffer, xfer_len);
421 if (total_bytes == 0) {
422 p_qtd->int_on_complete = true;
423 }
424 buffer += xfer_len;
425
426 if (prev_p_qtd) {
427 prev_p_qtd->next = (uint32_t)p_qtd;
428 } else {
429 first_p_qtd = p_qtd;
430 }
431 prev_p_qtd = p_qtd;
432 } while (total_bytes > 0);
433
434 p_qhd->qtd_overlay.next = (uint32_t)first_p_qtd; /* link qtd to qhd */
435
436 chipidea_edpt_xfer(USB_OTG_DEV, ep_idx);
437
438 return true;
439 }
440
usb_dc_low_level_init(uint8_t busid)441 __WEAK void usb_dc_low_level_init(uint8_t busid)
442 {
443 }
444
usb_dc_low_level_deinit(uint8_t busid)445 __WEAK void usb_dc_low_level_deinit(uint8_t busid)
446 {
447 }
448
usb_dc_init(uint8_t busid)449 int usb_dc_init(uint8_t busid)
450 {
451 uint32_t int_mask;
452 int_mask = (USB_USBINTR_UE_MASK | USB_USBINTR_UEE_MASK | USB_USBINTR_SLE_MASK |
453 USB_USBINTR_PCE_MASK | USB_USBINTR_URE_MASK);
454
455 usb_dc_low_level_init(busid);
456
457 memset(&g_chipidea_udc[busid], 0, sizeof(struct chipidea_udc));
458 g_chipidea_udc[busid].dcd_data = g_dcd_data[busid];
459 memset(g_chipidea_udc[busid].dcd_data, 0, sizeof(dcd_data_t));
460
461 chipidea_init(USB_OTG_DEV);
462
463 /* Set endpoint list address */
464 USB_OTG_DEV->ENDPTLISTADDR = ((uint32_t)g_chipidea_udc[busid].dcd_data->qhd) & USB_ENDPTLISTADDR_EPBASE_MASK;
465
466 /* Clear status */
467 USB_OTG_DEV->USBSTS = USB_OTG_DEV->USBSTS;
468
469 #ifdef CONFIG_USBDEV_SOF_ENABLE
470 int_mask |= USB_USBINTR_SRE_MASK;
471 #endif
472
473 /* Enable interrupt mask */
474 USB_OTG_DEV->USBINTR |= int_mask;
475
476 /* Connect by enabling internal pull-up resistor on D+/D- */
477 USB_OTG_DEV->USBCMD |= USB_USBCMD_RS_MASK;
478 return 0;
479 }
480
usb_dc_deinit(uint8_t busid)481 int usb_dc_deinit(uint8_t busid)
482 {
483 chipidea_deinit(USB_OTG_DEV);
484
485 for (uint32_t i = 0; i < CONFIG_USBDEV_EP_NUM; i++) {
486 chipidea_edpt_close(USB_OTG_DEV, (i | 0x80));
487 chipidea_edpt_close(USB_OTG_DEV, (i | 0x00));
488 }
489
490 usb_dc_low_level_deinit(busid);
491 return 0;
492 }
493
usbd_set_address(uint8_t busid,const uint8_t addr)494 int usbd_set_address(uint8_t busid, const uint8_t addr)
495 {
496 USB_OTG_DEV->DEVICEADDR = USB_DEVICEADDR_USBADR_SET(addr) | USB_DEVICEADDR_USBADRA_MASK;
497 return 0;
498 }
499
usbd_set_remote_wakeup(uint8_t busid)500 int usbd_set_remote_wakeup(uint8_t busid)
501 {
502 if (!USB_PORTSC1_SUSP_GET(USB_OTG_DEV->PORTSC1)) {
503 return -1;
504 }
505
506 USB_OTG_DEV->PORTSC1 |= USB_PORTSC1_FPR_MASK;
507 while (USB_OTG_DEV->PORTSC1 & USB_PORTSC1_FPR_MASK) {
508 }
509
510 return 0;
511 }
512
usbd_get_port_speed(uint8_t busid)513 uint8_t usbd_get_port_speed(uint8_t busid)
514 {
515 uint8_t speed;
516
517 speed = USB_PORTSC1_PSPD_GET(USB_OTG_DEV->PORTSC1);
518
519 if (speed == 0x00) {
520 return USB_SPEED_FULL;
521 }
522 if (speed == 0x01) {
523 return USB_SPEED_LOW;
524 }
525 if (speed == 0x02) {
526 return USB_SPEED_HIGH;
527 }
528
529 return 0;
530 }
531
usbd_ep_open(uint8_t busid,const struct usb_endpoint_descriptor * ep)532 int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
533 {
534 uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
535
536 USB_ASSERT_MSG(ep_idx < CONFIG_USBDEV_EP_NUM, "Ep addr %02x overflow", ep->bEndpointAddress);
537
538 chipidea_edpt_open(busid, ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), ep->wMaxPacketSize);
539
540 if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
541 g_chipidea_udc[busid].out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
542 g_chipidea_udc[busid].out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
543 g_chipidea_udc[busid].out_ep[ep_idx].ep_enable = true;
544 } else {
545 g_chipidea_udc[busid].in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
546 g_chipidea_udc[busid].in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
547 g_chipidea_udc[busid].in_ep[ep_idx].ep_enable = true;
548 }
549
550 return 0;
551 }
552
usbd_ep_close(uint8_t busid,const uint8_t ep)553 int usbd_ep_close(uint8_t busid, const uint8_t ep)
554 {
555 uint8_t ep_idx = USB_EP_GET_IDX(ep);
556
557 if (USB_EP_DIR_IS_OUT(ep)) {
558 g_chipidea_udc[busid].out_ep[ep_idx].ep_enable = false;
559 } else {
560 g_chipidea_udc[busid].in_ep[ep_idx].ep_enable = false;
561 }
562
563 chipidea_edpt_close(USB_OTG_DEV, ep);
564
565 return 0;
566 }
567
usbd_ep_set_stall(uint8_t busid,const uint8_t ep)568 int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
569 {
570 chipidea_edpt_stall(USB_OTG_DEV, ep);
571 return 0;
572 }
573
usbd_ep_clear_stall(uint8_t busid,const uint8_t ep)574 int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
575 {
576 chipidea_edpt_clear_stall(USB_OTG_DEV, ep);
577 return 0;
578 }
579
usbd_ep_is_stalled(uint8_t busid,const uint8_t ep,uint8_t * stalled)580 int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
581 {
582 *stalled = chipidea_edpt_check_stall(USB_OTG_DEV, ep);
583 return 0;
584 }
585
usbd_ep_start_write(uint8_t busid,const uint8_t ep,const uint8_t * data,uint32_t data_len)586 int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
587 {
588 uint8_t ep_idx = USB_EP_GET_IDX(ep);
589
590 if (!data && data_len) {
591 return -1;
592 }
593 if (!g_chipidea_udc[busid].in_ep[ep_idx].ep_enable) {
594 return -2;
595 }
596
597 g_chipidea_udc[busid].in_ep[ep_idx].xfer_buf = (uint8_t *)data;
598 g_chipidea_udc[busid].in_ep[ep_idx].xfer_len = data_len;
599 g_chipidea_udc[busid].in_ep[ep_idx].actual_xfer_len = 0;
600
601 chipidea_start_xfer(busid, ep, (uint8_t *)data, data_len);
602
603 return 0;
604 }
605
usbd_ep_start_read(uint8_t busid,const uint8_t ep,uint8_t * data,uint32_t data_len)606 int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
607 {
608 uint8_t ep_idx = USB_EP_GET_IDX(ep);
609
610 if (!data && data_len) {
611 return -1;
612 }
613 if (!g_chipidea_udc[busid].out_ep[ep_idx].ep_enable) {
614 return -2;
615 }
616
617 g_chipidea_udc[busid].out_ep[ep_idx].xfer_buf = (uint8_t *)data;
618 g_chipidea_udc[busid].out_ep[ep_idx].xfer_len = data_len;
619 g_chipidea_udc[busid].out_ep[ep_idx].actual_xfer_len = 0;
620
621 chipidea_start_xfer(busid, ep, data, data_len);
622
623 return 0;
624 }
625
USBD_IRQHandler(uint8_t busid)626 void USBD_IRQHandler(uint8_t busid)
627 {
628 uint32_t int_status;
629 uint32_t transfer_len;
630 bool ep_cb_req;
631
632 /* Acknowledge handled interrupt */
633 int_status = USB_OTG_DEV->USBSTS;
634 int_status &= USB_OTG_DEV->USBINTR;
635 USB_OTG_DEV->USBSTS = int_status;
636
637 if (int_status & intr_error) {
638 USB_LOG_ERR("usbd intr error!\r\n");
639 }
640
641 #ifdef CONFIG_USBDEV_SOF_ENABLE
642 if (int_status & intr_sof) {
643 usbd_event_sof_handler(busid);
644 }
645 #endif
646
647 if (int_status & intr_reset) {
648 g_chipidea_udc[busid].is_suspend = false;
649 memset(g_chipidea_udc[busid].in_ep, 0, sizeof(struct chipidea_ep_state) * CONFIG_USBDEV_EP_NUM);
650 memset(g_chipidea_udc[busid].out_ep, 0, sizeof(struct chipidea_ep_state) * CONFIG_USBDEV_EP_NUM);
651 usbd_event_reset_handler(busid);
652 chipidea_bus_reset(busid, 64);
653 }
654
655 if (int_status & intr_suspend) {
656 if (USB_PORTSC1_SUSP_GET(USB_OTG_DEV->PORTSC1)) {
657 /* Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. */
658 if (USB_DEVICEADDR_USBADR_GET(USB_OTG_DEV->DEVICEADDR)) {
659 g_chipidea_udc[busid].is_suspend = true;
660 usbd_event_suspend_handler(busid);
661 }
662 } else {
663 }
664 }
665
666 if (int_status & intr_port_change) {
667 if (!USB_PORTSC1_CCS_GET(USB_OTG_DEV->PORTSC1)) {
668 usbd_event_disconnect_handler(busid);
669 } else {
670 if (g_chipidea_udc[busid].is_suspend) {
671 g_chipidea_udc[busid].is_suspend = false;
672 usbd_event_resume_handler(busid);
673 }
674 usbd_event_connect_handler(busid);
675 }
676 }
677
678 if (int_status & intr_usb) {
679 uint32_t const edpt_complete = USB_OTG_DEV->ENDPTCOMPLETE;
680 uint32_t edpt_setup_status = USB_OTG_DEV->ENDPTSETUPSTAT;
681
682 if (edpt_complete) {
683 USB_OTG_DEV->ENDPTCOMPLETE = edpt_complete;
684 for (uint8_t ep_idx = 0; ep_idx < (CONFIG_USBDEV_EP_NUM * 2); ep_idx++) {
685 if (edpt_complete & (1 << ep_idx2bit(ep_idx))) {
686 transfer_len = 0;
687 ep_cb_req = true;
688
689 /* Failed QTD also get ENDPTCOMPLETE set */
690 dcd_qtd_t *p_qtd = chipidea_qtd_get(busid, ep_idx);
691 while (1) {
692 if (p_qtd->halted || p_qtd->xact_err || p_qtd->buffer_err) {
693 USB_LOG_ERR("usbd transfer error!\r\n");
694 ep_cb_req = false;
695 break;
696 } else if (p_qtd->active) {
697 ep_cb_req = false;
698 break;
699 } else {
700 transfer_len += p_qtd->expected_bytes - p_qtd->total_bytes;
701 }
702
703 if (p_qtd->next == 1) {
704 break;
705 } else {
706 p_qtd = (dcd_qtd_t *)p_qtd->next;
707 }
708 }
709
710 if (ep_cb_req) {
711 uint8_t const ep_addr = (ep_idx / 2) | ((ep_idx & 0x01) ? 0x80 : 0);
712 if (ep_addr & 0x80) {
713 usbd_event_ep_in_complete_handler(busid, ep_addr, transfer_len);
714 } else {
715 usbd_event_ep_out_complete_handler(busid, ep_addr, transfer_len);
716 }
717 }
718 }
719 }
720 }
721
722 if (edpt_setup_status) {
723 /*------------- Set up Received -------------*/
724 USB_OTG_DEV->ENDPTSETUPSTAT = edpt_setup_status;
725 dcd_qhd_t *qhd0 = chipidea_qhd_get(busid, 0);
726 usbd_event_ep0_setup_complete_handler(busid, (uint8_t *)&qhd0->setup_request);
727 }
728 }
729 }