xtensa/esp32: Add functions to switch CPU frequency from 80MHz to 240Mhz

This commit is contained in:
chenwen 2020-08-20 09:03:13 -03:00 committed by patacongo
parent 0ddefd7c69
commit 1e9ef469dc
4 changed files with 471 additions and 45 deletions

View File

@ -5,6 +5,26 @@
if ARCH_CHIP_ESP32
choice ESP32_DEFAULT_CPU_FREQ_MHZ
prompt "CPU frequency"
default ESP32_DEFAULT_CPU_FREQ_240
help
CPU frequency to be set on application startup.
config ESP32_DEFAULT_CPU_FREQ_80
bool "80 MHz"
config ESP32_DEFAULT_CPU_FREQ_160
bool "160 MHz"
config ESP32_DEFAULT_CPU_FREQ_240
bool "240 MHz"
endchoice # CPU frequency
config ESP32_DEFAULT_CPU_FREQ_MHZ
int
default 80 if ESP32_DEFAULT_CPU_FREQ_80
default 160 if ESP32_DEFAULT_CPU_FREQ_160
default 240 if ESP32_DEFAULT_CPU_FREQ_240
menu "ESP32 Peripheral Selection"
config ESP32_UART

View File

@ -31,20 +31,14 @@
#include <stdint.h>
#include "xtensa.h"
#ifndef CONFIG_SUPPRESS_CLOCK_CONFIG
#warning REVISIT ... function prototypes
void phy_get_romfunc_addr(void);
void rtc_init_lite(void);
void rtc_set_cpu_freq(xtal_freq_t xtal_freq, enum xtal_freq_e cpu_freq);
#endif
#include "hardware/esp32_dport.h"
#include "hardware/esp32_soc.h"
/****************************************************************************
* Private Types
****************************************************************************/
#ifndef CONFIG_SUPPRESS_CLOCK_CONFIG
enum xtal_freq_e
enum xtal_freq_t
{
XTAL_40M = 40,
XTAL_26M = 26,
@ -52,13 +46,276 @@ enum xtal_freq_e
XTAL_AUTO = 0
};
enum xtal_freq_e
enum cpu_freq_t
{
CPU_80M = 1,
CPU_160M = 2,
CPU_240M = 3,
CPU_80M = 0,
CPU_160M = 1,
CPU_240M = 2,
};
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: esp32_set_cpu_freq
*
* Description:
* Switch to one of PLL-based frequencies.
* Current frequency can be XTAL or PLL.
*
* Input Parameters:
* cpu_freq_mhz - new CPU frequency
*
* Returned Value:
* None
*
****************************************************************************/
static void esp32_set_cpu_freq(int cpu_freq_mhz)
{
int dbias = DIG_DBIAS_80M_160M;
int per_conf;
uint32_t value;
switch (cpu_freq_mhz)
{
case 160:
per_conf = CPU_160M;
break;
case 240:
dbias = DIG_DBIAS_240M;
per_conf = CPU_240M;
break;
case 80:
per_conf = CPU_80M;
default:
break;
}
value = (((80 * MHZ) >> 12) & UINT16_MAX)
| ((((80 * MHZ) >> 12) & UINT16_MAX) << 16);
putreg32(value, RTC_APB_FREQ_REG);
putreg32(per_conf, DPORT_CPU_PER_CONF_REG);
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias);
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL,
RTC_CNTL_SOC_CLK_SEL_PLL);
}
/****************************************************************************
* Name: esp32_bbpll_configure
*
* Description:
* Configure main XTAL frequency values according to pll_freq.
*
* Input Parameters:
* xtal_freq - XTAL frequency values
* pll_freq - PLL frequency values
*
* Returned Value:
* None
*
****************************************************************************/
static void esp32_bbpll_configure(enum xtal_freq_t xtal_freq, int pll_freq)
{
uint8_t div_ref;
uint8_t div7_0;
uint8_t div10_8;
uint8_t lref;
uint8_t dcur;
uint8_t bw;
uint8_t i2c_bbpll_lref;
uint8_t i2c_bbpll_div_7_0;
uint8_t i2c_bbpll_dcur;
if (pll_freq == RTC_PLL_FREQ_320M)
{
/* Raise the voltage, if needed */
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK,
DIG_DBIAS_80M_160M);
/* Configure 320M PLL */
switch (xtal_freq)
{
case XTAL_40M:
div_ref = 0;
div7_0 = 32;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
break;
case XTAL_26M:
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
break;
case XTAL_24M:
div_ref = 11;
div7_0 = 224;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
break;
default:
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
break;
}
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_320M);
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP,
BBPLL_BBADC_DSMP_VAL_320M);
}
else
{
/* Raise the voltage */
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_240M);
ets_delay_us(DELAY_PLL_DBIAS_RAISE);
/* Configure 480M PLL */
switch (xtal_freq)
{
case XTAL_40M:
div_ref = 0;
div7_0 = 28;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
break;
case XTAL_26M:
div_ref = 12;
div7_0 = 144;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
break;
case XTAL_24M:
div_ref = 11;
div7_0 = 144;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
break;
default:
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
break;
}
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_480M);
I2C_WRITEREG_RTC(I2C_BBPLL,
I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_480M);
}
i2c_bbpll_lref = (lref << 7) | (div10_8 << 4) | (div_ref);
i2c_bbpll_div_7_0 = div7_0;
i2c_bbpll_dcur = (bw << 6) | dcur;
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_LREF, i2c_bbpll_lref);
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
}
/****************************************************************************
* Name: esp32_bbpll_enable
*
* Description:
* Reset BBPLL configuration.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void esp32_bbpll_enable(void)
{
modifyreg32(RTC_CNTL_OPTIONS0_REG,
RTC_CNTL_BIAS_I2C_FORCE_PD | RTC_CNTL_BB_I2C_FORCE_PD |
RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0);
/* reset BBPLL configuration */
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_DELAY,
BBPLL_IR_CAL_DELAY_VAL);
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_EXT_CAP,
BBPLL_IR_CAL_EXT_CAP_VAL);
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_ENB_FCAL,
BBPLL_OC_ENB_FCAL_VAL);
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_ENB_VCON,
BBPLL_OC_ENB_VCON_VAL);
I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_CAL_7_0,
BBPLL_BBADC_CAL_7_0_VAL);
}
/****************************************************************************
* Name: esp32_update_to_xtal
*
* Description:
* Switch to XTAL frequency, does not disable the PLL
*
* Input Parameters:
* freq - XTAL frequency
* div - REF_TICK divider
*
* Returned Value:
* none
*
****************************************************************************/
static void esp32_update_to_xtal(int freq, int div)
{
uint32_t value = (((freq * MHZ) >> 12) & UINT16_MAX)
| ((((freq * MHZ) >> 12) & UINT16_MAX) << 16);
putreg32(value, RTC_APB_FREQ_REG);
/* set divider from XTAL to APB clock */
REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, div - 1);
/* switch clock source */
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL,
RTC_CNTL_SOC_CLK_SEL_XTL);
/* adjust ref_tick */
modifyreg32(APB_CTRL_XTAL_TICK_CONF_REG, 0,
(freq * MHZ) / REF_CLK_FREQ - 1);
/* 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);
}
}
/****************************************************************************
* Public Functions
@ -76,40 +333,29 @@ enum xtal_freq_e
void esp32_clockconfig(void)
{
#ifdef CONFIG_SUPPRESS_CLOCK_CONFIG
# warning WARNING: Clock configuration disabled
#else
uint32_t freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
enum xtal_freq_e freq;
phy_get_romfunc_addr();
/* Frequency will be changed to 40MHz in rtc_init_lite */
rtc_init_lite();
uint32_t source_freq_mhz;
enum xtal_freq_t xtal_freq = XTAL_40M;
enum cpu_freq_t freq;
freq = CPU_80M;
switch (freq_mhz)
{
case 240:
freq = CPU_240M;
break;
case 160:
freq = CPU_160M;
break;
default:
freq_mhz = 80;
/* no break */
case 80:
freq = CPU_80M;
break;
case 240:
freq = CPU_240M;
source_freq_mhz = RTC_PLL_FREQ_480M;
break;
case 160:
freq = CPU_160M;
source_freq_mhz = RTC_PLL_FREQ_320M;
break;
case 80:
default:
return;
}
/* Frequency will be changed to freq in rtc_set_cpu_freq */
rtc_set_cpu_freq(XTAL_AUTO, freq);
ets_update_cpu_frequency(freq_mhz);
#endif
esp32_update_to_xtal(xtal_freq, 1);
esp32_bbpll_enable();
esp32_bbpll_configure(xtal_freq, source_freq_mhz);
esp32_set_cpu_freq(freq_mhz);
}

View File

@ -168,7 +168,7 @@
/* Set bits of register controlled by mask */
#define SET_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask))) */
#define SET_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask)))
/* Get bits of register controlled by mask */
@ -192,6 +192,7 @@
#define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM
#define CPU_CLK_FREQ APB_CLK_FREQ
#define APB_CLK_FREQ 80*1000000 /* Unit: Hz */
#define REF_CLK_FREQ ( 1000000 )
#define UART_CLK_FREQ APB_CLK_FREQ
#define WDT_CLK_FREQ APB_CLK_FREQ
#define TIMER_CLK_FREQ (80000000>>4) /* 80MHz divided by 16 */
@ -371,4 +372,159 @@
/* Other interrupt numbers should be managed by the user */
#define DR_REG_APB_CTRL_BASE 0x3ff66000 /* Old name for SYSCON, to be removed */
#define APB_CTRL_SYSCLK_CONF_REG (DR_REG_APB_CTRL_BASE + 0x0)
#define APB_CTRL_XTAL_TICK_CONF_REG (DR_REG_APB_CTRL_BASE + 0x4)
/* APB_CTRL_PRE_DIV_CNT : R/W ;bitpos:[9:0] ;default: 10'h0 ; */
#define APB_CTRL_PRE_DIV_CNT 0x000003FF
#define APB_CTRL_PRE_DIV_CNT_M ((APB_CTRL_PRE_DIV_CNT_V)<<(APB_CTRL_PRE_DIV_CNT_S))
#define APB_CTRL_PRE_DIV_CNT_V 0x3FF
#define APB_CTRL_PRE_DIV_CNT_S 0
#define I2C_BBPLL_IR_CAL_DELAY 0
#define I2C_BBPLL_IR_CAL_EXT_CAP 1
#define I2C_BBPLL_OC_ENB_FCAL 4
#define I2C_BBPLL_OC_ENB_VCON 10
#define I2C_BBPLL_BBADC_CAL_7_0 12
#define I2C_BBPLL_OC_LREF 2
#define I2C_BBPLL_OC_LREF_MSB 7
#define I2C_BBPLL_OC_LREF_LSB 7
#define I2C_BBPLL_OC_DIV_7_0 3
#define I2C_BBPLL_OC_DIV_7_0_MSB 7
#define I2C_BBPLL_OC_DIV_7_0_LSB 0
#define I2C_BBPLL_BBADC_DSMP 9
#define I2C_BBPLL_BBADC_DSMP_MSB 7
#define I2C_BBPLL_BBADC_DSMP_LSB 4
#define I2C_BBPLL_OC_DCUR 5
#define I2C_BBPLL_OC_DCUR_MSB 2
#define I2C_BBPLL_OC_DCUR_LSB 0
#define I2C_BBPLL_ENDIV5 11
#define I2C_BBPLL 0x66
#define I2C_BBPLL_HOSTID 4
#define I2C_WRITEREG_RTC(block, reg_add, indata) \
rom_i2c_writeReg(block, block##_HOSTID, reg_add, indata)
/* BBPLL configuration values */
#define BBPLL_ENDIV5_VAL_320M 0x43
#define BBPLL_BBADC_DSMP_VAL_320M 0x84
#define BBPLL_ENDIV5_VAL_480M 0xc3
#define BBPLL_BBADC_DSMP_VAL_480M 0x74
#define BBPLL_IR_CAL_DELAY_VAL 0x18
#define BBPLL_IR_CAL_EXT_CAP_VAL 0x20
#define BBPLL_OC_ENB_FCAL_VAL 0x9a
#define BBPLL_OC_ENB_VCON_VAL 0x00
#define BBPLL_BBADC_CAL_7_0_VAL 0x00
#define EFUSE_BLK0_RDATA5_REG (DR_REG_EFUSE_BASE + 0x014)
#define EFUSE_RD_VOL_LEVEL_HP_INV 0x03
#define EFUSE_RD_VOL_LEVEL_HP_INV_S 22
#define REG_TIMG_BASE(i) (DR_REG_TIMERGROUP0_BASE + i*0x1000)
#define TIMG_RTCCALICFG_REG(i) (REG_TIMG_BASE(i) + 0x0068)
#define RTC_CNTL_OPTIONS0_REG (DR_REG_RTCCNTL_BASE + 0x0)
#define RTC_CNTL_STORE5_REG (DR_REG_RTCCNTL_BASE + 0xb4)
#define RTC_APB_FREQ_REG RTC_CNTL_STORE5_REG
#define RTC_CNTL_REG (DR_REG_RTCCNTL_BASE + 0x7c)
#define RTC_CNTL_CLK_CONF_REG (DR_REG_RTCCNTL_BASE + 0x70)
#define RTC_CNTL_ANA_CONF_REG (DR_REG_RTCCNTL_BASE + 0x30)
#define RTC_CNTL_STORE4_REG (DR_REG_RTCCNTL_BASE + 0xb0)
#define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG
/* Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP,
* RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values.
* Valid if RTC_CNTL_DBG_ATTEN is 0.
*/
#define RTC_CNTL_DBIAS_1V00 2
#define RTC_CNTL_DBIAS_1V10 4
#define RTC_CNTL_DBIAS_1V25 7
/* RTC_CNTL_DIG_DBIAS_WAK : R/W ;bitpos:[13:11] ;default: 3'd4 ; */
#define RTC_CNTL_DIG_DBIAS_WAK 0x00000007
#define RTC_CNTL_DIG_DBIAS_WAK_S 11
/* RTC_CNTL_SOC_CLK_SEL : R/W ;bitpos:[28:27] ;default: 2'd0 ;
* description: SOC clock sel. 0: XTAL 1: PLL 2: CK8M 3: APLL
*/
#define RTC_CNTL_SOC_CLK_SEL 0x00000003
#define RTC_CNTL_SOC_CLK_SEL_S 27
#define RTC_CNTL_SOC_CLK_SEL_XTL 0
#define RTC_CNTL_SOC_CLK_SEL_PLL 1
#define RTC_CNTL_SOC_CLK_SEL_8M 2
#define RTC_CNTL_SOC_CLK_SEL_APLL 3
/* Core voltage needs to be increased in two cases:
* 1. running at 240 MHz
* 2. running with 80MHz Flash frequency
* There is a record in efuse which indicates the
* proper voltage for these two cases.
*/
#define RTC_CNTL_DBIAS_HP_VOLT (RTC_CNTL_DBIAS_1V25 - (REG_GET_FIELD(EFUSE_BLK0_RDATA5_REG, EFUSE_RD_VOL_LEVEL_HP_INV)))
#ifdef CONFIG_ESPTOOLPY_FLASHFREQ_80M
#define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_HP_VOLT
#else
#define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V10
#endif
#define DIG_DBIAS_240M RTC_CNTL_DBIAS_HP_VOLT
#define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10
#define DIG_DBIAS_2M RTC_CNTL_DBIAS_1V00
#define DELAY_PLL_DBIAS_RAISE 3
#define DELAY_PLL_ENABLE_WITH_150K 80
#define DELAY_PLL_ENABLE_WITH_32K 160
/* RTC_CNTL_BB_I2C_FORCE_PD : R/W ;bitpos:[6] ;default: 1'b0 ;
* description: BB_I2C force power down
*/
#define RTC_CNTL_BB_I2C_FORCE_PD (BIT(6))
/* RTC_CNTL_BBPLL_FORCE_PD : R/W ;bitpos:[10] ;default: 1'b0 ;
* description: BB_PLL force power down
*/
#define RTC_CNTL_BBPLL_FORCE_PD (BIT(10))
/* RTC_CNTL_BBPLL_I2C_FORCE_PD : R/W ;bitpos:[8] ;default: 1'b0 ;
* description: BB_PLL _I2C force power down
*/
#define RTC_CNTL_BBPLL_I2C_FORCE_PD (BIT(8))
/* RTC_CNTL_PLLA_FORCE_PD : R/W ;bitpos:[23] ;default: 1'b1 ;
* description: PLLA force power down
*/
#define RTC_CNTL_PLLA_FORCE_PD (BIT(23))
#define RTC_CNTL_PLLA_FORCE_PD_S 23
/* RTC_CNTL_BIAS_I2C_FORCE_PD : R/W ;bitpos:[18] ;default: 1'b0 ;
* description: BIAS_I2C force power down
*/
#define RTC_CNTL_BIAS_I2C_FORCE_PD (BIT(18))
#define MHZ (1000000)
#define RTC_PLL_FREQ_320M 320
#define RTC_PLL_FREQ_480M 480
#endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_SOC_H */

View File

@ -70,13 +70,17 @@
* which is 40MHz by default.
*
* Reference:
* https://github.com/espressif/esp-idf/blob/6fd855ab8d00d23bad4660216bc2122c2285d5be/components/bootloader_support/src/bootloader_clock.c#L38-L62
* https://bit.ly/3aJhjPH (shorten URL to avoid nxstyle issues)
*/
#ifdef CONFIG_ESP32CORE_RUN_IRAM
# define BOARD_CLOCK_FREQUENCY (2 * BOARD_XTAL_FREQUENCY)
#else
#ifdef CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
# define BOARD_CLOCK_FREQUENCY (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000)
#else
# define BOARD_CLOCK_FREQUENCY 80000000
#endif
#endif
#endif /* __BOARDS_XTENSA_ESP32_ESP32_CORE_INCLUDE_BOARD_H */