diff --git a/components/bootloader_support/src/bootloader_clock_init.c b/components/bootloader_support/src/bootloader_clock_init.c index 417dc47db2..e5c63be31d 100644 --- a/components/bootloader_support/src/bootloader_clock_init.c +++ b/components/bootloader_support/src/bootloader_clock_init.c @@ -9,7 +9,7 @@ #include "hal/efuse_hal.h" #include "soc/rtc_cntl_reg.h" #if CONFIG_IDF_TARGET_ESP32 -#include "soc/dport_reg.h" +#include "hal/clk_tree_ll.h" #endif #include "esp_rom_sys.h" #include "esp_rom_uart.h" @@ -33,22 +33,28 @@ __attribute__((weak)) void bootloader_clock_configure(void) * previously. */ if (efuse_hal_get_chip_revision() == 0 && - DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL) == DPORT_CPUPERIOD_SEL_240) { + clk_ll_cpu_get_freq_mhz_from_pll() == CLK_LL_PLL_240M_FREQ_MHZ) { cpu_freq_mhz = 240; } #elif CONFIG_IDF_TARGET_ESP32H2 cpu_freq_mhz = 64; #endif - if (rtc_clk_apb_freq_get() < APB_CLK_FREQ || esp_rom_get_reset_reason(0) != RESET_REASON_CPU0_SW) { + if (esp_rom_get_reset_reason(0) != RESET_REASON_CPU0_SW || rtc_clk_apb_freq_get() < APB_CLK_FREQ) { rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT(); #if CONFIG_IDF_TARGET_ESP32 clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ; #endif - /* ESP32-S2 doesn't have XTAL_FREQ choice, always 40MHz */ + /* Except ESP32, there is no XTAL_FREQ choice */ clk_cfg.cpu_freq_mhz = cpu_freq_mhz; 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; + } clk_cfg.fast_clk_src = rtc_clk_fast_src_get(); + if (clk_cfg.fast_clk_src == SOC_RTC_FAST_CLK_SRC_INVALID) { + clk_cfg.fast_clk_src = SOC_RTC_FAST_CLK_SRC_XTAL_DIV; + } rtc_clk_init(clk_cfg); } diff --git a/components/esp_hw_support/esp_clk.c b/components/esp_hw_support/esp_clk.c index 93100519e5..0fd5deec93 100644 --- a/components/esp_hw_support/esp_clk.c +++ b/components/esp_hw_support/esp_clk.c @@ -14,6 +14,7 @@ #include "esp_rom_caps.h" #include "esp_rom_sys.h" #include "esp_private/esp_clk.h" +#include "hal/clk_tree_ll.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/rtc.h" @@ -126,12 +127,12 @@ void esp_clk_slowclk_cal_set(uint32_t new_cal) */ esp_rtc_get_time_us(); #endif // CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER - REG_WRITE(RTC_SLOW_CLK_CAL_REG, new_cal); + clk_ll_rtc_slow_store_cal(new_cal); } uint32_t esp_clk_slowclk_cal_get(void) { - return REG_READ(RTC_SLOW_CLK_CAL_REG); + return clk_ll_rtc_slow_load_cal(); } uint64_t esp_clk_rtc_time(void) diff --git a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h index 17918dfb85..a43097cfb3 100644 --- a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h +++ b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h @@ -47,7 +47,7 @@ void regi2c_exit_critical(void); #endif // BOOTLOADER_BUILD /* Convenience macros for the above functions, these use register definitions - * from regi2c_apll.h/regi2c_bbpll.h header files. + * from regi2c_xxx.h header files. */ #define REGI2C_WRITE_MASK(block, reg_add, indata) \ regi2c_ctrl_write_reg_mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB, indata) diff --git a/components/esp_hw_support/port/esp32/rtc_clk.c b/components/esp_hw_support/port/esp32/rtc_clk.c index e1c83f1572..4e9889cebf 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk.c +++ b/components/esp_hw_support/port/esp32/rtc_clk.c @@ -12,92 +12,24 @@ #include "soc/rtc_periph.h" #include "soc/sens_periph.h" #include "soc/soc_caps.h" -#include "soc/dport_reg.h" #include "hal/efuse_ll.h" #include "hal/efuse_hal.h" -#include "soc/syscon_reg.h" #include "soc/gpio_struct.h" #include "hal/cpu_hal.h" #include "hal/gpio_ll.h" #include "esp_hw_log.h" #include "sdkconfig.h" -#include "rtc_clk_common.h" - #include "esp_rom_sys.h" #include "esp_rom_gpio.h" #include "esp32/rom/ets_sys.h" // for ets_update_cpu_frequency #include "esp32/rom/rtc.h" +#include "hal/clk_tree_ll.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/io_mux_reg.h" -#include "regi2c_ctrl.h" -#include "regi2c_apll.h" -#include "regi2c_bbpll.h" - -/* BBPLL configuration values */ -#define BBPLL_ENDIV5_VAL_320M 0x43 -#define BBPLL_BBADC_DSMP_VAL_320M 0x84 -#define BBPLL_ENDIV5_VAL_480M 0xc3 -#define BBPLL_BBADC_DSMP_VAL_480M 0x74 -#define BBPLL_IR_CAL_DELAY_VAL 0x18 -#define BBPLL_IR_CAL_EXT_CAP_VAL 0x20 -#define BBPLL_OC_ENB_FCAL_VAL 0x9a -#define BBPLL_OC_ENB_VCON_VAL 0x00 -#define BBPLL_BBADC_CAL_7_0_VAL 0x00 - -#define APLL_SDM_STOP_VAL_1 0x09 -#define APLL_SDM_STOP_VAL_2_REV0 0x69 -#define APLL_SDM_STOP_VAL_2_REV1 0x49 - -#define APLL_CAL_DELAY_1 0x0f -#define APLL_CAL_DELAY_2 0x3f -#define APLL_CAL_DELAY_3 0x1f - -#define XTAL_32K_DAC_VAL 1 -#define XTAL_32K_DRES_VAL 3 -#define XTAL_32K_DBIAS_VAL 0 - -#define XTAL_32K_BOOTSTRAP_DAC_VAL 3 -#define XTAL_32K_BOOTSTRAP_DRES_VAL 3 -#define XTAL_32K_BOOTSTRAP_DBIAS_VAL 0 #define XTAL_32K_BOOTSTRAP_TIME_US 7 -#define XTAL_32K_EXT_DAC_VAL 2 -#define XTAL_32K_EXT_DRES_VAL 3 -#define XTAL_32K_EXT_DBIAS_VAL 1 - -/* Delays for various clock sources to be enabled/switched. - * All values are in microseconds. - * TODO: some of these are excessive, and should be reduced. - */ -#define DELAY_PLL_DBIAS_RAISE 3 -#define DELAY_PLL_ENABLE_WITH_150K 80 -#define DELAY_PLL_ENABLE_WITH_32K 160 -#define DELAY_FAST_CLK_SWITCH 3 -#define DELAY_SLOW_CLK_SWITCH 300 -#define DELAY_8M_ENABLE 50 - -/* Core voltage needs to be increased in two cases: - * 1. running at 240 MHz - * 2. running with 80MHz Flash frequency - * - * There is a record in efuse which indicates the proper voltage for these two cases. - */ -#define RTC_CNTL_DBIAS_HP_VOLT (RTC_CNTL_DBIAS_1V25 - efuse_ll_get_vol_level_hp_inv()) -#ifdef CONFIG_ESPTOOLPY_FLASHFREQ_80M -#define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_HP_VOLT -#else -#define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V10 -#endif -#define DIG_DBIAS_240M RTC_CNTL_DBIAS_HP_VOLT -#define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10 -#define DIG_DBIAS_2M RTC_CNTL_DBIAS_1V00 - -#define RTC_PLL_FREQ_320M 320 -#define RTC_PLL_FREQ_480M 480 -#define DELAY_RTC_CLK_SWITCH 5 - static void rtc_clk_cpu_freq_to_8m(void); -static void rtc_clk_bbpll_disable(void); -static void rtc_clk_bbpll_enable(void); static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz); // Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. @@ -105,20 +37,12 @@ static uint32_t s_cur_pll_freq; static const char* TAG = "rtc_clk"; -static void rtc_clk_32k_enable_common(int dac, int dres, int dbias) +static void rtc_clk_32k_enable_common(clk_ll_xtal32k_enable_mode_t mode) { CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_RDE | RTC_IO_X32P_RUE | RTC_IO_X32N_RUE | RTC_IO_X32N_RDE | RTC_IO_X32N_FUN_IE | RTC_IO_X32P_FUN_IE); SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL); - /* Set the parameters of xtal - dac --> current - dres --> resistance - dbias --> bais voltage - */ - REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DAC_XTAL_32K, dac); - REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DRES_XTAL_32K, dres); - REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DBIAS_XTAL_32K, dbias); #ifdef CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT uint8_t chip_ver = efuse_hal_get_chip_revision(); @@ -157,17 +81,17 @@ static void rtc_clk_32k_enable_common(int dac, int dres, int dbias) CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_START_M); } #endif - /* Power up external xtal */ - SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M); + + clk_ll_xtal32k_enable(mode); } void rtc_clk_32k_enable(bool enable) { if (enable) { - rtc_clk_32k_enable_common(XTAL_32K_DAC_VAL, XTAL_32K_DRES_VAL, XTAL_32K_DBIAS_VAL); + rtc_clk_32k_enable_common(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL); } else { + clk_ll_xtal32k_disable(); /* Disable X32N and X32P pad drive external xtal */ - CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M); CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL); #ifdef CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT @@ -191,7 +115,7 @@ void rtc_clk_32k_enable(bool enable) void rtc_clk_32k_enable_external(void) { - rtc_clk_32k_enable_common(XTAL_32K_EXT_DAC_VAL, XTAL_32K_EXT_DRES_VAL, XTAL_32K_EXT_DBIAS_VAL); + rtc_clk_32k_enable_common(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL); } /* Helping external 32kHz crystal to start up. @@ -201,88 +125,86 @@ void rtc_clk_32k_enable_external(void) void rtc_clk_32k_bootstrap(uint32_t cycle) { if (cycle){ - const uint32_t pin_32 = 32; - const uint32_t pin_33 = 33; - - esp_rom_gpio_pad_select_gpio(pin_32); - esp_rom_gpio_pad_select_gpio(pin_33); - gpio_ll_output_enable(&GPIO, pin_32); - gpio_ll_output_enable(&GPIO, pin_33); - gpio_ll_set_level(&GPIO, pin_32, 1); - gpio_ll_set_level(&GPIO, pin_33, 0); + esp_rom_gpio_pad_select_gpio(XTAL32K_P_GPIO_NUM); + esp_rom_gpio_pad_select_gpio(XTAL32K_N_GPIO_NUM); + gpio_ll_output_enable(&GPIO, XTAL32K_P_GPIO_NUM); + gpio_ll_output_enable(&GPIO, XTAL32K_N_GPIO_NUM); + gpio_ll_set_level(&GPIO, XTAL32K_P_GPIO_NUM, 1); + gpio_ll_set_level(&GPIO, XTAL32K_N_GPIO_NUM, 0); const uint32_t delay_us = (1000000 / SOC_CLK_XTAL32K_FREQ_APPROX / 2); - while(cycle){ - gpio_ll_set_level(&GPIO, pin_32, 1); - gpio_ll_set_level(&GPIO, pin_33, 0); + while (cycle) { + gpio_ll_set_level(&GPIO, XTAL32K_P_GPIO_NUM, 1); + gpio_ll_set_level(&GPIO, XTAL32K_N_GPIO_NUM, 0); esp_rom_delay_us(delay_us); - gpio_ll_set_level(&GPIO, pin_33, 1); - gpio_ll_set_level(&GPIO, pin_32, 0); + gpio_ll_set_level(&GPIO, XTAL32K_N_GPIO_NUM, 1); + gpio_ll_set_level(&GPIO, XTAL32K_P_GPIO_NUM, 0); esp_rom_delay_us(delay_us); cycle--; } // disable pins - gpio_ll_output_disable(&GPIO, pin_32); - gpio_ll_output_disable(&GPIO, pin_33); + gpio_ll_output_disable(&GPIO, XTAL32K_P_GPIO_NUM); + gpio_ll_output_disable(&GPIO, XTAL32K_N_GPIO_NUM); } - CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K); + clk_ll_xtal32k_disable(); SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_RUE | RTC_IO_X32N_RDE); esp_rom_delay_us(XTAL_32K_BOOTSTRAP_TIME_US); - rtc_clk_32k_enable_common(XTAL_32K_BOOTSTRAP_DAC_VAL, - XTAL_32K_BOOTSTRAP_DRES_VAL, XTAL_32K_BOOTSTRAP_DBIAS_VAL); + rtc_clk_32k_enable_common(CLK_LL_XTAL32K_ENABLE_MODE_BOOTSTRAP); } bool rtc_clk_32k_enabled(void) { - return GET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K) != 0; + return clk_ll_xtal32k_is_enabled(); } void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en) { if (clk_8m_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); + clk_ll_rc_fast_enable(); if (d256_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_enable(); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_disable(); } - esp_rom_delay_us(DELAY_8M_ENABLE); + esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); + clk_ll_rc_fast_disable(); } } bool rtc_clk_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; + return clk_ll_rc_fast_is_enabled(); } bool rtc_clk_8md256_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; + return clk_ll_rc_fast_d256_is_enabled(); } void rtc_clk_apll_enable(bool enable) { - REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD, enable ? 0 : 1); - REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, enable ? 1 : 0); - - if (!enable && - REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL) != RTC_CNTL_SOC_CLK_SEL_PLL) { - REG_SET_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD); + if (enable) { + clk_ll_apll_enable(); } else { - REG_CLR_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD); + clk_ll_apll_disable(); + } + + if (!enable && (clk_ll_cpu_get_src() != SOC_CPU_CLK_SRC_PLL)) { + // if apll and bbpll are both not in use, then can also power down the internal I2C bus + // this power down affects most of the analog peripherals + clk_ll_i2c_pd(); + } else { + clk_ll_i2c_pu(); } } uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2) { - uint32_t rtc_xtal_freq = (uint32_t)rtc_clk_xtal_freq_get(); - if (rtc_xtal_freq == 0) { + uint32_t xtal_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); + if (xtal_freq_mhz == 0) { // xtal_freq has not set yet ESP_HW_LOGE(TAG, "Get xtal clock frequency failed, it has not been set yet"); abort(); @@ -316,9 +238,9 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm } } // sdm2 = (int)(((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2 = (int)(((o_div + 2) * 2 * freq) / (rtc_xtal_freq * 1000000)) - 4; + sdm2 = (int)(((o_div + 2) * 2 * freq) / (xtal_freq_mhz * MHZ)) - 4; // numrator = (((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2 - float numrator = (((o_div + 2) * 2 * freq) / ((float)rtc_xtal_freq * 1000000)) - 4 - sdm2; + float numrator = (((o_div + 2) * 2 * freq) / ((float)xtal_freq_mhz * MHZ)) - 4 - sdm2; // If numrator is bigger than 255/256 + 255/65536 + (1/65536)/2 = 1 - (1 / 65536)/2, carry bit to sdm2 if (numrator > 1.0 - (1.0 / 65536.0) / 2.0) { sdm2++; @@ -330,7 +252,7 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm // Get the closest sdm0 sdm0 = (int)(numrator * 65536.0 + 0.5) % 256; } - uint32_t real_freq = (uint32_t)(rtc_xtal_freq * 1000000 * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / (((float)o_div + 2) * 2)); + uint32_t real_freq = (uint32_t)(xtal_freq_mhz * MHZ * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / (((float)o_div + 2) * 2)); *_o_div = o_div; *_sdm0 = sdm0; *_sdm1 = sdm1; @@ -340,168 +262,90 @@ 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) { - uint8_t sdm_stop_val_2 = APLL_SDM_STOP_VAL_2_REV1; - uint32_t is_rev0 = (efuse_ll_get_chip_ver_rev1() == 0); - if (is_rev0) { - sdm0 = 0; - sdm1 = 0; - sdm_stop_val_2 = APLL_SDM_STOP_VAL_2_REV0; - } - REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM2, sdm2); - REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM0, sdm0); - REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM1, sdm1); - REGI2C_WRITE(I2C_APLL, I2C_APLL_SDM_STOP, APLL_SDM_STOP_VAL_1); - REGI2C_WRITE(I2C_APLL, I2C_APLL_SDM_STOP, sdm_stop_val_2); - REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OR_OUTPUT_DIV, o_div); + bool is_rev0 = (efuse_ll_get_chip_ver_rev1() == 0); + clk_ll_apll_set_config(is_rev0, o_div, sdm0, sdm1, sdm2); /* calibration */ - REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_1); - REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_2); - REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_3); + clk_ll_apll_set_calibration(); /* wait for calibration end */ - while (!(REGI2C_READ_MASK(I2C_APLL, I2C_APLL_OR_CAL_END))) { + while (!clk_ll_apll_calibration_is_done()) { /* use esp_rom_delay_us so the RTC bus doesn't get flooded */ esp_rom_delay_us(1); } } -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq) +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); + clk_ll_rtc_slow_set_src(clk_src); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, - (slow_freq == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? 1 : 0); + // The logic should be moved to BT driver + if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + clk_ll_xtal32k_digi_enable(); + } else { + clk_ll_xtal32k_digi_disable(); + } - esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH); + esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + return clk_ll_rtc_slow_get_src(); } uint32_t rtc_clk_slow_freq_get_hz(void) { - 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_RC_FAST_D256: return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + 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_RC_FAST_D256: return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: return 0; } - return 0; } -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq) +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq); - esp_rom_delay_us(DELAY_FAST_CLK_SWITCH); + 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) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + return clk_ll_rtc_fast_get_src(); } -void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) +static void rtc_clk_bbpll_disable(void) { - uint8_t div_ref; - uint8_t div7_0; - uint8_t div10_8; - uint8_t lref; - uint8_t dcur; - uint8_t bw; + clk_ll_bbpll_disable(); + s_cur_pll_freq = 0; - if (pll_freq == RTC_PLL_FREQ_320M) { - /* Raise the voltage, if needed */ + // if apll is under force power down, then can also power down the internal I2C bus + // this power down affects most of the analog peripherals + if (clk_ll_apll_is_fpd()) { + clk_ll_i2c_pd(); + } +} + +static void rtc_clk_bbpll_enable(void) +{ + clk_ll_i2c_pu(); + clk_ll_bbpll_enable(); +} + +static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) +{ + /* Raise the voltage */ + if (pll_freq == CLK_LL_PLL_320M_FREQ_MHZ) { REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_80M_160M); - /* Configure 320M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 32; - div10_8 = 0; - lref = 0; - dcur = 6; - bw = 3; - break; - case RTC_XTAL_FREQ_26M: - div_ref = 12; - div7_0 = 224; - div10_8 = 4; - lref = 1; - dcur = 0; - bw = 1; - break; - case RTC_XTAL_FREQ_24M: - div_ref = 11; - div7_0 = 224; - div10_8 = 4; - lref = 1; - dcur = 0; - bw = 1; - break; - default: - div_ref = 12; - div7_0 = 224; - div10_8 = 4; - lref = 0; - dcur = 0; - bw = 0; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_320M); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_320M); - } else { - /* Raise the voltage */ + } else { // CLK_LL_PLL_480M_FREQ_MHZ REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_240M); - esp_rom_delay_us(DELAY_PLL_DBIAS_RAISE); - /* Configure 480M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 28; - div10_8 = 0; - lref = 0; - dcur = 6; - bw = 3; - break; - case RTC_XTAL_FREQ_26M: - div_ref = 12; - div7_0 = 144; - div10_8 = 4; - lref = 1; - dcur = 0; - bw = 1; - break; - case RTC_XTAL_FREQ_24M: - div_ref = 11; - div7_0 = 144; - div10_8 = 4; - lref = 1; - dcur = 0; - bw = 1; - break; - default: - div_ref = 12; - div7_0 = 224; - div10_8 = 4; - lref = 0; - dcur = 0; - bw = 0; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_480M); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_480M); + esp_rom_delay_us(SOC_DELAY_PLL_DBIAS_RAISE); } - uint8_t i2c_bbpll_lref = (lref << 7) | (div10_8 << 4) | (div_ref); - uint8_t i2c_bbpll_div_7_0 = div7_0; - uint8_t i2c_bbpll_dcur = (bw << 6) | dcur; - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_LREF, i2c_bbpll_lref); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); - uint32_t delay_pll_en = (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ? - DELAY_PLL_ENABLE_WITH_150K : DELAY_PLL_ENABLE_WITH_32K; + clk_ll_bbpll_set_config(pll_freq, xtal_freq); + uint32_t delay_pll_en = (clk_ll_rtc_slow_get_src() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ? + SOC_DELAY_PLL_ENABLE_WITH_150K : SOC_DELAY_PLL_ENABLE_WITH_32K; esp_rom_delay_us(delay_pll_en); s_cur_pll_freq = pll_freq; } @@ -513,58 +357,29 @@ void rtc_clk_cpu_freq_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); /* set divider from XTAL to APB clock */ - REG_SET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_PRE_DIV_CNT, div - 1); + clk_ll_cpu_set_divider(div); /* adjust ref_tick */ - REG_WRITE(SYSCON_XTAL_TICK_CONF_REG, freq * MHZ / REF_CLK_FREQ - 1); + clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_XTAL, freq); /* switch clock source */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_XTL); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); rtc_clk_apb_freq_update(freq * MHZ); /* lower the voltage */ - if (freq <= 2) { - REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_2M); - } else { - REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); - } + int dbias = (freq <= 2) ? DIG_DBIAS_2M : DIG_DBIAS_XTAL; + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias); } static void rtc_clk_cpu_freq_to_8m(void) { ets_update_cpu_frequency(8); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); - REG_SET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_PRE_DIV_CNT, 0); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_8M); + clk_ll_cpu_set_divider(1); + /* adjust ref_tick */ + clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_RC_FAST, 8); + /* switch clock source */ + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX); } -static void rtc_clk_bbpll_disable(void) -{ - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, - RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD | - RTC_CNTL_BBPLL_I2C_FORCE_PD); - s_cur_pll_freq = 0; - - /* is APLL under force power down? */ - uint32_t apll_fpd = REG_GET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); - if (apll_fpd) { - /* then also power down the internal I2C bus */ - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD); - } -} - -static void rtc_clk_bbpll_enable(void) -{ - CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, - RTC_CNTL_BIAS_I2C_FORCE_PD | RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); - - /* reset BBPLL configuration */ - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_IR_CAL_DELAY, BBPLL_IR_CAL_DELAY_VAL); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_IR_CAL_EXT_CAP, BBPLL_IR_CAL_EXT_CAP_VAL); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_ENB_FCAL, BBPLL_OC_ENB_FCAL_VAL); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_ENB_VCON, BBPLL_OC_ENB_VCON_VAL); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_BBADC_CAL_7_0, BBPLL_BBADC_CAL_7_0_VAL); -} - /** * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL. * PLL must already be enabled. @@ -572,22 +387,13 @@ static void rtc_clk_bbpll_enable(void) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { - int dbias = DIG_DBIAS_80M_160M; - int per_conf = DPORT_CPUPERIOD_SEL_80; - if (cpu_freq_mhz == 80) { - /* nothing to do */ - } else if (cpu_freq_mhz == 160) { - per_conf = DPORT_CPUPERIOD_SEL_160; - } else if (cpu_freq_mhz == 240) { - dbias = DIG_DBIAS_240M; - per_conf = DPORT_CPUPERIOD_SEL_240; - } else { - ESP_HW_LOGE(TAG, "invalid frequency"); - abort(); - } - DPORT_REG_WRITE(DPORT_CPU_PER_CONF_REG, per_conf); + int dbias = (cpu_freq_mhz == 240) ? DIG_DBIAS_240M : DIG_DBIAS_80M_160M; + clk_ll_cpu_set_freq_mhz_from_pll(cpu_freq_mhz); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_PLL); + /* adjust ref_tick */ + clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_PLL, cpu_freq_mhz); + /* switch clock source */ + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); rtc_clk_apb_freq_update(80 * MHZ); ets_update_cpu_frequency(cpu_freq_mhz); rtc_clk_wait_for_slow_cycle(); @@ -595,7 +401,7 @@ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) void rtc_clk_cpu_freq_set_xtal(void) { - int freq_mhz = (int) rtc_clk_xtal_freq_get(); + int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); rtc_clk_wait_for_slow_cycle(); @@ -623,17 +429,17 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* ou } else if (freq_mhz == 80) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_320M; + source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ; divider = 4; } else if (freq_mhz == 160) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_320M; + source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ; divider = 2; } else if (freq_mhz == 240) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 2; } else { // unsupported frequency @@ -651,14 +457,15 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* ou void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t* config) { rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get(); - uint32_t soc_clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL); - if (soc_clk_sel != RTC_CNTL_SOC_CLK_SEL_XTL) { + soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); + if (old_cpu_clk_src != SOC_CPU_CLK_SRC_XTAL) { rtc_clk_cpu_freq_to_xtal(xtal_freq, 1); rtc_clk_wait_for_slow_cycle(); } - if (soc_clk_sel == RTC_CNTL_SOC_CLK_SEL_PLL) { + if (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) { rtc_clk_bbpll_disable(); } + if (config->source == SOC_CPU_CLK_SRC_XTAL) { if (config->div > 1) { rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); @@ -675,50 +482,43 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t* config) void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t* out_config) { - soc_cpu_clk_src_t source; + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); uint32_t source_freq_mhz; uint32_t div; uint32_t freq_mhz; - uint32_t soc_clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL); - switch (soc_clk_sel) { - case RTC_CNTL_SOC_CLK_SEL_XTL: { - source = SOC_CPU_CLK_SRC_XTAL; - div = REG_GET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_PRE_DIV_CNT) + 1; - source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); - freq_mhz = source_freq_mhz / div; - } - break; - case RTC_CNTL_SOC_CLK_SEL_PLL: { - source = SOC_CPU_CLK_SRC_PLL; - uint32_t cpuperiod_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL); - if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_80) { - source_freq_mhz = RTC_PLL_FREQ_320M; - div = 4; - freq_mhz = 80; - } else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_160) { - source_freq_mhz = RTC_PLL_FREQ_320M; - div = 2; - freq_mhz = 160; - } else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_240) { - source_freq_mhz = RTC_PLL_FREQ_480M; - div = 2; - freq_mhz = 240; - } else { - ESP_HW_LOGE(TAG, "unsupported frequency configuration"); - abort(); - } - break; - } - case RTC_CNTL_SOC_CLK_SEL_8M: - source = SOC_CPU_CLK_SRC_RC_FAST; - source_freq_mhz = 8; - div = 1; - freq_mhz = source_freq_mhz; - break; - case RTC_CNTL_SOC_CLK_SEL_APLL: - default: + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); + freq_mhz = source_freq_mhz / div; + } + break; + case SOC_CPU_CLK_SRC_PLL: { + freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll(); + if (freq_mhz == CLK_LL_PLL_80M_FREQ_MHZ) { + source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ; + div = 4; + } else if (freq_mhz == CLK_LL_PLL_160M_FREQ_MHZ) { + source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ; + div = 2; + } else if (freq_mhz == CLK_LL_PLL_240M_FREQ_MHZ) { + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; + div = 2; + } else { ESP_HW_LOGE(TAG, "unsupported frequency configuration"); abort(); + } + break; + } + case SOC_CPU_CLK_SRC_RC_FAST: + source_freq_mhz = 8; + div = 1; + freq_mhz = source_freq_mhz; + break; + case SOC_CPU_CLK_SRC_APLL: + default: + ESP_HW_LOGE(TAG, "unsupported frequency configuration"); + abort(); } *out_config = (rtc_cpu_freq_config_t) { .source = source, @@ -743,26 +543,21 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t* config) rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) { - /* We may have already written XTAL value into RTC_XTAL_FREQ_REG */ - uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); - if (!clk_val_is_valid(xtal_freq_reg)) { + uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz(); + if (xtal_freq_mhz == 0) { return RTC_XTAL_FREQ_AUTO; } - return reg_val_to_clk_val(xtal_freq_reg & ~RTC_DISABLE_ROM_LOG); + return (rtc_xtal_freq_t)xtal_freq_mhz; } void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq) { - uint32_t reg = READ_PERI_REG(RTC_XTAL_FREQ_REG) & RTC_DISABLE_ROM_LOG; - if (reg == RTC_DISABLE_ROM_LOG) { - xtal_freq |= 1; - } - WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq)); + clk_ll_xtal_store_freq_mhz((uint32_t)xtal_freq); } void rtc_clk_apb_freq_update(uint32_t apb_freq) { - WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12)); + clk_ll_apb_store_freq_hz(apb_freq); } uint32_t rtc_clk_apb_freq_get(void) @@ -770,28 +565,24 @@ uint32_t rtc_clk_apb_freq_get(void) #if CONFIG_IDF_ENV_FPGA return CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * MHZ; #endif // CONFIG_IDF_ENV_FPGA - uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12; - // round to the nearest MHz - freq_hz += MHZ / 2; - uint32_t remainder = freq_hz % MHZ; - return freq_hz - remainder; + return clk_ll_apb_load_freq_hz(); } void rtc_dig_clk8m_enable(void) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } void rtc_dig_clk8m_disable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_disable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } bool rtc_dig_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + return clk_ll_rc_fast_digi_is_enabled(); } /* Name used in libphy.a:phy_chip_v7.o diff --git a/components/esp_hw_support/port/esp32/rtc_clk_common.h b/components/esp_hw_support/port/esp32/rtc_clk_common.h deleted file mode 100644 index 6721cf6f41..0000000000 --- a/components/esp_hw_support/port/esp32/rtc_clk_common.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include - -#define MHZ (1000000) - -#ifdef __cplusplus -extern "C" { -#endif - -void rtc_clk_cpu_freq_to_xtal(int freq, int div); - -/* Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in - * lower and upper 16-bit halves. These are the routines to work with such a - * representation. - */ -static inline bool clk_val_is_valid(uint32_t val) { - return (val & 0xffff) == ((val >> 16) & 0xffff) && - val != 0 && - val != UINT32_MAX; -} - -static inline uint32_t reg_val_to_clk_val(uint32_t val) { - return val & UINT16_MAX; -} - -static inline uint32_t clk_val_to_reg_val(uint32_t val) { - return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_hw_support/port/esp32/rtc_clk_init.c b/components/esp_hw_support/port/esp32/rtc_clk_init.c index 89731b256e..70551cc9df 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32/rtc_clk_init.c @@ -14,12 +14,11 @@ #include "soc/rtc_periph.h" #include "soc/sens_periph.h" #include "soc/efuse_periph.h" -#include "soc/syscon_reg.h" #include "hal/cpu_hal.h" -#include "regi2c_ctrl.h" +#include "hal/clk_tree_ll.h" +#include "hal/regi2c_ctrl_ll.h" #include "esp_hw_log.h" #include "sdkconfig.h" -#include "rtc_clk_common.h" /* Number of 8M/256 clock cycles to use for XTAL frequency estimation. * 10 cycles will take approximately 300 microseconds. @@ -27,6 +26,7 @@ #define XTAL_FREQ_EST_CYCLES 10 static rtc_xtal_freq_t rtc_clk_xtal_freq_estimate(void); +extern void rtc_clk_cpu_freq_to_xtal(int freq, int div); static const char* TAG = "rtc_clk_init"; @@ -43,7 +43,7 @@ void rtc_clk_init(rtc_clk_config_t cfg) * PLL is configured for 480M, but it takes less time to switch to 40M and * run the following code than querying the PLL does. */ - if (REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL) == RTC_CNTL_SOC_CLK_SEL_PLL) { + if (clk_ll_cpu_get_src() == SOC_CPU_CLK_SRC_PLL) { /* We don't know actual XTAL frequency yet, assume 40MHz. * REF_TICK divider will be corrected below, once XTAL frequency is * determined. @@ -63,18 +63,22 @@ void rtc_clk_init(rtc_clk_config_t cfg) REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, cfg.clk_8m_dfreq); /* Configure 8M clock division */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, cfg.clk_8m_div); + clk_ll_rc_fast_set_divider(cfg.clk_8m_div + 1); + /* Reset (disable) i2c internal bus for all regi2c registers */ + regi2c_ctrl_ll_i2c_reset(); // TODO: This should be move out from rtc_clk_init /* Enable the internal bus used to configure PLLs */ - SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_APLL_M | I2C_BBPLL_M); + regi2c_ctrl_ll_i2c_bbpll_enable(); // TODO: This should be moved to bbpll_set_config + regi2c_ctrl_ll_i2c_apll_enable(); // TODO: This should be moved to apll_set_config /* Estimate XTAL frequency */ - rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; - if (xtal_freq == RTC_XTAL_FREQ_AUTO) { - if (clk_val_is_valid(READ_PERI_REG(RTC_XTAL_FREQ_REG))) { + rtc_xtal_freq_t configured_xtal_freq = cfg.xtal_freq; + rtc_xtal_freq_t stored_xtal_freq = rtc_clk_xtal_freq_get(); // read the xtal freq value from RTC storage register + rtc_xtal_freq_t xtal_freq = configured_xtal_freq; + if (configured_xtal_freq == RTC_XTAL_FREQ_AUTO) { + if (stored_xtal_freq != RTC_XTAL_FREQ_AUTO) { /* XTAL frequency has already been set, use existing value */ - xtal_freq = rtc_clk_xtal_freq_get(); + xtal_freq = stored_xtal_freq; } else { /* Not set yet, estimate XTAL frequency based on RTC_FAST_CLK */ xtal_freq = rtc_clk_xtal_freq_estimate(); @@ -83,16 +87,16 @@ void rtc_clk_init(rtc_clk_config_t cfg) xtal_freq = RTC_XTAL_FREQ_26M; } } - } else if (!clk_val_is_valid(READ_PERI_REG(RTC_XTAL_FREQ_REG))) { + } else if (stored_xtal_freq == RTC_XTAL_FREQ_AUTO) { /* Exact frequency was set in sdkconfig, but still warn if autodetected * frequency is different. If autodetection failed, worst case we get a * bit of garbage output. */ rtc_xtal_freq_t est_xtal_freq = rtc_clk_xtal_freq_estimate(); - if (est_xtal_freq != xtal_freq) { + if (est_xtal_freq != configured_xtal_freq) { ESP_HW_LOGW(TAG, "Possibly invalid CONFIG_ESP32_XTAL_FREQ setting (%dMHz). Detected %d MHz.", - xtal_freq, est_xtal_freq); + configured_xtal_freq, est_xtal_freq); } } esp_rom_uart_tx_wait_idle(0); @@ -112,8 +116,10 @@ void rtc_clk_init(rtc_clk_config_t cfg) rtc_clk_cpu_freq_set_config(&new_config); /* Configure REF_TICK */ - REG_WRITE(SYSCON_XTAL_TICK_CONF_REG, xtal_freq - 1); - REG_WRITE(SYSCON_PLL_TICK_CONF_REG, APB_CLK_FREQ / MHZ - 1); /* Under PLL, APB frequency is always 80MHz */ + // Initialize it in the bootloader stage, but it is not a must to do here + // REF_TICK divider value always gets updated when switching cpu clock source + clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_XTAL, xtal_freq); + clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_PLL, new_config.freq_mhz); /* Re-calculate the ccount to make time calculation correct. */ cpu_hal_set_cycle_count( (uint64_t)cpu_hal_get_cycle_count() * cfg.cpu_freq_mhz / freq_before ); diff --git a/components/esp_hw_support/port/esp32/rtc_time.c b/components/esp_hw_support/port/esp32/rtc_time.c index 76e5017656..777b5a9a4d 100644 --- a/components/esp_hw_support/port/esp32/rtc_time.c +++ b/components/esp_hw_support/port/esp32/rtc_time.c @@ -6,12 +6,11 @@ #include #include "esp_rom_sys.h" +#include "hal/clk_tree_ll.h" #include "soc/rtc.h" #include "soc/timer_periph.h" #include "esp_hw_log.h" -#define MHZ (1000000) - static const char* TAG = "rtc_time"; /* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0. @@ -36,13 +35,13 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc { assert(slowclk_cycles < 32767); /* Enable requested clock (150k clock is always on) */ - int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); - if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); + bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { + clk_ll_xtal32k_digi_enable(); } if (cal_clk == RTC_CAL_8MD256) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_enable(); } /* Prepare calibration */ REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk); @@ -88,10 +87,13 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc esp_rom_delay_us(1); } - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); + /* 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) { + clk_ll_xtal32k_digi_disable(); + } if (cal_clk == RTC_CAL_8MD256) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_disable(); } if (timeout_us == 0) { /* timed out waiting for calibration */ @@ -139,7 +141,7 @@ uint64_t rtc_time_get(void) while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) { esp_rom_delay_us(1); // might take 1 RTC slowclk period, don't flood RTC bus if (attempts) { - if (--attempts == 0 && REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN)) { + if (--attempts == 0 && clk_ll_xtal32k_digi_is_enabled()) { ESP_HW_LOGE(TAG, "rtc_time_get() 32kHz xtal has been stopped"); } } @@ -165,7 +167,7 @@ void rtc_clk_wait_for_slow_cycle(void) while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) { esp_rom_delay_us(1); if (attempts) { - if (--attempts == 0 && REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN)) { + if (--attempts == 0 && clk_ll_xtal32k_digi_is_enabled()) { ESP_HW_LOGE(TAG, "32kHz xtal has been stopped"); } } diff --git a/components/esp_hw_support/port/esp32c2/rtc_clk.c b/components/esp_hw_support/port/esp32c2/rtc_clk.c index 12474d7f45..4d1064c1d9 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c2/rtc_clk.c @@ -15,80 +15,75 @@ #include "esp32c2/rom/uart.h" #include "esp32c2/rom/gpio.h" #include "soc/rtc.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/efuse_reg.h" -#include "soc/syscon_reg.h" -#include "soc/system_reg.h" +#include "hal/gpio_ll.h" #include "soc/io_mux_reg.h" #include "soc/soc.h" -#include "regi2c_ctrl.h" -#include "regi2c_bbpll.h" #include "esp_hw_log.h" -#include "rtc_clk_common.h" #include "esp_rom_sys.h" +#include "hal/clk_tree_ll.h" +#include "hal/regi2c_ctrl_ll.h" static const char *TAG = "rtc_clk"; -#define RTC_PLL_FREQ_480M 480 -#define DELAY_RTC_CLK_SWITCH 5 - -// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. +// Current PLL frequency, in 480MHZ. Zero if PLL is not enabled. static int s_cur_pll_freq; +static void rtc_clk_cpu_freq_to_xtal(int freq, int div); static void rtc_clk_cpu_freq_to_8m(void); void rtc_clk_32k_enable_external(void) { - REG_SET_BIT(PERIPHS_IO_MUX_XTAL_32K_P_U, FUN_IE); - REG_SET_BIT(RTC_CNTL_PAD_HOLD_REG, RTC_CNTL_GPIO_PIN0_HOLD); + gpio_ll_input_enable(&GPIO, EXT_OSC_SLOW_GPIO_NUM); + gpio_ll_hold_en(&GPIO, EXT_OSC_SLOW_GPIO_NUM); } void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en) { if (clk_8m_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); - esp_rom_delay_us(DELAY_8M_ENABLE); + clk_ll_rc_fast_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); + clk_ll_rc_fast_disable(); } /* d256 should be independent configured with 8M * Maybe we can split this function into 8m and dmd256 */ if (d256_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_enable(); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_disable(); } } bool rtc_clk_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; + return clk_ll_rc_fast_is_enabled(); } bool rtc_clk_8md256_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; + return clk_ll_rc_fast_d256_is_enabled(); } -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq) +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); + clk_ll_rtc_slow_set_src(clk_src); /* Why we need to connect this clock to digital? * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead? */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, - (slow_freq == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) ? 1 : 0); + if (clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + clk_ll_xtal32k_digi_enable(); + } else { + clk_ll_xtal32k_digi_disable(); + } - esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH); + esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + return clk_ll_rtc_slow_get_src(); } uint32_t rtc_clk_slow_freq_get_hz(void) @@ -97,60 +92,39 @@ uint32_t rtc_clk_slow_freq_get_hz(void) case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX; case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: return SOC_CLK_OSC_SLOW_FREQ_APPROX; case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: return 0; } - return 0; } -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq) +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq); - esp_rom_delay_us(DELAY_FAST_CLK_SWITCH); + 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) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + return clk_ll_rtc_fast_get_src(); } static void rtc_clk_bbpll_disable(void) { - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + clk_ll_bbpll_disable(); s_cur_pll_freq = 0; } static void rtc_clk_bbpll_enable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + clk_ll_bbpll_enable(); } -void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) +static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) { - (void) xtal_freq; - // ESP32-C2 only support 40M XTAL, all the parameters are given as 40M XTAL directly. - uint8_t div_ref = 0; - uint8_t div7_0 = 8; - uint8_t dr1 = 0; - uint8_t dr3 = 0; - uint8_t dchgp = 5; - uint8_t dcur = 3; - uint8_t dbias = 2; - - CLEAR_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); - SET_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); - /* Set this register to let the digital part know 480M PLL is used */ - SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); - 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_VCO_DBIAS, dbias); + /* Digital part */ + clk_ll_bbpll_set_freq_mhz(pll_freq); + /* Analog part */ + regi2c_ctrl_ll_bbpll_calibration_start(); + clk_ll_bbpll_set_config(pll_freq, xtal_freq); s_cur_pll_freq = pll_freq; } @@ -162,18 +136,9 @@ void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { - int per_conf = DPORT_CPUPERIOD_SEL_80; - if (cpu_freq_mhz == 80) { - /* nothing to do */ - } else if (cpu_freq_mhz == 120) { - per_conf = DPORT_CPUPERIOD_SEL_120; - } else { - ESP_HW_LOGE(TAG, "invalid frequency"); - abort(); - } - REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL); + clk_ll_cpu_set_freq_mhz_from_pll(cpu_freq_mhz); + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); rtc_clk_apb_freq_update(40 * MHZ); ets_update_cpu_frequency(cpu_freq_mhz); } @@ -185,7 +150,7 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou uint32_t divider; uint32_t real_freq_mhz; - uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get(); + uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get(); if (freq_mhz <= xtal_freq && freq_mhz != 0) { divider = xtal_freq / freq_mhz; real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */ @@ -199,12 +164,12 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou } else if (freq_mhz == 80) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + 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 = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 4; } else { // unsupported frequency @@ -221,21 +186,21 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) { - uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); + 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 (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { + if (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) { rtc_clk_bbpll_disable(); } } else if (config->source == SOC_CPU_CLK_SRC_PLL) { - if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL) { + if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) { rtc_clk_bbpll_enable(); rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); } rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); - if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { + if (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) { rtc_clk_bbpll_disable(); } } @@ -243,38 +208,32 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) { - soc_cpu_clk_src_t source; + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); uint32_t source_freq_mhz; uint32_t div; uint32_t freq_mhz; - uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); - switch (soc_clk_sel) { - case DPORT_SOC_CLK_SEL_XTAL: { - source = SOC_CPU_CLK_SRC_XTAL; - div = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; - source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); freq_mhz = source_freq_mhz / div; } break; - case DPORT_SOC_CLK_SEL_PLL: { - source = SOC_CPU_CLK_SRC_PLL; - uint32_t cpuperiod_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL); - source_freq_mhz = RTC_PLL_FREQ_480M; // PLL clock on ESP32-C2 was fixed to 480MHz - if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_80) { + case SOC_CPU_CLK_SRC_PLL: { + freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll(); + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; // PLL clock on ESP32-C2 was fixed to 480MHz + if (freq_mhz == CLK_LL_PLL_80M_FREQ_MHZ) { div = 6; - freq_mhz = 80; - } else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_120) { + } else if (freq_mhz == CLK_LL_PLL_120M_FREQ_MHZ) { div = 4; - freq_mhz = 120; } else { ESP_HW_LOGE(TAG, "unsupported frequency configuration"); abort(); } break; } - case DPORT_SOC_CLK_SEL_8M: - source = SOC_CPU_CLK_SRC_RC_FAST; - source_freq_mhz = 8; + case SOC_CPU_CLK_SRC_RC_FAST: + source_freq_mhz = 20; div = 1; freq_mhz = source_freq_mhz; break; @@ -305,7 +264,7 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { - int freq_mhz = (int) rtc_clk_xtal_freq_get(); + int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); rtc_clk_bbpll_disable(); @@ -314,84 +273,75 @@ void rtc_clk_cpu_freq_set_xtal(void) /** * Switch to XTAL frequency. Does not disable the PLL. */ -void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, div - 1); - /* no need to adjust the REF_TICK */ + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_divider(div); /* switch clock source */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); rtc_clk_apb_freq_update(freq * MHZ); } static void rtc_clk_cpu_freq_to_8m(void) { - ets_update_cpu_frequency(8); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M); + ets_update_cpu_frequency(20); + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX); } rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) { - uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); - if (!clk_val_is_valid(xtal_freq_reg)) { - ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg); + uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz(); + if (xtal_freq_mhz == 0) { + ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz"); return RTC_XTAL_FREQ_40M; } - return reg_val_to_clk_val(xtal_freq_reg); + return (rtc_xtal_freq_t)xtal_freq_mhz; } void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq) { - WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq)); + clk_ll_xtal_store_freq_mhz(xtal_freq); } void rtc_clk_apb_freq_update(uint32_t apb_freq) { - WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12)); + clk_ll_apb_store_freq_hz(apb_freq); } uint32_t rtc_clk_apb_freq_get(void) { - uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12; - // round to the nearest MHz - freq_hz += MHZ / 2; - uint32_t remainder = freq_hz % MHZ; - return freq_hz - remainder; + return clk_ll_apb_load_freq_hz(); } void rtc_clk_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); - REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div); - SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + clk_ll_rc_slow_set_divider(div + 1); } void rtc_clk_8m_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div); - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + clk_ll_rc_fast_set_divider(div + 1); } void rtc_dig_clk8m_enable(void) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } void rtc_dig_clk8m_disable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_disable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } bool rtc_dig_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + return clk_ll_rc_fast_digi_is_enabled(); } /* Name used in libphy.a:phy_chip_v7.o diff --git a/components/esp_hw_support/port/esp32c2/rtc_clk_common.h b/components/esp_hw_support/port/esp32c2/rtc_clk_common.h deleted file mode 100644 index 7311d32c17..0000000000 --- a/components/esp_hw_support/port/esp32c2/rtc_clk_common.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#define MHZ (1000000) - -#define DPORT_CPUPERIOD_SEL_80 0 -#define DPORT_CPUPERIOD_SEL_120 1 - -#define DPORT_SOC_CLK_SEL_XTAL 0 -#define DPORT_SOC_CLK_SEL_PLL 1 -#define DPORT_SOC_CLK_SEL_8M 2 - -#ifdef __cplusplus -extern "C" { -#endif - -void rtc_clk_cpu_freq_to_xtal(int freq, int div); - -/* Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in - * lower and upper 16-bit halves. These are the routines to work with such a - * representation. - */ -static inline bool clk_val_is_valid(uint32_t val) -{ - return (val & 0xffff) == ((val >> 16) & 0xffff) && - val != 0 && - val != UINT32_MAX; -} - -static inline uint32_t reg_val_to_clk_val(uint32_t val) -{ - return val & UINT16_MAX; -} - -static inline uint32_t clk_val_to_reg_val(uint32_t val) -{ - return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_hw_support/port/esp32c2/rtc_clk_init.c b/components/esp_hw_support/port/esp32c2/rtc_clk_init.c index ef48528415..bc3eac0d2a 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32c2/rtc_clk_init.c @@ -15,10 +15,9 @@ #include "soc/rtc_periph.h" #include "soc/efuse_periph.h" #include "hal/cpu_hal.h" -#include "regi2c_ctrl.h" +#include "hal/regi2c_ctrl_ll.h" #include "esp_hw_log.h" #include "sdkconfig.h" -#include "rtc_clk_common.h" #include "esp_rom_uart.h" static const char *TAG = "rtc_clk_init"; @@ -44,9 +43,10 @@ void rtc_clk_init(rtc_clk_config_t cfg) /* Configure 8M clock division */ rtc_clk_8m_divider_set(cfg.clk_8m_clk_div); - /* Enable the internal bus used to configure PLLs */ - SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_BBPLL_M); + /* Reset (disable) i2c internal bus for all regi2c registers */ + regi2c_ctrl_ll_i2c_reset(); // TODO: This should be move out from rtc_clk_init + /* Enable the internal bus used to configure BBPLL */ + regi2c_ctrl_ll_i2c_bbpll_enable(); // TODO: This should be moved to bbpll_set_config rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; esp_rom_uart_tx_wait_idle(0); @@ -66,7 +66,7 @@ void rtc_clk_init(rtc_clk_config_t cfg) /* Re-calculate the ccount to make time calculation correct. */ cpu_hal_set_cycle_count( (uint64_t)cpu_hal_get_cycle_count() * cfg.cpu_freq_mhz / freq_before ); - /* fast clocks setup */ + /* Slow & fast clocks setup */ if (cfg.fast_clk_src == SOC_RTC_FAST_CLK_SRC_RC_FAST) { bool need_8md256 = cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256; rtc_clk_8m_enable(true, need_8md256); diff --git a/components/esp_hw_support/port/esp32c2/rtc_time.c b/components/esp_hw_support/port/esp32c2/rtc_time.c index 206d9f7365..a48a7af301 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_time.c +++ b/components/esp_hw_support/port/esp32c2/rtc_time.c @@ -8,6 +8,7 @@ #include "esp32c2/rom/ets_sys.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "hal/clk_tree_ll.h" #include "soc/timer_group_reg.h" #include "esp_rom_sys.h" @@ -45,13 +46,13 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } } /* Enable requested clock (150k clock is always on) */ - int dig_ext_clk_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); - if (cal_clk == RTC_CAL_EXT_CLK && !dig_ext_clk_state) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); + bool dig_ext_clk_enabled = clk_ll_xtal32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_EXT_CLK && !dig_ext_clk_enabled) { + clk_ll_xtal32k_digi_enable(); } if (cal_clk == RTC_CAL_8MD256) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_enable(); } /* Prepare calibration */ REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk); @@ -99,10 +100,13 @@ 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); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_ext_clk_state); + /* if dig_ext_clk was originally off and enabled due to calibration, then set back to off state */ + if (cal_clk == RTC_CAL_EXT_CLK && !dig_ext_clk_enabled) { + clk_ll_xtal32k_digi_disable(); + } if (cal_clk == RTC_CAL_8MD256) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_disable(); } return cal_val; diff --git a/components/esp_hw_support/port/esp32c3/rtc_clk.c b/components/esp_hw_support/port/esp32c3/rtc_clk.c index dea9f93d8d..ff3930a460 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c3/rtc_clk.c @@ -12,57 +12,34 @@ #include "sdkconfig.h" #include "esp32c3/rom/ets_sys.h" #include "esp32c3/rom/rtc.h" -#include "esp32c3/rom/uart.h" -#include "esp32c3/rom/gpio.h" #include "soc/rtc.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/efuse_reg.h" -#include "soc/syscon_reg.h" -#include "soc/system_reg.h" -#include "regi2c_ctrl.h" -#include "regi2c_bbpll.h" #include "esp_hw_log.h" -#include "rtc_clk_common.h" #include "esp_rom_sys.h" #include "hal/usb_serial_jtag_ll.h" +#include "hal/clk_tree_ll.h" +#include "hal/regi2c_ctrl_ll.h" static const char *TAG = "rtc_clk"; -#define RTC_PLL_FREQ_320M 320 -#define RTC_PLL_FREQ_480M 480 -#define DELAY_RTC_CLK_SWITCH 5 - // Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. static int s_cur_pll_freq; +static void rtc_clk_cpu_freq_to_xtal(int freq, int div); static void rtc_clk_cpu_freq_to_8m(void); static bool rtc_clk_set_bbpll_always_on(void); -void rtc_clk_32k_enable_internal(x32k_config_t cfg) -{ - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf); - SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); -} - void rtc_clk_32k_enable(bool enable) { if (enable) { - x32k_config_t cfg = X32K_CONFIG_DEFAULT(); - rtc_clk_32k_enable_internal(cfg); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL); } else { - SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE); - CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + clk_ll_xtal32k_disable(); } } void rtc_clk_32k_enable_external(void) { - /* TODO ESP32-C3 IDF-2408: external 32k source may need different settings */ - x32k_config_t cfg = X32K_CONFIG_DEFAULT(); - rtc_clk_32k_enable_internal(cfg); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL); } void rtc_clk_32k_bootstrap(uint32_t cycle) @@ -70,67 +47,62 @@ void rtc_clk_32k_bootstrap(uint32_t cycle) /* No special bootstrapping needed for ESP32-C3, 'cycle' argument is to keep the signature * same as for the ESP32. Just enable the XTAL here. */ - (void) cycle; + (void)cycle; rtc_clk_32k_enable(true); } bool rtc_clk_32k_enabled(void) { - uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG); - /* If xtal xpd is controlled by software */ - bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S; - /* If xtal xpd software control is on */ - bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S; - bool disabled = xtal_xpd_sw && !xtal_xpd_st; - return !disabled; + return clk_ll_xtal32k_is_enabled(); } void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en) { if (clk_8m_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); - esp_rom_delay_us(DELAY_8M_ENABLE); + clk_ll_rc_fast_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); + clk_ll_rc_fast_disable(); } /* d256 should be independent configured with 8M * Maybe we can split this function into 8m and dmd256 */ if (d256_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_enable(); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_disable(); } } bool rtc_clk_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; + return clk_ll_rc_fast_is_enabled(); } bool rtc_clk_8md256_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; + return clk_ll_rc_fast_d256_is_enabled(); } -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq) +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); + clk_ll_rtc_slow_set_src(clk_src); /* Why we need to connect this clock to digital? * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead? */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, - (slow_freq == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? 1 : 0); + if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + clk_ll_xtal32k_digi_enable(); + } else { + clk_ll_xtal32k_digi_disable(); + } - esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH); + esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + return clk_ll_rtc_slow_get_src(); } uint32_t rtc_clk_slow_freq_get_hz(void) @@ -139,126 +111,39 @@ uint32_t rtc_clk_slow_freq_get_hz(void) 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_RC_FAST_D256: return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: return 0; } - return 0; } -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq) +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq); - esp_rom_delay_us(DELAY_FAST_CLK_SWITCH); + 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) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + return clk_ll_rtc_fast_get_src(); } static void rtc_clk_bbpll_disable(void) { - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + clk_ll_bbpll_disable(); s_cur_pll_freq = 0; } static void rtc_clk_bbpll_enable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + clk_ll_bbpll_enable(); } -void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) +static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) { - uint8_t div_ref; - uint8_t div7_0; - uint8_t dr1; - uint8_t dr3; - uint8_t dchgp; - uint8_t dcur; - uint8_t dbias; - - CLEAR_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); - SET_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); - if (pll_freq == RTC_PLL_FREQ_480M) { - /* Set this register to let the digital part know 480M PLL is used */ - SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); - /* Configure 480M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 8; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - case RTC_XTAL_FREQ_32M: - div_ref = 1; - div7_0 = 26; - dr1 = 1; - dr3 = 1; - dchgp = 4; - dcur = 0; - dbias = 2; - break; - default: - div_ref = 0; - div7_0 = 8; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); - } else { - /* Clear this register to let the digital part know 320M PLL is used */ - CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); - /* Configure 320M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 4; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - case RTC_XTAL_FREQ_32M: - div_ref = 1; - div7_0 = 6; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - default: - div_ref = 0; - div7_0 = 4; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69); - } - 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 = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (1 << 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_VCO_DBIAS, dbias); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 2); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1); + /* Digital part */ + clk_ll_bbpll_set_freq_mhz(pll_freq); + /* Analog part */ + regi2c_ctrl_ll_bbpll_calibration_start(); + clk_ll_bbpll_set_config(pll_freq, xtal_freq); s_cur_pll_freq = pll_freq; } @@ -270,18 +155,9 @@ void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { - int per_conf = DPORT_CPUPERIOD_SEL_80; - if (cpu_freq_mhz == 80) { - /* nothing to do */ - } else if (cpu_freq_mhz == 160) { - per_conf = DPORT_CPUPERIOD_SEL_160; - } else { - ESP_HW_LOGE(TAG, "invalid frequency"); - abort(); - } - REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL); + clk_ll_cpu_set_freq_mhz_from_pll(cpu_freq_mhz); + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); rtc_clk_apb_freq_update(80 * MHZ); ets_update_cpu_frequency(cpu_freq_mhz); } @@ -293,7 +169,7 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou uint32_t divider; uint32_t real_freq_mhz; - uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get(); + uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get(); if (freq_mhz <= xtal_freq && freq_mhz != 0) { divider = xtal_freq / freq_mhz; real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */ @@ -307,12 +183,12 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou } else if (freq_mhz == 80) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 6; } else if (freq_mhz == 160) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 3; } else { // unsupported frequency @@ -329,22 +205,22 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) { - uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); + 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 ((soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) && !rtc_clk_set_bbpll_always_on()) { + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { // We don't turn off the bbpll if some consumers only depends on bbpll rtc_clk_bbpll_disable(); } } else if (config->source == SOC_CPU_CLK_SRC_PLL) { - if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL) { + if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) { rtc_clk_bbpll_enable(); rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); } rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); - if ((soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) && !rtc_clk_set_bbpll_always_on()) { + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { // We don't turn off the bbpll if some consumers only depends on bbpll rtc_clk_bbpll_disable(); } @@ -353,40 +229,32 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) { - soc_cpu_clk_src_t source; + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); uint32_t source_freq_mhz; uint32_t div; uint32_t freq_mhz; - uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); - switch (soc_clk_sel) { - case DPORT_SOC_CLK_SEL_XTAL: { - source = SOC_CPU_CLK_SRC_XTAL; - div = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; - source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); freq_mhz = source_freq_mhz / div; } break; - case DPORT_SOC_CLK_SEL_PLL: { - source = SOC_CPU_CLK_SRC_PLL; - uint32_t cpuperiod_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL); - uint32_t pllfreq_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); - source_freq_mhz = (pllfreq_sel) ? RTC_PLL_FREQ_480M : RTC_PLL_FREQ_320M; - if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_80) { - div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 6 : 4; - freq_mhz = 80; - } else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_160) { - div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 3 : 2; - div = 3; - freq_mhz = 160; + case SOC_CPU_CLK_SRC_PLL: { + freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll(); + source_freq_mhz = clk_ll_bbpll_get_freq_mhz(); + if (freq_mhz == CLK_LL_PLL_80M_FREQ_MHZ) { + div = (source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) ? 6 : 4; + } else if (freq_mhz == CLK_LL_PLL_160M_FREQ_MHZ) { + div = (source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) ? 3 : 2; } else { ESP_HW_LOGE(TAG, "unsupported frequency configuration"); abort(); } break; } - case DPORT_SOC_CLK_SEL_8M: - source = SOC_CPU_CLK_SRC_RC_FAST; - source_freq_mhz = 8; + case SOC_CPU_CLK_SRC_RC_FAST: + source_freq_mhz = 20; div = 1; freq_mhz = source_freq_mhz; break; @@ -417,7 +285,7 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { - int freq_mhz = (int) rtc_clk_xtal_freq_get(); + int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); // We don't turn off the bbpll if some consumers only depends on bbpll @@ -429,84 +297,75 @@ void rtc_clk_cpu_freq_set_xtal(void) /** * Switch to XTAL frequency. Does not disable the PLL. */ -void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, div - 1); - /* no need to adjust the REF_TICK */ + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_divider(div); /* switch clock source */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); rtc_clk_apb_freq_update(freq * MHZ); } static void rtc_clk_cpu_freq_to_8m(void) { - ets_update_cpu_frequency(8); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M); + ets_update_cpu_frequency(20); + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX); } rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) { - uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); - if (!clk_val_is_valid(xtal_freq_reg)) { - ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg); + uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz(); + if (xtal_freq_mhz == 0) { + ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz"); return RTC_XTAL_FREQ_40M; } - return reg_val_to_clk_val(xtal_freq_reg); + return (rtc_xtal_freq_t)xtal_freq_mhz; } void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq) { - WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq)); + clk_ll_xtal_store_freq_mhz(xtal_freq); } void rtc_clk_apb_freq_update(uint32_t apb_freq) { - WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12)); + clk_ll_apb_store_freq_hz(apb_freq); } uint32_t rtc_clk_apb_freq_get(void) { - uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12; - // round to the nearest MHz - freq_hz += MHZ / 2; - uint32_t remainder = freq_hz % MHZ; - return freq_hz - remainder; + return clk_ll_apb_load_freq_hz(); } void rtc_clk_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); - REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div); - SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + clk_ll_rc_slow_set_divider(div + 1); } void rtc_clk_8m_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div); - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + clk_ll_rc_fast_set_divider(div + 1); } void rtc_dig_clk8m_enable(void) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } void rtc_dig_clk8m_disable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_disable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } bool rtc_dig_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + return clk_ll_rc_fast_digi_is_enabled(); } static bool rtc_clk_set_bbpll_always_on(void) diff --git a/components/esp_hw_support/port/esp32c3/rtc_clk_common.h b/components/esp_hw_support/port/esp32c3/rtc_clk_common.h deleted file mode 100644 index 44f6e2b7c4..0000000000 --- a/components/esp_hw_support/port/esp32c3/rtc_clk_common.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#define MHZ (1000000) - -#define DPORT_CPUPERIOD_SEL_80 0 -#define DPORT_CPUPERIOD_SEL_160 1 - -#define DPORT_SOC_CLK_SEL_XTAL 0 -#define DPORT_SOC_CLK_SEL_PLL 1 -#define DPORT_SOC_CLK_SEL_8M 2 - -#ifdef __cplusplus -extern "C" { -#endif - -void rtc_clk_cpu_freq_to_xtal(int freq, int div); - -/* Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in - * lower and upper 16-bit halves. These are the routines to work with such a - * representation. - */ -static inline bool clk_val_is_valid(uint32_t val) -{ - return (val & 0xffff) == ((val >> 16) & 0xffff) && - val != 0 && - val != UINT32_MAX; -} - -static inline uint32_t reg_val_to_clk_val(uint32_t val) -{ - return val & UINT16_MAX; -} - -static inline uint32_t clk_val_to_reg_val(uint32_t val) -{ - return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_hw_support/port/esp32c3/rtc_clk_init.c b/components/esp_hw_support/port/esp32c3/rtc_clk_init.c index 32eeb79424..68687ba005 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32c3/rtc_clk_init.c @@ -14,12 +14,10 @@ #include "soc/rtc.h" #include "soc/rtc_periph.h" #include "soc/efuse_periph.h" -#include "soc/syscon_reg.h" #include "hal/cpu_hal.h" -#include "regi2c_ctrl.h" +#include "hal/regi2c_ctrl_ll.h" #include "esp_hw_log.h" #include "sdkconfig.h" -#include "rtc_clk_common.h" #include "esp_rom_uart.h" static const char *TAG = "rtc_clk_init"; @@ -45,9 +43,10 @@ void rtc_clk_init(rtc_clk_config_t cfg) /* Configure 8M clock division */ rtc_clk_8m_divider_set(cfg.clk_8m_clk_div); - /* Enable the internal bus used to configure PLLs */ - SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_BBPLL_M); + /* Reset (disable) i2c internal bus for all regi2c registers */ + regi2c_ctrl_ll_i2c_reset(); // TODO: This should be move out from rtc_clk_init + /* Enable the internal bus used to configure BBPLL */ + regi2c_ctrl_ll_i2c_bbpll_enable(); // TODO: This should be moved to bbpll_set_config rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; esp_rom_uart_tx_wait_idle(0); diff --git a/components/esp_hw_support/port/esp32c3/rtc_time.c b/components/esp_hw_support/port/esp32c3/rtc_time.c index 31a29098bf..22ef6169bf 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_time.c +++ b/components/esp_hw_support/port/esp32c3/rtc_time.c @@ -8,6 +8,7 @@ #include "esp32c3/rom/ets_sys.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "hal/clk_tree_ll.h" #include "soc/timer_group_reg.h" #include "esp_rom_sys.h" @@ -49,13 +50,13 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) /* Enable requested clock (150k clock is always on) */ - int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); - if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); + bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { + clk_ll_xtal32k_digi_enable(); } if (cal_clk == RTC_CAL_8MD256) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_enable(); } /* There may be another calibration process already running during we call this function, * so we should wait the last process is done. @@ -108,10 +109,13 @@ 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); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); + /* 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) { + clk_ll_xtal32k_digi_disable(); + } if (cal_clk == RTC_CAL_8MD256) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_disable(); } return cal_val; diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk.c b/components/esp_hw_support/port/esp32h2/rtc_clk.c index 83aed1de4c..801ccca5c9 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk.c @@ -15,70 +15,48 @@ #include "esp32h2/rom/uart.h" #include "esp32h2/rom/gpio.h" #include "soc/rtc.h" -#include "i2c_bbpll.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/efuse_reg.h" -#include "soc/syscon_reg.h" -#include "soc/system_reg.h" -#include "regi2c_ctrl.h" +#include "soc/io_mux_reg.h" +#include "hal/clk_tree_ll.h" +#include "hal/regi2c_ctrl_ll.h" +#include "hal/gpio_ll.h" #include "esp_hw_log.h" -#include "rtc_clk_common.h" #include "esp_rom_sys.h" static const char *TAG = "rtc_clk"; -#define RTC_PLL_FREQ_96M 96 #define RTC_OSC_FREQ_RC8M 8 -#define DELAY_RTC_CLK_SWITCH 5 -#define RTC_CNTL_ANA_CONF0_CAL_REG 0x6000e040 -#define RTC_CNTL_ANA_CONF0_CAL_START BIT(2) -#define RTC_CNTL_ANA_CONF0_CAL_STOP BIT(3) -#define RTC_CNTL_ANA_CONF0_CAL_DONE BIT(24) // Current PLL frequency, in 96MHZ. Zero if PLL is not enabled. static int s_cur_pll_freq; +static uint32_t rtc_clk_ahb_freq_get(void); +static void rtc_clk_cpu_freq_to_xtal(int freq, int div); void rtc_clk_cpu_freq_to_8m(void); -static uint32_t rtc_clk_ahb_freq_set(uint32_t div); -void rtc_clk_32k_enable_internal(x32k_config_t cfg) +static void rtc_gpio_hangup(uint32_t gpio_no) { - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf); - SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + gpio_ll_pulldown_dis(&GPIO, gpio_no); + gpio_ll_pullup_dis(&GPIO, gpio_no); + gpio_ll_output_disable(&GPIO, gpio_no); + gpio_ll_input_disable(&GPIO, gpio_no); + gpio_ll_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_no], PIN_FUNC_GPIO); } void rtc_clk_32k_enable(bool enable) { if (enable) { - /* need to hangup gpio0 & 1 before enable xtal_32k */ - rtc_gpio_hangup(0); - rtc_gpio_hangup(1); - x32k_config_t cfg = X32K_CONFIG_DEFAULT(); - rtc_clk_32k_enable_internal(cfg); + /* need to hangup 32K_P and 32K_N pins before enable xtal_32k */ + rtc_gpio_hangup(XTAL32K_P_GPIO_NUM); + rtc_gpio_hangup(XTAL32K_N_GPIO_NUM); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL); } else { - SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE); - CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + clk_ll_xtal32k_disable(); } } -void rtc_clk_rc32k_dfreq(uint32_t dfreq) -{ - REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_DFREQ, dfreq); -} - -void rtc_clk_rc32k_enable(bool enable) -{ - rc32k_config_t cfg = RC32K_CONFIG_DEFAULT(); - rtc_clk_rc32k_dfreq(cfg.dfreq); - REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_XPD, enable); -} - void rtc_clk_32k_enable_external(void) { - rtc_clk_32k_enable(true); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL); } void rtc_clk_32k_bootstrap(uint32_t cycle) @@ -86,32 +64,35 @@ void rtc_clk_32k_bootstrap(uint32_t cycle) /* No special bootstrapping needed for ESP32-H2, 'cycle' argument is to keep the signature * same as for the ESP32. Just enable the XTAL here. */ - (void) cycle; + (void)cycle; rtc_clk_32k_enable(true); } bool rtc_clk_32k_enabled(void) { - uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG); - /* If xtal xpd is controlled by software */ - bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S; - /* If xtal xpd software control is on */ - bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S; - bool disabled = xtal_xpd_sw && !xtal_xpd_st; - return !disabled; + return clk_ll_xtal32k_is_enabled(); } -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq) +void rtc_clk_rc32k_enable(bool enable) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); - rtc_clk_32k_enable((slow_freq == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? 1 : 0); - rtc_clk_rc32k_enable((slow_freq == SOC_RTC_SLOW_CLK_SRC_RC32K) ? 1 : 0); - esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH); + if (enable) { + clk_ll_rc32k_enable(); + } else { + clk_ll_rc32k_disable(); + } +} + +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) +{ + clk_ll_rtc_slow_set_src(clk_src); + rtc_clk_32k_enable((clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? 1 : 0); + rtc_clk_rc32k_enable((clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) ? 1 : 0); + esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + return clk_ll_rtc_slow_get_src(); } uint32_t rtc_clk_slow_freq_get_hz(void) @@ -120,62 +101,86 @@ uint32_t rtc_clk_slow_freq_get_hz(void) 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; } - return 0; } -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq) +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq); - esp_rom_delay_us(DELAY_FAST_CLK_SWITCH); + 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) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + return clk_ll_rtc_fast_get_src(); } static void rtc_clk_bbpll_disable(void) { - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + clk_ll_bbpll_disable(); s_cur_pll_freq = 0; } static void rtc_clk_bbpll_enable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); -} -static void rtc_clk_bbpll_cali_stop(void) -{ - while (!REG_GET_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_DONE)); - REG_CLR_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_STOP); - REG_SET_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_START); - + clk_ll_bbpll_enable(); } -void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) +static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) { - uint8_t div_ref; - uint8_t div5_0; - if ((pll_freq == RTC_PLL_FREQ_96M) && (xtal_freq == RTC_XTAL_FREQ_32M)) { - /* Configure 96M PLL */ - div_ref = 0; - div5_0 = 1; - } else { - div_ref = 0; - div5_0 = 1; - ESP_HW_LOGE(TAG, "invalid pll frequency"); + if (!((pll_freq == CLK_LL_PLL_96M_FREQ_MHZ) && (xtal_freq == RTC_XTAL_FREQ_32M))) { + ESP_HW_LOGE(TAG, "invalid pll or xtal frequency"); } - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, div_ref); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DIV, div5_0); //I2C_BBPLL_OC_DIV_5_0 - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 3); // need update to 3 since s2 - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1); + // No digital part needs to be set, pll_freq can only be 96MHz + + // Configure analog part + regi2c_ctrl_ll_bbpll_calibration_start(); + clk_ll_bbpll_set_config(pll_freq, xtal_freq); + // Wait until calibration finishes + while (!regi2c_ctrl_ll_bbpll_calibration_is_done()); + // Prevent BBPLL clock jitter + regi2c_ctrl_ll_bbpll_calibration_stop(); s_cur_pll_freq = pll_freq; } +uint32_t rtc_clk_select_root_clk(soc_cpu_clk_src_t cpu_clk_src) +{ + uint32_t root_clk_freq_mhz; + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + root_clk_freq_mhz = RTC_XTAL_FREQ_32M; + rtc_clk_bbpll_disable(); + break; + case SOC_CPU_CLK_SRC_PLL: + // SPLL_ENABLE + root_clk_freq_mhz = CLK_LL_PLL_96M_FREQ_MHZ; + rtc_clk_bbpll_enable(); + rtc_clk_bbpll_configure(RTC_XTAL_FREQ_32M, root_clk_freq_mhz); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + root_clk_freq_mhz = RTC_OSC_FREQ_RC8M; + rtc_dig_clk8m_enable(); // TODO: Do we need to enable digital gating here? + rtc_clk_8m_divider_set(1); + rtc_clk_bbpll_disable(); + break; + case SOC_CPU_CLK_SRC_XTAL_D2: + root_clk_freq_mhz = RTC_XTAL_FREQ_32M / 2; + rtc_clk_bbpll_disable(); + break; + default: + ESP_HW_LOGE(TAG, "unsupported source clk configuration"); + // fallback to XTAL as root clock source + root_clk_freq_mhz = RTC_XTAL_FREQ_32M; + rtc_clk_bbpll_disable(); + cpu_clk_src = SOC_CPU_CLK_SRC_XTAL; + break; + } + clk_ll_cpu_set_src(cpu_clk_src); + return root_clk_freq_mhz; +} + /** * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL. * PLL must already be enabled. @@ -184,39 +189,40 @@ void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { int div = 1; - if (RTC_PLL_FREQ_96M % cpu_freq_mhz == 0) { - div = RTC_PLL_FREQ_96M / cpu_freq_mhz; + if (CLK_LL_PLL_96M_FREQ_MHZ % cpu_freq_mhz == 0) { + div = CLK_LL_PLL_96M_FREQ_MHZ / cpu_freq_mhz; } else { ESP_HW_LOGE(TAG, "invalid frequency"); abort(); } - rtc_clk_cpu_freq_set(DPORT_SOC_CLK_SEL_PLL, div - 1); + rtc_clk_cpu_freq_set(SOC_CPU_CLK_SRC_PLL, div); if (cpu_freq_mhz > RTC_XTAL_FREQ_32M) { - rtc_clk_ahb_freq_set(2); + clk_ll_ahb_set_divider(2); } else { - rtc_clk_ahb_freq_set(1); + clk_ll_ahb_set_divider(1); } - rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); ets_update_cpu_frequency(cpu_freq_mhz); + rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); } bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config) { + // TODO: This function supposes to only fill a cpu config, but it is writing to registers, needs to check uint32_t source_freq_mhz; soc_cpu_clk_src_t source; uint32_t divider; - uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get(); + uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get(); if (freq_mhz > xtal_freq) { source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_96M; - divider = RTC_PLL_FREQ_96M / freq_mhz; - rtc_clk_ahb_freq_set(2); + source_freq_mhz = CLK_LL_PLL_96M_FREQ_MHZ; + divider = CLK_LL_PLL_96M_FREQ_MHZ / freq_mhz; + clk_ll_ahb_set_divider(2); } else if (freq_mhz != 0) { - source = root_clk_get(); - source_freq_mhz = root_clk_slt(source); + source = clk_ll_cpu_get_src(); + source_freq_mhz = rtc_clk_select_root_clk(source); divider = source_freq_mhz / freq_mhz; - rtc_clk_ahb_freq_set(1); + clk_ll_ahb_set_divider(1); } else { // unsupported frequency return false; @@ -232,7 +238,7 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) { - uint32_t src_freq_mhz = root_clk_slt(config->source); + uint32_t src_freq_mhz = rtc_clk_select_root_clk(config->source); uint32_t div = src_freq_mhz / (config->freq_mhz); rtc_clk_cpu_freq_set(config->source, div); ets_update_cpu_frequency(config->freq_mhz); @@ -240,37 +246,32 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) { - soc_cpu_clk_src_t source; + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); uint32_t source_freq_mhz; uint32_t div; uint32_t freq_mhz; - uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); - switch (soc_clk_sel) { - case DPORT_SOC_CLK_SEL_XTAL: { - source = SOC_CPU_CLK_SRC_XTAL; - div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; - source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); freq_mhz = source_freq_mhz / div; break; } - case DPORT_SOC_CLK_SEL_PLL: { - source = SOC_CPU_CLK_SRC_PLL; - div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; - source_freq_mhz = RTC_PLL_FREQ_96M; + case SOC_CPU_CLK_SRC_PLL: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = CLK_LL_PLL_96M_FREQ_MHZ; freq_mhz = source_freq_mhz / div; break; } - case DPORT_SOC_CLK_SEL_8M: { - source = SOC_CPU_CLK_SRC_RC_FAST; + case SOC_CPU_CLK_SRC_RC_FAST: { source_freq_mhz = RTC_OSC_FREQ_RC8M; - div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; + div = clk_ll_cpu_get_divider(); freq_mhz = source_freq_mhz / div; break; } - case DPORT_SOC_CLK_SEL_XTAL_D2: { - source = SOC_CPU_CLK_SRC_XTAL_D2; - div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; - source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); + case SOC_CPU_CLK_SRC_XTAL_D2: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); freq_mhz = source_freq_mhz / div / 2; break; } @@ -302,7 +303,8 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { - int freq_mhz = (int) rtc_clk_xtal_freq_get(); + int freq_mhz = (int)rtc_clk_xtal_freq_get(); + rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); rtc_clk_bbpll_disable(); } @@ -310,11 +312,11 @@ void rtc_clk_cpu_freq_set_xtal(void) /** * Switch to XTAL frequency. Does not disable the PLL. */ -void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ - rtc_clk_cpu_freq_set(DPORT_SOC_CLK_SEL_XTAL, div); + rtc_clk_cpu_freq_set(SOC_CPU_CLK_SRC_XTAL, div); /* no need to adjust the REF_TICK */ /* switch clock source */ rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); @@ -323,148 +325,75 @@ void rtc_clk_cpu_freq_to_xtal(int freq, int div) void rtc_clk_cpu_freq_to_8m(void) { ets_update_cpu_frequency(RTC_OSC_FREQ_RC8M); - root_clk_slt(DPORT_SOC_CLK_SEL_8M); + rtc_clk_select_root_clk(SOC_CPU_CLK_SRC_RC_FAST); rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); } rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) { - uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); - if (!clk_val_is_valid(xtal_freq_reg)) { - ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg); + uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz(); + if (xtal_freq_mhz == 0) { + ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value, assume 32MHz"); return RTC_XTAL_FREQ_32M; } - return reg_val_to_clk_val(xtal_freq_reg); + return (rtc_xtal_freq_t)xtal_freq_mhz; } void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq) { - WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq)); + clk_ll_xtal_store_freq_mhz(xtal_freq); } void rtc_clk_apb_freq_update(uint32_t apb_freq) { - WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12)); + clk_ll_apb_store_freq_hz(apb_freq); } - uint32_t rtc_clk_apb_freq_get(void) { - uint32_t apb_div = REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM) + 1; - return rtc_clk_ahb_freq_get() / apb_div; + return rtc_clk_ahb_freq_get() / clk_ll_apb_get_divider(); } -uint32_t rtc_clk_ahb_freq_get() +static uint32_t rtc_clk_ahb_freq_get(void) { rtc_cpu_freq_config_t cpu_config; - uint32_t ahb_div = REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM) + 1; - rtc_clk_cpu_freq_get_config(&cpu_config) ; - return cpu_config.freq_mhz * MHZ / ahb_div; -} - -uint32_t rtc_clk_ahb_freq_set(uint32_t div) -{ - REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM, div - 1); - return rtc_clk_ahb_freq_get(); -} - -uint32_t rtc_clk_apb_freq_set(uint32_t div) -{ - REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM, div - 1); - return rtc_clk_apb_freq_get(); + rtc_clk_cpu_freq_get_config(&cpu_config); + return cpu_config.freq_mhz * MHZ / clk_ll_ahb_get_divider(); } void rtc_clk_cpu_freq_set(uint32_t source, uint32_t div) { - if (root_clk_get() != source) { - root_clk_slt(source); + if ((uint32_t)clk_ll_cpu_get_src() != source) { + rtc_clk_select_root_clk(source); } - REG_SET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_CPU_DIV_NUM, div - 1); + clk_ll_cpu_set_divider(div); } void rtc_clk_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); - REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div - 1); - SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + clk_ll_rc_slow_set_divider(div); } void rtc_clk_8m_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div - 1); - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + clk_ll_rc_fast_set_divider(div); } void rtc_dig_clk8m_enable(void) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } void rtc_dig_clk8m_disable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_disable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } bool rtc_dig_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); -} - -uint32_t read_spll_freq(void) -{ - return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SPLL_FREQ); -} - -uint32_t read_xtal_freq(void) -{ - return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_CLK_XTAL_FREQ); -} - -/* Select clock root source for esp32h2. return source clk freq_mhz - */ -uint32_t root_clk_slt(uint32_t source) -{ - uint32_t root_clk_freq_mhz; - switch (source) { - case SOC_CPU_CLK_SRC_XTAL: - root_clk_freq_mhz = RTC_XTAL_FREQ_32M; - rtc_clk_bbpll_disable(); - break; - case SOC_CPU_CLK_SRC_PLL: - // SPLL_ENABLE - root_clk_freq_mhz = RTC_PLL_FREQ_96M; - rtc_clk_bbpll_enable(); - rtc_clk_bbpll_configure(RTC_XTAL_FREQ_32M, root_clk_freq_mhz); - rtc_clk_bbpll_cali_stop(); - break; - case SOC_CPU_CLK_SRC_RC_FAST: - root_clk_freq_mhz = RTC_OSC_FREQ_RC8M; - rtc_dig_clk8m_enable(); - rtc_clk_8m_divider_set(1); - rtc_clk_bbpll_disable(); - break; - case SOC_CPU_CLK_SRC_XTAL_D2: - root_clk_freq_mhz = RTC_XTAL_FREQ_32M / 2; - rtc_clk_bbpll_disable(); - break; - default: - ESP_HW_LOGE(TAG, "unsupported source clk configuration"); - root_clk_freq_mhz = RTC_XTAL_FREQ_32M; - rtc_clk_bbpll_disable(); - source = 0; - break; - } - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, source); - return root_clk_freq_mhz; -} - -uint32_t root_clk_get() -{ - uint32_t src_slt = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); - return src_slt; + return clk_ll_rc_fast_digi_is_enabled(); } /* Name used in libphy.a:phy_chip_v7.o diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk_common.h b/components/esp_hw_support/port/esp32h2/rtc_clk_common.h deleted file mode 100644 index ea32098590..0000000000 --- a/components/esp_hw_support/port/esp32h2/rtc_clk_common.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#define MHZ (1000000) - -#define DPORT_CPUPERIOD_SEL_80 0 -#define DPORT_CPUPERIOD_SEL_160 1 - -#define DPORT_SOC_CLK_SEL_XTAL 0 -#define DPORT_SOC_CLK_SEL_PLL 1 -#define DPORT_SOC_CLK_SEL_8M 2 -#define DPORT_SOC_CLK_SEL_XTAL_D2 3 - -#ifdef __cplusplus -extern "C" { -#endif - -void rtc_clk_cpu_freq_to_xtal(int freq, int div); - -/* Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in - * lower and upper 16-bit halves. These are the routines to work with such a - * representation. - */ -static inline bool clk_val_is_valid(uint32_t val) -{ - return (val & 0xffff) == ((val >> 16) & 0xffff) && - val != 0 && - val != UINT32_MAX; -} - -static inline uint32_t reg_val_to_clk_val(uint32_t val) -{ - return val & UINT16_MAX; -} - -static inline uint32_t clk_val_to_reg_val(uint32_t val) -{ - return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk_init.c b/components/esp_hw_support/port/esp32h2/rtc_clk_init.c index f9efc1cdbc..0abfbdde96 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk_init.c @@ -17,18 +17,13 @@ #include "soc/rtc_periph.h" #include "soc/rtc_cntl_reg.h" #include "soc/efuse_periph.h" -#include "soc/syscon_reg.h" #include "hal/cpu_hal.h" -#include "regi2c_ctrl.h" #include "esp_hw_log.h" #include "sdkconfig.h" -#include "rtc_clk_common.h" #include "esp_rom_uart.h" -#include "soc/efuse_reg.h" -#include "soc/syscon_reg.h" #include "soc/system_reg.h" -#include "rtc_clk_common.h" #include "esp_rom_sys.h" + static const char *TAG = "rtc_clk_init"; void rtc_clk_init(rtc_clk_config_t cfg) @@ -68,7 +63,7 @@ void rtc_clk_init(rtc_clk_config_t cfg) rtc_clk_cpu_freq_get_config(&old_config); uint32_t freq_before = old_config.freq_mhz; - root_clk_slt(cfg.root_clk_slt); + rtc_clk_select_root_clk(cfg.root_clk_slt); 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"); diff --git a/components/esp_hw_support/port/esp32h2/rtc_init.c b/components/esp_hw_support/port/esp32h2/rtc_init.c index c7fc512a0e..975b5bf85e 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_init.c +++ b/components/esp_hw_support/port/esp32h2/rtc_init.c @@ -9,7 +9,6 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/io_mux_reg.h" #include "soc/efuse_periph.h" #include "soc/gpio_reg.h" #include "soc/spi_mem_reg.h" @@ -207,41 +206,3 @@ void rtc_vddsdio_set_config(rtc_vddsdio_config_t config) val |= RTC_CNTL_SDIO_PD_EN; REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val); } - -void dig_gpio_setpd(uint32_t gpio_no, bool pd) -{ - SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, 0x1, pd, FUN_PD_S); -} - -void dig_gpio_setpu(uint32_t gpio_no, bool pu) -{ - SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, 0x1, pu, FUN_PU_S); -} - -void dig_gpio_in_en(uint32_t gpio_no, bool enable) -{ - SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, 0x1, enable, FUN_IE_S); -} - -void dig_gpio_out_en(uint32_t gpio_no, bool enable) -{ - if (enable) - SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, 1 << gpio_no); - else - SET_PERI_REG_MASK(GPIO_ENABLE_W1TC_REG, 1 << gpio_no); -} - -void dig_gpio_mcusel(uint32_t gpio_no, uint32_t mcu_sel) -{ - SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, MCU_SEL, mcu_sel, MCU_SEL_S); -} - - -void rtc_gpio_hangup(uint32_t gpio_no) -{ - dig_gpio_setpd(gpio_no, 0); - dig_gpio_setpu(gpio_no, 0); - dig_gpio_out_en(gpio_no, 0); - dig_gpio_in_en(gpio_no, 0); - dig_gpio_mcusel(gpio_no, 1); -} diff --git a/components/esp_hw_support/port/esp32h2/rtc_time.c b/components/esp_hw_support/port/esp32h2/rtc_time.c index f9947fe327..6c817b6315 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_time.c +++ b/components/esp_hw_support/port/esp32h2/rtc_time.c @@ -8,6 +8,7 @@ #include "esp32h2/rom/ets_sys.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "hal/clk_tree_ll.h" #include "soc/timer_group_reg.h" #include "esp_rom_sys.h" @@ -44,15 +45,15 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) cal_clk = RTC_CAL_RC32K; } } - /* Enable requested clock (150k clock is always on) */ - bool dig_32k_xtal_state = REG_GET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); - if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); + /* Enable requested clock (150k clock is always on) */ + bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { + clk_ll_xtal32k_digi_enable(); } - bool dig_rc32k_state = REG_GET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN); - if (cal_clk == RTC_CAL_RC32K && !dig_rc32k_state) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN, 1); + bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_RC32K && !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. @@ -104,8 +105,15 @@ 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); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN, dig_rc32k_state); + + /* 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) { + clk_ll_xtal32k_digi_disable(); + } + /* if dig_rc32k was originally off and enabled due to calibration, then set back to off state */ + if (cal_clk == RTC_CAL_RC32K && !dig_rc32k_enabled) { + clk_ll_rc32k_digi_disable(); + } return cal_val; } diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk.c b/components/esp_hw_support/port/esp32s2/rtc_clk.c index c4c66ac0e9..6bb02ceea2 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk.c @@ -16,50 +16,28 @@ #include "soc/rtc_cntl_reg.h" #include "soc/rtc_io_reg.h" #include "soc/soc_caps.h" -#include "soc/sens_reg.h" -#include "soc/dport_reg.h" -#include "soc/efuse_reg.h" -#include "soc/syscon_reg.h" #include "esp_rom_sys.h" #include "esp_hw_log.h" -#include "rtc_clk_common.h" #include "sdkconfig.h" - -#include "regi2c_ctrl.h" -#include "regi2c_apll.h" -#include "regi2c_bbpll.h" +#include "hal/clk_tree_ll.h" static const char *TAG = "rtc_clk"; -#define RTC_PLL_FREQ_320M 320 -#define RTC_PLL_FREQ_480M 480 -#define DELAY_RTC_CLK_SWITCH 5 - // Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. // On the ESP32-S2, 480MHz PLL is enabled at reset. -static uint32_t s_cur_pll_freq = RTC_PLL_FREQ_480M; +static uint32_t s_cur_pll_freq = CLK_LL_PLL_480M_FREQ_MHZ; +static void rtc_clk_cpu_freq_to_xtal(int freq, int div); static void rtc_clk_cpu_freq_to_8m(void); -void rtc_clk_32k_enable_internal(x32k_config_t cfg) -{ - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf); - SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); -} - void rtc_clk_32k_enable(bool enable) { if (enable) { SET_PERI_REG_MASK(RTC_IO_XTAL_32P_PAD_REG, RTC_IO_X32P_MUX_SEL); SET_PERI_REG_MASK(RTC_IO_XTAL_32N_PAD_REG, RTC_IO_X32N_MUX_SEL); - x32k_config_t cfg = X32K_CONFIG_DEFAULT(); - rtc_clk_32k_enable_internal(cfg); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL); } else { - SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE); - CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + clk_ll_xtal32k_disable(); } } @@ -67,9 +45,7 @@ void rtc_clk_32k_enable_external(void) { SET_PERI_REG_MASK(RTC_IO_XTAL_32P_PAD_REG, RTC_IO_X32P_MUX_SEL); SET_PERI_REG_MASK(RTC_IO_XTAL_32N_PAD_REG, RTC_IO_X32N_MUX_SEL); - /* TODO: external 32k source may need different settings */ - x32k_config_t cfg = X32K_CONFIG_DEFAULT(); - rtc_clk_32k_enable_internal(cfg); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL); } void rtc_clk_32k_bootstrap(uint32_t cycle) @@ -77,55 +53,50 @@ void rtc_clk_32k_bootstrap(uint32_t cycle) /* No special bootstrapping needed for ESP32-S2, 'cycle' argument is to keep the signature * same as for the ESP32. Just enable the XTAL here. */ - (void) cycle; + (void)cycle; rtc_clk_32k_enable(true); } bool rtc_clk_32k_enabled(void) { - uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG); - /* If xtal xpd is controlled by software */ - bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S; - /* If xtal xpd software control is on */ - bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S; - bool disabled = xtal_xpd_sw && !xtal_xpd_st; - return !disabled; + return clk_ll_xtal32k_is_enabled(); } void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en) { if (clk_8m_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); - esp_rom_delay_us(DELAY_8M_ENABLE); + clk_ll_rc_fast_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); + clk_ll_rc_fast_disable(); } /* d256 should be independent configured with 8M * Maybe we can split this function into 8m and dmd256 */ if (d256_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_enable(); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_disable(); } } bool rtc_clk_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; + return clk_ll_rc_fast_is_enabled(); } bool rtc_clk_8md256_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; + return clk_ll_rc_fast_d256_is_enabled(); } void rtc_clk_apll_enable(bool enable) { - REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD, enable ? 0 : 1); - REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, enable ? 1 : 0); + 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) @@ -165,9 +136,9 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm } } // sdm2 = (int)(((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2 = (int)(((o_div + 2) * 2 * freq) / (rtc_xtal_freq * 1000000)) - 4; + sdm2 = (int)(((o_div + 2) * 2 * freq) / (rtc_xtal_freq * MHZ)) - 4; // numrator = (((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2 - float numrator = (((o_div + 2) * 2 * freq) / ((float)rtc_xtal_freq * 1000000)) - 4 - sdm2; + float numrator = (((o_div + 2) * 2 * freq) / ((float)rtc_xtal_freq * MHZ)) - 4 - sdm2; // If numrator is bigger than 255/256 + 255/65536 + (1/65536)/2 = 1 - (1 / 65536)/2, carry bit to sdm2 if (numrator > 1.0 - (1.0 / 65536.0) / 2.0) { sdm2++; @@ -179,7 +150,7 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm // Get the closest sdm0 sdm0 = (int)(numrator * 65536.0 + 0.5) % 256; } - uint32_t real_freq = (uint32_t)(rtc_xtal_freq * 1000000 * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / (((float)o_div + 2) * 2)); + uint32_t real_freq = (uint32_t)(rtc_xtal_freq * MHZ * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / (((float)o_div + 2) * 2)); *_o_div = o_div; *_sdm0 = sdm0; *_sdm1 = sdm1; @@ -189,41 +160,37 @@ 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) { - REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM2, sdm2); - REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM0, sdm0); - REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM1, sdm1); - REGI2C_WRITE(I2C_APLL, I2C_APLL_SDM_STOP, APLL_SDM_STOP_VAL_1); - REGI2C_WRITE(I2C_APLL, I2C_APLL_SDM_STOP, APLL_SDM_STOP_VAL_2_REV1); - REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OR_OUTPUT_DIV, o_div); + clk_ll_apll_set_config(o_div, sdm0, sdm1, sdm2); /* calibration */ - REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_1); - REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_2); - REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_3); + clk_ll_apll_set_calibration(); /* wait for calibration end */ - while (!(REGI2C_READ_MASK(I2C_APLL, I2C_APLL_OR_CAL_END))) { + while (!clk_ll_apll_calibration_is_done()) { /* use esp_rom_delay_us so the RTC bus doesn't get flooded */ esp_rom_delay_us(1); } } -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq) +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); + clk_ll_rtc_slow_set_src(clk_src); /* Why we need to connect this clock to digital? * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead? */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, - (slow_freq == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? 1 : 0); + if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + clk_ll_xtal32k_digi_enable(); + } else { + clk_ll_xtal32k_digi_disable(); + } - esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH); + esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + return clk_ll_rtc_slow_get_src(); } uint32_t rtc_clk_slow_freq_get_hz(void) @@ -232,84 +199,45 @@ uint32_t rtc_clk_slow_freq_get_hz(void) 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_RC_FAST_D256: return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: return 0; } - return 0; } -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq) +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq); - esp_rom_delay_us(DELAY_FAST_CLK_SWITCH); + 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) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + return clk_ll_rtc_fast_get_src(); } static void rtc_clk_bbpll_disable(void) { - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + clk_ll_bbpll_disable(); s_cur_pll_freq = 0; } static void rtc_clk_bbpll_enable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + clk_ll_bbpll_enable(); } -void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) +static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) { - uint8_t div_ref; - uint8_t div7_0; - uint8_t dr1; - uint8_t dr3; - uint8_t dchgp; - uint8_t dcur; - assert(xtal_freq == RTC_XTAL_FREQ_40M); - if (pll_freq == RTC_PLL_FREQ_480M) { - /* Clear this register to let the digital part know 480M PLL is used */ - SET_PERI_REG_MASK(DPORT_CPU_PER_CONF_REG, DPORT_PLL_FREQ_SEL); - /* Configure 480M PLL */ - div_ref = 0; - div7_0 = 8; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 4; - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); - } else { - /* Clear this register to let the digital part know 320M PLL is used */ - CLEAR_PERI_REG_MASK(DPORT_CPU_PER_CONF_REG, DPORT_PLL_FREQ_SEL); - /* Configure 320M PLL */ - div_ref = 0; - div7_0 = 4; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 5; - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69); - } - 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 = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (1 << 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); + /* Digital part */ + clk_ll_bbpll_set_freq_mhz(pll_freq); + /* Analog part */ + clk_ll_bbpll_set_config(pll_freq, xtal_freq); // Enable calibration by software - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_IR_CAL_ENX_CAP, 1); + clk_ll_bbpll_calibration_enable(); for (int ext_cap = 0; ext_cap < 16; ext_cap++) { - uint8_t cal_result; - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_IR_CAL_EXT_CAP, ext_cap); - cal_result = REGI2C_READ_MASK(I2C_BBPLL, I2C_BBPLL_OR_CAL_CAP); - if (cal_result == 0) { + if (clk_ll_bbpll_calibration_is_done(ext_cap)) { break; } if (ext_cap == 15) { @@ -328,23 +256,11 @@ void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { - int dbias = DIG_DBIAS_80M_160M; - int per_conf = DPORT_CPUPERIOD_SEL_80; - if (cpu_freq_mhz == 80) { - /* nothing to do */ - } else if (cpu_freq_mhz == 160) { - per_conf = DPORT_CPUPERIOD_SEL_160; - } else if (cpu_freq_mhz == 240) { - dbias = DIG_DBIAS_240M; - per_conf = DPORT_CPUPERIOD_SEL_240; - } else { - ESP_HW_LOGE(TAG, "invalid frequency"); - abort(); - } - REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, per_conf); - REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_PRE_DIV_CNT, 0); + int dbias = (cpu_freq_mhz == 240) ? DIG_DBIAS_240M : DIG_DBIAS_80M_160M; + clk_ll_cpu_set_freq_mhz_from_pll(cpu_freq_mhz); + clk_ll_cpu_set_divider(1); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias); - REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); rtc_clk_apb_freq_update(80 * MHZ); ets_update_cpu_frequency(cpu_freq_mhz); } @@ -356,7 +272,7 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* ou uint32_t divider; uint32_t real_freq_mhz; - uint32_t xtal_freq = RTC_XTAL_FREQ; + uint32_t xtal_freq = CLK_LL_XTAL_FREQ_MHZ; if (freq_mhz <= xtal_freq && freq_mhz != 0) { divider = xtal_freq / freq_mhz; real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */ @@ -370,17 +286,17 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* ou } else if (freq_mhz == 80) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 6; } else if (freq_mhz == 160) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 3; } else if (freq_mhz == 240) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 2; } else { // unsupported frequency @@ -397,20 +313,21 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* ou void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t* config) { - uint32_t soc_clk_sel = REG_GET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL); - if (soc_clk_sel != DPORT_SOC_CLK_SEL_XTAL) { - rtc_clk_cpu_freq_to_xtal(RTC_XTAL_FREQ, 1); + soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); + if (old_cpu_clk_src != SOC_CPU_CLK_SRC_XTAL) { + rtc_clk_cpu_freq_to_xtal(CLK_LL_XTAL_FREQ_MHZ, 1); } - if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL && config->source_freq_mhz != s_cur_pll_freq) { + if (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL && config->source_freq_mhz != s_cur_pll_freq) { rtc_clk_bbpll_disable(); } + if (config->source == SOC_CPU_CLK_SRC_XTAL) { if (config->div > 1) { rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); } } else if (config->source == SOC_CPU_CLK_SRC_PLL) { rtc_clk_bbpll_enable(); - rtc_clk_bbpll_configure(RTC_XTAL_FREQ, config->source_freq_mhz); + rtc_clk_bbpll_configure((rtc_xtal_freq_t)CLK_LL_XTAL_FREQ_MHZ, config->source_freq_mhz); rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); @@ -419,47 +336,38 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t* config) void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t* out_config) { - soc_cpu_clk_src_t source; + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); uint32_t source_freq_mhz; uint32_t div; uint32_t freq_mhz; - uint32_t soc_clk_sel = REG_GET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL); - switch (soc_clk_sel) { - case DPORT_SOC_CLK_SEL_XTAL: { - source = SOC_CPU_CLK_SRC_XTAL; - div = REG_GET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_PRE_DIV_CNT) + 1; - source_freq_mhz = RTC_XTAL_FREQ; + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = CLK_LL_XTAL_FREQ_MHZ; freq_mhz = source_freq_mhz / div; } break; - case DPORT_SOC_CLK_SEL_PLL: { - source = SOC_CPU_CLK_SRC_PLL; - uint32_t cpuperiod_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL); - uint32_t pllfreq_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_PLL_FREQ_SEL); - source_freq_mhz = (pllfreq_sel) ? RTC_PLL_FREQ_480M : RTC_PLL_FREQ_320M; - if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_80) { - div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 6 : 4; - freq_mhz = 80; - } else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_160) { - div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 3 : 2; - div = 3; - freq_mhz = 160; - } else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_240) { + case SOC_CPU_CLK_SRC_PLL: { + freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll(); + source_freq_mhz = clk_ll_bbpll_get_freq_mhz(); + if (freq_mhz == CLK_LL_PLL_80M_FREQ_MHZ) { + div = (source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) ? 6 : 4; + } else if (freq_mhz == CLK_LL_PLL_160M_FREQ_MHZ) { + div = (source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) ? 3 : 2; + } else if (freq_mhz == CLK_LL_PLL_240M_FREQ_MHZ && source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) { div = 2; - freq_mhz = 240; } else { ESP_HW_LOGE(TAG, "unsupported frequency configuration"); abort(); } break; } - case DPORT_SOC_CLK_SEL_8M: - source = SOC_CPU_CLK_SRC_RC_FAST; + case SOC_CPU_CLK_SRC_RC_FAST: source_freq_mhz = 8; div = 1; freq_mhz = source_freq_mhz; break; - case DPORT_SOC_CLK_SEL_APLL: + case SOC_CPU_CLK_SRC_APLL: default: ESP_HW_LOGE(TAG, "unsupported frequency configuration"); abort(); @@ -488,88 +396,77 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t* config) void rtc_clk_cpu_freq_set_xtal(void) { /* BBPLL is kept enabled */ - rtc_clk_cpu_freq_to_xtal(RTC_XTAL_FREQ, 1); + rtc_clk_cpu_freq_to_xtal(CLK_LL_XTAL_FREQ_MHZ, 1); } /** * Switch to XTAL frequency. Does not disable the PLL. */ -void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ - REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_PRE_DIV_CNT, 0); - REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_PRE_DIV_CNT, div - 1); - /* no need to adjust the REF_TICK */ + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_divider(div); + /* no need to adjust the REF_TICK, default register value already set it to 1MHz with any cpu clock source */ /* switch clock source */ - REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); rtc_clk_apb_freq_update(freq * MHZ); /* lower the voltage */ - if (freq <= 2) { - REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_2M); - } else { - REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); - } + int dbias = (freq <= 2) ? DIG_DBIAS_2M : DIG_DBIAS_XTAL; + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias); } static void rtc_clk_cpu_freq_to_8m(void) { ets_update_cpu_frequency(8); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); - REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_PRE_DIV_CNT, 0); - REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M); + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX); } rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) { - // Note, inside esp32s2-only code it's better to use RTC_XTAL_FREQ constant - return RTC_XTAL_FREQ; + // Note, inside esp32s2-only code it's better to use CLK_LL_XTAL_FREQ_MHZ constant + return (rtc_xtal_freq_t)CLK_LL_XTAL_FREQ_MHZ; } void rtc_clk_apb_freq_update(uint32_t apb_freq) { - WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12)); + clk_ll_apb_store_freq_hz(apb_freq); } uint32_t rtc_clk_apb_freq_get(void) { - uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12; - // round to the nearest MHz - freq_hz += MHZ / 2; - uint32_t remainder = freq_hz % MHZ; - return freq_hz - remainder; + return clk_ll_apb_load_freq_hz(); } void rtc_clk_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); - REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div); - SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + clk_ll_rc_slow_set_divider(div + 1); } void rtc_clk_8m_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div); - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + clk_ll_rc_fast_set_divider(div + 1); } void rtc_dig_clk8m_enable(void) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } void rtc_dig_clk8m_disable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_disable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } bool rtc_dig_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + return clk_ll_rc_fast_digi_is_enabled(); } /* Name used in libphy.a:phy_chip_v7.o diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk_common.h b/components/esp_hw_support/port/esp32s2/rtc_clk_common.h deleted file mode 100644 index 210c617cf7..0000000000 --- a/components/esp_hw_support/port/esp32s2/rtc_clk_common.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include - -#define MHZ (1000000) - -#define DPORT_CPUPERIOD_SEL_80 0 -#define DPORT_CPUPERIOD_SEL_160 1 -#define DPORT_CPUPERIOD_SEL_240 2 - -#define DPORT_SOC_CLK_SEL_XTAL 0 -#define DPORT_SOC_CLK_SEL_PLL 1 -#define DPORT_SOC_CLK_SEL_8M 2 -#define DPORT_SOC_CLK_SEL_APLL 3 - -#ifdef __cplusplus -extern "C" { -#endif - -void rtc_clk_cpu_freq_to_xtal(int freq, int div); - -/* Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in - * lower and upper 16-bit halves. These are the routines to work with such a - * representation. - */ -static inline bool clk_val_is_valid(uint32_t val) { - return (val & 0xffff) == ((val >> 16) & 0xffff) && - val != 0 && - val != UINT32_MAX; -} - -static inline uint32_t reg_val_to_clk_val(uint32_t val) { - return val & UINT16_MAX; -} - -static inline uint32_t clk_val_to_reg_val(uint32_t val) { - return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk_init.c b/components/esp_hw_support/port/esp32s2/rtc_clk_init.c index 2d7d3399dc..98a472481b 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk_init.c @@ -16,10 +16,9 @@ #include "soc/efuse_periph.h" #include "soc/syscon_reg.h" #include "hal/cpu_hal.h" -#include "regi2c_ctrl.h" +#include "hal/regi2c_ctrl_ll.h" #include "esp_hw_log.h" #include "sdkconfig.h" -#include "rtc_clk_common.h" static const char* TAG = "rtc_clk_init"; @@ -44,9 +43,11 @@ void rtc_clk_init(rtc_clk_config_t cfg) /* Configure 8M clock division */ rtc_clk_8m_divider_set(cfg.clk_8m_clk_div); + /* Reset (disable) i2c internal bus for all regi2c registers */ + regi2c_ctrl_ll_i2c_reset(); // TODO: This should be move out from rtc_clk_init /* Enable the internal bus used to configure PLLs */ - SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_APLL_M | I2C_BBPLL_M); + regi2c_ctrl_ll_i2c_bbpll_enable(); // TODO: This should be moved to bbpll_set_config + regi2c_ctrl_ll_i2c_apll_enable(); // TODO: This should be moved to apll_set_config rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; esp_rom_uart_tx_wait_idle(0); diff --git a/components/esp_hw_support/port/esp32s2/rtc_time.c b/components/esp_hw_support/port/esp32s2/rtc_time.c index 840fc34012..e2209da9bb 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_time.c +++ b/components/esp_hw_support/port/esp32s2/rtc_time.c @@ -8,6 +8,7 @@ #include "esp_rom_sys.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "hal/clk_tree_ll.h" #include "soc/timer_group_reg.h" /* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0. @@ -151,13 +152,13 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, ui } /* Enable requested clock (90k clock is always on) */ - int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); - if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); + bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { + clk_ll_xtal32k_digi_enable(); } if (cal_clk == RTC_CAL_8MD256) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_enable(); } uint32_t cal_val; @@ -169,10 +170,13 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, ui CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); + /* 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) { + clk_ll_xtal32k_digi_disable(); + } if (cal_clk == RTC_CAL_8MD256) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_disable(); } return cal_val; diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk.c b/components/esp_hw_support/port/esp32s3/rtc_clk.c index 9b222885c2..b8b2558202 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s3/rtc_clk.c @@ -13,55 +13,35 @@ #include "esp32s3/rom/ets_sys.h" #include "esp32s3/rom/rtc.h" #include "soc/rtc.h" -#include "soc/rtc_cntl_reg.h" #include "soc/rtc_io_reg.h" -#include "soc/sens_reg.h" -#include "soc/dport_reg.h" -#include "soc/efuse_reg.h" -#include "soc/syscon_reg.h" -#include "soc/system_reg.h" #include "esp_rom_sys.h" -#include "regi2c_ctrl.h" -#include "regi2c_dig_reg.h" -#include "regi2c_bbpll.h" #include "esp_hw_log.h" -#include "rtc_clk_common.h" #include "hal/usb_serial_jtag_ll.h" +#include "hal/clk_tree_ll.h" +#include "hal/regi2c_ctrl_ll.h" +#include "esp_private/regi2c_ctrl.h" +#include "regi2c_dig_reg.h" #include "sdkconfig.h" static const char *TAG = "rtc_clk"; -#define RTC_PLL_FREQ_320M 320 -#define RTC_PLL_FREQ_480M 480 -#define DELAY_RTC_CLK_SWITCH 5 - // Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. static uint32_t s_cur_pll_freq; static uint32_t s_apb_freq; +static void rtc_clk_cpu_freq_to_xtal(int freq, int div); static void rtc_clk_cpu_freq_to_8m(void); static bool rtc_clk_set_bbpll_always_on(void); -void rtc_clk_32k_enable_internal(x32k_config_t cfg) -{ - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm); - REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf); - SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); -} - void rtc_clk_32k_enable(bool enable) { if (enable) { SET_PERI_REG_MASK(RTC_IO_XTAL_32P_PAD_REG, RTC_IO_X32P_MUX_SEL); SET_PERI_REG_MASK(RTC_IO_XTAL_32N_PAD_REG, RTC_IO_X32N_MUX_SEL); - x32k_config_t cfg = X32K_CONFIG_DEFAULT(); - rtc_clk_32k_enable_internal(cfg); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL); } else { - SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE); - CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + clk_ll_xtal32k_disable(); } } @@ -69,9 +49,7 @@ void rtc_clk_32k_enable_external(void) { SET_PERI_REG_MASK(RTC_IO_XTAL_32P_PAD_REG, RTC_IO_X32P_MUX_SEL); SET_PERI_REG_MASK(RTC_IO_XTAL_32N_PAD_REG, RTC_IO_X32N_MUX_SEL); - /* TODO: external 32k source may need different settings */ - x32k_config_t cfg = X32K_CONFIG_DEFAULT(); - rtc_clk_32k_enable_internal(cfg); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL); } void rtc_clk_32k_bootstrap(uint32_t cycle) @@ -79,49 +57,41 @@ void rtc_clk_32k_bootstrap(uint32_t cycle) /* No special bootstrapping needed for ESP32-S3, 'cycle' argument is to keep the signature * same as for the ESP32. Just enable the XTAL here. */ - (void) cycle; + (void)cycle; rtc_clk_32k_enable(true); } bool rtc_clk_32k_enabled(void) { - uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG); - /* If xtal xpd is controlled by software */ - bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S; - /* If xtal xpd software control is on */ - bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S; - bool disabled = xtal_xpd_sw && !xtal_xpd_st; - return !disabled; + return clk_ll_xtal32k_is_enabled(); } void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en) { if (clk_8m_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); - esp_rom_delay_us(DELAY_8M_ENABLE); + clk_ll_rc_fast_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); + clk_ll_rc_fast_disable(); } /* d256 should be independent configured with 8M * Maybe we can split this function into 8m and dmd256 */ if (d256_en) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_enable(); } else { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); + clk_ll_rc_fast_d256_disable(); } } bool rtc_clk_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; + return clk_ll_rc_fast_is_enabled(); } bool rtc_clk_8md256_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; + return clk_ll_rc_fast_d256_is_enabled(); } static void wait_dig_dbias_valid(uint64_t rtc_cycles) @@ -136,22 +106,25 @@ static void wait_dig_dbias_valid(uint64_t rtc_cycles) rtc_clk_cal(cal_clk, rtc_cycles); } -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq) +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); + clk_ll_rtc_slow_set_src(clk_src); /* Why we need to connect this clock to digital? * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead? */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, - (slow_freq == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? 1 : 0); + if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + clk_ll_xtal32k_digi_enable(); + } else { + clk_ll_xtal32k_digi_disable(); + } - esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH); + esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); } soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + return clk_ll_rtc_slow_get_src(); } uint32_t rtc_clk_slow_freq_get_hz(void) @@ -160,132 +133,45 @@ uint32_t rtc_clk_slow_freq_get_hz(void) 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_RC_FAST_D256: return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: return 0; } - return 0; } -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq) +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq); - esp_rom_delay_us(DELAY_FAST_CLK_SWITCH); + 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) { - return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + return clk_ll_rtc_fast_get_src(); } static void rtc_clk_bbpll_disable(void) { - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + clk_ll_bbpll_disable(); s_cur_pll_freq = 0; } static void rtc_clk_bbpll_enable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + clk_ll_bbpll_enable(); } -void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) +static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) { - uint8_t div_ref; - uint8_t div7_0; - uint8_t dr1; - uint8_t dr3; - uint8_t dchgp; - uint8_t dcur; - uint8_t dbias; - + /* Digital part */ + clk_ll_bbpll_set_freq_mhz(pll_freq); + /* Analog part */ /* BBPLL CALIBRATION START */ - CLEAR_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); - SET_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); - - if (pll_freq == RTC_PLL_FREQ_480M) { - /* Set this register to let the digital part know 480M PLL is used */ - SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); - /* Configure 480M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 8; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - case RTC_XTAL_FREQ_32M: - div_ref = 1; - div7_0 = 26; - dr1 = 1; - dr3 = 1; - dchgp = 4; - dcur = 0; - dbias = 2; - break; - default: - div_ref = 0; - div7_0 = 8; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); - } else { - /* Clear this register to let the digital part know 320M PLL is used */ - CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); - /* Configure 320M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 4; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - case RTC_XTAL_FREQ_32M: - div_ref = 1; - div7_0 = 6; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - default: - div_ref = 0; - div7_0 = 4; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69); - } - 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_VCO_DBIAS, dbias); - + regi2c_ctrl_ll_bbpll_calibration_start(); + clk_ll_bbpll_set_config(pll_freq, xtal_freq); /* WAIT CALIBRATION DONE */ - while (!GET_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_CAL_DONE)); + while(!regi2c_ctrl_ll_bbpll_calibration_is_done()); /* BBPLL CALIBRATION STOP */ - CLEAR_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); - SET_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); + regi2c_ctrl_ll_bbpll_calibration_stop(); + s_cur_pll_freq = pll_freq; } @@ -296,24 +182,15 @@ void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { - int dbias = DIG_DBIAS_80M_160M; - int per_conf = DPORT_CPUPERIOD_SEL_80; - if (cpu_freq_mhz == 80) { - /* nothing to do */ - } else if (cpu_freq_mhz == 160) { - per_conf = DPORT_CPUPERIOD_SEL_160; - } else if (cpu_freq_mhz == 240) { - dbias = DIG_DBIAS_240M; - per_conf = DPORT_CPUPERIOD_SEL_240; - } else { - ESP_HW_LOGE(TAG, "invalid frequency"); - } + int dbias = (cpu_freq_mhz == 240) ? DIG_DBIAS_240M : DIG_DBIAS_80M_160M; REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, dbias); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, dbias); wait_dig_dbias_valid(2); - REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL); + + clk_ll_cpu_set_freq_mhz_from_pll(cpu_freq_mhz); + clk_ll_cpu_set_divider(1); + /* switch clock source */ + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); rtc_clk_apb_freq_update(80 * MHZ); ets_update_cpu_frequency(cpu_freq_mhz); } @@ -325,7 +202,7 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou uint32_t divider; uint32_t real_freq_mhz; - uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get(); + uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get(); if (freq_mhz <= xtal_freq && freq_mhz != 0) { divider = xtal_freq / freq_mhz; real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */ @@ -339,17 +216,17 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou } else if (freq_mhz == 80) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 6; } else if (freq_mhz == 160) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 3; } else if (freq_mhz == 240) { real_freq_mhz = freq_mhz; source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; divider = 2; } else { // unsupported frequency @@ -366,22 +243,22 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) { - uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); + 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 ((soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) && !rtc_clk_set_bbpll_always_on()) { + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { // We don't turn off the bbpll if some consumers only depends on bbpll rtc_clk_bbpll_disable(); } } else if (config->source == SOC_CPU_CLK_SRC_PLL) { - if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL) { + if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) { rtc_clk_bbpll_enable(); rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); } rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); - if ((soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) && !rtc_clk_set_bbpll_always_on()) { + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { // We don't turn off the bbpll if some consumers only depends on bbpll rtc_clk_bbpll_disable(); } @@ -390,43 +267,34 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) { - soc_cpu_clk_src_t source; + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); uint32_t source_freq_mhz; uint32_t div; uint32_t freq_mhz; - uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); - switch (soc_clk_sel) { - case DPORT_SOC_CLK_SEL_XTAL: { - source = SOC_CPU_CLK_SRC_XTAL; - div = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; - source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); freq_mhz = source_freq_mhz / div; } break; - case DPORT_SOC_CLK_SEL_PLL: { - source = SOC_CPU_CLK_SRC_PLL; - uint32_t cpuperiod_sel = DPORT_REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL); - uint32_t pllfreq_sel = DPORT_REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); - source_freq_mhz = (pllfreq_sel) ? RTC_PLL_FREQ_480M : RTC_PLL_FREQ_320M; - if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_80) { - div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 6 : 4; - freq_mhz = 80; - } else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_160) { - div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 3 : 2; - div = 3; - freq_mhz = 160; - } else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_240) { + case SOC_CPU_CLK_SRC_PLL: { + freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll(); + source_freq_mhz = clk_ll_bbpll_get_freq_mhz(); + if (freq_mhz == CLK_LL_PLL_80M_FREQ_MHZ) { + div = (source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) ? 6 : 4; + } else if (freq_mhz == CLK_LL_PLL_160M_FREQ_MHZ) { + div = (source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) ? 3 : 2; + } else if (freq_mhz == CLK_LL_PLL_240M_FREQ_MHZ && source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) { div = 2; - freq_mhz = 240; } else { ESP_HW_LOGE(TAG, "unsupported frequency configuration"); return; } break; } - case DPORT_SOC_CLK_SEL_8M: - source = SOC_CPU_CLK_SRC_RC_FAST; - source_freq_mhz = 8; + case SOC_CPU_CLK_SRC_RC_FAST: + source_freq_mhz = 20; div = 1; freq_mhz = source_freq_mhz; break; @@ -457,10 +325,9 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { - int freq_mhz = (int) rtc_clk_xtal_freq_get(); + int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); - // We don't turn off the bbpll if some consumers only depends on bbpll if (!rtc_clk_set_bbpll_always_on()) { rtc_clk_bbpll_disable(); @@ -470,48 +337,44 @@ void rtc_clk_cpu_freq_set_xtal(void) /** * Switch to XTAL frequency. Does not disable the PLL. */ -void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); /* set digital voltage for different cpu freq from xtal */ - if (freq <= 2) { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, DIG_DBIAS_2M); - } else { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, DIG_DBIAS_XTAL); - } + int dbias = (freq <= 2) ? DIG_DBIAS_2M : DIG_DBIAS_XTAL; + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, dbias); wait_dig_dbias_valid(2); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, div - 1); - /* no need to adjust the REF_TICK */ + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_divider(div); /* switch clock source */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); rtc_clk_apb_freq_update(freq * MHZ); } static void rtc_clk_cpu_freq_to_8m(void) { - ets_update_cpu_frequency(8); + ets_update_cpu_frequency(20); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, DIG_DBIAS_XTAL); wait_dig_dbias_valid(2); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M); + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX); } rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) { - uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); - if (!clk_val_is_valid(xtal_freq_reg)) { - ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg); + uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz(); + if (xtal_freq_mhz == 0) { + ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz"); return RTC_XTAL_FREQ_40M; } - return reg_val_to_clk_val(xtal_freq_reg); + return (rtc_xtal_freq_t)xtal_freq_mhz; } void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq) { - WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq)); + clk_ll_xtal_store_freq_mhz(xtal_freq); } void rtc_clk_apb_freq_update(uint32_t apb_freq) @@ -526,33 +389,29 @@ uint32_t rtc_clk_apb_freq_get(void) void rtc_clk_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); - REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div); - SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + clk_ll_rc_slow_set_divider(div + 1); } void rtc_clk_8m_divider_set(uint32_t div) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div); - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + clk_ll_rc_fast_set_divider(div + 1); } void rtc_dig_clk8m_enable(void) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } void rtc_dig_clk8m_disable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); + clk_ll_rc_fast_digi_disable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); } bool rtc_dig_8m_enabled(void) { - return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + return clk_ll_rc_fast_digi_is_enabled(); } static bool rtc_clk_set_bbpll_always_on(void) diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk_common.h b/components/esp_hw_support/port/esp32s3/rtc_clk_common.h deleted file mode 100644 index c6b8e17be8..0000000000 --- a/components/esp_hw_support/port/esp32s3/rtc_clk_common.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include - -#define MHZ (1000000) - -#define DPORT_CPUPERIOD_SEL_80 0 -#define DPORT_CPUPERIOD_SEL_160 1 -#define DPORT_CPUPERIOD_SEL_240 2 - -#define DPORT_SOC_CLK_SEL_XTAL 0 -#define DPORT_SOC_CLK_SEL_PLL 1 -#define DPORT_SOC_CLK_SEL_8M 2 - -#ifdef __cplusplus -extern "C" { -#endif - -void rtc_clk_cpu_freq_to_xtal(int freq, int div); - -/* 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. - */ -static inline bool clk_val_is_valid(uint32_t val) -{ - return (val & 0xffff) == ((val >> 16) & 0xffff) && - val != 0 && - val != UINT32_MAX; -} - -static inline uint32_t reg_val_to_clk_val(uint32_t val) -{ - return val & UINT16_MAX; -} - -static inline uint32_t clk_val_to_reg_val(uint32_t val) -{ - return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16); -} - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk_init.c b/components/esp_hw_support/port/esp32s3/rtc_clk_init.c index 47168babac..88c21a7f89 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32s3/rtc_clk_init.c @@ -12,11 +12,9 @@ #include "esp32s3/rom/rtc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/syscon_reg.h" #include "hal/cpu_hal.h" -#include "regi2c_ctrl.h" +#include "hal/regi2c_ctrl_ll.h" #include "esp_hw_log.h" -#include "rtc_clk_common.h" static const char *TAG = "rtc_clk_init"; @@ -41,9 +39,10 @@ void rtc_clk_init(rtc_clk_config_t cfg) /* Configure 8M clock division */ rtc_clk_8m_divider_set(cfg.clk_8m_clk_div); - /* Enable the internal bus used to configure PLLs */ - SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_BBPLL_M); + /* Reset (disable) i2c internal bus for all regi2c registers */ + regi2c_ctrl_ll_i2c_reset(); // TODO: This should be move out from rtc_clk_init + /* Enable the internal bus used to configure BBPLL */ + regi2c_ctrl_ll_i2c_bbpll_enable(); // TODO: This should be moved to bbpll_set_config rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; esp_rom_uart_tx_wait_idle(0); diff --git a/components/esp_hw_support/port/esp32s3/rtc_time.c b/components/esp_hw_support/port/esp32s3/rtc_time.c index 060c97de23..68eb091c03 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_time.c +++ b/components/esp_hw_support/port/esp32s3/rtc_time.c @@ -8,6 +8,7 @@ #include "esp_rom_sys.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "hal/clk_tree_ll.h" #include "soc/timer_group_reg.h" /* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0. @@ -47,13 +48,13 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } /* Enable requested clock (150k clock is always on) */ - int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); - if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); + bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { + clk_ll_xtal32k_digi_enable(); } if (cal_clk == RTC_CAL_8MD256) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_enable(); } /* There may be another calibration process already running during we call this function, * so we should wait the last process is done. @@ -106,10 +107,13 @@ 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); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); + /* 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) { + clk_ll_xtal32k_digi_disable(); + } if (cal_clk == RTC_CAL_8MD256) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); + clk_ll_rc_fast_d256_digi_disable(); } return cal_val; diff --git a/components/esp_system/test/test_sleep.c b/components/esp_system/test/test_sleep.c index c9857dcc4a..9979b1e624 100644 --- a/components/esp_system/test/test_sleep.c +++ b/components/esp_system/test/test_sleep.c @@ -213,7 +213,7 @@ TEST_CASE("light sleep and frequency switching", "[deepsleep]") rtc_cpu_freq_config_t config_xtal, config_default; rtc_clk_cpu_freq_get_config(&config_default); - rtc_clk_cpu_freq_mhz_to_config((int) rtc_clk_xtal_freq_get(), &config_xtal); + rtc_clk_cpu_freq_mhz_to_config(esp_clk_xtal_freq() / MHZ, &config_xtal); esp_sleep_enable_timer_wakeup(1000); for (int i = 0; i < 1000; ++i) { diff --git a/components/hal/esp32/include/hal/clk_tree_ll.h b/components/hal/esp32/include/hal/clk_tree_ll.h new file mode 100644 index 0000000000..a5d6fc631e --- /dev/null +++ b/components/hal/esp32/include/hal/clk_tree_ll.h @@ -0,0 +1,859 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/clk_tree_defs.h" +#include "soc/rtc.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_io_reg.h" +#include "soc/dport_reg.h" +#include "soc/syscon_reg.h" +#include "esp_private/regi2c_ctrl.h" +#include "regi2c_bbpll.h" +#include "regi2c_apll.h" +#include "hal/assert.h" +#include "esp32/rom/rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MHZ (1000000) + +#define CLK_LL_PLL_80M_FREQ_MHZ (80) +#define CLK_LL_PLL_160M_FREQ_MHZ (160) +#define CLK_LL_PLL_240M_FREQ_MHZ (240) + +#define CLK_LL_PLL_320M_FREQ_MHZ (320) +#define CLK_LL_PLL_480M_FREQ_MHZ (480) + +/* BBPLL configuration parameters at reset */ +#define CLK_LL_BBPLL_IR_CAL_DELAY_VAL 0x18 +#define CLK_LL_BBPLL_IR_CAL_EXT_CAP_VAL 0x20 +#define CLK_LL_BBPLL_OC_ENB_FCAL_VAL 0x9a +#define CLK_LL_BBPLL_OC_ENB_VCON_VAL 0x00 +#define CLK_LL_BBPLL_BBADC_CAL_7_0_VAL 0x00 + +/* BBPLL configuration parameters */ +#define CLK_LL_BBPLL_ENDIV5_VAL_320M 0x43 +#define CLK_LL_BBPLL_BBADC_DSMP_VAL_320M 0x84 +#define CLK_LL_BBPLL_ENDIV5_VAL_480M 0xc3 +#define CLK_LL_BBPLL_BBADC_DSMP_VAL_480M 0x74 + +/* APLL configuration parameters */ +#define CLK_LL_APLL_SDM_STOP_VAL_1 0x09 +#define CLK_LL_APLL_SDM_STOP_VAL_2_REV0 0x69 +#define CLK_LL_APLL_SDM_STOP_VAL_2_REV1 0x49 + +/* APLL calibration parameters */ +#define CLK_LL_APLL_CAL_DELAY_1 0x0f +#define CLK_LL_APLL_CAL_DELAY_2 0x3f +#define CLK_LL_APLL_CAL_DELAY_3 0x1f + +/* XTAL32K configuration parameters for 32kHz crystal */ +#define CLK_LL_XTAL_32K_DAC_VAL 1 +#define CLK_LL_XTAL_32K_DRES_VAL 3 +#define CLK_LL_XTAL_32K_DBIAS_VAL 0 + +/* XTAL32K configuration parameters for external oscillator clock */ +#define CLK_LL_XTAL_32K_EXT_DAC_VAL 2 +#define CLK_LL_XTAL_32K_EXT_DRES_VAL 3 +#define CLK_LL_XTAL_32K_EXT_DBIAS_VAL 1 + +/* XTAL32K configuration parameters for fast startup with bootstrap */ +#define CLK_LL_XTAL_32K_BOOTSTRAP_DAC_VAL 3 +#define CLK_LL_XTAL_32K_BOOTSTRAP_DRES_VAL 3 +#define CLK_LL_XTAL_32K_BOOTSTRAP_DBIAS_VAL 0 + +/** + * @brief XTAL32K_CLK enable modes + */ +typedef enum { + CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL, //!< Enable the external 32kHz crystal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL, //!< Enable the external clock signal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_BOOTSTRAP, //!< Bootstrap the crystal oscillator for faster XTAL32K_CLK start up */ +} clk_ll_xtal32k_enable_mode_t; + +/** + * @brief Power up internal I2C bus + */ +static inline __attribute__((always_inline)) void clk_ll_i2c_pu(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD); +} + +/** + * @brief Power down internal I2C bus + */ +static inline __attribute__((always_inline)) void clk_ll_i2c_pd(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD); +} + +/** + * @brief Power up BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, + RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD | + RTC_CNTL_BBPLL_I2C_FORCE_PD); + // Reset BBPLL configuration + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_IR_CAL_DELAY, CLK_LL_BBPLL_IR_CAL_DELAY_VAL); + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_IR_CAL_EXT_CAP, CLK_LL_BBPLL_IR_CAL_EXT_CAP_VAL); + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_ENB_FCAL, CLK_LL_BBPLL_OC_ENB_FCAL_VAL); + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_ENB_VCON, CLK_LL_BBPLL_OC_ENB_VCON_VAL); + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_BBADC_CAL_7_0, CLK_LL_BBPLL_BBADC_CAL_7_0_VAL); +} + +/** + * @brief Power down BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, + RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD | + RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Power up APLL circuit + */ +static inline void clk_ll_apll_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU); +} + +/** + * @brief Power down APLL circuit + */ +static inline void clk_ll_apll_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU); +} + +/** + * @brief Check whether APLL is under force power down state + * + * @return True if APLL is under force power down; otherwise false + */ +static inline bool clk_ll_apll_is_fpd(void) +{ + return REG_GET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); +} + +/** + * @brief Set APLL configuration + * + * @param is_rev0 True if chip version is rev0 + * @param o_div Frequency divider, 0..31 + * @param sdm0 Frequency adjustment parameter, 0..255 + * @param sdm1 Frequency adjustment parameter, 0..255 + * @param sdm2 Frequency adjustment parameter, 0..63 + */ +static inline void clk_ll_apll_set_config(bool is_rev0, uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2) +{ + uint8_t sdm_stop_val_2 = CLK_LL_APLL_SDM_STOP_VAL_2_REV1; + if (is_rev0) { + sdm0 = 0; + sdm1 = 0; + sdm_stop_val_2 = CLK_LL_APLL_SDM_STOP_VAL_2_REV0; + } + REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM2, sdm2); + REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM0, sdm0); + REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM1, sdm1); + REGI2C_WRITE(I2C_APLL, I2C_APLL_SDM_STOP, CLK_LL_APLL_SDM_STOP_VAL_1); + REGI2C_WRITE(I2C_APLL, I2C_APLL_SDM_STOP, sdm_stop_val_2); + REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OR_OUTPUT_DIV, o_div); +} + +/** + * @brief Set APLL calibration parameters + */ +static inline void clk_ll_apll_set_calibration(void) +{ + REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, CLK_LL_APLL_CAL_DELAY_1); + REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, CLK_LL_APLL_CAL_DELAY_2); + REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, CLK_LL_APLL_CAL_DELAY_3); +} + +/** + * @brief Check whether APLL calibration is done + * + * @return True if calibration is done; otherwise false + */ +static inline bool clk_ll_apll_calibration_is_done(void) +{ + return REGI2C_READ_MASK(I2C_APLL, I2C_APLL_OR_CAL_END); +} + +/** + * @brief Enable the 32kHz crystal oscillator + * + * @param mode Used to determine the xtal32k configuration parameters + */ +static inline void clk_ll_xtal32k_enable(clk_ll_xtal32k_enable_mode_t mode) +{ + // Configure xtal32k + // Default mode as CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL + uint32_t dac = CLK_LL_XTAL_32K_DAC_VAL; // current + uint32_t dres = CLK_LL_XTAL_32K_DRES_VAL; // resistance + uint32_t dbias = CLK_LL_XTAL_32K_DBIAS_VAL; // dbias voltage + if (mode == CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL) { + dac = CLK_LL_XTAL_32K_EXT_DAC_VAL; + dres = CLK_LL_XTAL_32K_EXT_DRES_VAL; + dbias = CLK_LL_XTAL_32K_EXT_DBIAS_VAL; + } else if (mode == CLK_LL_XTAL32K_ENABLE_MODE_BOOTSTRAP) { + dac = CLK_LL_XTAL_32K_BOOTSTRAP_DAC_VAL; + dres = CLK_LL_XTAL_32K_BOOTSTRAP_DRES_VAL; + dbias = CLK_LL_XTAL_32K_BOOTSTRAP_DBIAS_VAL; + } + REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DAC_XTAL_32K, dac); + REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DRES_XTAL_32K, dres); + REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DBIAS_XTAL_32K, dbias); + // Enable xtal32k xpd status + SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M); +} + +/** + * @brief Disable the 32kHz crystal oscillator + */ +static inline void clk_ll_xtal32k_disable(void) +{ + // Disable xtal32k xpd status + CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K_M); +} + +/** + * @brief Get the state of the 32kHz crystal clock + * + * @return True if the 32kHz XTAL is enabled + */ +static inline bool clk_ll_xtal32k_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K); +} + +/** + * @brief Enable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); +} + +/** + * @brief Disable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); +} + +/** + * @brief Get the state of the internal oscillator for RC_FAST_CLK + * + * @return True if the oscillator is enabled + */ +static inline bool clk_ll_rc_fast_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; +} + +/** + * @brief Enable the output from the internal oscillator to be passed into a configurable divider, + * which by default divides the input clock frequency by 256. i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Divider values other than 256 may be configured, but this facility is not currently needed, + * so is not exposed in the code. + * The output of the divider, RC_FAST_D256_CLK, is referred as 8md256 or simply d256 in reg. descriptions. + */ +static inline void clk_ll_rc_fast_d256_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Disable the output from the internal oscillator to be passed into a configurable divider. + * i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Disabling this divider could reduce power consumption. + */ +static inline void clk_ll_rc_fast_d256_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Get the state of the divider which is applied to the output from the internal oscillator (RC_FAST_CLK) + * + * @return True if the divided output is enabled + */ +static inline bool clk_ll_rc_fast_d256_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; +} + +/** + * @brief Enable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Get the state of the digital RC_FAST_CLK + * + * @return True if the digital RC_FAST_CLK is enabled + */ +static inline bool clk_ll_rc_fast_digi_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Enable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Enable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Disable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Get the state of the digital XTAL32K_CLK + * + * @return True if the digital XTAL32K_CLK is enabled + */ +static inline bool clk_ll_xtal32k_digi_is_enabled(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); +} + +/** + * @brief Get PLL_CLK frequency + * + * @return PLL clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline uint32_t clk_ll_bbpll_get_freq_mhz(void) +{ + // ESP32 BBPLL frequency is determined by the cpu freq sel + uint32_t cpu_freq_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL); + switch (cpu_freq_sel) { + case 0: + case 1: + return CLK_LL_PLL_320M_FREQ_MHZ; + case 2: + return CLK_LL_PLL_480M_FREQ_MHZ; + default: + // Invalid CPUPERIOD_SEL value + return 0; + } +} + +/** + * @brief Set BBPLL frequency from XTAL source (digital part) + * + * @param pll_freq_mhz PLL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_freq_mhz(uint32_t pll_freq_mhz) +{ + (void)pll_freq_mhz; + // No such operation on ESP32 +} + +/** + * @brief Set BBPLL frequency from XTAL source (Analog part) + * + * @param pll_freq_mhz PLL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_config(uint32_t pll_freq_mhz, uint32_t xtal_freq_mhz) +{ + uint8_t div_ref; + uint8_t div7_0; + uint8_t div10_8; + uint8_t lref; + uint8_t dcur; + uint8_t bw; + + if (pll_freq_mhz == CLK_LL_PLL_320M_FREQ_MHZ) { + /* Configure 320M PLL */ + switch (xtal_freq_mhz) { + case RTC_XTAL_FREQ_40M: + div_ref = 0; + div7_0 = 32; + div10_8 = 0; + lref = 0; + dcur = 6; + bw = 3; + break; + case RTC_XTAL_FREQ_26M: + div_ref = 12; + div7_0 = 224; + div10_8 = 4; + lref = 1; + dcur = 0; + bw = 1; + break; + case RTC_XTAL_FREQ_24M: + div_ref = 11; + div7_0 = 224; + div10_8 = 4; + lref = 1; + dcur = 0; + bw = 1; + break; + default: + div_ref = 12; + div7_0 = 224; + div10_8 = 4; + lref = 0; + dcur = 0; + bw = 0; + break; + } + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_ENDIV5, CLK_LL_BBPLL_ENDIV5_VAL_320M); + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, CLK_LL_BBPLL_BBADC_DSMP_VAL_320M); + } else { + /* Configure 480M PLL */ + switch (xtal_freq_mhz) { + case RTC_XTAL_FREQ_40M: + div_ref = 0; + div7_0 = 28; + div10_8 = 0; + lref = 0; + dcur = 6; + bw = 3; + break; + case RTC_XTAL_FREQ_26M: + div_ref = 12; + div7_0 = 144; + div10_8 = 4; + lref = 1; + dcur = 0; + bw = 1; + break; + case RTC_XTAL_FREQ_24M: + div_ref = 11; + div7_0 = 144; + div10_8 = 4; + lref = 1; + dcur = 0; + bw = 1; + break; + default: + div_ref = 12; + div7_0 = 224; + div10_8 = 4; + lref = 0; + dcur = 0; + bw = 0; + break; + } + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_ENDIV5, CLK_LL_BBPLL_ENDIV5_VAL_480M); + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, CLK_LL_BBPLL_BBADC_DSMP_VAL_480M); + } + + uint8_t i2c_bbpll_lref = (lref << 7) | (div10_8 << 4) | (div_ref); + uint8_t i2c_bbpll_div_7_0 = div7_0; + uint8_t i2c_bbpll_dcur = (bw << 6) | dcur; + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_LREF, i2c_bbpll_lref); + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); +} + +/** + * @brief Select the clock source for CPU_CLK + * + * @param in_sel One of the clock sources in soc_cpu_clk_src_t + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_src(soc_cpu_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_CPU_CLK_SRC_XTAL: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, 0); + break; + case SOC_CPU_CLK_SRC_PLL: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, 1); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, 2); + break; + case SOC_CPU_CLK_SRC_APLL: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, 3); + break; + default: + // Unsupported CPU_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for CPU_CLK + * + * @return Currently selected clock source (one of soc_cpu_clk_src_t values) + */ +static inline __attribute__((always_inline)) soc_cpu_clk_src_t clk_ll_cpu_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL); + switch (clk_sel) { + 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 3: + return SOC_CPU_CLK_SRC_APLL; + default: + return SOC_CPU_CLK_SRC_INVALID; + } +} + +/** + * @brief Set CPU frequency from PLL clock + * + * @param cpu_mhz CPU frequency value, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_freq_mhz_from_pll(uint32_t cpu_mhz) +{ + switch (cpu_mhz) { + case CLK_LL_PLL_80M_FREQ_MHZ: + DPORT_REG_WRITE(DPORT_CPU_PER_CONF_REG, 0); + break; + case CLK_LL_PLL_160M_FREQ_MHZ: + DPORT_REG_WRITE(DPORT_CPU_PER_CONF_REG, 1); + break; + case CLK_LL_PLL_240M_FREQ_MHZ: + DPORT_REG_WRITE(DPORT_CPU_PER_CONF_REG, 2); + break; + default: + // Unsupported CPU_CLK freq from PLL + abort(); + } +} + +/** + * @brief Get CPU_CLK frequency from PLL_CLK source + * + * @return CPU clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_freq_mhz_from_pll(void) +{ + uint32_t cpu_freq_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL); + switch (cpu_freq_sel) { + case 0: + return CLK_LL_PLL_80M_FREQ_MHZ; + case 1: + return CLK_LL_PLL_160M_FREQ_MHZ; + case 2: + return CLK_LL_PLL_240M_FREQ_MHZ; + default: + // Invalid CPUPERIOD_SEL value + return 0; + } +} + +/** + * @brief Set CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @param divider Divider. Usually this divider is set to 1 in bootloader stage. PRE_DIV_CNT = divider - 1. + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + REG_SET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_PRE_DIV_CNT, divider - 1); +} + +/** + * @brief Get CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @return Divider. Divider = (PRE_DIV_CNT + 1). + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(void) +{ + return REG_GET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_PRE_DIV_CNT) + 1; +} + +/** + * @brief Set REF_TICK divider to make REF_TICK frequency at 1MHz + * + * @param cpu_clk_src Selected CPU clock source (one of soc_cpu_clk_src_t values) + * @param cpu_freq_mhz CPU frequency value, in MHz + * + * Divider = APB_CLK freq in Hz / 1MHz. Value in register = divider - 1. + */ +static inline __attribute__((always_inline)) void clk_ll_ref_tick_set_divider(soc_cpu_clk_src_t cpu_clk_src, uint32_t cpu_freq_mhz) +{ + uint32_t apb_freq_mhz; + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + apb_freq_mhz = cpu_freq_mhz; + REG_WRITE(SYSCON_XTAL_TICK_CONF_REG, apb_freq_mhz - 1); + break; + case SOC_CPU_CLK_SRC_PLL: + apb_freq_mhz = 80; + REG_WRITE(SYSCON_PLL_TICK_CONF_REG, apb_freq_mhz - 1); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + apb_freq_mhz = cpu_freq_mhz; + REG_WRITE(SYSCON_CK8M_TICK_CONF_REG, apb_freq_mhz - 1); + break; + case SOC_CPU_CLK_SRC_APLL: + apb_freq_mhz = cpu_freq_mhz >> 1; + REG_WRITE(SYSCON_APLL_TICK_CONF_REG, apb_freq_mhz - 1); + break; + default: + // Unsupported CPU_CLK mux input sel + abort(); + } +} + +/** + * @brief Select the clock source for RTC_SLOW_CLK + * + * @param in_sel One of the clock sources in soc_rtc_slow_clk_src_t + */ +static inline void clk_ll_rtc_slow_set_src(soc_rtc_slow_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 0); + break; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 1); + break; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 2); + break; + default: + // Unsupported RTC_SLOW_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_SLOW_CLK + * + * @return Currently selected clock source (one of soc_rtc_slow_clk_src_t values) + */ +static inline soc_rtc_slow_clk_src_t clk_ll_rtc_slow_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_SLOW_CLK_SRC_RC_SLOW; + case 1: + return SOC_RTC_SLOW_CLK_SRC_XTAL32K; + case 2: + return SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256; + default: + // Invalid ANA_CLK_RTC_SEL value + return SOC_RTC_SLOW_CLK_SRC_INVALID; + } +} + +/** + * @brief Select the clock source for RTC_FAST_CLK + * + * @param in_sel One of the clock sources in soc_rtc_fast_clk_src_t + */ +static inline void clk_ll_rtc_fast_set_src(soc_rtc_fast_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_FAST_CLK_SRC_XTAL_D4: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 0); + break; + case SOC_RTC_FAST_CLK_SRC_RC_FAST: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 1); + break; + default: + // Unsupported RTC_FAST_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_FAST_CLK + * + * @return Currently selected clock source (one of soc_rtc_fast_clk_src_t values) + */ +static inline soc_rtc_fast_clk_src_t clk_ll_rtc_fast_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_FAST_CLK_SRC_XTAL_D4; + case 1: + return SOC_RTC_FAST_CLK_SRC_RC_FAST; + default: + return SOC_RTC_FAST_CLK_SRC_INVALID; + } +} + +/** + * @brief Set RC_FAST_CLK divider. The output from the divider is passed into rtc_fast_clk MUX. + * + * @param divider Divider of RC_FAST_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_fast_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, divider - 1); +} + +/** + * @brief Get RC_FAST_CLK divider + * + * @return Divider. Divider = (CK8M_DIV_SEL + 1). + */ +static inline uint32_t clk_ll_rc_fast_get_divider(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL) + 1; +} + +/************************* RTC STORAGE REGISTER STORE/LOAD **************************/ +/** + * @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 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 format 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 or haven't written XTAL value into RTC_XTAL_FREQ_REG + return 0; +} + +/** + * @brief Store APB_CLK frequency in RTC storage register + * + * Value of RTC_APB_FREQ_REG is stored as two copies in lower and upper 16-bit + * halves. These are the routines to work with that representation. + * + * @param apb_freq_hz APB frequency, in Hz + */ +static inline __attribute__((always_inline)) void clk_ll_apb_store_freq_hz(uint32_t apb_freq_hz) +{ + uint32_t val = apb_freq_hz >> 12; + WRITE_PERI_REG(RTC_APB_FREQ_REG, (val & UINT16_MAX) | ((val & UINT16_MAX) << 16)); +} + +/** + * @brief Load APB_CLK frequency from RTC storage register + * + * Value of RTC_APB_FREQ_REG is stored as two copies in lower and upper 16-bit + * halves. These are the routines to work with that representation. + * + * @return The stored APB frequency, in Hz + */ +static inline uint32_t clk_ll_apb_load_freq_hz(void) +{ + // Read from RTC storage register + uint32_t apb_freq_hz = (READ_PERI_REG(RTC_APB_FREQ_REG) & UINT16_MAX) << 12; + // Round to the nearest MHz + apb_freq_hz += MHZ / 2; + uint32_t remainder = apb_freq_hz % MHZ; + return apb_freq_hz - remainder; +} + +/** + * @brief Store RTC_SLOW_CLK calibration value in RTC storage register + * + * Value of RTC_SLOW_CLK_CAL_REG has to be in the same format as returned by rtc_clk_cal (microseconds, + * in Q13.19 fixed-point format). + * + * @param cal_value The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline void clk_ll_rtc_slow_store_cal(uint32_t cal_value) +{ + REG_WRITE(RTC_SLOW_CLK_CAL_REG, cal_value); +} + +/** + * @brief Load the calibration value of RTC_SLOW_CLK frequency from RTC storage register + * + * This value gets updated (i.e. rtc slow clock gets calibrated) every time RTC_SLOW_CLK source switches + * + * @return The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline uint32_t clk_ll_rtc_slow_load_cal(void) +{ + return REG_READ(RTC_SLOW_CLK_CAL_REG); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32/include/hal/regi2c_ctrl_ll.h b/components/hal/esp32/include/hal/regi2c_ctrl_ll.h new file mode 100644 index 0000000000..aa0e449607 --- /dev/null +++ b/components/hal/esp32/include/hal/regi2c_ctrl_ll.h @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/regi2c_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Reset (Disable) the I2C internal bus for all regi2c registers + */ +static inline void regi2c_ctrl_ll_i2c_reset(void) +{ + SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); +} + +/** + * @brief Enable the I2C internal bus to do I2C read/write operation to the BBPLL configuration register + */ +static inline void regi2c_ctrl_ll_i2c_bbpll_enable(void) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_BBPLL_M); +} + +/** + * @brief Enable the I2C internal bus to do I2C read/write operation to the APLL configuration register + */ +static inline void regi2c_ctrl_ll_i2c_apll_enable(void) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_APLL_M); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c2/include/hal/clk_tree_ll.h b/components/hal/esp32c2/include/hal/clk_tree_ll.h new file mode 100644 index 0000000000..f753b9b349 --- /dev/null +++ b/components/hal/esp32c2/include/hal/clk_tree_ll.h @@ -0,0 +1,562 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/clk_tree_defs.h" +#include "soc/rtc.h" +#include "soc/system_reg.h" +#include "soc/rtc_cntl_reg.h" +#include "esp_private/regi2c_ctrl.h" +#include "regi2c_bbpll.h" +#include "hal/assert.h" +#include "hal/log.h" +#include "esp32c2/rom/rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MHZ (1000000) + +#define CLK_LL_PLL_80M_FREQ_MHZ (80) +#define CLK_LL_PLL_120M_FREQ_MHZ (120) + +#define CLK_LL_PLL_480M_FREQ_MHZ (480) + +/** + * @brief XTAL32K_CLK enable modes + */ +typedef enum { + CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL, //!< Enable the external clock signal for XTAL32K_CLK (i.e. EXT_OSC_CLK) +} clk_ll_xtal32k_enable_mode_t; + + +/** + * @brief Power up BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_enable(void) +{ + REG_CLR_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Power down BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void) +{ + REG_SET_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Enable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); +} + +/** + * @brief Disable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); +} + +/** + * @brief Get the state of the internal oscillator for RC_FAST_CLK + * + * @return True if the oscillator is enabled + */ +static inline bool clk_ll_rc_fast_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; +} + +/** + * @brief Enable the output from the internal oscillator to be passed into a configurable divider, + * which by default divides the input clock frequency by 256. i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Divider values other than 256 may be configured, but this facility is not currently needed, + * so is not exposed in the code. + * The output of the divider, RC_FAST_D256_CLK, is referred as 8md256 or simply d256 in reg. descriptions. + */ +static inline void clk_ll_rc_fast_d256_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Disable the output from the internal oscillator to be passed into a configurable divider. + * i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Disabling this divider could reduce power consumption. + */ +static inline void clk_ll_rc_fast_d256_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Get the state of the divider which is applied to the output from the internal oscillator (RC_FAST_CLK) + * + * @return True if the divided output is enabled + */ +static inline bool clk_ll_rc_fast_d256_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; +} + +/** + * @brief Enable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Get the state of the digital RC_FAST_CLK + * + * @return True if the digital RC_FAST_CLK is enabled + */ +static inline bool clk_ll_rc_fast_digi_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Enable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Enable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Disable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Get the state of the digital XTAL32K_CLK + * + * @return True if the digital XTAL32K_CLK is enabled + */ +static inline bool clk_ll_xtal32k_digi_is_enabled(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); +} + +/** + * @brief Get PLL_CLK frequency + * + * @return PLL clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_bbpll_get_freq_mhz(void) +{ + // ESP32C2 only support 480MHz PLL + uint32_t pll_freq_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); + switch (pll_freq_sel) { + case 1: // PLL_480M + return CLK_LL_PLL_480M_FREQ_MHZ; + default: + // Invalid PLL_FREQ_SEL value + return 0; + } +} + +/** + * @brief Set BBPLL frequency from XTAL source (Digital part) + * + * @param pll_freq_mhz PLL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_freq_mhz(uint32_t pll_freq_mhz) +{ + // ESP32C2 only support 480MHz PLL + HAL_ASSERT(pll_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ); + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 1); +} + +/** + * @brief Set BBPLL frequency from XTAL source (Analog part) + * + * @param pll_freq_mhz PLL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_config(uint32_t pll_freq_mhz, uint32_t xtal_freq_mhz) +{ + (void)pll_freq_mhz; + (void)xtal_freq_mhz; + // ESP32C2 only support 40M XTAL, all the parameters are given as 40M XTAL directly + uint8_t div_ref = 0; + uint8_t div7_0 = 8; + uint8_t dr1 = 0; + uint8_t dr3 = 0; + uint8_t dchgp = 5; + uint8_t dcur = 3; + uint8_t dbias = 2; + + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); + 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_VCO_DBIAS, dbias); +} + +/** + * @brief Select the clock source for CPU_CLK + * + * @param in_sel One of the clock sources in soc_cpu_clk_src_t + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_src(soc_cpu_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_CPU_CLK_SRC_XTAL: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 0); + break; + case SOC_CPU_CLK_SRC_PLL: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 1); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 2); + break; + default: + // Unsupported CPU_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for CPU_CLK + * + * @return Currently selected clock source (one of soc_cpu_clk_src_t values) + */ +static inline __attribute__((always_inline)) soc_cpu_clk_src_t clk_ll_cpu_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); + switch (clk_sel) { + 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; + default: + // Invalid SOC_CLK_SEL value + return SOC_CPU_CLK_SRC_INVALID; + } +} + +/** + * @brief Set CPU frequency from PLL clock + * + * @param cpu_mhz CPU frequency value, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_freq_mhz_from_pll(uint32_t cpu_mhz) +{ + switch (cpu_mhz) { + case CLK_LL_PLL_80M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 0); + break; + case CLK_LL_PLL_120M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 1); + break; + default: + // Unsupported CPU_CLK freq from PLL + abort(); + } +} + +/** + * @brief Get CPU_CLK frequency from PLL_CLK source + * + * @return CPU clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_freq_mhz_from_pll(void) +{ + uint32_t cpu_freq_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL); + switch (cpu_freq_sel) { + case 0: + return CLK_LL_PLL_80M_FREQ_MHZ; + case 1: + return CLK_LL_PLL_120M_FREQ_MHZ; + default: + // Invalid CPUPERIOD_SEL value + return 0; + } +} + +/** + * @brief Set CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @param divider Divider. Usually this divider is set to 1 in bootloader stage. PRE_DIV_CNT = divider - 1. + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, divider - 1); +} + +/** + * @brief Get CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @return Divider. Divider = (PRE_DIV_CNT + 1). + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(void) +{ + return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; +} + +/** + * @brief Select the clock source for RTC_SLOW_CLK + * + * @param in_sel One of the clock sources in soc_rtc_slow_clk_src_t + */ +static inline void clk_ll_rtc_slow_set_src(soc_rtc_slow_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 0); + break; + case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 1); + break; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 2); + break; + default: + // Unsupported RTC_SLOW_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_SLOW_CLK + * + * @return Currently selected clock source (one of soc_rtc_slow_clk_src_t values) + */ +static inline soc_rtc_slow_clk_src_t clk_ll_rtc_slow_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_SLOW_CLK_SRC_RC_SLOW; + case 1: + return SOC_RTC_SLOW_CLK_SRC_OSC_SLOW; + case 2: + return SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256; + default: + // Invalid ANA_CLK_RTC_SEL value + return SOC_RTC_SLOW_CLK_SRC_INVALID; + } +} + +/** + * @brief Select the clock source for RTC_FAST_CLK + * + * @param in_sel One of the clock sources in soc_rtc_fast_clk_src_t + */ +static inline void clk_ll_rtc_fast_set_src(soc_rtc_fast_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_FAST_CLK_SRC_XTAL_D2: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 0); + break; + case SOC_RTC_FAST_CLK_SRC_RC_FAST: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 1); + break; + default: + // Unsupported RTC_FAST_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_FAST_CLK + * + * @return Currently selected clock source (one of soc_rtc_fast_clk_src_t values) + */ +static inline soc_rtc_fast_clk_src_t clk_ll_rtc_fast_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_FAST_CLK_SRC_XTAL_D2; + case 1: + return SOC_RTC_FAST_CLK_SRC_RC_FAST; + default: + return SOC_RTC_FAST_CLK_SRC_INVALID; + } +} + +/** + * @brief Set RC_FAST_CLK divider. The output from the divider is passed into rtc_fast_clk MUX. + * + * @param divider Divider of RC_FAST_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_fast_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); +} + +/** + * @brief Get RC_FAST_CLK divider + * + * @return Divider. Divider = (CK8M_DIV_SEL + 1). + */ +static inline uint32_t clk_ll_rc_fast_get_divider(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL) + 1; +} + +/** + * @brief Set RC_SLOW_CLK divider + * + * @param divider Divider of RC_SLOW_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_slow_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); +} + +/************************* RTC STORAGE REGISTER STORE/LOAD **************************/ +/** + * @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 + */ +static inline void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) +{ + 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) +{ + // ESP32C2 has a fixed crystal frequency (40MHz), but we will still read from the RTC storage register + uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); + if ((xtal_freq_reg & UINT16_MAX) != RTC_XTAL_FREQ_40M) { + return 0; + } + return (uint32_t)RTC_XTAL_FREQ_40M; +} + +/** + * @brief Store APB_CLK frequency in RTC storage register + * + * Value of RTC_APB_FREQ_REG is stored as two copies in lower and upper 16-bit + * halves. These are the routines to work with that representation. + * + * @param apb_freq_hz APB frequency, in Hz + */ +static inline __attribute__((always_inline)) void clk_ll_apb_store_freq_hz(uint32_t apb_freq_hz) +{ + uint32_t val = apb_freq_hz >> 12; + WRITE_PERI_REG(RTC_APB_FREQ_REG, (val & UINT16_MAX) | ((val & UINT16_MAX) << 16)); +} + +/** + * @brief Load APB_CLK frequency from RTC storage register + * + * Value of RTC_APB_FREQ_REG is stored as two copies in lower and upper 16-bit + * halves. These are the routines to work with that representation. + * + * @return The stored APB frequency, in Hz + */ +static inline uint32_t clk_ll_apb_load_freq_hz(void) +{ + // Read from RTC storage register + uint32_t apb_freq_hz = (READ_PERI_REG(RTC_APB_FREQ_REG) & UINT16_MAX) << 12; + // Round to the nearest MHz + apb_freq_hz += MHZ / 2; + uint32_t remainder = apb_freq_hz % MHZ; + return apb_freq_hz - remainder; +} + +/** + * @brief Store RTC_SLOW_CLK calibration value in RTC storage register + * + * Value of RTC_SLOW_CLK_CAL_REG has to be in the same format as returned by rtc_clk_cal (microseconds, + * in Q13.19 fixed-point format). + * + * @param cal_value The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline void clk_ll_rtc_slow_store_cal(uint32_t cal_value) +{ + REG_WRITE(RTC_SLOW_CLK_CAL_REG, cal_value); +} + +/** + * @brief Load the calibration value of RTC_SLOW_CLK frequency from RTC storage register + * + * This value gets updated (i.e. rtc slow clock gets calibrated) every time RTC_SLOW_CLK source switches + * + * @return The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline uint32_t clk_ll_rtc_slow_load_cal(void) +{ + return REG_READ(RTC_SLOW_CLK_CAL_REG); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c2/include/hal/regi2c_ctrl_ll.h b/components/hal/esp32c2/include/hal/regi2c_ctrl_ll.h new file mode 100644 index 0000000000..0b9139357b --- /dev/null +++ b/components/hal/esp32c2/include/hal/regi2c_ctrl_ll.h @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/regi2c_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Reset (Disable) the I2C internal bus for all regi2c registers + */ +static inline void regi2c_ctrl_ll_i2c_reset(void) +{ + SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); +} + +/** + * @brief Enable the I2C internal bus to do I2C read/write operation to the BBPLL configuration register + */ +static inline void regi2c_ctrl_ll_i2c_bbpll_enable(void) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_BBPLL_M); +} + +/** + * @brief Start BBPLL self-calibration + */ +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_bbpll_calibration_start(void) +{ + REG_CLR_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); + REG_SET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c3/include/hal/clk_tree_ll.h b/components/hal/esp32c3/include/hal/clk_tree_ll.h new file mode 100644 index 0000000000..e80ba7157b --- /dev/null +++ b/components/hal/esp32c3/include/hal/clk_tree_ll.h @@ -0,0 +1,702 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/clk_tree_defs.h" +#include "soc/rtc.h" +#include "soc/system_reg.h" +#include "soc/rtc_cntl_reg.h" +#include "esp_private/regi2c_ctrl.h" +#include "regi2c_bbpll.h" +#include "hal/assert.h" +#include "hal/log.h" +#include "esp32c3/rom/rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MHZ (1000000) + +#define CLK_LL_PLL_80M_FREQ_MHZ (80) +#define CLK_LL_PLL_160M_FREQ_MHZ (160) + +#define CLK_LL_PLL_320M_FREQ_MHZ (320) +#define CLK_LL_PLL_480M_FREQ_MHZ (480) + +#define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ + .dac = 3, \ + .dres = 3, \ + .dgm = 3, \ + .dbuf = 1, \ +} + +/** + * @brief XTAL32K_CLK enable modes + */ +typedef enum { + CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL, //!< Enable the external 32kHz crystal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL, //!< Enable the external clock signal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_BOOTSTRAP, //!< Bootstrap the crystal oscillator for faster XTAL32K_CLK start up */ +} clk_ll_xtal32k_enable_mode_t; + +/** + * @brief XTAL32K_CLK configuration structure + */ +typedef struct { + uint32_t dac : 6; + uint32_t dres : 3; + uint32_t dgm : 3; + uint32_t dbuf: 1; +} clk_ll_xtal32k_config_t; + +/** + * @brief Power up BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_enable(void) +{ + REG_CLR_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Power down BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void) +{ + REG_SET_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Enable the 32kHz crystal oscillator + * + * @param mode Used to determine the xtal32k configuration parameters + */ +static inline void clk_ll_xtal32k_enable(clk_ll_xtal32k_enable_mode_t mode) +{ + // Configure xtal32k + clk_ll_xtal32k_config_t cfg = CLK_LL_XTAL32K_CONFIG_DEFAULT(); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf); + // Enable xtal32k xpd status + SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + if (mode == CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL) { + /* TODO ESP32-C3 IDF-2408:: external 32k source may need different settings */ + ; + } +} + +/** + * @brief Disable the 32kHz crystal oscillator + */ +static inline void clk_ll_xtal32k_disable(void) +{ + // Set xtal32k xpd to be controlled by software + SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE); + // Disable xtal32k xpd status + CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); +} + +/** + * @brief Get the state of the 32kHz crystal clock + * + * @return True if the 32kHz XTAL is enabled + */ +static inline bool clk_ll_xtal32k_is_enabled(void) +{ + uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG); + /* If xtal xpd is controlled by software */ + bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S; + /* If xtal xpd software control is on */ + bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S; + // disabled = xtal_xpd_sw && !xtal_xpd_st; enabled = !disbaled + bool enabled = !xtal_xpd_sw || xtal_xpd_st; + return enabled; +} + +/** + * @brief Enable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); +} + +/** + * @brief Disable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); +} + +/** + * @brief Get the state of the internal oscillator for RC_FAST_CLK + * + * @return True if the oscillator is enabled + */ +static inline bool clk_ll_rc_fast_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; +} + +/** + * @brief Enable the output from the internal oscillator to be passed into a configurable divider, + * which by default divides the input clock frequency by 256. i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Divider values other than 256 may be configured, but this facility is not currently needed, + * so is not exposed in the code. + * The output of the divider, RC_FAST_D256_CLK, is referred as 8md256 or simply d256 in reg. descriptions. + */ +static inline void clk_ll_rc_fast_d256_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Disable the output from the internal oscillator to be passed into a configurable divider. + * i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Disabling this divider could reduce power consumption. + */ +static inline void clk_ll_rc_fast_d256_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Get the state of the divider which is applied to the output from the internal oscillator (RC_FAST_CLK) + * + * @return True if the divided output is enabled + */ +static inline bool clk_ll_rc_fast_d256_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; +} + +/** + * @brief Enable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Get the state of the digital RC_FAST_CLK + * + * @return True if the digital RC_FAST_CLK is enabled + */ +static inline bool clk_ll_rc_fast_digi_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Enable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Enable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Disable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Get the state of the digital XTAL32K_CLK + * + * @return True if the digital XTAL32K_CLK is enabled + */ +static inline bool clk_ll_xtal32k_digi_is_enabled(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); +} + +/** + * @brief Get PLL_CLK frequency + * + * @return PLL clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_bbpll_get_freq_mhz(void) +{ + uint32_t pll_freq_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); + switch (pll_freq_sel) { + case 0: // PLL_320M + return CLK_LL_PLL_320M_FREQ_MHZ; + case 1: // PLL_480M + return CLK_LL_PLL_480M_FREQ_MHZ; + default: + return 0; + } +} + +/** + * @brief Set BBPLL frequency from XTAL source (Digital part) + * + * @param pll_freq_mhz PLL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_freq_mhz(uint32_t pll_freq_mhz) +{ + switch (pll_freq_mhz) { + case CLK_LL_PLL_320M_FREQ_MHZ: // PLL_320M + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 0); + break; + case CLK_LL_PLL_480M_FREQ_MHZ: // PLL_480M + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 1); + break; + default: + abort(); + } +} + +/** + * @brief Set BBPLL frequency from XTAL source (Analog part) + * + * @param pll_freq_mhz PLL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_config(uint32_t pll_freq_mhz, uint32_t xtal_freq_mhz) +{ + uint8_t div_ref; + uint8_t div7_0; + uint8_t dr1; + uint8_t dr3; + uint8_t dchgp; + uint8_t dcur; + uint8_t dbias; + + if (pll_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) { + /* Configure 480M PLL */ + switch (xtal_freq_mhz) { + case RTC_XTAL_FREQ_40M: + div_ref = 0; + div7_0 = 8; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + case RTC_XTAL_FREQ_32M: + div_ref = 1; + div7_0 = 26; + dr1 = 1; + dr3 = 1; + dchgp = 4; + dcur = 0; + dbias = 2; + break; + default: + div_ref = 0; + div7_0 = 8; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + } + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); + } else { + /* Configure 320M PLL */ + switch (xtal_freq_mhz) { + case RTC_XTAL_FREQ_40M: + div_ref = 0; + div7_0 = 4; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + case RTC_XTAL_FREQ_32M: + div_ref = 1; + div7_0 = 6; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + default: + div_ref = 0; + div7_0 = 4; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + } + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69); + } + 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 = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (1 << 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_VCO_DBIAS, dbias); + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 2); + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1); +} + +/** + * @brief Select the clock source for CPU_CLK + * + * @param in_sel One of the clock sources in soc_cpu_clk_src_t + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_src(soc_cpu_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_CPU_CLK_SRC_XTAL: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 0); + break; + case SOC_CPU_CLK_SRC_PLL: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 1); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 2); + break; + default: + // Unsupported CPU_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for CPU_CLK + * + * @return Currently selected clock source (one of soc_cpu_clk_src_t values) + */ +static inline __attribute__((always_inline)) soc_cpu_clk_src_t clk_ll_cpu_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); + switch (clk_sel) { + 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; + default: + // Invalid SOC_CLK_SEL value + return SOC_CPU_CLK_SRC_INVALID; + } +} + +/** + * @brief Set CPU frequency from PLL clock + * + * @param cpu_mhz CPU frequency value, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_freq_mhz_from_pll(uint32_t cpu_mhz) +{ + switch (cpu_mhz) { + case CLK_LL_PLL_80M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 0); + break; + case CLK_LL_PLL_160M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 1); + break; + default: + // Unsupported CPU_CLK freq from PLL + abort(); + } +} + +/** + * @brief Get CPU_CLK frequency from PLL_CLK source + * + * @return CPU clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_freq_mhz_from_pll(void) +{ + uint32_t cpu_freq_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL); + switch (cpu_freq_sel) { + case 0: + return CLK_LL_PLL_80M_FREQ_MHZ; + case 1: + return CLK_LL_PLL_160M_FREQ_MHZ; + default: + // Invalid CPUPERIOD_SEL value + return 0; + } +} + +/** + * @brief Set CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @param divider Divider. Usually this divider is set to 1 in bootloader stage. PRE_DIV_CNT = divider - 1. + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, divider - 1); +} + +/** + * @brief Get CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @return Divider. Divider = (PRE_DIV_CNT + 1). + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(void) +{ + return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; +} + +/** + * @brief Select the clock source for RTC_SLOW_CLK + * + * @param in_sel One of the clock sources in soc_rtc_slow_clk_src_t + */ +static inline void clk_ll_rtc_slow_set_src(soc_rtc_slow_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 0); + break; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 1); + break; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 2); + break; + default: + // Unsupported RTC_SLOW_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_SLOW_CLK + * + * @return Currently selected clock source (one of soc_rtc_slow_clk_src_t values) + */ +static inline soc_rtc_slow_clk_src_t clk_ll_rtc_slow_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_SLOW_CLK_SRC_RC_SLOW; + case 1: + return SOC_RTC_SLOW_CLK_SRC_XTAL32K; + case 2: + return SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256; + default: + // Invalid ANA_CLK_RTC_SEL value + return SOC_RTC_SLOW_CLK_SRC_INVALID; + } +} + +/** + * @brief Select the clock source for RTC_FAST_CLK + * + * @param in_sel One of the clock sources in soc_rtc_fast_clk_src_t + */ +static inline void clk_ll_rtc_fast_set_src(soc_rtc_fast_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_FAST_CLK_SRC_XTAL_D2: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 0); + break; + case SOC_RTC_FAST_CLK_SRC_RC_FAST: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 1); + break; + default: + // Unsupported RTC_FAST_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_FAST_CLK + * + * @return Currently selected clock source (one of soc_rtc_fast_clk_src_t values) + */ +static inline soc_rtc_fast_clk_src_t clk_ll_rtc_fast_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_FAST_CLK_SRC_XTAL_D2; + case 1: + return SOC_RTC_FAST_CLK_SRC_RC_FAST; + default: + return SOC_RTC_FAST_CLK_SRC_INVALID; + } +} + +/** + * @brief Set RC_FAST_CLK divider. The output from the divider is passed into rtc_fast_clk MUX. + * + * @param divider Divider of RC_FAST_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_fast_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); +} + +/** + * @brief Get RC_FAST_CLK divider + * + * @return Divider. Divider = (CK8M_DIV_SEL + 1). + */ +static inline uint32_t clk_ll_rc_fast_get_divider(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL) + 1; +} + +/** + * @brief Set RC_SLOW_CLK divider + * + * @param divider Divider of RC_SLOW_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_slow_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); +} + +/************************* RTC STORAGE REGISTER STORE/LOAD **************************/ +/** + * @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 + */ +static inline void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) +{ + 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 & UINT16_MAX; + } + // If the format in reg is invalid + return 0; +} + +/** + * @brief Store APB_CLK frequency in RTC storage register + * + * Value of RTC_APB_FREQ_REG is stored as two copies in lower and upper 16-bit + * halves. These are the routines to work with that representation. + * + * @param apb_freq_hz APB frequency, in Hz + */ +static inline __attribute__((always_inline)) void clk_ll_apb_store_freq_hz(uint32_t apb_freq_hz) +{ + uint32_t val = apb_freq_hz >> 12; + WRITE_PERI_REG(RTC_APB_FREQ_REG, (val & UINT16_MAX) | ((val & UINT16_MAX) << 16)); +} + +/** + * @brief Load APB_CLK frequency from RTC storage register + * + * Value of RTC_APB_FREQ_REG is stored as two copies in lower and upper 16-bit + * halves. These are the routines to work with that representation. + * + * @return The stored APB frequency, in Hz + */ +static inline uint32_t clk_ll_apb_load_freq_hz(void) +{ + // Read from RTC storage register + uint32_t apb_freq_hz = (READ_PERI_REG(RTC_APB_FREQ_REG) & UINT16_MAX) << 12; + // Round to the nearest MHz + apb_freq_hz += MHZ / 2; + uint32_t remainder = apb_freq_hz % MHZ; + return apb_freq_hz - remainder; +} + +/** + * @brief Store RTC_SLOW_CLK calibration value in RTC storage register + * + * Value of RTC_SLOW_CLK_CAL_REG has to be in the same format as returned by rtc_clk_cal (microseconds, + * in Q13.19 fixed-point format). + * + * @param cal_value The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline void clk_ll_rtc_slow_store_cal(uint32_t cal_value) +{ + REG_WRITE(RTC_SLOW_CLK_CAL_REG, cal_value); +} + +/** + * @brief Load the calibration value of RTC_SLOW_CLK frequency from RTC storage register + * + * This value gets updated (i.e. rtc slow clock gets calibrated) every time RTC_SLOW_CLK source switches + * + * @return The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline uint32_t clk_ll_rtc_slow_load_cal(void) +{ + return REG_READ(RTC_SLOW_CLK_CAL_REG); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c3/include/hal/regi2c_ctrl_ll.h b/components/hal/esp32c3/include/hal/regi2c_ctrl_ll.h new file mode 100644 index 0000000000..0b9139357b --- /dev/null +++ b/components/hal/esp32c3/include/hal/regi2c_ctrl_ll.h @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/regi2c_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Reset (Disable) the I2C internal bus for all regi2c registers + */ +static inline void regi2c_ctrl_ll_i2c_reset(void) +{ + SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); +} + +/** + * @brief Enable the I2C internal bus to do I2C read/write operation to the BBPLL configuration register + */ +static inline void regi2c_ctrl_ll_i2c_bbpll_enable(void) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_BBPLL_M); +} + +/** + * @brief Start BBPLL self-calibration + */ +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_bbpll_calibration_start(void) +{ + REG_CLR_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); + REG_SET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h2/include/hal/clk_tree_ll.h b/components/hal/esp32h2/include/hal/clk_tree_ll.h new file mode 100644 index 0000000000..2c2c4295ec --- /dev/null +++ b/components/hal/esp32h2/include/hal/clk_tree_ll.h @@ -0,0 +1,572 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/soc.h" +#include "soc/clk_tree_defs.h" +#include "soc/rtc.h" +#include "soc/system_reg.h" +#include "soc/clkrst_reg.h" +#include "soc/rtc_cntl_reg.h" +#include "esp_private/regi2c_ctrl.h" +#include "regi2c_bbpll.h" +#include "hal/assert.h" +#include "hal/log.h" +#include "esp32h2/rom/rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MHZ (1000000) + +#define CLK_LL_PLL_96M_FREQ_MHZ (96) + +#define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ + .dac = 3, \ + .dres = 3, \ + .dgm = 3, \ + .dbuf = 1, \ +} + +#define CLK_LL_RC32K_DFREQ_DEFAULT 707 + +/** + * @brief XTAL32K_CLK enable modes + */ +typedef enum { + CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL, //!< Enable the external 32kHz crystal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL, //!< Enable the external clock signal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_BOOTSTRAP, //!< Bootstrap the crystal oscillator for faster XTAL32K_CLK start up */ +} clk_ll_xtal32k_enable_mode_t; + +/** + * @brief XTAL32K_CLK configuration structure + */ +typedef struct { + uint32_t dac : 6; + uint32_t dres : 3; + uint32_t dgm : 3; + uint32_t dbuf: 1; +} clk_ll_xtal32k_config_t; + +/** + * @brief Power up BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_enable(void) +{ + REG_CLR_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Power down BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void) +{ + REG_SET_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Enable the 32kHz crystal oscillator + * + * @param mode Used to determine the xtal32k configuration parameters + */ +static inline void clk_ll_xtal32k_enable(clk_ll_xtal32k_enable_mode_t mode) +{ + // Configure xtal32k (or only for mode == CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL?) + clk_ll_xtal32k_config_t cfg = CLK_LL_XTAL32K_CONFIG_DEFAULT(); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf); + // Enable xtal32k xpd status + SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + if (mode == CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL) { + // Not supported yet? + ; + } +} + +/** + * @brief Disable the 32kHz crystal oscillator + */ +static inline void clk_ll_xtal32k_disable(void) +{ + // Set xtal32k xpd to be controlled by software + SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE); + // Disable xtal32k xpd status + CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); +} + +/** + * @brief Get the state of the 32kHz crystal clock + * + * @return True if the 32kHz XTAL is enabled + */ +static inline bool clk_ll_xtal32k_is_enabled(void) +{ + uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG); + /* If xtal xpd is controlled by software */ + bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S; + /* If xtal xpd software control is on */ + bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S; + // disabled = xtal_xpd_sw && !xtal_xpd_st; enabled = !disbaled + bool enabled = !xtal_xpd_sw || xtal_xpd_st; + return enabled; +} + +/** + * @brief Enable the internal oscillator output for RC32K_CLK + */ +static inline void clk_ll_rc32k_enable(void) +{ + // Configure rc32k + REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_DFREQ, CLK_LL_RC32K_DFREQ_DEFAULT); + // Enable rc32k xpd status + SET_PERI_REG_MASK(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_XPD); +} + +/** + * @brief Disable the internal oscillator output for RC32k_CLK + */ +static inline void clk_ll_rc32k_disable(void) +{ + // Configure rc32k + REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_DFREQ, CLK_LL_RC32K_DFREQ_DEFAULT); + // Disable rc32k xpd status + CLEAR_PERI_REG_MASK(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_XPD); +} + +/** + * @brief Enable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Get the state of the digital RC_FAST_CLK + * + * @return True if the digital RC_FAST_CLK is enabled + */ +static inline bool clk_ll_rc_fast_digi_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Enable the digital RC32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc32k_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN_M); +} + +/** + * @brief Disable the digital RC32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc32k_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN_M); +} + +/** + * @brief Get the state of the digital RC32K_CLK + * + * @return True if the digital RC32K_CLK is enabled + */ +static inline bool clk_ll_rc32k_digi_is_enabled(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN); +} + +/** + * @brief Enable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Disable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Get the state of the digital XTAL32K_CLK + * + * @return True if the digital XTAL32K_CLK is enabled + */ +static inline bool clk_ll_xtal32k_digi_is_enabled(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); +} + +/** + * @brief Get PLL_CLK frequency + * + * @return PLL clock frequency, in MHz + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_bbpll_get_freq_mhz(void) +{ + uint32_t bbpll_freq = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SPLL_FREQ); + HAL_ASSERT(bbpll_freq == CLK_LL_PLL_96M_FREQ_MHZ); + return bbpll_freq; +} + +/** + * @brief Set BBPLL frequency from XTAL source (Digital part) + * + * @param pll_freq_mhz PLL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_freq_mhz(uint32_t pll_freq_mhz) +{ + (void)pll_freq_mhz; + // ESP32H2 bbpll frequency cannot be changed, fixed to 96MHz + // Do nothing +} + +/** + * @brief Set BBPLL frequency from XTAL source (Analog part) + * + * @param pll_freq_mhz PLL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_config(uint32_t pll_freq_mhz, uint32_t xtal_freq_mhz) +{ + (void)xtal_freq_mhz; + switch (pll_freq_mhz) { + case CLK_LL_PLL_96M_FREQ_MHZ: // PLL_96M + /* set up PLL by analog control registers */ + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, 0); + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DIV, 1); // I2C_BBPLL_OC_DIV_5_0 + break; + default: + break; + } + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 3); + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1); +} + +/** + * @brief Select the clock source for CPU_CLK + * + * @param in_sel One of the clock sources in soc_cpu_clk_src_t + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_src(soc_cpu_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_CPU_CLK_SRC_XTAL: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 0); + break; + case SOC_CPU_CLK_SRC_PLL: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 1); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 2); + break; + case SOC_CPU_CLK_SRC_XTAL_D2: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 3); + break; + default: + // Unsupported CPU_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for CPU_CLK + * + * @return Currently selected clock source (one of soc_cpu_clk_src_t values) + */ +static inline __attribute__((always_inline)) soc_cpu_clk_src_t clk_ll_cpu_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); + switch (clk_sel) { + 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 3: + return SOC_CPU_CLK_SRC_XTAL_D2; + default: + return SOC_CPU_CLK_SRC_INVALID; + } +} + +/** + * @brief Set CPU_CLK divider. freq of CPU_CLK = freq of CPU clock source / divider + * + * @param divider Divider. CPU_DIV_NUM = divider - 1. + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + REG_SET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_CPU_DIV_NUM, divider - 1); +} + +/** + * @brief Get CPU_CLK divider + * + * @return Divider. Divider = (CPU_DIV_NUM + 1). + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(void) +{ + return REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_CPU_DIV_NUM) + 1; +} + +/** + * @brief Set AHB_CLK divider. freq of AHB_CLK = freq of CPU_CLK / divider + * + * @param divider Divider. AHB_DIV_NUM = divider - 1. + */ +static inline void clk_ll_ahb_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM, divider - 1); +} + +/** + * @brief Get AHB_CLK divider + * + * @return Divider. Divider = (AHB_DIV_NUM + 1). + */ +static inline uint32_t clk_ll_ahb_get_divider(void) +{ + return REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM) + 1; +} + +/** + * @brief Set APB_CLK divider. freq of APB_CLK = freq of AHB_CLK / divider + * + * @param divider Divider. APB_DIV_NUM = divider - 1. + */ +static inline void clk_ll_apb_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM, divider - 1); +} + +/** + * @brief Get APB_CLK divider + * + * @return Divider. Divider = (APB_DIV_NUM + 1). + */ +static inline uint32_t clk_ll_apb_get_divider(void) +{ + return REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM) + 1; +} + +/** + * @brief Select the clock source for RTC_SLOW_CLK + * + * @param in_sel One of the clock sources in soc_rtc_slow_clk_src_t + */ +static inline void clk_ll_rtc_slow_set_src(soc_rtc_slow_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 0); + break; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 1); + break; + case SOC_RTC_SLOW_CLK_SRC_RC32K: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 2); + break; + default: + // Unsupported RTC_SLOW_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_SLOW_CLK + * + * @return Currently selected clock source (one of soc_rtc_slow_clk_src_t values) + */ +static inline soc_rtc_slow_clk_src_t clk_ll_rtc_slow_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_SLOW_CLK_SRC_RC_SLOW; + case 1: + return SOC_RTC_SLOW_CLK_SRC_XTAL32K; + case 2: + return SOC_RTC_SLOW_CLK_SRC_RC32K; + default: + // Invalid ANA_CLK_RTC_SEL value + return SOC_RTC_SLOW_CLK_SRC_INVALID; + } +} + +/** + * @brief Select the clock source for RTC_FAST_CLK + * + * @param in_sel One of the clock sources in soc_rtc_fast_clk_src_t + */ +static inline void clk_ll_rtc_fast_set_src(soc_rtc_fast_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_FAST_CLK_SRC_XTAL_D2: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 0); + break; + case SOC_RTC_FAST_CLK_SRC_RC_FAST: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 1); + break; + default: + // Unsupported RTC_FAST_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_FAST_CLK + * + * @return Currently selected clock source (one of soc_rtc_fast_clk_src_t values) + */ +static inline soc_rtc_fast_clk_src_t clk_ll_rtc_fast_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_FAST_CLK_SRC_XTAL_D2; + case 1: + return SOC_RTC_FAST_CLK_SRC_RC_FAST; + default: + return SOC_RTC_FAST_CLK_SRC_INVALID; + } +} + +/** + * @brief Set RC_FAST_CLK divider. The output from the divider is passed into rtc_fast_clk MUX. + * + * @param divider Divider of RC_FAST_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_fast_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); +} + +/** + * @brief Get RC_FAST_CLK divider + * + * @return Divider. Divider = (CK8M_DIV_SEL + 1). + */ +static inline uint32_t clk_ll_rc_fast_get_divider(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL) + 1; +} + +/** + * @brief Set RC_SLOW_CLK divider + * + * @param divider Divider of RC_SLOW_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_slow_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); +} + +/************************* RTC STORAGE REGISTER STORE/LOAD **************************/ +/** + * @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 + */ +static inline void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) +{ + 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) +{ + // ESP32H2 has a fixed crystal frequency (32MHz), but we will still read from the RTC storage register + uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); + if ((xtal_freq_reg & UINT16_MAX) != RTC_XTAL_FREQ_32M) { + return 0; + } + return (uint32_t)RTC_XTAL_FREQ_32M; +} + +/** + * @brief Store APB_CLK frequency in RTC storage register + * + * Value of RTC_APB_FREQ_REG is stored as two copies in lower and upper 16-bit + * halves. These are the routines to work with that representation. + * + * @param apb_freq_hz APB frequency, in Hz + */ +static inline __attribute__((always_inline)) void clk_ll_apb_store_freq_hz(uint32_t apb_freq_hz) +{ + uint32_t val = apb_freq_hz >> 12; + WRITE_PERI_REG(RTC_APB_FREQ_REG, (val & UINT16_MAX) | ((val & UINT16_MAX) << 16)); +} + +/** + * @brief Store RTC_SLOW_CLK calibration value in RTC storage register + * + * Value of RTC_SLOW_CLK_CAL_REG has to be in the same format as returned by rtc_clk_cal (microseconds, + * in Q13.19 fixed-point format). + * + * @param cal_value The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline void clk_ll_rtc_slow_store_cal(uint32_t cal_value) +{ + REG_WRITE(RTC_SLOW_CLK_CAL_REG, cal_value); +} + +/** + * @brief Load the calibration value of RTC_SLOW_CLK frequency from RTC storage register + * + * This value gets updated (i.e. rtc slow clock gets calibrated) every time RTC_SLOW_CLK source switches + * + * @return The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline uint32_t clk_ll_rtc_slow_load_cal(void) +{ + return REG_READ(RTC_SLOW_CLK_CAL_REG); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h2/include/hal/regi2c_ctrl_ll.h b/components/hal/esp32h2/include/hal/regi2c_ctrl_ll.h new file mode 100644 index 0000000000..52e2158d24 --- /dev/null +++ b/components/hal/esp32h2/include/hal/regi2c_ctrl_ll.h @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/regi2c_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Reset (Disable) the I2C internal bus for all regi2c registers + */ +static inline void regi2c_ctrl_ll_i2c_reset(void) +{ + // On ESP32-H2, don't need to do anything (indeed do need? not fully supported yet?) + + // SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); +} + +/** + * @brief Enable the I2C internal bus to do I2C read/write operation to the BBPLL configuration register + */ +static inline void regi2c_ctrl_ll_i2c_bbpll_enable(void) +{ + // On ESP32-H2, don't need to do anything (indeed do need? not fully supported yet?) + + // CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_BBPLL_M); +} + +/** + * @brief Start BBPLL self-calibration + */ +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_bbpll_calibration_start(void) +{ + REG_CLR_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); + REG_SET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); +} + +/** + * @brief Stop BBPLL self-calibration + * + * This helps to prevent BBPLL jitter (phenomenon is significant on ESP32H2) + */ +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_bbpll_calibration_stop(void) +{ + REG_CLR_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); + REG_SET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); +} + +/** + * @brief Check whether BBPLL calibration is done + * + * @return True if calibration is done; otherwise false + */ +static inline __attribute__((always_inline)) bool regi2c_ctrl_ll_bbpll_calibration_is_done(void) +{ + return REG_GET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_CAL_DONE); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/include/hal/clk_tree_ll.h b/components/hal/esp32s2/include/hal/clk_tree_ll.h new file mode 100644 index 0000000000..d6d60c3254 --- /dev/null +++ b/components/hal/esp32s2/include/hal/clk_tree_ll.h @@ -0,0 +1,749 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/clk_tree_defs.h" +#include "soc/rtc.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/dport_reg.h" +#include "soc/syscon_reg.h" +#include "esp_private/regi2c_ctrl.h" +#include "regi2c_bbpll.h" +#include "regi2c_apll.h" +#include "hal/assert.h" +#include "esp32s2/rom/rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MHZ (1000000) + +#define CLK_LL_PLL_80M_FREQ_MHZ (80) +#define CLK_LL_PLL_160M_FREQ_MHZ (160) +#define CLK_LL_PLL_240M_FREQ_MHZ (240) + +#define CLK_LL_PLL_320M_FREQ_MHZ (320) +#define CLK_LL_PLL_480M_FREQ_MHZ (480) + +// ESP32S2 only supports 40MHz crystal +#define CLK_LL_XTAL_FREQ_MHZ (40) + +/* APLL configuration parameters */ +#define CLK_LL_APLL_SDM_STOP_VAL_1 0x09 +#define CLK_LL_APLL_SDM_STOP_VAL_2_REV0 0x69 +#define CLK_LL_APLL_SDM_STOP_VAL_2_REV1 0x49 + +/* APLL calibration parameters */ +#define CLK_LL_APLL_CAL_DELAY_1 0x0f +#define CLK_LL_APLL_CAL_DELAY_2 0x3f +#define CLK_LL_APLL_CAL_DELAY_3 0x1f + +#define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ + .dac = 3, \ + .dres = 3, \ + .dgm = 3, \ + .dbuf = 1, \ +} + +/** + * @brief XTAL32K_CLK enable modes + */ +typedef enum { + CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL, //!< Enable the external 32kHz crystal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL, //!< Enable the external clock signal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_BOOTSTRAP, //!< Bootstrap the crystal oscillator for faster XTAL32K_CLK start up */ +} clk_ll_xtal32k_enable_mode_t; + +/** + * @brief XTAL32K_CLK configuration structure + */ +typedef struct { + uint32_t dac : 6; + uint32_t dres : 3; + uint32_t dgm : 3; + uint32_t dbuf: 1; +} clk_ll_xtal32k_config_t; + +/** + * @brief Power up BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Power down BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Power up APLL circuit + */ +static inline void clk_ll_apll_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU); +} + +/** + * @brief Power down APLL circuit + */ +static inline void clk_ll_apll_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU); +} + +/** + * @brief Set APLL configuration + * + * @param o_div Frequency divider, 0..31 + * @param sdm0 Frequency adjustment parameter, 0..255 + * @param sdm1 Frequency adjustment parameter, 0..255 + * @param sdm2 Frequency adjustment parameter, 0..63 + */ +static inline void clk_ll_apll_set_config(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2) +{ + REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM2, sdm2); + REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM0, sdm0); + REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM1, sdm1); + REGI2C_WRITE(I2C_APLL, I2C_APLL_SDM_STOP, CLK_LL_APLL_SDM_STOP_VAL_1); + REGI2C_WRITE(I2C_APLL, I2C_APLL_SDM_STOP, CLK_LL_APLL_SDM_STOP_VAL_2_REV1); + REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OR_OUTPUT_DIV, o_div); +} + +/** + * @brief Set APLL calibration parameters + */ +static inline void clk_ll_apll_set_calibration(void) +{ + REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, CLK_LL_APLL_CAL_DELAY_1); + REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, CLK_LL_APLL_CAL_DELAY_2); + REGI2C_WRITE(I2C_APLL, I2C_APLL_IR_CAL_DELAY, CLK_LL_APLL_CAL_DELAY_3); +} + +/** + * @brief Check whether APLL calibration is done + * + * @return True if calibration is done; otherwise false + */ +static inline bool clk_ll_apll_calibration_is_done(void) +{ + return REGI2C_READ_MASK(I2C_APLL, I2C_APLL_OR_CAL_END); +} + +/** + * @brief Enable the 32kHz crystal oscillator + * + * @param mode Used to determine the xtal32k configuration parameters + */ +static inline void clk_ll_xtal32k_enable(clk_ll_xtal32k_enable_mode_t mode) +{ + // Configure xtal32k + clk_ll_xtal32k_config_t cfg = CLK_LL_XTAL32K_CONFIG_DEFAULT(); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf); + // Enable xtal32k xpd status + SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + if (mode == CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL) { + /* TODO: external 32k source may need different settings */ + ; + } +} + +/** + * @brief Disable the 32kHz crystal oscillator + */ +static inline void clk_ll_xtal32k_disable(void) +{ + // Set xtal32k xpd to be controlled by software + SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE); + // Disable xtal32k xpd status + CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); +} + +/** + * @brief Get the state of the 32kHz crystal clock + * + * @return True if the 32kHz XTAL is enabled + */ +static inline bool clk_ll_xtal32k_is_enabled(void) +{ + uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG); + /* If xtal xpd is controlled by software */ + bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S; + /* If xtal xpd software control is on */ + bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S; + // disabled = xtal_xpd_sw && !xtal_xpd_st; enabled = !disbaled + bool enabled = !xtal_xpd_sw || xtal_xpd_st; + return enabled; +} + +/** + * @brief Enable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); +} + +/** + * @brief Disable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); +} + +/** + * @brief Get the state of the internal oscillator for RC_FAST_CLK + * + * @return True if the oscillator is enabled + */ +static inline bool clk_ll_rc_fast_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; +} + +/** + * @brief Enable the output from the internal oscillator to be passed into a configurable divider, + * which by default divides the input clock frequency by 256. i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Divider values other than 256 may be configured, but this facility is not currently needed, + * so is not exposed in the code. + * The output of the divider, RC_FAST_D256_CLK, is referred as 8md256 or simply d256 in reg. descriptions. + */ +static inline void clk_ll_rc_fast_d256_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Disable the output from the internal oscillator to be passed into a configurable divider. + * i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Disabling this divider could reduce power consumption. + */ +static inline void clk_ll_rc_fast_d256_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Get the state of the divider which is applied to the output from the internal oscillator (RC_FAST_CLK) + * + * @return True if the divided output is enabled + */ +static inline bool clk_ll_rc_fast_d256_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; +} + +/** + * @brief Enable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Get the state of the digital RC_FAST_CLK + * + * @return True if the digital RC_FAST_CLK is enabled + */ +static inline bool clk_ll_rc_fast_digi_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Enable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Enable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Disable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Get the state of the digital XTAL32K_CLK + * + * @return True if the digital XTAL32K_CLK is enabled + */ +static inline bool clk_ll_xtal32k_digi_is_enabled(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); +} + +/** + * @brief Get PLL_CLK frequency + * + * @return PLL clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_bbpll_get_freq_mhz(void) +{ + uint32_t pll_freq_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_PLL_FREQ_SEL); + switch (pll_freq_sel) { + case 0: // PLL_320M + return CLK_LL_PLL_320M_FREQ_MHZ; + case 1: // PLL_480M + return CLK_LL_PLL_480M_FREQ_MHZ; + default: + return 0; + } +} + +/** + * @brief Set BBPLL frequency from XTAL source (digital part) + * + * @param pll_freq_mhz PLL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_freq_mhz(uint32_t pll_freq_mhz) +{ + switch (pll_freq_mhz) { + case CLK_LL_PLL_320M_FREQ_MHZ: // PLL_320M + CLEAR_PERI_REG_MASK(DPORT_CPU_PER_CONF_REG, DPORT_PLL_FREQ_SEL); + break; + case CLK_LL_PLL_480M_FREQ_MHZ: // PLL_480M + SET_PERI_REG_MASK(DPORT_CPU_PER_CONF_REG, DPORT_PLL_FREQ_SEL); + break; + default: + abort(); + } +} + +/** + * @brief Set BBPLL frequency from XTAL source (Analog part) + * + * @param pll_freq_mhz PLL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_config(uint32_t pll_freq_mhz, uint32_t xtal_freq_mhz) +{ + (void)xtal_freq_mhz; + uint8_t div_ref; + uint8_t div7_0; + uint8_t dr1; + uint8_t dr3; + uint8_t dchgp; + uint8_t dcur; + + if (pll_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) { + /* Configure 480M PLL */ + div_ref = 0; + div7_0 = 8; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 4; + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); + } else { + /* Configure 320M PLL */ + div_ref = 0; + div7_0 = 4; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 5; + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69); + } + 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 = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (1 << 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); +} + +/** + * @brief Enable BBPLL self-calibration + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_calibration_enable(void) +{ + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_IR_CAL_ENX_CAP, 1); +} + +/** + * @brief Check whether BBPLL calibration is done + * + * @param ext_cap Steps write to I2C_BBPLL_IR_CAL_EXT_CAP + * + * @return True if calibration is done; otherwise false + */ +static inline __attribute__((always_inline)) bool clk_ll_bbpll_calibration_is_done(uint32_t ext_cap) +{ + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_IR_CAL_EXT_CAP, ext_cap); + return REGI2C_READ_MASK(I2C_BBPLL, I2C_BBPLL_OR_CAL_CAP) == 0; +} + +/** + * @brief Select the clock source for CPU_CLK + * + * @param in_sel One of the clock sources in soc_cpu_clk_src_t + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_src(soc_cpu_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_CPU_CLK_SRC_XTAL: + REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, 0); + break; + case SOC_CPU_CLK_SRC_PLL: + REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, 1); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, 2); + break; + case SOC_CPU_CLK_SRC_APLL: + REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, 3); + break; + default: + // Unsupported CPU_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for CPU_CLK + * + * @return Currently selected clock source (one of soc_cpu_clk_src_t values) + */ +static inline __attribute__((always_inline)) soc_cpu_clk_src_t clk_ll_cpu_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL); + switch (clk_sel) { + 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 3: + return SOC_CPU_CLK_SRC_APLL; + default: + return SOC_CPU_CLK_SRC_INVALID; + } +} + +/** + * @brief Set CPU frequency from PLL clock + * + * @param cpu_mhz CPU frequency value, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_freq_mhz_from_pll(uint32_t cpu_mhz) +{ + switch (cpu_mhz) { + case CLK_LL_PLL_80M_FREQ_MHZ: + REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 0); + break; + case CLK_LL_PLL_160M_FREQ_MHZ: + REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 1); + break; + case CLK_LL_PLL_240M_FREQ_MHZ: + REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 2); + break; + default: + // Unsupported CPU_CLK freq from PLL + abort(); + } +} + +/** + * @brief Get CPU_CLK frequency from PLL_CLK source + * + * @return CPU clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_freq_mhz_from_pll(void) +{ + uint32_t cpu_freq_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL); + switch (cpu_freq_sel) { + case 0: + return CLK_LL_PLL_80M_FREQ_MHZ; + case 1: + return CLK_LL_PLL_160M_FREQ_MHZ; + case 2: + // When PLL frequency selection is 320MHz but CPU frequency selection is 240MHz, it is an undetermined state. + // It is checked in the upper layer. + return CLK_LL_PLL_240M_FREQ_MHZ; + default: + // Invalid CPUPERIOD_SEL value + return 0; + } +} + +/** + * @brief Set CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @param divider Divider. Usually this divider is set to 1 in bootloader stage. PRE_DIV_CNT = divider - 1. + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_PRE_DIV_CNT, divider - 1); +} + +/** + * @brief Get CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @return Divider. Divider = (PRE_DIV_CNT + 1). + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(void) +{ + return REG_GET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_PRE_DIV_CNT) + 1; +} + +/** + * @brief Set REF_TICK divider to make REF_TICK frequency at 1MHz + * + * @param cpu_clk_src Selected CPU clock source (one of soc_cpu_clk_src_t values) + * + * When PLL, APLL, or XTAL is set as CPU clock source, divider = XTAL_CLK freq in Hz / 1MHz. + * When RC_FAST is set as CPU clock source, divider = RC_FAST_CLK freq in Hz / 1MHz. + * Value in register = divider - 1. + */ +static inline __attribute__((always_inline)) void clk_ll_ref_tick_set_divider(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + case SOC_CPU_CLK_SRC_PLL: + case SOC_CPU_CLK_SRC_APLL: + REG_SET_FIELD(SYSCON_TICK_CONF_REG, SYSCON_XTAL_TICK_NUM, CLK_LL_XTAL_FREQ_MHZ - 1); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + REG_SET_FIELD(SYSCON_TICK_CONF_REG, SYSCON_CK8M_TICK_NUM, 8 - 1); + break; + default: + // Unsupported CPU_CLK mux input sel + abort(); + } +} + +/** + * @brief Select the clock source for RTC_SLOW_CLK + * + * @param in_sel One of the clock sources in soc_rtc_slow_clk_src_t + */ +static inline void clk_ll_rtc_slow_set_src(soc_rtc_slow_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 0); + break; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 1); + break; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 2); + break; + default: + // Unsupported RTC_SLOW_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_SLOW_CLK + * + * @return Currently selected clock source (one of soc_rtc_slow_clk_src_t values) + */ +static inline soc_rtc_slow_clk_src_t clk_ll_rtc_slow_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_SLOW_CLK_SRC_RC_SLOW; + case 1: + return SOC_RTC_SLOW_CLK_SRC_XTAL32K; + case 2: + return SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256; + default: + // Invalid ANA_CLK_RTC_SEL value + return SOC_RTC_SLOW_CLK_SRC_INVALID; + } +} + +/** + * @brief Select the clock source for RTC_FAST_CLK + * + * @param in_sel One of the clock sources in soc_rtc_fast_clk_src_t + */ +static inline void clk_ll_rtc_fast_set_src(soc_rtc_fast_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_FAST_CLK_SRC_XTAL_D4: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 0); + break; + case SOC_RTC_FAST_CLK_SRC_RC_FAST: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 1); + break; + default: + // Unsupported RTC_FAST_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_FAST_CLK + * + * @return Currently selected clock source (one of soc_rtc_fast_clk_src_t values) + */ +static inline soc_rtc_fast_clk_src_t clk_ll_rtc_fast_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_FAST_CLK_SRC_XTAL_D4; + case 1: + return SOC_RTC_FAST_CLK_SRC_RC_FAST; + default: + return SOC_RTC_FAST_CLK_SRC_INVALID; + } +} + +/** + * @brief Set RC_FAST_CLK divider. The output from the divider is passed into rtc_fast_clk MUX. + * + * @param divider Divider of RC_FAST_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_fast_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); +} + +/** + * @brief Get RC_FAST_CLK divider + * + * @return Divider. Divider = (CK8M_DIV_SEL + 1). + */ +static inline uint32_t clk_ll_rc_fast_get_divider(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL) + 1; +} + +/** + * @brief Set RC_SLOW_CLK divider + * + * @param divider Divider of RC_SLOW_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_slow_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); +} + +/************************* RTC STORAGE REGISTER STORE/LOAD **************************/ +/** + * @brief Store APB_CLK frequency in RTC storage register + * + * Value of RTC_APB_FREQ_REG is stored as two copies in lower and upper 16-bit + * halves. These are the routines to work with that representation. + * + * @param apb_freq_hz APB frequency, in Hz + */ +static inline __attribute__((always_inline)) void clk_ll_apb_store_freq_hz(uint32_t apb_freq_hz) +{ + uint32_t val = apb_freq_hz >> 12; + WRITE_PERI_REG(RTC_APB_FREQ_REG, (val & UINT16_MAX) | ((val & UINT16_MAX) << 16)); +} + +/** + * @brief Load APB_CLK frequency from RTC storage register + * + * Value of RTC_APB_FREQ_REG is stored as two copies in lower and upper 16-bit + * halves. These are the routines to work with that representation. + * + * @return The stored APB frequency, in Hz + */ +static inline uint32_t clk_ll_apb_load_freq_hz(void) +{ + // Read from RTC storage register + uint32_t apb_freq_hz = (READ_PERI_REG(RTC_APB_FREQ_REG) & UINT16_MAX) << 12; + // Round to the nearest MHz + apb_freq_hz += MHZ / 2; + uint32_t remainder = apb_freq_hz % MHZ; + return apb_freq_hz - remainder; +} + +/** + * @brief Store RTC_SLOW_CLK calibration value in RTC storage register + * + * Value of RTC_SLOW_CLK_CAL_REG has to be in the same format as returned by rtc_clk_cal (microseconds, + * in Q13.19 fixed-point format). + * + * @param cal_value The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline void clk_ll_rtc_slow_store_cal(uint32_t cal_value) +{ + REG_WRITE(RTC_SLOW_CLK_CAL_REG, cal_value); +} + +/** + * @brief Load the calibration value of RTC_SLOW_CLK frequency from RTC storage register + * + * This value gets updated (i.e. rtc slow clock gets calibrated) every time RTC_SLOW_CLK source switches + * + * @return The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline uint32_t clk_ll_rtc_slow_load_cal(void) +{ + return REG_READ(RTC_SLOW_CLK_CAL_REG); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/include/hal/regi2c_ctrl_ll.h b/components/hal/esp32s2/include/hal/regi2c_ctrl_ll.h new file mode 100644 index 0000000000..aa0e449607 --- /dev/null +++ b/components/hal/esp32s2/include/hal/regi2c_ctrl_ll.h @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/regi2c_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Reset (Disable) the I2C internal bus for all regi2c registers + */ +static inline void regi2c_ctrl_ll_i2c_reset(void) +{ + SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); +} + +/** + * @brief Enable the I2C internal bus to do I2C read/write operation to the BBPLL configuration register + */ +static inline void regi2c_ctrl_ll_i2c_bbpll_enable(void) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_BBPLL_M); +} + +/** + * @brief Enable the I2C internal bus to do I2C read/write operation to the APLL configuration register + */ +static inline void regi2c_ctrl_ll_i2c_apll_enable(void) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_APLL_M); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/clk_tree_ll.h b/components/hal/esp32s3/include/hal/clk_tree_ll.h new file mode 100644 index 0000000000..3aa8ec78f9 --- /dev/null +++ b/components/hal/esp32s3/include/hal/clk_tree_ll.h @@ -0,0 +1,677 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/clk_tree_defs.h" +#include "soc/rtc.h" +#include "soc/system_reg.h" +#include "soc/rtc_cntl_reg.h" +#include "esp_private/regi2c_ctrl.h" +#include "regi2c_bbpll.h" +#include "hal/assert.h" +#include "hal/log.h" +#include "esp32s3/rom/rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MHZ (1000000) + +#define CLK_LL_PLL_80M_FREQ_MHZ (80) +#define CLK_LL_PLL_160M_FREQ_MHZ (160) +#define CLK_LL_PLL_240M_FREQ_MHZ (240) + +#define CLK_LL_PLL_320M_FREQ_MHZ (320) +#define CLK_LL_PLL_480M_FREQ_MHZ (480) + +#define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ + .dac = 3, \ + .dres = 3, \ + .dgm = 3, \ + .dbuf = 1, \ +} + +/** + * @brief XTAL32K_CLK enable modes + */ +typedef enum { + CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL, //!< Enable the external 32kHz crystal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL, //!< Enable the external clock signal for XTAL32K_CLK + CLK_LL_XTAL32K_ENABLE_MODE_BOOTSTRAP, //!< Bootstrap the crystal oscillator for faster XTAL32K_CLK start up */ +} clk_ll_xtal32k_enable_mode_t; + +/** + * @brief XTAL32K_CLK configuration structure + */ +typedef struct { + uint32_t dac : 6; + uint32_t dres : 3; + uint32_t dgm : 3; + uint32_t dbuf: 1; +} clk_ll_xtal32k_config_t; + +/** + * @brief Power up BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_enable(void) +{ + REG_CLR_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Power down BBPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void) +{ + REG_SET_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); +} + +/** + * @brief Enable the 32kHz crystal oscillator + * + * @param mode Used to determine the xtal32k configuration parameters + */ +static inline void clk_ll_xtal32k_enable(clk_ll_xtal32k_enable_mode_t mode) +{ + // Configure xtal32k + clk_ll_xtal32k_config_t cfg = CLK_LL_XTAL32K_CONFIG_DEFAULT(); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm); + REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf); + // Enable xtal32k xpd status + SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + if (mode == CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL) { + /* TODO: external 32k oscillator may need different settings */ + ; + } +} + +/** + * @brief Disable the 32kHz crystal oscillator + */ +static inline void clk_ll_xtal32k_disable(void) +{ + // Set xtal32k xpd to be controlled by software + SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE); + // Disable xtal32k xpd status + CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); +} + +/** + * @brief Get the state of the 32kHz crystal clock + * + * @return True if the 32kHz XTAL is enabled + */ +static inline bool clk_ll_xtal32k_is_enabled(void) +{ + uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG); + /* If xtal xpd is controlled by software */ + bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S; + /* If xtal xpd software control is on */ + bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S; + // disabled = xtal_xpd_sw && !xtal_xpd_st; enabled = !disbaled + bool enabled = !xtal_xpd_sw || xtal_xpd_st; + return enabled; +} + +/** + * @brief Enable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); +} + +/** + * @brief Disable the internal oscillator output for RC_FAST_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_rc_fast_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); +} + +/** + * @brief Get the state of the internal oscillator for RC_FAST_CLK + * + * @return True if the oscillator is enabled + */ +static inline bool clk_ll_rc_fast_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; +} + +/** + * @brief Enable the output from the internal oscillator to be passed into a configurable divider, + * which by default divides the input clock frequency by 256. i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Divider values other than 256 may be configured, but this facility is not currently needed, + * so is not exposed in the code. + * The output of the divider, RC_FAST_D256_CLK, is referred as 8md256 or simply d256 in reg. descriptions. + */ +static inline void clk_ll_rc_fast_d256_enable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Disable the output from the internal oscillator to be passed into a configurable divider. + * i.e. RC_FAST_D256_CLK = RC_FAST_CLK / 256 + * + * Disabling this divider could reduce power consumption. + */ +static inline void clk_ll_rc_fast_d256_disable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); +} + +/** + * @brief Get the state of the divider which is applied to the output from the internal oscillator (RC_FAST_CLK) + * + * @return True if the divided output is enabled + */ +static inline bool clk_ll_rc_fast_d256_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; +} + +/** + * @brief Enable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Get the state of the digital RC_FAST_CLK + * + * @return True if the digital RC_FAST_CLK is enabled + */ +static inline bool clk_ll_rc_fast_digi_is_enabled(void) +{ + return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); +} + +/** + * @brief Enable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Disable the digital RC_FAST_D256_CLK, which is used to support peripherals. + */ +static inline void clk_ll_rc_fast_d256_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN_M); +} + +/** + * @brief Enable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_enable(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Disable the digital XTAL32K_CLK, which is used to support peripherals. + */ +static inline void clk_ll_xtal32k_digi_disable(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN_M); +} + +/** + * @brief Get the state of the digital XTAL32K_CLK + * + * @return True if the digital XTAL32K_CLK is enabled + */ +static inline bool clk_ll_xtal32k_digi_is_enabled(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); +} + +/** + * @brief Get PLL_CLK frequency + * + * @return PLL clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_bbpll_get_freq_mhz(void) +{ + uint32_t pll_freq_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); + switch (pll_freq_sel) { + case 0: // PLL_320M + return CLK_LL_PLL_320M_FREQ_MHZ; + case 1: // PLL_480M + return CLK_LL_PLL_480M_FREQ_MHZ; + default: + return 0; + } +} + +/** + * @brief Set BBPLL frequency from XTAL source (Digital part) + * + * @param pll_freq_mhz PLL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_freq_mhz(uint32_t pll_freq_mhz) +{ + switch (pll_freq_mhz) { + case CLK_LL_PLL_320M_FREQ_MHZ: // PLL_320M + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 0); + break; + case CLK_LL_PLL_480M_FREQ_MHZ: // PLL_480M + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 1); + break; + default: + abort(); + } +} + +/** + * @brief Set BBPLL frequency from XTAL source (Analog part) + * + * @param pll_freq_mhz PLL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_bbpll_set_config(uint32_t pll_freq_mhz, uint32_t xtal_freq_mhz) +{ + uint8_t div_ref; + uint8_t div7_0; + uint8_t dr1; + uint8_t dr3; + uint8_t dchgp; + uint8_t dcur; + uint8_t dbias; + + if (pll_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) { + /* Configure 480M PLL */ + switch (xtal_freq_mhz) { + case RTC_XTAL_FREQ_40M: + div_ref = 0; + div7_0 = 8; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + case RTC_XTAL_FREQ_32M: + div_ref = 1; + div7_0 = 26; + dr1 = 1; + dr3 = 1; + dchgp = 4; + dcur = 0; + dbias = 2; + break; + default: + div_ref = 0; + div7_0 = 8; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + } + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); + } else { + /* Configure 320M PLL */ + switch (xtal_freq_mhz) { + case RTC_XTAL_FREQ_40M: + div_ref = 0; + div7_0 = 4; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + case RTC_XTAL_FREQ_32M: + div_ref = 1; + div7_0 = 6; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + default: + div_ref = 0; + div7_0 = 4; + dr1 = 0; + dr3 = 0; + dchgp = 5; + dcur = 3; + dbias = 2; + break; + } + REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69); + } + 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_VCO_DBIAS, dbias); +} + +/** + * @brief Select the clock source for CPU_CLK + * + * @param in_sel One of the clock sources in soc_cpu_clk_src_t + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_src(soc_cpu_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_CPU_CLK_SRC_XTAL: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 0); + break; + case SOC_CPU_CLK_SRC_PLL: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 1); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 2); + break; + default: + // Unsupported CPU_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for CPU_CLK + * + * @return Currently selected clock source (one of soc_cpu_clk_src_t values) + */ +static inline __attribute__((always_inline)) soc_cpu_clk_src_t clk_ll_cpu_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); + switch (clk_sel) { + 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; + default: + // Invalid SOC_CLK_SEL value + return SOC_CPU_CLK_SRC_INVALID; + } +} + +/** + * @brief Set CPU frequency from PLL clock + * + * @param cpu_mhz CPU frequency value, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_freq_mhz_from_pll(uint32_t cpu_mhz) +{ + switch (cpu_mhz) { + case CLK_LL_PLL_80M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 0); + break; + case CLK_LL_PLL_160M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 1); + break; + case CLK_LL_PLL_240M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 2); + break; + default: + // Unsupported CPU_CLK freq from PLL + abort(); + } +} + +/** + * @brief Get CPU_CLK frequency from PLL_CLK source + * + * @return CPU clock frequency, in MHz. Returns 0 if register field value is invalid. + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_freq_mhz_from_pll(void) +{ + uint32_t cpu_freq_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL); + switch (cpu_freq_sel) { + case 0: + return CLK_LL_PLL_80M_FREQ_MHZ; + case 1: + return CLK_LL_PLL_160M_FREQ_MHZ; + case 2: + // When PLL frequency selection is 320MHz but CPU frequency selection is 240MHz, it is an undetermined state. + // It is checked in the upper layer. + return CLK_LL_PLL_240M_FREQ_MHZ; + default: + // Invalid CPUPERIOD_SEL value + return 0; + } +} + +/** + * @brief Set CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @param divider Divider. Usually this divider is set to 1 in bootloader stage. PRE_DIV_CNT = divider - 1. + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, divider - 1); +} + +/** + * @brief Get CPU_CLK's XTAL/FAST_RC clock source path divider + * + * @return Divider. Divider = (PRE_DIV_CNT + 1). + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(void) +{ + return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; +} + +/** + * @brief Select the clock source for RTC_SLOW_CLK + * + * @param in_sel One of the clock sources in soc_rtc_slow_clk_src_t + */ +static inline void clk_ll_rtc_slow_set_src(soc_rtc_slow_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 0); + break; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 1); + break; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, 2); + break; + default: + // Unsupported RTC_SLOW_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_SLOW_CLK + * + * @return Currently selected clock source (one of soc_rtc_slow_clk_src_t values) + */ +static inline soc_rtc_slow_clk_src_t clk_ll_rtc_slow_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_SLOW_CLK_SRC_RC_SLOW; + case 1: + return SOC_RTC_SLOW_CLK_SRC_XTAL32K; + case 2: + return SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256; + default: + // Invalid ANA_CLK_RTC_SEL value + HAL_ASSERT(false); + return SOC_RTC_SLOW_CLK_SRC_INVALID; + } +} + +/** + * @brief Select the clock source for RTC_FAST_CLK + * + * @param in_sel One of the clock sources in soc_rtc_fast_clk_src_t + */ +static inline void clk_ll_rtc_fast_set_src(soc_rtc_fast_clk_src_t in_sel) +{ + switch (in_sel) { + case SOC_RTC_FAST_CLK_SRC_XTAL_D2: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 0); + break; + case SOC_RTC_FAST_CLK_SRC_RC_FAST: + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, 1); + break; + default: + // Unsupported RTC_FAST_CLK mux input sel + abort(); + } +} + +/** + * @brief Get the clock source for RTC_FAST_CLK + * + * @return Currently selected clock source (one of soc_rtc_fast_clk_src_t values) + */ +static inline soc_rtc_fast_clk_src_t clk_ll_rtc_fast_get_src(void) +{ + uint32_t clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL); + switch (clk_sel) { + case 0: + return SOC_RTC_FAST_CLK_SRC_XTAL_D2; + case 1: + return SOC_RTC_FAST_CLK_SRC_RC_FAST; + default: + return SOC_RTC_FAST_CLK_SRC_INVALID; + } +} + +/** + * @brief Set RC_FAST_CLK divider. The output from the divider is passed into rtc_fast_clk MUX. + * + * @param divider Divider of RC_FAST_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_fast_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); +} + +/** + * @brief Get RC_FAST_CLK divider + * + * @return Divider. Divider = (CK8M_DIV_SEL + 1). + */ +static inline uint32_t clk_ll_rc_fast_get_divider(void) +{ + return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL) + 1; +} + +/** + * @brief Set RC_SLOW_CLK divider + * + * @param divider Divider of RC_SLOW_CLK. Usually this divider is set to 1 (reg. value is 0) in bootloader stage. + */ +static inline void clk_ll_rc_slow_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider > 0); + CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); + REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, divider - 1); + SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); +} + +/************************* RTC STORAGE REGISTER STORE/LOAD **************************/ +/** + * @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 + */ +static inline void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) +{ + 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 the 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 & UINT16_MAX; + } + // If the format in reg is invalid + return 0; +} + +/** + * @brief Store RTC_SLOW_CLK calibration value in RTC storage register + * + * Value of RTC_SLOW_CLK_CAL_REG has to be in the same format as returned by rtc_clk_cal (microseconds, + * in Q13.19 fixed-point format). + * + * @param cal_value The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline void clk_ll_rtc_slow_store_cal(uint32_t cal_value) +{ + REG_WRITE(RTC_SLOW_CLK_CAL_REG, cal_value); +} + +/** + * @brief Load the calibration value of RTC_SLOW_CLK frequency from RTC storage register + * + * This value gets updated (i.e. rtc slow clock gets calibrated) every time RTC_SLOW_CLK source switches + * + * @return The calibration value of slow clock period in microseconds, in Q13.19 fixed point format + */ +static inline uint32_t clk_ll_rtc_slow_load_cal(void) +{ + return REG_READ(RTC_SLOW_CLK_CAL_REG); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/regi2c_ctrl_ll.h b/components/hal/esp32s3/include/hal/regi2c_ctrl_ll.h new file mode 100644 index 0000000000..73d90128e5 --- /dev/null +++ b/components/hal/esp32s3/include/hal/regi2c_ctrl_ll.h @@ -0,0 +1,72 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/regi2c_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Reset (Disable) the I2C internal bus for all regi2c registers + */ +static inline void regi2c_ctrl_ll_i2c_reset(void) +{ + SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); +} + +/** + * @brief Enable the I2C internal bus to do I2C read/write operation to the BBPLL configuration register + */ +static inline void regi2c_ctrl_ll_i2c_bbpll_enable(void) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_BBPLL_M); +} + +/** + * @brief Enable the I2C internal bus to do I2C read/write operation to the SAR_ADC register + */ +static inline void regi2c_ctrl_ll_i2c_saradc_enable(void) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_SAR_M); + SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_SAR_CFG2_M); +} + +/** + * @brief Start BBPLL self-calibration + */ +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_bbpll_calibration_start(void) +{ + REG_CLR_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); + REG_SET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); +} + +/** + * @brief Stop BBPLL self-calibration + */ +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_bbpll_calibration_stop(void) +{ + REG_CLR_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); + REG_SET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); +} + +/** + * @brief Check whether BBPLL calibration is done + * + * @return True if calibration is done; otherwise false + */ +static inline __attribute__((always_inline)) bool regi2c_ctrl_ll_bbpll_calibration_is_done(void) +{ + return REG_GET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_CAL_DONE); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32/include/soc/clk_tree_defs.h b/components/soc/esp32/include/soc/clk_tree_defs.h index 086b8549d7..2296635bfa 100644 --- a/components/soc/esp32/include/soc/clk_tree_defs.h +++ b/components/soc/esp32/include/soc/clk_tree_defs.h @@ -66,6 +66,7 @@ typedef enum { SOC_CPU_CLK_SRC_PLL = 1, /*!< Select PLL_CLK as CPU_CLK source (PLL_CLK is the output of 40MHz crystal oscillator frequency multiplier, can be 480MHz or 320MHz) */ SOC_CPU_CLK_SRC_RC_FAST = 2, /*!< Select RC_FAST_CLK as CPU_CLK source */ SOC_CPU_CLK_SRC_APLL = 3, /*!< Select APLL_CLK as CPU_CLK source */ + SOC_CPU_CLK_SRC_INVALID, /*!< Invalid CPU_CLK source */ } soc_cpu_clk_src_t; /** @@ -76,6 +77,7 @@ 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_RC_FAST_D256 = 2, /*!< Select RC_FAST_D256_CLK (referred as FOSC_DIV or 8m_d256/8md256 in TRM and reg. description) as RTC_SLOW_CLK source */ + SOC_RTC_SLOW_CLK_SRC_INVALID, /*!< Invalid RTC_SLOW_CLK source */ } soc_rtc_slow_clk_src_t; /** @@ -86,6 +88,7 @@ typedef enum { SOC_RTC_FAST_CLK_SRC_XTAL_D4 = 0, /*!< Select XTAL_D4_CLK (may referred as XTAL_CLK_DIV_4) as RTC_FAST_CLK source */ SOC_RTC_FAST_CLK_SRC_XTAL_DIV = SOC_RTC_FAST_CLK_SRC_XTAL_D4, /*!< Alias name for `SOC_RTC_FAST_CLK_SRC_XTAL_D4` */ SOC_RTC_FAST_CLK_SRC_RC_FAST = 1, /*!< Select RC_FAST_CLK as RTC_FAST_CLK source */ + SOC_RTC_FAST_CLK_SRC_INVALID, /*!< Invalid RTC_FAST_CLK source */ } soc_rtc_fast_clk_src_t; // Naming convention: SOC_MOD_CLK_{[upstream]clock_name}_[attr] diff --git a/components/soc/esp32/include/soc/dport_reg.h b/components/soc/esp32/include/soc/dport_reg.h index 367c9e43e0..941ff4544c 100644 --- a/components/soc/esp32/include/soc/dport_reg.h +++ b/components/soc/esp32/include/soc/dport_reg.h @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_DPORT_REG_H_ #define _SOC_DPORT_REG_H_ @@ -179,9 +171,6 @@ #define DPORT_CPUPERIOD_SEL_M ((DPORT_CPUPERIOD_SEL_V)<<(DPORT_CPUPERIOD_SEL_S)) #define DPORT_CPUPERIOD_SEL_V 0x3 #define DPORT_CPUPERIOD_SEL_S 0 -#define DPORT_CPUPERIOD_SEL_80 0 -#define DPORT_CPUPERIOD_SEL_160 1 -#define DPORT_CPUPERIOD_SEL_240 2 #define DPORT_PRO_CACHE_CTRL_REG (DR_REG_DPORT_BASE + 0x040) /* DPORT_PRO_DRAM_HL : R/W ;bitpos:[16] ;default: 1'b0 ; */ diff --git a/components/soc/esp32/include/soc/io_mux_reg.h b/components/soc/esp32/include/soc/io_mux_reg.h index 3e9bbe1ce0..58fed3502d 100644 --- a/components/soc/esp32/include/soc/io_mux_reg.h +++ b/components/soc/esp32/include/soc/io_mux_reg.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_IO_MUX_REG_H_ #define _SOC_IO_MUX_REG_H_ @@ -98,6 +90,8 @@ #define SPI_D_GPIO_NUM 8 #define SPI_WP_GPIO_NUM 10 #define SPI_HD_GPIO_NUM 9 +#define XTAL32K_P_GPIO_NUM 32 +#define XTAL32K_N_GPIO_NUM 33 #define PIN_CTRL (DR_REG_IO_MUX_BASE +0x00) #define CLK_OUT3 0xf diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index 854383e85a..8733679aa7 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -47,6 +47,33 @@ extern "C" { * - rtc_init: initialization */ +/* Delays for various clock sources to be enabled/switched. + * All values are in microseconds. + */ +#define SOC_DELAY_PLL_DBIAS_RAISE 3 +#define SOC_DELAY_PLL_ENABLE_WITH_150K 80 +#define SOC_DELAY_PLL_ENABLE_WITH_32K 160 +#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 + +/* Core voltage needs to be increased in two cases: + * 1. running at 240 MHz + * 2. running with 80MHz Flash frequency + * + * There is a record in efuse which indicates the proper voltage for these two cases. + */ +#define RTC_CNTL_DBIAS_HP_VOLT (RTC_CNTL_DBIAS_1V25 - efuse_ll_get_vol_level_hp_inv()) +#ifdef CONFIG_ESPTOOLPY_FLASHFREQ_80M +#define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_HP_VOLT +#else +#define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V10 +#endif +#define DIG_DBIAS_240M RTC_CNTL_DBIAS_HP_VOLT +#define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10 +#define DIG_DBIAS_2M RTC_CNTL_DBIAS_1V00 + /** * @brief Possible main XTAL frequency values. * @@ -84,7 +111,7 @@ typedef enum { typedef struct rtc_clk_config_s { rtc_xtal_freq_t xtal_freq : 8; //!< Main XTAL frequency uint32_t cpu_freq_mhz : 10; //!< CPU frequency to set, in MHz - soc_rtc_fast_clk_src_t fast_clk_src : 1; //!< RTC_FAST_CLK clock source to choose + soc_rtc_fast_clk_src_t fast_clk_src : 2; //!< RTC_FAST_CLK clock source to choose soc_rtc_slow_clk_src_t slow_clk_src : 2; //!< RTC_SLOW_CLK clock source to choose uint32_t clk_8m_div : 3; //!< RTC 8M clock divider (division is by clk_8m_div+1, i.e. 0 means 8MHz frequency) uint32_t slow_clk_dcap : 8; //!< RTC 150k clock adjustment parameter (higher value leads to lower frequency) @@ -241,9 +268,9 @@ void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32 /** * @brief Select source for RTC_SLOW_CLK - * @param slow_freq clock source (one of soc_rtc_slow_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_slow_clk_src_t values) */ -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq); +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src); /** * @brief Get the RTC_SLOW_CLK source @@ -267,9 +294,9 @@ uint32_t rtc_clk_slow_freq_get_hz(void); /** * @brief Select source for RTC_FAST_CLK - * @param fast_freq clock source (one of soc_rtc_fast_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_fast_clk_src_t values) */ -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq); +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src); /** * @brief Get the RTC_FAST_CLK source diff --git a/components/soc/esp32/include/soc/rtc_cntl_reg.h b/components/soc/esp32/include/soc/rtc_cntl_reg.h index 7e53e96993..aec51adf6a 100644 --- a/components/soc/esp32/include/soc/rtc_cntl_reg.h +++ b/components/soc/esp32/include/soc/rtc_cntl_reg.h @@ -893,10 +893,6 @@ #define RTC_CNTL_SOC_CLK_SEL_M ((RTC_CNTL_SOC_CLK_SEL_V)<<(RTC_CNTL_SOC_CLK_SEL_S)) #define RTC_CNTL_SOC_CLK_SEL_V 0x3 #define RTC_CNTL_SOC_CLK_SEL_S 27 -#define RTC_CNTL_SOC_CLK_SEL_XTL 0 -#define RTC_CNTL_SOC_CLK_SEL_PLL 1 -#define RTC_CNTL_SOC_CLK_SEL_8M 2 -#define RTC_CNTL_SOC_CLK_SEL_APLL 3 /* RTC_CNTL_CK8M_FORCE_PU : R/W ;bitpos:[26] ;default: 1'd0 ; */ /*description: CK8M force power up*/ #define RTC_CNTL_CK8M_FORCE_PU (BIT(26)) diff --git a/components/soc/esp32c2/include/soc/clk_tree_defs.h b/components/soc/esp32c2/include/soc/clk_tree_defs.h index 90c9f7f2dd..230b6251fc 100644 --- a/components/soc/esp32c2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c2/include/soc/clk_tree_defs.h @@ -62,6 +62,7 @@ typedef enum { SOC_CPU_CLK_SRC_XTAL = 0, /*!< Select XTAL_CLK as CPU_CLK source */ SOC_CPU_CLK_SRC_PLL = 1, /*!< Select PLL_CLK as CPU_CLK source (PLL_CLK is the output of 40MHz crystal oscillator frequency multiplier, 480MHz) */ SOC_CPU_CLK_SRC_RC_FAST = 2, /*!< Select RC_FAST_CLK as CPU_CLK source */ + SOC_CPU_CLK_SRC_INVALID, /*!< Invalid CPU_CLK source */ } soc_cpu_clk_src_t; /** @@ -72,6 +73,7 @@ typedef enum { SOC_RTC_SLOW_CLK_SRC_RC_SLOW = 0, /*!< Select RC_SLOW_CLK as RTC_SLOW_CLK source */ SOC_RTC_SLOW_CLK_SRC_OSC_SLOW = 1, /*!< Select OSC_SLOW_CLK (external slow clock) as RTC_SLOW_CLK source */ SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256 = 2, /*!< Select RC_FAST_D256_CLK (referred as FOSC_DIV or 8m_d256/8md256 in TRM and reg. description) as RTC_SLOW_CLK source */ + SOC_RTC_SLOW_CLK_SRC_INVALID, /*!< Invalid RTC_SLOW_CLK source */ } soc_rtc_slow_clk_src_t; /** @@ -82,6 +84,7 @@ typedef enum { SOC_RTC_FAST_CLK_SRC_XTAL_D2 = 0, /*!< Select XTAL_D2_CLK (may referred as XTAL_CLK_DIV_2) 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` */ SOC_RTC_FAST_CLK_SRC_RC_FAST = 1, /*!< Select RC_FAST_CLK as RTC_FAST_CLK source */ + SOC_RTC_FAST_CLK_SRC_INVALID, /*!< Invalid RTC_FAST_CLK source */ } soc_rtc_fast_clk_src_t; // Naming convention: SOC_MOD_CLK_{[upstream]clock_name}_[attr] diff --git a/components/soc/esp32c2/include/soc/io_mux_reg.h b/components/soc/esp32c2/include/soc/io_mux_reg.h index d5f9f9359b..4da0498397 100644 --- a/components/soc/esp32c2/include/soc/io_mux_reg.h +++ b/components/soc/esp32c2/include/soc/io_mux_reg.h @@ -125,6 +125,8 @@ #define SPI_D_GPIO_NUM 16 #define SPI_Q_GPIO_NUM 17 +#define EXT_OSC_SLOW_GPIO_NUM 0 + #define MAX_RTC_GPIO_NUM 5 #define MAX_PAD_GPIO_NUM 20 #define MAX_GPIO_NUM 24 diff --git a/components/soc/esp32c2/include/soc/rtc.h b/components/soc/esp32c2/include/soc/rtc.h index 28abe9c0c6..24ef4444ce 100644 --- a/components/soc/esp32c2/include/soc/rtc.h +++ b/components/soc/esp32c2/include/soc/rtc.h @@ -67,18 +67,17 @@ extern "C" { #define RTC_CNTL_DBIAS_1V25 30 #define RTC_CNTL_DBIAS_1V30 31 //voltage is about 1.34v in fact -#define DELAY_FAST_CLK_SWITCH 3 -#define DELAY_SLOW_CLK_SWITCH 300 -#define DELAY_8M_ENABLE 50 - -/* Number of 8M/256 clock cycles to use for XTAL frequency estimation. - * 10 cycles will take approximately 300 microseconds. +/* Delays for various clock sources to be enabled/switched. + * All values are in microseconds. */ -#define XTAL_FREQ_EST_CYCLES 10 - -#define DIG_DBIAS_80M RTC_CNTL_DBIAS_1V20 -#define DIG_DBIAS_160M RTC_CNTL_DBIAS_1V20 +#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 +/* Core voltage (to be supported) */ +#define DIG_DBIAS_80M RTC_CNTL_DBIAS_1V20 +#define DIG_DBIAS_120M RTC_CNTL_DBIAS_1V20 #define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10 #define DIG_DBIAS_2M RTC_CNTL_DBIAS_1V00 @@ -161,7 +160,7 @@ typedef enum { typedef struct { rtc_xtal_freq_t xtal_freq : 8; //!< Main XTAL frequency uint32_t cpu_freq_mhz : 10; //!< CPU frequency to set, in MHz - soc_rtc_fast_clk_src_t fast_clk_src : 1; //!< RTC_FAST_CLK clock source to choose + soc_rtc_fast_clk_src_t fast_clk_src : 2; //!< RTC_FAST_CLK clock source to choose soc_rtc_slow_clk_src_t slow_clk_src : 2; //!< RTC_SLOW_CLK clock source to choose uint32_t clk_rtc_clk_div : 8; uint32_t clk_8m_clk_div : 3; //!< RTC 8M clock divider (division is by clk_8m_div+1, i.e. 0 means 8MHz frequency) @@ -277,9 +276,9 @@ bool rtc_clk_8md256_enabled(void); /** * @brief Select source for RTC_SLOW_CLK - * @param slow_freq clock source (one of soc_rtc_slow_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_slow_clk_src_t values) */ -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq); +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src); /** * @brief Get the RTC_SLOW_CLK source @@ -303,9 +302,9 @@ uint32_t rtc_clk_slow_freq_get_hz(void); /** * @brief Select source for RTC_FAST_CLK - * @param fast_freq clock source (one of soc_rtc_fast_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_fast_clk_src_t values) */ -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq); +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src); /** * @brief Get the RTC_FAST_CLK source diff --git a/components/soc/esp32c3/include/soc/clk_tree_defs.h b/components/soc/esp32c3/include/soc/clk_tree_defs.h index 897b2754b2..103799b094 100644 --- a/components/soc/esp32c3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c3/include/soc/clk_tree_defs.h @@ -63,6 +63,7 @@ typedef enum { SOC_CPU_CLK_SRC_XTAL = 0, /*!< Select XTAL_CLK as CPU_CLK source */ SOC_CPU_CLK_SRC_PLL = 1, /*!< Select PLL_CLK as CPU_CLK source (PLL_CLK is the output of 40MHz crystal oscillator frequency multiplier, can be 480MHz or 320MHz) */ SOC_CPU_CLK_SRC_RC_FAST = 2, /*!< Select RC_FAST_CLK as CPU_CLK source */ + SOC_CPU_CLK_SRC_INVALID, /*!< Invalid CPU_CLK source */ } soc_cpu_clk_src_t; /** @@ -73,6 +74,7 @@ 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_RC_FAST_D256 = 2, /*!< Select RC_FAST_D256_CLK (referred as FOSC_DIV or 8m_d256/8md256 in TRM and reg. description) as RTC_SLOW_CLK source */ + SOC_RTC_SLOW_CLK_SRC_INVALID, /*!< Invalid RTC_SLOW_CLK source */ } soc_rtc_slow_clk_src_t; /** @@ -83,6 +85,7 @@ typedef enum { SOC_RTC_FAST_CLK_SRC_XTAL_D2 = 0, /*!< Select XTAL_D2_CLK (may referred as XTAL_CLK_DIV_2) 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` */ SOC_RTC_FAST_CLK_SRC_RC_FAST = 1, /*!< Select RC_FAST_CLK as RTC_FAST_CLK source */ + SOC_RTC_FAST_CLK_SRC_INVALID, /*!< Invalid RTC_FAST_CLK source */ } soc_rtc_fast_clk_src_t; // Naming convention: SOC_MOD_CLK_{[upstream]clock_name}_[attr] diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index 2a99ee4a76..2ad87e60d0 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -67,18 +67,20 @@ extern "C" { #define RTC_CNTL_DBIAS_1V25 30 #define RTC_CNTL_DBIAS_1V30 31 //voltage is about 1.34v in fact -#define DELAY_FAST_CLK_SWITCH 3 -#define DELAY_SLOW_CLK_SWITCH 300 -#define DELAY_8M_ENABLE 50 - -/* Number of 8M/256 clock cycles to use for XTAL frequency estimation. - * 10 cycles will take approximately 300 microseconds. +/* Delays for various clock sources to be enabled/switched. + * All values are in microseconds. */ -#define XTAL_FREQ_EST_CYCLES 10 - -#define DIG_DBIAS_80M RTC_CNTL_DBIAS_1V20 -#define DIG_DBIAS_160M RTC_CNTL_DBIAS_1V20 +#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 +/* Core voltage: + * Currently, ESP32C3 never adjust its wake voltage in runtime + * Only sets dig/rtc voltage dbias at startup time + */ +#define DIG_DBIAS_80M RTC_CNTL_DBIAS_1V20 +#define DIG_DBIAS_160M RTC_CNTL_DBIAS_1V20 #define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10 #define DIG_DBIAS_2M RTC_CNTL_DBIAS_1V00 @@ -163,7 +165,7 @@ typedef enum { typedef struct { rtc_xtal_freq_t xtal_freq : 8; //!< Main XTAL frequency uint32_t cpu_freq_mhz : 10; //!< CPU frequency to set, in MHz - soc_rtc_fast_clk_src_t fast_clk_src : 1; //!< RTC_FAST_CLK clock source to choose + soc_rtc_fast_clk_src_t fast_clk_src : 2; //!< RTC_FAST_CLK clock source to choose soc_rtc_slow_clk_src_t slow_clk_src : 2; //!< RTC_SLOW_CLK clock source to choose uint32_t clk_rtc_clk_div : 8; uint32_t clk_8m_clk_div : 3; //!< RTC 8M clock divider (division is by clk_8m_div+1, i.e. 0 means 8MHz frequency) @@ -185,20 +187,6 @@ typedef struct { .clk_8m_dfreq = RTC_CNTL_CK8M_DFREQ_DEFAULT, \ } -typedef struct { - uint32_t dac : 6; - uint32_t dres : 3; - uint32_t dgm : 3; - uint32_t dbuf: 1; -} x32k_config_t; - -#define X32K_CONFIG_DEFAULT() { \ - .dac = 3, \ - .dres = 3, \ - .dgm = 3, \ - .dbuf = 1, \ -} - typedef struct { uint16_t wifi_powerup_cycles : 7; uint16_t wifi_wait_cycles : 9; @@ -317,9 +305,9 @@ bool rtc_clk_8md256_enabled(void); /** * @brief Select source for RTC_SLOW_CLK - * @param slow_freq clock source (one of soc_rtc_slow_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_slow_clk_src_t values) */ -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq); +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src); /** * @brief Get the RTC_SLOW_CLK source @@ -343,9 +331,9 @@ uint32_t rtc_clk_slow_freq_get_hz(void); /** * @brief Select source for RTC_FAST_CLK - * @param fast_freq clock source (one of soc_rtc_fast_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_fast_clk_src_t values) */ -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq); +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src); /** * @brief Get the RTC_FAST_CLK source diff --git a/components/soc/esp32h2/include/rev1/soc/io_mux_reg.h b/components/soc/esp32h2/include/rev1/soc/io_mux_reg.h index 276c526990..62bcd9ac29 100644 --- a/components/soc/esp32h2/include/rev1/soc/io_mux_reg.h +++ b/components/soc/esp32h2/include/rev1/soc/io_mux_reg.h @@ -152,6 +152,9 @@ #define USB_DM_GPIO_NUM 18 #define USB_DP_GPIO_NUM 19 +#define XTAL32K_P_GPIO_NUM 0 +#define XTAL32K_N_GPIO_NUM 1 + #define MAX_RTC_GPIO_NUM 5 #define MAX_PAD_GPIO_NUM 40 #define MAX_GPIO_NUM 44 diff --git a/components/soc/esp32h2/include/rev2/soc/io_mux_reg.h b/components/soc/esp32h2/include/rev2/soc/io_mux_reg.h index 829adedcf3..4182513522 100644 --- a/components/soc/esp32h2/include/rev2/soc/io_mux_reg.h +++ b/components/soc/esp32h2/include/rev2/soc/io_mux_reg.h @@ -127,6 +127,9 @@ #define USB_DM_GPIO_NUM 24 #define USB_DP_GPIO_NUM 25 +#define XTAL32K_P_GPIO_NUM 10 +#define XTAL32K_N_GPIO_NUM 11 + #define MAX_RTC_GPIO_NUM 12 // GPIO7~12 are the rtc_io pads #define MAX_PAD_GPIO_NUM 25 #define MAX_GPIO_NUM 29 diff --git a/components/soc/esp32h2/include/soc/clk_tree_defs.h b/components/soc/esp32h2/include/soc/clk_tree_defs.h index baee147015..ac3412794d 100644 --- a/components/soc/esp32h2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h2/include/soc/clk_tree_defs.h @@ -70,6 +70,7 @@ typedef enum { SOC_CPU_CLK_SRC_PLL = 1, /*!< Select PLL_CLK as CPU_CLK source (PLL_CLK is the output of 32MHz crystal oscillator frequency multiplier, 96MHz) */ SOC_CPU_CLK_SRC_RC_FAST = 2, /*!< Select RC_FAST_CLK as CPU_CLK source */ SOC_CPU_CLK_SRC_XTAL_D2 = 3, /*!< Select XTAL_D2_CLK as CPU_CLK source */ + SOC_CPU_CLK_SRC_INVALID, /*!< Invalid CPU_CLK source */ } soc_cpu_clk_src_t; /** @@ -80,6 +81,7 @@ 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 */ + SOC_RTC_SLOW_CLK_SRC_INVALID, /*!< Invalid RTC_SLOW_CLK source */ } soc_rtc_slow_clk_src_t; /** @@ -90,6 +92,7 @@ typedef enum { SOC_RTC_FAST_CLK_SRC_XTAL_D2 = 0, /*!< Select XTAL_D2_CLK (may referred as XTAL_CLK_DIV_2) 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` */ SOC_RTC_FAST_CLK_SRC_RC_FAST = 1, /*!< Select RC_FAST_CLK as RTC_FAST_CLK source */ + SOC_RTC_FAST_CLK_SRC_INVALID, /*!< Invalid RTC_FAST_CLK source */ } soc_rtc_fast_clk_src_t; // Naming convention: SOC_MOD_CLK_{[upstream]clock_name}_[attr] diff --git a/components/soc/esp32h2/include/soc/regi2c_defs.h b/components/soc/esp32h2/include/soc/regi2c_defs.h index 741ebfbc3e..3199b89e38 100644 --- a/components/soc/esp32h2/include/soc/regi2c_defs.h +++ b/components/soc/esp32h2/include/soc/regi2c_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,7 +12,8 @@ /* Analog function control register */ #define I2C_MST_ANA_CONF0_REG 0x6000E040 #define I2C_MST_BBPLL_STOP_FORCE_HIGH (BIT(2)) -#define I2C_MST_BBPLL_STOP_FORCE_LOW (BIT(3)) +#define I2C_MST_BBPLL_STOP_FORCE_LOW (BIT(3)) +#define I2C_MST_BBPLL_CAL_DONE (BIT(24)) #define ANA_CONFIG_REG 0x6000E044 #define ANA_CONFIG_S (8) @@ -21,7 +22,6 @@ #define ANA_I2C_SAR_FORCE_PD BIT(18) #define ANA_I2C_BBPLL_M BIT(17) /* Clear to enable BBPLL */ - #define ANA_CONFIG2_REG 0x6000E048 #define ANA_CONFIG2_M BIT(18) diff --git a/components/soc/esp32h2/include/soc/rtc.h b/components/soc/esp32h2/include/soc/rtc.h index aa588e0f8b..09d704f039 100644 --- a/components/soc/esp32h2/include/soc/rtc.h +++ b/components/soc/esp32h2/include/soc/rtc.h @@ -87,18 +87,16 @@ extern "C" { #define RTC_CNTL_DIG_DBIAS_1V15 6 #define RTC_CNTL_DIG_DBIAS_1V20 7 -#define DELAY_FAST_CLK_SWITCH 3 -#define DELAY_SLOW_CLK_SWITCH 300 -#define DELAY_8M_ENABLE 50 - -/* Number of 8M/256 clock cycles to use for XTAL frequency estimation. - * 10 cycles will take approximately 300 microseconds. +/* Delays for various clock sources to be enabled/switched. + * All values are in microseconds. */ -#define XTAL_FREQ_EST_CYCLES 10 - -#define DIG_DBIAS_80M RTC_CNTL_DBIAS_1V20 -#define DIG_DBIAS_160M RTC_CNTL_DBIAS_1V20 +#define SOC_DELAY_RTC_FAST_CLK_SWITCH 3 +#define SOC_DELAY_RTC_SLOW_CLK_SWITCH 300 +#define SOC_DELAY_RC_FAST_DIGI_SWITCH 5 +/* Core voltage (to be supported) */ +#define DIG_DBIAS_80M RTC_CNTL_DBIAS_1V20 +#define DIG_DBIAS_160M RTC_CNTL_DBIAS_1V20 #define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10 #define DIG_DBIAS_2M RTC_CNTL_DBIAS_1V00 @@ -109,7 +107,6 @@ extern "C" { #define RTC_CNTL_CK8M_DFREQ_DEFAULT 600 #define RTC_CNTL_SCK_DCAP_DEFAULT 128 -#define RTC_CNTL_RC32K_DFREQ_DEFAULT 707 /* Various delays to be programmed into power control state machines */ @@ -140,7 +137,6 @@ set sleep_init default param */ typedef enum { RTC_XTAL_FREQ_32M = 32, - RTC_XTAL_FREQ_40M = 40, //!< 40 MHz XTAL } rtc_xtal_freq_t; /** @@ -173,7 +169,7 @@ typedef enum { typedef struct { rtc_xtal_freq_t xtal_freq : 8; //!< Main XTAL frequency uint32_t cpu_freq_mhz : 10; //!< CPU frequency to set, in MHz - soc_rtc_fast_clk_src_t fast_clk_src : 1; //!< RTC_FAST_CLK clock source to choose + soc_rtc_fast_clk_src_t fast_clk_src : 2; //!< RTC_FAST_CLK clock source to choose soc_rtc_slow_clk_src_t slow_clk_src : 2; //!< RTC_SLOW_CLK clock source to choose uint32_t clk_rtc_clk_div : 8; uint32_t clk_8m_clk_div : 3; //!< RTC 8M clock divider (division is by clk_8m_div+1, i.e. 0 means 8MHz frequency) @@ -197,29 +193,6 @@ typedef struct { .root_clk_slt = 0, \ } -typedef struct { - uint32_t dac : 6; - uint32_t dres : 3; - uint32_t dgm : 3; - uint32_t dbuf: 1; -} x32k_config_t; - - -#define X32K_CONFIG_DEFAULT() { \ - .dac = 3, \ - .dres = 3, \ - .dgm = 3, \ - .dbuf = 1, \ -} - -typedef struct { - uint32_t dfreq : 10; -} rc32k_config_t; - -#define RC32K_CONFIG_DEFAULT() {\ - .dfreq = RTC_CNTL_RC32K_DFREQ_DEFAULT,\ -} - typedef struct { uint16_t wifi_powerup_cycles : 7; uint16_t wifi_wait_cycles : 9; @@ -344,9 +317,9 @@ bool rtc_clk_8md256_enabled(void); /** * @brief Select source for RTC_SLOW_CLK - * @param slow_freq clock source (one of soc_rtc_slow_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_slow_clk_src_t values) */ -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq); +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src); /** * @brief Get the RTC_SLOW_CLK source @@ -370,9 +343,9 @@ uint32_t rtc_clk_slow_freq_get_hz(void); /** * @brief Select source for RTC_FAST_CLK - * @param fast_freq clock source (one of soc_rtc_fast_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_fast_clk_src_t values) */ -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq); +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src); /** * @brief Get the RTC_FAST_CLK source @@ -455,18 +428,13 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq); /** * @brief Get the current stored APB frequency. - * @return The APB frequency value as last set via rtc_clk_apb_freq_update(), in Hz. + * @return The APB frequency value computed from upstream, in Hz. */ uint32_t rtc_clk_apb_freq_get(void); void rtc_clk_cpu_freq_set(uint32_t source, uint32_t div); -/** - * @brief Get the current stored AHB frequency. - * @return The AHB frequency value as last set via rtc_clk_ahb_freq_set(), in Hz. - */ -uint32_t rtc_clk_ahb_freq_get(void); - +uint32_t rtc_clk_select_root_clk(soc_cpu_clk_src_t cpu_clk_src); uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles); @@ -910,12 +878,6 @@ rtc_vddsdio_config_t rtc_vddsdio_get_config(void); */ void rtc_vddsdio_set_config(rtc_vddsdio_config_t config); - -/* Select clock root source for esp32h2. return source clk freq_mhz - */ -uint32_t root_clk_slt(uint32_t source); -uint32_t root_clk_get(void); - /** * Regulator config */ @@ -946,12 +908,6 @@ typedef struct { } -/** - * gpio hangup - */ -void rtc_gpio_hangup(uint32_t gpio_no); - - // -------------------------- CLOCK TREE DEFS ALIAS ---------------------------- // **WARNING**: The following are only for backwards compatibility. // Please use the declarations in soc/clk_tree_defs.h instead. diff --git a/components/soc/esp32s2/include/soc/clk_tree_defs.h b/components/soc/esp32s2/include/soc/clk_tree_defs.h index 63dafa779b..65f467d51a 100644 --- a/components/soc/esp32s2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s2/include/soc/clk_tree_defs.h @@ -64,6 +64,7 @@ typedef enum { SOC_CPU_CLK_SRC_PLL = 1, /*!< Select PLL_CLK as CPU_CLK source (PLL_CLK is the output of 40MHz crystal oscillator frequency multiplier, can be 480MHz or 320MHz) */ SOC_CPU_CLK_SRC_RC_FAST = 2, /*!< Select RC_FAST_CLK as CPU_CLK source */ SOC_CPU_CLK_SRC_APLL = 3, /*!< Select APLL_CLK as CPU_CLK source */ + SOC_CPU_CLK_SRC_INVALID, /*!< Invalid CPU_CLK source */ } soc_cpu_clk_src_t; /** @@ -74,6 +75,7 @@ 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_RC_FAST_D256 = 2, /*!< Select RC_FAST_D256_CLK (referred as FOSC_DIV or 8m_d256/8md256 in TRM and reg. description) as RTC_SLOW_CLK source */ + SOC_RTC_SLOW_CLK_SRC_INVALID, /*!< Invalid RTC_SLOW_CLK source */ } soc_rtc_slow_clk_src_t; /** @@ -84,6 +86,7 @@ typedef enum { SOC_RTC_FAST_CLK_SRC_XTAL_D4 = 0, /*!< Select XTAL_D4_CLK (may referred as XTAL_CLK_DIV_4) as RTC_FAST_CLK source */ SOC_RTC_FAST_CLK_SRC_XTAL_DIV = SOC_RTC_FAST_CLK_SRC_XTAL_D4, /*!< Alias name for `SOC_RTC_FAST_CLK_SRC_XTAL_D4` */ SOC_RTC_FAST_CLK_SRC_RC_FAST = 1, /*!< Select RC_FAST_CLK as RTC_FAST_CLK source */ + SOC_RTC_FAST_CLK_SRC_INVALID, /*!< Invalid RTC_FAST_CLK source */ } soc_rtc_fast_clk_src_t; // Naming convention: SOC_MOD_CLK_{[upstream]clock_name}_[attr] diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index b931052de3..6ee19ad7b5 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -66,14 +66,13 @@ extern "C" { #define RTC_CNTL_DBIAS_1V20 6 #define RTC_CNTL_DBIAS_1V25 7 -#define DELAY_FAST_CLK_SWITCH 3 -#define DELAY_SLOW_CLK_SWITCH 300 -#define DELAY_8M_ENABLE 50 - -/* Number of 8M/256 clock cycles to use for XTAL frequency estimation. - * 10 cycles will take approximately 300 microseconds. +/* Delays for various clock sources to be enabled/switched. + * All values are in microseconds. */ -#define XTAL_FREQ_EST_CYCLES 10 +#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 /* Core voltage needs to be increased in two cases: * 1. running at 240 MHz @@ -119,13 +118,6 @@ set sleep_init default param #define RTC_CNTL_PD_CUR_SLEEP_ON 0 #define RTC_CNTL_PD_CUR_SLEEP_DEFAULT 1 -#define APLL_SDM_STOP_VAL_1 0x09 -#define APLL_SDM_STOP_VAL_2_REV0 0x69 -#define APLL_SDM_STOP_VAL_2_REV1 0x49 -#define APLL_CAL_DELAY_1 0x0f -#define APLL_CAL_DELAY_2 0x3f -#define APLL_CAL_DELAY_3 0x1f - /** * @brief Possible main XTAL frequency values. * @@ -135,13 +127,6 @@ typedef enum { RTC_XTAL_FREQ_40M = 40, //!< 40 MHz XTAL } rtc_xtal_freq_t; -/** @brief Fixed crystal frequency for this SoC - - On an SoC where only one crystal frequency is supported, - using this macro is an alternative to calling rtc_clk_xtal_freq_get() - */ -#define RTC_XTAL_FREQ RTC_XTAL_FREQ_40M - /** * @brief CPU clock configuration structure */ @@ -173,7 +158,7 @@ typedef enum { typedef struct { rtc_xtal_freq_t xtal_freq : 8; //!< Main XTAL frequency uint32_t cpu_freq_mhz : 10; //!< CPU frequency to set, in MHz - soc_rtc_fast_clk_src_t fast_clk_src : 1; //!< RTC_FAST_CLK clock source to choose + soc_rtc_fast_clk_src_t fast_clk_src : 2; //!< RTC_FAST_CLK clock source to choose soc_rtc_slow_clk_src_t slow_clk_src : 2; //!< RTC_SLOW_CLK clock source to choose uint32_t clk_rtc_clk_div : 8; uint32_t clk_8m_clk_div : 3; //!< RTC 8M clock divider (division is by clk_8m_div+1, i.e. 0 means 8MHz frequency) @@ -195,42 +180,6 @@ typedef struct { .clk_8m_dfreq = RTC_CNTL_CK8M_DFREQ_DEFAULT, \ } -typedef struct { - uint32_t dac : 6; - uint32_t dres : 3; - uint32_t dgm : 3; - uint32_t dbuf: 1; -} x32k_config_t; - -#define X32K_CONFIG_DEFAULT() { \ - .dac = 3, \ - .dres = 3, \ - .dgm = 3, \ - .dbuf = 1, \ -} - -#if 0 -#define X32K_CONFIG_BOOTSTRAP_DEFAULT() { \ - .dac = 3, \ - .dres = 3, \ - .dgm = 0, \ -} - -typedef struct { - x32k_config_t x32k_cfg; - uint32_t bt_lpck_div_num : 12; - uint32_t bt_lpck_div_a : 12; - uint32_t bt_lpck_div_b : 12; -} x32k_bootstrap_config_t; - -#define X32K_BOOTSTRAP_CONFIG_DEFAULT() { \ - .x32k_cfg = X32K_CONFIG_BOOTSTRAP_DEFAULT(), \ - .bt_lpck_div_num = 2441, \ - .bt_lpck_div_a = 32, \ - .bt_lpck_div_b = 13, \ -} -#endif - typedef struct { uint16_t wifi_powerup_cycles : 7; uint16_t wifi_wait_cycles : 9; @@ -274,10 +223,10 @@ void rtc_clk_init(rtc_clk_config_t cfg); * Result is a constant as XTAL frequency is fixed. * * @note Function is included for ESP32 compatible code only. Code which only - * needs to support this SoC can use the macro RTC_XTAL_FREQ for this SoC's + * needs to support this SoC can use the macro CLK_LL_XTAL_FREQ_MHZ for this SoC's * fixed crystal value. * - * @return XTAL frequency in MHz, RTC_XTAL_FREQ_40M + * @return XTAL frequency in MHz */ rtc_xtal_freq_t rtc_clk_xtal_freq_get(void); @@ -381,9 +330,9 @@ void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32 /** * @brief Select source for RTC_SLOW_CLK - * @param slow_freq clock source (one of soc_rtc_slow_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_slow_clk_src_t values) */ -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq); +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src); /** * @brief Get the RTC_SLOW_CLK source @@ -407,9 +356,9 @@ uint32_t rtc_clk_slow_freq_get_hz(void); /** * @brief Select source for RTC_FAST_CLK - * @param fast_freq clock source (one of soc_rtc_fast_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_fast_clk_src_t values) */ -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq); +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src); /** * @brief Get the RTC_FAST_CLK source diff --git a/components/soc/esp32s2/include/soc/system_reg.h b/components/soc/esp32s2/include/soc/system_reg.h index 39abccdc4d..12e3c71d6a 100644 --- a/components/soc/esp32s2/include/soc/system_reg.h +++ b/components/soc/esp32s2/include/soc/system_reg.h @@ -1,16 +1,8 @@ -// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SYSTEM_REG_H_ #define _SOC_SYSTEM_REG_H_ @@ -886,10 +878,6 @@ extern "C" { #define DPORT_SOC_CLK_SEL_M ((DPORT_SOC_CLK_SEL_V)<<(DPORT_SOC_CLK_SEL_S)) #define DPORT_SOC_CLK_SEL_V 0x3 #define DPORT_SOC_CLK_SEL_S 10 -#define DPORT_SOC_CLK_SEL_XTL 0 -#define DPORT_SOC_CLK_SEL_PLL 1 -#define DPORT_SOC_CLK_SEL_8M 2 -#define DPORT_SOC_CLK_SEL_APLL 3 /* DPORT_PRE_DIV_CNT : R/W ;bitpos:[9:0] ;default: 10'h1 ; */ /*description: */ #define DPORT_PRE_DIV_CNT 0x000003FF diff --git a/components/soc/esp32s3/include/soc/clk_tree_defs.h b/components/soc/esp32s3/include/soc/clk_tree_defs.h index 8429c42971..74a3252fe2 100644 --- a/components/soc/esp32s3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s3/include/soc/clk_tree_defs.h @@ -63,6 +63,7 @@ typedef enum { SOC_CPU_CLK_SRC_XTAL = 0, /*!< Select XTAL_CLK as CPU_CLK source */ SOC_CPU_CLK_SRC_PLL = 1, /*!< Select PLL_CLK as CPU_CLK source (PLL_CLK is the output of 40MHz crystal oscillator frequency multiplier, can be 480MHz or 320MHz) */ SOC_CPU_CLK_SRC_RC_FAST = 2, /*!< Select RC_FAST_CLK as CPU_CLK source */ + SOC_CPU_CLK_SRC_INVALID, /*!< Invalid CPU_CLK source */ } soc_cpu_clk_src_t; /** @@ -73,6 +74,7 @@ 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_RC_FAST_D256 = 2, /*!< Select RC_FAST_D256_CLK (referred as FOSC_DIV or 8m_d256/8md256 in TRM and reg. description) as RTC_SLOW_CLK source */ + SOC_RTC_SLOW_CLK_SRC_INVALID, /*!< Invalid RTC_SLOW_CLK source */ } soc_rtc_slow_clk_src_t; /** @@ -83,6 +85,7 @@ typedef enum { SOC_RTC_FAST_CLK_SRC_XTAL_D2 = 0, /*!< Select XTAL_D2_CLK (may referred as XTAL_CLK_DIV_2) 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` */ SOC_RTC_FAST_CLK_SRC_RC_FAST = 1, /*!< Select RC_FAST_CLK as RTC_FAST_CLK source */ + SOC_RTC_FAST_CLK_SRC_INVALID, /*!< Invalid RTC_FAST_CLK source */ } soc_rtc_fast_clk_src_t; // Naming convention: SOC_MOD_CLK_{[upstream]clock_name}_[attr] diff --git a/components/soc/esp32s3/include/soc/io_mux_reg.h b/components/soc/esp32s3/include/soc/io_mux_reg.h index f8456b33b7..e595824e09 100644 --- a/components/soc/esp32s3/include/soc/io_mux_reg.h +++ b/components/soc/esp32s3/include/soc/io_mux_reg.h @@ -156,6 +156,8 @@ #define SD_DATA3_GPIO_NUM 10 #define USB_DM_GPIO_NUM 19 #define USB_DP_GPIO_NUM 20 +#define XTAL32K_P_GPIO_NUM 15 +#define XTAL32K_N_GPIO_NUM 16 #define MAX_RTC_GPIO_NUM 21 #define MAX_PAD_GPIO_NUM 48 diff --git a/components/soc/esp32s3/include/soc/regi2c_defs.h b/components/soc/esp32s3/include/soc/regi2c_defs.h index c3344e65c1..8b90a70b6c 100644 --- a/components/soc/esp32s3/include/soc/regi2c_defs.h +++ b/components/soc/esp32s3/include/soc/regi2c_defs.h @@ -11,8 +11,8 @@ /* Analog function control register */ #define I2C_MST_ANA_CONF0_REG 0x6000E040 #define I2C_MST_BBPLL_STOP_FORCE_HIGH (BIT(2)) -#define I2C_MST_BBPLL_STOP_FORCE_LOW (BIT(3)) -#define I2C_MST_BBPLL_CAL_DONE (BIT(24)) +#define I2C_MST_BBPLL_STOP_FORCE_LOW (BIT(3)) +#define I2C_MST_BBPLL_CAL_DONE (BIT(24)) #define ANA_CONFIG_REG 0x6000E044 #define ANA_CONFIG_S (8) diff --git a/components/soc/esp32s3/include/soc/rtc.h b/components/soc/esp32s3/include/soc/rtc.h index 02f7e1c9e2..09827e0681 100644 --- a/components/soc/esp32s3/include/soc/rtc.h +++ b/components/soc/esp32s3/include/soc/rtc.h @@ -68,14 +68,13 @@ extern "C" { #define RTC_CNTL_DBIAS_1V25 30 #define RTC_CNTL_DBIAS_1V30 31 ///< voltage is about 1.34v in fact -#define DELAY_FAST_CLK_SWITCH 3 -#define DELAY_SLOW_CLK_SWITCH 300 -#define DELAY_8M_ENABLE 50 - -/* Number of 8M/256 clock cycles to use for XTAL frequency estimation. - * 10 cycles will take approximately 300 microseconds. +/* Delays for various clock sources to be enabled/switched. + * All values are in microseconds. */ -#define XTAL_FREQ_EST_CYCLES 10 +#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 /* Core voltage needs to be increased in two cases: * 1. running at 240 MHz @@ -168,7 +167,7 @@ typedef enum { typedef struct { rtc_xtal_freq_t xtal_freq : 8; //!< Main XTAL frequency uint32_t cpu_freq_mhz : 10; //!< CPU frequency to set, in MHz - soc_rtc_fast_clk_src_t fast_clk_src : 1; //!< RTC_FAST_CLK clock source to choose + soc_rtc_fast_clk_src_t fast_clk_src : 2; //!< RTC_FAST_CLK clock source to choose soc_rtc_slow_clk_src_t slow_clk_src : 2; //!< RTC_SLOW_CLK clock source to choose uint32_t clk_rtc_clk_div : 8; uint32_t clk_8m_clk_div : 3; //!< RTC 8M clock divider (division is by clk_8m_div+1, i.e. 0 means 8MHz frequency) @@ -190,20 +189,6 @@ typedef struct { .clk_8m_dfreq = RTC_CNTL_CK8M_DFREQ_DEFAULT, \ } -typedef struct { - uint32_t dac : 6; - uint32_t dres : 3; - uint32_t dgm : 3; - uint32_t dbuf: 1; -} x32k_config_t; - -#define X32K_CONFIG_DEFAULT() { \ - .dac = 3, \ - .dres = 3, \ - .dgm = 3, \ - .dbuf = 1, \ -} - typedef struct { uint16_t wifi_powerup_cycles : 7; uint16_t wifi_wait_cycles : 9; @@ -330,9 +315,9 @@ bool rtc_clk_8md256_enabled(void); /** * @brief Select source for RTC_SLOW_CLK - * @param slow_freq clock source (one of soc_rtc_slow_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_slow_clk_src_t values) */ -void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t slow_freq); +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src); /** * @brief Get the RTC_SLOW_CLK source @@ -356,9 +341,9 @@ uint32_t rtc_clk_slow_freq_get_hz(void); /** * @brief Select source for RTC_FAST_CLK - * @param fast_freq clock source (one of soc_rtc_fast_clk_src_t values) + * @param clk_src clock source (one of soc_rtc_fast_clk_src_t values) */ -void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t fast_freq); +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src); /** * @brief Get the RTC_FAST_CLK source diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 5ce37ea15d..ae09e1d633 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -1154,7 +1154,6 @@ components/soc/esp32/include/soc/can_periph.h components/soc/esp32/include/soc/can_struct.h components/soc/esp32/include/soc/clkout_channel.h components/soc/esp32/include/soc/dac_channel.h -components/soc/esp32/include/soc/dport_reg.h components/soc/esp32/include/soc/emac_dma_struct.h components/soc/esp32/include/soc/emac_ext_struct.h components/soc/esp32/include/soc/emac_mac_struct.h @@ -1173,7 +1172,6 @@ components/soc/esp32/include/soc/host_struct.h components/soc/esp32/include/soc/hwcrypto_reg.h components/soc/esp32/include/soc/i2c_reg.h components/soc/esp32/include/soc/i2c_struct.h -components/soc/esp32/include/soc/io_mux_reg.h components/soc/esp32/include/soc/ledc_reg.h components/soc/esp32/include/soc/ledc_struct.h components/soc/esp32/include/soc/nrx_reg.h @@ -1371,7 +1369,6 @@ components/soc/esp32s2/include/soc/spi_reg.h components/soc/esp32s2/include/soc/spi_struct.h components/soc/esp32s2/include/soc/syscon_reg.h components/soc/esp32s2/include/soc/syscon_struct.h -components/soc/esp32s2/include/soc/system_reg.h components/soc/esp32s2/include/soc/systimer_reg.h components/soc/esp32s2/include/soc/systimer_struct.h components/soc/esp32s2/include/soc/touch_sensor_channel.h