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 = &REGS->DEVICE;
81 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->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 = &regs->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 = &REGS->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 = &REGS->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 = &REGS->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 = &REGS->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 = &REGS->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 = &REGS->DEVICE;
384 	uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr);
385 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->DEVICE;
457 	uint8_t for_in = USB_EP_GET_DIR(ep);
458 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
459 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->DEVICE;
478 	uint8_t for_in = USB_EP_GET_DIR(ep);
479 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
480 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->DEVICE;
499 	uint8_t for_in = USB_EP_GET_DIR(ep);
500 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
501 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->DEVICE;
548 	uint8_t for_in = USB_EP_GET_DIR(ep);
549 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
550 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->DEVICE;
574 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
575 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->DEVICE;
594 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
595 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->DEVICE;
637 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
638 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->DEVICE;
705 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
706 	UsbDeviceEndpoint *endpoint = &regs->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 = &REGS->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 = &regs->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