Skip to content

Commit

Permalink
Merge branch 'bugfix/fix_cpu_switches_freq_bug_s2_to_v4.3' into 'rele…
Browse files Browse the repository at this point in the history
…ase/v4.3'

EspS2: fixed the bug of insufficient voltage when the CPU switches frequency(V4.3)

See merge request espressif/esp-idf!26283
  • Loading branch information
jack0c committed Dec 4, 2023
2 parents f994bb8 + bcfec3e commit 8196913
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 8 deletions.
52 changes: 44 additions & 8 deletions components/esp_hw_support/port/esp32s2/rtc_clk.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions components/soc/esp32s2/include/soc/rtc.h
Expand Up @@ -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
Expand Down

0 comments on commit 8196913

Please sign in to comment.