diff --git a/components/driver/include/driver/periph_ctrl.h b/components/driver/include/driver/periph_ctrl.h index b61477223b..b6c6a9d71b 100644 --- a/components/driver/include/driver/periph_ctrl.h +++ b/components/driver/include/driver/periph_ctrl.h @@ -67,6 +67,29 @@ void periph_module_disable(periph_module_t periph); */ void periph_module_reset(periph_module_t periph); +/** + * @brief enable wifi bt common module + * + * @note If wifi_bt_common_module_enable is called a number of times, + * wifi_bt_common_module_disable has to be called the same number of times + * in order to put the peripheral into disabled state. + * + * @return NULL + * + */ +void wifi_bt_common_module_enable(void); + +/** + * @brief disable wifi bt common module + * + * @note If wifi_bt_common_module_enable is called a number of times, + * wifi_bt_common_module_disable has to be called the same number of times + * in order to put the peripheral into disabled state. + * + * @return NULL + * + */ +void wifi_bt_common_module_disable(void); #ifdef __cplusplus } diff --git a/components/driver/periph_ctrl.c b/components/driver/periph_ctrl.c index 0cc747ef03..abb5a8a1b5 100644 --- a/components/driver/periph_ctrl.c +++ b/components/driver/periph_ctrl.c @@ -48,3 +48,23 @@ void periph_module_reset(periph_module_t periph) periph_ll_reset(periph); portEXIT_CRITICAL_SAFE(&periph_spinlock); } + +IRAM_ATTR void wifi_bt_common_module_enable(void) +{ + portENTER_CRITICAL_SAFE(&periph_spinlock); + if (ref_counts[PERIPH_WIFI_BT_COMMON_MODULE] == 0) { + periph_ll_wifi_bt_module_enable_clk_clear_rst(); + } + ref_counts[PERIPH_WIFI_BT_COMMON_MODULE]++; + portEXIT_CRITICAL_SAFE(&periph_spinlock); +} + +IRAM_ATTR void wifi_bt_common_module_disable(void) +{ + portENTER_CRITICAL_SAFE(&periph_spinlock); + ref_counts[PERIPH_WIFI_BT_COMMON_MODULE]--; + if (ref_counts[PERIPH_WIFI_BT_COMMON_MODULE] == 0) { + periph_ll_wifi_bt_module_disable_clk_set_rst(); + } + portEXIT_CRITICAL_SAFE(&periph_spinlock); +} \ No newline at end of file diff --git a/components/esp_wifi/src/phy_init.c b/components/esp_wifi/src/phy_init.c index 036679b9d1..e50f21dae9 100644 --- a/components/esp_wifi/src/phy_init.c +++ b/components/esp_wifi/src/phy_init.c @@ -59,14 +59,6 @@ static uint32_t s_module_phy_rf_init = 0; /* Whether modem sleep is turned on */ static volatile bool s_is_phy_rf_en = false; -#if CONFIG_IDF_TARGET_ESP32 -/* Whether WiFi/BT common clock enabled reference */ -static volatile int32_t s_common_clock_enable_ref = 0; - -/* PHY spinlock mux */ -static portMUX_TYPE s_phy_spin_lock = portMUX_INITIALIZER_UNLOCKED; -#endif - /* Bit mask of modules needing to enter modem sleep mode */ static uint32_t s_modem_sleep_module_enter = 0; @@ -195,63 +187,16 @@ static inline void phy_update_wifi_mac_time(bool en_clock_stopped, int64_t now) } } } - -IRAM_ATTR static inline void phy_spin_lock(void) -{ - if (xPortInIsrContext()) { - portENTER_CRITICAL_ISR(&s_phy_spin_lock); - } else { - portENTER_CRITICAL(&s_phy_spin_lock); - } -} - -IRAM_ATTR static inline void phy_spin_unlock(void) -{ - if (xPortInIsrContext()) { - portEXIT_CRITICAL_ISR(&s_phy_spin_lock); - } else { - portEXIT_CRITICAL(&s_phy_spin_lock); - } -} #endif IRAM_ATTR void esp_phy_common_clock_enable(void) { -#if CONFIG_IDF_TARGET_ESP32 - phy_spin_lock(); - - if (s_common_clock_enable_ref == 0) { - // Enable WiFi/BT common clock - periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE); - } - - s_common_clock_enable_ref++; - phy_spin_unlock(); -#else - periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE); -#endif + wifi_bt_common_module_enable(); } IRAM_ATTR void esp_phy_common_clock_disable(void) { -#if CONFIG_IDF_TARGET_ESP32 - phy_spin_lock(); - - if (s_common_clock_enable_ref > 0) { - s_common_clock_enable_ref --; - - if (s_common_clock_enable_ref == 0) { - // Disable WiFi/BT common clock - periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE); - } - } else { - abort(); - } - - phy_spin_unlock(); -#else - periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE); -#endif + wifi_bt_common_module_disable(); } esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibration_mode_t mode, diff --git a/components/soc/src/esp32/include/hal/clk_gate_ll.h b/components/soc/src/esp32/include/hal/clk_gate_ll.h index 1679afff69..bedfc6e770 100644 --- a/components/soc/src/esp32/include/hal/clk_gate_ll.h +++ b/components/soc/src/esp32/include/hal/clk_gate_ll.h @@ -242,6 +242,18 @@ static inline void periph_ll_disable_clk_set_rst(periph_module_t periph) DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)); } +static inline void IRAM_ATTR periph_ll_wifi_bt_module_enable_clk_clear_rst(void) +{ + DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_BT_COMMON_M); + DPORT_CLEAR_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); +} + +static inline void IRAM_ATTR periph_ll_wifi_bt_module_disable_clk_set_rst(void) +{ + DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_BT_COMMON_M); + DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); +} + static inline void periph_ll_reset(periph_module_t periph) { DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)); diff --git a/components/soc/src/esp32s2/include/hal/clk_gate_ll.h b/components/soc/src/esp32s2/include/hal/clk_gate_ll.h index 73104e1e09..868be82b86 100644 --- a/components/soc/src/esp32s2/include/hal/clk_gate_ll.h +++ b/components/soc/src/esp32s2/include/hal/clk_gate_ll.h @@ -254,6 +254,18 @@ static inline void periph_ll_disable_clk_set_rst(periph_module_t periph) DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)); } +static inline void IRAM_ATTR periph_ll_wifi_bt_module_enable_clk_clear_rst(void) +{ + DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_BT_COMMON_M); + DPORT_CLEAR_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); +} + +static inline void IRAM_ATTR periph_ll_wifi_bt_module_disable_clk_set_rst(void) +{ + DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_BT_COMMON_M); + DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); +} + static inline void periph_ll_reset(periph_module_t periph) { DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false));