• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }