Merge branch 'bugfix/fix_cpu_switches_freq_bug_s2s3_to_v4.4' into 'release/v4.4'

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

See merge request espressif/esp-idf!26282
This commit is contained in:
Jiang Jiang Jian
2023-10-25 10:24:32 +08:00
3 changed files with 79 additions and 40 deletions

View File

@@ -268,25 +268,46 @@ 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) static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
{ {
int dbias = DIG_DBIAS_80M_160M; rtc_cpu_freq_config_t cur_config;
rtc_clk_cpu_freq_get_config(&cur_config);
int per_conf = DPORT_CPUPERIOD_SEL_80; int per_conf = DPORT_CPUPERIOD_SEL_80;
if (cpu_freq_mhz == 80) { if (cpu_freq_mhz == 80) {
/* nothing to do */ /* nothing to do */
} else if (cpu_freq_mhz == 160) { } else if (cpu_freq_mhz == 160) {
per_conf = DPORT_CPUPERIOD_SEL_160; per_conf = DPORT_CPUPERIOD_SEL_160;
} else if (cpu_freq_mhz == 240) { } else if (cpu_freq_mhz == 240) {
dbias = DIG_DBIAS_240M;
per_conf = DPORT_CPUPERIOD_SEL_240; per_conf = DPORT_CPUPERIOD_SEL_240;
} else { } else {
SOC_LOGE(TAG, "invalid frequency"); SOC_LOGE(TAG, "invalid frequency");
abort(); abort();
} }
/* 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_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, per_conf);
REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_PRE_DIV_CNT, 0); 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); REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL);
rtc_clk_apb_freq_update(80 * MHZ); rtc_clk_apb_freq_update(80 * MHZ);
ets_update_cpu_frequency(cpu_freq_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) bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* out_config)
@@ -436,6 +457,9 @@ void rtc_clk_cpu_freq_set_xtal(void)
*/ */
void rtc_clk_cpu_freq_to_xtal(int freq, int div) 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); ets_update_cpu_frequency(freq);
/* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ /* 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, 0);
@@ -444,18 +468,24 @@ void rtc_clk_cpu_freq_to_xtal(int freq, int div)
/* switch clock source */ /* switch clock source */
REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL);
rtc_clk_apb_freq_update(freq * MHZ); rtc_clk_apb_freq_update(freq * MHZ);
/* lower the voltage */ /* lower the voltage
if (freq <= 2) { * cpu_frequency < 240M: dbias = DIG_DBIAS_XTAL_80M_160M;
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_2M); * cpu_frequency = 240M: dbias = DIG_DBIAS_240M;
} else { */
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); 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) static void rtc_clk_cpu_freq_to_8m(void)
{ {
assert(0 && "LDO dbias need to modified");
ets_update_cpu_frequency(8); ets_update_cpu_frequency(8);
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); 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_PRE_DIV_CNT, 0);
REG_SET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M); 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); rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M);

View File

@@ -301,18 +301,6 @@ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
SOC_LOGE(TAG, "invalid frequency"); SOC_LOGE(TAG, "invalid frequency");
} }
/* 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. /* 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. * 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; * 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;
@@ -323,23 +311,34 @@ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
int pd_slave = cpu_freq_mhz / 80; int pd_slave = cpu_freq_mhz / 80;
rtc_cpu_freq_config_t cur_config; rtc_cpu_freq_config_t cur_config;
rtc_clk_cpu_freq_get_config(&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 > cur_config.freq_mhz) {
REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE >> pd_slave); if (cpu_freq_mhz == 240) {
REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_240m);
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_240m);
/* switch clock source */ esp_rom_delay_us(40);
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL); }
rtc_clk_apb_freq_update(80 * MHZ);
ets_update_cpu_frequency(cpu_freq_mhz);
} else {
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);
/* switch clock source */
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL);
rtc_clk_apb_freq_update(80 * MHZ);
ets_update_cpu_frequency(cpu_freq_mhz);
REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE >> pd_slave); REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE >> pd_slave);
} }
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);
/* switch clock source */
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_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) {
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);
}
} }
bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config) bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config)
@@ -496,9 +495,9 @@ void rtc_clk_cpu_freq_set_xtal(void)
*/ */
void rtc_clk_cpu_freq_to_xtal(int freq, int div) void rtc_clk_cpu_freq_to_xtal(int freq, int div)
{ {
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_non_240m); rtc_cpu_freq_config_t cur_config;
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_non_240m); rtc_clk_cpu_freq_get_config(&cur_config);
esp_rom_delay_us(40);
ets_update_cpu_frequency(freq); ets_update_cpu_frequency(freq);
/* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ /* 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, 0);
@@ -507,18 +506,25 @@ void rtc_clk_cpu_freq_to_xtal(int freq, int div)
/* switch clock source */ /* switch clock source */
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL);
rtc_clk_apb_freq_update(freq * MHZ); rtc_clk_apb_freq_update(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); REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE);
} }
static void rtc_clk_cpu_freq_to_8m(void) static void rtc_clk_cpu_freq_to_8m(void)
{ {
assert(0 && "LDO dbias need to modified");
ets_update_cpu_frequency(8); ets_update_cpu_frequency(8);
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(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); 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); REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M);
rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M); rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M);
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); REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE);
} }

View File

@@ -96,7 +96,10 @@ extern "C" {
#define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V10 #define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V10
#endif #endif
#define DIG_DBIAS_240M RTC_CNTL_DBIAS_1V25 #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 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 DIG_DBIAS_2M RTC_CNTL_DBIAS_1V00
#define RTC_CNTL_PLL_BUF_WAIT_DEFAULT 20 #define RTC_CNTL_PLL_BUF_WAIT_DEFAULT 20