diff --git a/components/esp_hw_support/include/esp_private/rtc_clk.h b/components/esp_hw_support/include/esp_private/rtc_clk.h index 7edf69be06..620b03654f 100644 --- a/components/esp_hw_support/include/esp_private/rtc_clk.h +++ b/components/esp_hw_support/include/esp_private/rtc_clk.h @@ -7,6 +7,8 @@ #pragma once #include +#include +#include "soc/soc_caps.h" #ifdef __cplusplus extern "C" { @@ -44,6 +46,27 @@ void rtc_clk_bbpll_add_consumer(void); */ void rtc_clk_bbpll_remove_consumer(void); +#if SOC_CLK_MPLL_SUPPORTED +//------------------------------------MPLL-------------------------------------// +/** + * @brief Enable MPLL + */ +void rtc_clk_mpll_enable(void); + +/** + * @brief Disable MPLL + */ +void rtc_clk_mpll_disable(void); + +/** + * @brief Configure MPLL + * + * @param[in] xtal_freq XTAL frequency + * @param[in] mpll_freq MPLL frequency + */ +void rtc_clk_mpll_configure(uint32_t xtal_freq, uint32_t mpll_freq); +#endif //#if SOC_CLK_MPLL_SUPPORTED + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk.c b/components/esp_hw_support/port/esp32p4/rtc_clk.c index 6c67021a9b..df3890a6c3 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk.c @@ -405,3 +405,26 @@ bool rtc_dig_8m_enabled(void) * TODO: update the library to use rtc_clk_xtal_freq_get */ rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get"))); + +//------------------------------------MPLL-------------------------------------// +void rtc_clk_mpll_disable(void) +{ + clk_ll_mpll_disable(); +} + +void rtc_clk_mpll_enable(void) +{ + clk_ll_mpll_enable(); +} + +void rtc_clk_mpll_configure(uint32_t xtal_freq, uint32_t mpll_freq) +{ + /* Analog part */ + /* MPLL calibration start */ + regi2c_ctrl_ll_mpll_calibration_start(); + clk_ll_mpll_set_config(mpll_freq, xtal_freq); + /* wait calibration done */ + while(!regi2c_ctrl_ll_mpll_calibration_is_done()); + /* MPLL calibration stop */ + regi2c_ctrl_ll_mpll_calibration_stop(); +} diff --git a/components/hal/esp32p4/include/hal/clk_tree_ll.h b/components/hal/esp32p4/include/hal/clk_tree_ll.h index 29a38bdfc5..a607f723bf 100644 --- a/components/hal/esp32p4/include/hal/clk_tree_ll.h +++ b/components/hal/esp32p4/include/hal/clk_tree_ll.h @@ -10,8 +10,9 @@ #include "soc/soc.h" #include "soc/clk_tree_defs.h" #include "soc/rtc.h" +#include "soc/pmu_reg.h" #include "hal/regi2c_ctrl.h" -#include "soc/regi2c_bbpll.h" +#include "soc/regi2c_mpll.h" #include "hal/assert.h" #include "hal/log.h" #include "esp32p4/rom/rtc.h" @@ -82,6 +83,22 @@ static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void) } +/** + * @brief Power up MPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_mpll_enable(void) +{ + REG_SET_BIT(PMU_RF_PWC_REG, PMU_MSPI_PHY_XPD); +} + +/** + * @brief Power down MPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_mpll_disable(void) +{ + REG_CLR_BIT(PMU_RF_PWC_REG, PMU_MSPI_PHY_XPD); +} + /** * @brief Enable the 32kHz crystal oscillator * @@ -272,6 +289,25 @@ static inline __attribute__((always_inline)) void clk_ll_bbpll_set_config(uint32 } +/** + * @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 == RTC_XTAL_FREQ_40M); + + // MPLL_Freq = XTAL_Freq * (div + 1) / (ref_div + 1) + uint8_t ref_div = 1; + uint8_t div = mpll_freq_mhz / 20 - 1; + + uint32_t val = REGI2C_READ(I2C_MPLL, I2C_MPLL_DIV_REG_ADDR); + val |= ((div << 3) | ref_div); + REGI2C_WRITE(I2C_MPLL, I2C_MPLL_DIV_REG_ADDR, val); +} + /** * @brief Select the clock source for CPU_CLK (SOC Clock Root) * diff --git a/components/hal/esp32p4/include/hal/regi2c_ctrl_ll.h b/components/hal/esp32p4/include/hal/regi2c_ctrl_ll.h index e22a025815..c4d7e26646 100644 --- a/components/hal/esp32p4/include/hal/regi2c_ctrl_ll.h +++ b/components/hal/esp32p4/include/hal/regi2c_ctrl_ll.h @@ -10,6 +10,7 @@ #include #include "soc/soc.h" #include "soc/regi2c_defs.h" +#include "soc/hp_sys_clkrst_reg.h" #ifdef __cplusplus extern "C" { @@ -45,6 +46,32 @@ static inline __attribute__((always_inline)) bool regi2c_ctrl_ll_bbpll_calibrati return REG_GET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_CAL_DONE); } +/** + * @brief Start MPLL self-calibration + */ +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_mpll_calibration_start(void) +{ + CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, HP_SYS_CLKRST_REG_MSPI_CAL_STOP); +} + +/** + * @brief Stop MPLL self-calibration + */ +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_mpll_calibration_stop(void) +{ + SET_PERI_REG_MASK(HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, HP_SYS_CLKRST_REG_MSPI_CAL_STOP); +} + +/** + * @brief Check whether MPLL calibration is done + * + * @return True if calibration is done; otherwise false + */ +static inline __attribute__((always_inline)) bool regi2c_ctrl_ll_mpll_calibration_is_done(void) +{ + return REG_GET_BIT(HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, HP_SYS_CLKRST_REG_MSPI_CAL_END); +} + /** * @brief Enable the I2C internal bus to do I2C read/write operation to the SAR_ADC register */ diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 72745e393c..d115e7a740 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1307,6 +1307,10 @@ config SOC_CLK_APLL_SUPPORTED bool default y +config SOC_CLK_MPLL_SUPPORTED + bool + default y + config SOC_CLK_XTAL32K_SUPPORTED bool default y diff --git a/components/soc/esp32p4/include/soc/regi2c_mpll.h b/components/soc/esp32p4/include/soc/regi2c_mpll.h new file mode 100644 index 0000000000..58caa6bf22 --- /dev/null +++ b/components/soc/esp32p4/include/soc/regi2c_mpll.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#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 0x63 +#define I2C_MPLL_HOSTID 0 + +#define I2C_MPLL_DIV_REG_ADDR 2 +#define I2C_MPLL_REF_DIV_ADDR I2C_MPLL_DIV_REG_ADDR +#define I2C_MPLL_REF_DIV_ADDR_MSB 2 +#define I2C_MPLL_REF_DIV_ADDR_LSB 0 + +#define I2C_MPLL_DIV_ADDR I2C_MPLL_DIV_REG_ADDR +#define I2C_MPLL_DIV_ADDR_MSB 7 +#define I2C_MPLL_DIV_ADDR_LSB 3 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index a3e72e4ba5..1356308ff8 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -563,6 +563,7 @@ #define SOC_MODEM_CLOCK_IS_INDEPENDENT (0) #define SOC_CLK_APLL_SUPPORTED (1) /*!< Support Audio PLL */ +#define SOC_CLK_MPLL_SUPPORTED (1) /*!< Support MSPI PLL */ #define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */ #define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */ #define SOC_CLK_RC32K_SUPPORTED (1) /*!< Support an internal 32kHz RC oscillator */