1 /*
2  * Copyright (c) 2024, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbd_core.h"
7 #include "usb_kinetis_reg.h"
8 
9 #undef CONFIG_USBDEV_EP_NUM
10 #define CONFIG_USBDEV_EP_NUM 16
11 
12 #define USB_OTG_DEV ((KINETIS_TypeDef *)g_usbdev_bus[busid].reg_base)
13 
14 /* Endpoint state */
15 struct kinetis_ep_state {
16     uint16_t ep_mps;    /* Endpoint max packet size */
17     uint8_t ep_type;    /* Endpoint type */
18     uint8_t ep_stalled; /* Endpoint stall flag */
19     uint8_t ep_enable;  /* Endpoint enable */
20     bool ep_odd;        /* Endpoint odd */
21     uint8_t *xfer_buf;
22     uint32_t xfer_len;
23     uint32_t actual_xfer_len;
24 };
25 
26 /* Driver state */
27 struct kinetis_udc {
28     uint8_t dev_addr;
29     struct kinetis_ep_state in_ep[CONFIG_USBDEV_EP_NUM];  /*!< IN endpoint parameters*/
30     struct kinetis_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
31 } g_kinetis_udc[CONFIG_USBDEV_MAX_BUS];
32 
33 USB_NOCACHE_RAM_SECTION __attribute__((aligned(512))) kinetis_bd_table_t g_kinetis_bdt[CONFIG_USBDEV_MAX_BUS];
34 USB_NOCACHE_RAM_SECTION __attribute__((aligned(32))) uint8_t setup_packet[CONFIG_USBDEV_MAX_BUS][8];
35 
kinetis_start_transfer(uint8_t busid,uint8_t ep,uint8_t * buffer,uint16_t buflen)36 static int kinetis_start_transfer(uint8_t busid, uint8_t ep, uint8_t *buffer, uint16_t buflen)
37 {
38     uint8_t ep_idx = USB_EP_GET_IDX(ep);
39     uint8_t dir;
40     uint8_t odd;
41     uint16_t ep_mps;
42     kinetis_bd_t *bd;
43     kinetis_bd_t *next;
44 
45     if (USB_EP_DIR_IS_OUT(ep)) {
46         dir = 0;
47         odd = g_kinetis_udc[busid].out_ep[ep_idx].ep_odd;
48         ep_mps = g_kinetis_udc[busid].out_ep[ep_idx].ep_mps;
49     } else {
50         dir = 1;
51         odd = g_kinetis_udc[busid].in_ep[ep_idx].ep_odd;
52         ep_mps = g_kinetis_udc[busid].in_ep[ep_idx].ep_mps;
53     }
54 
55     bd = &g_kinetis_bdt[busid].table[ep_idx][dir][odd];
56 
57     if (bd->own) {
58         USB_LOG_INFO("ep%02x is busy\r\n", ep);
59         return -1;
60     }
61 
62     bd->bc = buflen >= ep_mps ? ep_mps : buflen;
63     bd->addr = (uint32_t)buffer;
64     bd->own = 1;
65     return 0;
66 }
67 
kinetis_read_setup(uint8_t busid)68 static void kinetis_read_setup(uint8_t busid)
69 {
70     uint8_t out_odd = g_kinetis_udc[busid].out_ep[0].ep_odd;
71     uint8_t in_odd = g_kinetis_udc[busid].in_ep[0].ep_odd;
72 
73     if (g_kinetis_bdt[busid].table[0][0][out_odd].own) {
74         USB_LOG_INFO("ep0 is busy\r\n");
75         return;
76     }
77 
78     g_kinetis_bdt[busid].table[0][0][out_odd].data = 0;
79     g_kinetis_bdt[busid].table[0][0][out_odd ^ 1].data = 1;
80     g_kinetis_bdt[busid].table[0][1][in_odd].data = 1;
81     g_kinetis_bdt[busid].table[0][1][in_odd ^ 1].data = 0;
82 
83     kinetis_start_transfer(busid, USB_CONTROL_OUT_EP0, setup_packet[busid], 8);
84 }
85 
usb_dc_low_level_init(uint8_t busid)86 __WEAK void usb_dc_low_level_init(uint8_t busid)
87 {
88 }
89 
usb_dc_low_level_deinit(uint8_t busid)90 __WEAK void usb_dc_low_level_deinit(uint8_t busid)
91 {
92 }
93 
usb_dc_init(uint8_t busid)94 int usb_dc_init(uint8_t busid)
95 {
96     usb_dc_low_level_init(busid);
97 
98     memset(&g_kinetis_udc[busid], 0, sizeof(g_kinetis_udc[busid]));
99 
100     USB_OTG_DEV->BDTPAGE1 = (uint8_t)((uintptr_t)&g_kinetis_bdt[busid] >> 8);
101     USB_OTG_DEV->BDTPAGE2 = (uint8_t)((uintptr_t)&g_kinetis_bdt[busid] >> 16);
102     USB_OTG_DEV->BDTPAGE3 = (uint8_t)((uintptr_t)&g_kinetis_bdt[busid] >> 24);
103 
104     USB_OTG_DEV->INTEN = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK |
105                          USB_INTEN_SLEEPEN_MASK | USB_INTEN_RESUMEEN_MASK |
106                          USB_INTEN_ERROREN_MASK;
107 
108 #ifdef CONFIG_USBDEV_SOF_ENABLE
109     USB_OTG_DEV->INTEN |= USB_INTEN_SOFTOKEN_MASK;
110 #endif
111 
112     USB_OTG_DEV->CTL |= USB_CTL_USBENSOFEN_MASK;
113     return 0;
114 }
115 
usb_dc_deinit(uint8_t busid)116 int usb_dc_deinit(uint8_t busid)
117 {
118     USB_OTG_DEV->INTEN = 0;
119     USB_OTG_DEV->CTL &= ~USB_CTL_USBENSOFEN_MASK;
120 
121     memset(&g_kinetis_udc[busid], 0, sizeof(g_kinetis_udc[busid]));
122 
123     USB_OTG_DEV->BDTPAGE1 = (uint8_t)((uintptr_t)&g_kinetis_bdt[busid] >> 8);
124     USB_OTG_DEV->BDTPAGE2 = (uint8_t)((uintptr_t)&g_kinetis_bdt[busid] >> 16);
125     USB_OTG_DEV->BDTPAGE3 = (uint8_t)((uintptr_t)&g_kinetis_bdt[busid] >> 24);
126 
127     usb_dc_low_level_deinit(busid);
128     return 0;
129 }
130 
usbd_set_address(uint8_t busid,const uint8_t addr)131 int usbd_set_address(uint8_t busid, const uint8_t addr)
132 {
133     g_kinetis_udc[busid].dev_addr = addr;
134 
135     if (addr == 0) {
136         USB_OTG_DEV->ADDR = 0;
137     }
138     return 0;
139 }
140 
usbd_set_remote_wakeup(uint8_t busid)141 int usbd_set_remote_wakeup(uint8_t busid)
142 {
143     USB_OTG_DEV->CTL |= USB_CTL_RESUME_MASK;
144 
145     usbd_kinetis_delay_ms(10);
146 
147     USB_OTG_DEV->CTL &= ~USB_CTL_RESUME_MASK;
148 
149     return 0;
150 }
151 
usbd_get_port_speed(uint8_t busid)152 uint8_t usbd_get_port_speed(uint8_t busid)
153 {
154     return USB_SPEED_FULL;
155 }
156 
usbd_ep_open(uint8_t busid,const struct usb_endpoint_descriptor * ep)157 int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
158 {
159     uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
160     uint8_t odd;
161     uint8_t dir;
162     kinetis_bd_t *bd;
163     uint8_t regval;
164 
165     /* Must not exceed max endpoint number */
166     USB_ASSERT_MSG(ep_idx < CONFIG_USBDEV_EP_NUM, "Ep addr %02x overflow", ep->bEndpointAddress);
167 
168     if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
169         g_kinetis_udc[busid].out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
170         g_kinetis_udc[busid].out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
171         g_kinetis_udc[busid].out_ep[ep_idx].ep_enable = true;
172 
173         dir = 0;
174         odd = g_kinetis_udc[busid].out_ep[ep_idx].ep_odd;
175     } else {
176         g_kinetis_udc[busid].in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
177         g_kinetis_udc[busid].in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
178         g_kinetis_udc[busid].in_ep[ep_idx].ep_enable = true;
179 
180         dir = 1;
181         odd = g_kinetis_udc[busid].in_ep[ep_idx].ep_odd;
182     }
183 
184     if (ep_idx != 0) {
185         regval = USB_ENDPT_EPCTLDIS_MASK;
186         regval |= (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK : 0;
187         regval |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK;
188         USB_OTG_DEV->ENDPOINT[ep_idx].ENDPT |= regval;
189 
190         if (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
191             bd = &g_kinetis_bdt[busid].table[ep_idx][dir][odd];
192             bd->dts = 1;
193             bd->data = 0;
194 
195             bd = &g_kinetis_bdt[busid].table[ep_idx][dir][odd ^ 1];
196             bd->dts = 1;
197             bd->data = 1;
198         }
199     }
200 
201     return 0;
202 }
203 
usbd_ep_close(uint8_t busid,const uint8_t ep)204 int usbd_ep_close(uint8_t busid, const uint8_t ep)
205 {
206     uint8_t ep_idx = USB_EP_GET_IDX(ep);
207     uint8_t dir;
208     kinetis_bd_t *bd;
209 
210     if (USB_EP_DIR_IS_OUT(ep)) {
211         g_kinetis_udc[busid].out_ep[ep_idx].ep_enable = false;
212         dir = 0;
213     } else {
214         g_kinetis_udc[busid].in_ep[ep_idx].ep_enable = false;
215         dir = 1;
216     }
217 
218     bd = &g_kinetis_bdt[busid].table[ep_idx][dir][0];
219     bd->head = 0;
220 
221     bd = &g_kinetis_bdt[busid].table[ep_idx][dir][1];
222     bd->head = 0;
223 
224     USB_OTG_DEV->ENDPOINT[ep_idx].ENDPT &= ~(dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK);
225     return 0;
226 }
227 
usbd_ep_set_stall(uint8_t busid,const uint8_t ep)228 int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
229 {
230     uint8_t ep_idx = USB_EP_GET_IDX(ep);
231     kinetis_bd_t *bd;
232     uint8_t odd;
233     uint8_t dir;
234 
235     if (0 == ep_idx) {
236         USB_OTG_DEV->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPSTALL_MASK;
237 
238         if (ep_idx == 0) {
239             kinetis_read_setup(busid);
240         }
241     } else {
242         if (USB_EP_DIR_IS_OUT(ep)) {
243             dir = 0;
244             odd = g_kinetis_udc[busid].out_ep[ep_idx].ep_odd;
245         } else {
246             dir = 1;
247             odd = g_kinetis_udc[busid].in_ep[ep_idx].ep_odd;
248         }
249 
250         bd = &g_kinetis_bdt[busid].table[ep_idx][dir][odd];
251 
252         bd->bdt_stall = 1;
253         bd->own = 1;
254     }
255     return 0;
256 }
257 
usbd_ep_clear_stall(uint8_t busid,const uint8_t ep)258 int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
259 {
260     uint8_t ep_idx = USB_EP_GET_IDX(ep);
261     kinetis_bd_t *bd;
262     uint8_t odd;
263     uint8_t dir;
264 
265     if (USB_EP_DIR_IS_OUT(ep)) {
266         dir = 0;
267         odd = g_kinetis_udc[busid].out_ep[ep_idx].ep_odd;
268     } else {
269         dir = 1;
270         odd = g_kinetis_udc[busid].in_ep[ep_idx].ep_odd;
271     }
272 
273     bd = &g_kinetis_bdt[busid].table[ep_idx][dir][odd];
274 
275     bd->own = 0;
276     bd->bdt_stall = 0;
277     bd->data = 0;
278 
279     bd = &g_kinetis_bdt[busid].table[ep_idx][dir][odd ^ 1];
280     bd->data = 1;
281 
282     uint8_t regval = USB_OTG_DEV->ENDPOINT[ep_idx].ENDPT;
283     if (regval & USB_ENDPT_EPSTALL_MASK) {
284         USB_OTG_DEV->ENDPOINT[ep_idx].ENDPT = regval & ~USB_ENDPT_EPSTALL_MASK;
285     }
286 
287     return 0;
288 }
289 
usbd_ep_is_stalled(uint8_t busid,const uint8_t ep,uint8_t * stalled)290 int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
291 {
292     uint8_t ep_idx = USB_EP_GET_IDX(ep);
293 
294     uint8_t regval = USB_OTG_DEV->ENDPOINT[ep_idx].ENDPT;
295     if (regval & USB_ENDPT_EPSTALL_MASK) {
296         *stalled = 1;
297     } else {
298         *stalled = 0;
299     }
300 
301     return 0;
302 }
303 
usbd_ep_start_write(uint8_t busid,const uint8_t ep,const uint8_t * data,uint32_t data_len)304 int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data,
305                         uint32_t data_len)
306 {
307     uint8_t ep_idx = USB_EP_GET_IDX(ep);
308 
309     if (!data && data_len) {
310         return -1;
311     }
312     if (!g_kinetis_udc[busid].in_ep[ep_idx].ep_enable) {
313         return -2;
314     }
315 
316     g_kinetis_udc[busid].in_ep[ep_idx].xfer_buf = (uint8_t *)data;
317     g_kinetis_udc[busid].in_ep[ep_idx].xfer_len = data_len;
318     g_kinetis_udc[busid].in_ep[ep_idx].actual_xfer_len = 0;
319 
320     return kinetis_start_transfer(busid, ep, (uint8_t *)data, MIN(data_len, g_kinetis_udc[busid].in_ep[ep_idx].ep_mps));
321 }
322 
usbd_ep_start_read(uint8_t busid,const uint8_t ep,uint8_t * data,uint32_t data_len)323 int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data,
324                        uint32_t data_len)
325 {
326     uint8_t ep_idx = USB_EP_GET_IDX(ep);
327 
328     if (!data && data_len) {
329         return -1;
330     }
331     if (!g_kinetis_udc[busid].out_ep[ep_idx].ep_enable) {
332         return -2;
333     }
334 
335     g_kinetis_udc[busid].out_ep[ep_idx].xfer_buf = (uint8_t *)data;
336     g_kinetis_udc[busid].out_ep[ep_idx].xfer_len = data_len;
337     g_kinetis_udc[busid].out_ep[ep_idx].actual_xfer_len = 0;
338 
339     return kinetis_start_transfer(busid, ep, (uint8_t *)data, MIN(data_len, g_kinetis_udc[busid].out_ep[ep_idx].ep_mps));
340 }
341 
USBD_IRQHandler(uint8_t busid)342 void USBD_IRQHandler(uint8_t busid)
343 {
344     uint8_t s;
345     uint8_t pid;
346     uint8_t ep_idx;
347     uint8_t dir;
348     uint8_t odd;
349     uint16_t bc;
350     uint8_t is = USB_OTG_DEV->ISTAT;
351     uint8_t mask = USB_OTG_DEV->INTEN;
352     kinetis_bd_t *bd;
353 
354     USB_OTG_DEV->ISTAT = is & ~mask;
355     is &= mask;
356 
357     if (is & USB_ISTAT_ERROR_MASK) {
358         uint32_t es = USB_OTG_DEV->ERRSTAT;
359         USB_OTG_DEV->ERRSTAT = es;
360         USB_OTG_DEV->ISTAT = is;
361     }
362 
363     if (is & USB_ISTAT_USBRST_MASK) {
364         USB_OTG_DEV->ISTAT = is;
365         USB_OTG_DEV->CTL |= USB_CTL_ODDRST_MASK;
366         USB_OTG_DEV->ADDR = 0;
367 
368         USB_OTG_DEV->ENDPOINT[0].ENDPT = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK;
369         for (uint8_t i = 1; i < 16; i++) {
370             USB_OTG_DEV->ENDPOINT[i].ENDPT = 0;
371         }
372 
373         memset(&g_kinetis_bdt[busid], 0, sizeof(g_kinetis_bdt[busid]));
374         memset(g_kinetis_udc[busid].in_ep, 0, sizeof(struct kinetis_ep_state) * CONFIG_USBDEV_EP_NUM);
375         memset(g_kinetis_udc[busid].out_ep, 0, sizeof(struct kinetis_ep_state) * CONFIG_USBDEV_EP_NUM);
376         usbd_event_reset_handler(busid);
377 
378         kinetis_read_setup(busid);
379 
380         USB_OTG_DEV->CTL &= ~USB_CTL_ODDRST_MASK;
381     }
382 
383     if (is & USB_ISTAT_SLEEP_MASK) {
384         USB_OTG_DEV->ISTAT = USB_ISTAT_SLEEP_MASK;
385     }
386 
387     if (is & USB_ISTAT_RESUME_MASK) {
388         USB_OTG_DEV->ISTAT = USB_ISTAT_RESUME_MASK;
389     }
390 #ifdef CONFIG_USBDEV_SOF_ENABLE
391     if (is & USB_ISTAT_SOFTOK_MASK) {
392         USB_OTG_DEV->ISTAT = USB_ISTAT_SOFTOK_MASK;
393         usbd_event_sof_handler(busid);
394     }
395 #endif
396     if (is & USB_ISTAT_STALL_MASK) {
397         USB_OTG_DEV->ISTAT = USB_ISTAT_STALL_MASK;
398     }
399 
400     if (is & USB_ISTAT_TOKDNE_MASK) {
401         s = USB_OTG_DEV->STAT;
402         USB_OTG_DEV->ISTAT = USB_ISTAT_TOKDNE_MASK; /* must be cleared after get STAT */
403 
404         ep_idx = (s & USB_STAT_ENDP_MASK) >> USB_STAT_ENDP_SHIFT;
405         dir = (s & USB_STAT_TX_MASK) >> USB_STAT_TX_SHIFT;
406         odd = (s & USB_STAT_ODD_MASK) >> USB_STAT_ODD_SHIFT;
407 
408         bd = &g_kinetis_bdt[busid].table[ep_idx][dir][odd];
409 
410         pid = bd->tok_pid;
411         bc = bd->bc;
412 
413         bd->bdt_stall = 0;
414         bd->dts = 1;
415         bd->ninc = 0;
416         bd->keep = 0;
417 
418         if (dir) {
419             g_kinetis_udc[busid].in_ep[ep_idx].ep_odd = odd ^ 1;
420         } else {
421             g_kinetis_udc[busid].out_ep[ep_idx].ep_odd = odd ^ 1;
422         }
423 
424         if (pid == USB_TOKEN_PID_SETUP) {
425             USB_OTG_DEV->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
426             usbd_event_ep0_setup_complete_handler(busid, (uint8_t *)bd->addr);
427             return;
428         }
429 
430         if (dir) {
431             g_kinetis_udc[busid].in_ep[ep_idx].xfer_buf += bc;
432             g_kinetis_udc[busid].in_ep[ep_idx].xfer_len -= bc;
433             g_kinetis_udc[busid].in_ep[ep_idx].actual_xfer_len += bc;
434 
435             if (g_kinetis_udc[busid].in_ep[ep_idx].xfer_len == 0) {
436                 usbd_event_ep_in_complete_handler(busid, ep_idx | 0x80, g_kinetis_udc[busid].in_ep[ep_idx].actual_xfer_len);
437             } else {
438                 kinetis_start_transfer(busid, ep_idx | 0x80, g_kinetis_udc[busid].in_ep[ep_idx].xfer_buf,
439                                        MIN(g_kinetis_udc[busid].in_ep[ep_idx].xfer_len, g_kinetis_udc[busid].in_ep[ep_idx].ep_mps));
440             }
441         } else {
442             g_kinetis_udc[busid].out_ep[ep_idx].xfer_buf += bc;
443             g_kinetis_udc[busid].out_ep[ep_idx].xfer_len -= bc;
444             g_kinetis_udc[busid].out_ep[ep_idx].actual_xfer_len += bc;
445 
446             if ((bc < g_kinetis_udc[busid].out_ep[ep_idx].ep_mps) || (g_kinetis_udc[busid].out_ep[ep_idx].xfer_len == 0)) {
447                 usbd_event_ep_out_complete_handler(busid, ep_idx, g_kinetis_udc[busid].out_ep[ep_idx].actual_xfer_len);
448             } else {
449                 kinetis_start_transfer(busid, ep_idx, g_kinetis_udc[busid].out_ep[ep_idx].xfer_buf,
450                                        MIN(g_kinetis_udc[busid].out_ep[ep_idx].xfer_len, g_kinetis_udc[busid].out_ep[ep_idx].ep_mps));
451             }
452         }
453 
454         if ((bc == 0) && (ep_idx == 0)) {
455             if ((g_kinetis_udc[busid].dev_addr > 0) && dir) {
456                 USB_OTG_DEV->ADDR = g_kinetis_udc[busid].dev_addr;
457                 g_kinetis_udc[busid].dev_addr = 0;
458             }
459 
460             kinetis_read_setup(busid);
461         }
462     }
463 }