1 /*
2  * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT espressif_esp32_mcpwm
8 
9 #include <hal/mcpwm_hal.h>
10 #include <hal/mcpwm_ll.h>
11 #include "driver/mcpwm.h"
12 
13 #include <soc.h>
14 #include <errno.h>
15 #include <string.h>
16 #include <zephyr/drivers/pwm.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/drivers/pinctrl.h>
19 #include <zephyr/drivers/clock_control.h>
20 #ifdef CONFIG_PWM_CAPTURE
21 #include <zephyr/drivers/interrupt_controller/intc_esp32.h>
22 #endif /* CONFIG_PWM_CAPTURE */
23 #include <zephyr/logging/log.h>
24 LOG_MODULE_REGISTER(mcpwm_esp32, CONFIG_PWM_LOG_LEVEL);
25 
26 #ifdef CONFIG_PWM_CAPTURE
27 #define SKIP_IRQ_NUM 4U
28 #define MCPWM_INTR_CAP0  BIT(0)
29 #define MCPWM_INTR_CAP1  BIT(1)
30 #define MCPWM_INTR_CAP2  BIT(2)
31 #define MCPWM_CHANNEL_NUM   8U
32 #define CAPTURE_CHANNEL_IDX 6U
33 #else
34 #define MCPWM_CHANNEL_NUM 6U
35 #endif /* CONFIG_PWM_CAPTURE */
36 
37 struct mcpwm_esp32_data {
38 	mcpwm_hal_context_t hal;
39 	mcpwm_hal_init_config_t init_config;
40 	struct k_sem cmd_sem;
41 };
42 
43 #ifdef CONFIG_PWM_CAPTURE
44 struct capture_data {
45 	uint32_t value;
46 	mcpwm_capture_on_edge_t edge;
47 };
48 
49 struct mcpwm_esp32_capture_config {
50 	uint8_t capture_signal;
51 	pwm_capture_callback_handler_t callback;
52 	void *user_data;
53 	uint32_t period;
54 	uint32_t pulse;
55 	uint32_t overflows;
56 	uint8_t skip_irq;
57 	bool capture_period;
58 	bool capture_pulse;
59 	bool continuous;
60 	struct capture_data capture_data[SKIP_IRQ_NUM];
61 };
62 #endif /* CONFIG_PWM_CAPTURE */
63 
64 struct mcpwm_esp32_channel_config {
65 	uint8_t idx;
66 	uint8_t timer_id;
67 	uint8_t operator_id;
68 	uint8_t generator_id;
69 	uint32_t freq;
70 	uint32_t duty;
71 	uint8_t prescale;
72 	bool inverted;
73 #ifdef CONFIG_PWM_CAPTURE
74 	struct mcpwm_esp32_capture_config capture;
75 #endif /* CONFIG_PWM_CAPTURE */
76 };
77 
78 struct mcpwm_esp32_config {
79 	const uint8_t index;
80 	const struct pinctrl_dev_config *pincfg;
81 	const struct device *clock_dev;
82 	const clock_control_subsys_t clock_subsys;
83 	uint8_t prescale;
84 	uint8_t prescale_timer0;
85 	uint8_t prescale_timer1;
86 	uint8_t prescale_timer2;
87 	struct mcpwm_esp32_channel_config channel_config[MCPWM_CHANNEL_NUM];
88 #ifdef CONFIG_PWM_CAPTURE
89 	void (*irq_config_func)(const struct device *dev);
90 #endif /* CONFIG_PWM_CAPTURE */
91 };
92 
mcpwm_esp32_duty_set(const struct device * dev,struct mcpwm_esp32_channel_config * channel)93 static void mcpwm_esp32_duty_set(const struct device *dev,
94 				 struct mcpwm_esp32_channel_config *channel)
95 {
96 	struct mcpwm_esp32_data *data = (struct mcpwm_esp32_data *const)(dev)->data;
97 	mcpwm_duty_type_t duty_type;
98 	uint32_t set_duty;
99 
100 	if (channel->inverted) {
101 		duty_type = channel->duty == 0 ?
102 			MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH : channel->duty == 100 ?
103 			MCPWM_HAL_GENERATOR_MODE_FORCE_LOW  : MCPWM_DUTY_MODE_1;
104 	} else {
105 		duty_type = channel->duty == 0 ?
106 			MCPWM_HAL_GENERATOR_MODE_FORCE_LOW  : channel->duty == 100 ?
107 			MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH : MCPWM_DUTY_MODE_0;
108 	}
109 
110 	set_duty = mcpwm_ll_timer_get_peak(data->hal.dev, channel->timer_id, false) *
111 		   channel->duty / 100;
112 	mcpwm_ll_operator_select_timer(data->hal.dev, channel->operator_id, channel->timer_id);
113 	mcpwm_ll_operator_set_compare_value(data->hal.dev, channel->operator_id,
114 					    channel->generator_id, set_duty);
115 	mcpwm_ll_operator_enable_update_compare_on_tez(data->hal.dev, channel->operator_id,
116 						       channel->generator_id, true);
117 
118 	if (duty_type == MCPWM_DUTY_MODE_0) {
119 		mcpwm_ll_generator_set_action_on_timer_event(
120 			data->hal.dev, channel->operator_id, channel->generator_id,
121 			MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_GEN_ACTION_HIGH);
122 		mcpwm_ll_generator_set_action_on_timer_event(
123 			data->hal.dev, channel->operator_id, channel->generator_id,
124 			MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_GEN_ACTION_KEEP);
125 		mcpwm_ll_generator_set_action_on_compare_event(
126 			data->hal.dev, channel->operator_id, channel->generator_id,
127 			MCPWM_TIMER_DIRECTION_UP, channel->generator_id, MCPWM_ACTION_FORCE_LOW);
128 	} else if (duty_type == MCPWM_DUTY_MODE_1) {
129 		mcpwm_ll_generator_set_action_on_timer_event(
130 			data->hal.dev, channel->operator_id, channel->generator_id,
131 			MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_GEN_ACTION_LOW);
132 		mcpwm_ll_generator_set_action_on_timer_event(
133 			data->hal.dev, channel->operator_id, channel->generator_id,
134 			MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_NO_CHANGE);
135 		mcpwm_ll_generator_set_action_on_compare_event(
136 			data->hal.dev, channel->operator_id, channel->generator_id,
137 			MCPWM_TIMER_DIRECTION_UP, channel->generator_id, MCPWM_ACTION_FORCE_HIGH);
138 	} else if (duty_type == MCPWM_HAL_GENERATOR_MODE_FORCE_LOW) {
139 		mcpwm_ll_generator_set_action_on_timer_event(
140 			data->hal.dev, channel->operator_id, channel->generator_id,
141 			MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_LOW);
142 		mcpwm_ll_generator_set_action_on_timer_event(
143 			data->hal.dev, channel->operator_id, channel->generator_id,
144 			MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_LOW);
145 		mcpwm_ll_generator_set_action_on_compare_event(
146 			data->hal.dev, channel->operator_id, channel->generator_id,
147 			MCPWM_TIMER_DIRECTION_UP, channel->generator_id, MCPWM_ACTION_FORCE_LOW);
148 	} else if (duty_type == MCPWM_HAL_GENERATOR_MODE_FORCE_HIGH) {
149 		mcpwm_ll_generator_set_action_on_timer_event(
150 			data->hal.dev, channel->operator_id, channel->generator_id,
151 			MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_ZERO, MCPWM_ACTION_FORCE_HIGH);
152 		mcpwm_ll_generator_set_action_on_timer_event(
153 			data->hal.dev, channel->operator_id, channel->generator_id,
154 			MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_PEAK, MCPWM_ACTION_FORCE_HIGH);
155 		mcpwm_ll_generator_set_action_on_compare_event(
156 			data->hal.dev, channel->operator_id, channel->generator_id,
157 			MCPWM_TIMER_DIRECTION_UP, channel->generator_id, MCPWM_ACTION_FORCE_HIGH);
158 	}
159 }
160 
mcpwm_esp32_configure_pinctrl(const struct device * dev)161 static int mcpwm_esp32_configure_pinctrl(const struct device *dev)
162 {
163 	int ret;
164 	struct mcpwm_esp32_config *config = (struct mcpwm_esp32_config *)dev->config;
165 
166 	ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
167 	if (ret < 0) {
168 		LOG_ERR("PWM pinctrl setup failed (%d)", ret);
169 		return ret;
170 	}
171 	return 0;
172 }
173 
mcpwm_esp32_timer_set(const struct device * dev,struct mcpwm_esp32_channel_config * channel)174 static int mcpwm_esp32_timer_set(const struct device *dev,
175 				 struct mcpwm_esp32_channel_config *channel)
176 {
177 	struct mcpwm_esp32_data *data = (struct mcpwm_esp32_data *const)(dev)->data;
178 
179 	__ASSERT_NO_MSG(channel->freq > 0);
180 
181 	mcpwm_ll_timer_set_clock_prescale(data->hal.dev, channel->timer_id, channel->prescale);
182 	mcpwm_ll_timer_set_count_mode(data->hal.dev, channel->timer_id, MCPWM_TIMER_COUNT_MODE_UP);
183 	mcpwm_ll_timer_update_period_at_once(data->hal.dev, channel->timer_id);
184 	int real_group_prescale = mcpwm_ll_group_get_clock_prescale(data->hal.dev);
185 	uint32_t real_timer_clk_hz =
186 		SOC_MCPWM_BASE_CLK_HZ / real_group_prescale /
187 		mcpwm_ll_timer_get_clock_prescale(data->hal.dev, channel->timer_id);
188 	mcpwm_ll_timer_set_peak(data->hal.dev, channel->timer_id, real_timer_clk_hz / channel->freq,
189 				false);
190 
191 	return 0;
192 }
193 
mcpwm_esp32_get_cycles_per_sec(const struct device * dev,uint32_t channel_idx,uint64_t * cycles)194 static int mcpwm_esp32_get_cycles_per_sec(const struct device *dev, uint32_t channel_idx,
195 					  uint64_t *cycles)
196 {
197 	struct mcpwm_esp32_config *config = (struct mcpwm_esp32_config *)dev->config;
198 	struct mcpwm_esp32_channel_config *channel = &config->channel_config[channel_idx];
199 
200 	if (!channel) {
201 		LOG_ERR("Error getting channel %d", channel_idx);
202 		return -EINVAL;
203 	}
204 
205 #ifdef CONFIG_PWM_CAPTURE
206 	if (channel->idx >= CAPTURE_CHANNEL_IDX) {
207 		*cycles = (uint64_t)APB_CLK_FREQ;
208 		return 0;
209 	}
210 #endif /* CONFIG_PWM_CAPTURE */
211 
212 	*cycles =
213 		(uint64_t)SOC_MCPWM_BASE_CLK_HZ / (config->prescale + 1) / (channel->prescale + 1);
214 
215 	return 0;
216 }
217 
mcpwm_esp32_set_cycles(const struct device * dev,uint32_t channel_idx,uint32_t period_cycles,uint32_t pulse_cycles,pwm_flags_t flags)218 static int mcpwm_esp32_set_cycles(const struct device *dev, uint32_t channel_idx,
219 				  uint32_t period_cycles, uint32_t pulse_cycles, pwm_flags_t flags)
220 {
221 	int ret = 0;
222 	uint64_t clk_freq;
223 	struct mcpwm_esp32_config *config = (struct mcpwm_esp32_config *)dev->config;
224 	struct mcpwm_esp32_data *data = (struct mcpwm_esp32_data *const)(dev)->data;
225 	struct mcpwm_esp32_channel_config *channel = &config->channel_config[channel_idx];
226 
227 	if (!channel) {
228 		LOG_ERR("Error getting channel %d", channel_idx);
229 		return -EINVAL;
230 	}
231 
232 	/* Update PWM frequency according to period_cycles */
233 	mcpwm_esp32_get_cycles_per_sec(dev, channel_idx, &clk_freq);
234 
235 	channel->freq = (uint32_t)(clk_freq / period_cycles);
236 	if (!channel->freq) {
237 		return -EINVAL;
238 	}
239 
240 	k_sem_take(&data->cmd_sem, K_FOREVER);
241 
242 	ret = mcpwm_esp32_timer_set(dev, channel);
243 	if (ret < 0) {
244 		k_sem_give(&data->cmd_sem);
245 		return ret;
246 	}
247 
248 	double duty_cycle = (double)pulse_cycles * 100 / (double)period_cycles;
249 
250 	channel->duty = (uint32_t)duty_cycle;
251 
252 	channel->inverted = (flags & PWM_POLARITY_INVERTED);
253 
254 	mcpwm_esp32_duty_set(dev, channel);
255 
256 	ret = mcpwm_esp32_configure_pinctrl(dev);
257 	if (ret < 0) {
258 		k_sem_give(&data->cmd_sem);
259 		return ret;
260 	}
261 
262 	mcpwm_ll_timer_set_execute_command(data->hal.dev, channel->timer_id,
263 					   MCPWM_TIMER_START_NO_STOP);
264 
265 	k_sem_give(&data->cmd_sem);
266 
267 	return ret;
268 }
269 
270 #ifdef CONFIG_PWM_CAPTURE
mcpwm_esp32_configure_capture(const struct device * dev,uint32_t channel_idx,pwm_flags_t flags,pwm_capture_callback_handler_t cb,void * user_data)271 static int mcpwm_esp32_configure_capture(const struct device *dev, uint32_t channel_idx,
272 					 pwm_flags_t flags, pwm_capture_callback_handler_t cb,
273 					 void *user_data)
274 {
275 	struct mcpwm_esp32_config *config = (struct mcpwm_esp32_config *)dev->config;
276 	struct mcpwm_esp32_data *data = (struct mcpwm_esp32_data *const)(dev)->data;
277 	struct mcpwm_esp32_channel_config *channel = &config->channel_config[channel_idx];
278 	struct mcpwm_esp32_capture_config *capture = &channel->capture;
279 
280 	if (!channel) {
281 		LOG_ERR("Error getting channel %d", channel_idx);
282 		return -EINVAL;
283 	}
284 
285 	if ((channel->idx < CAPTURE_CHANNEL_IDX) || (channel->idx > CAPTURE_CHANNEL_IDX + 2)) {
286 		LOG_ERR("PWM capture only supported on channels 6, 7 and 8");
287 		return -EINVAL;
288 	}
289 
290 	if (data->hal.dev->cap_chn_cfg[capture->capture_signal].capn_en) {
291 		LOG_ERR("PWM Capture already in progress");
292 		return -EBUSY;
293 	}
294 
295 	if (!(flags & PWM_CAPTURE_TYPE_MASK)) {
296 		LOG_ERR("No PWM capture type specified");
297 		return -EINVAL;
298 	}
299 
300 	channel->inverted = (flags & PWM_POLARITY_INVERTED);
301 	capture->capture_signal = channel->idx - CAPTURE_CHANNEL_IDX;
302 	capture->callback = cb;
303 	capture->user_data = user_data;
304 	capture->capture_period = (flags & PWM_CAPTURE_TYPE_PERIOD);
305 	capture->capture_pulse = (flags & PWM_CAPTURE_TYPE_PULSE);
306 	capture->continuous = (flags & PWM_CAPTURE_MODE_CONTINUOUS);
307 
308 	return 0;
309 }
310 
mcpwm_esp32_disable_capture(const struct device * dev,uint32_t channel_idx)311 static int mcpwm_esp32_disable_capture(const struct device *dev, uint32_t channel_idx)
312 {
313 	struct mcpwm_esp32_config *config = (struct mcpwm_esp32_config *)dev->config;
314 	struct mcpwm_esp32_data *data = (struct mcpwm_esp32_data *const)(dev)->data;
315 	struct mcpwm_esp32_channel_config *channel = &config->channel_config[channel_idx];
316 	struct mcpwm_esp32_capture_config *capture = &channel->capture;
317 
318 	if (!channel) {
319 		LOG_ERR("Error getting channel %d", channel_idx);
320 		return -EINVAL;
321 	}
322 
323 	if ((channel->idx < CAPTURE_CHANNEL_IDX) || (channel->idx > CAPTURE_CHANNEL_IDX + 2)) {
324 		LOG_ERR("PWM capture only supported on channels 6, 7 and 8");
325 		return -EINVAL;
326 	}
327 
328 	mcpwm_ll_capture_enable_channel(data->hal.dev, capture->capture_signal, false);
329 	mcpwm_ll_intr_enable_capture(data->hal.dev, capture->capture_signal, false);
330 
331 	return 0;
332 }
333 
mcpwm_esp32_enable_capture(const struct device * dev,uint32_t channel_idx)334 static int mcpwm_esp32_enable_capture(const struct device *dev, uint32_t channel_idx)
335 {
336 	struct mcpwm_esp32_config *config = (struct mcpwm_esp32_config *)dev->config;
337 	struct mcpwm_esp32_data *data = (struct mcpwm_esp32_data *const)(dev)->data;
338 	struct mcpwm_esp32_channel_config *channel = &config->channel_config[channel_idx];
339 	struct mcpwm_esp32_capture_config *capture = &channel->capture;
340 
341 	if (!channel) {
342 		LOG_ERR("Error getting channel %d", channel_idx);
343 		return -EINVAL;
344 	}
345 
346 	if (!capture->callback) {
347 		LOG_ERR("Capture not configured");
348 		return -EINVAL;
349 	}
350 
351 	if ((channel->idx < CAPTURE_CHANNEL_IDX) || (channel->idx > CAPTURE_CHANNEL_IDX + 2)) {
352 		LOG_ERR("PWM capture only supported on channels 6, 7 and 8");
353 		return -EINVAL;
354 	}
355 
356 	if (data->hal.dev->cap_chn_cfg[capture->capture_signal].capn_en) {
357 		LOG_ERR("PWM Capture already in progress");
358 		return -EBUSY;
359 	}
360 
361 	/**
362 	 * Capture prescale is different from other modules as it is applied to the input
363 	 * signal, not the timer source. It is disabled by default.
364 	 */
365 	mcpwm_capture_config_t cap_conf = {
366 		.cap_edge = MCPWM_BOTH_EDGE,
367 		.cap_prescale = 1,
368 	};
369 
370 	mcpwm_hal_init(&data->hal, &data->init_config);
371 	mcpwm_ll_group_set_clock_prescale(data->hal.dev, config->prescale);
372 	mcpwm_ll_group_enable_shadow_mode(data->hal.dev);
373 	mcpwm_ll_group_flush_shadow(data->hal.dev);
374 
375 	mcpwm_ll_capture_enable_timer(data->hal.dev, true);
376 	mcpwm_ll_capture_enable_channel(data->hal.dev, capture->capture_signal, true);
377 	mcpwm_ll_capture_enable_negedge(data->hal.dev, capture->capture_signal,
378 					cap_conf.cap_edge & MCPWM_NEG_EDGE);
379 	mcpwm_ll_capture_enable_posedge(data->hal.dev, capture->capture_signal,
380 					cap_conf.cap_edge & MCPWM_POS_EDGE);
381 	mcpwm_ll_capture_set_prescale(data->hal.dev, capture->capture_signal,
382 				      cap_conf.cap_prescale);
383 
384 	mcpwm_ll_intr_enable_capture(data->hal.dev, capture->capture_signal, true);
385 	mcpwm_ll_intr_clear_capture_status(data->hal.dev, 1 << capture->capture_signal);
386 
387 	capture->skip_irq = 0;
388 
389 	return 0;
390 }
391 #endif /* CONFIG_PWM_CAPTURE */
392 
channel_init(const struct device * dev)393 static void channel_init(const struct device *dev)
394 {
395 	struct mcpwm_esp32_config *config = (struct mcpwm_esp32_config *)dev->config;
396 	struct mcpwm_esp32_channel_config *channel;
397 
398 	for (uint8_t i = 0; i < MCPWM_CHANNEL_NUM; i++) {
399 		channel = &config->channel_config[i];
400 		channel->idx = i;
401 		channel->timer_id = i < 2 ? 0 : i < 4 ? 1 : 2;
402 		channel->operator_id = i < 2 ? 0 : i < 4 ? 1 : 2;
403 		channel->generator_id = i % 2 ? 1 : 0;
404 		channel->prescale = i < 2   ? config->prescale_timer0
405 				    : i < 4 ? config->prescale_timer1
406 					    : config->prescale_timer2;
407 	}
408 }
409 
mcpwm_esp32_init(const struct device * dev)410 int mcpwm_esp32_init(const struct device *dev)
411 {
412 	int ret;
413 	struct mcpwm_esp32_config *config = (struct mcpwm_esp32_config *)dev->config;
414 	struct mcpwm_esp32_data *data = (struct mcpwm_esp32_data *const)(dev)->data;
415 	struct mcpwm_esp32_channel_config *channel;
416 
417 	if (!device_is_ready(config->clock_dev)) {
418 		LOG_ERR("clock control device not ready");
419 		return -ENODEV;
420 	}
421 
422 	/* Enable peripheral */
423 	ret = clock_control_on(config->clock_dev, config->clock_subsys);
424 	if (ret < 0) {
425 		LOG_ERR("Could not initialize clock (%d)", ret);
426 		return ret;
427 	}
428 
429 	channel_init(dev);
430 
431 	mcpwm_hal_init(&data->hal, &data->init_config);
432 	mcpwm_ll_group_set_clock_prescale(data->hal.dev, config->prescale);
433 	mcpwm_ll_group_enable_shadow_mode(data->hal.dev);
434 	mcpwm_ll_group_flush_shadow(data->hal.dev);
435 
436 #ifdef CONFIG_PWM_CAPTURE
437 	config->irq_config_func(dev);
438 #endif /* CONFIG_PWM_CAPTURE */
439 	return 0;
440 }
441 
442 #ifdef CONFIG_PWM_CAPTURE
mcpwm_esp32_isr(const struct device * dev)443 static void IRAM_ATTR mcpwm_esp32_isr(const struct device *dev)
444 {
445 	struct mcpwm_esp32_config *config = (struct mcpwm_esp32_config *)dev->config;
446 	struct mcpwm_esp32_data *data = (struct mcpwm_esp32_data *const)(dev)->data;
447 	struct mcpwm_esp32_channel_config *channel;
448 	struct mcpwm_esp32_capture_config *capture;
449 	uint32_t mcpwm_intr_status;
450 	struct capture_data cap_data;
451 
452 	mcpwm_intr_status = mcpwm_ll_intr_get_capture_status(data->hal.dev);
453 
454 	mcpwm_ll_intr_clear_capture_status(data->hal.dev, mcpwm_intr_status);
455 
456 	if (mcpwm_intr_status & MCPWM_INTR_CAP0) {
457 		channel = &config->channel_config[CAPTURE_CHANNEL_IDX];
458 	} else if (mcpwm_intr_status & MCPWM_INTR_CAP1) {
459 		channel = &config->channel_config[CAPTURE_CHANNEL_IDX + 1];
460 	} else if (mcpwm_intr_status & MCPWM_INTR_CAP2) {
461 		channel = &config->channel_config[CAPTURE_CHANNEL_IDX + 2];
462 	} else {
463 		return;
464 	}
465 
466 	if (!channel) {
467 		return;
468 	}
469 
470 	capture = &channel->capture;
471 
472 	/* We need to wait at least 4 (2 positive edges and 2 negative edges) interrupts to
473 	 * calculate the period
474 	 */
475 	if (capture->skip_irq < SKIP_IRQ_NUM) {
476 		capture->capture_data[capture->skip_irq].value =
477 			mcpwm_ll_capture_get_value(data->hal.dev, capture->capture_signal);
478 		capture->capture_data[capture->skip_irq].edge =
479 			mcpwm_ll_capture_is_negedge(data->hal.dev, capture->capture_signal)
480 				? MCPWM_NEG_EDGE
481 				: MCPWM_POS_EDGE;
482 		capture->skip_irq++;
483 
484 	} else {
485 		/**
486 		 * The capture timer is a 32-bit counter incrementing continuously, once enabled.
487 		 * On the input it has an APB clock running typically at 80 MHz
488 		 */
489 		capture->period = channel->inverted ?
490 			capture->capture_data[0].edge == MCPWM_NEG_EDGE
491 				? (capture->capture_data[2].value - capture->capture_data[0].value)
492 				: (capture->capture_data[3].value - capture->capture_data[1].value)
493 			: capture->capture_data[0].edge == MCPWM_POS_EDGE
494 				? (capture->capture_data[2].value - capture->capture_data[0].value)
495 				: (capture->capture_data[3].value - capture->capture_data[1].value);
496 
497 		capture->pulse = channel->inverted ?
498 			capture->capture_data[0].edge == MCPWM_NEG_EDGE
499 				? (capture->capture_data[1].value - capture->capture_data[0].value)
500 				: (capture->capture_data[2].value - capture->capture_data[1].value)
501 			: capture->capture_data[0].edge == MCPWM_POS_EDGE
502 				? (capture->capture_data[1].value - capture->capture_data[0].value)
503 				: (capture->capture_data[2].value - capture->capture_data[1].value);
504 
505 		capture->skip_irq = 0;
506 		if (!capture->continuous) {
507 			mcpwm_esp32_disable_capture(dev, channel->idx);
508 		}
509 
510 		if (capture->callback) {
511 			capture->callback(dev, capture->capture_signal + CAPTURE_CHANNEL_IDX,
512 					  capture->capture_period ? capture->period : 0u,
513 					  capture->capture_pulse ? capture->pulse : 0u, 0u,
514 					  capture->user_data);
515 		}
516 	}
517 }
518 #endif /* CONFIG_PWM_CAPTURE */
519 
520 static const struct pwm_driver_api mcpwm_esp32_api = {
521 	.set_cycles = mcpwm_esp32_set_cycles,
522 	.get_cycles_per_sec = mcpwm_esp32_get_cycles_per_sec,
523 #ifdef CONFIG_PWM_CAPTURE
524 	.configure_capture = mcpwm_esp32_configure_capture,
525 	.enable_capture = mcpwm_esp32_enable_capture,
526 	.disable_capture = mcpwm_esp32_disable_capture,
527 #endif /* CONFIG_PWM_CAPTURE */
528 };
529 
530 #ifdef CONFIG_PWM_CAPTURE
531 #define IRQ_CONFIG_FUNC(idx)                                                                       \
532 	static void mcpwm_esp32_irq_config_func_##idx(const struct device *dev)                    \
533 	{                                                                                          \
534 		esp_intr_alloc(DT_INST_IRQN(idx), 0, (intr_handler_t)mcpwm_esp32_isr, (void *)dev, \
535 			       NULL);                                                              \
536 	}
537 #define CAPTURE_INIT(idx) .irq_config_func = mcpwm_esp32_irq_config_func_##idx
538 #else
539 #define IRQ_CONFIG_FUNC(idx)
540 #define CAPTURE_INIT(idx)
541 #endif /* CONFIG_PWM_CAPTURE */
542 
543 #define ESP32_MCPWM_INIT(idx)                                                                      \
544 	PINCTRL_DT_INST_DEFINE(idx);                                                               \
545 	IRQ_CONFIG_FUNC(idx);                                                                      \
546 	static struct mcpwm_esp32_data mcpwm_esp32_data_##idx = {                                  \
547 		.hal =                                                                             \
548 			{                                                                          \
549 				.dev = (mcpwm_dev_t *)DT_INST_REG_ADDR(idx),                       \
550 			},                                                                         \
551 		.init_config =                                                                     \
552 			{                                                                          \
553 				.host_id = idx,                                                    \
554 			},                                                                         \
555 		.cmd_sem = Z_SEM_INITIALIZER(mcpwm_esp32_data_##idx.cmd_sem, 1, 1),                \
556 	};                                                                                         \
557                                                                                                    \
558 	static struct mcpwm_esp32_config mcpwm_esp32_config_##idx = {                              \
559 		.index = idx,                                                                      \
560 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx),                                     \
561 		.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)),                              \
562 		.clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset),          \
563 		.prescale = DT_INST_PROP(idx, prescale),                                           \
564 		.prescale_timer0 = DT_INST_PROP_OR(idx, prescale_timer0, 0),                       \
565 		.prescale_timer1 = DT_INST_PROP_OR(idx, prescale_timer1, 0),                       \
566 		.prescale_timer2 = DT_INST_PROP_OR(idx, prescale_timer2, 0),                       \
567 		CAPTURE_INIT(idx)};                                                                \
568                                                                                                    \
569 	DEVICE_DT_INST_DEFINE(idx, &mcpwm_esp32_init, NULL, &mcpwm_esp32_data_##idx,               \
570 			      &mcpwm_esp32_config_##idx, POST_KERNEL,                              \
571 			      CONFIG_PWM_INIT_PRIORITY, &mcpwm_esp32_api);
572 
573 DT_INST_FOREACH_STATUS_OKAY(ESP32_MCPWM_INIT)
574