This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 48cf91a7be arm64/imx9: ccm: add default clk init
48cf91a7be is described below
commit 48cf91a7be1289b5744d832015b6afe4204ad68d
Author: Eero Nurkkala <[email protected]>
AuthorDate: Tue Jul 9 11:00:06 2024 +0300
arm64/imx9: ccm: add default clk init
This adds enablers for setting various clocks to some default
values. Also, this provides helpers to grant nonsecure access
to a number of clocks. Bootloader may utilize these to make
the system boot in a deterministic manner.
Signed-off-by: Eero Nurkkala <[email protected]>
---
arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h | 38 ++-
arch/arm64/src/imx9/imx9_ccm.c | 363 +++++++++++++++++++++++++
arch/arm64/src/imx9/imx9_ccm.h | 34 +++
arch/arm64/src/imx9/imx9_clockconfig.c | 57 +++-
boards/arm64/imx9/imx93-evk/include/board.h | 2 +-
5 files changed, 486 insertions(+), 8 deletions(-)
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 \
{ \