From bb33a2bf6b3c1ae2574a8e7854134279ff2291c2 Mon Sep 17 00:00:00 2001 From: hongshuqing Date: Tue, 19 Sep 2023 11:27:08 +0800 Subject: [PATCH] fix cpu switches freq bug s2s3 to v5.1 --- .../esp_hw_support/port/esp32s2/rtc_clk.c | 53 ++++++++++++-- .../esp_hw_support/port/esp32s3/rtc_clk.c | 70 ++++++++++--------- components/soc/esp32s2/include/soc/rtc.h | 3 + 3 files changed, 88 insertions(+), 38 deletions(-) diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk.c b/components/esp_hw_support/port/esp32s2/rtc_clk.c index bf53944bb4..369ce96355 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -256,13 +256,41 @@ static 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 = (cpu_freq_mhz == 240) ? DIG_DBIAS_240M : DIG_DBIAS_80M_160M; + /* 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); + } + } + 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); clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); rtc_clk_apb_freq_update(80 * MHZ); esp_rom_set_cpu_ticks_per_us(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) @@ -411,6 +439,9 @@ void rtc_clk_cpu_set_to_default_config(void) */ static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { + rtc_cpu_freq_config_t cur_config; + rtc_clk_cpu_freq_get_config(&cur_config); + esp_rom_set_cpu_ticks_per_us(cpu_freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ clk_ll_cpu_set_divider(1); @@ -419,15 +450,25 @@ static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) /* switch clock source */ clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); rtc_clk_apb_freq_update(cpu_freq * MHZ); - /* lower the voltage */ - int dbias = (cpu_freq <= 2) ? DIG_DBIAS_2M : DIG_DBIAS_XTAL; - REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias); + + /* 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"); esp_rom_set_cpu_ticks_per_us(8); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); + esp_rom_delay_us(40); 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); diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk.c b/components/esp_hw_support/port/esp32s3/rtc_clk.c index 29b96aac18..a17ccc80ed 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s3/rtc_clk.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -185,18 +185,6 @@ static 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) { - /* cpu_frequency < 240M: dbias = pvt-dig + 2; - cpu_frequency = 240M: dbias = pvt-dig + 3; - */ - if (cpu_freq_mhz != 240) { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_non_240m); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_non_240m); - } else { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_240m); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_240m); - } - esp_rom_delay_us(40); - /* There are totally 6 LDO slaves(all on by default). At the moment of swithing LDO slave, LDO voltage will also change instantaneously. * LDO slave can reduce the voltage change caused by switching frequency. * CPU frequency <= 40M : just open 3 LDO slaves; CPU frequency = 80M : open 4 LDO slaves; CPU frequency = 160M : open 5 LDO slaves; CPU frequency = 240M : open 6 LDO slaves; @@ -207,21 +195,32 @@ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) int pd_slave = cpu_freq_mhz / 80; rtc_cpu_freq_config_t cur_config; rtc_clk_cpu_freq_get_config(&cur_config); + /* cpu_frequency < 240M: dbias = pvt-dig + 2; + * cpu_frequency = 240M: dbias = pvt-dig + 3; + */ if (cpu_freq_mhz > cur_config.freq_mhz) { + if (cpu_freq_mhz == 240) { + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_240m); + esp_rom_delay_us(40); + } REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE >> pd_slave); - 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); - esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz); - } else { - 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); - esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz); + } + + 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); + esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz); + + if (cpu_freq_mhz < cur_config.freq_mhz) { + if (cur_config.freq_mhz == 240) { + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_non_240m); + esp_rom_delay_us(40); + } + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE >> pd_slave); } } @@ -376,9 +375,9 @@ void rtc_clk_cpu_set_to_default_config(void) */ void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_non_240m); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_non_240m); - esp_rom_delay_us(40); + rtc_cpu_freq_config_t cur_config; + rtc_clk_cpu_freq_get_config(&cur_config); + esp_rom_set_cpu_ticks_per_us(cpu_freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ clk_ll_cpu_set_divider(1); @@ -386,18 +385,25 @@ void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) /* switch clock source */ clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); rtc_clk_apb_freq_update(cpu_freq * MHZ); + + if (cur_config.freq_mhz == 240) { + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_non_240m); + esp_rom_delay_us(40); + } + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE); } static void rtc_clk_cpu_freq_to_8m(void) { + assert(0 && "LDO dbias need to modified"); esp_rom_set_cpu_ticks_per_us(20); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_non_240m); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_non_240m); - esp_rom_delay_us(40); 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); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_non_240m); REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE); } diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index e703c4c0bc..174ca22d7b 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -84,7 +84,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