1 /*
2  * Copyright (c) 2018 Aurelien Jarno <aurelien@aurel32.net>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT atmel_sam_usbhs
8 
9 #include <zephyr/usb/usb_device.h>
10 #include <zephyr/drivers/clock_control/atmel_sam_pmc.h>
11 #include <zephyr/irq.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/sys/barrier.h>
14 #include <soc.h>
15 #include <string.h>
16 
17 #define LOG_LEVEL CONFIG_USB_DRIVER_LOG_LEVEL
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(usb_dc_sam_usbhs);
20 
21 /*
22  * This is defined in the support files for the SAM S7x, but not for
23  * the SAM E7x nor SAM V7x.
24  */
25 #ifndef USBHS_RAM_ADDR
26 #define USBHS_RAM_ADDR		(0xA0100000)
27 #endif
28 
29 /*
30  * The new Atmel DFP headers provide mode-specific interrupt register field
31  * definitions.  Map the existing generic definitions to these.
32  */
33 #ifndef USBHS_DEVEPTISR_CTRL_RXSTPI
34 #define USBHS_DEVEPTISR_CTRL_RXSTPI	USBHS_DEVEPTISR_RXSTPI
35 #endif
36 #ifndef USBHS_DEVEPTICR_CTRL_RXSTPIC
37 #define USBHS_DEVEPTICR_CTRL_RXSTPIC	USBHS_DEVEPTICR_RXSTPIC
38 #endif
39 #ifndef USBHS_DEVEPTIMR_CTRL_STALLRQ
40 #define USBHS_DEVEPTIMR_CTRL_STALLRQ	USBHS_DEVEPTIMR_STALLRQ
41 #endif
42 #ifndef USBHS_DEVEPTIER_CTRL_RXSTPES
43 #define USBHS_DEVEPTIER_CTRL_RXSTPES	USBHS_DEVEPTIER_RXSTPES
44 #endif
45 #ifndef USBHS_DEVEPTIER_CTRL_STALLRQS
46 #define USBHS_DEVEPTIER_CTRL_STALLRQS	USBHS_DEVEPTIER_STALLRQS
47 #endif
48 #ifndef USBHS_DEVEPTIDR_CTRL_STALLRQC
49 #define USBHS_DEVEPTIDR_CTRL_STALLRQC	USBHS_DEVEPTIDR_STALLRQC
50 #endif
51 
52 #define NUM_OF_EP_MAX		DT_INST_PROP(0, num_bidir_endpoints)
53 #define USB_MAXIMUM_SPEED	DT_INST_ENUM_IDX_OR(0, maximum_speed, 1)
54 BUILD_ASSERT(USB_MAXIMUM_SPEED, "low-speed is not supported");
55 
56 struct usb_device_ep_data {
57 	uint16_t mps;
58 	usb_dc_ep_callback cb_in;
59 	usb_dc_ep_callback cb_out;
60 	uint8_t *fifo;
61 };
62 
63 struct usb_device_data {
64 	bool addr_enabled;
65 	usb_dc_status_callback status_cb;
66 	struct usb_device_ep_data ep_data[NUM_OF_EP_MAX];
67 };
68 
69 static struct usb_device_data dev_data;
70 
71 /* Enable the USB device clock */
usb_dc_enable_clock(void)72 static void usb_dc_enable_clock(void)
73 {
74 	/* Start the USB PLL */
75 	PMC->CKGR_UCKR |= CKGR_UCKR_UPLLEN;
76 
77 	/* Wait for it to be ready */
78 	while (!(PMC->PMC_SR & PMC_SR_LOCKU)) {
79 		k_yield();
80 	}
81 
82 	/* In low power mode, provide a 48MHZ clock instead of the 480MHz one */
83 	if ((USBHS->USBHS_DEVCTRL & USBHS_DEVCTRL_SPDCONF_Msk)
84 	    == USBHS_DEVCTRL_SPDCONF_LOW_POWER) {
85 		/* Configure the USB_48M clock to be UPLLCK/10 */
86 		PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2;
87 		PMC->PMC_USB = PMC_USB_USBDIV(9) | PMC_USB_USBS;
88 
89 		/* Enable USB_48M clock */
90 		PMC->PMC_SCER |= PMC_SCER_USBCLK;
91 	}
92 }
93 
94 /* Disable the USB device clock */
usb_dc_disable_clock(void)95 static void usb_dc_disable_clock(void)
96 {
97 	/* Disable USB_48M clock */
98 	PMC->PMC_SCER &= ~PMC_SCER_USBCLK;
99 
100 	/* Disable the USB PLL */
101 	PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;
102 }
103 
104 /* Check if the USB device is attached */
usb_dc_is_attached(void)105 static bool usb_dc_is_attached(void)
106 {
107 	return (USBHS->USBHS_DEVCTRL & USBHS_DEVCTRL_DETACH) == 0;
108 }
109 
110 /* Check if an endpoint is configured */
usb_dc_ep_is_configured(uint8_t ep_idx)111 static bool usb_dc_ep_is_configured(uint8_t ep_idx)
112 {
113 	return USBHS->USBHS_DEVEPTISR[ep_idx] & USBHS_DEVEPTISR_CFGOK;
114 }
115 
116 /* Check if an endpoint is enabled */
usb_dc_ep_is_enabled(uint8_t ep_idx)117 static bool usb_dc_ep_is_enabled(uint8_t ep_idx)
118 {
119 	return USBHS->USBHS_DEVEPT & BIT(USBHS_DEVEPT_EPEN0_Pos + ep_idx);
120 }
121 
122 /* Reset and endpoint */
usb_dc_ep_reset(uint8_t ep_idx)123 static void usb_dc_ep_reset(uint8_t ep_idx)
124 {
125 	USBHS->USBHS_DEVEPT |= BIT(USBHS_DEVEPT_EPRST0_Pos + ep_idx);
126 	USBHS->USBHS_DEVEPT &= ~BIT(USBHS_DEVEPT_EPRST0_Pos + ep_idx);
127 	barrier_dsync_fence_full();
128 }
129 
130 /* Enable endpoint interrupts, depending of the type and direction */
usb_dc_ep_enable_interrupts(uint8_t ep_idx)131 static void usb_dc_ep_enable_interrupts(uint8_t ep_idx)
132 {
133 	if (ep_idx == 0U) {
134 		/* Control endpoint: enable SETUP and OUT */
135 		USBHS->USBHS_DEVEPTIER[ep_idx] = USBHS_DEVEPTIER_CTRL_RXSTPES;
136 		USBHS->USBHS_DEVEPTIER[ep_idx] = USBHS_DEVEPTIER_RXOUTES;
137 	} else if ((USBHS->USBHS_DEVEPTCFG[ep_idx] & USBHS_DEVEPTCFG_EPDIR_Msk)
138 		   == USBHS_DEVEPTCFG_EPDIR_IN) {
139 		/* IN direction: acknowledge FIFO empty interrupt */
140 		USBHS->USBHS_DEVEPTICR[ep_idx] = USBHS_DEVEPTICR_TXINIC;
141 		USBHS->USBHS_DEVEPTIER[ep_idx] = USBHS_DEVEPTIER_TXINES;
142 	} else {
143 		/* OUT direction */
144 		USBHS->USBHS_DEVEPTIER[ep_idx] = USBHS_DEVEPTIER_RXOUTES;
145 	}
146 }
147 
148 /* Reset the endpoint FIFO pointer to the beginning of the endpoint memory */
usb_dc_ep_fifo_reset(uint8_t ep_idx)149 static void usb_dc_ep_fifo_reset(uint8_t ep_idx)
150 {
151 	uint8_t *p;
152 
153 	p = (uint8_t *)(USBHS_RAM_ADDR + 0x8000 * ep_idx);
154 	dev_data.ep_data[ep_idx].fifo = p;
155 }
156 
157 /* Fetch a byte from the endpoint FIFO */
usb_dc_ep_fifo_get(uint8_t ep_idx)158 static uint8_t usb_dc_ep_fifo_get(uint8_t ep_idx)
159 {
160 	return *(dev_data.ep_data[ep_idx].fifo++);
161 }
162 
163 /* Put a byte from the endpoint FIFO */
usb_dc_ep_fifo_put(uint8_t ep_idx,uint8_t data)164 static void usb_dc_ep_fifo_put(uint8_t ep_idx, uint8_t data)
165 {
166 	*(dev_data.ep_data[ep_idx].fifo++) = data;
167 }
168 
169 /* Handle interrupts on a control endpoint */
usb_dc_ep0_isr(void)170 static void usb_dc_ep0_isr(void)
171 {
172 	uint32_t sr = USBHS->USBHS_DEVEPTISR[0] & USBHS->USBHS_DEVEPTIMR[0];
173 	uint32_t dev_ctrl = USBHS->USBHS_DEVCTRL;
174 
175 	if (sr & USBHS_DEVEPTISR_CTRL_RXSTPI) {
176 		/* SETUP data received */
177 		usb_dc_ep_fifo_reset(0);
178 		dev_data.ep_data[0].cb_out(USB_EP_DIR_OUT, USB_DC_EP_SETUP);
179 	}
180 	if (sr & USBHS_DEVEPTISR_RXOUTI) {
181 		/* OUT (to device) data received */
182 		usb_dc_ep_fifo_reset(0);
183 		dev_data.ep_data[0].cb_out(USB_EP_DIR_OUT, USB_DC_EP_DATA_OUT);
184 	}
185 	if (sr & USBHS_DEVEPTISR_TXINI) {
186 		/* Disable the interrupt */
187 		USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC;
188 
189 		/* IN (to host) transmit complete */
190 		usb_dc_ep_fifo_reset(0);
191 		dev_data.ep_data[0].cb_in(USB_EP_DIR_IN, USB_DC_EP_DATA_IN);
192 
193 		if (!(dev_ctrl & USBHS_DEVCTRL_ADDEN) &&
194 		    (dev_ctrl & USBHS_DEVCTRL_UADD_Msk) != 0U) {
195 			/* Commit the pending address update.  This
196 			 * must be done after the ack to the host
197 			 * completes else the ack will get dropped.
198 			 */
199 			USBHS->USBHS_DEVCTRL = dev_ctrl | USBHS_DEVCTRL_ADDEN;
200 		}
201 	}
202 }
203 
204 /* Handle interrupts on a non-control endpoint */
usb_dc_ep_isr(uint8_t ep_idx)205 static void usb_dc_ep_isr(uint8_t ep_idx)
206 {
207 	uint32_t sr = USBHS->USBHS_DEVEPTISR[ep_idx] &
208 		   USBHS->USBHS_DEVEPTIMR[ep_idx];
209 
210 	if (sr & USBHS_DEVEPTISR_RXOUTI) {
211 		uint8_t ep = ep_idx | USB_EP_DIR_OUT;
212 
213 		/* Acknowledge the interrupt */
214 		USBHS->USBHS_DEVEPTICR[ep_idx] = USBHS_DEVEPTICR_RXOUTIC;
215 
216 		/* OUT (to device) data received */
217 		usb_dc_ep_fifo_reset(ep_idx);
218 		dev_data.ep_data[ep_idx].cb_out(ep, USB_DC_EP_DATA_OUT);
219 	}
220 	if (sr & USBHS_DEVEPTISR_TXINI) {
221 		uint8_t ep = ep_idx | USB_EP_DIR_IN;
222 
223 		/* Acknowledge the interrupt */
224 		USBHS->USBHS_DEVEPTICR[ep_idx] = USBHS_DEVEPTICR_TXINIC;
225 
226 		/* IN (to host) transmit complete */
227 		usb_dc_ep_fifo_reset(ep_idx);
228 		dev_data.ep_data[ep_idx].cb_in(ep, USB_DC_EP_DATA_IN);
229 	}
230 }
231 
232 /* Top level interrupt handler */
usb_dc_isr(void)233 static void usb_dc_isr(void)
234 {
235 	uint32_t sr = USBHS->USBHS_DEVISR & USBHS->USBHS_DEVIMR;
236 
237 	/* End of resume interrupt */
238 	if (sr & USBHS_DEVISR_EORSM) {
239 		/* Acknowledge the interrupt */
240 		USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSMC;
241 
242 		/* Callback function */
243 		dev_data.status_cb(USB_DC_RESUME, NULL);
244 	}
245 
246 	/* End of reset interrupt */
247 	if (sr & USBHS_DEVISR_EORST) {
248 		/* Acknowledge the interrupt */
249 		USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC;
250 
251 		if (!usb_dc_ep_is_configured(0) && dev_data.ep_data[0].mps) {
252 			/* Restore EP0 configuration to previously set mps */
253 			struct usb_dc_ep_cfg_data cfg = {
254 				.ep_addr = 0,
255 				.ep_mps = dev_data.ep_data[0].mps,
256 				.ep_type = USB_DC_EP_CONTROL,
257 			};
258 			usb_dc_ep_configure(&cfg);
259 			usb_dc_ep_enable(0);
260 		}
261 		if (usb_dc_ep_is_enabled(0)) {
262 			/* The device clears some of the configuration of EP0
263 			 * when it receives the EORST.  Re-enable interrupts.
264 			 */
265 			usb_dc_ep_enable_interrupts(0);
266 		}
267 
268 		/* Free all endpoint memory */
269 		for (int idx = 1; idx < NUM_OF_EP_MAX; idx++) {
270 			usb_dc_ep_disable(idx);
271 			USBHS->USBHS_DEVEPTCFG[idx] &= ~USBHS_DEVEPTCFG_ALLOC;
272 		}
273 
274 		/* Callback function */
275 		dev_data.status_cb(USB_DC_RESET, NULL);
276 	}
277 
278 	/* Suspend interrupt */
279 	if (sr & USBHS_DEVISR_SUSP) {
280 		/* Acknowledge the interrupt */
281 		USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC;
282 
283 		/* Callback function */
284 		dev_data.status_cb(USB_DC_SUSPEND, NULL);
285 	}
286 
287 #ifdef CONFIG_USB_DEVICE_SOF
288 	/* SOF interrupt */
289 	if (sr & USBHS_DEVISR_SOF) {
290 		/* Acknowledge the interrupt */
291 		USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC;
292 
293 		/* Callback function */
294 		dev_data.status_cb(USB_DC_SOF, NULL);
295 	}
296 #endif
297 
298 	/* EP0 endpoint interrupt */
299 	if (sr & USBHS_DEVISR_PEP_0) {
300 		usb_dc_ep0_isr();
301 	}
302 
303 	/* Other endpoints interrupt */
304 	for (int ep_idx = 1; ep_idx < NUM_OF_EP_MAX; ep_idx++) {
305 		if (sr & BIT(USBHS_DEVISR_PEP_0_Pos + ep_idx)) {
306 			usb_dc_ep_isr(ep_idx);
307 		}
308 	}
309 }
310 
311 /* Attach USB for device connection */
usb_dc_attach(void)312 int usb_dc_attach(void)
313 {
314 	const struct atmel_sam_pmc_config clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(0);
315 	uint32_t regval;
316 
317 	/* Enable USBHS clock in PMC */
318 	(void)clock_control_on(SAM_DT_PMC_CONTROLLER,
319 			       (clock_control_subsys_t)&clock_cfg);
320 
321 	/* Enable the USB controller in device mode with the clock frozen */
322 	USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE |
323 			    USBHS_CTRL_FRZCLK;
324 	barrier_dsync_fence_full();
325 
326 	/* Select the speed */
327 	regval = USBHS_DEVCTRL_DETACH;
328 #if (USB_MAXIMUM_SPEED == 2) && IS_ENABLED(CONFIG_USB_DC_HAS_HS_SUPPORT)
329 	/* high-speed */
330 	regval |= USBHS_DEVCTRL_SPDCONF_NORMAL;
331 #else
332 	/* full-speed */
333 	regval |= USBHS_DEVCTRL_SPDCONF_LOW_POWER;
334 #endif
335 	USBHS->USBHS_DEVCTRL = regval;
336 
337 	/* Enable the USB clock */
338 	usb_dc_enable_clock();
339 
340 	/* Unfreeze the clock */
341 	USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE;
342 
343 	/* Enable device interrupts */
344 	USBHS->USBHS_DEVIER = USBHS_DEVIER_EORSMES;
345 	USBHS->USBHS_DEVIER = USBHS_DEVIER_EORSTES;
346 	USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES;
347 #ifdef CONFIG_USB_DEVICE_SOF
348 	USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES;
349 #endif
350 
351 	/* Connect and enable the interrupt */
352 	IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
353 		    usb_dc_isr, 0, 0);
354 	irq_enable(DT_INST_IRQN(0));
355 
356 	/* Attach the device */
357 	USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH;
358 
359 	LOG_DBG("");
360 	return 0;
361 }
362 
363 /* Detach the USB device */
usb_dc_detach(void)364 int usb_dc_detach(void)
365 {
366 	const struct atmel_sam_pmc_config clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(0);
367 
368 	/* Detach the device */
369 	USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH;
370 
371 	/* Disable the USB clock */
372 	usb_dc_disable_clock();
373 
374 	/* Disable the USB controller and freeze the clock */
375 	USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_FRZCLK;
376 
377 	/* Disable USBHS clock in PMC */
378 	(void)clock_control_off(SAM_DT_PMC_CONTROLLER,
379 				(clock_control_subsys_t)&clock_cfg);
380 
381 	/* Disable interrupt */
382 	irq_disable(DT_INST_IRQN(0));
383 
384 	LOG_DBG("");
385 	return 0;
386 }
387 
388 /* Reset the USB device */
usb_dc_reset(void)389 int usb_dc_reset(void)
390 {
391 	/* Reset the controller */
392 	USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_FRZCLK;
393 
394 	/* Clear private data */
395 	(void)memset(&dev_data, 0, sizeof(dev_data));
396 
397 	LOG_DBG("");
398 	return 0;
399 }
400 
401 /* Set USB device address */
usb_dc_set_address(uint8_t addr)402 int usb_dc_set_address(uint8_t addr)
403 {
404 	/*
405 	 * Set the address but keep it disabled for now. It should be enabled
406 	 * only after the ack to the host completes.
407 	 */
408 	USBHS->USBHS_DEVCTRL &= ~(USBHS_DEVCTRL_UADD_Msk | USBHS_DEVCTRL_ADDEN);
409 	USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_UADD(addr);
410 	LOG_DBG("");
411 
412 	return 0;
413 }
414 
415 /* Set USB device controller status callback */
usb_dc_set_status_callback(const usb_dc_status_callback cb)416 void usb_dc_set_status_callback(const usb_dc_status_callback cb)
417 {
418 	LOG_DBG("");
419 
420 	dev_data.status_cb = cb;
421 }
422 
423 /* Check endpoint capabilities */
usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data * const cfg)424 int usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data * const cfg)
425 {
426 	uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr);
427 
428 	if (ep_idx >= NUM_OF_EP_MAX) {
429 		LOG_ERR("endpoint index/address out of range");
430 		return -1;
431 	}
432 
433 	if (ep_idx == 0U) {
434 		if (cfg->ep_type != USB_DC_EP_CONTROL) {
435 			LOG_ERR("pre-selected as control endpoint");
436 			return -1;
437 		}
438 	} else if (ep_idx & BIT(0)) {
439 		if (USB_EP_GET_DIR(cfg->ep_addr) != USB_EP_DIR_IN) {
440 			LOG_INF("pre-selected as IN endpoint");
441 			return -1;
442 		}
443 	} else {
444 		if (USB_EP_GET_DIR(cfg->ep_addr) != USB_EP_DIR_OUT) {
445 			LOG_INF("pre-selected as OUT endpoint");
446 			return -1;
447 		}
448 	}
449 
450 	if (cfg->ep_mps < 1 || cfg->ep_mps > 1024 ||
451 	    (cfg->ep_type == USB_DC_EP_CONTROL && cfg->ep_mps > 64)) {
452 		LOG_ERR("invalid endpoint size");
453 		return -1;
454 	}
455 
456 	return 0;
457 }
458 
459 /* Configure endpoint */
usb_dc_ep_configure(const struct usb_dc_ep_cfg_data * const cfg)460 int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data *const cfg)
461 {
462 	uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr);
463 	bool ep_configured[NUM_OF_EP_MAX];
464 	bool ep_enabled[NUM_OF_EP_MAX];
465 	uint32_t regval = 0U;
466 	int log2ceil_mps;
467 
468 	if (usb_dc_ep_check_cap(cfg) != 0) {
469 		return -EINVAL;
470 	}
471 
472 	if (!usb_dc_is_attached()) {
473 		LOG_ERR("device not attached");
474 		return -ENODEV;
475 	}
476 
477 	if (usb_dc_ep_is_enabled(ep_idx)) {
478 		LOG_WRN("endpoint already configured & enabled 0x%x", ep_idx);
479 		return -EBUSY;
480 	}
481 
482 	LOG_INF("Configure ep %x, mps %d, type %d", cfg->ep_addr, cfg->ep_mps,
483 		cfg->ep_type);
484 
485 	/* Reset the endpoint */
486 	usb_dc_ep_reset(ep_idx);
487 	/* Initialize the endpoint FIFO */
488 	usb_dc_ep_fifo_reset(ep_idx);
489 
490 	/* Map the endpoint type */
491 	switch (cfg->ep_type) {
492 	case USB_DC_EP_CONTROL:
493 		regval |= USBHS_DEVEPTCFG_EPTYPE_CTRL;
494 		break;
495 	case USB_DC_EP_ISOCHRONOUS:
496 		regval |= USBHS_DEVEPTCFG_EPTYPE_ISO;
497 		break;
498 	case USB_DC_EP_BULK:
499 		regval |= USBHS_DEVEPTCFG_EPTYPE_BLK;
500 		break;
501 	case USB_DC_EP_INTERRUPT:
502 		regval |= USBHS_DEVEPTCFG_EPTYPE_INTRPT;
503 		break;
504 	default:
505 		return -EINVAL;
506 	}
507 
508 	/* Map the endpoint direction */
509 	if (USB_EP_DIR_IS_OUT(cfg->ep_addr) ||
510 	    cfg->ep_type == USB_DC_EP_CONTROL) {
511 		regval |= USBHS_DEVEPTCFG_EPDIR_OUT;
512 	} else {
513 		regval |= USBHS_DEVEPTCFG_EPDIR_IN;
514 	}
515 
516 	/*
517 	 * Map the endpoint size to the buffer size. Only power of 2 buffer
518 	 * sizes between 8 and 1024 are possible, get the next power of 2.
519 	 */
520 	log2ceil_mps = 32 - __builtin_clz((MAX(cfg->ep_mps, 8) << 1) - 1) - 1;
521 	regval |= USBHS_DEVEPTCFG_EPSIZE(log2ceil_mps - 3);
522 	dev_data.ep_data[ep_idx].mps = cfg->ep_mps;
523 
524 	/* Use double bank buffering for isochronous endpoints */
525 	if (cfg->ep_type == USB_DC_EP_ISOCHRONOUS) {
526 		regval |= USBHS_DEVEPTCFG_EPBK_2_BANK;
527 	} else {
528 		regval |= USBHS_DEVEPTCFG_EPBK_1_BANK;
529 	}
530 
531 	/* Configure the endpoint */
532 	USBHS->USBHS_DEVEPTCFG[ep_idx] = regval;
533 
534 	/*
535 	 * Allocate the memory. This part is a bit tricky as memory can only be
536 	 * allocated if all above endpoints are disabled and not allocated. Loop
537 	 * backward through the above endpoints, disable them if they are
538 	 * enabled, deallocate their memory if needed. Then loop again through
539 	 * all the above endpoints to allocate and enabled them.
540 	 */
541 	for (int i = NUM_OF_EP_MAX - 1; i > ep_idx; i--) {
542 		ep_configured[i] = usb_dc_ep_is_configured(i);
543 		ep_enabled[i] = usb_dc_ep_is_enabled(i);
544 
545 		if (ep_enabled[i]) {
546 			LOG_INF("Temporary disable ep idx %x", i);
547 			usb_dc_ep_disable(i);
548 		}
549 		if (ep_configured[i]) {
550 			USBHS->USBHS_DEVEPTCFG[i] &= ~USBHS_DEVEPTCFG_ALLOC;
551 		}
552 	}
553 	ep_configured[ep_idx] = true;
554 	ep_enabled[ep_idx] = false;
555 	for (int i = ep_idx; i < NUM_OF_EP_MAX; i++) {
556 		if (ep_configured[i]) {
557 			USBHS->USBHS_DEVEPTCFG[i] |= USBHS_DEVEPTCFG_ALLOC;
558 		}
559 		if (ep_enabled[i]) {
560 			usb_dc_ep_enable(i);
561 		}
562 	}
563 
564 	/* Check that the endpoint is correctly configured */
565 	if (!usb_dc_ep_is_configured(ep_idx)) {
566 		LOG_ERR("endpoint configuration failed");
567 		return -EINVAL;
568 	}
569 
570 	return 0;
571 }
572 
573 /* Set stall condition for the selected endpoint */
usb_dc_ep_set_stall(uint8_t ep)574 int usb_dc_ep_set_stall(uint8_t ep)
575 {
576 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
577 
578 	if (ep_idx >= NUM_OF_EP_MAX) {
579 		LOG_ERR("wrong endpoint index/address");
580 		return -EINVAL;
581 	}
582 
583 	USBHS->USBHS_DEVEPTIER[ep_idx] = USBHS_DEVEPTIER_CTRL_STALLRQS;
584 
585 	LOG_DBG("ep 0x%x", ep);
586 	return 0;
587 }
588 
589 /* Clear stall condition for the selected endpoint */
usb_dc_ep_clear_stall(uint8_t ep)590 int usb_dc_ep_clear_stall(uint8_t ep)
591 {
592 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
593 
594 	if (ep_idx >= NUM_OF_EP_MAX) {
595 		LOG_ERR("wrong endpoint index/address");
596 		return -EINVAL;
597 	}
598 
599 	USBHS->USBHS_DEVEPTIDR[ep_idx] = USBHS_DEVEPTIDR_CTRL_STALLRQC;
600 
601 	LOG_DBG("ep 0x%x", ep);
602 	return 0;
603 }
604 
605 /* Check if the selected endpoint is stalled */
usb_dc_ep_is_stalled(uint8_t ep,uint8_t * stalled)606 int usb_dc_ep_is_stalled(uint8_t ep, uint8_t *stalled)
607 {
608 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
609 
610 	if (ep_idx >= NUM_OF_EP_MAX) {
611 		LOG_ERR("wrong endpoint index/address");
612 		return -EINVAL;
613 	}
614 
615 	if (!stalled) {
616 		return -EINVAL;
617 	}
618 
619 	*stalled = (USBHS->USBHS_DEVEPTIMR[ep_idx] &
620 		    USBHS_DEVEPTIMR_CTRL_STALLRQ) != 0;
621 
622 	LOG_DBG("ep 0x%x", ep);
623 	return 0;
624 }
625 
626 /* Halt the selected endpoint */
usb_dc_ep_halt(uint8_t ep)627 int usb_dc_ep_halt(uint8_t ep)
628 {
629 	return usb_dc_ep_set_stall(ep);
630 }
631 
632 /* Enable the selected endpoint */
usb_dc_ep_enable(uint8_t ep)633 int usb_dc_ep_enable(uint8_t ep)
634 {
635 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
636 
637 	if (ep_idx >= NUM_OF_EP_MAX) {
638 		LOG_ERR("wrong endpoint index/address");
639 		return -EINVAL;
640 	}
641 
642 	if (!usb_dc_ep_is_configured(ep_idx)) {
643 		LOG_ERR("endpoint not configured");
644 		return -ENODEV;
645 	}
646 
647 	/* Enable endpoint */
648 	USBHS->USBHS_DEVEPT |= BIT(USBHS_DEVEPT_EPEN0_Pos + ep_idx);
649 
650 	/* Enable endpoint interrupts */
651 	USBHS->USBHS_DEVIER = BIT(USBHS_DEVIER_PEP_0_Pos + ep_idx);
652 
653 	/* Enable SETUP, IN or OUT endpoint interrupts */
654 	usb_dc_ep_enable_interrupts(ep_idx);
655 
656 	LOG_INF("Enable ep 0x%x", ep);
657 
658 	return 0;
659 }
660 
661 /* Disable the selected endpoint */
usb_dc_ep_disable(uint8_t ep)662 int usb_dc_ep_disable(uint8_t ep)
663 {
664 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
665 
666 	if (ep_idx >= NUM_OF_EP_MAX) {
667 		LOG_ERR("wrong endpoint index/address");
668 		return -EINVAL;
669 	}
670 
671 	/* Disable endpoint interrupt */
672 	USBHS->USBHS_DEVIDR = BIT(USBHS_DEVIDR_PEP_0_Pos + ep_idx);
673 
674 	/* Disable endpoint and SETUP, IN or OUT interrupts */
675 	USBHS->USBHS_DEVEPT &= ~BIT(USBHS_DEVEPT_EPEN0_Pos + ep_idx);
676 
677 	LOG_INF("Disable ep 0x%x", ep);
678 
679 	return 0;
680 }
681 
682 /* Flush the selected endpoint */
usb_dc_ep_flush(uint8_t ep)683 int usb_dc_ep_flush(uint8_t ep)
684 {
685 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
686 
687 	if (ep_idx >= NUM_OF_EP_MAX) {
688 		LOG_ERR("wrong endpoint index/address");
689 		return -EINVAL;
690 	}
691 
692 	if (!usb_dc_ep_is_enabled(ep_idx)) {
693 		LOG_ERR("endpoint not enabled");
694 		return -ENODEV;
695 	}
696 
697 	/* Disable the IN interrupt */
698 	USBHS->USBHS_DEVEPTIDR[ep_idx] = USBHS_DEVEPTIDR_TXINEC;
699 
700 	/* Kill the last written bank if needed */
701 	if (USBHS->USBHS_DEVEPTISR[ep_idx] & USBHS_DEVEPTISR_NBUSYBK_Msk) {
702 		USBHS->USBHS_DEVEPTIER[ep_idx] = USBHS_DEVEPTIER_KILLBKS;
703 		barrier_dsync_fence_full();
704 		while (USBHS->USBHS_DEVEPTIMR[ep_idx] &
705 		       USBHS_DEVEPTIMR_KILLBK) {
706 			k_yield();
707 		}
708 	}
709 
710 	/* Reset the endpoint */
711 	usb_dc_ep_reset(ep_idx);
712 
713 	/* Re-enable interrupts */
714 	usb_dc_ep_enable_interrupts(ep_idx);
715 
716 	LOG_DBG("ep 0x%x", ep);
717 	return 0;
718 }
719 
720 /* Write data to the specified endpoint */
usb_dc_ep_write(uint8_t ep,const uint8_t * data,uint32_t data_len,uint32_t * ret_bytes)721 int usb_dc_ep_write(uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes)
722 {
723 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
724 	uint32_t packet_len;
725 
726 	if (ep_idx >= NUM_OF_EP_MAX) {
727 		LOG_ERR("wrong endpoint index/address");
728 		return -EINVAL;
729 	}
730 
731 	if (!usb_dc_ep_is_enabled(ep_idx)) {
732 		LOG_ERR("endpoint not enabled");
733 		return -ENODEV;
734 	}
735 
736 	if (USB_EP_GET_DIR(ep) != USB_EP_DIR_IN) {
737 		LOG_ERR("wrong endpoint direction");
738 		return -EINVAL;
739 	}
740 
741 	if ((USBHS->USBHS_DEVEPTIMR[ep_idx] & USBHS_DEVEPTIMR_CTRL_STALLRQ)
742 		!= 0) {
743 		LOG_WRN("endpoint is stalled");
744 		return -EBUSY;
745 	}
746 
747 	/* Write the data to the FIFO */
748 	packet_len = MIN(data_len, dev_data.ep_data[ep_idx].mps);
749 	for (int i = 0; i < packet_len; i++) {
750 		usb_dc_ep_fifo_put(ep_idx, data[i]);
751 	}
752 	barrier_dsync_fence_full();
753 
754 	if (ep_idx == 0U) {
755 		/*
756 		 * Control endpoint: clear the interrupt flag to send the data,
757 		 * and re-enable the interrupts to trigger an interrupt at the
758 		 * end of the transfer.
759 		 */
760 		USBHS->USBHS_DEVEPTICR[ep_idx] = USBHS_DEVEPTICR_TXINIC;
761 		USBHS->USBHS_DEVEPTIER[ep_idx] = USBHS_DEVEPTIER_TXINES;
762 	} else {
763 		/*
764 		 * Other endpoint types: clear the FIFO control flag to send
765 		 * the data.
766 		 */
767 		USBHS->USBHS_DEVEPTIDR[ep_idx] = USBHS_DEVEPTIDR_FIFOCONC;
768 	}
769 
770 	if (ret_bytes) {
771 		*ret_bytes = packet_len;
772 	}
773 
774 	LOG_DBG("ep 0x%x write %d bytes from %d", ep, packet_len, data_len);
775 	return 0;
776 }
777 
778 /* Read data from the specified endpoint */
usb_dc_ep_read(uint8_t ep,uint8_t * data,uint32_t max_data_len,uint32_t * read_bytes)779 int usb_dc_ep_read(uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes)
780 {
781 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
782 	int rc;
783 
784 	rc = usb_dc_ep_read_wait(ep, data, max_data_len, read_bytes);
785 
786 	if (rc) {
787 		return rc;
788 	}
789 
790 	if (!data && !max_data_len) {
791 		/* When both buffer and max data to read are zero the above
792 		 * call would fetch the data len and we simply return.
793 		 */
794 		return 0;
795 	}
796 
797 	/* If the packet has been read entirely, get the next one */
798 	if (!(USBHS->USBHS_DEVEPTISR[ep_idx] & USBHS_DEVEPTISR_RWALL)) {
799 		rc = usb_dc_ep_read_continue(ep);
800 	}
801 
802 	LOG_DBG("ep 0x%x", ep);
803 	return rc;
804 }
805 
806 /* Set callback function for the specified endpoint */
usb_dc_ep_set_callback(uint8_t ep,const usb_dc_ep_callback cb)807 int usb_dc_ep_set_callback(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) {
812 		LOG_ERR("wrong endpoint index/address");
813 		return -EINVAL;
814 	}
815 
816 	if (USB_EP_DIR_IS_IN(ep)) {
817 		dev_data.ep_data[ep_idx].cb_in = cb;
818 	} else {
819 		dev_data.ep_data[ep_idx].cb_out = cb;
820 	}
821 
822 	LOG_DBG("ep 0x%x", ep);
823 	return 0;
824 }
825 
826 /* Read data from the specified endpoint */
usb_dc_ep_read_wait(uint8_t ep,uint8_t * data,uint32_t max_data_len,uint32_t * read_bytes)827 int usb_dc_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len,
828 			uint32_t *read_bytes)
829 {
830 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
831 	uint32_t data_len = (USBHS->USBHS_DEVEPTISR[ep_idx] &
832 			  USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos;
833 
834 	if (ep_idx >= NUM_OF_EP_MAX) {
835 		LOG_ERR("wrong endpoint index/address");
836 		return -EINVAL;
837 	}
838 
839 	if (!usb_dc_ep_is_enabled(ep_idx)) {
840 		LOG_ERR("endpoint not enabled");
841 		return -ENODEV;
842 	}
843 
844 	if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) {
845 		LOG_ERR("wrong endpoint direction");
846 		return -EINVAL;
847 	}
848 
849 	if ((USBHS->USBHS_DEVEPTIMR[ep_idx] & USBHS_DEVEPTIMR_CTRL_STALLRQ)
850 		!= 0) {
851 		LOG_WRN("endpoint is stalled");
852 		return -EBUSY;
853 	}
854 
855 	if (!data && !max_data_len) {
856 		/*
857 		 * When both buffer and max data to read are zero return
858 		 * the available data in buffer.
859 		 */
860 		if (read_bytes) {
861 			*read_bytes = data_len;
862 		}
863 		return 0;
864 	}
865 
866 	if (data_len > max_data_len) {
867 		LOG_WRN("Not enough space to copy all the data!");
868 		data_len = max_data_len;
869 	}
870 
871 	if (data != NULL) {
872 		for (int i = 0; i < data_len; i++) {
873 			data[i] = usb_dc_ep_fifo_get(ep_idx);
874 		}
875 	}
876 
877 	if (read_bytes) {
878 		*read_bytes = data_len;
879 	}
880 
881 	LOG_DBG("ep 0x%x read %d bytes", ep, data_len);
882 	return 0;
883 }
884 
885 /* Continue reading data from the endpoint */
usb_dc_ep_read_continue(uint8_t ep)886 int usb_dc_ep_read_continue(uint8_t ep)
887 {
888 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
889 
890 	if (ep_idx >= NUM_OF_EP_MAX) {
891 		LOG_ERR("wrong endpoint index/address");
892 		return -EINVAL;
893 	}
894 
895 	if (!usb_dc_ep_is_enabled(ep_idx)) {
896 		LOG_ERR("endpoint not enabled");
897 		return -ENODEV;
898 	}
899 
900 	if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) {
901 		LOG_ERR("wrong endpoint direction");
902 		return -EINVAL;
903 	}
904 
905 	if (ep_idx == 0U) {
906 		/*
907 		 * Control endpoint: clear the interrupt flag to send the data.
908 		 * It is easier to clear both SETUP and OUT flag than checking
909 		 * the stage of the transfer.
910 		 */
911 		USBHS->USBHS_DEVEPTICR[ep_idx] = USBHS_DEVEPTICR_RXOUTIC;
912 		USBHS->USBHS_DEVEPTICR[ep_idx] = USBHS_DEVEPTICR_CTRL_RXSTPIC;
913 	} else {
914 		/*
915 		 * Other endpoint types: clear the FIFO control flag to
916 		 * receive more data.
917 		 */
918 		USBHS->USBHS_DEVEPTIDR[ep_idx] = USBHS_DEVEPTIDR_FIFOCONC;
919 	}
920 
921 	LOG_DBG("ep 0x%x continue", ep);
922 	return 0;
923 }
924 
925 /* Endpoint max packet size (mps) */
usb_dc_ep_mps(uint8_t ep)926 int usb_dc_ep_mps(uint8_t ep)
927 {
928 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
929 
930 	if (ep_idx >= NUM_OF_EP_MAX) {
931 		LOG_ERR("wrong endpoint index/address");
932 		return -EINVAL;
933 	}
934 
935 	return dev_data.ep_data[ep_idx].mps;
936 }
937