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