1 /* usb_dc_kinetis.c - Kinetis USBFSOTG usb device driver */
2
3 /*
4 * Copyright (c) 2017 PHYTEC Messtechnik GmbH
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #define DT_DRV_COMPAT nxp_kinetis_usbd
10
11 #include <soc.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/usb/usb_device.h>
17 #include <zephyr/init.h>
18
19 #define LOG_LEVEL CONFIG_USB_DRIVER_LOG_LEVEL
20 #include <zephyr/logging/log.h>
21 #include <zephyr/irq.h>
22 LOG_MODULE_REGISTER(usb_dc_kinetis);
23
24 #define NUM_OF_EP_MAX DT_INST_PROP(0, num_bidir_endpoints)
25
26 #define BD_OWN_MASK (1 << 5)
27 #define BD_DATA01_MASK (1 << 4)
28 #define BD_KEEP_MASK (1 << 3)
29 #define BD_NINC_MASK (1 << 2)
30 #define BD_DTS_MASK (1 << 1)
31 #define BD_STALL_MASK (1 << 0)
32
33 #define KINETIS_SETUP_TOKEN 0x0d
34 #define KINETIS_IN_TOKEN 0x09
35 #define KINETIS_OUT_TOKEN 0x01
36
37 #define USBFSOTG_PERID 0x04
38 #define USBFSOTG_REV 0x33
39
40 #define KINETIS_EP_NUMOF_MASK 0xf
41 #define KINETIS_ADDR2IDX(addr) ((addr) & (KINETIS_EP_NUMOF_MASK))
42
43 /*
44 * Buffer Descriptor (BD) entry provides endpoint buffer control
45 * information for USBFS controller. Every endpoint direction requires
46 * two BD entries.
47 */
48 struct buf_descriptor {
49 union {
50 uint32_t bd_fields;
51
52 struct {
53 uint32_t reserved_1_0 : 2;
54 uint32_t tok_pid : 4;
55 uint32_t data01 : 1;
56 uint32_t own : 1;
57 uint32_t reserved_15_8 : 8;
58 uint32_t bc : 16;
59 } get __packed;
60
61 struct {
62 uint32_t reserved_1_0 : 2;
63 uint32_t bd_ctrl : 6;
64 uint32_t reserved_15_8 : 8;
65 uint32_t bc : 16;
66 } set __packed;
67
68 } __packed;
69 uint32_t buf_addr;
70 } __packed;
71
72 /*
73 * Buffer Descriptor Table for the endpoints buffer management.
74 * The driver configuration with 16 fully bidirectional endpoints would require
75 * four BD entries per endpoint and 512 bytes of memory.
76 */
77 static struct buf_descriptor __aligned(512) bdt[(NUM_OF_EP_MAX) * 2 * 2];
78
79 #define BD_IDX_EP0TX_EVEN 2
80 #define BD_IDX_EP0TX_ODD 3
81
82 #define EP_BUF_NUMOF_BLOCKS (NUM_OF_EP_MAX / 2)
83
84 K_HEAP_DEFINE(ep_buf_pool, 512 * EP_BUF_NUMOF_BLOCKS + 128);
85
86 struct ep_mem_block {
87 void *data;
88 };
89
90 struct usb_ep_ctrl_data {
91 struct ep_status {
92 uint16_t in_enabled : 1;
93 uint16_t out_enabled : 1;
94 uint16_t in_data1 : 1;
95 uint16_t out_data1 : 1;
96 uint16_t in_odd : 1;
97 uint16_t out_odd : 1;
98 uint16_t in_stalled : 1;
99 uint16_t out_stalled : 1;
100 } status;
101 uint16_t mps_in;
102 uint16_t mps_out;
103 struct ep_mem_block mblock_in;
104 struct ep_mem_block mblock_out;
105 usb_dc_ep_callback cb_in;
106 usb_dc_ep_callback cb_out;
107 };
108
109 #define USBD_THREAD_STACK_SIZE 1024
110
111 struct usb_device_data {
112 usb_dc_status_callback status_cb;
113 uint8_t address;
114 uint32_t bd_active;
115 struct usb_ep_ctrl_data ep_ctrl[NUM_OF_EP_MAX];
116 bool attached;
117
118 K_KERNEL_STACK_MEMBER(thread_stack, USBD_THREAD_STACK_SIZE);
119 struct k_thread thread;
120 };
121
122 static struct usb_device_data dev_data;
123
124 #define USB_DC_CB_TYPE_MGMT 0
125 #define USB_DC_CB_TYPE_EP 1
126
127 struct cb_msg {
128 uint8_t ep;
129 uint8_t type;
130 uint32_t cb;
131 };
132
133 K_MSGQ_DEFINE(usb_dc_msgq, sizeof(struct cb_msg), 10, 4);
134 static void usb_kinetis_isr_handler(void);
135
136 /*
137 * This function returns the BD element index based on
138 * endpoint address and the odd bit.
139 */
get_bdt_idx(uint8_t ep,uint8_t odd)140 static inline uint8_t get_bdt_idx(uint8_t ep, uint8_t odd)
141 {
142 if (ep & USB_EP_DIR_IN) {
143 return ((((KINETIS_ADDR2IDX(ep)) * 4) + 2 + (odd & 1)));
144 }
145 return ((((KINETIS_ADDR2IDX(ep)) * 4) + (odd & 1)));
146 }
147
kinetis_usb_init(void)148 static int kinetis_usb_init(void)
149 {
150 #if !DT_INST_PROP(0, no_voltage_regulator)
151 /* enable USB voltage regulator */
152 SIM->SOPT1 |= SIM_SOPT1_USBREGEN_MASK;
153 #endif
154
155 USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
156 k_busy_wait(2000);
157
158 USB0->CTL = 0;
159 /* enable USB module, AKA USBEN bit in CTL1 register */
160 USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
161
162 if ((USB0->PERID != USBFSOTG_PERID) ||
163 (USB0->REV != USBFSOTG_REV)) {
164 return -1;
165 }
166
167 USB0->BDTPAGE1 = (uint8_t)(((uint32_t)bdt) >> 8);
168 USB0->BDTPAGE2 = (uint8_t)(((uint32_t)bdt) >> 16);
169 USB0->BDTPAGE3 = (uint8_t)(((uint32_t)bdt) >> 24);
170
171 /* clear interrupt flags */
172 USB0->ISTAT = 0xFF;
173
174 /* enable reset interrupt */
175 USB0->INTEN = USB_INTEN_USBRSTEN_MASK;
176
177 USB0->USBCTRL = USB_USBCTRL_PDE_MASK;
178
179
180
181 LOG_DBG("");
182
183 return 0;
184 }
185
usb_dc_reset(void)186 int usb_dc_reset(void)
187 {
188 for (uint8_t i = 0; i < 16; i++) {
189 USB0->ENDPOINT[i].ENDPT = 0;
190 }
191 dev_data.bd_active = 0U;
192 dev_data.address = 0U;
193
194 USB0->CTL |= USB_CTL_ODDRST_MASK;
195 USB0->CTL &= ~USB_CTL_ODDRST_MASK;
196
197 /* Clear interrupt status flags */
198 USB0->ISTAT = 0xFF;
199 /* Clear error flags */
200 USB0->ERRSTAT = 0xFF;
201 /* Enable all error interrupt sources */
202 USB0->ERREN = 0xFF;
203 /* Reset default address */
204 USB0->ADDR = 0x00;
205
206 USB0->INTEN = (USB_INTEN_USBRSTEN_MASK |
207 USB_INTEN_TOKDNEEN_MASK |
208 USB_INTEN_SLEEPEN_MASK |
209 USB_INTEN_SOFTOKEN_MASK |
210 USB_INTEN_STALLEN_MASK |
211 USB_INTEN_ERROREN_MASK);
212
213 LOG_DBG("");
214
215 return 0;
216 }
217
usb_dc_attach(void)218 int usb_dc_attach(void)
219 {
220 if (dev_data.attached) {
221 LOG_WRN("already attached");
222 }
223
224 kinetis_usb_init();
225
226 /*
227 * Call usb_dc_reset here because the device stack does not make it
228 * after USB_DC_RESET status event.
229 */
230 usb_dc_reset();
231
232 dev_data.attached = 1;
233 LOG_DBG("attached");
234
235 /* non-OTG device mode, enable DP Pullup */
236 USB0->CONTROL = USB_CONTROL_DPPULLUPNONOTG_MASK;
237
238 return 0;
239 }
240
usb_dc_detach(void)241 int usb_dc_detach(void)
242 {
243 LOG_DBG("");
244 /* disable USB and DP Pullup */
245 USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
246 USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
247
248 return 0;
249 }
250
usb_dc_set_address(const uint8_t addr)251 int usb_dc_set_address(const uint8_t addr)
252 {
253 LOG_DBG("");
254
255 if (!dev_data.attached) {
256 return -EINVAL;
257 }
258
259 /*
260 * The device stack tries to set the address before
261 * sending the ACK with ZLP, which is totally stupid,
262 * as workaround the address will be buffered and
263 * placed later inside isr handler (see KINETIS_IN_TOKEN).
264 */
265 dev_data.address = 0x80 | (addr & 0x7f);
266
267 return 0;
268 }
269
usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data * const cfg)270 int usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data * const cfg)
271 {
272 uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr);
273
274 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
275 LOG_ERR("endpoint index/address out of range");
276 return -EINVAL;
277 }
278
279 switch (cfg->ep_type) {
280 case USB_DC_EP_CONTROL:
281 if (cfg->ep_mps > USB_MAX_CTRL_MPS) {
282 return -EINVAL;
283 }
284 return 0;
285 case USB_DC_EP_BULK:
286 if (cfg->ep_mps > USB_MAX_FS_BULK_MPS) {
287 return -EINVAL;
288 }
289 break;
290 case USB_DC_EP_INTERRUPT:
291 if (cfg->ep_mps > USB_MAX_FS_INT_MPS) {
292 return -EINVAL;
293 }
294 break;
295 case USB_DC_EP_ISOCHRONOUS:
296 if (cfg->ep_mps > USB_MAX_FS_ISO_MPS) {
297 return -EINVAL;
298 }
299 break;
300 default:
301 LOG_ERR("Unknown endpoint type!");
302 return -EINVAL;
303 }
304
305 if (ep_idx & BIT(0)) {
306 if (USB_EP_GET_DIR(cfg->ep_addr) != USB_EP_DIR_IN) {
307 LOG_INF("pre-selected as IN endpoint");
308 return -1;
309 }
310 } else {
311 if (USB_EP_GET_DIR(cfg->ep_addr) != USB_EP_DIR_OUT) {
312 LOG_INF("pre-selected as OUT endpoint");
313 return -1;
314 }
315 }
316
317 return 0;
318 }
319
usb_dc_ep_configure(const struct usb_dc_ep_cfg_data * const cfg)320 int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data * const cfg)
321 {
322 uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr);
323 struct usb_ep_ctrl_data *ep_ctrl;
324 struct ep_mem_block *block;
325 uint8_t idx_even;
326 uint8_t idx_odd;
327
328 if (usb_dc_ep_check_cap(cfg)) {
329 return -EINVAL;
330 }
331
332 idx_even = get_bdt_idx(cfg->ep_addr, 0);
333 idx_odd = get_bdt_idx(cfg->ep_addr, 1);
334 ep_ctrl = &dev_data.ep_ctrl[ep_idx];
335
336 if (ep_idx && (dev_data.ep_ctrl[ep_idx].status.in_enabled ||
337 dev_data.ep_ctrl[ep_idx].status.out_enabled)) {
338 LOG_WRN("endpoint already configured");
339 return -EALREADY;
340 }
341
342 LOG_DBG("ep %x, mps %d, type %d", cfg->ep_addr, cfg->ep_mps,
343 cfg->ep_type);
344
345 if (USB_EP_DIR_IS_OUT(cfg->ep_addr)) {
346 block = &(ep_ctrl->mblock_out);
347 } else {
348 block = &(ep_ctrl->mblock_in);
349 }
350
351 if (bdt[idx_even].buf_addr) {
352 k_heap_free(&ep_buf_pool, block->data);
353 }
354
355 USB0->ENDPOINT[ep_idx].ENDPT = 0;
356 (void)memset(&bdt[idx_even], 0, sizeof(struct buf_descriptor));
357 (void)memset(&bdt[idx_odd], 0, sizeof(struct buf_descriptor));
358
359 block->data = k_heap_alloc(&ep_buf_pool, cfg->ep_mps * 2U, K_NO_WAIT);
360 if (block->data != NULL) {
361 (void)memset(block->data, 0, cfg->ep_mps * 2U);
362 } else {
363 LOG_ERR("Memory allocation time-out");
364 return -ENOMEM;
365 }
366
367 bdt[idx_even].buf_addr = (uint32_t)block->data;
368 LOG_INF("idx_even %x", (uint32_t)block->data);
369 bdt[idx_odd].buf_addr = (uint32_t)((uint8_t *)block->data + cfg->ep_mps);
370 LOG_INF("idx_odd %x", (uint32_t)((uint8_t *)block->data + cfg->ep_mps));
371
372 if (cfg->ep_addr & USB_EP_DIR_IN) {
373 dev_data.ep_ctrl[ep_idx].mps_in = cfg->ep_mps;
374 } else {
375 dev_data.ep_ctrl[ep_idx].mps_out = cfg->ep_mps;
376 }
377
378 bdt[idx_even].set.bc = cfg->ep_mps;
379 bdt[idx_odd].set.bc = cfg->ep_mps;
380
381 dev_data.ep_ctrl[ep_idx].status.out_data1 = false;
382 dev_data.ep_ctrl[ep_idx].status.in_data1 = false;
383
384 switch (cfg->ep_type) {
385 case USB_DC_EP_CONTROL:
386 LOG_DBG("configure control endpoint");
387 USB0->ENDPOINT[ep_idx].ENDPT |= (USB_ENDPT_EPHSHK_MASK |
388 USB_ENDPT_EPRXEN_MASK |
389 USB_ENDPT_EPTXEN_MASK);
390 break;
391 case USB_DC_EP_BULK:
392 case USB_DC_EP_INTERRUPT:
393 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPHSHK_MASK;
394 if (USB_EP_DIR_IS_OUT(cfg->ep_addr)) {
395 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPRXEN_MASK;
396 } else {
397 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPTXEN_MASK;
398 }
399 break;
400 case USB_DC_EP_ISOCHRONOUS:
401 if (USB_EP_DIR_IS_OUT(cfg->ep_addr)) {
402 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPRXEN_MASK;
403 } else {
404 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPTXEN_MASK;
405 }
406 break;
407 default:
408 return -EINVAL;
409 }
410
411 return 0;
412 }
413
usb_dc_ep_set_stall(const uint8_t ep)414 int usb_dc_ep_set_stall(const uint8_t ep)
415 {
416 uint8_t ep_idx = USB_EP_GET_IDX(ep);
417 uint8_t bd_idx;
418
419 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
420 LOG_ERR("Wrong endpoint index/address");
421 return -EINVAL;
422 }
423
424 LOG_DBG("ep %x, idx %d", ep, ep_idx);
425
426 if (USB_EP_DIR_IS_OUT(ep)) {
427 dev_data.ep_ctrl[ep_idx].status.out_stalled = 1U;
428 bd_idx = get_bdt_idx(ep,
429 ~dev_data.ep_ctrl[ep_idx].status.out_odd);
430 } else {
431 dev_data.ep_ctrl[ep_idx].status.in_stalled = 1U;
432 bd_idx = get_bdt_idx(ep,
433 dev_data.ep_ctrl[ep_idx].status.in_odd);
434 }
435
436 bdt[bd_idx].set.bd_ctrl = BD_STALL_MASK | BD_DTS_MASK | BD_OWN_MASK;
437
438 return 0;
439 }
440
usb_dc_ep_clear_stall(const uint8_t ep)441 int usb_dc_ep_clear_stall(const uint8_t ep)
442 {
443 uint8_t ep_idx = USB_EP_GET_IDX(ep);
444 uint8_t bd_idx;
445
446 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
447 LOG_ERR("Wrong endpoint index/address");
448 return -EINVAL;
449 }
450
451 LOG_DBG("ep %x, idx %d", ep, ep_idx);
452 USB0->ENDPOINT[ep_idx].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
453
454 if (USB_EP_DIR_IS_OUT(ep)) {
455 dev_data.ep_ctrl[ep_idx].status.out_stalled = 0U;
456 dev_data.ep_ctrl[ep_idx].status.out_data1 = false;
457 bd_idx = get_bdt_idx(ep,
458 ~dev_data.ep_ctrl[ep_idx].status.out_odd);
459 bdt[bd_idx].set.bd_ctrl = 0U;
460 bdt[bd_idx].set.bd_ctrl = BD_DTS_MASK | BD_OWN_MASK;
461 } else {
462 dev_data.ep_ctrl[ep_idx].status.in_stalled = 0U;
463 dev_data.ep_ctrl[ep_idx].status.in_data1 = false;
464 bd_idx = get_bdt_idx(ep,
465 dev_data.ep_ctrl[ep_idx].status.in_odd);
466 bdt[bd_idx].set.bd_ctrl = 0U;
467 }
468
469 /* Resume TX token processing, see USBx_CTL field descriptions */
470 if (ep == 0U) {
471 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
472 }
473
474 return 0;
475 }
476
usb_dc_ep_is_stalled(const uint8_t ep,uint8_t * const stalled)477 int usb_dc_ep_is_stalled(const uint8_t ep, uint8_t *const stalled)
478 {
479 uint8_t ep_idx = USB_EP_GET_IDX(ep);
480
481 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
482 LOG_ERR("Wrong endpoint index/address");
483 return -EINVAL;
484 }
485
486 LOG_DBG("ep %x, idx %d", ep_idx, ep);
487 if (!stalled) {
488 return -EINVAL;
489 }
490
491 *stalled = 0U;
492 if (USB_EP_DIR_IS_OUT(ep)) {
493 *stalled = dev_data.ep_ctrl[ep_idx].status.out_stalled;
494 } else {
495 *stalled = dev_data.ep_ctrl[ep_idx].status.in_stalled;
496 }
497
498 uint8_t bd_idx = get_bdt_idx(ep,
499 dev_data.ep_ctrl[ep_idx].status.in_odd);
500 LOG_WRN("active bd ctrl: %x", bdt[bd_idx].set.bd_ctrl);
501 bd_idx = get_bdt_idx(ep,
502 ~dev_data.ep_ctrl[ep_idx].status.in_odd);
503 LOG_WRN("next bd ctrl: %x", bdt[bd_idx].set.bd_ctrl);
504
505 return 0;
506 }
507
usb_dc_ep_halt(const uint8_t ep)508 int usb_dc_ep_halt(const uint8_t ep)
509 {
510 return usb_dc_ep_set_stall(ep);
511 }
512
usb_dc_ep_enable(const uint8_t ep)513 int usb_dc_ep_enable(const uint8_t ep)
514 {
515 uint8_t ep_idx = USB_EP_GET_IDX(ep);
516 uint8_t idx_even;
517 uint8_t idx_odd;
518
519 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
520 LOG_ERR("Wrong endpoint index/address");
521 return -EINVAL;
522 }
523
524 idx_even = get_bdt_idx(ep, 0);
525 idx_odd = get_bdt_idx(ep, 1);
526
527 if (ep_idx && (dev_data.ep_ctrl[ep_idx].status.in_enabled ||
528 dev_data.ep_ctrl[ep_idx].status.out_enabled)) {
529 LOG_WRN("endpoint 0x%x already enabled", ep);
530 return -EALREADY;
531 }
532
533 if (USB_EP_DIR_IS_OUT(ep)) {
534 bdt[idx_even].set.bd_ctrl = BD_DTS_MASK | BD_OWN_MASK;
535 bdt[idx_odd].set.bd_ctrl = 0U;
536 dev_data.ep_ctrl[ep_idx].status.out_odd = 0U;
537 dev_data.ep_ctrl[ep_idx].status.out_stalled = 0U;
538 dev_data.ep_ctrl[ep_idx].status.out_data1 = false;
539 dev_data.ep_ctrl[ep_idx].status.out_enabled = true;
540 } else {
541 bdt[idx_even].bd_fields = 0U;
542 bdt[idx_odd].bd_fields = 0U;
543 dev_data.ep_ctrl[ep_idx].status.in_odd = 0U;
544 dev_data.ep_ctrl[ep_idx].status.in_stalled = 0U;
545 dev_data.ep_ctrl[ep_idx].status.in_data1 = false;
546 dev_data.ep_ctrl[ep_idx].status.in_enabled = true;
547 }
548
549 LOG_INF("ep 0x%x, ep_idx %d", ep, ep_idx);
550
551 return 0;
552 }
553
usb_dc_ep_disable(const uint8_t ep)554 int usb_dc_ep_disable(const uint8_t ep)
555 {
556 uint8_t ep_idx = USB_EP_GET_IDX(ep);
557 uint8_t idx_even;
558 uint8_t idx_odd;
559
560 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
561 LOG_ERR("Wrong endpoint index/address");
562 return -EINVAL;
563 }
564
565 idx_even = get_bdt_idx(ep, 0);
566 idx_odd = get_bdt_idx(ep, 1);
567
568 LOG_INF("ep %x, idx %d", ep_idx, ep);
569
570 bdt[idx_even].bd_fields = 0U;
571 bdt[idx_odd].bd_fields = 0U;
572 if (USB_EP_DIR_IS_OUT(ep)) {
573 dev_data.ep_ctrl[ep_idx].status.out_enabled = false;
574 } else {
575 dev_data.ep_ctrl[ep_idx].status.in_enabled = false;
576 }
577
578 return 0;
579 }
580
usb_dc_ep_flush(const uint8_t ep)581 int usb_dc_ep_flush(const uint8_t ep)
582 {
583 uint8_t ep_idx = USB_EP_GET_IDX(ep);
584
585 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
586 LOG_ERR("Wrong endpoint index/address");
587 return -EINVAL;
588 }
589
590 LOG_DBG("ep %x, idx %d", ep_idx, ep);
591
592 return 0;
593 }
594
usb_dc_ep_write(const uint8_t ep,const uint8_t * const data,const uint32_t data_len,uint32_t * const ret_bytes)595 int usb_dc_ep_write(const uint8_t ep, const uint8_t *const data,
596 const uint32_t data_len, uint32_t * const ret_bytes)
597 {
598 uint8_t ep_idx = USB_EP_GET_IDX(ep);
599 uint32_t len_to_send = data_len;
600 uint8_t odd;
601 uint8_t bd_idx;
602 uint8_t *bufp;
603
604 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
605 LOG_ERR("Wrong endpoint index/address");
606 return -EINVAL;
607 }
608
609 odd = dev_data.ep_ctrl[ep_idx].status.in_odd;
610 bd_idx = get_bdt_idx(ep, odd);
611 bufp = (uint8_t *)bdt[bd_idx].buf_addr;
612
613 if (USB_EP_GET_DIR(ep) != USB_EP_DIR_IN) {
614 LOG_ERR("Wrong endpoint direction");
615 return -EINVAL;
616 }
617
618 if (dev_data.ep_ctrl[ep_idx].status.in_stalled) {
619 LOG_WRN("endpoint is stalled");
620 return -EBUSY;
621 }
622
623 while (bdt[bd_idx].get.own) {
624 LOG_DBG("ep 0x%x is busy", ep);
625 k_yield();
626 }
627
628 LOG_DBG("bd idx %x bufp %p odd %d", bd_idx, bufp, odd);
629
630 if (data_len > dev_data.ep_ctrl[ep_idx].mps_in) {
631 len_to_send = dev_data.ep_ctrl[ep_idx].mps_in;
632 }
633
634 bdt[bd_idx].set.bc = len_to_send;
635
636 for (uint32_t n = 0; n < len_to_send; n++) {
637 bufp[n] = data[n];
638 }
639
640 dev_data.ep_ctrl[ep_idx].status.in_odd = ~odd;
641 if (dev_data.ep_ctrl[ep_idx].status.in_data1) {
642 bdt[bd_idx].set.bd_ctrl = BD_DTS_MASK |
643 BD_DATA01_MASK |
644 BD_OWN_MASK;
645 } else {
646 bdt[bd_idx].set.bd_ctrl = BD_DTS_MASK | BD_OWN_MASK;
647 }
648
649 /* Toggle next Data1 */
650 dev_data.ep_ctrl[ep_idx].status.in_data1 ^= 1;
651
652 LOG_DBG("ep 0x%x write %d bytes from %d", ep, len_to_send, data_len);
653
654 if (ret_bytes) {
655 *ret_bytes = len_to_send;
656 }
657
658 return 0;
659 }
660
usb_dc_ep_read_wait(uint8_t ep,uint8_t * data,uint32_t max_data_len,uint32_t * read_bytes)661 int usb_dc_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len,
662 uint32_t *read_bytes)
663 {
664 uint8_t ep_idx = USB_EP_GET_IDX(ep);
665 uint32_t data_len;
666 uint8_t bd_idx;
667 uint8_t *bufp;
668
669 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
670 LOG_ERR("Wrong endpoint index/address");
671 return -EINVAL;
672 }
673
674 /* select the index of active endpoint buffer */
675 bd_idx = get_bdt_idx(ep, dev_data.ep_ctrl[ep_idx].status.out_odd);
676 bufp = (uint8_t *)bdt[bd_idx].buf_addr;
677
678 if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) {
679 LOG_ERR("Wrong endpoint direction");
680 return -EINVAL;
681 }
682
683 if (dev_data.ep_ctrl[ep_idx].status.out_stalled) {
684 LOG_WRN("endpoint is stalled");
685 return -EBUSY;
686 }
687
688 /* Allow to read 0 bytes */
689 if (!data && max_data_len) {
690 LOG_ERR("Wrong arguments");
691 return -EINVAL;
692 }
693
694 while (bdt[bd_idx].get.own) {
695 LOG_ERR("Endpoint is occupied by the controller");
696 return -EBUSY;
697 }
698
699 data_len = bdt[bd_idx].get.bc;
700
701 if (!data && !max_data_len) {
702 /*
703 * When both buffer and max data to read are zero return
704 * the available data in buffer.
705 */
706 if (read_bytes) {
707 *read_bytes = data_len;
708 }
709 return 0;
710 }
711
712 if (data_len > max_data_len) {
713 LOG_WRN("Not enough room to copy all the data!");
714 data_len = max_data_len;
715 }
716
717 if (data != NULL) {
718 for (uint32_t i = 0; i < data_len; i++) {
719 data[i] = bufp[i];
720 }
721 }
722
723 LOG_DBG("Read idx %d, req %d, read %d bytes", bd_idx, max_data_len,
724 data_len);
725
726 if (read_bytes) {
727 *read_bytes = data_len;
728 }
729
730 return 0;
731 }
732
733
usb_dc_ep_read_continue(uint8_t ep)734 int usb_dc_ep_read_continue(uint8_t ep)
735 {
736 uint8_t ep_idx = USB_EP_GET_IDX(ep);
737 uint8_t bd_idx;
738
739 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
740 LOG_ERR("Wrong endpoint index/address");
741 return -EINVAL;
742 }
743
744 bd_idx = get_bdt_idx(ep, dev_data.ep_ctrl[ep_idx].status.out_odd);
745
746 if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) {
747 LOG_ERR("Wrong endpoint direction");
748 return -EINVAL;
749 }
750
751 if (bdt[bd_idx].get.own) {
752 /* May occur when usb_transfer initializes the OUT transfer */
753 LOG_WRN("Current buffer is claimed by the controller");
754 return 0;
755 }
756
757 /* select the index of the next endpoint buffer */
758 bd_idx = get_bdt_idx(ep, ~dev_data.ep_ctrl[ep_idx].status.out_odd);
759 /* Update next toggle bit */
760 dev_data.ep_ctrl[ep_idx].status.out_data1 ^= 1;
761 bdt[bd_idx].set.bc = dev_data.ep_ctrl[ep_idx].mps_out;
762
763 /* Reset next buffer descriptor and set next toggle bit */
764 if (dev_data.ep_ctrl[ep_idx].status.out_data1) {
765 bdt[bd_idx].set.bd_ctrl = BD_DTS_MASK |
766 BD_DATA01_MASK |
767 BD_OWN_MASK;
768 } else {
769 bdt[bd_idx].set.bd_ctrl = BD_DTS_MASK | BD_OWN_MASK;
770 }
771
772 /* Resume TX token processing, see USBx_CTL field descriptions */
773 if (ep_idx == 0U) {
774 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
775 }
776
777 LOG_DBG("idx next %x", bd_idx);
778
779 return 0;
780 }
781
usb_dc_ep_read(const uint8_t ep,uint8_t * const data,const uint32_t max_data_len,uint32_t * const read_bytes)782 int usb_dc_ep_read(const uint8_t ep, uint8_t *const data,
783 const uint32_t max_data_len, uint32_t *const read_bytes)
784 {
785 int retval = usb_dc_ep_read_wait(ep, data, max_data_len, read_bytes);
786
787 if (retval) {
788 return retval;
789 }
790
791 if (!data && !max_data_len) {
792 /* When both buffer and max data to read are zero the above
793 * call would fetch the data len and we simply return.
794 */
795 return 0;
796 }
797
798 if (usb_dc_ep_read_continue(ep) != 0) {
799 return -EINVAL;
800 }
801
802 LOG_DBG("");
803
804 return 0;
805 }
806
usb_dc_ep_set_callback(const uint8_t ep,const usb_dc_ep_callback cb)807 int usb_dc_ep_set_callback(const uint8_t ep, const usb_dc_ep_callback cb)
808 {
809 uint8_t ep_idx = USB_EP_GET_IDX(ep);
810
811 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
812 LOG_ERR("Wrong endpoint index/address");
813 return -EINVAL;
814 }
815
816 if (!dev_data.attached) {
817 return -EINVAL;
818 }
819
820 if (ep & USB_EP_DIR_IN) {
821 dev_data.ep_ctrl[ep_idx].cb_in = cb;
822 } else {
823 dev_data.ep_ctrl[ep_idx].cb_out = cb;
824 }
825 LOG_DBG("ep_idx %x", ep_idx);
826
827 return 0;
828 }
829
usb_dc_set_status_callback(const usb_dc_status_callback cb)830 void usb_dc_set_status_callback(const usb_dc_status_callback cb)
831 {
832 LOG_DBG("");
833
834 dev_data.status_cb = cb;
835 }
836
usb_dc_ep_mps(const uint8_t ep)837 int usb_dc_ep_mps(const uint8_t ep)
838 {
839 uint8_t ep_idx = USB_EP_GET_IDX(ep);
840
841 if (ep_idx > (NUM_OF_EP_MAX - 1)) {
842 LOG_ERR("Wrong endpoint index/address");
843 return -EINVAL;
844 }
845
846 if (ep & USB_EP_DIR_IN) {
847 return dev_data.ep_ctrl[ep_idx].mps_in;
848 } else {
849 return dev_data.ep_ctrl[ep_idx].mps_out;
850 }
851 }
852
reenable_control_endpoints(void)853 static inline void reenable_control_endpoints(void)
854 {
855 struct usb_dc_ep_cfg_data ep_cfg;
856
857 /* Reconfigure control endpoint 0 after a reset */
858 ep_cfg.ep_addr = USB_CONTROL_EP_OUT;
859 ep_cfg.ep_mps = USB_CONTROL_EP_MPS;
860 ep_cfg.ep_type = USB_DC_EP_CONTROL;
861 usb_dc_ep_configure(&ep_cfg);
862 ep_cfg.ep_addr = USB_CONTROL_EP_IN;
863 usb_dc_ep_configure(&ep_cfg);
864
865 /* Enable both endpoint directions */
866 usb_dc_ep_enable(USB_CONTROL_EP_OUT);
867 usb_dc_ep_enable(USB_CONTROL_EP_IN);
868 }
869
usb_kinetis_isr_handler(void)870 static void usb_kinetis_isr_handler(void)
871 {
872 uint8_t istatus = USB0->ISTAT;
873 uint8_t status = USB0->STAT;
874 struct cb_msg msg;
875
876
877 if (istatus & USB_ISTAT_USBRST_MASK) {
878 dev_data.address = 0U;
879 USB0->ADDR = (uint8_t)0;
880 /*
881 * Device reset is not possible because the stack does not
882 * configure the endpoints after the USB_DC_RESET event,
883 * therefore, we must re-enable the default control 0 endpoint
884 * after a reset event
885 */
886 USB0->CTL |= USB_CTL_ODDRST_MASK;
887 USB0->CTL &= ~USB_CTL_ODDRST_MASK;
888 reenable_control_endpoints();
889 msg.ep = 0U;
890 msg.type = USB_DC_CB_TYPE_MGMT;
891 msg.cb = USB_DC_RESET;
892 k_msgq_put(&usb_dc_msgq, &msg, K_NO_WAIT);
893 }
894
895 if (istatus == USB_ISTAT_ERROR_MASK) {
896 USB0->ERRSTAT = 0xFF;
897 msg.ep = 0U;
898 msg.type = USB_DC_CB_TYPE_MGMT;
899 msg.cb = USB_DC_ERROR;
900 k_msgq_put(&usb_dc_msgq, &msg, K_NO_WAIT);
901 }
902
903 if (istatus & USB_ISTAT_STALL_MASK) {
904 if (dev_data.ep_ctrl[0].status.out_stalled) {
905 usb_dc_ep_clear_stall(0);
906 }
907 if (dev_data.ep_ctrl[0].status.in_stalled) {
908 usb_dc_ep_clear_stall(0x80);
909 }
910 }
911
912 if (istatus & USB_ISTAT_TOKDNE_MASK) {
913
914 uint8_t ep_idx = status >> USB_STAT_ENDP_SHIFT;
915 uint8_t ep = ((status << 4) & USB_EP_DIR_IN) | ep_idx;
916 uint8_t odd = (status & USB_STAT_ODD_MASK) >> USB_STAT_ODD_SHIFT;
917 uint8_t idx = get_bdt_idx(ep, odd);
918 uint8_t token_pid = bdt[idx].get.tok_pid;
919
920 msg.ep = ep;
921 msg.type = USB_DC_CB_TYPE_EP;
922
923 switch (token_pid) {
924 case KINETIS_SETUP_TOKEN:
925 dev_data.ep_ctrl[ep_idx].status.out_odd = odd;
926 /* clear tx entries */
927 bdt[BD_IDX_EP0TX_EVEN].bd_fields = 0U;
928 bdt[BD_IDX_EP0TX_ODD].bd_fields = 0U;
929 /*
930 * Set/Reset here the toggle bits for control endpoint
931 * because the device stack does not care about it.
932 */
933 dev_data.ep_ctrl[ep_idx].status.in_data1 = true;
934 dev_data.ep_ctrl[ep_idx].status.out_data1 = false;
935 dev_data.ep_ctrl[ep_idx].status.out_odd = odd;
936
937 msg.cb = USB_DC_EP_SETUP;
938 k_msgq_put(&usb_dc_msgq, &msg, K_NO_WAIT);
939 break;
940 case KINETIS_OUT_TOKEN:
941 dev_data.ep_ctrl[ep_idx].status.out_odd = odd;
942
943 msg.cb = USB_DC_EP_DATA_OUT;
944 k_msgq_put(&usb_dc_msgq, &msg, K_NO_WAIT);
945 break;
946 case KINETIS_IN_TOKEN:
947 /* SET ADDRESS workaround */
948 if (dev_data.address & 0x80) {
949 USB0->ADDR = dev_data.address & 0x7f;
950 dev_data.address = 0U;
951 }
952
953 msg.cb = USB_DC_EP_DATA_IN;
954 k_msgq_put(&usb_dc_msgq, &msg, K_NO_WAIT);
955 break;
956 default:
957 break;
958 }
959 }
960
961 if (istatus & USB_ISTAT_SLEEP_MASK) {
962 /* Enable resume interrupt */
963 USB0->INTEN |= USB_INTEN_RESUMEEN_MASK;
964 msg.ep = 0U;
965 msg.type = USB_DC_CB_TYPE_MGMT;
966 msg.cb = USB_DC_SUSPEND;
967 k_msgq_put(&usb_dc_msgq, &msg, K_NO_WAIT);
968 }
969
970 if (istatus & USB_ISTAT_RESUME_MASK) {
971 /* Disable resume interrupt */
972 USB0->INTEN &= ~USB_INTEN_RESUMEEN_MASK;
973 msg.ep = 0U;
974 msg.type = USB_DC_CB_TYPE_MGMT;
975 msg.cb = USB_DC_RESUME;
976 k_msgq_put(&usb_dc_msgq, &msg, K_NO_WAIT);
977 }
978
979 /* Clear interrupt status bits */
980 USB0->ISTAT = istatus;
981 }
982
983 /*
984 * This thread is only used to not run the USB device stack and endpoint
985 * callbacks in the ISR context, which happens when an callback function
986 * is called. TODO: something similar should be implemented in the USB
987 * device stack so that it can be used by all drivers.
988 */
usb_kinetis_thread_main(void * arg1,void * unused1,void * unused2)989 static void usb_kinetis_thread_main(void *arg1, void *unused1, void *unused2)
990 {
991 ARG_UNUSED(arg1);
992 ARG_UNUSED(unused1);
993 ARG_UNUSED(unused2);
994 struct cb_msg msg;
995 uint8_t ep_idx;
996
997 while (true) {
998 k_msgq_get(&usb_dc_msgq, &msg, K_FOREVER);
999 ep_idx = USB_EP_GET_IDX(msg.ep);
1000
1001 if (msg.type == USB_DC_CB_TYPE_EP) {
1002 switch (msg.cb) {
1003 case USB_DC_EP_SETUP:
1004 if (dev_data.ep_ctrl[ep_idx].cb_out) {
1005 dev_data.ep_ctrl[ep_idx].cb_out(msg.ep,
1006 USB_DC_EP_SETUP);
1007 }
1008 break;
1009 case USB_DC_EP_DATA_OUT:
1010 if (dev_data.ep_ctrl[ep_idx].cb_out) {
1011 dev_data.ep_ctrl[ep_idx].cb_out(msg.ep,
1012 USB_DC_EP_DATA_OUT);
1013 }
1014 break;
1015 case USB_DC_EP_DATA_IN:
1016 if (dev_data.ep_ctrl[ep_idx].cb_in) {
1017 dev_data.ep_ctrl[ep_idx].cb_in(msg.ep,
1018 USB_DC_EP_DATA_IN);
1019 }
1020 break;
1021 default:
1022 LOG_ERR("unknown msg");
1023 break;
1024 }
1025 } else if (dev_data.status_cb) {
1026 switch (msg.cb) {
1027 case USB_DC_RESET:
1028 dev_data.status_cb(USB_DC_RESET, NULL);
1029 break;
1030 case USB_DC_ERROR:
1031 dev_data.status_cb(USB_DC_ERROR, NULL);
1032 break;
1033 case USB_DC_SUSPEND:
1034 dev_data.status_cb(USB_DC_SUSPEND, NULL);
1035 break;
1036 case USB_DC_RESUME:
1037 dev_data.status_cb(USB_DC_RESUME, NULL);
1038 break;
1039 default:
1040 LOG_ERR("unknown msg");
1041 break;
1042 }
1043 }
1044 }
1045 }
1046
usb_kinetis_init(void)1047 static int usb_kinetis_init(void)
1048 {
1049
1050 (void)memset(bdt, 0, sizeof(bdt));
1051 k_thread_create(&dev_data.thread, dev_data.thread_stack,
1052 USBD_THREAD_STACK_SIZE,
1053 usb_kinetis_thread_main, NULL, NULL, NULL,
1054 K_PRIO_COOP(2), 0, K_NO_WAIT);
1055 k_thread_name_set(&dev_data.thread, "usb_kinetis");
1056
1057 IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
1058 usb_kinetis_isr_handler, 0, 0);
1059 irq_enable(DT_INST_IRQN(0));
1060
1061 return 0;
1062 }
1063
1064 SYS_INIT(usb_kinetis_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
1065