diff --git a/components/bt/controller/esp32c6/Kconfig.in b/components/bt/controller/esp32c6/Kconfig.in index 577123d8e5..db991124dd 100644 --- a/components/bt/controller/esp32c6/Kconfig.in +++ b/components/bt/controller/esp32c6/Kconfig.in @@ -395,6 +395,26 @@ choice BT_LE_WAKEUP_SOURCE Use BLE rtc timer to wakeup CPU endchoice +choice BT_LE_LP_CLK_SRC + prompt "BLE low power clock source" + default BT_LE_LP_CLK_SRC_MAIN_XTAL + config BT_LE_LP_CLK_SRC_MAIN_XTAL + bool "Use main XTAL as RTC clock source" + help + User main XTAL as RTC clock source. + This option is recommended if external 32.768k XTAL is not available. + Using the external 32.768 kHz XTAL will have lower current consumption + in light sleep compared to using the main XTAL. + + config BT_LE_LP_CLK_SRC_DEFAULT + bool "Use system RTC slow clock source" + help + Use the same slow clock source as system RTC + Using any clock source other than external 32.768 kHz XTAL supports only + legacy ADV and SCAN due to low clock accuracy. + +endchoice + config BT_LE_USE_ESP_TIMER bool "Enable Esp Timer for Callout" depends on !BT_NIMBLE_ENABLED diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index c6a37dd7ab..4cd73dbc78 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -40,6 +40,10 @@ #include "hci_uart.h" #include "bt_osi_mem.h" +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#include "esp_private/sleep_retention.h" +#endif + #ifdef CONFIG_BT_BLUEDROID_ENABLED #include "hci/hci_hal.h" #endif // CONFIG_BT_BLUEDROID_ENABLED @@ -126,7 +130,10 @@ extern uint32_t r_os_cputime_get32(void); extern uint32_t r_os_cputime_ticks_to_usecs(uint32_t ticks); extern void ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, void *w_arg, uint32_t us_to_enabled); -extern void ble_rtc_wake_up_state_clr(void); +extern void r_ble_rtc_wake_up_state_clr(void); +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +extern const sleep_retention_entries_config_t *esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ extern int os_msys_init(void); extern void os_msys_buf_free(void); extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, @@ -186,11 +193,13 @@ static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; #endif // CONFIG_PM_ENABLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER -#define BLE_RTC_DELAY_US (1100) +#define BLE_RTC_DELAY_US_LIGHT_SLEEP (2500) +#define BLE_RTC_DELAY_US_MODEM_SLEEP (500) #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER -#define BLE_RTC_DELAY_US (0) +#define BLE_RTC_DELAY_US_LIGHT_SLEEP (2000) +#define BLE_RTC_DELAY_US_MODEM_SLEEP (0) static void ble_sleep_timer_callback(void *arg); static DRAM_ATTR esp_timer_handle_t s_ble_sleep_timer = NULL; #endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER @@ -429,8 +438,7 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) if (!s_ble_active) { return; } - -#ifdef CONFIG_PM_ENABLE +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER uint32_t delta_tick; uint32_t us_to_sleep; @@ -451,7 +459,7 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) esp_err_t err = esp_timer_start_once(s_ble_sleep_timer, us_to_sleep - BTDM_MIN_TIMER_UNCERTAINTY_US); if (err != ESP_OK) { - ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ESP timer start failed\n"); + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ESP timer start failed"); return; } } @@ -460,11 +468,14 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER r_ble_rtc_wake_up_state_clr(); #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - +#if SOC_PM_RETENTION_HAS_CLOCK_BUG + sleep_retention_do_extra_retention(true); +#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ + esp_phy_disable(); +#ifdef CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); #endif // CONFIG_PM_ENABLE - - esp_phy_disable(); s_ble_active = false; } @@ -473,37 +484,57 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) if (s_ble_active) { return; } - esp_phy_enable(); - #ifdef CONFIG_PM_ENABLE +#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER esp_pm_lock_acquire(s_pm_lock); + r_ble_rtc_wake_up_state_clr(); +#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); +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG */ #endif //CONFIG_PM_ENABLE - + esp_phy_enable(); s_ble_active = true; } -#ifdef CONFIG_PM_ENABLE +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER static void ble_sleep_timer_callback(void * arg) { + esp_pm_lock_acquire(s_pm_lock); +} +#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER +esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) +{ + uint8_t size; + const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra); + esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BLE_MAC); + if (err == ESP_OK) { + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Modem BLE MAC retention initialization"); + } + return err; } -#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER -#endif // CONFIG_PM_ENABLE +static void sleep_modem_ble_mac_modem_state_deinit(void) +{ + sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_MAC); +} +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ esp_err_t controller_sleep_init(void) { esp_err_t rc = 0; #ifdef CONFIG_BT_LE_SLEEP_ENABLE - ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled\n"); + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled"); +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0, - 500 + BLE_RTC_DELAY_US); - -#ifdef CONFIG_PM_ENABLE - esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON); -#endif // CONFIG_PM_ENABLE + BLE_RTC_DELAY_US_LIGHT_SLEEP); +#else + ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0, + BLE_RTC_DELAY_US_MODEM_SLEEP); +#endif /* FREERTOS_USE_TICKLESS_IDLE */ #endif // CONFIG_BT_LE_SLEEP_ENABLE #ifdef CONFIG_PM_ENABLE @@ -512,7 +543,7 @@ esp_err_t controller_sleep_init(void) goto error; } esp_pm_lock_acquire(s_pm_lock); - +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER esp_timer_create_args_t create_args = { .callback = ble_sleep_timer_callback, @@ -526,20 +557,23 @@ esp_err_t controller_sleep_init(void) ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is ESP timer"); #endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER + /* Create a new regdma link for BLE related register restoration */ + rc = sleep_modem_ble_mac_modem_state_init(1); + assert(rc == 0); #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); #endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ return rc; error: - /*lock should release first and then delete*/ - if (s_pm_lock != NULL) { - esp_pm_lock_release(s_pm_lock); - esp_pm_lock_delete(s_pm_lock); - s_pm_lock = NULL; - } + +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER + esp_sleep_disable_bt_wakeup(); +#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER + #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER if (s_ble_sleep_timer != NULL) { esp_timer_stop(s_ble_sleep_timer); @@ -547,34 +581,26 @@ error: s_ble_sleep_timer = NULL; } #endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER - -#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - esp_sleep_disable_bt_wakeup(); -#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - -#endif //CONFIG_PM_ENABLE +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ + /*lock should release first and then delete*/ + if (s_pm_lock != NULL) { + esp_pm_lock_release(s_pm_lock); + esp_pm_lock_delete(s_pm_lock); + s_pm_lock = NULL; + } +#endif // CONFIG_PM_ENABLE return rc; } void controller_sleep_deinit(void) { -#ifdef CONFIG_PM_ENABLE +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER r_ble_rtc_wake_up_state_clr(); esp_sleep_disable_bt_wakeup(); #endif //CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER - - esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_AUTO); - - /* lock should be released first */ - if (s_ble_active) { - esp_pm_lock_release(s_pm_lock); - } - - esp_pm_lock_delete(s_pm_lock); - s_pm_lock = NULL; - + sleep_modem_ble_mac_modem_state_deinit(); #ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER if (s_ble_sleep_timer != NULL) { esp_timer_stop(s_ble_sleep_timer); @@ -582,6 +608,12 @@ void controller_sleep_deinit(void) s_ble_sleep_timer = NULL; } #endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#ifdef CONFIG_PM_ENABLE + /* lock should be released first */ + esp_pm_lock_release(s_pm_lock); + esp_pm_lock_delete(s_pm_lock); + s_pm_lock = NULL; #endif //CONFIG_PM_ENABLE } @@ -647,15 +679,36 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) */ ble_npl_eventq_init(nimble_port_get_dflt_eventq()); #endif // CONFIG_BT_NIMBLE_ENABLED - /* Enable BT-related clocks */ modem_clock_module_enable(PERIPH_BT_MODULE); + + /* Select slow clock source for BT momdule */ +#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); chip_version = efuse_hal_chip_revision(); if (chip_version == 0) { - modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, (160 - 1)); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, (400 - 1)); } else{ - modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, (2 - 1)); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, (5 - 1)); } +#else +#if CONFIG_RTC_CLK_SRC_INT_RC + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_RC_SLOW, (5 - 1)); +#elif CONFIG_RTC_CLK_SRC_EXT_CRYS + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using external 32.768 kHz XTAL as clock source"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_XTAL32K, (1 - 1)); +#elif CONFIG_RTC_CLK_SRC_INT_RC32K + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_RC32K, (1 - 1)); +#elif CONFIG_RTC_CLK_SRC_EXT_OSC + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz oscillator as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_EXT32K, (1 - 1)); +#else + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source"); + assert(0); +#endif +#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ esp_phy_modem_init(); esp_phy_enable(); esp_btbb_enable(); @@ -682,7 +735,6 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGW(NIMBLE_PORT_LOG_TAG, "controller_sleep_init failed %d", ret); goto free_controller; } - ESP_ERROR_CHECK(esp_read_mac((uint8_t *)mac, ESP_MAC_BT)); swap_in_place(mac, 6); esp_ble_ll_set_public_addr(mac); diff --git a/components/bt/include/esp32c6/include/esp_bt_cfg.h b/components/bt/include/esp32c6/include/esp_bt_cfg.h index 658e39ae4e..3d5506b892 100644 --- a/components/bt/include/esp32c6/include/esp_bt_cfg.h +++ b/components/bt/include/esp32c6/include/esp_bt_cfg.h @@ -196,7 +196,17 @@ extern "C" { #define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N (3000) -#define RTC_FREQ_N (250000) /* in Hz */ +#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL +#define RTC_FREQ_N (100000) /* in Hz */ +#else +#if CONFIG_RTC_CLK_SRC_INT_RC +#define RTC_FREQ_N (30000) /* in Hz */ +#elif CONFIG_RTC_CLK_SRC_EXT_CRYS +#define RTC_FREQ_N (32768) /* in Hz */ +#else +#define RTC_FREQ_N (32000) /* in Hz */ +#endif +#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ #define BLE_LL_TX_PWR_DBM_N (9) diff --git a/components/esp_hw_support/include/esp_private/esp_regdma.h b/components/esp_hw_support/include/esp_private/esp_regdma.h index 85a3fe8386..b1f0115556 100644 --- a/components/esp_hw_support/include/esp_private/esp_regdma.h +++ b/components/esp_hw_support/include/esp_private/esp_regdma.h @@ -39,6 +39,8 @@ extern "C" { #define REGDMA_IOMUX_LINK(_pri) ((0x12 << 8) | _pri) #define REGDMA_SPIMEM_LINK(_pri) ((0x13 << 8) | _pri) #define REGDMA_SYSTIMER_LINK(_pri) ((0x14 << 8) | _pri) +#define REGDMA_BLE_MAC_LINK(_pri) ((0x15 << 8) | _pri) +#define REGDMA_MODEM_BT_BB_LINK(_pri) ((0x16 << 8) | _pri) #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) typedef enum { diff --git a/components/esp_hw_support/sleep_clock.c b/components/esp_hw_support/sleep_clock.c index c504a801e4..47866bfc32 100644 --- a/components/esp_hw_support/sleep_clock.c +++ b/components/esp_hw_support/sleep_clock.c @@ -68,21 +68,21 @@ bool IRAM_ATTR clock_domain_pd_allowed(void) const uint32_t modules = sleep_retention_get_modules(); const uint32_t mask = (const uint32_t) ( SLEEP_RETENTION_MODULE_CLOCK_SYSTEM -#if CONFIG_MAC_BB_PD +#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE | SLEEP_RETENTION_MODULE_CLOCK_MODEM #endif ); return ((modules & mask) == mask); } -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP || CONFIG_MAC_BB_PD +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP || CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, BIT(0), 106) { #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP sleep_clock_system_retention_init(); #endif -#if CONFIG_MAC_BB_PD +#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE sleep_clock_modem_retention_init(); #endif return ESP_OK; diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c index 6f8994d2e6..6b732bcf75 100644 --- a/components/esp_hw_support/sleep_modem.c +++ b/components/esp_hw_support/sleep_modem.c @@ -276,8 +276,15 @@ bool IRAM_ATTR modem_domain_pd_allowed(void) { #if SOC_PM_MODEM_RETENTION_BY_REGDMA const uint32_t modules = sleep_retention_get_modules(); - const uint32_t mask = (const uint32_t) (SLEEP_RETENTION_MODULE_WIFI_MAC | SLEEP_RETENTION_MODULE_WIFI_BB); - return ((modules & mask) == mask); + const uint32_t mask_wifi = (const uint32_t) (SLEEP_RETENTION_MODULE_WIFI_MAC | + SLEEP_RETENTION_MODULE_WIFI_BB); + const uint32_t mask_ble = (const uint32_t) (SLEEP_RETENTION_MODULE_BLE_MAC | + SLEEP_RETENTION_MODULE_BLE_BB); + const uint32_t mask_154 = (const uint32_t) (SLEEP_RETENTION_MODULE_802154_MAC | + SLEEP_RETENTION_MODULE_802154_BB); + return (((modules & mask_wifi) == mask_wifi) || + ((modules & mask_ble) == mask_ble) || + ((modules & mask_154) == mask_154)); #else return false; /* MODEM power domain is controlled by each module (WiFi, Bluetooth or 15.4) of modem */ #endif diff --git a/components/esp_phy/esp32c6/include/btbb_retention_reg.h b/components/esp_phy/esp32c6/include/btbb_retention_reg.h new file mode 100644 index 0000000000..54a3b3d193 --- /dev/null +++ b/components/esp_phy/esp32c6/include/btbb_retention_reg.h @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +// btbb sleep retention reg + +#define BB_PART_0_SIZE 93 +#define BB_PART_1_SIZE 62 +#define BB_PART_2_SIZE 19 +#define BB_PART_0_ADDR 0x600A2000 +#define BB_PART_1_ADDR 0x600A2800 +#define BB_PART_2_ADDR 0x600A2C00 + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_phy/src/btbb_init.c b/components/esp_phy/src/btbb_init.c index 726afd0e9d..efe7b19013 100644 --- a/components/esp_phy/src/btbb_init.c +++ b/components/esp_phy/src/btbb_init.c @@ -5,6 +5,8 @@ */ #include +#include "esp_check.h" +#include "esp_log.h" #include "freertos/FreeRTOS.h" #include "esp_private/btbb.h" @@ -14,11 +16,46 @@ static _lock_t s_btbb_access_lock; /* Reference count of enabling BT BB */ static uint8_t s_btbb_access_ref = 0; + +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE +#include "esp_private/sleep_retention.h" +#include "btbb_retention_reg.h" +static const char* TAG = "btbb_init"; + +#if SOC_PM_RETENTION_HAS_CLOCK_BUG +#define BTBB_LINK_OWNER ENTRY(3) +#else +#define BTBB_LINK_OWNER ENTRY(0) | ENTRY(2) +#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG + +static esp_err_t btbb_sleep_retention_init(void) +{ + const static sleep_retention_entries_config_t btbb_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_BT_BB_LINK(0x00), BB_PART_0_ADDR, BB_PART_0_ADDR, BB_PART_0_SIZE, 0, 0), .owner = BTBB_LINK_OWNER }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_BT_BB_LINK(0x01), BB_PART_1_ADDR, BB_PART_1_ADDR, BB_PART_1_SIZE, 0, 0), .owner = BTBB_LINK_OWNER }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_BT_BB_LINK(0x02), BB_PART_2_ADDR, BB_PART_2_ADDR, BB_PART_2_SIZE, 0, 0), .owner = BTBB_LINK_OWNER } + }; + esp_err_t err = sleep_retention_entries_create(btbb_regs_retention, ARRAY_SIZE(btbb_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BLE_BB); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for btbb retention"); + ESP_LOGI(TAG, "btbb sleep retention initialization"); + return ESP_OK; +} + +static void btbb_sleep_retention_deinit(void) +{ + sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_BB); +} +#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE + + void esp_btbb_enable(void) { _lock_acquire(&s_btbb_access_lock); if (s_btbb_access_ref == 0) { bt_bb_v2_init_cmplx(BTBB_ENABLE_VERSION_PRINT); +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE + btbb_sleep_retention_init(); +#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE } s_btbb_access_ref++; _lock_release(&s_btbb_access_lock); @@ -27,8 +64,10 @@ void esp_btbb_enable(void) void esp_btbb_disable(void) { _lock_acquire(&s_btbb_access_lock); - if (s_btbb_access_ref > 0) { - s_btbb_access_ref--; + if (s_btbb_access_ref && (--s_btbb_access_ref == 0)) { +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE + btbb_sleep_retention_deinit(); +#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE } _lock_release(&s_btbb_access_lock); }