Merge branch 'fix/fix_mpll_enable_order_v6.1' into 'release/v6.1'

fix(esp_hw_support): fix esp32s31 mpll initialization (v6.1)

See merge request espressif/esp-idf!50430
This commit is contained in:
Jiang Jiang Jian
2026-07-16 11:28:17 +08:00
11 changed files with 33 additions and 21 deletions
@@ -32,6 +32,8 @@
#include "soc/reset_reasons.h" #include "soc/reset_reasons.h"
#include "hal/assist_debug_ll.h" #include "hal/assist_debug_ll.h"
#include "esp_rom_sys.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"); 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_force_enable_clock(true); // TODO: IDF-14678 Remove this?
regi2c_ctrl_ll_master_configure_clock(); regi2c_ctrl_ll_master_configure_clock();
#endif #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) void bootloader_enable_cpu_reset_info(void)
@@ -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(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(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_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); 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(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_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);
} }
/** /**
@@ -63,21 +63,6 @@ extern "C" {
#define PSRAM_CTRLR_LL_INTR_EVENT_SUPPORTED 1 #define PSRAM_CTRLR_LL_INTR_EVENT_SUPPORTED 1
#define PSRAM_CTRLR_LL_DEDICATED_LDO 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 * @brief Set PSRAM write cmd
* *
@@ -151,6 +151,10 @@ static inline void ldo_ll_enable(int ldo_unit, bool enable)
//for compatibility //for compatibility
//PMU.hp_sys[PMU_MODE_HP_ACTIVE].regulator0.xpd is for chip internal LDO for chip power //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 //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;
}
} }
/** /**
@@ -15,6 +15,7 @@
#include "hal/ldo_ll.h" #include "hal/ldo_ll.h"
#include "esp_ldo_regulator.h" #include "esp_ldo_regulator.h"
#include "esp_private/critical_section.h" #include "esp_private/critical_section.h"
#include "esp_rom_sys.h"
ESP_LOG_ATTR_TAG(TAG, "ldo"); 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_adjustable_constraint_valid = true;
bool check_voltage_constraint_valid = true; bool check_voltage_constraint_valid = true;
bool ldo_enabled = false;
esp_os_enter_critical(&s_spinlock); esp_os_enter_critical(&s_spinlock);
if (config->flags.adjustable) { if (config->flags.adjustable) {
// the user wants to adjust it // 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_ripple_suppression(unit_id, true);
ldo_ll_enable(unit_id, true); ldo_ll_enable(unit_id, true);
ldo_ll_enable_current_limit(unit_id, false); ldo_ll_enable_current_limit(unit_id, false);
ldo_enabled = true;
} }
// update the channel attributes // update the channel attributes
channel->ref_cnt++; 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, 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"); "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) { if (out_handle) {
*out_handle = channel; *out_handle = channel;
} }
@@ -25,6 +25,7 @@ typedef struct ldo_regulator_channel_t *esp_ldo_channel_handle_t;
typedef struct { 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 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 */ 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 /// Extra flags of a LDO channel
struct ldo_extra_flags { struct ldo_extra_flags {
@@ -63,4 +63,9 @@ menu "LDO Regulator Configurations"
config ESP_LDO_VOLTAGE_PSRAM_DOMAIN config ESP_LDO_VOLTAGE_PSRAM_DOMAIN
int int
default 1800 if ESP_LDO_VOLTAGE_PSRAM_1800_MV 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 endmenu
@@ -31,4 +31,9 @@ menu "LDO Regulator Configurations"
config ESP_LDO_VOLTAGE_PSRAM_DOMAIN config ESP_LDO_VOLTAGE_PSRAM_DOMAIN
int int
default 1800 if ESP_LDO_VOLTAGE_PSRAM_1800_MV 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 endmenu
@@ -42,11 +42,11 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param");
.xpd_cpll_i2c = 1, \ .xpd_cpll_i2c = 1, \
.xpd_bbpll_i2c = 1, \ .xpd_bbpll_i2c = 1, \
.xpd_apll_i2c = 0, \ .xpd_apll_i2c = 0, \
.xpd_mpll_i2c = 1, \ .xpd_mpll_i2c = 0, \
.xpd_cpll = 1, \ .xpd_cpll = 1, \
.xpd_bbpll = 1, \ .xpd_bbpll = 1, \
.xpd_apll = 0, \ .xpd_apll = 0, \
.xpd_mpll = 1, \ .xpd_mpll = 0, \
}, \ }, \
.xtal = { \ .xtal = { \
.xpd_xtal = 1 \ .xpd_xtal = 1 \
@@ -328,6 +328,7 @@ esp_err_t IRAM_ATTR esp_clk_tree_mpll_acquire(void)
esp_ldo_channel_config_t ldo_mpll_config = { esp_ldo_channel_config_t ldo_mpll_config = {
.chan_id = CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN, .chan_id = CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN,
.voltage_mv = CONFIG_ESP_LDO_VOLTAGE_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"); ESP_RETURN_ON_ERROR(esp_ldo_acquire_channel(&ldo_mpll_config, &s_ldo_chan), TAG, "acquire internal LDO for MPLL failed");
} }
@@ -412,8 +412,6 @@ static void s_configure_psram_ecc(void)
esp_err_t esp_psram_impl_enable(void) esp_err_t esp_psram_impl_enable(void)
{ {
psram_ctrlr_ll_enable_power(true);
#if SOC_CLK_MPLL_SUPPORTED #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 // 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(); esp_clk_tree_mpll_acquire();