From 6f992acf31155105e5e79c6a1132e6746bcd9649 Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 25 Nov 2024 13:49:33 +0800 Subject: [PATCH] feat(mipi): fine tune DPHY PLL clock --- .../port/esp32p4/esp_clk_tree.c | 2 +- .../hal/esp32p4/include/hal/clk_tree_ll.h | 22 ++++++++++++++++++- components/hal/mipi_dsi_hal.c | 13 ++++++++--- .../soc/esp32p4/include/soc/clk_tree_defs.h | 12 +++++----- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c index 546f25c34b..0105cb062a 100644 --- a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c @@ -31,7 +31,7 @@ esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_sr clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ; break; case SOC_MOD_CLK_PLL_F20M: - clk_src_freq = CLK_LL_PLL_20M_FREQ_MHZ * MHZ; + clk_src_freq = CLK_LL_PLL_480M_FREQ_MHZ / clk_ll_pll_f20m_get_divider() * MHZ; break; case SOC_MOD_CLK_PLL_F80M: clk_src_freq = CLK_LL_PLL_80M_FREQ_MHZ * MHZ; diff --git a/components/hal/esp32p4/include/hal/clk_tree_ll.h b/components/hal/esp32p4/include/hal/clk_tree_ll.h index d37ac910ea..9627b33eb9 100644 --- a/components/hal/esp32p4/include/hal/clk_tree_ll.h +++ b/components/hal/esp32p4/include/hal/clk_tree_ll.h @@ -35,7 +35,6 @@ extern "C" { #define CLK_LL_PLL_8M_FREQ_MHZ (8) -#define CLK_LL_PLL_20M_FREQ_MHZ (20) #define CLK_LL_PLL_80M_FREQ_MHZ (80) #define CLK_LL_PLL_160M_FREQ_MHZ (160) #define CLK_LL_PLL_240M_FREQ_MHZ (240) @@ -693,6 +692,27 @@ static inline __attribute__((always_inline)) void clk_ll_pll_f25m_set_divider(ui HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.ref_clk_ctrl0, reg_ref_25m_clk_div_num, divider - 1); } +/** + * @brief Set PLL_F20M_CLK divider. freq of PLL_F20M_CLK = freq of SPLL_CLK / divider + * + * @param divider Divider. CLK_DIV_NUM = divider - 1. + */ +static inline __attribute__((always_inline)) void clk_ll_pll_f20m_set_divider(uint32_t divider) +{ + HAL_ASSERT(divider >= 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.ref_clk_ctrl1, reg_ref_20m_clk_div_num, divider - 1); +} + +/** + * @brief Get PLL_F20M_CLK divider + * + * @return Divider. Divider = (CLK_DIV_NUM + 1). + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_pll_f20m_get_divider(void) +{ + return HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.ref_clk_ctrl1, reg_ref_20m_clk_div_num) + 1; +} + /** * @brief Select the clock source for RTC_SLOW_CLK * diff --git a/components/hal/mipi_dsi_hal.c b/components/hal/mipi_dsi_hal.c index e8689aa46d..090585db94 100644 --- a/components/hal/mipi_dsi_hal.c +++ b/components/hal/mipi_dsi_hal.c @@ -47,13 +47,20 @@ void mipi_dsi_hal_configure_phy_pll(mipi_dsi_hal_context_t *hal, uint32_t phy_cl // 5MHz <= f_ref/N <= 40MHz uint8_t min_N = MAX(1, ref_freq_mhz / 40); uint8_t max_N = ref_freq_mhz / 5; + uint16_t min_delta = UINT16_MAX; for (uint8_t n = min_N; n <= max_N; n++) { uint16_t m = vco_freq_mhz * n / ref_freq_mhz; // M must be even number if ((m & 0x01) == 0) { - pll_M = m; - pll_N = n; - break; + uint16_t delta = vco_freq_mhz - ref_freq_mhz * m / n; + if (delta < min_delta) { + min_delta = delta; + pll_M = m; + pll_N = n; + if (min_delta == 0) { + break; + } + } } } HAL_ASSERT(pll_M && pll_N); diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index c17d83319f..b5e53e0cd4 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -143,13 +143,13 @@ typedef enum { SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL, RC_FAST, or LP_PLL by configuring soc_rtc_fast_clk_src_t */ SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, or RC32K by configuring soc_rtc_slow_clk_src_t */ // For digital domain: peripherals - SOC_MOD_CLK_PLL_F20M, /*!< PLL_F20M_CLK is derived from SPLL (clock gating + "fixed" divider of 24), it has a fixed frequency of 20MHz */ + SOC_MOD_CLK_PLL_F20M, /*!< PLL_F20M_CLK is derived from SPLL (clock gating + default divider 24), its default frequency is 20MHz */ SOC_MOD_CLK_PLL_F25M, /*!< PLL_F25M_CLK is derived from MPLL (clock gating + configurable divider), it will have a frequency of 25MHz */ - SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from SPLL (clock gating + "fixed" divider of 6), it has a fixed frequency of 80MHz */ - SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from SPLL (clock gating + "fixed" divider of 3), it has a fixed frequency of 160MHz */ - SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from SPLL (clock gating + "fixed" divider of 2), it has a fixed frequency of 240MHz */ + SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from SPLL (clock gating + default divider 6), its default frequency is 80MHz */ + SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from SPLL (clock gating + default divider 3), its default frequency is 160MHz */ + SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from SPLL (clock gating + default divider 2), its default frequency is 240MHz */ SOC_MOD_CLK_CPLL, /*!< CPLL is from 40MHz XTAL oscillator frequency multipliers */ - SOC_MOD_CLK_SPLL, /*!< SPLL is from 40MHz XTAL oscillator frequency multipliers, it has a "fixed" frequency of 480MHz */ + SOC_MOD_CLK_SPLL, /*!< SPLL is from 40MHz XTAL oscillator frequency multipliers, its default frequency is 480MHz */ SOC_MOD_CLK_MPLL, /*!< MPLL is from 40MHz XTAL oscillator frequency multipliers */ SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */ SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */ @@ -720,7 +720,7 @@ typedef enum { //////////////////////////////////////////////CLOCK OUTPUT/////////////////////////////////////////////////////////// typedef enum { CLKOUT_SIG_MPLL = 0, /*!< MPLL is from 40MHz XTAL oscillator frequency multipliers */ - CLKOUT_SIG_SPLL = 1, /*!< SPLL is from 40MHz XTAL oscillator frequency multipliers, it has a "fixed" frequency of 480MHz */ + CLKOUT_SIG_SPLL = 1, /*!< SPLL is from 40MHz XTAL oscillator frequency multipliers, its default frequency is 480MHz */ CLKOUT_SIG_CPLL = 2, /*!< CPLL_CLK is the output of 40MHz crystal oscillator frequency multiplier, can be 320/360/400MHz */ CLKOUT_SIG_XTAL = 3, /*!< External 40MHz crystal */ CLKOUT_SIG_RC_FAST = 4, /*!< Internal 17.5MHz RC oscillator */