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