1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2017-10-30 ZYH the first version
9 * 2019-12-19 tyustli port to stm32 series
10 * 2021-01-19 Leslie Lee port to imxrt series
11 */
12 #include <rtthread.h>
13
14 #if defined(BSP_USB0_HOST) || defined(BSP_USB1_HOST)
15 #include "drv_usbh.h"
16 #include <usb/include/usb_host_config.h>
17 #include <usb/include/usb.h>
18 #include <usb/phy/usb_phy.h>
19 #include <usb/host/usb_host.h>
20 #include <usb/host/usb_host_hci.h>
21 #include <usb/host/usb_host_ehci.h>
22 #include <rtdevice.h>
23
24 //#define DRV_DEBUG
25 #define LOG_TAG "drv.usb.host"
26 #include <drv_log.h>
27
28 /* USB PHY configuration */
29 #ifndef BOARD_USB_PHY_D_CAL
30 #ifdef SOC_IMXRT1170_SERIES
31 #define BOARD_USB_PHY_D_CAL (0x07U)
32 #else
33 #define BOARD_USB_PHY_D_CAL (0x0CU)
34 #endif
35 #endif
36 #ifndef BOARD_USB_PHY_TXCAL45DP
37 #define BOARD_USB_PHY_TXCAL45DP (0x06U)
38 #endif
39 #ifndef BOARD_USB_PHY_TXCAL45DM
40 #define BOARD_USB_PHY_TXCAL45DM (0x06U)
41 #endif
42
43 #define USB_HOST_INTERRUPT_PRIORITY 6
44
45 /* Allocate the memory for the heap. */
46 #if defined(configAPPLICATION_ALLOCATED_HEAP) && (configAPPLICATION_ALLOCATED_HEAP)
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)47 USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t ucHeap[configTOTAL_HEAP_SIZE];
48 #endif
49
50 enum
51 {
52 #ifdef BSP_USB0_HOST
53 USBH0_INDEX,
54 #endif
55 #ifdef BSP_USB1_HOST
56 USBH1_INDEX,
57 #endif
58 };
59
60 struct imxrt_usb_host_pipe
61 {
62 usb_host_pipe_handle pipe_handle;
63 struct rt_completion urb_completion;
64 usb_status_t transfer_status;
65 };
66
67 struct imxrt_usb_host
68 {
69 struct uhcd uhcd;
70 usb_host_handle host_handle;
71 usb_device_handle device_handle;
72 struct imxrt_usb_host_pipe pipes[16];
73 volatile rt_bool_t connect_status;
74 char *name;
75 };
76
77 static struct imxrt_usb_host imxrt_usb_host_obj[] =
78 {
79 #ifdef BSP_USB0_HOST
80 {
81 .connect_status = RT_FALSE,
82 .name = "usbh0"
83 },
84 #endif
85 #ifdef BSP_USB1_HOST
86 {
87 .connect_status = RT_FALSE,
88 .name = "usbh1"
89 },
90 #endif
91 };
92
_imxrt_usb_host_send_callback(void * param,usb_host_transfer_t * transfer,usb_status_t status)93 static void _imxrt_usb_host_send_callback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
94 {
95 struct imxrt_usb_host_pipe *pipe = (struct imxrt_usb_host_pipe *)param;
96 pipe->transfer_status = status;
97 rt_completion_done(&pipe->urb_completion);
98 }
99
100
101 /*!
102 * @brief Initializes USB specific setting that was not set by the Clocks tool.
103 */
USB_HostClockInit(usb_controller_index_t controller_id)104 static void USB_HostClockInit(usb_controller_index_t controller_id)
105 {
106 uint32_t usbClockFreq;
107 usb_phy_config_struct_t phyConfig = {
108 BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
109 };
110
111 usbClockFreq = 24000000;
112
113 if (controller_id == kUSB_ControllerEhci0)
114 {
115 CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, usbClockFreq);
116 CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, usbClockFreq);
117 }
118 else
119 {
120 CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, usbClockFreq);
121 CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, usbClockFreq);
122 }
123
124 USB_EhciPhyInit(controller_id, 24000000U, &phyConfig);
125 }
126
127 /*!
128 * @brief Enables interrupt service routines for device.
129 */
USB_HostIsrEnable(usb_controller_index_t controller_id)130 void USB_HostIsrEnable(usb_controller_index_t controller_id)
131 {
132 uint8_t irqNumber;
133 #if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U))
134 IRQn_Type usbHOSTEhciIrq[] = USBHS_IRQS;
135 irqNumber = usbHOSTEhciIrq[controller_id - kUSB_ControllerEhci0];
136 #endif
137 /* Install isr, set priority, and enable IRQ. */
138 #if defined(__GIC_PRIO_BITS)
139 GIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY);
140 #else
141 NVIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY);
142 #endif
143 EnableIRQ((IRQn_Type)irqNumber);
144 }
145
146 #ifdef BSP_USB0_HOST
USB_OTG1_IRQHandler(void)147 void USB_OTG1_IRQHandler(void)
148 {
149 /* enter interrupt */
150 rt_interrupt_enter();
151
152 USB_HostEhciIsrFunction(imxrt_usb_host_obj[USBH0_INDEX].host_handle);
153 /* leave interrupt */
154 rt_interrupt_leave();
155 }
156
_ehci0_reset_port(rt_uint8_t port)157 static rt_err_t _ehci0_reset_port(rt_uint8_t port)
158 {
159 // No reset port function available
160 return RT_EOK;
161 }
162
163 static uint8_t _ehci0_pipe_buf[64];
164 static uint8_t _ehci0_pipe_idx;
165
_ehci0_pipe_xfer(upipe_t pipe,rt_uint8_t token,void * buffer,int nbytes,int timeouts)166 static int _ehci0_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
167 {
168 // int timeout = timeouts;
169
170 if (!imxrt_usb_host_obj[USBH0_INDEX].connect_status)
171 {
172 return -1;
173 }
174 usb_host_transfer_t *transfer;
175 if (imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle == NULL)
176 {
177 LOG_D("error operation on null pipe");
178 return -1;
179 }
180 if (USB_HostMallocTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, &transfer) != kStatus_USB_Success)
181 {
182 LOG_D("error to get transfer");
183 return -1;
184 }
185 transfer->transferBuffer = buffer;
186 transfer->transferLength = nbytes;
187 transfer->transferSofar = 0;
188 transfer->callbackFn = _imxrt_usb_host_send_callback;
189 transfer->callbackParam = &(imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index]);
190 transfer->direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT;
191 if (pipe->ep.bmAttributes == USB_ENDPOINT_CONTROL)
192 {
193 if (token == USBH_PID_SETUP)
194 {
195 struct urequest *setup = (struct urequest *)buffer;
196 transfer->setupStatus = 0;
197 transfer->setupPacket->bmRequestType = setup->request_type;
198 transfer->setupPacket->bRequest = setup->bRequest;
199 transfer->setupPacket->wIndex = setup->wIndex;
200 transfer->setupPacket->wLength = setup->wLength;
201 transfer->setupPacket->wValue = setup->wValue;
202 transfer->transferBuffer = RT_NULL;
203 transfer->transferLength = 0;
204 transfer->next = RT_NULL;
205 if ((transfer->setupPacket->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN)
206 {
207 transfer->direction = USB_IN;
208 transfer->transferBuffer = _ehci0_pipe_buf;
209 transfer->transferLength = setup->wLength;
210 _ehci0_pipe_idx = 0;
211 }
212 else
213 {
214 transfer->direction = USB_OUT;
215 }
216 }
217 else
218 {
219 rt_memcpy(buffer, _ehci0_pipe_buf + _ehci0_pipe_idx, nbytes);
220 imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].transfer_status = kStatus_USB_Success;
221 transfer->transferSofar = nbytes;
222 _ehci0_pipe_idx += nbytes;
223 if (_ehci0_pipe_idx >= 64)
224 {
225 _ehci0_pipe_idx = 0;
226 }
227 goto _ehci0_pipe_xfer_finish;
228 }
229
230 }
231 rt_completion_init(&(imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].urb_completion));
232 if (USB_HostEhciWritePipe(((usb_host_instance_t *)imxrt_usb_host_obj[USBH0_INDEX].host_handle)->controllerHandle, imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle, transfer) != kStatus_USB_Success)
233 {
234 LOG_D("usb host failed to send");
235 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
236 return -1;
237 }
238 if (-RT_ETIMEOUT == rt_completion_wait(&(imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].urb_completion), RT_WAITING_FOREVER))
239 {
240 LOG_D("usb transfer timeout");
241 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
242 return -1;
243 }
244 _ehci0_pipe_xfer_finish:
245 switch (imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].transfer_status)
246 {
247 case kStatus_USB_Success:
248 {
249 LOG_D("ok");
250 pipe->status = UPIPE_STATUS_OK;
251 if (pipe->callback != RT_NULL)
252 {
253 pipe->callback(pipe);
254 }
255 size_t size = transfer->transferSofar;
256 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
257 if (pipe->ep.bEndpointAddress & 0x80)
258 {
259 return size;
260 }
261 else if (pipe->ep.bEndpointAddress & 0x00)
262 {
263 return size;
264 }
265 return nbytes;
266 break;
267 }
268 case kStatus_USB_TransferStall:
269 {
270 LOG_D("stall");
271 pipe->status = UPIPE_STATUS_STALL;
272 if (pipe->callback != RT_NULL)
273 {
274 pipe->callback(pipe);
275 }
276 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
277 return -1;
278 break;
279 }
280 case kStatus_USB_TransferFailed:
281 default:
282 {
283 LOG_D("error");
284 pipe->status = UPIPE_STATUS_ERROR;
285 if (pipe->callback != RT_NULL)
286 {
287 pipe->callback(pipe);
288 }
289 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer);
290 return -1;
291 break;
292 }
293 }
294 }
295
296 static rt_uint16_t _ehci0_pipe_index = 0;
_ehci0_get_free_pipe_index(void)297 static rt_uint8_t _ehci0_get_free_pipe_index(void)
298 {
299 rt_uint8_t idx;
300 for (idx = 1; idx < 16; idx++)
301 {
302 if (!(_ehci0_pipe_index & (0x01 << idx)))
303 {
304 _ehci0_pipe_index |= (0x01 << idx);
305 return idx;
306 }
307 }
308 return 0xff;
309 }
310
_ehci0_free_pipe_index(rt_uint8_t index)311 static void _ehci0_free_pipe_index(rt_uint8_t index)
312 {
313 _ehci0_pipe_index &= ~(0x01 << index);
314 }
315
_ehci0_open_pipe(upipe_t pipe)316 static rt_err_t _ehci0_open_pipe(upipe_t pipe)
317 {
318 pipe->pipe_index = _ehci0_get_free_pipe_index();
319 if (pipe->pipe_index == 0xFF)
320 {
321 return -RT_ERROR;
322 }
323 usb_host_pipe_init_t pipe_init =
324 {
325 .devInstance = imxrt_usb_host_obj[USBH0_INDEX].device_handle,
326 .pipeType = pipe->ep.bmAttributes,
327 .direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT,
328 .endpointAddress = (pipe->ep.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK),
329 .interval = pipe->ep.bInterval,
330 .maxPacketSize = (uint16_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK),
331 .numberPerUframe = (uint8_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK),
332 .nakCount = USB_HOST_CONFIG_MAX_NAK,
333 };
334 USB_HostOpenPipe(imxrt_usb_host_obj[USBH0_INDEX].host_handle, &imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle, &pipe_init);
335 return RT_EOK;
336 }
337
_ehci0_close_pipe(upipe_t pipe)338 static rt_err_t _ehci0_close_pipe(upipe_t pipe)
339 {
340 (void)USB_HostClosePipe(imxrt_usb_host_obj[USBH0_INDEX].host_handle, imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle);
341 _ehci0_free_pipe_index(pipe->pipe_index);
342 return RT_EOK;
343 }
344
345 static struct uhcd_ops _ehci0_uhcd_ops =
346 {
347 _ehci0_reset_port,
348 _ehci0_pipe_xfer,
349 _ehci0_open_pipe,
350 _ehci0_close_pipe,
351 };
352
usb0_host_callback(usb_device_handle handle,usb_host_configuration_handle config_handle,rt_uint32_t event_code)353 static usb_status_t usb0_host_callback(usb_device_handle handle, usb_host_configuration_handle config_handle, rt_uint32_t event_code)
354 {
355 usb_status_t status = kStatus_USB_Success;
356
357 switch (event_code)
358 {
359 case kUSB_HostEventAttach:
360 if (!imxrt_usb_host_obj[USBH0_INDEX].connect_status)
361 {
362 imxrt_usb_host_obj[USBH0_INDEX].connect_status = RT_TRUE;
363 imxrt_usb_host_obj[USBH0_INDEX].device_handle = handle;
364 LOG_D("usb connected");
365 rt_usbh_root_hub_connect_handler(&(imxrt_usb_host_obj[USBH0_INDEX].uhcd), OTG_PORT, RT_TRUE);
366 }
367 break;
368
369 case kUSB_HostEventNotSupported:
370 LOG_D("usb device not supported");
371 break;
372
373 case kUSB_HostEventEnumerationDone:
374 LOG_D("enumeration done");
375 break;
376
377 case kUSB_HostEventDetach:
378 if (imxrt_usb_host_obj[USBH0_INDEX].connect_status)
379 {
380 imxrt_usb_host_obj[USBH0_INDEX].connect_status = RT_FALSE;
381 imxrt_usb_host_obj[USBH0_INDEX].device_handle = handle;
382 LOG_D("usb disconnnect");
383 rt_usbh_root_hub_disconnect_handler(&(imxrt_usb_host_obj[USBH0_INDEX].uhcd), OTG_PORT);
384 (void)USB_HostCloseDeviceInterface(handle, NULL);
385 }
386 break;
387
388 default:
389 break;
390 }
391 return status;
392 }
393
394 rt_thread_t usbh0_thread;
395
_ehci0_usbh_thread(void * param)396 static void _ehci0_usbh_thread(void* param)
397 {
398 while (1)
399 {
400 USB_HostEhciTaskFunction(imxrt_usb_host_obj[USBH0_INDEX].host_handle);
401 }
402 }
403
_ehci0_usbh_init(rt_device_t device)404 static rt_err_t _ehci0_usbh_init(rt_device_t device)
405 {
406 USB_HostClockInit(kUSB_ControllerEhci0);
407
408 if (kStatus_USB_Success == USB_HostInit(kUSB_ControllerEhci0, &imxrt_usb_host_obj[USBH0_INDEX].host_handle, usb0_host_callback))
409 {
410 usbh0_thread = rt_thread_create("ehci0", _ehci0_usbh_thread, RT_NULL, 500, 4, 9999999);
411 rt_thread_startup(usbh0_thread);
412 USB_HostIsrEnable(kUSB_ControllerEhci0);
413 }
414 else
415 {
416 rt_kprintf("USB_HostInit ehci0 error\r\n");
417 return -RT_ERROR;
418 }
419 return RT_EOK;
420 }
421 #endif
422
423 #ifdef BSP_USB1_HOST
USB_OTG2_IRQHandler(void)424 void USB_OTG2_IRQHandler(void)
425 {
426 /* enter interrupt */
427 rt_interrupt_enter();
428
429 USB_HostEhciIsrFunction(imxrt_usb_host_obj[USBH1_INDEX].host_handle);
430 /* leave interrupt */
431 rt_interrupt_leave();
432 }
433
_ehci1_reset_port(rt_uint8_t port)434 static rt_err_t _ehci1_reset_port(rt_uint8_t port)
435 {
436 // No reset port function available
437 return RT_EOK;
438 }
439
440 static uint8_t _ehci1_pipe_buf[64];
441 static uint8_t _ehci1_pipe_idx;
442
_ehci1_pipe_xfer(upipe_t pipe,rt_uint8_t token,void * buffer,int nbytes,int timeouts)443 static int _ehci1_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
444 {
445 int timeout = timeouts;
446
447 if (!imxrt_usb_host_obj[USBH1_INDEX].connect_status)
448 {
449 return -1;
450 }
451 usb_host_transfer_t *transfer;
452 if (imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle == NULL)
453 {
454 LOG_D("error operation on null pipe");
455 return -1;
456 }
457 if (USB_HostMallocTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, &transfer) != kStatus_USB_Success)
458 {
459 LOG_D("error to get transfer");
460 return -1;
461 }
462 transfer->transferBuffer = buffer;
463 transfer->transferLength = nbytes;
464 transfer->transferSofar = 0;
465 transfer->callbackFn = _imxrt_usb_host_send_callback;
466 transfer->callbackParam = &(imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index]);
467 transfer->direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT;
468 if (pipe->ep.bmAttributes == USB_ENDPOINT_CONTROL)
469 {
470 if (token == USBH_PID_SETUP)
471 {
472 struct urequest *setup = (struct urequest *)buffer;
473 transfer->setupStatus = 0;
474 transfer->setupPacket->bmRequestType = setup->request_type;
475 transfer->setupPacket->bRequest = setup->bRequest;
476 transfer->setupPacket->wIndex = setup->wIndex;
477 transfer->setupPacket->wLength = setup->wLength;
478 transfer->setupPacket->wValue = setup->wValue;
479 transfer->transferBuffer = RT_NULL;
480 transfer->transferLength = 0;
481 transfer->next = RT_NULL;
482 if ((transfer->setupPacket->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN)
483 {
484 transfer->direction = USB_IN;
485 transfer->transferBuffer = _ehci1_pipe_buf;
486 transfer->transferLength = setup->wLength;
487 _ehci1_pipe_idx = 0;
488 }
489 else
490 {
491 transfer->direction = USB_OUT;
492 }
493 }
494 else
495 {
496 rt_memcpy(buffer, _ehci1_pipe_buf + _ehci1_pipe_idx, nbytes);
497 imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].transfer_status = kStatus_USB_Success;
498 transfer->transferSofar = nbytes;
499 _ehci1_pipe_idx += nbytes;
500 if (_ehci1_pipe_idx >= 64)
501 {
502 _ehci1_pipe_idx = 0;
503 }
504 goto _ehci1_pipe_xfer_finish;
505 }
506
507 }
508 rt_completion_init(&(imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].urb_completion));
509 if (USB_HostEhciWritePipe(((usb_host_instance_t *)imxrt_usb_host_obj[USBH1_INDEX].host_handle)->controllerHandle, imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle, transfer) != kStatus_USB_Success)
510 {
511 LOG_D("usb host failed to send");
512 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
513 return -1;
514 }
515 if (-RT_ETIMEOUT == rt_completion_wait(&(imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].urb_completion), RT_WAITING_FOREVER))
516 {
517 LOG_D("usb transfer timeout");
518 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
519 return -1;
520 }
521 // rt_thread_mdelay(1);
522 _ehci1_pipe_xfer_finish:
523 switch (imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].transfer_status)
524 {
525 case kStatus_USB_Success:
526 {
527 LOG_D("ok");
528 pipe->status = UPIPE_STATUS_OK;
529 if (pipe->callback != RT_NULL)
530 {
531 pipe->callback(pipe);
532 }
533 size_t size = transfer->transferSofar;
534 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
535 if (pipe->ep.bEndpointAddress & 0x80)
536 {
537 return size;
538 }
539 else if (pipe->ep.bEndpointAddress & 0x00)
540 {
541 return size;
542 }
543 return nbytes;
544 break;
545 }
546 case kStatus_USB_TransferStall:
547 {
548 LOG_D("stall");
549 pipe->status = UPIPE_STATUS_STALL;
550 if (pipe->callback != RT_NULL)
551 {
552 pipe->callback(pipe);
553 }
554 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
555 return -1;
556 break;
557 }
558 case kStatus_USB_TransferFailed:
559 default:
560 {
561 LOG_D("error");
562 pipe->status = UPIPE_STATUS_ERROR;
563 if (pipe->callback != RT_NULL)
564 {
565 pipe->callback(pipe);
566 }
567 (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer);
568 return -1;
569 break;
570 }
571 }
572 }
573
574 static rt_uint16_t _ehci1_pipe_index = 0;
_ehci1_get_free_pipe_index(void)575 static rt_uint8_t _ehci1_get_free_pipe_index(void)
576 {
577 rt_uint8_t idx;
578 for (idx = 1; idx < 16; idx++)
579 {
580 if (!(_ehci1_pipe_index & (0x01 << idx)))
581 {
582 _ehci1_pipe_index |= (0x01 << idx);
583 return idx;
584 }
585 }
586 return 0xff;
587 }
588
_ehci1_free_pipe_index(rt_uint8_t index)589 static void _ehci1_free_pipe_index(rt_uint8_t index)
590 {
591 _ehci1_pipe_index &= ~(0x01 << index);
592 }
593
_ehci1_open_pipe(upipe_t pipe)594 static rt_err_t _ehci1_open_pipe(upipe_t pipe)
595 {
596 pipe->pipe_index = _ehci1_get_free_pipe_index();
597 if (pipe->pipe_index == 0xFF)
598 {
599 return -RT_ERROR;
600 }
601 usb_host_pipe_init_t pipe_init =
602 {
603 .devInstance = imxrt_usb_host_obj[USBH1_INDEX].device_handle,
604 .pipeType = pipe->ep.bmAttributes,
605 .direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT,
606 .endpointAddress = (pipe->ep.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK),
607 .interval = pipe->ep.bInterval,
608 .maxPacketSize = (uint16_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK),
609 .numberPerUframe = (uint8_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK),
610 .nakCount = USB_HOST_CONFIG_MAX_NAK,
611 };
612 USB_HostOpenPipe(imxrt_usb_host_obj[USBH1_INDEX].host_handle, &imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle, &pipe_init);
613 return RT_EOK;
614 }
615
_ehci1_close_pipe(upipe_t pipe)616 static rt_err_t _ehci1_close_pipe(upipe_t pipe)
617 {
618 (void)USB_HostClosePipe(imxrt_usb_host_obj[USBH1_INDEX].host_handle, imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle);
619 _ehci1_free_pipe_index(pipe->pipe_index);
620 return RT_EOK;
621 }
622
623 static struct uhcd_ops _ehci1_uhcd_ops =
624 {
625 _ehci1_reset_port,
626 _ehci1_pipe_xfer,
627 _ehci1_open_pipe,
628 _ehci1_close_pipe,
629 };
630
usb1_host_callback(usb_device_handle handle,usb_host_configuration_handle config_handle,rt_uint32_t event_code)631 static usb_status_t usb1_host_callback(usb_device_handle handle, usb_host_configuration_handle config_handle, rt_uint32_t event_code)
632 {
633 usb_status_t status = kStatus_USB_Success;
634
635 switch (event_code)
636 {
637 case kUSB_HostEventAttach:
638 if (!imxrt_usb_host_obj[USBH1_INDEX].connect_status)
639 {
640 imxrt_usb_host_obj[USBH1_INDEX].connect_status = RT_TRUE;
641 imxrt_usb_host_obj[USBH1_INDEX].device_handle = handle;
642 LOG_D("usb connected");
643 rt_usbh_root_hub_connect_handler(&(imxrt_usb_host_obj[USBH1_INDEX].uhcd), OTG_PORT, RT_TRUE);
644 }
645 break;
646
647 case kUSB_HostEventNotSupported:
648 LOG_D("usb device not supported");
649 break;
650
651 case kUSB_HostEventEnumerationDone:
652 LOG_D("enumeration done");
653 break;
654
655 case kUSB_HostEventDetach:
656 if (imxrt_usb_host_obj[USBH1_INDEX].connect_status)
657 {
658 imxrt_usb_host_obj[USBH1_INDEX].connect_status = RT_FALSE;
659 imxrt_usb_host_obj[USBH1_INDEX].device_handle = handle;
660 LOG_D("usb disconnnect");
661 rt_usbh_root_hub_disconnect_handler(&(imxrt_usb_host_obj[USBH1_INDEX].uhcd), OTG_PORT);
662 (void)USB_HostCloseDeviceInterface(handle, NULL);
663 }
664 break;
665
666 default:
667 break;
668 }
669 return status;
670 }
671
672 rt_thread_t usbh1_thread;
673
_ehci1_usbh_thread(void * param)674 static void _ehci1_usbh_thread(void* param)
675 {
676 while (1)
677 {
678 USB_HostEhciTaskFunction(imxrt_usb_host_obj[USBH1_INDEX].host_handle);
679 }
680 }
681
_ehci1_usbh_init(rt_device_t device)682 static rt_err_t _ehci1_usbh_init(rt_device_t device)
683 {
684 USB_HostClockInit(kUSB_ControllerEhci1);
685
686 if (kStatus_USB_Success == USB_HostInit(kUSB_ControllerEhci1, &imxrt_usb_host_obj[USBH1_INDEX].host_handle, usb1_host_callback))
687 {
688 usbh1_thread = rt_thread_create("ehci1", _ehci1_usbh_thread, RT_NULL, 500, 4, 9999999);
689 rt_thread_startup(usbh1_thread);
690 USB_HostIsrEnable(kUSB_ControllerEhci1);
691 }
692 else
693 {
694 rt_kprintf("USB_HostInit ehci1 error\r\n");
695 return -RT_ERROR;
696 }
697 return RT_EOK;
698 }
699 #endif
700
imxrt_usbh_register(void)701 int imxrt_usbh_register(void)
702 {
703 rt_err_t res = -RT_ERROR;
704 struct imxrt_usb_host *usb_host_obj;
705
706 #ifdef BSP_USB0_HOST
707 usb_host_obj = &(imxrt_usb_host_obj[USBH0_INDEX]);
708 rt_memset((void *)(&(usb_host_obj->uhcd)), 0, sizeof(struct uhcd));
709 usb_host_obj->uhcd.parent.type = RT_Device_Class_USBHost;
710 usb_host_obj->uhcd.parent.init = _ehci0_usbh_init;
711 usb_host_obj->uhcd.parent.user_data = usb_host_obj;
712 usb_host_obj->uhcd.ops = &_ehci0_uhcd_ops;
713 usb_host_obj->uhcd.num_ports = OTG_PORT;
714 res = rt_device_register(&(usb_host_obj->uhcd.parent), usb_host_obj->name, RT_DEVICE_FLAG_DEACTIVATE);
715 if (res != RT_EOK)
716 {
717 rt_kprintf("register usb0 host failed res = %d\r\n", res);
718 return -RT_ERROR;
719 }
720
721 rt_usb_host_init(usb_host_obj->name);
722 #endif
723 #ifdef BSP_USB1_HOST
724 usb_host_obj = &(imxrt_usb_host_obj[USBH1_INDEX]);
725 rt_memset((void *)(&(usb_host_obj->uhcd)), 0, sizeof(struct uhcd));
726 usb_host_obj->uhcd.parent.type = RT_Device_Class_USBHost;
727 usb_host_obj->uhcd.parent.init = _ehci1_usbh_init;
728 usb_host_obj->uhcd.parent.user_data = usb_host_obj;
729 usb_host_obj->uhcd.ops = &_ehci1_uhcd_ops;
730 usb_host_obj->uhcd.num_ports = OTG_PORT;
731 res = rt_device_register(&(usb_host_obj->uhcd.parent), usb_host_obj->name, RT_DEVICE_FLAG_DEACTIVATE);
732 if (res != RT_EOK)
733 {
734 rt_kprintf("register usb0 host failed res = %d\r\n", res);
735 return -RT_ERROR;
736 }
737
738 rt_usb_host_init(usb_host_obj->name);
739 #endif
740 return RT_EOK;
741 }
742 INIT_DEVICE_EXPORT(imxrt_usbh_register);
743
744 #endif
745