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