Skip to content

Commit

Permalink
arm64/imx9: ccm: add default clk init
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
eenurkka committed Jul 9, 2024
1 parent b881868 commit 847483d
Show file tree
Hide file tree
Showing 5 changed files with 429 additions and 8 deletions.
38 changes: 36 additions & 2 deletions arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) */
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */
308 changes: 308 additions & 0 deletions arch/arm64/src/imx9/imx9_ccm.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <stdint.h>
#include <stdbool.h>
#include <assert.h>

#include <sys/param.h>
#include <sys/types.h>
Expand All @@ -49,6 +50,192 @@
} \
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:
* None
*
****************************************************************************/

static void 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);
assert(ret == 0);
}

for (i = 0; i < CCM_CLK_ROOT_NUM; i++)
{
ret = imx9_ccm_clk_root_tz_access(i, true, false, false);
assert(ret == 0);
}

for (i = 0; i < CCM_CCGR_NUM; i++)
{
ret = imx9_ccm_lpcg_tz_access(i, true, false, false);
assert(ret == 0);
}

for (i = 0; i < CCM_SHARED_GPR_NUM; i++)
{
ret = imx9_ccm_shared_gpr_tz_access(i, true, false, false);
assert(ret == 0);
}
}

/****************************************************************************
* Public Functions
****************************************************************************/
Expand Down Expand Up @@ -195,3 +382,124 @@ 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_bus_clock_init
*
* Description:
* Initializes bus clocks for a known default state.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/

void imx9_ccm_clock_init(void)
{
int ret;

imx9_ccm_clock_prepare();

/* 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);
assert(ret == 0);

/* Set A55 periphal to 333 MHz */

ret = imx9_ccm_configure_root_clock(CCM_ARM_A55_PERIPH_CLK_ROOT,
SYS_PLL1PFD0, 3);
assert(ret == 0);

/* Set A55 mtr bus to 133 MHz */

ret = imx9_ccm_configure_root_clock(CCM_ARM_A55_MTR_BUS_CLK_ROOT,
SYS_PLL1PFD1DIV2, 3);
assert(ret == 0);

/* ELE to 200 MHz */

ret = imx9_ccm_configure_root_clock(CCM_ELE_CLK_ROOT, SYS_PLL1PFD1DIV2, 2);
assert(ret == 0);

/* Bus_wakeup to 133 MHz */

ret = imx9_ccm_configure_root_clock(CCM_BUS_WAKEUP_CLK_ROOT,
SYS_PLL1PFD1DIV2, 3);
assert(ret == 0);

/* Bus_AON to 133 MHz */

ret = imx9_ccm_configure_root_clock(CCM_BUS_AON_CLK_ROOT, SYS_PLL1PFD1DIV2,
3);
assert(ret == 0);

/* M33 to 200 MHz */

ret = imx9_ccm_configure_root_clock(CCM_M33_CLK_ROOT, SYS_PLL1PFD1DIV2, 2);
assert(ret == 0);

/* 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);
assert(ret == 0);

/* SWO TRACE to 133 MHz */

ret = imx9_ccm_configure_root_clock(CCM_SWO_TRACE_CLK_ROOT,
SYS_PLL1PFD1DIV2, 3);
assert(ret == 0);

/* M33 systetick to 24 MHz */

ret = imx9_ccm_configure_root_clock(CCM_M33_SYSTICK_CLK_ROOT, OSC_24M, 1);
assert(ret == 0);

/* NIC to 400 MHz */

ret = imx9_ccm_configure_root_clock(CCM_NIC_CLK_ROOT, SYS_PLL1PFD1, 2);
assert(ret == 0);

/* NIC_APB to 133 MHz */

ret = imx9_ccm_configure_root_clock(CCM_NIC_APB_CLK_ROOT, SYS_PLL1PFD1DIV2,
3);
assert(ret == 0);
}
Loading

0 comments on commit 847483d

Please sign in to comment.