diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index 2356a09e43..3f279e34c7 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -449,6 +441,18 @@ static void btdm_slp_tmr_callback(void *arg); #endif /* #ifdef CONFIG_PM_ENABLE */ +static inline void esp_bt_power_domain_on(void) +{ + // Bluetooth module power up + esp_wifi_bt_power_domain_on(); +} + +static inline void esp_bt_power_domain_off(void) +{ + // Bluetooth module power down + esp_wifi_bt_power_domain_off(); +} + static inline void btdm_check_and_init_bb(void) { /* init BT-BB if PHY/RF has been switched off since last BT-BB init */ @@ -1393,6 +1397,8 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) goto error; } + esp_bt_power_domain_on(); + btdm_controller_mem_init(); periph_module_enable(PERIPH_BT_MODULE); @@ -1554,6 +1560,8 @@ esp_err_t esp_bt_controller_deinit(void) btdm_lpcycle_us = 0; btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); + esp_bt_power_domain_off(); + return ESP_OK; } diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index 04c35768e4..f8ec29ee21 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -45,6 +37,7 @@ #include "esp32c3/rom/rom_layout.h" #include "esp_timer.h" #include "esp_sleep.h" +#include "phy.h" #if CONFIG_BT_ENABLED @@ -409,7 +402,7 @@ static DRAM_ATTR esp_pm_lock_handle_t s_light_sleep_pm_lock; void IRAM_ATTR btdm_hw_mac_power_down_wrapper(void) { #if CONFIG_MAC_BB_PD - // le module power down + // Bluetooth module power down SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); @@ -420,7 +413,7 @@ void IRAM_ATTR btdm_hw_mac_power_down_wrapper(void) void IRAM_ATTR btdm_hw_mac_power_up_wrapper(void) { #if CONFIG_MAC_BB_PD - // le module power up + // Bluetooth module power up CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); @@ -428,6 +421,22 @@ void IRAM_ATTR btdm_hw_mac_power_up_wrapper(void) #endif } +static inline void esp_bt_power_domain_on(void) +{ + // Bluetooth module power up + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); + esp_wifi_bt_power_domain_on(); +} + +static inline void esp_bt_power_domain_off(void) +{ + // Bluetooth module power down + SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); + SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); + esp_wifi_bt_power_domain_off(); +} + void IRAM_ATTR btdm_backup_dma_copy_wrapper(uint32_t reg, uint32_t mem_addr, uint32_t num, bool to_mem) { #if CONFIG_MAC_BB_PD @@ -953,6 +962,11 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) // overwrite some parameters cfg->magic = ESP_BT_CTRL_CONFIG_MAGIC_VAL; +#if CONFIG_MAC_BB_PD + esp_mac_bb_pd_mem_init(); +#endif + esp_bt_power_domain_on(); + sdk_config_extend_set_pll_track(false); #if CONFIG_MAC_BB_PD @@ -1231,6 +1245,14 @@ esp_err_t esp_bt_controller_deinit(void) esp_unregister_mac_bb_pd_callback(btdm_mac_bb_power_down_cb); esp_unregister_mac_bb_pu_callback(btdm_mac_bb_power_up_cb); #endif + + /* Fix the issue caused by the power off the bt power domain. + * This issue is only on ESP32C3. + */ + phy_init_flag(); + + esp_bt_power_domain_off(); + free(osi_funcs_p); osi_funcs_p = NULL; diff --git a/components/bt/include/esp32/include/esp_bt.h b/components/bt/include/esp32/include/esp_bt.h index 390c62b15f..c02885703e 100644 --- a/components/bt/include/esp32/include/esp_bt.h +++ b/components/bt/include/esp32/include/esp_bt.h @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __ESP_BT_H__ #define __ESP_BT_H__ @@ -496,6 +488,16 @@ esp_err_t esp_bt_sleep_disable(void); */ esp_err_t esp_ble_scan_dupilcate_list_flush(void); +/** + * @brief bt Wi-Fi power domain power on + */ +void esp_wifi_bt_power_domain_on(void); + +/** + * @brief bt Wi-Fi power domain power off + */ +void esp_wifi_bt_power_domain_off(void); + #ifdef __cplusplus } #endif diff --git a/components/bt/include/esp32c3/include/esp_bt.h b/components/bt/include/esp32c3/include/esp_bt.h index 2874406dee..2ec3064d6e 100644 --- a/components/bt/include/esp32c3/include/esp_bt.h +++ b/components/bt/include/esp32c3/include/esp_bt.h @@ -525,6 +525,16 @@ void esp_bt_controller_wakeup_request(void); */ int esp_bt_h4tl_eif_io_event_notify(int event); +/** + * @brief bt Wi-Fi power domain power on + */ +void esp_wifi_bt_power_domain_on(void); + +/** + * @brief bt Wi-Fi power domain power off + */ +void esp_wifi_bt_power_domain_off(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32/rtc_init.c b/components/esp_hw_support/port/esp32/rtc_init.c index f86811a99f..67fd56bba8 100644 --- a/components/esp_hw_support/port/esp32/rtc_init.c +++ b/components/esp_hw_support/port/esp32/rtc_init.c @@ -96,6 +96,9 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } + /* force power down wifi and bt power domain */ + 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); REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); diff --git a/components/esp_hw_support/port/esp32c3/rtc_init.c b/components/esp_hw_support/port/esp32c3/rtc_init.c index 1dbca83e54..320b9fa2c2 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_init.c +++ b/components/esp_hw_support/port/esp32c3/rtc_init.c @@ -152,6 +152,13 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } + /* force power down wifi and bt power domain */ + 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); + /* force power down bt power domain */ + SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO); + SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD); + REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 1); diff --git a/components/esp_hw_support/port/esp32s2/rtc_init.c b/components/esp_hw_support/port/esp32s2/rtc_init.c index 3ff028c4ff..82909f58c3 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_init.c +++ b/components/esp_hw_support/port/esp32s2/rtc_init.c @@ -152,6 +152,11 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } + + /* force power down wifi and bt power domain */ + 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); + if (cfg.cali_ocode) { uint32_t rtc_calib_version = 0; esp_efuse_read_field_blob(ESP_EFUSE_BLOCK2_VERSION, &rtc_calib_version, 32); diff --git a/components/esp_wifi/include/esp_private/wifi.h b/components/esp_wifi/include/esp_private/wifi.h index 428cc7d918..957f68791b 100644 --- a/components/esp_wifi/include/esp_private/wifi.h +++ b/components/esp_wifi/include/esp_private/wifi.h @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* * All the APIs declared here are internal only APIs, it can only be used by @@ -505,6 +497,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/include/phy.h b/components/esp_wifi/include/phy.h index 40c3a1d499..84cbbf5b4d 100644 --- a/components/esp_wifi/include/phy.h +++ b/components/esp_wifi/include/phy.h @@ -76,6 +76,14 @@ void phy_close_rf(void); void phy_xpd_tsens(void); #endif +#if CONFIG_IDF_TARGET_ESP32C3 +/** + * @brief Update internal state of PHY when wifi deinit powers off the wifi power domain. + */ +void phy_init_flag(void); +#endif + + /** * @brief Store and load PHY digital registers. * diff --git a/components/esp_wifi/linker.lf b/components/esp_wifi/linker.lf index d955938bce..27407adda9 100644 --- a/components/esp_wifi/linker.lf +++ b/components/esp_wifi/linker.lf @@ -63,6 +63,7 @@ entries: esp_adapter:wifi_clock_disable_wrapper (noflash) phy_init:esp_phy_enable (noflash) phy_init:esp_phy_disable (noflash) + phy_init:esp_wifi_bt_power_domain_off (noflash) wifi_init:wifi_apb80m_request (noflash) wifi_init:wifi_apb80m_release (noflash) diff --git a/components/esp_wifi/src/phy_init.c b/components/esp_wifi/src/phy_init.c index 82b11f11fe..cb6c89c58d 100644 --- a/components/esp_wifi/src/phy_init.c +++ b/components/esp_wifi/src/phy_init.c @@ -58,6 +58,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; @@ -286,6 +291,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 + 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); +} + void esp_phy_pd_mem_init(void) { _lock_acquire(&s_phy_access_lock); @@ -340,12 +369,12 @@ void esp_mac_bb_pd_mem_deinit(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; @@ -354,14 +383,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 @@ -942,3 +973,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/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 0c3caba29b..910fdd0164 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -26,6 +26,7 @@ #include "driver/adc2_wifi_private.h" #include "esp_coexist_internal.h" #include "esp_phy_init.h" +#include "phy.h" #if (CONFIG_ESP32_WIFI_RX_BA_WIN > CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM) #error "WiFi configuration check: WARNING, WIFI_RX_BA_WIN should not be larger than WIFI_DYNAMIC_RX_BUFFER_NUM!" @@ -136,11 +137,15 @@ 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 - +#if CONFIG_IDF_TARGET_ESP32C3 + phy_init_flag(); +#endif + esp_wifi_power_domain_off(); #if CONFIG_MAC_BB_PD esp_mac_bb_pd_mem_deinit(); #endif esp_phy_pd_mem_deinit(); + return err; } @@ -185,6 +190,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",