Merge branch 'fix/fix_mpll_cali_flow_s31' into 'master'

mpll: improved mpll calibration flow on s31

See merge request espressif/esp-idf!51928
This commit is contained in:
Armando (Dou Yiwen)
2026-08-25 02:48:14 +00:00
4 changed files with 68 additions and 26 deletions
@@ -57,8 +57,9 @@ static inline void bootloader_hardware_init(void)
regi2c_ctrl_ll_master_configure_clock();
#endif
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1, 10);
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 10);
REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_IR_CAL_EXT_CAP, 3);
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1, 12);
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
/* During mmu_hal_init, a valid clock source is required for the PSRAM,
so before shutting down MPLL in rtc_clk_init, the PSRAM clock source
@@ -18,13 +18,13 @@
#include "soc/hp_alive_sys_struct.h"
#include "hal/regi2c_ctrl.h"
#include "soc/regi2c_apll.h"
#include "soc/regi2c_mpll.h"
#include "soc/pmu_reg.h"
#include "hal/clkout_channel.h"
#include "hal/assert.h"
#include "hal/log.h"
#include "esp32s31/rom/rtc.h"
#include "hal/misc.h"
#define MHZ (1000000)
#define CLK_LL_PLL_8M_FREQ_MHZ (8)
@@ -487,23 +487,9 @@ static inline __attribute__((always_inline)) bool clk_ll_cpll_calibration_is_don
*/
static inline __attribute__((always_inline)) uint32_t clk_ll_mpll_get_freq_mhz(uint32_t xtal_freq_mhz)
{
uint8_t fb_div = REG_GET_FIELD(LP_AONCLKRST_MSPI_DIV_REG, LP_AONCLKRST_MSPI_FB_DIV);
return xtal_freq_mhz * (fb_div + 1) / 2;
}
/**
* @brief Set MPLL frequency from XTAL source
*
* @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);
uint8_t ref_div = 1;
uint8_t fb_div = mpll_freq_mhz * (ref_div + 1) / xtal_freq_mhz - 1;
REG_SET_FIELD(LP_AONCLKRST_MSPI_DIV_REG, LP_AONCLKRST_MSPI_FB_DIV, fb_div);
uint8_t div = REG_GET_FIELD(LP_AONCLKRST_MSPI_DIV_REG, LP_AONCLKRST_MSPI_FB_DIV);
uint8_t ref_div = REG_GET_FIELD(LP_AONCLKRST_MSPI_DIV_REG, LP_AONCLKRST_MSPI_REF_DIV);
return xtal_freq_mhz * (div + 1) / (ref_div + 1);
}
/**
@@ -532,6 +518,32 @@ static inline __attribute__((always_inline)) bool clk_ll_mpll_calibration_is_don
return REG_GET_BIT(HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, HP_SYS_CLKRST_REG_MSPI_CAL_END);
}
/**
* @brief Set MPLL frequency from XTAL source
*
* @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);
REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_IR_CAL_EXT_CAP, 3);
REGI2C_WRITE_MASK(I2C_MPLL, I2C_MPLL_IR_CAL_ENX_CAP, 1);
REG_SET_FIELD(LP_AONCLKRST_MSPI_DIV_REG, LP_AONCLKRST_MSPI_FB_DIV, 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 ref_div = 1;
uint8_t fb_div = mpll_freq_mhz * (ref_div + 1) / xtal_freq_mhz - 1;
REG_SET_FIELD(LP_AONCLKRST_MSPI_DIV_REG, LP_AONCLKRST_MSPI_FB_DIV, fb_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
*
@@ -657,13 +657,8 @@ 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 (thread_safe) {
_regi2c_ctrl_ll_master_enable_clock(false);
@@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
#pragma once
/**
* @file regi2c_mpll.h
* @brief Register definitions for MSPI_PLL (MPLL)
*
* This file lists register fields of MPLL, located on an internal configuration
* bus. These definitions are used via macros defined in regi2c_ctrl.h
*/
#define I2C_MPLL 0xB
#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
#define I2C_MPLL_DHREF 3
#define I2C_MPLL_DHREF_MSB 5
#define I2C_MPLL_DHREF_LSB 4