diff --git a/components/bootloader_support/src/esp32s31/bootloader_esp32s31.c b/components/bootloader_support/src/esp32s31/bootloader_esp32s31.c index 974935c685f..d90ccb52bb5 100644 --- a/components/bootloader_support/src/esp32s31/bootloader_esp32s31.c +++ b/components/bootloader_support/src/esp32s31/bootloader_esp32s31.c @@ -32,6 +32,8 @@ #include "soc/reset_reasons.h" #include "hal/assist_debug_ll.h" #include "esp_rom_sys.h" +#include "hal/clk_tree_ll.h" +#include "hal/psram_ctrlr_ll.h" ESP_LOG_ATTR_TAG(TAG, "boot.esp32s31"); @@ -53,6 +55,12 @@ static inline void bootloader_hardware_init(void) regi2c_ctrl_ll_master_force_enable_clock(true); // TODO: IDF-14678 Remove this? regi2c_ctrl_ll_master_configure_clock(); #endif + + /* Disable MPLL by default, during mmu_hal_init, a valid clock source is required for the PSRAM, + so before shutting down mpll, the PSRAM clock source should be selected to an always-on source. */ + _psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_XTAL); + _psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_XTAL); + clk_ll_mpll_disable(); } void bootloader_enable_cpu_reset_info(void) diff --git a/components/esp_hal_clock/esp32s31/include/hal/clk_tree_ll.h b/components/esp_hal_clock/esp32s31/include/hal/clk_tree_ll.h index d40c5fb1d6b..a8d8839e49a 100644 --- a/components/esp_hal_clock/esp32s31/include/hal/clk_tree_ll.h +++ b/components/esp_hal_clock/esp32s31/include/hal/clk_tree_ll.h @@ -154,7 +154,6 @@ static inline __attribute__((always_inline)) void clk_ll_mpll_enable(void) SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_XPD_MPLL | PMU_TIE_HIGH_XPD_MPLL_I2C); SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_MPLL_500M_CLK_EN); SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_MPLL_I2C | PMU_HP_ACTIVE_XPD_MPLL); - SET_PERI_REG_MASK(PMU_PSRAM_CFG_REG, PMU_PSRAM_XPD); } /** @@ -166,7 +165,6 @@ static inline __attribute__((always_inline)) void clk_ll_mpll_disable(void) SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_XPD_MPLL | PMU_TIE_LOW_XPD_MPLL_I2C); CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_MPLL_500M_CLK_EN); CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_MPLL_I2C | PMU_HP_ACTIVE_XPD_MPLL); - CLEAR_PERI_REG_MASK(PMU_PSRAM_CFG_REG, PMU_PSRAM_XPD); } /** diff --git a/components/esp_hal_mspi/esp32s31/include/hal/psram_ctrlr_ll.h b/components/esp_hal_mspi/esp32s31/include/hal/psram_ctrlr_ll.h index f18fc2755cb..d2474305cfe 100644 --- a/components/esp_hal_mspi/esp32s31/include/hal/psram_ctrlr_ll.h +++ b/components/esp_hal_mspi/esp32s31/include/hal/psram_ctrlr_ll.h @@ -63,21 +63,6 @@ extern "C" { #define PSRAM_CTRLR_LL_INTR_EVENT_SUPPORTED 1 #define PSRAM_CTRLR_LL_DEDICATED_LDO 1 -/** - * @brief Enable PSRAM power - * - * @param en enable / disable - */ -__attribute__((always_inline)) -static inline void psram_ctrlr_ll_enable_power(bool en) -{ - if (en) { - REG_SET_BIT(PMU_PSRAM_CFG_REG, PMU_PSRAM_XPD); - } else { - REG_CLR_BIT(PMU_PSRAM_CFG_REG, PMU_PSRAM_XPD); - } -} - /** * @brief Set PSRAM write cmd * diff --git a/components/esp_hal_pmu/esp32s31/include/hal/ldo_ll.h b/components/esp_hal_pmu/esp32s31/include/hal/ldo_ll.h index e68f850f21b..3e1e5285b6b 100644 --- a/components/esp_hal_pmu/esp32s31/include/hal/ldo_ll.h +++ b/components/esp_hal_pmu/esp32s31/include/hal/ldo_ll.h @@ -151,6 +151,10 @@ static inline void ldo_ll_enable(int ldo_unit, bool enable) //for compatibility //PMU.hp_sys[PMU_MODE_HP_ACTIVE].regulator0.xpd is for chip internal LDO for chip power //this will not be controlled by this general purpose LDO file + if (ldo_unit == 0) { + // Enable MPLL PHY with power enable. + PMU.psram_cfg.psram_xpd = enable; + } } /** diff --git a/components/esp_hw_support/ldo/esp_ldo_regulator.c b/components/esp_hw_support/ldo/esp_ldo_regulator.c index de02a7b88dd..164fb88c463 100644 --- a/components/esp_hw_support/ldo/esp_ldo_regulator.c +++ b/components/esp_hw_support/ldo/esp_ldo_regulator.c @@ -15,6 +15,7 @@ #include "hal/ldo_ll.h" #include "esp_ldo_regulator.h" #include "esp_private/critical_section.h" +#include "esp_rom_sys.h" ESP_LOG_ATTR_TAG(TAG, "ldo"); @@ -56,6 +57,7 @@ esp_err_t esp_ldo_acquire_channel(const esp_ldo_channel_config_t *config, esp_ld bool check_adjustable_constraint_valid = true; bool check_voltage_constraint_valid = true; + bool ldo_enabled = false; esp_os_enter_critical(&s_spinlock); if (config->flags.adjustable) { // the user wants to adjust it @@ -97,6 +99,7 @@ esp_err_t esp_ldo_acquire_channel(const esp_ldo_channel_config_t *config, esp_ld ldo_ll_enable_ripple_suppression(unit_id, true); ldo_ll_enable(unit_id, true); ldo_ll_enable_current_limit(unit_id, false); + ldo_enabled = true; } // update the channel attributes channel->ref_cnt++; @@ -112,6 +115,10 @@ esp_err_t esp_ldo_acquire_channel(const esp_ldo_channel_config_t *config, esp_ld ESP_RETURN_ON_FALSE(check_adjustable_constraint_valid, ESP_ERR_INVALID_ARG, TAG, "can't acquire the channel, already in use by others or not adjustable"); + if (ldo_enabled && config->voltage_stable_delay_us > 0) { + esp_rom_delay_us(config->voltage_stable_delay_us); + } + if (out_handle) { *out_handle = channel; } diff --git a/components/esp_hw_support/ldo/include/esp_ldo_regulator.h b/components/esp_hw_support/ldo/include/esp_ldo_regulator.h index 67c78727d5e..dc8a9e07477 100644 --- a/components/esp_hw_support/ldo/include/esp_ldo_regulator.h +++ b/components/esp_hw_support/ldo/include/esp_ldo_regulator.h @@ -25,6 +25,7 @@ typedef struct ldo_regulator_channel_t *esp_ldo_channel_handle_t; typedef struct { int chan_id; /*!< You must set the LDO channel ID according to the datasheet, e.g., set it to 1 for LDO_VO1 */ int voltage_mv; /*!< The voltage value to be set to the LDO channel */ + uint32_t voltage_stable_delay_us; /*!< Delay in microseconds after LDO enable, wait for output voltage to stabilize. Set to 0 to skip */ /// Extra flags of a LDO channel struct ldo_extra_flags { diff --git a/components/esp_hw_support/port/esp32p4/Kconfig.ldo b/components/esp_hw_support/port/esp32p4/Kconfig.ldo index 804f685f87f..a29b0254763 100644 --- a/components/esp_hw_support/port/esp32p4/Kconfig.ldo +++ b/components/esp_hw_support/port/esp32p4/Kconfig.ldo @@ -63,4 +63,9 @@ menu "LDO Regulator Configurations" config ESP_LDO_VOLTAGE_PSRAM_DOMAIN int default 1800 if ESP_LDO_VOLTAGE_PSRAM_1800_MV + + config ESP_LDO_VOLTAGE_STABLE_DELAY_US + int + depends on ESP_LDO_RESERVE_PSRAM + default 0 endmenu diff --git a/components/esp_hw_support/port/esp32s31/Kconfig.ldo b/components/esp_hw_support/port/esp32s31/Kconfig.ldo index 9b5dd7d4924..d641d79f650 100644 --- a/components/esp_hw_support/port/esp32s31/Kconfig.ldo +++ b/components/esp_hw_support/port/esp32s31/Kconfig.ldo @@ -31,4 +31,9 @@ menu "LDO Regulator Configurations" config ESP_LDO_VOLTAGE_PSRAM_DOMAIN int default 1800 if ESP_LDO_VOLTAGE_PSRAM_1800_MV + + config ESP_LDO_VOLTAGE_STABLE_DELAY_US + int + depends on ESP_LDO_RESERVE_PSRAM + default 1000 endmenu diff --git a/components/esp_hw_support/port/esp32s31/pmu_param.c b/components/esp_hw_support/port/esp32s31/pmu_param.c index fecd96a0642..23a4f26ea96 100644 --- a/components/esp_hw_support/port/esp32s31/pmu_param.c +++ b/components/esp_hw_support/port/esp32s31/pmu_param.c @@ -42,11 +42,11 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param"); .xpd_cpll_i2c = 1, \ .xpd_bbpll_i2c = 1, \ .xpd_apll_i2c = 0, \ - .xpd_mpll_i2c = 1, \ + .xpd_mpll_i2c = 0, \ .xpd_cpll = 1, \ .xpd_bbpll = 1, \ .xpd_apll = 0, \ - .xpd_mpll = 1, \ + .xpd_mpll = 0, \ }, \ .xtal = { \ .xpd_xtal = 1 \ diff --git a/components/esp_hw_support/port/esp_clk_tree_common.c b/components/esp_hw_support/port/esp_clk_tree_common.c index 6663316c56e..4c6378bbfd5 100644 --- a/components/esp_hw_support/port/esp_clk_tree_common.c +++ b/components/esp_hw_support/port/esp_clk_tree_common.c @@ -328,6 +328,7 @@ esp_err_t IRAM_ATTR esp_clk_tree_mpll_acquire(void) esp_ldo_channel_config_t ldo_mpll_config = { .chan_id = CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN, .voltage_mv = CONFIG_ESP_LDO_VOLTAGE_PSRAM_DOMAIN, + .voltage_stable_delay_us = CONFIG_ESP_LDO_VOLTAGE_STABLE_DELAY_US, }; ESP_RETURN_ON_ERROR(esp_ldo_acquire_channel(&ldo_mpll_config, &s_ldo_chan), TAG, "acquire internal LDO for MPLL failed"); } diff --git a/components/esp_psram/device/esp_psram_impl_ap_oct.c b/components/esp_psram/device/esp_psram_impl_ap_oct.c index 7ff19283cfb..753d6d30265 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_oct.c +++ b/components/esp_psram/device/esp_psram_impl_ap_oct.c @@ -412,8 +412,6 @@ static void s_configure_psram_ecc(void) esp_err_t esp_psram_impl_enable(void) { - psram_ctrlr_ll_enable_power(true); - #if SOC_CLK_MPLL_SUPPORTED // We need to use the acquire and freq_set functions directly instead of general clk_tree API for IRAM safe function esp_clk_tree_mpll_acquire();