diff --git a/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h b/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h index a86f4e72f2..1768e7f12d 100644 --- a/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h +++ b/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h @@ -158,7 +158,7 @@ #define CCM_CR_AUTH_TZ_USER (1 << 8) /* Bit 8: Clock root can be changed in user mode (TZ_USER) */ #define CCM_CR_AUTH_TZ_NS (1 << 9) /* Bit 9: Clock root can be changed in non-secure mode (TZ_NS) */ /* Bit 10: Reserved */ -#define CCM_CR_AUTH_LOCK_TZ (1 << 11) /* Bit 1: Lock TrustZone settings (LOCK_TZ) */ +#define CCM_CR_AUTH_LOCK_TZ (1 << 11) /* Bit 11: Lock TrustZone settings (LOCK_TZ) */ /* Bits 12-14: Reserved */ #define CCM_CR_AUTH_LOCK_LIST (1 << 12) /* Bit 15: Lock whitelist settings (LOCK_LIST) */ #define CCM_CR_AUTH_WHITE_LIST_SHIFT (16) /* Bits 16-31: Allow domains to change clock (WHITE_LIST) */ @@ -337,6 +337,12 @@ #define CCM_LPCG_AUTH_WHITE_LIST_SHIFT (16) /* Bits 16-31: Allow domains to change clock (WHITE_LIST) */ #define CCM_LPCG_AUTH_WHITE_LIST_MASK (0xffff << CCM_LPCG_AUTH_WHITE_LIST_SHIFT) +/* Auth access bits */ + +#define CCM_AUTH_TZ_USER(n) ((n) << 8) +#define CCM_AUTH_TZ_NS(n) ((n) << 9) +#define CCM_AUTH_LOCK_TZ(n) ((n) << 11) + /* Clock roots */ #define CCM_CR_A55PERIPH 0 /* CLOCK Root Arm A55 Periph. */ @@ -570,12 +576,14 @@ #define CCM_SHARED_EXT_CLK 0 #define CCM_SHARED_A55_CLK 1 #define CCM_SHARED_DRAM_CLK 2 +#define CCM_SHARED_GPR_COUNT 7 /* Other parameters */ #define ROOT_MUX_MAX 4 /* Count of root clock MUX options */ #define CCM_CR_COUNT 94 /* Count of clock roots */ -#define CCM_LPCG_COUNT 126 /* Counte of clock gates */ +#define CCM_LPCG_COUNT 126 /* Count of clock gates */ +#define CCM_OSCPLL_COUNT 18 /* Count of osc plls */ /**************************************************************************** * Public Types @@ -708,4 +716,30 @@ static const int g_ccm_root_mux[][ROOT_MUX_MAX] = {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, SYS_PLL1PFD2}, /* Pal Came Scan */ }; +#define CCM_ARM_A55_PERIPH_CLK_ROOT 0 +#define CCM_ARM_A55_MTR_BUS_CLK_ROOT 1 +#define CCM_ARM_A55_CLK_ROOT 2 +#define CCM_M33_CLK_ROOT 3 +#define CCM_ELE_CLK_ROOT 4 +#define CCM_BUS_WAKEUP_CLK_ROOT 5 +#define CCM_BUS_AON_CLK_ROOT 6 +#define CCM_WAKEUP_AXI_CLK_ROOT 7 +#define CCM_SWO_TRACE_CLK_ROOT 8 +#define CCM_M33_SYSTICK_CLK_ROOT 9 +#define CCM_NIC_CLK_ROOT 65 +#define CCM_NIC_APB_CLK_ROOT 66 +#define CCM_DRAM_ALT_CLK_ROOT 76 +#define CCM_DRAM_APB_CLK_ROOT 77 +#define CCM_CLK_ROOT_NUM 95 + +#define CCM_OSCPLL_END 19 +#define CCM_CCGR_NUM 127 + +#define CCM_SHARED_GPR_DRAM_CLK 2 +#define CCM_SHARED_GPR_DRAM_CLK_SEL_PLL 0 +#define CCM_SHARED_GPR_DRAM_CLK_SEL_CCM BIT(0) +#define CCM_SHARED_GPR_NUM 8 + +#define MHZ(x) ((x) * 1000000UL) + #endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_CCM_H */ diff --git a/arch/arm64/src/imx9/imx9_ccm.c b/arch/arm64/src/imx9/imx9_ccm.c index 1d8cef9562..69597b46dc 100644 --- a/arch/arm64/src/imx9/imx9_ccm.c +++ b/arch/arm64/src/imx9/imx9_ccm.c @@ -49,6 +49,206 @@ } \ while (0) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ccm_clk_src_tz_access + * + * Description: + * Clock source access contol enable. + * + * Input Parameters: + * pscll - Clock source + * non_secure - Grant non-secure access + * user_mode - Grant user mode access + * lock_tz - Lock settings + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +static int imx9_ccm_clk_src_tz_access(uint32_t oscpll, bool non_secure, + bool user_mode, bool lock_tz) +{ + if (oscpll > CCM_OSCPLL_COUNT) + { + return -EINVAL; + } + + modifyreg32(IMX9_CCM_OSCPLL_AUTH(oscpll), 0, + CCM_AUTH_TZ_USER(user_mode) | + CCM_AUTH_TZ_NS(non_secure) | + CCM_AUTH_LOCK_TZ(lock_tz)); + + return 0; +} + +/**************************************************************************** + * Name: ccm_clk_root_tz_access + * + * Description: + * Root clock access control enable. + * + * Input Parameters: + * clk_root_id - Root clock id + * non_secure - Grant non-secure access + * user_mode - Grant user mode access + * lock_tz - Lock settings + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +static int imx9_ccm_clk_root_tz_access(uint32_t clk_root_id, bool non_secure, + bool user_mode, bool lock_tz) +{ + if (clk_root_id > CCM_CR_COUNT) + { + return -EINVAL; + } + + modifyreg32(IMX9_CCM_CR_AUTH(clk_root_id), 0, + CCM_AUTH_TZ_USER(user_mode) | + CCM_AUTH_TZ_NS(non_secure) | + CCM_AUTH_LOCK_TZ(lock_tz)); + + return 0; +} + +/**************************************************************************** + * Name: imx9_ccm_lpcg_tz_access + * + * Description: + * Low power clock gatig unit access enable. + * + * Input Parameters: + * lpcg - Clock id + * non_secure - Grant non-secure access + * user_mode - Grant user mode access + * lock_tz - Lock settings + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +static int imx9_ccm_lpcg_tz_access(uint32_t lpcg, bool non_secure, + bool user_mode, bool lock_tz) +{ + if (lpcg > CCM_LPCG_COUNT) + { + return -EINVAL; + } + + modifyreg32(IMX9_CCM_LPCG_AUTH(lpcg), 0, + CCM_AUTH_TZ_USER(user_mode) | + CCM_AUTH_TZ_NS(non_secure) | + CCM_AUTH_LOCK_TZ(lock_tz)); + + return 0; +} + +/**************************************************************************** + * Name: imx9_ccm_shared_gpr_tz_access + * + * Description: + * General purpose access enable. + * + * Input Parameters: + * grp - Gpr id + * non_secure - Grant non-secure access + * user_mode - Grant user mode access + * lock_tz - Lock settings + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +static int imx9_ccm_shared_gpr_tz_access(uint32_t gpr, bool non_secure, + bool user_mode, bool lock_tz) +{ + if (gpr > CCM_SHARED_GPR_COUNT) + { + return -EINVAL; + } + + modifyreg32(IMX9_CCM_GPR_SH_AUTH(gpr), 0, + CCM_AUTH_TZ_USER(user_mode) | + CCM_AUTH_TZ_NS(non_secure) | + CCM_AUTH_LOCK_TZ(lock_tz)); + + return 0; +} + +/**************************************************************************** + * Name: imx9_ccm_clock_prepare + * + * Description: + * Prepares the clocks, grants non-secure access for clocks. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero on success, a negated error code otherwise + * + ****************************************************************************/ + +static int imx9_ccm_clock_prepare(void) +{ + int ret; + int i; + + /* allow for non-secure access */ + + for (i = 0; i < CCM_OSCPLL_END; i++) + { + ret = imx9_ccm_clk_src_tz_access(i, true, false, false); + if (ret != 0) + { + return ret; + } + } + + for (i = 0; i < CCM_CLK_ROOT_NUM; i++) + { + ret = imx9_ccm_clk_root_tz_access(i, true, false, false); + if (ret != 0) + { + return ret; + } + } + + for (i = 0; i < CCM_CCGR_NUM; i++) + { + ret = imx9_ccm_lpcg_tz_access(i, true, false, false); + if (ret != 0) + { + return ret; + } + } + + for (i = 0; i < CCM_SHARED_GPR_NUM; i++) + { + ret = imx9_ccm_shared_gpr_tz_access(i, true, false, false); + if (ret != 0) + { + return ret; + } + } + + return 0; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -195,3 +395,166 @@ int imx9_ccm_gate_on(int gate, bool enabled) return OK; } + +/**************************************************************************** + * Name: imx9_ccm_shared_gpr_set + * + * Description: + * Set shared gpr clock register value + * + * Input Parameters: + * gpr - General purpose clock index + * val - Value + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int imx9_ccm_shared_gpr_set(uint32_t gpr, uint32_t val) +{ + if (gpr > CCM_SHARED_GPR_COUNT) + { + return -EINVAL; + } + + putreg32(val, IMX9_CCM_GPR_SH(gpr)); + + return 0; +} + +/**************************************************************************** + * Name: imx9_ccm_clock_init + * + * Description: + * Initializes bus clocks for a known default state. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success, a negated error value otherwise + * + ****************************************************************************/ + +int imx9_ccm_clock_init(void) +{ + int ret; + + ret = imx9_ccm_clock_prepare(); + if (ret != 0) + { + return ret; + } + + /* Set A55 clk to 500M. This clock root is normally used as intermediate + * clock source for A55 core / DSU when doing ARM PLL reconfig. Set it to + * 500 MHz. + */ + + ret = imx9_ccm_configure_root_clock(CCM_ARM_A55_CLK_ROOT, SYS_PLL1PFD0, 2); + if (ret != 0) + { + return ret; + } + + /* Set A55 periphal to 333 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_ARM_A55_PERIPH_CLK_ROOT, + SYS_PLL1PFD0, 3); + if (ret != 0) + { + return ret; + } + + /* Set A55 mtr bus to 133 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_ARM_A55_MTR_BUS_CLK_ROOT, + SYS_PLL1PFD1DIV2, 3); + if (ret != 0) + { + return ret; + } + + /* ELE to 200 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_ELE_CLK_ROOT, SYS_PLL1PFD1DIV2, 2); + if (ret != 0) + { + return ret; + } + + /* Bus_wakeup to 133 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_BUS_WAKEUP_CLK_ROOT, + SYS_PLL1PFD1DIV2, 3); + if (ret != 0) + { + return ret; + } + + /* Bus_AON to 133 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_BUS_AON_CLK_ROOT, SYS_PLL1PFD1DIV2, + 3); + if (ret != 0) + { + return ret; + } + + /* M33 to 200 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_M33_CLK_ROOT, SYS_PLL1PFD1DIV2, 2); + if (ret != 0) + { + return ret; + } + + /* WAKEUP_AXI to 312.5 MHz, because of FEC only can support to 320M for + * generating MII clock at 2.5 MHz + */ + + ret = imx9_ccm_configure_root_clock(CCM_WAKEUP_AXI_CLK_ROOT, SYS_PLL1PFD2, + 2); + if (ret != 0) + { + return ret; + } + + /* SWO TRACE to 133 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_SWO_TRACE_CLK_ROOT, + SYS_PLL1PFD1DIV2, 3); + if (ret != 0) + { + return ret; + } + + /* M33 systetick to 24 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_M33_SYSTICK_CLK_ROOT, OSC_24M, 1); + if (ret != 0) + { + return ret; + } + + /* NIC to 400 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_NIC_CLK_ROOT, SYS_PLL1PFD1, 2); + if (ret != 0) + { + return ret; + } + + /* NIC_APB to 133 MHz */ + + ret = imx9_ccm_configure_root_clock(CCM_NIC_APB_CLK_ROOT, SYS_PLL1PFD1DIV2, + 3); + if (ret != 0) + { + return ret; + } + + return OK; +} diff --git a/arch/arm64/src/imx9/imx9_ccm.h b/arch/arm64/src/imx9/imx9_ccm.h index fa2017b314..c8b1c56881 100644 --- a/arch/arm64/src/imx9/imx9_ccm.h +++ b/arch/arm64/src/imx9/imx9_ccm.h @@ -85,4 +85,38 @@ int imx9_ccm_root_clock_on(int root, bool enabled); int imx9_ccm_gate_on(int gate, bool enabled); +/**************************************************************************** + * Name: imx9_ccm_shared_gpr_set + * + * Description: + * Set shared gpr clock register value + * + * Input Parameters: + * gpr - General purpose clock index + * val - Value + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int imx9_ccm_shared_gpr_set(uint32_t gpr, uint32_t val); + +/**************************************************************************** + * Name: imx9_ccm_clock_init + * + * Description: + * Initializes bus clocks for a known default state. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success, a negated error value otherwise + * + ****************************************************************************/ + +int imx9_ccm_clock_init(void); + #endif /* __ARCH_ARM64_SRC_IMX9_IMX9_CCM_H */ diff --git a/arch/arm64/src/imx9/imx9_clockconfig.c b/arch/arm64/src/imx9/imx9_clockconfig.c index 156e1f5a2a..30eecf13f7 100644 --- a/arch/arm64/src/imx9/imx9_clockconfig.c +++ b/arch/arm64/src/imx9/imx9_clockconfig.c @@ -67,6 +67,11 @@ static int pll_init(uintptr_t reg, bool frac, struct pll_parms_s *parm) { uint32_t val; + if (!frac) + { + modifyreg32(PLL_CLR(PLL_CTRL(reg)), 0, PLL_CTRL_HW_CTRL_SEL); + } + /* Bypass and disable PLL */ putreg32(PLL_CTRL_CLKMUX_BYPASS, PLL_SET(PLL_CTRL(reg))); @@ -80,14 +85,15 @@ static int pll_init(uintptr_t reg, bool frac, struct pll_parms_s *parm) putreg32(val, PLL_DIV(reg)); - /* Disable spread spectrum */ - - putreg32(PLL_SPREAD_SPECTRUM_ENABLE, PLL_CLR(PLL_SPREAD_SPECTRUM(reg))); - /* Set the fractional parts */ if (frac) { + /* Disable spread spectrum */ + + putreg32(PLL_SPREAD_SPECTRUM_ENABLE, + PLL_CLR(PLL_SPREAD_SPECTRUM(reg))); + putreg32(PLL_NUMERATOR_MFN(parm->mfn), PLL_NUMERATOR(reg)); putreg32(PLL_DENOMINATOR_MFD(parm->mfd), PLL_DENOMINATOR(reg)); } @@ -108,6 +114,7 @@ static int pll_init(uintptr_t reg, bool frac, struct pll_parms_s *parm) return OK; } +#ifdef CONFIG_IMX9_CFG_PLLS static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms_s *pfdparm) { uint32_t ctrl; @@ -175,6 +182,7 @@ static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms_s *pfdparm) return OK; } +#endif /* CONFIG_IMX9_CFG_PLLS */ #endif static uint32_t calculate_vco_freq(const struct pll_parms_s *parm, bool frac) @@ -352,6 +360,34 @@ static uint32_t pll_pfd_freq_out(uintptr_t reg, int pfd, int div2) return ((uint64_t)vco * 5) / (parm.mfi * 5 + parm.mfn) / div2; } +/**************************************************************************** + * Name: imx9_ccm_dram_disable_bypass + * + * Description: + * Disable clock bypass + * + * Input Parameters: + * None + * + * Returned Value: + * None + *> + ****************************************************************************/ + +#ifdef CONFIG_IMX9_BOOTLOADER +static void imx9_dram_disable_bypass(void) +{ + /* Set DRAM APB to 133Mhz */ + + imx9_ccm_configure_root_clock(CCM_DRAM_APB_CLK_ROOT, SYS_PLL1PFD1DIV2, 3); + + /* Switch from DRAM clock root from CCM to PLL */ + + imx9_ccm_shared_gpr_set(CCM_SHARED_GPR_DRAM_CLK, + CCM_SHARED_GPR_DRAM_CLK_SEL_PLL); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -369,10 +405,13 @@ static uint32_t pll_pfd_freq_out(uintptr_t reg, int pfd, int div2) void imx9_clockconfig(void) { #ifdef CONFIG_IMX9_BOOTLOADER + struct imx9_pll_cfg_s pll_arm = ARMPLL_CFG; + struct imx9_pll_cfg_s pll_ddr = DRAMPLL_CFG; +#ifdef CONFIG_IMX9_CFG_PLLS 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; +#endif /* Set the CPU clock */ @@ -380,6 +419,13 @@ void imx9_clockconfig(void) pll_init(pll_arm.reg, pll_arm.frac, &pll_arm.parms); putreg32(CCM_GPR_A55_CLK_SEL_PLL, IMX9_CCM_GPR_SH_SET(CCM_SHARED_A55_CLK)); + /* DRAM clk to 933 MHz */ + + pll_init(pll_ddr.reg, pll_ddr.frac, &pll_ddr.parms); + imx9_dram_disable_bypass(); + +#ifdef CONFIG_IMX9_CFG_PLLS + /* Run the PLL configuration */ for (i = 0; i < nitems(pll_cfgs); i++) @@ -396,6 +442,7 @@ void imx9_clockconfig(void) pll_pfd_init(cfg->reg, cfg->pfd, &cfg->parms); } #endif +#endif /* CONFIG_IMX9_BOOTLOADER */ } /**************************************************************************** diff --git a/boards/arm64/imx9/imx93-evk/include/board.h b/boards/arm64/imx9/imx93-evk/include/board.h index 1d93aef9c7..d1f53ce920 100644 --- a/boards/arm64/imx9/imx93-evk/include/board.h +++ b/boards/arm64/imx9/imx93-evk/include/board.h @@ -140,7 +140,7 @@ */ #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 DRAMPLL_CFG PLL_CFG(IMX9_DRAMPLL_BASE, true, PLL_PARMS(1, 4, 155, 1, 2)) #define PLL_CFGS \ { \