| /* |
| * Copyright (c) 2021, Laird Connectivity |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <device.h> |
| #include <fsl_clock.h> |
| #include <fsl_common.h> |
| #include <fsl_rdc.h> |
| #include <init.h> |
| #include <kernel.h> |
| #include <soc.h> |
| |
| #include <dt-bindings/rdc/imx_rdc.h> |
| |
| /* OSC/PLL is already initialized by ROM and Cortex-A53 (u-boot) */ |
| static void SOC_RdcInit(void) |
| { |
| /* Move M7 core to specific RDC domain 1 */ |
| rdc_domain_assignment_t assignment = {0}; |
| uint8_t domainId = 0U; |
| |
| domainId = RDC_GetCurrentMasterDomainId(RDC); |
| /* Only configure the RDC if RDC peripheral write access allowed. */ |
| if ((0x1U & RDC_GetPeriphAccessPolicy(RDC, kRDC_Periph_RDC, domainId)) != 0U) { |
| assignment.domainId = M7_DOMAIN_ID; |
| RDC_SetMasterDomainAssignment(RDC, kRDC_Master_M7, &assignment); |
| } |
| |
| /* |
| * The M7 core is running at domain 1, now enable the clock gate of the following IP/BUS/PLL |
| * in domain 1 in the CCM. In this way, to ensure the clock of the peripherals used by M |
| * core not be affected by A core which is running at domain 0. |
| */ |
| CLOCK_EnableClock(kCLOCK_Iomux); |
| |
| CLOCK_EnableClock(kCLOCK_Ipmux1); |
| CLOCK_EnableClock(kCLOCK_Ipmux2); |
| CLOCK_EnableClock(kCLOCK_Ipmux3); |
| |
| #if defined(FLASH_TARGET) |
| CLOCK_EnableClock(kCLOCK_Qspi); |
| #endif |
| |
| /* Enable the CCGR gate for SysPLL1 in Domain 1 */ |
| CLOCK_ControlGate(kCLOCK_SysPll1Gate, kCLOCK_ClockNeededAll); |
| /* Enable the CCGR gate for SysPLL2 in Domain 1 */ |
| CLOCK_ControlGate(kCLOCK_SysPll2Gate, kCLOCK_ClockNeededAll); |
| /* Enable the CCGR gate for SysPLL3 in Domain 1 */ |
| CLOCK_ControlGate(kCLOCK_SysPll3Gate, kCLOCK_ClockNeededAll); |
| #ifdef CONFIG_INIT_VIDEO_PLL |
| /* Enable the CCGR gate for VideoPLL1 in Domain 1 */ |
| CLOCK_ControlGate(kCLOCK_VideoPll1Gate, kCLOCK_ClockNeededAll); |
| #endif |
| } |
| |
| /* Integer PLLs: Fout = (mainDiv * refSel) / (preDiv * 2^ postDiv) */ |
| /* SYSTEM PLL1 configuration */ |
| const ccm_analog_integer_pll_config_t g_sysPll1Config = { |
| .refSel = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */ |
| .mainDiv = 400U, |
| .preDiv = 3U, |
| .postDiv = 2U, /*!< SYSTEM PLL1 frequency = 800MHZ */ |
| }; |
| |
| /* SYSTEM PLL2 configuration */ |
| const ccm_analog_integer_pll_config_t g_sysPll2Config = { |
| .refSel = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */ |
| .mainDiv = 250U, |
| .preDiv = 3U, |
| .postDiv = 1U, /*!< SYSTEM PLL2 frequency = 1000MHZ */ |
| }; |
| |
| /* SYSTEM PLL3 configuration */ |
| const ccm_analog_integer_pll_config_t g_sysPll3Config = { |
| .refSel = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */ |
| .mainDiv = 300, |
| .preDiv = 3U, |
| .postDiv = 2U, /*!< SYSTEM PLL3 frequency = 600MHZ */ |
| }; |
| |
| static void SOC_ClockInit(void) |
| { |
| /* |
| * The following steps just show how to configure the PLL clock sources using the clock |
| * driver on M7 core side . Please note that the ROM has already configured the SYSTEM PLL1 |
| * to 800Mhz when power up the SOC, meanwhile A core would enable SYSTEM PLL1, SYSTEM PLL2 |
| * and SYSTEM PLL3 by U-Boot. Therefore, there is no need to configure the system PLL again |
| * on M7 side, otherwise it would have a risk to make the SOC hang. |
| */ |
| |
| /* switch AHB NOC root to 24M first in order to configure the SYSTEM PLL1. */ |
| CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxOsc24M); |
| |
| /* switch AXI M7 root to 24M first in order to configure the SYSTEM PLL2. */ |
| CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxOsc24M); |
| |
| /* Set root clock to 800M */ |
| CLOCK_SetRootDivider(kCLOCK_RootM7, 1U, 1U); |
| /* switch cortex-m7 to SYSTEM PLL1 */ |
| CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxSysPll1); |
| |
| /* Set root clock freq to 133M / 1= 133MHZ */ |
| CLOCK_SetRootDivider(kCLOCK_RootAhb, 1U, 1U); |
| /* switch AHB to SYSTEM PLL1 DIV6 */ |
| CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxSysPll1Div6); |
| |
| #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart4), okay) && CONFIG_UART_MCUX_IUART |
| /* Set UART source to SysPLL1 Div10 80MHZ */ |
| CLOCK_SetRootMux(kCLOCK_RootUart4, kCLOCK_UartRootmuxSysPll1Div10); |
| /* Set root clock to 80MHZ/ 1= 80MHZ */ |
| CLOCK_SetRootDivider(kCLOCK_RootUart4, 1U, 1U); |
| #endif |
| |
| CLOCK_EnableClock(kCLOCK_Rdc); /* Enable RDC clock */ |
| CLOCK_EnableClock(kCLOCK_Ocram); /* Enable Ocram clock */ |
| |
| /* The purpose to enable the following modules clock is to make sure the M7 core could work |
| * normally when A53 core enters the low power status. |
| */ |
| CLOCK_EnableClock(kCLOCK_Sim_m); |
| CLOCK_EnableClock(kCLOCK_Sim_main); |
| CLOCK_EnableClock(kCLOCK_Sim_s); |
| CLOCK_EnableClock(kCLOCK_Sim_wakeup); |
| CLOCK_EnableClock(kCLOCK_Debug); |
| CLOCK_EnableClock(kCLOCK_Dram); |
| CLOCK_EnableClock(kCLOCK_Sec_Debug); |
| |
| #if DT_NODE_HAS_STATUS(DT_NODELABEL(uart4), okay) && CONFIG_UART_MCUX_IUART |
| CLOCK_EnableClock(kCLOCK_Uart4); |
| #endif |
| } |
| |
| static int nxp_mimx8ml8_init(const struct device *arg) |
| { |
| ARG_UNUSED(arg); |
| |
| /* SoC specific RDC settings */ |
| SOC_RdcInit(); |
| |
| /* SoC specific Clock settings */ |
| SOC_ClockInit(); |
| |
| return 0; |
| } |
| |
| SYS_INIT(nxp_mimx8ml8_init, PRE_KERNEL_1, 0); |