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