1 /*
2 * Copyright (c) 2018 Google LLC.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT atmel_sam0_usb
8
9 #define LOG_LEVEL CONFIG_USB_DRIVER_LOG_LEVEL
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(usb_dc_sam0);
12
13 #include <zephyr/kernel.h>
14 #include <zephyr/usb/usb_device.h>
15 #include <zephyr/drivers/pinctrl.h>
16 #include <soc.h>
17 #include <string.h>
18 #include <zephyr/irq.h>
19
20 #define NVM_USB_PAD_TRANSN_POS 45
21 #define NVM_USB_PAD_TRANSN_SIZE 5
22 #define NVM_USB_PAD_TRANSP_POS 50
23 #define NVM_USB_PAD_TRANSP_SIZE 5
24 #define NVM_USB_PAD_TRIM_POS 55
25 #define NVM_USB_PAD_TRIM_SIZE 3
26
27 #define USB_SAM0_IN_EP 0x80
28
29 #define REGS ((Usb *)DT_INST_REG_ADDR(0))
30 #define USB_NUM_ENDPOINTS DT_INST_PROP(0, num_bidir_endpoints)
31
32 /* The endpoint size stored in USB.PCKSIZE.SIZE */
33 enum usb_sam0_pcksize_size {
34 USB_SAM0_PCKSIZE_SIZE_8 = 0,
35 USB_SAM0_PCKSIZE_SIZE_16,
36 USB_SAM0_PCKSIZE_SIZE_32,
37 USB_SAM0_PCKSIZE_SIZE_64,
38 USB_SAM0_PCKSIZE_SIZE_128,
39 USB_SAM0_PCKSIZE_SIZE_256,
40 USB_SAM0_PCKSIZE_SIZE_512,
41 USB_SAM0_PCKSIZE_SIZE_1023,
42 };
43
44 static const uint16_t usb_sam0_pcksize_bytes[] = {
45 [USB_SAM0_PCKSIZE_SIZE_8] = 8,
46 [USB_SAM0_PCKSIZE_SIZE_16] = 16,
47 [USB_SAM0_PCKSIZE_SIZE_32] = 32,
48 [USB_SAM0_PCKSIZE_SIZE_64] = 64,
49 [USB_SAM0_PCKSIZE_SIZE_128] = 128,
50 [USB_SAM0_PCKSIZE_SIZE_256] = 256,
51 [USB_SAM0_PCKSIZE_SIZE_512] = 512,
52 [USB_SAM0_PCKSIZE_SIZE_1023] = 1023,
53 };
54
55 BUILD_ASSERT(ARRAY_SIZE(usb_sam0_pcksize_bytes) == 8);
56
57 struct usb_sam0_data {
58 UsbDeviceDescriptor descriptors[USB_NUM_ENDPOINTS];
59
60 usb_dc_status_callback cb;
61 usb_dc_ep_callback ep_cb[2][USB_NUM_ENDPOINTS];
62
63 uint8_t addr;
64 uint32_t out_at;
65 };
66
67 static struct usb_sam0_data usb_sam0_data_0;
68 PINCTRL_DT_INST_DEFINE(0);
69 static const struct pinctrl_dev_config *pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0);
70
usb_sam0_get_data(void)71 static struct usb_sam0_data *usb_sam0_get_data(void)
72 {
73 return &usb_sam0_data_0;
74 }
75
76 /* Handles interrupts on an endpoint */
usb_sam0_ep_isr(uint8_t ep)77 static void usb_sam0_ep_isr(uint8_t ep)
78 {
79 struct usb_sam0_data *data = usb_sam0_get_data();
80 UsbDevice *regs = ®S->DEVICE;
81 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep];
82 uint32_t intflag = endpoint->EPINTFLAG.reg;
83
84 endpoint->EPINTFLAG.reg = intflag;
85
86 if ((intflag & USB_DEVICE_EPINTFLAG_RXSTP) != 0U) {
87 /* Setup */
88 data->ep_cb[0][ep](ep, USB_DC_EP_SETUP);
89 }
90
91 if ((intflag & USB_DEVICE_EPINTFLAG_TRCPT0) != 0U) {
92 /* Out (to device) data received */
93 data->ep_cb[0][ep](ep, USB_DC_EP_DATA_OUT);
94 }
95
96 if ((intflag & USB_DEVICE_EPINTFLAG_TRCPT1) != 0U) {
97 /* In (to host) transmit complete */
98 data->ep_cb[1][ep](ep | USB_SAM0_IN_EP, USB_DC_EP_DATA_IN);
99
100 if (data->addr != 0U) {
101 /* Commit the pending address update. This
102 * must be done after the ack to the host
103 * completes else the ack will get dropped.
104 */
105 regs->DADD.reg = data->addr;
106 data->addr = 0U;
107 }
108 }
109 }
110
111 /* Top level interrupt handler */
usb_sam0_isr(void)112 static void usb_sam0_isr(void)
113 {
114 struct usb_sam0_data *data = usb_sam0_get_data();
115 UsbDevice *regs = ®S->DEVICE;
116 uint32_t intflag = regs->INTFLAG.reg;
117 uint32_t epint = regs->EPINTSMRY.reg;
118 uint8_t ep;
119
120 /* Acknowledge all interrupts */
121 regs->INTFLAG.reg = intflag;
122
123 if ((intflag & USB_DEVICE_INTFLAG_EORST) != 0U) {
124 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[0];
125
126 /* The device clears some of the configuration of EP0
127 * when it receives the EORST. Re-enable interrupts.
128 */
129 endpoint->EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 |
130 USB_DEVICE_EPINTENSET_TRCPT1 |
131 USB_DEVICE_EPINTENSET_RXSTP;
132
133 data->cb(USB_DC_RESET, NULL);
134 }
135
136 /* Dispatch the endpoint interrupts */
137 for (ep = 0U; epint != 0U; epint >>= 1) {
138 /* Scan bit-by-bit as the Cortex-M0 doesn't have ffs */
139 if ((epint & 1) != 0U) {
140 usb_sam0_ep_isr(ep);
141 }
142 ep++;
143 }
144 }
145
146 /* Wait for the device to process the last config write */
usb_sam0_wait_syncbusy(void)147 static void usb_sam0_wait_syncbusy(void)
148 {
149 UsbDevice *regs = ®S->DEVICE;
150
151 while (regs->SYNCBUSY.reg != 0) {
152 }
153 }
154
155 /* Load the pad calibration from the built-in fuses */
usb_sam0_load_padcal(void)156 static void usb_sam0_load_padcal(void)
157 {
158 UsbDevice *regs = ®S->DEVICE;
159 uint32_t pad_transn;
160 uint32_t pad_transp;
161 uint32_t pad_trim;
162
163 #ifdef USB_FUSES_TRANSN_ADDR
164 pad_transn = *(uint32_t *)USB_FUSES_TRANSN_ADDR;
165 #else
166 pad_transn = (*((uint32_t *)(NVMCTRL_OTP4) +
167 (NVM_USB_PAD_TRANSN_POS / 32)) >>
168 (NVM_USB_PAD_TRANSN_POS % 32)) &
169 ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
170
171 if (pad_transn == 0x1F) {
172 pad_transn = 5U;
173 }
174 #endif
175
176 regs->PADCAL.bit.TRANSN = pad_transn;
177
178 #ifdef USB_FUSES_TRANSP_ADDR
179 pad_transp = *(uint32_t *)USB_FUSES_TRANSP_ADDR;
180 #else
181 pad_transp = (*((uint32_t *)(NVMCTRL_OTP4) +
182 (NVM_USB_PAD_TRANSP_POS / 32)) >>
183 (NVM_USB_PAD_TRANSP_POS % 32)) &
184 ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
185
186 if (pad_transp == 0x1F) {
187 pad_transp = 29U;
188 }
189 #endif
190
191 regs->PADCAL.bit.TRANSP = pad_transp;
192
193 #ifdef USB_FUSES_TRIM_ADDR
194 pad_trim = *(uint32_t *)USB_FUSES_TRIM_ADDR;
195 #else
196 pad_trim = (*((uint32_t *)(NVMCTRL_OTP4) +
197 (NVM_USB_PAD_TRIM_POS / 32)) >>
198 (NVM_USB_PAD_TRIM_POS % 32)) &
199 ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
200
201 if (pad_trim == 0x7) {
202 pad_trim = 3U;
203 }
204 #endif
205
206 regs->PADCAL.bit.TRIM = pad_trim;
207 }
208
209 #define SAM0_USB_IRQ_CONNECT(n) \
210 do { \
211 IRQ_CONNECT(DT_INST_IRQ_BY_IDX(0, n, irq), \
212 DT_INST_IRQ_BY_IDX(0, n, priority), \
213 usb_sam0_isr, 0, 0); \
214 irq_enable(DT_INST_IRQ_BY_IDX(0, n, irq)); \
215 } while (false)
216
217 /* Attach by initializing the device */
usb_dc_attach(void)218 int usb_dc_attach(void)
219 {
220 UsbDevice *regs = ®S->DEVICE;
221 struct usb_sam0_data *data = usb_sam0_get_data();
222 int retval;
223
224 #ifdef MCLK
225 /* Enable the clock in MCLK */
226 MCLK->APBBMASK.bit.USB_ = 1;
227
228 /* Enable the GCLK - use 48 MHz source */
229 GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_GEN(2)
230 | GCLK_PCHCTRL_CHEN;
231
232 while (GCLK->SYNCBUSY.reg) {
233 }
234 #else
235 /* Enable the clock in PM */
236 PM->APBBMASK.bit.USB_ = 1;
237
238 /* Enable the GCLK */
239 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_USB | GCLK_CLKCTRL_GEN_GCLK0 |
240 GCLK_CLKCTRL_CLKEN;
241
242 while (GCLK->STATUS.bit.SYNCBUSY) {
243 }
244 #endif /* !MCLK */
245
246 /* Configure */
247 regs->CTRLA.bit.SWRST = 1;
248 usb_sam0_wait_syncbusy();
249
250 /* Change QOS values to have the best performance and correct USB
251 * behaviour
252 */
253 regs->QOSCTRL.bit.CQOS = 2;
254 regs->QOSCTRL.bit.DQOS = 2;
255
256 retval = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT);
257 if (retval < 0) {
258 return retval;
259 }
260
261 usb_sam0_load_padcal();
262
263 regs->CTRLA.reg = USB_CTRLA_MODE_DEVICE | USB_CTRLA_RUNSTDBY;
264 regs->CTRLB.reg = USB_DEVICE_CTRLB_SPDCONF_HS;
265
266 (void)memset(data->descriptors, 0, sizeof(data->descriptors));
267 regs->DESCADD.reg = (uintptr_t)&data->descriptors[0];
268
269 regs->INTENSET.reg = USB_DEVICE_INTENSET_EORST;
270
271 /* Connect and enable the interrupt */
272 #if DT_INST_IRQ_HAS_CELL(0, irq)
273 SAM0_USB_IRQ_CONNECT(0);
274 #endif
275 #if DT_INST_IRQ_HAS_IDX(0, 1)
276 SAM0_USB_IRQ_CONNECT(1);
277 #endif
278 #if DT_INST_IRQ_HAS_IDX(0, 2)
279 SAM0_USB_IRQ_CONNECT(2);
280 #endif
281 #if DT_INST_IRQ_HAS_IDX(0, 3)
282 SAM0_USB_IRQ_CONNECT(3);
283 #endif
284
285 /* Enable and attach */
286 regs->CTRLA.bit.ENABLE = 1;
287 usb_sam0_wait_syncbusy();
288 regs->CTRLB.bit.DETACH = 0;
289
290 return 0;
291 }
292
usb_dc_release_buffers(void)293 static void usb_dc_release_buffers(void)
294 {
295 struct usb_sam0_data *data = usb_sam0_get_data();
296 UsbDeviceDescBank *bank;
297 void *buf;
298
299 /* release the buffers */
300 for (int i = 0; i < ARRAY_SIZE(data->descriptors); i++) {
301 for (int j = 0; j < ARRAY_SIZE(data->descriptors[0].DeviceDescBank); j++) {
302 bank = &data->descriptors[i].DeviceDescBank[j];
303 buf = (void *)bank->ADDR.reg;
304 /*
305 * We free the ep descriptor memory that was
306 * allocated in usb_dc_ep_configure().
307 * Therefore a disabled ep must be reconfigured
308 * before it can be enabled again.
309 */
310 if (buf != NULL) {
311 k_free(buf);
312 bank->ADDR.reg = (uintptr_t) NULL;
313 }
314 }
315 }
316 }
317
318 /* Detach from the bus */
usb_dc_detach(void)319 int usb_dc_detach(void)
320 {
321 UsbDevice *regs = ®S->DEVICE;
322
323 regs->CTRLB.bit.DETACH = 1;
324 usb_sam0_wait_syncbusy();
325
326 usb_dc_release_buffers();
327
328 return 0;
329 }
330
331 /* Remove the interrupt and reset the device */
usb_dc_reset(void)332 int usb_dc_reset(void)
333 {
334 UsbDevice *regs = ®S->DEVICE;
335
336 irq_disable(DT_INST_IRQN(0));
337
338 regs->CTRLA.bit.SWRST = 1;
339 usb_sam0_wait_syncbusy();
340
341 return 0;
342 }
343
344 /* Queue a change in address. This is processed later when the
345 * current transfers are complete.
346 */
usb_dc_set_address(const uint8_t addr)347 int usb_dc_set_address(const uint8_t addr)
348 {
349 struct usb_sam0_data *data = usb_sam0_get_data();
350
351 data->addr = addr | USB_DEVICE_DADD_ADDEN;
352
353 return 0;
354 }
355
usb_dc_set_status_callback(const usb_dc_status_callback cb)356 void usb_dc_set_status_callback(const usb_dc_status_callback cb)
357 {
358 struct usb_sam0_data *data = usb_sam0_get_data();
359
360 data->cb = cb;
361 }
362
usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data * const cfg)363 int usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data * const cfg)
364 {
365 uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr);
366
367 if ((cfg->ep_type == USB_DC_EP_CONTROL) && ep_idx) {
368 LOG_ERR("invalid endpoint configuration");
369 return -1;
370 }
371
372 if (ep_idx > USB_NUM_ENDPOINTS) {
373 LOG_ERR("endpoint index/address too high");
374 return -1;
375 }
376
377 return 0;
378 }
379
usb_dc_ep_configure(const struct usb_dc_ep_cfg_data * const cfg)380 int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data *const cfg)
381 {
382 struct usb_sam0_data *data = usb_sam0_get_data();
383 UsbDevice *regs = ®S->DEVICE;
384 uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr);
385 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
386 UsbDeviceDescriptor *desc = &data->descriptors[ep_idx];
387 UsbDeviceDescBank *bank;
388 void *buf;
389 int type;
390 int size = -1;
391 int i;
392
393 /* Map the type to native type */
394 switch (cfg->ep_type) {
395 case USB_DC_EP_CONTROL:
396 type = 1;
397 break;
398 case USB_DC_EP_ISOCHRONOUS:
399 type = 2;
400 break;
401 case USB_DC_EP_BULK:
402 type = 3;
403 break;
404 case USB_DC_EP_INTERRUPT:
405 type = 4;
406 break;
407 default:
408 return -EINVAL;
409 }
410
411 /* Map the endpoint size to native size */
412 for (i = 0; i < ARRAY_SIZE(usb_sam0_pcksize_bytes); i++) {
413 if (usb_sam0_pcksize_bytes[i] == cfg->ep_mps) {
414 size = i;
415 break;
416 }
417 }
418
419 if (size < 0) {
420 return -EINVAL;
421 }
422
423 if (USB_EP_DIR_IS_IN(cfg->ep_addr)) {
424 bank = &desc->DeviceDescBank[1];
425 } else {
426 bank = &desc->DeviceDescBank[0];
427 }
428
429 buf = (void *)bank->ADDR.reg;
430
431 if (bank->PCKSIZE.bit.SIZE != size || buf == NULL) {
432 /* Release the previous buffer, if any */
433 k_free(buf);
434
435 buf = k_malloc(cfg->ep_mps);
436 if (buf == NULL) {
437 return -ENOMEM;
438 }
439 bank->PCKSIZE.bit.SIZE = size;
440 bank->ADDR.reg = (uintptr_t)buf;
441 }
442
443 if (USB_EP_DIR_IS_IN(cfg->ep_addr)) {
444 endpoint->EPCFG.bit.EPTYPE1 = type;
445 endpoint->EPSTATUSCLR.bit.BK1RDY = 1;
446 } else {
447 endpoint->EPCFG.bit.EPTYPE0 = type;
448 endpoint->EPSTATUSCLR.bit.BK0RDY = 1;
449 }
450
451 return 0;
452 }
453
usb_dc_ep_set_stall(const uint8_t ep)454 int usb_dc_ep_set_stall(const uint8_t ep)
455 {
456 UsbDevice *regs = ®S->DEVICE;
457 uint8_t for_in = USB_EP_GET_DIR(ep);
458 uint8_t ep_idx = USB_EP_GET_IDX(ep);
459 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
460
461 if (ep_idx >= USB_NUM_ENDPOINTS) {
462 LOG_ERR("endpoint index/address out of range");
463 return -1;
464 }
465
466 if (for_in) {
467 endpoint->EPSTATUSSET.bit.STALLRQ1 = 1;
468 } else {
469 endpoint->EPSTATUSSET.bit.STALLRQ0 = 1;
470 }
471
472 return 0;
473 }
474
usb_dc_ep_clear_stall(const uint8_t ep)475 int usb_dc_ep_clear_stall(const uint8_t ep)
476 {
477 UsbDevice *regs = ®S->DEVICE;
478 uint8_t for_in = USB_EP_GET_DIR(ep);
479 uint8_t ep_idx = USB_EP_GET_IDX(ep);
480 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
481
482 if (ep_idx >= USB_NUM_ENDPOINTS) {
483 LOG_ERR("endpoint index/address out of range");
484 return -1;
485 }
486
487 if (for_in) {
488 endpoint->EPSTATUSCLR.bit.STALLRQ1 = 1;
489 } else {
490 endpoint->EPSTATUSCLR.bit.STALLRQ0 = 1;
491 }
492
493 return 0;
494 }
495
usb_dc_ep_is_stalled(const uint8_t ep,uint8_t * stalled)496 int usb_dc_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
497 {
498 UsbDevice *regs = ®S->DEVICE;
499 uint8_t for_in = USB_EP_GET_DIR(ep);
500 uint8_t ep_idx = USB_EP_GET_IDX(ep);
501 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
502
503 if (ep_idx >= USB_NUM_ENDPOINTS) {
504 LOG_ERR("endpoint index/address out of range");
505 return -1;
506 }
507
508 if (stalled == NULL) {
509 LOG_ERR("parameter must not be NULL");
510 return -1;
511 }
512
513 if (for_in) {
514 *stalled = endpoint->EPSTATUS.bit.STALLRQ1;
515 } else {
516 *stalled = endpoint->EPSTATUS.bit.STALLRQ0;
517 }
518
519 return 0;
520 }
521
522 /* Halt the selected endpoint */
usb_dc_ep_halt(uint8_t ep)523 int usb_dc_ep_halt(uint8_t ep)
524 {
525 return usb_dc_ep_set_stall(ep);
526 }
527
528 /* Flush the selected endpoint */
usb_dc_ep_flush(uint8_t ep)529 int usb_dc_ep_flush(uint8_t ep)
530 {
531 uint8_t ep_idx = USB_EP_GET_IDX(ep);
532
533 if (ep_idx >= USB_NUM_ENDPOINTS) {
534 LOG_ERR("endpoint index/address out of range");
535 return -1;
536 }
537
538 /* TODO */
539 LOG_WRN("flush not implemented");
540
541 return 0;
542 }
543
544 /* Enable an endpoint and the endpoint interrupts */
usb_dc_ep_enable(const uint8_t ep)545 int usb_dc_ep_enable(const uint8_t ep)
546 {
547 UsbDevice *regs = ®S->DEVICE;
548 uint8_t for_in = USB_EP_GET_DIR(ep);
549 uint8_t ep_idx = USB_EP_GET_IDX(ep);
550 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
551
552 if (ep_idx >= USB_NUM_ENDPOINTS) {
553 LOG_ERR("endpoint index/address out of range");
554 return -EINVAL;
555 }
556
557 if (for_in) {
558 endpoint->EPSTATUSCLR.bit.BK1RDY = 1;
559 } else {
560 endpoint->EPSTATUSCLR.bit.BK0RDY = 1;
561 }
562
563 endpoint->EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 |
564 USB_DEVICE_EPINTENSET_TRCPT1 |
565 USB_DEVICE_EPINTENSET_RXSTP;
566
567 return 0;
568 }
569
570 /* Disable the selected endpoint */
usb_dc_ep_disable(uint8_t ep)571 int usb_dc_ep_disable(uint8_t ep)
572 {
573 UsbDevice *regs = ®S->DEVICE;
574 uint8_t ep_idx = USB_EP_GET_IDX(ep);
575 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
576
577 if (ep_idx >= USB_NUM_ENDPOINTS) {
578 LOG_ERR("endpoint index/address out of range");
579 return -EINVAL;
580 }
581
582 endpoint->EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRCPT0
583 | USB_DEVICE_EPINTENCLR_TRCPT1
584 | USB_DEVICE_EPINTENCLR_RXSTP;
585
586 return 0;
587 }
588
589 /* Write a single payload to the IN buffer on the endpoint */
usb_dc_ep_write(uint8_t ep,const uint8_t * buf,uint32_t len,uint32_t * ret_bytes)590 int usb_dc_ep_write(uint8_t ep, const uint8_t *buf, uint32_t len, uint32_t *ret_bytes)
591 {
592 struct usb_sam0_data *data = usb_sam0_get_data();
593 UsbDevice *regs = ®S->DEVICE;
594 uint8_t ep_idx = USB_EP_GET_IDX(ep);
595 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
596 UsbDeviceDescriptor *desc = &data->descriptors[ep_idx];
597 uint32_t addr = desc->DeviceDescBank[1].ADDR.reg;
598 uint32_t capacity = usb_sam0_pcksize_bytes[
599 desc->DeviceDescBank[1].PCKSIZE.bit.SIZE];
600
601 if (ep_idx >= USB_NUM_ENDPOINTS) {
602 LOG_ERR("endpoint index/address out of range");
603 return -1;
604 }
605
606 if (endpoint->EPSTATUS.bit.BK1RDY) {
607 /* Write in progress, drop */
608 return -EAGAIN;
609 }
610
611 len = Z_MIN(len, capacity);
612
613 /* Note that this code does not use the hardware's
614 * multi-packet and automatic zero-length packet features as
615 * the upper layers in Zephyr implement these in code.
616 */
617 memcpy((void *)addr, buf, len);
618 desc->DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
619 desc->DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = len;
620 endpoint->EPINTFLAG.reg =
621 USB_DEVICE_EPINTFLAG_TRCPT1 | USB_DEVICE_EPINTFLAG_TRFAIL1;
622 endpoint->EPSTATUSSET.bit.BK1RDY = 1;
623
624 if (ret_bytes != NULL) {
625 *ret_bytes = len;
626 }
627
628 return 0;
629 }
630
631 /* Read data from an OUT endpoint */
usb_dc_ep_read_ex(uint8_t ep,uint8_t * buf,uint32_t max_data_len,uint32_t * read_bytes,bool wait)632 int usb_dc_ep_read_ex(uint8_t ep, uint8_t *buf, uint32_t max_data_len,
633 uint32_t *read_bytes, bool wait)
634 {
635 struct usb_sam0_data *data = usb_sam0_get_data();
636 UsbDevice *regs = ®S->DEVICE;
637 uint8_t ep_idx = USB_EP_GET_IDX(ep);
638 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
639 UsbDeviceDescriptor *desc = &data->descriptors[ep_idx];
640 uint32_t addr = desc->DeviceDescBank[0].ADDR.reg;
641 uint32_t bytes = desc->DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT;
642 uint32_t take;
643 int remain;
644
645 if (ep_idx >= USB_NUM_ENDPOINTS) {
646 LOG_ERR("endpoint index/address out of range");
647 return -1;
648 }
649
650 if (!endpoint->EPSTATUS.bit.BK0RDY) {
651 return -EAGAIN;
652 }
653
654 /* The code below emulates the Quark FIFO which the Zephyr USB
655 * API is based on. Reading with buf == NULL returns the
656 * number of bytes available and starts the read. The caller
657 * then keeps calling until all bytes are consumed which
658 * also marks the OUT buffer as freed.
659 */
660 if (buf == NULL) {
661 data->out_at = 0U;
662
663 if (read_bytes != NULL) {
664 *read_bytes = bytes;
665 }
666
667 return 0;
668 }
669
670 remain = bytes - data->out_at;
671 take = MIN(max_data_len, remain);
672 memcpy(buf, (uint8_t *)addr + data->out_at, take);
673
674 if (read_bytes != NULL) {
675 *read_bytes = take;
676 }
677
678 if (take == remain) {
679 if (!wait) {
680 endpoint->EPSTATUSCLR.bit.BK0RDY = 1;
681 data->out_at = 0U;
682 }
683 } else {
684 data->out_at += take;
685 }
686
687 return 0;
688 }
689
usb_dc_ep_read(uint8_t ep,uint8_t * buf,uint32_t max_data_len,uint32_t * read_bytes)690 int usb_dc_ep_read(uint8_t ep, uint8_t *buf, uint32_t max_data_len, uint32_t *read_bytes)
691 {
692 return usb_dc_ep_read_ex(ep, buf, max_data_len, read_bytes, false);
693 }
694
usb_dc_ep_read_wait(uint8_t ep,uint8_t * buf,uint32_t max_data_len,uint32_t * read_bytes)695 int usb_dc_ep_read_wait(uint8_t ep, uint8_t *buf, uint32_t max_data_len,
696 uint32_t *read_bytes)
697 {
698 return usb_dc_ep_read_ex(ep, buf, max_data_len, read_bytes, true);
699 }
700
usb_dc_ep_read_continue(uint8_t ep)701 int usb_dc_ep_read_continue(uint8_t ep)
702 {
703 struct usb_sam0_data *data = usb_sam0_get_data();
704 UsbDevice *regs = ®S->DEVICE;
705 uint8_t ep_idx = USB_EP_GET_IDX(ep);
706 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
707
708 if (ep_idx >= USB_NUM_ENDPOINTS) {
709 LOG_ERR("endpoint index/address out of range");
710 return -1;
711 }
712
713 endpoint->EPSTATUSCLR.bit.BK0RDY = 1;
714 data->out_at = 0U;
715
716 return 0;
717 }
718
usb_dc_ep_set_callback(const uint8_t ep,const usb_dc_ep_callback cb)719 int usb_dc_ep_set_callback(const uint8_t ep, const usb_dc_ep_callback cb)
720 {
721 struct usb_sam0_data *data = usb_sam0_get_data();
722 uint8_t for_in = USB_EP_GET_DIR(ep);
723 uint8_t ep_idx = USB_EP_GET_IDX(ep);
724
725 if (ep_idx >= USB_NUM_ENDPOINTS) {
726 LOG_ERR("endpoint index/address out of range");
727 return -1;
728 }
729
730 data->ep_cb[for_in ? 1 : 0][ep_idx] = cb;
731
732 return 0;
733 }
734
usb_dc_ep_mps(const uint8_t ep)735 int usb_dc_ep_mps(const uint8_t ep)
736 {
737 struct usb_sam0_data *data = usb_sam0_get_data();
738 UsbDevice *regs = ®S->DEVICE;
739 uint8_t for_in = USB_EP_GET_DIR(ep);
740 uint8_t ep_idx = USB_EP_GET_IDX(ep);
741 UsbDeviceDescriptor *desc = &data->descriptors[ep_idx];
742 UsbDeviceEndpoint *endpoint = ®s->DeviceEndpoint[ep_idx];
743
744 if (ep_idx >= USB_NUM_ENDPOINTS) {
745 LOG_ERR("endpoint index/address out of range");
746 return -1;
747 }
748
749 if (for_in) {
750 /* if endpoint is not configured, this should return 0 */
751 if (endpoint->EPCFG.bit.EPTYPE1 == 0) {
752 return 0;
753 }
754
755 return usb_sam0_pcksize_bytes[
756 desc->DeviceDescBank[1].PCKSIZE.bit.SIZE];
757 } else {
758 /* if endpoint is not configured, this should return 0 */
759 if (endpoint->EPCFG.bit.EPTYPE0 == 0) {
760 return 0;
761 }
762
763 return usb_sam0_pcksize_bytes[
764 desc->DeviceDescBank[0].PCKSIZE.bit.SIZE];
765 }
766 }
767