1 /*
2 * Copyright (c) 2017 PHYTEC Messtechnik GmbH
3 * Copyright (c) 2022 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /*
9 * Driver for the USBFSOTG device controller which can be found on
10 * devices like Kinetis K64F.
11 */
12 #define DT_DRV_COMPAT nxp_kinetis_usbd
13
14 #include <soc.h>
15 #include <string.h>
16 #include <stdio.h>
17
18 #include <zephyr/device.h>
19 #include <zephyr/kernel.h>
20 #include <zephyr/sys/byteorder.h>
21 #include <zephyr/drivers/usb/udc.h>
22
23 #include "udc_common.h"
24
25 #include <zephyr/logging/log.h>
26 LOG_MODULE_REGISTER(usbfsotg, CONFIG_UDC_DRIVER_LOG_LEVEL);
27
28 #define USBFSOTG_BD_OWN BIT(5)
29 #define USBFSOTG_BD_DATA1 BIT(4)
30 #define USBFSOTG_BD_KEEP BIT(3)
31 #define USBFSOTG_BD_NINC BIT(2)
32 #define USBFSOTG_BD_DTS BIT(1)
33 #define USBFSOTG_BD_STALL BIT(0)
34
35 #define USBFSOTG_SETUP_TOKEN 0x0D
36 #define USBFSOTG_IN_TOKEN 0x09
37 #define USBFSOTG_OUT_TOKEN 0x01
38
39 #define USBFSOTG_PERID 0x04
40 #define USBFSOTG_REV 0x33
41
42 /*
43 * There is no real advantage to change control endpoint size
44 * but we can use it for testing UDC driver API and higher layers.
45 */
46 #define USBFSOTG_MPS0 UDC_MPS0_64
47 #define USBFSOTG_EP0_SIZE 64
48
49 /*
50 * Buffer Descriptor (BD) entry provides endpoint buffer control
51 * information for USBFSOTG controller. Every endpoint direction requires
52 * two BD entries.
53 */
54 struct usbfsotg_bd {
55 union {
56 uint32_t bd_fields;
57
58 struct {
59 uint32_t reserved_1_0 : 2;
60 uint32_t tok_pid : 4;
61 uint32_t data1 : 1;
62 uint32_t own : 1;
63 uint32_t reserved_15_8 : 8;
64 uint32_t bc : 16;
65 } get __packed;
66
67 struct {
68 uint32_t reserved_1_0 : 2;
69 uint32_t bd_ctrl : 6;
70 uint32_t reserved_15_8 : 8;
71 uint32_t bc : 16;
72 } set __packed;
73
74 } __packed;
75 uint32_t buf_addr;
76 } __packed;
77
78 struct usbfsotg_config {
79 USB_Type *base;
80 /*
81 * Pointer to Buffer Descriptor Table for the endpoints
82 * buffer management. The driver configuration with 16 fully
83 * bidirectional endpoints would require four BD entries
84 * per endpoint and 512 bytes of memory.
85 */
86 struct usbfsotg_bd *bdt;
87 void (*irq_enable_func)(const struct device *dev);
88 void (*irq_disable_func)(const struct device *dev);
89 size_t num_of_eps;
90 struct udc_ep_config *ep_cfg_in;
91 struct udc_ep_config *ep_cfg_out;
92 };
93
94 enum usbfsotg_event_type {
95 /* Trigger next transfer, must not be used for control OUT */
96 USBFSOTG_EVT_XFER,
97 /* Setup packet received */
98 USBFSOTG_EVT_SETUP,
99 /* OUT transaction for specific endpoint is finished */
100 USBFSOTG_EVT_DOUT,
101 /* IN transaction for specific endpoint is finished */
102 USBFSOTG_EVT_DIN,
103 /* Workaround for clear halt in ISR */
104 USBFSOTG_EVT_CLEAR_HALT,
105 };
106
107 /* Structure for driver's endpoint events */
108 struct usbfsotg_ep_event {
109 sys_snode_t node;
110 const struct device *dev;
111 enum usbfsotg_event_type event;
112 uint8_t ep;
113 };
114
115 K_MEM_SLAB_DEFINE(usbfsotg_ee_slab, sizeof(struct usbfsotg_ep_event),
116 CONFIG_UDC_KINETIS_EVENT_COUNT, sizeof(void *));
117
118 struct usbfsotg_data {
119 struct k_work work;
120 struct k_fifo fifo;
121 /*
122 * Buffer pointers and busy flags used only for control OUT
123 * to map the buffers to BDs when both are occupied
124 */
125 struct net_buf *out_buf[2];
126 bool busy[2];
127 };
128
129 static int usbfsotg_ep_clear_halt(const struct device *dev,
130 struct udc_ep_config *const cfg);
131
132 /* Get buffer descriptor (BD) based on endpoint address */
usbfsotg_get_ebd(const struct device * const dev,struct udc_ep_config * const cfg,const bool opposite)133 static struct usbfsotg_bd *usbfsotg_get_ebd(const struct device *const dev,
134 struct udc_ep_config *const cfg,
135 const bool opposite)
136 {
137 const struct usbfsotg_config *config = dev->config;
138 uint8_t bd_idx;
139
140 bd_idx = USB_EP_GET_IDX(cfg->addr) * 4U + (cfg->stat.odd ^ opposite);
141 if (USB_EP_DIR_IS_IN(cfg->addr)) {
142 bd_idx += 2U;
143 }
144
145 return &config->bdt[bd_idx];
146 }
147
usbfsotg_bd_is_busy(const struct usbfsotg_bd * const bd)148 static bool usbfsotg_bd_is_busy(const struct usbfsotg_bd *const bd)
149 {
150 /* Do not use it for control OUT endpoint */
151 return bd->get.own;
152 }
153
usbfsotg_bd_set_ctrl(struct usbfsotg_bd * const bd,const size_t bc,uint8_t * const data,const bool data1)154 static void usbfsotg_bd_set_ctrl(struct usbfsotg_bd *const bd,
155 const size_t bc,
156 uint8_t *const data,
157 const bool data1)
158 {
159 bd->set.bc = bc;
160 bd->buf_addr = POINTER_TO_UINT(data);
161
162 if (data1) {
163 bd->set.bd_ctrl = USBFSOTG_BD_OWN | USBFSOTG_BD_DATA1 |
164 USBFSOTG_BD_DTS;
165 } else {
166 bd->set.bd_ctrl = USBFSOTG_BD_OWN | USBFSOTG_BD_DTS;
167 }
168
169 }
170
171 /* Resume TX token processing, see USBx_CTL field descriptions */
usbfsotg_resume_tx(const struct device * dev)172 static ALWAYS_INLINE void usbfsotg_resume_tx(const struct device *dev)
173 {
174 const struct usbfsotg_config *config = dev->config;
175 USB_Type *base = config->base;
176
177 base->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
178 }
179
usbfsotg_xfer_continue(const struct device * dev,struct udc_ep_config * const cfg,struct net_buf * const buf)180 static int usbfsotg_xfer_continue(const struct device *dev,
181 struct udc_ep_config *const cfg,
182 struct net_buf *const buf)
183 {
184 const struct usbfsotg_config *config = dev->config;
185 USB_Type *base = config->base;
186 struct usbfsotg_bd *bd;
187 uint8_t *data_ptr;
188 size_t len;
189
190 bd = usbfsotg_get_ebd(dev, cfg, false);
191 if (unlikely(usbfsotg_bd_is_busy(bd))) {
192 LOG_ERR("ep 0x%02x buf busy", cfg->addr);
193 __ASSERT_NO_MSG(false);
194 return -EBUSY;
195 }
196
197 if (USB_EP_DIR_IS_OUT(cfg->addr)) {
198 len = MIN(net_buf_tailroom(buf), cfg->mps);
199 data_ptr = net_buf_tail(buf);
200 } else {
201 len = MIN(buf->len, cfg->mps);
202 data_ptr = buf->data;
203 }
204
205 usbfsotg_bd_set_ctrl(bd, len, data_ptr, cfg->stat.data1);
206
207 if (USB_EP_GET_IDX(cfg->addr) == 0U) {
208 usbfsotg_resume_tx(dev);
209 }
210
211 LOG_DBG("xfer %p, bd %p, ENDPT 0x%x, bd field 0x%02x",
212 buf, bd, base->ENDPOINT[USB_EP_GET_IDX(cfg->addr)].ENDPT,
213 bd->bd_fields);
214
215 return 0;
216 }
217
218 /* Initiate a new transfer, must not be used for control endpoint OUT */
usbfsotg_xfer_next(const struct device * dev,struct udc_ep_config * const cfg)219 static int usbfsotg_xfer_next(const struct device *dev,
220 struct udc_ep_config *const cfg)
221 {
222 struct net_buf *buf;
223
224 buf = udc_buf_peek(dev, cfg->addr);
225 if (buf == NULL) {
226 return -ENODATA;
227 }
228
229 return usbfsotg_xfer_continue(dev, cfg, buf);
230 }
231
usbfsotg_ctrl_feed_start(const struct device * dev,struct net_buf * const buf)232 static inline int usbfsotg_ctrl_feed_start(const struct device *dev,
233 struct net_buf *const buf)
234 {
235 struct usbfsotg_data *priv = udc_get_private(dev);
236 struct udc_ep_config *cfg;
237 struct usbfsotg_bd *bd;
238 size_t length;
239
240 cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
241 if (priv->busy[cfg->stat.odd]) {
242 return -EBUSY;
243 }
244
245 bd = usbfsotg_get_ebd(dev, cfg, false);
246 length = MIN(net_buf_tailroom(buf), cfg->mps);
247
248 priv->out_buf[cfg->stat.odd] = buf;
249 priv->busy[cfg->stat.odd] = true;
250 usbfsotg_bd_set_ctrl(bd, length, net_buf_tail(buf), cfg->stat.data1);
251 LOG_DBG("ep0 %p|odd: %u|d: %u", buf, cfg->stat.odd, cfg->stat.data1);
252
253 return 0;
254 }
255
usbfsotg_ctrl_feed_start_next(const struct device * dev,struct net_buf * const buf)256 static inline int usbfsotg_ctrl_feed_start_next(const struct device *dev,
257 struct net_buf *const buf)
258 {
259 struct usbfsotg_data *priv = udc_get_private(dev);
260 struct udc_ep_config *cfg;
261 struct usbfsotg_bd *bd;
262 size_t length;
263
264 cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
265 if (priv->busy[!cfg->stat.odd]) {
266 return -EBUSY;
267 }
268
269 bd = usbfsotg_get_ebd(dev, cfg, true);
270 length = MIN(net_buf_tailroom(buf), cfg->mps);
271
272 priv->out_buf[!cfg->stat.odd] = buf;
273 priv->busy[!cfg->stat.odd] = true;
274 usbfsotg_bd_set_ctrl(bd, length, net_buf_tail(buf), cfg->stat.data1);
275 LOG_DBG("ep0 %p|odd: %u|d: %u (n)", buf, cfg->stat.odd, cfg->stat.data1);
276
277 return 0;
278 }
279
280 /*
281 * Allocate buffer and initiate a new control OUT transfer,
282 * use successive buffer descriptor when next is true.
283 */
usbfsotg_ctrl_feed_dout(const struct device * dev,const size_t length,const bool next,const bool resume_tx)284 static int usbfsotg_ctrl_feed_dout(const struct device *dev,
285 const size_t length,
286 const bool next,
287 const bool resume_tx)
288 {
289 struct net_buf *buf;
290 int ret;
291
292 buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, length);
293 if (buf == NULL) {
294 return -ENOMEM;
295 }
296
297 if (next) {
298 ret = usbfsotg_ctrl_feed_start_next(dev, buf);
299 } else {
300 ret = usbfsotg_ctrl_feed_start(dev, buf);
301 }
302
303 if (ret) {
304 net_buf_unref(buf);
305 return ret;
306 }
307
308 if (resume_tx) {
309 usbfsotg_resume_tx(dev);
310 }
311
312 return 0;
313 }
314
work_handler_setup(const struct device * dev)315 static inline int work_handler_setup(const struct device *dev)
316 {
317 struct net_buf *buf;
318 int err;
319
320 buf = udc_buf_get(dev, USB_CONTROL_EP_OUT);
321 if (buf == NULL) {
322 return -ENODATA;
323 }
324
325 /* Update to next stage of control transfer */
326 udc_ctrl_update_stage(dev, buf);
327
328 if (udc_ctrl_stage_is_data_out(dev)) {
329 /* Allocate and feed buffer for data OUT stage */
330 LOG_DBG("s:%p|feed for -out-", buf);
331 err = usbfsotg_ctrl_feed_dout(dev, udc_data_stage_length(buf),
332 false, true);
333 if (err == -ENOMEM) {
334 err = udc_submit_ep_event(dev, buf, err);
335 }
336 } else if (udc_ctrl_stage_is_data_in(dev)) {
337 /*
338 * Here we have to feed both descriptor tables so that
339 * no setup packets are lost in case of successive
340 * status OUT stage and next setup.
341 */
342 LOG_DBG("s:%p|feed for -in-status >setup", buf);
343 err = usbfsotg_ctrl_feed_dout(dev, 8U, false, false);
344 if (err == 0) {
345 err = usbfsotg_ctrl_feed_dout(dev, 8U, true, true);
346 }
347
348 /* Finally alloc buffer for IN and submit to upper layer */
349 if (err == 0) {
350 err = udc_ctrl_submit_s_in_status(dev);
351 }
352 } else {
353 LOG_DBG("s:%p|feed >setup", buf);
354 /*
355 * For all other cases we feed with a buffer
356 * large enough for setup packet.
357 */
358 err = usbfsotg_ctrl_feed_dout(dev, 8U, false, true);
359 if (err == 0) {
360 err = udc_ctrl_submit_s_status(dev);
361 }
362 }
363
364 return err;
365 }
366
work_handler_out(const struct device * dev,const uint8_t ep)367 static inline int work_handler_out(const struct device *dev,
368 const uint8_t ep)
369 {
370 struct net_buf *buf;
371 int err = 0;
372
373 buf = udc_buf_get(dev, ep);
374 if (buf == NULL) {
375 return -ENODATA;
376 }
377
378 if (ep == USB_CONTROL_EP_OUT) {
379 if (udc_ctrl_stage_is_status_out(dev)) {
380 /* s-in-status finished, next bd is already fed */
381 LOG_DBG("dout:%p|no feed", buf);
382 /* Status stage finished, notify upper layer */
383 udc_ctrl_submit_status(dev, buf);
384 } else {
385 /*
386 * For all other cases we feed with a buffer
387 * large enough for setup packet.
388 */
389 LOG_DBG("dout:%p|feed >setup", buf);
390 err = usbfsotg_ctrl_feed_dout(dev, 8U, false, false);
391 }
392
393 /* Update to next stage of control transfer */
394 udc_ctrl_update_stage(dev, buf);
395
396 if (udc_ctrl_stage_is_status_in(dev)) {
397 err = udc_ctrl_submit_s_out_status(dev, buf);
398 }
399 } else {
400 err = udc_submit_ep_event(dev, buf, 0);
401 }
402
403 return err;
404 }
405
work_handler_in(const struct device * dev,const uint8_t ep)406 static inline int work_handler_in(const struct device *dev,
407 const uint8_t ep)
408 {
409 struct net_buf *buf;
410
411 buf = udc_buf_get(dev, ep);
412 if (buf == NULL) {
413 return -ENODATA;
414 }
415
416 if (ep == USB_CONTROL_EP_IN) {
417 if (udc_ctrl_stage_is_status_in(dev) ||
418 udc_ctrl_stage_is_no_data(dev)) {
419 /* Status stage finished, notify upper layer */
420 udc_ctrl_submit_status(dev, buf);
421 }
422
423 /* Update to next stage of control transfer */
424 udc_ctrl_update_stage(dev, buf);
425
426 if (udc_ctrl_stage_is_status_out(dev)) {
427 /*
428 * IN transfer finished, release buffer,
429 * control OUT buffer should be already fed.
430 */
431 net_buf_unref(buf);
432 }
433
434 return 0;
435 }
436
437 return udc_submit_ep_event(dev, buf, 0);
438 }
439
usbfsotg_event_submit(const struct device * dev,const uint8_t ep,const enum usbfsotg_event_type event)440 static void usbfsotg_event_submit(const struct device *dev,
441 const uint8_t ep,
442 const enum usbfsotg_event_type event)
443 {
444 struct usbfsotg_data *priv = udc_get_private(dev);
445 struct usbfsotg_ep_event *ev;
446 int ret;
447
448 ret = k_mem_slab_alloc(&usbfsotg_ee_slab, (void **)&ev, K_NO_WAIT);
449 if (ret) {
450 udc_submit_event(dev, UDC_EVT_ERROR, ret);
451 LOG_ERR("Failed to allocate slab");
452 return;
453 }
454
455 ev->dev = dev;
456 ev->ep = ep;
457 ev->event = event;
458 k_fifo_put(&priv->fifo, ev);
459 k_work_submit_to_queue(udc_get_work_q(), &priv->work);
460 }
461
xfer_work_handler(struct k_work * item)462 static void xfer_work_handler(struct k_work *item)
463 {
464 struct usbfsotg_ep_event *ev;
465 struct usbfsotg_data *priv;
466
467 priv = CONTAINER_OF(item, struct usbfsotg_data, work);
468 while ((ev = k_fifo_get(&priv->fifo, K_NO_WAIT)) != NULL) {
469 struct udc_ep_config *ep_cfg;
470 int err = 0;
471
472 LOG_DBG("dev %p, ep 0x%02x, event %u",
473 ev->dev, ev->ep, ev->event);
474 ep_cfg = udc_get_ep_cfg(ev->dev, ev->ep);
475 if (unlikely(ep_cfg == NULL)) {
476 udc_submit_event(ev->dev, UDC_EVT_ERROR, -ENODATA);
477 goto xfer_work_error;
478 }
479
480 switch (ev->event) {
481 case USBFSOTG_EVT_SETUP:
482 err = work_handler_setup(ev->dev);
483 break;
484 case USBFSOTG_EVT_DOUT:
485 err = work_handler_out(ev->dev, ev->ep);
486 udc_ep_set_busy(ev->dev, ev->ep, false);
487 break;
488 case USBFSOTG_EVT_DIN:
489 err = work_handler_in(ev->dev, ev->ep);
490 udc_ep_set_busy(ev->dev, ev->ep, false);
491 break;
492 case USBFSOTG_EVT_CLEAR_HALT:
493 err = usbfsotg_ep_clear_halt(ev->dev, ep_cfg);
494 case USBFSOTG_EVT_XFER:
495 default:
496 break;
497 }
498
499 if (unlikely(err)) {
500 udc_submit_event(ev->dev, UDC_EVT_ERROR, err);
501 }
502
503 /* Peek next transfer */
504 if (ev->ep != USB_CONTROL_EP_OUT && !udc_ep_is_busy(ev->dev, ev->ep)) {
505 if (usbfsotg_xfer_next(ev->dev, ep_cfg) == 0) {
506 udc_ep_set_busy(ev->dev, ev->ep, true);
507 }
508 }
509
510 xfer_work_error:
511 k_mem_slab_free(&usbfsotg_ee_slab, (void *)ev);
512 }
513 }
514
stat_reg_get_ep(const uint8_t status)515 static ALWAYS_INLINE uint8_t stat_reg_get_ep(const uint8_t status)
516 {
517 uint8_t ep_idx = status >> USB_STAT_ENDP_SHIFT;
518
519 return (status & USB_STAT_TX_MASK) ? (USB_EP_DIR_IN | ep_idx) : ep_idx;
520 }
521
stat_reg_is_odd(const uint8_t status)522 static ALWAYS_INLINE bool stat_reg_is_odd(const uint8_t status)
523 {
524 return (status & USB_STAT_ODD_MASK) >> USB_STAT_ODD_SHIFT;
525 }
526
set_control_in_pid_data1(const struct device * dev)527 static ALWAYS_INLINE void set_control_in_pid_data1(const struct device *dev)
528 {
529 struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN);
530
531 /* Set DATA1 PID for data or status stage */
532 ep_cfg->stat.data1 = true;
533 }
534
isr_handle_xfer_done(const struct device * dev,const uint8_t istatus,const uint8_t status)535 static ALWAYS_INLINE void isr_handle_xfer_done(const struct device *dev,
536 const uint8_t istatus,
537 const uint8_t status)
538 {
539 struct usbfsotg_data *priv = udc_get_private(dev);
540 uint8_t ep = stat_reg_get_ep(status);
541 bool odd = stat_reg_is_odd(status);
542 struct usbfsotg_bd *bd, *bd_op;
543 struct udc_ep_config *ep_cfg;
544 struct net_buf *buf;
545 uint8_t token_pid;
546 bool data1;
547 size_t len;
548
549 ep_cfg = udc_get_ep_cfg(dev, ep);
550 bd = usbfsotg_get_ebd(dev, ep_cfg, false);
551 bd_op = usbfsotg_get_ebd(dev, ep_cfg, true);
552 token_pid = bd->get.tok_pid;
553 len = bd->get.bc;
554 data1 = bd->get.data1 ? true : false;
555
556 LOG_DBG("TOKDNE, ep 0x%02x len %u odd %u data1 %u",
557 ep, len, odd, data1);
558
559 switch (token_pid) {
560 case USBFSOTG_SETUP_TOKEN:
561 ep_cfg->stat.odd = !odd;
562 ep_cfg->stat.data1 = true;
563 set_control_in_pid_data1(dev);
564
565 if (priv->out_buf[odd] != NULL) {
566 net_buf_add(priv->out_buf[odd], len);
567 udc_ep_buf_set_setup(priv->out_buf[odd]);
568 udc_buf_put(ep_cfg, priv->out_buf[odd]);
569 priv->busy[odd] = false;
570 priv->out_buf[odd] = NULL;
571 usbfsotg_event_submit(dev, ep, USBFSOTG_EVT_SETUP);
572 } else {
573 LOG_ERR("No buffer for ep 0x00");
574 udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS);
575 }
576
577 break;
578 case USBFSOTG_OUT_TOKEN:
579 ep_cfg->stat.odd = !odd;
580 ep_cfg->stat.data1 = !data1;
581
582 if (ep == USB_CONTROL_EP_OUT) {
583 buf = priv->out_buf[odd];
584 priv->busy[odd] = false;
585 priv->out_buf[odd] = NULL;
586 } else {
587 buf = udc_buf_peek(dev, ep_cfg->addr);
588 }
589
590 if (buf == NULL) {
591 LOG_ERR("No buffer for ep 0x%02x", ep);
592 udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS);
593 break;
594 }
595
596 net_buf_add(buf, len);
597 if (net_buf_tailroom(buf) >= ep_cfg->mps && len == ep_cfg->mps) {
598 if (ep == USB_CONTROL_EP_OUT) {
599 usbfsotg_ctrl_feed_start(dev, buf);
600 } else {
601 usbfsotg_xfer_continue(dev, ep_cfg, buf);
602 }
603 } else {
604 if (ep == USB_CONTROL_EP_OUT) {
605 udc_buf_put(ep_cfg, buf);
606 }
607
608 usbfsotg_event_submit(dev, ep, USBFSOTG_EVT_DOUT);
609 }
610
611 break;
612 case USBFSOTG_IN_TOKEN:
613 ep_cfg->stat.odd = !odd;
614 ep_cfg->stat.data1 = !data1;
615
616 buf = udc_buf_peek(dev, ep_cfg->addr);
617 if (buf == NULL) {
618 LOG_ERR("No buffer for ep 0x%02x", ep);
619 udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS);
620 break;
621 }
622
623 net_buf_pull(buf, len);
624 if (buf->len) {
625 usbfsotg_xfer_continue(dev, ep_cfg, buf);
626 } else {
627 if (udc_ep_buf_has_zlp(buf)) {
628 usbfsotg_xfer_continue(dev, ep_cfg, buf);
629 udc_ep_buf_clear_zlp(buf);
630 break;
631 }
632
633 usbfsotg_event_submit(dev, ep, USBFSOTG_EVT_DIN);
634 }
635
636 break;
637 default:
638 break;
639 }
640 }
641
usbfsotg_isr_handler(const struct device * dev)642 static void usbfsotg_isr_handler(const struct device *dev)
643 {
644 const struct usbfsotg_config *config = dev->config;
645 USB_Type *base = config->base;
646 const uint8_t istatus = base->ISTAT;
647 const uint8_t status = base->STAT;
648
649 if (istatus & USB_ISTAT_USBRST_MASK) {
650 base->ADDR = 0U;
651 udc_submit_event(dev, UDC_EVT_RESET, 0);
652 }
653
654 if (istatus == USB_ISTAT_SOFTOK_MASK) {
655 udc_submit_event(dev, UDC_EVT_SOF, 0);
656 }
657
658 if (istatus == USB_ISTAT_ERROR_MASK) {
659 LOG_DBG("ERROR IRQ 0x%02x", base->ERRSTAT);
660 udc_submit_event(dev, UDC_EVT_ERROR, base->ERRSTAT);
661 base->ERRSTAT = 0xFF;
662 }
663
664 if (istatus & USB_ISTAT_STALL_MASK) {
665 struct udc_ep_config *ep_cfg;
666
667 LOG_DBG("STALL sent");
668
669 ep_cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
670 if (ep_cfg->stat.halted) {
671 /*
672 * usbfsotg_ep_clear_halt(dev, ep_cfg); cannot
673 * be called in ISR context
674 */
675 usbfsotg_event_submit(dev, USB_CONTROL_EP_OUT,
676 USBFSOTG_EVT_CLEAR_HALT);
677 }
678
679 ep_cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN);
680 if (ep_cfg->stat.halted) {
681 usbfsotg_event_submit(dev, USB_CONTROL_EP_IN,
682 USBFSOTG_EVT_CLEAR_HALT);
683 }
684 }
685
686 if (istatus & USB_ISTAT_TOKDNE_MASK) {
687 isr_handle_xfer_done(dev, istatus, status);
688 }
689
690 if (istatus & USB_ISTAT_SLEEP_MASK) {
691 LOG_DBG("SLEEP IRQ");
692 /* Enable resume interrupt */
693 base->INTEN |= USB_INTEN_RESUMEEN_MASK;
694
695 udc_set_suspended(dev, true);
696 udc_submit_event(dev, UDC_EVT_SUSPEND, 0);
697 }
698
699 if (istatus & USB_ISTAT_RESUME_MASK) {
700 LOG_DBG("RESUME IRQ");
701 /* Disable resume interrupt */
702 base->INTEN &= ~USB_INTEN_RESUMEEN_MASK;
703
704 udc_set_suspended(dev, false);
705 udc_submit_event(dev, UDC_EVT_RESUME, 0);
706 }
707
708 /* Clear interrupt status bits */
709 base->ISTAT = istatus;
710 }
711
usbfsotg_ep_enqueue(const struct device * dev,struct udc_ep_config * const cfg,struct net_buf * const buf)712 static int usbfsotg_ep_enqueue(const struct device *dev,
713 struct udc_ep_config *const cfg,
714 struct net_buf *const buf)
715 {
716
717 udc_buf_put(cfg, buf);
718 if (cfg->stat.halted) {
719 LOG_DBG("ep 0x%02x halted", cfg->addr);
720 return 0;
721 }
722
723 usbfsotg_event_submit(dev, cfg->addr, USBFSOTG_EVT_XFER);
724
725 return 0;
726 }
727
usbfsotg_ep_dequeue(const struct device * dev,struct udc_ep_config * const cfg)728 static int usbfsotg_ep_dequeue(const struct device *dev,
729 struct udc_ep_config *const cfg)
730 {
731 struct usbfsotg_bd *bd;
732 unsigned int lock_key;
733 struct net_buf *buf;
734
735 bd = usbfsotg_get_ebd(dev, cfg, false);
736
737 lock_key = irq_lock();
738 bd->set.bd_ctrl = USBFSOTG_BD_DTS;
739 irq_unlock(lock_key);
740
741 cfg->stat.halted = false;
742 buf = udc_buf_get_all(dev, cfg->addr);
743 if (buf) {
744 udc_submit_ep_event(dev, buf, -ECONNABORTED);
745 }
746
747 udc_ep_set_busy(dev, cfg->addr, false);
748
749 return 0;
750 }
751
ctrl_drop_out_successor(const struct device * dev)752 static void ctrl_drop_out_successor(const struct device *dev)
753 {
754 struct usbfsotg_data *priv = udc_get_private(dev);
755 struct udc_ep_config *cfg;
756 struct usbfsotg_bd *bd;
757 struct net_buf *buf;
758
759 cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
760
761 if (priv->busy[!cfg->stat.odd]) {
762 bd = usbfsotg_get_ebd(dev, cfg, true);
763 buf = priv->out_buf[!cfg->stat.odd];
764
765 bd->bd_fields = 0U;
766 priv->busy[!cfg->stat.odd] = false;
767 if (buf) {
768 net_buf_unref(buf);
769 }
770 }
771 }
772
usbfsotg_ep_set_halt(const struct device * dev,struct udc_ep_config * const cfg)773 static int usbfsotg_ep_set_halt(const struct device *dev,
774 struct udc_ep_config *const cfg)
775 {
776 struct usbfsotg_bd *bd;
777
778 bd = usbfsotg_get_ebd(dev, cfg, false);
779 bd->set.bd_ctrl = USBFSOTG_BD_STALL | USBFSOTG_BD_DTS | USBFSOTG_BD_OWN;
780 cfg->stat.halted = true;
781 LOG_DBG("Halt ep 0x%02x bd %p", cfg->addr, bd);
782
783 if (cfg->addr == USB_CONTROL_EP_IN) {
784 /* Drop subsequent out transfer, current can be re-used */
785 ctrl_drop_out_successor(dev);
786 }
787
788 if (USB_EP_GET_IDX(cfg->addr) == 0U) {
789 usbfsotg_resume_tx(dev);
790 }
791
792 return 0;
793 }
794
usbfsotg_ep_clear_halt(const struct device * dev,struct udc_ep_config * const cfg)795 static int usbfsotg_ep_clear_halt(const struct device *dev,
796 struct udc_ep_config *const cfg)
797 {
798 const struct usbfsotg_config *config = dev->config;
799 struct usbfsotg_data *priv = udc_get_private(dev);
800 USB_Type *base = config->base;
801 uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr);
802 struct usbfsotg_bd *bd;
803
804 LOG_DBG("Clear halt ep 0x%02x", cfg->addr);
805 bd = usbfsotg_get_ebd(dev, cfg, false);
806
807 if (bd->set.bd_ctrl & USBFSOTG_BD_STALL) {
808 LOG_DBG("bd %p: %x", bd, bd->set.bd_ctrl);
809 bd->set.bd_ctrl = USBFSOTG_BD_DTS;
810 } else {
811 LOG_WRN("bd %p is not halted", bd);
812 }
813
814 cfg->stat.data1 = false;
815 cfg->stat.halted = false;
816 base->ENDPOINT[ep_idx].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
817
818 if (cfg->addr == USB_CONTROL_EP_OUT) {
819 if (priv->busy[cfg->stat.odd]) {
820 LOG_DBG("bd %p restarted", bd);
821 bd->set.bd_ctrl = USBFSOTG_BD_DTS | USBFSOTG_BD_OWN;
822 } else {
823 usbfsotg_ctrl_feed_dout(dev, 8U, false, false);
824 }
825 }
826
827 if (USB_EP_GET_IDX(cfg->addr) == 0U) {
828 usbfsotg_resume_tx(dev);
829 } else {
830 /* trigger queued transfers */
831 usbfsotg_event_submit(dev, cfg->addr, USBFSOTG_EVT_XFER);
832 }
833
834 return 0;
835 }
836
usbfsotg_ep_enable(const struct device * dev,struct udc_ep_config * const cfg)837 static int usbfsotg_ep_enable(const struct device *dev,
838 struct udc_ep_config *const cfg)
839 {
840 const struct usbfsotg_config *config = dev->config;
841 struct usbfsotg_data *priv = udc_get_private(dev);
842 USB_Type *base = config->base;
843 const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr);
844 struct usbfsotg_bd *bd_even, *bd_odd;
845
846 LOG_DBG("Enable ep 0x%02x", cfg->addr);
847 bd_even = usbfsotg_get_ebd(dev, cfg, false);
848 bd_odd = usbfsotg_get_ebd(dev, cfg, true);
849
850 bd_even->bd_fields = 0U;
851 bd_even->buf_addr = 0U;
852 bd_odd->bd_fields = 0U;
853 bd_odd->buf_addr = 0U;
854
855 switch (cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) {
856 case USB_EP_TYPE_CONTROL:
857 base->ENDPOINT[ep_idx].ENDPT = (USB_ENDPT_EPHSHK_MASK |
858 USB_ENDPT_EPRXEN_MASK |
859 USB_ENDPT_EPTXEN_MASK);
860 break;
861 case USB_EP_TYPE_BULK:
862 case USB_EP_TYPE_INTERRUPT:
863 base->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPHSHK_MASK;
864 if (USB_EP_DIR_IS_OUT(cfg->addr)) {
865 base->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPRXEN_MASK;
866 } else {
867 base->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPTXEN_MASK;
868 }
869 break;
870 case USB_EP_TYPE_ISO:
871 if (USB_EP_DIR_IS_OUT(cfg->addr)) {
872 base->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPRXEN_MASK;
873 } else {
874 base->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPTXEN_MASK;
875 }
876 break;
877 default:
878 return -EINVAL;
879 }
880
881 if (cfg->addr == USB_CONTROL_EP_OUT) {
882 struct net_buf *buf;
883
884 buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, USBFSOTG_EP0_SIZE);
885 usbfsotg_bd_set_ctrl(bd_even, buf->size, buf->data, false);
886 priv->out_buf[0] = buf;
887 }
888
889 return 0;
890 }
891
usbfsotg_ep_disable(const struct device * dev,struct udc_ep_config * const cfg)892 static int usbfsotg_ep_disable(const struct device *dev,
893 struct udc_ep_config *const cfg)
894 {
895 const struct usbfsotg_config *config = dev->config;
896 USB_Type *base = config->base;
897 uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr);
898 struct usbfsotg_bd *bd_even, *bd_odd;
899
900 bd_even = usbfsotg_get_ebd(dev, cfg, false);
901 bd_odd = usbfsotg_get_ebd(dev, cfg, true);
902
903 if (USB_EP_DIR_IS_OUT(cfg->addr)) {
904 base->ENDPOINT[ep_idx].ENDPT &= ~USB_ENDPT_EPRXEN_MASK;
905 } else {
906 base->ENDPOINT[ep_idx].ENDPT &= ~USB_ENDPT_EPTXEN_MASK;
907 }
908
909 if (usbfsotg_bd_is_busy(bd_even) || usbfsotg_bd_is_busy(bd_odd)) {
910 LOG_DBG("Endpoint buffer is busy");
911 }
912
913 bd_even->bd_fields = 0U;
914 bd_even->buf_addr = 0U;
915 bd_odd->bd_fields = 0U;
916 bd_odd->buf_addr = 0U;
917
918 LOG_DBG("Disable ep 0x%02x", cfg->addr);
919
920 return 0;
921 }
922
usbfsotg_host_wakeup(const struct device * dev)923 static int usbfsotg_host_wakeup(const struct device *dev)
924 {
925 return -ENOTSUP;
926 }
927
usbfsotg_set_address(const struct device * dev,const uint8_t addr)928 static int usbfsotg_set_address(const struct device *dev, const uint8_t addr)
929 {
930 const struct usbfsotg_config *config = dev->config;
931 USB_Type *base = config->base;
932
933 base->ADDR = addr;
934
935 return 0;
936 }
937
usbfsotg_enable(const struct device * dev)938 static int usbfsotg_enable(const struct device *dev)
939 {
940 const struct usbfsotg_config *config = dev->config;
941 USB_Type *base = config->base;
942
943 /* non-OTG device mode, enable DP Pullup */
944 base->CONTROL = USB_CONTROL_DPPULLUPNONOTG_MASK;
945
946 return 0;
947 }
948
usbfsotg_disable(const struct device * dev)949 static int usbfsotg_disable(const struct device *dev)
950 {
951 const struct usbfsotg_config *config = dev->config;
952 USB_Type *base = config->base;
953
954 /* disable USB and DP Pullup */
955 base->CTL &= ~USB_CTL_USBENSOFEN_MASK;
956 base->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
957
958 return 0;
959 }
960
usbfsotg_is_supported(const struct device * dev)961 static bool usbfsotg_is_supported(const struct device *dev)
962 {
963 const struct usbfsotg_config *config = dev->config;
964 USB_Type *base = config->base;
965
966 if ((base->PERID != USBFSOTG_PERID) || (base->REV != USBFSOTG_REV)) {
967 return false;
968 }
969
970 return true;
971 }
972
usbfsotg_init(const struct device * dev)973 static int usbfsotg_init(const struct device *dev)
974 {
975 const struct usbfsotg_config *config = dev->config;
976 USB_Type *base = config->base;
977
978 /* (FIXME) Enable USB voltage regulator */
979 SIM->SOPT1 |= SIM_SOPT1_USBREGEN_MASK;
980
981 /* Reset USB module */
982 base->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
983 k_busy_wait(2000);
984
985 /* enable USB module, AKA USBEN bit in CTL1 register */
986 base->CTL = USB_CTL_USBENSOFEN_MASK;
987
988 if (!usbfsotg_is_supported(dev)) {
989 return -ENOTSUP;
990 }
991
992 for (uint8_t i = 0; i < 16U; i++) {
993 base->ENDPOINT[i].ENDPT = 0;
994 }
995
996 base->BDTPAGE1 = (uint8_t)(POINTER_TO_UINT(config->bdt) >> 8);
997 base->BDTPAGE2 = (uint8_t)(POINTER_TO_UINT(config->bdt) >> 16);
998 base->BDTPAGE3 = (uint8_t)(POINTER_TO_UINT(config->bdt) >> 24);
999
1000 /* (FIXME) Enables the weak pulldowns on the USB transceiver */
1001 base->USBCTRL = USB_USBCTRL_PDE_MASK;
1002
1003 /* Clear interrupt flags */
1004 base->ISTAT = 0xFF;
1005 /* Clear error flags */
1006 base->ERRSTAT = 0xFF;
1007
1008 /* Enable all error interrupt sources */
1009 base->ERREN = 0xFF;
1010 /* Enable reset interrupt */
1011 base->INTEN = (USB_INTEN_SLEEPEN_MASK |
1012 USB_INTEN_STALLEN_MASK |
1013 USB_INTEN_TOKDNEEN_MASK |
1014 USB_INTEN_SOFTOKEN_MASK |
1015 USB_INTEN_ERROREN_MASK |
1016 USB_INTEN_USBRSTEN_MASK);
1017
1018 if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT,
1019 USB_EP_TYPE_CONTROL,
1020 USBFSOTG_EP0_SIZE, 0)) {
1021 LOG_ERR("Failed to enable control endpoint");
1022 return -EIO;
1023 }
1024
1025 if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN,
1026 USB_EP_TYPE_CONTROL,
1027 USBFSOTG_EP0_SIZE, 0)) {
1028 LOG_ERR("Failed to enable control endpoint");
1029 return -EIO;
1030 }
1031
1032 /* Connect and enable USB interrupt */
1033 config->irq_enable_func(dev);
1034
1035 LOG_DBG("Initialized USB controller %p", base);
1036
1037 return 0;
1038 }
1039
usbfsotg_shutdown(const struct device * dev)1040 static int usbfsotg_shutdown(const struct device *dev)
1041 {
1042 const struct usbfsotg_config *config = dev->config;
1043
1044 config->irq_disable_func(dev);
1045
1046 if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) {
1047 LOG_ERR("Failed to disable control endpoint");
1048 return -EIO;
1049 }
1050
1051 if (udc_ep_disable_internal(dev, USB_CONTROL_EP_IN)) {
1052 LOG_ERR("Failed to disable control endpoint");
1053 return -EIO;
1054 }
1055
1056 /* Disable USB module */
1057 config->base->CTL = 0;
1058
1059 /* Disable USB voltage regulator */
1060 SIM->SOPT1 &= ~SIM_SOPT1_USBREGEN_MASK;
1061
1062 return 0;
1063 }
1064
usbfsotg_lock(const struct device * dev)1065 static int usbfsotg_lock(const struct device *dev)
1066 {
1067 return udc_lock_internal(dev, K_FOREVER);
1068 }
1069
usbfsotg_unlock(const struct device * dev)1070 static int usbfsotg_unlock(const struct device *dev)
1071 {
1072 return udc_unlock_internal(dev);
1073 }
1074
usbfsotg_driver_preinit(const struct device * dev)1075 static int usbfsotg_driver_preinit(const struct device *dev)
1076 {
1077 const struct usbfsotg_config *config = dev->config;
1078 struct udc_data *data = dev->data;
1079 struct usbfsotg_data *priv = data->priv;
1080 int err;
1081
1082 k_mutex_init(&data->mutex);
1083 k_fifo_init(&priv->fifo);
1084 k_work_init(&priv->work, xfer_work_handler);
1085
1086 for (int i = 0; i < config->num_of_eps; i++) {
1087 config->ep_cfg_out[i].caps.out = 1;
1088 if (i == 0) {
1089 config->ep_cfg_out[i].caps.control = 1;
1090 config->ep_cfg_out[i].caps.mps = 64;
1091 } else {
1092 config->ep_cfg_out[i].caps.bulk = 1;
1093 config->ep_cfg_out[i].caps.interrupt = 1;
1094 config->ep_cfg_out[i].caps.iso = 1;
1095 config->ep_cfg_out[i].caps.mps = 1023;
1096 }
1097
1098 config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i;
1099 err = udc_register_ep(dev, &config->ep_cfg_out[i]);
1100 if (err != 0) {
1101 LOG_ERR("Failed to register endpoint");
1102 return err;
1103 }
1104 }
1105
1106 for (int i = 0; i < config->num_of_eps; i++) {
1107 config->ep_cfg_in[i].caps.in = 1;
1108 if (i == 0) {
1109 config->ep_cfg_in[i].caps.control = 1;
1110 config->ep_cfg_in[i].caps.mps = 64;
1111 } else {
1112 config->ep_cfg_in[i].caps.bulk = 1;
1113 config->ep_cfg_in[i].caps.interrupt = 1;
1114 config->ep_cfg_in[i].caps.iso = 1;
1115 config->ep_cfg_in[i].caps.mps = 1023;
1116 }
1117
1118 config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i;
1119 err = udc_register_ep(dev, &config->ep_cfg_in[i]);
1120 if (err != 0) {
1121 LOG_ERR("Failed to register endpoint");
1122 return err;
1123 }
1124 }
1125
1126 data->caps.rwup = false;
1127 data->caps.mps0 = USBFSOTG_MPS0;
1128
1129 return 0;
1130 }
1131
1132 static const struct udc_api usbfsotg_api = {
1133 .ep_enqueue = usbfsotg_ep_enqueue,
1134 .ep_dequeue = usbfsotg_ep_dequeue,
1135 .ep_set_halt = usbfsotg_ep_set_halt,
1136 .ep_clear_halt = usbfsotg_ep_clear_halt,
1137 .ep_try_config = NULL,
1138 .ep_enable = usbfsotg_ep_enable,
1139 .ep_disable = usbfsotg_ep_disable,
1140 .host_wakeup = usbfsotg_host_wakeup,
1141 .set_address = usbfsotg_set_address,
1142 .enable = usbfsotg_enable,
1143 .disable = usbfsotg_disable,
1144 .init = usbfsotg_init,
1145 .shutdown = usbfsotg_shutdown,
1146 .lock = usbfsotg_lock,
1147 .unlock = usbfsotg_unlock,
1148 };
1149
1150 #define USBFSOTG_DEVICE_DEFINE(n) \
1151 static void udc_irq_enable_func##n(const struct device *dev) \
1152 { \
1153 IRQ_CONNECT(DT_INST_IRQN(n), \
1154 DT_INST_IRQ(n, priority), \
1155 usbfsotg_isr_handler, \
1156 DEVICE_DT_INST_GET(n), 0); \
1157 \
1158 irq_enable(DT_INST_IRQN(n)); \
1159 } \
1160 \
1161 static void udc_irq_disable_func##n(const struct device *dev) \
1162 { \
1163 irq_disable(DT_INST_IRQN(n)); \
1164 } \
1165 \
1166 static struct usbfsotg_bd __aligned(512) \
1167 bdt_##n[DT_INST_PROP(n, num_bidir_endpoints) * 2 * 2]; \
1168 \
1169 static struct udc_ep_config \
1170 ep_cfg_out[DT_INST_PROP(n, num_bidir_endpoints)]; \
1171 static struct udc_ep_config \
1172 ep_cfg_in[DT_INST_PROP(n, num_bidir_endpoints)]; \
1173 \
1174 static struct usbfsotg_config priv_config_##n = { \
1175 .base = (USB_Type *)DT_INST_REG_ADDR(n), \
1176 .bdt = bdt_##n, \
1177 .irq_enable_func = udc_irq_enable_func##n, \
1178 .irq_disable_func = udc_irq_disable_func##n, \
1179 .num_of_eps = DT_INST_PROP(n, num_bidir_endpoints), \
1180 .ep_cfg_in = ep_cfg_out, \
1181 .ep_cfg_out = ep_cfg_in, \
1182 }; \
1183 \
1184 static struct usbfsotg_data priv_data_##n = { \
1185 }; \
1186 \
1187 static struct udc_data udc_data_##n = { \
1188 .mutex = Z_MUTEX_INITIALIZER(udc_data_##n.mutex), \
1189 .priv = &priv_data_##n, \
1190 }; \
1191 \
1192 DEVICE_DT_INST_DEFINE(n, usbfsotg_driver_preinit, NULL, \
1193 &udc_data_##n, &priv_config_##n, \
1194 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
1195 &usbfsotg_api);
1196
1197 DT_INST_FOREACH_STATUS_OKAY(USBFSOTG_DEVICE_DEFINE)
1198