1 /*
2  * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /* Include esp-idf headers first to avoid redefining BIT() macro */
8 #include <hal/gpio_ll.h>
9 #include <hal/rtc_io_hal.h>
10 
11 #include <soc.h>
12 #include <zephyr/drivers/pinctrl.h>
13 #include <zephyr/drivers/pinctrl/pinctrl_esp32_common.h>
14 
15 #ifdef CONFIG_SOC_SERIES_ESP32C2
16 #define out	out.val
17 #define in	in.val
18 #define out_w1ts out_w1ts.val
19 #define out_w1tc out_w1tc.val
20 #elif CONFIG_SOC_SERIES_ESP32C3
21 /* gpio structs in esp32c3 series are different from xtensa ones */
22 #define out out.data
23 #define in in.data
24 #define out_w1ts out_w1ts.val
25 #define out_w1tc out_w1tc.val
26 #elif CONFIG_SOC_SERIES_ESP32C6
27 /* gpio structs in esp32c6 are also different */
28 #define out out.out_data_orig
29 #define in in.in_data_next
30 #define out_w1ts out_w1ts.val
31 #define out_w1tc out_w1tc.val
32 #endif
33 
34 #ifndef SOC_GPIO_SUPPORT_RTC_INDEPENDENT
35 #define SOC_GPIO_SUPPORT_RTC_INDEPENDENT 0
36 #endif
37 
38 #define ESP32_INVALID_PORT_ADDR          0UL
39 
40 #define ESP32_GPIO_PORT_ADDR(nodelabel)				\
41 	COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)),	\
42 		(DT_REG_ADDR(DT_NODELABEL(nodelabel)),),	\
43 		(ESP32_INVALID_PORT_ADDR))
44 
45 /**
46  * @brief Array containing each GPIO port address.
47  *
48  * Entries will be an invalid address if the port is not enabled.
49  */
50 static const uint32_t esp32_gpio_ports_addrs[] = {
51 	ESP32_GPIO_PORT_ADDR(gpio0)
52 	ESP32_GPIO_PORT_ADDR(gpio1)
53 };
54 
55 /** Number of GPIO ports. */
56 static const size_t esp32_gpio_ports_cnt = ARRAY_SIZE(esp32_gpio_ports_addrs);
57 
rtc_gpio_is_valid_gpio(uint32_t gpio_num)58 static inline bool rtc_gpio_is_valid_gpio(uint32_t gpio_num)
59 {
60 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
61 	return (gpio_num < SOC_GPIO_PIN_COUNT && rtc_io_num_map[gpio_num] >= 0);
62 #else
63 	return false;
64 #endif
65 }
66 
esp32_pin_is_valid(uint32_t pin)67 static inline bool esp32_pin_is_valid(uint32_t pin)
68 {
69 	return ((BIT(pin) & SOC_GPIO_VALID_GPIO_MASK) != 0);
70 }
71 
esp32_pin_is_output_capable(uint32_t pin)72 static inline bool esp32_pin_is_output_capable(uint32_t pin)
73 {
74 	return ((BIT(pin) & SOC_GPIO_VALID_OUTPUT_GPIO_MASK) != 0);
75 }
76 
esp32_pin_apply_config(uint32_t pin,uint32_t flags)77 static int esp32_pin_apply_config(uint32_t pin, uint32_t flags)
78 {
79 	gpio_dev_t *const gpio_base = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0));
80 	uint32_t io_pin = (uint32_t) pin + ((ESP32_PORT_IDX(pin) == 1 && pin < 32) ? 32 : 0);
81 	int ret = 0;
82 
83 	if (!esp32_pin_is_valid(io_pin)) {
84 		return -EINVAL;
85 	}
86 
87 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
88 	if (rtc_gpio_is_valid_gpio(io_pin)) {
89 		rtcio_hal_function_select(rtc_io_num_map[io_pin], RTCIO_FUNC_DIGITAL);
90 	}
91 #endif
92 
93 	if (io_pin >= GPIO_NUM_MAX) {
94 		ret = -EINVAL;
95 		goto end;
96 	}
97 
98 	/* Set pin function as GPIO */
99 	gpio_ll_iomux_func_sel(GPIO_PIN_MUX_REG[io_pin], PIN_FUNC_GPIO);
100 
101 	if (flags & ESP32_PULL_UP_FLAG) {
102 		if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
103 			gpio_ll_pulldown_dis(&GPIO, io_pin);
104 			gpio_ll_pullup_en(&GPIO, io_pin);
105 		} else {
106 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
107 			int rtcio_num = rtc_io_num_map[io_pin];
108 
109 			rtcio_hal_pulldown_disable(rtc_io_num_map[io_pin]);
110 
111 			if (rtc_io_desc[rtcio_num].pullup) {
112 				rtcio_hal_pullup_enable(rtc_io_num_map[io_pin]);
113 			} else {
114 				ret = -ENOTSUP;
115 				goto end;
116 			}
117 #endif
118 		}
119 	} else if (flags & ESP32_PULL_DOWN_FLAG) {
120 		if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
121 			gpio_ll_pullup_dis(&GPIO, io_pin);
122 			gpio_ll_pulldown_en(&GPIO, io_pin);
123 		} else {
124 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
125 			int rtcio_num = rtc_io_num_map[io_pin];
126 
127 			rtcio_hal_pulldown_enable(rtc_io_num_map[io_pin]);
128 
129 			if (rtc_io_desc[rtcio_num].pullup) {
130 				rtcio_hal_pullup_disable(rtc_io_num_map[io_pin]);
131 			} else {
132 				ret = -ENOTSUP;
133 				goto end;
134 			}
135 #endif
136 		}
137 	}
138 
139 	if (flags & ESP32_DIR_OUT_FLAG) {
140 		if (!esp32_pin_is_output_capable(pin)) {
141 			ret = -EINVAL;
142 			goto end;
143 		}
144 
145 		if (flags & ESP32_OPEN_DRAIN_FLAG) {
146 			gpio_ll_od_enable(gpio_base, io_pin);
147 		} else {
148 			gpio_ll_od_disable(gpio_base, io_pin);
149 		}
150 
151 		/* Set output pin initial value */
152 		if (flags & ESP32_PIN_OUT_HIGH_FLAG) {
153 			gpio_ll_set_level(gpio_base, io_pin, 1);
154 		} else if (flags & ESP32_PIN_OUT_LOW_FLAG) {
155 			gpio_ll_set_level(gpio_base, io_pin, 0);
156 		}
157 
158 		gpio_ll_output_enable(&GPIO, io_pin);
159 		esp_rom_gpio_matrix_out(io_pin, SIG_GPIO_OUT_IDX, false, false);
160 	} else {
161 		if (!(flags & ESP32_PIN_OUT_EN_FLAG)) {
162 			gpio_ll_output_disable(&GPIO, io_pin);
163 		}
164 	}
165 
166 	if (flags & ESP32_DIR_INP_FLAG) {
167 		gpio_ll_input_enable(&GPIO, io_pin);
168 	} else {
169 		if (!(flags & ESP32_PIN_IN_EN_FLAG)) {
170 			gpio_ll_input_disable(&GPIO, io_pin);
171 		}
172 	}
173 
174 end:
175 	return ret;
176 }
177 
esp32_pin_configure(const uint32_t pin_mux,const uint32_t pin_cfg)178 static int esp32_pin_configure(const uint32_t pin_mux, const uint32_t pin_cfg)
179 {
180 	uint32_t port_addr;
181 	uint32_t pin_num = ESP32_PIN_NUM(pin_mux);
182 	uint32_t sig_in = ESP32_PIN_SIGI(pin_mux);
183 	uint32_t sig_out = ESP32_PIN_SIGO(pin_mux);
184 	uint32_t flags = 0;
185 
186 	if (ESP32_PORT_IDX(pin_num) >= esp32_gpio_ports_cnt) {
187 		return -EINVAL;
188 	}
189 
190 	port_addr = esp32_gpio_ports_addrs[ESP32_PORT_IDX(pin_num)];
191 
192 	if (port_addr == ESP32_INVALID_PORT_ADDR) {
193 		return -EINVAL;
194 	}
195 
196 	switch (ESP32_PIN_BIAS(pin_cfg)) {
197 	case ESP32_PULL_UP:
198 		flags |= ESP32_PULL_UP_FLAG;
199 		break;
200 	case ESP32_PULL_DOWN:
201 		flags |= ESP32_PULL_DOWN_FLAG;
202 		break;
203 	default:
204 		break;
205 	}
206 
207 	switch (ESP32_PIN_DRV(pin_cfg)) {
208 	case ESP32_PUSH_PULL:
209 		flags |= ESP32_PUSH_PULL_FLAG;
210 		break;
211 	case ESP32_OPEN_DRAIN:
212 		flags |= ESP32_OPEN_DRAIN_FLAG;
213 		break;
214 	default:
215 		break;
216 	}
217 
218 	if (sig_in == ESP_SIG_INVAL && sig_out == ESP_SIG_INVAL) {
219 		return -ENOTSUP;
220 	}
221 
222 	if (sig_in != ESP_SIG_INVAL) {
223 		flags |= ESP32_DIR_INP_FLAG;
224 	}
225 
226 	if (sig_out != ESP_SIG_INVAL) {
227 		flags |= ESP32_DIR_OUT_FLAG;
228 	}
229 
230 	switch (ESP32_PIN_MODE_OUT(pin_cfg)) {
231 	case ESP32_PIN_OUT_HIGH:
232 		flags |= ESP32_PIN_OUT_HIGH_FLAG;
233 		break;
234 	case ESP32_PIN_OUT_LOW:
235 		flags |= ESP32_PIN_OUT_LOW_FLAG;
236 		break;
237 	default:
238 		break;
239 	}
240 
241 	switch (ESP32_PIN_EN_DIR(pin_cfg)) {
242 	case ESP32_PIN_OUT_EN:
243 		flags |= ESP32_PIN_OUT_EN_FLAG;
244 		break;
245 	case ESP32_PIN_IN_EN:
246 		flags |= ESP32_PIN_IN_EN_FLAG;
247 		break;
248 	default:
249 		break;
250 	}
251 
252 	if (flags & ESP32_PIN_OUT_HIGH_FLAG) {
253 		if (ESP32_PORT_IDX(pin_num) == 0) {
254 			gpio_dev_t *const gpio_dev =
255 				(gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0));
256 			gpio_dev->out_w1ts = BIT(pin_num);
257 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio1))
258 		} else {
259 			gpio_dev_t *const gpio_dev =
260 				(gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio1));
261 			gpio_dev->out1_w1ts.data = BIT(pin_num - 32);
262 #endif
263 		}
264 	}
265 
266 	if (flags & ESP32_PIN_OUT_LOW_FLAG) {
267 		if (ESP32_PORT_IDX(pin_num) == 0) {
268 			gpio_dev_t *const gpio_dev =
269 				(gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0));
270 			gpio_dev->out_w1tc = BIT(pin_num);
271 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio1))
272 		} else {
273 			gpio_dev_t *const gpio_dev =
274 				(gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio1));
275 			gpio_dev->out1_w1tc.data = BIT(pin_num - 32);
276 #endif
277 		}
278 	}
279 
280 	esp32_pin_apply_config(pin_num, flags);
281 
282 	if (flags & ESP32_DIR_OUT_FLAG) {
283 		esp_rom_gpio_matrix_out(pin_num, sig_out, 0, 0);
284 	}
285 
286 	if (flags & ESP32_DIR_INP_FLAG) {
287 		esp_rom_gpio_matrix_in(pin_num, sig_in, 0);
288 	}
289 
290 	return 0;
291 }
292 
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)293 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
294 			   uintptr_t reg)
295 {
296 	uint32_t pin_mux, pin_cfg;
297 	int ret = 0;
298 
299 	ARG_UNUSED(reg);
300 
301 	for (uint8_t i = 0U; i < pin_cnt; i++) {
302 		pin_mux = pins[i].pinmux;
303 		pin_cfg = pins[i].pincfg;
304 
305 		ret = esp32_pin_configure(pin_mux, pin_cfg);
306 		if (ret < 0) {
307 			return ret;
308 		}
309 	}
310 
311 	return 0;
312 }
313