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