feat(volt): chip auto adjust volt for esp32c6 & esp32h2

This commit is contained in:
zlq
2023-09-06 16:09:26 +08:00
committed by BOT
parent d7bb1b27e2
commit b221f87e00
28 changed files with 2132 additions and 21 deletions

View File

@@ -5,6 +5,7 @@ set(srcs "rtc_clk_init.c"
"pmu_sleep.c"
"rtc_time.c"
"chip_info.c"
"pmu_pvt_pump.c"
)
if(NOT BOOTLOADER_BUILD)

View File

@@ -13,6 +13,7 @@
#include "soc/pmu_struct.h"
#include "hal/pmu_hal.h"
#include "pmu_param.h"
#include "esp_rom_sys.h"
#include "esp_private/esp_pmu.h"
#include "soc/regi2c_pmu.h"
#include "soc/regi2c_bias.h"
@@ -193,9 +194,6 @@ static void pmu_lp_system_init_default(pmu_context_t *ctx)
void pmu_init()
{
/* No peripheral reg i2c power up required on the target */
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG_SLP, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG_SLP, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_RTC_REG, 0);
@@ -215,4 +213,12 @@ void pmu_init()
pmu_lp_system_init_default(PMU_instance());
pmu_power_domain_force_default(PMU_instance());
pvt_auto_dbias_init();
charge_pump_init();
//HP dbias initialization
pvt_func_enable(1);
charge_pump_enable(1);
esp_rom_delay_us(1000);
}

View File

@@ -295,7 +295,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m
| BIT(PMU_ICG_FUNC_ENA_SEC) \
| BIT(PMU_ICG_FUNC_ENA_PWM) \
| BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \
| BIT(PMU_ICG_FUNC_ENA_UART0)), \
| BIT(PMU_ICG_FUNC_ENA_UART0)) \
| BIT(PMU_ICG_FUNC_ENA_PVT_MONITOR), \
}
#define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \
@@ -342,7 +343,8 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m
| BIT(PMU_ICG_FUNC_ENA_SEC) \
| BIT(PMU_ICG_FUNC_ENA_PWM) \
| BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \
| BIT(PMU_ICG_FUNC_ENA_UART0)), \
| BIT(PMU_ICG_FUNC_ENA_UART0)) \
| BIT(PMU_ICG_FUNC_ENA_PVT_MONITOR), \
}
const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode)

View File

@@ -0,0 +1,86 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdlib.h>
#include <esp_types.h>
#include "sdkconfig.h"
#include "soc/soc.h"
#include "soc/pvt_reg.h"
#include "soc/pmu_reg.h"
#include "soc/pcr_reg.h"
#include "pmu_param.h"
#include "esp_private/esp_pmu.h"
#include "soc/regi2c_pmu.h"
#include "soc/regi2c_bias.h"
#include "regi2c_ctrl.h"
#include "soc/rtc.h"
static __attribute__((unused)) const char *TAG = "pmu_pvt_pump";
void pvt_auto_dbias_init(void)
{
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, 0);
/*config for dbias func*/
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL_SEL0_REG, PVT_DBIAS_CHANNEL0_SEL, PVT_CHANNEL0_SEL, PVT_DBIAS_CHANNEL0_SEL_S);
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL_SEL0_REG, PVT_DBIAS_CHANNEL1_SEL, PVT_CHANNEL1_SEL, PVT_DBIAS_CHANNEL1_SEL_S); // Select monitor cell ,which used to monitor PVT situation
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL0_SEL_REG, PVT_DBIAS_CHANNEL0_CFG, PVT_CHANNEL0_CFG, PVT_DBIAS_CHANNEL0_CFG_S);
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL1_SEL_REG, PVT_DBIAS_CHANNEL1_CFG, PVT_CHANNEL1_CFG, PVT_DBIAS_CHANNEL1_CFG_S);
SET_PERI_REG_BITS(PVT_DBIAS_CHANNEL2_SEL_REG, PVT_DBIAS_CHANNEL2_CFG, PVT_CHANNEL2_CFG, PVT_DBIAS_CHANNEL2_CFG_S); // Configure filter threshold for avoiding auto-dbias overly sensitive regulation
SET_PERI_REG_BITS(PVT_DBIAS_CMD0_REG, PVT_DBIAS_CMD0, PVT_CMD0, PVT_DBIAS_CMD0_S);
SET_PERI_REG_BITS(PVT_DBIAS_CMD1_REG, PVT_DBIAS_CMD1, PVT_CMD1, PVT_DBIAS_CMD1_S);
SET_PERI_REG_BITS(PVT_DBIAS_CMD2_REG, PVT_DBIAS_CMD2, PVT_CMD2, PVT_DBIAS_CMD2_S); // Configure auto-dbias adjust property, such as adjusting step
SET_PERI_REG_BITS(PVT_DBIAS_TIMER_REG, PVT_TIMER_TARGET, PVT_TARGET, PVT_TIMER_TARGET_S); // Configure auto-dbias voltage regulation cycle
SET_PERI_REG_BITS(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM, PVT_CLK_DIV, PCR_PVT_MONITOR_FUNC_CLK_DIV_NUM_S); //pvt function clock divider number
/*config for pvt cell: unit0; site2; vt0*/
SET_PERI_REG_MASK(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_SEL); //pvt function clock source select
SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT0_VT0_CONF2_REG, PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT0, PVT_EDG_MODE, PVT_MONITOR_EDG_MOD_VT0_PD_SITE2_UNIT0_S); // Select edge_mode
SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT0_VT0_CONF1_REG, PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT0, PVT_DELAY_NUM_HIGH, PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT0_S); // The threshold for determining whether the voltage is too high
SET_PERI_REG_BITS(PVT_COMB_PD_SITE2_UNIT1_VT0_CONF1_REG, PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT1, PVT_DELAY_NUM_LOW, PVT_DELAY_LIMIT_VT0_PD_SITE2_UNIT1_S); // The threshold for determining whether the voltage is too low
}
void pvt_func_enable(bool enable)
{
if (enable) {
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_DBIAS_INIT);
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // hand over control of dbias to pvt
SET_PERI_REG_MASK(PVT_CLK_CFG_REG, PVT_MONITOR_CLK_PVT_EN);
SET_PERI_REG_MASK(PVT_COMB_PD_SITE2_UNIT0_VT0_CONF1_REG, PVT_MONITOR_EN_VT0_PD_SITE2_UNIT0); // enable pvt clk
SET_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); // enable auto dbias
} else {
uint32_t pvt_cali_dbias = get_pvt_dbias(); // update pvt_cali_dbias
SET_PERI_REG_BITS(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_V, pvt_cali_dbias, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_S);
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // hand over control of dbias to pmu
CLEAR_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); //disable auto dbias
CLEAR_PERI_REG_MASK(PVT_COMB_PD_SITE2_UNIT0_VT0_CONF1_REG, PVT_MONITOR_EN_VT0_PD_SITE2_UNIT0);
CLEAR_PERI_REG_MASK(PVT_CLK_CFG_REG, PVT_MONITOR_CLK_PVT_EN);
}
}
void charge_pump_init(void)
{
/*config for charge pump*/
SET_PERI_REG_BITS(PVT_PMUP_CHANNEL_CFG_REG, PVT_PUMP_CHANNEL_CODE0, PVT_PUMP_CHANNEL_CODE, PVT_PUMP_CHANNEL_CODE0_S); //Set channel code
WRITE_PERI_REG(PVT_PMUP_BITMAP_LOW0_REG, PVT_PUMP_BITMAP); // Select monitor cell for charge pump
SET_PERI_REG_BITS(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_DRV0, PVT_PUMP_DRV, PVT_PUMP_DRV0_S); //Configure the charging intensity
}
void charge_pump_enable(bool enable)
{
if (enable) {
SET_PERI_REG_MASK(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_EN); // enable charge pump
} else {
CLEAR_PERI_REG_MASK(PVT_PMUP_DRV_CFG_REG, PVT_PUMP_EN); //disable charge pump
}
}
inline uint32_t get_pvt_dbias()
{
return REG_GET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_DBIAS_VOL);
}

View File

@@ -164,6 +164,8 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias);
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b);
pmu_ll_hp_set_trx_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd_trx);
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(MODEM), get_pvt_dbias());
pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur);
pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep);
pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_xpd);

View File

@@ -13,6 +13,7 @@
#include "esp32h2/rom/rtc.h"
#include "soc/rtc.h"
#include "esp_private/rtc_clk.h"
#include "esp_private/esp_pmu.h"
#include "esp_hw_log.h"
#include "esp_rom_sys.h"
#include "hal/clk_tree_ll.h"
@@ -203,6 +204,10 @@ static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL);
clk_ll_bus_update();
esp_rom_set_cpu_ticks_per_us(cpu_freq);
#ifndef BOOTLOADER_BUILD
charge_pump_enable(0);
pvt_func_enable(0);
#endif
}
static void rtc_clk_cpu_freq_to_8m(void)
@@ -213,6 +218,10 @@ static void rtc_clk_cpu_freq_to_8m(void)
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST);
clk_ll_bus_update();
esp_rom_set_cpu_ticks_per_us(8);
#ifndef BOOTLOADER_BUILD
charge_pump_enable(0);
pvt_func_enable(0);
#endif
}
/**
@@ -222,6 +231,10 @@ static void rtc_clk_cpu_freq_to_8m(void)
*/
static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
{
#ifndef BOOTLOADER_BUILD
pvt_func_enable(1);
charge_pump_enable(1);
#endif
// f_hp_root = 96MHz
uint32_t cpu_divider = CLK_LL_PLL_96M_FREQ_MHZ / cpu_freq_mhz;
clk_ll_cpu_set_divider(cpu_divider);
@@ -241,6 +254,10 @@ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
*/
static void rtc_clk_cpu_freq_to_flash_pll(uint32_t cpu_freq_mhz, uint32_t cpu_divider)
{
#ifndef BOOTLOADER_BUILD
pvt_func_enable(1);
charge_pump_enable(1);
#endif
// f_hp_root = 64MHz
clk_ll_cpu_set_divider(cpu_divider);
// Constraint: f_ahb <= 32MHz; f_cpu = N * f_ahb (N = 1, 2, 3...)

View File

@@ -20,6 +20,8 @@
#include "sdkconfig.h"
#include "esp_rom_uart.h"
#include "hal/clk_tree_ll.h"
#include "soc/pmu_reg.h"
#include "pmu_param.h"
static const char *TAG = "rtc_clk_init";
@@ -39,6 +41,10 @@ void rtc_clk_init(rtc_clk_config_t cfg)
REG_SET_FIELD(LP_CLKRST_FOSC_CNTL_REG, LP_CLKRST_FOSC_DFREQ, cfg.clk_8m_dfreq);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OC_SCK_DCAP, cfg.slow_clk_dcap);
REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, 0);
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, HP_CALI_DBIAS);
REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS);
clk_ll_rc_fast_tick_conf();