M480 BSP  V3.05.001
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
30 HCCA_T _hcca;
31 #else
32 HCCA_T _hcca __attribute__((aligned(256)));
33 #endif
34 
35 ED_T * _Ied[6];
36 
37 
38 static ED_T *ed_remove_list;
39 
40 static 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 
68 static 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 
103 static 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 
144 static 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 
157 static 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 
172 static 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 
220 static 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 
239 static 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 
250 static 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  */
263 static 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 
293 uint32_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 
335 static 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 
344 static 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 
467 static 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 
579 mem_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 
590 static 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 */
600  return USBH_ERR_INVALID_PARAM;
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 
686 static 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 
796 mem_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 
807 static 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 
822 static 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 
850 port_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 */
854  return USBH_ERR_DISCONNECTED;
855  }
856  return USBH_OK; /* port reset success */
857 }
858 
859 static 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 */
871  _ohci->HcRhPortStatus[i] = USBH_HcRhPortStatus_OCIC_Msk | USBH_HcRhPortStatus_PRSC_Msk |
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 
941 void 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 
1016 td_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 */
1030 static 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)
1151 void 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) &&
1161  (int_sts & USBH_HcInterruptStatus_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 
1215 void 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 
1237 void 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 
1267 void 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 
1274 HC_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. ***/
#define USBH_ERR_SCH_OVERRUN
Definition: usbh_lib.h:49
#define USBH_ERR_NOT_FOUND
Definition: usbh_lib.h:39
#define USBH_ERR_INVALID_PARAM
Definition: usbh_lib.h:38
#define USBH_HcRhPortStatus_PRSC_Msk
Definition: usbh_reg.h:1425
#define USBH_HcRhDescriptorA_PSM_Msk
Definition: usbh_reg.h:1362
#define USBH_HcRhPortStatus_CCS_Msk
Definition: usbh_reg.h:1392
#define USBH_HcInterruptDisable_SF_Msk
Definition: usbh_reg.h:1299
#define USBH_HcRhPortStatus_OCIC_Msk
Definition: usbh_reg.h:1422
#define USBH_HcInterruptStatus_RHSC_Msk
Definition: usbh_reg.h:1269
#define USBH_HcRhPortStatus_LSDA_Msk
Definition: usbh_reg.h:1410
#define USBH_HcInterruptEnable_RD_Msk
Definition: usbh_reg.h:1281
#define USBH_HcControl_CLE_Msk
Definition: usbh_reg.h:1233
#define USBH_HcCommandStatus_BLF_Msk
Definition: usbh_reg.h:1248
#define USBH_HcInterruptEnable_RHSC_Msk
Definition: usbh_reg.h:1287
#define USBH_ERR_TRANSFER
Definition: usbh_lib.h:45
NuMicro peripheral access layer header file.
#define USBH_HcInterruptDisable_RHSC_Msk
Definition: usbh_reg.h:1308
#define SYS
Definition: M480.h:367
USB Host hub class driver header file.
#define USBH_HcInterruptStatus_SF_Msk
Definition: usbh_reg.h:1260
#define USBH_ERR_NOT_ACCESS1
Definition: usbh_lib.h:69
#define SYS_CSERVER_VERSION_Msk
Definition: sys_reg.h:6034
#define USBH_HcCommandStatus_CLF_Msk
Definition: usbh_reg.h:1245
#define USBH_ERR_STALL
Definition: usbh_lib.h:60
void *__dso_handle __attribute__((weak))
Definition: _syscalls.c:35
#define USBH_HcRhStatus_DRWE_Msk
Definition: usbh_reg.h:1380
#define USBH_ERR_CC_NO_ERR
Definition: usbh_lib.h:56
#define USBH_HcRhPortStatus_PPS_Msk
Definition: usbh_reg.h:1407
#define USBH_HcControl_IE_Msk
Definition: usbh_reg.h:1230
#define USBH_HcInterruptEnable_WDH_Msk
Definition: usbh_reg.h:1275
#define USBH_HcControl_CBSR_Pos
Definition: usbh_reg.h:1223
#define USBH_HcControl_BLE_Msk
Definition: usbh_reg.h:1236
#define USBH_ERR_ABORT
Definition: usbh_lib.h:47
#define USBH_ERR_PORT_RESET
Definition: usbh_lib.h:48
uint32_t get_ticks(void)
A function return current tick count.
#define USBH_HcInterruptStatus_WDH_Msk
Definition: usbh_reg.h:1257
#define USBH_HcInterruptEnable_SF_Msk
Definition: usbh_reg.h:1278
#define USBH_HcControl_HCFS_Msk
Definition: usbh_reg.h:1239
#define USBH_ERR_MEMORY_OUT
Definition: usbh_lib.h:32
#define USBH
Definition: M480.h:388
#define USBH_ERR_DISCONNECTED
Definition: usbh_lib.h:50
USB OHCI host controller driver header file.
#define USBH_HcControl_HCFS_Pos
Definition: usbh_reg.h:1238
UDEV_T * udev
Definition: usbh_uac.h:111
#define USBH_HcRhPortStatus_PES_Msk
Definition: usbh_reg.h:1395
#define USBH_HcCommandStatus_HCR_Msk
Definition: usbh_reg.h:1242
#define USBH_HcRhPortStatus_PSSC_Msk
Definition: usbh_reg.h:1419
#define USBH_HcInterruptEnable_MIE_Msk
Definition: usbh_reg.h:1290
USB Host library header file.
#define USBH_HcControl_PLE_Msk
Definition: usbh_reg.h:1227
#define USBH_HcRhPortStatus_PESC_Msk
Definition: usbh_reg.h:1416
#define USBH_HcRhPortStatus_PRS_Msk
Definition: usbh_reg.h:1404
#define USBH_ERR_OHCI_EP_BUSY
Definition: usbh_lib.h:72
#define USBH_HcInterruptDisable_MIE_Msk
Definition: usbh_reg.h:1311
#define NULL
NULL pointer.
Definition: M480.h:604
#define USBH_HcRhPortStatus_CSC_Msk
Definition: usbh_reg.h:1413
#define USBH_OK
Definition: usbh_lib.h:31
#define USBH_HcRhStatus_LPSC_Msk
Definition: usbh_reg.h:1383
#define USBH_HcRhStatus_OCI_Msk
Definition: usbh_reg.h:1377
#define USBH_HcRhStatus_LPS_Msk
Definition: usbh_reg.h:1374