diff --git a/soc/st/stm32/stm32wbax/hci_if/linklayer_plat.c b/soc/st/stm32/stm32wbax/hci_if/linklayer_plat.c index 4f99a3e684875d..f67f5e79ed0696 100644 --- a/soc/st/stm32/stm32wbax/hci_if/linklayer_plat.c +++ b/soc/st/stm32/stm32wbax/hci_if/linklayer_plat.c @@ -30,6 +30,10 @@ typedef void (*radio_isr_cb_t) (void); radio_isr_cb_t radio_callback; radio_isr_cb_t low_isr_callback; +/* Radio bus clock control variables */ +uint8_t AHB5_SwitchedOff; +uint32_t radio_sleep_timer_val; + extern const struct device *rng_dev; /* Radio critical sections */ @@ -44,6 +48,9 @@ volatile uint8_t radio_sw_low_isr_is_running_high_prio; void LINKLAYER_PLAT_ClockInit(void) { + AHB5_SwitchedOff = 0; + radio_sleep_timer_val = 0; + LL_PWR_EnableBkUpAccess(); /* Select LSE as Sleep CLK */ @@ -314,3 +321,27 @@ void LINKLAYER_PLAT_SCHLDR_TIMING_UPDATE_NOT(Evnt_timing_t *p_evnt_timing) {} void LINKLAYER_PLAT_EnableOSContextSwitch(void) {} void LINKLAYER_PLAT_DisableOSContextSwitch(void) {} + +void LINKLAYER_PLAT_NotifyWFIEnter(void) +{ + /* Check if Radio state will allow the AHB5 clock to be cut */ + + /* AHB5 clock will be cut in the following cases: + * - 2.4GHz radio is not in ACTIVE mode (in SLEEP or DEEPSLEEP mode). + * - RADIOSMEN and STRADIOCLKON bits are at 0. + */ + if ((LL_PWR_GetRadioMode() != LL_PWR_RADIO_ACTIVE_MODE) || + ((__HAL_RCC_RADIO_IS_CLK_SLEEP_ENABLED() == 0) && + (LL_RCC_RADIO_IsEnabledSleepTimerClock() == 0))) { + AHB5_SwitchedOff = 1; + } +} + +void LINKLAYER_PLAT_NotifyWFIExit(void) +{ + /* Check if AHB5 clock has been turned of and needs resynchronisation */ + if (AHB5_SwitchedOff) { + /* Read sleep register as earlier as possible */ + radio_sleep_timer_val = ll_intf_cmn_get_slptmr_value(); + } +} diff --git a/soc/st/stm32/stm32wbax/hci_if/ll_sys_if.c b/soc/st/stm32/stm32wbax/hci_if/ll_sys_if.c index 8607cbbafd8dde..618d90e5e8ea17 100644 --- a/soc/st/stm32/stm32wbax/hci_if/ll_sys_if.c +++ b/soc/st/stm32/stm32wbax/hci_if/ll_sys_if.c @@ -14,11 +14,17 @@ LOG_MODULE_REGISTER(ll_sys_if); #include "ll_sys.h" #include "linklayer_plat.h" #include "app_conf.h" +#include "ll_intf_cmn.h" +#include "utilities_common.h" extern struct k_mutex ble_ctlr_stack_mutex; extern struct k_work_q ll_work_q; struct k_work ll_sys_work; +static void ll_sys_sleep_clock_source_selection(void); + +void ll_sys_reset(void); + void ll_sys_schedule_bg_process(void) { k_work_submit_to_queue(&ll_work_q, &ll_sys_work); @@ -45,3 +51,83 @@ void ll_sys_config_params(void) { ll_intf_config_ll_ctx_params(USE_RADIO_LOW_ISR, NEXT_EVENT_SCHEDULING_FROM_ISR); } + +#if (CFG_RADIO_LSE_SLEEP_TIMER_CUSTOM_SCA_RANGE == 0) +uint8_t ll_sys_BLE_sleep_clock_accuracy_selection(void) +{ + uint8_t BLE_sleep_clock_accuracy = 0; + uint32_t RevID = LL_DBGMCU_GetRevisionID(); + uint32_t linklayer_slp_clk_src = LL_RCC_RADIO_GetSleepTimerClockSource(); + + if (linklayer_slp_clk_src == LL_RCC_RADIOSLEEPSOURCE_LSE) { + /* LSE selected as Link Layer sleep clock source. */ + /* Sleep clock accuracy is different regarding the WBA device ID and revision */ +#if defined(STM32WBA52xx) || defined(STM32WBA54xx) || defined(STM32WBA55xx) + if (RevID == REV_ID_A) { + BLE_sleep_clock_accuracy = STM32WBA5x_REV_ID_A_SCA_RANGE; + } else if (RevID == REV_ID_B) { + BLE_sleep_clock_accuracy = STM32WBA5x_REV_ID_B_SCA_RANGE; + } else { + /* Revision ID not supported, default value of 500ppm applied */ + BLE_sleep_clock_accuracy = STM32WBA5x_DEFAULT_SCA_RANGE; + } +#else + UNUSED(RevID); +#endif + /* defined(STM32WBA52xx) || defined(STM32WBA54xx) || defined(STM32WBA55xx) */ + } else { + /* LSE is not the Link Layer sleep clock source, sleep clock accurcay + * default value is 500 ppm */ + BLE_sleep_clock_accuracy = STM32WBA5x_DEFAULT_SCA_RANGE; + } + + return BLE_sleep_clock_accuracy; +} +#endif /* CFG_RADIO_LSE_SLEEP_TIMER_CUSTOM_SCA_RANGE */ + +void ll_sys_sleep_clock_source_selection(void) +{ + uint16_t freq_value = 0; + uint32_t linklayer_slp_clk_src = LL_RCC_RADIOSLEEPSOURCE_NONE; + + linklayer_slp_clk_src = LL_RCC_RADIO_GetSleepTimerClockSource(); + switch(linklayer_slp_clk_src) { + case LL_RCC_RADIOSLEEPSOURCE_LSE: + linklayer_slp_clk_src = RTC_SLPTMR; + break; + + case LL_RCC_RADIOSLEEPSOURCE_LSI: + linklayer_slp_clk_src = RCO_SLPTMR; + break; + + case LL_RCC_RADIOSLEEPSOURCE_HSE_DIV1000: + linklayer_slp_clk_src = CRYSTAL_OSCILLATOR_SLPTMR; + break; + + case LL_RCC_RADIOSLEEPSOURCE_NONE: + /* No Link Layer sleep clock source selected */ + assert_param(0); + break; + } + ll_intf_cmn_le_select_slp_clk_src((uint8_t)linklayer_slp_clk_src, &freq_value); +} + +void ll_sys_reset(void) +{ +#if (CFG_RADIO_LSE_SLEEP_TIMER_CUSTOM_SCA_RANGE == 0) + uint8_t bsca = 0; +#endif /* CFG_RADIO_LSE_SLEEP_TIMER_CUSTOM_SCA_RANGE */ + + /* Apply the selected link layer sleep timer source */ + ll_sys_sleep_clock_source_selection(); + + /* Configure the link layer sleep clock accuracy if different from the default one */ +#if (CFG_RADIO_LSE_SLEEP_TIMER_CUSTOM_SCA_RANGE != 0) + ll_intf_le_set_sleep_clock_accuracy(CFG_RADIO_LSE_SLEEP_TIMER_CUSTOM_SCA_RANGE); +#else + bsca = ll_sys_BLE_sleep_clock_accuracy_selection(); + if (bsca != STM32WBA5x_DEFAULT_SCA_RANGE) { + ll_intf_le_set_sleep_clock_accuracy(bsca); + } +#endif /* CFG_RADIO_LSE_SLEEP_TIMER_CUSTOM_SCA_RANGE */ +} diff --git a/west.yml b/west.yml index a20edb3c48779c..7512e403a32e52 100644 --- a/west.yml +++ b/west.yml @@ -233,7 +233,7 @@ manifest: groups: - hal - name: hal_stm32 - revision: 6f0e5f70cb540c487e3e3678af2e95d0937f9863 + revision: pull/237/head path: modules/hal/stm32 groups: - hal