From 51278cfac22179471fc426277408860bbac932f5 Mon Sep 17 00:00:00 2001 From: "Kenneth J. Miller" Date: Tue, 13 Jun 2023 06:18:16 +0200 Subject: [PATCH] soc: arm: stm32wl: Reinit select peripherals on STOP2 exit Reinitialize the following peripherals with recently added reinit logic upon exiting STOP2 power state: ADC, I2C, SPI, and USART. These peripherals lose clock context and register contents when the SoC enters STOP2 mode, and don't operate correctly when it reenters RUN mode without individual peripheral reinitialization. closes: #37352 #37414 #59194 Signed-off-by: Kenneth J. Miller --- soc/arm/st_stm32/stm32wl/power.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/soc/arm/st_stm32/stm32wl/power.c b/soc/arm/st_stm32/stm32wl/power.c index e85f55ea39a3d76..49d8459cda313ba 100644 --- a/soc/arm/st_stm32/stm32wl/power.c +++ b/soc/arm/st_stm32/stm32wl/power.c @@ -20,6 +20,11 @@ #include LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); +#include +#include +#include +#include + /* select MSI as wake-up system clock if configured, HSI otherwise */ #if STM32_SYSCLK_SRC_MSI #define RCC_STOP_WAKEUPCLOCK_SELECTED LL_RCC_STOP_WAKEUPCLOCK_MSI @@ -27,6 +32,11 @@ LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); #define RCC_STOP_WAKEUPCLOCK_SELECTED LL_RCC_STOP_WAKEUPCLOCK_HSI #endif +#define STM32_ADC_REINIT(node_id) adc_stm32_reinit(DEVICE_DT_GET(node_id)) +#define STM32_I2C_REINIT(node_id) i2c_stm32_reinit(DEVICE_DT_GET(node_id)) +#define STM32_SPI_REINIT(node_id) spi_stm32_reinit(DEVICE_DT_GET(node_id)) +#define STM32_USART_REINIT(node_id) uart_stm32_reinit(DEVICE_DT_GET(node_id)) + /* Invoke Low Power/System Off specific Tasks */ __weak void pm_state_set(enum pm_state state, uint8_t substate_id) { @@ -76,12 +86,26 @@ __weak void pm_state_set(enum pm_state state, uint8_t substate_id) /* Handle SOC specific activity after Low Power Mode Exit */ __weak void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) { - ARG_UNUSED(substate_id); - switch (state) { case PM_STATE_SUSPEND_TO_IDLE: LL_LPM_DisableSleepOnExit(); LL_LPM_EnableSleep(); + switch (substate_id) { + case 1: /* STOP0 */ + break; + case 2: /* STOP1 */ + break; + case 3: /* STOP2 */ + /* Reinitialize peripheral functionality */ + DT_FOREACH_STATUS_OKAY(st_stm32_adc, STM32_ADC_REINIT); + DT_FOREACH_STATUS_OKAY(st_stm32_i2c_v2, STM32_I2C_REINIT); + DT_FOREACH_STATUS_OKAY(st_stm32_spi, STM32_SPI_REINIT); + DT_FOREACH_STATUS_OKAY(st_stm32_usart, STM32_USART_REINIT); + break; + default: + LOG_DBG("Unsupported power substate-id %u", substate_id); + break; + } /* need to restore the clock */ stm32_clock_control_init(NULL); break; @@ -89,7 +113,7 @@ __weak void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) /* Nothing to do. */ break; default: - LOG_DBG("Unsupported power substate-id %u", state); + LOG_DBG("Unsupported power state %u", state); break; }