From a79519d8440849de74f578a78e02b73b70dc7a74 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 | 12 ++-- .../lowpower/port/esp32c5/sleep_phy.c | 64 +++++++++--------- .../lowpower/port/esp32c6/sleep_phy.c | 58 ++++++++--------- .../lowpower/port/esp32c61/sleep_phy.c | 65 +++++++++---------- .../lowpower/port/esp32s31/sleep_phy.c | 38 ++++++++--- components/esp_phy/Kconfig | 6 ++ components/esp_phy/include/esp_phy_init.h | 1 + components/esp_phy/src/phy_init.c | 34 ++++++---- 8 files changed, 157 insertions(+), 121 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 873295f7ae8..0f3a564b13b 100644 --- a/components/esp_hw_support/include/esp_private/sleep_modem.h +++ b/components/esp_hw_support/include/esp_private/sleep_modem.h @@ -95,9 +95,9 @@ void sleep_modem_mac_bb_power_up_prepare(void); * @brief The retention action in the modem state of PHY module * * @param restore true for restore the PHY context, false for backup the PHY context - * @param wifimac_link_is_sel true to trigger REGDMA via PHY link + * @param flags Configure flags for phy link */ -void sleep_modem_do_phy_retention(bool restore, bool wifimac_link_is_sel); +void sleep_modem_do_phy_retention(bool restore, bool wifimac_link_is_sel, uint8_t flags); /** * @brief Get phy link state @@ -254,24 +254,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/esp32c5/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_phy.c index 829ff294d8d..a3bd8d480f4 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_phy.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -37,24 +37,20 @@ ESP_LOG_ATTR_TAG(TAG, "sleep"); -static DRAM_ATTR struct{ - void *skip_link[4]; -} s_phy_skip_links; - #if SOC_PM_PAU_REGDMA_LINK_IDX_PHY typedef struct { #define DESC_IDX_I2C_MST_ENA (0) #define DESC_IDX_I2C_MST_DIS (1) - void *regdma_desc[DESC_IDX_I2C_MST_DIS + 1]; +#define DESC_IDX_SKIP_WIFI (2) +#define DESC_SKIP_WIFI_ENTRY_CNT (4) +#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 esp_err_t sleep_phy_retention_init(void *arg) { #define PHY_ENTRY() (BIT(SOC_PM_PAU_REGDMA_LINK_IDX_PHY)) - const int skip_idx_list[] = { - REGDMA_PHY_LINK(0x0b), REGDMA_PHY_LINK(0x15), REGDMA_PHY_LINK(0x16), REGDMA_PHY_LINK(0x17) - }; static sleep_retention_entries_config_t phy_modem_config[] = { [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 */ @@ -99,15 +95,11 @@ static esp_err_t sleep_phy_retention_init(void *arg) 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), 7, SLEEP_RETENTION_MODULE_MODEM_PHY); ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate modem phy link"); - for (int i = 0; i < ARRAY_SIZE(skip_idx_list); i++) { - s_phy_skip_links.skip_link[i] = sleep_retention_find_link_by_id(skip_idx_list[i]); - assert(s_phy_skip_links.skip_link[i] != NULL); - } return ESP_OK; } #endif -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; @@ -117,7 +109,9 @@ esp_err_t sleep_phy_link_init(void **link_head) if (err == ESP_OK) { err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_MODEM_PHY); if (err == ESP_OK) { - const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x14) }; + const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x14), /* I2C MST CLK entries */ + REGDMA_PHY_LINK(0x0b), REGDMA_PHY_LINK(0x15), REGDMA_PHY_LINK(0x16), REGDMA_PHY_LINK(0x17) /* 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++) { @@ -129,10 +123,13 @@ esp_err_t sleep_phy_link_init(void **link_head) } } if (err == ESP_OK) { - *link_head = (void *)&phy_link_context; + *link_context = (void *)&phy_link_context; } } } + if (err != ESP_OK) { + sleep_phy_link_deinit(NULL); + } #endif return err; } @@ -142,33 +139,36 @@ void IRAM_ATTR sleep_phy_link_config(void *link_context, uint32_t flags) #if SOC_PM_PAU_REGDMA_LINK_IDX_PHY 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_DIS], true, true); } else { regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], 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); + } + } + } #endif } -esp_err_t sleep_phy_link_deinit(void *link_head) +esp_err_t sleep_phy_link_deinit(void *link_context) { - esp_err_t err = ESP_OK; #if SOC_PM_PAU_REGDMA_LINK_IDX_PHY - err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_MODEM_PHY); - if (err == ESP_OK) { - sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_MODEM_PHY); - } + sleep_retention_module_free(SLEEP_RETENTION_MODULE_MODEM_PHY); + sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_MODEM_PHY); #endif - return err; + 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_hw_support/lowpower/port/esp32c6/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_phy.c index c229945c745..54cdba41f19 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_hw_support/lowpower/port/esp32c61/sleep_phy.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_phy.c index b63768f41dd..ddc7602542f 100644 --- a/components/esp_hw_support/lowpower/port/esp32c61/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_phy.c @@ -36,19 +36,15 @@ typedef struct { void *link_head; #define DESC_IDX_I2C_MST_ENA (0) #define DESC_IDX_I2C_MST_DIS (1) - void *regdma_desc[DESC_IDX_I2C_MST_DIS + 1]; +#define DESC_IDX_SKIP_WIFI (2) +#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(0x0f), REGDMA_PHY_LINK(0x1b), REGDMA_PHY_LINK(0x1c), REGDMA_PHY_LINK(0x1d), REGDMA_PHY_LINK(0x1e), - REGDMA_PHY_LINK(0x1f), REGDMA_PHY_LINK(0x20), REGDMA_PHY_LINK(0x21), - }; #if SOC_PM_PAU_REGDMA_LINK_MODEM static regdma_link_config_t phy_modem_config[] = { @@ -106,17 +102,9 @@ esp_err_t sleep_phy_link_init(void **link_head) phy_modem_config[19].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) { - 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; - } - } link = next; } else { regdma_link_destroy(link, 0); @@ -126,7 +114,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(0x1a) }; + const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x1a), /* I2C MST CLK entries */ + REGDMA_PHY_LINK(0x0f), REGDMA_PHY_LINK(0x1b), REGDMA_PHY_LINK(0x1c), REGDMA_PHY_LINK(0x1d), + REGDMA_PHY_LINK(0x1e), REGDMA_PHY_LINK(0x1f), REGDMA_PHY_LINK(0x20), REGDMA_PHY_LINK(0x21) /* 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++) { @@ -139,7 +130,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 @@ -150,28 +143,34 @@ 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_DIS], true, true); } else { regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], true, false); regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], false, true); } -} -esp_err_t sleep_phy_link_deinit(void *link_head) -{ -#if SOC_PM_PAU_REGDMA_LINK_MODEM - regdma_link_destroy(((sleep_modem_state_phy_link_context_t *)link_head)->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); + 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_context) +{ +#if SOC_PM_PAU_REGDMA_LINK_MODEM + regdma_link_destroy(((sleep_phy_link_context_t *)link_context)->link_head, 0); +#endif + return ESP_OK; +} #endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */ 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 afe078ed07f..1ab483b9103 100644 --- a/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c +++ b/components/esp_hw_support/lowpower/port/esp32s31/sleep_phy.c @@ -40,7 +40,11 @@ static __attribute__((unused)) const char *TAG = "sleep"; typedef struct { #define DESC_IDX_I2C_MST_ENA (0) #define DESC_IDX_I2C_MST_DIS (1) - void *regdma_desc[DESC_IDX_I2C_MST_DIS + 1]; +#define DESC_IDX_SKIP_WIFI (2) +#define DESC_SKIP_WIFI_ENTRY_CNT (4) +#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 esp_err_t sleep_phy_retention_init(void *arg) @@ -104,7 +108,9 @@ esp_err_t sleep_phy_link_init(void **link_head) if (err == ESP_OK) { err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_MODEM_PHY); if (err == ESP_OK) { - const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x14) }; + const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x14), + REGDMA_PHY_LINK(0x0b), REGDMA_PHY_LINK(0x15), REGDMA_PHY_LINK(0x16), REGDMA_PHY_LINK(0x17) /* 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++) { @@ -120,6 +126,9 @@ esp_err_t sleep_phy_link_init(void **link_head) } } } + if (err != ESP_OK) { + sleep_phy_link_deinit(NULL); + } #endif return err; } @@ -129,26 +138,37 @@ void IRAM_ATTR sleep_phy_link_config(void *link_context, uint32_t flags) #if SOC_PM_PAU_REGDMA_LINK_IDX_PHY 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_DIS], true, true); } else { regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_ENA], 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); + } + } + } #endif } esp_err_t sleep_phy_link_deinit(void *link_head) { - esp_err_t err = ESP_OK; #if SOC_PM_PAU_REGDMA_LINK_IDX_PHY - err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_MODEM_PHY); - if (err == ESP_OK) { - sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_MODEM_PHY); - } + sleep_retention_module_free(SLEEP_RETENTION_MODULE_MODEM_PHY); + sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_MODEM_PHY); #endif - return err; + return ESP_OK; } #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 b05c9fe82c8..edf27e7a21e 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 99c239ee521..aeaf3c14870 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -103,7 +103,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 @@ -343,11 +343,16 @@ void esp_phy_enable(esp_phy_modem_t modem) } else { #if SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY #if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP - bool wifimac_link_is_sel = false; 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()) { -#if SOC_PM_PAU_REGDMA_LINK_IDX_PHY && SOC_PM_PAU_REGDMA_MODEM_WIFIMAC_WORKAROUND + 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; + } + 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 /* * 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 @@ -360,7 +365,7 @@ void esp_phy_enable(esp_phy_modem_t modem) */ wifimac_link_is_sel = pm_get_wifimac_regdma_link_selection(); #endif - sleep_modem_do_phy_retention(true, wifimac_link_is_sel); + sleep_modem_do_phy_retention(true, wifimac_link_is_sel, modem_flags); } else { phy_wakeup_init(); } @@ -430,11 +435,16 @@ 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()) { + 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; + } bool wifimac_link_is_sel = false; -#if SOC_PM_PAU_REGDMA_LINK_IDX_PHY && SOC_PM_PAU_REGDMA_MODEM_WIFIMAC_WORKAROUND +#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(); #endif - sleep_modem_do_phy_retention(false, wifimac_link_is_sel); + sleep_modem_do_phy_retention(false, wifimac_link_is_sel, modem_flags); } else #endif /* SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY */ { @@ -503,7 +513,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 @@ -511,16 +521,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) { @@ -541,9 +551,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 }