From bcf2830200ecf30310307ebe28aa8e6de0836cdc Mon Sep 17 00:00:00 2001 From: MartDur Date: Wed, 15 May 2024 15:29:56 +0200 Subject: [PATCH] drivers: i2c: stm32wl: fix i2c stm32wl power managment. Fixes the power managment of the i2c driver for the stm32wl (#[37414]). Initialisation parameters for the stm32wl were lost when going out of power mode STOP2 leaving the i2c driver in a unitialize state. Re-initialising i2c timing when pm device resume solves the issue. Signed-off-by: MartDur --- drivers/i2c/i2c_ll_stm32.c | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/i2c/i2c_ll_stm32.c b/drivers/i2c/i2c_ll_stm32.c index 29f5a5ae08fe508..0c611f8acca3e0a 100644 --- a/drivers/i2c/i2c_ll_stm32.c +++ b/drivers/i2c/i2c_ll_stm32.c @@ -426,6 +426,42 @@ static int i2c_stm32_init(const struct device *dev) return 0; } +#if defined(CONFIG_SOC_SERIES_STM32WLX) +static int i2c_stm32_reinit_timing(const struct device *dev) +{ + int ret; + const struct i2c_stm32_config *cfg = dev->config; + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + uint32_t i2c_clock = 0U; + + if (IS_ENABLED(STM32_I2C_DOMAIN_CLOCK_SUPPORT) && (cfg->pclk_len > 1)) { + if (clock_control_get_rate(clk, (clock_control_subsys_t)&cfg->pclken[1], + &i2c_clock) < 0) { + LOG_ERR("Failed call clock_control_get_rate(pclken[1])"); + return -EIO; + } + } else { + if (clock_control_get_rate(clk, (clock_control_subsys_t)&cfg->pclken[0], + &i2c_clock) < 0) { + LOG_ERR("Failed call clock_control_get_rate(pclken[0])"); + return -EIO; + } + } + +#ifdef CONFIG_PM_DEVICE_RUNTIME + ret = clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken[0]); + if (ret < 0) { + LOG_ERR("failure Enabling I2C clock"); + return ret; + } +#endif + + ret = stm32_i2c_configure_timing(dev, i2c_clock); + + return ret; +} +#endif + #ifdef CONFIG_PM_DEVICE static int i2c_stm32_pm_action(const struct device *dev, enum pm_device_action action) @@ -435,6 +471,9 @@ static int i2c_stm32_pm_action(const struct device *dev, enum pm_device_action a switch (action) { case PM_DEVICE_ACTION_RESUME: err = i2c_stm32_activate(dev); + #if defined(CONFIG_SOC_SERIES_STM32WLX) + i2c_stm32_reinit_timing(dev); + #endif break; case PM_DEVICE_ACTION_SUSPEND: err = i2c_stm32_suspend(dev);