From 09e86e9026daca86fbb1c22e920ad282cbe444da Mon Sep 17 00:00:00 2001 From: cjin Date: Tue, 18 Aug 2026 11:50:47 +0800 Subject: [PATCH] feat(phy): supported bt etm triggered rf --- components/esp_phy/include/esp_private/phy.h | 4 ++ components/esp_phy/src/phy_common.c | 24 +++++-- components/esp_phy/src/phy_init.c | 38 ++++------- components/esp_phy/src/phy_init_esp32hxx.c | 64 ++++++++++++++++++- .../esp32h4/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32h4/include/soc/soc_caps.h | 2 +- 6 files changed, 100 insertions(+), 34 deletions(-) diff --git a/components/esp_phy/include/esp_private/phy.h b/components/esp_phy/include/esp_private/phy.h index b08f0ede614..df9a800ee79 100644 --- a/components/esp_phy/include/esp_private/phy.h +++ b/components/esp_phy/include/esp_private/phy.h @@ -291,6 +291,10 @@ void esp_phy_sleep_data_deinit(void); */ void phy_wait_freq_hw_hop_done(void); +#if SOC_PM_REGDMA_MODEM_LINK_PROTECT +void phy_regi2c_lock_apply(bool enable); +#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT + #if CONFIG_ESP_PHY_PLL_TRACK_TEMP_DEBUG /** * @brief Set the temperature delta for PHY track pll diff --git a/components/esp_phy/src/phy_common.c b/components/esp_phy/src/phy_common.c index 8de60bae03b..3f2efccdd10 100644 --- a/components/esp_phy/src/phy_common.c +++ b/components/esp_phy/src/phy_common.c @@ -54,6 +54,10 @@ typedef struct { extern void phy_param_track_tot(bool en_wifi, bool en_ble_154); extern const phy_param_track_result_t* phy_debug_get_track_result(); +#if SOC_PM_REGDMA_MODEM_LINK_PROTECT +extern void phy_i2c_enter_critical(void); +extern void phy_i2c_exit_critical(void); +#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT static esp_timer_handle_t phy_track_pll_timer; #if CONFIG_ESP_WIFI_ENABLED @@ -376,12 +380,12 @@ typedef enum { static uint32_t phy_ana_i2c_master_burst_config(phy_i2c_master_command_attribute_t *attr, int size, phy_i2c_master_command_type_t type) { -#if !CONFIG_IDF_TARGET_ESP32H4 - #define I2C1_BURST_VAL(en, start, end) (((en) << 31) | ((end) << 22) | ((start) << 16)) - #define I2C0_BURST_VAL(en, start, end) (((en) << 15) | ((end) << 6) | ((start) << 0)) -#else +#if CONFIG_IDF_TARGET_ESP32H4 #define I2C0_BURST_VAL(valid, start, end) (((valid) << 15) | ((end) << 7) | (start)) #define I2C1_BURST_VAL(valid, start, end) (((valid) << 31) | ((end) << 23) | ((start) << 16)) +#else + #define I2C1_BURST_VAL(en, start, end) (((en) << 31) | ((end) << 22) | ((start) << 16)) + #define I2C0_BURST_VAL(en, start, end) (((en) << 15) | ((end) << 6) | ((start) << 0)) #endif // !CONFIG_IDF_TARGET_ESP32H4 uint32_t brust = 0; @@ -441,3 +445,15 @@ __attribute__((weak)) void phy_wait_freq_hw_hop_done(void) } return; } + + +#if SOC_PM_REGDMA_MODEM_LINK_PROTECT +void IRAM_ATTR phy_regi2c_lock_apply(bool enable) +{ + if (enable) { + phy_i2c_enter_critical(); + } else { + phy_i2c_exit_critical(); + } +} +#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index 1bdff3bbf37..f6794e07e8c 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -77,11 +77,6 @@ extern bool pm_get_wifimac_regdma_link_selection(void); #endif #endif -#if SOC_PM_REGDMA_MODEM_LINK_PROTECT -extern void phy_i2c_enter_critical(void); -extern void phy_i2c_exit_critical(void); -#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT - static const char* TAG = "phy_init"; static _lock_t s_phy_access_lock; @@ -315,16 +310,16 @@ void esp_phy_enable(esp_phy_modem_t modem) } bool wifimac_link_is_sel = false; #if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP && \ - SOC_PM_PAU_REGDMA_LINK_IDX_PHY && SOC_PM_PAU_REGDMA_MODEM_WIFIMAC_WORKAROUND +SOC_PM_PAU_REGDMA_LINK_IDX_PHY && SOC_PM_PAU_REGDMA_MODEM_WIFIMAC_WORKAROUND /* - * A race exists between SoC wakeup and modem state sleep. After modem initiates sleep, - * SoC may wake up before REGDMA completes RF close, leaving mac_modem_sleep_flag uncleared - * (it depends on regdma done). The stale flag can incorrectly trigger a sleep request - * on the next modem entry, causing abnormal sleep behavior. - * - * Therefore, this workaround ensures that mac_modem_sleep_flag is properly - * cleared by regdma closing RF with wifimac link. - * See WIFI-7246 for details. +* A race exists between SoC wakeup and modem state sleep. After modem initiates sleep, +* SoC may wake up before REGDMA completes RF close, leaving mac_modem_sleep_flag uncleared +* (it depends on regdma done). The stale flag can incorrectly trigger a sleep request +* on the next modem entry, causing abnormal sleep behavior. +* +* Therefore, this workaround ensures that mac_modem_sleep_flag is properly +* cleared by regdma closing RF with wifimac link. +* See WIFI-7246 for details. */ wifimac_link_is_sel = pm_get_wifimac_regdma_link_selection(); #endif @@ -402,7 +397,7 @@ void esp_phy_disable(esp_phy_modem_t modem) if (!sleep_modem_wifi_modem_state_is_enabled()) { modem_flags |= SLEEP_MODEM_SKIP_WIFI_RETENTION; } - bool wifimac_link_is_sel = false; + bool wifimac_link_is_sel = false; #if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP && \ SOC_PM_PAU_REGDMA_LINK_IDX_PHY && SOC_PM_PAU_REGDMA_MODEM_WIFIMAC_WORKAROUND wifimac_link_is_sel = pm_get_wifimac_regdma_link_selection(); @@ -474,17 +469,6 @@ void esp_wifi_bt_power_domain_off(void) #endif // SOC_PM_SUPPORT_MODEM_PD || SOC_PM_SUPPORT_WIFI_PD } -#if SOC_PM_REGDMA_MODEM_LINK_PROTECT -void IRAM_ATTR esp_phy_regi2c_lock_apply(bool enable) -{ - if (enable) { - phy_i2c_enter_critical(); - } else { - phy_i2c_exit_critical(); - } -} -#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT - void esp_phy_modem_init(uint8_t modem) { #if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP || CONFIG_ESP_PHY_HW_SWITCH_RF @@ -497,7 +481,7 @@ void esp_phy_modem_init(uint8_t modem) #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA #if (SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP) || CONFIG_ESP_PHY_HW_SWITCH_RF #if SOC_PM_REGDMA_MODEM_LINK_PROTECT - pau_regdma_register_modem_link_protect(esp_phy_regi2c_lock_apply); + pau_regdma_register_modem_link_protect(phy_regi2c_lock_apply); #endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT if (sleep_modem_phy_init(modem) != ESP_OK) { ESP_LOGE(TAG, "failed to initialize sleep modem phy"); diff --git a/components/esp_phy/src/phy_init_esp32hxx.c b/components/esp_phy/src/phy_init_esp32hxx.c index 6916ae0feb7..cdbe998e899 100644 --- a/components/esp_phy/src/phy_init_esp32hxx.c +++ b/components/esp_phy/src/phy_init_esp32hxx.c @@ -20,17 +20,32 @@ #if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY #include "esp_private/sleep_modem.h" #endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY +#if SOC_PM_REGDMA_MODEM_LINK_PROTECT +#include "esp_private/esp_pau.h" +#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT + #ifndef PHY_INIT_MODEM_CLOCK_REQUIRED_BITS #warning "PHY_INIT_MODEM_CLOCK_REQUIRED_BITS not defined; using default value 0" #define PHY_INIT_MODEM_CLOCK_REQUIRED_BITS 0 #endif +#if CONFIG_ESP_PHY_HW_SWITCH_RF static const char* TAG = "phy_init"; +#if SOC_PM_REGDMA_MODEM_LINK_PROTECT +static uint8_t s_phy_modem_init_ref = 0; +#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT +#endif // CONFIG_ESP_PHY_HW_SWITCH_RF + static DRAM_ATTR portMUX_TYPE s_phy_int_mux = portMUX_INITIALIZER_UNLOCKED; extern void phy_version_print(void); + +#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF +bool btdm_lp_check_phy_etm_task_triggered(void); +void btdm_lp_disable_etm_phy_retention_task(void); +#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF static _lock_t s_phy_access_lock; /* Reference count of enabling PHY */ @@ -58,10 +73,34 @@ void IRAM_ATTR phy_exit_critical(uint32_t level) } } +#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY +static bool phy_retention_link_is_triggered(void) +{ + bool ret = false; +#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF + if (btdm_lp_check_phy_etm_task_triggered()) { + return true; + } +#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF + + return ret; +} + +static void phy_disable_etm_phy_retention_link(void) +{ +#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF + btdm_lp_disable_etm_phy_retention_task(); +#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF +} +#endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY + void esp_phy_enable(esp_phy_modem_t modem) { _lock_acquire(&s_phy_access_lock); if (phy_get_modem_flag() == 0) { +#if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY + phy_disable_etm_phy_retention_link(); +#endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY #if SOC_MODEM_CLOCK_IS_INDEPENDENT modem_clock_module_enable(PERIPH_PHY_MODULE); #endif @@ -79,7 +118,15 @@ void esp_phy_enable(esp_phy_modem_t modem) } else { #if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY if (sleep_modem_phy_link_enabled() && sleep_modem_phy_link_done()) { - sleep_modem_do_phy_retention(true, false, SLEEP_MODEM_SKIP_I2C_MST_CLK_RETENTION); + if (!phy_retention_link_is_triggered()) { + sleep_modem_do_phy_retention(true, false, SLEEP_MODEM_SKIP_I2C_MST_CLK_RETENTION); + } +#if CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF + else { + pau_regdma_wait_work_done(); + pau_regdma_stop_etm_modem_link(); + } +#endif // CONFIG_BT_CTRL_SLEEP_ETM_TRIGGERED_RF } else #endif // SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY { @@ -141,6 +188,10 @@ void esp_phy_modem_init(uint8_t modem) { #if CONFIG_ESP_PHY_HW_SWITCH_RF _lock_acquire(&s_phy_access_lock); +#if SOC_PM_REGDMA_MODEM_LINK_PROTECT + s_phy_modem_init_ref++; + pau_regdma_register_modem_link_protect(phy_regi2c_lock_apply); +#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT if (sleep_modem_phy_init(modem) != ESP_OK) { ESP_LOGE(TAG, "failed to initialize sleep modem phy"); } @@ -152,6 +203,17 @@ void esp_phy_modem_deinit(uint8_t modem) { #if CONFIG_ESP_PHY_HW_SWITCH_RF _lock_acquire(&s_phy_access_lock); + +#if SOC_PM_REGDMA_MODEM_LINK_PROTECT + if (s_phy_modem_init_ref == 0) { + _lock_release(&s_phy_access_lock); + return; + } + s_phy_modem_init_ref--; + if (s_phy_modem_init_ref == 0) { + pau_regdma_unregister_modem_link_protect(); + } +#endif // SOC_PM_REGDMA_MODEM_LINK_PROTECT sleep_modem_phy_deinit(modem); _lock_release(&s_phy_access_lock); #endif // CONFIG_ESP_PHY_HW_SWITCH_RF diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index ea09bb393f4..7496b4a11ce 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -1203,7 +1203,7 @@ config SOC_PM_SUPPORT_PMU_MODEM_STATE bool default y -config SOC_PM_REGDMA_RF_RETENTION_REGI2C_CONFLICT +config SOC_PM_REGDMA_MODEM_LINK_PROTECT bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index c61e29530f3..62c88617f95 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -498,7 +498,7 @@ #define SOC_PM_SUPPORT_PMU_MODEM_STATE (1) // /* macro redefine for pass esp_wifi headers md5sum check */ // #define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE -#define SOC_PM_REGDMA_RF_RETENTION_REGI2C_CONFLICT (1) +#define SOC_PM_REGDMA_MODEM_LINK_PROTECT (1) #define SOC_PM_SUPPORT_PMU_CLK_ICG (1) #define SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG (1)