From bcfec3e09e9062506af2d850d39578a7b577b925 Mon Sep 17 00:00:00 2001 From: hongshuqing Date: Thu, 28 Sep 2023 14:09:12 +0800 Subject: [PATCH] s2 cpu sw freq --- .../esp_hw_support/port/esp32s2/rtc_clk.c | 52 ++++++++++++++++--- components/soc/esp32s2/include/soc/rtc.h | 3 ++ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk.c b/components/esp_hw_support/port/esp32s2/rtc_clk.c index 8a11266efb..540fa0a567 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk.c @@ -275,25 +275,52 @@ 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 { SOC_LOGE(TAG, "invalid frequency"); abort(); } + + /* To avoid the problem of insufficient voltage when the CPU frequency is switched: + * When the CPU frequency is switched from low to high, it is necessary to + * increase the voltage first and then increase the frequency, and the frequency + * needs to wait for the voltage to fully increase before proceeding. + * When the frequency of the CPU is switched from high to low, it is necessary + * to reduce the frequency first and then reduce the voltage. + */ + + rtc_cpu_freq_config_t cur_config; + rtc_clk_cpu_freq_get_config(&cur_config); + /* cpu_frequency < 240M: dbias = DIG_DBIAS_XTAL_80M_160M; + * cpu_frequency = 240M: dbias = DIG_DBIAS_240M; + */ + if (cpu_freq_mhz > cur_config.freq_mhz) { + if (cpu_freq_mhz == 240) { + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_240M); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_DBIAS_240M); + esp_rom_delay_us(40); + } + } + 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); - 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); rtc_clk_apb_freq_update(80 * MHZ); ets_update_cpu_frequency(cpu_freq_mhz); + + if (cpu_freq_mhz < cur_config.freq_mhz) { + if (cur_config.freq_mhz == 240) { + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL_80M_160M); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_DBIAS_XTAL_80M_160M); + esp_rom_delay_us(40); + } + } } bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* out_config) @@ -446,6 +473,9 @@ void rtc_clk_cpu_freq_set_xtal(void) */ void rtc_clk_cpu_freq_to_xtal(int freq, int div) { + rtc_cpu_freq_config_t cur_config; + rtc_clk_cpu_freq_get_config(&cur_config); + 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); @@ -454,18 +484,24 @@ void rtc_clk_cpu_freq_to_xtal(int freq, int div) /* switch clock source */ REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_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); + + /* lower the voltage + * cpu_frequency < 240M: dbias = DIG_DBIAS_XTAL_80M_160M; + * cpu_frequency = 240M: dbias = DIG_DBIAS_240M; + */ + if (cur_config.freq_mhz == 240) { + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL_80M_160M); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_DBIAS_XTAL_80M_160M); + esp_rom_delay_us(40); } } static void rtc_clk_cpu_freq_to_8m(void) { + assert(0 && "LDO dbias need to modified"); ets_update_cpu_frequency(8); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); + esp_rom_delay_us(40); 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); rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M); diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index 1503f34892..afeb4dd931 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -96,7 +96,10 @@ extern "C" { #define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V10 #endif #define DIG_DBIAS_240M RTC_CNTL_DBIAS_1V25 +#define RTC_DBIAS_240M RTC_CNTL_DBIAS_1V25 #define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10 +#define DIG_DBIAS_XTAL_80M_160M RTC_CNTL_DBIAS_1V10 +#define RTC_DBIAS_XTAL_80M_160M RTC_CNTL_DBIAS_1V10 #define DIG_DBIAS_2M RTC_CNTL_DBIAS_1V00 #define RTC_CNTL_PLL_BUF_WAIT_DEFAULT 20