From a98db6dbd324ec33c7c28e81f57ea153a1c16a76 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Wed, 14 Jun 2023 14:56:44 +0800 Subject: [PATCH 1/5] modem clock: gatable clock interface which can gate or ungate modem clock domain --- .../include/esp_private/esp_modem_clock.h | 28 +++++++++++++ components/esp_hw_support/modem_clock.c | 32 ++++++++++++++ .../hal/esp32c6/include/hal/modem_lpcon_ll.h | 24 +++++++++++ .../hal/esp32c6/include/hal/modem_syscon_ll.h | 37 ++++++++++++++++ components/hal/esp32c6/modem_clock_hal.c | 42 +++++++++++++++++++ components/hal/include/hal/modem_clock_hal.h | 1 + 6 files changed, 164 insertions(+) diff --git a/components/esp_hw_support/include/esp_private/esp_modem_clock.h b/components/esp_hw_support/include/esp_private/esp_modem_clock.h index e01f912d83..bd822ebfbd 100644 --- a/components/esp_hw_support/include/esp_private/esp_modem_clock.h +++ b/components/esp_hw_support/include/esp_private/esp_modem_clock.h @@ -10,9 +10,11 @@ #include #include +#include "esp_err.h" #include "soc/soc_caps.h" #include "soc/periph_defs.h" #include "hal/modem_clock_types.h" +#include "esp_private/esp_pmu.h" #if SOC_MODEM_CLOCK_IS_INDEPENDENT #include "hal/modem_clock_hal.h" @@ -77,6 +79,32 @@ void modem_clock_module_mac_reset(periph_module_t module); */ void modem_clock_domain_pmu_state_icg_map_init(void); +#if SOC_PMU_SUPPORTED +/** + * @brief Enable modem clock domain clock gate to gate it's output + * + * @param domain modem module clock domain + * @param mode PMU HP system ACTIVE, MODEM and SLEEP state + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if the argument value are not correct + */ +esp_err_t modem_clock_domain_clk_gate_enable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode); + +/** + * @brief Disable modem clock domain clock gate to ungate it's output + * + * @param domain modem module clock domain + * @param mode PMU HP system ACTIVE, MODEM and SLEEP state + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if the argument value are not correct + */ +esp_err_t modem_clock_domain_clk_gate_disable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode); +#endif + /** * @brief Select the modem module lowpower clock source and configure the clock divider * diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index dec1c3c332..0e14ee4fc5 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -180,6 +180,38 @@ void modem_clock_domain_pmu_state_icg_map_init(void) { modem_clock_domain_power_state_icg_map_init(MODEM_CLOCK_instance()); } + +esp_err_t modem_clock_domain_clk_gate_enable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode) +{ + if (domain >= MODEM_CLOCK_DOMAIN_MAX || domain < MODEM_CLOCK_DOMAIN_MODEM_APB) { + return ESP_ERR_INVALID_ARG; + } + if (mode > PMU_HP_ICG_MODEM_CODE_ACTIVE || mode < PMU_HP_ICG_MODEM_CODE_SLEEP) { + return ESP_ERR_INVALID_ARG; + } + + portENTER_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); + uint32_t code = modem_clock_hal_get_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain); + modem_clock_hal_set_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain, (code & ~BIT(mode))); + portEXIT_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); + return ESP_OK; +} + +esp_err_t modem_clock_domain_clk_gate_disable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode) +{ + if (domain >= MODEM_CLOCK_DOMAIN_MAX || domain < MODEM_CLOCK_DOMAIN_MODEM_APB) { + return ESP_ERR_INVALID_ARG; + } + if (mode > PMU_HP_ICG_MODEM_CODE_ACTIVE || mode < PMU_HP_ICG_MODEM_CODE_SLEEP) { + return ESP_ERR_INVALID_ARG; + } + + portENTER_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); + uint32_t code = modem_clock_hal_get_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain); + modem_clock_hal_set_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain, (code | BIT(mode))); + portEXIT_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); + return ESP_OK; +} #endif // #if SOC_PM_SUPPORT_PMU_MODEM_STATE static void IRAM_ATTR modem_clock_device_enable(modem_clock_context_t *ctx, uint32_t dev_map) diff --git a/components/hal/esp32c6/include/hal/modem_lpcon_ll.h b/components/hal/esp32c6/include/hal/modem_lpcon_ll.h index 3374defb42..aa4288f519 100644 --- a/components/hal/esp32c6/include/hal/modem_lpcon_ll.h +++ b/components/hal/esp32c6/include/hal/modem_lpcon_ll.h @@ -192,24 +192,48 @@ static inline void modem_lpcon_ll_enable_ble_rtc_timer_force_clock(modem_lpcon_d hw->clk_conf_force_on.clk_lp_timer_fo = en; } +__attribute__((always_inline)) +static inline uint32_t modem_lpcon_ll_get_wifipwr_icg_bitmap(modem_lpcon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_wifipwr_st_map; +} + __attribute__((always_inline)) static inline void modem_lpcon_ll_set_wifipwr_icg_bitmap(modem_lpcon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_wifipwr_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_lpcon_ll_get_coex_icg_bitmap(modem_lpcon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_coex_st_map; +} + __attribute__((always_inline)) static inline void modem_lpcon_ll_set_coex_icg_bitmap(modem_lpcon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_coex_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_lpcon_ll_get_i2c_master_icg_bitmap(modem_lpcon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_i2c_mst_st_map; +} + __attribute__((always_inline)) static inline void modem_lpcon_ll_set_i2c_master_icg_bitmap(modem_lpcon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_i2c_mst_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_lpcon_ll_get_lp_apb_icg_bitmap(modem_lpcon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_lp_apb_st_map; +} + __attribute__((always_inline)) static inline void modem_lpcon_ll_set_lp_apb_icg_bitmap(modem_lpcon_dev_t *hw, uint32_t bitmap) { diff --git a/components/hal/esp32c6/include/hal/modem_syscon_ll.h b/components/hal/esp32c6/include/hal/modem_syscon_ll.h index 9fc2b50a3e..1b9a6a9056 100644 --- a/components/hal/esp32c6/include/hal/modem_syscon_ll.h +++ b/components/hal/esp32c6/include/hal/modem_syscon_ll.h @@ -105,36 +105,73 @@ static inline void modem_syscon_ll_enable_data_dump_force_clock(modem_syscon_dev { hw->clk_conf_force_on.clk_data_dump_fo = 1; } + +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_ieee802154_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_zb_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_ieee802154_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_zb_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_fe_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_fe_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_fe_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_fe_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_bt_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_bt_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_bt_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_bt_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_wifi_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_wifi_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_wifi_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_wifi_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_modem_periph_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_modem_peri_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_modem_periph_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_modem_peri_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_modem_apb_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_modem_apb_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_modem_apb_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { diff --git a/components/hal/esp32c6/modem_clock_hal.c b/components/hal/esp32c6/modem_clock_hal.c index 449006b701..a59aa84e2c 100644 --- a/components/hal/esp32c6/modem_clock_hal.c +++ b/components/hal/esp32c6/modem_clock_hal.c @@ -58,6 +58,48 @@ void modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, } } +uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain) +{ + HAL_ASSERT(domain < MODEM_CLOCK_DOMAIN_MAX); + uint32_t bitmap = 0; + switch (domain) + { + case MODEM_CLOCK_DOMAIN_MODEM_APB: + bitmap = modem_syscon_ll_get_modem_apb_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_MODEM_PERIPH: + bitmap = modem_syscon_ll_get_modem_periph_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_WIFI: + bitmap = modem_syscon_ll_get_wifi_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_BT: + bitmap = modem_syscon_ll_get_bt_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_FE: + bitmap = modem_syscon_ll_get_fe_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_IEEE802154: + bitmap = modem_syscon_ll_get_ieee802154_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_LP_APB: + bitmap = modem_lpcon_ll_get_lp_apb_icg_bitmap(hal->lpcon_dev); + break; + case MODEM_CLOCK_DOMAIN_I2C_MASTER: + bitmap = modem_lpcon_ll_get_i2c_master_icg_bitmap(hal->lpcon_dev); + break; + case MODEM_CLOCK_DOMAIN_COEX: + bitmap = modem_lpcon_ll_get_coex_icg_bitmap(hal->lpcon_dev); + break; + case MODEM_CLOCK_DOMAIN_WIFIPWR: + bitmap = modem_lpcon_ll_get_wifipwr_icg_bitmap(hal->lpcon_dev); + break; + default: + break; + } + return bitmap; +} + void modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable) { if (enable) { diff --git a/components/hal/include/hal/modem_clock_hal.h b/components/hal/include/hal/modem_clock_hal.h index 9912308f5e..0ce13035aa 100644 --- a/components/hal/include/hal/modem_clock_hal.h +++ b/components/hal/include/hal/modem_clock_hal.h @@ -24,6 +24,7 @@ typedef struct { #if MAC_SUPPORT_PMU_MODEM_STATE void modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain, uint32_t bitmap); +uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain); #endif void modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable); From 78683c7c3371bfaadf668e0cff1cb23a7946296f Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 16 Jun 2023 17:36:18 +0800 Subject: [PATCH 2/5] modem clock: provide a protected wifipwr clock enable/disable interface to fix the bug of selecting xtal as the low power clock source for ble --- components/esp_hw_support/modem_clock.c | 4 ++-- components/hal/esp32c6/modem_clock_hal.c | 20 ++++++++++++++++++++ components/hal/include/hal/modem_clock_hal.h | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 0e14ee4fc5..0348d68652 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -324,7 +324,7 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl modem_clock_hal_deselect_all_wifi_lpclk_source(MODEM_CLOCK_instance()->hal); modem_clock_hal_select_wifi_lpclk_source(MODEM_CLOCK_instance()->hal, src); modem_lpcon_ll_set_wifi_lpclk_divisor_value(MODEM_CLOCK_instance()->hal->lpcon_dev, divider); - modem_lpcon_ll_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal->lpcon_dev, true); + modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, true); break; #endif // SOC_WIFI_SUPPORTED @@ -377,7 +377,7 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module) #if SOC_WIFI_SUPPORTED case PERIPH_WIFI_MODULE: modem_clock_hal_deselect_all_wifi_lpclk_source(MODEM_CLOCK_instance()->hal); - modem_lpcon_ll_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal->lpcon_dev, false); + modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, false); break; #endif // SOC_WIFI_SUPPORTED diff --git a/components/hal/esp32c6/modem_clock_hal.c b/components/hal/esp32c6/modem_clock_hal.c index a59aa84e2c..553c7cbfac 100644 --- a/components/hal/esp32c6/modem_clock_hal.c +++ b/components/hal/esp32c6/modem_clock_hal.c @@ -10,6 +10,7 @@ #include "esp_attr.h" #include "hal/modem_clock_hal.h" #include "hal/modem_clock_types.h" +#include "hal/efuse_hal.h" #include "hal/assert.h" typedef enum { @@ -239,3 +240,22 @@ void modem_clock_hal_select_wifi_lpclk_source(modem_clock_hal_context_t *hal, mo break; } } + +void modem_clock_hal_enable_wifipwr_clock(modem_clock_hal_context_t *hal, bool enable) +{ + if (efuse_hal_chip_revision() == 0) { /* eco0 */ + modem_lpcon_ll_enable_wifipwr_clock(hal->lpcon_dev, enable); + } else { + static int ref = 0; + if (enable) { + if (ref++ == 0) { + modem_lpcon_ll_enable_wifipwr_clock(hal->lpcon_dev, enable); + } + } else { + if (--ref == 0) { + modem_lpcon_ll_enable_wifipwr_clock(hal->lpcon_dev, enable); + } + } + HAL_ASSERT(ref > 0); + } +} diff --git a/components/hal/include/hal/modem_clock_hal.h b/components/hal/include/hal/modem_clock_hal.h index 0ce13035aa..9e74e37d22 100644 --- a/components/hal/include/hal/modem_clock_hal.h +++ b/components/hal/include/hal/modem_clock_hal.h @@ -42,6 +42,7 @@ void modem_clock_hal_deselect_all_coex_lpclk_source(modem_clock_hal_context_t *h #if SOC_WIFI_SUPPORTED void modem_clock_hal_select_wifi_lpclk_source(modem_clock_hal_context_t *hal, modem_clock_lpclk_src_t src); void modem_clock_hal_deselect_all_wifi_lpclk_source(modem_clock_hal_context_t *hal); +void modem_clock_hal_enable_wifipwr_clock(modem_clock_hal_context_t *hal, bool enable); #endif #ifdef __cplusplus From ee3452d410568ec4e19a273887a46187727f5e84 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Mon, 26 Jun 2023 11:26:27 +0800 Subject: [PATCH 3/5] light sleep: enable system clock in PMU HP sleep state when selecting a 40 MHz XTAL as low power clock source of ble --- .../esp_hw_support/include/esp_private/esp_pmu.h | 9 +++++++++ components/esp_hw_support/modem_clock.c | 10 ++++++++-- components/esp_hw_support/port/esp32c6/pmu_sleep.c | 5 +++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 4dcb820b11..187784fae6 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -249,6 +249,15 @@ bool pmu_sleep_finish(void); */ void pmu_init(void); +/** + * @brief Enable or disable system clock in PMU HP sleep state + * + * This API only used for fix BLE 40 MHz low power clock source issue + * + * @param enable true to enable, false to disable + */ +void pmu_sleep_enable_hp_sleep_sysclk(bool enable); + #endif //#if SOC_PMU_SUPPORTED diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 0348d68652..443b7c78bb 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -334,6 +334,9 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl modem_clock_hal_select_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal, src); modem_clock_hal_set_ble_rtc_timer_divisor_value(MODEM_CLOCK_instance()->hal, divider); modem_clock_hal_enable_ble_rtc_timer_clock(MODEM_CLOCK_instance()->hal, true); + if (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + pmu_sleep_enable_hp_sleep_sysclk(true); + } break; #endif // SOC_BT_SUPPORTED @@ -372,6 +375,8 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module) { assert(IS_MODEM_MODULE(module)); portENTER_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); + modem_clock_lpclk_src_t last_src = MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN]; + MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN] = MODEM_CLOCK_LPCLK_SRC_INVALID; switch (module) { #if SOC_WIFI_SUPPORTED @@ -385,6 +390,9 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module) case PERIPH_BT_MODULE: modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal); modem_clock_hal_enable_ble_rtc_timer_clock(MODEM_CLOCK_instance()->hal, false); + if (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + pmu_sleep_enable_hp_sleep_sysclk(false); + } break; #endif // SOC_BT_SUPPORTED case PERIPH_COEX_MODULE: @@ -394,8 +402,6 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module) default: break; } - modem_clock_lpclk_src_t last_src = MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN]; - MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN] = MODEM_CLOCK_LPCLK_SRC_INVALID; portEXIT_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) ( \ diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index 07f96f4803..dfb63c9ff3 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -294,3 +294,8 @@ bool pmu_sleep_finish(void) { return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev); } + +void pmu_sleep_enable_hp_sleep_sysclk(bool enable) +{ + pmu_ll_hp_set_icg_sysclk_enable(PMU_instance()->hal->dev, HP(SLEEP), enable); +} From 6c62d135505d128fa2a6df9200ca3cc09100b6f3 Mon Sep 17 00:00:00 2001 From: cjin Date: Mon, 26 Jun 2023 12:11:04 +0800 Subject: [PATCH 4/5] ble: support eco1 BLE light sleep --- components/esp_hw_support/modem_clock.c | 21 +++++++++++++++---- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32c6/include/soc/soc_caps.h | 2 ++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 443b7c78bb..715a8ac211 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -16,6 +16,7 @@ #include "esp_private/esp_modem_clock.h" #include "esp_private/esp_pmu.h" #include "esp_sleep.h" +#include "hal/efuse_hal.h" // Please define the frequently called modules in the low bit, // which will improve the execution efficiency @@ -334,9 +335,15 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl modem_clock_hal_select_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal, src); modem_clock_hal_set_ble_rtc_timer_divisor_value(MODEM_CLOCK_instance()->hal, divider); modem_clock_hal_enable_ble_rtc_timer_clock(MODEM_CLOCK_instance()->hal, true); - if (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { - pmu_sleep_enable_hp_sleep_sysclk(true); +#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND + if (efuse_hal_chip_revision() != 0) { + if (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + pmu_sleep_enable_hp_sleep_sysclk(true); + } + modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, true); + modem_clock_domain_clk_gate_disable(MODEM_CLOCK_DOMAIN_WIFIPWR, PMU_HP_ICG_MODEM_CODE_SLEEP); } +#endif break; #endif // SOC_BT_SUPPORTED @@ -390,9 +397,15 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module) case PERIPH_BT_MODULE: modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal); modem_clock_hal_enable_ble_rtc_timer_clock(MODEM_CLOCK_instance()->hal, false); - if (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { - pmu_sleep_enable_hp_sleep_sysclk(false); +#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND + if (efuse_hal_chip_revision() != 0) { + if (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + pmu_sleep_enable_hp_sleep_sysclk(false); + } + modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, false); + modem_clock_domain_clk_gate_enable(MODEM_CLOCK_DOMAIN_WIFI, PMU_HP_ICG_MODEM_CODE_SLEEP); } +#endif break; #endif // SOC_BT_SUPPORTED case PERIPH_COEX_MODULE: diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index bbf30c4705..b1ace25e8c 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1270,3 +1270,7 @@ config SOC_BLE_POWER_CONTROL_SUPPORTED config SOC_BLUFI_SUPPORTED bool default y + +config SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND + bool + default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 676709dae2..e5208eeaf0 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -520,3 +520,5 @@ #define SOC_BLE_DEVICE_PRIVACY_SUPPORTED (1) /*!< Support BLE device privacy mode */ #define SOC_BLE_POWER_CONTROL_SUPPORTED (1) /*!< Support Bluetooth Power Control */ #define SOC_BLUFI_SUPPORTED (1) /*!< Support BLUFI */ + +#define SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND (1) From 5ec30e6fc24bec5bb545e74074d09d69beb9016d Mon Sep 17 00:00:00 2001 From: cjin Date: Thu, 13 Jul 2023 12:19:27 +0800 Subject: [PATCH 5/5] ble : remove extra retention cnt upon deinit temporarily --- components/bt/controller/esp32c6/bt.c | 10 ++++++++++ .../include/esp_private/sleep_retention.h | 2 ++ components/esp_hw_support/sleep_retention.c | 9 +++++++++ 3 files changed, 21 insertions(+) diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index 4923857579..c314a8a8bb 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -186,6 +186,10 @@ static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; /* This variable tells if BLE is running */ +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +static bool s_ble_backed_up = false; +#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE + static bool s_ble_active = false; #ifdef CONFIG_PM_ENABLE static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; @@ -470,6 +474,7 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER #if SOC_PM_RETENTION_HAS_CLOCK_BUG sleep_retention_do_extra_retention(true); + s_ble_backed_up = true; #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ esp_phy_disable(); @@ -491,6 +496,7 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER #if CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG sleep_retention_do_extra_retention(false); + s_ble_backed_up = false; #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG */ #endif //CONFIG_PM_ENABLE esp_phy_enable(); @@ -596,6 +602,10 @@ error: void controller_sleep_deinit(void) { #if CONFIG_FREERTOS_USE_TICKLESS_IDLE + if (s_ble_backed_up) { + sleep_retention_module_deinit(); + s_ble_backed_up = false; + } #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER r_ble_rtc_wake_up_state_clr(); esp_sleep_disable_bt_wakeup(); diff --git a/components/esp_hw_support/include/esp_private/sleep_retention.h b/components/esp_hw_support/include/esp_private/sleep_retention.h index 007f973f42..e64a95a9c0 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -108,6 +108,8 @@ void sleep_retention_entries_get(sleep_retention_entries_t *entries); * or false for restore to register from memory */ void sleep_retention_do_extra_retention(bool backup_or_restore); + +void sleep_retention_module_deinit(void); #endif /** diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index 562fd3158a..95e90d5e07 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -528,6 +528,15 @@ void sleep_retention_do_extra_retention(bool backup_or_restore) _lock_release_recursive(&s_retention.lock); assert(refs >= 0 && refs <= cnt_modules); } + +void sleep_retention_module_deinit(void) +{ + _lock_acquire_recursive(&s_retention.lock); + if (s_retention.extra_refs) { + s_retention.extra_refs--; + } + _lock_release_recursive(&s_retention.lock); +} #endif #if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG