Merge branch 'feat/wait_pll_stable_after_sleep_wakeup_fix_xtal_v5.4' into 'release/v5.4'

feat(esp_hw_support): wait pll stable after sleep wakeup (v5.4)

See merge request espressif/esp-idf!36018
This commit is contained in:
Jiang Jiang Jian 2025-02-20 10:36:20 +08:00
commit 23db06892b
19 changed files with 429 additions and 329 deletions

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -46,11 +46,11 @@ typedef enum {
#define RTC_SLEEP_PD_MODEM PMU_SLEEP_PD_MODEM //!< Power down modem(include wifi, ble and 15.4)
//These flags are not power domains, but will affect some sleep parameters
#define RTC_SLEEP_DIG_USE_8M BIT(16)
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
#define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(19)
#define RTC_SLEEP_LP_PERIPH_USE_XTAL BIT(20)
#define RTC_SLEEP_DIG_USE_8M BIT(27)
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(28)
#define RTC_SLEEP_NO_ULTRA_LOW BIT(29) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
#define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(30)
#define RTC_SLEEP_LP_PERIPH_USE_XTAL BIT(31)
#if SOC_PM_SUPPORT_EXT0_WAKEUP
#define RTC_EXT0_TRIG_EN PMU_EXT0_WAKEUP_EN //!< EXT0 wakeup
@ -205,40 +205,40 @@ bool pmu_sleep_pll_already_enabled(void);
/**
* @brief Calculate the LP system hardware time overhead during sleep
*
* @param pd_flags flags indicates the power domain that will be powered down
* @param sleep_flags flags indicates the power domain that will be powered down and the sleep submode
* @param slowclk_period re-calibrated slow clock period
* @param fastclk_period re-calibrated fast clock period
*
* @return hardware time overhead in us
*/
uint32_t pmu_sleep_calculate_lp_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period);
uint32_t pmu_sleep_calculate_lp_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period);
/**
* @brief Calculate the HP system hardware time overhead during sleep
*
* @param pd_flags flags indicates the power domain that will be powered down
* @param sleep_flags flags indicates the power domain that will be powered down and the sleep submode
* @param slowclk_period re-calibrated slow clock period
* @param fastclk_period re-calibrated fast clock period
*
* @return hardware time overhead in us
*/
uint32_t pmu_sleep_calculate_hp_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period);
uint32_t pmu_sleep_calculate_hp_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period);
/**
* @brief Calculate the hardware time overhead during sleep to compensate for sleep time
*
* @param pd_flags flags indicates the power domain that will be powered down
* @param sleep_flags flags indicates the power domain that will be powered down and the sleep submode
* @param slowclk_period re-calibrated slow clock period
* @param fastclk_period re-calibrated fast clock period
*
* @return hardware time overhead in us
*/
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period);
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period);
/**
* @brief Get default sleep configuration
* @param config pmu_sleep_config instance
* @param pd_flags flags indicates the power domain that will be powered down
* @param sleep_flags flags indicates the power domain that will be powered down and the sleep submode
* @param adjustment total software and hardware time overhead
* @param slowclk_period re-calibrated slow clock period in microseconds,
* Q13.19 fixed point format
@ -248,7 +248,7 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe
* @return hardware time overhead in us
*/
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, uint32_t pd_flags, uint32_t adjustment, uint32_t slowclk_period, uint32_t fastclk_period, bool dslp);
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, uint32_t sleep_flags, uint32_t adjustment, uint32_t slowclk_period, uint32_t fastclk_period, bool dslp);
/**
* @brief Prepare the chip to enter sleep mode

View File

@ -6,10 +6,12 @@
#include "esp_private/sleep_clock.h"
#include "soc/pcr_reg.h"
#include "soc/pmu_reg.h"
#include "soc/rtc.h"
#include "modem/modem_syscon_reg.h"
#include "modem/modem_lpcon_reg.h"
#include "soc/i2c_ana_mst_reg.h"
#include "soc/regi2c_defs.h"
#include "soc/chip_revision.h"
#include "hal/efuse_hal.h"
@ -18,18 +20,30 @@ static const char *TAG = "sleep_clock";
esp_err_t sleep_clock_system_retention_init(void *arg)
{
const static sleep_retention_entries_config_t pcr_regs_retention[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), PCR_AHB_FREQ_CONF_REG, 0, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(0) | ENTRY(1) }, /* Set AHB bus frequency to XTAL frequency */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(0) | ENTRY(1) },
/* Enable i2c master clock */
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PCR_LINK(0), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(0) },
/* Start BBPLL self-calibration */
[1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PCR_LINK(1), I2C_ANA_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) },
[2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PCR_LINK(2), I2C_ANA_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW, I2C_MST_BBPLL_STOP_FORCE_LOW, 1, 0), .owner = ENTRY(0) },
/* Wait calibration done */
[3] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(3), I2C_ANA_MST_ANA_CONF0_REG, I2C_MST_BBPLL_CAL_DONE, I2C_MST_BBPLL_CAL_DONE, 1, 0), .owner = ENTRY(0) },
/* Stop BBPLL self-calibration */
[4] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PCR_LINK(4), I2C_ANA_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_LOW, 1, 0), .owner = ENTRY(0) },
[5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PCR_LINK(5), I2C_ANA_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) },
/* Clock configuration retention */
[6] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(6), PMU_CLK_STATE0_REG, PMU_STABLE_XPD_BBPLL_STATE, PMU_STABLE_XPD_BBPLL_STATE_M, 1, 0), .owner = ENTRY(0)}, /* Wait PMU_WAIT_XTL_STABLE done */
[7] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PCR_LINK(7), PCR_AHB_FREQ_CONF_REG, 0, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(0) | ENTRY(1) }, /* Set AHB bus frequency to XTAL frequency */
[8] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PCR_LINK(8), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(0) | ENTRY(1) },
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
[2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(2), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 75, 0, 0, 0xffffffff, 0xffffffff, 0x200007f7, 0x0), .owner = ENTRY(0) | ENTRY(1) },
[9] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(9), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 75, 0, 0, 0xffffffff, 0xffffffff, 0x200007f7, 0x0), .owner = ENTRY(0) | ENTRY(1) },
#endif
};
esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention");
const static sleep_retention_entries_config_t modem_ahb_config[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(3), PCR_AHB_FREQ_CONF_REG, 3, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(1) }, /* Set AHB bus frequency to 40 MHz under PMU MODEM state */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(4), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(1) },
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(4), PCR_AHB_FREQ_CONF_REG, 3, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(1) }, /* Set AHB bus frequency to 40 MHz under PMU MODEM state */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(5), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(1) },
};
err = sleep_retention_entries_create(modem_ahb_config, ARRAY_SIZE(modem_ahb_config), REGDMA_LINK_PRI_4, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention, 4 level priority");
@ -41,10 +55,10 @@ esp_err_t sleep_clock_system_retention_init(void *arg)
* the PHY_I2C_MST_CMD_TYPE_BBPLL_CFG command from PHY i2c master
* command memory */
sleep_retention_entries_config_t bbpll_config[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(5), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(1) }, /* I2C MST enable */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(6), I2C_ANA_MST_I2C_BURST_CONF_REG, 0, 0xffffffff, 1, 0), .owner = ENTRY(1) },
[2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(7), I2C_ANA_MST_I2C_BURST_STATUS_REG, I2C_ANA_MST_BURST_DONE, 0x1, 1, 0), .owner = ENTRY(1) },
[3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(8), MODEM_LPCON_CLK_CONF_REG, 0, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(1) }, /* I2C MST disable */
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(6), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(1) }, /* I2C MST enable */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(7), I2C_ANA_MST_I2C_BURST_CONF_REG, 0, 0xffffffff, 1, 0), .owner = ENTRY(1) },
[2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(8), I2C_ANA_MST_I2C_BURST_STATUS_REG, I2C_ANA_MST_BURST_DONE, 0x1, 1, 0), .owner = ENTRY(1) },
[3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(9), MODEM_LPCON_CLK_CONF_REG, 0, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(1) }, /* I2C MST disable */
};
extern uint32_t phy_ana_i2c_master_burst_bbpll_config(void);
bbpll_config[1].config.write_wait.value = phy_ana_i2c_master_burst_bbpll_config();

View File

@ -6,6 +6,9 @@
#include "esp_private/sleep_clock.h"
#include "soc/pcr_reg.h"
#include "soc/pmu_reg.h"
#include "soc/regi2c_defs.h"
#include "modem/modem_lpcon_reg.h"
#include "modem/modem_syscon_reg.h"
static const char *TAG = "sleep_clock";
@ -15,8 +18,19 @@ esp_err_t sleep_clock_system_retention_init(void *arg)
#define N_REGS_PCR() (((PCR_SRAM_POWER_CONF_REG - DR_REG_PCR_BASE) / 4) + 1)
const static sleep_retention_entries_config_t pcr_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(0), DR_REG_PCR_BASE, DR_REG_PCR_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(0x1), PCR_RESET_EVENT_BYPASS_REG, PCR_RESET_EVENT_BYPASS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
/* Enable i2c master clock */
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(0) },
/* Start BBPLL self-calibration */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), I2C_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) },
[2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(2), I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW, I2C_MST_BBPLL_STOP_FORCE_LOW, 1, 0), .owner = ENTRY(0) },
/* Wait calibration done */
[3] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(3), I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_CAL_DONE, I2C_MST_BBPLL_CAL_DONE, 1, 0), .owner = ENTRY(0) },
/* Stop BBPLL self-calibration */
[4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(4), I2C_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_LOW, 1, 0), .owner = ENTRY(0) },
[5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(5), I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) },
/* Clock configuration retention */
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(6), DR_REG_PCR_BASE, DR_REG_PCR_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(7), PCR_RESET_EVENT_BYPASS_REG, PCR_RESET_EVENT_BYPASS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
};
esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);

View File

@ -6,6 +6,10 @@
#include "esp_private/sleep_clock.h"
#include "soc/pcr_reg.h"
#include "soc/pmu_reg.h"
#include "soc/i2c_ana_mst_reg.h"
#include "soc/regi2c_defs.h"
#include "modem/modem_lpcon_reg.h"
#include "modem/modem_syscon_reg.h"
static const char *TAG = "sleep_clock";
@ -13,10 +17,22 @@ static const char *TAG = "sleep_clock";
esp_err_t sleep_clock_system_retention_init(void *arg)
{
const static sleep_retention_entries_config_t pcr_regs_retention[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), PCR_AHB_FREQ_CONF_REG, 0, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(0) | ENTRY(1) }, /* Set AHB bus frequency to XTAL frequency */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(0) | ENTRY(1) },
/* Enable i2c master clock */
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(0) },
/* Start BBPLL self-calibration */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), I2C_ANA_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) },
[2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(2), I2C_ANA_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW, I2C_MST_BBPLL_STOP_FORCE_LOW, 1, 0), .owner = ENTRY(0) },
/* Wait calibration done */
[3] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(3), I2C_ANA_MST_ANA_CONF0_REG, I2C_MST_BBPLL_CAL_DONE, I2C_MST_BBPLL_CAL_DONE, 1, 0), .owner = ENTRY(0) },
/* Stop BBPLL self-calibration */
[4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(4), I2C_ANA_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_LOW, 1, 0), .owner = ENTRY(0) },
[5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(5), I2C_ANA_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) },
/* Clock configuration retention */
[6] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(6), PMU_CLK_STATE0_REG, PMU_STABLE_XPD_BBPLL_STATE, PMU_STABLE_XPD_BBPLL_STATE_M, 1, 0), .owner = ENTRY(0)}, /* Wait PMU_WAIT_XTL_STABLE done */
[7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(7), PCR_AHB_FREQ_CONF_REG, 0, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(0) | ENTRY(1) }, /* Set AHB bus frequency to XTAL frequency */
[8] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(8), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(0) | ENTRY(1) },
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
[2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(2), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 63, 0, 0, 0xfd73ffff, 0xfdffffff, 0xe001, 0x0), .owner = ENTRY(0) | ENTRY(1) }
[9] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(9), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 63, 0, 0, 0xfd73ffff, 0xfdffffff, 0xe001, 0x0), .owner = ENTRY(0) | ENTRY(1) }
#endif
};
@ -24,8 +40,8 @@ esp_err_t sleep_clock_system_retention_init(void *arg)
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention");
const static sleep_retention_entries_config_t modem_ahb_config[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(3), PCR_AHB_FREQ_CONF_REG, 3, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(1) }, /* Set AHB bus frequency to 40 MHz under PMU MODEM state */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(4), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(1) },
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(4), PCR_AHB_FREQ_CONF_REG, 3, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(1) }, /* Set AHB bus frequency to 40 MHz under PMU MODEM state */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(5), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(1) },
};
err = sleep_retention_entries_create(modem_ahb_config, ARRAY_SIZE(modem_ahb_config), REGDMA_LINK_PRI_4, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention, 4 level priority");

View File

@ -5,7 +5,10 @@
*/
#include "esp_private/sleep_clock.h"
#include "soc/i2c_ana_mst_reg.h"
#include "soc/regi2c_defs.h"
#include "soc/pcr_reg.h"
#include "soc/regi2c_defs.h"
#include "modem/modem_syscon_reg.h"
#include "modem/modem_lpcon_reg.h"
@ -17,10 +20,21 @@ esp_err_t sleep_clock_system_retention_init(void *arg)
#define N_REGS_PCR() (((PCR_PWDET_SAR_CLK_CONF_REG - DR_REG_PCR_BASE) / 4) + 1)
const static sleep_retention_entries_config_t pcr_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(0), DR_REG_PCR_BASE, DR_REG_PCR_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(0x1), PCR_RESET_EVENT_BYPASS_REG, PCR_RESET_EVENT_BYPASS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0x2), PCR_BUS_CLK_UPDATE_REG, PCR_BUS_CLOCK_UPDATE, PCR_BUS_CLOCK_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[3] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(0x3), PCR_BUS_CLK_UPDATE_REG, 0x0, PCR_BUS_CLOCK_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
/* Enable i2c master clock */
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(0) },
/* Start BBPLL self-calibration */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), I2C_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) },
[2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(2), I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW, I2C_MST_BBPLL_STOP_FORCE_LOW, 1, 0), .owner = ENTRY(0) },
/* Wait calibration done */
[3] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(3), I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_CAL_DONE, I2C_MST_BBPLL_CAL_DONE, 1, 0), .owner = ENTRY(0) },
/* Stop BBPLL self-calibration */
[4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(4), I2C_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_LOW, 1, 0), .owner = ENTRY(0) },
[5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(5), I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) },
/* Clock configuration retention */
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(6), DR_REG_PCR_BASE, DR_REG_PCR_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(7), PCR_RESET_EVENT_BYPASS_REG, PCR_RESET_EVENT_BYPASS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[8] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(8), PCR_BUS_CLK_UPDATE_REG, PCR_BUS_CLOCK_UPDATE, PCR_BUS_CLOCK_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[9] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(9), PCR_BUS_CLK_UPDATE_REG, 0x0, PCR_BUS_CLOCK_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
};
esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);

View File

@ -6,6 +6,9 @@
#include "esp_private/sleep_clock.h"
#include "soc/hp_sys_clkrst_reg.h"
#include "soc/pmu_reg.h"
#include "soc/lpperi_reg.h"
#include "pmu_bit_defs.h"
static const char *TAG = "sleep_clock";
@ -14,11 +17,20 @@ esp_err_t sleep_clock_system_retention_init(void *arg)
#define N_REGS_PCR() (((HP_SYS_CLKRST_HPCORE_WDT_RESET_SOURCE0_REG - DR_REG_HP_SYS_CLKRST_BASE) / 4) + 1)
const static sleep_retention_entries_config_t pcr_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(0x0), DR_REG_HP_SYS_CLKRST_BASE, DR_REG_HP_SYS_CLKRST_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) }, /* pcr */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0x01), HP_SYS_CLKRST_ROOT_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_SOC_CLK_DIV_UPDATE, HP_SYS_CLKRST_REG_SOC_CLK_DIV_UPDATE_M, 1, 0), .owner = ENTRY(0) },
[2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(0x02), HP_SYS_CLKRST_ROOT_CLK_CTRL0_REG, 0x0, HP_SYS_CLKRST_REG_SOC_CLK_DIV_UPDATE_M, 1, 0), .owner = ENTRY(0) },
[3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0x03), HP_SYS_CLKRST_PERI_CLK_CTRL02_REG, HP_SYS_CLKRST_REG_SDIO_LS_CLK_EDGE_CFG_UPDATE, HP_SYS_CLKRST_REG_SDIO_LS_CLK_EDGE_CFG_UPDATE_M, 1, 0), .owner = ENTRY(0) },
[4] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(0x04), HP_SYS_CLKRST_PERI_CLK_CTRL02_REG, 0x0, HP_SYS_CLKRST_REG_SDIO_LS_CLK_EDGE_CFG_UPDATE_M, 1, 0), .owner = ENTRY(0) },
/* Enable i2c master clock */
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), LPPERI_CLK_EN_REG, LPPERI_CK_EN_LP_I2CMST, LPPERI_CK_EN_LP_I2CMST_M, 1, 1), .owner = ENTRY(0) },
/* Start SYSPLL self-calibration */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, 0, HP_SYS_CLKRST_REG_SYS_PLL_CAL_STOP_M, 1, 1), .owner = ENTRY(0) },
/* Wait calibration done */
[2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(2), HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, HP_SYS_CLKRST_REG_SYS_PLL_CAL_END, HP_SYS_CLKRST_REG_SYS_PLL_CAL_END_M, 1, 0), .owner = ENTRY(0) },
/* Stop SYSPLL self-calibration */
[3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(3), HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, HP_SYS_CLKRST_REG_SYS_PLL_CAL_STOP, HP_SYS_CLKRST_REG_SYS_PLL_CAL_STOP_M, 1, 0), .owner = ENTRY(0) },
/* Clock configuration retention */
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(4), DR_REG_HP_SYS_CLKRST_BASE, DR_REG_HP_SYS_CLKRST_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) }, /* pcr */
[5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(5), HP_SYS_CLKRST_ROOT_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_SOC_CLK_DIV_UPDATE, HP_SYS_CLKRST_REG_SOC_CLK_DIV_UPDATE_M, 1, 0), .owner = ENTRY(0) },
[6] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(6), HP_SYS_CLKRST_ROOT_CLK_CTRL0_REG, 0x0, HP_SYS_CLKRST_REG_SOC_CLK_DIV_UPDATE_M, 1, 0), .owner = ENTRY(0) },
[7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(7), HP_SYS_CLKRST_PERI_CLK_CTRL02_REG, HP_SYS_CLKRST_REG_SDIO_LS_CLK_EDGE_CFG_UPDATE, HP_SYS_CLKRST_REG_SDIO_LS_CLK_EDGE_CFG_UPDATE_M, 1, 0), .owner = ENTRY(0) },
[8] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(8), HP_SYS_CLKRST_PERI_CLK_CTRL02_REG, 0x0, HP_SYS_CLKRST_REG_SDIO_LS_CLK_EDGE_CFG_UPDATE_M, 1, 0), .owner = ENTRY(0) },
};
esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -51,17 +51,18 @@ void pmu_sleep_disable_regdma_backup(void)
}
}
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period)
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period)
{
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
/* LP core hardware wait time, microsecond */
const int lp_wakeup_wait_time_us = rtc_time_slowclk_to_us(mc->lp.wakeup_wait_cycle, slowclk_period);
const int lp_clk_switch_time_us = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period);
const int lp_clk_power_on_wait_time_us = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
/* If XTAL is used as RTC_FAST clock source, it is started in LP_SLEEP -> LP_ACTIVE stage and the clock waiting time is counted into lp_hw_wait_time */
const int lp_clk_power_on_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && (sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
const int lp_control_wait_time_us = mc->lp.isolate_wait_time_us + mc->lp.reset_wait_time_us;
const int lp_hw_wait_time_us = mc->lp.min_slp_time_us + mc->lp.analog_wait_time_us + lp_clk_power_on_wait_time_us \
+ lp_wakeup_wait_time_us + lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us \
+ mc->lp.power_up_wait_time_us + lp_control_wait_time_us;
@ -69,11 +70,15 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe
/* HP core hardware wait time, microsecond */
const int hp_digital_power_up_wait_time_us = mc->hp.power_supply_wait_time_us + mc->hp.power_up_wait_time_us;
const int hp_control_wait_time_us = mc->hp.isolate_wait_time_us + mc->hp.reset_wait_time_us;
const int hp_regdma_wait_time_us = MAX(mc->hp.regdma_s2m_work_time_us + mc->hp.regdma_m2a_work_time_us, mc->hp.regdma_s2a_work_time_us);
const int hp_clock_wait_time_us = mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us;
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + MAX(hp_clock_wait_time_us, \
hp_digital_power_up_wait_time_us + hp_control_wait_time_us + hp_regdma_wait_time_us);
const int hp_regdma_wait_time_us = s_pmu_sleep_regdma_backup_enabled \
? MAX(mc->hp.regdma_s2m_work_time_us + mc->hp.regdma_m2a_work_time_us, mc->hp.regdma_s2a_work_time_us) \
: 0;
/* If XTAL is not used as RTC_FAST clock source, it is started in HP_SLEEP -> HP_ACTIVE stage and the clock waiting time is counted into hp_hw_wait_time */
const int hp_clock_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && !(sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us \
: mc->hp.pll_wait_stable_time_us;
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + hp_digital_power_up_wait_time_us + hp_clock_wait_time_us \
+ hp_regdma_wait_time_us + hp_control_wait_time_us;
/* When the SOC wakeup (lp timer or GPIO wakeup) and Modem wakeup (Beacon wakeup) complete, the soc
* wakeup will be delayed until the RF is turned on in Modem state.
@ -107,7 +112,7 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe
static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
pmu_sleep_param_config_t *param,
pmu_sleep_power_config_t *power, /* We'll use the runtime power parameter to determine some hardware parameters */
const uint32_t pd_flags,
const uint32_t sleep_flags,
const uint32_t adjustment,
const uint32_t slowclk_period,
const uint32_t fastclk_period
@ -123,7 +128,7 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
param->hp_sys.isolate_wait_cycle = rtc_time_us_to_fastclk(mc->hp.isolate_wait_time_us, fastclk_period);
param->hp_sys.reset_wait_cycle = rtc_time_us_to_fastclk(mc->hp.reset_wait_time_us, fastclk_period);
const int hw_wait_time_us = pmu_sleep_calculate_hw_wait_time(pd_flags, slowclk_period, fastclk_period);
const int hw_wait_time_us = pmu_sleep_calculate_hw_wait_time(sleep_flags, slowclk_period, fastclk_period);
const int modem_state_skip_time_us = mc->hp.regdma_m2a_work_time_us + mc->hp.system_dfs_up_work_time_us + mc->lp.min_slp_time_us;
const int modem_wakeup_wait_time_us = adjustment - hw_wait_time_us + modem_state_skip_time_us + mc->hp.regdma_rf_on_work_time_us;
param->hp_sys.modem_wakeup_wait_cycle = rtc_time_us_to_fastclk(modem_wakeup_wait_time_us, fastclk_period);
@ -145,36 +150,30 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
const pmu_sleep_config_t* pmu_sleep_config_default(
pmu_sleep_config_t *config,
uint32_t pd_flags,
uint32_t sleep_flags,
uint32_t adjustment,
uint32_t slowclk_period,
uint32_t fastclk_period,
bool dslp
)
{
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags);
uint32_t iram_pd_flags = 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G0) ? BIT(0) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G1) ? BIT(1) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G2) ? BIT(2) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G3) ? BIT(3) : 0;
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
config->power = power_default;
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags);
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period);
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period);
if (dslp) {
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags);
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
config->analog = analog_default;
} else {
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags);
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
if (!(pd_flags & PMU_SLEEP_PD_XTAL) || !(pd_flags & PMU_SLEEP_PD_RC_FAST)){
if (!(sleep_flags & PMU_SLEEP_PD_XTAL) || !(sleep_flags & PMU_SLEEP_PD_RC_FAST)){
analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
analog_default.hp_sys.analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
analog_default.hp_sys.analog.dbias = HP_CALI_DBIAS_SLP_1V1;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -273,14 +273,14 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_power_config_t;
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.dig_power = { \
.vdd_spi_pd_en = ((pd_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \
.wifi_pd_en = ((pd_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \
.cpu_pd_en = ((pd_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \
.aon_pd_en = ((pd_flags) & PMU_SLEEP_PD_HP_AON) ? 1 : 0, \
.top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
.vdd_spi_pd_en = ((sleep_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0,\
.wifi_pd_en = ((sleep_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0,\
.cpu_pd_en = ((sleep_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0,\
.aon_pd_en = ((sleep_flags) & PMU_SLEEP_PD_HP_AON) ? 1 : 0,\
.top_pd_en = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0,\
.mem_pd_en = 0, \
.mem_dslp = 0 \
}, \
@ -292,7 +292,7 @@ typedef struct {
.xpd_bbpll = 0 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
@ -301,23 +301,23 @@ typedef struct {
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = 1 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.dig_power = { \
.peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.peri_pd_en = ((sleep_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((sleep_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
} \
}
@ -326,9 +326,9 @@ typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.syscntl = { \
.dig_pad_slp_sel = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
} \
}
@ -341,7 +341,7 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_analog_config_t;
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
@ -366,7 +366,7 @@ typedef struct {
} \
}
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.pd_cur = PMU_PD_CUR_SLEEP_ON, \
@ -395,7 +395,7 @@ typedef struct {
pmu_hp_lp_param_t hp_lp;
} pmu_sleep_param_config_t;
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \
.analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \
@ -485,7 +485,7 @@ typedef struct pmu_sleep_machine_constant {
.regdma_rf_on_work_time_us = 60, \
.regdma_rf_off_work_time_us = 25, \
.xtal_wait_stable_time_us = 250, \
.pll_wait_stable_time_us = 1 \
.pll_wait_stable_time_us = 50 \
} \
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -105,26 +105,32 @@ void pmu_sleep_disable_regdma_backup(void)
}
}
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period)
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period)
{
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
/* LP core hardware wait time, microsecond */
const int lp_wakeup_wait_time_us = rtc_time_slowclk_to_us(mc->lp.wakeup_wait_cycle, slowclk_period);
const int lp_clk_switch_time_us = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period);
const int lp_clk_power_on_wait_time_us = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
/* If XTAL is used as RTC_FAST clock source, it is started in LP_SLEEP -> LP_ACTIVE stage and the clock waiting time is counted into lp_hw_wait_time */
const int lp_clk_power_on_wait_time_us = (sleep_flags & PMU_SLEEP_PD_XTAL) && (sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST) \
? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
const int lp_hw_wait_time_us = mc->lp.min_slp_time_us + mc->lp.analog_wait_time_us + lp_clk_power_on_wait_time_us \
+ lp_wakeup_wait_time_us + lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us \
+ mc->lp.power_up_wait_time_us;
/* HP core hardware wait time, microsecond */
const int hp_digital_power_up_wait_time_us = mc->hp.power_supply_wait_time_us + mc->hp.power_up_wait_time_us;
const int hp_regdma_wait_time_us = MAX(mc->hp.regdma_s2m_work_time_us + mc->hp.regdma_m2a_work_time_us, mc->hp.regdma_s2a_work_time_us);
const int hp_clock_wait_time_us = mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us;
const int hp_regdma_wait_time_us = s_pmu_sleep_regdma_backup_enabled \
? MAX(mc->hp.regdma_s2m_work_time_us + mc->hp.regdma_m2a_work_time_us, mc->hp.regdma_s2a_work_time_us) \
: 0;
/* If XTAL is not used as RTC_FAST clock source, it is started in HP_SLEEP -> HP_ACTIVE stage and the clock waiting time is counted into hp_hw_wait_time */
const int hp_clock_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && !(sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us \
: mc->hp.pll_wait_stable_time_us;
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + MAX(hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us, hp_clock_wait_time_us);
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us + hp_clock_wait_time_us;
/* When the SOC wakeup (lp timer or GPIO wakeup) and Modem wakeup (Beacon wakeup) complete, the soc
* wakeup will be delayed until the RF is turned on in Modem state.
@ -158,7 +164,7 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe
static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
pmu_sleep_param_config_t *param,
pmu_sleep_power_config_t *power, /* We'll use the runtime power parameter to determine some hardware parameters */
const uint32_t pd_flags,
const uint32_t sleep_flags,
const uint32_t adjustment,
const uint32_t slowclk_period,
const uint32_t fastclk_period
@ -172,7 +178,7 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
param->hp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_up_wait_time_us, fastclk_period);
param->hp_sys.pll_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.pll_wait_stable_time_us, fastclk_period);
const int hw_wait_time_us = pmu_sleep_calculate_hw_wait_time(pd_flags, slowclk_period, fastclk_period);
const int hw_wait_time_us = pmu_sleep_calculate_hw_wait_time(sleep_flags, slowclk_period, fastclk_period);
const int modem_state_skip_time_us = mc->hp.regdma_m2a_work_time_us + mc->hp.system_dfs_up_work_time_us + mc->lp.min_slp_time_us;
const int modem_wakeup_wait_time_us = adjustment - hw_wait_time_us + modem_state_skip_time_us + mc->hp.regdma_rf_on_work_time_us;
param->hp_sys.modem_wakeup_wait_cycle = rtc_time_us_to_fastclk(modem_wakeup_wait_time_us, fastclk_period);

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -269,14 +269,14 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_power_config_t;
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.dig_power = { \
.vdd_spi_pd_en = ((pd_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \
.wifi_pd_en = ((pd_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \
.cpu_pd_en = ((pd_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \
.aon_pd_en = ((pd_flags) & PMU_SLEEP_PD_HP_AON) ? 1 : 0, \
.top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
.vdd_spi_pd_en = ((sleep_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0,\
.wifi_pd_en = ((sleep_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0,\
.cpu_pd_en = ((sleep_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0,\
.aon_pd_en = ((sleep_flags) & PMU_SLEEP_PD_HP_AON) ? 1 : 0,\
.top_pd_en = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0,\
.mem_pd_en = 0, \
.mem_dslp = 0 \
}, \
@ -288,7 +288,7 @@ typedef struct {
.xpd_bbpll = 0 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
@ -297,23 +297,23 @@ typedef struct {
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = 1 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.dig_power = { \
.peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.peri_pd_en = ((sleep_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.mem_dslp = 1 \
}, \
.clk_power = { \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((sleep_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
} \
}
@ -322,9 +322,9 @@ typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.syscntl = { \
.dig_pad_slp_sel = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
} \
}
@ -337,7 +337,7 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_analog_config_t;
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
@ -362,7 +362,7 @@ typedef struct {
} \
}
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
@ -391,7 +391,7 @@ typedef struct {
pmu_hp_lp_param_t hp_lp;
} pmu_sleep_param_config_t;
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \
.analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \
@ -474,7 +474,7 @@ typedef struct pmu_sleep_machine_constant {
.regdma_rf_on_work_time_us = 70, \
.regdma_rf_off_work_time_us = 23, \
.xtal_wait_stable_time_us = 250, \
.pll_wait_stable_time_us = 1 \
.pll_wait_stable_time_us = 50 \
} \
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -51,17 +51,18 @@ void pmu_sleep_disable_regdma_backup(void)
}
}
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period)
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period)
{
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
/* LP core hardware wait time, microsecond */
const int lp_wakeup_wait_time_us = rtc_time_slowclk_to_us(mc->lp.wakeup_wait_cycle, slowclk_period);
const int lp_clk_switch_time_us = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period);
const int lp_clk_power_on_wait_time_us = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
/* If XTAL is used as RTC_FAST clock source, it is started in LP_SLEEP -> LP_ACTIVE stage and the clock waiting time is counted into lp_hw_wait_time */
const int lp_clk_power_on_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && (sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
const int lp_control_wait_time_us = mc->lp.isolate_wait_time_us + mc->lp.reset_wait_time_us;
const int lp_hw_wait_time_us = mc->lp.min_slp_time_us + mc->lp.analog_wait_time_us + lp_clk_power_on_wait_time_us \
+ lp_wakeup_wait_time_us + lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us \
+ mc->lp.power_up_wait_time_us + lp_control_wait_time_us;
@ -69,11 +70,15 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe
/* HP core hardware wait time, microsecond */
const int hp_digital_power_up_wait_time_us = mc->hp.power_supply_wait_time_us + mc->hp.power_up_wait_time_us;
const int hp_control_wait_time_us = mc->hp.isolate_wait_time_us + mc->hp.reset_wait_time_us;
const int hp_regdma_wait_time_us = MAX(mc->hp.regdma_s2m_work_time_us + mc->hp.regdma_m2a_work_time_us, mc->hp.regdma_s2a_work_time_us);
const int hp_clock_wait_time_us = mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us;
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + MAX(hp_clock_wait_time_us, \
hp_digital_power_up_wait_time_us + hp_control_wait_time_us + hp_regdma_wait_time_us);
const int hp_regdma_wait_time_us = s_pmu_sleep_regdma_backup_enabled \
? MAX(mc->hp.regdma_s2m_work_time_us + mc->hp.regdma_m2a_work_time_us, mc->hp.regdma_s2a_work_time_us) \
: 0;
/* If XTAL is not used as RTC_FAST clock source, it is started in HP_SLEEP -> HP_ACTIVE stage and the clock waiting time is counted into hp_hw_wait_time */
const int hp_clock_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && !(sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us \
: mc->hp.pll_wait_stable_time_us;
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + hp_digital_power_up_wait_time_us + hp_clock_wait_time_us \
+ hp_regdma_wait_time_us + hp_control_wait_time_us;
/* When the SOC wakeup (lp timer or GPIO wakeup) and Modem wakeup (Beacon wakeup) complete, the soc
* wakeup will be delayed until the RF is turned on in Modem state.
@ -107,7 +112,7 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe
static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
pmu_sleep_param_config_t *param,
pmu_sleep_power_config_t *power, /* We'll use the runtime power parameter to determine some hardware parameters */
const uint32_t pd_flags,
const uint32_t sleep_flags,
const uint32_t adjustment,
const uint32_t slowclk_period,
const uint32_t fastclk_period
@ -123,7 +128,7 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
param->hp_sys.isolate_wait_cycle = rtc_time_us_to_fastclk(mc->hp.isolate_wait_time_us, fastclk_period);
param->hp_sys.reset_wait_cycle = rtc_time_us_to_fastclk(mc->hp.reset_wait_time_us, fastclk_period);
const int hw_wait_time_us = pmu_sleep_calculate_hw_wait_time(pd_flags, slowclk_period, fastclk_period);
const int hw_wait_time_us = pmu_sleep_calculate_hw_wait_time(sleep_flags, slowclk_period, fastclk_period);
const int modem_state_skip_time_us = mc->hp.regdma_m2a_work_time_us + mc->hp.system_dfs_up_work_time_us + mc->lp.min_slp_time_us;
const int modem_wakeup_wait_time_us = adjustment - hw_wait_time_us + modem_state_skip_time_us + mc->hp.regdma_rf_on_work_time_us;
param->hp_sys.modem_wakeup_wait_cycle = rtc_time_us_to_fastclk(modem_wakeup_wait_time_us, fastclk_period);
@ -145,36 +150,30 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
const pmu_sleep_config_t* pmu_sleep_config_default(
pmu_sleep_config_t *config,
uint32_t pd_flags,
uint32_t sleep_flags,
uint32_t adjustment,
uint32_t slowclk_period,
uint32_t fastclk_period,
bool dslp
)
{
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags);
uint32_t iram_pd_flags = 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G0) ? BIT(0) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G1) ? BIT(1) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G2) ? BIT(2) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G3) ? BIT(3) : 0;
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
config->power = power_default;
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags);
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period);
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period);
if (dslp) {
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags);
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
config->analog = analog_default;
} else {
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags);
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
if (!(pd_flags & PMU_SLEEP_PD_XTAL) || !(pd_flags & PMU_SLEEP_PD_RC_FAST)){
if (!(sleep_flags & PMU_SLEEP_PD_XTAL) || !(sleep_flags & PMU_SLEEP_PD_RC_FAST)){
analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
analog_default.hp_sys.analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
analog_default.hp_sys.analog.dbias = HP_CALI_DBIAS_SLP_1V1;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -271,14 +271,14 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_power_config_t;
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.dig_power = { \
.vdd_spi_pd_en = ((pd_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \
.wifi_pd_en = ((pd_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \
.cpu_pd_en = ((pd_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \
.aon_pd_en = ((pd_flags) & PMU_SLEEP_PD_HP_AON) ? 1 : 0, \
.top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
.vdd_spi_pd_en = ((sleep_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0,\
.wifi_pd_en = ((sleep_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0,\
.cpu_pd_en = ((sleep_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0,\
.aon_pd_en = ((sleep_flags) & PMU_SLEEP_PD_HP_AON) ? 1 : 0,\
.top_pd_en = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0,\
.mem_pd_en = 0, \
.mem_dslp = 0 \
}, \
@ -290,7 +290,7 @@ typedef struct {
.xpd_bbpll = 0 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
@ -299,23 +299,23 @@ typedef struct {
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = 1 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.dig_power = { \
.peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.peri_pd_en = ((sleep_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((sleep_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
} \
}
@ -324,9 +324,9 @@ typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.syscntl = { \
.dig_pad_slp_sel = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
} \
}
@ -339,7 +339,7 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_analog_config_t;
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
@ -364,7 +364,7 @@ typedef struct {
} \
}
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
@ -393,7 +393,7 @@ typedef struct {
pmu_hp_lp_param_t hp_lp;
} pmu_sleep_param_config_t;
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \
.analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \
@ -483,7 +483,7 @@ typedef struct pmu_sleep_machine_constant {
.regdma_rf_on_work_time_us = 138, \
.regdma_rf_off_work_time_us = 28, \
.xtal_wait_stable_time_us = 250, \
.pll_wait_stable_time_us = 1 \
.pll_wait_stable_time_us = 50 \
} \
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -63,29 +63,32 @@ void pmu_sleep_disable_regdma_backup(void)
pmu_hal_hp_set_sleep_active_backup_disable(PMU_instance()->hal);
}
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period)
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period)
{
pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
/* LP core hardware wait time, microsecond */
const int lp_clk_switch_time_us = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period);
const int lp_clk_power_on_wait_time_us = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
/* If XTAL is used as RTC_FAST clock source, it is started in LP_SLEEP -> LP_ACTIVE stage and the clock waiting time is counted into lp_hw_wait_time */
const int lp_clk_power_on_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && (sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
const int lp_hw_wait_time_us = mc->lp.min_slp_time_us + mc->lp.analog_wait_time_us + lp_clk_power_on_wait_time_us \
+ lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us + mc->lp.power_up_wait_time_us;
+ lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us + mc->lp.power_up_wait_time_us;
/* HP core hardware wait time, microsecond */
const int hp_digital_power_up_wait_time_us = mc->hp.power_supply_wait_time_us + mc->hp.power_up_wait_time_us;
if (pd_flags & PMU_SLEEP_PD_TOP) {
if (sleep_flags & PMU_SLEEP_PD_TOP) {
mc->hp.regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_PD_TOP_US;
} else {
mc->hp.regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_PU_TOP_US;
}
const int hp_regdma_wait_time_us = mc->hp.regdma_s2a_work_time_us;
const int hp_clock_wait_time_us = mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us;
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + MAX(hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us, hp_clock_wait_time_us);
/* If XTAL is not used as RTC_FAST clock source, it is started in HP_SLEEP -> HP_ACTIVE stage and the clock waiting time is counted into hp_hw_wait_time */
const int hp_clock_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && !(sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us \
: mc->hp.pll_wait_stable_time_us;
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us + hp_clock_wait_time_us;
const int rf_on_protect_time_us = 0;
const int total_hw_wait_time_us = lp_hw_wait_time_us + hp_hw_wait_time_us;
@ -98,7 +101,7 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe
static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
pmu_sleep_param_config_t *param,
pmu_sleep_power_config_t *power, /* We'll use the runtime power parameter to determine some hardware parameters */
const uint32_t pd_flags,
const uint32_t sleep_flags,
const uint32_t adjustment,
const uint32_t slowclk_period,
const uint32_t fastclk_period
@ -127,37 +130,31 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
const pmu_sleep_config_t* pmu_sleep_config_default(
pmu_sleep_config_t *config,
uint32_t pd_flags,
uint32_t sleep_flags,
uint32_t adjustment,
uint32_t slowclk_period,
uint32_t fastclk_period,
bool dslp
)
{
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags);
uint32_t iram_pd_flags = 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G0) ? BIT(0) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G1) ? BIT(1) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G2) ? BIT(2) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G3) ? BIT(3) : 0;
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
config->power = power_default;
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags);
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period);
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period);
if (dslp) {
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags);
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
config->analog = analog_default;
} else {
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags);
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
analog_default.hp_sys.analog.dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6_DEFAULT;
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
if (!(pd_flags & PMU_SLEEP_PD_XTAL)){
if (!(sleep_flags & PMU_SLEEP_PD_XTAL)){
analog_default.hp_sys.analog.xpd_trx = PMU_XPD_TRX_SLEEP_ON;
analog_default.hp_sys.analog.dbias = get_act_hp_dbias();
analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
@ -166,7 +163,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_act_lp_dbias();
} else if (!(pd_flags & PMU_SLEEP_PD_RC_FAST)) {
} else if (!(sleep_flags & PMU_SLEEP_PD_RC_FAST)) {
analog_default.hp_sys.analog.dbias = get_act_hp_dbias();
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_act_lp_dbias();
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -259,13 +259,13 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_power_config_t;
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.dig_power = { \
.vdd_spi_pd_en = ((pd_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \
.wifi_pd_en = ((pd_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \
.cpu_pd_en = ((pd_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \
.top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
.vdd_spi_pd_en = ((sleep_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0,\
.wifi_pd_en = ((sleep_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0,\
.cpu_pd_en = ((sleep_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0,\
.top_pd_en = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0,\
.mem_pd_en = 0, \
.mem_dslp = 0 \
}, \
@ -277,7 +277,7 @@ typedef struct {
.xpd_bbpll = 0 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
@ -286,23 +286,23 @@ typedef struct {
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = 1 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.dig_power = { \
.peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.peri_pd_en = ((sleep_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.mem_dslp = 1 \
}, \
.clk_power = { \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((sleep_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
} \
}
@ -312,9 +312,9 @@ typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.syscntl = { \
.dig_pad_slp_sel = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
} \
}
@ -327,7 +327,7 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_analog_config_t;
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.xpd_trx = PMU_XPD_TRX_SLEEP_DEFAULT, \
@ -351,7 +351,7 @@ typedef struct {
} \
}
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.xpd_trx = PMU_XPD_TRX_SLEEP_DEFAULT, \
@ -379,7 +379,7 @@ typedef struct {
pmu_hp_lp_param_t hp_lp;
} pmu_sleep_param_config_t;
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \
.analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \
@ -447,7 +447,7 @@ typedef struct pmu_sleep_machine_constant {
.regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_PD_TOP_US, \
.regdma_a2s_work_time_us = 0, \
.xtal_wait_stable_time_us = 250, \
.pll_wait_stable_time_us = 1 \
.pll_wait_stable_time_us = 50 \
} \
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -67,14 +67,16 @@ void pmu_sleep_disable_regdma_backup(void)
}
}
uint32_t pmu_sleep_calculate_lp_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period)
uint32_t pmu_sleep_calculate_lp_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period)
{
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
/* LP core hardware wait time, microsecond */
const int lp_wakeup_wait_time_us = rtc_time_slowclk_to_us(mc->lp.wakeup_wait_cycle, slowclk_period);
const int lp_clk_switch_time_us = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period);
const int lp_clk_power_on_wait_time_us = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
/* If XTAL is used as RTC_FAST clock source, it is started in LP_SLEEP -> LP_ACTIVE stage and the clock waiting time is counted into lp_hw_wait_time */
const int lp_clk_power_on_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && (sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
const int lp_hw_wait_time_us = mc->lp.min_slp_time_us + mc->lp.analog_wait_time_us + lp_clk_power_on_wait_time_us \
+ lp_wakeup_wait_time_us + lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us \
@ -83,28 +85,31 @@ uint32_t pmu_sleep_calculate_lp_hw_wait_time(uint32_t pd_flags, uint32_t slowclk
return (uint32_t)lp_hw_wait_time_us;
}
uint32_t pmu_sleep_calculate_hp_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period)
uint32_t pmu_sleep_calculate_hp_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period)
{
pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
/* HP core hardware wait time, microsecond */
const int hp_digital_power_up_wait_time_us = mc->hp.power_supply_wait_time_us + mc->hp.power_up_wait_time_us;
const int hp_regdma_wait_time_us = (pd_flags & PMU_SLEEP_PD_TOP) ? mc->hp.regdma_s2a_work_time_us : 0;
const int hp_clock_wait_time_us = mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us;
const int hp_regdma_wait_time_us = s_pmu_sleep_regdma_backup_enabled ? mc->hp.regdma_s2a_work_time_us : 0;
/* If XTAL is not used as RTC_FAST clock source, it is started in HP_SLEEP -> HP_ACTIVE stage and the clock waiting time is counted into hp_hw_wait_time */
const int hp_clock_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && !(sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us \
: mc->hp.pll_wait_stable_time_us;
if (pd_flags & PMU_SLEEP_PD_TOP) {
if (sleep_flags & PMU_SLEEP_PD_TOP) {
mc->hp.analog_wait_time_us = PMU_HP_ANA_WAIT_TIME_PD_TOP_US;
} else {
mc->hp.analog_wait_time_us = PMU_HP_ANA_WAIT_TIME_PU_TOP_US;
}
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + MAX(hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us, hp_clock_wait_time_us);
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us + hp_clock_wait_time_us;
return (uint32_t)hp_hw_wait_time_us;
}
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period)
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period)
{
const uint32_t lp_hw_wait_time_us = pmu_sleep_calculate_lp_hw_wait_time(pd_flags, slowclk_period, fastclk_period);
const uint32_t hp_hw_wait_time_us = pmu_sleep_calculate_hp_hw_wait_time(pd_flags, slowclk_period, fastclk_period);
const uint32_t lp_hw_wait_time_us = pmu_sleep_calculate_lp_hw_wait_time(sleep_flags, slowclk_period, fastclk_period);
const uint32_t hp_hw_wait_time_us = pmu_sleep_calculate_hp_hw_wait_time(sleep_flags, slowclk_period, fastclk_period);
const uint32_t total_hw_wait_time_us = lp_hw_wait_time_us + hp_hw_wait_time_us;
return total_hw_wait_time_us;
}
@ -114,7 +119,7 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe
static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
pmu_sleep_param_config_t *param,
pmu_sleep_power_config_t *power, /* We'll use the runtime power parameter to determine some hardware parameters */
const uint32_t pd_flags,
const uint32_t sleep_flags,
const uint32_t adjustment,
const uint32_t slowclk_period,
const uint32_t fastclk_period

View File

@ -31,6 +31,12 @@ extern "C" {
#define PMU_LP_TIMER1_WAKEUP_EN BIT(18)
#define PMU_LP_I2S_WAKEUP_EN BIT(19)
// BIT order in PLL control registers in PMU
#define PMU_CPLL_CTRL BIT(0)
#define PMU_SPLL_CTRL BIT(1)
#define PMU_APLL_CTRL BIT(2)
#define PMU_SDIOPLL_CTRL BIT(3)
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -263,12 +263,12 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_power_config_t;
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.dig_power = { \
.cnnt_pd_en = ((pd_flags) & PMU_SLEEP_PD_CNNT) ? 1 : 0, \
.top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
.mem_pd_en = ((pd_flags) & PMU_SLEEP_PD_MEM) ? 1 : 0, \
.cnnt_pd_en = ((sleep_flags) & PMU_SLEEP_PD_CNNT) ? 1 : 0,\
.top_pd_en = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0,\
.mem_pd_en = ((sleep_flags) & PMU_SLEEP_PD_MEM) ? 1 : 0,\
.mem_dslp = 0, \
.dcdc_switch_pd_en = 1 \
}, \
@ -279,7 +279,7 @@ typedef struct {
.xpd_pll = 0 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
@ -292,8 +292,8 @@ typedef struct {
}, \
.clk_power = { \
.xpd_lppll = 1, \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = 1 \
} \
}, \
@ -302,17 +302,17 @@ typedef struct {
.lp_pad_slp_sel = 0, \
.bod_source_sel = 0, \
.vddbat_mode = 0, \
.peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.peri_pd_en = ((sleep_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_lppll = 0,\
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1,\
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((sleep_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
}, \
.xtal = { \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
} \
}
@ -322,17 +322,17 @@ typedef struct {
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.syscntl = { \
.dig_pad_slp_sel = 0, \
.lp_pad_hold_all = (pd_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
} \
}
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.syscntl = { \
.dig_pad_slp_sel = 0, \
.lp_pad_hold_all = (pd_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
} \
}
@ -345,7 +345,7 @@ typedef struct {
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_analog_config_t;
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
@ -379,7 +379,7 @@ typedef struct {
} \
}
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
@ -417,7 +417,7 @@ typedef struct {
pmu_hp_lp_param_t hp_lp;
} pmu_sleep_param_config_t;
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags) { \
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \
.analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \
@ -508,7 +508,7 @@ typedef struct pmu_sleep_machine_constant {
.regdma_rf_on_work_time_us = 70, \
.regdma_rf_off_work_time_us = 23, \
.xtal_wait_stable_time_us = 250, \
.pll_wait_stable_time_us = 1 \
.pll_wait_stable_time_us = 50 \
} \
}

View File

@ -299,6 +299,7 @@ static RTC_FAST_ATTR int32_t s_sleep_sub_mode_ref_cnt[ESP_SLEEP_MODE_MAX] = { 0
static uint32_t get_power_down_flags(void);
static uint32_t get_sleep_flags(uint32_t pd_flags, bool deepsleep);
#if SOC_PM_SUPPORT_EXT0_WAKEUP
static void ext0_wakeup_prepare(void);
#endif
@ -515,8 +516,8 @@ static uint32_t s_stopped_tgwdt_bmap = 0;
#endif
// Must be called from critical sections.
static void IRAM_ATTR suspend_timers(uint32_t pd_flags) {
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
static void IRAM_ATTR suspend_timers(uint32_t sleep_flags) {
if (!(sleep_flags & RTC_SLEEP_PD_XTAL)) {
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
/* If timegroup implemented task watchdog or interrupt watchdog is running, we have to stop it. */
for (uint32_t tg_num = 0; tg_num < SOC_TIMER_GROUPS; ++tg_num) {
@ -537,8 +538,8 @@ static void IRAM_ATTR suspend_timers(uint32_t pd_flags) {
}
// Must be called from critical sections.
static void IRAM_ATTR resume_timers(uint32_t pd_flags) {
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
static void IRAM_ATTR resume_timers(uint32_t sleep_flags) {
if (!(sleep_flags & RTC_SLEEP_PD_XTAL)) {
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) {
systimer_ll_enable_counter(&SYSTIMER, counter_id, true);
@ -625,7 +626,7 @@ FORCE_INLINE_ATTR void resume_uarts(void)
completion time has exceeded the wakeup time, we should abandon the flush, skip the sleep and
return ESP_ERR_SLEEP_REJECT.
*/
FORCE_INLINE_ATTR bool light_sleep_uart_prepare(uint32_t pd_flags, int64_t sleep_duration)
FORCE_INLINE_ATTR bool light_sleep_uart_prepare(uint32_t sleep_flags, int64_t sleep_duration)
{
bool should_skip_sleep = false;
#if !SOC_PM_SUPPORT_TOP_PD || !CONFIG_ESP_CONSOLE_UART
@ -636,7 +637,7 @@ FORCE_INLINE_ATTR bool light_sleep_uart_prepare(uint32_t pd_flags, int64_t sleep
#else
#define FORCE_FLUSH_CONSOLE_UART 0
#endif
if (FORCE_FLUSH_CONSOLE_UART || (pd_flags & PMU_SLEEP_PD_TOP)) {
if (FORCE_FLUSH_CONSOLE_UART || (sleep_flags & PMU_SLEEP_PD_TOP)) {
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) &&
// +1 is for cover the last character flush time
(sleep_duration < (int64_t)((UART_LL_FIFO_DEF_LEN - uart_ll_get_txfifo_len(CONSOLE_UART_DEV) + 1) * UART_FLUSH_US_PER_CHAR) + SLEEP_UART_FLUSH_DONE_TO_SLEEP_US)) {
@ -658,7 +659,7 @@ FORCE_INLINE_ATTR bool light_sleep_uart_prepare(uint32_t pd_flags, int64_t sleep
/**
* These save-restore workaround should be moved to lower layer
*/
FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t pd_flags, bool deep_sleep)
FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool deep_sleep)
{
if (deep_sleep){
for (int n = 0; n < MAX_DSLP_HOOKS; n++) {
@ -672,7 +673,7 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t pd_flags, bool deep_s
sleep_console_usj_pad_backup_and_disable();
#endif
#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD
if (!(pd_flags & PMU_SLEEP_PD_CNNT)) {
if (!(sleep_flags & PMU_SLEEP_PD_CNNT)) {
sleep_usb_otg_phy_backup_and_disable();
}
#endif
@ -691,7 +692,7 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t pd_flags, bool deep_s
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW && SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN && CONFIG_SPIRAM
/* When using SPIRAM on the ESP32-C5, we need to use Cache_WriteBack_All to protect SPIRAM data
because the cache powers down when we power down the CPU */
if(pd_flags & PMU_SLEEP_PD_CPU) {
if(sleep_flags & PMU_SLEEP_PD_CPU) {
Cache_WriteBack_All();
}
#endif
@ -714,10 +715,10 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t pd_flags, bool deep_s
/**
* These save-restore workaround should be moved to lower layer
*/
FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t pd_flags)
FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t sleep_flags)
{
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
if (pd_flags & PMU_SLEEP_PD_TOP) {
if (sleep_flags & PMU_SLEEP_PD_TOP) {
// There is no driver to manage the flashboot watchdog, and it is definitely be in off state when
// the system is running, after waking up from pd_top sleep, shut it down by software here.
wdt_hal_context_t mwdt_ctx = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
@ -731,7 +732,7 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t pd_flags)
sleep_console_usj_pad_restore();
#endif
#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD
if (!(pd_flags & PMU_SLEEP_PD_CNNT)) {
if (!(sleep_flags & PMU_SLEEP_PD_CNNT)) {
sleep_usb_otg_phy_restore();
}
#endif
@ -798,7 +799,7 @@ static IRAM_ATTR void sleep_low_power_clock_calibration(bool is_dslp)
inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp);
static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection)
static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t sleep_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection)
{
// Stop UART output so that output is not lost due to APB frequency change.
// For light sleep, suspend UART output — it will resume after wakeup.
@ -812,7 +813,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
if (deep_sleep) {
flush_uarts();
} else {
should_skip_sleep = light_sleep_uart_prepare(pd_flags, sleep_duration);
should_skip_sleep = light_sleep_uart_prepare(sleep_flags, sleep_duration);
}
#if CONFIG_ESP_PHY_ENABLED && SOC_DEEP_SLEEP_SUPPORTED
@ -829,7 +830,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#endif
#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
if (!deep_sleep && (pd_flags & PMU_SLEEP_PD_TOP)) {
if (!deep_sleep && (sleep_flags & PMU_SLEEP_PD_TOP)) {
sleep_retention_do_system_retention(true);
}
#endif
@ -887,7 +888,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
}
#endif // CONFIG_ULP_COPROC_ENABLED
misc_modules_sleep_prepare(pd_flags, deep_sleep);
misc_modules_sleep_prepare(sleep_flags, deep_sleep);
#if SOC_TOUCH_SENSOR_VERSION >= 2
if (deep_sleep) {
@ -897,7 +898,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
/* Workaround: In deep sleep, for ESP32S2, Power down the RTC_PERIPH will change the slope configuration of Touch sensor sleep pad.
* The configuration change will change the reading of the sleep pad, which will cause the touch wake-up sensor to trigger falsely.
*/
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
sleep_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
#endif
}
} else {
@ -910,14 +911,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
bool keep_rtc_power_on = touch_ll_get_fsm_state();
#endif
if (keep_rtc_power_on) { // Check if the touch sensor is working properly.
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
sleep_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
}
}
#elif CONFIG_IDF_TARGET_ESP32P4
/* Due to esp32p4 eco0 hardware bug, if LP peripheral power domain is powerdowned in sleep, there will be a possibility of
triggering the EFUSE_CRC reset, so disable the power-down of this power domain on lightsleep for ECO0 version. */
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
sleep_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
}
#endif
@ -930,42 +931,6 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
reject_triggers |= sleep_modem_reject_triggers();
}
// Override user-configured FOSC power modes.
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_RTC_USE_RC_FAST_MODE]) {
pd_flags &= ~RTC_SLEEP_PD_INT_8M;
}
// Override user-configured XTAL power modes.
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_XTAL_MODE] && !deep_sleep) {
pd_flags &= ~RTC_SLEEP_PD_XTAL;
}
//Append some flags in addition to power domains
uint32_t sleep_flags = pd_flags;
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_RC_FAST_MODE] && !deep_sleep) {
sleep_flags &= ~RTC_SLEEP_PD_INT_8M;
sleep_flags |= RTC_SLEEP_DIG_USE_8M;
}
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE]) {
sleep_flags |= RTC_SLEEP_USE_ADC_TESEN_MONITOR;
}
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_ULTRA_LOW_MODE] == 0) {
sleep_flags |= RTC_SLEEP_NO_ULTRA_LOW;
}
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_RTC_FAST_USE_XTAL_MODE]) {
sleep_flags |= RTC_SLEEP_XTAL_AS_RTC_FAST;
}
#if SOC_LP_VAD_SUPPORTED
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_LP_USE_XTAL_MODE] && !deep_sleep) {
sleep_flags |= RTC_SLEEP_LP_PERIPH_USE_XTAL;
}
#endif
#if CONFIG_ESP_SLEEP_DEBUG
if (s_sleep_ctx != NULL) {
s_sleep_ctx->sleep_flags = sleep_flags;
@ -1056,14 +1021,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
#endif
} else {
suspend_timers(pd_flags);
suspend_timers(sleep_flags);
/* Cache Suspend 1: will wait cache idle in cache suspend */
suspend_cache();
/* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode.
In order to avoid the leakage of the SPI cs pin, hold it here */
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
if(!(pd_flags & RTC_SLEEP_PD_VDDSDIO) && (pd_flags & PMU_SLEEP_PD_TOP)) {
if(!(sleep_flags & RTC_SLEEP_PD_VDDSDIO) && (sleep_flags & PMU_SLEEP_PD_TOP)) {
#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
/* Cache suspend also means SPI bus IDLE, then we can hold SPI CS pin safely */
#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359
@ -1078,7 +1043,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#endif
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD
if (pd_flags & PMU_SLEEP_PD_TOP) {
if (sleep_flags & PMU_SLEEP_PD_TOP) {
esp_sleep_mmu_retention(true);
}
#endif
@ -1094,7 +1059,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#if SOC_PMU_SUPPORTED
#if SOC_PM_CPU_RETENTION_BY_SW && ESP_SLEEP_POWER_DOWN_CPU
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0);
if (pd_flags & (PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_TOP)) {
if (sleep_flags & (PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_TOP)) {
result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
} else
#endif
@ -1111,14 +1076,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#endif
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD
if (pd_flags & PMU_SLEEP_PD_TOP) {
if (sleep_flags & PMU_SLEEP_PD_TOP) {
esp_sleep_mmu_retention(false);
}
#endif
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
/* Unhold the SPI CS pin */
if(!(pd_flags & RTC_SLEEP_PD_VDDSDIO) && (pd_flags & PMU_SLEEP_PD_TOP)) {
if(!(sleep_flags & RTC_SLEEP_PD_VDDSDIO) && (sleep_flags & PMU_SLEEP_PD_TOP)) {
#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359
gpio_ll_hold_dis(&GPIO, MSPI_IOMUX_PIN_NUM_CS0);
@ -1132,11 +1097,11 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
/* Cache Resume 1: Resume cache for continue running*/
resume_cache();
resume_timers(pd_flags);
resume_timers(sleep_flags);
}
}
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
if (sleep_flags & RTC_SLEEP_PD_VDDSDIO) {
/* Cache Suspend 2: If previous sleep powerdowned the flash, suspend cache here so that the
access to flash before flash ready can be explicitly exposed. */
suspend_cache();
@ -1158,12 +1123,12 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
if (result == ESP_OK) {
s_config.ccount_ticks_record = esp_cpu_get_cycle_count();
#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
if (pd_flags & PMU_SLEEP_PD_TOP) {
if (sleep_flags & PMU_SLEEP_PD_TOP) {
sleep_retention_do_system_retention(false);
}
#endif
}
misc_modules_wake_prepare(pd_flags);
misc_modules_wake_prepare(sleep_flags);
}
#if MSPI_TIMING_LL_FLASH_CPU_CLK_SRC_BINDED
@ -1254,9 +1219,11 @@ static esp_err_t IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
force_pd_flags |= RTC_SLEEP_PD_BT;
#endif
// Append flags to indicate the sleep sub-mode and modify the pd_flags according to sub-mode attributes.
uint32_t sleep_flags = get_sleep_flags(force_pd_flags | pd_flags, true);
// Enter sleep
esp_err_t err = ESP_OK;
if (esp_sleep_start(force_pd_flags | pd_flags, ESP_SLEEP_MODE_DEEP_SLEEP, allow_sleep_rejection) == ESP_ERR_SLEEP_REJECT) {
if (esp_sleep_start(sleep_flags, ESP_SLEEP_MODE_DEEP_SLEEP, allow_sleep_rejection) == ESP_ERR_SLEEP_REJECT) {
err = ESP_ERR_SLEEP_REJECT;
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
/* Cache Resume 2: if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is enabled, cache has been suspended in esp_sleep_start */
@ -1293,10 +1260,10 @@ esp_err_t IRAM_ATTR esp_deep_sleep_try_to_start(void)
* Helper function which handles entry to and exit from light sleep
* Placed into IRAM as flash may need some time to be powered on.
*/
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags,
uint32_t flash_enable_time_us) IRAM_ATTR __attribute__((noinline));
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags,
uint32_t flash_enable_time_us)
{
#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
@ -1304,7 +1271,7 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
#endif
// Enter sleep
esp_err_t reject = esp_sleep_start(pd_flags, ESP_SLEEP_MODE_LIGHT_SLEEP, true);
esp_err_t reject = esp_sleep_start(sleep_flags, ESP_SLEEP_MODE_LIGHT_SLEEP, true);
#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
// If VDDSDIO regulator was controlled by RTC registers before sleep,
@ -1315,9 +1282,9 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
#endif
// If SPI flash was powered down, wait for it to become ready
if (!reject && (pd_flags & RTC_SLEEP_PD_VDDSDIO)) {
if (!reject && (sleep_flags & RTC_SLEEP_PD_VDDSDIO)) {
#if SOC_PM_SUPPORT_TOP_PD
if (pd_flags & PMU_SLEEP_PD_TOP) {
if (sleep_flags & PMU_SLEEP_PD_TOP) {
uint32_t flash_ready_hw_waited_time_us = pmu_sleep_get_wakup_retention_cost();
uint32_t flash_ready_sw_waited_time_us = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / MHZ);
uint32_t flash_ready_waited_time_us = flash_ready_hw_waited_time_us + flash_ready_sw_waited_time_us;
@ -1333,7 +1300,7 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
}
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
if (sleep_flags & RTC_SLEEP_PD_VDDSDIO) {
/* Cache Resume 2: flash is ready now, we can resume the cache and access flash safely after */
resume_cache();
}
@ -1351,11 +1318,11 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
* x | 1 | pd flash with relaxed conditions(force_pd)
* 1 | 0 | pd flash with strict conditions(safe_pd)
*/
FORCE_INLINE_ATTR bool can_power_down_vddsdio(uint32_t pd_flags, const uint32_t vddsdio_pd_sleep_duration)
FORCE_INLINE_ATTR bool can_power_down_vddsdio(uint32_t sleep_flags, const uint32_t vddsdio_pd_sleep_duration)
{
bool force_pd = !(s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) || (s_config.sleep_duration > vddsdio_pd_sleep_duration);
bool safe_pd = (s_config.wakeup_triggers == RTC_TIMER_TRIG_EN) && (s_config.sleep_duration > vddsdio_pd_sleep_duration);
return (pd_flags & RTC_SLEEP_PD_VDDSDIO) ? force_pd : safe_pd;
return (sleep_flags & RTC_SLEEP_PD_VDDSDIO) ? force_pd : safe_pd;
}
esp_err_t esp_light_sleep_start(void)
@ -1435,10 +1402,8 @@ esp_err_t esp_light_sleep_start(void)
// Decide which power domains can be powered down
uint32_t pd_flags = get_power_down_flags();
#ifdef CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
#endif
// Append flags to indicate the sleep sub-mode and modify the pd_flags according to sub-mode attributes.
uint32_t sleep_flags = get_sleep_flags(pd_flags, false);
// Re-calibrate the RTC clock
sleep_low_power_clock_calibration(false);
@ -1452,10 +1417,10 @@ esp_err_t esp_light_sleep_start(void)
*/
#if SOC_PMU_SUPPORTED
int sleep_time_sw_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out;
int sleep_time_hw_adjustment = pmu_sleep_calculate_hw_wait_time(pd_flags, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period);
int sleep_time_hw_adjustment = pmu_sleep_calculate_hw_wait_time(sleep_flags, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period);
s_config.sleep_time_adjustment = sleep_time_sw_adjustment + sleep_time_hw_adjustment;
#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD
int sleep_time_sw_mmu_table_restore = (pd_flags & PMU_SLEEP_PD_TOP) ? SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US : 0;
int sleep_time_sw_mmu_table_restore = (sleep_flags & PMU_SLEEP_PD_TOP) ? SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US : 0;
s_config.sleep_time_adjustment += sleep_time_sw_mmu_table_restore;
#endif
#else
@ -1470,9 +1435,9 @@ esp_err_t esp_light_sleep_start(void)
/**
* If VDD_SDIO power domain is requested to be turned off, bit `RTC_SLEEP_PD_VDDSDIO`
* will be set in `pd_flags`.
* will be set in `sleep_flags`.
*/
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
if (sleep_flags & RTC_SLEEP_PD_VDDSDIO) {
/*
* When VDD_SDIO power domain has to be turned off, the minimum sleep time of the
* system needs to meet the sum below:
@ -1490,7 +1455,7 @@ esp_err_t esp_light_sleep_start(void)
flash_enable_time_us + LIGHT_SLEEP_MIN_TIME_US + s_config.sleep_time_adjustment
+ rtc_time_slowclk_to_us(RTC_MODULE_SLEEP_PREPARE_CYCLES, s_config.rtc_clk_cal_period));
if (can_power_down_vddsdio(pd_flags, vddsdio_pd_sleep_duration)) {
if (can_power_down_vddsdio(sleep_flags, vddsdio_pd_sleep_duration)) {
if (s_config.sleep_time_overhead_out < flash_enable_time_us) {
s_config.sleep_time_adjustment += flash_enable_time_us;
}
@ -1499,7 +1464,7 @@ esp_err_t esp_light_sleep_start(void)
* Minimum sleep time is not enough, then keep the VDD_SDIO power
* domain on.
*/
pd_flags &= ~RTC_SLEEP_PD_VDDSDIO;
sleep_flags &= ~RTC_SLEEP_PD_VDDSDIO;
if (s_config.sleep_time_overhead_out > flash_enable_time_us) {
s_config.sleep_time_adjustment -= flash_enable_time_us;
}
@ -1539,7 +1504,7 @@ esp_err_t esp_light_sleep_start(void)
err = ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION;
} else {
// Enter sleep, then wait for flash to be ready on wakeup
err = esp_light_sleep_inner(pd_flags, flash_enable_time_us);
err = esp_light_sleep_inner(sleep_flags, flash_enable_time_us);
}
// light sleep wakeup flag only makes sense after a successful light sleep
@ -2526,6 +2491,58 @@ static uint32_t get_power_down_flags(void)
return pd_flags;
}
static uint32_t get_sleep_flags(uint32_t sleep_flags, bool deepsleep)
{
// Override user-configured FOSC power modes.
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_RTC_USE_RC_FAST_MODE]) {
sleep_flags &= ~RTC_SLEEP_PD_INT_8M;
}
// Override user-configured XTAL power modes.
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_XTAL_MODE] && !deepsleep) {
sleep_flags &= ~RTC_SLEEP_PD_XTAL;
}
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_DIG_USE_RC_FAST_MODE] && !deepsleep) {
sleep_flags &= ~RTC_SLEEP_PD_INT_8M;
sleep_flags |= RTC_SLEEP_DIG_USE_8M;
}
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE]) {
sleep_flags |= RTC_SLEEP_USE_ADC_TESEN_MONITOR;
}
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_ULTRA_LOW_MODE] == 0) {
sleep_flags |= RTC_SLEEP_NO_ULTRA_LOW;
}
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_RTC_FAST_USE_XTAL_MODE]) {
sleep_flags |= RTC_SLEEP_XTAL_AS_RTC_FAST;
}
#if SOC_LP_VAD_SUPPORTED
if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_LP_USE_XTAL_MODE] && !deepsleep) {
sleep_flags |= RTC_SLEEP_LP_PERIPH_USE_XTAL;
}
#endif
#ifdef CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND
if (!deepsleep) {
sleep_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
}
#endif
#if CONFIG_IDF_TARGET_ESP32P4
/* Due to esp32p4 eco0 hardware bug, if LP peripheral power domain is powerdowned in sleep, there will be a possibility of
triggering the EFUSE_CRC reset, so disable the power-down of this power domain on lightsleep for ECO0 version. */
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
sleep_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
}
#endif
return sleep_flags;
}
#if CONFIG_IDF_TARGET_ESP32
/* APP core of esp32 can't access to RTC FAST MEMORY, do not define it with RTC_IRAM_ATTR */
void

View File

@ -16,6 +16,7 @@ entries:
sleep_modes:esp_sleep_enable_timer_wakeup (noflash)
sleep_modes:timer_wakeup_prepare (noflash)
sleep_modes:get_power_down_flags (noflash)
sleep_modes:get_sleep_flags (noflash)
esp_clk:esp_clk_slowclk_cal_set (noflash)
esp_clk:esp_clk_slowclk_cal_get (noflash)
esp_clk:esp_rtc_get_time_us (noflash)