diff --git a/drivers/st/ddr/stm32mp1_ddr_helpers.c b/drivers/st/ddr/stm32mp1_ddr_helpers.c index 4690d0956223fb85d0f1b0f8e1c363a6aa76369a..1d08e24a31e35fdc7db949cebeb45d967c5d8012 100644 --- a/drivers/st/ddr/stm32mp1_ddr_helpers.c +++ b/drivers/st/ddr/stm32mp1_ddr_helpers.c @@ -9,11 +9,15 @@ #include <arch_helpers.h> #include <common/debug.h> #include <drivers/delay_timer.h> +#include <drivers/st/stm32mp1_ddr.h> #include <drivers/st/stm32mp1_ddr_helpers.h> +#include <drivers/st/stm32mp1_ddr_regs.h> #include <lib/mmio.h> #define TIMEOUT_500US 500U +static enum stm32mp1_ddr_sr_mode saved_ddr_sr_mode; + void ddr_enable_clock(void) { stm32mp1_clk_rcc_regs_lock(); @@ -380,7 +384,7 @@ int ddr_standby_sr_entry(void) return 0; } -void ddr_sr_mode_ssr(void) +static void ddr_sr_mode_ssr(void) { uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); @@ -432,7 +436,7 @@ void ddr_sr_mode_ssr(void) DDRCTRL_PWRCTL_SELFREF_EN); } -void ddr_sr_mode_asr(void) +static void ddr_sr_mode_asr(void) { uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); @@ -473,7 +477,7 @@ void ddr_sr_mode_asr(void) DDRCTRL_PWRCTL_SELFREF_EN); } -void ddr_sr_mode_hsr(void) +static void ddr_sr_mode_hsr(void) { uintptr_t rcc_ddritfcr = stm32mp_rcc_base() + RCC_DDRITFCR; uintptr_t ddrctrl_base = stm32mp_ddrctrl_base(); @@ -509,3 +513,54 @@ void ddr_sr_mode_hsr(void) mmio_setbits_32(ddrctrl_base + DDRCTRL_PWRCTL, DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE); } + +enum stm32mp1_ddr_sr_mode ddr_read_sr_mode(void) +{ + uint32_t pwrctl = mmio_read_32(stm32mp_ddrctrl_base() + DDRCTRL_PWRCTL); + + switch (pwrctl & (DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE | + DDRCTRL_PWRCTL_SELFREF_EN)) { + case 0U: + return DDR_SSR_MODE; + + case DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE: + return DDR_HSR_MODE; + + case DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE | DDRCTRL_PWRCTL_SELFREF_EN: + return DDR_ASR_MODE; + + default: + return DDR_SR_MODE_INVALID; + } +} + +void ddr_set_sr_mode(enum stm32mp1_ddr_sr_mode mode) +{ + switch (mode) { + case DDR_SSR_MODE: + ddr_sr_mode_ssr(); + break; + + case DDR_HSR_MODE: + ddr_sr_mode_hsr(); + break; + + case DDR_ASR_MODE: + ddr_sr_mode_asr(); + break; + + default: + ERROR("Unknown Self Refresh mode\n"); + panic(); + } +} + +void ddr_save_sr_mode(void) +{ + saved_ddr_sr_mode = ddr_read_sr_mode(); +} + +void ddr_restore_sr_mode(void) +{ + ddr_set_sr_mode(saved_ddr_sr_mode); +} diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c index 33065bd082d96c3096efb3beee8f4da095cbbd97..c26b5f6f04e0ccac299bff3634cfd5fbcd2db2e3 100644 --- a/drivers/st/ddr/stm32mp1_ram.c +++ b/drivers/st/ddr/stm32mp1_ram.c @@ -344,8 +344,12 @@ static int stm32mp1_ddr_setup(void) } } - /* Switch to Automatic Self-Refresh */ - ddr_sr_mode_asr(); + /* + * Initialization sequence has configured DDR registers with settings. + * The Self Refresh (SR) mode corresponding to these settings has now + * to be set. + */ + ddr_set_sr_mode(ddr_read_sr_mode()); if (stm32mp_unmap_ddr() != 0) { panic(); diff --git a/include/drivers/st/stm32mp1_ddr_helpers.h b/include/drivers/st/stm32mp1_ddr_helpers.h index 920ead00a63dd4a9ff27cc26ba695f9f904fcc70..29c5057d75a0196796f5a3a5e80a948a983c0235 100644 --- a/include/drivers/st/stm32mp1_ddr_helpers.h +++ b/include/drivers/st/stm32mp1_ddr_helpers.h @@ -9,12 +9,20 @@ #include <stdint.h> +enum stm32mp1_ddr_sr_mode { + DDR_SR_MODE_INVALID = 0, + DDR_SSR_MODE, + DDR_HSR_MODE, + DDR_ASR_MODE, +}; + void ddr_enable_clock(void); int ddr_sw_self_refresh_exit(void); uint32_t ddr_get_io_calibration_val(void); int ddr_standby_sr_entry(void); -void ddr_sr_mode_ssr(void); -void ddr_sr_mode_asr(void); -void ddr_sr_mode_hsr(void); +enum stm32mp1_ddr_sr_mode ddr_read_sr_mode(void); +void ddr_set_sr_mode(enum stm32mp1_ddr_sr_mode mode); +void ddr_save_sr_mode(void); +void ddr_restore_sr_mode(void); #endif /* STM32MP1_DDR_HELPERS_H */ diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c index 1ca1cf74a36d29f6f447c22116f34fe89a594df1..9f9011665e554aa4e5d3a64e81784d10dc70b8af 100644 --- a/plat/st/stm32mp1/sp_min/sp_min_setup.c +++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c @@ -28,6 +28,7 @@ #include <drivers/st/stm32mp_clkfunc.h> #include <drivers/st/stm32mp_pmic.h> #include <drivers/st/stm32mp1_clk.h> +#include <drivers/st/stm32mp1_ddr_helpers.h> #include <drivers/st/stpmic1.h> #include <dt-bindings/clock/stm32mp1-clks.h> #include <lib/el3_runtime/context_mgmt.h> @@ -415,6 +416,8 @@ static void init_sec_peripherals(void) ******************************************************************************/ void sp_min_platform_setup(void) { + ddr_save_sr_mode(); + /* Initialize tzc400 after DDR initialization */ stm32mp1_security_setup(); diff --git a/plat/st/stm32mp1/stm32mp1_low_power.c b/plat/st/stm32mp1/stm32mp1_low_power.c index 13f2596da0cdc9c13674e9795a865b09c33f75fb..0eda7b74f1954a944fa4c57f92366a5fad9830c8 100644 --- a/plat/st/stm32mp1/stm32mp1_low_power.c +++ b/plat/st/stm32mp1/stm32mp1_low_power.c @@ -133,8 +133,8 @@ static void enter_cstop(uint32_t mode, uint32_t nsec_addr) stm32mp1_syscfg_disable_io_compensation(); - /* Switch to Software Self-Refresh */ - ddr_sr_mode_ssr(); + /* Switch to Software Self-Refresh mode */ + ddr_set_sr_mode(DDR_SSR_MODE); dcsw_op_all(DC_OP_CISW); @@ -252,8 +252,8 @@ void stm32_exit_cstop(void) panic(); } - /* Switch to Automatic Self-Refresh */ - ddr_sr_mode_asr(); + /* Switch to memorized Self-Refresh mode */ + ddr_restore_sr_mode(); plat_ic_set_priority_mask(gicc_pmr);