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-12-04     ZYH          first implementation
9  */
10 #include <usb/include/usb_device_config.h>
11 #include <usb/include/usb.h>
12 #include <rtthread.h>
13 #include <usb/phy/usb_phy.h>
14 #include <usb/device/usb_device.h>
15 #include <usb/device/usb_device_dci.h>
16 #include <rtdevice.h>
17 
18 /* USB PHY condfiguration */
19 #define BOARD_USB_PHY_D_CAL (0x0CU)
20 #define BOARD_USB_PHY_TXCAL45DP (0x06U)
21 #define BOARD_USB_PHY_TXCAL45DM (0x06U)
22 
23 static usb_device_handle ehci0_handle;
24 static struct udcd _fsl_udc_0;
25 
26 static usb_status_t usb_device_callback(usb_device_handle handle, uint32_t callbackEvent, void *eventParam);
27 static usb_status_t usb_device_endpoint_callback(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam);
28 
USB_DeviceIsrEnable(uint8_t controllerId)29 static void USB_DeviceIsrEnable(uint8_t controllerId)
30 {
31     uint8_t irqNumber;
32 #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
33     uint8_t usbDeviceEhciIrq[] = USBHS_IRQS;
34     irqNumber = usbDeviceEhciIrq[controllerId - kUSB_ControllerEhci0];
35 #endif
36     /* Install isr, set priority, and enable IRQ. */
37 #if defined(__GIC_PRIO_BITS)
38     GIC_SetPriority((IRQn_Type)irqNumber, 3);
39 #else
40     NVIC_SetPriority((IRQn_Type)irqNumber, 3);
41 #endif
42     EnableIRQ((IRQn_Type)irqNumber);
43 }
44 
45 /*!
46  * @brief Initializes USB specific setting that was not set by the Clocks tool.
47  */
USB_DeviceClockInit(uint8_t controllerId)48 static void USB_DeviceClockInit(uint8_t controllerId)
49 {
50 #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
51     usb_phy_config_struct_t phyConfig = {
52         BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
53     };
54 #endif
55 #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
56     if (controllerId == kUSB_ControllerEhci0)
57     {
58         CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
59         CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
60     }
61     else
62     {
63         CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
64         CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
65     }
66     USB_EhciPhyInit(controllerId, 0, &phyConfig);
67 #endif
68 }
69 
70 static struct ep_id _ehci0_ep_pool[] =
71 {
72     {0x0,  USB_EP_ATTR_CONTROL,     USB_DIR_INOUT,  64, ID_ASSIGNED  },
73     {0x1,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
74     {0x1,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
75     {0x2,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
76     {0x2,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
77     {0x3,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
78     {0x3,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
79     {0x4,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
80     {0x4,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
81     {0x5,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
82     {0x5,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
83     {0x6,  USB_EP_ATTR_INT,         USB_DIR_IN,     64, ID_UNASSIGNED},
84     {0x6,  USB_EP_ATTR_INT,         USB_DIR_OUT,    64, ID_UNASSIGNED},
85     {0x7,  USB_EP_ATTR_BULK,        USB_DIR_IN,     64, ID_UNASSIGNED},
86     {0x7,  USB_EP_ATTR_BULK,        USB_DIR_OUT,    64, ID_UNASSIGNED},
87     {0xFF, USB_EP_ATTR_TYPE_MASK,   USB_DIR_MASK,   0,  ID_ASSIGNED  },
88 };
89 
90 /*!
91  * @brief USB Interrupt service routine.
92  *
93  * This function serves as the USB interrupt service routine.
94  *
95  * @return None.
96  */
USB_OTG1_IRQHandler(void)97 void USB_OTG1_IRQHandler(void)
98 {
99     /* enter interrupt */
100     rt_interrupt_enter();
101 
102     USB_DeviceEhciIsrFunction(ehci0_handle);
103     /* leave interrupt */
104     rt_interrupt_leave();
105 }
106 
_ehci0_ep_set_stall(rt_uint8_t address)107 static rt_err_t _ehci0_ep_set_stall(rt_uint8_t address)
108 {
109     USB_DeviceStallEndpoint(ehci0_handle, address);
110     return RT_EOK;
111 }
112 
_ehci0_ep_clear_stall(rt_uint8_t address)113 static rt_err_t _ehci0_ep_clear_stall(rt_uint8_t address)
114 {
115     USB_DeviceUnstallEndpoint(ehci0_handle, address);
116     return RT_EOK;
117 }
118 
_ehci0_set_address(rt_uint8_t address)119 static rt_err_t _ehci0_set_address(rt_uint8_t address)
120 {
121     USB_DeviceSetStatus(ehci0_handle, kUSB_DeviceStatusAddress, &address);
122     return RT_EOK;
123 }
124 
_ehci0_set_config(rt_uint8_t address)125 static rt_err_t _ehci0_set_config(rt_uint8_t address)
126 {
127     return RT_EOK;
128 }
129 
_ehci0_ep_enable(uep_t ep)130 static rt_err_t _ehci0_ep_enable(uep_t ep)
131 {
132     usb_device_endpoint_init_struct_t ep_init;
133     usb_device_endpoint_callback_struct_t ep_callback;
134     rt_uint32_t param = ep->ep_desc->bEndpointAddress;
135     RT_ASSERT(ep != RT_NULL);
136     RT_ASSERT(ep->ep_desc != RT_NULL);
137     ep_init.maxPacketSize = ep->ep_desc->wMaxPacketSize;
138     ep_init.endpointAddress = ep->ep_desc->bEndpointAddress;
139     ep_init.transferType = ep->ep_desc->bmAttributes;
140     ep_init.zlt = 0;
141     ep_callback.callbackFn = usb_device_endpoint_callback;
142     ep_callback.callbackParam = (void *)param;
143     ep_callback.isBusy = 0;
144     USB_DeviceInitEndpoint(ehci0_handle, &ep_init, &ep_callback);
145     return RT_EOK;
146 }
_ehci0_ep_disable(uep_t ep)147 static rt_err_t _ehci0_ep_disable(uep_t ep)
148 {
149     RT_ASSERT(ep != RT_NULL);
150     RT_ASSERT(ep->ep_desc != RT_NULL);
151     USB_DeviceDeinitEndpoint(ehci0_handle, ep->ep_desc->bEndpointAddress);
152     return RT_EOK;
153 }
154 
_ehci0_ep_read(rt_uint8_t address,void * buffer)155 static rt_ssize_t _ehci0_ep_read(rt_uint8_t address, void *buffer)
156 {
157     rt_size_t size = 0;
158 
159     RT_ASSERT(buffer != RT_NULL);
160 
161     return size;
162 }
163 
_ehci0_ep_read_prepare(rt_uint8_t address,void * buffer,rt_size_t size)164 static rt_ssize_t _ehci0_ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
165 {
166     USB_DeviceRecvRequest(ehci0_handle, address, buffer, size);
167     return size;
168 }
169 
_ehci0_ep_write(rt_uint8_t address,void * buffer,rt_size_t size)170 static rt_ssize_t _ehci0_ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
171 {
172     USB_DeviceSendRequest(ehci0_handle, address, buffer, size);
173     return size;
174 }
175 
_ehci0_ep0_send_status(void)176 static rt_err_t _ehci0_ep0_send_status(void)
177 {
178     _ehci0_ep_write(0x00, NULL, 0);
179     return RT_EOK;
180 }
181 
_ehci0_suspend(void)182 static rt_err_t _ehci0_suspend(void)
183 {
184     return RT_EOK;
185 }
186 
_ehci0_wakeup(void)187 static rt_err_t _ehci0_wakeup(void)
188 {
189     return RT_EOK;
190 }
191 
192 const static struct udcd_ops _ehci0_udc_ops =
193 {
194     _ehci0_set_address,
195     _ehci0_set_config,
196     _ehci0_ep_set_stall,
197     _ehci0_ep_clear_stall,
198     _ehci0_ep_enable,
199     _ehci0_ep_disable,
200     _ehci0_ep_read_prepare,
201     _ehci0_ep_read,
202     _ehci0_ep_write,
203     _ehci0_ep0_send_status,
204     _ehci0_suspend,
205     _ehci0_wakeup,
206 };
207 
drv_ehci0_usbd_init(rt_device_t device)208 static rt_err_t drv_ehci0_usbd_init(rt_device_t device)
209 {
210     usb_status_t result;
211     USB_DeviceClockInit(kUSB_ControllerEhci0);
212 
213     result = USB_DeviceInit(kUSB_ControllerEhci0, usb_device_callback, &ehci0_handle);
214     RT_ASSERT(ehci0_handle);
215     if(result == kStatus_USB_Success)
216     {
217         USB_DeviceIsrEnable(kUSB_ControllerEhci0);
218         USB_DeviceRun(ehci0_handle);
219     }
220     else
221     {
222         rt_kprintf("USB_DeviceInit ehci0 error\r\n");
223         return -RT_ERROR;
224     }
225     return RT_EOK;
226 }
227 
rt_usbd_init(void)228 static int rt_usbd_init(void)
229 {
230     rt_memset((void *)&_fsl_udc_0, 0, sizeof(struct udcd));
231     _fsl_udc_0.parent.type = RT_Device_Class_USBDevice;
232     _fsl_udc_0.parent.init = drv_ehci0_usbd_init;
233     _fsl_udc_0.ops = &_ehci0_udc_ops;
234     /* Register endpoint infomation */
235     _fsl_udc_0.ep_pool = _ehci0_ep_pool;
236     _fsl_udc_0.ep0.id = &_ehci0_ep_pool[0];
237 
238     _fsl_udc_0.device_is_hs = RT_FALSE;
239     rt_device_register((rt_device_t)&_fsl_udc_0, "usbd", 0);
240     rt_usb_device_init();
241 
242     return 0;
243 }
244 INIT_DEVICE_EXPORT(rt_usbd_init);
245 
usb_device_endpoint_callback(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)246 static usb_status_t usb_device_endpoint_callback(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam)
247 {
248     rt_uint32_t ep_addr = (rt_uint32_t)callbackParam;
249     usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
250     udcd_t udcd = RT_NULL;
251     uint8_t state;
252     if(deviceHandle->controllerId == kUSB_ControllerEhci0)
253         udcd = &_fsl_udc_0;
254 
255     if(message->isSetup)
256     {
257         rt_usbd_ep0_setup_handler(udcd, (struct urequest*)message->buffer);
258     }
259     else if(ep_addr == 0x00)
260     {
261         USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
262         if(state == kUSB_DeviceStateAddressing)
263         {
264             if (kStatus_USB_Success == USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL))
265             {
266                 state = kUSB_DeviceStateAddress;
267                 USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
268             }
269         }
270         rt_usbd_ep0_out_handler(udcd, message->length);
271     }
272     else if(ep_addr == 0x80)
273     {
274         USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
275         if(state == kUSB_DeviceStateAddressing)
276         {
277             if (kStatus_USB_Success == USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL))
278             {
279                 state = kUSB_DeviceStateAddress;
280                 USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
281             }
282         }
283         rt_usbd_ep0_in_handler(udcd);
284     }
285     else if(ep_addr & 0x80)
286     {
287         rt_usbd_ep_in_handler(udcd, ep_addr, message->length);
288     }
289     else
290     {
291         rt_usbd_ep_out_handler(udcd, ep_addr, message->length);
292     }
293     return kStatus_USB_Success;
294 }
295 
usb_device_callback(usb_device_handle handle,uint32_t callbackEvent,void * eventParam)296 static usb_status_t usb_device_callback(usb_device_handle handle, uint32_t callbackEvent, void *eventParam)
297 {
298     usb_status_t error = kStatus_USB_Error;
299     usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
300     usb_device_endpoint_init_struct_t ep0_init =
301     {
302         0x40,
303         0x00,
304         USB_EP_ATTR_CONTROL,
305         0
306     };
307     usb_device_endpoint_callback_struct_t ep0_callback =
308     {
309         usb_device_endpoint_callback,
310         0,
311         0
312     };
313     udcd_t udcd = RT_NULL;
314     if(deviceHandle->controllerId == kUSB_ControllerEhci0)
315         udcd = &_fsl_udc_0;
316 
317     switch (callbackEvent)
318     {
319     case kUSB_DeviceEventBusReset:
320         ep0_init.endpointAddress = 0x00;
321         ep0_callback.callbackParam = (void *)0x00;
322         USB_DeviceInitEndpoint(deviceHandle, &ep0_init, &ep0_callback);
323         ep0_init.endpointAddress = 0x80;
324         ep0_callback.callbackParam = (void *)0x80;
325         USB_DeviceInitEndpoint(deviceHandle, &ep0_init, &ep0_callback);
326         rt_usbd_reset_handler(udcd);
327         break;
328     case kUSB_DeviceEventAttach:
329         rt_usbd_connect_handler(udcd);
330         break;
331     case kUSB_DeviceEventDetach:
332         rt_usbd_disconnect_handler(udcd);
333         break;
334     }
335     return error;
336 }
337 
338 /********************* end of file ************************/
339