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 <jbroersen@interact.nl>
This commit is contained in:
Jeroen Broersen 2024-09-19 09:57:32 +02:00 committed by Mahesh Mahadevan
parent f61b8f9fd2
commit cf837dd371
2 changed files with 10 additions and 3 deletions

View File

@ -469,6 +469,7 @@ static int gpio_stm32_config(const struct device *dev,
{ {
int err; int err;
uint32_t pincfg; uint32_t pincfg;
struct gpio_stm32_data *data = dev->data;
/* figure out if we can map the requested GPIO /* figure out if we can map the requested GPIO
* configuration * configuration
@ -479,11 +480,13 @@ static int gpio_stm32_config(const struct device *dev,
} }
/* Enable device clock before configuration (requires bank writes) */ /* 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); err = pm_device_runtime_get(dev);
if (err < 0) { if (err < 0) {
return err; return err;
} }
data->pin_has_clock_enabled |= BIT(pin);
} }
if ((flags & GPIO_OUTPUT) != 0) { if ((flags & GPIO_OUTPUT) != 0) {
@ -515,12 +518,14 @@ static int gpio_stm32_config(const struct device *dev,
} }
#endif /* CONFIG_STM32_WKUP_PINS */ #endif /* CONFIG_STM32_WKUP_PINS */
/* Release clock only if pin is disconnected */ /* Decrement GPIO usage count only if pin is now disconnected after being connected */
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_put(dev); err = pm_device_runtime_put(dev);
if (err < 0) { if (err < 0) {
return err; return err;
} }
data->pin_has_clock_enabled &= ~BIT(pin);
} }
return 0; return 0;

View File

@ -259,6 +259,8 @@ struct gpio_stm32_data {
const struct device *dev; const struct device *dev;
/* user ISR cb */ /* user ISR cb */
sys_slist_t 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;
}; };
/** /**