diff --git a/components/esp_hal_clock/esp32p4/include/hal/clk_tree_ll.h b/components/esp_hal_clock/esp32p4/include/hal/clk_tree_ll.h index bb6e74e4887..010d1c02ef9 100644 --- a/components/esp_hal_clock/esp32p4/include/hal/clk_tree_ll.h +++ b/components/esp_hal_clock/esp32p4/include/hal/clk_tree_ll.h @@ -466,32 +466,6 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_mpll_get_freq_mhz(u return xtal_freq_mhz * (div + 1) / (ref_div + 1); } -/** - * @brief Set MPLL frequency from XTAL source (Analog part - through regi2c) - * - * @param mpll_freq_mhz MPLL frequency, in MHz - * @param xtal_freq_mhz XTAL frequency, in MHz - */ -static inline __attribute__((always_inline)) void clk_ll_mpll_set_config(uint32_t mpll_freq_mhz, uint32_t xtal_freq_mhz) -{ - HAL_ASSERT(xtal_freq_mhz == SOC_XTAL_FREQ_40M); - - // There are sequential regi2c operations in `clk_ll_mpll_set_config`, use the raw regi2c API with one lock wrapper to save time. - REGI2C_ENTER_CRITICAL(); - uint8_t mpll_dhref_val = regi2c_impl_read(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_DHREF); - regi2c_impl_write(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_DHREF, mpll_dhref_val | (3 << I2C_MPLL_DHREF_LSB)); - uint8_t mpll_rstb_val = regi2c_impl_read(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_IR_CAL_RSTB); - regi2c_impl_write(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_IR_CAL_RSTB, mpll_rstb_val & 0xdf); - regi2c_impl_write(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_IR_CAL_RSTB, mpll_rstb_val | (1 << I2C_MPLL_IR_CAL_RSTB_lSB)); - - // MPLL_Freq = XTAL_Freq * (div + 1) / (ref_div + 1) - uint8_t ref_div = 1; - uint8_t div = mpll_freq_mhz / 20 - 1; - uint8_t val = ((div << 3) | ref_div); - regi2c_impl_write(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_DIV_REG_ADDR, val); - REGI2C_EXIT_CRITICAL(); -} - /** * @brief Start MPLL self-calibration */ @@ -518,6 +492,65 @@ static inline __attribute__((always_inline)) bool clk_ll_mpll_calibration_is_don return HP_SYS_CLKRST.ana_pll_ctrl0.reg_mspi_cal_end; } +/** + * @brief Set MPLL frequency from XTAL source (Analog part - through regi2c) + * + * @param mpll_freq_mhz MPLL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz + */ +static inline __attribute__((always_inline)) void clk_ll_mpll_set_config_v1(uint32_t mpll_freq_mhz, uint32_t xtal_freq_mhz) +{ + HAL_ASSERT(xtal_freq_mhz == SOC_XTAL_FREQ_40M); + + /* MPLL calibration start */ + clk_ll_mpll_calibration_start(); + + // There are sequential regi2c operations in `clk_ll_mpll_set_config`, use the raw regi2c API with one lock wrapper to save time. + REGI2C_ENTER_CRITICAL(); + uint8_t mpll_dhref_val = regi2c_impl_read(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_DHREF); + regi2c_impl_write(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_DHREF, mpll_dhref_val | (3 << I2C_MPLL_DHREF_LSB)); + uint8_t mpll_rstb_val = regi2c_impl_read(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_IR_CAL_RSTB); + regi2c_impl_write(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_IR_CAL_RSTB, mpll_rstb_val & 0xdf); + regi2c_impl_write(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_IR_CAL_RSTB, mpll_rstb_val | (1 << I2C_MPLL_IR_CAL_RSTB_lSB)); + + // MPLL_Freq = XTAL_Freq * (div + 1) / (ref_div + 1) + uint8_t ref_div = 1; + uint8_t div = mpll_freq_mhz / 20 - 1; + uint8_t val = ((div << 3) | ref_div); + regi2c_impl_write(I2C_MPLL, I2C_MPLL_HOSTID, I2C_MPLL_DIV_REG_ADDR, val); + REGI2C_EXIT_CRITICAL(); + /* wait calibration done */ + while(!clk_ll_mpll_calibration_is_done()); + /* MPLL calibration stop */ + clk_ll_mpll_calibration_stop(); +} + +/** + * @brief MPLL hardware self-calibration (debug flow) + * + * Power up MPLL, configure IR cal / div / dhref, run HW calibration and wait until done. + * Caller must enable the regi2c master clock before calling this function. + */ +static inline __attribute__((always_inline)) void clk_ll_mpll_set_config_v3(uint32_t mpll_freq_mhz, uint32_t xtal_freq_mhz) +{ + HAL_ASSERT(xtal_freq_mhz == SOC_XTAL_FREQ_40M); + + REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_IR_CAL_EXT_CAP, 3); + REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_IR_CAL_ENX_CAP, 1); + REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_DIV_ADDR, 9); + REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_DHREF, 3); + + REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_IR_CAL_ENX_CAP, 0); + clk_ll_mpll_calibration_start(); + + uint8_t div = mpll_freq_mhz / 20 - 1; + REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_DIV_ADDR, div); + + while (!clk_ll_mpll_calibration_is_done()) { + } + clk_ll_mpll_calibration_stop(); +} + /** * @brief Get APLL configuration which can be used to calculate APLL frequency * diff --git a/components/esp_hw_support/port/esp32p4/Kconfig.ldo b/components/esp_hw_support/port/esp32p4/Kconfig.ldo index a29b0254763..3e2fcc4c98a 100644 --- a/components/esp_hw_support/port/esp32p4/Kconfig.ldo +++ b/components/esp_hw_support/port/esp32p4/Kconfig.ldo @@ -67,5 +67,5 @@ menu "LDO Regulator Configurations" config ESP_LDO_VOLTAGE_STABLE_DELAY_US int depends on ESP_LDO_RESERVE_PSRAM - default 0 + default 200 endmenu diff --git a/components/esp_hw_support/port/esp32p4/pmu_init.c b/components/esp_hw_support/port/esp32p4/pmu_init.c index f3b10a338f1..e9fc454242f 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_init.c +++ b/components/esp_hw_support/port/esp32p4/pmu_init.c @@ -18,6 +18,9 @@ #include "pmu_param.h" #include "esp_private/esp_pmu.h" #include "soc/regi2c_dig_reg.h" +#include "soc/regi2c_mpll.h" +#include "soc/regi2c_bias.h" +#include "hal/regi2c_ctrl_ll.h" #include "soc/lp_system_reg.h" #include "regi2c_ctrl.h" #include "esp_rom_sys.h" @@ -221,4 +224,10 @@ void pmu_init(void) // For PVT func taking effect, need delay. esp_rom_delay_us(1000); #endif +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 + REG_SET_BIT(PMU_RF_PWC_REG, PMU_MSPI_PHY_XPD); + REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1, 12); + REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12); + REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_IR_CAL_EXT_CAP, 3); +#endif } diff --git a/components/esp_hw_support/port/esp32p4/pmu_param.c b/components/esp_hw_support/port/esp32p4/pmu_param.c index 66620cf82e1..386f01024f2 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_param.c +++ b/components/esp_hw_support/port/esp32p4/pmu_param.c @@ -53,7 +53,7 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param"); .clk_power = { \ .i2c_iso_en = 1, \ .i2c_retention = 1, \ - .xpd_pll_i2c = 1, \ + .xpd_pll_i2c = 0xf, \ .xpd_pll = 0 \ }, \ .xtal = { \ diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index 4a57103e7c1..f761b1b2f94 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -18,6 +18,7 @@ #include "soc/soc.h" #include "soc/regi2c_syspll.h" #include "soc/regi2c_cpll.h" +#include "soc/regi2c_mpll.h" #include "soc/rtc.h" #include "soc/cache_reg.h" #include "soc/pau_reg.h" @@ -488,6 +489,13 @@ SPM_IRAM_ATTR bool pmu_sleep_finish(bool dslp) esp_rom_delay_us(DCDC_STARTUP_TIME_US); } pmu_sleep_shutdown_ldo(); + } else if (s_mpll_freq_mhz_before_sleep) { + rtc_clk_mpll_enable(); +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 + _regi2c_ctrl_ll_master_enable_clock(true); + REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_IR_CAL_EXT_CAP, 3); + esp_rom_delay_us(10); +#endif } pmu_ll_imm_set_pad_slp_sel(&PMU, false); @@ -497,7 +505,6 @@ SPM_IRAM_ATTR bool pmu_sleep_finish(bool dslp) if (!dslp) { if (s_mpll_freq_mhz_before_sleep) { - rtc_clk_mpll_enable(); rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), s_mpll_freq_mhz_before_sleep, true); #if CONFIG_SPIRAM if (!s_pmu_sleep_regdma_backup_enabled) { diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk.c b/components/esp_hw_support/port/esp32p4/rtc_clk.c index 133f0b8e298..b1f3f57404c 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk.c @@ -661,13 +661,12 @@ void rtc_clk_mpll_configure(uint32_t xtal_freq, uint32_t mpll_freq, bool thread_ } else { ANALOG_CLOCK_ENABLE(); } - /* MPLL calibration start */ - clk_ll_mpll_calibration_start(); - clk_ll_mpll_set_config(mpll_freq, xtal_freq); - /* wait calibration done */ - while(!clk_ll_mpll_calibration_is_done()); - /* MPLL calibration stop */ - clk_ll_mpll_calibration_stop(); + +#if CONFIG_ESP32P4_SELECTS_REV_LESS_V3 + clk_ll_mpll_set_config_v1(mpll_freq, xtal_freq); +#else + clk_ll_mpll_set_config_v3(mpll_freq, xtal_freq); +#endif if (thread_safe) { _regi2c_ctrl_ll_master_enable_clock(false); diff --git a/components/soc/esp32p4/include/soc/regi2c_mpll.h b/components/soc/esp32p4/include/soc/regi2c_mpll.h index a59eafb222d..0d5ec71148e 100644 --- a/components/soc/esp32p4/include/soc/regi2c_mpll.h +++ b/components/soc/esp32p4/include/soc/regi2c_mpll.h @@ -17,6 +17,14 @@ #define I2C_MPLL 0x63 #define I2C_MPLL_HOSTID 0 +#define I2C_MPLL_IR_CAL_EXT_CAP 1 +#define I2C_MPLL_IR_CAL_EXT_CAP_MSB 1 +#define I2C_MPLL_IR_CAL_EXT_CAP_LSB 0 + +#define I2C_MPLL_IR_CAL_ENX_CAP 1 +#define I2C_MPLL_IR_CAL_ENX_CAP_MSB 2 +#define I2C_MPLL_IR_CAL_ENX_CAP_LSB 2 + #define I2C_MPLL_IR_CAL_RSTB 1 #define I2C_MPLL_IR_CAL_RSTB_MSB 5 #define I2C_MPLL_IR_CAL_RSTB_lSB 5