feat(clk_tree): support derived PLL clocks

Add a generic derived-PLL clock engine to esp_clk_tree_common that
handles acquire/release, mux selection, and divider programming for
target-defined derived clocks. Per-target descriptors (ESP32-P4,
ESP32-S31) plug into the engine via
esp_clk_tree_get_derived_clk_desc().
This commit is contained in:
Ondrej Kosta
2026-05-21 15:59:42 +08:00
parent 4811388910
commit c7d6c41198
8 changed files with 706 additions and 36 deletions
@@ -14,6 +14,7 @@
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/lp_clkrst_struct.h"
#include "soc/lp_clkrst_reg.h"
#include "soc/hp_sys_clkrst_struct.h"
#ifdef __cplusplus
extern "C" {
@@ -34,6 +35,96 @@ FORCE_INLINE_ATTR void _clk_gate_ll_rtc_fast_to_lp_periph_en(bool enable)
_clk_gate_ll_rtc_fast_to_lp_periph_en(__VA_ARGS__); \
} while(0)
/**
* Enable or disable the clock gate for ref_20m (derived from BBPLL).
* @param enable Enable / disable
*/
FORCE_INLINE_ATTR void _clk_gate_ll_ref_20m_clk_en(bool enable)
{
HP_SYS_CLKRST.ref_20m_ctrl0.reg_ref_20m_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define clk_gate_ll_ref_20m_clk_en(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_clk_gate_ll_ref_20m_clk_en(__VA_ARGS__); \
} while(0)
/**
* Enable or disable the clock gate for ref_25m (derived from MPLL).
* @param enable Enable / disable
*/
FORCE_INLINE_ATTR void _clk_gate_ll_ref_25m_clk_en(bool enable)
{
HP_SYS_CLKRST.ref_25m_ctrl0.reg_ref_25m_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define clk_gate_ll_ref_25m_clk_en(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_clk_gate_ll_ref_25m_clk_en(__VA_ARGS__); \
} while(0)
/**
* Enable or disable the clock gate for ref_50m (derived from MPLL).
* @param enable Enable / disable
*/
FORCE_INLINE_ATTR void _clk_gate_ll_ref_50m_clk_en(bool enable)
{
HP_SYS_CLKRST.ref_50m_ctrl0.reg_ref_50m_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define clk_gate_ll_ref_50m_clk_en(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_clk_gate_ll_ref_50m_clk_en(__VA_ARGS__); \
} while(0)
/**
* Enable or disable the clock gate for ref_80m (derived from BBPLL).
* @param enable Enable / disable
*/
FORCE_INLINE_ATTR void _clk_gate_ll_ref_80m_clk_en(bool enable)
{
HP_SYS_CLKRST.ref_80m_ctrl0.reg_ref_80m_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define clk_gate_ll_ref_80m_clk_en(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_clk_gate_ll_ref_80m_clk_en(__VA_ARGS__); \
} while(0)
/**
* Enable or disable the clock gate for ref_160m (derived from BBPLL).
* @param enable Enable / disable
*/
FORCE_INLINE_ATTR void _clk_gate_ll_ref_160m_clk_en(bool enable)
{
HP_SYS_CLKRST.ref_160m_ctrl0.reg_ref_160m_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define clk_gate_ll_ref_160m_clk_en(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_clk_gate_ll_ref_160m_clk_en(__VA_ARGS__); \
} while(0)
/**
* Enable or disable the clock gate for ref_240m (derived from BBPLL).
* @param enable Enable / disable
*/
FORCE_INLINE_ATTR void _clk_gate_ll_ref_240m_clk_en(bool enable)
{
HP_SYS_CLKRST.ref_240m_ctrl0.reg_ref_240m_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define clk_gate_ll_ref_240m_clk_en(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_clk_gate_ll_ref_240m_clk_en(__VA_ARGS__); \
} while(0)
/**
* @brief Set the default clock gate configuration
*/
@@ -701,13 +701,16 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_apb_get_divider(voi
return HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.apb_freq_ctrl0, reg_apb_clk_div_num) + 1;
}
// TODO: IDF-14730
// static inline __attribute__((always_inline)) void clk_ll_ref_500m_set_src(soc_ref_500m_clk_src_t in_sel)
// {
// // 0: cpll (320MHz)
// // 1: mpll (500MHz)
// HP_SYS_CLKRST.ref_500m_ctrl0.reg_ref_500m_sel = in_sel;
// }
/**
* @brief Select REF_500M_CLK source
*
* @param in_sel 0 selects CPLL (320 MHz), 1 selects MPLL (500 MHz).
*/
static inline __attribute__((always_inline)) void clk_ll_ref_500m_set_src(uint8_t in_sel)
{
HAL_ASSERT(in_sel == 0 || in_sel == 1);
HP_SYS_CLKRST.ref_500m_ctrl0.reg_ref_500m_sel = in_sel;
}
/**
* @brief Set PLL_F50M_CLK divider. freq of PLL_F50M_CLK = freq of MPLL_CLK / divider