Merge branch 'feat/support_esp32p4_flash_psram_sleep_pd_v5.3' into 'release/v5.3'

feat(esp_hw_support): support power down PSRAM or Flash during sleep for esp32p4 v1.0 (v5.3)

See merge request espressif/esp-idf!34390
This commit is contained in:
morris
2024-10-25 11:00:08 +08:00
9 changed files with 67 additions and 13 deletions

View File

@ -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

View File

@ -9,8 +9,10 @@
#include <esp_types.h>
#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);

View File

@ -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 \

View File

@ -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);

View File

@ -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, \
} \
}

View File

@ -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"
@ -1110,6 +1114,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();
@ -1175,6 +1183,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();
@ -2240,6 +2252,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
@ -2324,6 +2341,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;
}

View File

@ -8,8 +8,11 @@
#include <stdint.h>
#include <stdbool.h>
#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;
}

View File

@ -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)

View File

@ -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;