diff --git a/components/esp_hal_pmu/esp32h4/include/hal/pau_etm_ll.h b/components/esp_hal_pmu/esp32h4/include/hal/pau_etm_ll.h new file mode 100644 index 00000000000..b2a5e282064 --- /dev/null +++ b/components/esp_hal_pmu/esp32h4/include/hal/pau_etm_ll.h @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "soc/soc.h" +#include "soc/soc_etm_struct.h" +#include "soc/soc_etm_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline bool pau_etm_ll_get_regdma_event_done_status(int index) +{ + return SOC_ETM.etm_evt_st4.val & (SOC_ETM_REGDMA_EVT_DONE0_ST << index); +} + +static inline bool pau_etm_ll_get_regdma_event_err_status(int index) +{ + return SOC_ETM.etm_evt_st4.val & (SOC_ETM_REGDMA_EVT_ERR0_ST << index); +} + +static inline bool pau_etm_ll_get_regdma_task_start_status(int index) +{ + return SOC_ETM.etm_task_st4.val & (SOC_ETM_REGDMA_TASK_START0_ST << index); +} + +static inline void pau_etm_ll_clear_regdma_event_done_status(int index) +{ + SOC_ETM.etm_evt_st4_clr.val = SOC_ETM_REGDMA_EVT_DONE0_ST << index; +} + +static inline void pau_etm_ll_clear_regdma_event_err_status(int index) +{ + SOC_ETM.etm_evt_st4_clr.val = SOC_ETM_REGDMA_EVT_ERR0_ST << index; +} + +static inline void pau_etm_ll_clear_regdma_task_start_status(int index) +{ + SOC_ETM.etm_task_st4_clr.val = SOC_ETM_REGDMA_TASK_START0_ST << index; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_pmu/esp32h4/pau_hal.c b/components/esp_hal_pmu/esp32h4/pau_hal.c index b989c6fe5dd..b0f9266df7e 100644 --- a/components/esp_hal_pmu/esp32h4/pau_hal.c +++ b/components/esp_hal_pmu/esp32h4/pau_hal.c @@ -11,6 +11,7 @@ #include "hal/pau_hal.h" #include "hal/pau_types.h" #include "hal/lp_aon_ll.h" +#include "hal/pau_etm_ll.h" void pau_hal_set_regdma_entry_link_addr(pau_hal_context_t *hal, pau_regdma_link_addr_t *link_addr) { @@ -103,3 +104,13 @@ void IRAM_ATTR pau_hal_stop_etm_modem_link(pau_hal_context_t *hal) pau_ll_select_regdma_etm_entry_link0(hal->dev, 0); /* restore link select to default */ pau_ll_clear_regdma_backup_done_intr_state(hal->dev); } + +bool IRAM_ATTR pau_hal_check_etm_task_triggered(pau_hal_context_t *hal, uint8_t index) +{ + return pau_etm_ll_get_regdma_task_start_status(index); +} + +void IRAM_ATTR pau_hal_clear_etm_task_triggered(pau_hal_context_t *hal, uint8_t index) +{ + pau_etm_ll_clear_regdma_task_start_status(index); +} diff --git a/components/esp_hal_pmu/include/hal/pau_hal.h b/components/esp_hal_pmu/include/hal/pau_hal.h index eced82f2279..235899dfe90 100644 --- a/components/esp_hal_pmu/include/hal/pau_hal.h +++ b/components/esp_hal_pmu/include/hal/pau_hal.h @@ -227,6 +227,22 @@ void pau_hal_set_etm_modem_link_config(pau_hal_context_t *hal); * @param hal regdma hal context */ void pau_hal_stop_etm_modem_link(pau_hal_context_t *hal); + +/** + * @brief Check if the ETM task is triggered + * + * @param hal regdma hal context + * @param index the index of the ETM task + */ +bool pau_hal_check_etm_task_triggered(pau_hal_context_t *hal, uint8_t index); + +/** + * @brief Clear the ETM task triggered status + * + * @param hal regdma hal context + * @param index the index of the ETM task + */ +void pau_hal_clear_etm_task_triggered(pau_hal_context_t *hal, uint8_t index); #endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY #endif diff --git a/components/esp_hw_support/include/esp_private/esp_pau.h b/components/esp_hw_support/include/esp_private/esp_pau.h index ac6b456a8b3..7112fe0cf0d 100644 --- a/components/esp_hw_support/include/esp_private/esp_pau.h +++ b/components/esp_hw_support/include/esp_private/esp_pau.h @@ -161,7 +161,20 @@ void pau_regdma_unregister_modem_link_protect(void); /** * @brief Wait for REGDMA to complete */ -void pau_regdma_wait_done(void); +void pau_regdma_wait_work_done(void); + +/** + * @brief Check if the REGDMA task is triggered + * @param index the index of the task + * @return true if the task is triggered, false otherwise + */ +bool pau_regdma_check_etm_task_triggered(uint8_t index); + +/** + * @brief Clear the REGDMA task triggered status + * @param index the index of the task + */ +void pau_regdma_clear_etm_task_triggered(uint8_t index); /** * @brief Set the configuration of the REGDMA etm modem link diff --git a/components/esp_hw_support/include/esp_private/sleep_modem.h b/components/esp_hw_support/include/esp_private/sleep_modem.h index 2430d3f9ce6..1f5d614faf1 100644 --- a/components/esp_hw_support/include/esp_private/sleep_modem.h +++ b/components/esp_hw_support/include/esp_private/sleep_modem.h @@ -285,6 +285,7 @@ esp_err_t sleep_phy_link_deinit(void *link_context); * @param flags A bitmap to indicate the PHY link regdma description configuration flag */ void sleep_phy_link_config(void *link_context, uint32_t flags); + #endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */ #ifdef __cplusplus diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_phy.c index 3b25380f226..2ea1baf1e69 100644 --- a/components/esp_hw_support/lowpower/port/esp32h4/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_phy.c @@ -41,12 +41,11 @@ typedef struct { #define DESC_MODEM_SYSCON_CLK_DIS (3) void *regdma_desc[DESC_MODEM_SYSCON_CLK_DIS + 1]; } sleep_phy_link_context_t; - #define SYSCON_FE_CLOCK_MSK (MODEM_SYSCON_CLK_FE_APB_EN|MODEM_SYSCON_CLK_FE_32M_EN|MODEM_SYSCON_CLK_FE_SDM_EN|MODEM_SYSCON_CLK_FE_ADC_EN|MODEM_SYSCON_CLK_FE_16M_EN|MODEM_SYSCON_CLK_FE_TXLOGAIN_EN) esp_err_t sleep_phy_retention_init(void *args) { #define PHY_ENTRY() (BIT(SOC_PM_PAU_REGDMA_LINK_IDX_PHY)) - static sleep_retention_entries_config_t phy_modem_config[] = { + static const sleep_retention_entries_config_t phy_modem_config_template[] = { /* Open modem clock for PHY */ [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x00), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = PHY_ENTRY() }, /* I2C MST enable */ [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x01), MODEM_SYSCON_CLK_CONF1_REG, SYSCON_FE_CLOCK_MSK, SYSCON_FE_CLOCK_MSK, 1, 0), .owner = PHY_ENTRY() }, /* FE clock */ @@ -84,10 +83,16 @@ esp_err_t sleep_phy_retention_init(void *args) [27] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x1b), PMU_SLP_WAKEUP_CNTL7_REG, 0x200000, 0xffff0000, 1, 0), .owner = PHY_ENTRY() }, [28] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x1c), PMU_SLP_WAKEUP_CNTL7_REG, 0x9730000, 0xffff0000, 0, 1), .owner = PHY_ENTRY() }, }; + sleep_retention_entries_config_t *phy_modem_config = malloc(sizeof(phy_modem_config_template)); + if (phy_modem_config == NULL) { + return ESP_ERR_NO_MEM; + } + memcpy(phy_modem_config, phy_modem_config_template, sizeof(phy_modem_config_template)); extern uint32_t phy_ana_i2c_master_burst_rf_onoff(bool on); phy_modem_config[0x0a].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(true); phy_modem_config[0x13].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false); - esp_err_t err = sleep_retention_entries_create(phy_modem_config, ARRAY_SIZE(phy_modem_config), 7, SLEEP_RETENTION_MODULE_MODEM_PHY); + esp_err_t err = sleep_retention_entries_create(phy_modem_config, ARRAY_SIZE(phy_modem_config_template), 5, SLEEP_RETENTION_MODULE_MODEM_PHY); + free(phy_modem_config); ESP_RETURN_ON_ERROR(err, TAG, "failed to init modem phy link"); return err; } diff --git a/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c index 115bd8493f2..58106763f5e 100644 --- a/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c @@ -99,7 +99,7 @@ static esp_err_t sleep_phy_retention_init(void *arg) extern uint32_t phy_ana_i2c_master_burst_rf_onoff(bool on); phy_modem_config[4].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(true); phy_modem_config[15].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false); - esp_err_t err = sleep_retention_entries_create(phy_modem_config, ARRAY_SIZE(phy_modem_config_template), 7, SLEEP_RETENTION_MODULE_MODEM_PHY); + esp_err_t err = sleep_retention_entries_create(phy_modem_config, ARRAY_SIZE(phy_modem_config_template), 5, SLEEP_RETENTION_MODULE_MODEM_PHY); free(phy_modem_config); ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate modem phy link"); return ESP_OK; diff --git a/components/esp_hw_support/port/pau_regdma.c b/components/esp_hw_support/port/pau_regdma.c index 0db2684e3c4..44106206f11 100644 --- a/components/esp_hw_support/port/pau_regdma.c +++ b/components/esp_hw_support/port/pau_regdma.c @@ -246,8 +246,18 @@ void IRAM_ATTR pau_regdma_stop_etm_modem_link(void) pau_hal_stop_etm_modem_link(PAU_instance()->hal); } -void IRAM_ATTR pau_regdma_wait_done(void) +void IRAM_ATTR pau_regdma_wait_work_done(void) { pau_hal_regdma_wait_done(PAU_instance()->hal); } + +bool IRAM_ATTR pau_regdma_check_etm_task_triggered(uint8_t index) +{ + return pau_hal_check_etm_task_triggered(PAU_instance()->hal, index); +} + +void IRAM_ATTR pau_regdma_clear_etm_task_triggered(uint8_t index) +{ + pau_hal_clear_etm_task_triggered(PAU_instance()->hal, index); +} #endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c index f7c19fac44d..782b0d0d4ff 100644 --- a/components/esp_hw_support/sleep_modem.c +++ b/components/esp_hw_support/sleep_modem.c @@ -219,7 +219,6 @@ inline __attribute__((always_inline)) bool sleep_modem_phy_link_done(void) { return (s_sleep_modem.phy_link_done == 1); } - #endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */ bool modem_domain_pd_allowed(void) @@ -257,21 +256,21 @@ bool modem_domain_pd_allowed(void) uint32_t sleep_modem_reject_triggers(void) { uint32_t reject_triggers = 0; -#if SOC_PM_SUPPORT_PMU_MODEM_STATE +#if SOC_PM_SUPPORT_PMU_MODEM_STATE && SOC_WIFI_SUPPORTED reject_triggers = sleep_modem_wifi_modem_state_is_enabled() ? PMU_MODEM_WAKEUP_PROTECT : 0; -#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */ +#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE && SOC_WIFI_SUPPORTED */ return reject_triggers; } bool IRAM_ATTR sleep_modem_wifi_modem_state_skip_light_sleep(void) { bool skip = false; -#if SOC_PM_SUPPORT_PMU_MODEM_STATE +#if SOC_PM_SUPPORT_PMU_MODEM_STATE && SOC_WIFI_SUPPORTED /* To block the system from entering sleep before modem link done. In light * sleep mode, the system may switch to modem state, which will cause * hardware to fail to enable RF */ skip = sleep_modem_wifi_modem_state_is_enabled() && !sleep_modem_phy_link_done(); -#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */ +#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE && SOC_WIFI_SUPPORTED */ return skip; }