1 /*
2  * Copyright (c) 2016 Open-RnD Sp. z o.o.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT st_stm32_gpio
8 
9 #include <errno.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <soc.h>
14 #include <stm32_ll_bus.h>
15 #include <stm32_ll_exti.h>
16 #include <stm32_ll_gpio.h>
17 #include <stm32_ll_pwr.h>
18 #include <zephyr/drivers/gpio.h>
19 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
20 #include <zephyr/sys/util.h>
21 #include <zephyr/drivers/interrupt_controller/gpio_intc_stm32.h>
22 #include <zephyr/pm/device.h>
23 #include <zephyr/pm/device_runtime.h>
24 #include <zephyr/drivers/misc/stm32_wkup_pins/stm32_wkup_pins.h>
25 #include <zephyr/dt-bindings/gpio/stm32-gpio.h>
26 
27 #include "stm32_hsem.h"
28 #include "gpio_stm32.h"
29 #include <zephyr/drivers/gpio/gpio_utils.h>
30 
31 #include <zephyr/logging/log.h>
32 
33 LOG_MODULE_REGISTER(stm32, CONFIG_GPIO_LOG_LEVEL);
34 
35 /**
36  * @brief Common GPIO driver for STM32 MCUs.
37  */
38 
39 /**
40  * @brief EXTI interrupt callback
41  */
gpio_stm32_isr(gpio_port_pins_t pin,void * arg)42 static void gpio_stm32_isr(gpio_port_pins_t pin, void *arg)
43 {
44 	struct gpio_stm32_data *data = arg;
45 
46 	gpio_fire_callbacks(&data->cb, data->dev, pin);
47 }
48 
49 /**
50  * @brief Common gpio flags to custom flags
51  */
gpio_stm32_flags_to_conf(gpio_flags_t flags,uint32_t * pincfg)52 static int gpio_stm32_flags_to_conf(gpio_flags_t flags, uint32_t *pincfg)
53 {
54 
55 	if ((flags & GPIO_OUTPUT) != 0) {
56 		/* Output only or Output/Input */
57 
58 		*pincfg = STM32_PINCFG_MODE_OUTPUT;
59 
60 		if ((flags & GPIO_SINGLE_ENDED) != 0) {
61 			if (flags & GPIO_LINE_OPEN_DRAIN) {
62 				*pincfg |= STM32_PINCFG_OPEN_DRAIN;
63 			} else  {
64 				/* Output can't be open source */
65 				return -ENOTSUP;
66 			}
67 		} else {
68 			*pincfg |= STM32_PINCFG_PUSH_PULL;
69 		}
70 
71 		if ((flags & GPIO_PULL_UP) != 0) {
72 			*pincfg |= STM32_PINCFG_PULL_UP;
73 		} else if ((flags & GPIO_PULL_DOWN) != 0) {
74 			*pincfg |= STM32_PINCFG_PULL_DOWN;
75 		}
76 
77 	} else if  ((flags & GPIO_INPUT) != 0) {
78 		/* Input */
79 
80 		*pincfg = STM32_PINCFG_MODE_INPUT;
81 
82 		if ((flags & GPIO_PULL_UP) != 0) {
83 			*pincfg |= STM32_PINCFG_PULL_UP;
84 		} else if ((flags & GPIO_PULL_DOWN) != 0) {
85 			*pincfg |= STM32_PINCFG_PULL_DOWN;
86 		} else {
87 			*pincfg |= STM32_PINCFG_FLOATING;
88 		}
89 	} else {
90 		/* Deactivated: Analog */
91 		*pincfg = STM32_PINCFG_MODE_ANALOG;
92 	}
93 
94 	return 0;
95 }
96 
97 #if defined(CONFIG_GPIO_GET_CONFIG) && !defined(CONFIG_SOC_SERIES_STM32F1X)
98 /**
99  * @brief Custom stm32 flags to zephyr
100  */
gpio_stm32_pincfg_to_flags(struct gpio_stm32_pin pin_cfg,gpio_flags_t * out_flags)101 static int gpio_stm32_pincfg_to_flags(struct gpio_stm32_pin pin_cfg,
102 				      gpio_flags_t *out_flags)
103 {
104 	gpio_flags_t flags = 0;
105 
106 	if (pin_cfg.mode == LL_GPIO_MODE_OUTPUT) {
107 		flags |= GPIO_OUTPUT;
108 		if (pin_cfg.type == LL_GPIO_OUTPUT_OPENDRAIN) {
109 			flags |= GPIO_OPEN_DRAIN;
110 		}
111 	} else if (pin_cfg.mode == LL_GPIO_MODE_INPUT) {
112 		flags |= GPIO_INPUT;
113 #ifdef CONFIG_SOC_SERIES_STM32F1X
114 	} else if (pin_cfg.mode == LL_GPIO_MODE_FLOATING) {
115 		flags |= GPIO_INPUT;
116 #endif
117 	} else {
118 		flags |= GPIO_DISCONNECTED;
119 	}
120 
121 	if (pin_cfg.pupd == LL_GPIO_PULL_UP) {
122 		flags |= GPIO_PULL_UP;
123 	} else if (pin_cfg.pupd == LL_GPIO_PULL_DOWN) {
124 		flags |= GPIO_PULL_DOWN;
125 	}
126 
127 	if (pin_cfg.out_state != 0) {
128 		flags |= GPIO_OUTPUT_HIGH;
129 	} else {
130 		flags |= GPIO_OUTPUT_LOW;
131 	}
132 
133 	*out_flags = flags;
134 
135 	return 0;
136 }
137 #endif /* CONFIG_GPIO_GET_CONFIG */
138 
139 /**
140  * @brief Translate pin to pinval that the LL library needs
141  */
stm32_pinval_get(gpio_pin_t pin)142 static inline uint32_t stm32_pinval_get(gpio_pin_t pin)
143 {
144 	uint32_t pinval;
145 
146 #ifdef CONFIG_SOC_SERIES_STM32F1X
147 	pinval = (1 << pin) << GPIO_PIN_MASK_POS;
148 	if (pin < 8) {
149 		pinval |= 1 << pin;
150 	} else {
151 		pinval |= (1 << (pin % 8)) | 0x04000000;
152 	}
153 #else
154 	pinval = 1 << pin;
155 #endif
156 	return pinval;
157 }
158 
ll_gpio_set_pin_pull(GPIO_TypeDef * GPIOx,uint32_t Pin,uint32_t Pull)159 static inline void ll_gpio_set_pin_pull(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Pull)
160 {
161 #if defined(CONFIG_SOC_SERIES_STM32WB0X)
162 	/* On STM32WB0, the PWRC PU/PD control registers should be used instead
163 	 * of the GPIO controller registers, so we cannot use LL_GPIO_SetPinPull.
164 	 */
165 	const uint32_t gpio = (GPIOx == GPIOA) ? LL_PWR_GPIO_A : LL_PWR_GPIO_B;
166 
167 	if (Pull == LL_GPIO_PULL_UP) {
168 		LL_PWR_EnableGPIOPullUp(gpio, Pin);
169 		LL_PWR_DisableGPIOPullDown(gpio, Pin);
170 	} else if (Pull == LL_GPIO_PULL_DOWN) {
171 		LL_PWR_EnableGPIOPullDown(gpio, Pin);
172 		LL_PWR_DisableGPIOPullUp(gpio, Pin);
173 	} else if (Pull == LL_GPIO_PULL_NO) {
174 		LL_PWR_DisableGPIOPullUp(gpio, Pin);
175 		LL_PWR_DisableGPIOPullDown(gpio, Pin);
176 	}
177 #else
178 	LL_GPIO_SetPinPull(GPIOx, Pin, Pull);
179 #endif /* CONFIG_SOC_SERIES_STM32WB0X */
180 }
181 
ll_gpio_get_pin_pull(GPIO_TypeDef * GPIOx,uint32_t Pin)182 __maybe_unused static inline uint32_t ll_gpio_get_pin_pull(GPIO_TypeDef *GPIOx, uint32_t Pin)
183 {
184 #if defined(CONFIG_SOC_SERIES_STM32WB0X)
185 	/* On STM32WB0, the PWRC PU/PD control registers should be used instead
186 	 * of the GPIO controller registers, so we cannot use LL_GPIO_GetPinPull.
187 	 */
188 	const uint32_t gpio = (GPIOx == GPIOA) ? LL_PWR_GPIO_A : LL_PWR_GPIO_B;
189 
190 	if (LL_PWR_IsEnabledGPIOPullDown(gpio, Pin)) {
191 		return LL_GPIO_PULL_DOWN;
192 	} else if (LL_PWR_IsEnabledGPIOPullUp(gpio, Pin)) {
193 		return LL_GPIO_PULL_UP;
194 	} else {
195 		return LL_GPIO_PULL_NO;
196 	}
197 #else
198 	return LL_GPIO_GetPinPull(GPIOx, Pin);
199 #endif /* CONFIG_SOC_SERIES_STM32WB0X */
200 }
201 
gpio_stm32_disable_pin_irqs(uint32_t port,gpio_pin_t pin)202 static inline void gpio_stm32_disable_pin_irqs(uint32_t port, gpio_pin_t pin)
203 {
204 #if defined(CONFIG_EXTI_STM32)
205 	if (port != stm32_exti_get_line_src_port(pin)) {
206 		/* EXTI line not owned by this port - do nothing */
207 		return;
208 	}
209 #endif
210 	stm32_gpio_irq_line_t irq_line = stm32_gpio_intc_get_pin_irq_line(port, pin);
211 
212 	stm32_gpio_intc_disable_line(irq_line);
213 	stm32_gpio_intc_remove_irq_callback(irq_line);
214 	stm32_gpio_intc_select_line_trigger(irq_line, STM32_GPIO_IRQ_TRIG_NONE);
215 }
216 
217 /**
218  * @brief Configure the hardware.
219  */
gpio_stm32_configure_raw(const struct device * dev,gpio_pin_t pin,uint32_t conf,uint32_t func)220 static void gpio_stm32_configure_raw(const struct device *dev, gpio_pin_t pin,
221 					uint32_t conf, uint32_t func)
222 {
223 	const struct gpio_stm32_config *cfg = dev->config;
224 	GPIO_TypeDef *gpio = (GPIO_TypeDef *)cfg->base;
225 
226 	uint32_t pin_ll = stm32_pinval_get(pin);
227 
228 #ifdef CONFIG_SOC_SERIES_STM32F1X
229 	ARG_UNUSED(func);
230 
231 	uint32_t temp = conf &
232 			      (STM32_MODE_INOUT_MASK << STM32_MODE_INOUT_SHIFT);
233 
234 	if (temp == STM32_MODE_INPUT) {
235 		temp = conf & (STM32_CNF_IN_MASK << STM32_CNF_IN_SHIFT);
236 
237 		if (temp == STM32_CNF_IN_ANALOG) {
238 			LL_GPIO_SetPinMode(gpio, pin_ll, LL_GPIO_MODE_ANALOG);
239 		} else if (temp == STM32_CNF_IN_FLOAT) {
240 			LL_GPIO_SetPinMode(gpio, pin_ll, LL_GPIO_MODE_FLOATING);
241 		} else {
242 			temp = conf & (STM32_PUPD_MASK << STM32_PUPD_SHIFT);
243 
244 			if (temp == STM32_PUPD_PULL_UP) {
245 				LL_GPIO_SetPinPull(gpio, pin_ll,
246 							       LL_GPIO_PULL_UP);
247 			} else {
248 				LL_GPIO_SetPinPull(gpio, pin_ll,
249 							     LL_GPIO_PULL_DOWN);
250 			}
251 
252 			LL_GPIO_SetPinMode(gpio, pin_ll, LL_GPIO_MODE_INPUT);
253 		}
254 
255 	} else {
256 		temp = conf & (STM32_CNF_OUT_1_MASK << STM32_CNF_OUT_1_SHIFT);
257 
258 		if (temp == STM32_CNF_GP_OUTPUT) {
259 			LL_GPIO_SetPinMode(gpio, pin_ll, LL_GPIO_MODE_OUTPUT);
260 		} else {
261 			LL_GPIO_SetPinMode(gpio, pin_ll,
262 							LL_GPIO_MODE_ALTERNATE);
263 		}
264 
265 		temp = conf & (STM32_CNF_OUT_0_MASK << STM32_CNF_OUT_0_SHIFT);
266 
267 		if (temp == STM32_CNF_PUSH_PULL) {
268 			LL_GPIO_SetPinOutputType(gpio, pin_ll,
269 						       LL_GPIO_OUTPUT_PUSHPULL);
270 		} else {
271 			LL_GPIO_SetPinOutputType(gpio, pin_ll,
272 						      LL_GPIO_OUTPUT_OPENDRAIN);
273 		}
274 
275 		temp = conf &
276 			    (STM32_MODE_OSPEED_MASK << STM32_MODE_OSPEED_SHIFT);
277 
278 		if (temp == STM32_MODE_OUTPUT_MAX_2) {
279 			LL_GPIO_SetPinSpeed(gpio, pin_ll,
280 							LL_GPIO_SPEED_FREQ_LOW);
281 		} else if (temp == STM32_MODE_OUTPUT_MAX_10) {
282 			LL_GPIO_SetPinSpeed(gpio, pin_ll,
283 						     LL_GPIO_SPEED_FREQ_MEDIUM);
284 		} else {
285 			LL_GPIO_SetPinSpeed(gpio, pin_ll,
286 						       LL_GPIO_SPEED_FREQ_HIGH);
287 		}
288 	}
289 #else
290 	uint32_t mode, otype, ospeed, pupd;
291 
292 	mode = conf & (STM32_MODER_MASK << STM32_MODER_SHIFT);
293 	otype = conf & (STM32_OTYPER_MASK << STM32_OTYPER_SHIFT);
294 	ospeed = conf & (STM32_OSPEEDR_MASK << STM32_OSPEEDR_SHIFT);
295 	pupd = conf & (STM32_PUPDR_MASK << STM32_PUPDR_SHIFT);
296 
297 	z_stm32_hsem_lock(CFG_HW_GPIO_SEMID, HSEM_LOCK_DEFAULT_RETRY);
298 
299 #if defined(CONFIG_SOC_SERIES_STM32L4X) && defined(GPIO_ASCR_ASC0)
300 	/*
301 	 * For STM32L47xx/48xx, register ASCR should be configured to connect
302 	 * analog switch of gpio lines to the ADC.
303 	 */
304 	if (mode == STM32_MODER_ANALOG_MODE) {
305 		LL_GPIO_EnablePinAnalogControl(gpio, pin_ll);
306 	}
307 #endif
308 
309 	LL_GPIO_SetPinOutputType(gpio, pin_ll, otype >> STM32_OTYPER_SHIFT);
310 
311 	LL_GPIO_SetPinSpeed(gpio, pin_ll, ospeed >> STM32_OSPEEDR_SHIFT);
312 
313 	ll_gpio_set_pin_pull(gpio, pin_ll, pupd >> STM32_PUPDR_SHIFT);
314 
315 	if (mode == STM32_MODER_ALT_MODE) {
316 		if (pin < 8) {
317 			LL_GPIO_SetAFPin_0_7(gpio, pin_ll, func);
318 		} else {
319 			LL_GPIO_SetAFPin_8_15(gpio, pin_ll, func);
320 		}
321 	}
322 
323 	LL_GPIO_SetPinMode(gpio, pin_ll, mode >> STM32_MODER_SHIFT);
324 
325 	z_stm32_hsem_unlock(CFG_HW_GPIO_SEMID);
326 #endif  /* CONFIG_SOC_SERIES_STM32F1X */
327 
328 }
329 
330 /**
331  * @brief GPIO port clock handling
332  */
gpio_stm32_clock_request(const struct device * dev,bool on)333 static int gpio_stm32_clock_request(const struct device *dev, bool on)
334 {
335 	const struct gpio_stm32_config *cfg = dev->config;
336 	int ret;
337 
338 	__ASSERT_NO_MSG(dev != NULL);
339 
340 	/* enable clock for subsystem */
341 	const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
342 
343 	if (on) {
344 		ret = clock_control_on(clk,
345 					(clock_control_subsys_t)&cfg->pclken);
346 	} else {
347 		ret = clock_control_off(clk,
348 					(clock_control_subsys_t)&cfg->pclken);
349 	}
350 
351 	return ret;
352 }
353 
gpio_stm32_port_get_raw(const struct device * dev,uint32_t * value)354 static int gpio_stm32_port_get_raw(const struct device *dev, uint32_t *value)
355 {
356 	const struct gpio_stm32_config *cfg = dev->config;
357 	GPIO_TypeDef *gpio = (GPIO_TypeDef *)cfg->base;
358 
359 	*value = LL_GPIO_ReadInputPort(gpio);
360 
361 	return 0;
362 }
363 
gpio_stm32_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)364 static int gpio_stm32_port_set_masked_raw(const struct device *dev,
365 					  gpio_port_pins_t mask,
366 					  gpio_port_value_t value)
367 {
368 	const struct gpio_stm32_config *cfg = dev->config;
369 	GPIO_TypeDef *gpio = (GPIO_TypeDef *)cfg->base;
370 	uint32_t port_value;
371 
372 	z_stm32_hsem_lock(CFG_HW_GPIO_SEMID, HSEM_LOCK_DEFAULT_RETRY);
373 
374 	port_value = LL_GPIO_ReadOutputPort(gpio);
375 	LL_GPIO_WriteOutputPort(gpio, (port_value & ~mask) | (mask & value));
376 
377 	z_stm32_hsem_unlock(CFG_HW_GPIO_SEMID);
378 
379 	return 0;
380 }
381 
gpio_stm32_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)382 static int gpio_stm32_port_set_bits_raw(const struct device *dev,
383 					gpio_port_pins_t pins)
384 {
385 	const struct gpio_stm32_config *cfg = dev->config;
386 	GPIO_TypeDef *gpio = (GPIO_TypeDef *)cfg->base;
387 
388 	/*
389 	 * On F1 series, using LL API requires a costly pin mask translation.
390 	 * Skip it and use CMSIS API directly. Valid also on other series.
391 	 */
392 	WRITE_REG(gpio->BSRR, pins);
393 
394 	return 0;
395 }
396 
gpio_stm32_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)397 static int gpio_stm32_port_clear_bits_raw(const struct device *dev,
398 					  gpio_port_pins_t pins)
399 {
400 	const struct gpio_stm32_config *cfg = dev->config;
401 	GPIO_TypeDef *gpio = (GPIO_TypeDef *)cfg->base;
402 
403 #ifdef CONFIG_SOC_SERIES_STM32F1X
404 	/*
405 	 * On F1 series, using LL API requires a costly pin mask translation.
406 	 * Skip it and use CMSIS API directly.
407 	 */
408 	WRITE_REG(gpio->BRR, pins);
409 #else
410 	/* On other series, LL abstraction is needed  */
411 	LL_GPIO_ResetOutputPin(gpio, pins);
412 #endif
413 
414 	return 0;
415 }
416 
gpio_stm32_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)417 static int gpio_stm32_port_toggle_bits(const struct device *dev,
418 				       gpio_port_pins_t pins)
419 {
420 	const struct gpio_stm32_config *cfg = dev->config;
421 	GPIO_TypeDef *gpio = (GPIO_TypeDef *)cfg->base;
422 
423 	/*
424 	 * On F1 series, using LL API requires a costly pin mask translation.
425 	 * Skip it and use CMSIS API directly. Valid also on other series.
426 	 */
427 	z_stm32_hsem_lock(CFG_HW_GPIO_SEMID, HSEM_LOCK_DEFAULT_RETRY);
428 	WRITE_REG(gpio->ODR, READ_REG(gpio->ODR) ^ pins);
429 	z_stm32_hsem_unlock(CFG_HW_GPIO_SEMID);
430 
431 	return 0;
432 }
433 
434 #ifdef CONFIG_SOC_SERIES_STM32F1X
435 #define IS_GPIO_OUT GPIO_OUT
436 #else
437 #define IS_GPIO_OUT STM32_GPIO
438 #endif
439 
gpio_stm32_configure(const struct device * dev,gpio_pin_t pin,uint32_t conf,uint32_t func)440 int gpio_stm32_configure(const struct device *dev, gpio_pin_t pin, uint32_t conf, uint32_t func)
441 {
442 	int ret;
443 
444 	ret = pm_device_runtime_get(dev);
445 	if (ret < 0) {
446 		return ret;
447 	}
448 
449 	gpio_stm32_configure_raw(dev, pin, conf, func);
450 
451 	if (func == IS_GPIO_OUT) {
452 		uint32_t gpio_out = conf & (STM32_ODR_MASK << STM32_ODR_SHIFT);
453 
454 		if (gpio_out == STM32_ODR_1) {
455 			gpio_stm32_port_set_bits_raw(dev, BIT(pin));
456 		} else if (gpio_out == STM32_ODR_0) {
457 			gpio_stm32_port_clear_bits_raw(dev, BIT(pin));
458 		}
459 	}
460 
461 	return pm_device_runtime_put(dev);
462 }
463 
464 /**
465  * @brief Configure pin or port
466  */
gpio_stm32_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)467 static int gpio_stm32_config(const struct device *dev,
468 			     gpio_pin_t pin, gpio_flags_t flags)
469 {
470 	int err;
471 	uint32_t pincfg;
472 	struct gpio_stm32_data *data = dev->data;
473 
474 	/* figure out if we can map the requested GPIO
475 	 * configuration
476 	 */
477 	err = gpio_stm32_flags_to_conf(flags, &pincfg);
478 	if (err != 0) {
479 		return err;
480 	}
481 
482 	/* Enable device clock before configuration (requires bank writes) */
483 	if ((((flags & GPIO_OUTPUT) != 0) || ((flags & GPIO_INPUT) != 0)) &&
484 	    !(data->pin_has_clock_enabled & BIT(pin))) {
485 		err = pm_device_runtime_get(dev);
486 		if (err < 0) {
487 			return err;
488 		}
489 		data->pin_has_clock_enabled |= BIT(pin);
490 	}
491 
492 	if ((flags & GPIO_OUTPUT) != 0) {
493 		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
494 			gpio_stm32_port_set_bits_raw(dev, BIT(pin));
495 		} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
496 			gpio_stm32_port_clear_bits_raw(dev, BIT(pin));
497 		}
498 	}
499 
500 	gpio_stm32_configure_raw(dev, pin, pincfg, 0);
501 
502 #ifdef CONFIG_STM32_WKUP_PINS
503 	if (flags & STM32_GPIO_WKUP) {
504 #ifdef CONFIG_POWEROFF
505 		struct gpio_dt_spec gpio_dt_cfg = {
506 			.port = dev,
507 			.pin = pin,
508 			.dt_flags = (gpio_dt_flags_t)flags,
509 		};
510 
511 		if (stm32_pwr_wkup_pin_cfg_gpio((const struct gpio_dt_spec *)&gpio_dt_cfg)) {
512 			LOG_ERR("Could not configure GPIO %s pin %d as a wake-up source",
513 					gpio_dt_cfg.port->name, gpio_dt_cfg.pin);
514 		}
515 #else
516 		LOG_DBG("STM32_GPIO_WKUP flag has no effect when CONFIG_POWEROFF=n");
517 #endif /* CONFIG_POWEROFF */
518 	}
519 #endif /* CONFIG_STM32_WKUP_PINS */
520 
521 	/* Decrement GPIO usage count only if pin is now disconnected after being connected */
522 	if (((flags & GPIO_OUTPUT) == 0) && ((flags & GPIO_INPUT) == 0) &&
523 	    (data->pin_has_clock_enabled & BIT(pin))) {
524 		err = pm_device_runtime_put(dev);
525 		if (err < 0) {
526 			return err;
527 		}
528 		data->pin_has_clock_enabled &= ~BIT(pin);
529 	}
530 
531 	return 0;
532 }
533 
534 #if defined(CONFIG_GPIO_GET_CONFIG) && !defined(CONFIG_SOC_SERIES_STM32F1X)
535 /**
536  * @brief Get configuration of pin
537  */
gpio_stm32_get_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t * flags)538 static int gpio_stm32_get_config(const struct device *dev,
539 				 gpio_pin_t pin, gpio_flags_t *flags)
540 {
541 	const struct gpio_stm32_config *cfg = dev->config;
542 	GPIO_TypeDef *gpio = (GPIO_TypeDef *)cfg->base;
543 	struct gpio_stm32_pin pin_config;
544 	uint32_t pin_ll;
545 	int err;
546 
547 	err = pm_device_runtime_get(dev);
548 	if (err < 0) {
549 		return err;
550 	}
551 
552 	pin_ll = stm32_pinval_get(pin);
553 	pin_config.type = LL_GPIO_GetPinOutputType(gpio, pin_ll);
554 	pin_config.pupd = ll_gpio_get_pin_pull(gpio, pin_ll);
555 	pin_config.mode = LL_GPIO_GetPinMode(gpio, pin_ll);
556 	pin_config.out_state = LL_GPIO_IsOutputPinSet(gpio, pin_ll);
557 
558 	gpio_stm32_pincfg_to_flags(pin_config, flags);
559 
560 	return pm_device_runtime_put(dev);
561 }
562 #endif /* CONFIG_GPIO_GET_CONFIG */
563 
gpio_stm32_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)564 static int gpio_stm32_pin_interrupt_configure(const struct device *dev,
565 					      gpio_pin_t pin,
566 					      enum gpio_int_mode mode,
567 					      enum gpio_int_trig trig)
568 {
569 	const struct gpio_stm32_config *cfg = dev->config;
570 	struct gpio_stm32_data *data = dev->data;
571 	const stm32_gpio_irq_line_t irq_line = stm32_gpio_intc_get_pin_irq_line(cfg->port, pin);
572 	uint32_t irq_trigger = 0;
573 	int err = 0;
574 
575 #ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
576 	if (mode == GPIO_INT_MODE_DISABLE_ONLY) {
577 		stm32_gpio_intc_disable_line(irq_line);
578 		goto exit;
579 	} else if (mode == GPIO_INT_MODE_ENABLE_ONLY) {
580 		stm32_gpio_intc_enable_line(irq_line);
581 		goto exit;
582 	}
583 #endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
584 
585 	if (mode == GPIO_INT_MODE_DISABLED) {
586 		gpio_stm32_disable_pin_irqs(cfg->port, pin);
587 		goto exit;
588 	}
589 
590 	if (mode == GPIO_INT_MODE_LEVEL) {
591 		/* Level-sensitive interrupts are only supported on STM32WB0. */
592 		if (!IS_ENABLED(CONFIG_SOC_SERIES_STM32WB0X)) {
593 			err = -ENOTSUP;
594 			goto exit;
595 		} else {
596 			switch (trig) {
597 			case GPIO_INT_TRIG_LOW:
598 				irq_trigger = STM32_GPIO_IRQ_TRIG_LOW_LEVEL;
599 				break;
600 			case GPIO_INT_TRIG_HIGH:
601 				irq_trigger = STM32_GPIO_IRQ_TRIG_HIGH_LEVEL;
602 				break;
603 			default:
604 				err = -EINVAL;
605 				goto exit;
606 			}
607 		}
608 	} else {
609 		switch (trig) {
610 		case GPIO_INT_TRIG_LOW:
611 			irq_trigger = STM32_GPIO_IRQ_TRIG_FALLING;
612 			break;
613 		case GPIO_INT_TRIG_HIGH:
614 			irq_trigger = STM32_GPIO_IRQ_TRIG_RISING;
615 			break;
616 		case GPIO_INT_TRIG_BOTH:
617 			irq_trigger = STM32_GPIO_IRQ_TRIG_BOTH;
618 			break;
619 		default:
620 			err = -EINVAL;
621 			goto exit;
622 		}
623 	}
624 
625 	if (stm32_gpio_intc_set_irq_callback(irq_line, gpio_stm32_isr, data) != 0) {
626 		err = -EBUSY;
627 		goto exit;
628 	}
629 
630 #if defined(CONFIG_EXTI_STM32)
631 	stm32_exti_set_line_src_port(pin, cfg->port);
632 #endif
633 
634 	stm32_gpio_intc_select_line_trigger(irq_line, irq_trigger);
635 
636 	stm32_gpio_intc_enable_line(irq_line);
637 
638 exit:
639 	return err;
640 }
641 
gpio_stm32_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)642 static int gpio_stm32_manage_callback(const struct device *dev,
643 				      struct gpio_callback *callback,
644 				      bool set)
645 {
646 	struct gpio_stm32_data *data = dev->data;
647 
648 	return gpio_manage_callback(&data->cb, callback, set);
649 }
650 
651 static DEVICE_API(gpio, gpio_stm32_driver) = {
652 	.pin_configure = gpio_stm32_config,
653 #if defined(CONFIG_GPIO_GET_CONFIG) && !defined(CONFIG_SOC_SERIES_STM32F1X)
654 	.pin_get_config = gpio_stm32_get_config,
655 #endif /* CONFIG_GPIO_GET_CONFIG */
656 	.port_get_raw = gpio_stm32_port_get_raw,
657 	.port_set_masked_raw = gpio_stm32_port_set_masked_raw,
658 	.port_set_bits_raw = gpio_stm32_port_set_bits_raw,
659 	.port_clear_bits_raw = gpio_stm32_port_clear_bits_raw,
660 	.port_toggle_bits = gpio_stm32_port_toggle_bits,
661 	.pin_interrupt_configure = gpio_stm32_pin_interrupt_configure,
662 	.manage_callback = gpio_stm32_manage_callback,
663 };
664 
665 #ifdef CONFIG_PM_DEVICE
gpio_stm32_pm_action(const struct device * dev,enum pm_device_action action)666 static int gpio_stm32_pm_action(const struct device *dev,
667 				enum pm_device_action action)
668 {
669 	switch (action) {
670 	case PM_DEVICE_ACTION_RESUME:
671 		return gpio_stm32_clock_request(dev, true);
672 	case PM_DEVICE_ACTION_SUSPEND:
673 		return gpio_stm32_clock_request(dev, false);
674 	default:
675 		return -ENOTSUP;
676 	}
677 
678 	return 0;
679 }
680 #endif /* CONFIG_PM_DEVICE */
681 
682 
683 /**
684  * @brief Initialize GPIO port
685  *
686  * Perform basic initialization of a GPIO port. The code will
687  * enable the clock for corresponding peripheral.
688  *
689  * @param dev GPIO device struct
690  *
691  * @return 0
692  */
gpio_stm32_init(const struct device * dev)693 static int gpio_stm32_init(const struct device *dev)
694 {
695 	struct gpio_stm32_data *data = dev->data;
696 	int ret;
697 
698 	data->dev = dev;
699 
700 	if (!device_is_ready(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE))) {
701 		return -ENODEV;
702 	}
703 
704 #if (defined(PWR_CR2_IOSV) || defined(PWR_SVMCR_IO2SV)) && \
705 	DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpiog))
706 	z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
707 	/* Port G[15:2] requires external power supply */
708 	/* Cf: L4/L5 RM, Chapter "Independent I/O supply rail" */
709 	LL_PWR_EnableVddIO2();
710 	z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
711 #endif
712 	/* enable port clock (if runtime PM is not enabled) */
713 	ret = gpio_stm32_clock_request(dev, !IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME));
714 	if (ret < 0) {
715 		return ret;
716 	}
717 
718 	if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
719 		pm_device_init_suspended(dev);
720 	}
721 	(void)pm_device_runtime_enable(dev);
722 
723 	return 0;
724 }
725 
726 #define GPIO_DEVICE_INIT(__node, __suffix, __base_addr, __port, __cenr, __bus) \
727 	static const struct gpio_stm32_config gpio_stm32_cfg_## __suffix = {   \
728 		.common = {						       \
729 			 .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_NGPIOS(16U), \
730 		},							       \
731 		.base = (uint32_t *)__base_addr,				       \
732 		.port = __port,						       \
733 		.pclken = { .bus = __bus, .enr = __cenr }		       \
734 	};								       \
735 	static struct gpio_stm32_data gpio_stm32_data_## __suffix;	       \
736 	PM_DEVICE_DT_DEFINE(__node, gpio_stm32_pm_action);		       \
737 	DEVICE_DT_DEFINE(__node,					       \
738 			    gpio_stm32_init,				       \
739 			    PM_DEVICE_DT_GET(__node),			       \
740 			    &gpio_stm32_data_## __suffix,		       \
741 			    &gpio_stm32_cfg_## __suffix,		       \
742 			    PRE_KERNEL_1,				       \
743 			    CONFIG_GPIO_INIT_PRIORITY,			       \
744 			    &gpio_stm32_driver)
745 
746 #define GPIO_DEVICE_INIT_STM32(__suffix, __SUFFIX)			\
747 	GPIO_DEVICE_INIT(DT_NODELABEL(gpio##__suffix),	\
748 			 __suffix,					\
749 			 DT_REG_ADDR(DT_NODELABEL(gpio##__suffix)),	\
750 			 STM32_PORT##__SUFFIX,				\
751 			 DT_CLOCKS_CELL(DT_NODELABEL(gpio##__suffix), bits),\
752 			 DT_CLOCKS_CELL(DT_NODELABEL(gpio##__suffix), bus))
753 
754 #define GPIO_DEVICE_INIT_STM32_IF_OKAY(__suffix, __SUFFIX) \
755 	COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio##__suffix)), \
756 		    (GPIO_DEVICE_INIT_STM32(__suffix, __SUFFIX)), \
757 		    ())
758 
759 GPIO_DEVICE_INIT_STM32_IF_OKAY(a, A);
760 GPIO_DEVICE_INIT_STM32_IF_OKAY(b, B);
761 GPIO_DEVICE_INIT_STM32_IF_OKAY(c, C);
762 GPIO_DEVICE_INIT_STM32_IF_OKAY(d, D);
763 GPIO_DEVICE_INIT_STM32_IF_OKAY(e, E);
764 GPIO_DEVICE_INIT_STM32_IF_OKAY(f, F);
765 GPIO_DEVICE_INIT_STM32_IF_OKAY(g, G);
766 GPIO_DEVICE_INIT_STM32_IF_OKAY(h, H);
767 GPIO_DEVICE_INIT_STM32_IF_OKAY(i, I);
768 GPIO_DEVICE_INIT_STM32_IF_OKAY(j, J);
769 GPIO_DEVICE_INIT_STM32_IF_OKAY(k, K);
770 
771 GPIO_DEVICE_INIT_STM32_IF_OKAY(m, M);
772 GPIO_DEVICE_INIT_STM32_IF_OKAY(n, N);
773 GPIO_DEVICE_INIT_STM32_IF_OKAY(o, O);
774 GPIO_DEVICE_INIT_STM32_IF_OKAY(p, P);
775