Merge branch 'feat/esp_idfesp32h4_eco1_sleep_support' into 'master'

Feat/ESP32H4 ECO1 Sleep Support

Closes PM-633

See merge request espressif/esp-idf!47023
This commit is contained in:
He Binglin
2026-04-20 15:44:19 +08:00
15 changed files with 252 additions and 84 deletions
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,6 +10,11 @@
#include <stdbool.h>
#include "esp_attr.h"
#include "soc/pcr_struct.h"
#include "soc/soc.h"
#include "soc/reset_reasons.h"
#include "soc/usb_serial_jtag_struct.h"
#include "soc/lpperi_struct.h"
#include "soc/lp_clkrst_struct.h"
#ifdef __cplusplus
extern "C" {
@@ -87,6 +92,124 @@ FORCE_INLINE_ATTR void _clk_gate_ll_ref_96m_clk_en(bool enable)
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define clk_gate_ll_ref_96m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_96m_clk_en(__VA_ARGS__)
/**
* @brief Configuration structure for peripheral clock gate settings
*/
typedef struct {
bool disable_uart0_clk; ///< Disable UART0 clock (when UART0 is not console)
bool disable_uart1_clk; ///< Disable UART1 clock (when UART1 is not console)
bool disable_mspi_flash_clk; ///< Disable MSPI flash clock (for PURE_RAM_APP)
bool disable_assist_clk; ///< Disable ASSIST Debug module clock
bool disable_crypto_periph_clk; ///< Disable crypto peripherals clock when TEE is not enabled
bool disable_usb_serial_jtag; ///< Disable USB-Serial-JTAG clock and pad (when not enabled)
bool disable_pvt_clk; ///< Disable PVT monitor clocks when PVT is not used
} periph_ll_clk_gate_config_t;
/**
* @brief Set default clock gates: turn off unused peripheral root clocks at CPU start.
*
* @note LP_PERI clocks are gated on cold boot paths; efuse clock stays enabled.
*/
static inline void periph_ll_clk_gate_set_default(soc_reset_reason_t rst_reason, const periph_ll_clk_gate_config_t *config)
{
if ((rst_reason != RESET_REASON_CPU0_MWDT0) && (rst_reason != RESET_REASON_CPU0_MWDT1) \
&& (rst_reason != RESET_REASON_CPU0_SW) && (rst_reason != RESET_REASON_CPU0_RTC_WDT) \
&& (rst_reason != RESET_REASON_CPU0_JTAG)) {
/* Use independent ifs: console may be neither UART0 nor UART1 (e.g. USB), both need gating. */
if (config->disable_uart0_clk) {
PCR.uart0_conf.uart0_clk_en = 0;
PCR.uart0_sclk_conf.uart0_sclk_en = 0;
}
if (config->disable_uart1_clk) {
PCR.uart1_conf.uart1_clk_en = 0;
PCR.uart1_sclk_conf.uart1_sclk_en = 0;
}
PCR.i2c0_conf.i2c0_clk_en = 0;
PCR.i2c1_conf.i2c1_clk_en = 0;
PCR.i2c0_sclk_conf.i2c0_sclk_en = 0;
PCR.i2c1_sclk_conf.i2c1_sclk_en = 0;
PCR.rmt_conf.rmt_clk_en = 0;
PCR.rmt_sclk_conf.rmt_sclk_en = 0;
PCR.ledc_sclk_conf.ledc_sclk_en = 0;
PCR.ledc_conf.ledc_clk_en = 0;
PCR.timergroup0_timer_clk_conf.tg0_timer_clk_en = 0;
PCR.timergroup1_timer_clk_conf.tg1_timer_clk_en = 0;
PCR.timergroup0_conf.tg0_clk_en = 0;
PCR.timergroup1_conf.tg1_clk_en = 0;
PCR.twai0_func_clk_conf.twai0_func_clk_en = 0;
PCR.twai0_conf.twai0_clk_en = 0;
PCR.i2s_conf.i2s_clk_en = 0;
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_en = 0;
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_en = 0;
PCR.pcnt_conf.pcnt_clk_en = 0;
PCR.etm_conf.etm_clk_en = 0;
PCR.pwm0_conf.pwm0_clk_en = 0;
PCR.pwm0_clk_conf.pwm0_clkm_en = 0;
PCR.pwm1_conf.pwm1_clk_en = 0;
PCR.pwm1_clk_conf.pwm1_clkm_en = 0;
PCR.parl_clk_rx_conf.parl_clk_rx_en = 0;
PCR.parl_clk_tx_conf.parl_clk_tx_en = 0;
PCR.parl_io_conf.parl_clk_en = 0;
PCR.gdma_conf.gdma_clk_en = 0;
if (config->disable_mspi_flash_clk) {
PCR.mspi_conf.mspi_clk_en = 0;
}
PCR.spi2_conf.spi2_clk_en = 0;
PCR.spi3_conf.spi3_clk_en = 0;
PCR.tsens_clk_conf.tsens_clk_en = 0;
PCR.uhci_conf.uhci_clk_en = 0;
PCR.saradc_conf.saradc_clk_en = 0;
PCR.asrc_func_clk_conf.asrc_func_clk_en = 0;
PCR.asrc_func_clk_conf.asrc_apb_clk_en = 0;
PCR.zero_det_conf.zero_det_clk_en = 0;
PCR.zero_det_clk_conf.zero_det_func_clk_en = 0;
if (config->disable_assist_clk) {
/* Disable ASSIST Debug module clock if PC recording is not used;
* stack guard may re-enable in esp_hw_stack_guard_init */
PCR.assist_conf.assist_clk_en = 0;
}
if (config->disable_crypto_periph_clk) {
// NOTE: [ESP-TEE] The TEE is responsible for the AES and SHA peripherals
PCR.aes_conf.aes_clk_en = 0;
PCR.sha_conf.sha_clk_en = 0;
PCR.ecc_conf.ecc_clk_en = 0;
PCR.hmac_conf.hmac_clk_en = 0;
PCR.km_conf.km_clk_en = 0;
PCR.ecdsa_conf.ecdsa_clk_en = 0;
}
PCR.trace_conf.trace_clk_en = 0;
PCR.tcm_mem_monitor_conf.tcm_mem_monitor_clk_en = 0;
PCR.psram_mem_monitor_conf.psram_mem_monitor_clk_en = 0;
if (config->disable_pvt_clk) {
PCR.pvt_monitor_conf.pvt_monitor_clk_en = 0;
PCR.pvt_monitor_func_clk_conf.pvt_monitor_func_clk_en = 0;
}
PCR.ctrl_clk_out_en.val = 0;
if (config->disable_usb_serial_jtag) {
// Disable USB-Serial-JTAG clock and its pad if not used
USB_SERIAL_JTAG.serial_jtag_conf0.serial_jtag_usb_pad_enable = 0;
PCR.usb_device_conf.usb_device_clk_en = 0;
PCR.usb_otg11_conf.usb_otg11_clk_en = 0;
}
}
if ((rst_reason == RESET_REASON_CHIP_POWER_ON) || (rst_reason == RESET_REASON_CHIP_BROWN_OUT) \
|| (rst_reason == RESET_REASON_SYS_RTC_WDT) || (rst_reason == RESET_REASON_SYS_SUPER_WDT)) {
LPPERI.clk_en.val = 0;
LPPERI.clk_en.lp_io_ck_en = 1; // TODO: PM-699
LPPERI.clk_en.efuse_ck_en = 1; // keep efuse clock enabled
LP_CLKRST.lp_clk_po_en.val = 0;
}
}
#ifdef __cplusplus
}
#endif
@@ -578,13 +578,6 @@ FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_on_mask(pmu_dev_t *hw, uint32_
hw->power.mem_mask.mem2_mask = (mem_mask & BIT(2)) ? 1 : 0;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_off_mask(pmu_dev_t *hw, uint32_t mem0_pd_mask, uint32_t mem1_pd_mask, uint32_t mem2_pd_mask)
{
hw->power.mem_mask.mem0_pd_mask = mem0_pd_mask;
hw->power.mem_mask.mem1_pd_mask = mem1_pd_mask;
hw->power.mem_mask.mem2_pd_mask = mem2_pd_mask;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_vdd_flash_tiel_enable(pmu_dev_t *hw, bool enable)
{
hw->power.vdd_flash.ldo_tiel_en = enable;
@@ -178,6 +178,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();
analog_default.lp_sys[LP(SLEEP)].analog.dcm_vset = 20;
} else if (!(sleep_flags & PMU_SLEEP_PD_RC_FAST)) {
analog_default.hp_sys.analog.drv_b = get_act_hp_drvb();
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_act_lp_dbias();
@@ -30,6 +30,12 @@ static int s_cur_pll_freq;
static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG
#if !BOOTLOADER_BUILD
// Indicate whether the specific cpu clock source is acquired by the hp root clock (i.e. whether ref_cnt in esp_clk_tree.c is incremented by the hp root clock)
static bool s_is_pll_acquired = (CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 96 || CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 48);
static bool s_is_xtal_x2_acquired = (CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 64);
#endif
void rtc_clk_bbpll_add_consumer(void)
{
s_bbpll_digi_consumers_ref_count += 1;
@@ -283,7 +289,10 @@ static void rtc_clk_cpu_src_clk_enable(soc_cpu_clk_src_t new_src, uint32_t new_s
rtc_clk_bbpll_enable();
truly_enabled = true;
#else
truly_enabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_BBPLL, true);
if (!s_is_pll_acquired) {
truly_enabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_BBPLL, true);
s_is_pll_acquired = true;
}
#endif
if (truly_enabled || (s_cur_pll_freq != new_src_freq_mhz)) {
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), new_src_freq_mhz);
@@ -292,7 +301,10 @@ static void rtc_clk_cpu_src_clk_enable(soc_cpu_clk_src_t new_src, uint32_t new_s
#if BOOTLOADER_BUILD
clk_ll_xtal_x2_enable();
#else
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_XTAL_X2, true);
if (!s_is_xtal_x2_acquired) {
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_XTAL_X2, true);
s_is_xtal_x2_acquired = true;
}
#endif
}
}
@@ -303,7 +315,9 @@ static void rtc_clk_cpu_src_clk_disable(soc_cpu_clk_src_t old_src)
#if BOOTLOADER_BUILD
rtc_clk_bbpll_disable();
#else
assert(s_is_pll_acquired);
bool truly_disabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_BBPLL, false);
s_is_pll_acquired = false;
if (truly_disabled) {
s_cur_pll_freq = 0;
}
@@ -312,7 +326,9 @@ static void rtc_clk_cpu_src_clk_disable(soc_cpu_clk_src_t old_src)
#if BOOTLOADER_BUILD
clk_ll_xtal_x2_disable();
#else
assert(s_is_xtal_x2_acquired);
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_XTAL_X2, false);
s_is_xtal_x2_acquired = false;
#endif
}
}
@@ -385,7 +401,10 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
rtc_clk_cpu_freq_to_rc_fast();
} else if (config->source == SOC_CPU_CLK_SRC_XTAL_X2
&& esp_clk_tree_is_power_on(SOC_ROOT_CIRCUIT_CLK_XTAL_X2)) {
#if !BOOTLOADER_BUILD
&& s_is_xtal_x2_acquired
#endif
) {
rtc_clk_cpu_freq_to_xtal_x2(config->freq_mhz, config->div);
} else {
/* fallback */
@@ -395,12 +414,13 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
void rtc_clk_cpu_freq_set_xtal(void)
{
rtc_clk_cpu_set_to_default_config();
#if BOOTLOADER_BUILD
rtc_clk_bbpll_disable();
#else
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_BBPLL, false);
#endif
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
int freq_mhz = (int)rtc_clk_xtal_freq_get();
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_XTAL) {
rtc_clk_cpu_src_clk_disable(old_cpu_clk_src);
}
}
FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void)
@@ -161,5 +161,5 @@ esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable)
break;
}
}
return ESP_OK; // TODO: PM-456
return ESP_OK;
}
@@ -153,7 +153,9 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
analog_default.hp_sys.analog.drv_b = PMU_HP_DRVB_LIGHTSLEEP;
if (sleep_flags & PMU_SLEEP_PD_TOP) {
analog_default.hp_sys.analog.drv_b = PMU_HP_DRVB_LIGHTSLEEP_TOP_PD;
}
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
if (!(sleep_flags & PMU_SLEEP_PD_XTAL)){
analog_default.hp_sys.analog.xpd_trx = PMU_XPD_TRX_SLEEP_ON;
@@ -164,6 +166,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();
analog_default.lp_sys[LP(SLEEP)].analog.dcm_vset = 20;
} else if (!(sleep_flags & PMU_SLEEP_PD_RC_FAST)) {
analog_default.hp_sys.analog.drv_b = get_act_hp_drvb();
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_act_lp_dbias();
@@ -214,6 +217,7 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd);
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b);
pmu_ll_hp_set_trx_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd_trx);
pmu_ll_hp_set_discnnt_dig_rtc (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.discnnt_dig_rtc);
pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur);
pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep);
@@ -222,6 +226,7 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_dbias);
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbias);
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.drv_b);
pmu_ll_lp_set_discnnt_dig_rtc (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.discnnt_dig_rtc);
pmu_ll_hp_set_dcm_mode (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dcm_mode);
pmu_ll_hp_set_dcm_vset (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dcm_vset);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -27,18 +27,19 @@ extern "C" {
// FOR BOTH LIGHTSLEEP & DEEPSLEEP
#define PMU_PD_CUR_SLEEP_DEFAULT 1
#define PMU_BIASSLP_SLEEP_DEFAULT 1
#define PMU_LP_XPD_SLEEP_DEFAULT 1
#define PMU_LP_SLP_XPD_SLEEP_DEFAULT 0
#define PMU_LP_SLP_DBIAS_SLEEP_DEFAULT 0
// FOR LIGHTSLEEP
#define PMU_HP_DRVB_LIGHTSLEEP 0
#define PMU_HP_DRVB_LIGHTSLEEP_TOP_PU 25
#define PMU_HP_DRVB_LIGHTSLEEP_TOP_PD 23
#define PMU_LP_DRVB_LIGHTSLEEP 0
#define PMU_HP_XPD_LIGHTSLEEP 1
#define PMU_LP_XPD_LIGHTSLEEP_DEFAULT 1
#define PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT 0
#define PMU_HP_DBIAS_LIGHTSLEEP_0V6_DEFAULT 1
#define PMU_LP_DBIAS_LIGHTSLEEP_0V7_DEFAULT 12
#define PMU_HP_DBIAS_LIGHTSLEEP_0V6_DEFAULT 0
#define PMU_LP_DBIAS_LIGHTSLEEP_0V7_DEFAULT 3
#define PMU_REGDMA_S2A_WORK_TIME_PD_TOP_US 0
// The current value of this depends on the restoration time overhead of the longest chain in regdma
@@ -48,9 +49,9 @@ extern "C" {
#define PMU_DBG_HP_DEEPSLEEP 0
#define PMU_HP_XPD_DEEPSLEEP 0
#define PMU_LP_DRVB_DEEPSLEEP 0
#define PMU_LP_XPD_DEEPSLEEP_DEFAULT 0
#define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12
#define PMU_LP_DBIAS_SLEEP_0V7_DEFAULT 23
#define PMU_LP_DBIAS_SLEEP_0V7_DEFAULT 3
uint32_t get_act_hp_drvb(void);
uint32_t get_act_lp_dbias(void);
@@ -330,8 +331,7 @@ typedef struct {
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.dig_power = { \
/* TODO: PM-638 */\
.vdd_io_mode = 0, \
.vdd_io_mode = 3, \
.bod_source_sel = 0, \
.vddbat_mode = 0, \
.peri_pd_en = ((sleep_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0,\
@@ -391,8 +391,9 @@ typedef struct {
.dcm_mode = 3, \
.discnnt_dig_rtc = 0, \
.xpd_trx = 0, \
.xpd_bias = 0, \
.power_det_bypass = 0, \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP_TOP_PU, \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.xpd = PMU_HP_XPD_LIGHTSLEEP, \
@@ -405,7 +406,7 @@ typedef struct {
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 1, \
.dig_reg_dsfmos = 4, \
.dcm_vset = 20, \
.dcm_vset = 0, \
.dcm_mode = 3, \
.discnnt_dig_rtc = 0, \
.drv_b = PMU_LP_DRVB_DEEPSLEEP, \
@@ -413,7 +414,7 @@ typedef struct {
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \
.slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \
.xpd = PMU_LP_XPD_SLEEP_DEFAULT, \
.xpd = PMU_LP_XPD_LIGHTSLEEP_DEFAULT, \
.dbias = PMU_LP_DBIAS_LIGHTSLEEP_0V7_DEFAULT \
} \
} \
@@ -426,7 +427,7 @@ typedef struct {
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 1, \
.dig_reg_dsfmos = 4, \
.dcm_vset = 23, \
.dcm_vset = 20, \
.dcm_mode = 3, \
.discnnt_dig_rtc = 0, \
.xpd_trx = 0, \
@@ -450,7 +451,7 @@ typedef struct {
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \
.slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \
.xpd = PMU_LP_XPD_SLEEP_DEFAULT, \
.xpd = PMU_LP_XPD_DEEPSLEEP_DEFAULT, \
.dbias = PMU_LP_DBIAS_SLEEP_0V7_DEFAULT \
} \
} \
@@ -30,6 +30,12 @@ static int s_cur_pll_freq;
static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG
#if !BOOTLOADER_BUILD
// Indicate whether the specific cpu clock source is acquired by the hp root clock (i.e. whether ref_cnt in esp_clk_tree.c is incremented by the hp root clock)
static bool s_is_pll_acquired = (CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 96 || CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 48);
static bool s_is_xtal_x2_acquired = (CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 64);
#endif
void rtc_clk_bbpll_add_consumer(void)
{
s_bbpll_digi_consumers_ref_count += 1;
@@ -283,7 +289,10 @@ static void rtc_clk_cpu_src_clk_enable(soc_cpu_clk_src_t new_src, uint32_t new_s
rtc_clk_bbpll_enable();
truly_enabled = true;
#else
truly_enabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_BBPLL, true);
if (!s_is_pll_acquired) {
truly_enabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_BBPLL, true);
s_is_pll_acquired = true;
}
#endif
if (truly_enabled || (s_cur_pll_freq != new_src_freq_mhz)) {
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), new_src_freq_mhz);
@@ -292,7 +301,10 @@ static void rtc_clk_cpu_src_clk_enable(soc_cpu_clk_src_t new_src, uint32_t new_s
#if BOOTLOADER_BUILD
clk_ll_xtal_x2_enable();
#else
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_XTAL_X2, true);
if (!s_is_xtal_x2_acquired) {
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_XTAL_X2, true);
s_is_xtal_x2_acquired = true;
}
#endif
}
}
@@ -303,7 +315,9 @@ static void rtc_clk_cpu_src_clk_disable(soc_cpu_clk_src_t old_src)
#if BOOTLOADER_BUILD
rtc_clk_bbpll_disable();
#else
assert(s_is_pll_acquired);
bool truly_disabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_BBPLL, false);
s_is_pll_acquired = false;
if (truly_disabled) {
s_cur_pll_freq = 0;
}
@@ -312,7 +326,9 @@ static void rtc_clk_cpu_src_clk_disable(soc_cpu_clk_src_t old_src)
#if BOOTLOADER_BUILD
clk_ll_xtal_x2_disable();
#else
assert(s_is_xtal_x2_acquired);
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_XTAL_X2, false);
s_is_xtal_x2_acquired = false;
#endif
}
}
@@ -385,7 +401,10 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
rtc_clk_cpu_freq_to_rc_fast();
} else if (config->source == SOC_CPU_CLK_SRC_XTAL_X2
&& esp_clk_tree_is_power_on(SOC_ROOT_CIRCUIT_CLK_XTAL_X2)) {
#if !BOOTLOADER_BUILD
&& s_is_xtal_x2_acquired
#endif
) {
rtc_clk_cpu_freq_to_xtal_x2(config->freq_mhz, config->div);
} else {
/* fallback */
@@ -395,12 +414,13 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
void rtc_clk_cpu_freq_set_xtal(void)
{
rtc_clk_cpu_set_to_default_config();
#if BOOTLOADER_BUILD
rtc_clk_bbpll_disable();
#else
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_BBPLL, false);
#endif
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
int freq_mhz = (int)rtc_clk_xtal_freq_get();
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_XTAL) {
rtc_clk_cpu_src_clk_disable(old_cpu_clk_src);
}
}
FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -28,47 +28,10 @@
ESP_HW_LOG_ATTR_TAG(TAG, "rtc_clk_init");
/**
* Initialize the ICG map of some modem clock domains in the PMU_ACTIVE state
*
* A pre-initialization interface is used to initialize the ICG map of the
* MODEM_APB, I2C_MST and LP_APB clock domains in the PMU_ACTIVE state, and
* disable the clock gating of these clock domains in the PMU_ACTIVE state,
* because the system clock source (PLL) in the system boot up process needs
* to use the i2c master peripheral.
*
* ICG map of all modem clock domains under different power states (PMU_ACTIVE,
* PMU_MODEM and PMU_SLEEP) will be initialized in esp_perip_clk_init().
*/
static void rtc_clk_modem_clock_domain_active_state_icg_map_preinit(void)
{
/* Configure modem ICG code in PMU_ACTIVE state */
pmu_ll_hp_set_icg_modem(&PMU, PMU_MODE_HP_ACTIVE, PMU_HP_ICG_MODEM_CODE_ACTIVE);
#if SOC_MODEM_CLOCK_SUPPORTED
/* Disable clock gating for MODEM_APB, I2C_MST and LP_APB clock domains in PMU_ACTIVE state */
modem_syscon_ll_set_modem_apb_icg_bitmap(&MODEM_SYSCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
modem_syscon_ll_set_ieee802154_icg_bitmap(&MODEM_SYSCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
modem_syscon_ll_set_fe_icg_bitmap(&MODEM_SYSCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
modem_syscon_ll_set_bt_icg_bitmap(&MODEM_SYSCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
modem_lpcon_ll_set_i2c_master_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
modem_lpcon_ll_set_lp_apb_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
modem_lpcon_ll_set_coex_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
#endif
/* Software trigger force update modem ICG code and ICG switch */
pmu_ll_imm_update_dig_icg_modem_code(&PMU, true);
pmu_ll_imm_update_dig_icg_switch(&PMU, true);
}
void rtc_clk_init(rtc_clk_config_t cfg)
{
rtc_cpu_freq_config_t old_config, new_config;
rtc_clk_modem_clock_domain_active_state_icg_map_preinit();
/* Set tuning parameters for RC_FAST and RC_SLOW clocks.
* Note: this doesn't attempt to set the clocks to precise frequencies.
* Instead, we calibrate these clocks against XTAL frequency later, when necessary.
+2 -2
View File
@@ -2962,9 +2962,9 @@ static SLEEP_FN_ATTR uint32_t get_power_down_flags(void)
}
#endif
#if CONFIG_IDF_TARGET_ESP32C6
#if SOC_PM_TOP_DEPENDS_ON_RTC_PERIPH
if (!(pd_flags & PMU_SLEEP_PD_TOP)) {
// TOP power domain depends on the RTC_PERIPH power domain on ESP32C6, RTC_PERIPH should only be disabled when the TOP domain is down.
// TOP power domain depends on the RTC_PERIPH power domain on ESP32C6 and ESP32H4, RTC_PERIPH should only be disabled when the TOP domain is down.
pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
}
#endif
+27 -1
View File
@@ -21,6 +21,7 @@
#if SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED
#include "hal/wdt_hal.h"
#endif
#include "hal/clk_gate_ll.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/esp_clk.h"
#include "esp_private/esp_pmu.h"
@@ -196,5 +197,30 @@ void rtc_clk_select_rtc_slow_clk(void)
*/
__attribute__((weak)) void esp_perip_clk_init(void)
{
ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet");
soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
periph_ll_clk_gate_config_t clk_gate_config = {0};
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
clk_gate_config.disable_uart0_clk = true;
#endif
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
clk_gate_config.disable_uart1_clk = true;
#endif
#if CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
clk_gate_config.disable_mspi_flash_clk = true;
#endif
#if !CONFIG_ESP_SYSTEM_HW_PC_RECORD
clk_gate_config.disable_assist_clk = true;
#endif
#if !CONFIG_SECURE_ENABLE_TEE
clk_gate_config.disable_crypto_periph_clk = true;
#endif
#if !CONFIG_USJ_ENABLE_USB_SERIAL_JTAG && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED
clk_gate_config.disable_usb_serial_jtag = true;
#endif
#if !CONFIG_ESP_ENABLE_PVT
clk_gate_config.disable_pvt_clk = true;
#endif
periph_ll_clk_gate_set_default(rst_reason, &clk_gate_config);
}
@@ -1203,6 +1203,10 @@ config SOC_PM_RETENTION_MODULE_NUM
int
default 32
config SOC_PM_TOP_DEPENDS_ON_RTC_PERIPH
bool
default y
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
bool
default y
@@ -494,6 +494,8 @@
#define SOC_PM_RETENTION_MODULE_NUM (32)
#define SOC_PM_TOP_DEPENDS_ON_RTC_PERIPH (1)
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
#define SOC_MODEM_CLOCK_IS_INDEPENDENT (1)
@@ -1099,6 +1099,10 @@ config SOC_PM_SUPPORT_MAC_BB_PD
bool
default y
config SOC_PM_SUPPORT_RTC_PERIPH_PD
bool
default y
config SOC_PM_SUPPORT_PMU_CLK_ICG
bool
default y
@@ -1139,6 +1143,10 @@ config SOC_PM_RETENTION_MODULE_NUM
int
default 64
config SOC_PM_TOP_DEPENDS_ON_RTC_PERIPH
bool
default y
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
bool
default y
@@ -476,7 +476,7 @@
#define SOC_PM_SUPPORT_TOP_PD (1)
#define SOC_PM_SUPPORT_HP_AON_PD (1)
#define SOC_PM_SUPPORT_MAC_BB_PD (1)
// #define SOC_PM_SUPPORT_RTC_PERIPH_PD (1) // TODO [ESP32H4] PM-484
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)
// #define SOC_PM_SUPPORT_PMU_MODEM_STATE (1)
// /* macro redefine for pass esp_wifi headers md5sum check */
@@ -495,6 +495,8 @@
#define SOC_PM_PAU_REGDMA_LINK_CONFIGURABLE (1)
#define SOC_PM_RETENTION_MODULE_NUM (64)
#define SOC_PM_TOP_DEPENDS_ON_RTC_PERIPH (1) // In ESP32H4, RTC_PERIPH should be pd only together with TOP, otherwise there is some current leak.
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)