diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 49f22dbbb1..88c42eb394 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -296,6 +296,15 @@ menu "Hardware Settings" RC32K (it cannot operate below -40 degrees Celsius), please avoid using it whenever possible + config ESP_ENABLE_PVT + bool "Auto adjust hp & lp voltage using pvt function (MUST ENABLE FOR MP)" + depends on SOC_PMU_PVT_SUPPORTED + default y + help + If enabled, hp & lp voltage can be auto adjust by PVT characteristic. + Otherwise, internal voltage will be set to fix dbias. + This is a must for stable mass production. Disable for debugging only. + config ESP_INTR_IN_IRAM bool "Place esp_intr_alloc functions in IRAM" if SPI_FLASH_AUTO_SUSPEND default y diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 4f72c89fef..b4e010c8af 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -43,6 +43,8 @@ entries: elif PM_SLP_IRAM_OPT = y && IDF_TARGET_ESP32P4 != y: pmu_param:get_act_hp_dbias (noflash) pmu_param:get_act_lp_dbias (noflash) + if SOC_PMU_PVT_SUPPORTED = y: + pmu_pvt (noflash) if PM_SLP_IRAM_OPT = y && SOC_USB_SERIAL_JTAG_SUPPORTED = y: sleep_console (noflash) if PM_SLP_IRAM_OPT = y && SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD = y: diff --git a/components/esp_hw_support/port/esp32p4/CMakeLists.txt b/components/esp_hw_support/port/esp32p4/CMakeLists.txt index f238efa3fe..4cd7fecdbc 100644 --- a/components/esp_hw_support/port/esp32p4/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32p4/CMakeLists.txt @@ -13,6 +13,10 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "sar_periph_ctrl.c") endif() +if(NOT BOOTLOADER_BUILD AND CONFIG_ESP_ENABLE_PVT) + list(APPEND srcs "pmu_pvt.c") +endif() + add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") target_sources(${COMPONENT_LIB} PRIVATE "${srcs}") diff --git a/components/esp_hw_support/port/esp32p4/include/soc/rtc.h b/components/esp_hw_support/port/esp32p4/include/soc/rtc.h index 7c627a03bd..20875057b1 100644 --- a/components/esp_hw_support/port/esp32p4/include/soc/rtc.h +++ b/components/esp_hw_support/port/esp32p4/include/soc/rtc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -95,6 +95,36 @@ set sleep_init default param #define RTC_CNTL_PD_CUR_SLEEP_DEFAULT 1 #define RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT 254 +#if CONFIG_ESP_ENABLE_PVT + +#define PVT_CHANNEL0_SEL 49 +#define PVT_CHANNEL1_SEL 53 +#define PVT_CHANNEL0_CFG 0x13e80 +#define PVT_CHANNEL1_CFG 0x13e80 +#define PVT_CHANNEL2_CFG 0x10000 +#define PVT_CMD0 0x24 +#define PVT_CMD1 0x5 +#define PVT_CMD2 0x427 +#define PVT_TARGET 0x7d00 +#define PVT_CLK_DIV 1 +#define PVT_EDG_MODE 1 +#define PVT_DELAY_NUM_HIGH 164 +#define PVT_DELAY_NUM_LOW 157 + +/** + * @brief Initialize PVT related parameters + */ +void pvt_auto_dbias_init(void); + +/** + * @brief Enable or disable PVT functions + * + * @param enable true to enable, false to disable + */ +void pvt_func_enable(bool enable); + +#endif //#if CONFIG_ESP_ENABLE_PVT + /* The follow value is used to get a reasonable rtc voltage dbias value according to digital dbias & some other value storing in efuse (based on ATE 5k ECO3 chips) diff --git a/components/esp_hw_support/port/esp32p4/pmu_init.c b/components/esp_hw_support/port/esp32p4/pmu_init.c index f511dd4341..a223985f57 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_init.c +++ b/components/esp_hw_support/port/esp32p4/pmu_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,6 +18,8 @@ #include "esp_private/esp_pmu.h" #include "soc/regi2c_dig_reg.h" #include "regi2c_ctrl.h" +#include "esp_rom_sys.h" +#include "soc/rtc.h" static __attribute__((unused)) const char *TAG = "pmu_init"; @@ -194,4 +196,10 @@ void pmu_init(void) pmu_hp_system_init_default(PMU_instance()); pmu_lp_system_init_default(PMU_instance()); pmu_power_domain_force_default(PMU_instance()); +#if CONFIG_ESP_ENABLE_PVT + pvt_auto_dbias_init(); + pvt_func_enable(true); + // For PVT func taking effect, need delay. + esp_rom_delay_us(1000); +#endif } diff --git a/components/esp_hw_support/port/esp32p4/pmu_param.c b/components/esp_hw_support/port/esp32p4/pmu_param.c index f9a410ec46..c951454811 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_param.c +++ b/components/esp_hw_support/port/esp32p4/pmu_param.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,11 @@ #include "soc/pmu_icg_mapping.h" #include "esp_private/esp_pmu.h" #include "soc/clk_tree_defs.h" +#include "hal/efuse_ll.h" +#include "hal/efuse_hal.h" +#include "esp_hw_log.h" + +static __attribute__((unused)) const char *TAG = "pmu_param"; #ifndef ARRAY_SIZE #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) @@ -323,3 +328,46 @@ const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_m assert(mode < ARRAY_SIZE(lp_analog)); return &lp_analog[mode]; } + +uint32_t get_act_hp_dbias(void) +{ + /* hp_cali_dbias is read from efuse to ensure that the hp_active_voltage is close to 1.15V + */ + uint32_t hp_cali_dbias = HP_CALI_ACTIVE_DBIAS_DEFAULT; + uint32_t blk_version = efuse_hal_blk_version(); + uint32_t hp_cali_dbias_efuse = 0; + if (blk_version >= 2) { + hp_cali_dbias_efuse = efuse_ll_get_active_hp_dbias(); + } + if (hp_cali_dbias_efuse > 0) { + hp_cali_dbias = hp_cali_dbias_efuse + 16; + if (hp_cali_dbias > 31) { + hp_cali_dbias = 31; + } + } else { + ESP_HW_LOGW(TAG, "hp_cali_dbias not burnt in efuse, use default."); + } + return hp_cali_dbias; +} + +uint32_t get_act_lp_dbias(void) +{ + /* lp_cali_dbias is read from efuse to ensure that the lp_active_voltage is close to 1.15V + */ + uint32_t lp_cali_dbias = LP_CALI_ACTIVE_DBIAS_DEFAULT; + uint32_t blk_version = efuse_hal_blk_version(); + uint32_t lp_cali_dbias_efuse = 0; + if (blk_version >= 2) { + lp_cali_dbias_efuse = efuse_ll_get_active_lp_dbias(); + } + if (lp_cali_dbias_efuse > 0) { + //efuse dbias need to add 4 to near to dcdc voltage + lp_cali_dbias = lp_cali_dbias_efuse + 16 + 4; + if (lp_cali_dbias > 31) { + lp_cali_dbias = 31; + } + } else { + ESP_HW_LOGW(TAG, "lp_cali_dbias not burnt in efuse, use default."); + } + return lp_cali_dbias; +} diff --git a/components/esp_hw_support/port/esp32p4/pmu_pvt.c b/components/esp_hw_support/port/esp32p4/pmu_pvt.c new file mode 100644 index 0000000000..4c99b938c6 --- /dev/null +++ b/components/esp_hw_support/port/esp32p4/pmu_pvt.c @@ -0,0 +1,153 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc.h" +#include "soc/pmu_struct.h" +#include "soc/pvt_reg.h" +#include "soc/pmu_reg.h" +#include "hal/pmu_hal.h" +#include "pmu_param.h" +#include "esp_rom_sys.h" +#include "esp_private/esp_pmu.h" +#include "soc/regi2c_dig_reg.h" +#include "regi2c_ctrl.h" +#include "soc/rtc.h" +#include "hal/efuse_ll.h" +#include "hal/efuse_hal.h" +#include "esp_hw_log.h" + +static __attribute__((unused)) const char *TAG = "pmu_pvt"; + +#if CONFIG_ESP_ENABLE_PVT + +static uint8_t get_lp_hp_gap(void) +{ + int8_t lp_hp_gap = 0; + uint32_t blk_version = efuse_hal_blk_version(); + uint8_t lp_hp_gap_efuse = 0; + if (blk_version >= 2) { + lp_hp_gap_efuse = efuse_ll_get_dbias_vol_gap(); + bool gap_flag = lp_hp_gap_efuse >> 4; + uint8_t gap_abs_value = lp_hp_gap_efuse & 0xf; + if (gap_flag) { + lp_hp_gap = -1 * gap_abs_value; + } else { + lp_hp_gap = gap_abs_value; + } + lp_hp_gap = lp_hp_gap - 8; + assert((lp_hp_gap >= -15) && (lp_hp_gap <= 7)); + if (lp_hp_gap < 0 ) { + lp_hp_gap = 16 - lp_hp_gap; + } + } + return lp_hp_gap; +} + +static void set_pvt_hp_lp_gap(uint8_t value) +{ + bool flag = value >> 4; + uint8_t abs_value = value & 0xf; + + SET_PERI_REG_BITS(PVT_DBIAS_CMD0_REG, PVT_DBIAS_CMD0_OFFSET_FLAG, flag, PVT_DBIAS_CMD0_OFFSET_FLAG_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD0_REG, PVT_DBIAS_CMD0_OFFSET_VALUE, abs_value, PVT_DBIAS_CMD0_OFFSET_VALUE_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD1_REG, PVT_DBIAS_CMD1_OFFSET_FLAG, flag, PVT_DBIAS_CMD1_OFFSET_FLAG_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD1_REG, PVT_DBIAS_CMD1_OFFSET_VALUE, abs_value, PVT_DBIAS_CMD1_OFFSET_VALUE_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD2_REG, PVT_DBIAS_CMD2_OFFSET_FLAG, flag, PVT_DBIAS_CMD2_OFFSET_FLAG_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD2_REG, PVT_DBIAS_CMD2_OFFSET_VALUE, abs_value, PVT_DBIAS_CMD2_OFFSET_VALUE_S); +} + +static uint32_t pvt_get_dcmvset(void) +{ + return GET_PERI_REG_BITS2(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_DBIAS_VOL_V, PMU_HP_DBIAS_VOL_S); +} + +static uint32_t pvt_get_lp_dbias(void) +{ + return GET_PERI_REG_BITS2(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_LP_DBIAS_VOL_V, PMU_LP_DBIAS_VOL_S); +} + +void pvt_auto_dbias_init(void) +{ + uint32_t blk_version = efuse_hal_blk_version(); + if (blk_version >= 2) { + SET_PERI_REG_MASK(HP_SYS_CLKRST_REF_CLK_CTRL2_REG, HP_SYS_CLKRST_REG_REF_160M_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_SOC_CLK_CTRL1_REG, HP_SYS_CLKRST_REG_PVT_SYS_CLK_EN); + /*config for dbias func*/ + CLEAR_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); + esp_rom_delay_us(100); + 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, PVT_CMD0, PVT_DBIAS_CMD0_PVT_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD1_REG, PVT_DBIAS_CMD1_PVT, PVT_CMD1, PVT_DBIAS_CMD1_PVT_S); + SET_PERI_REG_BITS(PVT_DBIAS_CMD2_REG, PVT_DBIAS_CMD2_PVT, PVT_CMD2, PVT_DBIAS_CMD2_PVT_S); // Configure auto-dbias adjust property, such as adjusting step + SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_DBIAS_INIT); // Start calibration @HP_CALI_DBIAS_DEFAULT + 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(HP_SYS_CLKRST_PERI_CLK_CTRL24_REG, HP_SYS_CLKRST_REG_PVT_CLK_DIV_NUM, PVT_CLK_DIV, HP_SYS_CLKRST_REG_PVT_CLK_DIV_NUM_S); // PVT function clock divider number + SET_PERI_REG_BITS(HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, HP_SYS_CLKRST_REG_PVT_PERI_GROUP_CLK_DIV_NUM, PVT_CLK_DIV, HP_SYS_CLKRST_REG_PVT_PERI_GROUP_CLK_DIV_NUM_S); // PVT function clock divider number + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL24_REG, HP_SYS_CLKRST_REG_PVT_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, HP_SYS_CLKRST_REG_PVT_PERI_GROUP1_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, HP_SYS_CLKRST_REG_PVT_PERI_GROUP2_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, HP_SYS_CLKRST_REG_PVT_PERI_GROUP3_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, HP_SYS_CLKRST_REG_PVT_PERI_GROUP4_CLK_EN); + + /*config for pvt cell: unit0; site3; vt1*/ + SET_PERI_REG_MASK(PVT_CLK_CFG_REG, PVT_MONITOR_CLK_PVT_EN); // Once enable cannot be closed + esp_rom_delay_us(100); + SET_PERI_REG_BITS(PVT_COMB_PD_SITE3_UNIT0_VT1_CONF2_REG, PVT_MONITOR_EDG_MOD_VT1_PD_SITE3_UNIT0, PVT_EDG_MODE, PVT_MONITOR_EDG_MOD_VT1_PD_SITE3_UNIT0_S); // Select edge_mode + SET_PERI_REG_BITS(PVT_COMB_PD_SITE3_UNIT0_VT1_CONF1_REG, PVT_DELAY_LIMIT_VT1_PD_SITE3_UNIT0, PVT_DELAY_NUM_HIGH, PVT_DELAY_LIMIT_VT1_PD_SITE3_UNIT0_S); // The threshold for determining whether the voltage is too high + SET_PERI_REG_BITS(PVT_COMB_PD_SITE3_UNIT1_VT1_CONF1_REG, PVT_DELAY_LIMIT_VT1_PD_SITE3_UNIT1, PVT_DELAY_NUM_LOW, PVT_DELAY_LIMIT_VT1_PD_SITE3_UNIT1_S); // The threshold for determining whether the voltage is too low + + /*config lp offset for pvt func*/ + uint8_t lp_hp_gap = get_lp_hp_gap(); + set_pvt_hp_lp_gap(lp_hp_gap); + } else { + ESP_HW_LOGW(TAG, "blk_version is less than 2, pvt auto dbias init not supported in efuse."); + } +} + +void pvt_func_enable(bool enable) +{ + uint32_t blk_version = efuse_hal_blk_version(); + if (blk_version >= 2){ + + if (enable) { + SET_PERI_REG_MASK(HP_SYS_CLKRST_REF_CLK_CTRL2_REG, HP_SYS_CLKRST_REG_REF_160M_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_SOC_CLK_CTRL1_REG, HP_SYS_CLKRST_REG_PVT_SYS_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL24_REG, HP_SYS_CLKRST_REG_PVT_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, HP_SYS_CLKRST_REG_PVT_PERI_GROUP1_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, HP_SYS_CLKRST_REG_PVT_PERI_GROUP2_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, HP_SYS_CLKRST_REG_PVT_PERI_GROUP3_CLK_EN); + SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, HP_SYS_CLKRST_REG_PVT_PERI_GROUP4_CLK_EN); + SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_DBIAS_INIT); // Start calibration @HP_CALI_DBIAS_DEFAULT + SET_PERI_REG_MASK(PVT_CLK_CFG_REG, PVT_MONITOR_CLK_PVT_EN); // Once enable cannot be closed + SET_PERI_REG_MASK(PVT_COMB_PD_SITE3_UNIT0_VT1_CONF1_REG, PVT_MONITOR_EN_VT1_PD_SITE3_UNIT0); // Enable pvt clk + esp_rom_delay_us(1000); + CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // Hand over control of dbias to pvt + CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_DBIAS_INIT); // Must clear @HP_CALI_DBIAS_DEFAULT + SET_PERI_REG_MASK(PVT_DBIAS_TIMER_REG, PVT_TIMER_EN); // Enable auto dbias + } else { + uint32_t pvt_dcmvset = pvt_get_dcmvset(); + uint32_t pvt_lpdbias = pvt_get_lp_dbias(); // Update pvt_cali_dbias + SET_PERI_REG_BITS(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, pvt_dcmvset, PMU_HP_ACTIVE_DCM_VSET_S); + SET_PERI_REG_BITS(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, pvt_lpdbias, PMU_HP_SLEEP_LP_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(HP_SYS_CLKRST_PERI_CLK_CTRL24_REG, HP_SYS_CLKRST_REG_PVT_CLK_EN); + } + } else { + ESP_HW_LOGD(TAG, "blk_version is less than 2, pvt function not supported in efuse."); + } +} + +#endif diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index f0e4152825..61f383de47 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -201,7 +201,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default( analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = PMU_BIASSLP_SLEEP_ON; analog_default.lp_sys[LP(SLEEP)].analog.dbg_atten = PMU_DBG_ATTEN_ACTIVE_DEFAULT; #if !CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON - analog_default.lp_sys[LP(SLEEP)].analog.dbias = LP_CALI_DBIAS; + analog_default.lp_sys[LP(SLEEP)].analog.dbias = LP_CALI_ACTIVE_DBIAS_DEFAULT; #endif } diff --git a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h index 32ca2ffbe3..d4b53eebaa 100644 --- a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,7 +18,7 @@ extern "C" { #define HP_CALI_ACTIVE_DCM_VSET_DEFAULT 27 // For DCDC, about 1.25v #define HP_CALI_ACTIVE_DBIAS_DEFAULT 24 // For HP regulator -#define LP_CALI_DBIAS 29 // For LP regulator +#define LP_CALI_ACTIVE_DBIAS_DEFAULT 29 // For LP regulator // FOR XTAL FORCE PU IN SLEEP #define PMU_PD_CUR_SLEEP_ON 0 @@ -53,6 +53,9 @@ extern "C" { #define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12 #define PMU_LP_DBIAS_DEEPSLEEP_0V7 23 +uint32_t get_act_hp_dbias(void); +uint32_t get_act_lp_dbias(void); + typedef struct { pmu_hp_dig_power_reg_t dig_power; pmu_hp_clk_power_reg_t clk_power; diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk_init.c b/components/esp_hw_support/port/esp32p4/rtc_clk_init.c index 5d054b8573..2cd85e78f1 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk_init.c @@ -53,11 +53,22 @@ void rtc_clk_init(rtc_clk_config_t cfg) REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_FORCE_XPD_IPH, 0); REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_FORCE_XPD_VGATE_BUF, 0); - pmu_ll_lp_set_regulator_dbias(&PMU, PMU_MODE_LP_ACTIVE, LP_CALI_DBIAS); + uint32_t hp_dbias = get_act_hp_dbias(); + uint32_t lp_dbias = get_act_lp_dbias(); + pmu_ll_hp_set_regulator_xpd(&PMU, PMU_MODE_HP_ACTIVE, true); + pmu_ll_hp_set_regulator_dbias(&PMU, PMU_MODE_HP_ACTIVE, hp_dbias); + pmu_ll_lp_set_regulator_dbias(&PMU, PMU_MODE_LP_ACTIVE, lp_dbias); + + uint32_t pvt_hp_dcmvset = GET_PERI_REG_BITS2(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_DBIAS_VOL_V, PMU_HP_DBIAS_VOL_S); + uint32_t hp_dcmvset = HP_CALI_ACTIVE_DCM_VSET_DEFAULT; + if (pvt_hp_dcmvset > hp_dcmvset) { + hp_dcmvset = pvt_hp_dcmvset; + } // Switch to DCDC pmu_ll_set_dcdc_en(&PMU, true); pmu_ll_set_dcdc_switch_force_power_down(&PMU, false); - pmu_ll_hp_set_dcm_vset(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); + pmu_ll_hp_set_dcm_vset(&PMU, PMU_MODE_HP_ACTIVE, hp_dcmvset); + SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_DIG_REGULATOR0_DBIAS_SEL); // Hand over control of dbias to pmu esp_rom_delay_us(1000); pmu_ll_hp_set_regulator_xpd(&PMU, PMU_MODE_HP_ACTIVE, false); diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 24301761c0..6672e26f42 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -20,6 +20,7 @@ #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_timer_private.h" #include "esp_private/rtc_clk.h" +#include "soc/rtc.h" #include "esp_private/sleep_event.h" #include "esp_private/system_internal.h" #include "esp_private/io_mux.h" @@ -741,6 +742,9 @@ static SLEEP_FN_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool regi2c_tsens_reg_read(); #endif } +#if CONFIG_ESP_ENABLE_PVT + pvt_func_enable(false); +#endif if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE] == 0) { // TODO: IDF-7370 @@ -753,6 +757,10 @@ static SLEEP_FN_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool */ static SLEEP_FN_ATTR void misc_modules_wake_prepare(uint32_t sleep_flags) { +#if CONFIG_ESP_ENABLE_PVT + pvt_func_enable(true); +#endif + #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP if (sleep_flags & PMU_SLEEP_PD_TOP) { // There is no driver to manage the flashboot watchdog, and it is definitely be in off state when diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 5b7805245b..bd8297654f 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -121,6 +121,16 @@ esp_err_t sleep_pau_retention_init(void) } #endif +#if CONFIG_ESP_ENABLE_PVT +esp_err_t sleep_pvt_retention_init(void) +{ + esp_err_t err = sleep_retention_entries_create(pvt_regs_retention, ARRAY_SIZE(pvt_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PVT) retention"); + ESP_LOGI(TAG, "PVT sleep retention initialization"); + return ESP_OK; +} +#endif + static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *arg) { esp_err_t err; @@ -152,6 +162,11 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *a if(err) goto error; #if SOC_PAU_IN_TOP_DOMAIN err = sleep_pau_retention_init(); + if(err) goto error; +#endif +#if CONFIG_ESP_ENABLE_PVT + err = sleep_pvt_retention_init(); + if(err) goto error; #endif error: diff --git a/components/esp_system/port/soc/esp32p4/clk.c b/components/esp_system/port/soc/esp32p4/clk.c index 9ca7f49cbe..591a6a45a4 100644 --- a/components/esp_system/port/soc/esp32p4/clk.c +++ b/components/esp_system/port/soc/esp32p4/clk.c @@ -380,7 +380,10 @@ __attribute__((weak)) void esp_perip_clk_init(void) REG_CLR_BIT(HP_SYS_CLKRST_REF_CLK_CTRL1_REG, HP_SYS_CLKRST_REG_REF_50M_CLK_EN); REG_CLR_BIT(HP_SYS_CLKRST_REF_CLK_CTRL1_REG, HP_SYS_CLKRST_REG_REF_25M_CLK_EN); // 240M CLK is for Key Management use, should not be gated +#if !CONFIG_ESP_ENABLE_PVT REG_CLR_BIT(HP_SYS_CLKRST_REF_CLK_CTRL2_REG, HP_SYS_CLKRST_REG_REF_160M_CLK_EN); +#endif + // 160M CLK is for PVT use, should not be gated REG_CLR_BIT(HP_SYS_CLKRST_REF_CLK_CTRL2_REG, HP_SYS_CLKRST_REG_REF_120M_CLK_EN); REG_CLR_BIT(HP_SYS_CLKRST_REF_CLK_CTRL2_REG, HP_SYS_CLKRST_REG_REF_80M_CLK_EN); REG_CLR_BIT(HP_SYS_CLKRST_REF_CLK_CTRL2_REG, HP_SYS_CLKRST_REG_REF_20M_CLK_EN); diff --git a/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.framepointer b/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.framepointer index 464cba0ee4..c504d304a3 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.framepointer +++ b/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.framepointer @@ -1 +1,3 @@ CONFIG_ESP_SYSTEM_USE_FRAME_POINTER=y +# Increase size of bootloader due to frame pointer +CONFIG_PARTITION_TABLE_OFFSET=0x10000 diff --git a/components/hal/esp32p4/include/hal/efuse_ll.h b/components/hal/esp32p4/include/hal/efuse_ll.h index e6899663e2..9011a8c50c 100644 --- a/components/hal/esp32p4/include/hal/efuse_ll.h +++ b/components/hal/esp32p4/include/hal/efuse_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -146,6 +146,21 @@ __attribute__((always_inline)) static inline uint32_t efuse_ll_get_controller_st return EFUSE.status.state; } +__attribute__((always_inline)) static inline uint32_t efuse_ll_get_active_hp_dbias(void) +{ + return EFUSE.rd_mac_sys_4.active_hp_dbias; +} + +__attribute__((always_inline)) static inline uint32_t efuse_ll_get_active_lp_dbias(void) +{ + return EFUSE.rd_mac_sys_4.active_lp_dbias; +} + +__attribute__((always_inline)) static inline int32_t efuse_ll_get_dbias_vol_gap(void) +{ + return EFUSE.rd_mac_sys_5.lp_dcdc_dbias_vol_gap; +} + /******************* eFuse control functions *************************/ #ifdef __cplusplus diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 3fe57bea31..2787ae062c 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -235,6 +235,10 @@ config SOC_PMU_SUPPORTED bool default y +config SOC_PMU_PVT_SUPPORTED + bool + default y + config SOC_DCDC_SUPPORTED bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 9bced6af54..27d05521b2 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -75,6 +75,7 @@ #define SOC_VBAT_SUPPORTED 1 #define SOC_APM_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1 +#define SOC_PMU_PVT_SUPPORTED 1 #define SOC_DCDC_SUPPORTED 1 #define SOC_PAU_SUPPORTED 1 //TODO: IDF-7531 #define SOC_LP_TIMER_SUPPORTED 1 diff --git a/components/soc/esp32p4/include/soc/system_periph_retention.h b/components/soc/esp32p4/include/soc/system_periph_retention.h index 56b867e487..f8bf6ac45c 100644 --- a/components/soc/esp32p4/include/soc/system_periph_retention.h +++ b/components/soc/esp32p4/include/soc/system_periph_retention.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -95,6 +95,16 @@ extern const regdma_entries_config_t systimer_regs_retention[SYSTIMER_RETENTION_ #define PAU_RETENTION_LINK_LEN 1 extern const regdma_entries_config_t pau_regs_retention[PAU_RETENTION_LINK_LEN]; +/** + * @brief Provide access to pvt configuration registers retention + * context definition. + * + * This is an internal function of the sleep retention driver, and is not + * useful for external use. + */ +#define PVT_RETENTION_LINK_LEN 1 +extern const regdma_entries_config_t pvt_regs_retention[PVT_RETENTION_LINK_LEN]; + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/register/soc/pvt_reg.h b/components/soc/esp32p4/register/soc/pvt_reg.h index 1e3e333dc1..71a97569f1 100644 --- a/components/soc/esp32p4/register/soc/pvt_reg.h +++ b/components/soc/esp32p4/register/soc/pvt_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -363,10 +363,12 @@ extern "C" { /** PVT_DBIAS_CMD0 : R/W; bitpos: [16:0]; default: 0; * needs field desc */ -#define PVT_DBIAS_CMD0 0x0001FFFFU -#define PVT_DBIAS_CMD0_M (PVT_DBIAS_CMD0_V << PVT_DBIAS_CMD0_S) -#define PVT_DBIAS_CMD0_V 0x0001FFFFU -#define PVT_DBIAS_CMD0_S 0 +#define PVT_DBIAS_CMD0_OFFSET_FLAG 1 +#define PVT_DBIAS_CMD0_OFFSET_FLAG_S 16 +#define PVT_DBIAS_CMD0_OFFSET_VALUE 0x1F +#define PVT_DBIAS_CMD0_OFFSET_VALUE_S 11 +#define PVT_DBIAS_CMD0_PVT 0x7FF +#define PVT_DBIAS_CMD0_PVT_S 0 /** PVT_DBIAS_CMD1_REG register * needs desc @@ -375,10 +377,12 @@ extern "C" { /** PVT_DBIAS_CMD1 : R/W; bitpos: [16:0]; default: 0; * needs field desc */ -#define PVT_DBIAS_CMD1 0x0001FFFFU -#define PVT_DBIAS_CMD1_M (PVT_DBIAS_CMD1_V << PVT_DBIAS_CMD1_S) -#define PVT_DBIAS_CMD1_V 0x0001FFFFU -#define PVT_DBIAS_CMD1_S 0 +#define PVT_DBIAS_CMD1_OFFSET_FLAG 1 +#define PVT_DBIAS_CMD1_OFFSET_FLAG_S 16 +#define PVT_DBIAS_CMD1_OFFSET_VALUE 0x1F +#define PVT_DBIAS_CMD1_OFFSET_VALUE_S 11 +#define PVT_DBIAS_CMD1_PVT 0x7FF +#define PVT_DBIAS_CMD1_PVT_S 0 /** PVT_DBIAS_CMD2_REG register * needs desc @@ -387,10 +391,12 @@ extern "C" { /** PVT_DBIAS_CMD2 : R/W; bitpos: [16:0]; default: 0; * needs field desc */ -#define PVT_DBIAS_CMD2 0x0001FFFFU -#define PVT_DBIAS_CMD2_M (PVT_DBIAS_CMD2_V << PVT_DBIAS_CMD2_S) -#define PVT_DBIAS_CMD2_V 0x0001FFFFU -#define PVT_DBIAS_CMD2_S 0 +#define PVT_DBIAS_CMD2_OFFSET_FLAG 1 +#define PVT_DBIAS_CMD2_OFFSET_FLAG_S 16 +#define PVT_DBIAS_CMD2_OFFSET_VALUE 0x1F +#define PVT_DBIAS_CMD2_OFFSET_VALUE_S 11 +#define PVT_DBIAS_CMD2_PVT 0x7FF +#define PVT_DBIAS_CMD2_PVT_S 0 /** PVT_DBIAS_CMD3_REG register * needs desc diff --git a/components/soc/esp32p4/register/soc/pvt_struct.h b/components/soc/esp32p4/register/soc/pvt_struct.h index ebde6a6427..c02f5d5ca1 100644 --- a/components/soc/esp32p4/register/soc/pvt_struct.h +++ b/components/soc/esp32p4/register/soc/pvt_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -347,10 +347,18 @@ typedef union { */ typedef union { struct { - /** dbias_cmd0 : R/W; bitpos: [16:0]; default: 0; + /** dbias_cmd0 : R/W; bitpos: [10:0]; default: 0; * needs field desc */ - uint32_t dbias_cmd0:17; + uint32_t dbias_cmd0_pvt:11; + /** dbias_cmd0_offset_value : R/W; bitpos: [15:11]; default: 0; + * needs field desc + */ + uint32_t dbias_cmd0_offset_value:5; + /** dbias_cmd0_offset_flag : R/W; bitpos: [16]; default: 0; + * needs field desc + */ + uint32_t dbias_cmd0_offset_flag:1; uint32_t reserved_17:15; }; uint32_t val; @@ -361,10 +369,18 @@ typedef union { */ typedef union { struct { - /** dbias_cmd1 : R/W; bitpos: [16:0]; default: 0; + /** dbias_cmd1 : R/W; bitpos: [10:0]; default: 0; * needs field desc */ - uint32_t dbias_cmd1:17; + uint32_t dbias_cmd1_pvt:11; + /** dbias_cmd1_offset_value : R/W; bitpos: [15:11]; default: 0; + * needs field desc + */ + uint32_t dbias_cmd1_offset_value:5; + /** dbias_cmd1_offset_flag : R/W; bitpos: [16]; default: 0; + * needs field desc + */ + uint32_t dbias_cmd1_offset_flag:1; uint32_t reserved_17:15; }; uint32_t val; @@ -375,10 +391,18 @@ typedef union { */ typedef union { struct { - /** dbias_cmd2 : R/W; bitpos: [16:0]; default: 0; + /** dbias_cmd2 : R/W; bitpos: [10:0]; default: 0; * needs field desc */ - uint32_t dbias_cmd2:17; + uint32_t dbias_cmd2_pvt:11; + /** dbias_cmd2_offset_value : R/W; bitpos: [15:11]; default: 0; + * needs field desc + */ + uint32_t dbias_cmd2_offset_value:5; + /** dbias_cmd2_offset_flag : R/W; bitpos: [16]; default: 0; + * needs field desc + */ + uint32_t dbias_cmd2_offset_flag:1; uint32_t reserved_17:15; }; uint32_t val; diff --git a/components/soc/esp32p4/system_retention_periph.c b/components/soc/esp32p4/system_retention_periph.c index acbae1c86d..87d94fc0fc 100644 --- a/components/soc/esp32p4/system_retention_periph.c +++ b/components/soc/esp32p4/system_retention_periph.c @@ -23,6 +23,7 @@ #include "soc/timer_periph.h" #include "soc/uart_reg.h" #include "esp32p4/rom/cache.h" +#include "soc/pvt_reg.h" /* Interrupt Matrix Registers Context */ #define N_REGS_INTR_CORE0() (((INTERRUPT_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE0_BASE) / 4) + 1) @@ -202,3 +203,10 @@ const regdma_entries_config_t pau_regs_retention[] = { [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PAU_LINK(0x0), DR_REG_PAU_BASE, DR_REG_PAU_BASE, N_REGS_PAU(), 0, 0), .owner = ENTRY(0) }, /* pau */ }; _Static_assert(ARRAY_SIZE(pau_regs_retention) == HP_SYSTEM_RETENTION_LINK_LEN, "Inconsistent PAU retention link length definitions"); + +/* PVT Registers Context */ +#define N_REGS_PVT (((PVT_COMB_PD_SITE3_UNIT0_VT1_CONF2_REG - DR_REG_PVT_MONITOR_BASE) / 4) + 1) +const regdma_entries_config_t pvt_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PVT_LINK(0x00), DR_REG_PVT_MONITOR_BASE, DR_REG_PVT_MONITOR_BASE, N_REGS_PVT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; +_Static_assert(ARRAY_SIZE(pvt_regs_retention) == PVT_RETENTION_LINK_LEN, "Inconsistent PVT retention link length definitions"); diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index e23525d8b3..5d3e940561 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -34,6 +34,7 @@ extern "C" { #define REGDMA_MODEMSYSCON_LINK(_pri) ((0x02 << 8) | _pri) #define REGDMA_MODEMLPCON_LINK(_pri) ((0x03 << 8) | _pri) #define REGDMA_PAU_LINK(_pri) ((0x04 << 8) | _pri) +#define REGDMA_PVT_LINK(_pri) ((0x05 << 8) | _pri) #define REGDMA_CACHE_LINK(_pri) ((0x0c << 8) | _pri) #define REGDMA_INTMTX_LINK(_pri) ((0x0d << 8) | _pri) @@ -63,6 +64,7 @@ extern "C" { #define REGDMA_LEDC_LINK(_pri) ((0x24 << 8) | _pri) #define REGDMA_PCNT_LINK(_pri) ((0x25 << 8) | _pri) #define REGDMA_MCPWM_LINK(_pri) ((0x26 << 8) | _pri) + #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) #define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0 diff --git a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults.esp32p4 b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults.esp32p4 new file mode 100644 index 0000000000..8b07012800 --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults.esp32p4 @@ -0,0 +1,2 @@ +# Increase size of bootloader due to frame pointer. Only overflowed on P4. +CONFIG_PARTITION_TABLE_OFFSET=0x10000