From 520f9ec6a50f3414f09a585104de61e770f98a8e Mon Sep 17 00:00:00 2001 From: cjin Date: Thu, 6 Nov 2025 15:56:32 +0800 Subject: [PATCH] feat(phy): add skip list to sleep phy link context and fix deinit crash --- .../include/esp_private/sleep_modem.h | 10 ++-- .../lowpower/port/esp32c6/sleep_phy.c | 58 +++++++++---------- components/esp_phy/Kconfig | 6 ++ components/esp_phy/include/esp_phy_init.h | 1 + components/esp_phy/src/phy_init.c | 26 ++++++--- 5 files changed, 58 insertions(+), 43 deletions(-) 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 ca95a3a197c..5467407ab4f 100644 --- a/components/esp_hw_support/include/esp_private/sleep_modem.h +++ b/components/esp_hw_support/include/esp_private/sleep_modem.h @@ -96,7 +96,7 @@ void sleep_modem_mac_bb_power_up_prepare(void); * * @param restore true for restore the PHY context, false for backup the PHY context */ -void sleep_modem_do_phy_retention(bool restore); +void sleep_modem_do_phy_retention(bool restore, uint8_t flags); /** * @brief Get phy link state @@ -253,24 +253,24 @@ bool sleep_modem_wifi_modem_state_skip_light_sleep(void); /** * @brief Function to initialize and create the phy link - * @param link_head the pointer that point to the head of the created phy link + * @param link_context PHY link regdma description conteoxt pointer * @return * - ESP_OK on success * - ESP_ERR_NO_MEM if no memory for link * - ESP_ERR_INVALID_ARG if value is out of range * - ESP_ERR_INVALID_STATE if the phy module retention state is invalid */ -esp_err_t sleep_phy_link_init(void **link_head); +esp_err_t sleep_phy_link_init(void **link_context); /** * @brief Function to destroy and de-initialize phy link - * @param link_head the phy link head will be destroyed + * @param link_context PHY link regdma description conteoxt pointer * @return * - ESP_OK on success * - ESP_ERR_INVALID_ARG if value is out of range * - ESP_ERR_INVALID_STATE if the phy module retention state is invalid */ -esp_err_t sleep_phy_link_deinit(void *link_head); +esp_err_t sleep_phy_link_deinit(void *link_context); /** * @brief Function to configure PHY link regdma description at runtime diff --git a/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c index c0c15bb6594..1160f799169 100644 --- a/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c @@ -39,19 +39,15 @@ typedef struct { #define DESC_IDX_I2C_MST_ENA (0) #define DESC_IDX_I2C_MST_SEL (1) #define DESC_IDX_I2C_MST_DIS (2) - void *regdma_desc[DESC_IDX_I2C_MST_DIS + 1]; +#define DESC_IDX_SKIP_WIFI (3) +#define DESC_SKIP_WIFI_ENTRY_CNT (8) +#define DESC_SKIP_WIFI_RESTORE_ENTRY_CNT (1) + void *regdma_desc[DESC_IDX_I2C_MST_DIS + 1 + DESC_SKIP_WIFI_ENTRY_CNT]; } sleep_phy_link_context_t; -static DRAM_ATTR struct{ - void *skip_link[8]; -} s_phy_skip_links; -esp_err_t sleep_phy_link_init(void **link_head) +esp_err_t sleep_phy_link_init(void **link_context) { esp_err_t err = ESP_OK; - const int skip_idx_list[] = { - REGDMA_PHY_LINK(0x10), REGDMA_PHY_LINK(0x1c), REGDMA_PHY_LINK(0x1d), REGDMA_PHY_LINK(0x1e), REGDMA_PHY_LINK(0x1f), - REGDMA_PHY_LINK(0x20), REGDMA_PHY_LINK(0x21), REGDMA_PHY_LINK(0x22) - }; #if SOC_PM_PAU_REGDMA_LINK_MODEM static regdma_link_config_t phy_modem_config[] = { @@ -111,18 +107,10 @@ esp_err_t sleep_phy_link_init(void **link_head) phy_modem_config[22].write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false); void *link = NULL; - uint8_t skip_idx = 0; for (int i = ARRAY_SIZE(phy_modem_config) - 1; (err == ESP_OK) && (i >= 0); i--) { void *next = regdma_link_init_safe(&phy_modem_config[i], false, 0, link); if (next) { link = next; - for (int idx = 0; idx < ARRAY_SIZE(skip_idx_list); idx ++) { - if (skip_idx_list[idx] == phy_modem_config[i].id) { - s_phy_skip_links.skip_link[skip_idx] = next; - skip_idx ++; - break; - } - } } else { regdma_link_destroy(link, 0); err = ESP_ERR_NO_MEM; @@ -131,7 +119,10 @@ esp_err_t sleep_phy_link_init(void **link_head) if (err == ESP_OK) { pau_regdma_set_modem_link_addr(link); - const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x01), REGDMA_PHY_LINK(0x1b) }; + const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x01), REGDMA_PHY_LINK(0x1b), /* I2C MST CLK entries */ + REGDMA_PHY_LINK(0x10), REGDMA_PHY_LINK(0x1c), REGDMA_PHY_LINK(0x1d), REGDMA_PHY_LINK(0x1e), + REGDMA_PHY_LINK(0x1f), REGDMA_PHY_LINK(0x20), REGDMA_PHY_LINK(0x21), REGDMA_PHY_LINK(0x22) /* WiFi Related entries */ + }; static DRAM_ATTR sleep_phy_link_context_t phy_link_context; for (int i = 0; (err == ESP_OK) && (i < ARRAY_SIZE(phy_link_context.regdma_desc)); i++) { @@ -144,7 +135,9 @@ esp_err_t sleep_phy_link_init(void **link_head) } if (err == ESP_OK) { phy_link_context.link_head = link; - *link_head = (void *)&phy_link_context; + *link_context = (void *)&phy_link_context; + } else { + regdma_link_destroy(link, 0); } } #endif @@ -155,7 +148,7 @@ void IRAM_ATTR sleep_phy_link_config(void *link_context, uint32_t flags) { sleep_phy_link_context_t *phy_link_context = (sleep_phy_link_context_t *)link_context; - if (flags & BIT(0)) { + if (flags & SLEEP_MODEM_SKIP_I2C_MST_CLK_RETENTION) { regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, true); regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_SEL], true, true); regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], true, true); @@ -164,20 +157,27 @@ void IRAM_ATTR sleep_phy_link_config(void *link_context, uint32_t flags) regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_SEL], true, false); regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], false, true); } + + if (flags & SLEEP_MODEM_SKIP_WIFI_RETENTION) { + for (int i = 0; i < DESC_SKIP_WIFI_ENTRY_CNT; i++) { + regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_SKIP_WIFI + i], true, true); + } + } else { + for (int i = 0; i < DESC_SKIP_WIFI_ENTRY_CNT; i++) { + if (i < DESC_SKIP_WIFI_RESTORE_ENTRY_CNT) { + regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_SKIP_WIFI + i], true, false); + } else { + regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_SKIP_WIFI + i], false, true); + } + } + } } -esp_err_t sleep_phy_link_deinit(void *link_head) +esp_err_t sleep_phy_link_deinit(void *link_context) { #if SOC_PM_PAU_REGDMA_LINK_MODEM - regdma_link_destroy(((sleep_modem_state_phy_link_context_t *)link_head)->link_head, 0); + regdma_link_destroy(((sleep_phy_link_context_t *)link_context)->link_head, 0); #endif return ESP_OK; } - -void sleep_phy_skip_wifi_reg(bool skip) -{ - for (int i = 0; i < ARRAY_SIZE(s_phy_skip_links.skip_link); i++) { - regdma_link_set_skip_flag(s_phy_skip_links.skip_link[i], skip, skip); - } -} #endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */ diff --git a/components/esp_phy/Kconfig b/components/esp_phy/Kconfig index e51102d1da3..2e14e8f89c9 100644 --- a/components/esp_phy/Kconfig +++ b/components/esp_phy/Kconfig @@ -260,5 +260,11 @@ menu "PHY" help Select to print PHY version in esp_phy_enable. This config only applies to esp32hxx for now. + config ESP_PHY_HW_SWITCH_RF + bool "Enable Hardware Triggered RF Switch" + depends on SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY + default n + help + Enabling this feature will allow PHY disable and enable using REGDMA. endif endmenu # PHY diff --git a/components/esp_phy/include/esp_phy_init.h b/components/esp_phy/include/esp_phy_init.h index 90272ace236..031c1aeec0a 100644 --- a/components/esp_phy/include/esp_phy_init.h +++ b/components/esp_phy/include/esp_phy_init.h @@ -212,6 +212,7 @@ void esp_phy_modem_init(uint8_t modem); * @param modem Modem calling phy retention */ void esp_phy_modem_deinit(uint8_t modem); + #if CONFIG_MAC_BB_PD /** * @brief Initialize backup memory for MAC and Baseband power up/down diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index 0ed688dbb82..9d29d2a9c2c 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -95,7 +95,7 @@ static bool s_is_phy_reg_stored = false; /* Memory to store PHY digital registers */ static uint32_t* s_phy_digital_regs_mem = NULL; #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA -#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP || CONFIG_ESP_PHY_HW_SWITCH_RF static uint8_t s_phy_modem_init_ref = 0; #endif @@ -338,7 +338,11 @@ void esp_phy_enable(esp_phy_modem_t modem) if (!pm_mac_modem_rf_already_enabled()) { #endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP */ if (sleep_modem_phy_link_enabled() && sleep_modem_phy_link_done()) { - sleep_modem_do_phy_retention(true); + uint8_t modem_flags = SLEEP_MODEM_SKIP_I2C_MST_CLK_RETENTION; + if (!sleep_modem_wifi_modem_state_is_enabled()) { + modem_flags |= SLEEP_MODEM_SKIP_WIFI_RETENTION; + } + sleep_modem_do_phy_retention(true, modem_flags); } else { phy_wakeup_init(); } @@ -409,7 +413,11 @@ void esp_phy_disable(esp_phy_modem_t modem) pm_mac_modem_clear_rf_power_state(); #endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP */ if (sleep_modem_phy_link_enabled()) { - sleep_modem_do_phy_retention(false); + uint8_t modem_flags = SLEEP_MODEM_SKIP_I2C_MST_CLK_RETENTION; + if (!sleep_modem_wifi_modem_state_is_enabled()) { + modem_flags |= SLEEP_MODEM_SKIP_WIFI_RETENTION; + } + sleep_modem_do_phy_retention(false, modem_flags); } else #endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */ { @@ -478,7 +486,7 @@ void esp_wifi_bt_power_domain_off(void) void esp_phy_modem_init(uint8_t modem) { -#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP || CONFIG_ESP_PHY_HW_SWITCH_RF _lock_acquire(&s_phy_access_lock); s_phy_modem_init_ref++; #if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA @@ -486,16 +494,16 @@ void esp_phy_modem_init(uint8_t modem) s_phy_digital_regs_mem = (uint32_t *)heap_caps_malloc(SOC_PHY_DIG_REGS_MEM_SIZE, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL); } #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA -#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP +#if (SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP) || CONFIG_ESP_PHY_HW_SWITCH_RF sleep_modem_phy_init(modem); -#endif // CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP +#endif // (SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP) || CONFIG_ESP_PHY_HW_SWITCH_RF _lock_release(&s_phy_access_lock); #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP } void esp_phy_modem_deinit(uint8_t modem) { -#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP || CONFIG_ESP_PHY_HW_SWITCH_RF _lock_acquire(&s_phy_access_lock); if (s_phy_modem_init_ref == 0) { @@ -516,9 +524,9 @@ void esp_phy_modem_deinit(uint8_t modem) #endif // CONFIG_IDF_TARGET_ESP32C3 #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA } -#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP +#if (SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP) || CONFIG_ESP_PHY_HW_SWITCH_RF sleep_modem_phy_deinit(modem); -#endif // SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP +#endif // (SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP) || CONFIG_ESP_PHY_HW_SWITCH_RF _lock_release(&s_phy_access_lock); #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP }