Skip to content

Commit

Permalink
Merge branch 'esp32_s2_s3_cpu_freq_to_pll' into 'master'
Browse files Browse the repository at this point in the history
EspS2/S3: fixed the bug of insufficient voltage when the CPU switches frequency

See merge request espressif/esp-idf!25396
  • Loading branch information
ginkgm committed Sep 18, 2023
2 parents ae80ad7 + 77a3032 commit efb9d9e
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 39 deletions.
2 changes: 1 addition & 1 deletion components/esp_hw_support/port/esp32/rtc_clk.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down
50 changes: 44 additions & 6 deletions components/esp_hw_support/port/esp32s2/rtc_clk.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -256,13 +256,39 @@ 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)
Expand Down Expand Up @@ -411,6 +437,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);
Expand All @@ -419,15 +448,24 @@ 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);
Expand Down
68 changes: 37 additions & 31 deletions components/esp_hw_support/port/esp32s3/rtc_clk.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -185,17 +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.
Expand All @@ -207,21 +196,31 @@ 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);
}
}
Expand Down Expand Up @@ -376,28 +375,35 @@ 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);
clk_ll_cpu_set_divider(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);
}

Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32/include/soc/rtc.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down
3 changes: 3 additions & 0 deletions components/soc/esp32s2/include/soc/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit efb9d9e

Please sign in to comment.