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_pcnt
8 
9 /* Include esp-idf headers first to avoid redefining BIT() macro */
10 #include <hal/pcnt_hal.h>
11 #include <hal/pcnt_ll.h>
12 #include <hal/pcnt_types.h>
13 
14 #include <soc.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <zephyr/drivers/sensor.h>
18 #include <zephyr/kernel.h>
19 #include <zephyr/drivers/pinctrl.h>
20 #include <zephyr/drivers/clock_control.h>
21 #ifdef CONFIG_PCNT_ESP32_TRIGGER
22 #include <zephyr/drivers/interrupt_controller/intc_esp32.h>
23 #endif /* CONFIG_PCNT_ESP32_TRIGGER */
24 
25 #include <zephyr/logging/log.h>
26 LOG_MODULE_REGISTER(pcnt_esp32, CONFIG_SENSOR_LOG_LEVEL);
27 
28 #define PCNT_INTR_UNIT_0  BIT(0)
29 #define PCNT_INTR_UNIT_1  BIT(1)
30 #define PCNT_INTR_UNIT_2  BIT(2)
31 #define PCNT_INTR_UNIT_3  BIT(3)
32 #ifdef CONFIG_SOC_SERIES_ESP32
33 #define PCNT_INTR_UNIT_4  BIT(4)
34 #define PCNT_INTR_UNIT_5  BIT(5)
35 #define PCNT_INTR_UNIT_6  BIT(6)
36 #define PCNT_INTR_UNIT_7  BIT(7)
37 #endif /* CONFIG_SOC_SERIES_ESP32 */
38 
39 #ifdef CONFIG_PCNT_ESP32_TRIGGER
40 #define PCNT_INTR_THRES_1 BIT(2)
41 #define PCNT_INTR_THRES_0 BIT(3)
42 #endif /* CONFIG_PCNT_ESP32_TRIGGER */
43 
44 struct pcnt_esp32_data {
45 	pcnt_hal_context_t hal;
46 	struct k_mutex cmd_mux;
47 #ifdef CONFIG_PCNT_ESP32_TRIGGER
48 	sensor_trigger_handler_t trigger_handler;
49 	const struct sensor_trigger *trigger;
50 #endif /* CONFIG_PCNT_ESP32_TRIGGER */
51 };
52 
53 struct pcnt_esp32_channel_config {
54 	uint8_t sig_pos_mode;
55 	uint8_t sig_neg_mode;
56 	uint8_t ctrl_h_mode;
57 	uint8_t ctrl_l_mode;
58 };
59 
60 struct pcnt_esp32_unit_config {
61 	const uint8_t idx;
62 	int16_t filter;
63 	int16_t count_val_acc;
64 	struct pcnt_esp32_channel_config channel_config[2];
65 	int32_t h_thr;
66 	int32_t l_thr;
67 	int32_t offset;
68 };
69 
70 struct pcnt_esp32_config {
71 	const struct pinctrl_dev_config *pincfg;
72 	const struct device *clock_dev;
73 	const clock_control_subsys_t clock_subsys;
74 	const int irq_source;
75 	const int irq_priority;
76 	const int irq_flags;
77 	struct pcnt_esp32_unit_config *unit_config;
78 	const int unit_len;
79 };
80 
pcnt_esp32_sample_fetch(const struct device * dev,enum sensor_channel chan)81 static int pcnt_esp32_sample_fetch(const struct device *dev, enum sensor_channel chan)
82 {
83 	const struct pcnt_esp32_config *config = dev->config;
84 	struct pcnt_esp32_data *data = (struct pcnt_esp32_data *const)(dev)->data;
85 
86 	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_ROTATION) {
87 		return -ENOTSUP;
88 	}
89 
90 	k_mutex_lock(&data->cmd_mux, K_FOREVER);
91 
92 	for (uint8_t i = 0; i < config->unit_len; i++) {
93 		struct pcnt_esp32_unit_config *unit_config = &config->unit_config[i];
94 
95 		unit_config->count_val_acc = pcnt_ll_get_count(data->hal.dev, i);
96 	}
97 
98 	k_mutex_unlock(&data->cmd_mux);
99 
100 	return 0;
101 }
102 
pcnt_esp32_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)103 static int pcnt_esp32_channel_get(const struct device *dev, enum sensor_channel chan,
104 				  struct sensor_value *val)
105 {
106 	int ret = 0;
107 	const struct pcnt_esp32_config *config = dev->config;
108 	struct pcnt_esp32_data *data = (struct pcnt_esp32_data *const)(dev)->data;
109 
110 	k_mutex_lock(&data->cmd_mux, K_FOREVER);
111 
112 	if (chan == SENSOR_CHAN_ROTATION) {
113 		val->val1 = config->unit_config[0].count_val_acc + config->unit_config[0].offset;
114 		val->val2 = 0;
115 	} else {
116 		ret = -ENOTSUP;
117 	}
118 
119 	k_mutex_unlock(&data->cmd_mux);
120 
121 	return ret;
122 }
123 
pcnt_esp32_configure_pinctrl(const struct device * dev)124 static int pcnt_esp32_configure_pinctrl(const struct device *dev)
125 {
126 	struct pcnt_esp32_config *config = (struct pcnt_esp32_config *)dev->config;
127 
128 	return pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
129 }
130 
pcnt_esp32_init(const struct device * dev)131 int pcnt_esp32_init(const struct device *dev)
132 {
133 	int ret;
134 	const struct pcnt_esp32_config *config = dev->config;
135 	struct pcnt_esp32_data *data = (struct pcnt_esp32_data *const)(dev)->data;
136 
137 	ret = clock_control_on(config->clock_dev, config->clock_subsys);
138 	if (ret < 0) {
139 		LOG_ERR("Could not initialize clock (%d)", ret);
140 		return ret;
141 	}
142 
143 	ret = pcnt_esp32_configure_pinctrl(dev);
144 	if (ret < 0) {
145 		LOG_ERR("PWM pinctrl setup failed (%d)", ret);
146 		return ret;
147 	}
148 
149 	pcnt_hal_init(&data->hal, 0);
150 
151 	for (uint8_t i = 0; i < config->unit_len; i++) {
152 		struct pcnt_esp32_unit_config *unit_config = &config->unit_config[i];
153 
154 		unit_config->h_thr = 0;
155 		unit_config->l_thr = 0;
156 		unit_config->offset = 0;
157 
158 		pcnt_ll_enable_thres_event(data->hal.dev, i, 0, false);
159 		pcnt_ll_enable_thres_event(data->hal.dev, i, 1, false);
160 		pcnt_ll_enable_low_limit_event(data->hal.dev, i, false);
161 		pcnt_ll_enable_high_limit_event(data->hal.dev, i, false);
162 		pcnt_ll_enable_zero_cross_event(data->hal.dev, i, false);
163 		pcnt_ll_set_edge_action(data->hal.dev, i, 0,
164 					unit_config->channel_config[0].sig_pos_mode,
165 					unit_config->channel_config[0].sig_neg_mode);
166 		pcnt_ll_set_edge_action(data->hal.dev, i, 1,
167 					unit_config->channel_config[1].sig_pos_mode,
168 					unit_config->channel_config[1].sig_neg_mode);
169 		pcnt_ll_set_level_action(data->hal.dev, i, 0,
170 					 unit_config->channel_config[0].ctrl_h_mode,
171 					 unit_config->channel_config[0].ctrl_l_mode);
172 		pcnt_ll_set_level_action(data->hal.dev, i, 1,
173 					 unit_config->channel_config[1].ctrl_h_mode,
174 					 unit_config->channel_config[1].ctrl_l_mode);
175 		pcnt_ll_clear_count(data->hal.dev, i);
176 
177 		pcnt_ll_set_glitch_filter_thres(data->hal.dev, i, unit_config->filter);
178 		pcnt_ll_enable_glitch_filter(data->hal.dev, i, (bool)unit_config->filter);
179 
180 		pcnt_ll_start_count(data->hal.dev, i);
181 	}
182 
183 	return 0;
184 }
185 
pcnt_esp32_attr_set_thresh(const struct device * dev,enum sensor_attribute attr,const struct sensor_value * val)186 static int pcnt_esp32_attr_set_thresh(const struct device *dev, enum sensor_attribute attr,
187 				      const struct sensor_value *val)
188 {
189 	const struct pcnt_esp32_config *config = dev->config;
190 	struct pcnt_esp32_data *data = (struct pcnt_esp32_data *const)(dev)->data;
191 
192 	for (uint8_t i = 0; i < config->unit_len; i++) {
193 		struct pcnt_esp32_unit_config *unit_config = &config->unit_config[i];
194 
195 		switch (attr) {
196 		case SENSOR_ATTR_LOWER_THRESH:
197 			unit_config->l_thr = val->val1;
198 			pcnt_ll_set_thres_value(data->hal.dev, i, 0, unit_config->l_thr);
199 			pcnt_ll_enable_thres_event(data->hal.dev, i, 0, true);
200 			break;
201 		case SENSOR_ATTR_UPPER_THRESH:
202 			unit_config->h_thr = val->val1;
203 			pcnt_ll_set_thres_value(data->hal.dev, i, 1, unit_config->h_thr);
204 			pcnt_ll_enable_thres_event(data->hal.dev, i, 1, true);
205 			break;
206 		default:
207 			return -ENOTSUP;
208 		}
209 		pcnt_ll_stop_count(data->hal.dev, i);
210 		pcnt_ll_clear_count(data->hal.dev, i);
211 		pcnt_ll_start_count(data->hal.dev, i);
212 	}
213 
214 	return 0;
215 }
216 
pcnt_esp32_attr_set_offset(const struct device * dev,const struct sensor_value * val)217 static int pcnt_esp32_attr_set_offset(const struct device *dev, const struct sensor_value *val)
218 {
219 	const struct pcnt_esp32_config *config = dev->config;
220 
221 	for (uint8_t i = 0; i < config->unit_len; i++) {
222 		struct pcnt_esp32_unit_config *unit_config = &config->unit_config[i];
223 
224 		unit_config->offset = val->val1;
225 	}
226 
227 	return 0;
228 }
229 
pcnt_esp32_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)230 static int pcnt_esp32_attr_set(const struct device *dev, enum sensor_channel chan,
231 			       enum sensor_attribute attr, const struct sensor_value *val)
232 {
233 	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_ROTATION) {
234 		return -ENOTSUP;
235 	}
236 
237 	switch (attr) {
238 	case SENSOR_ATTR_LOWER_THRESH:
239 	case SENSOR_ATTR_UPPER_THRESH:
240 		return pcnt_esp32_attr_set_thresh(dev, attr, val);
241 	case SENSOR_ATTR_OFFSET:
242 		return pcnt_esp32_attr_set_offset(dev, val);
243 	default:
244 		return -ENOTSUP;
245 	}
246 
247 	return 0;
248 }
249 
pcnt_esp32_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)250 static int pcnt_esp32_attr_get(const struct device *dev, enum sensor_channel chan,
251 			       enum sensor_attribute attr, struct sensor_value *val)
252 {
253 	const struct pcnt_esp32_config *config = dev->config;
254 
255 	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_ROTATION) {
256 		return -ENOTSUP;
257 	}
258 
259 	switch (attr) {
260 	case SENSOR_ATTR_LOWER_THRESH:
261 		val->val1 = config->unit_config[0].l_thr;
262 		break;
263 	case SENSOR_ATTR_UPPER_THRESH:
264 		val->val1 = config->unit_config[0].h_thr;
265 		break;
266 	case SENSOR_ATTR_OFFSET:
267 		val->val1 = config->unit_config[0].offset;
268 		break;
269 	default:
270 		return -ENOTSUP;
271 	}
272 
273 	val->val2 = 0;
274 
275 	return 0;
276 }
277 
278 #ifdef CONFIG_PCNT_ESP32_TRIGGER
pcnt_esp32_isr(const struct device * dev)279 static void IRAM_ATTR pcnt_esp32_isr(const struct device *dev)
280 {
281 	struct pcnt_esp32_data *data = (struct pcnt_esp32_data *const)(dev)->data;
282 
283 	uint32_t pcnt_intr_status;
284 	uint32_t pcnt_unit_status;
285 
286 	pcnt_intr_status = pcnt_ll_get_intr_status(data->hal.dev);
287 	pcnt_ll_clear_intr_status(data->hal.dev, pcnt_intr_status);
288 
289 	if (pcnt_intr_status & PCNT_INTR_UNIT_0) {
290 		pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 0);
291 	} else if (pcnt_intr_status & PCNT_INTR_UNIT_1) {
292 		pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 1);
293 	} else if (pcnt_intr_status & PCNT_INTR_UNIT_2) {
294 		pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 2);
295 	} else if (pcnt_intr_status & PCNT_INTR_UNIT_3) {
296 		pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 3);
297 #ifdef CONFIG_SOC_SERIES_ESP32
298 	} else if (pcnt_intr_status & PCNT_INTR_UNIT_4) {
299 		pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 4);
300 	} else if (pcnt_intr_status & PCNT_INTR_UNIT_5) {
301 		pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 5);
302 	} else if (pcnt_intr_status & PCNT_INTR_UNIT_6) {
303 		pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 6);
304 	} else if (pcnt_intr_status & PCNT_INTR_UNIT_7) {
305 		pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 7);
306 #endif /* CONFIG_SOC_SERIES_ESP32 */
307 	} else {
308 		return;
309 	}
310 
311 	if (!(pcnt_unit_status & PCNT_INTR_THRES_0) && !(pcnt_unit_status & PCNT_INTR_THRES_1)) {
312 		return;
313 	}
314 
315 	if (!data->trigger_handler) {
316 		return;
317 	}
318 
319 	data->trigger_handler(dev, data->trigger);
320 }
321 
pcnt_esp32_trigger_set(const struct device * dev,const struct sensor_trigger * trig,sensor_trigger_handler_t handler)322 static int pcnt_esp32_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
323 				  sensor_trigger_handler_t handler)
324 {
325 	int ret;
326 	const struct pcnt_esp32_config *config = dev->config;
327 	struct pcnt_esp32_data *data = (struct pcnt_esp32_data *const)(dev)->data;
328 
329 	if (trig->type != SENSOR_TRIG_THRESHOLD) {
330 		return -ENOTSUP;
331 	}
332 
333 	if ((trig->chan != SENSOR_CHAN_ALL) && (trig->chan != SENSOR_CHAN_ROTATION)) {
334 		return -ENOTSUP;
335 	}
336 
337 	if (!handler) {
338 		return -EINVAL;
339 	}
340 
341 	data->trigger_handler = handler;
342 	data->trigger = trig;
343 
344 	ret = esp_intr_alloc(config->irq_source,
345 			ESP_PRIO_TO_FLAGS(config->irq_priority) |
346 			ESP_INT_FLAGS_CHECK(config->irq_flags) | ESP_INTR_FLAG_IRAM,
347 			(intr_handler_t)pcnt_esp32_isr, (void *)dev, NULL);
348 
349 	if (ret != 0) {
350 		LOG_ERR("pcnt isr registration failed (%d)", ret);
351 		return ret;
352 	}
353 
354 	pcnt_ll_enable_intr(data->hal.dev, 1, true);
355 
356 	return 0;
357 }
358 #endif /* CONFIG_PCNT_ESP32_TRIGGER */
359 
360 static DEVICE_API(sensor, pcnt_esp32_api) = {
361 	.sample_fetch = pcnt_esp32_sample_fetch,
362 	.channel_get = pcnt_esp32_channel_get,
363 	.attr_set = pcnt_esp32_attr_set,
364 	.attr_get = pcnt_esp32_attr_get,
365 #ifdef CONFIG_PCNT_ESP32_TRIGGER
366 	.trigger_set = pcnt_esp32_trigger_set,
367 #endif /* CONFIG_PCNT_ESP32_TRIGGER */
368 };
369 
370 PINCTRL_DT_INST_DEFINE(0);
371 
372 #define UNIT_CONFIG(node_id)                                                                       \
373 	{                                                                                          \
374 		.idx = DT_REG_ADDR(node_id),                                                       \
375 		.filter = DT_PROP_OR(node_id, filter, 0) > 1024 ? 1024                             \
376 								: DT_PROP_OR(node_id, filter, 0),  \
377 		.channel_config[0] =                                                               \
378 			{                                                                          \
379 				.sig_pos_mode = DT_PROP_OR(DT_CHILD(node_id, channela_0),          \
380 							   sig_pos_mode, 0),                       \
381 				.sig_neg_mode = DT_PROP_OR(DT_CHILD(node_id, channela_0),          \
382 							   sig_neg_mode, 0),                       \
383 				.ctrl_l_mode =                                                     \
384 					DT_PROP_OR(DT_CHILD(node_id, channela_0), ctrl_l_mode, 0), \
385 				.ctrl_h_mode =                                                     \
386 					DT_PROP_OR(DT_CHILD(node_id, channela_0), ctrl_h_mode, 0), \
387 			},                                                                         \
388 		.channel_config[1] =                                                               \
389 			{                                                                          \
390 				.sig_pos_mode = DT_PROP_OR(DT_CHILD(node_id, channelb_0),          \
391 							   sig_pos_mode, 0),                       \
392 				.sig_neg_mode = DT_PROP_OR(DT_CHILD(node_id, channelb_0),          \
393 							   sig_neg_mode, 0),                       \
394 				.ctrl_l_mode =                                                     \
395 					DT_PROP_OR(DT_CHILD(node_id, channelb_0), ctrl_l_mode, 0), \
396 				.ctrl_h_mode =                                                     \
397 					DT_PROP_OR(DT_CHILD(node_id, channelb_0), ctrl_h_mode, 0), \
398 			},                                                                         \
399 	},
400 
401 static struct pcnt_esp32_unit_config unit_config[] = {DT_INST_FOREACH_CHILD(0, UNIT_CONFIG)};
402 
403 static struct pcnt_esp32_config pcnt_esp32_config = {
404 	.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
405 	.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
406 	.clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(0, offset),
407 	.irq_source = DT_INST_IRQ_BY_IDX(0, 0, irq),
408 	.irq_priority = DT_INST_IRQ_BY_IDX(0, 0, priority),
409 	.irq_flags = DT_INST_IRQ_BY_IDX(0, 0, flags),
410 	.unit_config = unit_config,
411 	.unit_len = ARRAY_SIZE(unit_config),
412 };
413 
414 static struct pcnt_esp32_data pcnt_esp32_data = {
415 	.hal = {
416 		.dev = (pcnt_dev_t *)DT_INST_REG_ADDR(0),
417 	},
418 	.cmd_mux = Z_MUTEX_INITIALIZER(pcnt_esp32_data.cmd_mux),
419 #ifdef CONFIG_PCNT_ESP32_TRIGGER
420 	.trigger_handler = NULL,
421 #endif /* CONFIG_PCNT_ESP32_TRIGGER */
422 };
423 
424 SENSOR_DEVICE_DT_INST_DEFINE(0, &pcnt_esp32_init, NULL,
425 			&pcnt_esp32_data,
426 			&pcnt_esp32_config,
427 			POST_KERNEL,
428 			CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
429 			&pcnt_esp32_api);
430