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