1 /*
2  * Copyright (c) 2023 Nuvoton Technology Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nuvoton_numaker_pwm
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/reset.h>
11 #include <zephyr/drivers/pinctrl.h>
12 #include <zephyr/drivers/pwm.h>
13 #include <zephyr/drivers/clock_control.h>
14 #include <zephyr/drivers/clock_control/clock_control_numaker.h>
15 #include <zephyr/logging/log.h>
16 #include <soc.h>
17 #include <NuMicro.h>
18 
19 LOG_MODULE_REGISTER(pwm_numaker, CONFIG_PWM_LOG_LEVEL);
20 
21 /* 11-bit prescaler in Numaker EPWM modules */
22 #define NUMAKER_PWM_MAX_PRESCALER BIT(11)
23 #define NUMAKER_PWM_CHANNEL_COUNT 6
24 #define NUMAKER_PWM_RELOAD_CNT    (0xFFFFU)
25 #define NUMAKER_SYSCLK_FREQ       DT_PROP(DT_NODELABEL(sysclk), clock_frequency)
26 /* EPWM channel 0~5 mask */
27 #define NUMAKER_PWM_CHANNEL_MASK  (0x3FU)
28 
29 /* Device config */
30 struct pwm_numaker_config {
31 	/* EPWM base address */
32 	EPWM_T *epwm;
33 	uint32_t prescale;
34 	const struct reset_dt_spec reset;
35 	/* clock configuration */
36 	uint32_t clk_modidx;
37 	uint32_t clk_src;
38 	uint32_t clk_div;
39 	const struct device *clk_dev;
40 	const struct pinctrl_dev_config *pincfg;
41 	void (*irq_config_func)(const struct device *dev);
42 };
43 
44 struct pwm_numaker_capture_data {
45 	pwm_capture_callback_handler_t callback;
46 	void *user_data;
47 	/* Only support either one of PWM_CAPTURE_TYPE_PULSE, PWM_CAPTURE_TYPE_PERIOD */
48 	bool pulse_capture;
49 	bool single_mode;
50 	bool is_busy;
51 	uint32_t curr_edge_mode;
52 	uint32_t next_edge_mode;
53 };
54 
55 /* Driver context/data */
56 struct pwm_numaker_data {
57 	uint32_t clock_freq;
58 	uint32_t cycles_per_sec;
59 #ifdef CONFIG_PWM_CAPTURE
60 	uint32_t overflows;
61 	struct pwm_numaker_capture_data capture[NUMAKER_PWM_CHANNEL_COUNT];
62 #endif /* CONFIG_PWM_CAPTURE */
63 };
64 
pwm_numaker_configure(const struct device * dev)65 static void pwm_numaker_configure(const struct device *dev)
66 {
67 	const struct pwm_numaker_config *cfg = dev->config;
68 	EPWM_T *epwm = cfg->epwm;
69 
70 	/* Disable EPWM channel 0~5 before config */
71 	EPWM_ForceStop(epwm, NUMAKER_PWM_CHANNEL_MASK);
72 
73 	/* Set EPWM default normal polarity as inverse disabled */
74 	epwm->POLCTL &= ~(NUMAKER_PWM_CHANNEL_MASK << EPWM_POLCTL_PINV0_Pos);
75 }
76 
77 /* PWM api functions */
pwm_numaker_set_cycles(const struct device * dev,uint32_t channel,uint32_t period_cycles,uint32_t pulse_cycles,pwm_flags_t flags)78 static int pwm_numaker_set_cycles(const struct device *dev, uint32_t channel,
79 				  uint32_t period_cycles, uint32_t pulse_cycles, pwm_flags_t flags)
80 {
81 	const struct pwm_numaker_config *cfg = dev->config;
82 	struct pwm_numaker_data *data = dev->data;
83 	EPWM_T *epwm = cfg->epwm;
84 	uint32_t channel_mask = BIT(channel);
85 
86 	LOG_DBG("Channel=0x%x, CAPIEN=0x%x, CAPIF=0x%x", channel, epwm->CAPIEN,
87 		epwm->CAPIF);
88 
89 	/* Set EPWM polarity */
90 	if (flags & PWM_POLARITY_INVERTED) {
91 		epwm->POLCTL |= BIT(EPWM_POLCTL_PINV0_Pos + channel);
92 	} else {
93 		epwm->POLCTL &= ~BIT(EPWM_POLCTL_PINV0_Pos + channel);
94 	}
95 
96 	/* Force disable EPWM channel as while pulse_cycles = 0 */
97 	if (period_cycles == 0U) {
98 		EPWM_Stop(epwm, channel_mask);
99 		EPWM_ForceStop(epwm, channel_mask);
100 		EPWM_DisableOutput(epwm, channel_mask);
101 		return 0;
102 	}
103 
104 	/* Set EPWM channel & output configuration */
105 	EPWM_ConfigOutputChannel(epwm, channel, data->cycles_per_sec / period_cycles,
106 				 (100U * pulse_cycles) / period_cycles);
107 
108 	/* Enable EPWM Output path for EPWM channel */
109 	EPWM_EnableOutput(epwm, channel_mask);
110 
111 	/* Enable Timer for EPWM channel */
112 	EPWM_Start(epwm, channel_mask);
113 
114 	LOG_DBG("cycles_per_sec=0x%x, pulse_cycles=0x%x, period_cycles=0x%x",
115 		data->cycles_per_sec, pulse_cycles, period_cycles);
116 	LOG_DBG("CTL1=0x%x, POEN=0x%x, CNTEN=0x%x", epwm->CTL1, epwm->POEN, epwm->CNTEN);
117 	LOG_DBG("Channel=0x%x, CAPIEN=0x%x, CAPIF=0x%x", channel, epwm->CAPIEN, epwm->CAPIF);
118 
119 	return 0;
120 }
121 
pwm_numaker_get_cycles_per_sec(const struct device * dev,uint32_t channel,uint64_t * cycles)122 static int pwm_numaker_get_cycles_per_sec(const struct device *dev, uint32_t channel,
123 					  uint64_t *cycles)
124 {
125 	const struct pwm_numaker_config *cfg = dev->config;
126 	struct pwm_numaker_data *data = dev->data;
127 
128 	ARG_UNUSED(channel);
129 
130 	data->cycles_per_sec = data->clock_freq / (cfg->prescale + 1U);
131 	*cycles = (uint64_t)data->cycles_per_sec;
132 
133 	return 0;
134 }
135 
136 #ifdef CONFIG_PWM_CAPTURE
pwm_numaker_configure_capture(const struct device * dev,uint32_t channel,pwm_flags_t flags,pwm_capture_callback_handler_t cb,void * user_data)137 static int pwm_numaker_configure_capture(const struct device *dev, uint32_t channel,
138 					 pwm_flags_t flags, pwm_capture_callback_handler_t cb,
139 					 void *user_data)
140 {
141 	struct pwm_numaker_data *data = dev->data;
142 	uint32_t pair = channel;
143 
144 	LOG_DBG("");
145 
146 	data->capture[pair].callback = cb;
147 	data->capture[pair].user_data = user_data;
148 
149 	if (data->capture[pair].is_busy) {
150 		LOG_ERR("Capture already active on this channel %d", pair);
151 		return -EBUSY;
152 	}
153 	if ((flags & PWM_CAPTURE_TYPE_MASK) == PWM_CAPTURE_TYPE_BOTH) {
154 		LOG_ERR("Cannot capture both period and pulse width");
155 		return -ENOTSUP;
156 	}
157 
158 	if ((flags & PWM_CAPTURE_MODE_MASK) == PWM_CAPTURE_MODE_CONTINUOUS) {
159 		data->capture[pair].single_mode = false;
160 	} else {
161 		data->capture[pair].single_mode = true;
162 	}
163 
164 	if (flags & PWM_CAPTURE_TYPE_PERIOD) {
165 		data->capture[pair].pulse_capture = false;
166 
167 		if (flags & PWM_POLARITY_INVERTED) {
168 			data->capture[pair].curr_edge_mode = EPWM_CAPTURE_INT_FALLING_LATCH;
169 			data->capture[pair].next_edge_mode = EPWM_CAPTURE_INT_FALLING_LATCH;
170 		} else {
171 			data->capture[pair].curr_edge_mode = EPWM_CAPTURE_INT_RISING_LATCH;
172 			data->capture[pair].next_edge_mode = EPWM_CAPTURE_INT_RISING_LATCH;
173 		}
174 	} else {
175 		data->capture[pair].pulse_capture = true;
176 
177 		if (flags & PWM_POLARITY_INVERTED) {
178 			data->capture[pair].curr_edge_mode = EPWM_CAPTURE_INT_FALLING_LATCH;
179 			data->capture[pair].next_edge_mode = EPWM_CAPTURE_INT_RISING_LATCH;
180 		} else {
181 			data->capture[pair].curr_edge_mode = EPWM_CAPTURE_INT_RISING_LATCH;
182 			data->capture[pair].next_edge_mode = EPWM_CAPTURE_INT_FALLING_LATCH;
183 		}
184 	}
185 
186 	return 0;
187 }
188 
pwm_numaker_enable_capture(const struct device * dev,uint32_t channel)189 static int pwm_numaker_enable_capture(const struct device *dev, uint32_t channel)
190 {
191 	const struct pwm_numaker_config *cfg = dev->config;
192 	struct pwm_numaker_data *data = dev->data;
193 	EPWM_T *epwm = cfg->epwm;
194 	uint32_t pair = channel;
195 	uint32_t channel_mask = BIT(channel);
196 	uint32_t unit_time_nsec = (1000000000U / data->cycles_per_sec);
197 
198 	LOG_DBG("");
199 
200 	if (!data->capture[pair].callback) {
201 		LOG_ERR("PWM capture not configured");
202 		return -EINVAL;
203 	}
204 
205 	if (data->capture[pair].is_busy) {
206 		LOG_ERR("Capture already active on this channel %d", pair);
207 		return -EBUSY;
208 	}
209 
210 	data->capture[pair].is_busy = true;
211 
212 	/* Set capture configuration */
213 	EPWM_ConfigCaptureChannel(epwm, channel, unit_time_nsec, 0);
214 
215 	/* Enable Capture Function for EPWM */
216 	EPWM_EnableCapture(epwm, channel_mask);
217 
218 	/* Enable Timer for EPWM */
219 	EPWM_Start(epwm, channel_mask);
220 
221 	EPWM_ClearCaptureIntFlag(epwm, channel,
222 				 EPWM_CAPTURE_INT_FALLING_LATCH | EPWM_CAPTURE_INT_RISING_LATCH);
223 
224 	/* EnableInterrupt */
225 	EPWM_EnableCaptureInt(epwm, channel, data->capture[pair].curr_edge_mode);
226 
227 	LOG_DBG("Channel=0x%x, CAPIEN=0x%x, CAPIF=0x%x", channel, epwm->CAPIEN,
228 		epwm->CAPIF);
229 
230 	return 0;
231 }
232 
pwm_numaker_disable_capture(const struct device * dev,uint32_t channel)233 static int pwm_numaker_disable_capture(const struct device *dev, uint32_t channel)
234 {
235 	const struct pwm_numaker_config *cfg = dev->config;
236 	struct pwm_numaker_data *data = dev->data;
237 	EPWM_T *epwm = cfg->epwm;
238 	uint32_t channel_mask = BIT(channel);
239 
240 	LOG_DBG("");
241 
242 	data->capture[channel].is_busy = false;
243 	EPWM_Stop(epwm, channel_mask);
244 	EPWM_ForceStop(epwm, channel_mask);
245 	EPWM_DisableCapture(epwm, channel_mask);
246 	EPWM_DisableCaptureInt(epwm, channel,
247 			       EPWM_CAPTURE_INT_RISING_LATCH | EPWM_CAPTURE_INT_FALLING_LATCH);
248 	EPWM_ClearCaptureIntFlag(epwm, channel,
249 				 EPWM_CAPTURE_INT_FALLING_LATCH | EPWM_CAPTURE_INT_RISING_LATCH);
250 	LOG_DBG("CAPIEN = 0x%x\n", epwm->CAPIEN);
251 	return 0;
252 }
253 
254 /*
255  * Get capture cycles between current channel edge until next chnannel edge.
256  * The capture period counter down count from 0x10000, and auto-reload to 0x10000
257  */
pwm_numaker_get_cap_cycle(EPWM_T * epwm,uint32_t channel,uint32_t curr_edge,uint32_t next_edge,uint32_t * cycles)258 static int pwm_numaker_get_cap_cycle(EPWM_T *epwm, uint32_t channel, uint32_t curr_edge,
259 				       uint32_t next_edge, uint32_t *cycles)
260 {
261 	uint16_t curr_cnt;
262 	uint16_t next_cnt;
263 	uint32_t next_if_mask;
264 	uint32_t capif_base;
265 	uint32_t time_out_cnt;
266 	int status = 0;
267 	uint32_t period_reloads = 0;
268 
269 	/* PWM counter is timing critical, to avoid print msg from irq_isr until getting cycles */
270 	LOG_DBG("");
271 
272 	EPWM_ClearPeriodIntFlag(epwm, channel);
273 
274 	capif_base = (next_edge == EPWM_CAPTURE_INT_FALLING_LATCH) ? EPWM_CAPIF_CFLIF0_Pos
275 								  : EPWM_CAPIF_CRLIF0_Pos;
276 	next_if_mask = BIT(capif_base + channel);
277 	time_out_cnt = NUMAKER_SYSCLK_FREQ / 2; /* 500 ms time-out */
278 	LOG_DBG("Channel=0x%x, R-Cnt=0x%x, F-Cnt0x%x, CNT-0x%x", channel,
279 		EPWM_GET_CAPTURE_RISING_DATA(epwm, channel),
280 		EPWM_GET_CAPTURE_FALLING_DATA(epwm, channel), epwm->CNT[channel]);
281 	curr_cnt = (curr_edge == EPWM_CAPTURE_INT_FALLING_LATCH)
282 			  ? EPWM_GET_CAPTURE_FALLING_DATA(epwm, channel)
283 			  : (uint16_t)EPWM_GET_CAPTURE_RISING_DATA(epwm, channel);
284 
285 	/* Wait for Capture Next Indicator */
286 	while ((epwm->CAPIF & next_if_mask) == 0) {
287 		if (EPWM_GetPeriodIntFlag(epwm, channel)) {
288 			EPWM_ClearPeriodIntFlag(epwm, channel);
289 			period_reloads++;
290 		}
291 		if (--time_out_cnt == 0) {
292 			status = -EAGAIN;
293 			goto done;
294 		}
295 	}
296 
297 	/* Clear Capture Falling and Rising Indicator */
298 	EPWM_ClearCaptureIntFlag(epwm, channel,
299 				 EPWM_CAPTURE_INT_FALLING_LATCH | EPWM_CAPTURE_INT_RISING_LATCH);
300 
301 	/* Get Capture Latch Counter Data */
302 	next_cnt = (next_edge == EPWM_CAPTURE_INT_FALLING_LATCH)
303 			  ? (uint16_t)EPWM_GET_CAPTURE_FALLING_DATA(epwm, channel)
304 			  : (uint16_t)EPWM_GET_CAPTURE_RISING_DATA(epwm, channel);
305 
306 	*cycles = (period_reloads * NUMAKER_PWM_RELOAD_CNT) + curr_cnt - next_cnt;
307 	LOG_DBG("cycles=0x%x, period_reloads=0x%x, CAPIF=0x%x, cur-0x%x ,next-0x%x",
308 		*cycles, period_reloads, epwm->CAPIF, curr_cnt, next_cnt);
309 
310 done:
311 	return status;
312 }
313 
pwm_numaker_channel_cap(const struct device * dev,EPWM_T * epwm,uint32_t channel)314 static void pwm_numaker_channel_cap(const struct device *dev, EPWM_T *epwm, uint32_t channel)
315 {
316 	struct pwm_numaker_data *data = dev->data;
317 	struct pwm_numaker_capture_data *capture;
318 	uint32_t cycles = 0;
319 	int status;
320 
321 	EPWM_DisableCaptureInt(epwm, channel, EPWM_CAPTURE_INT_RISING_LATCH |
322 				EPWM_CAPTURE_INT_FALLING_LATCH);
323 
324 	capture = &data->capture[channel];
325 
326 	/* Calculate cycles */
327 	status = pwm_numaker_get_cap_cycle(
328 		epwm, channel, data->capture[channel].curr_edge_mode,
329 		data->capture[channel].next_edge_mode, &cycles);
330 	if (capture->pulse_capture) {
331 		/* For PWM_CAPTURE_TYPE_PULSE */
332 		capture->callback(dev, channel, 0, cycles, status, capture->user_data);
333 	} else {
334 		/* For PWM_CAPTURE_TYPE_PERIOD */
335 		capture->callback(dev, channel, cycles, 0, status, capture->user_data);
336 	}
337 
338 	if (capture->single_mode) {
339 		EPWM_DisableCaptureInt(epwm, channel, EPWM_CAPTURE_INT_RISING_LATCH |
340 					EPWM_CAPTURE_INT_FALLING_LATCH);
341 		data->capture[channel].is_busy = false;
342 	} else {
343 		EPWM_ClearCaptureIntFlag(epwm, channel, EPWM_CAPTURE_INT_FALLING_LATCH |
344 					EPWM_CAPTURE_INT_RISING_LATCH);
345 		EPWM_EnableCaptureInt(epwm, channel, data->capture[channel].curr_edge_mode);
346 		/* data->capture[channel].is_busy = true; */
347 	}
348 }
349 
pwm_numaker_isr(const struct device * dev,uint32_t st_channel,uint32_t end_channel)350 static void pwm_numaker_isr(const struct device *dev, uint32_t st_channel, uint32_t end_channel)
351 {
352 	const struct pwm_numaker_config *cfg = dev->config;
353 	struct pwm_numaker_data *data = dev->data;
354 	EPWM_T *epwm = cfg->epwm;
355 	struct pwm_numaker_capture_data *capture;
356 	uint32_t int_status;
357 	uint32_t cap_intsts;
358 	int i;
359 	uint32_t int_mask = (BIT(st_channel) | BIT(end_channel));
360 	uint32_t cap_int_rise_mask, cap_int_fall_mask;
361 	uint32_t cap_int_mask =
362 		(EPWM_CAPIF_CFLIF0_Msk << st_channel | EPWM_CAPIF_CRLIF0_Msk << st_channel |
363 		 EPWM_CAPIF_CFLIF0_Msk << end_channel | EPWM_CAPIF_CRLIF0_Msk << end_channel);
364 
365 	/* Get Output int status */
366 	int_status = epwm->AINTSTS & int_mask;
367 	/* Clear Output int status */
368 	if (int_status != 0x00) {
369 		epwm->AINTSTS = int_status;
370 	}
371 
372 	/* Get CAP int status */
373 	cap_intsts = epwm->CAPIF & cap_int_mask;
374 
375 	/* PWM counter is timing critical, to avoid print msg from irq_isr
376 	 *  until getting capture cycles.
377 	 */
378 	LOG_DBG("Channel=0x%x, CAPIEN=0x%x, CAPIF=0x%x, capIntMask=0x%x",
379 		st_channel, epwm->CAPIEN, epwm->CAPIF, cap_int_mask);
380 	if (cap_intsts != 0x00) { /* Capture Interrupt */
381 		/* Clear CAP int status */
382 		epwm->CAPIF = cap_intsts;
383 
384 		/* Rising latch or Falling latch */
385 		for (i = st_channel; i <= end_channel; i++) {
386 			capture = &data->capture[i];
387 			if (capture == NULL) {
388 				continue;
389 			}
390 			cap_int_rise_mask = (EPWM_CAPTURE_INT_RISING_LATCH << i);
391 			cap_int_fall_mask = (EPWM_CAPTURE_INT_FALLING_LATCH << i);
392 			if ((cap_int_rise_mask | cap_int_fall_mask) & cap_intsts) {
393 				pwm_numaker_channel_cap(dev, epwm, i);
394 			}
395 		}
396 	}
397 }
398 
pwm_numaker_p0_isr(const struct device * dev)399 static void pwm_numaker_p0_isr(const struct device *dev)
400 {
401 	/* Pair0 service channel 0, 1 */
402 	pwm_numaker_isr(dev, 0, 1);
403 }
404 
pwm_numaker_p1_isr(const struct device * dev)405 static void pwm_numaker_p1_isr(const struct device *dev)
406 {
407 	/* Pair1 service channel 2, 3 */
408 	pwm_numaker_isr(dev, 2, 3);
409 }
410 
pwm_numaker_p2_isr(const struct device * dev)411 static void pwm_numaker_p2_isr(const struct device *dev)
412 {
413 	/* Pair2 service channel 4, 5 */
414 	pwm_numaker_isr(dev, 4, 5);
415 }
416 #endif /* CONFIG_PWM_CAPTURE */
417 
418 /* PWM driver registration */
419 static const struct pwm_driver_api pwm_numaker_driver_api = {
420 	.set_cycles = pwm_numaker_set_cycles,
421 	.get_cycles_per_sec = pwm_numaker_get_cycles_per_sec,
422 #ifdef CONFIG_PWM_CAPTURE
423 	.configure_capture = pwm_numaker_configure_capture,
424 	.enable_capture = pwm_numaker_enable_capture,
425 	.disable_capture = pwm_numaker_disable_capture,
426 #endif /* CONFIG_PWM_CAPTURE */
427 };
428 
429 /* Alternative EPWM clock get rate before support standard clock_control_get_rate */
pwm_numaker_clk_get_rate(EPWM_T * epwm,uint32_t * rate)430 static int pwm_numaker_clk_get_rate(EPWM_T *epwm, uint32_t *rate)
431 {
432 	uint32_t clk_src;
433 	uint32_t epwm_clk_src;
434 
435 	if (epwm == EPWM0) {
436 		clk_src = CLK->CLKSEL2 & CLK_CLKSEL2_EPWM0SEL_Msk;
437 	} else if (epwm == EPWM1) {
438 		clk_src = CLK->CLKSEL2 & CLK_CLKSEL2_EPWM1SEL_Msk;
439 	} else {
440 		LOG_ERR("Invalid EPWM node");
441 		return -EINVAL;
442 	}
443 
444 	if (clk_src == 0U) {
445 		/* clock source is from PLL clock */
446 		epwm_clk_src = CLK_GetPLLClockFreq();
447 	} else {
448 		/* clock source is from PCLK */
449 		SystemCoreClockUpdate();
450 		if (epwm == EPWM0) {
451 			epwm_clk_src = CLK_GetPCLK0Freq();
452 		} else { /* (epwm == EPWM1) */
453 			epwm_clk_src = CLK_GetPCLK1Freq();
454 		}
455 	}
456 	*rate = epwm_clk_src;
457 	return 0;
458 }
459 
pwm_numaker_init(const struct device * dev)460 static int pwm_numaker_init(const struct device *dev)
461 {
462 	const struct pwm_numaker_config *cfg = dev->config;
463 	struct pwm_numaker_data *data = dev->data;
464 	EPWM_T *epwm = cfg->epwm;
465 	uint32_t clock_freq;
466 	int err;
467 
468 	struct numaker_scc_subsys scc_subsys;
469 
470 	/* Validate this module's reset object */
471 	if (!device_is_ready(cfg->reset.dev)) {
472 		LOG_ERR("reset controller not ready");
473 		return -ENODEV;
474 	}
475 
476 	SYS_UnlockReg();
477 
478 	/* CLK controller */
479 	memset(&scc_subsys, 0x00, sizeof(scc_subsys));
480 	scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC;
481 	scc_subsys.pcc.clk_modidx = cfg->clk_modidx;
482 	scc_subsys.pcc.clk_src = cfg->clk_src;
483 	scc_subsys.pcc.clk_div = cfg->clk_div;
484 
485 	/* Equivalent to CLK_EnableModuleClock() */
486 	err = clock_control_on(cfg->clk_dev, (clock_control_subsys_t)&scc_subsys);
487 	if (err != 0) {
488 		goto done;
489 	}
490 	/* Equivalent to CLK_SetModuleClock() */
491 	err = clock_control_configure(cfg->clk_dev, (clock_control_subsys_t)&scc_subsys, NULL);
492 	if (err != 0) {
493 		goto done;
494 	}
495 
496 	/* Not support standard clock_control_get_rate yet */
497 	/* clock_control_get_rate(cfg->clk_dev,(clock_control_subsys_t)&scc_subsys,&clock_freq); */
498 	err =  pwm_numaker_clk_get_rate(epwm, &clock_freq);
499 
500 	if (err < 0) {
501 		LOG_ERR("Get EPWM clock rate failure %d", err);
502 		goto done;
503 	}
504 	data->clock_freq = clock_freq;
505 	data->cycles_per_sec = data->clock_freq / (cfg->prescale + 1U);
506 
507 	err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
508 	if (err) {
509 		LOG_ERR("Failed to apply pinctrl state");
510 		goto done;
511 	}
512 
513 	/* Reset PWM to default state, same as BSP's SYS_ResetModule(id_rst) */
514 	reset_line_toggle_dt(&cfg->reset);
515 
516 	/* Configure PWM device initially */
517 	pwm_numaker_configure(dev);
518 
519 #ifdef CONFIG_PWM_CAPTURE
520 	/* Enable NVIC */
521 	cfg->irq_config_func(dev);
522 #endif
523 
524 done:
525 	SYS_LockReg();
526 	return err;
527 }
528 
529 #ifdef CONFIG_PWM_CAPTURE
530 #define NUMAKER_PWM_IRQ_CONFIG_FUNC(n)                                                             \
531 	static void pwm_numaker_irq_config_##n(const struct device *dev)                           \
532 	{                                                                                          \
533 		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, pair0, irq),                                    \
534 			    DT_INST_IRQ_BY_NAME(n, pair0, priority), pwm_numaker_p0_isr,           \
535 			    DEVICE_DT_INST_GET(n), 0);                                             \
536                                                                                                    \
537 		irq_enable(DT_INST_IRQ_BY_NAME(n, pair0, irq));                                    \
538                                                                                                    \
539 		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, pair1, irq),                                    \
540 			    DT_INST_IRQ_BY_NAME(n, pair1, priority), pwm_numaker_p1_isr,           \
541 			    DEVICE_DT_INST_GET(n), 0);                                             \
542                                                                                                    \
543 		irq_enable(DT_INST_IRQ_BY_NAME(n, pair1, irq));                                    \
544                                                                                                    \
545 		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, pair2, irq),                                    \
546 			    DT_INST_IRQ_BY_NAME(n, pair2, priority), pwm_numaker_p2_isr,           \
547 			    DEVICE_DT_INST_GET(n), 0);                                             \
548                                                                                                    \
549 		irq_enable(DT_INST_IRQ_BY_NAME(n, pair2, irq));                                    \
550 	}
551 #define IRQ_FUNC_INIT(n) .irq_config_func = pwm_numaker_irq_config_##n
552 #else
553 #define NUMAKER_PWM_IRQ_CONFIG_FUNC(n)
554 #define IRQ_FUNC_INIT(n)
555 #endif
556 
557 #define NUMAKER_PWM_INIT(inst)                                                                     \
558 	PINCTRL_DT_INST_DEFINE(inst);                                                              \
559 	NUMAKER_PWM_IRQ_CONFIG_FUNC(inst)                                                          \
560                                                                                                    \
561 	static const struct pwm_numaker_config pwm_numaker_cfg_##inst = {                          \
562 		.epwm = (EPWM_T *)DT_INST_REG_ADDR(inst),                                          \
563 		.prescale = DT_INST_PROP(inst, prescaler),                                         \
564 		.reset = RESET_DT_SPEC_INST_GET(inst),                                             \
565 		.clk_modidx = DT_INST_CLOCKS_CELL(inst, clock_module_index),                       \
566 		.clk_src = DT_INST_CLOCKS_CELL(inst, clock_source),                                \
567 		.clk_div = DT_INST_CLOCKS_CELL(inst, clock_divider),                               \
568 		.clk_dev = DEVICE_DT_GET(DT_PARENT(DT_INST_CLOCKS_CTLR(inst))),                    \
569 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst),                                    \
570 		IRQ_FUNC_INIT(inst)};                                                              \
571                                                                                                    \
572 	static struct pwm_numaker_data pwm_numaker_data_##inst;                                    \
573                                                                                                    \
574 	DEVICE_DT_INST_DEFINE(inst, &pwm_numaker_init, NULL, &pwm_numaker_data_##inst,             \
575 			      &pwm_numaker_cfg_##inst, PRE_KERNEL_1,                               \
576 			      CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &pwm_numaker_driver_api);
577 
578 DT_INST_FOREACH_STATUS_OKAY(NUMAKER_PWM_INIT)
579