From 1c279178faf3617c16215714bd049dfa052f20c0 Mon Sep 17 00:00:00 2001 From: hebinglin Date: Mon, 18 May 2026 21:42:56 +0800 Subject: [PATCH] feat(esp_hw_support): support bbpll pd in modem state --- .../include/esp_private/esp_pmu.h | 2 +- .../include/esp_private/sleep_power.h | 2 +- .../esp_hw_support/lowpower/CMakeLists.txt | 2 +- .../lowpower/port/esp32h4/sleep_power.c | 17 +++++++++-------- .../esp_hw_support/port/esp32h4/pmu_param.c | 4 ++-- components/esp_hw_support/sleep_modes.c | 2 +- components/esp_phy/src/btbb_init.c | 5 ++++- .../soc/esp32h4/include/soc/Kconfig.soc_caps.in | 6 +++++- components/soc/esp32h4/include/soc/soc_caps.h | 3 ++- 9 files changed, 26 insertions(+), 17 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 3383455878a..2846bc34390 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_hw_support/include/esp_private/sleep_power.h b/components/esp_hw_support/include/esp_private/sleep_power.h index 77f046037e9..620688785d0 100644 --- a/components/esp_hw_support/include/esp_private/sleep_power.h +++ b/components/esp_hw_support/include/esp_private/sleep_power.h @@ -24,7 +24,7 @@ extern "C" { #endif -#if CONFIG_BT_CTRL_SLEEP_ENABLE +#if CONFIG_BT_CTRL_SLEEP_ENABLE && SOC_PM_MODEM_LOCK_CLK_WORKAROUND /** * @brief System power retention initialize. diff --git a/components/esp_hw_support/lowpower/CMakeLists.txt b/components/esp_hw_support/lowpower/CMakeLists.txt index 00b0040446a..46acd179560 100644 --- a/components/esp_hw_support/lowpower/CMakeLists.txt +++ b/components/esp_hw_support/lowpower/CMakeLists.txt @@ -40,7 +40,7 @@ if((CONFIG_SOC_PM_SUPPORT_MODEM_PD OR CONFIG_SOC_PM_SUPPORT_TOP_PD) AND CONFIG_S list(APPEND srcs "port/${target}/sleep_clock.c") endif() -if(CONFIG_SOC_PM_SUPPORT_PMU_MODEM_STATE AND CONFIG_BT_CTRL_SLEEP_ENABLE AND CONFIG_SOC_PM_XTALX2_PD_IN_MODEM_STATES) +if(CONFIG_BT_CTRL_SLEEP_ENABLE AND CONFIG_SOC_PM_MODEM_LOCK_CLK_WORKAROUND) list(APPEND srcs "port/${target}/sleep_power.c") set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u sleep_power_system_retention_init") diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_power.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_power.c index 7e1dfc8987e..9913929002d 100644 --- a/components/esp_hw_support/lowpower/port/esp32h4/sleep_power.c +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_power.c @@ -6,22 +6,23 @@ #include "esp_private/sleep_power.h" #include "soc/pmu_reg.h" +#include "modem/modem_lpcon_reg.h" ESP_LOG_ATTR_TAG(TAG, "sleep_power"); -#if CONFIG_BT_CTRL_SLEEP_ENABLE +#if CONFIG_BT_CTRL_SLEEP_ENABLE && SOC_PM_MODEM_LOCK_CLK_WORKAROUND esp_err_t sleep_power_system_retention_init(void *arg) { const static sleep_retention_entries_config_t power_regs_retention[] = { - /* During the modem-to-active transition, the MODEM lock keeps the xtalx2 xpd status unchanged. - * Therefore, if xtalx2 is disabled in modem state, we need to set xtalx2 tie-high to enable it in active state. */ - [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_POWER_LINK(0), PMU_IMM_HP_CK_POWER_REG, PMU_TIE_HIGH_XTALX2 | PMU_TIE_HIGH_GLOBAL_XTALX2_ICG, PMU_TIE_HIGH_XTALX2_M | PMU_TIE_HIGH_GLOBAL_XTALX2_ICG_M, 1, 0), .owner = ENTRY(2) }, + /* During the modem-to-active transition, the MODEM lock keeps the xtalx2, bbpll xpd status unchanged. + * Therefore, if xtalx2, bbpll is disabled in modem state, we need to set xtalx2, bbpll tie-high to enable it in active state. */ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_POWER_LINK(0), PMU_IMM_HP_CK_POWER_REG, PMU_TIE_HIGH_XTALX2 | PMU_TIE_HIGH_GLOBAL_XTALX2_ICG, PMU_TIE_HIGH_XTALX2_M | PMU_TIE_HIGH_GLOBAL_XTALX2_ICG_M, 1, 0), .owner = ENTRY(2) }, + [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_POWER_LINK(1), PMU_IMM_HP_CK_POWER_REG, PMU_TIE_HIGH_XPD_BBPLL | PMU_TIE_HIGH_XPD_BBPLL_I2C, PMU_TIE_HIGH_XPD_BBPLL_M | PMU_TIE_HIGH_XPD_BBPLL_I2C_M, 1, 0), .owner = ENTRY(2) }, }; - esp_err_t err = sleep_retention_entries_create(power_regs_retention, ARRAY_SIZE(power_regs_retention), REGDMA_LINK_PRI_POWER, SLEEP_RETENTION_MODULE_POWER); - ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system power retention"); - ESP_LOGI(TAG, "System power sleep retention initialization"); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for clock power retention"); + ESP_LOGI(TAG, "Clock power sleep retention initialization"); return ESP_OK; } @@ -29,7 +30,7 @@ ESP_SYSTEM_INIT_FN(sleep_power_startup_init, SECONDARY, BIT(0), 108) { sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_power_system_retention_init, .arg = NULL } }, - .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE | SLEEP_RETENTION_MODULE_ATTR_ATTACH }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_POWER, &init_param); diff --git a/components/esp_hw_support/port/esp32h4/pmu_param.c b/components/esp_hw_support/port/esp32h4/pmu_param.c index 16b2890334a..eccebaae0e3 100644 --- a/components/esp_hw_support/port/esp32h4/pmu_param.c +++ b/components/esp_hw_support/port/esp32h4/pmu_param.c @@ -68,8 +68,8 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param"); .i2c_iso_en = 0, \ .i2c_retention = 0, \ .xpd_bb_i2c = 1, \ - .xpd_bbpll_i2c = 1, \ - .xpd_bbpll = 1 \ + .xpd_bbpll_i2c = 0, \ + .xpd_bbpll = 0 \ }, \ .xtal = { \ .xpd_xtalx2 = 0, \ diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 91c349b6f38..dcdf8262b7d 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1181,7 +1181,7 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t cl } #endif // Restore CPU frequency -#if SOC_PM_SUPPORT_PMU_MODEM_STATE +#if SOC_PM_SUPPORT_PMU_MODEM_STATE && !SOC_PM_BBPLL_PD_IN_MODEM_STATE if (pmu_sleep_pll_already_enabled()) { rtc_clk_cpu_freq_to_pll_and_pll_lock_release(esp_pm_impl_get_cpu_freq(PM_MODE_CPU_MAX)); } else diff --git a/components/esp_phy/src/btbb_init.c b/components/esp_phy/src/btbb_init.c index d0d3b535101..bcd7768ec37 100644 --- a/components/esp_phy/src/btbb_init.c +++ b/components/esp_phy/src/btbb_init.c @@ -68,8 +68,11 @@ static esp_err_t btbb_sleep_retention_enable(void) sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = btbb_sleep_retention_init, .arg = NULL } }, .attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH, - .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) }; + init_param.depends.bitmap[SLEEP_RETENTION_MODULE_CLOCK_MODEM >> 5] |= BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM % 32); +#if SOC_PM_MODEM_LOCK_CLK_WORKAROUND && CONFIG_BT_CTRL_SLEEP_ENABLE + init_param.depends.bitmap[SLEEP_RETENTION_MODULE_POWER >> 5] |= BIT(SLEEP_RETENTION_MODULE_POWER % 32); +#endif esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BT_BB, &init_param); if (err != ESP_OK) { ESP_LOGW(TAG, "Modem BT BB retention callback register failed"); diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index f6822af5db9..720161d8b89 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -1223,7 +1223,11 @@ config SOC_PM_TOP_DEPENDS_ON_RTC_PERIPH bool default y -config SOC_PM_XTALX2_PD_IN_MODEM_STATES +config SOC_PM_BBPLL_PD_IN_MODEM_STATE + bool + default y + +config SOC_PM_MODEM_LOCK_CLK_WORKAROUND bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 13044dc9c9b..0d3d288b713 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -515,7 +515,8 @@ #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. -#define SOC_PM_XTALX2_PD_IN_MODEM_STATES (1) +#define SOC_PM_BBPLL_PD_IN_MODEM_STATE (1) +#define SOC_PM_MODEM_LOCK_CLK_WORKAROUND (1) // In ESP32H4, the modem lock will lock the xtalx2, bbpll and other xpd state during modem2active. /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)