blob: 85299643de73164e16f2e4916602082eab396e81 [file]
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <soc.h>
#include <zephyr/linker/sections.h>
#include <zephyr/linker/linker-defs.h>
#if defined(CONFIG_SOC_MIMXRT1189_CM7)
#include <zephyr/cache.h>
#elif defined(CONFIG_IMXRT118X_CM33_XCACHE_PS)
#include <fsl_cache.h>
#endif
#include <fsl_clock.h>
#include <fsl_gpc.h>
#include <fsl_pmu.h>
#include <fsl_dcdc.h>
#include <fsl_ele_base_api.h>
#include <fsl_trdc.h>
#include <zephyr/dt-bindings/clock/imx_ccm_rev2.h>
#include <cmsis_core.h>
/*
* Set ELE_STICK_FAILED_STS to 0 when ELE status check is not required,
* which is useful when debug reset, where the core has already get the
* TRDC ownership at first time and ELE is not able to release TRDC
* ownership again for the following TRDC ownership request.
*/
#define ELE_STICK_FAILED_STS 1
#if ELE_STICK_FAILED_STS
#define ELE_IS_FAILED(x) (x != kStatus_Success)
#else
#define ELE_IS_FAILED(x) false
#endif
#define ELE_TRDC_AON_ID 0x74
#define ELE_TRDC_WAKEUP_ID 0x78
#define ELE_CORE_CM33_ID 0x1
#define ELE_CORE_CM7_ID 0x2
#ifdef CONFIG_INIT_ARM_PLL
static const clock_arm_pll_config_t armPllConfig_BOARD_BootClockRUN = {
#if defined(CONFIG_SOC_MIMXRT1189_CM33) || defined(CONFIG_SOC_MIMXRT1189_CM7)
/* Post divider, 0 - DIV by 2, 1 - DIV by 4, 2 - DIV by 8, 3 - DIV by 1 */
.postDivider = kCLOCK_PllPostDiv2,
/* PLL Loop divider, Fout = Fin * ( loopDivider / ( 2 * postDivider ) ) */
.loopDivider = 132,
#else
#error "Unknown SOC, no pll configuration defined"
#endif
};
#endif
const clock_sys_pll1_config_t sysPll1Config_BOARD_BootClockRUN = {
/* Enable Sys Pll1 divide-by-2 clock or not */
.pllDiv2En = 1,
/* Enable Sys Pll1 divide-by-5 clock or not */
.pllDiv5En = 1,
/* Spread spectrum parameter */
.ss = NULL,
/* Enable spread spectrum or not */
.ssEnable = false,
};
const clock_sys_pll2_config_t sysPll2Config_BOARD_BootClockRUN = {
/* Denominator of spread spectrum */
.mfd = 268435455,
/* Spread spectrum parameter */
.ss = NULL,
/* Enable spread spectrum or not */
.ssEnable = false,
};
/**
* @brief Initialize the system clock
*/
static ALWAYS_INLINE void clock_init(void)
{
clock_root_config_t rootCfg = {0};
/* Init OSC RC 400M */
CLOCK_OSC_EnableOscRc400M();
CLOCK_OSC_GateOscRc400M(false);
#if CONFIG_CPU_CORTEX_M7
/* Switch both core to OscRC400M first */
rootCfg.mux = kCLOCK_M7_ClockRoot_MuxOscRc400M;
rootCfg.div = 1;
CLOCK_SetRootClock(kCLOCK_Root_M7, &rootCfg);
#endif
#if CONFIG_CPU_CORTEX_M33
rootCfg.mux = kCLOCK_M33_ClockRoot_MuxOscRc400M;
rootCfg.div = 2;
CLOCK_SetRootClock(kCLOCK_Root_M33, &rootCfg);
#endif
#if CONFIG_CPU_CORTEX_M7
DCDC_SetVDD1P0BuckModeTargetVoltage(DCDC, kDCDC_CORE0, kDCDC_1P0Target1P1V);
DCDC_SetVDD1P0BuckModeTargetVoltage(DCDC, kDCDC_CORE1, kDCDC_1P0Target1P1V);
/* FBB need to be enabled in OverDrive(OD) mode */
PMU_EnableFBB(ANADIG_PMU, true);
#endif
/* Config CLK_1M */
CLOCK_OSC_Set1MHzOutputBehavior(kCLOCK_1MHzOutEnableFreeRunning1Mhz);
/* Init OSC RC 24M */
CLOCK_OSC_EnableOscRc24M(true);
/* Config OSC 24M */
ANADIG_OSC->OSC_24M_CTRL |= ANADIG_OSC_OSC_24M_CTRL_OSC_EN(1) |
ANADIG_OSC_OSC_24M_CTRL_BYPASS_EN(0) | ANADIG_OSC_OSC_24M_CTRL_LP_EN(1) |
ANADIG_OSC_OSC_24M_CTRL_OSC_24M_GATE(0);
/* Wait for 24M OSC to be stable. */
while (ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK !=
(ANADIG_OSC->OSC_24M_CTRL & ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK)) {
}
#ifdef CONFIG_INIT_ARM_PLL
/* Init Arm Pll. */
CLOCK_InitArmPll(&armPllConfig_BOARD_BootClockRUN);
#endif
/* Init Sys Pll1. */
CLOCK_InitSysPll1(&sysPll1Config_BOARD_BootClockRUN);
/* Init Sys Pll2. */
CLOCK_InitSysPll2(&sysPll2Config_BOARD_BootClockRUN);
/* Init System Pll2 pfd0. */
CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd0, 27);
/* Init System Pll2 pfd1. */
CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd1, 16);
/* Init System Pll2 pfd2. */
CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd2, 24);
/* Init System Pll2 pfd3. */
CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd3, 32);
/* Init Sys Pll3. */
CLOCK_InitSysPll3();
/* Init System Pll3 pfd0. */
CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd0, 22);
/* Init System Pll3 pfd1. */
CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd1, 33);
/* Init System Pll3 pfd2. */
CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd2, 22);
/* Init System Pll3 pfd3. */
CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd3, 18);
/* Bypass Audio Pll. */
CLOCK_SetPllBypass(kCLOCK_PllAudio, true);
/* DeInit Audio Pll. */
CLOCK_DeinitAudioPll();
#if defined(CONFIG_SOC_MIMXRT1189_CM7)
/* Module clock root configurations. */
/* Configure M7 using ARM_PLL_CLK */
rootCfg.mux = kCLOCK_M7_ClockRoot_MuxArmPllOut;
rootCfg.div = 1;
CLOCK_SetRootClock(kCLOCK_Root_M7, &rootCfg);
#endif
#if defined(CONFIG_SOC_MIMXRT1189_CM33)
/* Configure M33 using SYS_PLL3_CLK */
rootCfg.mux = kCLOCK_M33_ClockRoot_MuxSysPll3Out;
rootCfg.div = 2;
CLOCK_SetRootClock(kCLOCK_Root_M33, &rootCfg);
#endif
/* Configure BUS_AON using SYS_PLL2_CLK */
rootCfg.mux = kCLOCK_BUS_AON_ClockRoot_MuxSysPll2Out;
rootCfg.div = 4;
CLOCK_SetRootClock(kCLOCK_Root_Bus_Aon, &rootCfg);
/* Configure BUS_WAKEUP using SYS_PLL2_CLK */
rootCfg.mux = kCLOCK_BUS_WAKEUP_ClockRoot_MuxSysPll2Out;
rootCfg.div = 4;
CLOCK_SetRootClock(kCLOCK_Root_Bus_Wakeup, &rootCfg);
/* Configure WAKEUP_AXI using SYS_PLL3_CLK */
rootCfg.mux = kCLOCK_WAKEUP_AXI_ClockRoot_MuxSysPll3Out;
rootCfg.div = 2;
CLOCK_SetRootClock(kCLOCK_Root_Wakeup_Axi, &rootCfg);
/* Configure SWO_TRACE using SYS_PLL3_DIV2_CLK */
rootCfg.mux = kCLOCK_SWO_TRACE_ClockRoot_MuxSysPll3Div2;
rootCfg.div = 3;
CLOCK_SetRootClock(kCLOCK_Root_Swo_Trace, &rootCfg);
#if CONFIG_CPU_CORTEX_M33
/* Configure M33_SYSTICK using OSC_24M */
rootCfg.mux = kCLOCK_M33_SYSTICK_ClockRoot_MuxOsc24MOut;
rootCfg.div = 240;
CLOCK_SetRootClock(kCLOCK_Root_M33_Systick, &rootCfg);
#endif
#if CONFIG_CPU_CORTEX_M7
/* Configure M7_SYSTICK using OSC_24M */
rootCfg.mux = kCLOCK_M7_SYSTICK_ClockRoot_MuxOsc24MOut;
rootCfg.div = 240;
CLOCK_SetRootClock(kCLOCK_Root_M7_Systick, &rootCfg);
#endif
#if defined(CONFIG_UART_MCUX_LPUART) && \
(DT_NODE_HAS_STATUS(DT_NODELABEL(lpuart1), okay) \
|| DT_NODE_HAS_STATUS(DT_NODELABEL(lpuart2), okay))
/* Configure LPUART0102 using SYS_PLL3_DIV2_CLK */
rootCfg.mux = kCLOCK_LPUART0102_ClockRoot_MuxSysPll3Div2;
rootCfg.div = 10;
#endif
#if defined(CONFIG_I2C_MCUX_LPI2C) && \
(DT_NODE_HAS_STATUS(DT_NODELABEL(lpi2c1), okay) \
|| DT_NODE_HAS_STATUS(DT_NODELABEL(lpi2c2), okay))
/* Configure LPI2C0102 using SYS_PLL3_DIV2_CLK */
rootCfg.mux = kCLOCK_LPI2C0102_ClockRoot_MuxSysPll3Div2;
rootCfg.div = 4;
CLOCK_SetRootClock(kCLOCK_Root_Lpi2c0102, &rootCfg);
#endif
#if defined(CONFIG_I2C_MCUX_LPI2C) && \
(DT_NODE_HAS_STATUS(DT_NODELABEL(lpi2c3), okay) \
|| DT_NODE_HAS_STATUS(DT_NODELABEL(lpi2c4), okay))
/* Configure LPI2C0304 using SYS_PLL3_DIV2_CLK */
rootCfg.mux = kCLOCK_LPI2C0304_ClockRoot_MuxSysPll3Div2;
rootCfg.div = 4;
CLOCK_SetRootClock(kCLOCK_Root_Lpi2c0304, &rootCfg);
#endif
#if defined(CONFIG_I2C_MCUX_LPI2C) && \
(DT_NODE_HAS_STATUS(DT_NODELABEL(lpi2c5), okay) \
|| DT_NODE_HAS_STATUS(DT_NODELABEL(lpi2c6), okay))
/* Configure LPI2C0506 using SYS_PLL3_DIV2_CLK */
rootCfg.mux = kCLOCK_LPI2C0506_ClockRoot_MuxSysPll3Div2;
rootCfg.div = 4;
CLOCK_SetRootClock(kCLOCK_Root_Lpi2c0506, &rootCfg);
#endif
#if defined(CONFIG_SPI_MCUX_LPSPI) && \
(DT_NODE_HAS_STATUS(DT_NODELABEL(lpspi1), okay) \
|| DT_NODE_HAS_STATUS(DT_NODELABEL(lpspi2), okay))
/* Configure LPSPI0102 using SYS_PLL3_PFD1_CLK */
rootCfg.mux = kCLOCK_LPSPI0102_ClockRoot_MuxSysPll3Pfd1;
rootCfg.div = 2;
CLOCK_SetRootClock(kCLOCK_Root_Lpspi0102, &rootCfg);
#endif
#if defined(CONFIG_COUNTER_MCUX_GPT)
#if (DT_NODE_HAS_STATUS(DT_NODELABEL(gpt1), okay))
/* Configure GPT1 using SYS_PLL3_DIV2_CLK */
rootCfg.mux = kCLOCK_GPT1_ClockRoot_MuxSysPll3Div2;
rootCfg.div = 1;
CLOCK_SetRootClock(kCLOCK_Root_Gpt1, &rootCfg);
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpt1), okay) */
#if (DT_NODE_HAS_STATUS(DT_NODELABEL(gpt2), okay))
/* Configure GPT2 using SYS_PLL3_DIV2_CLK */
rootCfg.mux = kCLOCK_GPT2_ClockRoot_MuxSysPll3Div2;
rootCfg.div = 1;
CLOCK_SetRootClock(kCLOCK_Root_Gpt2, &rootCfg);
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpt2), okay) */
#endif /* CONFIG_COUNTER_MCUX_GPT */
#ifdef CONFIG_MCUX_ACMP
#if (DT_NODE_HAS_STATUS(DT_NODELABEL(acmp1), okay) \
|| DT_NODE_HAS_STATUS(DT_NODELABEL(acmp2), okay) \
|| DT_NODE_HAS_STATUS(DT_NODELABEL(acmp3), okay) \
|| DT_NODE_HAS_STATUS(DT_NODELABEL(acmp4), okay))
/* Configure ACMP using MuxSysPll3Out */
rootCfg.mux = kCLOCK_ACMP_ClockRoot_MuxSysPll3Out;
rootCfg.div = 2;
CLOCK_SetRootClock(kCLOCK_Root_Acmp, &rootCfg);
#endif
#endif /* CONFIG_MCUX_ACMP */
/* Keep core clock ungated during WFI */
CCM->LPCG[1].LPM0 = 0x33333333;
CCM->LPCG[1].LPM1 = 0x33333333;
/* Keep the system clock running so SYSTICK can wake up
* the system from wfi.
*/
GPC_CM_SetNextCpuMode(0, kGPC_RunMode);
GPC_CM_SetNextCpuMode(1, kGPC_RunMode);
GPC_CM_EnableCpuSleepHold(0, false);
GPC_CM_EnableCpuSleepHold(1, false);
#if !defined(CONFIG_PM)
/* Enable the AHB clock while the CM7 is sleeping to allow debug access
* to TCM
*/
BLK_CTRL_S_AONMIX->M7_CFG |= BLK_CTRL_S_AONMIX_M7_CFG_TCM_SIZE_MASK;
#endif
}
/**
* @brief Initialize the system clock
*/
static ALWAYS_INLINE void trdc_enable_all_access(void)
{
status_t sts;
uint8_t i, j;
/* Get ELE FW status */
do {
uint32_t ele_fw_sts;
sts = ELE_BaseAPI_GetFwStatus(MU_RT_S3MUA, &ele_fw_sts);
} while (sts != kStatus_Success);
do {
#if defined(CONFIG_SOC_MIMXRT1189_CM33)
/* Release TRDC A to CM33 core */
sts = ELE_BaseAPI_ReleaseRDC(MU_RT_S3MUA, ELE_TRDC_AON_ID, ELE_CORE_CM33_ID);
#elif defined(CONFIG_SOC_MIMXRT1189_CM7)
/* Release TRDC A to CM7 core */
sts = ELE_BaseAPI_ReleaseRDC(MU_RT_S3MUA, ELE_TRDC_AON_ID, ELE_CORE_CM7_ID);
#endif
} while (ELE_IS_FAILED(sts));
/* Release TRDC W to CM33 core */
do {
#if defined(CONFIG_SOC_MIMXRT1189_CM33)
/* Release TRDC A to CM33 core */
sts = ELE_BaseAPI_ReleaseRDC(MU_RT_S3MUA, ELE_TRDC_WAKEUP_ID, ELE_CORE_CM33_ID);
#elif defined(CONFIG_SOC_MIMXRT1189_CM7)
/* Release TRDC A to CM7 core */
sts = ELE_BaseAPI_ReleaseRDC(MU_RT_S3MUA, ELE_TRDC_WAKEUP_ID, ELE_CORE_CM7_ID);
#endif
} while (ELE_IS_FAILED(sts));
/* Enable all access modes for MBC and MRC of TRDCA and TRDCW */
trdc_hardware_config_t hwConfig;
trdc_memory_access_control_config_t memAccessConfig;
(void)memset(&memAccessConfig, 0, sizeof(memAccessConfig));
memAccessConfig.nonsecureUsrX = 1U;
memAccessConfig.nonsecureUsrW = 1U;
memAccessConfig.nonsecureUsrR = 1U;
memAccessConfig.nonsecurePrivX = 1U;
memAccessConfig.nonsecurePrivW = 1U;
memAccessConfig.nonsecurePrivR = 1U;
memAccessConfig.secureUsrX = 1U;
memAccessConfig.secureUsrW = 1U;
memAccessConfig.secureUsrR = 1U;
memAccessConfig.securePrivX = 1U;
memAccessConfig.securePrivW = 1U;
memAccessConfig.securePrivR = 1U;
TRDC_GetHardwareConfig(TRDC1, &hwConfig);
for (i = 0U; i < hwConfig.mrcNumber; i++) {
for (j = 0U; j < 8; j++) {
TRDC_MrcSetMemoryAccessConfig(TRDC1, &memAccessConfig, i, j);
}
}
for (i = 0U; i < hwConfig.mbcNumber; i++) {
for (j = 0U; j < 8; j++) {
TRDC_MbcSetMemoryAccessConfig(TRDC1, &memAccessConfig, i, j);
}
}
TRDC_GetHardwareConfig(TRDC2, &hwConfig);
for (i = 0U; i < hwConfig.mrcNumber; i++) {
for (j = 0U; j < 8; j++) {
TRDC_MrcSetMemoryAccessConfig(TRDC2, &memAccessConfig, i, j);
}
}
for (i = 0U; i < hwConfig.mbcNumber; i++) {
for (j = 0U; j < 8; j++) {
TRDC_MbcSetMemoryAccessConfig(TRDC2, &memAccessConfig, i, j);
}
}
}
/**
*
* @brief Perform basic hardware initialization
*
* Initialize the interrupt controller device drivers.
* Also initialize the timer device driver, if required.
* If dual core operation is enabled, the second core image will be loaded to RAM
*
* @return 0
*/
void soc_early_init_hook(void)
{
/* Initialize system clock */
clock_init();
/* Get trdc and enable all access modes for MBC and MRC of TRDCA and TRDCW */
trdc_enable_all_access();
/* Enable data cache */
#if defined(CONFIG_IMXRT118X_CM33_XCACHE_PS)
XCACHE_EnableCache(XCACHE_PS);
#elif defined(CONFIG_SOC_MIMXRT1189_CM7)
sys_cache_data_enable();
#endif
__ISB();
__DSB();
}
#ifdef CONFIG_SOC_RESET_HOOK
void soc_reset_hook(void)
{
SystemInit();
}
#endif