1 /*
2  * Copyright (c) 2017 Vitor Massaru Iha <vitor@massaru.org>
3  * Copyright (c) 2022 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 esp-idf headers first to avoid redefining BIT() macro */
11 #include <hal/ledc_hal.h>
12 #include <hal/ledc_types.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 struct pwm_ledc_esp32_data {
26 	ledc_hal_context_t hal;
27 	struct k_sem cmd_sem;
28 };
29 
30 struct pwm_ledc_esp32_channel_config {
31 	const uint8_t idx;
32 	const uint8_t channel_num;
33 	const uint8_t timer_num;
34 	uint32_t freq;
35 	const ledc_mode_t speed_mode;
36 	uint8_t resolution;
37 	ledc_clk_src_t clock_src;
38 	uint32_t duty_val;
39 };
40 
41 struct pwm_ledc_esp32_config {
42 	const struct pinctrl_dev_config *pincfg;
43 	const struct device *clock_dev;
44 	const clock_control_subsys_t clock_subsys;
45 	struct pwm_ledc_esp32_channel_config *channel_config;
46 	const int channel_len;
47 };
48 
get_channel_config(const struct device * dev,int channel_id)49 static struct pwm_ledc_esp32_channel_config *get_channel_config(const struct device *dev,
50 	int channel_id)
51 {
52 	struct pwm_ledc_esp32_config *config =
53 		(struct pwm_ledc_esp32_config *) dev->config;
54 
55 	for (uint8_t i = 0; i < config->channel_len; i++) {
56 		if (config->channel_config[i].idx == channel_id) {
57 			return &config->channel_config[i];
58 		}
59 	}
60 	return NULL;
61 }
62 
pwm_led_esp32_low_speed_update(const struct device * dev,int speed_mode,int channel)63 static void pwm_led_esp32_low_speed_update(const struct device *dev, int speed_mode, int channel)
64 {
65 	uint32_t reg_addr;
66 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
67 
68 	if (speed_mode == LEDC_LOW_SPEED_MODE) {
69 		ledc_hal_ls_channel_update(&data->hal, channel);
70 	}
71 }
72 
pwm_led_esp32_update_duty(const struct device * dev,int speed_mode,int channel)73 static void pwm_led_esp32_update_duty(const struct device *dev, int speed_mode, int channel)
74 {
75 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
76 
77 	ledc_hal_set_sig_out_en(&data->hal, channel, true);
78 	ledc_hal_set_duty_start(&data->hal, channel, true);
79 
80 	pwm_led_esp32_low_speed_update(dev, speed_mode, channel);
81 }
82 
pwm_led_esp32_duty_set(const struct device * dev,struct pwm_ledc_esp32_channel_config * channel)83 static void pwm_led_esp32_duty_set(const struct device *dev,
84 	struct pwm_ledc_esp32_channel_config *channel)
85 {
86 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
87 
88 	ledc_hal_set_hpoint(&data->hal, channel->channel_num, 0);
89 	ledc_hal_set_duty_int_part(&data->hal, channel->channel_num, channel->duty_val);
90 	ledc_hal_set_duty_direction(&data->hal, channel->channel_num, 1);
91 	ledc_hal_set_duty_num(&data->hal, channel->channel_num, 1);
92 	ledc_hal_set_duty_cycle(&data->hal, channel->channel_num, 1);
93 	ledc_hal_set_duty_scale(&data->hal, channel->channel_num, 0);
94 	pwm_led_esp32_low_speed_update(dev, channel->speed_mode, channel->channel_num);
95 	pwm_led_esp32_update_duty(dev, channel->speed_mode, channel->channel_num);
96 }
97 
pwm_led_esp32_configure_pinctrl(const struct device * dev)98 static int pwm_led_esp32_configure_pinctrl(const struct device *dev)
99 {
100 	int ret;
101 	struct pwm_ledc_esp32_config *config = (struct pwm_ledc_esp32_config *) dev->config;
102 
103 	ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
104 	if (ret < 0) {
105 		LOG_ERR("PWM pinctrl setup failed (%d)", ret);
106 		return ret;
107 	}
108 	return 0;
109 }
110 
pwm_led_esp32_bind_channel_timer(const struct device * dev,struct pwm_ledc_esp32_channel_config * channel)111 static void pwm_led_esp32_bind_channel_timer(const struct device *dev,
112 	struct pwm_ledc_esp32_channel_config *channel)
113 {
114 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
115 
116 	ledc_hal_bind_channel_timer(&data->hal, channel->channel_num, channel->timer_num);
117 
118 	pwm_led_esp32_low_speed_update(dev, channel->speed_mode, channel->channel_num);
119 }
120 
pwm_led_esp32_calculate_max_resolution(struct pwm_ledc_esp32_channel_config * channel)121 static int pwm_led_esp32_calculate_max_resolution(struct pwm_ledc_esp32_channel_config *channel)
122 {
123 	/**
124 	 * Max duty resolution can be obtained with
125 	 * max_res = log2(CLK_FREQ/FREQ)
126 	 */
127 	uint64_t clock_freq = channel->clock_src == LEDC_APB_CLK ? APB_CLK_FREQ : REF_CLK_FREQ;
128 	uint32_t max_precision_n = clock_freq/channel->freq;
129 
130 	for (uint8_t i = 0; i <= SOC_LEDC_TIMER_BIT_WIDE_NUM; i++) {
131 		max_precision_n /= 2;
132 		if (!max_precision_n) {
133 			channel->resolution =  i;
134 			return 0;
135 		}
136 	}
137 	return -EINVAL;
138 
139 }
140 
pwm_led_esp32_timer_config(struct pwm_ledc_esp32_channel_config * channel)141 static int pwm_led_esp32_timer_config(struct pwm_ledc_esp32_channel_config *channel)
142 {
143 	/**
144 	 * Calculate max resolution based on the given frequency and the pwm clock.
145 	 *
146 	 * There are 2 clock resources for PWM:
147 	 *
148 	 * 1. APB_CLK (80MHz)
149 	 * 2. REF_TICK (1MHz)
150 	 *
151 	 * The low speed timers can be sourced from:
152 	 *
153 	 * 1. APB_CLK (80MHz)
154 	 * 2. RTC_CLK (8Mhz)
155 	 *
156 	 * The APB_CLK is mostly used
157 	 *
158 	 * First we try to find the largest resolution using the APB_CLK source.
159 	 * If the given frequency doesn't support it, we move to the next clock source.
160 	 */
161 
162 	channel->clock_src = LEDC_APB_CLK;
163 	if (!pwm_led_esp32_calculate_max_resolution(channel)) {
164 		return 0;
165 	}
166 
167 	channel->clock_src = LEDC_REF_TICK;
168 	if (!pwm_led_esp32_calculate_max_resolution(channel)) {
169 		return 0;
170 	}
171 
172 	/**
173 	 * ESP32 - S2,S3 and C3 variants have only 14 bits counter.
174 	 * where as the plain ESP32 variant has 20 bits counter.
175 	 * application failed to set low frequency(1Hz) in S2, S3 and C3 variants.
176 	 * to get very low frequencies on these variants,
177 	 * frequency needs to be tuned with 18 bits clock divider.
178 	 * so select the slow clock source (1MHz) with highest counter resolution.
179 	 * this can be handled on the func 'pwm_led_esp32_timer_set' with 'prescaler'.
180 	 */
181 	channel->resolution = SOC_LEDC_TIMER_BIT_WIDE_NUM;
182 	return 0;
183 }
184 
pwm_led_esp32_timer_set(const struct device * dev,struct pwm_ledc_esp32_channel_config * channel)185 static int pwm_led_esp32_timer_set(const struct device *dev,
186 	struct pwm_ledc_esp32_channel_config *channel)
187 {
188 	int prescaler = 0;
189 	uint32_t precision = (0x1 << channel->resolution);
190 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
191 
192 	__ASSERT_NO_MSG(channel->freq > 0);
193 
194 	switch (channel->clock_src) {
195 	case LEDC_APB_CLK:
196 		/** This expression comes from ESP32 Espressif's Technical Reference
197 		 * Manual chapter 13.2.2 Timers.
198 		 * div_num is a fixed point value (Q10.8).
199 		 */
200 		prescaler = ((uint64_t) APB_CLK_FREQ << 8) / channel->freq / precision;
201 	break;
202 	case LEDC_REF_TICK:
203 		prescaler = ((uint64_t) REF_CLK_FREQ << 8) / channel->freq / precision;
204 	break;
205 	default:
206 		LOG_ERR("Invalid clock source (%d)", channel->clock_src);
207 		return -EINVAL;
208 	}
209 
210 	if (prescaler < 0x100 || prescaler > 0x3FFFF) {
211 		LOG_ERR("Prescaler out of range: %#X", prescaler);
212 		return -EINVAL;
213 	}
214 
215 	if (channel->speed_mode == LEDC_LOW_SPEED_MODE) {
216 		ledc_hal_set_slow_clk(&data->hal, channel->clock_src);
217 	}
218 
219 	ledc_hal_set_clock_divider(&data->hal, channel->timer_num, prescaler);
220 	ledc_hal_set_duty_resolution(&data->hal, channel->timer_num, channel->resolution);
221 	ledc_hal_set_clock_source(&data->hal, channel->timer_num, channel->clock_src);
222 
223 	if (channel->speed_mode == LEDC_LOW_SPEED_MODE) {
224 		ledc_hal_ls_timer_update(&data->hal, channel->timer_num);
225 	}
226 
227 	/* reset low speed timer */
228 	ledc_hal_timer_rst(&data->hal, channel->timer_num);
229 
230 	return 0;
231 }
232 
pwm_led_esp32_get_cycles_per_sec(const struct device * dev,uint32_t channel_idx,uint64_t * cycles)233 static int pwm_led_esp32_get_cycles_per_sec(const struct device *dev,
234 					    uint32_t channel_idx, uint64_t *cycles)
235 {
236 	struct pwm_ledc_esp32_config *config = (struct pwm_ledc_esp32_config *) dev->config;
237 	struct pwm_ledc_esp32_channel_config *channel = get_channel_config(dev, channel_idx);
238 
239 	if (!channel) {
240 		LOG_ERR("Error getting channel %d", channel_idx);
241 		return -EINVAL;
242 	}
243 
244 	*cycles = channel->clock_src == LEDC_APB_CLK ? APB_CLK_FREQ : REF_CLK_FREQ;
245 
246 	return 0;
247 }
248 
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)249 static int pwm_led_esp32_set_cycles(const struct device *dev, uint32_t channel_idx,
250 				    uint32_t period_cycles,
251 				    uint32_t pulse_cycles, pwm_flags_t flags)
252 {
253 	int ret;
254 	uint64_t clk_freq;
255 	struct pwm_ledc_esp32_config *config = (struct pwm_ledc_esp32_config *) dev->config;
256 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
257 	struct pwm_ledc_esp32_channel_config *channel = get_channel_config(dev, channel_idx);
258 
259 	if (!channel) {
260 		LOG_ERR("Error getting channel %d", channel_idx);
261 		return -EINVAL;
262 	}
263 
264 	/* Update PWM frequency according to period_cycles */
265 	ret = pwm_led_esp32_get_cycles_per_sec(dev, channel_idx, &clk_freq);
266 	if (ret < 0) {
267 		return ret;
268 	}
269 
270 	channel->freq = (uint32_t) (clk_freq/period_cycles);
271 	if (!channel->freq) {
272 		channel->freq = 1;
273 	}
274 
275 	k_sem_take(&data->cmd_sem, K_FOREVER);
276 
277 	ledc_hal_init(&data->hal, channel->speed_mode);
278 
279 	ret = pwm_led_esp32_timer_config(channel);
280 	if (ret < 0) {
281 		k_sem_give(&data->cmd_sem);
282 		return ret;
283 	}
284 
285 	ret = pwm_led_esp32_timer_set(dev, channel);
286 	if (ret < 0) {
287 		k_sem_give(&data->cmd_sem);
288 		return ret;
289 	}
290 
291 	pwm_led_esp32_bind_channel_timer(dev, channel);
292 
293 	/* Update PWM duty  */
294 
295 	double duty_cycle = (double) pulse_cycles / (double) period_cycles;
296 
297 	channel->duty_val = (uint32_t)((double) (1 << channel->resolution) * duty_cycle);
298 
299 	pwm_led_esp32_duty_set(dev, channel);
300 
301 	ret = pwm_led_esp32_configure_pinctrl(dev);
302 	if (ret < 0) {
303 		k_sem_give(&data->cmd_sem);
304 		return ret;
305 	}
306 
307 	k_sem_give(&data->cmd_sem);
308 
309 	return ret;
310 }
311 
312 
pwm_led_esp32_init(const struct device * dev)313 int pwm_led_esp32_init(const struct device *dev)
314 {
315 	int ret;
316 	const struct pwm_ledc_esp32_config *config = dev->config;
317 	struct pwm_ledc_esp32_data *data = (struct pwm_ledc_esp32_data *const)(dev)->data;
318 
319 	if (!device_is_ready(config->clock_dev)) {
320 		LOG_ERR("clock control device not ready");
321 		return -ENODEV;
322 	}
323 
324 	/* Enable peripheral */
325 	clock_control_on(config->clock_dev, config->clock_subsys);
326 
327 	return 0;
328 }
329 
330 static const struct pwm_driver_api pwm_led_esp32_api = {
331 	.set_cycles = pwm_led_esp32_set_cycles,
332 	.get_cycles_per_sec = pwm_led_esp32_get_cycles_per_sec,
333 };
334 
335 PINCTRL_DT_INST_DEFINE(0);
336 
337 #define CHANNEL_CONFIG(node_id)                                                \
338 	{                                                                      \
339 		.idx = DT_REG_ADDR(node_id),                                   \
340 		.channel_num = DT_REG_ADDR(node_id) % 8,                       \
341 		.timer_num = DT_PROP(node_id, timer),                          \
342 		.speed_mode = DT_REG_ADDR(node_id) < SOC_LEDC_CHANNEL_NUM      \
343 				      ? LEDC_LOW_SPEED_MODE                    \
344 				      : !LEDC_LOW_SPEED_MODE,                  \
345 		.clock_src = LEDC_APB_CLK,                                     \
346 	},
347 
348 static struct pwm_ledc_esp32_channel_config channel_config[] = {
349 	DT_INST_FOREACH_CHILD(0, CHANNEL_CONFIG)
350 };
351 
352 static struct pwm_ledc_esp32_config pwm_ledc_esp32_config = {
353 	.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
354 	.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
355 	.clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(0, offset),
356 	.channel_config = channel_config,
357 	.channel_len = ARRAY_SIZE(channel_config),
358 };
359 
360 static struct pwm_ledc_esp32_data pwm_ledc_esp32_data = {
361 	.hal = {
362 		.dev = (ledc_dev_t *) DT_INST_REG_ADDR(0),
363 	},
364 	.cmd_sem = Z_SEM_INITIALIZER(pwm_ledc_esp32_data.cmd_sem, 1, 1),
365 };
366 
367 DEVICE_DT_INST_DEFINE(0, &pwm_led_esp32_init, NULL,
368 			&pwm_ledc_esp32_data,
369 			&pwm_ledc_esp32_config,
370 			POST_KERNEL,
371 			CONFIG_PWM_INIT_PRIORITY,
372 			&pwm_led_esp32_api);
373