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 6ff4517766..5e6aa72fa3 100644 --- a/components/esp_hw_support/include/esp_private/sleep_modem.h +++ b/components/esp_hw_support/include/esp_private/sleep_modem.h @@ -246,6 +246,13 @@ esp_err_t sleep_modem_state_phy_link_init(void **link_head); * - ESP_ERR_INVALID_STATE if the phy module retention state is invalid */ esp_err_t sleep_modem_state_phy_link_deinit(void *link_head); + +/** + * @brief Function to configure PHY link regdma description at runtime + * @param link_context PHY link regdma description conteoxt pointer + * @param flags A bitmap to indicate the PHY link regdma description configuration flag + */ +void sleep_modem_state_phy_link_config(void *link_context, uint32_t flags); #endif #ifdef __cplusplus diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_modem_state.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_modem_state.c index c2881711da..d754172e00 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_modem_state.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_modem_state.c @@ -5,6 +5,7 @@ */ #include "esp_log.h" #include "esp_check.h" +#include "esp_attr.h" #include "soc/soc_caps.h" #include "soc/i2c_ana_mst_reg.h" @@ -37,6 +38,13 @@ static __attribute__((unused)) const char *TAG = "sleep"; #if SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC + +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]; +} sleep_modem_state_phy_link_context_t; + static esp_err_t sleep_modem_state_phy_wifi_init(void *arg) { #define WIFIMAC_ENTRY() (BIT(SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC)) @@ -98,13 +106,41 @@ esp_err_t sleep_modem_state_phy_link_init(void **link_head) if (err == ESP_OK) { err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_MODEM_PHY); if (err == ESP_OK) { - *link_head = sleep_retention_find_link_by_id(REGDMA_PHY_LINK(0x00)); + const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x14) }; + static DRAM_ATTR sleep_modem_state_phy_link_context_t phy_link_context; + + for (int i = 0; (err == ESP_OK) && (i < ARRAY_SIZE(phy_link_context.regdma_desc)); i++) { + void *desc = sleep_retention_find_link_by_id(id_array[i]); + if (desc) { + phy_link_context.regdma_desc[i] = desc; + } else { + err = ESP_ERR_NOT_FOUND; + } + } + if (err == ESP_OK) { + *link_head = (void *)&phy_link_context; + } } } #endif return err; } +void IRAM_ATTR sleep_modem_state_phy_link_config(void *link_context, uint32_t flags) +{ +#if SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC + sleep_modem_state_phy_link_context_t *phy_link_context = (sleep_modem_state_phy_link_context_t *)link_context; + + if (flags & BIT(0)) { + 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); + } +#endif +} + esp_err_t sleep_modem_state_phy_link_deinit(void *link_head) { esp_err_t err = ESP_OK; diff --git a/components/esp_hw_support/lowpower/port/esp32c6/sleep_modem_state.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_modem_state.c index b374b70669..24ae81a91d 100644 --- a/components/esp_hw_support/lowpower/port/esp32c6/sleep_modem_state.c +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_modem_state.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include "esp_attr.h" + #include "soc/soc_caps.h" #include "soc/i2c_ana_mst_reg.h" #include "soc/pmu_reg.h" @@ -32,6 +34,14 @@ #define MODEM_FE_DATA_BASE (0x600a0400) #define MODEM_FE_CTRL_BASE (0x600a0800) +typedef struct { + void *link_head; +#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]; +} sleep_modem_state_phy_link_context_t; + esp_err_t sleep_modem_state_phy_link_init(void **link_head) { esp_err_t err = ESP_OK; @@ -105,16 +115,46 @@ esp_err_t sleep_modem_state_phy_link_init(void **link_head) } if (err == ESP_OK) { pau_regdma_set_modem_link_addr(link); - *link_head = link; + + const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x01), REGDMA_PHY_LINK(0x1b) }; + static DRAM_ATTR sleep_modem_state_phy_link_context_t phy_link_context; + + for (int i = 0; (err == ESP_OK) && (i < ARRAY_SIZE(phy_link_context.regdma_desc)); i++) { + void *desc = regdma_find_link_by_id(link, 0, id_array[i]); + if (desc) { + phy_link_context.regdma_desc[i] = desc; + } else { + err = ESP_ERR_NOT_FOUND; + } + } + if (err == ESP_OK) { + phy_link_context.link_head = link; + *link_head = (void *)&phy_link_context; + } } #endif return err; } +void IRAM_ATTR sleep_modem_state_phy_link_config(void *link_context, uint32_t flags) +{ + sleep_modem_state_phy_link_context_t *phy_link_context = (sleep_modem_state_phy_link_context_t *)link_context; + + if (flags & BIT(0)) { + 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); + } 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_SEL], true, false); + regdma_link_set_skip_flag(phy_link_context->regdma_desc[DESC_IDX_I2C_MST_DIS], false, true); + } +} + esp_err_t sleep_modem_state_phy_link_deinit(void *link_head) { #if SOC_PM_PAU_REGDMA_LINK_WIFIMAC - regdma_link_destroy(link_head, 0); + regdma_link_destroy(((sleep_modem_state_phy_link_context_t *)link_head)->link_head, 0); #endif return ESP_OK; } diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_modem_state.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_modem_state.c index b343bbe64b..cb3623011c 100644 --- a/components/esp_hw_support/lowpower/port/esp32c61/sleep_modem_state.c +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_modem_state.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include "esp_attr.h" + #include "soc/soc_caps.h" #include "soc/i2c_ana_mst_reg.h" #include "soc/pmu_reg.h" @@ -30,6 +32,13 @@ #define WDEVTXQ_BLOCK (0x600a4ca8) #define WDEV_RXBLOCK (BIT(12)) +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]; +} sleep_modem_state_phy_link_context_t; + esp_err_t sleep_modem_state_phy_link_init(void **link_head) { esp_err_t err = ESP_OK; @@ -101,16 +110,44 @@ esp_err_t sleep_modem_state_phy_link_init(void **link_head) } if (err == ESP_OK) { pau_regdma_set_modem_link_addr(link); - *link_head = link; + + const int id_array[] = { REGDMA_PHY_LINK(0x00), REGDMA_PHY_LINK(0x1a) }; + static DRAM_ATTR sleep_modem_state_phy_link_context_t phy_link_context; + + for (int i = 0; (err == ESP_OK) && (i < ARRAY_SIZE(phy_link_context.regdma_desc)); i++) { + void *desc = regdma_find_link_by_id(link, 0, id_array[i]); + if (desc) { + phy_link_context.regdma_desc[i] = desc; + } else { + err = ESP_ERR_NOT_FOUND; + } + } + if (err == ESP_OK) { + phy_link_context.link_head = link; + *link_head = (void *)&phy_link_context; + } } #endif return err; } +void IRAM_ATTR sleep_modem_state_phy_link_config(void *link_context, uint32_t flags) +{ + sleep_modem_state_phy_link_context_t *phy_link_context = (sleep_modem_state_phy_link_context_t *)link_context; + + if (flags & BIT(0)) { + 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_modem_state_phy_link_deinit(void *link_head) { #if SOC_PM_PAU_REGDMA_LINK_WIFIMAC - regdma_link_destroy(link_head, 0); + regdma_link_destroy(((sleep_modem_state_phy_link_context_t *)link_head)->link_head, 0); #endif return ESP_OK; } diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c index b57f3d6419..67d2feffdd 100644 --- a/components/esp_hw_support/sleep_modem.c +++ b/components/esp_hw_support/sleep_modem.c @@ -173,7 +173,9 @@ __attribute__((unused)) void sleep_modem_wifi_modem_state_deinit(void) void IRAM_ATTR sleep_modem_wifi_do_phy_retention(bool restore) { + sleep_modem_state_phy_link_config(s_sleep_modem.wifi.phy_link, 1); sleep_retention_do_phy_retention(!restore); + sleep_modem_state_phy_link_config(s_sleep_modem.wifi.phy_link, 0); if (!restore) { s_sleep_modem.wifi.modem_state_phy_done = 1; }