1 /*
2 * Copyright (c) 2022, sakumisu
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "usb_ehci_priv.h"
7
8 #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
9 #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */
10 #define EHCI_TUNE_RL_TT 0
11 #define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
12 #define EHCI_TUNE_MULT_TT 1
13
14 struct ehci_hcd g_ehci_hcd;
15
16 USB_NOCACHE_RAM_SECTION struct ehci_qh_hw ehci_qh_pool[CONFIG_USB_EHCI_QH_NUM];
17 USB_NOCACHE_RAM_SECTION struct ehci_qtd_hw ehci_qtd_pool[CONFIG_USB_EHCI_QTD_NUM];
18
19 /* The head of the asynchronous queue */
20 USB_NOCACHE_RAM_SECTION struct ehci_qh_hw g_async_qh_head;
21 /* The head of the periodic queue */
22 USB_NOCACHE_RAM_SECTION struct ehci_qh_hw g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM];
23
24 /* The frame list */
25 USB_NOCACHE_RAM_SECTION uint32_t g_framelist[CONFIG_USB_EHCI_FRAME_LIST_SIZE] __attribute__((aligned(4096)));
26
ehci_qh_alloc(void)27 static struct ehci_qh_hw *ehci_qh_alloc(void)
28 {
29 struct ehci_qh_hw *qh;
30 size_t flags;
31
32 for (uint32_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) {
33 if (!g_ehci_hcd.ehci_qh_used[i]) {
34 flags = usb_osal_enter_critical_section();
35 g_ehci_hcd.ehci_qh_used[i] = true;
36 usb_osal_leave_critical_section(flags);
37
38 qh = &ehci_qh_pool[i];
39 memset(qh, 0, sizeof(struct ehci_qh_hw));
40 qh->hw.hlp = QTD_LIST_END;
41 qh->hw.overlay.next_qtd = QTD_LIST_END;
42 qh->hw.overlay.alt_next_qtd = QTD_LIST_END;
43 return qh;
44 }
45 }
46 return NULL;
47 }
48
ehci_qh_free(struct ehci_qh_hw * qh)49 static void ehci_qh_free(struct ehci_qh_hw *qh)
50 {
51 size_t flags;
52
53 for (uint32_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) {
54 if (&ehci_qh_pool[i] == qh) {
55 flags = usb_osal_enter_critical_section();
56 g_ehci_hcd.ehci_qh_used[i] = false;
57 usb_osal_leave_critical_section(flags);
58
59 qh->urb = NULL;
60 return;
61 }
62 }
63 }
64
ehci_qtd_alloc(void)65 static struct ehci_qtd_hw *ehci_qtd_alloc(void)
66 {
67 struct ehci_qtd_hw *qtd;
68 size_t flags;
69
70 for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
71 if (!g_ehci_hcd.ehci_qtd_used[i]) {
72 flags = usb_osal_enter_critical_section();
73 g_ehci_hcd.ehci_qtd_used[i] = true;
74 usb_osal_leave_critical_section(flags);
75
76 qtd = &ehci_qtd_pool[i];
77 memset(qtd, 0, sizeof(struct ehci_qtd_hw));
78 qtd->hw.next_qtd = QTD_LIST_END;
79 qtd->hw.alt_next_qtd = QTD_LIST_END;
80 qtd->hw.token = QTD_TOKEN_STATUS_HALTED;
81 return qtd;
82 }
83 }
84 return NULL;
85 }
86
ehci_qtd_free(struct ehci_qtd_hw * qtd)87 static void ehci_qtd_free(struct ehci_qtd_hw *qtd)
88 {
89 size_t flags;
90
91 for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
92 if (&ehci_qtd_pool[i] == qtd) {
93 flags = usb_osal_enter_critical_section();
94 g_ehci_hcd.ehci_qtd_used[i] = false;
95 usb_osal_leave_critical_section(flags);
96
97 qtd->urb = NULL;
98 return;
99 }
100 }
101 }
102
ehci_pipe_alloc(void)103 static struct ehci_pipe *ehci_pipe_alloc(void)
104 {
105 int pipe;
106
107 for (pipe = 0; pipe < CONFIG_USB_EHCI_QH_NUM; pipe++) {
108 if (!g_ehci_hcd.pipe_pool[pipe].inuse) {
109 g_ehci_hcd.pipe_pool[pipe].inuse = true;
110 return &g_ehci_hcd.pipe_pool[pipe];
111 }
112 }
113 return NULL;
114 }
115
ehci_pipe_free(struct ehci_pipe * pipe)116 static void ehci_pipe_free(struct ehci_pipe *pipe)
117 {
118 pipe->inuse = false;
119 }
120
ehci_qh_add_head(struct ehci_qh_hw * head,struct ehci_qh_hw * n)121 static inline void ehci_qh_add_head(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
122 {
123 n->hw.hlp = head->hw.hlp;
124 head->hw.hlp = QH_HLP_QH(n);
125 }
126
ehci_qh_remove(struct ehci_qh_hw * head,struct ehci_qh_hw * n)127 static inline void ehci_qh_remove(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
128 {
129 struct ehci_qh_hw *tmp = head;
130
131 while (EHCI_ADDR2QH(tmp->hw.hlp) && EHCI_ADDR2QH(tmp->hw.hlp) != n) {
132 tmp = EHCI_ADDR2QH(tmp->hw.hlp);
133 }
134
135 if (tmp) {
136 tmp->hw.hlp = n->hw.hlp;
137 }
138 }
139
ehci_caculate_smask(int binterval)140 static int ehci_caculate_smask(int binterval)
141 {
142 int order, interval;
143
144 interval = 1;
145 while (binterval > 1) {
146 interval *= 2;
147 binterval--;
148 }
149
150 if (interval < 2) /* interval 1 */
151 return 0xFF;
152 if (interval < 4) /* interval 2 */
153 return 0x55;
154 if (interval < 8) /* interval 4 */
155 return 0x22;
156 for (order = 0; (interval > 1); order++) {
157 interval >>= 1;
158 }
159 return (0x1 << (order % 8));
160 }
161
ehci_get_periodic_qhead(uint8_t interval)162 static struct ehci_qh_hw *ehci_get_periodic_qhead(uint8_t interval)
163 {
164 interval /= 8;
165
166 for (uint8_t i = 0; i < EHCI_PERIOIDIC_QH_NUM - 1; i++) {
167 interval >>= 1;
168 if (interval == 0) {
169 return &g_periodic_qh_head[i];
170 }
171 }
172 return &g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1];
173 }
174
ehci_qh_fill(struct ehci_qh_hw * qh,uint8_t dev_addr,uint8_t ep_addr,uint8_t ep_type,uint16_t ep_mps,uint8_t ep_mult,uint8_t ep_interval,uint8_t speed,uint8_t hubaddr,uint8_t hubport)175 static void ehci_qh_fill(struct ehci_qh_hw *qh,
176 uint8_t dev_addr,
177 uint8_t ep_addr,
178 uint8_t ep_type,
179 uint16_t ep_mps,
180 uint8_t ep_mult,
181 uint8_t ep_interval,
182 uint8_t speed,
183 uint8_t hubaddr,
184 uint8_t hubport)
185 {
186 uint32_t epchar = 0;
187 uint32_t epcap = 0;
188
189 /* QH endpoint characteristics:
190 *
191 * FIELD DESCRIPTION
192 * -------- -------------------------------
193 * DEVADDR Device address
194 * I Inactivate on Next Transaction
195 * ENDPT Endpoint number
196 * EPS Endpoint speed
197 * DTC Data toggle control
198 * MAXPKT Max packet size
199 * C Control endpoint
200 * RL NAK count reloaded
201 */
202
203 /* QH endpoint capabilities
204 *
205 * FIELD DESCRIPTION
206 * -------- -------------------------------
207 * SSMASK Interrupt Schedule Mask
208 * SCMASK Split Completion Mask
209 * HUBADDR Hub Address
210 * PORT Port number
211 * MULT High band width multiplier
212 */
213
214 epchar |= ((ep_addr & 0xf) << QH_EPCHAR_ENDPT_SHIFT);
215 epchar |= (dev_addr << QH_EPCHAR_DEVADDR_SHIFT);
216 epchar |= (ep_mps << QH_EPCHAR_MAXPKT_SHIFT);
217
218 if (ep_type == USB_ENDPOINT_TYPE_CONTROL) {
219 epchar |= QH_EPCHAR_DTC; /* toggle from qtd */
220 }
221
222 switch (speed) {
223 case USB_SPEED_LOW:
224 epchar |= QH_EPCHAR_EPS_LOW;
225 case USB_SPEED_FULL:
226 if (ep_type == USB_ENDPOINT_TYPE_CONTROL) {
227 epchar |= QH_EPCHAR_C; /* for TT */
228 }
229
230 if (ep_type != USB_ENDPOINT_TYPE_INTERRUPT) {
231 epchar |= (EHCI_TUNE_RL_TT << QH_EPCHAR_RL_SHIFT);
232 }
233
234 epcap |= QH_EPCAPS_MULT(EHCI_TUNE_MULT_TT);
235
236 epcap |= QH_EPCAPS_HUBADDR(hubaddr);
237 epcap |= QH_EPCAPS_PORT(hubport);
238
239 if (ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
240 epcap |= QH_EPCAPS_SSMASK(2);
241 epcap |= QH_EPCAPS_SCMASK(0x78);
242 }
243
244 break;
245 case USB_SPEED_HIGH:
246 epchar |= QH_EPCHAR_EPS_HIGH;
247 if (ep_type == USB_ENDPOINT_TYPE_CONTROL) {
248 epchar |= (EHCI_TUNE_RL_HS << QH_EPCHAR_RL_SHIFT);
249
250 epcap |= QH_EPCAPS_MULT(EHCI_TUNE_MULT_HS);
251 } else if (ep_type == USB_ENDPOINT_TYPE_BULK) {
252 epcap |= QH_EPCAPS_MULT(EHCI_TUNE_MULT_HS);
253 } else {
254 /* only for interrupt ep */
255 epcap |= QH_EPCAPS_MULT(ep_mult);
256 epcap |= ehci_caculate_smask(ep_interval);
257 }
258 break;
259
260 default:
261 break;
262 }
263
264 qh->hw.epchar = epchar;
265 qh->hw.epcap = epcap;
266 }
267
ehci_qtd_bpl_fill(struct ehci_qtd_hw * qtd,uint32_t bufaddr,size_t buflen)268 static void ehci_qtd_bpl_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t buflen)
269 {
270 uint32_t rest;
271
272 qtd->hw.bpl[0] = bufaddr;
273 rest = 0x1000 - (bufaddr & 0xfff);
274
275 if (buflen < rest) {
276 rest = buflen;
277 } else {
278 bufaddr += 0x1000;
279 bufaddr &= ~0x0fff;
280
281 for (int i = 1; rest < buflen && i < 5; i++) {
282 qtd->hw.bpl[i] = bufaddr;
283 bufaddr += 0x1000;
284
285 if ((rest + 0x1000) < buflen) {
286 rest += 0x1000;
287 } else {
288 rest = buflen;
289 }
290 }
291 }
292 }
293
ehci_qtd_fill(struct ehci_qtd_hw * qtd,uint32_t bufaddr,size_t buflen,uint32_t token)294 static void ehci_qtd_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t buflen, uint32_t token)
295 {
296 /* qTD token
297 *
298 * FIELD DESCRIPTION
299 * -------- -------------------------------
300 * STATUS Status
301 * PID PID Code
302 * CERR Error Counter
303 * CPAGE Current Page
304 * IOC Interrupt on complete
305 * NBYTES Total Bytes to Transfer
306 * TOGGLE Data Toggle
307 */
308
309 qtd->hw.token = token;
310
311 ehci_qtd_bpl_fill(qtd, bufaddr, buflen);
312 qtd->total_len = buflen;
313 }
314
ehci_control_pipe_init(struct ehci_pipe * pipe,struct usb_setup_packet * setup,uint8_t * buffer,uint32_t buflen)315 static struct ehci_qh_hw *ehci_control_pipe_init(struct ehci_pipe *pipe, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
316 {
317 struct ehci_qh_hw *qh = NULL;
318 struct ehci_qtd_hw *qtd_setup = NULL;
319 struct ehci_qtd_hw *qtd_data = NULL;
320 struct ehci_qtd_hw *qtd_status = NULL;
321 uint32_t token;
322 size_t flags;
323
324 qh = ehci_qh_alloc();
325 if (qh == NULL) {
326 return NULL;
327 }
328
329 qtd_setup = ehci_qtd_alloc();
330 if (buflen > 0) {
331 qtd_data = ehci_qtd_alloc();
332 }
333
334 qtd_status = ehci_qtd_alloc();
335 if (qtd_status == NULL) {
336 ehci_qh_free(qh);
337 if (qtd_setup) {
338 ehci_qtd_free(qtd_setup);
339 }
340 if (qtd_data) {
341 ehci_qtd_free(qtd_data);
342 }
343 return NULL;
344 }
345
346 ehci_qh_fill(qh,
347 pipe->dev_addr,
348 pipe->ep_addr,
349 pipe->ep_type,
350 pipe->ep_mps,
351 0,
352 pipe->ep_interval,
353 pipe->hport->speed,
354 pipe->hport->parent->hub_addr,
355 pipe->hport->port);
356
357 /* fill setup qtd */
358 token = QTD_TOKEN_STATUS_ACTIVE |
359 QTD_TOKEN_PID_SETUP |
360 ((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
361 ((uint32_t)8 << QTD_TOKEN_NBYTES_SHIFT);
362
363 ehci_qtd_fill(qtd_setup, (uintptr_t)setup, 8, token);
364 qtd_setup->urb = pipe->urb;
365
366 /* fill data qtd */
367 if (setup->wLength > 0) {
368 if ((setup->bmRequestType & 0x80) == 0x80) {
369 token = QTD_TOKEN_PID_IN;
370 } else {
371 token = QTD_TOKEN_PID_OUT;
372 }
373 token |= QTD_TOKEN_STATUS_ACTIVE |
374 QTD_TOKEN_PID_OUT |
375 QTD_TOKEN_TOGGLE |
376 ((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
377 ((uint32_t)buflen << QTD_TOKEN_NBYTES_SHIFT);
378
379 ehci_qtd_fill(qtd_data, (uintptr_t)buffer, buflen, token);
380 qtd_data->urb = pipe->urb;
381 qtd_setup->hw.next_qtd = EHCI_PTR2ADDR(qtd_data);
382 qtd_data->hw.next_qtd = EHCI_PTR2ADDR(qtd_status);
383 } else {
384 qtd_setup->hw.next_qtd = EHCI_PTR2ADDR(qtd_status);
385 }
386
387 /* fill status qtd */
388 if ((setup->bmRequestType & 0x80) == 0x80) {
389 token = QTD_TOKEN_PID_OUT;
390 } else {
391 token = QTD_TOKEN_PID_IN;
392 }
393 token |= QTD_TOKEN_STATUS_ACTIVE |
394 QTD_TOKEN_TOGGLE |
395 QTD_TOKEN_IOC |
396 ((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
397 ((uint32_t)0 << QTD_TOKEN_NBYTES_SHIFT);
398
399 ehci_qtd_fill(qtd_status, 0, 0, token);
400 qtd_status->urb = pipe->urb;
401 qtd_status->hw.next_qtd = QTD_LIST_END;
402
403 /* update qh first qtd */
404 qh->hw.curr_qtd = EHCI_PTR2ADDR(qtd_setup);
405 qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(qtd_setup);
406
407 /* record qh first qtd */
408 qh->first_qtd = EHCI_PTR2ADDR(qtd_setup);
409
410 flags = usb_osal_enter_critical_section();
411
412 qh->urb = pipe->urb;
413 /* add qh into async list */
414 ehci_qh_add_head(&g_async_qh_head, qh);
415
416 EHCI_HCOR->usbcmd |= EHCI_USBCMD_ASEN;
417
418 usb_osal_leave_critical_section(flags);
419 return qh;
420 }
421
ehci_bulk_pipe_init(struct ehci_pipe * pipe,uint8_t * buffer,uint32_t buflen)422 static struct ehci_qh_hw *ehci_bulk_pipe_init(struct ehci_pipe *pipe, uint8_t *buffer, uint32_t buflen)
423 {
424 struct ehci_qh_hw *qh = NULL;
425 struct ehci_qtd_hw *qtd = NULL;
426 struct ehci_qtd_hw *first_qtd = NULL;
427 struct ehci_qtd_hw *prev_qtd = NULL;
428 uint32_t qtd_num = 0;
429 uint32_t xfer_len = 0;
430 uint32_t token;
431 size_t flags;
432
433 qh = ehci_qh_alloc();
434 if (qh == NULL) {
435 return NULL;
436 }
437
438 for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
439 if (!g_ehci_hcd.ehci_qtd_used[i]) {
440 qtd_num++;
441 }
442 }
443
444 if (qtd_num < ((buflen + 0x3fff) / 0x4000)) {
445 ehci_qh_free(qh);
446 return NULL;
447 }
448
449 ehci_qh_fill(qh,
450 pipe->dev_addr,
451 pipe->ep_addr,
452 pipe->ep_type,
453 pipe->ep_mps,
454 0,
455 pipe->ep_interval,
456 pipe->hport->speed,
457 pipe->hport->parent->hub_addr,
458 pipe->hport->port);
459
460 while (buflen >= 0) {
461 qtd = ehci_qtd_alloc();
462
463 if (buflen > 0x4000) {
464 xfer_len = 0x4000;
465 buflen -= 0x4000;
466 } else {
467 xfer_len = buflen;
468 buflen = 0;
469 }
470
471 if (pipe->ep_addr & 0x80) {
472 token = QTD_TOKEN_PID_IN;
473 } else {
474 token = QTD_TOKEN_PID_OUT;
475 }
476
477 token |= QTD_TOKEN_STATUS_ACTIVE |
478 ((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
479 ((uint32_t)xfer_len << QTD_TOKEN_NBYTES_SHIFT);
480
481 if (buflen == 0) {
482 token |= QTD_TOKEN_IOC;
483 }
484
485 ehci_qtd_fill(qtd, (uintptr_t)buffer, xfer_len, token);
486 qtd->urb = pipe->urb;
487 qtd->hw.next_qtd = QTD_LIST_END;
488 buffer += xfer_len;
489
490 if (prev_qtd) {
491 prev_qtd->hw.next_qtd = EHCI_PTR2ADDR(qtd);
492 } else {
493 first_qtd = qtd;
494 }
495 prev_qtd = qtd;
496
497 if (buflen == 0) {
498 break;
499 }
500 }
501
502 /* update qh first qtd */
503 qh->hw.curr_qtd = EHCI_PTR2ADDR(first_qtd);
504 qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(first_qtd);
505
506 /* update data toggle */
507 if (pipe->toggle) {
508 qh->hw.overlay.token = QTD_TOKEN_TOGGLE;
509 } else {
510 qh->hw.overlay.token = 0;
511 }
512
513 /* record qh first qtd */
514 qh->first_qtd = EHCI_PTR2ADDR(first_qtd);
515
516 flags = usb_osal_enter_critical_section();
517
518 qh->urb = pipe->urb;
519 /* add qh into async list */
520 ehci_qh_add_head(&g_async_qh_head, qh);
521
522 EHCI_HCOR->usbcmd |= EHCI_USBCMD_ASEN;
523
524 usb_osal_leave_critical_section(flags);
525 return qh;
526 }
527
ehci_intr_pipe_init(struct ehci_pipe * pipe,uint8_t * buffer,uint32_t buflen)528 static struct ehci_qh_hw *ehci_intr_pipe_init(struct ehci_pipe *pipe, uint8_t *buffer, uint32_t buflen)
529 {
530 struct ehci_qh_hw *qh = NULL;
531 struct ehci_qtd_hw *qtd = NULL;
532 struct ehci_qtd_hw *first_qtd = NULL;
533 struct ehci_qtd_hw *prev_qtd = NULL;
534 uint32_t qtd_num = 0;
535 uint32_t xfer_len = 0;
536 uint32_t token;
537 size_t flags;
538
539 qh = ehci_qh_alloc();
540 if (qh == NULL) {
541 return NULL;
542 }
543
544 for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
545 if (!g_ehci_hcd.ehci_qtd_used[i]) {
546 qtd_num++;
547 }
548 }
549
550 if (qtd_num < ((buflen + 0x3fff) / 0x4000)) {
551 ehci_qh_free(qh);
552 return NULL;
553 }
554
555 ehci_qh_fill(qh,
556 pipe->dev_addr,
557 pipe->ep_addr,
558 pipe->ep_type,
559 pipe->ep_mps,
560 pipe->mult + 1,
561 pipe->ep_interval,
562 pipe->hport->speed,
563 pipe->hport->parent->hub_addr,
564 pipe->hport->port);
565
566 while (buflen >= 0) {
567 qtd = ehci_qtd_alloc();
568
569 if (buflen > 0x4000) {
570 xfer_len = 0x4000;
571 buflen -= 0x4000;
572 } else {
573 xfer_len = buflen;
574 buflen = 0;
575 }
576
577 if (pipe->ep_addr & 0x80) {
578 token = QTD_TOKEN_PID_IN;
579 } else {
580 token = QTD_TOKEN_PID_OUT;
581 }
582
583 token |= QTD_TOKEN_STATUS_ACTIVE |
584 ((uint32_t)EHCI_TUNE_CERR << QTD_TOKEN_CERR_SHIFT) |
585 ((uint32_t)xfer_len << QTD_TOKEN_NBYTES_SHIFT);
586
587 if (buflen == 0) {
588 token |= QTD_TOKEN_IOC;
589 }
590
591 ehci_qtd_fill(qtd, (uintptr_t)buffer, xfer_len, token);
592 qtd->urb = pipe->urb;
593 qtd->hw.next_qtd = QTD_LIST_END;
594 buffer += xfer_len;
595
596 if (prev_qtd) {
597 prev_qtd->hw.next_qtd = EHCI_PTR2ADDR(qtd);
598 } else {
599 first_qtd = qtd;
600 }
601 prev_qtd = qtd;
602
603 if (buflen == 0) {
604 break;
605 }
606 }
607
608 /* update qh first qtd */
609 qh->hw.curr_qtd = EHCI_PTR2ADDR(first_qtd);
610 qh->hw.overlay.next_qtd = EHCI_PTR2ADDR(first_qtd);
611
612 /* update data toggle */
613 if (pipe->toggle) {
614 qh->hw.overlay.token = QTD_TOKEN_TOGGLE;
615 } else {
616 qh->hw.overlay.token = 0;
617 }
618
619 /* record qh first qtd */
620 qh->first_qtd = EHCI_PTR2ADDR(first_qtd);
621
622 flags = usb_osal_enter_critical_section();
623
624 qh->urb = pipe->urb;
625 /* add qh into periodic list */
626 if (pipe->speed == USB_SPEED_HIGH) {
627 ehci_qh_add_head(ehci_get_periodic_qhead(pipe->ep_interval), qh);
628 } else {
629 ehci_qh_add_head(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh);
630 }
631
632 EHCI_HCOR->usbcmd |= EHCI_USBCMD_PSEN;
633
634 usb_osal_leave_critical_section(flags);
635 return qh;
636 }
637
ehci_pipe_waitup(struct ehci_pipe * pipe)638 void ehci_pipe_waitup(struct ehci_pipe *pipe)
639 {
640 struct usbh_urb *urb;
641
642 urb = pipe->urb;
643 pipe->urb = NULL;
644
645 if (pipe->waiter) {
646 pipe->waiter = false;
647 usb_osal_sem_give(pipe->waitsem);
648 }
649
650 if (urb->complete) {
651 if (urb->errorcode < 0) {
652 urb->complete(urb->arg, urb->errorcode);
653 } else {
654 urb->complete(urb->arg, urb->actual_length);
655 }
656 }
657 }
658
ehci_qh_scan_qtds(struct ehci_qh_hw * qhead,struct ehci_qh_hw * qh)659 static void ehci_qh_scan_qtds(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
660 {
661 struct ehci_qtd_hw *qtd;
662
663 ehci_qh_remove(qhead, qh);
664
665 qtd = EHCI_ADDR2QTD(qh->first_qtd);
666
667 while (qtd) {
668 qtd->urb->actual_length += (qtd->total_len - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT));
669
670 ehci_qtd_free(qtd);
671 qh->first_qtd = qtd->hw.next_qtd;
672 qtd = EHCI_ADDR2QTD(qh->first_qtd);
673 }
674 }
675
ehci_check_qh(struct ehci_qh_hw * qhead,struct ehci_qh_hw * qh)676 static void ehci_check_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
677 {
678 struct usbh_urb *urb;
679 struct ehci_pipe *pipe;
680 struct ehci_qtd_hw *qtd;
681 uint32_t token;
682
683 token = qh->hw.overlay.token;
684
685 /* Check if token is only in active status without errors */
686 if ((token & (QTD_TOKEN_STATUS_ERRORS | QTD_TOKEN_STATUS_ACTIVE)) == QTD_TOKEN_STATUS_ACTIVE) {
687 return;
688 }
689
690 urb = qh->urb;
691 pipe = urb->pipe;
692
693 if ((token & QTD_TOKEN_STATUS_ERRORS) == 0) {
694 qtd = EHCI_ADDR2QTD(qh->first_qtd);
695
696 while (qtd) {
697 if (qtd->hw.token & QTD_TOKEN_STATUS_ACTIVE) {
698 return;
699 }
700 qtd = EHCI_ADDR2QTD(qtd->hw.next_qtd);
701 }
702
703 if (token & QTD_TOKEN_TOGGLE) {
704 pipe->toggle = true;
705 } else {
706 pipe->toggle = false;
707 }
708 urb->errorcode = 0;
709 } else {
710 if (token & QTD_TOKEN_STATUS_BABBLE) {
711 urb->errorcode = -EPERM;
712 pipe->toggle = 0;
713 } else if (token & QTD_TOKEN_STATUS_HALTED) {
714 urb->errorcode = -EPERM;
715 pipe->toggle = 0;
716 } else if (token & (QTD_TOKEN_STATUS_DBERR | QTD_TOKEN_STATUS_XACTERR)) {
717 urb->errorcode = -EIO;
718 }
719 }
720
721 ehci_qh_scan_qtds(qhead, qh);
722
723 if (pipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
724 qh->remove_in_iaad = 0;
725 ehci_qh_free(qh);
726 ehci_pipe_waitup(pipe);
727 } else {
728 qh->remove_in_iaad = 1;
729
730 EHCI_HCOR->usbcmd |= EHCI_USBCMD_IAAD;
731 }
732 }
733
ehci_kill_qh(struct ehci_qh_hw * qhead,struct ehci_qh_hw * qh)734 static void ehci_kill_qh(struct ehci_qh_hw *qhead, struct ehci_qh_hw *qh)
735 {
736 struct ehci_qtd_hw *qtd;
737
738 ehci_qh_remove(qhead, qh);
739
740 qtd = EHCI_ADDR2QTD(qh->first_qtd);
741
742 while (qtd) {
743 ehci_qtd_free(qtd);
744 qh->first_qtd = qtd->hw.next_qtd;
745 qtd = EHCI_ADDR2QTD(qh->first_qtd);
746 }
747
748 ehci_qh_free(qh);
749 }
750
usbh_reset_port(const uint8_t port)751 static int usbh_reset_port(const uint8_t port)
752 {
753 volatile uint32_t timeout = 0;
754 uint32_t regval;
755
756 #if defined(CONFIG_USB_EHCI_HPMICRO) && CONFIG_USB_EHCI_HPMICRO
757 if ((*(volatile uint32_t *)(CONFIG_HPM_USBH_BASE + 0x224) & 0xc0) == (2 << 6)) { /* Hardcode for hpm */
758 EHCI_HCOR->portsc[port - 1] |= (1 << 29);
759 } else {
760 EHCI_HCOR->portsc[port - 1] &= ~(1 << 29);
761 }
762 #endif
763 regval = EHCI_HCOR->portsc[port - 1];
764 regval &= ~EHCI_PORTSC_PE;
765 regval |= EHCI_PORTSC_RESET;
766 EHCI_HCOR->portsc[port - 1] = regval;
767 usb_osal_msleep(55);
768
769 EHCI_HCOR->portsc[port - 1] &= ~EHCI_PORTSC_RESET;
770 while ((EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_RESET) != 0) {
771 usb_osal_msleep(1);
772 timeout++;
773 if (timeout > 100) {
774 return -ETIMEDOUT;
775 }
776 }
777
778 return 0;
779 }
780
usb_hc_low_level_init(void)781 __WEAK void usb_hc_low_level_init(void)
782 {
783 }
784
usb_hc_low_level2_init(void)785 __WEAK void usb_hc_low_level2_init(void)
786 {
787 }
788
usb_hc_init(void)789 int usb_hc_init(void)
790 {
791 uint32_t interval;
792 struct ehci_qh_hw *qh;
793
794 volatile uint32_t timeout = 0;
795 uint32_t regval;
796
797 memset(&g_ehci_hcd, 0, sizeof(struct ehci_hcd));
798
799 if (sizeof(struct ehci_qh_hw) % 32) {
800 USB_LOG_ERR("struct ehci_qh_hw is not align 32\r\n");
801 return -EINVAL;
802 }
803 if (sizeof(struct ehci_qtd_hw) % 32) {
804 USB_LOG_ERR("struct ehci_qtd_hw is not align 32\r\n");
805 return -EINVAL;
806 }
807
808 for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
809 struct ehci_pipe *pipe;
810
811 pipe = &g_ehci_hcd.pipe_pool[index];
812 pipe->waitsem = usb_osal_sem_create(0);
813 }
814
815 memset(&g_async_qh_head, 0, sizeof(struct ehci_qh_hw));
816 g_async_qh_head.hw.hlp = QH_HLP_QH(&g_async_qh_head);
817 g_async_qh_head.hw.epchar = QH_EPCHAR_H;
818 g_async_qh_head.hw.overlay.next_qtd = QTD_LIST_END;
819 g_async_qh_head.hw.overlay.alt_next_qtd = QTD_LIST_END;
820 g_async_qh_head.hw.overlay.token = QTD_TOKEN_STATUS_HALTED;
821 g_async_qh_head.first_qtd = QTD_LIST_END;
822
823 memset(g_framelist, 0, sizeof(uint32_t) * CONFIG_USB_EHCI_FRAME_LIST_SIZE);
824
825 for (int i = EHCI_PERIOIDIC_QH_NUM - 1; i >= 0; i--) {
826 memset(&g_periodic_qh_head[i], 0, sizeof(struct ehci_qh_hw));
827 g_periodic_qh_head[i].hw.hlp = QH_HLP_END;
828 g_periodic_qh_head[i].hw.epchar = QH_EPCAPS_SSMASK(1);
829 g_periodic_qh_head[i].hw.overlay.next_qtd = QTD_LIST_END;
830 g_periodic_qh_head[i].hw.overlay.alt_next_qtd = QTD_LIST_END;
831 g_periodic_qh_head[i].hw.overlay.token = QTD_TOKEN_STATUS_HALTED;
832 g_periodic_qh_head[i].first_qtd = QTD_LIST_END;
833
834 interval = 1 << i;
835 for (uint32_t j = interval - 1; j < CONFIG_USB_EHCI_FRAME_LIST_SIZE; j += interval) {
836 if (g_framelist[j] == 0) {
837 g_framelist[j] = QH_HLP_QH(&g_periodic_qh_head[i]);
838 } else {
839 qh = EHCI_ADDR2QH(g_framelist[j]);
840 while (1) {
841 if (qh == &g_periodic_qh_head[i]) {
842 break;
843 }
844 if (qh->hw.hlp == QH_HLP_END) {
845 qh->hw.hlp = QH_HLP_QH(&g_periodic_qh_head[i]);
846 break;
847 }
848
849 qh = EHCI_ADDR2QH(qh->hw.hlp);
850 }
851 }
852 }
853 }
854
855 usb_hc_low_level_init();
856
857 EHCI_HCOR->usbcmd |= EHCI_USBCMD_HCRESET;
858 while (EHCI_HCOR->usbcmd & EHCI_USBCMD_HCRESET) {
859 usb_osal_msleep(1);
860 timeout++;
861 if (timeout > 100) {
862 return -ETIMEDOUT;
863 }
864 }
865
866 usb_hc_low_level2_init();
867
868 EHCI_HCOR->usbintr = 0;
869 EHCI_HCOR->usbsts = EHCI_HCOR->usbsts;
870 #if CONFIG_USB_EHCI_HCCR_BASE != 0
871 USB_LOG_INFO("EHCI HCIVERSION:%04x\r\n", (int)EHCI_HCCR->hciversion);
872 USB_LOG_INFO("EHCI HCSPARAMS:%06x\r\n", (int)EHCI_HCCR->hcsparams);
873 USB_LOG_INFO("EHCI HCCPARAMS:%04x\r\n", (int)EHCI_HCCR->hccparams);
874 #endif
875 /* Set the Current Asynchronous List Address. */
876 EHCI_HCOR->asynclistaddr = EHCI_PTR2ADDR(&g_async_qh_head);
877 /* Set the Periodic Frame List Base Address. */
878 EHCI_HCOR->periodiclistbase = EHCI_PTR2ADDR(g_framelist);
879
880 regval = 0;
881 #if CONFIG_USB_EHCI_FRAME_LIST_SIZE == 1024
882 regval |= EHCI_USBCMD_FLSIZE_1024;
883 #elif CONFIG_USB_EHCI_FRAME_LIST_SIZE == 512
884 regval |= EHCI_USBCMD_FLSIZE_512;
885 #elif CONFIG_USB_EHCI_FRAME_LIST_SIZE == 256
886 regval |= EHCI_USBCMD_FLSIZE_256;
887 #else
888 #error Unsupported frame size list size
889 #endif
890
891 regval |= EHCI_USBCMD_ITHRE_1MF;
892 regval |= EHCI_USBCMD_ASEN;
893 regval |= EHCI_USBCMD_PSEN;
894 regval |= EHCI_USBCMD_RUN;
895 EHCI_HCOR->usbcmd = regval;
896
897 #ifdef CONFIG_USB_EHCI_CONFIGFLAG
898 EHCI_HCOR->configflag = EHCI_CONFIGFLAG;
899 #endif
900 /* Wait for the EHCI to run (no longer report halted) */
901 timeout = 0;
902 while (EHCI_HCOR->usbsts & EHCI_USBSTS_HALTED) {
903 usb_osal_msleep(1);
904 timeout++;
905 if (timeout > 100) {
906 return -ETIMEDOUT;
907 }
908 }
909 #ifdef CONFIG_USB_EHCI_PORT_POWER
910 for (uint8_t port = 0; port < CONFIG_USBHOST_MAX_RHPORTS; port++) {
911 regval = EHCI_HCOR->portsc[port];
912 regval |= EHCI_PORTSC_PP;
913 EHCI_HCOR->portsc[port] = regval;
914 }
915 #endif
916
917 /* Enable EHCI interrupts. */
918 EHCI_HCOR->usbintr = EHCI_USBIE_INT | EHCI_USBIE_ERR | EHCI_USBIE_PCD | EHCI_USBIE_FATAL | EHCI_USBIE_IAA;
919 return 0;
920 }
921
usbh_get_frame_number(void)922 uint16_t usbh_get_frame_number(void)
923 {
924 return (((EHCI_HCOR->frindex & EHCI_FRINDEX_MASK) >> 3) & 0x3ff);
925 }
926
usbh_roothub_control(struct usb_setup_packet * setup,uint8_t * buf)927 int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
928 {
929 uint8_t nports;
930 uint8_t port;
931 uint32_t temp, status;
932
933 nports = CONFIG_USBHOST_MAX_RHPORTS;
934
935 port = setup->wIndex;
936 if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
937 switch (setup->bRequest) {
938 case HUB_REQUEST_CLEAR_FEATURE:
939 switch (setup->wValue) {
940 case HUB_FEATURE_HUB_C_LOCALPOWER:
941 break;
942 case HUB_FEATURE_HUB_C_OVERCURRENT:
943 break;
944 default:
945 return -EPIPE;
946 }
947 break;
948 case HUB_REQUEST_SET_FEATURE:
949 switch (setup->wValue) {
950 case HUB_FEATURE_HUB_C_LOCALPOWER:
951 break;
952 case HUB_FEATURE_HUB_C_OVERCURRENT:
953 break;
954 default:
955 return -EPIPE;
956 }
957 break;
958 case HUB_REQUEST_GET_DESCRIPTOR:
959 break;
960 case HUB_REQUEST_GET_STATUS:
961 memset(buf, 0, 4);
962 break;
963 default:
964 break;
965 }
966 } else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) {
967 switch (setup->bRequest) {
968 case HUB_REQUEST_CLEAR_FEATURE:
969 if (!port || port > nports) {
970 return -EPIPE;
971 }
972
973 switch (setup->wValue) {
974 case HUB_PORT_FEATURE_ENABLE:
975 EHCI_HCOR->portsc[port - 1] &= ~EHCI_PORTSC_PE;
976 break;
977 case HUB_PORT_FEATURE_SUSPEND:
978 case HUB_PORT_FEATURE_C_SUSPEND:
979 break;
980 case HUB_PORT_FEATURE_POWER:
981 #ifdef CONFIG_USB_EHCI_PORT_POWER
982 EHCI_HCOR->portsc[port - 1] &= ~EHCI_PORTSC_PP;
983 #endif
984 break;
985 case HUB_PORT_FEATURE_C_CONNECTION:
986 EHCI_HCOR->portsc[port - 1] |= EHCI_PORTSC_CSC;
987 break;
988 case HUB_PORT_FEATURE_C_ENABLE:
989 EHCI_HCOR->portsc[port - 1] |= EHCI_PORTSC_PEC;
990 break;
991 case HUB_PORT_FEATURE_C_OVER_CURREN:
992 EHCI_HCOR->portsc[port - 1] |= EHCI_PORTSC_OCC;
993 break;
994 case HUB_PORT_FEATURE_C_RESET:
995 break;
996 default:
997 return -EPIPE;
998 }
999 break;
1000 case HUB_REQUEST_SET_FEATURE:
1001 if (!port || port > nports) {
1002 return -EPIPE;
1003 }
1004
1005 switch (setup->wValue) {
1006 case HUB_PORT_FEATURE_SUSPEND:
1007 break;
1008 case HUB_PORT_FEATURE_POWER:
1009 #ifdef CONFIG_USB_EHCI_PORT_POWER
1010 EHCI_HCOR->portsc[port - 1] |= EHCI_PORTSC_PP;
1011 #endif
1012 break;
1013 case HUB_PORT_FEATURE_RESET:
1014 usbh_reset_port(port);
1015 break;
1016
1017 default:
1018 return -EPIPE;
1019 }
1020 break;
1021 case HUB_REQUEST_GET_STATUS:
1022 if (!port || port > nports) {
1023 return -EPIPE;
1024 }
1025 temp = EHCI_HCOR->portsc[port - 1];
1026
1027 status = 0;
1028 if (temp & EHCI_PORTSC_CSC) {
1029 status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
1030 }
1031 if (temp & EHCI_PORTSC_PEC) {
1032 status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
1033 }
1034 if (temp & EHCI_PORTSC_OCC) {
1035 status |= (1 << HUB_PORT_FEATURE_C_OVER_CURREN);
1036 }
1037
1038 if (temp & EHCI_PORTSC_CCS) {
1039 status |= (1 << HUB_PORT_FEATURE_CONNECTION);
1040 }
1041 if (temp & EHCI_PORTSC_PE) {
1042 status |= (1 << HUB_PORT_FEATURE_ENABLE);
1043
1044 if (usbh_get_port_speed(port) == USB_SPEED_LOW) {
1045 status |= (1 << HUB_PORT_FEATURE_LOWSPEED);
1046 } else if (usbh_get_port_speed(port) == USB_SPEED_HIGH) {
1047 status |= (1 << HUB_PORT_FEATURE_HIGHSPEED);
1048 }
1049 }
1050 if (temp & EHCI_PORTSC_SUSPEND) {
1051 status |= (1 << HUB_PORT_FEATURE_SUSPEND);
1052 }
1053 if (temp & EHCI_PORTSC_OCA) {
1054 status |= (1 << HUB_PORT_FEATURE_OVERCURRENT);
1055 }
1056 if (temp & EHCI_PORTSC_RESET) {
1057 status |= (1 << HUB_PORT_FEATURE_RESET);
1058 }
1059 if (temp & EHCI_PORTSC_PP) {
1060 status |= (1 << HUB_PORT_FEATURE_POWER);
1061 }
1062 memcpy(buf, &status, 4);
1063 break;
1064 default:
1065 break;
1066 }
1067 }
1068 return 0;
1069 }
1070
usbh_ep_pipe_reconfigure(usbh_pipe_t pipe,uint8_t dev_addr,uint8_t ep_mps,uint8_t mult)1071 int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t mult)
1072 {
1073 struct ehci_pipe *ppipe = (struct ehci_pipe *)pipe;
1074
1075 ppipe->dev_addr = dev_addr;
1076 ppipe->ep_mps = ep_mps;
1077 ppipe->mult = mult;
1078
1079 return 0;
1080 }
1081
usbh_pipe_alloc(usbh_pipe_t * pipe,const struct usbh_endpoint_cfg * ep_cfg)1082 int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
1083 {
1084 struct ehci_pipe *ppipe;
1085 usb_osal_sem_t waitsem;
1086
1087 ppipe = ehci_pipe_alloc();
1088 if (ppipe == NULL) {
1089 return -ENOMEM;
1090 }
1091
1092 /* store variables */
1093 waitsem = ppipe->waitsem;
1094
1095 memset(ppipe, 0, sizeof(struct ehci_pipe));
1096
1097 ppipe->ep_addr = ep_cfg->ep_addr;
1098 ppipe->ep_type = ep_cfg->ep_type;
1099 ppipe->ep_mps = ep_cfg->ep_mps;
1100 ppipe->ep_interval = ep_cfg->ep_interval;
1101 ppipe->mult = ep_cfg->mult;
1102 ppipe->speed = ep_cfg->hport->speed;
1103 ppipe->dev_addr = ep_cfg->hport->dev_addr;
1104 ppipe->hport = ep_cfg->hport;
1105
1106 #ifdef CONFIG_USB_EHCI_ISO
1107 if ((ppipe->speed == USB_SPEED_HIGH) && (ppipe->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS)) {
1108 if (ep_cfg->ep_interval == 0x01) { /* transfer interval 1 mf */
1109 ppipe->mf_unmask = 0xff;
1110 ppipe->mf_valid = 8;
1111 } else if (ep_cfg->ep_interval == 0x02) { /* transfer interval 2 mf */
1112 ppipe->mf_unmask = 0x55;
1113 ppipe->mf_valid = 4;
1114 } else if (ep_cfg->ep_interval == 0x03) { /* transfer interval 4 mf */
1115 ppipe->mf_unmask = 0x44;
1116 ppipe->mf_valid = 2;
1117 } else if (ep_cfg->ep_interval == 0x04) { /* transfer interval 8 mf */
1118 ppipe->mf_unmask = 0x01;
1119 ppipe->mf_valid = 1;
1120 }
1121 }
1122 #endif
1123 /* restore variable */
1124 ppipe->inuse = true;
1125 ppipe->waitsem = waitsem;
1126
1127 *pipe = (usbh_pipe_t)ppipe;
1128
1129 return 0;
1130 }
1131
usbh_pipe_free(usbh_pipe_t pipe)1132 int usbh_pipe_free(usbh_pipe_t pipe)
1133 {
1134 struct usbh_urb *urb;
1135 struct ehci_pipe *ppipe;
1136
1137 ppipe = (struct ehci_pipe *)pipe;
1138
1139 if (!ppipe) {
1140 return -EINVAL;
1141 }
1142
1143 urb = ppipe->urb;
1144
1145 if (urb) {
1146 usbh_kill_urb(urb);
1147 }
1148
1149 ehci_pipe_free(ppipe);
1150 return 0;
1151 }
1152
usbh_submit_urb(struct usbh_urb * urb)1153 int usbh_submit_urb(struct usbh_urb *urb)
1154 {
1155 struct ehci_pipe *pipe;
1156 struct ehci_qh_hw *qh = NULL;
1157 size_t flags;
1158 int ret = 0;
1159
1160 if (!urb || !urb->pipe) {
1161 return -EINVAL;
1162 }
1163
1164 pipe = urb->pipe;
1165
1166 if (!pipe->inuse /*|| !(EHCI_HCOR->portsc[pipe->hport->port-1] & EHCI_PORTSC_CCS)*/ || !pipe->hport->connected) {
1167 return -ENODEV;
1168 }
1169
1170 if (pipe->urb && (pipe->ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS)) {
1171 return -EBUSY;
1172 }
1173
1174 flags = usb_osal_enter_critical_section();
1175
1176 pipe->waiter = false;
1177 pipe->xfrd = 0;
1178 pipe->urb = urb;
1179 urb->errorcode = -EBUSY;
1180 urb->actual_length = 0;
1181
1182 if (urb->timeout > 0) {
1183 pipe->waiter = true;
1184 }
1185 usb_osal_leave_critical_section(flags);
1186
1187 switch (pipe->ep_type) {
1188 case USB_ENDPOINT_TYPE_CONTROL:
1189 qh = ehci_control_pipe_init(pipe, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
1190 if (qh == NULL) {
1191 return -ENOMEM;
1192 }
1193 break;
1194 case USB_ENDPOINT_TYPE_BULK:
1195 qh = ehci_bulk_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length);
1196 if (qh == NULL) {
1197 return -ENOMEM;
1198 }
1199 break;
1200 case USB_ENDPOINT_TYPE_INTERRUPT:
1201 qh = ehci_intr_pipe_init(pipe, urb->transfer_buffer, urb->transfer_buffer_length);
1202 if (qh == NULL) {
1203 return -ENOMEM;
1204 }
1205 break;
1206 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
1207 #ifdef CONFIG_USB_EHCI_ISO
1208 ehci_iso_pipe_init(pipe, urb);
1209 #endif
1210 break;
1211 default:
1212 break;
1213 }
1214
1215 if (urb->timeout > 0) {
1216 /* wait until timeout or sem give */
1217 ret = usb_osal_sem_take(pipe->waitsem, urb->timeout);
1218 if (ret < 0) {
1219 goto errout_timeout;
1220 }
1221 ret = urb->errorcode;
1222 }
1223 return ret;
1224 errout_timeout:
1225 /* Timeout will run here */
1226 pipe->waiter = false;
1227 usbh_kill_urb(urb);
1228 return ret;
1229 }
1230
usbh_kill_urb(struct usbh_urb * urb)1231 int usbh_kill_urb(struct usbh_urb *urb)
1232 {
1233 struct ehci_pipe *pipe;
1234 struct ehci_qh_hw *qh = NULL;
1235
1236 size_t flags;
1237
1238 if (!urb) {
1239 return -EINVAL;
1240 }
1241
1242 pipe = urb->pipe;
1243
1244 if (!pipe) {
1245 return -EINVAL;
1246 }
1247
1248 flags = usb_osal_enter_critical_section();
1249
1250 EHCI_HCOR->usbcmd &= ~(EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN);
1251
1252 if ((pipe->ep_type == USB_ENDPOINT_TYPE_CONTROL) || (pipe->ep_type == USB_ENDPOINT_TYPE_BULK)) {
1253 qh = EHCI_ADDR2QH(g_async_qh_head.hw.hlp);
1254 while ((qh != &g_async_qh_head) && qh) {
1255 if (qh->urb == urb) {
1256 ehci_kill_qh(&g_async_qh_head, qh);
1257 }
1258 qh = EHCI_ADDR2QH(qh->hw.hlp);
1259 }
1260 } else if (pipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
1261 qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
1262 while (qh) {
1263 if (qh->urb == urb) {
1264 if (pipe->speed == USB_SPEED_HIGH) {
1265 ehci_kill_qh(ehci_get_periodic_qhead(pipe->ep_interval), qh);
1266 } else {
1267 ehci_kill_qh(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh);
1268 }
1269 }
1270 qh = EHCI_ADDR2QH(qh->hw.hlp);
1271 }
1272 } else {
1273 #ifdef CONFIG_USB_EHCI_ISO
1274 ehci_remove_itd_urb(urb);
1275 #endif
1276 }
1277
1278 EHCI_HCOR->usbcmd |= (EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN);
1279
1280 pipe->urb = NULL;
1281
1282 if (pipe->waiter) {
1283 pipe->waiter = false;
1284 urb->errorcode = -ESHUTDOWN;
1285 usb_osal_sem_give(pipe->waitsem);
1286 }
1287
1288 usb_osal_leave_critical_section(flags);
1289
1290 return 0;
1291 }
1292
ehci_scan_async_list(void)1293 static void ehci_scan_async_list(void)
1294 {
1295 struct ehci_qh_hw *qh;
1296
1297 qh = EHCI_ADDR2QH(g_async_qh_head.hw.hlp);
1298 while ((qh != &g_async_qh_head) && qh) {
1299 if (qh->urb) {
1300 ehci_check_qh(&g_async_qh_head, qh);
1301 }
1302 qh = EHCI_ADDR2QH(qh->hw.hlp);
1303 }
1304 }
1305
ehci_scan_periodic_list(void)1306 static void ehci_scan_periodic_list(void)
1307 {
1308 struct ehci_qh_hw *qh;
1309 struct ehci_pipe *pipe;
1310
1311 qh = EHCI_ADDR2QH(g_periodic_qh_head[EHCI_PERIOIDIC_QH_NUM - 1].hw.hlp);
1312 while (qh) {
1313 if (qh->urb && qh->urb->pipe) {
1314 pipe = (struct ehci_pipe *)qh->urb->pipe;
1315 if (pipe->speed == USB_SPEED_HIGH) {
1316 ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval), qh);
1317 } else {
1318 ehci_check_qh(ehci_get_periodic_qhead(pipe->ep_interval * 8), qh);
1319 }
1320 }
1321 qh = EHCI_ADDR2QH(qh->hw.hlp);
1322 }
1323 }
1324
USBH_IRQHandler(void)1325 void USBH_IRQHandler(void)
1326 {
1327 uint32_t usbsts;
1328
1329 usbsts = EHCI_HCOR->usbsts & EHCI_HCOR->usbintr;
1330 EHCI_HCOR->usbsts = usbsts;
1331
1332 if (usbsts & EHCI_USBSTS_INT) {
1333 ehci_scan_async_list();
1334 ehci_scan_periodic_list();
1335 #ifdef CONFIG_USB_EHCI_ISO
1336 ehci_scan_isochronous_list();
1337 #endif
1338 }
1339
1340 if (usbsts & EHCI_USBSTS_ERR) {
1341 ehci_scan_async_list();
1342 ehci_scan_periodic_list();
1343 #ifdef CONFIG_USB_EHCI_ISO
1344 ehci_scan_isochronous_list();
1345 #endif
1346 }
1347
1348 if (usbsts & EHCI_USBSTS_PCD) {
1349 for (int port = 0; port < CONFIG_USBHOST_MAX_RHPORTS; port++) {
1350 uint32_t portsc = EHCI_HCOR->portsc[port];
1351
1352 if (portsc & EHCI_PORTSC_CSC) {
1353 if ((portsc & EHCI_PORTSC_CCS) == EHCI_PORTSC_CCS) {
1354 } else {
1355 for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
1356 g_ehci_hcd.ehci_qh_used[index] = false;
1357 }
1358 for (uint8_t index = 0; index < CONFIG_USB_EHCI_QTD_NUM; index++) {
1359 g_ehci_hcd.ehci_qtd_used[index] = false;
1360 }
1361 for (uint8_t index = 0; index < CONFIG_USB_EHCI_ITD_NUM; index++) {
1362 g_ehci_hcd.ehci_itd_used[index] = false;
1363 }
1364 }
1365
1366 usbh_roothub_thread_wakeup(port + 1);
1367 }
1368 }
1369 }
1370
1371 if (usbsts & EHCI_USBSTS_IAA) {
1372 for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
1373 struct ehci_qh_hw *qh = &ehci_qh_pool[index];
1374 if (g_ehci_hcd.ehci_qh_used[index] && qh->remove_in_iaad) {
1375 struct usbh_urb *urb;
1376 struct ehci_pipe *pipe;
1377
1378 urb = qh->urb;
1379 pipe = urb->pipe;
1380
1381 qh->remove_in_iaad = 0;
1382 ehci_qh_free(qh);
1383
1384 ehci_pipe_waitup(pipe);
1385 }
1386 }
1387 }
1388
1389 if (usbsts & EHCI_USBSTS_FATAL) {
1390 }
1391 }