From b774342402ebbfd16d34890aaca8a6f29ff52813 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 14 Sep 2021 17:15:58 +0800 Subject: [PATCH] Power Management: power up or down wifi power domain when wifi init or deinit --- components/esp_phy/linker.lf | 1 + components/esp_phy/src/phy_init.c | 53 +++++++++++++++---- .../esp_wifi/include/esp_private/wifi.h | 10 ++++ components/esp_wifi/src/wifi_init.c | 2 + 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/components/esp_phy/linker.lf b/components/esp_phy/linker.lf index 53125053d8..a5a355da2e 100644 --- a/components/esp_phy/linker.lf +++ b/components/esp_phy/linker.lf @@ -25,3 +25,4 @@ entries: if ESP_WIFI_SLP_IRAM_OPT =y: phy_init:esp_phy_enable (noflash) phy_init:esp_phy_disable (noflash) + phy_init:esp_wifi_bt_power_domain_off (noflash) diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index cac6bc9ebf..041ed18155 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -28,11 +28,10 @@ #include "esp_rom_crc.h" #include "esp_rom_sys.h" -#if CONFIG_IDF_TARGET_ESP32C3 #include "soc/rtc_cntl_reg.h" +#if CONFIG_IDF_TARGET_ESP32C3 #include "soc/syscon_reg.h" #elif CONFIG_IDF_TARGET_ESP32S3 -#include "soc/rtc_cntl_reg.h" #include "soc/syscon_reg.h" #endif @@ -44,6 +43,11 @@ static const char* TAG = "phy_init"; static _lock_t s_phy_access_lock; +static DRAM_ATTR struct { + int count; /* power on count of wifi and bt power domain */ + _lock_t lock; +} s_wifi_bt_pd_controller = { .count = 0 }; + /* Indicate PHY is calibrated or not */ static bool s_is_phy_calibrated = false; @@ -273,6 +277,30 @@ void esp_phy_disable(void) _lock_release(&s_phy_access_lock); } +void IRAM_ATTR esp_wifi_bt_power_domain_on(void) +{ + _lock_acquire(&s_wifi_bt_pd_controller.lock); + if (s_wifi_bt_pd_controller.count++ == 0) { + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + SET_PERI_REG_MASK(SYSCON_WIFI_RST_EN_REG, SYSTEM_BB_RST | SYSTEM_FE_RST); + CLEAR_PERI_REG_MASK(SYSCON_WIFI_RST_EN_REG, SYSTEM_BB_RST | SYSTEM_FE_RST); +#endif + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); + } + _lock_release(&s_wifi_bt_pd_controller.lock); +} + +void esp_wifi_bt_power_domain_off(void) +{ + _lock_acquire(&s_wifi_bt_pd_controller.lock); + if (--s_wifi_bt_pd_controller.count == 0) { + SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); + SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + } + _lock_release(&s_wifi_bt_pd_controller.lock); +} + #if CONFIG_MAC_BB_PD void esp_mac_bb_pd_mem_init(void) { @@ -287,12 +315,12 @@ void esp_mac_bb_pd_mem_init(void) IRAM_ATTR void esp_mac_bb_power_up(void) { - if (s_mac_bb_pd_mem != NULL && (!s_mac_bb_pu)) { + if (s_mac_bb_pd_mem == NULL) { + return; + } + esp_wifi_bt_power_domain_on(); + if (!s_mac_bb_pu) { esp_phy_common_clock_enable(); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); - SET_PERI_REG_MASK(SYSCON_WIFI_RST_EN_REG, SYSTEM_BB_RST | SYSTEM_FE_RST); - CLEAR_PERI_REG_MASK(SYSCON_WIFI_RST_EN_REG, SYSTEM_BB_RST | SYSTEM_FE_RST); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); phy_freq_mem_backup(false, s_mac_bb_pd_mem); esp_phy_common_clock_disable(); s_mac_bb_pu = true; @@ -301,14 +329,16 @@ IRAM_ATTR void esp_mac_bb_power_up(void) IRAM_ATTR void esp_mac_bb_power_down(void) { - if (s_mac_bb_pd_mem != NULL && s_mac_bb_pu) { + if (s_mac_bb_pd_mem == NULL) { + return; + } + if (s_mac_bb_pu) { esp_phy_common_clock_enable(); phy_freq_mem_backup(true, s_mac_bb_pd_mem); - SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); - SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); esp_phy_common_clock_disable(); s_mac_bb_pu = false; } + esp_wifi_bt_power_domain_off(); } #endif @@ -905,3 +935,6 @@ esp_err_t esp_phy_update_country_info(const char *country) #endif return ESP_OK; } + +void esp_wifi_power_domain_on(void) __attribute__((alias("esp_wifi_bt_power_domain_on"))); +void esp_wifi_power_domain_off(void) __attribute__((alias("esp_wifi_bt_power_domain_off"))); diff --git a/components/esp_wifi/include/esp_private/wifi.h b/components/esp_wifi/include/esp_private/wifi.h index 428cc7d918..21f6324e31 100644 --- a/components/esp_wifi/include/esp_private/wifi.h +++ b/components/esp_wifi/include/esp_private/wifi.h @@ -505,6 +505,16 @@ bool esp_wifi_internal_is_tsf_active(void); void esp_wifi_internal_update_light_sleep_wake_ahead_time(uint32_t); #endif +/** + * @brief Wifi power domain power on + */ +void esp_wifi_power_domain_on(void); + +/** + * @brief Wifi power domain power off + */ +void esp_wifi_power_domain_off(void); + #if CONFIG_MAC_BB_PD /** * @brief Enable or disable powering down MAC and baseband when Wi-Fi is sleeping. diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index f8ec7fbcca..40273d86bf 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -125,6 +125,7 @@ esp_err_t esp_wifi_deinit(void) esp_unregister_mac_bb_pd_callback(pm_mac_sleep); esp_unregister_mac_bb_pu_callback(pm_mac_wakeup); #endif + esp_wifi_power_domain_off(); return err; } @@ -169,6 +170,7 @@ static void esp_wifi_config_info(void) esp_err_t esp_wifi_init(const wifi_init_config_t *config) { + esp_wifi_power_domain_on(); #ifdef CONFIG_PM_ENABLE if (s_wifi_modem_sleep_lock == NULL) { esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "wifi",