1 /*
2  * Copyright (c) 2024 Nuvoton Technology Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nuvoton_numaker_usbd
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/usb/udc.h>
11 #include <zephyr/sys/math_extras.h>
12 #include <zephyr/drivers/clock_control.h>
13 #include <zephyr/drivers/clock_control/clock_control_numaker.h>
14 #include <zephyr/drivers/reset.h>
15 #include <zephyr/drivers/pinctrl.h>
16 
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(udc_numaker, CONFIG_UDC_DRIVER_LOG_LEVEL);
19 
20 #include <soc.h>
21 #include <NuMicro.h>
22 
23 #include "udc_common.h"
24 
25 /* USBD notes
26  *
27  * 1. Require 48MHz clock source
28  *    (1) Not support HIRC48 as clock source. It involves trim with USB SOF packets
29  *        and isn't suitable in HAL.
30  *    (2) Instead of HICR48, core clock is required to be multiple of 48MHz e.g. 192MHz,
31  *        to generate necessary 48MHz.
32  */
33 
34 /* For bus reset, keep 'SE0' (USB spec: SE0 >= 2.5 ms) */
35 #define NUMAKER_USBD_BUS_RESET_DRV_SE0_US 3000
36 
37 /* For bus resume, generate 'K' (USB spec: 'K' >= 1 ms) */
38 #define NUMAKER_USBD_BUS_RESUME_DRV_K_US 1500
39 
40 /* Reserve DMA buffer for Setup/CTRL OUT/CTRL IN, required to be 8-byte aligned */
41 #define NUMAKER_USBD_DMABUF_SIZE_SETUP   8
42 #define NUMAKER_USBD_DMABUF_SIZE_CTRLOUT 64
43 #define NUMAKER_USBD_DMABUF_SIZE_CTRLIN  64
44 
45 enum numaker_usbd_msg_type {
46 	/* Setup packet received */
47 	NUMAKER_USBD_MSG_TYPE_SETUP,
48 	/* OUT transaction for specific EP completed */
49 	NUMAKER_USBD_MSG_TYPE_OUT,
50 	/* IN transaction for specific EP completed */
51 	NUMAKER_USBD_MSG_TYPE_IN,
52 	/* Re-activate queued transfer for specific EP */
53 	NUMAKER_USBD_MSG_TYPE_XFER,
54 	/* S/W reconnect */
55 	NUMAKER_USBD_MSG_TYPE_SW_RECONN,
56 };
57 
58 struct numaker_usbd_msg {
59 	enum numaker_usbd_msg_type type;
60 	union {
61 		struct {
62 			enum udc_event_type type;
63 		} udc_bus_event;
64 		struct {
65 			uint8_t packet[8];
66 		} setup;
67 		struct {
68 			uint8_t ep;
69 		} out;
70 		struct {
71 			uint8_t ep;
72 		} in;
73 		struct {
74 			uint8_t ep;
75 		} xfer;
76 	};
77 };
78 
79 /* EP H/W context */
80 struct numaker_usbd_ep {
81 	bool valid;
82 
83 	const struct device *dev; /* Pointer to the containing device */
84 
85 	uint8_t ep_hw_idx;  /* BSP USBD driver EP index EP0, EP1, EP2, etc */
86 	uint32_t ep_hw_cfg; /* BSP USBD driver EP configuration */
87 
88 	/* EP DMA buffer */
89 	bool dmabuf_valid;
90 	uint32_t dmabuf_base;
91 	uint32_t dmabuf_size;
92 
93 	/* NOTE: On USBD, Setup and CTRL OUT are not completely separated. CTRL OUT MXPLD
94 	 * can be overridden to 8 by next Setup. To overcome it, we make one copy of CTRL
95 	 * OUT MXPLD immediately on its interrupt.
96 	 */
97 	uint32_t mxpld_ctrlout;
98 
99 	/* EP address */
100 	bool addr_valid;
101 	uint8_t addr;
102 
103 	/* EP MPS */
104 	bool mps_valid;
105 	uint16_t mps;
106 };
107 
108 /* Immutable device context */
109 struct udc_numaker_config {
110 	struct udc_ep_config *ep_cfg_out;
111 	struct udc_ep_config *ep_cfg_in;
112 	uint32_t ep_cfg_out_size;
113 	uint32_t ep_cfg_in_size;
114 	USBD_T *base;
115 	const struct reset_dt_spec reset;
116 	uint32_t clk_modidx;
117 	uint32_t clk_src;
118 	uint32_t clk_div;
119 	const struct device *clkctrl_dev;
120 	void (*irq_config_func)(const struct device *dev);
121 	void (*irq_unconfig_func)(const struct device *dev);
122 	const struct pinctrl_dev_config *pincfg;
123 	uint32_t dmabuf_size;
124 	bool disallow_iso_inout_same;
125 	void (*make_thread)(const struct device *dev);
126 };
127 
128 /* EP H/W context manager */
129 struct numaker_usbd_ep_mgmt {
130 	/* EP H/W context management
131 	 *
132 	 * Allocate-only, and de-allocate all on re-initialize in udc_numaker_init().
133 	 */
134 	uint8_t ep_idx;
135 
136 	/* DMA buffer management
137 	 *
138 	 * Allocate-only, and de-allocate all on re-initialize in udc_numaker_init().
139 	 */
140 	uint32_t dmabuf_pos;
141 };
142 
143 /* Mutable device context */
144 struct udc_numaker_data {
145 	uint8_t addr; /* Host assigned USB device address */
146 
147 	struct k_msgq *msgq;
148 
149 	struct numaker_usbd_ep_mgmt ep_mgmt; /* EP management */
150 
151 	struct numaker_usbd_ep *ep_pool;
152 	uint32_t ep_pool_size;
153 
154 	struct k_thread thread_data;
155 
156 	/* Track end of CTRL DATA OUT/STATUS OUT stage
157 	 *
158 	 * net_buf can over-allocate for UDC_BUF_GRANULARITY requirement
159 	 * and net_buf_tailroom() cannot reflect free buffer room exactly
160 	 * as allocate request. Manually track it instead.
161 	 */
162 	uint32_t ctrlout_tailroom;
163 };
164 
numaker_usbd_sw_connect(const struct device * dev)165 static inline void numaker_usbd_sw_connect(const struct device *dev)
166 {
167 	const struct udc_numaker_config *config = dev->config;
168 	USBD_T *const base = config->base;
169 
170 	/* Clear all interrupts first for clean */
171 	base->INTSTS = base->INTSTS;
172 
173 	/* Enable relevant interrupts */
174 	base->INTEN = USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP | USBD_INT_SOF;
175 
176 	/* Clear SE0 for connect */
177 	base->SE0 &= ~USBD_DRVSE0;
178 }
179 
numaker_usbd_sw_disconnect(const struct device * dev)180 static inline void numaker_usbd_sw_disconnect(const struct device *dev)
181 {
182 	const struct udc_numaker_config *config = dev->config;
183 	USBD_T *const base = config->base;
184 
185 	/* Set SE0 for disconnect */
186 	base->SE0 |= USBD_DRVSE0;
187 }
188 
numaker_usbd_sw_reconnect(const struct device * dev)189 static inline void numaker_usbd_sw_reconnect(const struct device *dev)
190 {
191 	/* Keep SE0 to trigger bus reset */
192 	numaker_usbd_sw_disconnect(dev);
193 	k_sleep(K_USEC(NUMAKER_USBD_BUS_RESET_DRV_SE0_US));
194 	numaker_usbd_sw_connect(dev);
195 }
196 
numaker_usbd_reset_addr(const struct device * dev)197 static inline void numaker_usbd_reset_addr(const struct device *dev)
198 {
199 	const struct udc_numaker_config *config = dev->config;
200 	struct udc_numaker_data *priv = udc_get_private(dev);
201 	USBD_T *const base = config->base;
202 
203 	base->FADDR = 0;
204 	priv->addr = 0;
205 }
206 
numaker_usbd_set_addr(const struct device * dev)207 static inline void numaker_usbd_set_addr(const struct device *dev)
208 {
209 	const struct udc_numaker_config *config = dev->config;
210 	struct udc_numaker_data *priv = udc_get_private(dev);
211 	USBD_T *const base = config->base;
212 
213 	if (base->FADDR != priv->addr) {
214 		base->FADDR = priv->addr;
215 	}
216 }
217 
218 /* USBD EP base by e.g. EP0, EP1, ... */
numaker_usbd_ep_base(const struct device * dev,uint32_t ep_hw_idx)219 static inline USBD_EP_T *numaker_usbd_ep_base(const struct device *dev, uint32_t ep_hw_idx)
220 {
221 	const struct udc_numaker_config *config = dev->config;
222 	USBD_T *const base = config->base;
223 
224 	return base->EP + ep_hw_idx;
225 }
226 
numaker_usbd_ep_sync_udc_halt(struct numaker_usbd_ep * ep_cur,bool stalled)227 static inline void numaker_usbd_ep_sync_udc_halt(struct numaker_usbd_ep *ep_cur, bool stalled)
228 {
229 	const struct device *dev = ep_cur->dev;
230 	struct udc_ep_config *ep_cfg;
231 
232 	__ASSERT_NO_MSG(ep_cur->addr_valid);
233 	ep_cfg = udc_get_ep_cfg(dev, ep_cur->addr);
234 	ep_cfg->stat.halted = stalled;
235 }
236 
numaker_usbd_ep_set_stall(struct numaker_usbd_ep * ep_cur)237 static inline void numaker_usbd_ep_set_stall(struct numaker_usbd_ep *ep_cur)
238 {
239 	const struct device *dev = ep_cur->dev;
240 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
241 
242 	/* Set EP to stalled */
243 	ep_base->CFGP |= USBD_CFGP_SSTALL_Msk;
244 	numaker_usbd_ep_sync_udc_halt(ep_cur, true);
245 }
246 
247 /* Reset EP to unstalled and data toggle bit to 0 */
numaker_usbd_ep_clear_stall_n_data_toggle(struct numaker_usbd_ep * ep_cur)248 static inline void numaker_usbd_ep_clear_stall_n_data_toggle(struct numaker_usbd_ep *ep_cur)
249 {
250 	const struct device *dev = ep_cur->dev;
251 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
252 
253 	/* Reset EP to unstalled */
254 	ep_base->CFGP &= ~USBD_CFGP_SSTALL_Msk;
255 	numaker_usbd_ep_sync_udc_halt(ep_cur, false);
256 
257 	/* Reset EP data toggle bit to 0 */
258 	ep_base->CFG &= ~USBD_CFG_DSQSYNC_Msk;
259 }
260 
numaker_usbd_send_msg(const struct device * dev,const struct numaker_usbd_msg * msg)261 static int numaker_usbd_send_msg(const struct device *dev, const struct numaker_usbd_msg *msg)
262 {
263 	struct udc_numaker_data *priv = udc_get_private(dev);
264 	int err;
265 
266 	err = k_msgq_put(priv->msgq, msg, K_NO_WAIT);
267 	if (err < 0) {
268 		/* Try to recover by S/W reconnect */
269 		struct numaker_usbd_msg msg_reconn = {
270 			.type = NUMAKER_USBD_MSG_TYPE_SW_RECONN,
271 		};
272 
273 		LOG_ERR("Message queue overflow");
274 
275 		/* Discard all not yet received messages for error recovery below */
276 		k_msgq_purge(priv->msgq);
277 
278 		err = k_msgq_put(priv->msgq, &msg_reconn, K_NO_WAIT);
279 		if (err < 0) {
280 			LOG_ERR("Message queue overflow again");
281 		}
282 	}
283 
284 	return err;
285 }
286 
numaker_usbd_hw_setup(const struct device * dev)287 static int numaker_usbd_hw_setup(const struct device *dev)
288 {
289 	const struct udc_numaker_config *config = dev->config;
290 	USBD_T *const base = config->base;
291 	int err;
292 	struct numaker_scc_subsys scc_subsys;
293 
294 	/* Reset controller ready? */
295 	if (!device_is_ready(config->reset.dev)) {
296 		LOG_ERR("Reset controller not ready");
297 		return -ENODEV;
298 	}
299 
300 	SYS_UnlockReg();
301 
302 	/* Configure USB PHY for USBD */
303 	SYS->USBPHY = (SYS->USBPHY & ~SYS_USBPHY_USBROLE_Msk) |
304 		      (SYS_USBPHY_USBROLE_STD_USBD | SYS_USBPHY_USBEN_Msk | SYS_USBPHY_SBO_Msk);
305 
306 	/* Invoke Clock controller to enable module clock */
307 	memset(&scc_subsys, 0x00, sizeof(scc_subsys));
308 	scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC;
309 	scc_subsys.pcc.clk_modidx = config->clk_modidx;
310 	scc_subsys.pcc.clk_src = config->clk_src;
311 	scc_subsys.pcc.clk_div = config->clk_div;
312 
313 	/* Equivalent to CLK_EnableModuleClock() */
314 	err = clock_control_on(config->clkctrl_dev, (clock_control_subsys_t)&scc_subsys);
315 	if (err < 0) {
316 		goto cleanup;
317 	}
318 	/* Equivalent to CLK_SetModuleClock() */
319 	err = clock_control_configure(config->clkctrl_dev, (clock_control_subsys_t)&scc_subsys,
320 				      NULL);
321 	if (err < 0) {
322 		goto cleanup;
323 	}
324 
325 	/* Configure pinmux (NuMaker's SYS MFP) */
326 	err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
327 	if (err < 0) {
328 		goto cleanup;
329 	}
330 
331 	/* Invoke Reset controller to reset module to default state */
332 	/* Equivalent to SYS_ResetModule()
333 	 */
334 	reset_line_toggle_dt(&config->reset);
335 
336 	/* Initialize USBD engine */
337 	/* NOTE: BSP USBD driver: ATTR = 0x7D0 */
338 	base->ATTR = USBD_ATTR_BYTEM_Msk | BIT(9) | USBD_ATTR_DPPUEN_Msk | USBD_ATTR_USBEN_Msk |
339 		     BIT(6) | USBD_ATTR_PHYEN_Msk;
340 
341 	/* Set SE0 for S/W disconnect */
342 	numaker_usbd_sw_disconnect(dev);
343 
344 	/* NOTE: Ignore DT maximum-speed with USBD fixed to full-speed */
345 
346 	/* Initialize IRQ */
347 	config->irq_config_func(dev);
348 
349 cleanup:
350 
351 	SYS_LockReg();
352 
353 	return err;
354 }
355 
numaker_usbd_hw_shutdown(const struct device * dev)356 static void numaker_usbd_hw_shutdown(const struct device *dev)
357 {
358 	const struct udc_numaker_config *config = dev->config;
359 	USBD_T *const base = config->base;
360 	struct numaker_scc_subsys scc_subsys;
361 
362 	SYS_UnlockReg();
363 
364 	/* Uninitialize IRQ */
365 	config->irq_unconfig_func(dev);
366 
367 	/* Set SE0 for S/W disconnect */
368 	numaker_usbd_sw_disconnect(dev);
369 
370 	/* Disable USB PHY */
371 	base->ATTR &= ~USBD_PHY_EN;
372 
373 	/* Invoke Clock controller to disable module clock */
374 	memset(&scc_subsys, 0x00, sizeof(scc_subsys));
375 	scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC;
376 	scc_subsys.pcc.clk_modidx = config->clk_modidx;
377 
378 	/* Equivalent to CLK_DisableModuleClock() */
379 	clock_control_off(config->clkctrl_dev, (clock_control_subsys_t)&scc_subsys);
380 
381 	/* Invoke Reset controller to reset module to default state */
382 	/* Equivalent to SYS_ResetModule() */
383 	reset_line_toggle_dt(&config->reset);
384 
385 	SYS_LockReg();
386 }
387 
388 /* Interrupt top half processing for bus reset */
numaker_usbd_bus_reset_th(const struct device * dev)389 static void numaker_usbd_bus_reset_th(const struct device *dev)
390 {
391 	struct udc_numaker_data *priv = udc_get_private(dev);
392 	USBD_EP_T *ep_base;
393 
394 	for (uint32_t i = 0ul; i < priv->ep_pool_size; i++) {
395 		ep_base = numaker_usbd_ep_base(dev, EP0 + i);
396 
397 		/* Cancel EP on-going transaction */
398 		ep_base->CFGP |= USBD_CFGP_CLRRDY_Msk;
399 
400 		/* Reset EP to unstalled */
401 		ep_base->CFGP &= ~USBD_CFGP_SSTALL_Msk;
402 
403 		/* Reset EP data toggle bit to 0 */
404 		ep_base->CFG &= ~USBD_CFG_DSQSYNC_Msk;
405 
406 		/* Except EP0/EP1 kept resident for CTRL OUT/IN, disable all other EPs */
407 		if (i >= 2) {
408 			ep_base->CFG = 0;
409 		}
410 	}
411 
412 	numaker_usbd_reset_addr(dev);
413 }
414 
415 /* USBD SRAM base for DMA */
numaker_usbd_buf_base(const struct device * dev)416 static inline uint32_t numaker_usbd_buf_base(const struct device *dev)
417 {
418 	const struct udc_numaker_config *config = dev->config;
419 	USBD_T *const base = config->base;
420 
421 	return ((uint32_t)base + 0x800ul);
422 }
423 
424 /* Copy Setup packet to user buffer */
numaker_usbd_setup_copy_to_user(const struct device * dev,uint8_t * usrbuf)425 static void numaker_usbd_setup_copy_to_user(const struct device *dev, uint8_t *usrbuf)
426 {
427 	const struct udc_numaker_config *config = dev->config;
428 	USBD_T *const base = config->base;
429 	uint32_t dmabuf_addr;
430 
431 	dmabuf_addr = numaker_usbd_buf_base(dev) + (base->STBUFSEG & USBD_STBUFSEG_STBUFSEG_Msk);
432 
433 	bytecpy(usrbuf, (uint8_t *)dmabuf_addr, 8ul);
434 }
435 
436 /* Copy data to user buffer
437  *
438  * size_p holds size to copy/copied on input/output
439  */
numaker_usbd_ep_copy_to_user(struct numaker_usbd_ep * ep_cur,uint8_t * usrbuf,uint32_t * size_p,uint32_t * rmn_p)440 static void numaker_usbd_ep_copy_to_user(struct numaker_usbd_ep *ep_cur, uint8_t *usrbuf,
441 					 uint32_t *size_p, uint32_t *rmn_p)
442 {
443 	const struct device *dev = ep_cur->dev;
444 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
445 	uint32_t dmabuf_addr;
446 	uint32_t data_rmn;
447 
448 	__ASSERT_NO_MSG(size_p);
449 	__ASSERT_NO_MSG(ep_cur->dmabuf_valid);
450 
451 	dmabuf_addr = numaker_usbd_buf_base(dev) + ep_base->BUFSEG;
452 
453 	/* NOTE: See comment on mxpld_ctrlout for why make one copy of CTRL OUT's MXPLD */
454 	if (ep_cur->addr == USB_CONTROL_EP_OUT) {
455 		data_rmn = ep_cur->mxpld_ctrlout;
456 	} else {
457 		data_rmn = ep_base->MXPLD;
458 	}
459 
460 	*size_p = MIN(*size_p, data_rmn);
461 
462 	bytecpy(usrbuf, (uint8_t *)dmabuf_addr, *size_p);
463 	data_rmn -= *size_p;
464 
465 	if (rmn_p) {
466 		*rmn_p = data_rmn;
467 	}
468 }
469 
470 /* Copy data from user buffer
471  *
472  * size_p holds size to copy/copied on input/output
473  */
numaker_usbd_ep_copy_from_user(struct numaker_usbd_ep * ep_cur,const uint8_t * usrbuf,uint32_t * size_p)474 static void numaker_usbd_ep_copy_from_user(struct numaker_usbd_ep *ep_cur, const uint8_t *usrbuf,
475 					   uint32_t *size_p)
476 {
477 	const struct device *dev = ep_cur->dev;
478 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
479 	uint32_t dmabuf_addr;
480 
481 	__ASSERT_NO_MSG(size_p);
482 	__ASSERT_NO_MSG(ep_cur->dmabuf_valid);
483 	__ASSERT_NO_MSG(ep_cur->mps_valid);
484 	__ASSERT_NO_MSG(ep_cur->mps <= ep_cur->dmabuf_size);
485 
486 	dmabuf_addr = numaker_usbd_buf_base(dev) + ep_base->BUFSEG;
487 
488 	*size_p = MIN(*size_p, ep_cur->mps);
489 
490 	bytecpy((uint8_t *)dmabuf_addr, (uint8_t *)usrbuf, *size_p);
491 }
492 
numaker_usbd_ep_config_dmabuf(struct numaker_usbd_ep * ep_cur,uint32_t dmabuf_base,uint32_t dmabuf_size)493 static void numaker_usbd_ep_config_dmabuf(struct numaker_usbd_ep *ep_cur, uint32_t dmabuf_base,
494 					  uint32_t dmabuf_size)
495 {
496 	const struct device *dev = ep_cur->dev;
497 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
498 
499 	ep_base->BUFSEG = dmabuf_base;
500 
501 	ep_cur->dmabuf_valid = true;
502 	ep_cur->dmabuf_base = dmabuf_base;
503 	ep_cur->dmabuf_size = dmabuf_size;
504 }
505 
numaker_usbd_ep_abort(struct numaker_usbd_ep * ep_cur)506 static void numaker_usbd_ep_abort(struct numaker_usbd_ep *ep_cur)
507 {
508 	const struct device *dev = ep_cur->dev;
509 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
510 
511 	/* Abort EP on-going transaction */
512 	ep_base->CFGP |= USBD_CFGP_CLRRDY_Msk;
513 
514 	if (ep_cur->addr_valid) {
515 		udc_ep_set_busy(dev, ep_cur->addr, false);
516 	}
517 }
518 
519 /* Configure EP major common parts */
numaker_usbd_ep_config_major(struct numaker_usbd_ep * ep_cur,struct udc_ep_config * const ep_cfg)520 static void numaker_usbd_ep_config_major(struct numaker_usbd_ep *ep_cur,
521 					 struct udc_ep_config *const ep_cfg)
522 {
523 	const struct device *dev = ep_cur->dev;
524 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
525 
526 	ep_cur->mps_valid = true;
527 	ep_cur->mps = ep_cfg->mps;
528 
529 	/* Configure EP transfer type, DATA0/1 toggle, direction, number, etc. */
530 	ep_cur->ep_hw_cfg = 0;
531 
532 	/* Clear STALL Response in Setup stage */
533 	if ((ep_cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) == USB_EP_TYPE_CONTROL) {
534 		ep_cur->ep_hw_cfg |= USBD_CFG_CSTALL;
535 	}
536 
537 	/* Default to DATA0 */
538 	ep_cur->ep_hw_cfg &= ~USBD_CFG_DSQSYNC_Msk;
539 
540 	/* Endpoint IN/OUT, though, default to disabled */
541 	ep_cur->ep_hw_cfg |= USBD_CFG_EPMODE_DISABLE;
542 
543 	/* Isochronous or not */
544 	if ((ep_cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) == USB_EP_TYPE_ISO) {
545 		ep_cur->ep_hw_cfg |= USBD_CFG_TYPE_ISO;
546 	}
547 
548 	/* Endpoint index */
549 	ep_cur->ep_hw_cfg |=
550 		(USB_EP_GET_IDX(ep_cfg->addr) << USBD_CFG_EPNUM_Pos) & USBD_CFG_EPNUM_Msk;
551 
552 	ep_base->CFG = ep_cur->ep_hw_cfg;
553 }
554 
numaker_usbd_ep_enable(struct numaker_usbd_ep * ep_cur)555 static void numaker_usbd_ep_enable(struct numaker_usbd_ep *ep_cur)
556 {
557 	const struct device *dev = ep_cur->dev;
558 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
559 
560 	/* For safe, EP (re-)enable from clean state */
561 	numaker_usbd_ep_abort(ep_cur);
562 	numaker_usbd_ep_clear_stall_n_data_toggle(ep_cur);
563 
564 	/* Enable EP to IN/OUT */
565 	ep_cur->ep_hw_cfg &= ~USBD_CFG_STATE_Msk;
566 	if (USB_EP_DIR_IS_IN(ep_cur->addr)) {
567 		ep_cur->ep_hw_cfg |= USBD_CFG_EPMODE_IN;
568 	} else {
569 		ep_cur->ep_hw_cfg |= USBD_CFG_EPMODE_OUT;
570 	}
571 
572 	ep_base->CFG = ep_cur->ep_hw_cfg;
573 
574 	/* For USBD, no separate EP interrupt control */
575 }
576 
numaker_usbd_ep_disable(struct numaker_usbd_ep * ep_cur)577 static void numaker_usbd_ep_disable(struct numaker_usbd_ep *ep_cur)
578 {
579 	const struct device *dev = ep_cur->dev;
580 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
581 
582 	/* For USBD, no separate EP interrupt control */
583 
584 	/* Disable EP */
585 	ep_cur->ep_hw_cfg = (ep_cur->ep_hw_cfg & ~USBD_CFG_STATE_Msk) | USBD_CFG_EPMODE_DISABLE;
586 	ep_base->CFG = ep_cur->ep_hw_cfg;
587 }
588 
589 /* Start EP data transaction */
udc_numaker_ep_trigger(struct numaker_usbd_ep * ep_cur,uint32_t len)590 static void udc_numaker_ep_trigger(struct numaker_usbd_ep *ep_cur, uint32_t len)
591 {
592 	const struct device *dev = ep_cur->dev;
593 	USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_cur->ep_hw_idx);
594 
595 	if (ep_cur->addr_valid) {
596 		udc_ep_set_busy(dev, ep_cur->addr, true);
597 	}
598 
599 	ep_base->MXPLD = len;
600 }
601 
numaker_usbd_ep_mgmt_alloc_ep(const struct device * dev)602 static struct numaker_usbd_ep *numaker_usbd_ep_mgmt_alloc_ep(const struct device *dev)
603 {
604 	struct udc_numaker_data *priv = udc_get_private(dev);
605 	struct numaker_usbd_ep_mgmt *ep_mgmt = &priv->ep_mgmt;
606 	struct numaker_usbd_ep *ep_cur = NULL;
607 
608 	if (ep_mgmt->ep_idx < priv->ep_pool_size) {
609 		ep_cur = priv->ep_pool + ep_mgmt->ep_idx;
610 		ep_mgmt->ep_idx++;
611 
612 		__ASSERT_NO_MSG(!ep_cur->valid);
613 
614 		/* Indicate this EP H/W context is allocated */
615 		ep_cur->valid = true;
616 	}
617 
618 	return ep_cur;
619 }
620 
621 /* Allocate DMA buffer
622  *
623  * Return -ENOMEM  on OOM error, or 0 on success with DMA buffer base/size (rounded up) allocated
624  */
numaker_usbd_ep_mgmt_alloc_dmabuf(const struct device * dev,uint32_t size,uint32_t * dmabuf_base_p,uint32_t * dmabuf_size_p)625 static int numaker_usbd_ep_mgmt_alloc_dmabuf(const struct device *dev, uint32_t size,
626 					     uint32_t *dmabuf_base_p, uint32_t *dmabuf_size_p)
627 {
628 	const struct udc_numaker_config *config = dev->config;
629 	struct udc_numaker_data *priv = udc_get_private(dev);
630 	struct numaker_usbd_ep_mgmt *ep_mgmt = &priv->ep_mgmt;
631 
632 	__ASSERT_NO_MSG(dmabuf_base_p);
633 	__ASSERT_NO_MSG(dmabuf_size_p);
634 
635 	/* Required to be 8-byte aligned */
636 	size = ROUND_UP(size, 8);
637 
638 	ep_mgmt->dmabuf_pos += size;
639 	if (ep_mgmt->dmabuf_pos > config->dmabuf_size) {
640 		ep_mgmt->dmabuf_pos -= size;
641 		return -ENOMEM;
642 	}
643 
644 	*dmabuf_base_p = ep_mgmt->dmabuf_pos - size;
645 	*dmabuf_size_p = size;
646 	return 0;
647 }
648 
649 /* Initialize all EP H/W contexts */
numaker_usbd_ep_mgmt_init(const struct device * dev)650 static void numaker_usbd_ep_mgmt_init(const struct device *dev)
651 {
652 	const struct udc_numaker_config *config = dev->config;
653 	struct udc_numaker_data *priv = udc_get_private(dev);
654 	USBD_T *const base = config->base;
655 	struct numaker_usbd_ep_mgmt *ep_mgmt = &priv->ep_mgmt;
656 
657 	struct numaker_usbd_ep *ep_cur;
658 	struct numaker_usbd_ep *ep_end;
659 
660 	/* Initialize all fields to zero for clean state */
661 	memset(ep_mgmt, 0x00, sizeof(*ep_mgmt));
662 
663 	ep_cur = priv->ep_pool;
664 	ep_end = priv->ep_pool + priv->ep_pool_size;
665 
666 	/* Initialize all EP H/W contexts */
667 	for (; ep_cur != ep_end; ep_cur++) {
668 		/* Zero-initialize */
669 		memset(ep_cur, 0x00, sizeof(*ep_cur));
670 
671 		/* Pointer to the containing device */
672 		ep_cur->dev = dev;
673 
674 		/* BSP USBD driver EP handle */
675 		ep_cur->ep_hw_idx = EP0 + (ep_cur - priv->ep_pool);
676 	}
677 
678 	/* Reserve 1st/2nd EP H/W contexts (BSP USBD driver EP0/EP1) for CTRL OUT/IN */
679 	ep_mgmt->ep_idx = 2;
680 
681 	/* Reserve DMA buffer for Setup/CTRL OUT/CTRL IN, starting from 0 */
682 	ep_mgmt->dmabuf_pos = 0;
683 
684 	/* Configure DMA buffer for Setup packet */
685 	base->STBUFSEG = ep_mgmt->dmabuf_pos;
686 	ep_mgmt->dmabuf_pos += NUMAKER_USBD_DMABUF_SIZE_SETUP;
687 
688 	/* Reserve 1st EP H/W context (BSP USBD driver EP0) for CTRL OUT */
689 	ep_cur = priv->ep_pool + 0;
690 	ep_cur->valid = true;
691 	ep_cur->addr_valid = true;
692 	ep_cur->addr = USB_EP_GET_ADDR(0, USB_EP_DIR_OUT);
693 	numaker_usbd_ep_config_dmabuf(ep_cur, ep_mgmt->dmabuf_pos,
694 				      NUMAKER_USBD_DMABUF_SIZE_CTRLOUT);
695 	ep_mgmt->dmabuf_pos += NUMAKER_USBD_DMABUF_SIZE_CTRLOUT;
696 	ep_cur->mps_valid = true;
697 	ep_cur->mps = NUMAKER_USBD_DMABUF_SIZE_CTRLOUT;
698 
699 	/* Reserve 2nd EP H/W context (BSP USBD driver EP1) for CTRL IN */
700 	ep_cur = priv->ep_pool + 1;
701 	ep_cur->valid = true;
702 	ep_cur->addr_valid = true;
703 	ep_cur->addr = USB_EP_GET_ADDR(0, USB_EP_DIR_IN);
704 	numaker_usbd_ep_config_dmabuf(ep_cur, ep_mgmt->dmabuf_pos, NUMAKER_USBD_DMABUF_SIZE_CTRLIN);
705 	ep_mgmt->dmabuf_pos += NUMAKER_USBD_DMABUF_SIZE_CTRLIN;
706 	ep_cur->mps_valid = true;
707 	ep_cur->mps = NUMAKER_USBD_DMABUF_SIZE_CTRLIN;
708 }
709 
710 /* Find EP H/W context by EP address */
numaker_usbd_ep_mgmt_find_ep(const struct device * dev,const uint8_t ep)711 static struct numaker_usbd_ep *numaker_usbd_ep_mgmt_find_ep(const struct device *dev,
712 							    const uint8_t ep)
713 {
714 	struct udc_numaker_data *priv = udc_get_private(dev);
715 	struct numaker_usbd_ep *ep_cur = priv->ep_pool;
716 	struct numaker_usbd_ep *ep_end = priv->ep_pool + priv->ep_pool_size;
717 
718 	for (; ep_cur != ep_end; ep_cur++) {
719 		if (!ep_cur->valid) {
720 			continue;
721 		}
722 
723 		if (!ep_cur->addr_valid) {
724 			continue;
725 		}
726 
727 		if (ep == ep_cur->addr) {
728 			return ep_cur;
729 		}
730 	}
731 
732 	return NULL;
733 }
734 
735 /* Bind EP H/W context to EP address */
numaker_usbd_ep_mgmt_bind_ep(const struct device * dev,const uint8_t ep)736 static struct numaker_usbd_ep *numaker_usbd_ep_mgmt_bind_ep(const struct device *dev,
737 							    const uint8_t ep)
738 {
739 	struct numaker_usbd_ep *ep_cur = numaker_usbd_ep_mgmt_find_ep(dev, ep);
740 
741 	if (!ep_cur) {
742 		ep_cur = numaker_usbd_ep_mgmt_alloc_ep(dev);
743 
744 		if (!ep_cur) {
745 			return NULL;
746 		}
747 
748 		/* Bind EP H/W context to EP address */
749 		ep_cur->addr = ep;
750 		ep_cur->addr_valid = true;
751 	}
752 
753 	/* Assert EP H/W context bound to EP address */
754 	__ASSERT_NO_MSG(ep_cur->valid);
755 	__ASSERT_NO_MSG(ep_cur->addr_valid);
756 	__ASSERT_NO_MSG(ep_cur->addr == ep);
757 
758 	return ep_cur;
759 }
760 
numaker_usbd_xfer_out(const struct device * dev,uint8_t ep,bool strict)761 static int numaker_usbd_xfer_out(const struct device *dev, uint8_t ep, bool strict)
762 {
763 	struct net_buf *buf;
764 	struct numaker_usbd_ep *ep_cur;
765 
766 	if (!USB_EP_DIR_IS_OUT(ep)) {
767 		LOG_ERR("Invalid EP address 0x%02x for data out", ep);
768 		return -EINVAL;
769 	}
770 
771 	if (udc_ep_is_busy(dev, ep)) {
772 		if (strict) {
773 			LOG_ERR("EP 0x%02x busy", ep);
774 			return -EAGAIN;
775 		}
776 
777 		return 0;
778 	}
779 
780 	buf = udc_buf_peek(dev, ep);
781 	if (buf == NULL) {
782 		if (strict) {
783 			LOG_ERR("No buffer queued for EP 0x%02x", ep);
784 			return -ENODATA;
785 		}
786 
787 		return 0;
788 	}
789 
790 	/* Bind EP H/W context to EP address */
791 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep);
792 	if (!ep_cur) {
793 		LOG_ERR("Bind EP H/W context: ep=0x%02x", ep);
794 		return -ENODEV;
795 	}
796 
797 	udc_numaker_ep_trigger(ep_cur, ep_cur->mps);
798 
799 	return 0;
800 }
801 
numaker_usbd_xfer_in(const struct device * dev,uint8_t ep,bool strict)802 static int numaker_usbd_xfer_in(const struct device *dev, uint8_t ep, bool strict)
803 {
804 	struct net_buf *buf;
805 	struct numaker_usbd_ep *ep_cur;
806 	uint32_t data_len;
807 
808 	if (!USB_EP_DIR_IS_IN(ep)) {
809 		LOG_ERR("Invalid EP address 0x%02x for data in", ep);
810 		return -EINVAL;
811 	}
812 
813 	if (udc_ep_is_busy(dev, ep)) {
814 		if (strict) {
815 			LOG_ERR("EP 0x%02x busy", ep);
816 			return -EAGAIN;
817 		}
818 
819 		return 0;
820 	}
821 
822 	buf = udc_buf_peek(dev, ep);
823 	if (buf == NULL) {
824 		if (strict) {
825 			LOG_ERR("No buffer queued for EP 0x%02x", ep);
826 			return -ENODATA;
827 		}
828 
829 		return 0;
830 	}
831 
832 	/* Bind EP H/W context to EP address */
833 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep);
834 	if (!ep_cur) {
835 		LOG_ERR("ep=0x%02x", ep);
836 		return -ENODEV;
837 	}
838 
839 	data_len = buf->len;
840 	if (data_len) {
841 		numaker_usbd_ep_copy_from_user(ep_cur, buf->data, &data_len);
842 		net_buf_pull(buf, data_len);
843 	} else if (udc_ep_buf_has_zlp(buf)) {
844 		/* zlp, send exactly once */
845 		udc_ep_buf_clear_zlp(buf);
846 	} else {
847 		/* initially empty net_buf, send exactly once */
848 	}
849 
850 	udc_numaker_ep_trigger(ep_cur, data_len);
851 
852 	return 0;
853 }
854 
numaker_usbd_ctrl_feed_dout(const struct device * dev,const size_t length)855 static int numaker_usbd_ctrl_feed_dout(const struct device *dev, const size_t length)
856 {
857 	struct udc_numaker_data *priv = udc_get_private(dev);
858 	struct udc_ep_config *ep_cfg;
859 	struct net_buf *buf;
860 
861 	ep_cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT);
862 	if (ep_cfg == NULL) {
863 		LOG_ERR("Bind udc_ep_config: ep=0x%02x", USB_CONTROL_EP_OUT);
864 		return -ENODEV;
865 	}
866 
867 	buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, length);
868 	if (buf == NULL) {
869 		LOG_ERR("Allocate net_buf: ep=0x%02x", USB_CONTROL_EP_OUT);
870 		return -ENOMEM;
871 	}
872 	priv->ctrlout_tailroom = length;
873 
874 	k_fifo_put(&ep_cfg->fifo, buf);
875 
876 	return numaker_usbd_xfer_out(dev, ep_cfg->addr, true);
877 }
878 
879 /* Message handler for Setup transaction completed */
numaker_usbd_msg_handle_setup(const struct device * dev,struct numaker_usbd_msg * msg)880 static int numaker_usbd_msg_handle_setup(const struct device *dev, struct numaker_usbd_msg *msg)
881 {
882 	int err;
883 	uint8_t ep;
884 	struct numaker_usbd_ep *ep_cur;
885 	struct net_buf *buf;
886 	uint8_t *data_ptr;
887 
888 	__ASSERT_NO_MSG(msg->type == NUMAKER_USBD_MSG_TYPE_SETUP);
889 
890 	ep = USB_CONTROL_EP_OUT;
891 
892 	/* Bind EP H/W context to EP address */
893 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep);
894 	if (!ep_cur) {
895 		LOG_ERR("Bind EP H/W context: ep=0x%02x", ep);
896 		return -ENODEV;
897 	}
898 
899 	/* We should have reserved 1st/2nd EP H/W contexts for CTRL OUT/IN */
900 	__ASSERT_NO_MSG(ep_cur->addr == USB_CONTROL_EP_OUT);
901 	__ASSERT_NO_MSG((ep_cur + 1)->addr == USB_CONTROL_EP_IN);
902 
903 	/* Abort previous CTRL OUT/IN */
904 	numaker_usbd_ep_abort(ep_cur);
905 	numaker_usbd_ep_abort(ep_cur + 1);
906 
907 	/* CTRL OUT/IN reset to unstalled by H/W on receive of Setup packet */
908 	numaker_usbd_ep_sync_udc_halt(ep_cur, false);
909 	numaker_usbd_ep_sync_udc_halt(ep_cur + 1, false);
910 
911 	buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, 8);
912 	if (buf == NULL) {
913 		LOG_ERR("Failed to allocate for Setup");
914 		return -ENOMEM;
915 	}
916 
917 	udc_ep_buf_set_setup(buf);
918 	data_ptr = net_buf_tail(buf);
919 	numaker_usbd_setup_copy_to_user(dev, data_ptr);
920 	net_buf_add(buf, 8);
921 
922 	/* Update to next stage of CTRL transfer */
923 	udc_ctrl_update_stage(dev, buf);
924 
925 	if (udc_ctrl_stage_is_data_out(dev)) {
926 		/*  Allocate and feed buffer for DATA OUT stage */
927 		err = numaker_usbd_ctrl_feed_dout(dev, udc_data_stage_length(buf));
928 		if (err == -ENOMEM) {
929 			err = udc_submit_ep_event(dev, buf, err);
930 		}
931 	} else if (udc_ctrl_stage_is_data_in(dev)) {
932 		err = udc_ctrl_submit_s_in_status(dev);
933 	} else {
934 		err = udc_ctrl_submit_s_status(dev);
935 	}
936 
937 	return err;
938 }
939 
940 /* Message handler for DATA OUT transaction completed */
numaker_usbd_msg_handle_out(const struct device * dev,struct numaker_usbd_msg * msg)941 static int numaker_usbd_msg_handle_out(const struct device *dev, struct numaker_usbd_msg *msg)
942 {
943 	struct udc_numaker_data *priv = udc_get_private(dev);
944 	int err;
945 	uint8_t ep;
946 	struct numaker_usbd_ep *ep_cur;
947 	struct net_buf *buf;
948 	uint8_t *data_ptr;
949 	uint32_t data_len;
950 	uint32_t data_rmn;
951 
952 	__ASSERT_NO_MSG(msg->type == NUMAKER_USBD_MSG_TYPE_OUT);
953 
954 	ep = msg->out.ep;
955 
956 	udc_ep_set_busy(dev, ep, false);
957 
958 	/* Bind EP H/W context to EP address */
959 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep);
960 	if (!ep_cur) {
961 		LOG_ERR("Bind EP H/W context: ep=0x%02x", ep);
962 		return -ENODEV;
963 	}
964 
965 	buf = udc_buf_peek(dev, ep);
966 	if (buf == NULL) {
967 		LOG_ERR("No buffer queued for ep=0x%02x", ep);
968 		return -ENODATA;
969 	}
970 
971 	if (ep == USB_CONTROL_EP_OUT) {
972 		__ASSERT_NO_MSG(net_buf_tailroom(buf) >= priv->ctrlout_tailroom);
973 		data_len = priv->ctrlout_tailroom;
974 	} else {
975 		data_len = net_buf_tailroom(buf);
976 	}
977 	data_ptr = net_buf_tail(buf);
978 	numaker_usbd_ep_copy_to_user(ep_cur, data_ptr, &data_len, &data_rmn);
979 	net_buf_add(buf, data_len);
980 	if (ep == USB_CONTROL_EP_OUT) {
981 		__ASSERT_NO_MSG(priv->ctrlout_tailroom >= data_len);
982 		priv->ctrlout_tailroom -= data_len;
983 	}
984 
985 	if (data_rmn) {
986 		LOG_ERR("Buffer queued for ep=0x%02x cannot accommodate packet", ep);
987 		return -ENOBUFS;
988 	}
989 
990 	/* CTRL DATA OUT/STATUS OUT stage completed */
991 	if (ep == USB_CONTROL_EP_OUT && priv->ctrlout_tailroom != 0) {
992 		goto next_xfer;
993 	}
994 
995 	/* To submit the peeked buffer */
996 	udc_buf_get(dev, ep);
997 
998 	if (ep == USB_CONTROL_EP_OUT) {
999 		if (udc_ctrl_stage_is_status_out(dev)) {
1000 			/* s-in-status finished */
1001 			err = udc_ctrl_submit_status(dev, buf);
1002 			if (err < 0) {
1003 				LOG_ERR("udc_ctrl_submit_status failed for s-in-status: %d", err);
1004 				return err;
1005 			}
1006 		}
1007 
1008 		/* Update to next stage of CTRL transfer */
1009 		udc_ctrl_update_stage(dev, buf);
1010 
1011 		if (udc_ctrl_stage_is_status_in(dev)) {
1012 			err = udc_ctrl_submit_s_out_status(dev, buf);
1013 			if (err < 0) {
1014 				LOG_ERR("udc_ctrl_submit_s_out_status failed for s-out-status: %d",
1015 					err);
1016 				return err;
1017 			}
1018 		}
1019 	} else {
1020 		err = udc_submit_ep_event(dev, buf, 0);
1021 		if (err < 0) {
1022 			LOG_ERR("udc_submit_ep_event failed for ep=0x%02x: %d", ep, err);
1023 			return err;
1024 		}
1025 	}
1026 
1027 next_xfer:
1028 	/* Continue with next DATA OUT transaction on request */
1029 	numaker_usbd_xfer_out(dev, ep, false);
1030 
1031 	return 0;
1032 }
1033 
1034 /* Message handler for DATA IN transaction completed */
numaker_usbd_msg_handle_in(const struct device * dev,struct numaker_usbd_msg * msg)1035 static int numaker_usbd_msg_handle_in(const struct device *dev, struct numaker_usbd_msg *msg)
1036 {
1037 	int err;
1038 	uint8_t ep;
1039 	struct numaker_usbd_ep *ep_cur;
1040 	struct net_buf *buf;
1041 
1042 	__ASSERT_NO_MSG(msg->type == NUMAKER_USBD_MSG_TYPE_IN);
1043 
1044 	ep = msg->in.ep;
1045 
1046 	udc_ep_set_busy(dev, ep, false);
1047 
1048 	/* Bind EP H/W context to EP address */
1049 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep);
1050 	if (!ep_cur) {
1051 		LOG_ERR("Bind EP H/W context: ep=0x%02x", ep);
1052 		return -ENODEV;
1053 	}
1054 
1055 	buf = udc_buf_peek(dev, ep);
1056 	if (buf == NULL) {
1057 		/* No DATA IN request */
1058 		return 0;
1059 	}
1060 
1061 	if (buf->len || udc_ep_buf_has_zlp(buf)) {
1062 		goto xfer_next;
1063 	}
1064 
1065 	/* To submit the peeked buffer */
1066 	udc_buf_get(dev, ep);
1067 
1068 	if (ep == USB_CONTROL_EP_IN) {
1069 		if (udc_ctrl_stage_is_status_in(dev) || udc_ctrl_stage_is_no_data(dev)) {
1070 			/* s-out-status/s-status finished */
1071 			err = udc_ctrl_submit_status(dev, buf);
1072 			if (err < 0) {
1073 				LOG_ERR("udc_ctrl_submit_status failed for s-out-status/s-status: "
1074 					"%d",
1075 					err);
1076 				return err;
1077 			}
1078 		}
1079 
1080 		/* Update to next stage of CTRL transfer */
1081 		udc_ctrl_update_stage(dev, buf);
1082 
1083 		if (udc_ctrl_stage_is_status_out(dev)) {
1084 			/* DATA IN stage finished, release buffer */
1085 			net_buf_unref(buf);
1086 
1087 			/*  Allocate and feed buffer for STATUS OUT stage */
1088 			err = numaker_usbd_ctrl_feed_dout(dev, 0);
1089 			if (err < 0) {
1090 				LOG_ERR("ctrl_feed_dout failed for status out: %d", err);
1091 				return err;
1092 			}
1093 		}
1094 	} else {
1095 		err = udc_submit_ep_event(dev, buf, 0);
1096 		if (err < 0) {
1097 			LOG_ERR("udc_submit_ep_event failed for ep=0x%02x: %d", ep, err);
1098 			return err;
1099 		}
1100 	}
1101 
1102 xfer_next:
1103 	/* Continue with next DATA IN transaction on request */
1104 	numaker_usbd_xfer_in(dev, ep, false);
1105 
1106 	return 0;
1107 }
1108 
1109 /* Message handler for queued transfer re-activated */
numaker_usbd_msg_handle_xfer(const struct device * dev,struct numaker_usbd_msg * msg)1110 static int numaker_usbd_msg_handle_xfer(const struct device *dev, struct numaker_usbd_msg *msg)
1111 {
1112 	uint8_t ep;
1113 
1114 	__ASSERT_NO_MSG(msg->type == NUMAKER_USBD_MSG_TYPE_XFER);
1115 
1116 	ep = msg->xfer.ep;
1117 
1118 	if (USB_EP_DIR_IS_OUT(ep)) {
1119 		numaker_usbd_xfer_out(dev, ep, false);
1120 	} else {
1121 		numaker_usbd_xfer_in(dev, ep, false);
1122 	}
1123 
1124 	return 0;
1125 }
1126 
1127 /* Message handler for S/W reconnect */
numaker_usbd_msg_handle_sw_reconn(const struct device * dev,struct numaker_usbd_msg * msg)1128 static int numaker_usbd_msg_handle_sw_reconn(const struct device *dev, struct numaker_usbd_msg *msg)
1129 {
1130 	__ASSERT_NO_MSG(msg->type == NUMAKER_USBD_MSG_TYPE_SW_RECONN);
1131 
1132 	/* S/W reconnect for error recovery */
1133 	numaker_usbd_sw_reconnect(dev);
1134 
1135 	return 0;
1136 }
1137 
numaker_usbd_msg_handler(const struct device * dev)1138 static void numaker_usbd_msg_handler(const struct device *dev)
1139 {
1140 	struct udc_numaker_data *priv = udc_get_private(dev);
1141 	int err;
1142 	struct numaker_usbd_msg msg;
1143 
1144 	while (true) {
1145 		if (k_msgq_get(priv->msgq, &msg, K_FOREVER)) {
1146 			continue;
1147 		}
1148 
1149 		err = 0;
1150 
1151 		udc_lock_internal(dev, K_FOREVER);
1152 
1153 		switch (msg.type) {
1154 		case NUMAKER_USBD_MSG_TYPE_SETUP:
1155 			err = numaker_usbd_msg_handle_setup(dev, &msg);
1156 			break;
1157 
1158 		case NUMAKER_USBD_MSG_TYPE_OUT:
1159 			err = numaker_usbd_msg_handle_out(dev, &msg);
1160 			break;
1161 
1162 		case NUMAKER_USBD_MSG_TYPE_IN:
1163 			err = numaker_usbd_msg_handle_in(dev, &msg);
1164 			break;
1165 
1166 		case NUMAKER_USBD_MSG_TYPE_XFER:
1167 			err = numaker_usbd_msg_handle_xfer(dev, &msg);
1168 			break;
1169 
1170 		case NUMAKER_USBD_MSG_TYPE_SW_RECONN:
1171 			err = numaker_usbd_msg_handle_sw_reconn(dev, &msg);
1172 			break;
1173 
1174 		default:
1175 			__ASSERT_NO_MSG(false);
1176 		}
1177 
1178 		udc_unlock_internal(dev);
1179 
1180 		if (err) {
1181 			udc_submit_event(dev, UDC_EVT_ERROR, err);
1182 		}
1183 	}
1184 }
1185 
numaker_udbd_isr(const struct device * dev)1186 static void numaker_udbd_isr(const struct device *dev)
1187 {
1188 	const struct udc_numaker_config *config = dev->config;
1189 	struct udc_numaker_data *priv = udc_get_private(dev);
1190 	USBD_T *const base = config->base;
1191 
1192 	struct numaker_usbd_msg msg = {0};
1193 
1194 	uint32_t volatile usbd_intsts = base->INTSTS;
1195 	uint32_t volatile usbd_bus_state = base->ATTR;
1196 
1197 	/* USB plug-in/unplug */
1198 	if (usbd_intsts & USBD_INTSTS_FLDET) {
1199 		/* Floating detect */
1200 		base->INTSTS = USBD_INTSTS_FLDET;
1201 
1202 		if (base->VBUSDET & USBD_VBUSDET_VBUSDET_Msk) {
1203 			/* USB plug-in */
1204 
1205 			/* Enable back USB/PHY */
1206 			base->ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk;
1207 
1208 			/* UDC stack would handle bottom-half processing */
1209 			udc_submit_event(dev, UDC_EVT_VBUS_READY, 0);
1210 
1211 			LOG_DBG("USB plug-in");
1212 		} else {
1213 			/* USB unplug */
1214 
1215 			/* Disable USB */
1216 			base->ATTR &= ~USBD_USB_EN;
1217 
1218 			/* UDC stack would handle bottom-half processing */
1219 			udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0);
1220 
1221 			LOG_DBG("USB unplug");
1222 		}
1223 	}
1224 
1225 	/* USB wake-up */
1226 	if (usbd_intsts & USBD_INTSTS_WAKEUP) {
1227 		/* Clear event flag */
1228 		base->INTSTS = USBD_INTSTS_WAKEUP;
1229 
1230 		LOG_DBG("USB wake-up");
1231 	}
1232 
1233 	/* USB reset/suspend/resume */
1234 	if (usbd_intsts & USBD_INTSTS_BUS) {
1235 		/* Clear event flag */
1236 		base->INTSTS = USBD_INTSTS_BUS;
1237 
1238 		if (usbd_bus_state & USBD_STATE_USBRST) {
1239 			/* Bus reset */
1240 
1241 			/* Enable back USB/PHY */
1242 			base->ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk;
1243 
1244 			/* Bus reset top half */
1245 			numaker_usbd_bus_reset_th(dev);
1246 
1247 			/* UDC stack would handle bottom-half processing,
1248 			 * including reset device address (udc_set_address),
1249 			 * un-configure device (udc_ep_disable), etc.
1250 			 */
1251 			udc_submit_event(dev, UDC_EVT_RESET, 0);
1252 
1253 			LOG_DBG("USB reset");
1254 		}
1255 		if (usbd_bus_state & USBD_STATE_SUSPEND) {
1256 			/* Enable USB but disable PHY */
1257 			base->ATTR &= ~USBD_PHY_EN;
1258 
1259 			/* UDC stack would handle bottom-half processing */
1260 			udc_submit_event(dev, UDC_EVT_SUSPEND, 0);
1261 
1262 			LOG_DBG("USB suspend");
1263 		}
1264 		if (usbd_bus_state & USBD_STATE_RESUME) {
1265 			/* Enable back USB/PHY */
1266 			base->ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk;
1267 
1268 			/* UDC stack would handle bottom-half processing */
1269 			udc_submit_event(dev, UDC_EVT_RESUME, 0);
1270 
1271 			LOG_DBG("USB resume");
1272 		}
1273 	}
1274 
1275 	/* USB SOF */
1276 	if (usbd_intsts & USBD_INTSTS_SOFIF_Msk) {
1277 		/* Clear event flag */
1278 		base->INTSTS = USBD_INTSTS_SOFIF_Msk;
1279 
1280 		/* UDC stack would handle bottom-half processing */
1281 		udc_submit_event(dev, UDC_EVT_SOF, 0);
1282 	}
1283 
1284 	/* USB Setup/EP */
1285 	if (usbd_intsts & USBD_INTSTS_USB) {
1286 		uint32_t epintsts;
1287 
1288 		/* Setup event */
1289 		if (usbd_intsts & USBD_INTSTS_SETUP) {
1290 			USBD_EP_T *ep0_base = numaker_usbd_ep_base(dev, EP0);
1291 			USBD_EP_T *ep1_base = numaker_usbd_ep_base(dev, EP1);
1292 
1293 			/* Clear event flag */
1294 			base->INTSTS = USBD_INTSTS_SETUP;
1295 
1296 			/* Clear the data IN/OUT ready flag of control endpoints */
1297 			ep0_base->CFGP |= USBD_CFGP_CLRRDY_Msk;
1298 			ep1_base->CFGP |= USBD_CFGP_CLRRDY_Msk;
1299 
1300 			/* By USB spec, following transactions, regardless of Data/Status stage,
1301 			 * will always be DATA1
1302 			 */
1303 			ep0_base->CFG |= USBD_CFG_DSQSYNC_Msk;
1304 			ep1_base->CFG |= USBD_CFG_DSQSYNC_Msk;
1305 
1306 			/* Message for bottom-half processing */
1307 			/* NOTE: In Zephyr USB device stack, Setup packet is passed via
1308 			 * CTRL OUT EP
1309 			 */
1310 			msg.type = NUMAKER_USBD_MSG_TYPE_SETUP;
1311 			numaker_usbd_setup_copy_to_user(dev, msg.setup.packet);
1312 			numaker_usbd_send_msg(dev, &msg);
1313 		}
1314 
1315 		/* EP events */
1316 		epintsts = base->EPINTSTS;
1317 
1318 		base->EPINTSTS = epintsts;
1319 
1320 		while (epintsts) {
1321 			uint32_t ep_hw_idx = u32_count_trailing_zeros(epintsts);
1322 			USBD_EP_T *ep_base = numaker_usbd_ep_base(dev, ep_hw_idx);
1323 			uint8_t ep_dir;
1324 			uint8_t ep_idx;
1325 			uint8_t ep;
1326 
1327 			/* We don't enable INNAKEN interrupt, so as long as EP event occurs,
1328 			 * we can just regard one data transaction has completed (ACK for
1329 			 * CTRL/BULK/INT or no-ACK for Iso), that is, no need to check EPSTS0,
1330 			 * EPSTS1, etc.
1331 			 */
1332 
1333 			/* EP direction, number, and address */
1334 			ep_dir = ((ep_base->CFG & USBD_CFG_STATE_Msk) == USBD_CFG_EPMODE_IN)
1335 					 ? USB_EP_DIR_IN
1336 					 : USB_EP_DIR_OUT;
1337 			ep_idx = (ep_base->CFG & USBD_CFG_EPNUM_Msk) >> USBD_CFG_EPNUM_Pos;
1338 			ep = USB_EP_GET_ADDR(ep_idx, ep_dir);
1339 
1340 			/* NOTE: See comment in udc_numaker_set_address()'s implementation
1341 			 * for safe place to change USB device address
1342 			 */
1343 			if (ep == USB_EP_GET_ADDR(0, USB_EP_DIR_IN)) {
1344 				numaker_usbd_set_addr(dev);
1345 			}
1346 
1347 			/* NOTE: See comment on mxpld_ctrlout for why make one copy of
1348 			 * CTRL OUT's MXPLD
1349 			 */
1350 			if (ep == USB_EP_GET_ADDR(0, USB_EP_DIR_OUT)) {
1351 				struct numaker_usbd_ep *ep_ctrlout = priv->ep_pool + 0;
1352 				USBD_EP_T *ep_ctrlout_base =
1353 					numaker_usbd_ep_base(dev, ep_ctrlout->ep_hw_idx);
1354 
1355 				ep_ctrlout->mxpld_ctrlout = ep_ctrlout_base->MXPLD;
1356 			}
1357 
1358 			/* Message for bottom-half processing */
1359 			if (USB_EP_DIR_IS_OUT(ep)) {
1360 				msg.type = NUMAKER_USBD_MSG_TYPE_OUT;
1361 				msg.out.ep = ep;
1362 			} else {
1363 				msg.type = NUMAKER_USBD_MSG_TYPE_IN;
1364 				msg.in.ep = ep;
1365 			}
1366 			numaker_usbd_send_msg(dev, &msg);
1367 
1368 			/* Have handled this EP and go next */
1369 			epintsts &= ~BIT(ep_hw_idx);
1370 		}
1371 	}
1372 }
1373 
udc_numaker_device_speed(const struct device * dev)1374 static enum udc_bus_speed udc_numaker_device_speed(const struct device *dev)
1375 {
1376 	return UDC_BUS_SPEED_FS;
1377 }
1378 
udc_numaker_ep_enqueue(const struct device * dev,struct udc_ep_config * const ep_cfg,struct net_buf * buf)1379 static int udc_numaker_ep_enqueue(const struct device *dev, struct udc_ep_config *const ep_cfg,
1380 				  struct net_buf *buf)
1381 {
1382 	struct numaker_usbd_msg msg = {0};
1383 
1384 	LOG_DBG("%p enqueue %p", dev, buf);
1385 	udc_buf_put(ep_cfg, buf);
1386 
1387 	/* Resume the EP's queued transfer */
1388 	if (!ep_cfg->stat.halted) {
1389 		msg.type = NUMAKER_USBD_MSG_TYPE_XFER;
1390 		msg.xfer.ep = ep_cfg->addr;
1391 		numaker_usbd_send_msg(dev, &msg);
1392 	}
1393 
1394 	return 0;
1395 }
1396 
udc_numaker_ep_dequeue(const struct device * dev,struct udc_ep_config * const ep_cfg)1397 static int udc_numaker_ep_dequeue(const struct device *dev, struct udc_ep_config *const ep_cfg)
1398 {
1399 	struct net_buf *buf;
1400 	struct numaker_usbd_ep *ep_cur;
1401 
1402 	/* Bind EP H/W context to EP address */
1403 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep_cfg->addr);
1404 	if (!ep_cur) {
1405 		LOG_ERR("Bind EP H/W context: ep=0x%02x", ep_cfg->addr);
1406 		return -ENODEV;
1407 	}
1408 
1409 	numaker_usbd_ep_abort(ep_cur);
1410 
1411 	buf = udc_buf_get_all(dev, ep_cfg->addr);
1412 	if (buf) {
1413 		udc_submit_ep_event(dev, buf, -ECONNABORTED);
1414 	}
1415 
1416 	return 0;
1417 }
1418 
udc_numaker_ep_set_halt(const struct device * dev,struct udc_ep_config * const ep_cfg)1419 static int udc_numaker_ep_set_halt(const struct device *dev, struct udc_ep_config *const ep_cfg)
1420 {
1421 	struct numaker_usbd_ep *ep_cur;
1422 
1423 	LOG_DBG("Set halt ep 0x%02x", ep_cfg->addr);
1424 
1425 	/* Bind EP H/W context to EP address */
1426 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep_cfg->addr);
1427 	if (!ep_cur) {
1428 		LOG_ERR("Bind EP H/W context: ep=0x%02x", ep_cfg->addr);
1429 		return -ENODEV;
1430 	}
1431 
1432 	/* Set EP to stalled */
1433 	numaker_usbd_ep_set_stall(ep_cur);
1434 
1435 	return 0;
1436 }
1437 
udc_numaker_ep_clear_halt(const struct device * dev,struct udc_ep_config * const ep_cfg)1438 static int udc_numaker_ep_clear_halt(const struct device *dev, struct udc_ep_config *const ep_cfg)
1439 {
1440 	struct numaker_usbd_ep *ep_cur;
1441 	struct numaker_usbd_msg msg = {0};
1442 
1443 	LOG_DBG("Clear halt ep 0x%02x", ep_cfg->addr);
1444 
1445 	/* Bind EP H/W context to EP address */
1446 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep_cfg->addr);
1447 	if (!ep_cur) {
1448 		LOG_ERR("Bind EP H/W context: ep=0x%02x", ep_cfg->addr);
1449 		return -ENODEV;
1450 	}
1451 
1452 	/* Reset EP to unstalled and data toggle bit to 0 */
1453 	numaker_usbd_ep_clear_stall_n_data_toggle(ep_cur);
1454 
1455 	/* Resume the EP's queued transfer */
1456 	msg.type = NUMAKER_USBD_MSG_TYPE_XFER;
1457 	msg.xfer.ep = ep_cfg->addr;
1458 	numaker_usbd_send_msg(dev, &msg);
1459 
1460 	return 0;
1461 }
1462 
udc_numaker_ep_enable(const struct device * dev,struct udc_ep_config * const ep_cfg)1463 static int udc_numaker_ep_enable(const struct device *dev, struct udc_ep_config *const ep_cfg)
1464 {
1465 	int err;
1466 	uint32_t dmabuf_base;
1467 	uint32_t dmabuf_size;
1468 	struct numaker_usbd_ep *ep_cur;
1469 
1470 	LOG_DBG("Enable ep 0x%02x", ep_cfg->addr);
1471 
1472 	/* Bind EP H/W context to EP address */
1473 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep_cfg->addr);
1474 	if (!ep_cur) {
1475 		LOG_ERR("Bind EP H/W context: ep=0x%02x", ep_cfg->addr);
1476 		return -ENODEV;
1477 	}
1478 
1479 	/* Configure EP DMA buffer */
1480 	if (!ep_cur->dmabuf_valid || ep_cur->dmabuf_size < ep_cfg->mps) {
1481 		/* Allocate DMA buffer */
1482 		err = numaker_usbd_ep_mgmt_alloc_dmabuf(dev, ep_cfg->mps, &dmabuf_base,
1483 							&dmabuf_size);
1484 		if (err < 0) {
1485 			LOG_ERR("Allocate DMA buffer failed");
1486 			return err;
1487 		}
1488 
1489 		/* Configure EP DMA buffer */
1490 		numaker_usbd_ep_config_dmabuf(ep_cur, dmabuf_base, dmabuf_size);
1491 	}
1492 
1493 	/* Configure EP majorly */
1494 	numaker_usbd_ep_config_major(ep_cur, ep_cfg);
1495 
1496 	/* Enable EP */
1497 	numaker_usbd_ep_enable(ep_cur);
1498 
1499 	return 0;
1500 }
1501 
udc_numaker_ep_disable(const struct device * dev,struct udc_ep_config * const ep_cfg)1502 static int udc_numaker_ep_disable(const struct device *dev, struct udc_ep_config *const ep_cfg)
1503 {
1504 	struct numaker_usbd_ep *ep_cur;
1505 
1506 	LOG_DBG("Disable ep 0x%02x", ep_cfg->addr);
1507 
1508 	/* Bind EP H/W context to EP address */
1509 	ep_cur = numaker_usbd_ep_mgmt_bind_ep(dev, ep_cfg->addr);
1510 	if (!ep_cur) {
1511 		LOG_ERR("Bind EP H/W context: ep=0x%02x", ep_cfg->addr);
1512 		return -ENODEV;
1513 	}
1514 
1515 	/* Disable EP */
1516 	numaker_usbd_ep_disable(ep_cur);
1517 
1518 	return 0;
1519 }
1520 
udc_numaker_host_wakeup(const struct device * dev)1521 static int udc_numaker_host_wakeup(const struct device *dev)
1522 {
1523 	const struct udc_numaker_config *config = dev->config;
1524 	USBD_T *const base = config->base;
1525 
1526 	/* Enable back USB/PHY first */
1527 	base->ATTR |= USBD_ATTR_USBEN_Msk | USBD_ATTR_PHYEN_Msk;
1528 
1529 	/* Then generate 'K' */
1530 	base->ATTR |= USBD_ATTR_RWAKEUP_Msk;
1531 	k_sleep(K_USEC(NUMAKER_USBD_BUS_RESUME_DRV_K_US));
1532 	base->ATTR ^= USBD_ATTR_RWAKEUP_Msk;
1533 
1534 	return 0;
1535 }
1536 
udc_numaker_set_address(const struct device * dev,const uint8_t addr)1537 static int udc_numaker_set_address(const struct device *dev, const uint8_t addr)
1538 {
1539 	struct udc_numaker_data *priv = udc_get_private(dev);
1540 
1541 	LOG_DBG("Set new address %u for %p", addr, dev);
1542 
1543 	/* NOTE: Timing for configuring USB device address into H/W is critical. It must be done
1544 	 * in-between SET_ADDRESS control transfer and next transfer. For this, it is done in
1545 	 * IN ACK ISR of SET_ADDRESS control transfer.
1546 	 */
1547 	priv->addr = addr;
1548 
1549 	return 0;
1550 }
1551 
udc_numaker_enable(const struct device * dev)1552 static int udc_numaker_enable(const struct device *dev)
1553 {
1554 	LOG_DBG("Enable device %p", dev);
1555 
1556 	/* S/W connect */
1557 	numaker_usbd_sw_connect(dev);
1558 
1559 	return 0;
1560 }
1561 
udc_numaker_disable(const struct device * dev)1562 static int udc_numaker_disable(const struct device *dev)
1563 {
1564 	LOG_DBG("Enable device %p", dev);
1565 
1566 	/* S/W disconnect */
1567 	numaker_usbd_sw_disconnect(dev);
1568 
1569 	return 0;
1570 }
1571 
udc_numaker_init(const struct device * dev)1572 static int udc_numaker_init(const struct device *dev)
1573 {
1574 	int err;
1575 
1576 	/* Initialize USBD H/W */
1577 	err = numaker_usbd_hw_setup(dev);
1578 	if (err < 0) {
1579 		LOG_ERR("Set up H/W: %d", err);
1580 		return err;
1581 	}
1582 
1583 	/* USB device address defaults to 0 */
1584 	numaker_usbd_reset_addr(dev);
1585 
1586 	/* Initialize all EP H/W contexts */
1587 	numaker_usbd_ep_mgmt_init(dev);
1588 
1589 	if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, USB_EP_TYPE_CONTROL, 64, 0)) {
1590 		LOG_ERR("Failed to enable control endpoint");
1591 		return -EIO;
1592 	}
1593 
1594 	if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, USB_EP_TYPE_CONTROL, 64, 0)) {
1595 		LOG_ERR("Failed to enable control endpoint");
1596 		return -EIO;
1597 	}
1598 
1599 	return 0;
1600 }
1601 
udc_numaker_shutdown(const struct device * dev)1602 static int udc_numaker_shutdown(const struct device *dev)
1603 {
1604 	struct udc_numaker_data *priv = udc_get_private(dev);
1605 
1606 	if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) {
1607 		LOG_ERR("Failed to disable control endpoint");
1608 		return -EIO;
1609 	}
1610 
1611 	if (udc_ep_disable_internal(dev, USB_CONTROL_EP_IN)) {
1612 		LOG_ERR("Failed to disable control endpoint");
1613 		return -EIO;
1614 	}
1615 
1616 	/* Uninitialize USBD H/W */
1617 	numaker_usbd_hw_shutdown(dev);
1618 
1619 	/* Purge message queue */
1620 	k_msgq_purge(priv->msgq);
1621 
1622 	return 0;
1623 }
1624 
udc_numaker_lock(const struct device * dev)1625 static int udc_numaker_lock(const struct device *dev)
1626 {
1627 	return udc_lock_internal(dev, K_FOREVER);
1628 }
1629 
udc_numaker_unlock(const struct device * dev)1630 static int udc_numaker_unlock(const struct device *dev)
1631 {
1632 	return udc_unlock_internal(dev);
1633 }
1634 
udc_numaker_driver_preinit(const struct device * dev)1635 static int udc_numaker_driver_preinit(const struct device *dev)
1636 {
1637 	const struct udc_numaker_config *config = dev->config;
1638 	struct udc_data *data = dev->data;
1639 	int err;
1640 
1641 	data->caps.rwup = true;
1642 	data->caps.addr_before_status = true;
1643 	data->caps.mps0 = UDC_MPS0_64;
1644 
1645 	/* Some soc series don't allow ISO IN/OUT to be assigned the same EP number.
1646 	 * This is addressed by limiting all OUT/IN EP addresses in top/bottom halves,
1647 	 * except CTRL OUT/IN.
1648 	 */
1649 
1650 	for (int i = 0; i < config->ep_cfg_out_size; i++) {
1651 		/* Limit all OUT EP numbers to 0, 1~7 */
1652 		if (config->disallow_iso_inout_same && i != 0 && i >= 8) {
1653 			continue;
1654 		}
1655 
1656 		config->ep_cfg_out[i].caps.out = 1;
1657 		if (i == 0) {
1658 			config->ep_cfg_out[i].caps.control = 1;
1659 			config->ep_cfg_out[i].caps.mps = 64;
1660 		} else {
1661 			config->ep_cfg_out[i].caps.bulk = 1;
1662 			config->ep_cfg_out[i].caps.interrupt = 1;
1663 			config->ep_cfg_out[i].caps.iso = 1;
1664 			config->ep_cfg_out[i].caps.mps = 1023;
1665 		}
1666 
1667 		config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i;
1668 		err = udc_register_ep(dev, &config->ep_cfg_out[i]);
1669 		if (err != 0) {
1670 			LOG_ERR("Failed to register endpoint");
1671 			return err;
1672 		}
1673 	}
1674 
1675 	for (int i = 0; i < config->ep_cfg_in_size; i++) {
1676 		/* Limit all IN EP numbers to 0, 8~15 */
1677 		if (config->disallow_iso_inout_same && i != 0 && i < 8) {
1678 			continue;
1679 		}
1680 
1681 		config->ep_cfg_in[i].caps.in = 1;
1682 		if (i == 0) {
1683 			config->ep_cfg_in[i].caps.control = 1;
1684 			config->ep_cfg_in[i].caps.mps = 64;
1685 		} else {
1686 			config->ep_cfg_in[i].caps.bulk = 1;
1687 			config->ep_cfg_in[i].caps.interrupt = 1;
1688 			config->ep_cfg_in[i].caps.iso = 1;
1689 			config->ep_cfg_in[i].caps.mps = 1023;
1690 		}
1691 
1692 		config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i;
1693 		err = udc_register_ep(dev, &config->ep_cfg_in[i]);
1694 		if (err != 0) {
1695 			LOG_ERR("Failed to register endpoint");
1696 			return err;
1697 		}
1698 	}
1699 
1700 	config->make_thread(dev);
1701 
1702 	return 0;
1703 }
1704 
1705 static const struct udc_api udc_numaker_api = {
1706 	.device_speed = udc_numaker_device_speed,
1707 	.ep_enqueue = udc_numaker_ep_enqueue,
1708 	.ep_dequeue = udc_numaker_ep_dequeue,
1709 	.ep_set_halt = udc_numaker_ep_set_halt,
1710 	.ep_clear_halt = udc_numaker_ep_clear_halt,
1711 	.ep_enable = udc_numaker_ep_enable,
1712 	.ep_disable = udc_numaker_ep_disable,
1713 	.host_wakeup = udc_numaker_host_wakeup,
1714 	.set_address = udc_numaker_set_address,
1715 	.enable = udc_numaker_enable,
1716 	.disable = udc_numaker_disable,
1717 	.init = udc_numaker_init,
1718 	.shutdown = udc_numaker_shutdown,
1719 	.lock = udc_numaker_lock,
1720 	.unlock = udc_numaker_unlock,
1721 };
1722 
1723 #define UDC_NUMAKER_DEVICE_DEFINE(inst)                                                            \
1724 	PINCTRL_DT_INST_DEFINE(inst);                                                              \
1725                                                                                                    \
1726 	static void udc_numaker_irq_config_func_##inst(const struct device *dev)                   \
1727 	{                                                                                          \
1728 		IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), numaker_udbd_isr,     \
1729 			    DEVICE_DT_INST_GET(inst), 0);                                          \
1730                                                                                                    \
1731 		irq_enable(DT_INST_IRQN(inst));                                                    \
1732 	}                                                                                          \
1733                                                                                                    \
1734 	static void udc_numaker_irq_unconfig_func_##inst(const struct device *dev)                 \
1735 	{                                                                                          \
1736 		irq_disable(DT_INST_IRQN(inst));                                                   \
1737 	}                                                                                          \
1738                                                                                                    \
1739 	K_THREAD_STACK_DEFINE(udc_numaker_stack_##inst, CONFIG_UDC_NUMAKER_THREAD_STACK_SIZE);     \
1740                                                                                                    \
1741 	static void udc_numaker_thread_##inst(void *dev, void *arg1, void *arg2)                   \
1742 	{                                                                                          \
1743 		ARG_UNUSED(arg1);                                                                  \
1744 		ARG_UNUSED(arg2);                                                                  \
1745 		numaker_usbd_msg_handler(dev);                                                     \
1746 	}                                                                                          \
1747                                                                                                    \
1748 	static void udc_numaker_make_thread_##inst(const struct device *dev)                       \
1749 	{                                                                                          \
1750 		struct udc_numaker_data *priv = udc_get_private(dev);                              \
1751                                                                                                    \
1752 		k_thread_create(&priv->thread_data, udc_numaker_stack_##inst,                      \
1753 				K_THREAD_STACK_SIZEOF(udc_numaker_stack_##inst),                   \
1754 				udc_numaker_thread_##inst, (void *)dev, NULL, NULL,                \
1755 				K_PRIO_COOP(CONFIG_UDC_NUMAKER_THREAD_PRIORITY), K_ESSENTIAL,      \
1756 				K_NO_WAIT);                                                        \
1757 		k_thread_name_set(&priv->thread_data, dev->name);                                  \
1758 	}                                                                                          \
1759                                                                                                    \
1760 	static struct udc_ep_config                                                                \
1761 		ep_cfg_out_##inst[MIN(DT_INST_PROP(inst, num_bidir_endpoints), 16)];               \
1762 	static struct udc_ep_config                                                                \
1763 		ep_cfg_in_##inst[MIN(DT_INST_PROP(inst, num_bidir_endpoints), 16)];                \
1764                                                                                                    \
1765 	static const struct udc_numaker_config udc_numaker_config_##inst = {                       \
1766 		.ep_cfg_out = ep_cfg_out_##inst,                                                   \
1767 		.ep_cfg_in = ep_cfg_in_##inst,                                                     \
1768 		.ep_cfg_out_size = ARRAY_SIZE(ep_cfg_out_##inst),                                  \
1769 		.ep_cfg_in_size = ARRAY_SIZE(ep_cfg_in_##inst),                                    \
1770 		.make_thread = udc_numaker_make_thread_##inst,                                     \
1771 		.base = (USBD_T *)DT_INST_REG_ADDR(inst),                                          \
1772 		.reset = RESET_DT_SPEC_INST_GET(inst),                                             \
1773 		.clk_modidx = DT_INST_CLOCKS_CELL(inst, clock_module_index),                       \
1774 		.clk_src = DT_INST_CLOCKS_CELL(inst, clock_source),                                \
1775 		.clk_div = DT_INST_CLOCKS_CELL(inst, clock_divider),                               \
1776 		.clkctrl_dev = DEVICE_DT_GET(DT_PARENT(DT_INST_CLOCKS_CTLR(inst))),                \
1777 		.irq_config_func = udc_numaker_irq_config_func_##inst,                             \
1778 		.irq_unconfig_func = udc_numaker_irq_unconfig_func_##inst,                         \
1779 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst),                                    \
1780 		.dmabuf_size = DT_INST_PROP(inst, dma_buffer_size),                                \
1781 		.disallow_iso_inout_same = DT_INST_PROP(inst, disallow_iso_in_out_same_number),    \
1782 	};                                                                                         \
1783                                                                                                    \
1784 	static struct numaker_usbd_ep                                                              \
1785 		numaker_usbd_ep_pool_##inst[DT_INST_PROP(inst, num_bidir_endpoints)];              \
1786                                                                                                    \
1787 	K_MSGQ_DEFINE(numaker_usbd_msgq_##inst, sizeof(struct numaker_usbd_msg),                   \
1788 		      CONFIG_UDC_NUMAKER_MSG_QUEUE_SIZE, 4);                                       \
1789                                                                                                    \
1790 	static struct udc_numaker_data udc_priv_##inst = {                                         \
1791 		.msgq = &numaker_usbd_msgq_##inst,                                                 \
1792 		.ep_pool = numaker_usbd_ep_pool_##inst,                                            \
1793 		.ep_pool_size = DT_INST_PROP(inst, num_bidir_endpoints),                           \
1794 	};                                                                                         \
1795                                                                                                    \
1796 	static struct udc_data udc_data_##inst = {                                                 \
1797 		.mutex = Z_MUTEX_INITIALIZER(udc_data_##inst.mutex),                               \
1798 		.priv = &udc_priv_##inst,                                                          \
1799 	};                                                                                         \
1800                                                                                                    \
1801 	DEVICE_DT_INST_DEFINE(inst, udc_numaker_driver_preinit, NULL, &udc_data_##inst,            \
1802 			      &udc_numaker_config_##inst, POST_KERNEL,                             \
1803 			      CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &udc_numaker_api);
1804 
1805 DT_INST_FOREACH_STATUS_OKAY(UDC_NUMAKER_DEVICE_DEFINE)
1806