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