fix(esp_hw_support): maintain pll ref_cnt in rtc_clk_cpu_freq_set_config_fast

This commit is contained in:
wuzhenghui
2025-07-04 16:58:38 +08:00
parent ff39ac40a1
commit 6124c8e30c
4 changed files with 83 additions and 54 deletions

View File

@@ -318,6 +318,7 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config);
*/
void rtc_clk_cpu_freq_set_xtal(void);
#ifndef BOOTLOADER_BUILD
/**
* @brief Switch root clock source to PLL (only used by sleep) release root clock source locked by PMU
*
@@ -330,6 +331,7 @@ void rtc_clk_cpu_freq_set_xtal(void);
* @param[in] Maximum CPU frequency, in MHz
*/
void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz);
#endif
/**
* @brief Get the current APB frequency.

View File

@@ -17,6 +17,12 @@
#include "hal/efuse_hal.h"
#include "esp_hw_log.h"
#define PMU_CLK_SRC_VAL(src) \
(((uint32_t)src == (uint32_t)SOC_MOD_CLK_XTAL) ? 0 : \
((uint32_t)src == (uint32_t)SOC_MOD_CLK_RC_FAST) ? 1 : \
((uint32_t)src == (uint32_t)SOC_MOD_CLK_PLL_F160M) ? 2 : \
((uint32_t)src == (uint32_t)SOC_MOD_CLK_PLL_F240M) ? 3 : 0)
static __attribute__((unused)) const char *TAG = "pmu_param";
#ifndef ARRAY_SIZE
@@ -111,7 +117,7 @@ const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mod
.icg_sysclk_en = 1, \
.sysclk_slp_sel = 0, \
.icg_slp_sel = 0, \
.dig_sysclk_sel = SOC_CPU_CLK_SRC_XTAL \
.dig_sysclk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL) \
} \
}
@@ -127,7 +133,7 @@ const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mod
.icg_sysclk_en = 1, \
.sysclk_slp_sel = 1, \
.icg_slp_sel = 1, \
.dig_sysclk_sel = SOC_CPU_CLK_SRC_PLL_F160M \
.dig_sysclk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_PLL_F160M) \
} \
}
@@ -142,7 +148,7 @@ const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mod
.icg_sysclk_en = 0, \
.sysclk_slp_sel = 1, \
.icg_slp_sel = 1, \
.dig_sysclk_sel = SOC_CPU_CLK_SRC_XTAL \
.dig_sysclk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL) \
} \
}
@@ -289,8 +295,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m
.hp_active_retention_mode = 0, \
.hp_sleep2active_retention_en = 0, \
.hp_modem2active_retention_en = 0, \
.hp_sleep2active_backup_clk_sel = SOC_CPU_CLK_SRC_XTAL, \
.hp_modem2active_backup_clk_sel = SOC_CPU_CLK_SRC_PLL_F160M, \
.hp_sleep2active_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL), \
.hp_modem2active_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_CPU_CLK_SRC_PLL_F160M), \
.hp_sleep2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 0), \
.hp_modem2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 2), \
.hp_sleep2active_backup_en = 0, \
@@ -304,7 +310,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m
.hp_sleep2modem_backup_modem_clk_code = 1, \
.hp_modem_retention_mode = 0, \
.hp_sleep2modem_retention_en = 0, \
.hp_sleep2modem_backup_clk_sel = SOC_CPU_CLK_SRC_XTAL, \
.hp_sleep2modem_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL), \
.hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \
.hp_sleep2modem_backup_en = 0, \
}, \
@@ -318,8 +324,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m
.hp_sleep_retention_mode = 0, \
.hp_modem2sleep_retention_en = 0, \
.hp_active2sleep_retention_en = 0, \
.hp_modem2sleep_backup_clk_sel = SOC_CPU_CLK_SRC_XTAL, \
.hp_active2sleep_backup_clk_sel = SOC_CPU_CLK_SRC_XTAL, \
.hp_modem2sleep_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL), \
.hp_active2sleep_backup_clk_sel = PMU_CLK_SRC_VAL(SOC_MOD_CLK_XTAL), \
.hp_modem2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 1), \
.hp_active2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 0), \
.hp_modem2sleep_backup_en = 0, \

View File

@@ -303,10 +303,10 @@ __attribute__((weak)) void rtc_clk_set_cpu_switch_to_pll(int event_id)
{
}
static void rtc_clk_update_pll_state_on_cpu_src_switching_start(soc_cpu_clk_src_t old_src, soc_cpu_clk_src_t new_src)
static void rtc_clk_update_pll_state_on_cpu_src_switching_start(soc_cpu_clk_src_t old_src, soc_cpu_clk_src_t new_src, bool fast_switching)
{
if ((new_src == SOC_CPU_CLK_SRC_PLL_F160M) || (new_src == SOC_CPU_CLK_SRC_PLL_F240M)) {
if (s_cur_pll_freq != CLK_LL_PLL_480M_FREQ_MHZ) {
if ((s_cur_pll_freq != CLK_LL_PLL_480M_FREQ_MHZ) && !fast_switching) {
rtc_clk_bbpll_enable();
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ);
}
@@ -316,13 +316,13 @@ static void rtc_clk_update_pll_state_on_cpu_src_switching_start(soc_cpu_clk_src_
}
}
static void rtc_clk_update_pll_state_on_cpu_switching_end(soc_cpu_clk_src_t old_src, soc_cpu_clk_src_t new_src)
static void rtc_clk_update_pll_state_on_cpu_src_switching_end(soc_cpu_clk_src_t old_src, soc_cpu_clk_src_t new_src, bool fast_switching)
{
if ((old_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_src == SOC_CPU_CLK_SRC_PLL_F240M)) {
#ifndef BOOTLOADER_BUILD
esp_clk_tree_enable_src((old_src == SOC_CPU_CLK_SRC_PLL_F240M) ? SOC_MOD_CLK_PLL_F240M : SOC_MOD_CLK_PLL_F160M, false);
#endif
if ((new_src != SOC_CPU_CLK_SRC_PLL_F160M) && (new_src != SOC_CPU_CLK_SRC_PLL_F240M) && !s_bbpll_digi_consumers_ref_count) {
if ((new_src != SOC_CPU_CLK_SRC_PLL_F160M) && (new_src != SOC_CPU_CLK_SRC_PLL_F240M) && !s_bbpll_digi_consumers_ref_count && !fast_switching) {
// We don't turn off the bbpll if some consumers depend on bbpll
rtc_clk_bbpll_disable();
}
@@ -333,7 +333,7 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
{
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
if (old_cpu_clk_src != config->source) {
rtc_clk_update_pll_state_on_cpu_src_switching_start(old_cpu_clk_src, config->source);
rtc_clk_update_pll_state_on_cpu_src_switching_start(old_cpu_clk_src, config->source, false);
}
if (config->source == SOC_CPU_CLK_SRC_XTAL) {
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
@@ -349,7 +349,7 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
rtc_clk_cpu_freq_to_rc_fast();
}
if (old_cpu_clk_src != config->source) {
rtc_clk_update_pll_state_on_cpu_switching_end(old_cpu_clk_src, config->source);
rtc_clk_update_pll_state_on_cpu_src_switching_end(old_cpu_clk_src, config->source, false);
}
}
@@ -389,16 +389,25 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
{
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
if (config->source == SOC_CPU_CLK_SRC_XTAL) {
rtc_clk_update_pll_state_on_cpu_src_switching_start(old_cpu_clk_src, config->source, true);
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
rtc_clk_update_pll_state_on_cpu_src_switching_end(old_cpu_clk_src, config->source, true);
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F160M &&
s_cur_pll_freq == CLK_LL_PLL_480M_FREQ_MHZ) {
rtc_clk_update_pll_state_on_cpu_src_switching_start(old_cpu_clk_src, config->source, true);
rtc_clk_cpu_freq_to_pll_160_mhz(config->freq_mhz);
rtc_clk_update_pll_state_on_cpu_src_switching_end(old_cpu_clk_src, config->source, true);
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M &&
s_cur_pll_freq == CLK_LL_PLL_480M_FREQ_MHZ) {
rtc_clk_update_pll_state_on_cpu_src_switching_start(old_cpu_clk_src, config->source, true);
rtc_clk_cpu_freq_to_pll_240_mhz(config->freq_mhz);
rtc_clk_update_pll_state_on_cpu_src_switching_end(old_cpu_clk_src, config->source, true);
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
rtc_clk_update_pll_state_on_cpu_src_switching_start(old_cpu_clk_src, config->source, true);
rtc_clk_cpu_freq_to_rc_fast();
rtc_clk_update_pll_state_on_cpu_src_switching_end(old_cpu_clk_src, config->source, true);
} else {
/* fallback */
rtc_clk_cpu_freq_set_config(config);
@@ -414,8 +423,13 @@ void rtc_clk_cpu_freq_set_xtal(void)
void rtc_clk_cpu_set_to_default_config(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
#ifndef BOOTLOADER_BUILD
soc_module_clk_t old_cpu_clk_src = (soc_module_clk_t)clk_ll_cpu_get_src();
#endif
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
#ifndef BOOTLOADER_BUILD
esp_clk_tree_enable_src(old_cpu_clk_src, false);
#endif
s_cur_pll_freq = 0; // no disable PLL, but set freq to 0 to trigger a PLL calibration after wake-up from sleep
}
@@ -424,26 +438,33 @@ void rtc_clk_cpu_freq_set_xtal_for_sleep(void)
rtc_clk_cpu_set_to_default_config();
}
#ifndef BOOTLOADER_BUILD
void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz)
{
// IDF-11064
if (cpu_freq_mhz == 240) {
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F240M, true);
rtc_clk_cpu_freq_to_pll_240_mhz(cpu_freq_mhz);
} else if (cpu_freq_mhz == 160) {
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F160M, true);
rtc_clk_cpu_freq_to_pll_160_mhz(cpu_freq_mhz);
} else {// cpu_freq_mhz is 80
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 101)) {// (use 240mhz pll if max cpu freq is 240MHz)
#if CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F240M, true);
rtc_clk_cpu_freq_to_pll_240_mhz(cpu_freq_mhz);
#else
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F160M, true);
rtc_clk_cpu_freq_to_pll_160_mhz(cpu_freq_mhz);
#endif
} else {// (fixed for chip rev. >= ECO3)
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F160M, true);
rtc_clk_cpu_freq_to_pll_160_mhz(cpu_freq_mhz);
}
}
clk_ll_cpu_clk_src_lock_release();
}
#endif
soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
{

View File

@@ -72,16 +72,50 @@ typedef enum {
SOC_ROOT_CIRCUIT_CLK_BBPLL, /*!< BBPLL_CLK is the output of the PLL generator circuit */
} soc_root_clk_circuit_t;
// Naming convention: SOC_MOD_CLK_{[upstream]clock_name}_[attr]
// {[upstream]clock_name}: XTAL, (BB)PLL, etc.
// [attr] - optional: FAST, SLOW, D<divider>, F<freq>
/**
* @brief Supported clock sources for modules (CPU, peripherals, RTC, etc.)
*
* @note enum starts from 1, to save 0 for special purpose
*/
typedef enum {
// For CPU domain
SOC_MOD_CLK_CPU = 1, /*!< CPU_CLK can be sourced from XTAL, PLL, or RC_FAST by configuring soc_cpu_clk_src_t */
// For RTC domain
SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL_D2 or RC_FAST by configuring soc_rtc_fast_clk_src_t */
SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, or OSC_SLOW by configuring soc_rtc_slow_clk_src_t */
// For digital domain: peripherals, WIFI, BLE
SOC_MOD_CLK_PLL_F12M, /*!< PLL_F12M_CLK is derived from SPLL (clock gating + fixed divider of 40), it has a fixed frequency of 12MHz */
SOC_MOD_CLK_PLL_F20M, /*!< PLL_F20M_CLK is derived from SPLL (clock gating + fixed divider of 24), it has a fixed frequency of 20MHz */
SOC_MOD_CLK_PLL_F40M, /*!< PLL_F40M_CLK is derived from SPLL (clock gating + fixed divider of 12), it has a fixed frequency of 40MHz */
SOC_MOD_CLK_PLL_F48M, /*!< PLL_F48M_CLK is derived from SPLL (clock gating + fixed divider of 10), it has a fixed frequency of 48MHz */
SOC_MOD_CLK_PLL_F60M, /*!< PLL_F60M_CLK is derived from SPLL (clock gating + fixed divider of 8), it has a fixed frequency of 60MHz */
SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from SPLL (clock gating + fixed divider of 6), it has a fixed frequency of 80MHz */
SOC_MOD_CLK_PLL_F120M, /*!< PLL_F120M_CLK is derived from SPLL (clock gating + fixed divider of 4), it has a fixed frequency of 120MHz */
SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from SPLL (clock gating + fixed divider of 3), it has a fixed frequency of 160MHz */
SOC_MOD_CLK_MODEM_APB = SOC_MOD_CLK_PLL_F160M, /*!< Modem APB clock comes from the CLK_160M_REF */
SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from SPLL (clock gating + fixed divider of 2), it has a fixed frequency of 240MHz */
SOC_MOD_CLK_SPLL, /*!< SPLL is from the main XTAL oscillator frequency multipliers, it has a "fixed" frequency of 480MHz */
SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */
SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */
SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 48MHz crystal */
// For LP peripherals
SOC_MOD_CLK_XTAL_D2, /*!< XTAL_D2_CLK comes from the external 48MHz crystal, passing a div of 2 to the LP peripherals */
SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */
} soc_module_clk_t;
/**
* @brief CPU_CLK mux inputs, which are the supported clock sources for the CPU_CLK
* @note Enum values are matched with the register field values on purpose
*/
typedef enum {
SOC_CPU_CLK_SRC_XTAL = 0, /*!< Select XTAL_CLK as CPU_CLK source */
SOC_CPU_CLK_SRC_RC_FAST = 1, /*!< Select RC_FAST_CLK as CPU_CLK source */
SOC_CPU_CLK_SRC_PLL_F160M = 2, /*!< Select PLL_F160M_CLK as CPU_CLK source (PLL_F160M_CLK is derived from SPLL (480MHz), which is the output of the main crystal oscillator frequency multiplier) */
SOC_CPU_CLK_SRC_PLL_F240M = 3, /*!< Select PLL_F240M_CLK as CPU_CLK source (PLL_F240M_CLK is derived from SPLL (480MHz), which is the output of the main crystal oscillator frequency multiplier) */
SOC_CPU_CLK_SRC_INVALID, /*!< Invalid CPU_CLK source */
SOC_CPU_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL_CLK as CPU_CLK source */
SOC_CPU_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST_CLK as CPU_CLK source */
SOC_CPU_CLK_SRC_PLL_F160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M_CLK as CPU_CLK source (PLL_F160M_CLK is derived from SPLL (480MHz), which is the output of the main crystal oscillator frequency multiplier) */
SOC_CPU_CLK_SRC_PLL_F240M = SOC_MOD_CLK_PLL_F240M, /*!< Select PLL_F240M_CLK as CPU_CLK source (PLL_F240M_CLK is derived from SPLL (480MHz), which is the output of the main crystal oscillator frequency multiplier) */
SOC_CPU_CLK_SRC_INVALID = SOC_MOD_CLK_INVALID, /*!< Invalid CPU_CLK source */
} soc_cpu_clk_src_t;
/**
@@ -119,40 +153,6 @@ typedef enum {
SOC_XTAL_FREQ_48M = 48, /*!< 48MHz XTAL */
} soc_xtal_freq_t;
// Naming convention: SOC_MOD_CLK_{[upstream]clock_name}_[attr]
// {[upstream]clock_name}: XTAL, (BB)PLL, etc.
// [attr] - optional: FAST, SLOW, D<divider>, F<freq>
/**
* @brief Supported clock sources for modules (CPU, peripherals, RTC, etc.)
*
* @note enum starts from 1, to save 0 for special purpose
*/
typedef enum {
// For CPU domain
SOC_MOD_CLK_CPU = 1, /*!< CPU_CLK can be sourced from XTAL, PLL, or RC_FAST by configuring soc_cpu_clk_src_t */
// For RTC domain
SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL_D2 or RC_FAST by configuring soc_rtc_fast_clk_src_t */
SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, or OSC_SLOW by configuring soc_rtc_slow_clk_src_t */
// For digital domain: peripherals, WIFI, BLE
SOC_MOD_CLK_PLL_F12M, /*!< PLL_F12M_CLK is derived from SPLL (clock gating + fixed divider of 40), it has a fixed frequency of 12MHz */
SOC_MOD_CLK_PLL_F20M, /*!< PLL_F20M_CLK is derived from SPLL (clock gating + fixed divider of 24), it has a fixed frequency of 20MHz */
SOC_MOD_CLK_PLL_F40M, /*!< PLL_F40M_CLK is derived from SPLL (clock gating + fixed divider of 12), it has a fixed frequency of 40MHz */
SOC_MOD_CLK_PLL_F48M, /*!< PLL_F48M_CLK is derived from SPLL (clock gating + fixed divider of 10), it has a fixed frequency of 48MHz */
SOC_MOD_CLK_PLL_F60M, /*!< PLL_F60M_CLK is derived from SPLL (clock gating + fixed divider of 8), it has a fixed frequency of 60MHz */
SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from SPLL (clock gating + fixed divider of 6), it has a fixed frequency of 80MHz */
SOC_MOD_CLK_PLL_F120M, /*!< PLL_F120M_CLK is derived from SPLL (clock gating + fixed divider of 4), it has a fixed frequency of 120MHz */
SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from SPLL (clock gating + fixed divider of 3), it has a fixed frequency of 160MHz */
SOC_MOD_CLK_MODEM_APB = SOC_MOD_CLK_PLL_F160M, /*!< Modem APB clock comes from the CLK_160M_REF */
SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from SPLL (clock gating + fixed divider of 2), it has a fixed frequency of 240MHz */
SOC_MOD_CLK_SPLL, /*!< SPLL is from the main XTAL oscillator frequency multipliers, it has a "fixed" frequency of 480MHz */
SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */
SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */
SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 48MHz crystal */
// For LP peripherals
SOC_MOD_CLK_XTAL_D2, /*!< XTAL_D2_CLK comes from the external 48MHz crystal, passing a div of 2 to the LP peripherals */
SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */
} soc_module_clk_t;
//////////////////////////////////////////////////SYSTIMER//////////////////////////////////////////////////////////////
/**