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