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 b232850ce0d..1325c262c81 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 @@ -152,13 +152,18 @@ static inline void periph_ll_clk_gate_set_default(soc_reset_reason_t rst_reason, 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; + PCR.regdma_conf.regdma_clk_en = 0; if (config->disable_mspi_flash_clk) { PCR.mspi_conf.mspi_clk_en = 0; + PCR.mspi_conf.mspi_pll_clk_en = 0; + PCR.mspi_clk_conf.mspi_func_clk_en = 0; } PCR.spi2_conf.spi2_clk_en = 0; + PCR.spi2_clkm_conf.spi2_clkm_en = 0; PCR.spi3_conf.spi3_clk_en = 0; + PCR.spi3_clkm_conf.spi3_clkm_en = 0; PCR.tsens_clk_conf.tsens_clk_en = 0; PCR.uhci_conf.uhci_clk_en = 0; @@ -172,6 +177,7 @@ static inline void periph_ll_clk_gate_set_default(soc_reset_reason_t rst_reason, /* 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; + PCR.assist_conf.assist1_clk_en = 0; } if (config->disable_crypto_periph_clk) { @@ -204,7 +210,6 @@ static inline void periph_ll_clk_gate_set_default(soc_reset_reason_t rst_reason, 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; } diff --git a/components/esp_hal_pmu/esp32/include/hal/rtc_cntl_ll.h b/components/esp_hal_pmu/esp32/include/hal/rtc_cntl_ll.h index 4b82a571ac0..cf08763d159 100644 --- a/components/esp_hal_pmu/esp32/include/hal/rtc_cntl_ll.h +++ b/components/esp_hal_pmu/esp32/include/hal/rtc_cntl_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,6 +85,11 @@ FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void) return REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE); } +FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_enable(void) +{ + return REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA); +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_pmu/esp32c2/include/hal/rtc_cntl_ll.h b/components/esp_hal_pmu/esp32c2/include/hal/rtc_cntl_ll.h index 7947ee3b8d5..0b0fc1d61da 100644 --- a/components/esp_hal_pmu/esp32c2/include/hal/rtc_cntl_ll.h +++ b/components/esp_hal_pmu/esp32c2/include/hal/rtc_cntl_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -61,6 +61,11 @@ FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void) return REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE); } +FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_enable(void) +{ + return REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA); +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_pmu/esp32c3/include/hal/rtc_cntl_ll.h b/components/esp_hal_pmu/esp32c3/include/hal/rtc_cntl_ll.h index 829f10280f3..136e2c9820a 100644 --- a/components/esp_hal_pmu/esp32c3/include/hal/rtc_cntl_ll.h +++ b/components/esp_hal_pmu/esp32c3/include/hal/rtc_cntl_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -67,6 +67,11 @@ FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void) return REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE); } +FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_enable(void) +{ + return REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA); +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_pmu/esp32c5/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32c5/include/hal/pmu_ll.h index 36af3b94080..b9524bbf82d 100644 --- a/components/esp_hal_pmu/esp32c5/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32c5/include/hal/pmu_ll.h @@ -529,6 +529,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_enable_sw_intr(pmu_dev_t *hw, bool enable) hw->hp_ext.int_ena.sw = enable; } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_enable(pmu_dev_t *hw) +{ + return hw->wakeup.cntl2; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) { return hw->wakeup.status0; diff --git a/components/esp_hal_pmu/esp32c6/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32c6/include/hal/pmu_ll.h index 3f8ee6ac871..e9fd16bbd3b 100644 --- a/components/esp_hal_pmu/esp32c6/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32c6/include/hal/pmu_ll.h @@ -529,6 +529,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_enable_sw_intr(pmu_dev_t *hw, bool enable) hw->hp_ext.int_ena.sw = enable; } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_enable(pmu_dev_t *hw) +{ + return hw->wakeup.cntl2; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) { return hw->wakeup.status0; diff --git a/components/esp_hal_pmu/esp32c61/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32c61/include/hal/pmu_ll.h index 2353926ad59..e678b4218dd 100644 --- a/components/esp_hal_pmu/esp32c61/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32c61/include/hal/pmu_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -519,6 +519,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw) hw->hp_ext.int_clr.reject = 1; } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_enable(pmu_dev_t *hw) +{ + return hw->wakeup.cntl2; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) { return hw->wakeup.status0; diff --git a/components/esp_hal_pmu/esp32h2/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32h2/include/hal/pmu_ll.h index 1272e2fb24e..c649e1c0dac 100644 --- a/components/esp_hal_pmu/esp32h2/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32h2/include/hal/pmu_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -475,6 +475,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw) hw->hp_ext.int_clr.reject = 1; } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_enable(pmu_dev_t *hw) +{ + return hw->wakeup.cntl2; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) { return hw->wakeup.status0; diff --git a/components/esp_hal_pmu/esp32h21/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32h21/include/hal/pmu_ll.h index bc4747517a9..e2b65687321 100644 --- a/components/esp_hal_pmu/esp32h21/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32h21/include/hal/pmu_ll.h @@ -600,6 +600,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw) hw->hp_ext.int_clr.soc_sleep_reject = 1; } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_enable(pmu_dev_t *hw) +{ + return hw->wakeup.cntl2; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) { return hw->wakeup.status0; 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 55526952c01..aa72e0b6579 100644 --- a/components/esp_hal_pmu/esp32h4/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32h4/include/hal/pmu_ll.h @@ -645,6 +645,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw) hw->hp_ext.int_clr.soc_sleep_reject = 1; } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_enable(pmu_dev_t *hw) +{ + return hw->wakeup.cntl2; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) { return hw->wakeup.status0.val; diff --git a/components/esp_hal_pmu/esp32p4/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32p4/include/hal/pmu_ll.h index e9cff5dcf04..960c3f6a157 100644 --- a/components/esp_hal_pmu/esp32p4/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32p4/include/hal/pmu_ll.h @@ -572,6 +572,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_clear_lp_cpu_exc_intr_status(pmu_dev_t *hw) hw->hp_ext.int_clr.lp_exception = 1; } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_enable(pmu_dev_t *hw) +{ + return hw->wakeup.cntl2.val; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) { return hw->wakeup.status0; diff --git a/components/esp_hal_pmu/esp32s2/include/hal/rtc_cntl_ll.h b/components/esp_hal_pmu/esp32s2/include/hal/rtc_cntl_ll.h index 81a32c93caf..25f1c9c9f9d 100644 --- a/components/esp_hal_pmu/esp32s2/include/hal/rtc_cntl_ll.h +++ b/components/esp_hal_pmu/esp32s2/include/hal/rtc_cntl_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -81,6 +81,11 @@ FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void) return REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE); } +FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_enable(void) +{ + return REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA); +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_pmu/esp32s3/include/hal/rtc_cntl_ll.h b/components/esp_hal_pmu/esp32s3/include/hal/rtc_cntl_ll.h index 9ef09f1869a..0ebc912284d 100644 --- a/components/esp_hal_pmu/esp32s3/include/hal/rtc_cntl_ll.h +++ b/components/esp_hal_pmu/esp32s3/include/hal/rtc_cntl_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -162,6 +162,11 @@ FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void) return REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE); } +FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_enable(void) +{ + return REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA); +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_pmu/esp32s31/include/hal/pmu_ll.h b/components/esp_hal_pmu/esp32s31/include/hal/pmu_ll.h index b120ba0815c..d76d5cf23de 100644 --- a/components/esp_hal_pmu/esp32s31/include/hal/pmu_ll.h +++ b/components/esp_hal_pmu/esp32s31/include/hal/pmu_ll.h @@ -624,6 +624,11 @@ FORCE_INLINE_ATTR void pmu_ll_hp_enable_sw_intr(pmu_dev_t *hw, bool enable) hw->hp_ext.int_ena.sw = enable; } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_enable(pmu_dev_t *hw) +{ + return hw->wakeup.cntl2; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) { return hw->wakeup.status0; 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 new file mode 100644 index 00000000000..620688785d0 --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_power.h @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include +#include +#include +#include +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_attr.h" +#include "esp_check.h" +#include "esp_regdma.h" +#include "esp_private/sleep_retention.h" +#include "esp_private/startup_internal.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_BT_CTRL_SLEEP_ENABLE && SOC_PM_MODEM_LOCK_CLK_WORKAROUND + +/** + * @brief System power retention initialize. + * + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM not enough memory for system power retention + * - ESP_ERR_INVALID_ARG if either of the arguments is out of range + */ +esp_err_t sleep_power_system_retention_init(void *arg); + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/lowpower/CMakeLists.txt b/components/esp_hw_support/lowpower/CMakeLists.txt index d2f5db0d7de..46acd179560 100644 --- a/components/esp_hw_support/lowpower/CMakeLists.txt +++ b/components/esp_hw_support/lowpower/CMakeLists.txt @@ -40,6 +40,12 @@ 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_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") +endif() + if(CONFIG_SOC_PM_SUPPORT_PMU_MODEM_STATE) list(APPEND srcs "port/${target}/sleep_modem_state.c") endif() diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock.c index 60db037050e..e66cd31aaa9 100644 --- a/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock.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 */ @@ -8,7 +8,6 @@ #include "soc/pcr_reg.h" #include "modem/modem_syscon_reg.h" #include "modem/modem_lpcon_reg.h" -#include "modem/i2c_ana_mst_reg.h" #include "soc/pmu_reg.h" #include "soc/lp_analog_peri_reg.h" @@ -46,16 +45,6 @@ esp_err_t sleep_clock_modem_retention_init(void *arg) /* SYSCON LPCON configuration retention */ [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMSYSCON_LINK(0), MODEM_SYSCON_TEST_CONF_REG, MODEM_SYSCON_TEST_CONF_REG, N_REGS_SYSCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) }, /* MODEM SYSCON */ [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMLPCON_LINK (0), MODEM_LPCON_TEST_CONF_REG, MODEM_LPCON_TEST_CONF_REG, N_REGS_LPCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) }, /* MODEM LPCON */ - /* Enable i2c master clock */ - [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(1), 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 */ - [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(2), I2C_ANA_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) }, - [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(3), 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 */ - [5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_MODEMSYSCON_LINK(4), 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 */ - [6] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(5), I2C_ANA_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_LOW, 1, 0), .owner = ENTRY(0) }, - [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(6), I2C_ANA_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) }, }; esp_err_t err = sleep_retention_entries_create(modem_regs_retention, ARRAY_SIZE(modem_regs_retention), REGDMA_LINK_PRI_MODEM_CLK, SLEEP_RETENTION_MODULE_CLOCK_MODEM); diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_power.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_power.c new file mode 100644 index 00000000000..9913929002d --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_power.c @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#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 && 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, 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 clock power retention"); + ESP_LOGI(TAG, "Clock power sleep retention initialization"); + return ESP_OK; +} + +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 | SLEEP_RETENTION_MODULE_ATTR_ATTACH + }; + + esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_POWER, &init_param); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to init power retention module, err=%d", err); + } + + return ESP_OK; +} + +#endif diff --git a/components/esp_hw_support/port/esp32h21/pmu_sleep.c b/components/esp_hw_support/port/esp32h21/pmu_sleep.c index 196350388fa..dba305b577d 100644 --- a/components/esp_hw_support/port/esp32h21/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h21/pmu_sleep.c @@ -306,7 +306,7 @@ bool pmu_sleep_finish(bool dslp) #if !SOC_APM_SUPPORTED apm_hal_enable_ctrl_filter_all(false); #else - ESP_STATIC_ASSERT(0, "TEE/APM retention need to be supported!"); + ESP_STATIC_ASSERT(0, "TEE/APM retention need to be supported!"); //TODO: IDF-15711 #endif return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev); diff --git a/components/esp_hw_support/port/esp32h4/pmu_param.c b/components/esp_hw_support/port/esp32h4/pmu_param.c index 54b1f73e79c..668390b0d68 100644 --- a/components/esp_hw_support/port/esp32h4/pmu_param.c +++ b/components/esp_hw_support/port/esp32h4/pmu_param.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 */ @@ -17,7 +17,13 @@ #include "esp_hw_log.h" #include "soc/clk_tree_defs.h" -static __attribute__((unused)) const char *TAG = "pmu_param"; +#define PMU_CLK_SRC_VAL(src) \ + (((uint32_t)src == (uint32_t)SOC_MOD_CLK_XTAL) ? 0 : \ + ((uint32_t)src == (uint32_t)SOC_MOD_CLK_RC_FAST) ? 1 : \ + ((uint32_t)src == (uint32_t)SOC_MOD_CLK_XTAL_X2_F64M) ? 2 : \ + ((uint32_t)src == (uint32_t)SOC_MOD_CLK_PLL_F96M) ? 3 : 0) + +ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param"); #ifndef ARRAY_SIZE #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) @@ -62,11 +68,11 @@ static __attribute__((unused)) const char *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 = 1, \ + .xpd_xtalx2 = 0, \ .xpd_xtal = 1 \ } \ } @@ -130,7 +136,7 @@ const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mod } #define PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT() { \ - .icg_func = 0, \ + .icg_func = BIT(PMU_ICG_FUNC_ENA_REGDMA) | BIT(PMU_ICG_FUNC_ENA_HPBUS), \ .icg_apb = 0, \ .icg_modem = { \ .code = PMU_HP_ICG_MODEM_CODE_MODEM \ @@ -250,24 +256,28 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp .bias = { \ .dcdc_ccm_enb = 0, \ .dcdc_clear_rdy = 0, \ - .dig_reg_dpcur_bias = 1, \ + .dig_reg_dpcur_bias = 3, \ .dig_reg_dsfmos = 15, \ .dcm_mode = 3, \ .dcm_vset = 24, \ .xpd_trx = 1, \ - .xpd_bias = 0, \ + .xpd_bias = 1, \ .discnnt_dig_rtc = 0, \ .pd_cur = 0, \ .bias_sleep = 0 \ }, \ .regulator0 = { \ .power_det_bypass = 0, \ + .lp_dbias_vol = 0xd, \ + .hp_dbias_vol = 0x1c, \ + .dbias_sel = 1, \ + .dbias_init = 1, \ .slp_mem_xpd = 0, \ .slp_logic_xpd = 0, \ .xpd = 1, \ .slp_mem_dbias = 0, \ .slp_logic_dbias = 0, \ - .dbias = 0 \ + .dbias = 0 \ }, \ .regulator1 = { \ .drv_b = HP_CALI_DRVB_DEFAULT \ @@ -319,8 +329,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .retention = { \ .hp_sleep2active_backup_modem_clk_code = 2, \ .hp_modem2active_backup_modem_clk_code = 2, \ - .hp_sleep2active_backup_clk_sel = 0, \ - .hp_modem2active_backup_clk_sel = 1, \ + .hp_sleep2active_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL_X2_F64M), \ + .hp_modem2active_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL), \ .hp_sleep2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 0), \ .hp_modem2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 2), \ .hp_sleep2active_backup_en = 0, \ @@ -332,7 +342,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m #define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \ .retention = { \ .hp_sleep2modem_backup_modem_clk_code = 1, \ - .hp_sleep2modem_backup_clk_sel = 0, \ + .hp_sleep2modem_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL), \ .hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \ .hp_sleep2modem_backup_en = 0, \ }, \ @@ -343,8 +353,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .retention = { \ .hp_modem2sleep_backup_modem_clk_code = 0, \ .hp_active2sleep_backup_modem_clk_code = 2, \ - .hp_modem2sleep_backup_clk_sel = 0, \ - .hp_active2sleep_backup_clk_sel = 0, \ + .hp_modem2sleep_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL), \ + .hp_active2sleep_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL_X2_F64M), \ .hp_modem2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 1), \ .hp_active2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 0), \ .hp_modem2sleep_backup_en = 0, \ diff --git a/components/esp_hw_support/port/esp32h4/pmu_sleep.c b/components/esp_hw_support/port/esp32h4/pmu_sleep.c index 0d1820139c6..b88b5b68238 100644 --- a/components/esp_hw_support/port/esp32h4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h4/pmu_sleep.c @@ -18,6 +18,9 @@ #include "hal/efuse_ll.h" #include "esp_private/esp_pmu.h" #include "pmu_param.h" +#if !SOC_APM_SUPPORTED +#include "hal/apm_hal.h" +#endif #define HP(state) (PMU_MODE_HP_ ## state) #define LP(state) (PMU_MODE_LP_ ## state) @@ -300,6 +303,12 @@ bool pmu_sleep_finish(bool dslp) // Wait eFuse memory update done. while (efuse_ll_get_controller_state() != EFUSE_CONTROLLER_STATE_IDLE) { } +#if !SOC_APM_SUPPORTED + apm_hal_enable_ctrl_filter_all(false); +#else + ESP_STATIC_ASSERT(0, "TEE/APM retention need to be supported!"); //TODO: IDF-15710 +#endif + return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev); } 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 dc0ae173c7d..16742a8b4de 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 @@ -387,7 +387,6 @@ typedef struct { .dcdc_clear_rdy = 0, \ .dig_reg_dpcur_bias = 1, \ .dig_reg_dsfmos = 4, \ - .dcm_vset = 20, \ .dcm_mode = 3, \ .discnnt_dig_rtc = 0, \ .xpd_trx = 0, \ @@ -406,7 +405,7 @@ typedef struct { .dcdc_clear_rdy = 0, \ .dig_reg_dpcur_bias = 1, \ .dig_reg_dsfmos = 4, \ - .dcm_vset = 0, \ + .dcm_vset = 20, \ .dcm_mode = 3, \ .discnnt_dig_rtc = 0, \ .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ diff --git a/components/esp_hw_support/port/esp32s31/pmu_sleep.c b/components/esp_hw_support/port/esp32s31/pmu_sleep.c index 632d70027b7..42837b69e76 100644 --- a/components/esp_hw_support/port/esp32s31/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32s31/pmu_sleep.c @@ -401,7 +401,7 @@ IRAM_ATTR bool pmu_sleep_finish(bool dslp) #if !SOC_APM_SUPPORTED apm_hal_enable_ctrl_filter_all(false); #else - ESP_STATIC_ASSERT(0, "TEE/APM retention need to be supported!"); + ESP_STATIC_ASSERT(0, "TEE/APM retention need to be supported!"); //TODO: IDF-15712 #endif return pmu_ll_hp_is_sleep_reject(&PMU); diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index ecf5aa936c8..a82fc537010 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -27,6 +27,13 @@ #include "soc/uart_pins.h" #include "hal/rtc_hal.h" +#if SOC_PMU_SUPPORTED +#include "hal/pmu_ll.h" +#include "esp_private/esp_pmu.h" +#else +#include "soc/rtc.h" +#include "hal/rtc_cntl_ll.h" +#endif #include "esp_private/esp_gpio_reserve.h" #include "esp_private/gpio.h" @@ -37,6 +44,18 @@ ESP_LOG_ATTR_TAG(TAG, "sleep_gpio"); +#if SOC_PM_SUPPORT_EXT0_WAKEUP +#define _IO_WAKEUP_EXT0 RTC_EXT0_TRIG_EN +#else +#define _IO_WAKEUP_EXT0 0 +#endif +#if SOC_PM_SUPPORT_EXT1_WAKEUP +#define _IO_WAKEUP_EXT1 RTC_EXT1_TRIG_EN +#else +#define _IO_WAKEUP_EXT1 0 +#endif +#define IO_WAKEUP_ENABLED (RTC_GPIO_TRIG_EN | _IO_WAKEUP_EXT0 | _IO_WAKEUP_EXT1) + #if CONFIG_IDF_TARGET_ESP32 /* On ESP32, for IOs with RTC functionality, setting SLP_PU, SLP_PD couldn't change IO status * from FUN_PU, FUN_PD to SLP_PU, SLP_PD at sleep. @@ -373,7 +392,12 @@ ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, SECONDARY, BIT(0), 105) { #if SOC_DEEP_SLEEP_SUPPORTED // Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins - if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { +#if SOC_PMU_SUPPORTED + uint32_t io_wakeup_enabled = pmu_ll_hp_get_wakeup_enable(&PMU) & IO_WAKEUP_ENABLED; +#else + uint32_t io_wakeup_enabled = rtc_cntl_ll_get_wakeup_enable() & IO_WAKEUP_ENABLED; +#endif + if (esp_reset_reason() == ESP_RST_DEEPSLEEP && io_wakeup_enabled) { esp_deep_sleep_wakeup_io_reset(); } #endif //#if SOC_DEEP_SLEEP_SUPPORTED 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_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c index 73a0251ad12..8f705317295 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c @@ -623,6 +623,7 @@ TEST_CASE("allocate 2 handlers for a same source and remove the later one", "[in // enable SPI2 PERIPH_RCC_ATOMIC() { + spi_ll_enable_clock(1, true); spi_ll_enable_bus_clock(1, true); spi_ll_reset_register(1); } 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/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index e28a73a22d9..0b9c8d8f736 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -96,6 +96,7 @@ SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/p SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32s31/sleep_clock.c on BIT(0) SECONDARY: 106: sleep_clock_icg_startup_init in components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c on BIT(0) SECONDARY: 107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0) +SECONDARY: 108: sleep_power_startup_init in components/esp_hw_support/lowpower/port/esp32h4/sleep_power.c on BIT(0) # app_trace doesn't have init dependencies SECONDARY: 115: apptrace_early_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 97ae2d271d4..720161d8b89 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -1223,6 +1223,14 @@ config SOC_PM_TOP_DEPENDS_ON_RTC_PERIPH bool default y +config SOC_PM_BBPLL_PD_IN_MODEM_STATE + bool + default y + +config SOC_PM_MODEM_LOCK_CLK_WORKAROUND + bool + default y + config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y diff --git a/components/soc/esp32h4/include/soc/pmu_icg_mapping.h b/components/soc/esp32h4/include/soc/pmu_icg_mapping.h index afb82d36282..4f7ae7a8dbd 100644 --- a/components/soc/esp32h4/include/soc/pmu_icg_mapping.h +++ b/components/soc/esp32h4/include/soc/pmu_icg_mapping.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 OR MIT */ @@ -14,7 +14,7 @@ #define PMU_ICG_APB_ENA_MSPI 5 #define PMU_ICG_APB_ENA_UART0 6 #define PMU_ICG_APB_ENA_UART1 7 -#define PMU_ICG_APB_ENA_SPI3 8 +#define PMU_ICG_APB_ENA_UHCI 8 #define PMU_ICG_APB_ENA_SARADC 9 #define PMU_ICG_APB_ENA_TG0 11 #define PMU_ICG_APB_ENA_TG1 12 @@ -23,8 +23,8 @@ #define PMU_ICG_APB_ENA_RMT 15 #define PMU_ICG_APB_ENA_SYSTIMER 16 #define PMU_ICG_APB_ENA_USB_DEVICE 17 -#define PMU_ICG_APB_ENA_CAN0 18 -#define PMU_ICG_APB_ENA_PWM1 19 +#define PMU_ICG_APB_ENA_TWAI0 18 +#define PMU_ICG_APB_ENA_TWAI1 19 #define PMU_ICG_APB_ENA_PCNT 20 #define PMU_ICG_APB_ENA_PWM 21 #define PMU_ICG_APB_ENA_SOC_ETM 22 @@ -33,19 +33,18 @@ #define PMU_ICG_APB_ENA_MEM_MONITOR 25 #define PMU_ICG_APB_ENA_IOMUX 26 #define PMU_ICG_APB_ENA_PVT_MONITOR 27 -#define PMU_ICG_APB_ENA_BS 28 #define PMU_ICG_FUNC_ENA_GDMA 0 #define PMU_ICG_FUNC_ENA_SPI2 1 #define PMU_ICG_FUNC_ENA_I2S_RX 2 #define PMU_ICG_FUNC_ENA_UART0 3 #define PMU_ICG_FUNC_ENA_UART1 4 -#define PMU_ICG_FUNC_ENA_PCNT 5 +#define PMU_ICG_FUNC_ENA_UHCI 5 #define PMU_ICG_FUNC_ENA_USB_DEVICE 6 #define PMU_ICG_FUNC_ENA_I2S_TX 7 -#define PMU_ICG_FUNC_ENA_ASRC 8 -#define PMU_ICG_FUNC_ENA_USB_OTG11 9 -#define PMU_ICG_FUNC_ENA_DEBUG 10 -#define PMU_ICG_FUNC_ENA_SPI3 11 +#define PMU_ICG_FUNC_ENA_REGDMA 8 +#define PMU_ICG_FUNC_ENA_RETENTION 9 +#define PMU_ICG_FUNC_ENA_MEM_MONITOR 10 +#define PMU_ICG_FUNC_ENA_SDIO_SLAVE 11 #define PMU_ICG_FUNC_ENA_TSENS 12 #define PMU_ICG_FUNC_ENA_TG1 13 #define PMU_ICG_FUNC_ENA_TG0 14 @@ -58,11 +57,11 @@ #define PMU_ICG_FUNC_ENA_RMT 21 #define PMU_ICG_FUNC_ENA_PWM 22 #define PMU_ICG_FUNC_ENA_PVT_MONITOR 23 -#define PMU_ICG_FUNC_ENA_PWM1 24 +#define PMU_ICG_FUNC_ENA_PARL_TX 24 #define PMU_ICG_FUNC_ENA_PARL_RX 25 #define PMU_ICG_FUNC_ENA_MSPI 26 #define PMU_ICG_FUNC_ENA_LEDC 27 #define PMU_ICG_FUNC_ENA_IOMUX 28 #define PMU_ICG_FUNC_ENA_I2C 29 -#define PMU_ICG_FUNC_ENA_PARL_TX 30 -#define PMU_ICG_FUNC_ENA_CAN0 31 +#define PMU_ICG_FUNC_ENA_TWAI1 30 +#define PMU_ICG_FUNC_ENA_TWAI0 31 diff --git a/components/soc/esp32h4/include/soc/retention_periph_defs.h b/components/soc/esp32h4/include/soc/retention_periph_defs.h index d58f6bd8f58..7ff5ad0d42b 100644 --- a/components/soc/esp32h4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h4/include/soc/retention_periph_defs.h @@ -56,6 +56,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_BLE_MAC = 30, SLEEP_RETENTION_MODULE_BT_BB = 31, SLEEP_RETENTION_MODULE_802154_MAC = 32, + SLEEP_RETENTION_MODULE_POWER = 33, SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 } periph_retention_module_t; diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 0bbb208e7a8..0d3d288b713 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -515,6 +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_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) diff --git a/components/soc/esp32h4/include/soc/system_periph_retention.h b/components/soc/esp32h4/include/soc/system_periph_retention.h index 8b6444b8f37..3b3a42c6759 100644 --- a/components/soc/esp32h4/include/soc/system_periph_retention.h +++ b/components/soc/esp32h4/include/soc/system_periph_retention.h @@ -54,7 +54,7 @@ extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH * This is an internal function of the sleep retention driver, and is not * useful for external use. */ -#define IOMUX_RETENTION_LINK_LEN 7 +#define IOMUX_RETENTION_LINK_LEN 6 extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN]; /** diff --git a/components/soc/esp32h4/system_retention_periph.c b/components/soc/esp32h4/system_retention_periph.c index fb2934c48ee..729477fd8ec 100644 --- a/components/soc/esp32h4/system_retention_periph.c +++ b/components/soc/esp32h4/system_retention_periph.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 OR MIT */ @@ -19,10 +19,10 @@ #include "soc/clic_reg.h" /* Interrupt Matrix Registers Context */ -#define N_REGS_INTR_MATRIX(i) (((INTERRUPT_CORE0_CLOCK_GATE_REG(i) - (DR_REG_INTERRUPT_CORE0_BASE + (i) * 0x1000)) / 4) + 1) +#define N_REGS_INTR_MATRIX(i) (((INTERRUPT_CORE0_CLOCK_GATE_REG(i) - INTERRUPT_CORE0_BT_MAC_INTR_MAP_REG(i)) / 4) + 1) const regdma_entries_config_t intr_matrix_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0), DR_REG_INTERRUPT_CORE0_BASE, DR_REG_INTERRUPT_CORE0_BASE, N_REGS_INTR_MATRIX(0), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* intr matrix */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(1), DR_REG_INTERRUPT_CORE1_BASE, DR_REG_INTERRUPT_CORE1_BASE, N_REGS_INTR_MATRIX(1), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* intr matrix */ + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0), INTERRUPT_CORE0_BT_MAC_INTR_MAP_REG(0), INTERRUPT_CORE0_BT_MAC_INTR_MAP_REG(0), N_REGS_INTR_MATRIX(0), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* intr matrix */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(1), INTERRUPT_CORE0_BT_MAC_INTR_MAP_REG(1), INTERRUPT_CORE0_BT_MAC_INTR_MAP_REG(1), N_REGS_INTR_MATRIX(1), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* intr matrix */ }; _Static_assert(ARRAY_SIZE(intr_matrix_regs_retention) == INT_MTX_RETENTION_LINK_LEN, "Inconsistent INT_MTX retention link length definitions"); @@ -51,19 +51,53 @@ const regdma_entries_config_t tee_apm_highpri_regs_retention[] = { _Static_assert((ARRAY_SIZE(tee_apm_regs_retention) == TEE_APM_RETENTION_LINK_LEN) && (ARRAY_SIZE(tee_apm_highpri_regs_retention) == TEE_APM_HIGH_PRI_RETENTION_LINK_LEN), "Inconsistent TEE_APM retention link length definitions"); /* IO MUX Registers Context */ -#define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_U_PAD_GPIO39 - REG_IO_MUX_BASE) / 4) + 1) -#define N_REGS_IOMUX_1() (((GPIO_FUNC39_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1) -#define N_REGS_IOMUX_2() (((GPIO_FUNC189_IN_SEL_CFG_REG - GPIO_FUNC0_IN_SEL_CFG_REG) / 4) + 1) -#define N_REGS_IOMUX_3() (((GPIO_PIN39_REG - GPIO_PIN0_REG) / 4) + 1) -#define N_REGS_IOMUX_4() (((GPIO_STATUS1_REG - GPIO_OUT_REG) / 4) + 1) +#define N_REGS_IOMUX_0() (SOC_GPIO_PIN_COUNT) +#define N_REGS_IOMUX_1() (SOC_GPIO_PIN_COUNT) +#define N_REGS_IOMUX_2() (SOC_GPIO_PIN_COUNT) + +/* + * (1) Backup 87 x FUNCx_IN_SEL_CFG from GPIO_FUNC0_IN_SEL_CFG_REG (FUNC0, FUNC8..FUNC19, FUNC29..FUNC37, FUNC43..FUNC47, FUNC49..FUNC69, FUNC75..FUNC93, FUNC97..FUNC100, FUNC102..FUNC117). + * Restore 87 x FUNCx_IN_SEL_CFG from GPIO_FUNC0_IN_SEL_CFG_REG (FUNC0, FUNC8..FUNC19, FUNC29..FUNC37, FUNC43..FUNC47, FUNC49..FUNC69, FUNC75..FUNC93, FUNC97..FUNC100, FUNC102..FUNC117). + */ +#define GPIO_IN_SEL_CFG_RETENTION_REGS_CNT0 87 +#define GPIO_IN_SEL_CFG_RETENTION_MAP_BASE0 GPIO_FUNC0_IN_SEL_CFG_REG +static const uint32_t gpio_in_sel_cfg_regs_map0[4] = {0xE00FFF01, 0xFFFEF83F, 0x3FFFF83F, 0x003FFFDE}; + +/* + * (2) Backup 25 x FUNCx_IN_SEL_CFG from GPIO_FUNC155_IN_SEL_CFG_REG (FUNC155..FUNC171, FUNC182..FUNC189). + * Restore 25 x FUNCx_IN_SEL_CFG from GPIO_FUNC155_IN_SEL_CFG_REG (FUNC155..FUNC171, FUNC182..FUNC189). + * gpio_in_sel_cfg_regs_map1 = 128-bit retention mask for this slice. + */ +#define GPIO_IN_SEL_CFG_RETENTION_REGS_CNT1 25 +#define GPIO_IN_SEL_CFG_RETENTION_MAP_BASE1 GPIO_FUNC155_IN_SEL_CFG_REG +static const uint32_t gpio_in_sel_cfg_regs_map1[4] = {0xF801FFFF, 0x00000007, 0x0, 0x0}; + +/* + * (3) Backup 6 words from GPIO_OUT_REG, GPIO_OUT1_REG, GPIO_ENABLE_REG, GPIO_ENABLE1_REG, GPIO_STATUS_REG, GPIO_STATUS_REG(GPIO0-31 and GPIO32-43). + * Restore 6 words from GPIO_OUT_W1TS_REG, GPIO_OUT1_W1TS_REG, GPIO_ENABLE_W1TS_REG, GPIO_ENABLE1_W1TS_REG, GPIO_STATUS_W1TS_REG, GPIO_STATUS1_W1TS_REG. + */ +#define GPIO_RETENTION_REGS_CNT 6 +#define GPIO_BACKUP_MAP_BASE GPIO_OUT_REG +#define GPIO_RETENTION_MAP_BASE GPIO_OUT_W1TS_REG +static const uint32_t gpio_regs_map[4] = {0x90009009, 0x0, 0x0, 0x0}; + const regdma_entries_config_t iomux_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* io_mux */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_FUNC0_IN_SEL_CFG_REG, GPIO_FUNC0_IN_SEL_CFG_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), GPIO_PIN0_REG, GPIO_PIN0_REG, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_OUT_REG, GPIO_OUT_W1TS_REG, N_REGS_IOMUX_4(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_ENABLE_REG, GPIO_ENABLE_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x06), GPIO_ENABLE1_REG, GPIO_ENABLE1_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), IO_MUX_GPIO0_REG, IO_MUX_GPIO0_REG, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* io_mux */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_PIN0_REG, GPIO_PIN0_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + + [3] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_IOMUX_LINK(0x03), GPIO_IN_SEL_CFG_RETENTION_MAP_BASE0, GPIO_IN_SEL_CFG_RETENTION_MAP_BASE0, GPIO_IN_SEL_CFG_RETENTION_REGS_CNT0, 0, 0, + gpio_in_sel_cfg_regs_map0[0], gpio_in_sel_cfg_regs_map0[1], gpio_in_sel_cfg_regs_map0[2], gpio_in_sel_cfg_regs_map0[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [4] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_IN_SEL_CFG_RETENTION_MAP_BASE1, GPIO_IN_SEL_CFG_RETENTION_MAP_BASE1, GPIO_IN_SEL_CFG_RETENTION_REGS_CNT1, 0, 0, + gpio_in_sel_cfg_regs_map1[0], gpio_in_sel_cfg_regs_map1[1], gpio_in_sel_cfg_regs_map1[2], gpio_in_sel_cfg_regs_map1[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [5] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_BACKUP_MAP_BASE, GPIO_RETENTION_MAP_BASE, GPIO_RETENTION_REGS_CNT, 0, 0, + gpio_regs_map[0], gpio_regs_map[1], gpio_regs_map[2], gpio_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + } }; _Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions"); diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index 471959ca104..6f0da9db1a7 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -68,7 +68,7 @@ extern "C" { #define REGDMA_JPEG_LINK(_pri) ((0x28 << 8) | _pri) #define REGDMA_LCDCAM_LINK(_pri) ((0x29 << 8) | _pri) #define REGDMA_H264_LINK(_pri) ((0x2a << 8) | _pri) - +#define REGDMA_POWER_LINK(_pri) ((0xFD << 8) | _pri) #define REGDMA_CLOCK_ICG_LINK(_pri) ((0xFE << 8) | _pri) #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) @@ -79,6 +79,7 @@ extern "C" { #define REGDMA_LINK_PRI_WIFI_MAC_BB REGDMA_LINK_PRI_3 #define REGDMA_LINK_PRI_NON_CRITICAL_TEE_APM REGDMA_LINK_PRI_4 #define REGDMA_LINK_PRI_BT_MAC_BB REGDMA_LINK_PRI_5 +#define REGDMA_LINK_PRI_POWER REGDMA_LINK_PRI_5 #define REGDMA_LINK_PRI_SYS_PERIPH_HIGH REGDMA_LINK_PRI_5 // INT_MTX & HP_SYSTEM & Console UART #define REGDMA_LINK_PRI_SYS_PERIPH_LOW REGDMA_LINK_PRI_6 // TG0 & IO MUX & SPI MEM & Systimer #define REGDMA_LINK_PRI_GENERAL_PERIPH REGDMA_LINK_PRI_7 // Low retenion priority for general peripherals