1 /*
2 * Copyright (c) 2017 Intel Corporation
3 * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT espressif_esp32_gpio
9
10 /* Include esp-idf headers first to avoid redefining BIT() macro */
11 #include <soc/gpio_reg.h>
12 #include <soc/io_mux_reg.h>
13 #include <soc/soc.h>
14 #include <hal/gpio_ll.h>
15 #include <esp_attr.h>
16 #include <hal/rtc_io_hal.h>
17
18 #include <soc.h>
19 #include <errno.h>
20 #include <zephyr/device.h>
21 #include <zephyr/drivers/gpio.h>
22 #include <zephyr/dt-bindings/gpio/espressif-esp32-gpio.h>
23 #ifdef CONFIG_SOC_SERIES_ESP32C3
24 #include <zephyr/drivers/interrupt_controller/intc_esp32c3.h>
25 #else
26 #include <zephyr/drivers/interrupt_controller/intc_esp32.h>
27 #endif
28 #include <zephyr/kernel.h>
29 #include <zephyr/sys/util.h>
30
31 #include <zephyr/drivers/gpio/gpio_utils.h>
32
33 #include <zephyr/logging/log.h>
34 LOG_MODULE_REGISTER(gpio_esp32, CONFIG_LOG_DEFAULT_LEVEL);
35
36 #ifdef CONFIG_SOC_SERIES_ESP32C3
37 /* gpio structs in esp32c3 series are different from xtensa ones */
38 #define out out.data
39 #define in in.data
40 #define out_w1ts out_w1ts.val
41 #define out_w1tc out_w1tc.val
42 /* arch_curr_cpu() is not available for riscv based chips */
43 #define CPU_ID() 0
44 #define ISR_HANDLER isr_handler_t
45 #else
46 #define CPU_ID() arch_curr_cpu()->id
47 #define ISR_HANDLER intr_handler_t
48 #endif
49
50 #ifndef SOC_GPIO_SUPPORT_RTC_INDEPENDENT
51 #define SOC_GPIO_SUPPORT_RTC_INDEPENDENT 0
52 #endif
53
54 struct gpio_esp32_config {
55 /* gpio_driver_config needs to be first */
56 struct gpio_driver_config drv_cfg;
57 gpio_dev_t *const gpio_base;
58 gpio_dev_t *const gpio_dev;
59 const int gpio_port;
60 };
61
62 struct gpio_esp32_data {
63 /* gpio_driver_data needs to be first */
64 struct gpio_driver_data common;
65 sys_slist_t cb;
66 };
67
rtc_gpio_is_valid_gpio(uint32_t gpio_num)68 static inline bool rtc_gpio_is_valid_gpio(uint32_t gpio_num)
69 {
70 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
71 return (gpio_num < SOC_GPIO_PIN_COUNT && rtc_io_num_map[gpio_num] >= 0);
72 #else
73 return false;
74 #endif
75 }
76
gpio_pin_is_valid(uint32_t pin)77 static inline bool gpio_pin_is_valid(uint32_t pin)
78 {
79 return ((BIT(pin) & SOC_GPIO_VALID_GPIO_MASK) != 0);
80 }
81
gpio_pin_is_output_capable(uint32_t pin)82 static inline bool gpio_pin_is_output_capable(uint32_t pin)
83 {
84 return ((BIT(pin) & SOC_GPIO_VALID_OUTPUT_GPIO_MASK) != 0);
85 }
86
gpio_esp32_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)87 static int gpio_esp32_config(const struct device *dev,
88 gpio_pin_t pin,
89 gpio_flags_t flags)
90 {
91 const struct gpio_esp32_config *const cfg = dev->config;
92 struct gpio_esp32_data *data = dev->data;
93 uint32_t io_pin = (uint32_t) pin + ((cfg->gpio_port == 1 && pin < 32) ? 32 : 0);
94 uint32_t key;
95 int ret = 0;
96
97 if (!gpio_pin_is_valid(io_pin)) {
98 LOG_ERR("Selected IO pin is not valid.");
99 return -EINVAL;
100 }
101
102 key = irq_lock();
103
104 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
105 if (rtc_gpio_is_valid_gpio(io_pin)) {
106 rtcio_hal_function_select(rtc_io_num_map[io_pin], RTCIO_FUNC_DIGITAL);
107 }
108 #endif
109
110 if (io_pin >= GPIO_NUM_MAX) {
111 LOG_ERR("Invalid pin.");
112 ret = -EINVAL;
113 goto end;
114 }
115
116 /* Set pin function as GPIO */
117 gpio_ll_iomux_func_sel(GPIO_PIN_MUX_REG[io_pin], PIN_FUNC_GPIO);
118
119 if (flags & GPIO_PULL_UP) {
120 if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
121 gpio_ll_pullup_en(&GPIO, io_pin);
122 } else {
123 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
124 int rtcio_num = rtc_io_num_map[io_pin];
125
126 if (rtc_io_desc[rtcio_num].pullup) {
127 rtcio_hal_pullup_enable(rtcio_num);
128 } else {
129 ret = -ENOTSUP;
130 goto end;
131 }
132 #endif
133 }
134 } else {
135 if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
136 gpio_ll_pullup_dis(&GPIO, io_pin);
137 } else {
138 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
139 int rtcio_num = rtc_io_num_map[io_pin];
140
141 if (rtc_io_desc[rtcio_num].pullup) {
142 rtcio_hal_pullup_disable(rtcio_num);
143 }
144 #else
145 ret = -ENOTSUP;
146 goto end;
147 #endif
148 }
149 }
150
151 if (flags & GPIO_SINGLE_ENDED) {
152 if (flags & GPIO_LINE_OPEN_DRAIN) {
153 gpio_ll_od_enable(cfg->gpio_base, io_pin);
154 } else {
155 LOG_ERR("GPIO configuration not supported");
156 ret = -ENOTSUP;
157 goto end;
158 }
159 } else {
160 gpio_ll_od_disable(cfg->gpio_base, io_pin);
161 }
162
163 if (flags & GPIO_PULL_DOWN) {
164 if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
165 gpio_ll_pulldown_en(&GPIO, io_pin);
166 } else {
167 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
168 int rtcio_num = rtc_io_num_map[io_pin];
169
170 if (rtc_io_desc[rtcio_num].pulldown) {
171 rtcio_hal_pulldown_enable(rtcio_num);
172 } else {
173 ret = -ENOTSUP;
174 goto end;
175 }
176 #endif
177 }
178 } else {
179 if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
180 gpio_ll_pulldown_dis(&GPIO, io_pin);
181 } else {
182 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
183 int rtcio_num = rtc_io_num_map[io_pin];
184
185 if (rtc_io_desc[rtcio_num].pulldown) {
186 rtcio_hal_pulldown_disable(rtcio_num);
187 }
188 #else
189 ret = -ENOTSUP;
190 goto end;
191 #endif
192 }
193 }
194
195 if (flags & GPIO_OUTPUT) {
196
197 if (!gpio_pin_is_output_capable(pin)) {
198 LOG_ERR("GPIO can only be used as input");
199 ret = -EINVAL;
200 goto end;
201 }
202
203 /*
204 * By default, drive strength is set to its maximum value when the pin is set
205 * to either low or high states. Alternative drive strength is weak-only,
206 * while any other intermediary combination is considered invalid.
207 */
208 switch (flags & ESP32_GPIO_DS_MASK) {
209 case ESP32_GPIO_DS_DFLT:
210 if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
211 gpio_ll_set_drive_capability(cfg->gpio_base,
212 io_pin,
213 GPIO_DRIVE_CAP_3);
214 } else {
215 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
216 rtcio_hal_set_drive_capability(rtc_io_num_map[io_pin],
217 GPIO_DRIVE_CAP_3);
218 #endif
219 }
220 break;
221 case ESP32_GPIO_DS_ALT:
222 if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
223 gpio_ll_set_drive_capability(cfg->gpio_base,
224 io_pin,
225 GPIO_DRIVE_CAP_0);
226 } else {
227 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
228 rtcio_hal_set_drive_capability(rtc_io_num_map[io_pin],
229 GPIO_DRIVE_CAP_0);
230 #endif
231 }
232 break;
233 default:
234 ret = -EINVAL;
235 goto end;
236 }
237
238 gpio_ll_output_enable(&GPIO, io_pin);
239 esp_rom_gpio_matrix_out(io_pin, SIG_GPIO_OUT_IDX, false, false);
240
241 /* Set output pin initial value */
242 if (flags & GPIO_OUTPUT_INIT_HIGH) {
243 gpio_ll_set_level(cfg->gpio_base, io_pin, 1);
244 } else if (flags & GPIO_OUTPUT_INIT_LOW) {
245 gpio_ll_set_level(cfg->gpio_base, io_pin, 0);
246 }
247 } else {
248 gpio_ll_output_disable(&GPIO, io_pin);
249 }
250
251 if (flags & GPIO_INPUT) {
252 gpio_ll_input_enable(&GPIO, io_pin);
253 } else {
254 gpio_ll_input_disable(&GPIO, io_pin);
255 }
256
257 end:
258 irq_unlock(key);
259
260 return ret;
261 }
262
gpio_esp32_port_get_raw(const struct device * port,uint32_t * value)263 static int gpio_esp32_port_get_raw(const struct device *port, uint32_t *value)
264 {
265 const struct gpio_esp32_config *const cfg = port->config;
266
267 if (cfg->gpio_port == 0) {
268 *value = cfg->gpio_dev->in;
269 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
270 } else {
271 *value = cfg->gpio_dev->in1.data;
272 #endif
273 }
274
275 return 0;
276 }
277
gpio_esp32_port_set_masked_raw(const struct device * port,uint32_t mask,uint32_t value)278 static int gpio_esp32_port_set_masked_raw(const struct device *port,
279 uint32_t mask, uint32_t value)
280 {
281 const struct gpio_esp32_config *const cfg = port->config;
282
283 uint32_t key = irq_lock();
284
285 if (cfg->gpio_port == 0) {
286 cfg->gpio_dev->out = (cfg->gpio_dev->out & ~mask) | (mask & value);
287 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
288 } else {
289 cfg->gpio_dev->out1.data = (cfg->gpio_dev->out1.data & ~mask) | (mask & value);
290 #endif
291 }
292
293 irq_unlock(key);
294
295 return 0;
296 }
297
gpio_esp32_port_set_bits_raw(const struct device * port,uint32_t pins)298 static int gpio_esp32_port_set_bits_raw(const struct device *port,
299 uint32_t pins)
300 {
301 const struct gpio_esp32_config *const cfg = port->config;
302
303 if (cfg->gpio_port == 0) {
304 cfg->gpio_dev->out_w1ts = pins;
305 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
306 } else {
307 cfg->gpio_dev->out1_w1ts.data = pins;
308 #endif
309 }
310
311 return 0;
312 }
313
gpio_esp32_port_clear_bits_raw(const struct device * port,uint32_t pins)314 static int gpio_esp32_port_clear_bits_raw(const struct device *port,
315 uint32_t pins)
316 {
317 const struct gpio_esp32_config *const cfg = port->config;
318
319 if (cfg->gpio_port == 0) {
320 cfg->gpio_dev->out_w1tc = pins;
321 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
322 } else {
323 cfg->gpio_dev->out1_w1tc.data = pins;
324 #endif
325 }
326
327 return 0;
328 }
329
gpio_esp32_port_toggle_bits(const struct device * port,uint32_t pins)330 static int gpio_esp32_port_toggle_bits(const struct device *port,
331 uint32_t pins)
332 {
333 const struct gpio_esp32_config *const cfg = port->config;
334 uint32_t key = irq_lock();
335
336 if (cfg->gpio_port == 0) {
337 cfg->gpio_dev->out ^= pins;
338 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
339 } else {
340 cfg->gpio_dev->out1.data ^= pins;
341 #endif
342 }
343
344 irq_unlock(key);
345
346 return 0;
347 }
348
convert_int_type(enum gpio_int_mode mode,enum gpio_int_trig trig)349 static int convert_int_type(enum gpio_int_mode mode,
350 enum gpio_int_trig trig)
351 {
352 if (mode == GPIO_INT_MODE_DISABLED) {
353 return GPIO_INTR_DISABLE;
354 }
355
356 if (mode == GPIO_INT_MODE_LEVEL) {
357 switch (trig) {
358 case GPIO_INT_TRIG_LOW:
359 return GPIO_INTR_LOW_LEVEL;
360 case GPIO_INT_TRIG_HIGH:
361 return GPIO_INTR_HIGH_LEVEL;
362 default:
363 return -EINVAL;
364 }
365 } else { /* edge interrupts */
366 switch (trig) {
367 case GPIO_INT_TRIG_HIGH:
368 return GPIO_INTR_POSEDGE;
369 case GPIO_INT_TRIG_LOW:
370 return GPIO_INTR_NEGEDGE;
371 case GPIO_INT_TRIG_BOTH:
372 return GPIO_INTR_ANYEDGE;
373 default:
374 return -EINVAL;
375 }
376 }
377
378 /* Any other type of interrupt triggering is invalid. */
379 return -EINVAL;
380 }
381
gpio_esp32_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)382 static int gpio_esp32_pin_interrupt_configure(const struct device *port,
383 gpio_pin_t pin,
384 enum gpio_int_mode mode,
385 enum gpio_int_trig trig)
386 {
387 const struct gpio_esp32_config *const cfg = port->config;
388 uint32_t io_pin = (uint32_t) pin + ((cfg->gpio_port == 1 && pin < 32) ? 32 : 0);
389 int intr_trig_mode = convert_int_type(mode, trig);
390 uint32_t key;
391
392 if (intr_trig_mode < 0) {
393 return intr_trig_mode;
394 }
395
396 key = irq_lock();
397 if (cfg->gpio_port == 0) {
398 gpio_ll_clear_intr_status(cfg->gpio_base, BIT(pin));
399 } else {
400 gpio_ll_clear_intr_status_high(cfg->gpio_base, BIT(pin));
401 }
402
403 gpio_ll_set_intr_type(cfg->gpio_base, io_pin, intr_trig_mode);
404 gpio_ll_intr_enable_on_core(cfg->gpio_base, CPU_ID(), io_pin);
405 irq_unlock(key);
406
407 return 0;
408 }
409
gpio_esp32_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)410 static int gpio_esp32_manage_callback(const struct device *dev,
411 struct gpio_callback *callback,
412 bool set)
413 {
414 struct gpio_esp32_data *data = dev->data;
415
416 return gpio_manage_callback(&data->cb, callback, set);
417 }
418
gpio_esp32_get_pending_int(const struct device * dev)419 static uint32_t gpio_esp32_get_pending_int(const struct device *dev)
420 {
421 const struct gpio_esp32_config *const cfg = dev->config;
422 uint32_t irq_status;
423 uint32_t const core_id = CPU_ID();
424
425 if (cfg->gpio_port == 0) {
426 gpio_ll_get_intr_status(cfg->gpio_base, core_id, &irq_status);
427 } else {
428 gpio_ll_get_intr_status_high(cfg->gpio_base, core_id, &irq_status);
429 }
430
431 return irq_status;
432 }
433
gpio_esp32_fire_callbacks(const struct device * dev)434 static void IRAM_ATTR gpio_esp32_fire_callbacks(const struct device *dev)
435 {
436 const struct gpio_esp32_config *const cfg = dev->config;
437 struct gpio_esp32_data *data = dev->data;
438 uint32_t irq_status;
439 uint32_t const core_id = CPU_ID();
440
441 if (cfg->gpio_port == 0) {
442 gpio_ll_get_intr_status(cfg->gpio_base, core_id, &irq_status);
443 gpio_ll_clear_intr_status(cfg->gpio_base, irq_status);
444 } else {
445 gpio_ll_get_intr_status_high(cfg->gpio_base, core_id, &irq_status);
446 gpio_ll_clear_intr_status_high(cfg->gpio_base, irq_status);
447 }
448
449 if (irq_status != 0) {
450 gpio_fire_callbacks(&data->cb, dev, irq_status);
451 }
452 }
453
454 static void gpio_esp32_isr(void *param);
455
gpio_esp32_init(const struct device * dev)456 static int gpio_esp32_init(const struct device *dev)
457 {
458 struct gpio_esp32_data *data = dev->data;
459 static bool isr_connected;
460
461 if (!isr_connected) {
462 esp_intr_alloc(DT_IRQN(DT_NODELABEL(gpio0)),
463 0,
464 (ISR_HANDLER)gpio_esp32_isr,
465 (void *)dev,
466 NULL);
467
468 isr_connected = true;
469 }
470
471 return 0;
472 }
473
474 static const struct gpio_driver_api gpio_esp32_driver_api = {
475 .pin_configure = gpio_esp32_config,
476 .port_get_raw = gpio_esp32_port_get_raw,
477 .port_set_masked_raw = gpio_esp32_port_set_masked_raw,
478 .port_set_bits_raw = gpio_esp32_port_set_bits_raw,
479 .port_clear_bits_raw = gpio_esp32_port_clear_bits_raw,
480 .port_toggle_bits = gpio_esp32_port_toggle_bits,
481 .pin_interrupt_configure = gpio_esp32_pin_interrupt_configure,
482 .manage_callback = gpio_esp32_manage_callback,
483 .get_pending_int = gpio_esp32_get_pending_int
484 };
485
486 #define ESP_SOC_GPIO_INIT(_id) \
487 static struct gpio_esp32_data gpio_data_##_id; \
488 static struct gpio_esp32_config gpio_config_##_id = { \
489 .drv_cfg = { \
490 .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(_id), \
491 }, \
492 .gpio_base = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0)), \
493 .gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio##_id)), \
494 .gpio_port = _id \
495 }; \
496 DEVICE_DT_DEFINE(DT_NODELABEL(gpio##_id), \
497 &gpio_esp32_init, \
498 NULL, \
499 &gpio_data_##_id, \
500 &gpio_config_##_id, \
501 PRE_KERNEL_1, \
502 CONFIG_GPIO_INIT_PRIORITY, \
503 &gpio_esp32_driver_api);
504
505 DT_INST_FOREACH_STATUS_OKAY(ESP_SOC_GPIO_INIT);
506
gpio_esp32_isr(void * param)507 static void IRAM_ATTR gpio_esp32_isr(void *param)
508 {
509 ARG_UNUSED(param);
510
511 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio0), okay)
512 gpio_esp32_fire_callbacks(DEVICE_DT_INST_GET(0));
513 #endif
514
515 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
516 gpio_esp32_fire_callbacks(DEVICE_DT_INST_GET(1));
517 #endif
518 }
519