From 855bba05823e3366418e3e5213f921d7a336abd1 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 22 Oct 2024 12:07:24 +0800 Subject: [PATCH] feat(esp_hw_support): support power down PSRAM or Flash during sleep for esp32p4 v1.0 --- components/esp_hw_support/Kconfig | 5 ++-- .../esp_hw_support/port/esp32p4/pmu_init.c | 6 ++++- .../esp_hw_support/port/esp32p4/pmu_param.c | 8 +++---- .../esp_hw_support/port/esp32p4/pmu_sleep.c | 11 ++++++++- .../port/esp32p4/private_include/pmu_param.h | 4 ++-- components/esp_hw_support/sleep_modes.c | 24 +++++++++++++++++++ components/hal/esp32p4/include/hal/ldo_ll.h | 7 ++++++ components/hal/esp32p4/include/hal/pmu_ll.h | 6 +++-- .../soc/esp32p4/include/soc/pmu_struct.h | 9 ++++++- 9 files changed, 67 insertions(+), 13 deletions(-) diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 196d54e723..4b7f2c1d9c 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -69,8 +69,9 @@ menu "Hardware Settings" # This is here since this option affect behavior of esp_light_sleep_start # regardless of power management configuration. config ESP_SLEEP_POWER_DOWN_FLASH - bool "Power down flash in light sleep when there is no SPIRAM" - depends on !SPIRAM + bool "Power down flash in light sleep when there is no SPIRAM or SPIRAM has independent power supply" + depends on !SPIRAM || ESP_LDO_RESERVE_PSRAM + depends on !(IDF_TARGET_ESP32P4 && (ESP32P4_REV_MIN_FULL >= 100)) default n help If enabled, chip will try to power down flash as part of esp_light_sleep_start(), which costs diff --git a/components/esp_hw_support/port/esp32p4/pmu_init.c b/components/esp_hw_support/port/esp32p4/pmu_init.c index 92d67002fd..ffebc6a0e2 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_init.c +++ b/components/esp_hw_support/port/esp32p4/pmu_init.c @@ -9,8 +9,10 @@ #include #include "sdkconfig.h" #include "esp_attr.h" +#include "soc/chip_revision.h" #include "soc/soc.h" #include "soc/pmu_struct.h" +#include "hal/efuse_hal.h" #include "hal/pmu_hal.h" #include "pmu_param.h" #include "esp_private/esp_pmu.h" @@ -84,7 +86,9 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, mode, anlg->bias.bias_sleep); pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd); pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd); - pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias); + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100) && (mode == PMU_MODE_HP_SLEEP)) { + pmu_ll_hp_enable_sleep_flash_ldo_channel(ctx->hal->dev, anlg->regulator0.xpd_0p1a); + } pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias); pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b); diff --git a/components/esp_hw_support/port/esp32p4/pmu_param.c b/components/esp_hw_support/port/esp32p4/pmu_param.c index 188d9c66ae..e96cd99dc8 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_param.c +++ b/components/esp_hw_support/port/esp32p4/pmu_param.c @@ -152,8 +152,8 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .dbias_init = 1, \ .slp_mem_xpd = 0, \ .slp_logic_xpd = 0, \ - .slp_mem_dbias = 0, \ - .slp_logic_dbias = 0, \ + .slp_mem_dbias = 1, /* slp_mem_dbias bit[3] controls ext_ldo_1 xpd for rev1.0*/ \ + .slp_logic_dbias = 0, \ }, \ .regulator1 = { \ .drv_b = 0x0 \ @@ -172,8 +172,8 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .regulator0 = { \ .slp_mem_xpd = 0, \ .slp_logic_xpd = 0, \ - .slp_mem_dbias = 0, \ - .slp_logic_dbias = 0, \ + .slp_mem_dbias = 1, /* slp_mem_dbias bit[3] controls ext_ldo_1 xpd for rev1.0*/ \ + .slp_logic_dbias = 0, \ }, \ .regulator1 = { \ .drv_b = 0x0 \ diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index e285bde363..93730e3f52 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -154,6 +154,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default( config->digital = digital_default; pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags); + analog_default.hp_sys.analog.xpd_0p1a = 0; config->analog = analog_default; } else { // Get light sleep digital_default @@ -163,6 +164,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default( // Get light sleep analog default pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags); #if CONFIG_SPIRAM + // Adjust analog parameters to keep EXT_LDO PSRAM channel volt outputting during light-sleep. analog_default.hp_sys.analog.pd_cur = 0; analog_default.lp_sys[PMU_MODE_LP_SLEEP].analog.pd_cur = 0; #endif @@ -189,6 +191,11 @@ const pmu_sleep_config_t* pmu_sleep_config_default( analog_default.hp_sys.analog.dcm_vset = CONFIG_ESP_SLEEP_DCM_VSET_VAL_IN_SLEEP; analog_default.hp_sys.analog.dcm_mode = 1; #endif + if (pd_flags & PMU_SLEEP_PD_VDDSDIO) { + analog_default.hp_sys.analog.xpd_0p1a = 0; + } else { + analog_default.hp_sys.analog.xpd_0p1a = 1; + } config->analog = analog_default; } @@ -229,7 +236,9 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd); pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd); pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd); - pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_dbias); + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) { + pmu_ll_hp_enable_sleep_flash_ldo_channel(ctx->hal->dev, analog->hp_sys.analog.xpd_0p1a); + } pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias); pmu_ll_hp_set_dbg_atten (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbg_atten); pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias); diff --git a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h index 9c8be63ac5..3ee432f291 100644 --- a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h @@ -173,7 +173,7 @@ typedef struct { uint32_t slp_mem_xpd : 1; uint32_t slp_logic_xpd : 1; uint32_t xpd : 1; - uint32_t slp_mem_dbias : 4; + uint32_t xpd_0p1a : 1; // Should map to slp_mem_dbias bit[3] on hardware. uint32_t slp_logic_dbias: 4; uint32_t dbias : 5; }; @@ -325,7 +325,7 @@ typedef struct { #define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(pd_flags) { \ .syscntl = { \ .dig_pad_slp_sel = 0, \ - .lp_pad_hold_all = (pd_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \ + .lp_pad_hold_all = 0, \ } \ } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 2e2b812b9b..5a9b80fac7 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -62,6 +62,10 @@ #include "hal/touch_sensor_hal.h" #endif +#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM +#include "hal/ldo_ll.h" +#endif + #include "sdkconfig.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" @@ -1109,6 +1113,10 @@ static esp_err_t IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection) portENTER_CRITICAL(&spinlock_rtc_deep_sleep); esp_ipc_isr_stall_other_cpu(); esp_ipc_isr_stall_pause(); +#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM + // Disable PSRAM chip power supply + ldo_ll_enable(LDO_ID2UNIT(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN), false); +#endif // record current RTC time s_config.rtc_ticks_at_sleep_start = rtc_time_get(); @@ -1174,6 +1182,10 @@ static esp_err_t IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection) ; } } +#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM + // Enable PSRAM chip power supply + ldo_ll_enable(LDO_ID2UNIT(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN), true); +#endif // Never returns here, except that the sleep is rejected. esp_ipc_isr_stall_resume(); esp_ipc_isr_release_other_cpu(); @@ -2233,6 +2245,11 @@ static uint32_t get_power_down_flags(void) if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option == ESP_PD_OPTION_AUTO) { #ifndef CONFIG_ESP_SLEEP_POWER_DOWN_FLASH s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option = ESP_PD_OPTION_ON; +#endif +#if CONFIG_IDF_TARGET_ESP32P4 + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) { + s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option = ESP_PD_OPTION_ON; + } #endif } #endif @@ -2317,6 +2334,13 @@ static uint32_t get_power_down_flags(void) } #endif +#if CONFIG_IDF_TARGET_ESP32P4 + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) { + if (pd_flags & RTC_SLEEP_PD_VDDSDIO) { + ESP_LOGE(TAG, "ESP32P4 chips lower than v1.0 are not allowed to power down the Flash"); + } + } +#endif return pd_flags; } diff --git a/components/hal/esp32p4/include/hal/ldo_ll.h b/components/hal/esp32p4/include/hal/ldo_ll.h index 6e707890ad..73a63eff19 100644 --- a/components/hal/esp32p4/include/hal/ldo_ll.h +++ b/components/hal/esp32p4/include/hal/ldo_ll.h @@ -8,8 +8,11 @@ #include #include +#include "soc/chip_revision.h" #include "esp_bit_defs.h" #include "hal/misc.h" +#include "hal/efuse_hal.h" +#include "hal/pmu_types.h" #include "soc/pmu_struct.h" #ifdef __cplusplus @@ -122,6 +125,10 @@ __attribute__((always_inline)) static inline void ldo_ll_enable(int ldo_unit, bool enable) { uint8_t index_array[LDO_LL_NUM_UNITS] = {0, 3, 1, 4}; + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100) && (ldo_unit == 0)) { + // If chip_rev >= v1.0, slp_mem_dbias[3] is used to control the volt output of VO1. + PMU.hp_sys[PMU_MODE_HP_ACTIVE].regulator0.xpd_0p1a = (enable ? 8 : 0); + } PMU.ext_ldo[index_array[ldo_unit]].pmu_ext_ldo.xpd = enable; } diff --git a/components/hal/esp32p4/include/hal/pmu_ll.h b/components/hal/esp32p4/include/hal/pmu_ll.h index 0378fbaf42..f64b60cccd 100644 --- a/components/hal/esp32p4/include/hal/pmu_ll.h +++ b/components/hal/esp32p4/include/hal/pmu_ll.h @@ -216,9 +216,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_dbias(pmu_dev_t *hw, hw->hp_sys[mode].regulator0.slp_logic_dbias = slp_dbias; } -FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias) +FORCE_INLINE_ATTR void pmu_ll_hp_enable_sleep_flash_ldo_channel(pmu_dev_t *hw, bool enable) { - hw->hp_sys[mode].regulator0.slp_mem_dbias = slp_dbias; + // slp_mem_dbias[3] is used to control the volt output of VO1 for chip_revision >= 100, + // and this field is not used for chip_revision < 100. + hw->hp_sys[PMU_MODE_HP_SLEEP].regulator0.xpd_0p1a = (enable ? 8 : 0); } FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t dbias) diff --git a/components/soc/esp32p4/include/soc/pmu_struct.h b/components/soc/esp32p4/include/soc/pmu_struct.h index f8727c5c88..d8936af001 100644 --- a/components/soc/esp32p4/include/soc/pmu_struct.h +++ b/components/soc/esp32p4/include/soc/pmu_struct.h @@ -121,6 +121,7 @@ typedef union { } pmu_hp_sysclk_reg_t; typedef union { + // For chip_revsion < 1.0 struct { uint32_t reserved0 : 4; /* Only HP_ACTIVE modem under hp system is valid */ uint32_t lp_dbias_vol : 5; /* Only HP_ACTIVE modem under hp system is valid */ @@ -130,10 +131,16 @@ typedef union { uint32_t slp_mem_xpd : 1; uint32_t slp_logic_xpd : 1; uint32_t xpd : 1; - uint32_t slp_mem_dbias : 4; + uint32_t slp_mem_dbias : 4; /* slp_mem_dbias is not used on chip_revision < 100 */ uint32_t slp_logic_dbias: 4; uint32_t dbias : 5; }; + // For chip revision >= 100 + struct { + uint32_t reserved1 : 19; + uint32_t xpd_0p1a : 4; /* slp_mem_dbias[3] is used to control the volt output of VO1 on chip_revision >= 1.0 */ + uint32_t reserved2 : 9; + }; uint32_t val; } pmu_hp_regulator0_reg_t;