mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
Merge branch 'feature/esp32s31_clock_support' into 'master'
feat(clk): support for esp32s31 clock tree Closes IDF-14696 and IDF-14871 See merge request espressif/esp-idf!47048
This commit is contained in:
@@ -195,7 +195,7 @@ esp_err_t IRAM_ATTR periph_rtc_mpll_freq_set(uint32_t expt_freq_hz, uint32_t *re
|
||||
/* If MPLL is not in use or only one peripheral in use, its frequency can be changed as will
|
||||
* But when more than one peripheral refers MPLL, its frequency is not allowed to change once it is set */
|
||||
if (s_cur_mpll_freq_hz == 0 || s_mpll_ref_cnt < 2) {
|
||||
uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz();
|
||||
uint32_t xtal_freq_mhz = clk_hal_xtal_get_freq_mhz();
|
||||
rtc_clk_mpll_configure(xtal_freq_mhz, expt_freq_hz / MHZ, false);
|
||||
s_cur_mpll_freq_hz = clk_ll_mpll_get_freq_mhz(xtal_freq_mhz) * MHZ;
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
target_include_directories(${COMPONENT_LIB} PUBLIC .)
|
||||
|
||||
set(srcs
|
||||
"rtc_clk_init.c"
|
||||
"rtc_clk.c"
|
||||
"rtc_time.c"
|
||||
"chip_info.c"
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# The content of this file is not accurate, please check IDF-14678
|
||||
|
||||
choice RTC_CLK_SRC
|
||||
prompt "RTC clock source"
|
||||
default RTC_CLK_SRC_INT_RC
|
||||
@@ -11,18 +9,13 @@ choice RTC_CLK_SRC
|
||||
config RTC_CLK_SRC_EXT_CRYS
|
||||
bool "External 32 kHz crystal"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
config RTC_CLK_SRC_EXT_OSC
|
||||
bool "External 32 kHz oscillator at 32K_XP pin"
|
||||
select ESP_SYSTEM_RTC_EXT_OSC
|
||||
config RTC_CLK_SRC_INT_8MD256
|
||||
bool "Internal 17.5 MHz oscillator, divided by 256"
|
||||
endchoice
|
||||
|
||||
config RTC_CLK_CAL_CYCLES
|
||||
int "Number of cycles for RTC_SLOW_CLK calibration"
|
||||
default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256
|
||||
default 3000 if RTC_CLK_SRC_EXT_CRYS
|
||||
default 1024 if RTC_CLK_SRC_INT_RC
|
||||
range 0 8190 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256
|
||||
range 0 8190 if RTC_CLK_SRC_EXT_CRYS
|
||||
range 0 32766 if RTC_CLK_SRC_INT_RC
|
||||
help
|
||||
When the startup code initializes RTC_SLOW_CLK, it can perform
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
|
||||
ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree");
|
||||
|
||||
/* TODO: [ESP32S31] IDF-14733 */
|
||||
|
||||
void esp_clk_tree_initialize(void)
|
||||
{
|
||||
/* TODO: [ESP32S31] IDF-14733 */
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -32,11 +25,9 @@ esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_sr
|
||||
|
||||
uint32_t clk_src_freq = 0;
|
||||
switch (clk_src) {
|
||||
#if SOC_CLK_TREE_SUPPORTED
|
||||
case SOC_MOD_CLK_CPU:
|
||||
clk_src_freq = clk_hal_cpu_get_freq_hz();
|
||||
break;
|
||||
#endif // SOC_CLK_TREE_SUPPORTED
|
||||
case SOC_MOD_CLK_XTAL:
|
||||
clk_src_freq = SOC_XTAL_FREQ_40M * MHZ;
|
||||
break;
|
||||
@@ -52,19 +43,15 @@ esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_sr
|
||||
case SOC_MOD_CLK_PLL_F240M:
|
||||
clk_src_freq = CLK_LL_PLL_240M_FREQ_MHZ * MHZ;
|
||||
break;
|
||||
#if SOC_CLK_TREE_SUPPORTED
|
||||
case SOC_MOD_CLK_CPLL:
|
||||
clk_src_freq = clk_ll_cpll_get_freq_mhz(clk_hal_xtal_get_freq_mhz()) * MHZ;
|
||||
break;
|
||||
case SOC_MOD_CLK_SPLL:
|
||||
case SOC_MOD_CLK_BBPLL:
|
||||
clk_src_freq = CLK_LL_PLL_480M_FREQ_MHZ * MHZ;
|
||||
break;
|
||||
case SOC_MOD_CLK_MPLL:
|
||||
clk_src_freq = clk_ll_mpll_get_freq_mhz(clk_hal_xtal_get_freq_mhz()) * MHZ;
|
||||
break;
|
||||
case SOC_MOD_CLK_SDIO_PLL:
|
||||
clk_src_freq = CLK_LL_PLL_SDIO_FREQ_MHZ * MHZ;
|
||||
break;
|
||||
case SOC_MOD_CLK_RTC_SLOW:
|
||||
clk_src_freq = esp_clk_tree_lp_slow_get_freq_hz(precision);
|
||||
break;
|
||||
@@ -82,10 +69,6 @@ esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_sr
|
||||
case SOC_MOD_CLK_XTAL_D2:
|
||||
clk_src_freq = (clk_hal_xtal_get_freq_mhz() * MHZ) >> 1;
|
||||
break;
|
||||
case SOC_MOD_CLK_LP_PLL:
|
||||
clk_src_freq = clk_ll_lp_pll_get_freq_mhz() * MHZ;
|
||||
break;
|
||||
#endif // SOC_CLK_TREE_SUPPORTED
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -97,8 +80,52 @@ esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_sr
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int16_t s_cpll_ref_cnt = 0;
|
||||
|
||||
void esp_clk_tree_initialize(void)
|
||||
{
|
||||
// Power
|
||||
soc_cpu_clk_src_t cpu_clk_src_btld = clk_ll_cpu_get_src();
|
||||
if (cpu_clk_src_btld == SOC_CPU_CLK_SRC_CPLL) {
|
||||
s_cpll_ref_cnt++;
|
||||
} else if (cpu_clk_src_btld == SOC_CPU_CLK_SRC_PLL_F240M) {
|
||||
// TODO: IDF-15502
|
||||
// pll_f240m clock gating ref count ++
|
||||
}
|
||||
|
||||
// Gating
|
||||
}
|
||||
|
||||
bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable)
|
||||
{
|
||||
bool toggled = false;
|
||||
switch (clk_circuit) {
|
||||
case SOC_ROOT_CIRCUIT_CLK_CPLL:
|
||||
if (enable) {
|
||||
s_cpll_ref_cnt++;
|
||||
} else {
|
||||
s_cpll_ref_cnt--;
|
||||
}
|
||||
|
||||
// Note that a calibration is usually needed after enabling CPLL
|
||||
if (s_cpll_ref_cnt == 1) {
|
||||
clk_ll_cpll_enable();
|
||||
toggled = true;
|
||||
} else if (s_cpll_ref_cnt == 0) {
|
||||
clk_ll_cpll_disable();
|
||||
toggled = true;
|
||||
}
|
||||
|
||||
assert(s_cpll_ref_cnt >= 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return toggled;
|
||||
}
|
||||
|
||||
esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable)
|
||||
{
|
||||
/* TODO: [ESP32S31] IDF-14733 */
|
||||
// TODO: IDF-15502
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// TODO: [ESP32S31] IDF-14678
|
||||
|
||||
/************************************************************************************/
|
||||
/***************** THIS FILE IS CONSIDERED AS A PRIVATE HEADER FILE *****************/
|
||||
/*** IT IS NOT RECOMMENDED TO USE THE APIS IN THIS FILE DIRECTLY IN APPLICATIONS ****/
|
||||
@@ -52,6 +50,15 @@ extern "C" {
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
/* Delays for various clock sources to be enabled/switched.
|
||||
* All values are in microseconds.
|
||||
*/
|
||||
#define SOC_DELAY_RTC_FAST_CLK_SWITCH 3
|
||||
#define SOC_DELAY_RTC_SLOW_CLK_SWITCH 300
|
||||
#define SOC_DELAY_RC_FAST_ENABLE 50
|
||||
#define SOC_DELAY_RC_FAST_DIGI_SWITCH 5
|
||||
#define SOC_DELAY_RC32K_ENABLE 300
|
||||
|
||||
#define RTC_CNTL_CK8M_DFREQ_DEFAULT 100
|
||||
#define RTC_CNTL_SCK_DCAP_DEFAULT 128
|
||||
#define RTC_CNTL_RC32K_DFREQ_DEFAULT 700
|
||||
@@ -68,28 +75,6 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
|
||||
#define RTC_CLK_CAL_FRACT 19 //!< Number of fractional bits in values returned by rtc_clk_cal
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*
|
||||
* @note On ESP32S31, the enum values somehow reflects the register field values of HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_SRC_SEL.
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
RTC_CAL_MPLL = 0, //!< 500MHz MSPI_PLL_CLK
|
||||
RTC_CAL_SPLL = 1, //!< 480MHz SYS_PLL_CLK
|
||||
RTC_CAL_CPLL = 2, //!< 400MHz CPU_PLL_CLK
|
||||
RTC_CAL_APLL = 3, //!< AUDIO_PLL_CLK
|
||||
RTC_CAL_SDIO_PLL0 = 4, //!< SDIO_PLL0_CLK
|
||||
RTC_CAL_SDIO_PLL1 = 5, //!< SDIO_PLL1_CLK
|
||||
RTC_CAL_SDIO_PLL2 = 6, //!< SDIO_PLL2_CLK
|
||||
RTC_CAL_RC_FAST = 7, //!< Internal 20MHz RC oscillator
|
||||
RTC_CAL_RC_SLOW = 8, //!< Internal 150kHz RC oscillator
|
||||
RTC_CAL_RC32K = 9, //!< Internal 32kHz RC oscillator, as one type of 32k clock
|
||||
RTC_CAL_32K_XTAL = 10, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_LP_PLL = 11, //!< 8MHz LP_PLL_CLK
|
||||
RTC_CAL_INVALID_CLK, //!< Clock not available to calibrate
|
||||
} rtc_cal_sel_t;
|
||||
|
||||
/**
|
||||
* Initialization parameters for rtc_clk_init
|
||||
*/
|
||||
@@ -110,7 +95,7 @@ typedef struct {
|
||||
*/
|
||||
#define RTC_CLK_CONFIG_DEFAULT() { \
|
||||
.xtal_freq = CONFIG_XTAL_FREQ, \
|
||||
.cpu_freq_mhz = 90, \
|
||||
.cpu_freq_mhz = CONFIG_BOOTLOADER_CPU_CLK_FREQ_MHZ, \
|
||||
.fast_clk_src = SOC_RTC_FAST_CLK_SRC_RC_FAST, \
|
||||
.slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, \
|
||||
.clk_rtc_clk_div = 0, \
|
||||
@@ -137,16 +122,6 @@ void rtc_clk_init(rtc_clk_config_t cfg);
|
||||
*/
|
||||
soc_xtal_freq_t rtc_clk_xtal_freq_get(void);
|
||||
|
||||
/**
|
||||
* @brief Update XTAL frequency
|
||||
*
|
||||
* Updates the XTAL value stored in RTC_XTAL_FREQ_REG. Usually this value is ignored
|
||||
* after startup.
|
||||
*
|
||||
* @param xtal_freq New frequency value
|
||||
*/
|
||||
void rtc_clk_xtal_freq_update(soc_xtal_freq_t xtal_freq);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable 32 kHz XTAL oscillator
|
||||
* @param en true to enable, false to disable
|
||||
@@ -190,20 +165,6 @@ void rtc_clk_8m_enable(bool clk_8m_en);
|
||||
*/
|
||||
bool rtc_clk_8m_enabled(void);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable LP_PLL_CLK
|
||||
* Note that to be able to use LP_PLL clock, besides turn on the power for LP_PLL, also needs to turn on the power for
|
||||
* the LP_PLL clock source (either XTAL32K or RC32K).
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
void rtc_clk_lp_pll_enable(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Select clock source for LP_PLL_CLK
|
||||
* @param clk_src clock source (one of soc_lp_pll_clk_src_t values)
|
||||
*/
|
||||
void rtc_clk_lp_pll_src_set(soc_lp_pll_clk_src_t clk_src);
|
||||
|
||||
/**
|
||||
* @brief Select source for RTC_SLOW_CLK
|
||||
* @param clk_src clock source (one of soc_rtc_slow_clk_src_t values)
|
||||
@@ -310,26 +271,6 @@ void rtc_clk_cpu_freq_set_xtal(void);
|
||||
*/
|
||||
uint32_t rtc_clk_apb_freq_get(void);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Measure RTC slow clock's period, based on main XTAL frequency
|
||||
*
|
||||
@@ -348,7 +289,7 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
* @return average slow clock period in microseconds, Q13.19 fixed point format,
|
||||
* or 0 if calibration has timed out
|
||||
*/
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk, uint32_t slow_clk_cycles);
|
||||
|
||||
/**
|
||||
* @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
|
||||
|
||||
@@ -96,6 +96,7 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa
|
||||
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias);
|
||||
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias);
|
||||
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_connect_enable(ctx->hal->dev, mode, anlg->regulator0.slp_connect_en);
|
||||
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b);
|
||||
|
||||
/* Default configuration of hp-system retention sub-system in active, modem
|
||||
@@ -203,9 +204,12 @@ static void pmu_lp_system_init_default(pmu_context_t *ctx)
|
||||
|
||||
void pmu_init(void)
|
||||
{
|
||||
/* Peripheral reg i2c power up */
|
||||
regi2c_ctrl_ll_i2c_sar_periph_enable();
|
||||
|
||||
pmu_hp_system_init_default(PMU_instance());
|
||||
pmu_lp_system_init_default(PMU_instance());
|
||||
pmu_power_domain_force_default(PMU_instance());
|
||||
|
||||
regi2c_ctrl_ll_i2c_sar_periph_enable(); // TODO: IDF-14733
|
||||
WRITE_PERI_REG(PMU_POWER_PD_MEM_CNTL_REG, 0);
|
||||
}
|
||||
|
||||
@@ -38,9 +38,9 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param");
|
||||
.clk_power = { \
|
||||
.i2c_iso_en = 0, \
|
||||
.i2c_retention = 0, \
|
||||
.xpd_bb_i2c = 1, \
|
||||
.xpd_pll_i2c = 0xf, \
|
||||
.xpd_pll = 0xf \
|
||||
.xpd_bb_i2c = 0, \
|
||||
.xpd_pll_i2c = 0x3, \
|
||||
.xpd_pll = 0x3 \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 1 \
|
||||
@@ -55,16 +55,16 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param");
|
||||
.hp_mem_pd_en = 0, \
|
||||
.modem_top_pd_en = 0, \
|
||||
.hp_cnnt_pd_en = 0, \
|
||||
.hp_cpu_pd_en = 1, \
|
||||
.hp_cpu_pd_en = 0, \
|
||||
.modem_pwr_pd_en = 0, \
|
||||
.top_pd_en = 0 \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.i2c_iso_en = 0, \
|
||||
.i2c_retention = 0, \
|
||||
.xpd_bb_i2c = 1, \
|
||||
.xpd_pll_i2c = 0xf, \
|
||||
.xpd_pll = 0xf \
|
||||
.i2c_iso_en = 1, \
|
||||
.i2c_retention = 1, \
|
||||
.xpd_bb_i2c = 0, \
|
||||
.xpd_pll_i2c = 0x3, \
|
||||
.xpd_pll = 0x3 \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 1 \
|
||||
@@ -73,22 +73,22 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param");
|
||||
|
||||
#define PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() { \
|
||||
.dig_power = { \
|
||||
.vdd_spi_pd_en = 1, \
|
||||
.pd_hp_alive_pd_en = 1, \
|
||||
.hp_mem_dslp = 1, \
|
||||
.vdd_spi_pd_en = 0, \
|
||||
.pd_hp_alive_pd_en = 0, \
|
||||
.hp_mem_dslp = 0, \
|
||||
.hp_mem_pd_en = 0, \
|
||||
.modem_top_pd_en = 1, \
|
||||
.hp_cnnt_pd_en = 1, \
|
||||
.hp_cpu_pd_en = 1, \
|
||||
.modem_top_pd_en = 0, \
|
||||
.hp_cnnt_pd_en = 0, \
|
||||
.hp_cpu_pd_en = 0, \
|
||||
.modem_pwr_pd_en = 0, \
|
||||
.top_pd_en = 1 \
|
||||
.top_pd_en = 0 \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.i2c_iso_en = 0, \
|
||||
.i2c_retention = 0, \
|
||||
.xpd_bb_i2c = 1, \
|
||||
.xpd_pll_i2c = 0xf, \
|
||||
.xpd_pll = 0xf \
|
||||
.i2c_iso_en = 1, \
|
||||
.i2c_retention = 1, \
|
||||
.xpd_bb_i2c = 0, \
|
||||
.xpd_pll_i2c = 0, \
|
||||
.xpd_pll = 0 \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 0 \
|
||||
@@ -186,13 +186,19 @@ const pmu_hp_system_clock_param_t * pmu_hp_system_clock_param_default(pmu_hp_mod
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* - hp_pad_hold_all:
|
||||
* - when top off: must set to 1;
|
||||
* - when top on: 0 if use pad; 1 if not use pad
|
||||
* - dig_pad_slp_sel: must set to 1 when sleep
|
||||
*/
|
||||
#define PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() { \
|
||||
.syscntl = { \
|
||||
.c_channel = 1, \
|
||||
.c_channel = 0, \
|
||||
.uart_wakeup_en = 1, \
|
||||
.lp_pad_hold_all = 0, \
|
||||
.hp_pad_hold_all = 0, \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.hp_pad_hold_all = 1, \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = 1, \
|
||||
.dig_cpu_stall = 1 \
|
||||
} \
|
||||
@@ -259,17 +265,17 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp
|
||||
.bias = { \
|
||||
.xpd_bias = 0, \
|
||||
.dbg_atten = 0x0, \
|
||||
.pd_cur = 0, \
|
||||
.bias_sleep = 0 \
|
||||
.pd_cur = 1, \
|
||||
.bias_sleep = 1 \
|
||||
}, \
|
||||
.regulator0 = { \
|
||||
.slp_connect_en = 0, \
|
||||
.slp_mem_xpd = 0, \
|
||||
.slp_logic_xpd = 0, \
|
||||
.xpd = 1, \
|
||||
.slp_mem_dbias = 1, \
|
||||
.slp_mem_dbias = 0, \
|
||||
.slp_logic_dbias = 0, \
|
||||
.dbias = 1 \
|
||||
.dbias = 0 \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
@@ -357,8 +363,8 @@ const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pm
|
||||
.peri_pd_en = 0, \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.xpd_xtal32k = 1, \
|
||||
.xpd_rc32k = 1, \
|
||||
.xpd_xtal32k = 0, \
|
||||
.xpd_rc32k = 0, \
|
||||
.xpd_fosc = 1, \
|
||||
.pd_osc = 0 \
|
||||
} \
|
||||
@@ -413,7 +419,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 = 12 \
|
||||
.dbias = 0 \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define HP_CALI_DBIAS_DEFAULT 28
|
||||
#define LP_CALI_DBIAS_DEFAULT 28
|
||||
#define HP_CALI_DBIAS_DEFAULT 24
|
||||
#define LP_CALI_DBIAS_DEFAULT 24
|
||||
#define HP_CALI_DBIAS_SLP_1V1 22
|
||||
#define LP_CALI_DBIAS_SLP_1V1 22
|
||||
|
||||
|
||||
@@ -13,27 +13,28 @@
|
||||
#include "esp32s31/rom/rtc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_private/rtc_clk.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_hw_log.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "hal/regi2c_ctrl_ll.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "esp_private/sleep_event.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
static const char *TAG = "rtc_clk";
|
||||
|
||||
// TODO: [ESP32S31] IDF-14678
|
||||
|
||||
// CPLL frequency option, in 360/400MHz. Zero if CPLL is not enabled.
|
||||
// CPLL frequency option, in 320MHz. Zero if CPLL is not enabled.
|
||||
static int s_cur_cpll_freq = 0;
|
||||
|
||||
// MPLL frequency option, 400MHz. Zero if MPLL is not enabled.
|
||||
// MPLL frequency option, 500MHz. Zero if MPLL is not enabled.
|
||||
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)
|
||||
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);
|
||||
#endif
|
||||
|
||||
|
||||
void rtc_clk_32k_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
@@ -45,7 +46,7 @@ void rtc_clk_32k_enable(bool enable)
|
||||
|
||||
void rtc_clk_32k_bootstrap(uint32_t cycle)
|
||||
{
|
||||
/* No special bootstrapping needed for ESP32-P4, 'cycle' argument is to keep the signature
|
||||
/* No special bootstrapping needed for ESP32-S31, 'cycle' argument is to keep the signature
|
||||
* same as for the ESP32. Just enable the XTAL here.
|
||||
*/
|
||||
(void)cycle;
|
||||
@@ -59,12 +60,22 @@ bool rtc_clk_32k_enabled(void)
|
||||
|
||||
void rtc_clk_rc32k_enable(bool enable)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
if (enable) {
|
||||
clk_ll_rc32k_enable();
|
||||
esp_rom_delay_us(SOC_DELAY_RC32K_ENABLE);
|
||||
} else {
|
||||
clk_ll_rc32k_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_8m_enable(bool clk_8m_en)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
if (clk_8m_en) {
|
||||
clk_ll_rc_fast_enable();
|
||||
esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE);
|
||||
} else {
|
||||
clk_ll_rc_fast_disable();
|
||||
}
|
||||
}
|
||||
|
||||
bool rtc_clk_8m_enabled(void)
|
||||
@@ -72,19 +83,23 @@ bool rtc_clk_8m_enabled(void)
|
||||
return clk_ll_rc_fast_is_enabled();
|
||||
}
|
||||
|
||||
void rtc_clk_lp_pll_enable(bool enable)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
}
|
||||
|
||||
void rtc_clk_lp_pll_src_set(soc_lp_pll_clk_src_t clk_src)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
}
|
||||
|
||||
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
clk_ll_rtc_slow_set_src(clk_src);
|
||||
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
||||
// TODO: IDF-14645
|
||||
// #ifndef BOOTLOADER_BUILD
|
||||
// if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
// esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL32K, ESP_PD_OPTION_ON);
|
||||
// } else {
|
||||
// esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL32K, ESP_PD_OPTION_AUTO);
|
||||
// }
|
||||
// if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
|
||||
// esp_sleep_pd_config(ESP_PD_DOMAIN_RC32K, ESP_PD_OPTION_ON);
|
||||
// } else {
|
||||
// esp_sleep_pd_config(ESP_PD_DOMAIN_RC32K, ESP_PD_OPTION_AUTO);
|
||||
// }
|
||||
// #endif
|
||||
}
|
||||
|
||||
soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void)
|
||||
@@ -94,18 +109,17 @@ soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void)
|
||||
|
||||
uint32_t rtc_clk_slow_freq_get_hz(void)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
switch (rtc_clk_slow_src_get()) {
|
||||
case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX;
|
||||
case SOC_RTC_SLOW_CLK_SRC_XTAL32K: return SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
case SOC_RTC_SLOW_CLK_SRC_RC32K: return SOC_CLK_RC32K_FREQ_APPROX;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
clk_ll_rtc_fast_set_src(clk_src);
|
||||
esp_rom_delay_us(SOC_DELAY_RTC_FAST_CLK_SWITCH);
|
||||
}
|
||||
|
||||
soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void)
|
||||
@@ -113,23 +127,49 @@ soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void)
|
||||
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)
|
||||
{
|
||||
/* Digital part */
|
||||
clk_ll_cpll_set_freq_mhz(cpll_freq, xtal_freq);
|
||||
|
||||
/* Analog part */
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
/* CPLL CALIBRATION START */
|
||||
clk_ll_cpll_calibration_start();
|
||||
clk_ll_cpll_set_config(cpll_freq, xtal_freq);
|
||||
/* WAIT CALIBRATION DONE */
|
||||
while(!clk_ll_cpll_calibration_is_done());
|
||||
esp_rom_delay_us(10); // wait for true stop
|
||||
/* CPLL CALIBRATION STOP */
|
||||
clk_ll_cpll_calibration_stop();
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
s_cur_cpll_freq = cpll_freq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to use XTAL as the CPU clock source.
|
||||
* Must satisfy: cpu_freq = XTAL_FREQ / div.
|
||||
* Does not disable the PLL.
|
||||
*
|
||||
* If to_default is set, then will configure CPU - MEM - SYS - APB frequencies back to power-on reset configuration (40 - 20 - 20 - 10)
|
||||
* If to_default is set, then will configure CPU - MEM - SYS - APB frequencies back to power-on reset configuration (40 - 20 - 40/3 - 40/6)
|
||||
* If to_default is not set, then will configure to 40 - 40 - 40 - 40
|
||||
*/
|
||||
static FORCE_IRAM_ATTR void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div, bool to_default)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
// let f_cpu = f_mem = f_sys = f_apb
|
||||
uint32_t mem_divider = 1;
|
||||
uint32_t sys_divider = 1;
|
||||
@@ -137,24 +177,156 @@ static FORCE_IRAM_ATTR void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div, bool
|
||||
if (to_default) {
|
||||
// f_cpu = 2 * f_mem = 2 * f_sys = 4 * f_apb
|
||||
mem_divider = 2;
|
||||
sys_divider = 3;
|
||||
apb_divider = 2;
|
||||
}
|
||||
// Update bit does not control CPU clock sel mux. Therefore, there will be a middle state during the switch (CPU falls)
|
||||
// Since before the switch, the clock source is CPLL, there is divider value constraints.
|
||||
// Setting the new dividers first is unguaranteed (hardware could automatically modify the real dividers)
|
||||
// Therefore, we will switch cpu clock source first, and then set the desired dividers.
|
||||
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL);
|
||||
clk_ll_cpu_set_divider(div, 0, 0);
|
||||
clk_ll_mem_set_divider(mem_divider);
|
||||
clk_ll_sys_set_divider(sys_divider);
|
||||
clk_ll_apb_set_divider(apb_divider);
|
||||
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_rc_fast(void)
|
||||
{
|
||||
// let f_cpu = f_mem = f_sys = f_apb
|
||||
clk_ll_cpu_set_divider(1, 0, 0);
|
||||
clk_ll_mem_set_divider(1);
|
||||
clk_ll_sys_set_divider(1);
|
||||
clk_ll_apb_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 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_240_mhz(int cpu_freq_mhz)
|
||||
{
|
||||
// f_hp_root = 240MHz
|
||||
assert(cpu_freq_mhz == 240);
|
||||
uint32_t cpu_divider = CLK_LL_PLL_240M_FREQ_MHZ / cpu_freq_mhz;
|
||||
clk_ll_cpu_set_divider(cpu_divider, 0, 0);
|
||||
clk_ll_mem_set_divider(2); // 120MHz
|
||||
clk_ll_sys_set_divider(3); // 80MHz
|
||||
clk_ll_apb_set_divider(2); // 40MHz
|
||||
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 one of CPLL-based frequencies. Current frequency can be XTAL or CPLL.
|
||||
* CPLL must already be enabled.
|
||||
* @param cpu_freq new CPU frequency
|
||||
*/
|
||||
static void rtc_clk_cpu_freq_to_cpll_mhz(int cpu_freq_mhz, hal_utils_clk_div_t *div)
|
||||
{
|
||||
/**
|
||||
* Constraint: MEM_CLK <= 160MHz, SYS_CLK <= (320/3)MHz, APB_CLK <= (320/6)MHz
|
||||
* This implies that when clock source is CPLL,
|
||||
* If cpu_divider < 2, mem_divider must be larger or equal to 2, sys_divider must be larger or equal to 3
|
||||
* If cpu_divider < 2, sys_divider = 3, apb_divider must be larger or equal to 2
|
||||
*
|
||||
* Current available configurations:
|
||||
* CPLL -> CPU_CLK -> MEM_CLK
|
||||
* -> SYS_CLK -> APB_CLK
|
||||
* 320 div1 320 div2 160
|
||||
* div4 80 div2 40
|
||||
* 320 div2 160 div1 160
|
||||
* div2 80 div2 40
|
||||
* 320 div4 80 div1 80
|
||||
* div1 80 div2 40
|
||||
*/
|
||||
uint32_t mem_divider = 1;
|
||||
uint32_t sys_divider = 1;
|
||||
uint32_t apb_divider = 1;
|
||||
switch (cpu_freq_mhz) {
|
||||
case 320:
|
||||
mem_divider = 2;
|
||||
sys_divider = 4;
|
||||
apb_divider = 2;
|
||||
break;
|
||||
case 160:
|
||||
mem_divider = 1;
|
||||
sys_divider = 2;
|
||||
apb_divider = 2;
|
||||
break;
|
||||
case 80:
|
||||
mem_divider = 1;
|
||||
sys_divider = 1;
|
||||
apb_divider = 2;
|
||||
break;
|
||||
default:
|
||||
// Unsupported configuration
|
||||
// This is dangerous to modify dividers. Hardware could automatically correct the divider, and it won't be
|
||||
// reflected to the registers. Therefore, you won't even be able to calculate out the real mem_clk, apb_clk freq.
|
||||
// To avoid such case, we will strictly do abort here.
|
||||
abort();
|
||||
}
|
||||
clk_ll_cpu_set_divider(div->integer, div->numerator, div->denominator);
|
||||
clk_ll_mem_set_divider(mem_divider);
|
||||
clk_ll_sys_set_divider(sys_divider);
|
||||
clk_ll_apb_set_divider(apb_divider);
|
||||
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_CPLL);
|
||||
clk_ll_bus_update();
|
||||
esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
|
||||
}
|
||||
|
||||
bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
uint32_t source_freq_mhz;
|
||||
soc_cpu_clk_src_t source;
|
||||
hal_utils_clk_div_t divider = {0}; // divider = freq of HP_ROOT_CLK / freq of CPU_CLK
|
||||
uint32_t real_freq_mhz;
|
||||
|
||||
// Keep default CPLL at 320MHz
|
||||
uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
if (freq_mhz <= xtal_freq && freq_mhz != 0) {
|
||||
divider.integer = xtal_freq / freq_mhz;
|
||||
real_freq_mhz = (xtal_freq + divider.integer / 2) / divider.integer; /* round */
|
||||
if (real_freq_mhz != freq_mhz) {
|
||||
// no suitable divider
|
||||
return false;
|
||||
}
|
||||
source_freq_mhz = xtal_freq;
|
||||
source = SOC_CPU_CLK_SRC_XTAL;
|
||||
} else if (freq_mhz == 80) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_CPLL;
|
||||
source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ;
|
||||
divider.integer = 4;
|
||||
} else if (freq_mhz == 160) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_CPLL;
|
||||
source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ;
|
||||
divider.integer = 2;
|
||||
} else if (freq_mhz == 240) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_PLL_F240M;
|
||||
source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
|
||||
divider.integer = 1;
|
||||
} else if (freq_mhz == 320) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_CPLL;
|
||||
source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ;
|
||||
divider.integer = 1;
|
||||
} else {
|
||||
// unsupported frequency
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_config = (rtc_cpu_freq_config_t) {
|
||||
.source = source,
|
||||
.div = divider,
|
||||
.source_freq_mhz = source_freq_mhz,
|
||||
.freq_mhz = real_freq_mhz
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -162,61 +334,179 @@ __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)
|
||||
{
|
||||
if (new_src == SOC_CPU_CLK_SRC_CPLL) {
|
||||
bool truly_enabled = false;
|
||||
#if BOOTLOADER_BUILD
|
||||
rtc_clk_cpll_enable();
|
||||
truly_enabled = true;
|
||||
#else
|
||||
if (!s_is_cpll_acquired) {
|
||||
truly_enabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_CPLL, true);
|
||||
s_is_cpll_acquired = true;
|
||||
}
|
||||
#endif
|
||||
if (truly_enabled || (s_cur_cpll_freq != 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) {
|
||||
#if !BOOTLOADER_BUILD
|
||||
if (!s_is_pll_f240m_acquired) {
|
||||
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F240M, true);
|
||||
s_is_pll_f240m_acquired = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void rtc_clk_cpu_src_clk_disable(soc_cpu_clk_src_t old_src)
|
||||
{
|
||||
if (old_src == SOC_CPU_CLK_SRC_CPLL) {
|
||||
#if BOOTLOADER_BUILD
|
||||
rtc_clk_cpll_disable();
|
||||
#else
|
||||
assert(s_is_cpll_acquired);
|
||||
bool truly_disabled = esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_CPLL, false);
|
||||
s_is_cpll_acquired = false;
|
||||
if (truly_disabled) {
|
||||
s_cur_cpll_freq = 0;
|
||||
}
|
||||
#endif
|
||||
} else if (old_src == SOC_CPU_CLK_SRC_PLL_F240M) {
|
||||
#if !BOOTLOADER_BUILD
|
||||
assert(s_is_pll_f240m_acquired);
|
||||
s_is_pll_f240m_acquired = false;
|
||||
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F240M, false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
|
||||
if (old_cpu_clk_src != config->source) {
|
||||
rtc_clk_cpu_src_clk_enable(config->source, config->source_freq_mhz);
|
||||
}
|
||||
|
||||
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) {
|
||||
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START);
|
||||
rtc_clk_cpu_freq_to_cpll_mhz(config->freq_mhz, (hal_utils_clk_div_t *)&config->div);
|
||||
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP);
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M) {
|
||||
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();
|
||||
}
|
||||
|
||||
if (old_cpu_clk_src != config->source) {
|
||||
rtc_clk_cpu_src_clk_disable(old_cpu_clk_src);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t rtc_clk_hp_root_get_freq_mhz(soc_cpu_clk_src_t clk_src)
|
||||
{
|
||||
uint32_t source_freq_mhz = 0;
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
switch (clk_src) {
|
||||
case SOC_CPU_CLK_SRC_XTAL:
|
||||
source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
break;
|
||||
case SOC_CPU_CLK_SRC_CPLL:
|
||||
source_freq_mhz = clk_ll_cpll_get_freq_mhz((uint32_t)rtc_clk_xtal_freq_get());
|
||||
break;
|
||||
case SOC_CPU_CLK_SRC_RC_FAST:
|
||||
source_freq_mhz = 20;
|
||||
break;
|
||||
case SOC_CPU_CLK_SRC_PLL_F240M:
|
||||
source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
|
||||
break;
|
||||
default:
|
||||
// Unknown HP_ROOT clock source
|
||||
ESP_HW_LOGE(TAG, "Invalid HP_ROOT_CLK");
|
||||
break;
|
||||
}
|
||||
return source_freq_mhz;
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
|
||||
uint32_t source_freq_mhz = rtc_clk_hp_root_get_freq_mhz(source);
|
||||
if (source_freq_mhz == 0) {
|
||||
// unsupported frequency configuration
|
||||
abort();
|
||||
}
|
||||
hal_utils_clk_div_t div = {0}; // div = freq of SOC_ROOT_CLK / freq of CPU_CLK
|
||||
clk_ll_cpu_get_divider(&div.integer, &div.numerator, &div.denominator);
|
||||
if (div.denominator == 0) {
|
||||
div.denominator = 1;
|
||||
div.numerator = 0;
|
||||
}
|
||||
uint32_t freq_mhz = source_freq_mhz * div.denominator / (div.integer * div.denominator + div.numerator);
|
||||
*out_config = (rtc_cpu_freq_config_t) {
|
||||
.source = source,
|
||||
.source_freq_mhz = source_freq_mhz,
|
||||
.div = div,
|
||||
.freq_mhz = freq_mhz
|
||||
};
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
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);
|
||||
rtc_clk_cpll_disable();
|
||||
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)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
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)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
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
|
||||
}
|
||||
|
||||
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();
|
||||
if (xtal_freq_mhz == 0) {
|
||||
ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz");
|
||||
return SOC_XTAL_FREQ_40M;
|
||||
}
|
||||
assert(xtal_freq_mhz == SOC_XTAL_FREQ_40M);
|
||||
return (soc_xtal_freq_t)xtal_freq_mhz;
|
||||
}
|
||||
|
||||
void rtc_clk_xtal_freq_update(soc_xtal_freq_t xtal_freq)
|
||||
{
|
||||
// clk_ll_xtal_store_freq_mhz(xtal_freq);
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_apb_freq_get(void)
|
||||
{
|
||||
soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
|
||||
@@ -228,14 +518,17 @@ uint32_t rtc_clk_apb_freq_get(void)
|
||||
numerator = 0;
|
||||
}
|
||||
uint32_t cpu_freq_hz = source_freq_mhz * MHZ * denominator / (integer * denominator + numerator);
|
||||
uint32_t mem_freq_hz = cpu_freq_hz / clk_ll_mem_get_divider();
|
||||
uint32_t sys_freq_hz = mem_freq_hz / clk_ll_sys_get_divider();
|
||||
uint32_t sys_freq_hz = cpu_freq_hz / clk_ll_sys_get_divider();
|
||||
return sys_freq_hz / clk_ll_apb_get_divider();
|
||||
}
|
||||
|
||||
void rtc_clk_apll_enable(bool enable)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
if (enable) {
|
||||
clk_ll_apll_enable();
|
||||
} else {
|
||||
clk_ll_apll_disable();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2)
|
||||
@@ -299,17 +592,19 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm
|
||||
|
||||
void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
// TODO: IDF-14771, IDF-14750
|
||||
}
|
||||
|
||||
void rtc_dig_clk8m_enable(void)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
clk_ll_rc_fast_digi_enable();
|
||||
esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH);
|
||||
}
|
||||
|
||||
void rtc_dig_clk8m_disable(void)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14678
|
||||
clk_ll_rc_fast_digi_disable();
|
||||
esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH);
|
||||
}
|
||||
|
||||
bool rtc_dig_8m_enabled(void)
|
||||
@@ -331,7 +626,6 @@ IRAM_ATTR void rtc_clk_mpll_enable(void)
|
||||
|
||||
void rtc_clk_mpll_configure(uint32_t xtal_freq, uint32_t mpll_freq, bool thread_safe)
|
||||
{
|
||||
/* Analog part */
|
||||
if (thread_safe) {
|
||||
_regi2c_ctrl_ll_master_enable_clock(true);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp32s31/rom/ets_sys.h"
|
||||
#include "esp32s31/rom/rtc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "regi2c_ctrl.h"
|
||||
#include "soc/regi2c_dig_reg.h"
|
||||
#include "soc/lp_clkrst_reg.h"
|
||||
#include "soc/lp_system_reg.h"
|
||||
#include "soc/pmu_reg.h"
|
||||
#include "soc/chip_revision.h"
|
||||
#include "esp_hw_log.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_serial_output.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
|
||||
ESP_HW_LOG_ATTR_TAG(TAG, "rtc_clk_init");
|
||||
|
||||
void rtc_clk_init(rtc_clk_config_t cfg)
|
||||
{
|
||||
rtc_cpu_freq_config_t old_config, new_config;
|
||||
|
||||
/* Set tuning parameters for RC_FAST, RC_SLOW, and RC32K clocks.
|
||||
* Note: this doesn't attempt to set the clocks to precise frequencies.
|
||||
* Instead, we calibrate these clocks against XTAL frequency later, when necessary.
|
||||
* - SCK_DCAP value controls tuning of RC_SLOW clock.
|
||||
* The higher the value of DCAP is, the lower is the frequency.
|
||||
* - CK8M_DFREQ value controls tuning of RC_FAST clock.
|
||||
* CLK_8M_DFREQ constant gives the best temperature characteristics.
|
||||
*/
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_SCK_DCAP, cfg.slow_clk_dcap);
|
||||
|
||||
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);
|
||||
|
||||
// XTAL freq determined by efuse, and can be directly informed from register field LP_AONCLKRST_CLK_XTAL_FREQ
|
||||
|
||||
// No need to wait UART0 TX idle since its default clock source is XTAL, should not be affected by system clock configuration
|
||||
|
||||
/* Set CPU frequency */
|
||||
rtc_clk_cpu_freq_get_config(&old_config);
|
||||
uint32_t freq_before = old_config.freq_mhz;
|
||||
bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config);
|
||||
if (!res) {
|
||||
ESP_HW_LOGE(TAG, "invalid CPU frequency value");
|
||||
abort();
|
||||
}
|
||||
rtc_clk_cpu_freq_set_config(&new_config);
|
||||
|
||||
/* Re-calculate the ccount to make time calculation correct. */
|
||||
esp_cpu_set_cycle_count( (uint64_t)esp_cpu_get_cycle_count() * cfg.cpu_freq_mhz / freq_before );
|
||||
|
||||
/* Slow & fast clocks setup */
|
||||
// We will not power off RC_FAST in bootloader stage even if it is not being used as any
|
||||
// cpu / rtc_fast / rtc_slow clock sources, this is because RNG always needs it in the bootloader stage.
|
||||
bool need_rc_fast_en = true;
|
||||
if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
rtc_clk_32k_enable(true);
|
||||
}
|
||||
rtc_clk_8m_enable(need_rc_fast_en);
|
||||
rtc_clk_fast_src_set(cfg.fast_clk_src);
|
||||
rtc_clk_slow_src_set(cfg.slow_clk_src);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -10,14 +10,12 @@
|
||||
#include "soc/rtc.h"
|
||||
#include "hal/rtc_timer_hal.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
// #include "hal/timer_ll.h"
|
||||
#include "hal/timg_ll.h"
|
||||
#include "soc/hp_sys_clkrst_reg.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
|
||||
// TODO: [ESP32S31] IDF-14678
|
||||
|
||||
__attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
|
||||
/* Calibration of clock frequency is performed using a special feature of TIMG0.
|
||||
@@ -25,46 +23,57 @@ __attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
* clock cycles.
|
||||
*/
|
||||
|
||||
#define CLK_CAL_TIMEOUT_THRES(cal_clk, cycles) ((cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL) ? (cycles << 12) : (cycles << 10))
|
||||
#define CLK_CAL_TIMEOUT_THRES(cal_clk_sel, cycles) ((cal_clk_sel == CLK_CAL_32K_XTAL) ? (cycles << 12) : (cycles << 10))
|
||||
|
||||
// Calibration can only be performed on relatively slow speed clock signal. Therefore, for high-speed clocks,
|
||||
// calibration is performed on their DIV_CLKs. The divider is configurable. We set:
|
||||
#define CLK_CAL_DIV_VAL(cal_clk) \
|
||||
((cal_clk == RTC_CAL_RC_SLOW || cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL) ? 1 : \
|
||||
(cal_clk == RTC_CAL_LP_PLL) ? 25 : \
|
||||
(cal_clk == RTC_CAL_RC_FAST) ? 50 : \
|
||||
(cal_clk == RTC_CAL_APLL) ? 200 : \
|
||||
#define CLK_CAL_DIV_VAL(cal_clk_sel) \
|
||||
((cal_clk_sel == CLK_CAL_RC_SLOW || cal_clk_sel == CLK_CAL_32K_XTAL) ? 1 : \
|
||||
(cal_clk_sel == CLK_CAL_RC_FAST) ? 50 : \
|
||||
(cal_clk_sel == CLK_CAL_APLL || cal_clk_sel == CLK_CAL_AHB || cal_clk_sel == CLK_CAL_ROM) ? 200 : \
|
||||
(cal_clk_sel == CLK_CAL_XTAL || cal_clk_sel == CLK_CAL_APB) ? 100 : \
|
||||
(cal_clk_sel == CLK_CAL_CORE0 || cal_clk_sel == CLK_CAL_CORE1) ? 1000 : \
|
||||
4000)
|
||||
|
||||
// CLK_CAL_FREQ_APPROX = CLK_FREQ_APPROX / CLK_CAL_DIV_VAL
|
||||
#define CLK_CAL_FREQ_APPROX(cal_clk) \
|
||||
((cal_clk == RTC_CAL_MPLL) ? (CLK_LL_PLL_500M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk == RTC_CAL_SPLL) ? (CLK_LL_PLL_480M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk == RTC_CAL_CPLL) ? (CLK_LL_PLL_400M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk == RTC_CAL_APLL) ? (105 * MHZ / 200) : \
|
||||
(cal_clk == RTC_CAL_SDIO_PLL0 || cal_clk == RTC_CAL_SDIO_PLL1 || cal_clk == RTC_CAL_SDIO_PLL2) ? (200 * MHZ / 4000) : \
|
||||
(cal_clk == RTC_CAL_RC_FAST) ? (SOC_CLK_RC_FAST_FREQ_APPROX / 50) : \
|
||||
(cal_clk == RTC_CAL_RC_SLOW) ? (SOC_CLK_RC_SLOW_FREQ_APPROX) : \
|
||||
(cal_clk == RTC_CAL_RC32K) ? (SOC_CLK_RC32K_FREQ_APPROX) : \
|
||||
(cal_clk == RTC_CAL_32K_XTAL) ? (SOC_CLK_XTAL32K_FREQ_APPROX) : \
|
||||
(cal_clk == RTC_CAL_LP_PLL) ? (CLK_LL_PLL_8M_FREQ_MHZ * MHZ / 25) : \
|
||||
#define CLK_CAL_FREQ_APPROX(cal_clk_sel) \
|
||||
((cal_clk_sel == CLK_CAL_MPLL) ? (CLK_LL_PLL_500M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk_sel == CLK_CAL_BBPLL) ? (CLK_LL_PLL_480M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk_sel == CLK_CAL_CPLL) ? (CLK_LL_PLL_320M_FREQ_MHZ * MHZ / 4000) : \
|
||||
(cal_clk_sel == CLK_CAL_APLL) ? (105 * MHZ / 200) : \
|
||||
(cal_clk_sel == CLK_CAL_AHB || cal_clk_sel == CLK_CAL_ROM) ? (100 * MHZ / 200) : \
|
||||
(cal_clk_sel == CLK_CAL_RC_FAST) ? (SOC_CLK_RC_FAST_FREQ_APPROX / 50) : \
|
||||
(cal_clk_sel == CLK_CAL_RC_SLOW) ? (SOC_CLK_RC_SLOW_FREQ_APPROX) : \
|
||||
(cal_clk_sel == CLK_CAL_32K_XTAL) ? (SOC_CLK_XTAL32K_FREQ_APPROX) : \
|
||||
(cal_clk_sel == CLK_CAL_XTAL || cal_clk_sel == CLK_CAL_APB) ? (40 * MHZ / 100) : \
|
||||
(cal_clk_sel == CLK_CAL_CORE0 || cal_clk_sel == CLK_CAL_CORE1) ? (CLK_LL_PLL_320M_FREQ_MHZ * MHZ / 1000) : \
|
||||
0)
|
||||
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
/**
|
||||
* @brief Clock frequency calculation function used by rtc_clk_cal
|
||||
*
|
||||
* Calculation of clock frequency is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* clock cycles.
|
||||
*
|
||||
* @param cal_clk_sel which clock to calculate frequency
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
if (cal_clk_sel == CLK_CAL_RTC_SLOW) {
|
||||
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;
|
||||
cal_clk_sel = CLK_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;
|
||||
cal_clk_sel = CLK_CAL_32K_XTAL;
|
||||
}
|
||||
}
|
||||
if (cal_clk < 0 || cal_clk >= RTC_CAL_INVALID_CLK) {
|
||||
|
||||
if (cal_clk_sel < 0) {
|
||||
ESP_EARLY_LOGE(TAG, "clock not supported to be calibrated");
|
||||
return 0;
|
||||
}
|
||||
@@ -74,13 +83,13 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
// Only enable if originally was disabled, and set back to the disable state after calibration is done
|
||||
// If the clock is already on, then do nothing
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
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 (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
@@ -89,17 +98,6 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
}
|
||||
|
||||
bool rc32k_enabled = clk_ll_rc32k_is_enabled();
|
||||
bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (!rc32k_enabled) {
|
||||
rtc_clk_rc32k_enable(true);
|
||||
}
|
||||
if (!dig_rc32k_enabled) {
|
||||
clk_ll_rc32k_digi_enable();
|
||||
}
|
||||
}
|
||||
|
||||
/* There may be another calibration process already running during we call this function,
|
||||
* so we should wait the last process is done.
|
||||
*/
|
||||
@@ -114,16 +112,16 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(HP_SYS_CLKRST_TIMERGRP0_TGRT_CTRL0_REG, HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_SRC_SEL, cal_clk);
|
||||
uint32_t clk_cal_divider = CLK_CAL_DIV_VAL(cal_clk);
|
||||
REG_SET_FIELD(HP_SYS_CLKRST_TIMERGRP0_TGRT_CTRL0_REG, HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_DIV_NUM, clk_cal_divider - 1);
|
||||
clk_ll_freq_calulation_set_target(cal_clk_sel);
|
||||
uint32_t clk_cal_divider = CLK_CAL_DIV_VAL(cal_clk_sel);
|
||||
clk_ll_freq_calculation_set_divider(clk_cal_divider);
|
||||
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 = CLK_CAL_FREQ_APPROX(cal_clk);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk_sel, slowclk_cycles));
|
||||
uint32_t expected_freq = CLK_CAL_FREQ_APPROX(cal_clk_sel);
|
||||
assert(expected_freq);
|
||||
uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
|
||||
/* Start calibration */
|
||||
@@ -145,14 +143,14 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_TIMERGRP0_TGRT_CTRL0_REG, HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_DIV_NUM_M);
|
||||
clk_ll_freq_calculation_set_divider(1);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (cal_clk_sel == CLK_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
@@ -161,15 +159,6 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
}
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (!dig_rc32k_enabled) {
|
||||
clk_ll_rc32k_digi_disable();
|
||||
}
|
||||
if (!rc32k_enabled) {
|
||||
rtc_clk_rc32k_enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
@@ -180,14 +169,14 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
uint32_t rtc_clk_cal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32_t slowclk_cycles)
|
||||
{
|
||||
slowclk_cycles /= (cal_clk == RTC_CAL_RTC_MUX) ? 1 : CLK_CAL_DIV_VAL(cal_clk);
|
||||
slowclk_cycles /= (cal_clk_sel == CLK_CAL_RTC_SLOW) ? 1 : CLK_CAL_DIV_VAL(cal_clk_sel);
|
||||
assert(slowclk_cycles);
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk_sel, slowclk_cycles);
|
||||
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
if (cal_clk_sel == CLK_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -230,5 +219,15 @@ uint32_t rtc_clk_freq_to_period(uint32_t) __attribute__((alias("rtc_clk_freq_cal
|
||||
__attribute__((constructor))
|
||||
static void enable_timer_group0_for_calibration(void)
|
||||
{
|
||||
// TODO: ["ESP32S31"] IDF-14871
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_TIMG0_MODULE, ref_count) {
|
||||
if (ref_count == 0) {
|
||||
timg_ll_enable_bus_clock(0, true);
|
||||
timg_ll_reset_register(0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
_timg_ll_enable_bus_clock(0, true);
|
||||
_timg_ll_reset_register(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
Reference in New Issue
Block a user