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