1 /*
2  * Copyright (c) 2021, Laird Connectivity
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 M7 core to specific RDC domain 1 */
21 	rdc_domain_assignment_t assignment = {0};
22 	uint8_t domainId                   = 0U;
23 
24 	domainId = RDC_GetCurrentMasterDomainId(RDC);
25 	/* Only configure the RDC if RDC peripheral write access allowed. */
26 	if ((0x1U & RDC_GetPeriphAccessPolicy(RDC, kRDC_Periph_RDC, domainId)) != 0U) {
27 		assignment.domainId = M7_DOMAIN_ID;
28 		RDC_SetMasterDomainAssignment(RDC, kRDC_Master_M7, &assignment);
29 	}
30 
31 	/*
32 	 * The M7 core is running at domain 1, now enable the clock gate of the following IP/BUS/PLL
33 	 * in domain 1 in the CCM. In this way, to ensure the clock of the peripherals used by M
34 	 * core not be affected by A core which is running at domain 0.
35 	 */
36 	CLOCK_EnableClock(kCLOCK_Iomux);
37 
38 	CLOCK_EnableClock(kCLOCK_Ipmux1);
39 	CLOCK_EnableClock(kCLOCK_Ipmux2);
40 	CLOCK_EnableClock(kCLOCK_Ipmux3);
41 
42 #if defined(FLASH_TARGET)
43 	CLOCK_EnableClock(kCLOCK_Qspi);
44 #endif
45 
46 	/* Enable the CCGR gate for SysPLL1 in Domain 1 */
47 	CLOCK_ControlGate(kCLOCK_SysPll1Gate, kCLOCK_ClockNeededAll);
48 	/* Enable the CCGR gate for SysPLL2 in Domain 1 */
49 	CLOCK_ControlGate(kCLOCK_SysPll2Gate, kCLOCK_ClockNeededAll);
50 	/* Enable the CCGR gate for SysPLL3 in Domain 1 */
51 	CLOCK_ControlGate(kCLOCK_SysPll3Gate, kCLOCK_ClockNeededAll);
52 #ifdef CONFIG_INIT_VIDEO_PLL
53 	/* Enable the CCGR gate for VideoPLL1 in Domain 1 */
54 	CLOCK_ControlGate(kCLOCK_VideoPll1Gate, kCLOCK_ClockNeededAll);
55 #endif
56 }
57 
58 /* Integer PLLs: Fout = (mainDiv * refSel) / (preDiv * 2^ postDiv) */
59 /* SYSTEM PLL1 configuration */
60 const ccm_analog_integer_pll_config_t g_sysPll1Config = {
61 	.refSel  = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */
62 	.mainDiv = 400U,
63 	.preDiv  = 3U,
64 	.postDiv = 2U, /*!< SYSTEM PLL1 frequency  = 800MHZ */
65 };
66 
67 /* SYSTEM PLL2 configuration */
68 const ccm_analog_integer_pll_config_t g_sysPll2Config = {
69 	.refSel  = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */
70 	.mainDiv = 250U,
71 	.preDiv  = 3U,
72 	.postDiv = 1U, /*!< SYSTEM PLL2 frequency  = 1000MHZ */
73 };
74 
75 /* SYSTEM PLL3 configuration */
76 const ccm_analog_integer_pll_config_t g_sysPll3Config = {
77 	.refSel  = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */
78 	.mainDiv = 300,
79 	.preDiv  = 3U,
80 	.postDiv = 2U, /*!< SYSTEM PLL3 frequency  = 600MHZ */
81 };
82 
SOC_ClockInit(void)83 static void SOC_ClockInit(void)
84 {
85 	/*
86 	 * The following steps just show how to configure the PLL clock sources using the clock
87 	 * driver on M7 core side . Please note that the ROM has already configured the SYSTEM PLL1
88 	 * to 800Mhz when power up the SOC, meanwhile A core would enable SYSTEM PLL1, SYSTEM PLL2
89 	 * and SYSTEM PLL3 by U-Boot. Therefore, there is no need to configure the system PLL again
90 	 * on M7 side, otherwise it would have a risk to make the SOC hang.
91 	 */
92 
93 	/* switch AHB NOC root to 24M first in order to configure the SYSTEM PLL1. */
94 	CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxOsc24M);
95 
96 	/* switch AXI M7 root to 24M first in order to configure the SYSTEM PLL2. */
97 	CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxOsc24M);
98 
99 	/* Set root clock to 800M */
100 	CLOCK_SetRootDivider(kCLOCK_RootM7, 1U, 1U);
101 	/* switch cortex-m7 to SYSTEM PLL1 */
102 	CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxSysPll1);
103 
104 	/* Set root clock freq to 133M / 1= 133MHZ */
105 	CLOCK_SetRootDivider(kCLOCK_RootAhb, 1U, 1U);
106 	/* switch AHB to SYSTEM PLL1 DIV6 */
107 	CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxSysPll1Div6);
108 
109 #if defined(CONFIG_UART_MCUX_IUART)
110 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1))
111 	/* Set UART source to SysPLL1 Div10 80MHZ */
112 	CLOCK_SetRootMux(kCLOCK_RootUart1, kCLOCK_UartRootmuxSysPll1Div10);
113 	/* Set root clock to 80MHZ/ 1= 80MHZ */
114 	CLOCK_SetRootDivider(kCLOCK_RootUart1, 1U, 1U);
115 #endif
116 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2))
117 	/* Set UART source to SysPLL1 Div10 80MHZ */
118 	CLOCK_SetRootMux(kCLOCK_RootUart2, kCLOCK_UartRootmuxSysPll1Div10);
119 	/* Set root clock to 80MHZ/ 1= 80MHZ */
120 	CLOCK_SetRootDivider(kCLOCK_RootUart2, 1U, 1U);
121 #endif
122 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3))
123 	/* Set UART source to SysPLL1 Div10 80MHZ */
124 	CLOCK_SetRootMux(kCLOCK_RootUart3, kCLOCK_UartRootmuxSysPll1Div10);
125 	/* Set root clock to 80MHZ/ 1= 80MHZ */
126 	CLOCK_SetRootDivider(kCLOCK_RootUart3, 1U, 1U);
127 #endif
128 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4))
129 	/* Set UART source to SysPLL1 Div10 80MHZ */
130 	CLOCK_SetRootMux(kCLOCK_RootUart4, kCLOCK_UartRootmuxSysPll1Div10);
131 	/* Set root clock to 80MHZ/ 1= 80MHZ */
132 	CLOCK_SetRootDivider(kCLOCK_RootUart4, 1U, 1U);
133 #endif
134 #endif
135 
136 #if defined(CONFIG_SPI_MCUX_ECSPI)
137 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ecspi1))
138 	/* Set ECSPI1 source to SYSTEM PLL1 800MHZ */
139 	CLOCK_SetRootMux(kCLOCK_RootEcspi1, kCLOCK_EcspiRootmuxSysPll1);
140 	/* Set root clock to 800MHZ / 10 = 80MHZ */
141 	CLOCK_SetRootDivider(kCLOCK_RootEcspi1, 2U, 5U);
142 #endif
143 
144 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ecspi2))
145 	/* Set ECSPI2 source to SYSTEM PLL1 800MHZ */
146 	CLOCK_SetRootMux(kCLOCK_RootEcspi2, kCLOCK_EcspiRootmuxSysPll1);
147 	/* Set root clock to 800MHZ / 10 = 80MHZ */
148 	CLOCK_SetRootDivider(kCLOCK_RootEcspi2, 2U, 5U);
149 #endif
150 
151 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ecspi3))
152 	/* Set ECSPI3 source to SYSTEM PLL1 800MHZ */
153 	CLOCK_SetRootMux(kCLOCK_RootEcspi3, kCLOCK_EcspiRootmuxSysPll1);
154 	/* Set root clock to 800MHZ / 10 = 80MHZ */
155 	CLOCK_SetRootDivider(kCLOCK_RootEcspi3, 2U, 5U);
156 #endif
157 #endif
158 
159 	CLOCK_EnableClock(kCLOCK_Rdc);   /* Enable RDC clock */
160 	CLOCK_EnableClock(kCLOCK_Ocram); /* Enable Ocram clock */
161 
162 	/* The purpose to enable the following modules clock is to make sure the M7 core could work
163 	 * normally when A53 core enters the low power status.
164 	 */
165 	CLOCK_EnableClock(kCLOCK_Sim_m);
166 	CLOCK_EnableClock(kCLOCK_Sim_main);
167 	CLOCK_EnableClock(kCLOCK_Sim_s);
168 	CLOCK_EnableClock(kCLOCK_Sim_wakeup);
169 	CLOCK_EnableClock(kCLOCK_Debug);
170 	CLOCK_EnableClock(kCLOCK_Dram);
171 	CLOCK_EnableClock(kCLOCK_Sec_Debug);
172 }
173 
gpio_init(void)174 static void gpio_init(void)
175 {
176 
177 #if defined(CONFIG_GPIO_MCUX_IGPIO)
178 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio1))
179 
180 	CLOCK_EnableClock(kCLOCK_Gpio1);
181 
182 #endif
183 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio2))
184 
185 	CLOCK_EnableClock(kCLOCK_Gpio2);
186 
187 #endif
188 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio3))
189 
190 	CLOCK_EnableClock(kCLOCK_Gpio3);
191 
192 #endif
193 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio4))
194 
195 	CLOCK_EnableClock(kCLOCK_Gpio4);
196 
197 #endif
198 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio5))
199 
200 	CLOCK_EnableClock(kCLOCK_Gpio5);
201 
202 #endif
203 #endif
204 }
205 
soc_early_init_hook(void)206 void soc_early_init_hook(void)
207 {
208 
209 	/* SoC specific RDC settings */
210 	SOC_RdcInit();
211 
212 	/* SoC specific Clock settings */
213 	SOC_ClockInit();
214 
215 	gpio_init();
216 }
217