diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index 1e06d46246f..ad2e88d6b07 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -47,6 +47,7 @@ #include "esp_rom_sys.h" #include "hli_api.h" +#include "esp_private/sleep_modem.h" #if CONFIG_BLE_LOG_ENABLED #include "ble_log.h" @@ -1692,7 +1693,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGI(BTDM_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version()); - esp_phy_modem_init(); + esp_phy_modem_init(SLEEP_MODEM_BT); esp_bt_power_domain_on(); @@ -1867,7 +1868,7 @@ static void bt_controller_deinit_internal(void) esp_bt_power_domain_off(); - esp_phy_modem_deinit(); + esp_phy_modem_deinit(SLEEP_MODEM_BT); } static void bt_controller_shutdown(void* arg) diff --git a/components/bt/controller/esp32c2/bt.c b/components/bt/controller/esp32c2/bt.c index 4f7a44083d9..fa45bf70bd5 100644 --- a/components/bt/controller/esp32c2/bt.c +++ b/components/bt/controller/esp32c2/bt.c @@ -48,9 +48,7 @@ #include "esp_private/esp_clk_tree_common.h" #include "bt_osi_mem.h" -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/sleep_modem.h" -#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/esp_modem_clock.h" #include "freertos/FreeRTOS.h" @@ -957,7 +955,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) os_msys_init(); - esp_phy_modem_init(); + esp_phy_modem_init(SLEEP_MODEM_BT); periph_module_enable(PERIPH_BT_MODULE); periph_module_reset(PERIPH_BT_MODULE); @@ -1037,7 +1035,7 @@ controller_init_err: #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED ble_controller_deinit(); modem_deint: - esp_phy_modem_deinit(); + esp_phy_modem_deinit(SLEEP_MODEM_BT); periph_module_disable(PERIPH_BT_MODULE); free_mem: @@ -1077,7 +1075,7 @@ esp_err_t esp_bt_controller_deinit(void) npl_freertos_mempool_deinit(); - esp_phy_modem_deinit(); + esp_phy_modem_deinit(SLEEP_MODEM_BT); ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index 72acdcfbcf5..b432cf2523f 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -62,6 +62,8 @@ #endif // CONFIG_BT_CTRL_LE_LOG_STORAGE_EN #include "esp_rom_gpio.h" #if CONFIG_BT_ENABLED +#include "esp_private/sleep_modem.h" + /* Macro definition ************************************************************************ @@ -1850,7 +1852,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #if CONFIG_MAC_BB_PD esp_mac_bb_pd_mem_init(); #endif - esp_phy_modem_init(); + esp_phy_modem_init(SLEEP_MODEM_BT); esp_bt_power_domain_on(); btdm_controller_mem_init(); @@ -2049,7 +2051,7 @@ static void bt_controller_deinit_internal(void) #if CONFIG_MAC_BB_PD esp_mac_bb_pd_mem_deinit(); #endif - esp_phy_modem_deinit(); + esp_phy_modem_deinit(SLEEP_MODEM_BT); #if CONFIG_BT_CTRL_LE_LOG_EN esp_bt_controller_log_deinit(); diff --git a/components/bt/controller/esp32c5/bt.c b/components/bt/controller/esp32c5/bt.c index e9d6739e273..1c5b0f25766 100644 --- a/components/bt/controller/esp32c5/bt.c +++ b/components/bt/controller/esp32c5/bt.c @@ -44,8 +44,8 @@ #include "soc/regdma.h" #include "bt_osi_mem.h" -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/sleep_modem.h" +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/sleep_retention.h" #include "esp_private/pm_impl.h" #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE @@ -1016,7 +1016,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) modem_clock_module_mac_reset(PERIPH_BT_MODULE); /* Select slow clock source for BT momdule */ ble_rtc_clk_init(cfg); - esp_phy_modem_init(); + esp_phy_modem_init(SLEEP_MODEM_BT); if (ble_osi_coex_funcs_register((struct osi_coex_funcs_t *)&s_osi_coex_funcs_ro) != 0) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "osi coex funcs reg failed"); @@ -1111,7 +1111,7 @@ modem_deint: #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - esp_phy_modem_deinit(); + esp_phy_modem_deinit(SLEEP_MODEM_BT); modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); modem_clock_module_disable(PERIPH_BT_MODULE); @@ -1136,7 +1136,7 @@ esp_err_t esp_bt_controller_deinit(void) os_msys_deinit(); - esp_phy_modem_deinit(); + esp_phy_modem_deinit(SLEEP_MODEM_BT); modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); modem_clock_module_disable(PERIPH_BT_MODULE); diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index d472e03bda4..71da469d2bd 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -45,8 +45,8 @@ #include "esp_private/esp_clk_tree_common.h" #include "bt_osi_mem.h" -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/sleep_modem.h" +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/sleep_retention.h" #include "esp_private/pm_impl.h" #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE @@ -1096,7 +1096,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) modem_clock_module_mac_reset(PERIPH_BT_MODULE); /* Select slow clock source for BT momdule */ ble_rtc_clk_init(cfg); - esp_phy_modem_init(); + esp_phy_modem_init(SLEEP_MODEM_BT); if (ble_osi_coex_funcs_register((struct osi_coex_funcs_t *)&s_osi_coex_funcs_ro) != 0) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "osi coex funcs reg failed"); @@ -1194,7 +1194,7 @@ modem_deint: #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - esp_phy_modem_deinit(); + esp_phy_modem_deinit(SLEEP_MODEM_BT); modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); modem_clock_module_disable(PERIPH_BT_MODULE); @@ -1219,7 +1219,7 @@ esp_err_t esp_bt_controller_deinit(void) os_msys_deinit(); - esp_phy_modem_deinit(); + esp_phy_modem_deinit(SLEEP_MODEM_BT); modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); modem_clock_module_disable(PERIPH_BT_MODULE); 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 002ae2e482f..ae6e5213dd4 100644 --- a/components/esp_hw_support/include/esp_private/sleep_modem.h +++ b/components/esp_hw_support/include/esp_private/sleep_modem.h @@ -15,6 +15,18 @@ extern "C" { #endif +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +#define SLEEP_MODEM_SKIP_I2C_MST_CLK_RETENTION (BIT(0)) +#define SLEEP_MODEM_SKIP_WIFI_RETENTION (BIT(1)) +#define SLEEP_MODEM_RESET_RETENTION (0) +#endif // SOC_PM_SUPPORT_PMU_MODEM_STATE +typedef enum { + SLEEP_MODEM_WIFI = 1, + SLEEP_MODEM_BT = 2, + SLEEP_MODEM_IEEE802154 = 4, +} sleep_modem_type_t; +#define SLEEP_MODEM_MAX_CNT 3 + /** * @file sleep_modem.h * @@ -88,18 +100,18 @@ void sleep_modem_mac_bb_power_up_prepare(void); void sleep_modem_do_phy_retention(bool restore, bool wifimac_link_is_sel); /** - * @brief Get WiFi modem state + * @brief Get phy link state * - * @return true or false for WiFi modem state is enabled or disabled + * @return true or false for phy link is enabled or disabled */ -bool sleep_modem_modem_state_enabled(void); +bool sleep_modem_phy_link_enabled(void); /** - * @brief Get WiFi modem link done state + * @brief Get phy link done state * - * @return true or false for WiFi modem link can be used to enable RF by REGDMA or can not be used + * @return true or false for phy link can be used to enable RF by REGDMA or can not be used */ -bool sleep_modem_modem_link_done(void); +bool sleep_modem_phy_link_done(void); #endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */ @@ -204,18 +216,31 @@ void esp_pm_unregister_light_sleep_default_params_config_callback(void); * @brief Init phy link. * * This function init phy link. - * @return - * - ESP_OK on success - * - ESP_ERR_NO_MEM if no memory for link + * + * @param modem_mask bit mask of modems + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM if no memory for link */ -esp_err_t sleep_modem_phy_init(void); +esp_err_t sleep_modem_phy_init(sleep_modem_type_t modem_mask); /** - * @brief Deinit phy link. + * @brief Deinit phy link. * * This function deinit phy link. + * + * @param modem_mask bit mask of modems */ -void sleep_modem_phy_deinit(void); +void sleep_modem_phy_deinit(sleep_modem_type_t modem_mask); + +/** + * @brief Check if Wi-Fi modem state is enabled + * + * @return + * - true Wi-Fi modem state is enabled + * - false Wi-Fi modem state is disabled + */ +bool sleep_modem_wifi_modem_state_is_enabled(void); /** * @brief Function to check Wi-Fi modem state to skip light sleep. @@ -254,14 +279,7 @@ esp_err_t sleep_phy_link_deinit(void *link_head); * @param flags A bitmap to indicate the PHY link regdma description configuration flag */ void sleep_phy_link_config(void *link_context, uint32_t flags); - -/** - * @brief Function to skip the retention entries involving Wi-Fi registers - * - * @param skip - */ -void sleep_phy_skip_wifi_reg(bool skip); -#endif +#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */ #ifdef __cplusplus } diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c index a86ac86ead8..e82a72d251c 100644 --- a/components/esp_hw_support/sleep_modem.c +++ b/components/esp_hw_support/sleep_modem.c @@ -132,43 +132,68 @@ void mac_bb_power_up_cb_execute(void) #if SOC_PM_SUPPORT_PMU_MODEM_STATE typedef struct sleep_modem_config { - struct { - void *phy_link; - union { - struct { - uint32_t phy_link_done: 1; - uint32_t reserved: 31; - }; - uint32_t flags; + _lock_t phy_link_lock; + void *phy_link; + union { + struct { + uint32_t phy_link_done: 1; + uint32_t modem_mask: SLEEP_MODEM_MAX_CNT; + uint32_t reserved: 27 - SLEEP_MODEM_MAX_CNT; }; + uint32_t flags; }; } sleep_modem_config_t; static sleep_modem_config_t s_sleep_modem = { .phy_link = NULL, .flags = 0 }; +bool IRAM_ATTR sleep_modem_wifi_modem_state_is_enabled(void) +{ + return !!(s_sleep_modem.modem_mask & SLEEP_MODEM_WIFI); +} -esp_err_t sleep_modem_phy_init(void) +esp_err_t sleep_modem_phy_init(sleep_modem_type_t modem_mask) { esp_err_t err = ESP_OK; - void *link = NULL; - if (s_sleep_modem.phy_link == NULL) { - err = sleep_phy_link_init(&link); - if (err == ESP_OK) { - s_sleep_modem.phy_link = link; - s_sleep_modem.flags = 0; + + _lock_acquire(&s_sleep_modem.phy_link_lock); + if (s_sleep_modem.modem_mask & modem_mask) { + _lock_release(&s_sleep_modem.phy_link_lock); + return ESP_ERR_INVALID_ARG; + } + + if (!s_sleep_modem.modem_mask) { + s_sleep_modem.flags = 0; + if (!s_sleep_modem.phy_link) { + err = sleep_phy_link_init(&link); + if (err == ESP_OK) { + s_sleep_modem.phy_link = link; + } else { + _lock_release(&s_sleep_modem.phy_link_lock); + return err; + } } } + s_sleep_modem.modem_mask |= modem_mask; + _lock_release(&s_sleep_modem.phy_link_lock); return err; } -__attribute__((unused)) void sleep_modem_phy_deinit(void) +__attribute__((unused)) void sleep_modem_phy_deinit(sleep_modem_type_t modem_mask) { - if (s_sleep_modem.phy_link) { + _lock_acquire(&s_sleep_modem.phy_link_lock); + if (!(s_sleep_modem.modem_mask & modem_mask)) { + _lock_release(&s_sleep_modem.phy_link_lock); + return; + } + + s_sleep_modem.modem_mask &= ~modem_mask; + if (s_sleep_modem.phy_link && !s_sleep_modem.modem_mask) { sleep_phy_link_deinit(s_sleep_modem.phy_link); s_sleep_modem.phy_link = NULL; s_sleep_modem.flags = 0; } + _lock_release(&s_sleep_modem.phy_link_lock); } void IRAM_ATTR sleep_modem_do_phy_retention(bool restore, bool wifimac_link_is_sel) @@ -226,7 +251,7 @@ uint32_t sleep_modem_reject_triggers(void) uint32_t reject_triggers = 0; #if SOC_PM_SUPPORT_PMU_MODEM_STATE reject_triggers = (s_sleep_modem.phy_link != NULL) ? BIT(16) : 0; -#endif +#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */ return reject_triggers; } @@ -237,8 +262,8 @@ bool IRAM_ATTR sleep_modem_wifi_modem_state_skip_light_sleep(void) /* 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_phy_link_enabled() && !sleep_modem_phy_link_done(); -#endif + skip = sleep_modem_wifi_modem_state_is_enabled() && !sleep_modem_phy_link_done(); +#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */ return skip; } diff --git a/components/esp_phy/include/esp_phy_init.h b/components/esp_phy/include/esp_phy_init.h index c41e970c5a6..90272ace236 100644 --- a/components/esp_phy/include/esp_phy_init.h +++ b/components/esp_phy/include/esp_phy_init.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -200,15 +200,18 @@ void esp_phy_load_cal_and_init(void); /** * @brief Initialize backup memory for Phy power up/down + * + * @param modem Modem calling phy retention */ -void esp_phy_modem_init(void); +void esp_phy_modem_init(uint8_t modem); /** * @brief Deinitialize backup memory for Phy power up/down * Set phy_init_flag if all modems deinit on ESP32C3 + * + * @param modem Modem calling phy retention */ -void esp_phy_modem_deinit(void); - +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 d66a85a1365..84d16802299 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -502,7 +502,7 @@ void esp_wifi_bt_power_domain_off(void) #endif // SOC_PM_SUPPORT_MODEM_PD || SOC_PM_SUPPORT_WIFI_PD } -void esp_phy_modem_init(void) +void esp_phy_modem_init(uint8_t modem) { #if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP _lock_acquire(&s_phy_access_lock); @@ -513,17 +513,21 @@ void esp_phy_modem_init(void) } #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA #if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP - sleep_modem_phy_init(); + sleep_modem_phy_init(modem); #endif // CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP _lock_release(&s_phy_access_lock); #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP } -void esp_phy_modem_deinit(void) +void esp_phy_modem_deinit(uint8_t modem) { #if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP _lock_acquire(&s_phy_access_lock); + 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) { #if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA @@ -537,10 +541,10 @@ void esp_phy_modem_deinit(void) phy_init_flag(); #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 - sleep_modem_phy_deinit(); -#endif // CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP } +#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + sleep_modem_phy_deinit(modem); +#endif // SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP _lock_release(&s_phy_access_lock); #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP } diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 32832d74583..94e9050ea11 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -258,7 +258,7 @@ static esp_err_t wifi_deinit_internal(void) #endif #endif /* CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP */ #ifdef CONFIG_ESP_PHY_ENABLED - esp_phy_modem_deinit(); + esp_phy_modem_deinit(SLEEP_MODEM_WIFI); #endif s_wifi_inited = false; @@ -450,10 +450,10 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) esp_wifi_mac_pd_mem_init(); #endif #ifdef CONFIG_ESP_PHY_ENABLED - esp_phy_modem_init(); + esp_phy_modem_init(SLEEP_MODEM_WIFI); #endif #if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP - if (sleep_modem_phy_link_enabled()) { + if (sleep_modem_wifi_modem_state_is_enabled()) { esp_pm_register_skip_light_sleep_callback(sleep_modem_wifi_modem_state_skip_light_sleep); esp_wifi_internal_modem_state_configure(true); /* require WiFi to enable automatically receives the beacon */ #if ESP_MODEM_RF_FLAG_UPDATE_CB_REQUIRED