M480 BSP V3.05.006
The Board Support Package for M480 Series
ohci.c
Go to the documentation of this file.
1/**************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include "NuMicro.h"
15
16#include "usb.h"
17#include "hub.h"
18#include "ohci.h"
19
21
22//#define TD_debug printf
23#define TD_debug(...)
24
25//#define ED_debug printf
26#define ED_debug(...)
27
28#ifdef __ICCARM__
29#pragma data_alignment=256
30HCCA_T _hcca;
31#else
32HCCA_T _hcca __attribute__((aligned(256)));
33#endif
34
35ED_T * _Ied[6];
36
37
38static ED_T *ed_remove_list;
39
40static void add_to_ED_remove_list(ED_T *ed)
41{
42 ED_T *p;
43
44 ED_debug("add_to_ED_remove_list - 0x%x (0x%x)\n", (int)ed, ed->Info);
45 DISABLE_OHCI_IRQ();
46
47 /* check if this ED found in ed_remove_list */
48 p = ed_remove_list;
49 while (p)
50 {
51 if (p == ed)
52 {
53 ENABLE_OHCI_IRQ(); /* This ED found in ed_remove_list */
54 return; /* do nothing */
55 }
56 p = p->next;
57 }
58
59 ed->Info |= ED_SKIP; /* ask OHCI controller skip this ED */
60 ed->next = ed_remove_list;
61 ed_remove_list = ed; /* insert to the head of ed_remove_list */
62 ENABLE_OHCI_IRQ();
63 _ohci->HcInterruptStatus = USBH_HcInterruptStatus_SF_Msk;
64 _ohci->HcInterruptEnable |= USBH_HcInterruptEnable_SF_Msk;
65 delay_us(2000); /* Full speed wait 2 ms is enough */
66}
67
68static int ohci_reset(void)
69{
70 volatile int t0;
71
72 /* Disable HC interrupts */
73 _ohci->HcInterruptDisable = USBH_HcInterruptDisable_MIE_Msk;
74
75 /* HC Reset requires max 10 ms delay */
76 _ohci->HcControl = 0;
77 _ohci->HcCommandStatus = USBH_HcCommandStatus_HCR_Msk;
78
79 delay_us(10000);
80
81 /* Check if OHCI reset completed? */
82 if ((USBH->HcCommandStatus & USBH_HcCommandStatus_HCR_Msk) != 0)
83 {
84 USB_error("Error! - USB OHCI reset timed out!\n");
85 return -1;
86 }
87
89
90 USBH->HcControl = HCFS_RESET;
91
92 delay_us(10000);
93
94 /* Check if OHCI reset completed? */
95 if ((USBH->HcCommandStatus & USBH_HcCommandStatus_HCR_Msk) != 0)
96 {
97 USB_error("Error! - USB HC reset timed out!\n");
98 return -1;
99 }
100 return 0;
101}
102
103static void init_hcca_int_table()
104{
105 ED_T *ed_p;
106 int i, idx, interval;
107
108 memset(_hcca.int_table, 0, sizeof(_hcca.int_table));
109
110 for (i = 5; i >= 0; i--) /* interval = i^2 */
111 {
112 _Ied[i] = alloc_ohci_ED();
113 _Ied[i]->Info = ED_SKIP;
114
115 interval = 0x1 << i;
116
117 for (idx = interval - 1; idx < 32; idx += interval)
118 {
119 if (_hcca.int_table[idx] == 0) /* is empty list, insert directly */
120 {
121 _hcca.int_table[idx] = (uint32_t)_Ied[i];
122 }
123 else
124 {
125 ed_p = (ED_T *)_hcca.int_table[idx];
126
127 while (1)
128 {
129 if (ed_p == _Ied[i])
130 break; /* already chained by previous visit */
131
132 if (ed_p->NextED == 0) /* reach end of list? */
133 {
134 ed_p->NextED = (uint32_t)_Ied[i];
135 break;
136 }
137 ed_p = (ED_T *)ed_p->NextED;
138 }
139 }
140 }
141 }
142}
143
144static ED_T * get_int_tree_head_node(int interval)
145{
146 int i;
147
148 for (i = 0; i < 5; i++)
149 {
150 interval >>= 1;
151 if (interval == 0)
152 return _Ied[i];
153 }
154 return _Ied[5]; /* for interval >= 32 */
155}
156
157static int get_ohci_interval(int interval)
158{
159 int i, bInterval = 1;
160
161 for (i = 0; i < 5; i++)
162 {
163 interval >>= 1;
164 if (interval == 0)
165 return bInterval;
166 bInterval *= 2;
167 }
168 return 32; /* for interval >= 32 */
169}
170
171
172static int ohci_init(void)
173{
174 uint32_t fminterval;
175 volatile int i;
176
177 if (ohci_reset() < 0)
178 return -1;
179
180 ed_remove_list = NULL;
181
182 init_hcca_int_table();
183
184 /* Tell the controller where the control and bulk lists are
185 * The lists are empty now. */
186 _ohci->HcControlHeadED = 0; /* control ED list head */
187 _ohci->HcBulkHeadED = 0; /* bulk ED list head */
188
189 _ohci->HcHCCA = (uint32_t)&_hcca; /* HCCA area */
190
191 /* periodic start 90% of frame interval */
192 fminterval = 0x2edf; /* 11,999 */
193 _ohci->HcPeriodicStart = (fminterval*9)/10;
194
195 /* set FSLargestDataPacket, 10,104 for 0x2edf frame interval */
196 fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
197 _ohci->HcFmInterval = fminterval;
198
199 _ohci->HcLSThreshold = 0x628;
200
201 /* start controller operations */
202 _ohci->HcControl = HCFS_OPER | (0x3 << USBH_HcControl_CBSR_Pos);
203
204#ifdef OHCI_PER_PORT_POWER
205 _ohci->HcRhDescriptorB = 0x60000;
206 _ohci->HcRhPortStatus[0] = USBH_HcRhPortStatus_PPS_Msk;
207 _ohci->HcRhPortStatus[1] = USBH_HcRhPortStatus_PPS_Msk;
208#else
209 _ohci->HcRhDescriptorA = (USBH->HcRhDescriptorA | (1<<9)) & ~USBH_HcRhDescriptorA_PSM_Msk;
210 _ohci->HcRhStatus = USBH_HcRhStatus_LPSC_Msk;
211#endif
212
214
215 /* POTPGT delay is bits 24-31, in 20 ms units. */
216 delay_us(20000);
217 return 0;
218}
219
220static void ohci_suspend(void)
221{
222 /* set port suspend if connected */
223 if (_ohci->HcRhPortStatus[0] & 0x1)
224 _ohci->HcRhPortStatus[0] = 0x4;
225
226 if (_ohci->HcRhPortStatus[1] & 0x1)
227 _ohci->HcRhPortStatus[1] = 0x4;
228
229 /* enable Device Remote Wakeup */
230 _ohci->HcRhStatus |= USBH_HcRhStatus_DRWE_Msk;
231
232 /* enable USBH RHSC interrupt for system wakeup */
234
235 /* set Host Controller enter suspend state */
236 _ohci->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (3 << USBH_HcControl_HCFS_Pos);
237}
238
239static void ohci_resume(void)
240{
241 _ohci->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (1 << USBH_HcControl_HCFS_Pos);
242 _ohci->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (2 << USBH_HcControl_HCFS_Pos);
243
244 if (_ohci->HcRhPortStatus[0] & 0x4)
245 _ohci->HcRhPortStatus[0] = 0x8;
246 if (_ohci->HcRhPortStatus[1] & 0x4)
247 _ohci->HcRhPortStatus[1] = 0x8;
248}
249
250static void ohci_shutdown(void)
251{
252 ohci_suspend();
253 NVIC_DisableIRQ(USBH_IRQn);
254#ifndef OHCI_PER_PORT_POWER
255 _ohci->HcRhStatus = USBH_HcRhStatus_LPS_Msk;
256#endif
257}
258
259
260/*
261 * Quit current trasnfer via UTR or hardware EP.
262 */
263static int ohci_quit_xfer(UTR_T *utr, EP_INFO_T *ep)
264{
265 ED_T *ed;
266
267 if (utr != NULL)
268 {
269 if (utr->ep == NULL)
270 return USBH_ERR_NOT_FOUND;
271
272 ed = (ED_T *)(utr->ep->hw_pipe);
273
274 if (!ed)
275 return USBH_ERR_NOT_FOUND;
276
277 /* add the endpoint to remove list, it will be removed on the next start of frame */
278 add_to_ED_remove_list(ed);
279 utr->ep->hw_pipe = NULL;
280 }
281
282 if ((ep != NULL) && (ep->hw_pipe != NULL))
283 {
284 ed = (ED_T *)(ep->hw_pipe);
285 /* add the endpoint to remove list, it will be removed on the next start of frame */
286 add_to_ED_remove_list(ed);
287 ep->hw_pipe = NULL;
288 }
289
290 return 0;
291}
292
293uint32_t ed_make_info(UDEV_T *udev, EP_INFO_T *ep)
294{
295 uint32_t info;
296
297 if (ep == NULL) /* is a control endpoint */
298 {
299 /* control endpoint direction is from TD */
300 if (udev->descriptor.bMaxPacketSize0 == 0) /* is 0 if device descriptor still not obtained. */
301 {
302 if (udev->speed == SPEED_LOW) /* give a default maximum packet size */
303 udev->descriptor.bMaxPacketSize0 = 8;
304 else
305 udev->descriptor.bMaxPacketSize0 = 64;
306 }
307 info = (udev->descriptor.bMaxPacketSize0 << 16) /* Control endpoint Maximum Packet Size from device descriptor */
308 | ED_DIR_BY_TD /* Direction (Get direction From TD) */
309 | ED_FORMAT_GENERAL /* General format */
310 | (0 << ED_CTRL_EN_Pos); /* Endpoint address 0 */
311 }
312 else /* Other endpoint direction is from endpoint descriptor */
313 {
314 info = (ep->wMaxPacketSize << 16); /* Maximum Packet Size from endpoint */
315
316 info |= ((ep->bEndpointAddress & 0xf) << ED_CTRL_EN_Pos); /* Endpoint Number */
317
318 if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN)
319 info |= ED_DIR_IN;
320 else
321 info |= ED_DIR_OUT;
322
323 if ((ep->bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_ISO)
324 info |= ED_FORMAT_ISO;
325 else
326 info |= ED_FORMAT_GENERAL;
327 }
328
329 info |= ((udev->speed == SPEED_LOW) ? ED_SPEED_LOW : ED_SPEED_FULL); /* Speed */
330 info |= (udev->dev_num); /* Function Address */
331
332 return info;
333}
334
335static void write_td(TD_T *td, uint32_t info, uint8_t *buff, uint32_t data_len)
336{
337 td->Info = info;
338 td->CBP = (uint32_t)((!buff || !data_len) ? 0 : buff);
339 td->BE = (uint32_t)((!buff || !data_len ) ? 0 : (uint32_t)buff + data_len - 1);
340 td->buff_start = td->CBP;
341 // TD_debug("TD [0x%x]: 0x%x, 0x%x, 0x%x\n", (int)td, td->Info, td->CBP, td->BE);
342}
343
344static int ohci_ctrl_xfer(UTR_T *utr)
345{
346 UDEV_T *udev;
347 ED_T *ed;
348 TD_T *td_setup, *td_data, *td_status;
349 uint32_t info;
350
351 udev = utr->udev;
352
353 /*------------------------------------------------------------------------------------*/
354 /* Allocate ED and TDs */
355 /*------------------------------------------------------------------------------------*/
356 td_setup = alloc_ohci_TD(utr);
357
358 if (utr->data_len > 0)
359 td_data = alloc_ohci_TD(utr);
360 else
361 td_data = NULL;
362
363 td_status = alloc_ohci_TD(utr);
364
365 if (td_status == NULL)
366 {
367 free_ohci_TD(td_setup);
368 if (utr->data_len > 0)
369 free_ohci_TD(td_data);
370 return USBH_ERR_MEMORY_OUT;
371 }
372
373 /* Check if there's any transfer pending on this endpoint... */
374 if (udev->ep0.hw_pipe == NULL)
375 {
376 ed = alloc_ohci_ED();
377 if (ed == NULL)
378 {
379 free_ohci_TD(td_setup);
380 free_ohci_TD(td_status);
381 if (utr->data_len > 0)
382 free_ohci_TD(td_data);
383 return USBH_ERR_MEMORY_OUT;
384 }
385 }
386 else
387 ed = (ED_T *)udev->ep0.hw_pipe;
388
389 /*------------------------------------------------------------------------------------*/
390 /* prepare SETUP stage TD */
391 /*------------------------------------------------------------------------------------*/
392 info = TD_CC | TD_T_DATA0 | TD_TYPE_CTRL;
393 write_td(td_setup, info, (uint8_t *)&utr->setup, 8);
394 td_setup->ed = ed;
395
396 /*------------------------------------------------------------------------------------*/
397 /* prepare DATA stage TD */
398 /*------------------------------------------------------------------------------------*/
399 if (utr->data_len > 0)
400 {
401 if ((utr->setup.bmRequestType & 0x80) == REQ_TYPE_OUT)
402 info = (TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 | TD_TYPE_CTRL | TD_CTRL_DATA);
403 else
404 info = (TD_CC | TD_R | TD_DP_IN | TD_T_DATA1 | TD_TYPE_CTRL | TD_CTRL_DATA);
405
406 write_td(td_data, info, utr->buff, utr->data_len);
407 td_data->ed = ed;
408 td_setup->NextTD = (uint32_t)td_data;
409 td_setup->next = td_data;
410 td_data->NextTD = (uint32_t)td_status;
411 td_data->next = td_status;
412 }
413 else
414 {
415 td_setup->NextTD = (uint32_t)td_status;
416 td_setup->next = td_status;
417 }
418
419 /*------------------------------------------------------------------------------------*/
420 /* prepare STATUS stage TD */
421 /*------------------------------------------------------------------------------------*/
422 ed->Info = ed_make_info(udev, NULL);
423 if ((utr->setup.bmRequestType & 0x80) == REQ_TYPE_OUT)
424 info = (TD_CC | TD_DP_IN | TD_T_DATA1 | TD_TYPE_CTRL);
425 else
426 info = (TD_CC | TD_DP_OUT | TD_T_DATA1 | TD_TYPE_CTRL);
427
428 write_td(td_status, info, NULL, 0);
429 td_status->ed = ed;
430 td_status->NextTD = 0;
431 td_status->next = 0;
432
433 /*------------------------------------------------------------------------------------*/
434 /* prepare ED */
435 /*------------------------------------------------------------------------------------*/
436 ed->TailP = 0;
437 ed->HeadP = (uint32_t)td_setup;
438 ed->Info = ed_make_info(udev, NULL);
439 ed->NextED = 0;
440
441 //TD_debug("TD SETUP [0x%x]: 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td_setup, td_setup->Info, td_setup->CBP, td_setup->BE, td_setup->NextTD);
442 //if (td_data)
443 // TD_debug("TD DATA [0x%x]: 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td_data, td_data->Info, td_data->CBP, td_data->BE, td_data->NextTD);
444 //TD_debug("TD STATUS [0x%x]: 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td_status, td_status->Info, td_status->CBP, td_status->BE, td_status->NextTD);
445 ED_debug("Xfer ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED);
446
447 if (utr->data_len > 0)
448 utr->td_cnt = 3;
449 else
450 utr->td_cnt = 2;
451
452 utr->ep = &udev->ep0; /* driver can find EP from UTR */
453 udev->ep0.hw_pipe = (void *)ed; /* driver can find ED from EP */
454
455 /*------------------------------------------------------------------------------------*/
456 /* Start transfer */
457 /*------------------------------------------------------------------------------------*/
458 DISABLE_OHCI_IRQ();
459 _ohci->HcControlHeadED = (uint32_t)ed; /* Link ED to OHCI */
460 _ohci->HcControl |= USBH_HcControl_CLE_Msk; /* enable control list */
461 ENABLE_OHCI_IRQ();
462 _ohci->HcCommandStatus = USBH_HcCommandStatus_CLF_Msk; /* start Control list */
463
464 return 0;
465}
466
467static int ohci_bulk_xfer(UTR_T *utr)
468{
469 UDEV_T *udev = utr->udev;
470 EP_INFO_T *ep = utr->ep;
471 ED_T *ed;
472 TD_T *td, *td_p, *td_list = NULL;
473 uint32_t info;
474 uint32_t data_len, xfer_len;
475 int8_t bIsNewED = 0;
476 uint8_t *buff;
477
478 /*------------------------------------------------------------------------------------*/
479 /* Check if there's uncompleted transfer on this endpoint... */
480 /* Prepare ED */
481 /*------------------------------------------------------------------------------------*/
482 info = ed_make_info(udev, ep);
483
484 /* Check if there's any transfer pending on this endpoint... */
485 ed = (ED_T *)_ohci->HcBulkHeadED; /* get the head of bulk endpoint list */
486 while (ed != NULL)
487 {
488 if (ed->Info == info) /* have transfer of this EP not completed? */
489 {
490 if ((ed->HeadP & 0xFFFFFFF0) != (ed->TailP & 0xFFFFFFF0))
491 return USBH_ERR_OHCI_EP_BUSY; /* endpoint is busy */
492 else
493 break; /* ED already there... */
494 }
495 ed = (ED_T *)ed->NextED;
496 }
497
498 if (ed == NULL)
499 {
500 bIsNewED = 1;
501 ed = alloc_ohci_ED(); /* allocate an Endpoint Descriptor */
502 if (ed == NULL)
503 return USBH_ERR_MEMORY_OUT;
504 ed->Info = info;
505 ed->HeadP = 0;
506 ED_debug("Link BULK ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED);
507 }
508
509 ep->hw_pipe = (void *)ed;
510
511 /*------------------------------------------------------------------------------------*/
512 /* Prepare TDs */
513 /*------------------------------------------------------------------------------------*/
514 utr->td_cnt = 0;
515 data_len = utr->data_len;
516 buff = utr->buff;
517
518 do
519 {
520 if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT)
521 info = (TD_CC | TD_R | TD_DP_OUT | TD_TYPE_BULK);
522 else
523 info = (TD_CC | TD_R | TD_DP_IN | TD_TYPE_BULK);
524
525 info &= ~(1 << 25); /* Data toggle from ED toggleCarry bit */
526
527 if (data_len > 4096) /* maximum transfer length is 4K for each TD */
528 xfer_len = 4096;
529 else
530 xfer_len = data_len; /* remaining data length < 4K */
531
532 td = alloc_ohci_TD(utr); /* allocate a TD */
533 if (td == NULL)
534 goto mem_out;
535 /* fill this TD */
536 write_td(td, info, buff, xfer_len);
537 td->ed = ed;
538
539 utr->td_cnt++; /* increase TD count, for recalim counter */
540
541 buff += xfer_len; /* advanced buffer pointer */
542 data_len -= xfer_len;
543
544 /* chain to end of TD list */
545 if (td_list == NULL)
546 {
547 td_list = td;
548 }
549 else
550 {
551 td_p = td_list;
552 while (td_p->NextTD != 0)
553 td_p = (TD_T *)td_p->NextTD;
554 td_p->NextTD = (uint32_t)td;
555 }
556
557 }
558 while (data_len > 0);
559
560 /*------------------------------------------------------------------------------------*/
561 /* Start transfer */
562 /*------------------------------------------------------------------------------------*/
563 utr->status = 0;
564 DISABLE_OHCI_IRQ();
565 ed->HeadP = (ed->HeadP & 0x2) | (uint32_t)td_list; /* keep toggleCarry bit */
566 if (bIsNewED)
567 {
568 ed->HeadP = (uint32_t)td_list;
569 /* Link ED to OHCI Bulk List */
570 ed->NextED = _ohci->HcBulkHeadED;
571 _ohci->HcBulkHeadED = (uint32_t)ed;
572 }
573 ENABLE_OHCI_IRQ();
574 _ohci->HcControl |= USBH_HcControl_BLE_Msk; /* enable bulk list */
575 _ohci->HcCommandStatus = USBH_HcCommandStatus_BLF_Msk; /* start bulk list */
576
577 return 0;
578
579mem_out:
580 while (td_list != NULL)
581 {
582 td = td_list;
583 td_list = (TD_T *)td_list->NextTD;
584 free_ohci_TD(td);
585 }
586 free_ohci_ED(ed);
587 return USBH_ERR_MEMORY_OUT;
588}
589
590static int ohci_int_xfer(UTR_T *utr)
591{
592 UDEV_T *udev = utr->udev;
593 EP_INFO_T *ep = utr->ep;
594 ED_T *ed, *ied;
595 TD_T *td, *td_new;
596 uint32_t info;
597 int8_t bIsNewED = 0;
598
599 if (utr->data_len > 64) /* USB 1.1 interrupt transfer maximum packet size is 64 */
601
602 td_new = alloc_ohci_TD(utr); /* allocate a TD for dummy TD */
603 if (td_new == NULL)
604 return USBH_ERR_MEMORY_OUT;
605
606 ied = get_int_tree_head_node(ep->bInterval); /* get head node of this interval */
607
608 /*------------------------------------------------------------------------------------*/
609 /* Find if this ED was already in the list */
610 /*------------------------------------------------------------------------------------*/
611 info = ed_make_info(udev, ep);
612 ed = ied;
613 while (ed != NULL)
614 {
615 if (ed->Info == info)
616 break; /* Endpoint found */
617 ed = (ED_T *)ed->NextED;
618 }
619
620 if (ed == NULL) /* ED not found, create it */
621 {
622 bIsNewED = 1;
623 ed = alloc_ohci_ED(); /* allocate an Endpoint Descriptor */
624 if (ed == NULL)
625 return USBH_ERR_MEMORY_OUT;
626 ed->Info = info;
627 ed->HeadP = 0;
628 ed->bInterval = ep->bInterval;
629
630 td = alloc_ohci_TD(NULL); /* allocate the initial dummy TD for ED */
631 if (td == NULL)
632 {
633 free_ohci_ED(ed);
634 free_ohci_TD(td_new);
635 return USBH_ERR_MEMORY_OUT;
636 }
637 ed->HeadP = (uint32_t)td; /* Let both HeadP and TailP point to dummy TD */
638 ed->TailP = ed->HeadP;
639 }
640 else
641 {
642 td = (TD_T *)(ed->TailP & ~0xf); /* TailP always point to the dummy TD */
643 }
644 ep->hw_pipe = (void *)ed;
645
646 /*------------------------------------------------------------------------------------*/
647 /* Prepare TD */
648 /*------------------------------------------------------------------------------------*/
649 if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT)
650 info = (TD_CC | TD_R | TD_DP_OUT | TD_TYPE_INT);
651 else
652 info = (TD_CC | TD_R | TD_DP_IN | TD_TYPE_INT);
653
654 /* Keep data toggle */
655 info = (info & ~(1<<25)) | (td->Info & (1<<25));
656
657 /* fill this TD */
658 write_td(td, info, utr->buff, utr->data_len);
659 td->ed = ed;
660 td->NextTD = (uint32_t)td_new;
661 td->utr = utr;
662 utr->td_cnt = 1; /* increase TD count, for recalim counter */
663 utr->status = 0;
664
665 /*------------------------------------------------------------------------------------*/
666 /* Hook ED and TD list to HCCA interrupt table */
667 /*------------------------------------------------------------------------------------*/
668 DISABLE_OHCI_IRQ();
669
670 ed->TailP = (uint32_t)td_new;
671 if (bIsNewED)
672 {
673 /* Add to list of the same interval */
674 ed->NextED = ied->NextED;
675 ied->NextED = (uint32_t)ed;
676 }
677
678 ENABLE_OHCI_IRQ();
679
680 //printf("Link INT ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED);
681
682 _ohci->HcControl |= USBH_HcControl_PLE_Msk; /* periodic list enable */
683 return 0;
684}
685
686static int ohci_iso_xfer(UTR_T *utr)
687{
688 UDEV_T *udev = utr->udev;
689 EP_INFO_T *ep = utr->ep;
690 ED_T *ed, *ied;
691 TD_T *td, *td_list, *last_td;
692 int i;
693 uint32_t info;
694 uint32_t buff_addr;
695 int8_t bIsNewED = 0;
696
697 ied = get_int_tree_head_node(ep->bInterval); /* get head node of this interval */
698
699 /*------------------------------------------------------------------------------------*/
700 /* Find if this ED was already in the list */
701 /*------------------------------------------------------------------------------------*/
702 info = ed_make_info(udev, ep);
703 ed = ied;
704 while (ed != NULL)
705 {
706 if (ed->Info == info)
707 break; /* Endpoint found */
708 ed = (ED_T *)ed->NextED;
709 }
710
711 if (ed == NULL) /* ED not found, create it */
712 {
713 bIsNewED = 1;
714 ed = alloc_ohci_ED(); /* allocate an Endpoint Descriptor */
715 if (ed == NULL)
716 return USBH_ERR_MEMORY_OUT;
717 ed->Info = info;
718 ed->HeadP = 0;
719 ed->bInterval = ep->bInterval;
720 }
721 else
722
723 ep->hw_pipe = (void *)ed;
724
725 /*------------------------------------------------------------------------------------*/
726 /* Prepare TDs */
727 /*------------------------------------------------------------------------------------*/
728 if (utr->bIsoNewSched) /* Is the starting of isochronous streaming? */
729 ed->next_sf = _hcca.frame_no + OHCI_ISO_DELAY;
730
731 utr->td_cnt = 0;
732 utr->iso_sf = ed->next_sf;
733
734 last_td = NULL;
735 td_list = NULL;
736
737 for (i = 0; i < IF_PER_UTR; i++)
738 {
739 utr->iso_status[i] = USBH_ERR_NOT_ACCESS1;
740
741 td = alloc_ohci_TD(utr); /* allocate a TD */
742 if (td == NULL)
743 goto mem_out;
744 /* fill this TD */
745 buff_addr = (uint32_t)(utr->iso_buff[i]);
746 td->Info = (TD_CC | TD_TYPE_ISO) | ed->next_sf;
747 ed->next_sf += get_ohci_interval(ed->bInterval);
748 td->CBP = buff_addr & ~0xFFF;
749 td->BE = buff_addr + utr->iso_xlen[i] - 1;
750 td->PSW[0] = 0xE000 | (buff_addr & 0xFFF);
751
752 td->ed = ed;
753 utr->td_cnt++; /* increase TD count, for reclaim counter */
754
755 /* chain to end of TD list */
756 if (td_list == NULL)
757 td_list = td;
758 else
759 last_td->NextTD = (uint32_t)td;
760
761 last_td = td;
762 };
763
764 /*------------------------------------------------------------------------------------*/
765 /* Hook ED and TD list to HCCA interrupt table */
766 /*------------------------------------------------------------------------------------*/
767 utr->status = 0;
768 DISABLE_OHCI_IRQ();
769
770 if ((ed->HeadP & ~0x3) == 0)
771 ed->HeadP = (ed->HeadP & 0x2) | (uint32_t)td_list; /* keep toggleCarry bit */
772 else
773 {
774 /* find the tail of TDs under this ED */
775 td = (TD_T *)(ed->HeadP & ~0x3);
776 while (td->NextTD != 0)
777 {
778 td = (TD_T *)td->NextTD;
779 }
780 td->NextTD = (uint32_t)td_list;
781 }
782
783 if (bIsNewED)
784 {
785 /* Add to list of the same interval */
786 ed->NextED = ied->NextED;
787 ied->NextED = (uint32_t)ed;
788 }
789
790 ENABLE_OHCI_IRQ();
791 ED_debug("Link ISO ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED);
792 _ohci->HcControl |= USBH_HcControl_PLE_Msk | USBH_HcControl_IE_Msk; /* enable periodic list and isochronous transfer */
793
794 return 0;
795
796mem_out:
797 while (td_list != NULL)
798 {
799 td = td_list;
800 td_list = (TD_T *)td_list->NextTD;
801 free_ohci_TD(td);
802 }
803 free_ohci_ED(ed);
804 return USBH_ERR_MEMORY_OUT;
805}
806
807static UDEV_T * ohci_find_device_by_port(int port)
808{
809 UDEV_T *udev;
810
811 udev = g_udev_list;
812 while (udev != NULL)
813 {
814 if ((udev->parent == NULL) && (udev->port_num == port) &&
815 ((udev->speed == SPEED_LOW) || (udev->speed == SPEED_FULL)))
816 return udev;
817 udev = udev->next;
818 }
819 return NULL;
820}
821
822static int ohci_rh_port_reset(int port)
823{
824 int retry;
825 int reset_time;
826 uint32_t t0;
827
828 reset_time = PORT_RESET_TIME_MS;
829
830 for (retry = 0; retry < PORT_RESET_RETRY; retry++)
831 {
832 _ohci->HcRhPortStatus[port] = USBH_HcRhPortStatus_PRS_Msk;
833
834 t0 = get_ticks();
835 while (get_ticks() - t0 < (reset_time/10)+1)
836 {
837 /*
838 * If device is disconnected or port enabled, we can stop port reset.
839 */
840 if (((_ohci->HcRhPortStatus[port] & USBH_HcRhPortStatus_CCS_Msk) == 0) ||
842 goto port_reset_done;
843 }
844 reset_time += PORT_RESET_RETRY_INC_MS;
845 }
846
847 USB_debug("OHCI port %d - port reset failed!\n", port+1);
848 return USBH_ERR_PORT_RESET;
849
850port_reset_done:
851 if ((_ohci->HcRhPortStatus[port] & USBH_HcRhPortStatus_CCS_Msk) == 0) /* check again if device disconnected */
852 {
853 _ohci->HcRhPortStatus[port] = USBH_HcRhPortStatus_CSC_Msk; /* clear CSC */
855 }
856 return USBH_OK; /* port reset success */
857}
858
859static int ohci_rh_polling(void)
860{
861 int i, change = 0;
862 UDEV_T *udev;
863 int ret;
864
865 for (i = 0; i < 2; i++)
866 {
867 if (((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x1) && (i == 0))
868 continue; /* M480LD OHCI has no root hub port 0 */
869
870 /* clear unwanted port change status */
873
874 if ((_ohci->HcRhPortStatus[i] & USBH_HcRhPortStatus_CSC_Msk) == 0)
875 continue;
876
877 /*--------------------------------------------------------------------------------*/
878 /* connect status change */
879 /*--------------------------------------------------------------------------------*/
880
881 _ohci->HcRhPortStatus[i] = USBH_HcRhPortStatus_CSC_Msk; /* clear CSC */
882
883 if (_ohci->HcRhPortStatus[i] & USBH_HcRhPortStatus_CCS_Msk)
884 {
885 /*----------------------------------------------------------------------------*/
886 /* First of all, check if there's any previously connected device. */
887 /*----------------------------------------------------------------------------*/
888 while (1)
889 {
890 udev = ohci_find_device_by_port(i+1);
891 if (udev == NULL)
892 break;
893 disconnect_device(udev);
894 }
895
896 if (ohci_rh_port_reset(i) != USBH_OK)
897 continue;
898
899 /*
900 * Port reset success...
901 */
902 udev = alloc_device();
903 if (udev == NULL)
904 continue;
905
906 udev->parent = NULL;
907 udev->port_num = i+1;
908 if (_ohci->HcRhPortStatus[i] & USBH_HcRhPortStatus_LSDA_Msk)
909 udev->speed = SPEED_LOW;
910 else
911 udev->speed = SPEED_FULL;
912 udev->hc_driver = &ohci_driver;
913
914 ret = connect_device(udev);
915 if (ret < 0)
916 {
917 USB_error("connect_device error! [%d]\n", ret);
918 free_device(udev);
919 }
920
921 change = 1;
922 }
923 else
924 {
925 /*
926 * Device disconnected
927 */
928 while (1)
929 {
930 udev = ohci_find_device_by_port(i+1);
931 if (udev == NULL)
932 break;
933 disconnect_device(udev);
934 }
935 change = 1;
936 }
937 }
938 return change;
939}
940
941void td_done(TD_T *td)
942{
943 UTR_T *utr = td->utr;
944 uint32_t info;
945 int cc;
946
947 info = td->Info;
948
949 TD_debug("td_done: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td, td->Info, td->CBP, td->NextTD, td->BE);
950
951 /* ISO ... drivers see per-TD length/status */
952 if ((info & TD_TYPE_Msk) == TD_TYPE_ISO)
953 {
954 uint16_t sf;
955 int idx;
956
957 sf = info & 0xFFFF;
958 idx = ((sf + 0x10000 - utr->iso_sf) & 0xFFFF) / get_ohci_interval(td->ed->bInterval);
959 if (idx >= IF_PER_UTR)
960 {
961 USB_error("ISO invalid index!! %d, %d\n", sf, utr->iso_sf);
962 goto td_out;
963 }
964
965 cc = (td->PSW[0] >> 12) & 0xF;
966 if (cc == 0xF) /* this frame was not transferred */
967 {
968 USB_debug("ISO F %d N/A!\n", sf);
969 utr->iso_status[idx] = USBH_ERR_SCH_OVERRUN;
970 goto td_out;
971 }
972 if ((cc != 0) && (cc != CC_DATA_UNDERRUN))
973 {
974 utr->iso_status[idx] = USBH_ERR_CC_NO_ERR - cc;
975 goto td_out;
976 }
977 utr->iso_status[idx] = 0;
978 utr->iso_xlen[idx] = td->PSW[0] & 0x7FF;
979 }
980 else
981 {
982 cc = TD_CC_GET(info);
983
984 /* short packet is fine */
985 if ((cc != CC_NOERROR) && (cc != CC_DATA_UNDERRUN))
986 {
987 USB_error("TD error, CC = 0x%x\n", cc);
988 if (cc == CC_STALL)
989 utr->status = USBH_ERR_STALL;
990 else
991 utr->status = USBH_ERR_TRANSFER;
992 }
993
994 switch (info & TD_TYPE_Msk)
995 {
996 case TD_TYPE_CTRL:
997 if (info & TD_CTRL_DATA)
998 {
999 if (td->CBP == 0)
1000 utr->xfer_len += td->BE - td->buff_start + 1;
1001 else
1002 utr->xfer_len += td->CBP - td->buff_start;
1003 }
1004 break;
1005
1006 case TD_TYPE_BULK:
1007 case TD_TYPE_INT:
1008 if (td->CBP == 0)
1009 utr->xfer_len += td->BE - td->buff_start + 1;
1010 else
1011 utr->xfer_len += td->CBP - td->buff_start;
1012 break;
1013 }
1014 }
1015
1016td_out:
1017
1018 utr->td_cnt--;
1019
1020 /* If all TDs are done, call-back to requester. */
1021 if (utr->td_cnt == 0)
1022 {
1023 utr->bIsTransferDone = 1;
1024 if (utr->func)
1025 utr->func(utr);
1026 }
1027}
1028
1029/* in IRQ context */
1030static void remove_ed()
1031{
1032 ED_T *ed, *ed_p, *ied;
1033 TD_T *td, *td_next;
1034 UTR_T *utr;
1035 int found;
1036
1037 while (ed_remove_list != NULL)
1038 {
1039 ED_debug("Remove ED: 0x%x, %d\n", (int)ed_remove_list, ed_remove_list->bInterval);
1040 ed_p = ed_remove_list;
1041 found = 0;
1042
1043 /*--------------------------------------------------------------------------------*/
1044 /* Remove endpoint from Control List if found */
1045 /*--------------------------------------------------------------------------------*/
1046 if ((ed_p->Info & ED_EP_ADDR_Msk) == 0)
1047 {
1048 if (_ohci->HcControlHeadED == (uint32_t)ed_p)
1049 {
1050 _ohci->HcControlHeadED = (uint32_t)ed_p->NextED;
1051 found = 1;
1052 }
1053 else
1054 {
1055 ed = (ED_T *)_ohci->HcControlHeadED;
1056 while (ed != NULL)
1057 {
1058 if (ed->NextED == (uint32_t)ed_p)
1059 {
1060 ed->NextED = ed_p->NextED;
1061 found = 1;
1062 }
1063 ed = (ED_T *)ed->NextED;
1064 }
1065 }
1066 }
1067
1068 /*--------------------------------------------------------------------------------*/
1069 /* Remove INT or ISO endpoint from HCCA interrupt table */
1070 /*--------------------------------------------------------------------------------*/
1071 else if (ed_p->bInterval > 0)
1072 {
1073 ied = get_int_tree_head_node(ed_p->bInterval);
1074
1075 ed = ied;
1076 while (ed != NULL)
1077 {
1078 if (ed->NextED == (uint32_t)ed_p)
1079 {
1080 ed->NextED = ed_p->NextED;
1081 found = 1;
1082 break;
1083 }
1084 ed = (ED_T *)ed->NextED;
1085 }
1086 }
1087
1088 /*--------------------------------------------------------------------------------*/
1089 /* Remove endpoint from Bulk List if found */
1090 /*--------------------------------------------------------------------------------*/
1091 else
1092 {
1093 if (_ohci->HcBulkHeadED == (uint32_t)ed_p)
1094 {
1095 ed = (ED_T *)ed_p;
1096 _ohci->HcBulkHeadED = ed_p->NextED;
1097 found = 1;
1098 }
1099 else
1100 {
1101 ed = (ED_T *)_ohci->HcBulkHeadED;
1102 while (ed != NULL)
1103 {
1104 if (ed->NextED == (uint32_t)ed_p)
1105 {
1106 ed->NextED = ed_p->NextED;
1107 found = 1;
1108 }
1109 ed = (ED_T *)ed->NextED;
1110 }
1111 }
1112 }
1113
1114 /*--------------------------------------------------------------------------------*/
1115 /* Remove and free all TDs under this endpoint */
1116 /*--------------------------------------------------------------------------------*/
1117 if (found)
1118 {
1119 td = (TD_T *)(ed_p->HeadP & ~0x3);
1120 if (td != NULL)
1121 {
1122 while (td != NULL)
1123 {
1124 utr = td->utr;
1125 td_next = (TD_T *)td->NextTD;
1126 free_ohci_TD(td);
1127 td = td_next;
1128
1129 utr->td_cnt--;
1130 if (utr->td_cnt == 0)
1131 {
1132 utr->status = USBH_ERR_ABORT;
1133 utr->bIsTransferDone = 1;
1134 if (utr->func)
1135 utr->func(utr);
1136 }
1137 }
1138 }
1139 }
1140
1141 /*
1142 * Done. Remove this ED from [ed_remove_list] and free it.
1143 */
1144 ed_remove_list = ed_p->next;
1145 free_ohci_ED(ed_p);
1146 }
1147}
1148
1149
1150//static irqreturn_t ohci_irq (struct usb_hcd *hcd)
1151void OHCI_IRQHandler(void)
1152{
1153 TD_T *td, *td_prev, *td_next;
1154 uint32_t int_sts;
1155
1156 int_sts = _ohci->HcInterruptStatus;
1157
1158 //USB_debug("ohci int_sts = 0x%x\n", int_sts);
1159
1160 if ((_ohci->HcInterruptEnable & USBH_HcInterruptEnable_SF_Msk) &&
1162 {
1163 int_sts &= ~USBH_HcInterruptStatus_SF_Msk;
1164
1165 _ohci->HcInterruptDisable = USBH_HcInterruptDisable_SF_Msk;
1166 remove_ed();
1167 _ohci->HcInterruptStatus = USBH_HcInterruptStatus_SF_Msk;
1168 }
1169
1170 if (int_sts & USBH_HcInterruptStatus_WDH_Msk)
1171 {
1172 //printf("!%02x\n", _ohci->HcFmNumber & 0xff);
1173 int_sts &= ~USBH_HcInterruptStatus_WDH_Msk;
1174 /*
1175 * reverse done list
1176 */
1177 td = (TD_T *)(_hcca.done_head & TD_ADDR_MASK);
1178 _hcca.done_head = 0;
1179 td_prev = NULL;
1180 _ohci->HcInterruptStatus = USBH_HcInterruptStatus_WDH_Msk;
1181
1182 while (td != NULL)
1183 {
1184 //TD_debug("Done list TD 0x%x => 0x%x\n", (int)td, (int)td->NextTD);
1185 td_next = (TD_T *)(td->NextTD & TD_ADDR_MASK);
1186 td->NextTD = (uint32_t)td_prev;
1187 td_prev = td;
1188 td = td_next;
1189 }
1190 td = td_prev; /* first TD of the reversed done list */
1191
1192 /*
1193 * reclaim TDs
1194 */
1195 while (td != NULL)
1196 {
1197 TD_debug("Reclaim TD 0x%x, next 0x%x\n", (int)td, td->NextTD);
1198 td_next = (TD_T *)td->NextTD;
1199 td_done(td);
1200 free_ohci_TD(td);
1201 td = td_next;
1202 }
1203 }
1204
1205 if (int_sts & USBH_HcInterruptStatus_RHSC_Msk)
1206 {
1207 _ohci->HcInterruptDisable = USBH_HcInterruptDisable_RHSC_Msk;
1208 }
1209
1210 _ohci->HcInterruptStatus = int_sts;
1211}
1212
1213#ifdef ENABLE_DEBUG_MSG
1214
1215void dump_ohci_int_table()
1216{
1217 int i;
1218 ED_T *ed;
1219
1220 for (i = 0; i < 32; i++)
1221// for (i = 0; i < 1; i++)
1222
1223 {
1224 USB_debug("%02d: ", i);
1225
1226 ed = (ED_T *)_hcca.int_table[i];
1227
1228 while (ed != NULL)
1229 {
1230 USB_debug("0x%x (0x%x) => ", (int)ed, ed->HeadP);
1231 ed = (ED_T *)ed->NextED;
1232 }
1233 printf("0\n");
1234 }
1235}
1236
1237void dump_ohci_regs()
1238{
1239 USB_debug("Dump OCHI registers:\n");
1240 USB_debug(" HcRevision = 0x%x\n", _ohci->HcRevision);
1241 USB_debug(" HcControl = 0x%x\n", _ohci->HcControl);
1242 USB_debug(" HcCommandStatus = 0x%x\n", _ohci->HcCommandStatus);
1243 USB_debug(" HcInterruptStatus = 0x%x\n", _ohci->HcInterruptStatus);
1244 USB_debug(" HcInterruptEnable = 0x%x\n", _ohci->HcInterruptEnable);
1245 USB_debug(" HcInterruptDisable = 0x%x\n", _ohci->HcInterruptDisable);
1246 USB_debug(" HcHCCA = 0x%x\n", _ohci->HcHCCA);
1247 USB_debug(" HcPeriodCurrentED = 0x%x\n", _ohci->HcPeriodCurrentED);
1248 USB_debug(" HcControlHeadED = 0x%x\n", _ohci->HcControlHeadED);
1249 USB_debug(" HcControlCurrentED = 0x%x\n", _ohci->HcControlCurrentED);
1250 USB_debug(" HcBulkHeadED = 0x%x\n", _ohci->HcBulkHeadED);
1251 USB_debug(" HcBulkCurrentED = 0x%x\n", _ohci->HcBulkCurrentED);
1252 USB_debug(" HcDoneHead = 0x%x\n", _ohci->HcDoneHead);
1253 USB_debug(" HcFmInterval = 0x%x\n", _ohci->HcFmInterval);
1254 USB_debug(" HcFmRemaining = 0x%x\n", _ohci->HcFmRemaining);
1255 USB_debug(" HcFmNumber = 0x%x\n", _ohci->HcFmNumber);
1256 USB_debug(" HcPeriodicStart = 0x%x\n", _ohci->HcPeriodicStart);
1257 USB_debug(" HcLSThreshold = 0x%x\n", _ohci->HcLSThreshold);
1258 USB_debug(" HcRhDescriptorA = 0x%x\n", _ohci->HcRhDescriptorA);
1259 USB_debug(" HcRhDescriptorB = 0x%x\n", _ohci->HcRhDescriptorB);
1260 USB_debug(" HcRhStatus = 0x%x\n", _ohci->HcRhStatus);
1261 USB_debug(" HcRhPortStatus0 = 0x%x\n", _ohci->HcRhPortStatus[0]);
1262 USB_debug(" HcRhPortStatus1 = 0x%x\n", _ohci->HcRhPortStatus[1]);
1263 USB_debug(" HcPhyControl = 0x%x\n", _ohci->HcPhyControl);
1264 USB_debug(" HcMiscControl = 0x%x\n", _ohci->HcMiscControl);
1265}
1266
1267void dump_ohci_ports()
1268{
1269 USB_debug("_ohci port0=0x%x, port1=0x%x\n", _ohci->HcRhPortStatus[0], _ohci->HcRhPortStatus[1]);
1270}
1271
1272#endif // ENABLE_DEBUG_MSG
1273
1274HC_DRV_T ohci_driver =
1275{
1276 ohci_init, /* init */
1277 ohci_shutdown, /* shutdown */
1278 ohci_suspend, /* suspend */
1279 ohci_resume, /* resume */
1280 ohci_ctrl_xfer, /* ctrl_xfer */
1281 ohci_bulk_xfer, /* bulk_xfer */
1282 ohci_int_xfer, /* int_xfer */
1283 ohci_iso_xfer, /* iso_xfer */
1284 ohci_quit_xfer, /* quit_xfer */
1285 ohci_rh_port_reset, /* rthub_port_reset */
1286 ohci_rh_polling /* rthub_polling */
1287};
1288
1290
1291/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/
void *__dso_handle __attribute__((weak))
Definition: _syscalls.c:35
NuMicro peripheral access layer header file.
@ USBH_IRQn
Definition: M480.h:134
#define NULL
NULL pointer.
Definition: M480.h:605
#define USBH
Definition: M480.h:388
#define SYS
Definition: M480.h:367
#define SYS_CSERVER_VERSION_Msk
Definition: sys_reg.h:6034
#define USBH_HcControl_CBSR_Pos
Definition: usbh_reg.h:1223
#define USBH_HcInterruptEnable_WDH_Msk
Definition: usbh_reg.h:1275
#define USBH_HcCommandStatus_CLF_Msk
Definition: usbh_reg.h:1245
#define USBH_HcRhPortStatus_PESC_Msk
Definition: usbh_reg.h:1416
#define USBH_HcInterruptDisable_SF_Msk
Definition: usbh_reg.h:1299
#define USBH_HcRhPortStatus_PPS_Msk
Definition: usbh_reg.h:1407
#define USBH_HcInterruptDisable_MIE_Msk
Definition: usbh_reg.h:1311
#define USBH_HcInterruptDisable_RHSC_Msk
Definition: usbh_reg.h:1308
#define USBH_HcRhStatus_DRWE_Msk
Definition: usbh_reg.h:1380
#define USBH_HcCommandStatus_HCR_Msk
Definition: usbh_reg.h:1242
#define USBH_HcRhStatus_LPSC_Msk
Definition: usbh_reg.h:1383
#define USBH_HcRhPortStatus_CSC_Msk
Definition: usbh_reg.h:1413
#define USBH_HcRhPortStatus_PRSC_Msk
Definition: usbh_reg.h:1425
#define USBH_HcInterruptStatus_RHSC_Msk
Definition: usbh_reg.h:1269
#define USBH_HcCommandStatus_BLF_Msk
Definition: usbh_reg.h:1248
#define USBH_HcInterruptEnable_RD_Msk
Definition: usbh_reg.h:1281
#define USBH_HcRhPortStatus_LSDA_Msk
Definition: usbh_reg.h:1410
#define USBH_HcControl_PLE_Msk
Definition: usbh_reg.h:1227
#define USBH_HcControl_BLE_Msk
Definition: usbh_reg.h:1236
#define USBH_HcRhPortStatus_PSSC_Msk
Definition: usbh_reg.h:1419
#define USBH_HcRhStatus_LPS_Msk
Definition: usbh_reg.h:1374
#define USBH_HcRhPortStatus_PRS_Msk
Definition: usbh_reg.h:1404
#define USBH_HcRhStatus_OCI_Msk
Definition: usbh_reg.h:1377
#define USBH_HcControl_CLE_Msk
Definition: usbh_reg.h:1233
#define USBH_HcInterruptEnable_RHSC_Msk
Definition: usbh_reg.h:1287
#define USBH_HcControl_HCFS_Pos
Definition: usbh_reg.h:1238
#define USBH_HcRhPortStatus_PES_Msk
Definition: usbh_reg.h:1395
#define USBH_HcRhPortStatus_OCIC_Msk
Definition: usbh_reg.h:1422
#define USBH_HcInterruptEnable_MIE_Msk
Definition: usbh_reg.h:1290
#define USBH_HcControl_IE_Msk
Definition: usbh_reg.h:1230
#define USBH_HcInterruptEnable_SF_Msk
Definition: usbh_reg.h:1278
#define USBH_HcRhPortStatus_CCS_Msk
Definition: usbh_reg.h:1392
#define USBH_HcInterruptStatus_WDH_Msk
Definition: usbh_reg.h:1257
#define USBH_HcInterruptStatus_SF_Msk
Definition: usbh_reg.h:1260
#define USBH_ERR_SCH_OVERRUN
Definition: usbh_lib.h:49
#define USBH_ERR_TRANSFER
Definition: usbh_lib.h:45
#define USBH_OK
Definition: usbh_lib.h:31
#define USBH_ERR_INVALID_PARAM
Definition: usbh_lib.h:38
#define USBH_ERR_ABORT
Definition: usbh_lib.h:47
#define USBH_ERR_PORT_RESET
Definition: usbh_lib.h:48
#define USBH_ERR_OHCI_EP_BUSY
Definition: usbh_lib.h:72
#define USBH_ERR_CC_NO_ERR
Definition: usbh_lib.h:56
#define USBH_ERR_NOT_FOUND
Definition: usbh_lib.h:39
#define USBH_ERR_NOT_ACCESS1
Definition: usbh_lib.h:69
#define USBH_ERR_STALL
Definition: usbh_lib.h:60
#define USBH_ERR_MEMORY_OUT
Definition: usbh_lib.h:32
#define USBH_ERR_DISCONNECTED
Definition: usbh_lib.h:50
uint32_t get_ticks(void)
A function return current tick count.
USB Host hub class driver header file.
USB OHCI host controller driver header file.
USB Host library header file.