fix(esp_hw_support): fix ESP32-S31 CPU/DFS clk_tree refcount and keep clock source during DFS

This commit is contained in:
wuzhenghui
2026-08-20 16:00:52 +08:00
parent 4b34a6b250
commit a3b62bc3c4
13 changed files with 235 additions and 157 deletions
@@ -95,6 +95,7 @@ static inline __attribute__((always_inline)) void clk_ll_cpll_enable(void)
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_XPD_CPLL | PMU_TIE_HIGH_XPD_CPLL_I2C); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_XPD_CPLL | PMU_TIE_HIGH_XPD_CPLL_I2C);
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_GLOBAL_CPLL_ICG); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_GLOBAL_CPLL_ICG);
SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_CPLL_300M_CLK_EN); SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_CPLL_300M_CLK_EN);
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_CPLL_I2C | PMU_HP_ACTIVE_XPD_CPLL);
} }
/** /**
@@ -105,6 +106,7 @@ static inline __attribute__((always_inline)) void clk_ll_cpll_disable(void)
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_GLOBAL_CPLL_ICG) ; SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_GLOBAL_CPLL_ICG) ;
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_XPD_CPLL | PMU_TIE_LOW_XPD_CPLL_I2C); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_XPD_CPLL | PMU_TIE_LOW_XPD_CPLL_I2C);
CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_CPLL_300M_CLK_EN); CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_CPLL_300M_CLK_EN);
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_CPLL_I2C | PMU_HP_ACTIVE_XPD_CPLL);
} }
/** /**
@@ -115,6 +117,7 @@ static inline __attribute__((always_inline)) void clk_ll_xtalx2_enable(void)
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_0_REG, PMU_TIE_HIGH_XPD_XTALX2); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_0_REG, PMU_TIE_HIGH_XPD_XTALX2);
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_0_REG, PMU_TIE_HIGH_GLOBAL_XTALX2_ICG); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_0_REG, PMU_TIE_HIGH_GLOBAL_XTALX2_ICG);
SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_XTALX2_80M_CLK_EN); SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_XTALX2_80M_CLK_EN);
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_XTALX2);
} }
/** /**
@@ -125,6 +128,7 @@ static inline __attribute__((always_inline)) void clk_ll_xtalx2_disable(void)
CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_XTALX2_80M_CLK_EN); CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_XTALX2_80M_CLK_EN);
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_0_REG, PMU_TIE_LOW_GLOBAL_XTALX2_ICG); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_0_REG, PMU_TIE_LOW_GLOBAL_XTALX2_ICG);
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_0_REG, PMU_TIE_LOW_XPD_XTALX2); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_0_REG, PMU_TIE_LOW_XPD_XTALX2);
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_XTALX2);
} }
/** /**
@@ -156,6 +160,7 @@ static inline __attribute__((always_inline)) void clk_ll_bbpll_enable(void)
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_XPD_BBPLL | PMU_TIE_HIGH_XPD_BBPLL_I2C); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_XPD_BBPLL | PMU_TIE_HIGH_XPD_BBPLL_I2C);
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_GLOBAL_BBPLL_ICG); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_GLOBAL_BBPLL_ICG);
SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_SPLL_480M_CLK_EN); SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_SPLL_480M_CLK_EN);
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_BBPLL_I2C | PMU_HP_ACTIVE_XPD_BBPLL);
} }
/** /**
@@ -166,6 +171,7 @@ static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void)
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_GLOBAL_BBPLL_ICG) ; SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_GLOBAL_BBPLL_ICG) ;
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_XPD_BBPLL | PMU_TIE_LOW_XPD_BBPLL_I2C); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_XPD_BBPLL | PMU_TIE_LOW_XPD_BBPLL_I2C);
CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_SPLL_480M_CLK_EN); CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_SPLL_480M_CLK_EN);
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_BBPLL_I2C | PMU_HP_ACTIVE_XPD_BBPLL);
} }
/** /**
@@ -176,6 +182,7 @@ static inline __attribute__((always_inline)) void clk_ll_apll_enable(void)
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_XPD_APLL | PMU_TIE_HIGH_XPD_APLL_I2C); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_XPD_APLL | PMU_TIE_HIGH_XPD_APLL_I2C);
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_GLOBAL_APLL_ICG); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_GLOBAL_APLL_ICG);
SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_AUDIO_PLL_CLK_EN); SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_AUDIO_PLL_CLK_EN);
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_APLL_I2C | PMU_HP_ACTIVE_XPD_APLL);
} }
/** /**
@@ -186,6 +193,7 @@ static inline __attribute__((always_inline)) void clk_ll_apll_disable(void)
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_GLOBAL_APLL_ICG) ; SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_GLOBAL_APLL_ICG) ;
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_XPD_APLL | PMU_TIE_LOW_XPD_APLL_I2C); SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_XPD_APLL | PMU_TIE_LOW_XPD_APLL_I2C);
CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_AUDIO_PLL_CLK_EN); CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_AUDIO_PLL_CLK_EN);
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_APLL_I2C | PMU_HP_ACTIVE_XPD_APLL);
} }
/** /**
@@ -48,7 +48,7 @@ extern "C" {
#define MSPI_LL_PERIPH_NUM 4 #define MSPI_LL_PERIPH_NUM 4
#define MSPI_TIMING_LL_MSPI_ID_0 0 #define MSPI_TIMING_LL_MSPI_ID_0 0
#define MSPI_TIMING_LL_MSPI_ID_1 1 #define MSPI_TIMING_LL_MSPI_ID_1 1
#define MSPI_TIMING_LL_FLASH_CORE_80M_CLK_DIV 4 #define MSPI_TIMING_LL_FLASH_CORE_80M_CLK_DIV 4 // clk src is 320M CPLL
// PSRAM frequency should be constrained by AXI frequency to avoid FIFO underflow. // PSRAM frequency should be constrained by AXI frequency to avoid FIFO underflow.
#define MSPI_TIMING_LL_PSRAM_FREQ_AXI_CONSTRAINED 1 #define MSPI_TIMING_LL_PSRAM_FREQ_AXI_CONSTRAINED 1
@@ -218,6 +218,30 @@ static inline void _mspi_timing_ll_set_flash_clk_src(uint32_t mspi_id, soc_perip
HP_SYS_CLKRST.flash_ctrl0.reg_flash_clk_src_sel = clk_val; HP_SYS_CLKRST.flash_ctrl0.reg_flash_clk_src_sel = clk_val;
} }
/**
* @brief Get FLASH clock source
*
* @param mspi_id mspi_id
*
* @return clock source, see valid sources in type `soc_periph_flash_clk_src_t`
*/
__attribute__((always_inline))
static inline soc_periph_flash_clk_src_t _mspi_timing_ll_get_flash_clk_src(uint32_t mspi_id)
{
HAL_ASSERT(mspi_id == MSPI_TIMING_LL_MSPI_ID_0);
switch (HP_SYS_CLKRST.flash_ctrl0.reg_flash_clk_src_sel) {
case 0:
return FLASH_CLK_SRC_XTAL;
case 1:
return FLASH_CLK_SRC_BBPLL;
case 2:
return FLASH_CLK_SRC_CPLL;
default:
HAL_ASSERT(false);
return FLASH_CLK_SRC_XTAL;
}
}
/** /**
* Set MSPI Flash core clock * Set MSPI Flash core clock
* *
@@ -122,6 +122,24 @@ FORCE_INLINE_ATTR void pmu_ll_hp_set_clk_power(pmu_dev_t *hw, pmu_hp_mode_t mode
hw->hp_sys[mode].clk_power.val = xpd_flag; hw->hp_sys[mode].clk_power.val = xpd_flag;
} }
/**
* @brief Set the power and isolation of the analog i2c master shared by all the PLLs
*
* @param hw Beginning address of the peripheral registers.
* @param mode The pmu mode
* @param xpd_bb_i2c Power up the analog i2c master
* @param iso_en Isolate the analog i2c master interface
* @param retention Retain the analog i2c master registers
*
* @return None
*/
FORCE_INLINE_ATTR void pmu_ll_hp_set_ana_i2c_power(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_bb_i2c, bool iso_en, bool retention)
{
hw->hp_sys[mode].clk_power.xpd_bb_i2c = xpd_bb_i2c;
hw->hp_sys[mode].clk_power.i2c_iso_en = iso_en;
hw->hp_sys[mode].clk_power.i2c_retention = retention;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_xtal_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_xtal) FORCE_INLINE_ATTR void pmu_ll_hp_set_xtal_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_xtal)
{ {
hw->hp_sys[mode].xtal.xpd_xtal = xpd_xtal; hw->hp_sys[mode].xtal.xpd_xtal = xpd_xtal;
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -26,6 +26,7 @@ extern "C" {
*/ */
void rtc_clk_cpu_set_to_default_config(void); void rtc_clk_cpu_set_to_default_config(void);
#ifndef BOOTLOADER_BUILD
/** /**
* @brief Switch CPU clock source to XTAL, the PLL has different processing methods for different chips. * @brief Switch CPU clock source to XTAL, the PLL has different processing methods for different chips.
* 1. For earlier chips without PMU, there is no PMU module that can turn off the CPU's PLL, so it has to be * 1. For earlier chips without PMU, there is no PMU module that can turn off the CPU's PLL, so it has to be
@@ -39,6 +40,7 @@ void rtc_clk_cpu_set_to_default_config(void);
* to 40MHz to speed up the retention speed. * to 40MHz to speed up the retention speed.
*/ */
void rtc_clk_cpu_freq_set_xtal_for_sleep(void); void rtc_clk_cpu_freq_set_xtal_for_sleep(void);
#endif
/** /**
* @brief Notify that the BBPLL has a new in-use consumer * @brief Notify that the BBPLL has a new in-use consumer
+2 -1
View File
@@ -15,7 +15,8 @@ entries:
clk_utils (noflash) clk_utils (noflash)
esp_clk_tree: esp_clk_tree_enable_src (noflash) esp_clk_tree: esp_clk_tree_enable_src (noflash)
if RTC_CLK_FUNC_IN_IRAM = y: if RTC_CLK_FUNC_IN_IRAM = y:
esp_clk_tree: esp_clk_tree_enable_power (noflash) esp_clk_tree:esp_clk_tree_enable_power (noflash)
esp_clk_tree:esp_clk_tree_port_is_power_on (noflash)
esp_clk_tree_common:esp_clk_tree_is_power_on (noflash) esp_clk_tree_common:esp_clk_tree_is_power_on (noflash)
if SOC_CLK_MPLL_SUPPORTED = y: if SOC_CLK_MPLL_SUPPORTED = y:
esp_clk_tree_common:esp_clk_tree_mpll_release (noflash) esp_clk_tree_common:esp_clk_tree_mpll_release (noflash)
@@ -3,14 +3,14 @@ target_include_directories(${COMPONENT_LIB} PUBLIC .)
set(srcs "rtc_clk_init.c" set(srcs "rtc_clk_init.c"
"rtc_clk.c" "rtc_clk.c"
"pmu_param.c" "pmu_param.c"
"pmu_init.c"
"pmu_sleep.c"
"rtc_time.c" "rtc_time.c"
"chip_info.c" "chip_info.c"
) )
if(NOT BOOTLOADER_BUILD) if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "sar_periph_ctrl.c") list(APPEND srcs "pmu_init.c"
"pmu_sleep.c"
"sar_periph_ctrl.c")
if(CONFIG_PM_SLEEP_CLK_ICG_ENABLE AND NOT CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) if(CONFIG_PM_SLEEP_CLK_ICG_ENABLE AND NOT CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
list(APPEND srcs "pmu_sleep_clock_icg.c") list(APPEND srcs "pmu_sleep_clock_icg.c")
@@ -30,7 +30,9 @@ ESP_HW_LOG_ATTR_TAG(TAG, "rtc_clk");
static int s_cur_cpll_freq = 0; static int s_cur_cpll_freq = 0;
// MPLL frequency option, 400MHz. Zero if MPLL is not enabled. // MPLL frequency option, 400MHz. Zero if MPLL is not enabled.
#ifndef BOOTLOADER_BUILD
static SPM_DRAM_ATTR uint32_t s_cur_mpll_freq = 0; static SPM_DRAM_ATTR uint32_t s_cur_mpll_freq = 0;
#endif
void rtc_clk_32k_enable(bool enable) void rtc_clk_32k_enable(bool enable)
{ {
@@ -641,6 +643,7 @@ bool rtc_dig_8m_enabled(void)
return clk_ll_rc_fast_digi_is_enabled(); return clk_ll_rc_fast_digi_is_enabled();
} }
#ifndef BOOTLOADER_BUILD
//------------------------------------MPLL-------------------------------------// //------------------------------------MPLL-------------------------------------//
SPM_IRAM_ATTR void rtc_clk_mpll_disable(void) SPM_IRAM_ATTR void rtc_clk_mpll_disable(void)
{ {
@@ -680,3 +683,4 @@ SPM_IRAM_ATTR uint32_t rtc_clk_mpll_get_freq(void)
{ {
return s_cur_mpll_freq; return s_cur_mpll_freq;
} }
#endif
@@ -5,13 +5,14 @@ set(srcs
"rtc_clk.c" "rtc_clk.c"
"rtc_time.c" "rtc_time.c"
"chip_info.c" "chip_info.c"
"pmu_param.c"
"pmu_init.c"
"pmu_sleep.c"
) )
if(NOT BOOTLOADER_BUILD) if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "sar_periph_ctrl.c") list(APPEND srcs "sar_periph_ctrl.c"
"pmu_param.c"
"pmu_init.c"
"pmu_sleep.c"
)
endif() endif()
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
@@ -6,6 +6,7 @@
#include <stdint.h> #include <stdint.h>
#include <assert.h> #include <assert.h>
#include "sdkconfig.h"
#include "esp_clk_tree.h" #include "esp_clk_tree.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_err.h" #include "esp_err.h"
@@ -17,6 +18,7 @@
#include "hal/clk_gate_ll.h" #include "hal/clk_gate_ll.h"
#include "hal/clk_tree_hal.h" #include "hal/clk_tree_hal.h"
#include "hal/clk_tree_ll.h" #include "hal/clk_tree_ll.h"
#include "hal/mspi_ll.h"
#include "esp_private/esp_clk_tree_common.h" #include "esp_private/esp_clk_tree_common.h"
#include "esp_private/esp_clk_tree_derived.h" #include "esp_private/esp_clk_tree_derived.h"
#include "esp_private/periph_ctrl.h" #include "esp_private/periph_ctrl.h"
@@ -431,49 +433,45 @@ esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_f
void esp_clk_tree_initialize(void) void esp_clk_tree_initialize(void)
{ {
soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
if ((rst_reason == RESET_REASON_CPU_SW) || (rst_reason == RESET_REASON_CPU_MWDT) || soc_periph_flash_clk_src_t flash_clk_src = _mspi_timing_ll_get_flash_clk_src(MSPI_TIMING_LL_MSPI_ID_0);
(rst_reason == RESET_REASON_CPU_RWDT) || (rst_reason == RESET_REASON_CPU_JTAG) ||
(rst_reason == RESET_REASON_CPU_LOCKUP)) {
s_clk_tree_initialized = true;
return;
}
// Cold boot only
soc_cpu_clk_src_t cpu_src = clk_ll_cpu_get_src(); soc_cpu_clk_src_t cpu_src = clk_ll_cpu_get_src();
if (cpu_src == SOC_CPU_CLK_SRC_PLL_F240M) { bool cpu_reset = (rst_reason == RESET_REASON_CPU_SW) || (rst_reason == RESET_REASON_CPU_MWDT) ||
s_mod_clk_gate_ref_cnt[SOC_MOD_CLK_PLL_F240M] = 1; (rst_reason == RESET_REASON_CPU_RWDT) || (rst_reason == RESET_REASON_CPU_JTAG) ||
s_root_pll_power_ref_cnt[SOC_ROOT_CIRCUIT_CLK_BBPLL] = 1; (rst_reason == RESET_REASON_CPU_LOCKUP);
} else if (cpu_src == SOC_CPU_CLK_SRC_CPLL) { if (!cpu_reset) {
s_root_pll_power_ref_cnt[SOC_ROOT_CIRCUIT_CLK_CPLL] = 1; /* Cold boot only: gate / power-down clocks not in use. */
if (cpu_src != SOC_CPU_CLK_SRC_PLL_F240M) {
_clk_gate_ll_ref_240m_clk_en(false);
}
if (cpu_src != SOC_CPU_CLK_SRC_CPLL && flash_clk_src != FLASH_CLK_SRC_CPLL) {
clk_ll_cpll_disable();
}
_clk_gate_ll_ref_160m_clk_en(false);
_clk_gate_ll_ref_120m_clk_en(false);
_clk_gate_ll_ref_80m_clk_en(false);
_clk_gate_ll_ref_60m_clk_en(false);
_clk_gate_ll_ref_20m_clk_en(false);
_clk_gate_ll_ref_50m_clk_en(false);
_clk_gate_ll_ref_25m_clk_en(false);
clk_ll_xtalx2_disable();
HP_ALIVE_SYS.hp_clk_ctrl.hp_audio_pll_clk_en = 0;
HP_ALIVE_SYS.hp_clk_ctrl.hp_sdio_pll2_clk_en = 0;
HP_ALIVE_SYS.hp_clk_ctrl.hp_sdio_pll1_clk_en = 0;
HP_ALIVE_SYS.hp_clk_ctrl.hp_sdio_pll0_clk_en = 0;
} }
if (cpu_src != SOC_CPU_CLK_SRC_PLL_F240M) {
_clk_gate_ll_ref_240m_clk_en(false);
// Not do clk_ll_bbpll_disable since MSPI depends on BBPLL: TODO: IDF-15889
}
// Add ref count for Flash using. // TODO: IDF-15889
s_root_pll_power_ref_cnt[SOC_ROOT_CIRCUIT_CLK_BBPLL]++;
if (cpu_src != SOC_CPU_CLK_SRC_CPLL) {
clk_ll_cpll_disable();
}
_clk_gate_ll_ref_160m_clk_en(false);
_clk_gate_ll_ref_120m_clk_en(false);
_clk_gate_ll_ref_80m_clk_en(false);
_clk_gate_ll_ref_60m_clk_en(false);
_clk_gate_ll_ref_20m_clk_en(false);
_clk_gate_ll_ref_50m_clk_en(false);
_clk_gate_ll_ref_25m_clk_en(false);
clk_ll_xtalx2_disable();
HP_ALIVE_SYS.hp_clk_ctrl.hp_audio_pll_clk_en = 0;
HP_ALIVE_SYS.hp_clk_ctrl.hp_sdio_pll2_clk_en = 0;
HP_ALIVE_SYS.hp_clk_ctrl.hp_sdio_pll1_clk_en = 0;
HP_ALIVE_SYS.hp_clk_ctrl.hp_sdio_pll0_clk_en = 0;
s_clk_tree_initialized = true; s_clk_tree_initialized = true;
#if CONFIG_USJ_ENABLE_USB_SERIAL_JTAG || CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED
/* Bootloader / USJ may keep BBPLL 480M on; declare a permanent hold. */
esp_clk_tree_enable_src(SOC_MOD_CLK_BBPLL, true);
#endif
/* Flash + CPU: sync clk_tree refs with HW already selected at boot. */
esp_clk_tree_enable_src((soc_module_clk_t)flash_clk_src, true);
if (cpu_src == SOC_CPU_CLK_SRC_CPLL) {
esp_clk_tree_enable_src(SOC_MOD_CLK_CPLL, true);
} else if (cpu_src == SOC_CPU_CLK_SRC_PLL_F240M) {
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F240M, true);
}
} }
bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable)
@@ -548,31 +546,33 @@ static const esp_clk_tree_gated_clk_t s_gated_ref_clks[] = {
FORCE_INLINE_ATTR esp_err_t esp_clk_tree_enable_gated_clk(const esp_clk_tree_gated_clk_t *entry, bool enable) FORCE_INLINE_ATTR esp_err_t esp_clk_tree_enable_gated_clk(const esp_clk_tree_gated_clk_t *entry, bool enable)
{ {
int16_t prev_ref_cnt; int16_t prev_ref_cnt;
bool released_too_many = false;
esp_os_enter_critical(&s_clk_tree_spinlock); esp_os_enter_critical(&s_clk_tree_spinlock);
if (enable) { if (enable) {
prev_ref_cnt = s_mod_clk_gate_ref_cnt[entry->clk_id]++; prev_ref_cnt = s_mod_clk_gate_ref_cnt[entry->clk_id]++;
if (prev_ref_cnt == 0) {
if (entry->parent_power != NULL) {
entry->parent_power(true);
}
ENABLE_CLK_GATE(entry->set_gate, true);
}
} else { } else {
prev_ref_cnt = s_mod_clk_gate_ref_cnt[entry->clk_id]--; prev_ref_cnt = s_mod_clk_gate_ref_cnt[entry->clk_id]--;
if (prev_ref_cnt <= 0) { if (prev_ref_cnt <= 0) {
s_mod_clk_gate_ref_cnt[entry->clk_id] = 0; s_mod_clk_gate_ref_cnt[entry->clk_id] = 0;
esp_os_exit_critical(&s_clk_tree_spinlock); released_too_many = true;
ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", entry->clk_id); } else if (prev_ref_cnt == 1) {
return ESP_OK; ENABLE_CLK_GATE(entry->set_gate, false);
if (entry->parent_power != NULL) {
entry->parent_power(false);
}
} }
} }
esp_os_exit_critical(&s_clk_tree_spinlock); esp_os_exit_critical(&s_clk_tree_spinlock);
if (prev_ref_cnt == 0 && enable) { if (released_too_many) {
if (entry->parent_power != NULL) { ESP_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", entry->clk_id);
entry->parent_power(true);
}
ENABLE_CLK_GATE(entry->set_gate, true);
} else if (prev_ref_cnt == 1 && !enable) {
ENABLE_CLK_GATE(entry->set_gate, false);
if (entry->parent_power != NULL) {
entry->parent_power(false);
}
} }
return ESP_OK; return ESP_OK;
} }
@@ -605,6 +605,12 @@ esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable)
esp_clk_tree_mpll_release(); esp_clk_tree_mpll_release();
return ESP_OK; return ESP_OK;
} }
case SOC_MOD_CLK_BBPLL:
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_BBPLL, enable);
return ESP_OK;
case SOC_MOD_CLK_CPLL:
esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_CPLL, enable);
return ESP_OK;
case SOC_MOD_CLK_RC_FAST: gated_clk_id = ESP_CLK_TREE_GATED_CLK_RC_FAST; break; case SOC_MOD_CLK_RC_FAST: gated_clk_id = ESP_CLK_TREE_GATED_CLK_RC_FAST; break;
case SOC_MOD_CLK_PLL_F20M: gated_clk_id = ESP_CLK_TREE_GATED_CLK_PLL_F20M; break; case SOC_MOD_CLK_PLL_F20M: gated_clk_id = ESP_CLK_TREE_GATED_CLK_PLL_F20M; break;
case SOC_MOD_CLK_PLL_F60M: gated_clk_id = ESP_CLK_TREE_GATED_CLK_PLL_F60M; break; case SOC_MOD_CLK_PLL_F60M: gated_clk_id = ESP_CLK_TREE_GATED_CLK_PLL_F60M; break;
@@ -109,7 +109,7 @@ typedef struct {
.rc32k_dfreq = RTC_CNTL_RC32K_DFREQ_DEFAULT, \ .rc32k_dfreq = RTC_CNTL_RC32K_DFREQ_DEFAULT, \
.disable_apll = 1, \ .disable_apll = 1, \
.disable_mpll = 1, \ .disable_mpll = 1, \
.disable_cpll = 0, \ .disable_cpll = 0, /* Keep CPLL: Flash (bootloader) and typical CPU freqs use it */ \
.disable_bbpll = 1, \ .disable_bbpll = 1, \
} }
@@ -233,6 +233,7 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou
*/ */
void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config); void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config);
#ifndef BOOTLOADER_BUILD
/** /**
* @brief Switch CPU frequency (optimized for speed) * @brief Switch CPU frequency (optimized for speed)
* *
@@ -254,6 +255,7 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config);
* @param config CPU frequency configuration structure * @param config CPU frequency configuration structure
*/ */
void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config); void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config);
#endif
/** /**
* @brief Get the currently used CPU frequency configuration * @brief Get the currently used CPU frequency configuration
@@ -261,17 +263,16 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config);
*/ */
void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config);
#ifndef BOOTLOADER_BUILD
/** /**
* @brief Switch CPU clock source to XTAL * @brief Switch CPU clock source to XTAL
* *
* Short form for filling in rtc_cpu_freq_config_t structure and calling * Short form for filling in rtc_cpu_freq_config_t structure and calling
* rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed.
* Assumes that XTAL frequency has been determined — don't call in startup code. * Assumes that XTAL frequency has been determined — don't call in startup code.
*
* @note On ESP32S31, this function always disables CPLL after switching the CPU clock source to XTAL,
* since there is no peripheral relies on CPLL clock (except Flash/PSRAM if their clock source selects CPLL).
*/ */
void rtc_clk_cpu_freq_set_xtal(void); void rtc_clk_cpu_freq_set_xtal(void);
#endif
/** /**
* @brief Get the current APB frequency. * @brief Get the current APB frequency.
@@ -76,7 +76,13 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa
assert(ctx->hal); assert(ctx->hal);
/* Default configuration of hp-system power in active, modem and sleep modes */ /* Default configuration of hp-system power in active, modem and sleep modes */
pmu_ll_hp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val); pmu_ll_hp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val);
pmu_ll_hp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val); if (mode == PMU_MODE_HP_ACTIVE) {
// In active mode the root clock circuit power (BBPLL/CPLL/MPLL/APLL/XTALx2, etc.) is owned by esp_clk_tree.
// The analog i2c master is shared by all the PLLs and is not refcounted there, so it is still configured here.
pmu_ll_hp_set_ana_i2c_power(ctx->hal->dev, mode, power->clk_power.xpd_bb_i2c, power->clk_power.i2c_iso_en, power->clk_power.i2c_retention);
} else {
pmu_ll_hp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val);
}
pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, mode, power->xtal.xpd_xtal); pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, mode, power->xtal.xpd_xtal);
/* Default configuration of hp-system clock in active, modem and sleep modes */ /* Default configuration of hp-system clock in active, modem and sleep modes */
@@ -36,6 +36,7 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param");
.top_pd_en = 0 \ .top_pd_en = 0 \
}, \ }, \
.clk_power = { \ .clk_power = { \
.xpd_xtalx2 = 0, \
.i2c_iso_en = 0, \ .i2c_iso_en = 0, \
.i2c_retention = 0, \ .i2c_retention = 0, \
.xpd_bb_i2c = 1, \ .xpd_bb_i2c = 1, \
@@ -20,17 +20,24 @@
#include "esp_private/sleep_event.h" #include "esp_private/sleep_event.h"
#include "esp_private/regi2c_ctrl.h" #include "esp_private/regi2c_ctrl.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_private/esp_clk_tree_common.h"
#include "hal/clk_gate_ll.h"
static const char *TAG = "rtc_clk"; static const char *TAG = "rtc_clk";
// CPLL frequency option, in 320MHz. Zero if CPLL is not enabled. #ifndef BOOTLOADER_BUILD
// CPLL frequency option, in 320MHz. Zero if CPLL is not enabled / needs recalibration.
static int s_cur_cpll_freq = 0; static int s_cur_cpll_freq = 0;
// BBPLL frequency option, in 480MHz. Zero if BBPLL is not enabled / needs recalibration.
static int s_cur_bbpll_freq = 0;
// MPLL frequency option, 500MHz. Zero if MPLL is not enabled. // MPLL frequency option, 500MHz. Zero if MPLL is not enabled.
static uint32_t s_cur_mpll_freq = 0; static uint32_t s_cur_mpll_freq = 0;
#if !BOOTLOADER_BUILD /**
// Indicate whether the specific clock sources are acquired by the hp root clock (i.e. whether ref_cnt in esp_clk_tree.c is incremented by the hp root clock) * Whether HP ROOT clock currently holds a clk_tree ref on CPLL / PLL_F240M.
* Survives DFS set_config_fast(XTAL) (keep-hot) and light-sleep (PMU restores ACTIVE XPD on wake). Cleared only on real leave via set_config/set_xtal.
*/
static bool s_is_cpll_acquired = (CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 80 || CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 160 || CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 320); static bool s_is_cpll_acquired = (CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 80 || CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 160 || CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 320);
static bool s_is_pll_f240m_acquired = (CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 240); static bool s_is_pll_f240m_acquired = (CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ == 240);
#endif #endif
@@ -122,19 +129,6 @@ soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void)
return clk_ll_rtc_fast_get_src(); return clk_ll_rtc_fast_get_src();
} }
#if BOOTLOADER_BUILD
static void rtc_clk_cpll_disable(void)
{
clk_ll_cpll_disable();
s_cur_cpll_freq = 0;
}
static void rtc_clk_cpll_enable(void)
{
clk_ll_cpll_enable();
}
#endif
static void rtc_clk_cpll_configure(soc_xtal_freq_t xtal_freq, int cpll_freq) static void rtc_clk_cpll_configure(soc_xtal_freq_t xtal_freq, int cpll_freq)
{ {
/* Digital part */ /* Digital part */
@@ -152,7 +146,9 @@ static void rtc_clk_cpll_configure(soc_xtal_freq_t xtal_freq, int cpll_freq)
clk_ll_cpll_calibration_stop(); clk_ll_cpll_calibration_stop();
ANALOG_CLOCK_DISABLE(); ANALOG_CLOCK_DISABLE();
#ifndef BOOTLOADER_BUILD
s_cur_cpll_freq = cpll_freq; s_cur_cpll_freq = cpll_freq;
#endif
} }
/** /**
@@ -340,63 +336,69 @@ __attribute__((weak)) void rtc_clk_set_cpu_switch_to_pll(int event_id)
{ {
} }
static void rtc_clk_cpu_src_clk_enable(soc_cpu_clk_src_t new_src, uint32_t new_src_freq_mhz) static void rtc_clk_update_pll_state_on_cpu_src_switching_start(soc_cpu_clk_src_t new_src, uint32_t new_src_freq_mhz)
{ {
#ifdef BOOTLOADER_BUILD
if (new_src == SOC_CPU_CLK_SRC_CPLL) { if (new_src == SOC_CPU_CLK_SRC_CPLL) {
bool truly_enabled = false; clk_ll_cpll_enable();
#if BOOTLOADER_BUILD rtc_clk_cpll_configure(rtc_clk_xtal_freq_get(), new_src_freq_mhz);
rtc_clk_cpll_enable(); } else if (new_src == SOC_CPU_CLK_SRC_PLL_F240M) {
truly_enabled = true; clk_ll_bbpll_enable();
_clk_gate_ll_ref_240m_clk_en(true);
}
#else #else
if (new_src == SOC_CPU_CLK_SRC_CPLL) {
bool need_configure = false;
if (!s_is_cpll_acquired) { if (!s_is_cpll_acquired) {
truly_enabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_CPLL, true); need_configure = !esp_clk_tree_is_power_on(SOC_ROOT_CIRCUIT_CLK_CPLL);
esp_clk_tree_enable_src(SOC_MOD_CLK_CPLL, true);
s_is_cpll_acquired = true; s_is_cpll_acquired = true;
} }
#endif if (need_configure || (s_cur_cpll_freq != (int)new_src_freq_mhz)) {
if (truly_enabled || (s_cur_cpll_freq != new_src_freq_mhz)) {
rtc_clk_cpll_configure(rtc_clk_xtal_freq_get(), new_src_freq_mhz); rtc_clk_cpll_configure(rtc_clk_xtal_freq_get(), new_src_freq_mhz);
} }
} else if (new_src == SOC_CPU_CLK_SRC_PLL_F240M) { } else if (new_src == SOC_CPU_CLK_SRC_PLL_F240M) {
#if BOOTLOADER_BUILD
clk_ll_bbpll_enable();
#else
if (!s_is_pll_f240m_acquired) { if (!s_is_pll_f240m_acquired) {
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F240M, true); esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F240M, true);
s_is_pll_f240m_acquired = true; s_is_pll_f240m_acquired = true;
} }
#endif s_cur_bbpll_freq = CLK_LL_PLL_480M_FREQ_MHZ;
} }
#endif
} }
static void rtc_clk_cpu_src_clk_disable(soc_cpu_clk_src_t old_src) #ifndef BOOTLOADER_BUILD
static void rtc_clk_update_pll_state_on_cpu_src_switching_end(soc_cpu_clk_src_t old_src)
{ {
if (old_src == SOC_CPU_CLK_SRC_CPLL) { if (old_src == SOC_CPU_CLK_SRC_CPLL) {
#if BOOTLOADER_BUILD
rtc_clk_cpll_disable();
#else
assert(s_is_cpll_acquired); assert(s_is_cpll_acquired);
bool truly_disabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_CPLL, false); esp_clk_tree_enable_src(SOC_MOD_CLK_CPLL, false);
s_is_cpll_acquired = false; s_is_cpll_acquired = false;
if (truly_disabled) { if (!esp_clk_tree_is_power_on(SOC_ROOT_CIRCUIT_CLK_CPLL)) {
s_cur_cpll_freq = 0; s_cur_cpll_freq = 0;
} }
#endif
} else if (old_src == SOC_CPU_CLK_SRC_PLL_F240M) { } else if (old_src == SOC_CPU_CLK_SRC_PLL_F240M) {
#if BOOTLOADER_BUILD
/* Do not clk_ll_bbpll_disable(): Flash may still use BBPLL (reg_flash_clk_src_sel==1) */
#else
assert(s_is_pll_f240m_acquired); assert(s_is_pll_f240m_acquired);
s_is_pll_f240m_acquired = false; s_is_pll_f240m_acquired = false;
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F240M, false); esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F240M, false);
#endif if (!esp_clk_tree_is_power_on(SOC_ROOT_CIRCUIT_CLK_BBPLL)) {
s_cur_bbpll_freq = 0;
}
} }
} }
#endif
void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
{ {
#ifdef BOOTLOADER_BUILD
// Always trigger clock source preparing in bootloader
bool src_changed = true;
#else
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
if (old_cpu_clk_src != config->source) { bool src_changed = (old_cpu_clk_src != config->source);
rtc_clk_cpu_src_clk_enable(config->source, config->source_freq_mhz); #endif
if (src_changed) {
rtc_clk_update_pll_state_on_cpu_src_switching_start(config->source, config->source_freq_mhz);
} }
if (config->source == SOC_CPU_CLK_SRC_XTAL) { if (config->source == SOC_CPU_CLK_SRC_XTAL) {
@@ -411,9 +413,11 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
rtc_clk_cpu_freq_to_rc_fast(); rtc_clk_cpu_freq_to_rc_fast();
} }
if (old_cpu_clk_src != config->source) { #ifndef BOOTLOADER_BUILD
rtc_clk_cpu_src_clk_disable(old_cpu_clk_src); if (src_changed) {
rtc_clk_update_pll_state_on_cpu_src_switching_end(old_cpu_clk_src);
} }
#endif
} }
static uint32_t rtc_clk_hp_root_get_freq_mhz(soc_cpu_clk_src_t clk_src) static uint32_t rtc_clk_hp_root_get_freq_mhz(soc_cpu_clk_src_t clk_src)
@@ -463,53 +467,6 @@ 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)
{
if (config->source == SOC_CPU_CLK_SRC_XTAL) {
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div.integer, false);
} else if (config->source == SOC_CPU_CLK_SRC_CPLL &&
s_cur_cpll_freq == config->source_freq_mhz) {
rtc_clk_cpu_freq_to_cpll_mhz(config->freq_mhz, (hal_utils_clk_div_t *)&config->div);
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
rtc_clk_cpu_freq_to_rc_fast();
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M
#if !BOOTLOADER_BUILD
&& s_is_pll_f240m_acquired
#endif
) {
rtc_clk_cpu_freq_to_pll_240_mhz(config->freq_mhz);
} else {
/* fallback */
rtc_clk_cpu_freq_set_config(config);
}
}
void rtc_clk_cpu_freq_set_xtal(void)
{
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
int freq_mhz = (int)rtc_clk_xtal_freq_get();
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1, false);
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_XTAL) {
rtc_clk_cpu_src_clk_disable(old_cpu_clk_src);
}
}
FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1, true);
}
void rtc_clk_cpu_freq_set_xtal_for_sleep(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1, false);
s_cur_cpll_freq = 0; // no disable PLL, but set freq to 0 to trigger a PLL calibration after wake-up from sleep
}
FORCE_IRAM_ATTR soc_xtal_freq_t rtc_clk_xtal_freq_get(void) FORCE_IRAM_ATTR soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
{ {
uint32_t xtal_freq_mhz = clk_ll_xtal_get_freq_mhz(); uint32_t xtal_freq_mhz = clk_ll_xtal_get_freq_mhz();
@@ -532,6 +489,54 @@ uint32_t rtc_clk_apb_freq_get(void)
return sys_freq_hz / clk_ll_apb_get_divider(); return sys_freq_hz / clk_ll_apb_get_divider();
} }
#ifndef BOOTLOADER_BUILD
void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
{
/* Mux only — Fall back to set_config when PLL must be reacquired or recalibrated (s_cur_* == 0 after sleep). */
if (config->source == SOC_CPU_CLK_SRC_XTAL) {
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div.integer, false);
} else if (config->source == SOC_CPU_CLK_SRC_CPLL &&
s_cur_cpll_freq == (int)config->source_freq_mhz) {
rtc_clk_cpu_freq_to_cpll_mhz(config->freq_mhz, (hal_utils_clk_div_t *)&config->div);
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M &&
s_is_pll_f240m_acquired &&
s_cur_bbpll_freq == CLK_LL_PLL_480M_FREQ_MHZ) {
rtc_clk_cpu_freq_to_pll_240_mhz(config->freq_mhz);
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
rtc_clk_cpu_freq_to_rc_fast();
} else {
/* fallback */
rtc_clk_cpu_freq_set_config(config);
}
}
void rtc_clk_cpu_freq_set_xtal(void)
{
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
int freq_mhz = (int)rtc_clk_xtal_freq_get();
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1, false);
rtc_clk_update_pll_state_on_cpu_src_switching_end(old_cpu_clk_src);
}
FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1, true);
}
void rtc_clk_cpu_freq_set_xtal_for_sleep(void)
{
int freq_mhz = (int)rtc_clk_xtal_freq_get();
/* Mux only — do not release CPU clk_tree hold. PMU restores ACTIVE XPD on
* wake; clearing s_cur_* forces recalibration via set_config fallback. */
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1, false);
s_cur_cpll_freq = 0;
s_cur_bbpll_freq = 0;
}
void rtc_clk_apll_enable(bool enable) void rtc_clk_apll_enable(bool enable)
{ {
if (enable) { if (enable) {
@@ -672,3 +677,4 @@ IRAM_ATTR uint32_t rtc_clk_mpll_get_freq(void)
{ {
return s_cur_mpll_freq; return s_cur_mpll_freq;
} }
#endif