mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(mpll): fix mpll calibration fail bug
This commit is contained in:
committed by
Michael.B
parent
c6e80a336a
commit
81acd9c18f
@@ -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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user