1 /*
2  * Copyright (c) 2021, Kwon Tae-young <tykwon@m2i.co.kr>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/device.h>
8 #include <fsl_clock.h>
9 #include <fsl_common.h>
10 #include <fsl_rdc.h>
11 #include <zephyr/init.h>
12 #include <zephyr/kernel.h>
13 #include <soc.h>
14 
15 #include <zephyr/dt-bindings/rdc/imx_rdc.h>
16 
17 /* OSC/PLL is already initialized by ROM and Cortex-A53 (u-boot) */
SOC_RdcInit(void)18 static void SOC_RdcInit(void)
19 {
20 	/* Move M4 core to specific RDC domain 1 */
21 	rdc_domain_assignment_t assignment = {0};
22 
23 	assignment.domainId = M4_DOMAIN_ID;
24 	RDC_SetMasterDomainAssignment(RDC, kRDC_Master_M4, &assignment);
25 
26 	/*
27 	 * The M4 core is running at domain 1, enable clock gate for
28 	 * Iomux to run at domain 1.
29 	 */
30 	CLOCK_EnableClock(kCLOCK_Iomux);
31 	CLOCK_EnableClock(kCLOCK_Ipmux1);
32 	CLOCK_EnableClock(kCLOCK_Ipmux2);
33 	CLOCK_EnableClock(kCLOCK_Ipmux3);
34 	CLOCK_EnableClock(kCLOCK_Ipmux4);
35 
36 	/*
37 	 * The M4 core is running at domain 1, enable the PLL clock sources
38 	 * to domain 1.
39 	 */
40 	CLOCK_ControlGate(kCLOCK_SysPll1Gate, kCLOCK_ClockNeededAll);
41 	CLOCK_ControlGate(kCLOCK_SysPll2Gate, kCLOCK_ClockNeededAll);
42 	CLOCK_ControlGate(kCLOCK_SysPll3Gate, kCLOCK_ClockNeededAll);
43 	CLOCK_ControlGate(kCLOCK_AudioPll1Gate, kCLOCK_ClockNeededAll);
44 	CLOCK_ControlGate(kCLOCK_AudioPll2Gate, kCLOCK_ClockNeededAll);
45 	CLOCK_ControlGate(kCLOCK_VideoPll1Gate, kCLOCK_ClockNeededAll);
46 	CLOCK_ControlGate(kCLOCK_VideoPll2Gate, kCLOCK_ClockNeededAll);
47 }
48 
SOC_ClockInit(void)49 static void SOC_ClockInit(void)
50 {
51 	/*
52 	 * Switch AHB NOC root to 25M first in order to configure
53 	 * the SYSTEM PLL1
54 	 */
55 	CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxOsc25m);
56 	CLOCK_SetRootDivider(kCLOCK_RootAhb, 1U, 1U);
57 	/* Switch AHB to SYSTEM PLL1 DIV6 = 133MHZ */
58 	CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxSysPll1Div6);
59 
60 	/*
61 	 * Switch AXI M4 root to 25M first in order to configure
62 	 * the SYSTEM PLL1
63 	 */
64 	CLOCK_SetRootMux(kCLOCK_RootM4, kCLOCK_M4RootmuxOsc25m);
65 	CLOCK_SetRootDivider(kCLOCK_RootM4, 1U, 1U);
66 	/* Switch cortex-m4 to SYSTEM PLL1 DIV3 */
67 	CLOCK_SetRootMux(kCLOCK_RootM4, kCLOCK_M4RootmuxSysPll1Div3);
68 
69 #if defined(CONFIG_UART_MCUX_IUART)
70 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1))
71 	/* Set UART source to SysPLL1 Div10 80MHZ */
72 	CLOCK_SetRootMux(kCLOCK_RootUart1, kCLOCK_UartRootmuxSysPll1Div10);
73 	/* Set root clock to 80MHZ/ 1= 80MHZ */
74 	CLOCK_SetRootDivider(kCLOCK_RootUart1, 1U, 1U);
75 #endif
76 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2))
77 	/* Set UART source to SysPLL1 Div10 80MHZ */
78 	CLOCK_SetRootMux(kCLOCK_RootUart2, kCLOCK_UartRootmuxSysPll1Div10);
79 	/* Set root clock to 80MHZ/ 1= 80MHZ */
80 	CLOCK_SetRootDivider(kCLOCK_RootUart2, 1U, 1U);
81 #endif
82 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3))
83 	/* Set UART source to SysPLL1 Div10 80MHZ */
84 	CLOCK_SetRootMux(kCLOCK_RootUart3, kCLOCK_UartRootmuxSysPll1Div10);
85 	/* Set root clock to 80MHZ/ 1= 80MHZ */
86 	CLOCK_SetRootDivider(kCLOCK_RootUart3, 1U, 1U);
87 #endif
88 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4))
89 	/* Set UART source to SysPLL1 Div10 80MHZ */
90 	CLOCK_SetRootMux(kCLOCK_RootUart4, kCLOCK_UartRootmuxSysPll1Div10);
91 	/* Set root clock to 80MHZ/ 1= 80MHZ */
92 	CLOCK_SetRootDivider(kCLOCK_RootUart4, 1U, 1U);
93 #endif
94 #endif
95 
96 	/* Enable RDC clock */
97 	CLOCK_EnableClock(kCLOCK_Rdc);
98 
99 	/*
100 	 * The purpose to enable the following modules clock is to make
101 	 * sure the M4 core could work normally when A53 core
102 	 * enters the low power state
103 	 */
104 	CLOCK_EnableClock(kCLOCK_Sim_display);
105 	CLOCK_EnableClock(kCLOCK_Sim_m);
106 	CLOCK_EnableClock(kCLOCK_Sim_main);
107 	CLOCK_EnableClock(kCLOCK_Sim_s);
108 	CLOCK_EnableClock(kCLOCK_Sim_wakeup);
109 	CLOCK_EnableClock(kCLOCK_Debug);
110 	CLOCK_EnableClock(kCLOCK_Dram);
111 	CLOCK_EnableClock(kCLOCK_Sec_Debug);
112 }
113 
soc_early_init_hook(void)114 void soc_early_init_hook(void)
115 {
116 
117 	/* SoC specific RDC settings */
118 	SOC_RdcInit();
119 
120 	/* SoC specific Clock settings */
121 	SOC_ClockInit();
122 }
123