1 /*
2  * Copyright (c) 2017 Vitor Massaru Iha <vitor@massaru.org>
3  * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT espressif_esp32_ledc
9 
10 #include <hal/ledc_hal.h>
11 #include <hal/ledc_types.h>
12 #include <esp_clk_tree.h>
13 
14 #include <soc.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <zephyr/drivers/pwm.h>
18 #include <zephyr/kernel.h>
19 #include <zephyr/drivers/pinctrl.h>
20 #include <zephyr/drivers/clock_control.h>
21 
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_REGISTER(pwm_ledc_esp32, CONFIG_PWM_LOG_LEVEL);
24 
25 static const int global_clks[] = LEDC_LL_GLOBAL_CLOCKS;
26 #if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
27 static const int timer_specific_clks[] = LEDC_LL_TIMER_SPECIFIC_CLOCKS;
28 static int lowspd_clks[ARRAY_SIZE(global_clks) + ARRAY_SIZE(timer_specific_clks)];
29 #endif
30 #if SOC_LEDC_SUPPORT_HS_MODE
31 static const int highspd_clks[] = {LEDC_APB_CLK, LEDC_REF_TICK};
32 #endif
33 
34 struct pwm_ledc_esp32_data {
35 	ledc_hal_context_t hal;
36 	struct k_sem cmd_sem;
37 };
38 
39 struct pwm_ledc_esp32_channel_config {
40 	const uint8_t idx;
41 	const uint8_t channel_num;
42 	const uint8_t timer_num;
43 	uint32_t freq;
44 	const ledc_mode_t speed_mode;
45 	uint8_t resolution;
46 	ledc_clk_src_t clock_src;
47 	uint32_t clock_src_hz;
48 	uint32_t duty_val;
49 	bool inverted;
50 };
51 
52 struct pwm_ledc_esp32_config {
53 	const struct pinctrl_dev_config *pincfg;
54 	const struct device *clock_dev;
55 	const clock_control_subsys_t clock_subsys;
56 	struct pwm_ledc_esp32_channel_config *channel_config;
57 	const int channel_len;
58 };
59 
get_channel_config(const struct device * dev,int channel_id)60 static struct pwm_ledc_esp32_channel_config *get_channel_config(const struct device *dev,
61 								int channel_id)
62 {
63 	struct pwm_ledc_esp32_config *config = (struct pwm_ledc_esp32_config *)dev->config;
64 
65 	for (uint8_t i = 0; i < config->channel_len; i++) {
66 		if (config->channel_config[i].idx == channel_id) {
67 			return &config->channel_config[i];
68 		}
69 	}
70 	return NULL;
71 }
72 
pwm_led_esp32_start(struct pwm_ledc_esp32_data * data,struct pwm_ledc_esp32_channel_config * channel)73 static void pwm_led_esp32_start(struct pwm_ledc_esp32_data *data,
74 				struct pwm_ledc_esp32_channel_config *channel)
75 {
76 	ledc_hal_set_sig_out_en(&data->hal, channel->channel_num, true);
77 	ledc_hal_set_duty_start(&data->hal, channel->channel_num, true);
78 
79 	if (channel->speed_mode == LEDC_LOW_SPEED_MODE) {
80 		ledc_hal_ls_channel_update(&data->hal, channel->channel_num);
81 	}
82 }
83 
pwm_led_esp32_stop(struct pwm_ledc_esp32_data * data,struct pwm_ledc_esp32_channel_config * channel,bool idle_level)84 static void pwm_led_esp32_stop(struct pwm_ledc_esp32_data *data,
85 			       struct pwm_ledc_esp32_channel_config *channel, bool idle_level)
86 {
87 	ledc_hal_set_idle_level(&data->hal, channel->channel_num, idle_level);
88 	ledc_hal_set_sig_out_en(&data->hal, channel->channel_num, false);
89 	ledc_hal_set_duty_start(&data->hal, channel->channel_num, false);
90 
91 	if (channel->speed_mode == LEDC_LOW_SPEED_MODE) {
92 		ledc_hal_ls_channel_update(&data->hal, channel->channel_num);
93 	}
94 }
95 
pwm_led_esp32_duty_set(const struct device * dev,struct pwm_ledc_esp32_channel_config * channel)96 static void pwm_led_esp32_duty_set(const struct device *dev,
97 				   struct pwm_ledc_esp32_channel_config *channel)
98 {
99 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
100 
101 	ledc_hal_set_hpoint(&data->hal, channel->channel_num, 0);
102 	ledc_hal_set_duty_int_part(&data->hal, channel->channel_num, channel->duty_val);
103 	ledc_hal_set_duty_direction(&data->hal, channel->channel_num, 1);
104 	ledc_hal_set_duty_num(&data->hal, channel->channel_num, 1);
105 	ledc_hal_set_duty_cycle(&data->hal, channel->channel_num, 1);
106 	ledc_hal_set_duty_scale(&data->hal, channel->channel_num, 0);
107 }
108 
pwm_led_esp32_calculate_max_resolution(struct pwm_ledc_esp32_channel_config * channel)109 static int pwm_led_esp32_calculate_max_resolution(struct pwm_ledc_esp32_channel_config *channel)
110 {
111 	/**
112 	 * Max duty resolution can be obtained with
113 	 * max_res = log2(CLK_FREQ/FREQ)
114 	 */
115 	uint32_t max_precision_n = channel->clock_src_hz / channel->freq;
116 
117 	for (uint8_t i = 0; i <= SOC_LEDC_TIMER_BIT_WIDTH; i++) {
118 		max_precision_n /= 2;
119 		if (!max_precision_n) {
120 			channel->resolution = i;
121 			return 0;
122 		}
123 	}
124 	return -EINVAL;
125 }
126 
pwm_led_esp32_timer_config(struct pwm_ledc_esp32_channel_config * channel)127 static int pwm_led_esp32_timer_config(struct pwm_ledc_esp32_channel_config *channel)
128 {
129 	const int *clock_src;
130 	int clock_src_num;
131 
132 	if (channel->speed_mode == LEDC_LOW_SPEED_MODE) {
133 #ifdef SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
134 		clock_src = lowspd_clks;
135 		clock_src_num = ARRAY_SIZE(lowspd_clks);
136 #else
137 		clock_src = global_clks;
138 		clock_src_num = ARRAY_SIZE(global_clks);
139 #endif
140 	}
141 #ifdef SOC_LEDC_SUPPORT_HS_MODE
142 	else {
143 		clock_src = highspd_clks;
144 		clock_src_num = ARRAY_SIZE(highspd_clks);
145 	}
146 #endif
147 
148 	/**
149 	 * Calculate max resolution based on the given frequency and the pwm clock.
150 	 * Try each clock source available depending on the device and channel type.
151 	 */
152 	for (int i = 0; i < clock_src_num; i++) {
153 		channel->clock_src = clock_src[i];
154 		esp_clk_tree_src_get_freq_hz(channel->clock_src,
155 					     ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED,
156 					     &channel->clock_src_hz);
157 		if (!pwm_led_esp32_calculate_max_resolution(channel)) {
158 			return 0;
159 		}
160 	}
161 
162 	/* Frequency is too low for this device, so even though best precision can't
163 	 * be achieved we can set max resolution and consider that the previous
164 	 * loop selects clock from fastest to slowest, so this is the best
165 	 * configuration achievable.
166 	 */
167 	channel->resolution = SOC_LEDC_TIMER_BIT_WIDTH;
168 
169 	return 0;
170 }
171 
pwm_led_esp32_timer_set(const struct device * dev,struct pwm_ledc_esp32_channel_config * channel)172 static int pwm_led_esp32_timer_set(const struct device *dev,
173 				   struct pwm_ledc_esp32_channel_config *channel)
174 {
175 	int prescaler = 0;
176 	uint32_t precision = (0x1 << channel->resolution);
177 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
178 
179 	__ASSERT_NO_MSG(channel->freq > 0);
180 
181 	prescaler = ((uint64_t)channel->clock_src_hz << 8) / channel->freq / precision;
182 
183 	if (prescaler < 0x100 || prescaler > 0x3FFFF) {
184 		LOG_ERR("Prescaler out of range: %#X", prescaler);
185 		return -EINVAL;
186 	}
187 
188 	if (channel->speed_mode == LEDC_LOW_SPEED_MODE) {
189 		ledc_hal_set_slow_clk_sel(&data->hal, channel->clock_src);
190 	}
191 
192 	ledc_hal_set_clock_divider(&data->hal, channel->timer_num, prescaler);
193 	ledc_hal_set_duty_resolution(&data->hal, channel->timer_num, channel->resolution);
194 	ledc_hal_set_clock_source(&data->hal, channel->timer_num, channel->clock_src);
195 
196 	if (channel->speed_mode == LEDC_LOW_SPEED_MODE) {
197 		ledc_hal_ls_timer_update(&data->hal, channel->timer_num);
198 	}
199 
200 	LOG_DBG("channel_num=%d, speed_mode=%d, timer_num=%d, clock_src=%d, prescaler=%d, "
201 		"resolution=%d\n",
202 		channel->channel_num, channel->speed_mode, channel->timer_num, channel->clock_src,
203 		prescaler, channel->resolution);
204 
205 	return 0;
206 }
207 
pwm_led_esp32_get_cycles_per_sec(const struct device * dev,uint32_t channel_idx,uint64_t * cycles)208 static int pwm_led_esp32_get_cycles_per_sec(const struct device *dev, uint32_t channel_idx,
209 					    uint64_t *cycles)
210 {
211 	struct pwm_ledc_esp32_channel_config *channel = get_channel_config(dev, channel_idx);
212 
213 	if (!channel) {
214 		LOG_ERR("Error getting channel %d", channel_idx);
215 		return -EINVAL;
216 	}
217 
218 	*cycles = (uint64_t)channel->clock_src_hz;
219 
220 	return 0;
221 }
222 
pwm_led_esp32_channel_update_frequency(const struct device * dev,struct pwm_ledc_esp32_channel_config * channel,uint32_t period_cycles)223 static int pwm_led_esp32_channel_update_frequency(const struct device *dev,
224 						  struct pwm_ledc_esp32_channel_config *channel,
225 						  uint32_t period_cycles)
226 {
227 	const struct pwm_ledc_esp32_config *config = dev->config;
228 	uint32_t current_freq = channel->freq;
229 	uint64_t clk_freq;
230 	int ret;
231 
232 	ret = pwm_led_esp32_get_cycles_per_sec(dev, channel->idx, &clk_freq);
233 
234 	if (ret < 0) {
235 		return ret;
236 	}
237 
238 	channel->freq = (uint32_t)(clk_freq / period_cycles);
239 
240 	if (!channel->freq) {
241 		channel->freq = 1;
242 	}
243 
244 	if (channel->freq == current_freq) {
245 		/* No need to reconfigure timer */
246 		return 0;
247 	}
248 
249 	/* Check whether another channel is using the same timer.
250 	 * Timers can only be shared if the same frequency is used, so
251 	 * first set operation will take precedence.
252 	 */
253 	for (int i = 0; i < config->channel_len; ++i) {
254 		struct pwm_ledc_esp32_channel_config *ch = &config->channel_config[i];
255 
256 		if (ch->freq && (channel->channel_num != ch->channel_num) &&
257 			(channel->timer_num == ch->timer_num) &&
258 			(channel->speed_mode == ch->speed_mode) &&
259 			(channel->freq != ch->freq)) {
260 			LOG_ERR("Timer can't be shared and different frequency be "
261 				"requested");
262 			channel->freq = 0;
263 			return -EINVAL;
264 		}
265 	}
266 
267 	pwm_led_esp32_timer_config(channel);
268 
269 	ret = pwm_led_esp32_timer_set(dev, channel);
270 
271 	if (ret < 0) {
272 		LOG_ERR("Error setting timer for channel %d", channel->idx);
273 		return ret;
274 	}
275 
276 	return 0;
277 }
278 
pwm_led_esp32_set_cycles(const struct device * dev,uint32_t channel_idx,uint32_t period_cycles,uint32_t pulse_cycles,pwm_flags_t flags)279 static int pwm_led_esp32_set_cycles(const struct device *dev, uint32_t channel_idx,
280 				    uint32_t period_cycles, uint32_t pulse_cycles,
281 				    pwm_flags_t flags)
282 {
283 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
284 	struct pwm_ledc_esp32_channel_config *channel = get_channel_config(dev, channel_idx);
285 	int ret = 0;
286 
287 	if (!channel) {
288 		LOG_ERR("Error getting channel %d", channel_idx);
289 		return -EINVAL;
290 	}
291 
292 	k_sem_take(&data->cmd_sem, K_FOREVER);
293 
294 	if (flags & PWM_POLARITY_INVERTED) {
295 		pulse_cycles = period_cycles - pulse_cycles;
296 		channel->inverted = true;
297 	} else {
298 		channel->inverted = false;
299 	}
300 
301 	ledc_hal_init(&data->hal, channel->speed_mode);
302 
303 	if ((pulse_cycles == period_cycles) || (pulse_cycles == 0)) {
304 		/* For duty 0% and 100% stop PWM, set output level and return */
305 		pwm_led_esp32_stop(data, channel, (pulse_cycles == period_cycles));
306 		goto sem_give;
307 	}
308 
309 	ret = pwm_led_esp32_channel_update_frequency(dev, channel, period_cycles);
310 
311 	if (ret < 0) {
312 		LOG_ERR("Error updating frequency of channel %d", channel_idx);
313 		goto sem_give;
314 	}
315 
316 	/* Update PWM duty  */
317 
318 	double duty_cycle = (double)pulse_cycles / (double)period_cycles;
319 
320 	channel->duty_val = (uint32_t)((double)(1 << channel->resolution) * duty_cycle);
321 
322 	pwm_led_esp32_duty_set(dev, channel);
323 
324 	pwm_led_esp32_start(data, channel);
325 
326 sem_give:
327 	k_sem_give(&data->cmd_sem);
328 
329 	return ret;
330 }
331 
pwm_led_esp32_init(const struct device * dev)332 int pwm_led_esp32_init(const struct device *dev)
333 {
334 	const struct pwm_ledc_esp32_config *config = dev->config;
335 	struct pwm_ledc_esp32_data *data = dev->data;
336 	struct pwm_ledc_esp32_channel_config *channel;
337 	int ret = 0;
338 
339 	if (!device_is_ready(config->clock_dev)) {
340 		LOG_ERR("clock control device not ready");
341 		return -ENODEV;
342 	}
343 
344 	/* Enable peripheral */
345 	clock_control_on(config->clock_dev, config->clock_subsys);
346 
347 #if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
348 	/* Combine clock sources to include timer specific sources */
349 	memcpy(lowspd_clks, global_clks, sizeof(global_clks));
350 	memcpy(&lowspd_clks[ARRAY_SIZE(global_clks)], timer_specific_clks,
351 	       sizeof(timer_specific_clks));
352 #endif
353 
354 	for (int i = 0; i < config->channel_len; ++i) {
355 		channel = &config->channel_config[i];
356 
357 		ledc_hal_init(&data->hal, channel->speed_mode);
358 
359 		if (channel->speed_mode == LEDC_LOW_SPEED_MODE) {
360 			channel->clock_src = global_clks[0];
361 			ledc_hal_set_slow_clk_sel(&data->hal, channel->clock_src);
362 		}
363 #ifdef SOC_LEDC_SUPPORT_HS_MODE
364 		else {
365 			channel->clock_src = highspd_clks[0];
366 		}
367 #endif
368 		ledc_hal_set_clock_source(&data->hal, channel->timer_num, channel->clock_src);
369 
370 		esp_clk_tree_src_get_freq_hz(channel->clock_src,
371 					     ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED,
372 					     &channel->clock_src_hz);
373 
374 		ledc_hal_bind_channel_timer(&data->hal, channel->channel_num, channel->timer_num);
375 		pwm_led_esp32_stop(data, channel, channel->inverted);
376 		ledc_hal_timer_rst(&data->hal, channel->timer_num);
377 	}
378 
379 	ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
380 
381 	if (ret < 0) {
382 		LOG_ERR("PWM pinctrl setup failed (%d)", ret);
383 		return ret;
384 	}
385 
386 	return 0;
387 }
388 
389 static DEVICE_API(pwm, pwm_led_esp32_api) = {
390 	.set_cycles = pwm_led_esp32_set_cycles,
391 	.get_cycles_per_sec = pwm_led_esp32_get_cycles_per_sec,
392 };
393 
394 PINCTRL_DT_INST_DEFINE(0);
395 
396 #define CHANNEL_CONFIG(node_id)                                                                    \
397 	{                                                                                          \
398 		.idx = DT_REG_ADDR(node_id),                                                       \
399 		.channel_num = DT_REG_ADDR(node_id) % 8,                                           \
400 		.timer_num = DT_PROP(node_id, timer),                                              \
401 		.speed_mode = DT_REG_ADDR(node_id) < SOC_LEDC_CHANNEL_NUM ? LEDC_LOW_SPEED_MODE    \
402 									  : !LEDC_LOW_SPEED_MODE,  \
403 		.inverted = DT_PROP(node_id, inverted),                                            \
404 	},
405 
406 static struct pwm_ledc_esp32_channel_config channel_config[] = {
407 	DT_INST_FOREACH_CHILD(0, CHANNEL_CONFIG)};
408 
409 static struct pwm_ledc_esp32_config pwm_ledc_esp32_config = {
410 	.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
411 	.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
412 	.clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(0, offset),
413 	.channel_config = channel_config,
414 	.channel_len = ARRAY_SIZE(channel_config),
415 };
416 
417 static struct pwm_ledc_esp32_data pwm_ledc_esp32_data = {
418 	.hal = {
419 		.dev = (ledc_dev_t *) DT_INST_REG_ADDR(0),
420 	},
421 	.cmd_sem = Z_SEM_INITIALIZER(pwm_ledc_esp32_data.cmd_sem, 1, 1),
422 };
423 
424 DEVICE_DT_INST_DEFINE(0, &pwm_led_esp32_init, NULL, &pwm_ledc_esp32_data, &pwm_ledc_esp32_config,
425 		      POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, &pwm_led_esp32_api);
426