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 bd822ebfbd..1aae8638e8 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 @@ -124,6 +124,13 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module); */ void modem_clock_wifi_mac_reset(void); +/** + * @brief Enable clock registers which shared by both modem and ADC. Need a ref count to enable/disable them + * + * @param enable true: enable; false: disable + */ +void modem_clock_shared_enable(bool enable); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 3ad811bdd6..16d08189b1 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -53,6 +53,9 @@ typedef struct modem_clock_context { modem_clock_lpclk_src_t lpclk_src[PERIPH_MODEM_MODULE_NUM]; } modem_clock_context_t; +extern portMUX_TYPE rtc_spinlock; + +static int modem_clock_apb_80m_cnt; #if SOC_WIFI_SUPPORTED static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx, bool enable) @@ -102,8 +105,32 @@ static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, boo static void IRAM_ATTR modem_clock_fe_configure(modem_clock_context_t *ctx, bool enable) { modem_clock_hal_enable_fe_clock(ctx->hal, enable); + modem_clock_shared_enable(enable); } +#if SOC_MODEM_CLOCK_IS_INDEPENDENT +void modem_clock_shared_enable(bool enable) +{ + if(enable) { + portENTER_CRITICAL_SAFE(&rtc_spinlock); + modem_clock_apb_80m_cnt++; + if (modem_clock_apb_80m_cnt == 1) { + modem_clock_hal_enable_shared_clock(true); + } + portEXIT_CRITICAL_SAFE(&rtc_spinlock); + } else { + portENTER_CRITICAL_SAFE(&rtc_spinlock); + modem_clock_apb_80m_cnt--; + if (modem_clock_apb_80m_cnt == 0) { + modem_clock_hal_enable_shared_clock(false); + } else if (modem_clock_apb_80m_cnt < 0) { + abort(); + } + portEXIT_CRITICAL_SAFE(&rtc_spinlock); + } +} +#endif // SOC_MODEM_CLOCK_IS_INDEPENDENT + static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) { modem_lpcon_ll_enable_i2c_master_clock(ctx->hal->lpcon_dev, enable); diff --git a/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c b/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c index c0b853124a..e4b4328d0e 100644 --- a/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c +++ b/components/esp_hw_support/port/esp32c6/sar_periph_ctrl.c @@ -18,6 +18,7 @@ #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "esp_private/sar_periph_ctrl.h" +#include "esp_private/esp_modem_clock.h" #include "hal/sar_ctrl_ll.h" static const char *TAG = "sar_periph_ctrl"; @@ -55,6 +56,7 @@ static int s_pwdet_power_on_cnt; static void s_sar_power_acquire(void) { + modem_clock_shared_enable(true); portENTER_CRITICAL_SAFE(&rtc_spinlock); s_pwdet_power_on_cnt++; if (s_pwdet_power_on_cnt == 1) { @@ -75,6 +77,7 @@ static void s_sar_power_release(void) sar_ctrl_ll_set_power_mode_from_pwdet(SAR_CTRL_LL_POWER_FSM); } portEXIT_CRITICAL_SAFE(&rtc_spinlock); + modem_clock_shared_enable(false); } diff --git a/components/hal/esp32c6/modem_clock_hal.c b/components/hal/esp32c6/modem_clock_hal.c index 553c7cbfac..7195d680e0 100644 --- a/components/hal/esp32c6/modem_clock_hal.c +++ b/components/hal/esp32c6/modem_clock_hal.c @@ -104,13 +104,17 @@ uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t * void modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable) { if (enable) { - modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_cal_160m_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_160m_clock(hal->syscon_dev, enable); - modem_syscon_ll_enable_fe_80m_clock(hal->syscon_dev, enable); } } +void IRAM_ATTR modem_clock_hal_enable_shared_clock(bool enable) +{ + modem_syscon_ll_enable_fe_apb_clock(&MODEM_SYSCON, enable); + modem_syscon_ll_enable_fe_80m_clock(&MODEM_SYSCON, enable); +} + void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider) { modem_lpcon_ll_set_ble_rtc_timer_divisor_value(hal->lpcon_dev, divider); diff --git a/components/hal/esp32h2/modem_clock_hal.c b/components/hal/esp32h2/modem_clock_hal.c index eb77e7b45b..0efb9fd09c 100644 --- a/components/hal/esp32h2/modem_clock_hal.c +++ b/components/hal/esp32h2/modem_clock_hal.c @@ -24,11 +24,15 @@ void modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable modem_lpcon_ll_enable_fe_mem_clock(hal->lpcon_dev, enable); modem_syscon_ll_enable_fe_sdm_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_adc_clock(hal->syscon_dev, enable); - modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_32m_clock(hal->syscon_dev, enable); modem_syscon_ll_enable_fe_16m_clock(hal->syscon_dev, enable); } +void IRAM_ATTR modem_clock_hal_enable_shared_clock(bool enable) +{ + modem_syscon_ll_enable_fe_apb_clock(&MODEM_SYSCON, enable); +} + void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider) { lp_clkrst_ll_set_ble_rtc_timer_divisor_value(&LP_CLKRST, divider); diff --git a/components/hal/include/hal/modem_clock_hal.h b/components/hal/include/hal/modem_clock_hal.h index 9e74e37d22..c744d51389 100644 --- a/components/hal/include/hal/modem_clock_hal.h +++ b/components/hal/include/hal/modem_clock_hal.h @@ -28,6 +28,7 @@ uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t * #endif void modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable); +void modem_clock_hal_enable_shared_clock(bool enable); #if SOC_BT_SUPPORTED void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider);