From cf837dd371f26472a1b4d2cdf628780184dc05ac Mon Sep 17 00:00:00 2001 From: Jeroen Broersen Date: Thu, 19 Sep 2024 09:57:32 +0200 Subject: [PATCH] drivers: gpio: stm32: keep track of clock enabling per pin The driver enables the clock of a gpio-port if any of the pins use the port. This is done by calling pm_device_runtime_get when a pin is used and pm_device_runtime_put when the pin is not used anymore. These calls needs to be balanced. But if a single pin was configured as GPIO_DISCONNECTED multiple times, every time pm_device_runtime_put was called. This caused the clock of the port to be stopped and therefore also other pins on the same port stopped working. This commit fixes this by keeping track of which pin on a port has requested the clock and only call pm_device_runtime_get or pm_device_runtime_put when the clock-request for the specific pin changes. Fixes #77698 Signed-off-by: Jeroen Broersen --- drivers/gpio/gpio_stm32.c | 11 ++++++++--- drivers/gpio/gpio_stm32.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio_stm32.c b/drivers/gpio/gpio_stm32.c index 407c1a414e6..d077f54e64d 100644 --- a/drivers/gpio/gpio_stm32.c +++ b/drivers/gpio/gpio_stm32.c @@ -469,6 +469,7 @@ static int gpio_stm32_config(const struct device *dev, { int err; uint32_t pincfg; + struct gpio_stm32_data *data = dev->data; /* figure out if we can map the requested GPIO * configuration @@ -479,11 +480,13 @@ static int gpio_stm32_config(const struct device *dev, } /* Enable device clock before configuration (requires bank writes) */ - if (((flags & GPIO_OUTPUT) != 0) || ((flags & GPIO_INPUT) != 0)) { + if ((((flags & GPIO_OUTPUT) != 0) || ((flags & GPIO_INPUT) != 0)) && + !(data->pin_has_clock_enabled & BIT(pin))) { err = pm_device_runtime_get(dev); if (err < 0) { return err; } + data->pin_has_clock_enabled |= BIT(pin); } if ((flags & GPIO_OUTPUT) != 0) { @@ -515,12 +518,14 @@ static int gpio_stm32_config(const struct device *dev, } #endif /* CONFIG_STM32_WKUP_PINS */ - /* Release clock only if pin is disconnected */ - if (((flags & GPIO_OUTPUT) == 0) && ((flags & GPIO_INPUT) == 0)) { + /* Decrement GPIO usage count only if pin is now disconnected after being connected */ + if (((flags & GPIO_OUTPUT) == 0) && ((flags & GPIO_INPUT) == 0) && + (data->pin_has_clock_enabled & BIT(pin))) { err = pm_device_runtime_put(dev); if (err < 0) { return err; } + data->pin_has_clock_enabled &= ~BIT(pin); } return 0; diff --git a/drivers/gpio/gpio_stm32.h b/drivers/gpio/gpio_stm32.h index 8bc4db4c8e2..65b6bcc95da 100644 --- a/drivers/gpio/gpio_stm32.h +++ b/drivers/gpio/gpio_stm32.h @@ -259,6 +259,8 @@ struct gpio_stm32_data { const struct device *dev; /* user ISR cb */ sys_slist_t cb; + /* keep track of pins that are connected and need GPIO clock to be enabled */ + uint32_t pin_has_clock_enabled; }; /**