From d4337bdcefad4fd4660b070d51bd05d701f44bd4 Mon Sep 17 00:00:00 2001 From: hebinglin Date: Wed, 25 Mar 2026 19:42:14 +0800 Subject: [PATCH 1/5] change(esp_hw_support): update pmu analog param for esp32h4 eco1 --- .../esp_hal_pmu/esp32h4/include/hal/pmu_ll.h | 7 ----- .../esp_hw_support/port/esp32h21/pmu_sleep.c | 1 + .../esp_hw_support/port/esp32h4/pmu_sleep.c | 7 ++++- .../port/esp32h4/private_include/pmu_param.h | 29 ++++++++++--------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/components/esp_hal_pmu/esp32h4/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32h4/include/hal/pmu_ll.h index f4a96deffe..55526952c0 100644 --- a/components/esp_hal_pmu/esp32h4/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32h4/include/hal/pmu_ll.h @@ -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; diff --git a/components/esp_hw_support/port/esp32h21/pmu_sleep.c b/components/esp_hw_support/port/esp32h21/pmu_sleep.c index e5587c3725..76b73a0abf 100644 --- a/components/esp_hw_support/port/esp32h21/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h21/pmu_sleep.c @@ -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(); diff --git a/components/esp_hw_support/port/esp32h4/pmu_sleep.c b/components/esp_hw_support/port/esp32h4/pmu_sleep.c index 505138d7d6..6de6b180dc 100644 --- a/components/esp_hw_support/port/esp32h4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h4/pmu_sleep.c @@ -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); diff --git a/components/esp_hw_support/port/esp32h4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32h4/private_include/pmu_param.h index 144af0a46a..dc0ae173c7 100644 --- a/components/esp_hw_support/port/esp32h4/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32h4/private_include/pmu_param.h @@ -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 \ } \ } \ From 4b2e135fd06773604dbb720996e0eabdb6da5a37 Mon Sep 17 00:00:00 2001 From: hebinglin Date: Thu, 26 Mar 2026 12:31:50 +0800 Subject: [PATCH 2/5] feat(esp_hw_support): optimize esp32h4 eco1 active current --- .../esp32h4/include/hal/clk_gate_ll.h | 125 +++++++++++++++++- components/esp_system/port/soc/esp32h4/clk.c | 28 +++- 2 files changed, 151 insertions(+), 2 deletions(-) diff --git a/components/esp_hal_clock/esp32h4/include/hal/clk_gate_ll.h b/components/esp_hal_clock/esp32h4/include/hal/clk_gate_ll.h index 4c41ecf4a9..b232850ce0 100644 --- a/components/esp_hal_clock/esp32h4/include/hal/clk_gate_ll.h +++ b/components/esp_hal_clock/esp32h4/include/hal/clk_gate_ll.h @@ -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 #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 diff --git a/components/esp_system/port/soc/esp32h4/clk.c b/components/esp_system/port/soc/esp32h4/clk.c index b3c3af9966..8dca9fb3b6 100644 --- a/components/esp_system/port/soc/esp32h4/clk.c +++ b/components/esp_system/port/soc/esp32h4/clk.c @@ -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" @@ -197,5 +198,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); } From c2a371a20dee342de0c842f3aa8a65acea9da74a Mon Sep 17 00:00:00 2001 From: hebinglin Date: Wed, 1 Apr 2026 11:52:01 +0800 Subject: [PATCH 3/5] change(esp_hw_support): allow rtc_periph pd when top pd for esp32h4 eco1 --- components/esp_hw_support/sleep_modes.c | 4 ++-- components/soc/esp32c6/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32c6/include/soc/soc_caps.h | 2 ++ components/soc/esp32h4/include/soc/Kconfig.soc_caps.in | 8 ++++++++ components/soc/esp32h4/include/soc/soc_caps.h | 4 +++- 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index e1599cf94b..4138fa6a5b 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -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 diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 0b268501ba..bacda29e73 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 05d60318dd..91ade7b782 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -497,6 +497,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) diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 17d21fbebb..4fd30da02e 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -1011,6 +1011,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 @@ -1051,6 +1055,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 diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 3e744fac91..8a2b6bf444 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -481,7 +481,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 */ @@ -500,6 +500,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) From 386911b35f91d0175361e18a1ac8f7eb4c1f5234 Mon Sep 17 00:00:00 2001 From: hebinglin Date: Wed, 1 Apr 2026 16:07:27 +0800 Subject: [PATCH 4/5] change(esp_hw_support): remove invalid modem clock preinit for esp32h4 eco1 --- .../port/esp32h4/rtc_clk_init.c | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/components/esp_hw_support/port/esp32h4/rtc_clk_init.c b/components/esp_hw_support/port/esp32h4/rtc_clk_init.c index 9baf0c4a3e..eb141e8049 100644 --- a/components/esp_hw_support/port/esp32h4/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32h4/rtc_clk_init.c @@ -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. From a65baea1afe027b66ba9be685733293ebafc0050 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Tue, 31 Mar 2026 20:52:04 +0800 Subject: [PATCH 5/5] fix(clk): fix hp root clock source ref count mismatch on esp32h4/h21 Mismatch happens when hp_active->hp_sleep->hp_active The ref count of the hp root clock source was over incremented by 1 when exiting sleep (since when entering sleep, the power down of the clock sources are done by PMU, no decrement of the ref count is done before entering sleep)) --- .../esp_hw_support/port/esp32h21/rtc_clk.c | 38 ++++++++++++++----- .../port/esp32h4/esp_clk_tree.c | 2 +- .../esp_hw_support/port/esp32h4/rtc_clk.c | 38 ++++++++++++++----- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/components/esp_hw_support/port/esp32h21/rtc_clk.c b/components/esp_hw_support/port/esp32h21/rtc_clk.c index d585f4c48f..3acace5c40 100644 --- a/components/esp_hw_support/port/esp32h21/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h21/rtc_clk.c @@ -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) diff --git a/components/esp_hw_support/port/esp32h4/esp_clk_tree.c b/components/esp_hw_support/port/esp32h4/esp_clk_tree.c index 9211539956..9a24714bf3 100644 --- a/components/esp_hw_support/port/esp32h4/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32h4/esp_clk_tree.c @@ -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; } diff --git a/components/esp_hw_support/port/esp32h4/rtc_clk.c b/components/esp_hw_support/port/esp32h4/rtc_clk.c index 95f8289a20..cd6083e4eb 100644 --- a/components/esp_hw_support/port/esp32h4/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h4/rtc_clk.c @@ -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)