1 /*
2  * Copyright (c) 2021, NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/init.h>
10 #include <soc.h>
11 #include <zephyr/linker/sections.h>
12 #include <zephyr/linker/linker-defs.h>
13 #include <fsl_clock.h>
14 #include <fsl_gpc.h>
15 #include <fsl_pmu.h>
16 #include <fsl_dcdc.h>
17 #include <zephyr/arch/cpu.h>
18 #include <zephyr/arch/arm/aarch32/cortex_m/cmsis.h>
19 #ifdef CONFIG_NXP_IMX_RT_BOOT_HEADER
20 #include <fsl_flexspi_nor_boot.h>
21 #endif
22 #include <zephyr/dt-bindings/clock/imx_ccm_rev2.h>
23 #if  defined(CONFIG_SECOND_CORE_MCUX) && defined(CONFIG_CPU_CORTEX_M7)
24 #include <zephyr_image_info.h>
25 /* Memcpy macro to copy segments from secondary core image stored in flash
26  * to RAM section that secondary core boots from.
27  * n is the segment number, as defined in zephyr_image_info.h
28  */
29 #define MEMCPY_SEGMENT(n, _)							\
30 	memcpy((uint32_t *)((SEGMENT_LMA_ADDRESS_ ## n) - ADJUSTED_LMA),	\
31 		(uint32_t *)(SEGMENT_LMA_ADDRESS_ ## n),			\
32 		(SEGMENT_SIZE_ ## n))
33 #endif
34 #if CONFIG_USB_DC_NXP_EHCI
35 #include "usb_phy.h"
36 #include "usb.h"
37 #endif
38 
39 #define DUAL_CORE_MU_ENABLED \
40 	(CONFIG_SECOND_CORE_MCUX && CONFIG_IPM && CONFIG_IPM_IMX_REV2)
41 
42 #if DUAL_CORE_MU_ENABLED
43 /* Dual core mode is enabled, and messaging unit is present */
44 #include <fsl_mu.h>
45 #define BOOT_FLAG 0x1U
46 #define MU_BASE (MU_Type *)DT_REG_ADDR(DT_INST(0, nxp_imx_mu_rev2))
47 #endif
48 
49 #if CONFIG_USB_DC_NXP_EHCI /* USB PHY configuration */
50 #define BOARD_USB_PHY_D_CAL (0x07U)
51 #define BOARD_USB_PHY_TXCAL45DP (0x06U)
52 #define BOARD_USB_PHY_TXCAL45DM (0x06U)
53 #endif
54 
55 #ifdef CONFIG_INIT_ARM_PLL
56 static const clock_arm_pll_config_t armPllConfig = {
57 #if defined(CONFIG_SOC_MIMXRT1176_CM4) || defined(CONFIG_SOC_MIMXRT1176_CM7)
58 	/* resulting frequency: 24 * (166/(2* 2)) = 984MHz */
59 	/* Post divider, 0 - DIV by 2, 1 - DIV by 4, 2 - DIV by 8, 3 - DIV by 1 */
60 	.postDivider = kCLOCK_PllPostDiv2,
61 	/* PLL Loop divider, Fout = Fin * ( loopDivider / ( 2 * postDivider ) ) */
62 	.loopDivider = 166,
63 #elif defined(CONFIG_SOC_MIMXRT1166_CM4) || defined(CONFIG_SOC_MIMXRT1166_CM7)
64 	/* resulting frequency: 24 * (200/(2 * 4)) = 600MHz */
65 	/* Post divider, 0 - DIV by 2, 1 - DIV by 4, 2 - DIV by 8, 3 - DIV by 1 */
66 	.postDivider = kCLOCK_PllPostDiv4,
67 	/* PLL Loop divider, Fout = Fin * ( loopDivider / ( 2 * postDivider ) ) */
68 	.loopDivider = 200,
69 #else
70 	#error "Unknown SOC, no pll configuration defined"
71 #endif
72 };
73 #endif
74 
75 static const clock_sys_pll2_config_t sysPll2Config = {
76 	/* Denominator of spread spectrum */
77 	.mfd = 268435455,
78 	/* Spread spectrum parameter */
79 	.ss = NULL,
80 	/* Enable spread spectrum or not */
81 	.ssEnable = false,
82 };
83 
84 #ifdef CONFIG_INIT_ENET_PLL
85 static const clock_sys_pll1_config_t sysPll1Config = {
86 	.pllDiv2En = true,
87 };
88 #endif
89 
90 #ifdef CONFIG_INIT_VIDEO_PLL
91 static const clock_video_pll_config_t videoPllConfig = {
92 	/* PLL Loop divider, valid range for DIV_SELECT divider value: 27 ~ 54. */
93 	.loopDivider = 41,
94 	/* Divider after PLL, should only be 1, 2, 4, 8, 16, 32 */
95 	.postDivider = 0,
96 	/*
97 	 * 30 bit numerator of fractional loop divider,
98 	 * Fout = Fin * ( loopDivider + numerator / denominator )
99 	 */
100 	.numerator = 1,
101 	/*
102 	 * 30 bit denominator of fractional loop divider,
103 	 * Fout = Fin * ( loopDivider + numerator / denominator )
104 	 */
105 	.denominator = 960000,
106 	/* Spread spectrum parameter */
107 	.ss = NULL,
108 	/* Enable spread spectrum or not */
109 	.ssEnable = false,
110 };
111 #endif
112 
113 #if CONFIG_USB_DC_NXP_EHCI
114 	usb_phy_config_struct_t usbPhyConfig = {
115 		BOARD_USB_PHY_D_CAL,
116 		BOARD_USB_PHY_TXCAL45DP,
117 		BOARD_USB_PHY_TXCAL45DM,
118 	};
119 #endif
120 
121 #ifdef CONFIG_NXP_IMX_RT_BOOT_HEADER
122 const __imx_boot_data_section BOOT_DATA_T boot_data = {
123 	.start = CONFIG_FLASH_BASE_ADDRESS,
124 	.size = KB(CONFIG_FLASH_SIZE),
125 	.plugin = PLUGIN_FLAG,
126 	.placeholder = 0xFFFFFFFF,
127 };
128 
129 extern char __start[];
130 const __imx_boot_ivt_section ivt image_vector_table = {
131 	.hdr = IVT_HEADER,
132 	.entry = (uint32_t) __start,
133 	.reserved1 = IVT_RSVD,
134 #ifdef CONFIG_DEVICE_CONFIGURATION_DATA
135 	.dcd = (uint32_t) dcd_data,
136 #else
137 	.dcd = (uint32_t) NULL,
138 #endif
139 	.boot_data = (uint32_t) &boot_data,
140 	.self = (uint32_t) &image_vector_table,
141 	.csf = (uint32_t)CSF_ADDRESS,
142 	.reserved2 = IVT_RSVD,
143 };
144 #endif
145 
146 /**
147  * @brief Initialize the system clock
148  */
clock_init(void)149 static ALWAYS_INLINE void clock_init(void)
150 {
151 	clock_root_config_t rootCfg = {0};
152 
153 #if CONFIG_ADJUST_DCDC
154 	DCDC_SetVDD1P0BuckModeTargetVoltage(DCDC, kDCDC_1P0BuckTarget1P15V);
155 #endif
156 
157 /* RT1160 does not have Forward Body Biasing on the CM7 core */
158 #if defined(CONFIG_SOC_MIMXRT1176_CM4) || defined(CONFIG_SOC_MIMXRT1176_CM7)
159 	/* Check if FBB need to be enabled in OverDrive(OD) mode */
160 	if (((OCOTP->FUSEN[7].FUSE & 0x10U) >> 4U) != 1) {
161 		PMU_EnableBodyBias(ANADIG_PMU, kPMU_FBB_CM7, true);
162 	} else {
163 		PMU_EnableBodyBias(ANADIG_PMU, kPMU_FBB_CM7, false);
164 	}
165 #endif
166 
167 #if CONFIG_BYPASS_LDO_LPSR
168 	PMU_StaticEnableLpsrAnaLdoBypassMode(ANADIG_LDO_SNVS, true);
169 	PMU_StaticEnableLpsrDigLdoBypassMode(ANADIG_LDO_SNVS, true);
170 #endif
171 
172 #if CONFIG_ADJUST_LDO
173 	pmu_static_lpsr_ana_ldo_config_t lpsrAnaConfig;
174 	pmu_static_lpsr_dig_config_t lpsrDigConfig;
175 
176 	if ((ANADIG_LDO_SNVS->PMU_LDO_LPSR_ANA &
177 		ANADIG_LDO_SNVS_PMU_LDO_LPSR_ANA_BYPASS_MODE_EN_MASK) == 0UL) {
178 		PMU_StaticGetLpsrAnaLdoDefaultConfig(&lpsrAnaConfig);
179 		PMU_StaticLpsrAnaLdoInit(ANADIG_LDO_SNVS, &lpsrAnaConfig);
180 	}
181 
182 	if ((ANADIG_LDO_SNVS->PMU_LDO_LPSR_DIG &
183 		ANADIG_LDO_SNVS_PMU_LDO_LPSR_DIG_BYPASS_MODE_MASK) == 0UL) {
184 		PMU_StaticGetLpsrDigLdoDefaultConfig(&lpsrDigConfig);
185 		lpsrDigConfig.targetVoltage = kPMU_LpsrDigTargetStableVoltage1P117V;
186 		PMU_StaticLpsrDigLdoInit(ANADIG_LDO_SNVS, &lpsrDigConfig);
187 	}
188 #endif
189 
190 	/* PLL LDO shall be enabled first before enable PLLs */
191 
192 	/* Config CLK_1M */
193 	CLOCK_OSC_Set1MHzOutputBehavior(kCLOCK_1MHzOutEnableFreeRunning1Mhz);
194 
195 	/* Init OSC RC 16M */
196 	ANADIG_OSC->OSC_16M_CTRL |= ANADIG_OSC_OSC_16M_CTRL_EN_IRC4M16M_MASK;
197 
198 	/* Init OSC RC 400M */
199 	CLOCK_OSC_EnableOscRc400M();
200 	CLOCK_OSC_GateOscRc400M(true);
201 
202 	/* Init OSC RC 48M */
203 	CLOCK_OSC_EnableOsc48M(true);
204 	CLOCK_OSC_EnableOsc48MDiv2(true);
205 
206 	/* Config OSC 24M */
207 	ANADIG_OSC->OSC_24M_CTRL |= ANADIG_OSC_OSC_24M_CTRL_OSC_EN(1) |
208 				    ANADIG_OSC_OSC_24M_CTRL_BYPASS_EN(0) |
209 				    ANADIG_OSC_OSC_24M_CTRL_BYPASS_CLK(0) |
210 				    ANADIG_OSC_OSC_24M_CTRL_LP_EN(1) |
211 				    ANADIG_OSC_OSC_24M_CTRL_OSC_24M_GATE(0);
212 
213 	/* Wait for 24M OSC to be stable. */
214 	while (ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK !=
215 		(ANADIG_OSC->OSC_24M_CTRL & ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK)) {
216 	}
217 
218 	rootCfg.div = 1;
219 
220 #ifdef CONFIG_CPU_CORTEX_M7
221 	/* Switch both core, M7 Systick and Bus_Lpsr to OscRC48MDiv2 first */
222 	rootCfg.mux = kCLOCK_M7_ClockRoot_MuxOscRc48MDiv2;
223 	rootCfg.div = 1;
224 	CLOCK_SetRootClock(kCLOCK_Root_M7, &rootCfg);
225 
226 	rootCfg.mux = kCLOCK_M7_SYSTICK_ClockRoot_MuxOscRc48MDiv2;
227 	rootCfg.div = 1;
228 	CLOCK_SetRootClock(kCLOCK_Root_M7_Systick, &rootCfg);
229 #endif
230 
231 #if CONFIG_CPU_CORTEX_M4
232 	rootCfg.mux = kCLOCK_M4_ClockRoot_MuxOscRc48MDiv2;
233 	rootCfg.div = 1;
234 	CLOCK_SetRootClock(kCLOCK_Root_M4, &rootCfg);
235 
236 	rootCfg.mux = kCLOCK_BUS_LPSR_ClockRoot_MuxOscRc48MDiv2;
237 	rootCfg.div = 1;
238 	CLOCK_SetRootClock(kCLOCK_Root_Bus_Lpsr, &rootCfg);
239 #endif
240 
241 	/*
242 	 * If DCD is used, please make sure the clock source of SEMC is not
243 	 * changed in the following PLL/PFD configuration code.
244 	 */
245 
246 #ifdef CONFIG_INIT_ARM_PLL
247 	/* Init Arm Pll. */
248 	CLOCK_InitArmPll(&armPllConfig);
249 #endif
250 
251 #ifdef CONFIG_INIT_ENET_PLL
252 	CLOCK_InitSysPll1(&sysPll1Config);
253 #else
254 	/* Bypass Sys Pll1. */
255 	CLOCK_SetPllBypass(kCLOCK_PllSys1, true);
256 
257 	/* DeInit Sys Pll1. */
258 	CLOCK_DeinitSysPll1();
259 #endif
260 
261 	/* Init Sys Pll2. */
262 	CLOCK_InitSysPll2(&sysPll2Config);
263 
264 	/* Init System Pll2 pfd0. */
265 	CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd0, 27);
266 
267 	/* Init System Pll2 pfd1. */
268 	CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd1, 16);
269 
270 	/* Init System Pll2 pfd2. */
271 	CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd2, 24);
272 
273 	/* Init System Pll2 pfd3. */
274 #ifdef CONFIG_ETH_MCUX
275 	CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd3, 24);
276 #else
277 	CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd3, 32);
278 #endif
279 
280 	/* Init Sys Pll3. */
281 	CLOCK_InitSysPll3();
282 
283 	/* Init System Pll3 pfd0. */
284 	CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd0, 13);
285 
286 	/* Init System Pll3 pfd1. */
287 	CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd1, 17);
288 
289 	/* Init System Pll3 pfd2. */
290 	CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd2, 32);
291 
292 	/* Init System Pll3 pfd3. */
293 	CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd3, 22);
294 
295 #ifdef CONFIG_INIT_VIDEO_PLL
296 	/* Init Video Pll. */
297 	CLOCK_InitVideoPll(&videoPllConfig);
298 #endif
299 
300 	/* Module clock root configurations. */
301 	/* Configure M7 using ARM_PLL_CLK */
302 #if defined(CONFIG_SOC_MIMXRT1176_CM7) || defined(CONFIG_SOC_MIMXRT1166_CM7)
303 	rootCfg.mux = kCLOCK_M7_ClockRoot_MuxArmPllOut;
304 	rootCfg.div = 1;
305 	CLOCK_SetRootClock(kCLOCK_Root_M7, &rootCfg);
306 #endif
307 
308 #if defined(CONFIG_SOC_MIMXRT1166_CM4)
309 	/* Configure M4 using SYS_PLL3_CLK */
310 	rootCfg.mux = kCLOCK_M4_ClockRoot_MuxSysPll3Out;
311 	rootCfg.div = 2;
312 	CLOCK_SetRootClock(kCLOCK_Root_M4, &rootCfg);
313 #elif defined(CONFIG_SOC_MIMXRT1176_CM4)
314 	/* Configure M4 using SYS_PLL3_CLK_PFD3_CLK */
315 	rootCfg.mux = kCLOCK_M4_ClockRoot_MuxSysPll3Pfd3;
316 	rootCfg.div = 1;
317 	CLOCK_SetRootClock(kCLOCK_Root_M4, &rootCfg);
318 #endif
319 
320 	/* Configure BUS using SYS_PLL3_CLK */
321 #ifdef CONFIG_ETH_MCUX
322 	/* Configure root bus clock at 198M */
323 	rootCfg.mux = kCLOCK_BUS_ClockRoot_MuxSysPll2Pfd3;
324 	rootCfg.div = 2;
325 	CLOCK_SetRootClock(kCLOCK_Root_Bus, &rootCfg);
326 #elif defined(CONFIG_SOC_MIMXRT1176_CM7) || defined(CONFIG_SOC_MIMXRT1166_CM7)
327 	/* Keep root bus clock at default 240M */
328 	rootCfg.mux = kCLOCK_BUS_ClockRoot_MuxSysPll3Out;
329 	rootCfg.div = 2;
330 	CLOCK_SetRootClock(kCLOCK_Root_Bus, &rootCfg);
331 #endif
332 
333 	/* Configure BUS_LPSR using SYS_PLL3_CLK */
334 #if defined(CONFIG_SOC_MIMXRT1176_CM4)
335 	rootCfg.mux = kCLOCK_BUS_LPSR_ClockRoot_MuxSysPll3Out;
336 	rootCfg.div = 3;
337 	CLOCK_SetRootClock(kCLOCK_Root_Bus_Lpsr, &rootCfg);
338 #elif defined(CONFIG_SOC_MIMXRT1166_CM4)
339 	rootCfg.mux = kCLOCK_BUS_LPSR_ClockRoot_MuxSysPll3Out;
340 	rootCfg.div = 4;
341 	CLOCK_SetRootClock(kCLOCK_Root_Bus_Lpsr, &rootCfg);
342 #endif
343 
344 	/* Configure CSSYS using OSC_RC_48M_DIV2 */
345 	rootCfg.mux = kCLOCK_CSSYS_ClockRoot_MuxOscRc48MDiv2;
346 	rootCfg.div = 1;
347 	CLOCK_SetRootClock(kCLOCK_Root_Cssys, &rootCfg);
348 
349 	/* Configure CSTRACE using SYS_PLL2_CLK */
350 	rootCfg.mux = kCLOCK_CSTRACE_ClockRoot_MuxSysPll2Out;
351 	rootCfg.div = 4;
352 	CLOCK_SetRootClock(kCLOCK_Root_Cstrace, &rootCfg);
353 
354 	/* Configure M4_SYSTICK using OSC_RC_48M_DIV2 */
355 #if defined(CONFIG_SOC_MIMXRT1176_CM4) || defined(CONFIG_SOC_MIMXRT1166_CM4)
356 	rootCfg.mux = kCLOCK_M4_SYSTICK_ClockRoot_MuxOscRc48MDiv2;
357 	rootCfg.div = 1;
358 	CLOCK_SetRootClock(kCLOCK_Root_M4_Systick, &rootCfg);
359 #endif
360 
361 	/* Configure M7_SYSTICK using OSC_RC_48M_DIV2 */
362 #if defined(CONFIG_SOC_MIMXRT1176_CM7) || defined(CONFIG_SOC_MIMXRT1166_CM7)
363 	rootCfg.mux = kCLOCK_M7_SYSTICK_ClockRoot_MuxOscRc48MDiv2;
364 	rootCfg.div = 240;
365 	CLOCK_SetRootClock(kCLOCK_Root_M7_Systick, &rootCfg);
366 #endif
367 
368 #ifdef CONFIG_UART_MCUX_LPUART
369 	/* Configure Lpuart1 using SysPll2*/
370 	rootCfg.mux = kCLOCK_LPUART1_ClockRoot_MuxSysPll2Out;
371 	rootCfg.div = 22;
372 	CLOCK_SetRootClock(kCLOCK_Root_Lpuart1, &rootCfg);
373 
374 	/* Configure Lpuart2 using SysPll2*/
375 	rootCfg.mux = kCLOCK_LPUART2_ClockRoot_MuxSysPll2Out;
376 	rootCfg.div = 22;
377 	CLOCK_SetRootClock(kCLOCK_Root_Lpuart2, &rootCfg);
378 #endif
379 
380 #ifdef CONFIG_I2C_MCUX_LPI2C
381 	/* Configure Lpi2c1 using Osc48MDiv2 */
382 	rootCfg.mux = kCLOCK_LPI2C1_ClockRoot_MuxOscRc48MDiv2;
383 	rootCfg.div = 1;
384 	CLOCK_SetRootClock(kCLOCK_Root_Lpi2c1, &rootCfg);
385 
386 	/* Configure Lpi2c5 using Osc48MDiv2 */
387 	rootCfg.mux = kCLOCK_LPI2C5_ClockRoot_MuxOscRc48MDiv2;
388 	rootCfg.div = 1;
389 	CLOCK_SetRootClock(kCLOCK_Root_Lpi2c5, &rootCfg);
390 #endif
391 
392 
393 #ifdef CONFIG_ETH_MCUX
394 #if DT_NODE_HAS_STATUS(DT_NODELABEL(enet), okay)
395 	/* 50 MHz ENET clock */
396 	rootCfg.mux = kCLOCK_ENET1_ClockRoot_MuxSysPll1Div2;
397 	rootCfg.div = 10;
398 	CLOCK_SetRootClock(kCLOCK_Root_Enet1, &rootCfg);
399 	/* Set ENET_REF_CLK as an output driven by ENET1_CLK_ROOT */
400 	IOMUXC_GPR->GPR4 |= (IOMUXC_GPR_GPR4_ENET_REF_CLK_DIR(0x01U) |
401 		IOMUXC_GPR_GPR4_ENET_TX_CLK_SEL(0x1U));
402 #endif
403 #if DT_NODE_HAS_STATUS(DT_NODELABEL(enet1g), okay)
404 	/*
405 	 * 50 MHz clock for 10/100Mbit RMII PHY -
406 	 * operate ENET1G just like ENET peripheral
407 	 */
408 	rootCfg.mux = kCLOCK_ENET2_ClockRoot_MuxSysPll1Div2;
409 	rootCfg.div = 10;
410 	CLOCK_SetRootClock(kCLOCK_Root_Enet2, &rootCfg);
411 	/* Set ENET1G_REF_CLK as an output driven by ENET2_CLK_ROOT */
412 	IOMUXC_GPR->GPR5 |= (IOMUXC_GPR_GPR5_ENET1G_REF_CLK_DIR(0x01U) |
413 		IOMUXC_GPR_GPR5_ENET1G_TX_CLK_SEL(0x1U));
414 #endif
415 #endif
416 
417 #ifdef CONFIG_PTP_CLOCK_MCUX
418 	/* 24MHz PTP clock */
419 	rootCfg.mux = kCLOCK_ENET_TIMER1_ClockRoot_MuxOscRc48MDiv2;
420 	rootCfg.div = 1;
421 	CLOCK_SetRootClock(kCLOCK_Root_Enet_Timer1, &rootCfg);
422 #endif
423 
424 #ifdef CONFIG_SPI_MCUX_LPSPI
425 	/* Configure lpspi using Osc48MDiv2 */
426 	rootCfg.mux = kCLOCK_LPSPI1_ClockRoot_MuxOscRc48MDiv2;
427 	rootCfg.div = 1;
428 	CLOCK_SetRootClock(kCLOCK_Root_Lpspi1, &rootCfg);
429 #endif
430 
431 #ifdef CONFIG_CAN_MCUX_FLEXCAN
432 #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan1), okay)
433 	/* Configure CAN1 using Osc48MDiv2 */
434 	rootCfg.mux = kCLOCK_CAN1_ClockRoot_MuxOscRc48MDiv2;
435 	rootCfg.div = 1;
436 	CLOCK_SetRootClock(kCLOCK_Root_Can1, &rootCfg);
437 #endif
438 #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan3), okay)
439 	/* Configure CAN1 using Osc48MDiv2 */
440 	rootCfg.mux = kCLOCK_CAN3_ClockRoot_MuxOscRc48MDiv2;
441 	rootCfg.div = 1;
442 	CLOCK_SetRootClock(kCLOCK_Root_Can3, &rootCfg);
443 #endif
444 #endif
445 
446 #ifdef CONFIG_MCUX_ACMP
447 #if DT_NODE_HAS_STATUS(DT_NODELABEL(acmp1), okay)
448 	/* Configure ACMP1 using Osc48MDiv2*/
449 	rootCfg.mux = kCLOCK_ACMP_ClockRoot_MuxOscRc48MDiv2;
450 	rootCfg.div = 1;
451 	CLOCK_SetRootClock(kCLOCK_Root_Acmp, &rootCfg);
452 #endif
453 #endif
454 
455 #ifdef CONFIG_DISPLAY_MCUX_ELCDIF
456 	rootCfg.mux = kCLOCK_LCDIF_ClockRoot_MuxSysPll2Out;
457 	/*
458 	 * PLL2 is fixed at 528MHz. Use desired panel clock clock to
459 	 * calculate LCDIF clock.
460 	 */
461 	rootCfg.div = ((SYS_PLL2_FREQ /
462 			DT_PROP(DT_CHILD(DT_NODELABEL(lcdif), display_timings),
463 			clock_frequency)) + 1);
464 	CLOCK_SetRootClock(kCLOCK_Root_Lcdif, &rootCfg);
465 #endif
466 
467 #ifdef CONFIG_COUNTER_MCUX_GPT
468 	rootCfg.mux = kCLOCK_GPT1_ClockRoot_MuxOscRc48MDiv2;
469 	rootCfg.div = 1;
470 	CLOCK_SetRootClock(kCLOCK_Root_Gpt1, &rootCfg);
471 #endif
472 
473 #if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) && CONFIG_USB_DC_NXP_EHCI
474 	CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usb480M,
475 		DT_PROP_BY_PHANDLE(DT_NODELABEL(usb1), clocks, clock_frequency));
476 	CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M,
477 		DT_PROP_BY_PHANDLE(DT_NODELABEL(usb1), clocks, clock_frequency));
478 	USB_EhciPhyInit(kUSB_ControllerEhci0, CPU_XTAL_CLK_HZ, &usbPhyConfig);
479 #endif
480 
481 #if DT_NODE_HAS_STATUS(DT_NODELABEL(usb2), okay) && CONFIG_USB_DC_NXP_EHCI
482 	CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usb480M,
483 		DT_PROP_BY_PHANDLE(DT_NODELABEL(usb2), clocks, clock_frequency));
484 	CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M,
485 		DT_PROP_BY_PHANDLE(DT_NODELABEL(usb2), clocks, clock_frequency));
486 	USB_EhciPhyInit(kUSB_ControllerEhci1, CPU_XTAL_CLK_HZ, &usbPhyConfig);
487 #endif
488 
489 #if CONFIG_IMX_USDHC
490 #if DT_NODE_HAS_STATUS(DT_NODELABEL(usdhc1), okay)
491 	/* Configure USDHC1 using  SysPll2Pfd2*/
492 	rootCfg.mux = kCLOCK_USDHC1_ClockRoot_MuxSysPll2Pfd2;
493 	rootCfg.div = 2;
494 	CLOCK_SetRootClock(kCLOCK_Root_Usdhc1, &rootCfg);
495 	CLOCK_EnableClock(kCLOCK_Usdhc1);
496 #endif
497 
498 #if DT_NODE_HAS_STATUS(DT_NODELABEL(usdhc2), okay)
499 	/* Configure USDHC2 using  SysPll2Pfd2*/
500 	rootCfg.mux = kCLOCK_USDHC2_ClockRoot_MuxSysPll2Pfd2;
501 	rootCfg.div = 2;
502 	CLOCK_SetRootClock(kCLOCK_Root_Usdhc2, &rootCfg);
503 	CLOCK_EnableClock(kCLOCK_Usdhc2);
504 #endif
505 #endif
506 
507 #if !(defined(CONFIG_CODE_FLEXSPI) || defined(CONFIG_CODE_FLEXSPI2)) && \
508 	defined(CONFIG_MEMC_MCUX_FLEXSPI) && \
509 	DT_NODE_HAS_STATUS(DT_NODELABEL(flexspi), okay)
510 	/* Configure FLEXSPI1 using OSC_RC_48M_DIV2 */
511 	rootCfg.mux = kCLOCK_FLEXSPI1_ClockRoot_MuxOscRc48MDiv2;
512 	rootCfg.div = 1;
513 	CLOCK_SetRootClock(kCLOCK_Root_Flexspi1, &rootCfg);
514 #endif
515 
516 	/* Keep core clock ungated during WFI */
517 	CCM->GPR_PRIVATE1_SET = 0x1;
518 	/* Keep the system clock running so SYSTICK can wake up the system from
519 	 * wfi.
520 	 */
521 	GPC_CM_SetNextCpuMode(GPC_CPU_MODE_CTRL_0, kGPC_RunMode);
522 	GPC_CM_SetNextCpuMode(GPC_CPU_MODE_CTRL_1, kGPC_RunMode);
523 	GPC_CM_EnableCpuSleepHold(GPC_CPU_MODE_CTRL_0, false);
524 	GPC_CM_EnableCpuSleepHold(GPC_CPU_MODE_CTRL_1, false);
525 
526 #if !defined(CONFIG_PM)
527 	/* Enable the AHB clock while the CM7 is sleeping to allow debug access
528 	 * to TCM
529 	 */
530 	IOMUXC_GPR->GPR16 |= IOMUXC_GPR_GPR16_CM7_FORCE_HCLK_EN_MASK;
531 #endif
532 }
533 
534 #if CONFIG_I2S_MCUX_SAI
imxrt_audio_codec_pll_init(uint32_t clock_name,uint32_t clk_src,uint32_t clk_pre_div,uint32_t clk_src_div)535 void imxrt_audio_codec_pll_init(uint32_t clock_name, uint32_t clk_src,
536 					uint32_t clk_pre_div, uint32_t clk_src_div)
537 {
538 	ARG_UNUSED(clk_pre_div);
539 
540 	switch (clock_name) {
541 	case IMX_CCM_SAI1_CLK:
542 		CLOCK_SetRootClockMux(kCLOCK_Root_Sai1, clk_src);
543 		CLOCK_SetRootClockDiv(kCLOCK_Root_Sai1, clk_src_div);
544 		break;
545 	case IMX_CCM_SAI2_CLK:
546 		CLOCK_SetRootClockMux(kCLOCK_Root_Sai2, clk_src);
547 		CLOCK_SetRootClockDiv(kCLOCK_Root_Sai2, clk_src_div);
548 		break;
549 	case IMX_CCM_SAI3_CLK:
550 		CLOCK_SetRootClockMux(kCLOCK_Root_Sai3, clk_src);
551 		CLOCK_SetRootClockDiv(kCLOCK_Root_Sai3, clk_src_div);
552 		break;
553 	case IMX_CCM_SAI4_CLK:
554 		CLOCK_SetRootClockMux(kCLOCK_Root_Sai4, clk_src);
555 		CLOCK_SetRootClockDiv(kCLOCK_Root_Sai4, clk_src_div);
556 		break;
557 	default:
558 		return;
559 	}
560 }
561 #endif
562 
563 #if CONFIG_MIPI_DSI
imxrt_pre_init_display_interface(void)564 void imxrt_pre_init_display_interface(void)
565 {
566 	/* elcdif output to MIPI DSI */
567 	CLOCK_EnableClock(kCLOCK_Video_Mux);
568 	VIDEO_MUX->VID_MUX_CTRL.CLR = VIDEO_MUX_VID_MUX_CTRL_MIPI_DSI_SEL_MASK;
569 
570 	/* Power on and isolation off. */
571 	PGMC_BPC4->BPC_POWER_CTRL |= (PGMC_BPC_BPC_POWER_CTRL_PSW_ON_SOFT_MASK |
572 				PGMC_BPC_BPC_POWER_CTRL_ISO_OFF_SOFT_MASK);
573 
574 	/* Assert MIPI reset. */
575 	IOMUXC_GPR->GPR62 &= ~(IOMUXC_GPR_GPR62_MIPI_DSI_PCLK_SOFT_RESET_N_MASK |
576 			IOMUXC_GPR_GPR62_MIPI_DSI_ESC_SOFT_RESET_N_MASK |
577 			IOMUXC_GPR_GPR62_MIPI_DSI_BYTE_SOFT_RESET_N_MASK |
578 			IOMUXC_GPR_GPR62_MIPI_DSI_DPI_SOFT_RESET_N_MASK);
579 
580 	/* setup clock */
581 	const clock_root_config_t mipiEscClockConfig = {
582 		.clockOff = false,
583 		.mux = 4,
584 		.div = 11,
585 	};
586 
587 	CLOCK_SetRootClock(kCLOCK_Root_Mipi_Esc, &mipiEscClockConfig);
588 
589 	/* TX esc clock */
590 	const clock_group_config_t mipiEscClockGroupConfig = {
591 		.clockOff = false,
592 		.resetDiv = 2,
593 		.div0 = 2,
594 	};
595 
596 	CLOCK_SetGroupConfig(kCLOCK_Group_MipiDsi, &mipiEscClockGroupConfig);
597 
598 	const clock_root_config_t mipiDphyRefClockConfig = {
599 		.clockOff = false,
600 		.mux = 1,
601 		.div = 1,
602 	};
603 
604 	CLOCK_SetRootClock(kCLOCK_Root_Mipi_Ref, &mipiDphyRefClockConfig);
605 
606 	/* Deassert PCLK and ESC reset. */
607 	IOMUXC_GPR->GPR62 |= (IOMUXC_GPR_GPR62_MIPI_DSI_PCLK_SOFT_RESET_N_MASK |
608 			IOMUXC_GPR_GPR62_MIPI_DSI_ESC_SOFT_RESET_N_MASK);
609 }
610 
imxrt_post_init_display_interface(void)611 void imxrt_post_init_display_interface(void)
612 {
613 	/* deassert BYTE and DBI reset */
614 	IOMUXC_GPR->GPR62 |= (IOMUXC_GPR_GPR62_MIPI_DSI_BYTE_SOFT_RESET_N_MASK |
615 			IOMUXC_GPR_GPR62_MIPI_DSI_DPI_SOFT_RESET_N_MASK);
616 }
617 
618 #endif
619 
620 /**
621  *
622  * @brief Perform basic hardware initialization
623  *
624  * Initialize the interrupt controller device drivers.
625  * Also initialize the timer device driver, if required.
626  * If dual core operation is enabled, the second core image will be loaded to RAM
627  *
628  * @return 0
629  */
630 
imxrt_init(void)631 static int imxrt_init(void)
632 {
633 
634 	unsigned int oldLevel; /* old interrupt lock level */
635 
636 	/* disable interrupts */
637 	oldLevel = irq_lock();
638 
639 
640 #if  defined(CONFIG_SECOND_CORE_MCUX) && defined(CONFIG_CPU_CORTEX_M7)
641 	/**
642 	 * Copy CM4 core from flash to memory. Note that depending on where the
643 	 * user decided to store CM4 code, this is likely going to read from the
644 	 * flexspi while using XIP. Provided we DO NOT WRITE TO THE FLEXSPI,
645 	 * this operation is safe.
646 	 *
647 	 * Note that this copy MUST occur before enabling the M7 caching to
648 	 * ensure the data is written directly to RAM (since the M4 core will use it)
649 	 */
650 	LISTIFY(SEGMENT_NUM, MEMCPY_SEGMENT, (;));
651 	/* Set the boot address for the second core */
652 	uint32_t boot_address = (uint32_t)(DT_REG_ADDR(DT_CHOSEN(zephyr_cpu1_region)));
653 	/* Set VTOR for the CM4 core */
654 	IOMUXC_LPSR_GPR->GPR0 = IOMUXC_LPSR_GPR_GPR0_CM4_INIT_VTOR_LOW(boot_address >> 3u);
655 	IOMUXC_LPSR_GPR->GPR1 = IOMUXC_LPSR_GPR_GPR1_CM4_INIT_VTOR_HIGH(boot_address >> 16u);
656 #endif
657 
658 #if DUAL_CORE_MU_ENABLED && CONFIG_CPU_CORTEX_M4
659 	/* Set boot flag in messaging unit to indicate boot to primary core */
660 	MU_SetFlags(MU_BASE, BOOT_FLAG);
661 #endif
662 
663 
664 #if defined(CONFIG_SOC_MIMXRT1176_CM7) || defined(CONFIG_SOC_MIMXRT1166_CM7)
665 #ifndef CONFIG_IMXRT1XXX_CODE_CACHE
666 	/* SystemInit enables code cache, disable it here */
667 	SCB_DisableICache();
668 #else
669 	/* z_arm_init_arch_hw_at_boot() disables code cache if CONFIG_ARCH_CACHE is enabled,
670 	 * enable it here.
671 	 */
672 	SCB_EnableICache();
673 #endif
674 
675 	if (IS_ENABLED(CONFIG_IMXRT1XXX_DATA_CACHE)) {
676 		if ((SCB->CCR & SCB_CCR_DC_Msk) == 0) {
677 			SCB_EnableDCache();
678 		}
679 	} else {
680 		SCB_DisableDCache();
681 	}
682 #endif
683 
684 	/* Initialize system clock */
685 	clock_init();
686 
687 	/*
688 	 * install default handler that simply resets the CPU
689 	 * if configured in the kernel, NOP otherwise
690 	 */
691 	NMI_INIT();
692 
693 	/* restore interrupt state */
694 	irq_unlock(oldLevel);
695 	return 0;
696 }
697 
698 #ifdef CONFIG_PLATFORM_SPECIFIC_INIT
z_arm_platform_init(void)699 void z_arm_platform_init(void)
700 {
701 #if (DT_DEP_ORD(DT_NODELABEL(ocram)) != DT_DEP_ORD(DT_CHOSEN(zephyr_sram))) && \
702 	CONFIG_OCRAM_NOCACHE
703 	/* Copy data from flash to OCRAM */
704 	memcpy(&__ocram_data_start, &__ocram_data_load_start,
705 		(&__ocram_data_end - &__ocram_data_start));
706 	/* Zero BSS region */
707 	memset(&__ocram_bss_start, 0, (&__ocram_bss_end - &__ocram_bss_start));
708 #endif
709 	SystemInit();
710 }
711 #endif
712 
713 SYS_INIT(imxrt_init, PRE_KERNEL_1, 0);
714 
715 #if  defined(CONFIG_SECOND_CORE_MCUX) && defined(CONFIG_CPU_CORTEX_M7)
716 /**
717  * @brief Kickoff secondary core.
718  *
719  * Kick the secondary core out of reset and wait for it to indicate boot. The
720  * core image was already copied to RAM (and the boot address was set) in
721  * imxrt_init()
722  *
723  * @return 0
724  */
second_core_boot(void)725 static int second_core_boot(void)
726 {
727 	/* Kick CM4 core out of reset */
728 	SRC->CTRL_M4CORE = SRC_CTRL_M4CORE_SW_RESET_MASK;
729 	SRC->SCR |= SRC_SCR_BT_RELEASE_M4_MASK;
730 #if DUAL_CORE_MU_ENABLED
731 	/* Wait for the secondary core to start up and set boot flag in
732 	 * imxrt_init
733 	 */
734 	while (MU_GetFlags(MU_BASE) != BOOT_FLAG) {
735 		/* Wait for secondary core to set flag */
736 	}
737 #endif
738 	return 0;
739 }
740 
741 SYS_INIT(second_core_boot, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
742 #endif
743