feat(clk): Add basic clock support for esp32c5 mp

- Support SOC ROOT clock source switch
- Support CPU frequency change
- Support RTC SLOW clock source switch
- Support RTC SLOW clock + RC FAST calibration
- Remove FPGA build
This commit is contained in:
Song Ruo Jing 2024-06-14 16:46:48 +08:00
parent ede24b0440
commit 40f3bc2e57
43 changed files with 449 additions and 595 deletions

View File

@ -122,7 +122,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
default "y" if IDF_TARGET="esp32c5"
select FREERTOS_UNICORE
select IDF_TARGET_ARCH_RISCV
select IDF_ENV_FPGA
config IDF_TARGET_ESP32P4
bool

View File

@ -28,7 +28,6 @@
#include "hal/mmu_ll.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "hal/clk_tree_ll.h"
void bootloader_flash_update_id()
{
@ -204,11 +203,6 @@ static void bootloader_spi_flash_resume(void)
esp_err_t bootloader_init_spi_flash(void)
{
// On ESP32C5, MSPI source clock's default HS divider leads to 120MHz, which is unusable before calibration
// Therefore, before switching SOC_ROOT_CLK to HS, we need to set MSPI source clock HS divider to make it run at
// 80MHz after the switch. PLL = 480MHz, so divider is 6.
clk_ll_mspi_fast_set_hs_divider(6);
bootloader_init_flash_configure();
bootloader_spi_flash_resume();
bootloader_flash_unlock();

View File

@ -53,18 +53,12 @@ __attribute__((weak)) void bootloader_clock_configure(void)
clk_cfg.cpu_freq_mhz = cpu_freq_mhz;
#if CONFIG_IDF_TARGET_ESP32C5
// TODO: [ESP32C5] IDF-9009 Check whether SOC_RTC_SLOW_CLK_SRC_RC_SLOW can be used on C5 MP
// RC150K can't do calibrate on ESP32C5MPW so not use it
clk_cfg.slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC32K;
#else
// Use RTC_SLOW clock source sel register field's default value, RC_SLOW, for 2nd stage bootloader
// RTC_SLOW clock source will be switched according to Kconfig selection at application startup
clk_cfg.slow_clk_src = rtc_clk_slow_src_get();
if (clk_cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_INVALID) {
clk_cfg.slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW;
}
#endif
// Use RTC_FAST clock source sel register field's default value, XTAL_DIV, for 2nd stage bootloader
// RTC_FAST clock source will be switched to RC_FAST at application startup

View File

@ -89,11 +89,7 @@ static inline void bootloader_hardware_init(void)
/* Enable analog i2c master clock */
SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN);
SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_FORCE_ON_REG, MODEM_LPCON_CLK_I2C_MST_FO); // TODO: IDF-8667 Remove this?
#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION
SET_PERI_REG_MASK(MODEM_LPCON_I2C_MST_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_SEL_160M);
#else // CONFIG_IDF_TARGET_ESP32C5_MP_VERSION
SET_PERI_REG_MASK(MODEM_SYSCON_CLK_CONF_REG, MODEM_SYSCON_CLK_I2C_MST_SEL_160M);
#endif
}
static inline void bootloader_ana_reset_config(void)

View File

@ -159,7 +159,6 @@ if(NOT BOOTLOADER_BUILD)
"sleep_modem.c" # TODO: [ESP32C5] IDF-8638
"sleep_wake_stub.c" # TODO: [ESP32C5] IDF-8638
"sleep_gpio.c" # TODO: [ESP32C5] IDF-8638
"port/esp_clk_tree_common.c" # TODO: [ESP32C5] IDF-8638
)
endif()

View File

@ -288,10 +288,7 @@ menu "Hardware Settings"
# Invisible bringup bypass options for esp_hw_support component
config ESP_BRINGUP_BYPASS_CPU_CLK_SETTING
bool
# TODO: [ESP32C5] IDF-8642 IDF_TARGET_ESP32C5 is added because clock
# is required when bringup on C5 beta3, remove it when clock tree is
# supported
default y if !SOC_CLK_TREE_SUPPORTED && !IDF_TARGET_ESP32C5
default y if !SOC_CLK_TREE_SUPPORTED
default n
help
This option is only used for new chip bringup, when

View File

@ -96,7 +96,7 @@ int IRAM_ATTR esp_clk_cpu_freq(void)
int IRAM_ATTR esp_clk_apb_freq(void)
{
// TODO: IDF-5173 Require cleanup, implementation should be unified
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C61
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61
return rtc_clk_apb_freq_get();
#else
return MIN(s_get_cpu_freq_mhz() * MHZ, APB_CLK_FREQ);

View File

@ -19,7 +19,7 @@ entries:
if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y || IDF_TARGET_ESP32S3 = y || IDF_TARGET_ESP32C2 = y || IDF_TARGET_ESP32C3 = y:
rtc_sleep (noflash_text)
rtc_time (noflash_text)
if SOC_PMU_SUPPORTED = y:
if SOC_PMU_SUPPORTED = y && SOC_LIGHT_SLEEP_SUPPORTED = y:
pmu_sleep (noflash)
if SOC_USB_SERIAL_JTAG_SUPPORTED = y:
sleep_console (noflash)

View File

@ -1,10 +1,11 @@
set(srcs "rtc_clk_init.c"
"rtc_time.c"
"rtc_clk.c"
"pmu_init.c"
"pmu_param.c"
"chip_info.c"
)
if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "sar_periph_ctrl.c"
"esp_crypto_lock.c")

View File

@ -11,21 +11,22 @@
#include "soc/rtc.h"
#include "hal/clk_tree_hal.h"
#include "hal/clk_tree_ll.h"
// #include "esp_private/esp_clk_tree_common.h"
#include "sdkconfig.h"
#include "esp_private/esp_clk_tree_common.h"
static const char *TAG = "esp_clk_tree";
esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision,
uint32_t *freq_value)
{
// TODO: [ESP32C5] IDF-8642 check again for MP version
ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src");
ESP_RETURN_ON_FALSE(precision < ESP_CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision");
ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer");
uint32_t clk_src_freq = 0;
switch (clk_src) {
case SOC_MOD_CLK_CPU:
clk_src_freq = clk_hal_cpu_get_freq_hz();
break;
case SOC_MOD_CLK_XTAL:
clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ;
break;
@ -41,9 +42,17 @@ uint32_t *freq_value)
case SOC_MOD_CLK_SPLL:
clk_src_freq = CLK_LL_PLL_480M_FREQ_MHZ * MHZ;
break;
case SOC_MOD_CLK_RTC_SLOW:
clk_src_freq = esp_clk_tree_lp_slow_get_freq_hz(precision);
break;
case SOC_MOD_CLK_RTC_FAST:
clk_src_freq = esp_clk_tree_lp_fast_get_freq_hz(precision);
break;
case SOC_MOD_CLK_RC_FAST:
// C5-beta3 unable to calibrate to get exact RC_FAST frequency
clk_src_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
clk_src_freq = esp_clk_tree_rc_fast_get_freq_hz(precision);
break;
case SOC_MOD_CLK_XTAL32K:
clk_src_freq = esp_clk_tree_xtal32k_get_freq_hz(precision);
break;
case SOC_MOD_CLK_XTAL_D2:
clk_src_freq = (clk_hal_xtal_get_freq_mhz() * MHZ) >> 1;

View File

@ -50,10 +50,6 @@ extern "C" {
#define MHZ (1000000)
#define RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(cycles) (cycles << 10)
#define RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12)
#define RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(cycles) (TIMG_RTC_CALI_TIMEOUT_THRES_V) // Just use the max timeout thres value
#define OTHER_BLOCKS_POWERUP 1
#define OTHER_BLOCKS_WAIT 1
@ -121,21 +117,19 @@ typedef struct rtc_cpu_freq_config_s {
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
/**
* @brief Clock source to be calibrated using rtc_clk_cal function
*
* @note On previous targets, the enum values somehow reflects the register field values of TIMG_RTC_CALI_CLK_SEL
* However, this is not true on ESP32C5. The conversion to register field values is explicitly done in
* rtc_clk_cal_internal
* @note On ESP32C5, the enum values somehow reflects the register field values of PCR_32K_SEL.
*/
typedef enum {
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
// RTC_CAL_RC_SLOW = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, //!< Internal 150kHz RC oscillator
RTC_CAL_RC32K = SOC_RTC_SLOW_CLK_SRC_RC32K, //!< Internal 32kHz RC oscillator, as one type of 32k clock
RTC_CAL_32K_XTAL = SOC_RTC_SLOW_CLK_SRC_XTAL32K, //!< External 32kHz XTAL, as one type of 32k clock
RTC_CAL_32K_OSC_SLOW = SOC_RTC_SLOW_CLK_SRC_OSC_SLOW, //!< External slow clock signal input by lp_pad_gpio0, as one type of 32k clock
RTC_CAL_RC_FAST //!< Internal 20MHz RC oscillator
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
RTC_CAL_RC32K = 0, //!< Internal 32kHz RC oscillator, as one type of 32k clock
RTC_CAL_32K_XTAL = 1, //!< External 32kHz XTAL, as one type of 32k clock
RTC_CAL_32K_OSC_SLOW = 2, //!< External slow clock signal input by lp_pad_gpio0, as one type of 32k clock
RTC_CAL_RC_SLOW = 3, //!< Internal 150kHz RC oscillator
RTC_CAL_RC_FAST = 4, //!< Internal 20MHz RC oscillator
RTC_CAL_INVALID_CLK, //!< Clock not available to calibrate
} rtc_cal_sel_t;
/**
@ -160,7 +154,7 @@ typedef struct {
.xtal_freq = CONFIG_XTAL_FREQ, \
.cpu_freq_mhz = 80, \
.fast_clk_src = SOC_RTC_FAST_CLK_SRC_RC_FAST, \
.slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC32K, \
.slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, \
.clk_rtc_clk_div = 0, \
.clk_8m_clk_div = 0, \
.slow_clk_dcap = RTC_CNTL_SCK_DCAP_DEFAULT, \

View File

@ -23,13 +23,13 @@ typedef struct {
const pmu_hp_system_power_param_t *power;
const pmu_hp_system_clock_param_t *clock;
const pmu_hp_system_digital_param_t *digital;
const pmu_hp_system_analog_param_t *analog;
pmu_hp_system_analog_param_t *analog; //param determined at runtime
const pmu_hp_system_retention_param_t *retent;
} pmu_hp_system_param_t;
typedef struct {
const pmu_lp_system_power_param_t *power;
const pmu_lp_system_analog_param_t *analog;
pmu_lp_system_analog_param_t *analog; //param determined at runtime
} pmu_lp_system_param_t;
pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
@ -42,7 +42,7 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
return &pmu_context;
}
void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_param_t *param)
void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, const pmu_hp_system_param_t *param)
{
const pmu_hp_system_power_param_t *power = param->power;
const pmu_hp_system_clock_param_t *clock = param->clock;
@ -101,7 +101,7 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa
pmu_ll_hp_set_sleep_protect_mode(ctx->hal->dev, PMU_SLEEP_PROTECT_HP_LP_SLEEP);
}
void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, pmu_lp_system_param_t *param)
void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, const pmu_lp_system_param_t *param)
{
const pmu_lp_system_power_param_t *power = param->power;
const pmu_lp_system_analog_param_t *anlg = param->analog;
@ -157,18 +157,26 @@ static inline void pmu_power_domain_force_default(pmu_context_t *ctx)
static inline void pmu_hp_system_param_default(pmu_hp_mode_t mode, pmu_hp_system_param_t *param)
{
assert (param->analog);
param->power = pmu_hp_system_power_param_default(mode);
param->clock = pmu_hp_system_clock_param_default(mode);
param->digital = pmu_hp_system_digital_param_default(mode);
param->analog = pmu_hp_system_analog_param_default(mode);
*param->analog = *pmu_hp_system_analog_param_default(mode); //copy default value
param->retent = pmu_hp_system_retention_param_default(mode);
if (mode == PMU_MODE_HP_ACTIVE || mode == PMU_MODE_HP_MODEM) {
param->analog->regulator0.dbias = get_act_hp_dbias();
}
}
static void pmu_hp_system_init_default(pmu_context_t *ctx)
{
assert(ctx);
pmu_hp_system_param_t param = { 0 };
for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) {
pmu_hp_system_analog_param_t analog = {};
pmu_hp_system_param_t param = {.analog = &analog};
pmu_hp_system_param_default(mode, &param);
pmu_hp_system_init(ctx, mode, &param);
}
@ -176,15 +184,23 @@ static void pmu_hp_system_init_default(pmu_context_t *ctx)
static inline void pmu_lp_system_param_default(pmu_lp_mode_t mode, pmu_lp_system_param_t *param)
{
assert (param->analog);
param->power = pmu_lp_system_power_param_default(mode);
param->analog = pmu_lp_system_analog_param_default(mode);
*param->analog = *pmu_lp_system_analog_param_default(mode); //copy default value
if (mode == PMU_MODE_LP_ACTIVE) {
param->analog->regulator0.dbias = get_act_lp_dbias();
}
}
static void pmu_lp_system_init_default(pmu_context_t *ctx)
{
assert(ctx);
pmu_lp_system_param_t param;
for (pmu_lp_mode_t mode = PMU_MODE_LP_ACTIVE; mode < PMU_MODE_LP_MAX; mode++) {
pmu_lp_system_analog_param_t analog = {};
pmu_lp_system_param_t param = {.analog = &analog};
pmu_lp_system_param_default(mode, &param);
pmu_lp_system_init(ctx, mode, &param);
}
@ -195,10 +211,6 @@ void pmu_init(void)
/* Peripheral reg i2c power up */
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0);
pmu_hp_system_init_default(PMU_instance());
pmu_lp_system_init_default(PMU_instance());

View File

@ -211,7 +211,7 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp
.xpd = 1, \
.slp_mem_dbias = 0, \
.slp_logic_dbias = 0, \
.dbias = HP_CALI_DBIAS \
.dbias = HP_CALI_DBIAS_DEFAULT \
}, \
.regulator1 = { \
.drv_b = 0x0 \
@ -231,7 +231,7 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp
.xpd = 1, \
.slp_mem_dbias = 0, \
.slp_logic_dbias = 0, \
.dbias = HP_CALI_DBIAS \
.dbias = HP_CALI_DBIAS_DEFAULT \
}, \
.regulator1 = { \
.drv_b = 0x0 \
@ -413,7 +413,7 @@ const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mod
.slp_xpd = 0, \
.xpd = 1, \
.slp_dbias = 0, \
.dbias = LP_CALI_DBIAS \
.dbias = LP_CALI_DBIAS_DEFAULT \
}, \
.regulator1 = { \
.drv_b = 0x0 \
@ -447,3 +447,53 @@ const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_m
assert(mode < ARRAY_SIZE(lp_analog));
return &lp_analog[mode];
}
uint32_t get_act_hp_dbias(void)
{
/* hp_cali_dbias is read from efuse to ensure that the hp_active_voltage is close to 1.15V
*/
uint32_t hp_cali_dbias = HP_CALI_DBIAS_DEFAULT;
// uint32_t blk_version = efuse_hal_blk_version();
// if (blk_version >= 3) {
// hp_cali_dbias = efuse_ll_get_active_hp_dbias();
// if (hp_cali_dbias != 0) {
// //efuse dbias need to add 2 to meet the CPU frequency switching
// if (hp_cali_dbias + 2 > 31) {
// hp_cali_dbias = 31;
// } else {
// hp_cali_dbias += 2;
// }
// } else {
// hp_cali_dbias = HP_CALI_DBIAS_DEFAULT;
// ESP_HW_LOGD(TAG, "hp_cali_dbias not burnt in efuse or wrong value was burnt in blk version: %" PRIu32 "\n", blk_version);
// }
// }
return hp_cali_dbias;
}
uint32_t get_act_lp_dbias(void)
{
/* lp_cali_dbias is read from efuse to ensure that the lp_active_voltage is close to 1.15V
*/
uint32_t lp_cali_dbias = LP_CALI_DBIAS_DEFAULT;
// uint32_t blk_version = efuse_hal_blk_version();
// if (blk_version >= 3) {
// lp_cali_dbias = efuse_ll_get_active_lp_dbias();
// if (lp_cali_dbias != 0) {
// //efuse dbias need to add 2 to meet the CPU frequency switching
// if (lp_cali_dbias + 2 > 31) {
// lp_cali_dbias = 31;
// } else {
// lp_cali_dbias += 2;
// }
// } else {
// lp_cali_dbias = LP_CALI_DBIAS_DEFAULT;
// ESP_HW_LOGD(TAG, "lp_cali_dbias not burnt in efuse or wrong value was burnt in blk version: %" PRIu32 "\n", blk_version);
// }
// } else {
// ESP_HW_LOGD(TAG, "blk_version is less than 3, act dbias not burnt in efuse\n");
// }
return lp_cali_dbias;
}

View File

@ -168,11 +168,11 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
if (!(pd_flags & PMU_SLEEP_PD_XTAL)){
analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
analog_default.hp_sys.analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
analog_default.hp_sys.analog.dbias = HP_CALI_DBIAS;
analog_default.hp_sys.analog.dbias = HP_CALI_DBIAS_DEFAULT;
analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
analog_default.lp_sys[LP(SLEEP)].analog.dbias = LP_CALI_DBIAS;
analog_default.lp_sys[LP(SLEEP)].analog.dbias = LP_CALI_DBIAS_DEFAULT;
}
config->analog = analog_default;

View File

@ -1,21 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize OCode
*
*/
void esp_ocode_calib_init(void);
#ifdef __cplusplus
}
#endif

View File

@ -19,9 +19,8 @@
extern "C" {
#endif
#define HP_CALI_DBIAS 25
#define LP_CALI_DBIAS 26
#define HP_CALI_DBIAS_DEFAULT 28
#define LP_CALI_DBIAS_DEFAULT 28
// FOR XTAL FORCE PU IN SLEEP
#define PMU_PD_CUR_SLEEP_ON 0
@ -51,6 +50,9 @@ extern "C" {
#define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12
#define PMU_LP_DBIAS_DEEPSLEEP_0V7 23
uint32_t get_act_hp_dbias(void);
uint32_t get_act_lp_dbias(void);
typedef struct {
pmu_hp_dig_power_reg_t dig_power;
pmu_hp_clk_power_reg_t clk_power;
@ -412,7 +414,7 @@ typedef struct {
typedef struct pmu_sleep_machine_constant {
struct {
uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */
uint16_t min_slp_time_us; /* Minimum sleep protection time (unit: microsecond) */
uint8_t wakeup_wait_cycle; /* Modem wakeup signal (WiFi MAC and BEACON wakeup) waits for the slow & fast clock domain synchronization and the wakeup signal triggers the PMU FSM switching wait cycle (unit: slow clock cycle) */
uint8_t reserved0;
uint16_t reserved1;
@ -424,7 +426,7 @@ typedef struct pmu_sleep_machine_constant {
uint16_t power_up_wait_time_us; /* (unit: microsecond) */
} lp;
struct {
uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */
uint16_t min_slp_time_us; /* Minimum sleep protection time (unit: microsecond) */
uint16_t clock_domain_sync_time_us; /* The Slow OSC clock domain synchronizes time with the Fast OSC domain, at least 4 slow clock cycles (unit: microsecond) */
uint16_t system_dfs_up_work_time_us; /* System DFS up scaling work time (unit: microsecond) */
uint16_t analog_wait_time_us; /* HP LDO power up wait time (unit: microsecond) */

View File

@ -172,6 +172,7 @@ static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq)
clk_ll_bbpll_set_config(pll_freq, xtal_freq);
/* WAIT CALIBRATION DONE */
while(!regi2c_ctrl_ll_bbpll_calibration_is_done());
esp_rom_delay_us(10); // wait for true stop
/* BBPLL CALIBRATION STOP */
regi2c_ctrl_ll_bbpll_calibration_stop();
rtc_clk_enable_i2c_ana_master_clock(false);
@ -185,29 +186,60 @@ static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq)
*/
static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
{
clk_ll_ahb_set_ls_divider(div);
clk_ll_cpu_set_ls_divider(div);
// let f_cpu = f_ahb
clk_ll_cpu_set_divider(div);
clk_ll_ahb_set_divider(div);
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL);
clk_ll_bus_update();
esp_rom_set_cpu_ticks_per_us(cpu_freq);
}
static void rtc_clk_cpu_freq_to_8m(void)
{
clk_ll_ahb_set_ls_divider(1);
clk_ll_cpu_set_ls_divider(1);
clk_ll_cpu_set_divider(1);
clk_ll_ahb_set_divider(1);
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST);
clk_ll_bus_update();
esp_rom_set_cpu_ticks_per_us(20);
}
/**
* Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
* Switch to PLL_F240M as cpu clock source.
* PLL must already be enabled.
* @param cpu_freq new CPU frequency
*/
static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
static void rtc_clk_cpu_freq_to_pll_240_mhz(int cpu_freq_mhz)
{
clk_ll_cpu_set_hs_divider(CLK_LL_PLL_480M_FREQ_MHZ / cpu_freq_mhz);
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL);
// f_hp_root = 240MHz
uint32_t cpu_divider = CLK_LL_PLL_240M_FREQ_MHZ / cpu_freq_mhz;
clk_ll_cpu_set_divider(cpu_divider);
// Constraint: f_ahb <= 48MHz; f_cpu = N * f_ahb (N = 1, 2, 3...)
// let f_ahb = 40MHz
const uint32_t ahb_divider = 6;
assert((cpu_divider <= ahb_divider) && (ahb_divider % cpu_divider == 0));
clk_ll_ahb_set_divider(ahb_divider);
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL_F240M);
clk_ll_bus_update();
esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
}
/**
* Switch to PLL_F160M as cpu clock source.
* PLL must already be enabled.
* @param cpu_freq new CPU frequency
*/
static void rtc_clk_cpu_freq_to_pll_160_mhz(int cpu_freq_mhz)
{
// f_hp_root = 160MHz
uint32_t cpu_divider = CLK_LL_PLL_160M_FREQ_MHZ / cpu_freq_mhz;
clk_ll_cpu_set_divider(cpu_divider);
// Constraint: f_ahb <= 48MHz; f_cpu = N * f_ahb (N = 1, 2, 3...)
// let f_ahb = 40MHz
const uint32_t ahb_divider = 4;
assert((cpu_divider <= ahb_divider) && (ahb_divider % cpu_divider == 0));
clk_ll_ahb_set_divider(ahb_divider);
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL_F160M);
clk_ll_bus_update();
esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
}
@ -219,7 +251,14 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou
uint32_t real_freq_mhz;
uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get();
if (freq_mhz <= xtal_freq && freq_mhz != 0) {
// To maintain APB_MAX (40MHz) while lowering CPU frequency when using a 48MHz XTAL, have to let CPU frequnecy be
// 40MHz with PLL_F160M or PLL_F240M clock source. This is a special case, has to handle separately.
if (xtal_freq == SOC_XTAL_FREQ_48M && freq_mhz == 40) {
real_freq_mhz = freq_mhz;
source = SOC_CPU_CLK_SRC_PLL_F160M;
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
divider = 4;
} else if (freq_mhz <= xtal_freq && freq_mhz != 0) {
divider = xtal_freq / freq_mhz;
real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */
if (real_freq_mhz != freq_mhz) {
@ -229,21 +268,21 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou
source_freq_mhz = xtal_freq;
source = SOC_CPU_CLK_SRC_XTAL;
} else if (freq_mhz == 80) {
} else if (freq_mhz == 240) {
real_freq_mhz = freq_mhz;
source = SOC_CPU_CLK_SRC_PLL;
source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
divider = 6;
} else if (freq_mhz == 120) {
real_freq_mhz = freq_mhz;
source = SOC_CPU_CLK_SRC_PLL;
source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
divider = 4;
source = SOC_CPU_CLK_SRC_PLL_F240M;
source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
divider = 1;
} else if (freq_mhz == 160) {
real_freq_mhz = freq_mhz;
source = SOC_CPU_CLK_SRC_PLL;
source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
divider = 3;
source = SOC_CPU_CLK_SRC_PLL_F160M;
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
divider = 1;
} else if (freq_mhz == 80) {
real_freq_mhz = freq_mhz;
source = SOC_CPU_CLK_SRC_PLL_F160M;
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
divider = 2;
} else {
// unsupported frequency
return false;
@ -266,21 +305,29 @@ 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 (config->source == SOC_CPU_CLK_SRC_XTAL) {
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) {
if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M)) && !s_bbpll_digi_consumers_ref_count) {
// We don't turn off the bbpll if some consumers depend on bbpll
rtc_clk_bbpll_disable();
}
} else if (config->source == SOC_CPU_CLK_SRC_PLL) {
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) {
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M) {
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240M && old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160M) {
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START);
rtc_clk_bbpll_enable();
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz);
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ);
}
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
rtc_clk_cpu_freq_to_pll_240_mhz(config->freq_mhz);
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP);
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F160M) {
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240M && old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160M) {
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START);
rtc_clk_bbpll_enable();
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ);
}
rtc_clk_cpu_freq_to_pll_160_mhz(config->freq_mhz);
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP);
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
rtc_clk_cpu_freq_to_8m();
if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) {
if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M)) && !s_bbpll_digi_consumers_ref_count) {
// We don't turn off the bbpll if some consumers depend on bbpll
rtc_clk_bbpll_disable();
}
@ -292,17 +339,21 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
uint32_t source_freq_mhz;
uint32_t freq_mhz;
uint32_t div = clk_ll_cpu_get_ls_divider(); // div = freq of SOC_ROOT_CLK / freq of CPU_CLK
uint32_t hs_div = clk_ll_cpu_get_hs_divider();
uint32_t div = clk_ll_cpu_get_divider(); // div = freq of SOC_ROOT_CLK / freq of CPU_CLK
switch (source) {
case SOC_CPU_CLK_SRC_XTAL: {
source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get();
freq_mhz = source_freq_mhz / div;
break;
}
case SOC_CPU_CLK_SRC_PLL: {
source_freq_mhz = clk_ll_bbpll_get_freq_mhz();
freq_mhz = source_freq_mhz / hs_div;
case SOC_CPU_CLK_SRC_PLL_F160M: {
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
freq_mhz = source_freq_mhz / div;
break;
}
case SOC_CPU_CLK_SRC_PLL_F240M: {
source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
freq_mhz = source_freq_mhz / div;
break;
}
case SOC_CPU_CLK_SRC_RC_FAST:
@ -325,11 +376,12 @@ 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);
} else if (
config->source == SOC_CPU_CLK_SRC_PLL &&
s_cur_pll_freq == config->source_freq_mhz
) {
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F160M &&
s_cur_pll_freq == CLK_LL_PLL_480M_FREQ_MHZ) {
rtc_clk_cpu_freq_to_pll_160_mhz(config->freq_mhz);
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M &&
s_cur_pll_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_8m();
} else {
@ -356,7 +408,8 @@ void rtc_clk_cpu_set_to_default_config(void)
void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz)
{
rtc_clk_cpu_freq_to_pll_mhz(cpu_freq_mhz);
// TODO: IDF-8641 CPU_MAX_FREQ don't know what to do... pll_240 or pll_160...
rtc_clk_cpu_freq_to_pll_240_mhz(cpu_freq_mhz);
clk_ll_cpu_clk_src_lock_release();
}
@ -375,15 +428,19 @@ static uint32_t rtc_clk_ahb_freq_get(void)
switch (source) {
case SOC_CPU_CLK_SRC_XTAL:
soc_root_freq_mhz = rtc_clk_xtal_freq_get();
divider = clk_ll_ahb_get_ls_divider();
divider = clk_ll_ahb_get_divider();
break;
case SOC_CPU_CLK_SRC_PLL:
soc_root_freq_mhz = clk_ll_bbpll_get_freq_mhz();
divider = clk_ll_ahb_get_hs_divider();
case SOC_CPU_CLK_SRC_PLL_F160M:
soc_root_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
divider = clk_ll_ahb_get_divider();
break;
case SOC_CPU_CLK_SRC_PLL_F240M:
soc_root_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
divider = clk_ll_ahb_get_divider();
break;
case SOC_CPU_CLK_SRC_RC_FAST:
soc_root_freq_mhz = 20;
divider = clk_ll_ahb_get_ls_divider();
divider = clk_ll_ahb_get_divider();
break;
default:
// Unknown SOC_ROOT clock source

View File

@ -79,10 +79,14 @@ void rtc_clk_init(rtc_clk_config_t cfg)
REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1);
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, HP_CALI_DBIAS);
REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0);
uint32_t hp_cali_dbias = get_act_hp_dbias();
uint32_t lp_cali_dbias = get_act_lp_dbias();
clk_ll_rc_fast_tick_conf(); // TODO: IDF-8642 Unnecessary or not?
SET_PERI_REG_BITS(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_S);
SET_PERI_REG_BITS(PMU_HP_MODEM_HP_REGULATOR0_REG, PMU_HP_MODEM_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_MODEM_HP_REGULATOR_DBIAS_S);
SET_PERI_REG_BITS(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, lp_cali_dbias, PMU_HP_SLEEP_LP_REGULATOR_DBIAS_S);
// XTAL freq determined by efuse, and can be directly informed from register field PCR_CLK_XTAL_FREQ

View File

@ -12,6 +12,7 @@
#include "hal/clk_tree_ll.h"
#include "hal/timer_ll.h"
#include "soc/timer_group_reg.h"
#include "soc/pcr_reg.h"
#include "esp_rom_sys.h"
#include "assert.h"
#include "hal/efuse_hal.h"
@ -23,64 +24,31 @@ __attribute__((unused)) static const char *TAG = "rtc_time";
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
* This feature counts the number of XTAL clock cycles within a given number of
* RTC_SLOW_CLK cycles.
*
* Slow clock calibration feature has two modes of operation: one-off and cycling.
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
* enabled using TIMG_RTC_CALI_START bit.
*/
/* On ESP32C5, TIMG_RTC_CALI_CLK_SEL can config to 0, 1, 2, 3
* 0 or 3: calibrate RC_SLOW clock
* 1: calibrate RC_FAST clock
* 2: calibrate 32K clock, which 32k depends on reg_32k_sel: 0: Internal 32 kHz RC oscillator, 1: External 32 kHz XTAL, 2: External 32kHz clock input by lp_pad_gpio0
*/
#define TIMG_RTC_CALI_CLK_SEL_RC_SLOW 0
#define TIMG_RTC_CALI_CLK_SEL_RC_FAST 1
#define TIMG_RTC_CALI_CLK_SEL_32K 2
#define CLK_CAL_TIMEOUT_THRES(cal_clk, cycles) ((cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL || cal_clk == RTC_CAL_32K_OSC_SLOW) ? (cycles << 12) : (cycles << 10))
/**
* @brief Clock calibration function used by rtc_clk_cal
*
* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
* This feature counts the number of XTAL clock cycles within a given number of
* RTC_SLOW_CLK cycles.
*
* Slow clock calibration feature has two modes of operation: one-off and cycling.
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
* enabled using TIMG_RTC_CALI_START bit.
*
* @param cal_clk which clock to calibrate
* @param slowclk_cycles number of slow clock cycles to count
* @return number of XTAL clock cycles within the given number of slow clock cycles
*/
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
{
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
uint32_t cali_clk_sel = 0;
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
soc_rtc_slow_clk_src_t old_32k_cal_clk_sel = clk_ll_32k_calibration_get_target();
if (cal_clk == RTC_CAL_RTC_MUX) {
cal_clk = (rtc_cal_sel_t)slow_clk_src;
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
cal_clk = RTC_CAL_RC_SLOW;
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
cal_clk = RTC_CAL_32K_XTAL;
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
cal_clk = RTC_CAL_RC32K;
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
cal_clk = RTC_CAL_32K_OSC_SLOW;
}
}
// TODO: [ESP32C5] IDF-8642 Seems RC_SLOW, RC_FAST can't be calibrated on beta3
// if (cal_clk == RTC_CAL_RC_FAST) {
// cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_FAST;
// } else if (cal_clk == RTC_CAL_RC_SLOW) {
// cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW;
// } else
{
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K;
clk_ll_32k_calibration_set_target((soc_rtc_slow_clk_src_t)cal_clk);
if (cal_clk < 0 || cal_clk >= RTC_CAL_INVALID_CLK) {
ESP_EARLY_LOGE(TAG, "clock not supported to be calibrated");
return 0;
}
/* Enable requested clock (150k clock is always on) */
// All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock
// Only enable if originally was disabled, and set back to the disable state after calibration is done
@ -90,16 +58,16 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
clk_ll_xtal32k_digi_enable();
}
// bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
// bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
// if (cal_clk == RTC_CAL_RC_FAST) {
// if (!rc_fast_enabled) {
// rtc_clk_8m_enable(true);
// }
// if (!dig_rc_fast_enabled) {
// rtc_dig_clk8m_enable();
// }
// }
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
if (cal_clk == RTC_CAL_RC_FAST) {
if (!rc_fast_enabled) {
rtc_clk_8m_enable(true);
}
if (!dig_rc_fast_enabled) {
rtc_dig_clk8m_enable();
}
}
bool rc32k_enabled = clk_ll_rc32k_is_enabled();
bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled();
@ -126,22 +94,22 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
}
/* Prepare calibration */
// calibration clock source is set by PCR register: PCR_32K_SEL
// REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel);
REG_SET_FIELD(PCR_CTRL_32K_CONF_REG, PCR_32K_SEL, cal_clk);
if (cal_clk == RTC_CAL_RC_FAST) {
clk_ll_rc_fast_tick_conf();
}
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
/* Figure out how long to wait for calibration to finish */
/* Set timeout reg and expect time delay*/
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk, slowclk_cycles));
uint32_t expected_freq;
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K) {
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles));
if (cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL || cal_clk == RTC_CAL_32K_OSC_SLOW) {
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
} else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles));
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
} else if (cal_clk == RTC_CAL_RC_FAST) {
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX >> CLK_LL_RC_FAST_TICK_DIV_BITS;
} else {
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles));
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX;
}
uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
@ -156,12 +124,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) {
cal_val = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE);
// TODO: IDF-8642 Check whether this workaround still need for C5
// /*The Fosc CLK of calibration circuit is divided by 32.
// So we need to multiply the frequency of the FOSC by 32 times.*/
// if (cal_clk == RTC_CAL_RC_FAST) {
// cal_val = cal_val >> 5;
// }
/*The Fosc CLK of calibration circuit is divided by a factor, k.
So we need to multiply the frequency of the FOSC by k times.*/
if (cal_clk == RTC_CAL_RC_FAST) {
cal_val = cal_val >> CLK_LL_RC_FAST_TICK_DIV_BITS;
}
break;
}
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) {
@ -176,14 +143,14 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
clk_ll_xtal32k_digi_disable();
}
// if (cal_clk == RTC_CAL_RC_FAST) {
// if (!dig_rc_fast_enabled) {
// rtc_dig_clk8m_disable();
// }
// if (!rc_fast_enabled) {
// rtc_clk_8m_enable(false);
// }
// }
if (cal_clk == RTC_CAL_RC_FAST) {
if (!dig_rc_fast_enabled) {
rtc_dig_clk8m_disable();
}
if (!rc_fast_enabled) {
rtc_clk_8m_enable(false);
}
}
if (cal_clk == RTC_CAL_RC32K) {
if (!dig_rc32k_enabled) {
@ -194,11 +161,6 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
}
}
// Always set back the calibration 32kHz clock selection
if (old_32k_cal_clk_sel != SOC_RTC_SLOW_CLK_SRC_INVALID) {
clk_ll_32k_calibration_set_target(old_32k_cal_clk_sel);
}
return cal_val;
}
@ -212,13 +174,13 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
{
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
// TODO: IDF-8642 Check whether this workaround still need for C5
// /*The Fosc CLK of calibration circuit is divided by 32.
// So we need to divide the calibrate cycles of the FOSC by 32 to
// avoid excessive calibration time.*/
// if (cal_clk == RTC_CAL_RC_FAST) {
// slowclk_cycles = slowclk_cycles >> 5;
// }
/*The Fosc CLK of calibration circuit is divided by a factor, k.
So we need to divide the calibrate cycles of the FOSC by k to
avoid excessive calibration time.*/
if (cal_clk == RTC_CAL_RC_FAST) {
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_TICK_DIV_BITS;
}
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
@ -246,8 +208,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
uint64_t rtc_time_get(void)
{
ESP_EARLY_LOGW(TAG, "rtc_timer has not been implemented yet");
return 0;
return lp_timer_hal_get_cycle_count();
}
uint32_t rtc_clk_freq_cal(uint32_t cal_val)

View File

@ -84,8 +84,6 @@ void rtc_clk_init(rtc_clk_config_t cfg)
SET_PERI_REG_BITS(PMU_HP_MODEM_HP_REGULATOR0_REG, PMU_HP_MODEM_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_MODEM_HP_REGULATOR_DBIAS_S);
SET_PERI_REG_BITS(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, lp_cali_dbias, PMU_HP_SLEEP_LP_REGULATOR_DBIAS_S);
clk_ll_rc_fast_tick_conf();
soc_xtal_freq_t xtal_freq = cfg.xtal_freq;
esp_rom_output_tx_wait_idle(0);
rtc_clk_xtal_freq_update(xtal_freq);

View File

@ -125,6 +125,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
/* Prepare calibration */
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel);
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
clk_ll_rc_fast_tick_conf();
}
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
/* Figure out how long to wait for calibration to finish */
@ -137,6 +140,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
} else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles));
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
expected_freq = expected_freq >> CLK_LL_RC_FAST_TICK_DIV_BITS;
}
} else {
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles));
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX;
@ -160,7 +166,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
calibration. */
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
if (cal_clk == RTC_CAL_RC_FAST) {
cal_val = cal_val >> 5;
cal_val = cal_val >> CLK_LL_RC_FAST_TICK_DIV_BITS;
CLEAR_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
}
}
@ -221,7 +227,7 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
avoid excessive calibration time.*/
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
if (cal_clk == RTC_CAL_RC_FAST) {
slowclk_cycles = slowclk_cycles >> 5;
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_TICK_DIV_BITS;
SET_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
}
}

View File

@ -52,8 +52,6 @@ void rtc_clk_init(rtc_clk_config_t cfg)
SET_PERI_REG_BITS(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_S);
SET_PERI_REG_BITS(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, lp_cali_dbias, PMU_HP_SLEEP_LP_REGULATOR_DBIAS_S);
clk_ll_rc_fast_tick_conf();
soc_xtal_freq_t xtal_freq = cfg.xtal_freq;
esp_rom_output_tx_wait_idle(0);
rtc_clk_xtal_freq_update(xtal_freq);

View File

@ -125,6 +125,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
/* Prepare calibration */
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel);
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
clk_ll_rc_fast_tick_conf();
}
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
/* Figure out how long to wait for calibration to finish */
@ -137,6 +140,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
} else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_8M_CAL_TIMEOUT_THRES(slowclk_cycles));
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
expected_freq = expected_freq >> CLK_LL_RC_FAST_TICK_DIV_BITS;
}
} else {
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles));
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX;
@ -160,7 +166,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
calibration. */
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
if (cal_clk == RTC_CAL_RC_FAST) {
cal_val = cal_val >> 5;
cal_val = cal_val >> CLK_LL_RC_FAST_TICK_DIV_BITS;
CLEAR_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
}
}
@ -221,7 +227,7 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
avoid excessive calibration time.*/
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
if (cal_clk == RTC_CAL_RC_FAST) {
slowclk_cycles = slowclk_cycles >> 5;
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_TICK_DIV_BITS;
SET_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
}
}

View File

@ -41,6 +41,9 @@ static esp_clk_tree_calibrated_freq_t s_calibrated_freq = {};
#define DEFAULT_32K_CLK_CAL_CYCLES 100
/* Number of cycles for RC_FAST calibration */
#define DEFAULT_RC_FAST_CAL_CYCLES 10000 // RC_FAST has a higher frequency, therefore, requires more cycles to get an accurate value
// Usually we calibrate on the divider of the RC_FAST clock, the cal_cycles is divided by
// the divider factor internally in rtc_clk_cal, so the time to spend on calibrating RC_FAST
// is always (10000 / f_rc_fast)
/**
@ -187,6 +190,10 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec
#if SOC_CLK_LP_FAST_SUPPORT_LP_PLL
case SOC_RTC_FAST_CLK_SRC_LP_PLL:
return clk_ll_lp_pll_get_freq_mhz() * MHZ;
#endif
#if SOC_CLK_LP_FAST_SUPPORT_XTAL
case SOC_RTC_FAST_CLK_SRC_XTAL:
return clk_hal_xtal_get_freq_mhz() * MHZ;
#endif
default:
// Invalid clock source

View File

@ -7,7 +7,6 @@
#include "esp_attr.h"
#include "soc/i2c_ana_mst_reg.h"
#include "modem/modem_lpcon_reg.h"
#include "soc/pmu_reg.h"
#define REGI2C_BIAS_MST_SEL (BIT(8))
#define REGI2C_BBPLL_MST_SEL (BIT(9))
@ -77,8 +76,6 @@ static IRAM_ATTR uint8_t regi2c_enable_block(uint8_t block)
uint32_t i2c_sel = 0;
REG_SET_BIT(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN);
REG_SET_BIT(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); // TODO: IDF-8642 Move to pmu_init()
REG_SET_BIT(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); // TODO: IDF-8642 Move to pmu_init()
/* Before config I2C register, enable corresponding slave. */
switch (block) {

View File

@ -30,7 +30,6 @@
#include "esp_private/esp_pmu.h"
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"
#include "ocode_init.h"
/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
* Larger values increase startup delay. Smaller values may cause false positive
@ -44,20 +43,13 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src);
static const char *TAG = "clk";
// TODO: [ESP32C5] IDF-8642
void esp_rtc_init(void)
{
#if !CONFIG_IDF_ENV_FPGA
#if SOC_PMU_SUPPORTED
pmu_init();
#endif
if (esp_rom_get_reset_reason(0) == RESET_REASON_CHIP_POWER_ON) {
esp_ocode_calib_init();
}
#endif
}
// TODO: [ESP32C5] IDF-8642
__attribute__((weak)) void esp_clk_init(void)
{
#if !CONFIG_IDF_ENV_FPGA
@ -122,7 +114,7 @@ __attribute__((weak)) void esp_clk_init(void)
// Re calculate the ccount to make time calculation correct.
esp_cpu_set_cycle_count((uint64_t)esp_cpu_get_cycle_count() * new_freq_mhz / old_freq_mhz);
// Set crypto clock (`clk_sec`) to use 160M SPLL clock
// Set crypto clock (`clk_sec`) to use 480M SPLL clock
REG_SET_FIELD(PCR_SEC_CONF_REG, PCR_SEC_CLK_SEL, 0x2);
}
@ -195,7 +187,8 @@ void rtc_clk_select_rtc_slow_clk(void)
*/
__attribute__((weak)) void esp_perip_clk_init(void)
{
// TODO: [ESP32C5] IDF-8844
// TODO: [ESP32C5] IDF-8844
#if SOC_MODEM_CLOCK_SUPPORTED
// modem_clock_domain_pmu_state_icg_map_init();
/* During system initialization, the low-power clock source of the modem
* (WiFi, BLE or Coexist) follows the configuration of the slow clock source
@ -211,6 +204,7 @@ __attribute__((weak)) void esp_perip_clk_init(void)
: (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_EXT32K
: MODEM_CLOCK_LPCLK_SRC_RC32K);
modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0);
#endif
ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet");
#if 0 // TODO: [ESP32C5] IDF-8844

View File

@ -3,8 +3,9 @@ menu "Serial flasher config"
config ESPTOOLPY_NO_STUB
bool "Disable download stub"
default "y" if IDF_ENV_FPGA || IDF_ENV_BRINGUP
default "n"
default y if IDF_ENV_FPGA || IDF_ENV_BRINGUP
default y if IDF_TARGET_ESP32C5 # TODO: IDF-8631 to be removed
default n
help
The flasher tool sends a precompiled download stub first by default. That stub allows things

View File

@ -56,7 +56,7 @@ if(NOT BOOTLOADER_BUILD)
endif()
endif()
if(CONFIG_SOC_CLK_TREE_SUPPORTED OR CONFIG_IDF_TARGET_ESP32C5) # TODO: IDF-8642
if(CONFIG_SOC_CLK_TREE_SUPPORTED)
list(APPEND srcs "${target}/clk_tree_hal.c")
endif()

View File

@ -17,8 +17,10 @@ uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src)
switch (cpu_clk_src) {
case SOC_CPU_CLK_SRC_XTAL:
return clk_hal_xtal_get_freq_mhz();
case SOC_CPU_CLK_SRC_PLL:
return clk_ll_bbpll_get_freq_mhz();
case SOC_CPU_CLK_SRC_PLL_F160M:
return CLK_LL_PLL_160M_FREQ_MHZ;
case SOC_CPU_CLK_SRC_PLL_F240M:
return CLK_LL_PLL_240M_FREQ_MHZ;
case SOC_CPU_CLK_SRC_RC_FAST:
return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ;
default:
@ -31,16 +33,14 @@ uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src)
uint32_t clk_hal_cpu_get_freq_hz(void)
{
soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
uint32_t divider = (source == SOC_CPU_CLK_SRC_PLL) ? clk_ll_cpu_get_hs_divider() : clk_ll_cpu_get_ls_divider();
uint32_t divider = clk_ll_cpu_get_divider();
return clk_hal_soc_root_get_freq_mhz(source) * MHZ / divider;
}
uint32_t clk_hal_ahb_get_freq_hz(void)
{
soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
uint32_t divider = (source == SOC_CPU_CLK_SRC_PLL) ? clk_ll_ahb_get_hs_divider() : clk_ll_ahb_get_ls_divider();
uint32_t divider = clk_ll_ahb_get_divider();
return clk_hal_soc_root_get_freq_mhz(source) * MHZ / divider;
}

View File

@ -40,12 +40,8 @@ extern "C" {
.dbuf = 1, \
}
/*
Set the frequency division factor of ref_tick
The FOSC of rtc calibration uses the 32 frequency division clock,
So the frequency division factor of ref_tick must be greater than or equal to 32
*/
#define REG_FOSC_TICK_NUM 255 // TODO: IDF-8642 No need? Can calibrate on RC_FAST directly?
// Fix default division factor for the RC_FAST clock for calibration to be 32
#define CLK_LL_RC_FAST_TICK_DIV_BITS 5
/**
* @brief XTAL32K_CLK enable modes
@ -289,7 +285,7 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_bbpll_get_freq_mhz(
}
/**
* @brief Set BBPLL frequency from XTAL source (Digital part)
* @brief Set SPLL frequency from XTAL source (Digital part)
*
* @param pll_freq_mhz PLL frequency, in MHz
*/
@ -301,7 +297,7 @@ static inline __attribute__((always_inline)) void clk_ll_bbpll_set_freq_mhz(uint
}
/**
* @brief Set BBPLL frequency from XTAL source (Analog part)
* @brief Set SPLL frequency from XTAL source (Analog part)
*
* @param pll_freq_mhz PLL frequency, in MHz
* @param xtal_freq_mhz XTAL frequency, in MHz
@ -313,36 +309,52 @@ static inline __attribute__((always_inline)) void clk_ll_bbpll_set_config(uint32
uint8_t div7_0;
uint8_t dr1;
uint8_t dr3;
uint8_t dchgp;
uint8_t dbias;
uint8_t dcur;
uint8_t dchgp = 5;
uint8_t dbias = 3;
uint8_t href = 3;
uint8_t lref = 1;
/* Configure 480M PLL */
switch (xtal_freq_mhz) {
case SOC_XTAL_FREQ_48M:
div_ref = 1;
div7_0 = 10;
dr1 = 1;
dr3 = 1;
break;
case SOC_XTAL_FREQ_40M:
default:
div_ref = 0;
div7_0 = 8;
div_ref = 1;
div7_0 = 12;
dr1 = 0;
dr3 = 0;
break;
default:
div_ref = 1;
div7_0 = 12;
dr1 = 0;
dr3 = 0;
dchgp = 5;
dcur = 3;
dbias = 2;
break;
}
uint8_t i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (div_ref);
uint8_t i2c_bbpll_div_7_0 = div7_0;
uint8_t i2c_bbpll_dcur = (1 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref);
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3);
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, lref);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, href);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias);
}
/**
* @brief To enable the change of soc_clk_sel, cpu_div_num, and ahb_div_num
*/
static inline __attribute__((always_inline)) void clk_ll_bus_update(void)
{
PCR.bus_clk_update.bus_clock_update = 1;
while (PCR.bus_clk_update.bus_clock_update);
}
/**
* @brief Select the clock source for CPU_CLK (SOC Clock Root)
*
@ -354,12 +366,15 @@ static inline __attribute__((always_inline)) void clk_ll_cpu_set_src(soc_cpu_clk
case SOC_CPU_CLK_SRC_XTAL:
PCR.sysclk_conf.soc_clk_sel = 0;
break;
case SOC_CPU_CLK_SRC_PLL:
case SOC_CPU_CLK_SRC_RC_FAST:
PCR.sysclk_conf.soc_clk_sel = 1;
break;
case SOC_CPU_CLK_SRC_RC_FAST:
case SOC_CPU_CLK_SRC_PLL_F160M:
PCR.sysclk_conf.soc_clk_sel = 2;
break;
case SOC_CPU_CLK_SRC_PLL_F240M:
PCR.sysclk_conf.soc_clk_sel = 3;
break;
default:
// Unsupported SOC_CLK mux input sel
abort();
@ -378,9 +393,11 @@ static inline __attribute__((always_inline)) soc_cpu_clk_src_t clk_ll_cpu_get_sr
case 0:
return SOC_CPU_CLK_SRC_XTAL;
case 1:
return SOC_CPU_CLK_SRC_PLL;
case 2:
return SOC_CPU_CLK_SRC_RC_FAST;
case 2:
return SOC_CPU_CLK_SRC_PLL_F160M;
case 3:
return SOC_CPU_CLK_SRC_PLL_F240M;
default:
// Invalid SOC_CLK_SEL value
return SOC_CPU_CLK_SRC_INVALID;
@ -388,129 +405,47 @@ static inline __attribute__((always_inline)) soc_cpu_clk_src_t clk_ll_cpu_get_sr
}
/**
* @brief Set CPU_CLK's high-speed divider (valid when SOC_ROOT clock source is PLL)
* @brief Set CPU_CLK's divider
*
* @param divider Divider. (PCR_HS_DIV_NUM + 1) * (PCR_CPU_HS_DIV_NUM + 1) = divider.
* @param divider Divider. (PCR_CPU_DIV_NUM + 1) = divider.
*/
static inline __attribute__((always_inline)) void clk_ll_cpu_set_hs_divider(uint32_t divider)
static inline __attribute__((always_inline)) void clk_ll_cpu_set_divider(uint32_t divider)
{
// SOC_ROOT_CLK ---(1)---> HP_ROOT_CLK ---(2)---> CPU_CLK
// (1) not configurable for the target (HRO register field: PCR_HS_DIV_NUM)
// Fixed at 3 for HS clock source
// Corresponding register field value is PCR_HS_DIV_NUM=2
// (2) configurable
// HS divider option: 1, 2, 4 (PCR_CPU_HS_DIV_NUM=0, 1, 3)
HAL_ASSERT(divider == 3 || divider == 4 || divider == 6 || divider == 12);
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.cpu_freq_conf, cpu_div_num, (divider / 3) - 1);
// 120MHz CPU freq cannot be achieved through divider, need to set force_120m
// This field is only valid if PCR_CPU_HS_DIV_NUM=0 and PCR_SOC_CLK_SEL=SOC_CPU_CLK_SRC_PLL
// bool force_120m = (divider == 4) ? 1 : 0;
// PCR.cpu_freq_conf.cpu_hs_120m_force = force_120m;
HAL_ASSERT(divider >= 1);
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.cpu_freq_conf, cpu_div_num, (divider) - 1);
}
/**
* @brief Set CPU_CLK's low-speed divider (valid when SOC_ROOT clock source is XTAL/RC_FAST)
* @brief Get CPU_CLK's divider
*
* @param divider Divider. (PCR_LS_DIV_NUM + 1) * (PCR_CPU_LS_DIV_NUM + 1) = divider.
* @return Divider. Divider = (PCR_CPU_DIV_NUM + 1).
*/
static inline __attribute__((always_inline)) void clk_ll_cpu_set_ls_divider(uint32_t divider)
static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(void)
{
// SOC_ROOT_CLK ---(1)---> HP_ROOT_CLK ---(2)---> CPU_CLK
// (1) not configurable for the target (HRO register field: PCR_LS_DIV_NUM)
// Fixed at 1 for LS clock source
// Corresponding register field value is PCR_LS_DIV_NUM=0
// (2) configurable
// LS divider option: 1, 2, 4, 8, 16, 32 (PCR_CPU_LS_DIV_NUM=0, 1, 3, 7, 15, 31)
HAL_ASSERT((divider > 0) && ((divider & (divider - 1)) == 0));
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.cpu_freq_conf, cpu_div_num, divider - 1);
return HAL_FORCE_READ_U32_REG_FIELD(PCR.cpu_freq_conf, cpu_div_num) + 1;
}
/**
* @brief Get CPU_CLK's high-speed divider
* @brief Set AHB_CLK's divider
*
* @return Divider. Divider = (PCR_HS_DIV_NUM + 1) * (PCR_CPU_HS_DIV_NUM + 1).
*/
static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_hs_divider(void)
{
// uint32_t force_120m = PCR.cpu_freq_conf.cpu_hs_120m_force;
uint32_t cpu_hs_div = HAL_FORCE_READ_U32_REG_FIELD(PCR.cpu_freq_conf, cpu_div_num);
if (cpu_hs_div == 0) {
return 4;
}
uint32_t hp_root_hs_div = HAL_FORCE_READ_U32_REG_FIELD(PCR.sysclk_conf, hs_div_num);
return (hp_root_hs_div + 1) * (cpu_hs_div + 1);
}
/**
* @brief Get CPU_CLK's low-speed divider
* Constraint: f_ahb <= 48 MHz, f_cpu = n * f_ahb
*
* @return Divider. Divider = (PCR_LS_DIV_NUM + 1) * (PCR_CPU_LS_DIV_NUM + 1).
* @param divider Divider. (PCR_AHB_DIV_NUM + 1) = divider.
*/
static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_ls_divider(void)
static inline __attribute__((always_inline)) void clk_ll_ahb_set_divider(uint32_t divider)
{
uint32_t cpu_ls_div = HAL_FORCE_READ_U32_REG_FIELD(PCR.cpu_freq_conf, cpu_div_num);
uint32_t hp_root_ls_div = HAL_FORCE_READ_U32_REG_FIELD(PCR.sysclk_conf, ls_div_num);
return (hp_root_ls_div + 1) * (cpu_ls_div + 1);
}
/**
* @brief Set AHB_CLK's high-speed divider (valid when SOC_ROOT clock source is PLL)
*
* @param divider Divider. (PCR_HS_DIV_NUM + 1) * (PCR_AHB_HS_DIV_NUM + 1) = divider.
*/
static inline __attribute__((always_inline)) void clk_ll_ahb_set_hs_divider(uint32_t divider)
{
// SOC_ROOT_CLK ---(1)---> HP_ROOT_CLK ---(2)---> AHB_CLK
// (1) not configurable for the target (HRO register field: PCR_HS_DIV_NUM)
// Fixed at 3 for HS clock source
// Corresponding register field value is PCR_HS_DIV_NUM=2
// (2) configurable
// HS divider option: 4, 8, 16 (PCR_AHB_HS_DIV_NUM=3, 7, 15)
HAL_ASSERT(divider == 12 || divider == 24 || divider == 48);
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.ahb_freq_conf, ahb_div_num, (divider / 3) - 1);
}
/**
* @brief Set AHB_CLK's low-speed divider (valid when SOC_ROOT clock source is XTAL/RC_FAST)
*
* @param divider Divider. (PCR_LS_DIV_NUM + 1) * (PCR_AHB_LS_DIV_NUM + 1) = divider.
*/
static inline __attribute__((always_inline)) void clk_ll_ahb_set_ls_divider(uint32_t divider)
{
// SOC_ROOT_CLK ---(1)---> HP_ROOT_CLK ---(2)---> AHB_CLK
// (1) not configurable for the target (HRO register field: PCR_LS_DIV_NUM)
// Fixed at 1 for LS clock source
// Corresponding register field value is PCR_LS_DIV_NUM=0
// (2) configurable
// LS divider option: 1, 2, 4, 8, 16, 32 (PCR_CPU_LS_DIV_NUM=0, 1, 3, 7, 15, 31)
HAL_ASSERT((divider > 0) && ((divider & (divider - 1)) == 0));
HAL_ASSERT(divider >= 1);
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.ahb_freq_conf, ahb_div_num, divider - 1);
}
/**
* @brief Get AHB_CLK's high-speed divider
* @brief Get AHB_CLK's divider
*
* @return Divider. Divider = (PCR_HS_DIV_NUM + 1) * (PCR_AHB_HS_DIV_NUM + 1).
* @return Divider. Divider = (PCR_AHB_DIV_NUM + 1).
*/
static inline __attribute__((always_inline)) uint32_t clk_ll_ahb_get_hs_divider(void)
static inline __attribute__((always_inline)) uint32_t clk_ll_ahb_get_divider(void)
{
uint32_t ahb_hs_div = HAL_FORCE_READ_U32_REG_FIELD(PCR.ahb_freq_conf, ahb_div_num);
uint32_t hp_root_hs_div = HAL_FORCE_READ_U32_REG_FIELD(PCR.sysclk_conf, hs_div_num);
return (hp_root_hs_div + 1) * (ahb_hs_div + 1);
}
/**
* @brief Get AHB_CLK's low-speed divider
*
* @return Divider. Divider = (PCR_LS_DIV_NUM + 1) * (PCR_AHB_LS_DIV_NUM + 1).
*/
static inline __attribute__((always_inline)) uint32_t clk_ll_ahb_get_ls_divider(void)
{
uint32_t ahb_ls_div = HAL_FORCE_READ_U32_REG_FIELD(PCR.ahb_freq_conf, ahb_div_num);
uint32_t hp_root_ls_div = HAL_FORCE_READ_U32_REG_FIELD(PCR.sysclk_conf, ls_div_num);
return (hp_root_ls_div + 1) * (ahb_ls_div + 1);
return HAL_FORCE_READ_U32_REG_FIELD(PCR.ahb_freq_conf, ahb_div_num) + 1;
}
/**
@ -536,103 +471,6 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_apb_get_divider(voi
return HAL_FORCE_READ_U32_REG_FIELD(PCR.apb_freq_conf, apb_div_num) + 1;
}
/**
* @brief Set MSPI_FAST_CLK's high-speed divider (valid when SOC_ROOT clock source is PLL)
*
* @param divider Divider.
*/
static inline __attribute__((always_inline)) void clk_ll_mspi_fast_set_hs_divider(uint32_t divider)
{
// SOC_ROOT_CLK ------> MSPI_FAST_CLK
// HS divider option: 4, 5, 6 (PCR_MSPI_FAST_HS_DIV_NUM=3, 4, 5)
uint32_t div_num = 0;
switch (divider) {
case 4:
div_num = 3;
break;
case 5:
div_num = 4;
break;
case 6:
div_num = 5;
break;
default:
// Unsupported HS MSPI_FAST divider
abort();
}
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.mspi_clk_conf, mspi_fast_div_num, div_num);
}
/**
* @brief Set MSPI_FAST_CLK's low-speed divider (valid when SOC_ROOT clock source is XTAL/RC_FAST)
*
* @param divider Divider.
*/
static inline __attribute__((always_inline)) void clk_ll_mspi_fast_set_ls_divider(uint32_t divider)
{
// SOC_ROOT_CLK ------> MSPI_FAST_CLK
// LS divider option: 1, 2, 4 (PCR_MSPI_FAST_LS_DIV_NUM=0, 1, 2)
uint32_t div_num = 0;
switch (divider) {
case 1:
div_num = 0;
break;
case 2:
div_num = 1;
break;
case 4:
div_num = 2;
break;
default:
// Unsupported LS MSPI_FAST divider
abort();
}
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.mspi_clk_conf, mspi_fast_div_num, div_num);
}
/**
* @brief Select the calibration 32kHz clock source for timergroup0
*
* @param in_sel One of the 32kHz clock sources (RC32K_CLK, XTAL32K_CLK, OSC_SLOW_CLK)
*/
static inline __attribute__((always_inline)) void clk_ll_32k_calibration_set_target(soc_rtc_slow_clk_src_t in_sel)
{
switch (in_sel) {
case SOC_RTC_SLOW_CLK_SRC_RC32K:
PCR.ctrl_32k_conf.clk_32k_sel = 0;
break;
case SOC_RTC_SLOW_CLK_SRC_XTAL32K:
PCR.ctrl_32k_conf.clk_32k_sel = 1;
break;
case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW:
PCR.ctrl_32k_conf.clk_32k_sel = 2;
break;
default:
// Unsupported 32K_SEL mux input
abort();
}
}
/**
* @brief Get the calibration 32kHz clock source for timergroup0
*
* @return soc_rtc_slow_clk_src_t Currently selected calibration 32kHz clock (one of the 32kHz clocks)
*/
static inline __attribute__((always_inline)) soc_rtc_slow_clk_src_t clk_ll_32k_calibration_get_target(void)
{
uint32_t clk_sel = PCR.ctrl_32k_conf.clk_32k_sel;
switch (clk_sel) {
case 0:
return SOC_RTC_SLOW_CLK_SRC_RC32K;
case 1:
return SOC_RTC_SLOW_CLK_SRC_XTAL32K;
case 2:
return SOC_RTC_SLOW_CLK_SRC_OSC_SLOW;
default:
return SOC_RTC_SLOW_CLK_SRC_INVALID;
}
}
/**
* @brief Select the clock source for RTC_SLOW_CLK
*
@ -695,6 +533,9 @@ static inline __attribute__((always_inline)) void clk_ll_rtc_fast_set_src(soc_rt
case SOC_RTC_FAST_CLK_SRC_XTAL_D2:
LP_CLKRST.lp_clk_conf.fast_clk_sel = 1;
break;
case SOC_RTC_FAST_CLK_SRC_XTAL:
LP_CLKRST.lp_clk_conf.fast_clk_sel = 2;
break;
default:
// Unsupported RTC_FAST_CLK mux input sel
abort();
@ -714,6 +555,8 @@ static inline __attribute__((always_inline)) soc_rtc_fast_clk_src_t clk_ll_rtc_f
return SOC_RTC_FAST_CLK_SRC_RC_FAST;
case 1:
return SOC_RTC_FAST_CLK_SRC_XTAL_D2;
case 2:
return SOC_RTC_FAST_CLK_SRC_XTAL;
default:
return SOC_RTC_FAST_CLK_SRC_INVALID;
}
@ -741,6 +584,14 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_rc_fast_get_divider
return 1;
}
/**
* @brief Set the frequency division factor of RC_FAST clock
*/
static inline void clk_ll_rc_fast_tick_conf(void)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.ctrl_32k_conf, fosc_tick_num, (1 << CLK_LL_RC_FAST_TICK_DIV_BITS) - 1); // divider = 1 << CLK_LL_RC_FAST_TICK_DIV_BITS
}
/**
* @brief Set RC_SLOW_CLK divider
*
@ -753,49 +604,6 @@ static inline __attribute__((always_inline)) void clk_ll_rc_slow_set_divider(uin
}
/************************** LP STORAGE REGISTER STORE/LOAD **************************/
#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION
/**
* @brief Store XTAL_CLK frequency in RTC storage register
*
* Value of RTC_XTAL_FREQ_REG is stored as two copies in lower and upper 16-bit
* halves. These are the routines to work with that representation.
*
* @param xtal_freq_mhz XTAL frequency, in MHz. The frequency must necessarily be even,
* otherwise there will be a conflict with the low bit, which is used to disable logs
* in the ROM code.
*/
static inline __attribute__((always_inline)) void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz)
{
// Read the status of whether disabling logging from ROM code
uint32_t reg = READ_PERI_REG(RTC_XTAL_FREQ_REG) & RTC_DISABLE_ROM_LOG;
// If so, need to write back this setting
if (reg == RTC_DISABLE_ROM_LOG) {
xtal_freq_mhz |= 1;
}
WRITE_PERI_REG(RTC_XTAL_FREQ_REG, (xtal_freq_mhz & UINT16_MAX) | ((xtal_freq_mhz & UINT16_MAX) << 16));
}
/**
* @brief Load XTAL_CLK frequency from RTC storage register
*
* Value of RTC_XTAL_FREQ_REG is stored as two copies in lower and upper 16-bit
* halves. These are the routines to work with that representation.
*
* @return XTAL frequency, in MHz. Returns 0 if value in reg is invalid.
*/
static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_load_freq_mhz(void)
{
// Read from RTC storage register
uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG);
if ((xtal_freq_reg & 0xFFFF) == ((xtal_freq_reg >> 16) & 0xFFFF) &&
xtal_freq_reg != 0 && xtal_freq_reg != UINT32_MAX) {
return xtal_freq_reg & ~RTC_DISABLE_ROM_LOG & UINT16_MAX;
}
// If the format in reg is invalid
return 0;
}
#endif
/**
* @brief Store RTC_SLOW_CLK calibration value in RTC storage register
*
@ -821,16 +629,6 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_rtc_slow_load_cal(v
return REG_READ(RTC_SLOW_CLK_CAL_REG);
}
/*
Set the frequency division factor of ref_tick
*/
static inline void clk_ll_rc_fast_tick_conf(void)
{
PCR.ctrl_32k_conf.fosc_tick_num = REG_FOSC_TICK_NUM;
}
#ifdef __cplusplus
}
#endif

View File

@ -44,7 +44,8 @@ Set the frequency division factor of ref_tick
The FOSC of rtc calibration uses the 32 frequency division clock for ECO1,
So the frequency division factor of ref_tick must be greater than or equal to 32
*/
#define REG_FOSC_TICK_NUM 255
#define CLK_LL_RC_FAST_TICK_DIV_BITS 5
#define REG_FOSC_TICK_NUM 255
/**
* @brief XTAL32K_CLK enable modes
@ -810,7 +811,7 @@ Set the frequency division factor of ref_tick
*/
static inline void clk_ll_rc_fast_tick_conf(void)
{
PCR.ctrl_tick_conf.fosc_tick_num = REG_FOSC_TICK_NUM;
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.ctrl_tick_conf, fosc_tick_num, REG_FOSC_TICK_NUM); // enable a division of 32 to the fosc clock
}

View File

@ -808,7 +808,7 @@ Set the frequency division factor of ref_tick
*/
static inline void clk_ll_rc_fast_tick_conf(void)
{
PCR.ctrl_32k_conf.fosc_tick_num = REG_FOSC_TICK_NUM;
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.ctrl_32k_conf, fosc_tick_num, REG_FOSC_TICK_NUM); // divider = (REG_FOSC_TICK_NUM + 1) = 256
}

View File

@ -43,7 +43,8 @@ Set the frequency division factor of ref_tick
The FOSC of rtc calibration uses the 32 frequency division clock for ECO2,
So the frequency division factor of ref_tick must be greater than or equal to 32
*/
#define REG_FOSC_TICK_NUM 255
#define CLK_LL_RC_FAST_TICK_DIV_BITS 5
#define REG_FOSC_TICK_NUM 255
/**
* @brief XTAL32K_CLK enable modes
@ -746,7 +747,7 @@ Set the frequency division factor of ref_tick
*/
static inline void clk_ll_rc_fast_tick_conf(void)
{
PCR.ctrl_tick_conf.fosc_tick_num = REG_FOSC_TICK_NUM;
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.ctrl_tick_conf, fosc_tick_num, REG_FOSC_TICK_NUM); // enable a division of 32 to the fosc clock
}
/*

View File

@ -131,6 +131,10 @@ config SOC_SECURE_BOOT_SUPPORTED
bool
default y
config SOC_PMU_SUPPORTED
bool
default y
config SOC_LP_TIMER_SUPPORTED
bool
default y
@ -139,6 +143,10 @@ config SOC_LP_PERIPHERALS_SUPPORTED
bool
default y
config SOC_CLK_TREE_SUPPORTED
bool
default y
config SOC_SPI_FLASH_SUPPORTED
bool
default y
@ -847,6 +855,14 @@ config SOC_UART_BITRATE_MAX
int
default 5000000
config SOC_UART_SUPPORT_PLL_F80M_CLK
bool
default y
config SOC_UART_SUPPORT_RTC_CLK
bool
default y
config SOC_UART_SUPPORT_XTAL_CLK
bool
default y
@ -895,6 +911,10 @@ config SOC_PM_SUPPORT_RTC_PERIPH_PD
bool
default y
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
bool
default y
config SOC_MODEM_CLOCK_IS_INDEPENDENT
bool
default y
@ -911,6 +931,10 @@ config SOC_CLK_RC32K_SUPPORTED
bool
default y
config SOC_CLK_LP_FAST_SUPPORT_XTAL
bool
default y
config SOC_RCC_IS_INDEPENDENT
bool
default y

View File

@ -19,7 +19,7 @@ extern "C" {
*
* The exact frequency of RC_FAST_CLK can be computed in runtime through calibration.
*
* 2) External 40/48MHz Crystal Clock: XTAL
* 2) External 48MHz Crystal Clock: XTAL
*
* 3) Internal 136kHz RC Oscillator: RC_SLOW (may also referred as SOSC in TRM or reg. description)
*
@ -45,7 +45,6 @@ extern "C" {
* OSC_SLOW_CLK can also be calibrated to get its exact frequency.
*/
// TODO: [ESP32C5] IDF-8642 (inherit from C6)
/* With the default value of FOSC_DFREQ = 100, RC_FAST clock frequency is 17.5 MHz +/- 7% */
#define SOC_CLK_RC_FAST_FREQ_APPROX 17500000 /*!< Approximate RC_FAST_CLK frequency in Hz */
#define SOC_CLK_RC_SLOW_FREQ_APPROX 136000 /*!< Approximate RC_SLOW_CLK frequency in Hz */
@ -60,10 +59,10 @@ extern "C" {
/**
* @brief Root clock
*/
typedef enum { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
typedef enum {
SOC_ROOT_CLK_INT_RC_FAST, /*!< Internal 17.5MHz RC oscillator */
SOC_ROOT_CLK_INT_RC_SLOW, /*!< Internal 136kHz RC oscillator */
SOC_ROOT_CLK_EXT_XTAL, /*!< External 40MHz crystal */
SOC_ROOT_CLK_EXT_XTAL, /*!< External 48MHz crystal */
SOC_ROOT_CLK_EXT_XTAL32K, /*!< External 32kHz crystal */
SOC_ROOT_CLK_INT_RC32K, /*!< Internal 32kHz RC oscillator */
SOC_ROOT_CLK_EXT_OSC_SLOW, /*!< External slow clock signal at pin0 */
@ -73,12 +72,11 @@ typedef enum { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
* @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 { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
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_PLL = SOC_CPU_CLK_SRC_PLL_F240M, // TODO: [IDF-8642] remove this alias
SOC_CPU_CLK_SRC_INVALID, /*!< Invalid CPU_CLK source */
} soc_cpu_clk_src_t;
@ -86,7 +84,7 @@ typedef enum { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
* @brief RTC_SLOW_CLK mux inputs, which are the supported clock sources for the RTC_SLOW_CLK
* @note Enum values are matched with the register field values on purpose
*/
typedef enum { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
typedef enum {
SOC_RTC_SLOW_CLK_SRC_RC_SLOW = 0, /*!< Select RC_SLOW_CLK as RTC_SLOW_CLK source */
SOC_RTC_SLOW_CLK_SRC_XTAL32K = 1, /*!< Select XTAL32K_CLK as RTC_SLOW_CLK source */
SOC_RTC_SLOW_CLK_SRC_RC32K = 2, /*!< Select RC32K_CLK as RTC_SLOW_CLK source */
@ -98,7 +96,7 @@ typedef enum { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
* @brief RTC_FAST_CLK mux inputs, which are the supported clock sources for the RTC_FAST_CLK
* @note Enum values are matched with the register field values on purpose
*/
typedef enum { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
typedef enum {
SOC_RTC_FAST_CLK_SRC_RC_FAST = 0, /*!< Select RC_FAST_CLK as RTC_FAST_CLK source */
SOC_RTC_FAST_CLK_SRC_XTAL_D2 = 1, /*!< Select XTAL_D2_CLK as RTC_FAST_CLK source */
SOC_RTC_FAST_CLK_SRC_XTAL_DIV = SOC_RTC_FAST_CLK_SRC_XTAL_D2, /*!< Alias name for `SOC_RTC_FAST_CLK_SRC_XTAL_D2` */
@ -125,7 +123,7 @@ typedef enum {
*
* @note enum starts from 1, to save 0 for special purpose
*/
typedef enum { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
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
@ -138,9 +136,9 @@ typedef enum { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
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 40MHz crystal */
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 40MHz crystal, passing a div of 2 to the 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;
@ -548,7 +546,7 @@ typedef enum { // TODO: [ESP32C5] IDF-8649
} soc_periph_mspi_clk_src_t;
//////////////////////////////////////////////CLOCK OUTPUT///////////////////////////////////////////////////////////
typedef enum { // TODO: [ESP32C5] IDF-8642 (inherit from C6)
typedef enum { // TODO
CLKOUT_SIG_PLL = 1, /*!< PLL_CLK is the output of crystal oscillator frequency multiplier */
CLKOUT_SIG_XTAL = 5, /*!< Main crystal oscillator clock */
CLKOUT_SIG_PLL_F80M = 13, /*!< From PLL, usually be 80MHz */

View File

@ -1902,21 +1902,6 @@ extern "C" {
* SYSCLK configuration register
*/
#define PCR_SYSCLK_CONF_REG (DR_REG_PCR_BASE + 0x110)
/** PCR_LS_DIV_NUM : HRO; bitpos: [7:0]; default: 0;
* clk_hproot is div1 of low-speed clock-source if clck-source is a low-speed
* clock-source such as XTAL/FOSC.
*/
#define PCR_LS_DIV_NUM 0x000000FFU
#define PCR_LS_DIV_NUM_M (PCR_LS_DIV_NUM_V << PCR_LS_DIV_NUM_S)
#define PCR_LS_DIV_NUM_V 0x000000FFU
#define PCR_LS_DIV_NUM_S 0
/** PCR_HS_DIV_NUM : HRO; bitpos: [15:8]; default: 2;
* clk_hproot is div3 of SPLL if the clock-source is high-speed clock SPLL.
*/
#define PCR_HS_DIV_NUM 0x000000FFU
#define PCR_HS_DIV_NUM_M (PCR_HS_DIV_NUM_V << PCR_HS_DIV_NUM_S)
#define PCR_HS_DIV_NUM_V 0x000000FFU
#define PCR_HS_DIV_NUM_S 8
/** PCR_SOC_CLK_SEL : R/W; bitpos: [17:16]; default: 0;
* Configures to select the clock source of HP_ROOT_CLK.\\
* 0 (default): XTAL_CLK\\

View File

@ -1642,15 +1642,7 @@ typedef union {
*/
typedef union {
struct {
/** ls_div_num : HRO; bitpos: [7:0]; default: 0;
* clk_hproot is div1 of low-speed clock-source if clck-source is a low-speed
* clock-source such as XTAL/FOSC.
*/
uint32_t ls_div_num:8;
/** hs_div_num : HRO; bitpos: [15:8]; default: 2;
* clk_hproot is div3 of SPLL if the clock-source is high-speed clock SPLL.
*/
uint32_t hs_div_num:8;
uint32_t reserved_0:16;
/** soc_clk_sel : R/W; bitpos: [17:16]; default: 0;
* Configures to select the clock source of HP_ROOT_CLK.\\
* 0 (default): XTAL_CLK\\
@ -1706,7 +1698,7 @@ typedef union {
typedef union {
struct {
/** cpu_div_num : R/W; bitpos: [7:0]; default: 0;
* Set this field to generate clk_cpu driven by clk_hproot. The clk_cpu is
* Set this field to generate clk_cpu derived by clk_hproot. The clk_cpu is
* div1(default)/div2/div4 of clk_hproot. This field is only available for low-speed
* clock-source such as XTAL/FOSC, and should be used together with PCR_AHB_DIV_NUM.
*/
@ -1722,7 +1714,7 @@ typedef union {
typedef union {
struct {
/** ahb_div_num : R/W; bitpos: [7:0]; default: 0;
* Set this field to generate clk_ahb driven by clk_hproot. The clk_ahb is
* Set this field to generate clk_ahb derived by clk_hproot. The clk_ahb is
* div1(default)/div2/div4/div8 of clk_hproot. This field is only available for
* low-speed clock-source such as XTAL/FOSC, and should be used together with
* PCR_CPU_DIV_NUM.
@ -1749,7 +1741,7 @@ typedef union {
*/
uint32_t apb_decrease_div_num:8;
/** apb_div_num : R/W; bitpos: [15:8]; default: 0;
* Set as one within (0,1,3) to generate clk_apb driven by clk_ahb. The clk_apb is
* Set as one within (0,1,3) to generate clk_apb derived by clk_ahb. The clk_apb is
* div1(default)/div2/div4 of clk_ahb.
*/
uint32_t apb_div_num:8;
@ -1764,47 +1756,47 @@ typedef union {
typedef union {
struct {
/** pll_240m_clk_en : R/W; bitpos: [0]; default: 1;
* This field is used to open 240 MHz clock (div2 of SPLL) driven from SPLL. 0: close,
* This field is used to open 240 MHz clock (div2 of SPLL) derived from SPLL. 0: close,
* 1: open(default). Only available when high-speed clock-source SPLL is active.
*/
uint32_t pll_240m_clk_en:1;
/** pll_160m_clk_en : R/W; bitpos: [1]; default: 1;
* This field is used to open 160 MHz clock (div3 of SPLL) driven from SPLL. 0: close,
* This field is used to open 160 MHz clock (div3 of SPLL) derived from SPLL. 0: close,
* 1: open(default). Only available when high-speed clock-source SPLL is active.
*/
uint32_t pll_160m_clk_en:1;
/** pll_120m_clk_en : R/W; bitpos: [2]; default: 1;
* This field is used to open 120 MHz clock (div4 of SPLL) driven from SPLL. 0: close,
* This field is used to open 120 MHz clock (div4 of SPLL) derived from SPLL. 0: close,
* 1: open(default). Only available when high-speed clock-source SPLL is active.
*/
uint32_t pll_120m_clk_en:1;
/** pll_80m_clk_en : R/W; bitpos: [3]; default: 1;
* This field is used to open 80 MHz clock (div6 of SPLL) driven from SPLL. 0: close,
* This field is used to open 80 MHz clock (div6 of SPLL) derived from SPLL. 0: close,
* 1: open(default). Only available when high-speed clock-source SPLL is active.
*/
uint32_t pll_80m_clk_en:1;
/** pll_60m_clk_en : R/W; bitpos: [4]; default: 1;
* This field is used to open 60 MHz clock (div8 of SPLL) driven from SPLL. 0: close,
* This field is used to open 60 MHz clock (div8 of SPLL) derived from SPLL. 0: close,
* 1: open(default). Only available when high-speed clock-source SPLL is active.
*/
uint32_t pll_60m_clk_en:1;
/** pll_48m_clk_en : R/W; bitpos: [5]; default: 1;
* This field is used to open 48 MHz clock (div10 of SPLL) driven from SPLL. 0: close,
* This field is used to open 48 MHz clock (div10 of SPLL) derived from SPLL. 0: close,
* 1: open(default). Only available when high-speed clock-source SPLL is active.
*/
uint32_t pll_48m_clk_en:1;
/** pll_40m_clk_en : R/W; bitpos: [6]; default: 1;
* This field is used to open 40 MHz clock (div12 of SPLL) driven from SPLL. 0: close,
* This field is used to open 40 MHz clock (div12 of SPLL) derived from SPLL. 0: close,
* 1: open(default). Only available when high-speed clock-source SPLL is active.
*/
uint32_t pll_40m_clk_en:1;
/** pll_20m_clk_en : R/W; bitpos: [7]; default: 1;
* This field is used to open 20 MHz clock (div24 of SPLL) driven from SPLL. 0: close,
* This field is used to open 20 MHz clock (div24 of SPLL) derived from SPLL. 0: close,
* 1: open(default). Only available when high-speed clock-source SPLL is active.
*/
uint32_t pll_20m_clk_en:1;
/** pll_12m_clk_en : R/W; bitpos: [8]; default: 1;
* This field is used to open 12 MHz clock (div40 of SPLL) driven from SPLL. 0: close,
* This field is used to open 12 MHz clock (div40 of SPLL) derived from SPLL. 0: close,
* 1: open(default). Only available when high-speed clock-source SPLL is active.
*/
uint32_t pll_12m_clk_en:1;

View File

@ -58,14 +58,14 @@
#define SOC_SECURE_BOOT_SUPPORTED 1
// #define SOC_BOD_SUPPORTED 1 // TODO: [ESP32C5] IDF-8647
// #define SOC_APM_SUPPORTED 1 // TODO: [ESP32C5] IDF-8614, IDF-8615
// #define SOC_PMU_SUPPORTED 1 // TODO: [ESP32C5] IDF-8667
#define SOC_PMU_SUPPORTED 1 // TODO: [ESP32C5] IDF-8667
// #define SOC_PAU_SUPPORTED 1 // TODO: [ESP32C5] IDF-8638
#define SOC_LP_TIMER_SUPPORTED 1
// #define SOC_LP_AON_SUPPORTED 1 // TODO: [ESP32C5] IDF-8638
#define SOC_LP_PERIPHERALS_SUPPORTED 1
// #define SOC_LP_I2C_SUPPORTED 1 // TODO: [ESP32C5] IDF-8634
// #define SOC_ULP_LP_UART_SUPPORTED 1 // TODO: [ESP32C5] IDF-8633
// #define SOC_CLK_TREE_SUPPORTED 1 // TODO: [ESP32C5] IDF-8642
#define SOC_CLK_TREE_SUPPORTED 1
// #define SOC_ASSIST_DEBUG_SUPPORTED 1 // TODO: [ESP32C5] IDF-8663
// #define SOC_WDT_SUPPORTED 1 // TODO: [ESP32C5] IDF-8650
#define SOC_SPI_FLASH_SUPPORTED 1 // TODO: [ESP32C5] IDF-8715
@ -493,8 +493,8 @@
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_LP_UART_FIFO_LEN (16) /*!< The LP UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
// #define SOC_UART_SUPPORT_PLL_F80M_CLK (1) /*!< Support PLL_F80M as the clock source */
// #define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */ // TODO: [ESP32C5] IDF-8642
#define SOC_UART_SUPPORT_PLL_F80M_CLK (1) /*!< Support PLL_F80M as the clock source */
#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_HAS_LP_UART (1) /*!< Support LP UART */
@ -545,12 +545,13 @@
// #define SOC_PM_PAU_LINK_NUM (4)
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
// #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) // TODO: IDF-8642
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
#define SOC_MODEM_CLOCK_IS_INDEPENDENT (1)
#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */
#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */
#define SOC_CLK_RC32K_SUPPORTED (1) /*!< Support an internal 32kHz RC oscillator */
#define SOC_CLK_LP_FAST_SUPPORT_XTAL (1) /*!< Support XTAL clock as the LP_FAST clock source */
#define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */

View File

@ -97,7 +97,6 @@ api-reference/peripherals/lcd.rst
api-reference/peripherals/ana_cmpr.rst
api-reference/peripherals/temp_sensor.rst
api-reference/peripherals/spi_features.rst
api-reference/peripherals/clk_tree.rst
api-reference/peripherals/spi_flash/spi_flash_concurrency.rst
api-reference/peripherals/spi_flash/spi_flash_override_driver.rst
api-reference/peripherals/spi_flash/spi_flash_optional_feature.rst

View File

@ -7,7 +7,7 @@ Clock Tree
{IDF_TARGET_RC_FAST_ADJUSTED_FREQ: default="17.5", esp32="8.5", esp32s2="8.5", esp32h2="8.5"}
{IDF_TARGET_XTAL_FREQ: default="40", esp32="2 ~ 40", esp32c2="40/26", esp32h2="32"}
{IDF_TARGET_XTAL_FREQ: default="40", esp32="2 ~ 40", esp32c2="40/26", esp32h2="32", esp32c5="48"}
{IDF_TARGET_RC_SLOW_VAGUE_FREQ: default="136", esp32="150", esp32s2="90"}

View File

@ -166,7 +166,7 @@ The source clock can also limit the PWM frequency. The higher the source clock f
- ~ 17.5 MHz
- Dynamic Frequency Scaling compatible, Light sleep compatible
* - XTAL_CLK
- 48/40 MHz
- 48 MHz
- Dynamic Frequency Scaling compatible
.. only:: esp32c6

View File

@ -7,7 +7,7 @@
{IDF_TARGET_RC_FAST_ADJUSTED_FREQ: default="17.5", esp32="8.5", esp32s2="8.5", esp32h2="8.5"}
{IDF_TARGET_XTAL_FREQ: default="40", esp32="2 ~ 40", esp32c2="40/26", esp32h2="32"}
{IDF_TARGET_XTAL_FREQ: default="40", esp32="2 ~ 40", esp32c2="40/26", esp32h2="32", esp32c5="48"}
{IDF_TARGET_RC_SLOW_VAGUE_FREQ: default="136", esp32="150", esp32s2="90"}

View File

@ -166,7 +166,7 @@ LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比,实
- ~ 17.5 MHz
- 支持动态调频 (DFS) 功能,支持 Light-sleep 模式
* - XTAL_CLK
- 48/40 MHz
- 48 MHz
- 支持动态调频 (DFS) 功能
.. only:: esp32c6