diff --git a/arch/arm64/src/imx9/Kconfig b/arch/arm64/src/imx9/Kconfig index f7809bc8be..ba72f37268 100644 --- a/arch/arm64/src/imx9/Kconfig +++ b/arch/arm64/src/imx9/Kconfig @@ -310,10 +310,6 @@ config IMX9_LPSPI bool "LPSPI support" default n -config IMX9_PLL - bool "PLL setup support" - default n - menu "LPI2C Peripherals" menuconfig IMX9_LPI2C1 diff --git a/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h b/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h index 6b43fb7edc..a86f4e72f2 100644 --- a/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h +++ b/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h @@ -168,6 +168,10 @@ #define CCM_GPR_SH_GPR_SHIFT (0) /* Bits 0-31: General purpose register, shared for all CPU domains (GPR) */ #define CCM_GPR_SH_GPR_MASK (0xffffffff << CCM_GPR_SH_GPR_SHIFT) +#define CCM_GPR_A55_CLK_SEL_SHIFT (0) +#define CCM_GPR_A55_CLK_SEL_MASK (0x01 << CCM_GPR_A55_CLK_SEL_SHIFT) +#define CCM_GPR_A55_CLK_SEL_CCM (0 << 0) +#define CCM_GPR_A55_CLK_SEL_PLL (1 << 0) /* General Purpose Register (GPR_SHAREDn_AUTHEN, n=0..7) */ @@ -561,6 +565,12 @@ #define CCM_LPCG_TMC 125 #define CCM_LPCG_PMRO 126 +/* Shared register indices */ + +#define CCM_SHARED_EXT_CLK 0 +#define CCM_SHARED_A55_CLK 1 +#define CCM_SHARED_DRAM_CLK 2 + /* Other parameters */ #define ROOT_MUX_MAX 4 /* Count of root clock MUX options */ diff --git a/arch/arm64/src/imx9/hardware/imx93/imx93_pll.h b/arch/arm64/src/imx9/hardware/imx93/imx93_pll.h index 31dbb7c0d3..fb0a5af737 100644 --- a/arch/arm64/src/imx9/hardware/imx93/imx93_pll.h +++ b/arch/arm64/src/imx9/hardware/imx93/imx93_pll.h @@ -175,7 +175,7 @@ #define PLL_DFS_MFN_MASK (0x7 << PLL_DFS_MFN_SHIFT) #define PLL_DFS_MFN(n) (((n) << PLL_DFS_MFN_SHIFT) & PLL_DFS_MFN_MASK) #define PLL_DFS_MFI_SHIFT (8) /* Bits 8-15: MFI */ -#define PLL_DFS_MFI_MASK (0xFF << PLL_DFS_MFI_SHIFT) +#define PLL_DFS_MFI_MASK (0xff << PLL_DFS_MFI_SHIFT) #define PLL_DFS_MFI(n) (((n) << PLL_DFS_MFI_SHIFT) & PLL_DFS_MFI_MASK) /* PLL Dividers (DIV) */ @@ -192,35 +192,4 @@ #define PLL_DFS_STATUS_DFS_OK_MASK (0x7 << PLL_DFS_STATUS_DFS_OK_SHIFT) #define PLL_DFS_STATUS_DFS_OK(n) (((n) << PLL_DFS_STATUS_DFS_OK_SHIFT) & PLL_DFS_STATUS_DFS_OK_MASK) -/**************************************************************************** - * Public Types - ****************************************************************************/ - -struct pll_parms -{ - /* Integer part (DIV) */ - - struct - { - uint32_t rdiv; /* Input clock divider */ - uint32_t odiv; /* PLL output divider */ - uint32_t mfi; /* PLL integer divider */ - }; - - /* Fractional part (NUMERATOR / DENOMINATOR) */ - - struct - { - uint32_t mfn; /* PLL fractional divider numerator */ - uint32_t mfd; /* PLL fractional divider denominator */ - }; -}; - -struct pfd_parms -{ - uint32_t mfi; /* PLL integer divider */ - uint32_t mfn; /* PLL fractional divider numerator */ - bool divby2_en; /* Enable the divide-by-2 output */ -}; - #endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_PLL_H_*/ diff --git a/arch/arm64/src/imx9/imx9_boot.c b/arch/arm64/src/imx9/imx9_boot.c index 121c228197..eb4e7e69d2 100644 --- a/arch/arm64/src/imx9/imx9_boot.c +++ b/arch/arm64/src/imx9/imx9_boot.c @@ -39,6 +39,7 @@ #include "arm64_mmu.h" #include "imx9_boot.h" +#include "imx9_clockconfig.h" #include "imx9_serial.h" #include "imx9_gpio.h" #include "imx9_lowputc.h" diff --git a/arch/arm64/src/imx9/imx9_clockconfig.c b/arch/arm64/src/imx9/imx9_clockconfig.c index a5a5238afb..ac3f976801 100644 --- a/arch/arm64/src/imx9/imx9_clockconfig.c +++ b/arch/arm64/src/imx9/imx9_clockconfig.c @@ -30,6 +30,8 @@ #include #include +#include + #include "barriers.h" #include "arm64_internal.h" @@ -42,6 +44,12 @@ * Pre-processor Definitions ****************************************************************************/ +/* The base oscillator frequency is 24MHz */ + +#define XTAL_FREQ 24000000u + +/* Common barrier */ + #define mb() \ do \ { \ @@ -50,16 +58,12 @@ } \ while (0) -/* The base oscillator frequency is 24MHz */ - -#define XTAL_FREQ 24000000u - /**************************************************************************** * Private Functions ****************************************************************************/ -#ifdef CONFIG_IMX9_PLL -static int pll_init(uintptr_t reg, bool frac, struct pll_parms *parm) +#ifdef CONFIG_IMX9_BOOTLOADER +static int pll_init(uintptr_t reg, bool frac, struct pll_parms_s *parm) { uint32_t val; @@ -104,7 +108,7 @@ static int pll_init(uintptr_t reg, bool frac, struct pll_parms *parm) return OK; } -static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms *pfdparm) +static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms_s *pfdparm) { uint32_t ctrl; uint32_t div; @@ -136,12 +140,13 @@ static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms *pfdparm) /* Bypass and disable DFS */ putreg32(PLL_DFS_BYPASS_EN, PLL_SET(ctrl)); - putreg32(PLL_DFS_CLKOUT_EN | PLL_DFS_ENABLE, PLL_CLR(ctrl)); + putreg32(PLL_DFS_CLKOUT_EN | PLL_DFS_CLKOUT_DIVBY2_EN | PLL_DFS_ENABLE, + PLL_CLR(ctrl)); /* Set the divider */ val = PLL_DFS_MFI(pfdparm->mfi) | PLL_DFS_MFN(pfdparm->mfn); - putreg32(val, PLL_SET(div)); + putreg32(val, PLL_VAL(div)); /* Enable (or disable) the divby2 output */ @@ -163,10 +168,16 @@ static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms *pfdparm) while (!(getreg32(PLL_DFS_STATUS(reg)) & (1 << pfd))); + /* Then disable bypass */ + + putreg32(PLL_DFS_BYPASS_EN, PLL_CLR(ctrl)); + mb(); + return OK; } +#endif -static uint32_t calculate_vco_freq(const struct pll_parms *parm, bool frac) +static uint32_t calculate_vco_freq(const struct pll_parms_s *parm, bool frac) { /* Base clock is common for all VCO:s */ @@ -183,7 +194,7 @@ static uint32_t calculate_vco_freq(const struct pll_parms *parm, bool frac) static uint32_t vco_freq_out(uintptr_t reg, bool frac) { - struct pll_parms parm; + struct pll_parms_s parm; uint32_t ctrl; uint32_t status; uint32_t div; @@ -193,7 +204,6 @@ static uint32_t vco_freq_out(uintptr_t reg, bool frac) ctrl = getreg32(PLL_CTRL(reg)); if ((ctrl & PLL_CTRL_POWERUP) == 0) { - return 0; } @@ -202,7 +212,6 @@ static uint32_t vco_freq_out(uintptr_t reg, bool frac) status = getreg32(PLL_PLL_STATUS(reg)); if ((status & PLL_PLL_STATUS_PLL_LOCK) == 0) { - return 0; } @@ -250,7 +259,6 @@ static uint32_t pll_freq_out(uintptr_t reg, bool frac) if ((ctrl & PLL_CTRL_CLKMUX_EN) == 0) { - return 0; } @@ -284,7 +292,7 @@ static uint32_t pll_freq_out(uintptr_t reg, bool frac) static uint32_t pll_pfd_freq_out(uintptr_t reg, int pfd, int div2) { - struct pfd_parms parm; + struct pfd_parms_s parm; uint32_t ctrl; uint32_t div; uint32_t vco; @@ -338,14 +346,12 @@ static uint32_t pll_pfd_freq_out(uintptr_t reg, int pfd, int div2) /* Populate the DFS parameters */ - parm.mfi = (div & PLL_DFS_MFI_MASK) >> PLL_DFS_MFI_SHIFT; - parm.mfn = (div & PLL_DFS_MFN_MASK) >> PLL_DFS_MFN_SHIFT; + parm.mfi = (div & PLL_DFS_MFI_MASK) >> PLL_DFS_MFI_SHIFT; + parm.mfn = (div & PLL_DFS_MFN_MASK) >> PLL_DFS_MFN_SHIFT; - return ((uint64_t)vco * 5) / (parm.mfi * 5 + parm.mfn) / div2; + return ((uint64_t)vco * 5) / (parm.mfi * 5 + parm.mfn) / div2; } -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -362,29 +368,34 @@ static uint32_t pll_pfd_freq_out(uintptr_t reg, int pfd, int div2) void imx9_clockconfig(void) { - /* REVISIT: Define a clock config and run it. For now we rely on the fact - * that the boot code + bootloader will have set us up. - * - * During boot the ROM code initializes the PLL clocks as follows: - * - * - OSC24M : 24 MHz - * - ARMPLL : 2000 MHz - * - ARMPLL_OUT : 2000 MHz - * - DRAMPLL : 1000 MHz - * - SYSPLL1 : 4000 MHz - * - SYSPLL_PFD0 : 1000 MHz - * - SYSPLL_PFD1 : 800 MHz - * - SYSPLL_PFD2 : 625 MHz - * - AUDIOPLL : OFF - * - AUDIOPLL_OUT : OFF - * - VIDEOPLL : OFF - * - VIDEOPLL_OUT : OFF - * - * After reset all clock sources (OSCPLL) and root clocks (CLOCK_ROOT) are - * running, but gated (LPCG). - * - * By default, all peripheral root clocks are set to the 24 MHz oscillator. - */ +#ifdef CONFIG_IMX9_BOOTLOADER + struct imx9_pll_cfg_s pll_cfgs[] = PLL_CFGS; + struct imx9_pfd_cfg_s pfd_cfgs[] = PFD_CFGS; + struct imx9_pll_cfg_s pll_arm = ARMPLL_CFG; + int i; + + /* Set the CPU clock */ + + putreg32(IMX9_CCM_GPR_SH_CLR(CCM_SHARED_A55_CLK), CCM_GPR_A55_CLK_SEL_PLL); + pll_init(pll_arm.reg, pll_arm.frac, &pll_arm.parms); + putreg32(IMX9_CCM_GPR_SH_SET(CCM_SHARED_A55_CLK), CCM_GPR_A55_CLK_SEL_PLL); + + /* Run the PLL configuration */ + + for (i = 0; i < nitems(pll_cfgs); i++) + { + struct imx9_pll_cfg_s *cfg = &pll_cfgs[i]; + pll_init(cfg->reg, cfg->frac, &cfg->parms); + } + + /* Run the PFD configuration */ + + for (i = 0; i < nitems(pfd_cfgs); i++) + { + struct imx9_pfd_cfg_s *cfg = &pfd_cfgs[i]; + pll_pfd_init(cfg->reg, cfg->pfd, &cfg->parms); + } +#endif } /**************************************************************************** diff --git a/arch/arm64/src/imx9/imx9_clockconfig.h b/arch/arm64/src/imx9/imx9_clockconfig.h index 90301989a9..cf8ffc1f45 100644 --- a/arch/arm64/src/imx9/imx9_clockconfig.h +++ b/arch/arm64/src/imx9/imx9_clockconfig.h @@ -29,6 +29,85 @@ #include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PLL_PARMS(_rdiv, _odiv, _mfi, _mfn, _mfd) \ + { \ + .rdiv = (_rdiv), \ + .odiv = (_odiv), \ + .mfi = (_mfi), \ + .mfn = (_mfn), \ + .mfd = (_mfd), \ + } + +#define PLL_CFG(_reg, _frac, _parms) \ + { \ + .reg = (_reg), \ + .frac = (_frac), \ + .parms = _parms, \ + } + +#define PFD_PARMS(_mfi, _mfn, _div2) \ + { \ + .mfi = (_mfi), \ + .mfn = (_mfn), \ + .divby2_en = (_div2) \ + } + +#define PFD_CFG(_reg, _pfd, _parms) \ + { \ + .reg = (_reg), \ + .pfd = (_pfd), \ + .parms = _parms, \ + } + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct pll_parms_s +{ + /* Integer part (DIV) */ + + struct + { + uint32_t rdiv; /* Input clock divider */ + uint32_t odiv; /* PLL output divider */ + uint32_t mfi; /* PLL integer divider */ + }; + + /* Fractional part (NUMERATOR / DENOMINATOR) */ + + struct + { + uint32_t mfn; /* PLL fractional divider numerator */ + uint32_t mfd; /* PLL fractional divider denominator */ + }; +}; + +struct pfd_parms_s +{ + uint32_t mfi; /* PLL integer divider */ + uint32_t mfn; /* PLL fractional divider numerator */ + bool divby2_en; /* Enable the divide-by-2 output */ +}; + +struct imx9_pll_cfg_s +{ + uintptr_t reg; /* The PLL register base */ + bool frac; /* Fractional PLL ? */ + struct pll_parms_s parms; /* The PLL parameters */ +}; + +struct imx9_pfd_cfg_s +{ + uintptr_t reg; /* The PLL register base */ + int pfd; /* The PFD number */ + struct pfd_parms_s parms; /* The PFD parameters */ +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/boards/arm64/imx9/imx93-evk/include/board.h b/boards/arm64/imx9/imx93-evk/include/board.h index d1a74a7e5a..4632d5443e 100644 --- a/boards/arm64/imx9/imx93-evk/include/board.h +++ b/boards/arm64/imx9/imx93-evk/include/board.h @@ -88,6 +88,39 @@ #define MUX_LPSPI6_CS IOMUX_CFG(IOMUXC_PAD_GPIO_IO00_GPIO2_IO00, IOMUX_GPIO_DEFAULT, IOMUXC_MUX_SION_ON) #define GPIO_LPSPI6_CS (GPIO_PORT2 | GPIO_PIN0 | GPIO_OUTPUT | GPIO_OUTPUT_ONE) +/* Set the PLL clocks as follows: + * + * - OSC24M : 24 MHz + * - ARMPLL_OUT : 1692 MHz + * - DRAMPLL : 933 MHz + * - SYSPLL1 : 4000 MHz + * - SYSPLL_PFD0 : 1000 MHz + * - SYSPLL_PFD1 : 800 MHz + * - SYSPLL_PFD2 : 625 MHz + * - AUDIOPLL_OUT : OFF + * - VIDEOPLL_OUT : OFF + * + * After reset all clock sources (OSCPLL) and root clocks (CLOCK_ROOT) are + * running, but gated (LPCG). + * + * By default, all peripheral root clocks are set to the 24 MHz oscillator. + */ + +#define ARMPLL_CFG PLL_CFG(IMX9_ARMPLL_BASE, false, PLL_PARMS(1, 2, 141, 0, 0)) +#define DRAMPLL_CFG PLL_CFG(IMX9_DRAMPLL_BASE, true, PLL_PARMS(1, 2, 155, 1, 2)) + +#define PLL_CFGS \ + { \ + PLL_CFG(IMX9_SYSPLL_BASE, true, PLL_PARMS(1, 4, 166, 2, 3)), \ + } + +#define PFD_CFGS \ + { \ + PFD_CFG(IMX9_SYSPLL_BASE, 0, PFD_PARMS(4, 0, true)), \ + PFD_CFG(IMX9_SYSPLL_BASE, 1, PFD_PARMS(5, 0, true)), \ + PFD_CFG(IMX9_SYSPLL_BASE, 2, PFD_PARMS(6, 2, true)), \ + } + /**************************************************************************** * Public Data ****************************************************************************/