1 /*
2 * Copyright 2022-2023, NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief System/hardware module for NXP RT5XX platform
10 *
11 * This module provides routines to initialize and support board-level
12 * hardware for the RT5XX platforms.
13 */
14
15 #include <zephyr/init.h>
16 #include <zephyr/devicetree.h>
17 #include <zephyr/linker/sections.h>
18 #include <zephyr/logging/log.h>
19 #include <soc.h>
20 #include "fsl_power.h"
21 #include "fsl_clock.h"
22 #include <fsl_cache.h>
23
24 LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL);
25
26 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
27 #include "flash_clock_setup.h"
28 #endif
29
30 #if CONFIG_USB_DC_NXP_LPCIP3511
31 #include "usb_phy.h"
32 #include "usb.h"
33 #endif
34
35 /* Board System oscillator settling time in us */
36 #define BOARD_SYSOSC_SETTLING_US 100U
37 /* Board xtal frequency in Hz */
38 #define BOARD_XTAL_SYS_CLK_HZ 24000000U
39 /* Core clock frequency: 198000000Hz */
40 #define CLOCK_INIT_CORE_CLOCK 198000000U
41
42 #define CTIMER_CLOCK_SOURCE(node_id) \
43 TO_CTIMER_CLOCK_SOURCE(DT_CLOCKS_CELL(node_id, name), DT_PROP(node_id, clk_source))
44 #define TO_CTIMER_CLOCK_SOURCE(inst, val) TO_CLOCK_ATTACH_ID(inst, val)
45 #define TO_CLOCK_ATTACH_ID(inst, val) CLKCTL1_TUPLE_MUXA(CT32BIT##inst##FCLKSEL_OFFSET, val)
46 #define CTIMER_CLOCK_SETUP(node_id) CLOCK_AttachClk(CTIMER_CLOCK_SOURCE(node_id));
47
48 const clock_sys_pll_config_t g_sysPllConfig_clock_init = {
49 /* OSC clock */
50 .sys_pll_src = kCLOCK_SysPllXtalIn,
51 /* Numerator of the SYSPLL0 fractional loop divider is 0 */
52 .numerator = 0,
53 /* Denominator of the SYSPLL0 fractional loop divider is 1 */
54 .denominator = 1,
55 /* Divide by 22 */
56 .sys_pll_mult = kCLOCK_SysPllMult22};
57
58 const clock_audio_pll_config_t g_audioPllConfig_clock_init = {
59 /* OSC clock */
60 .audio_pll_src = kCLOCK_AudioPllXtalIn,
61 /* Numerator of the Audio PLL fractional loop divider is 0 */
62 .numerator = 5040,
63 /* Denominator of the Audio PLL fractional loop divider is 1 */
64 .denominator = 27000,
65 /* Divide by 22 */
66 .audio_pll_mult = kCLOCK_AudioPllMult22};
67
68 const clock_frg_clk_config_t g_frg0Config_clock_init = {
69 .num = 0, .sfg_clock_src = kCLOCK_FrgPllDiv, .divider = 255U, .mult = 0};
70
71 const clock_frg_clk_config_t g_frg12Config_clock_init = {
72 .num = 12, .sfg_clock_src = kCLOCK_FrgMainClk, .divider = 255U, .mult = 167};
73
74 #if CONFIG_USB_DC_NXP_LPCIP3511
75 /* USB PHY configuration */
76 #define BOARD_USB_PHY_D_CAL (0x0CU)
77 #define BOARD_USB_PHY_TXCAL45DP (0x06U)
78 #define BOARD_USB_PHY_TXCAL45DM (0x06U)
79 #endif
80
81 /* System clock frequency. */
82 extern uint32_t SystemCoreClock;
83 /* Main stack pointer */
84 extern char z_main_stack[];
85
86 #ifdef CONFIG_NXP_IMXRT_BOOT_HEADER
87 extern char _flash_used[];
88
89 extern void z_arm_reset(void);
90 extern void z_arm_nmi(void);
91 extern void z_arm_hard_fault(void);
92 extern void z_arm_mpu_fault(void);
93 extern void z_arm_bus_fault(void);
94 extern void z_arm_usage_fault(void);
95 extern void z_arm_secure_fault(void);
96 extern void z_arm_svc(void);
97 extern void z_arm_debug_monitor(void);
98 extern void z_arm_pendsv(void);
99 extern void sys_clock_isr(void);
100 extern void z_arm_exc_spurious(void);
101
102 __imx_boot_ivt_section void (*const image_vector_table[])(void) = {
103 (void (*)())(z_main_stack + CONFIG_MAIN_STACK_SIZE), /* 0x00 */
104 z_arm_reset, /* 0x04 */
105 z_arm_nmi, /* 0x08 */
106 z_arm_hard_fault, /* 0x0C */
107 z_arm_mpu_fault, /* 0x10 */
108 z_arm_bus_fault, /* 0x14 */
109 z_arm_usage_fault, /* 0x18 */
110 #if defined(CONFIG_ARM_SECURE_FIRMWARE)
111 z_arm_secure_fault, /* 0x1C */
112 #else
113 z_arm_exc_spurious,
114 #endif /* CONFIG_ARM_SECURE_FIRMWARE */
115 (void (*)())_flash_used, /* 0x20, imageLength. */
116 0, /* 0x24, imageType (Plain Image) */
117 0, /* 0x28, authBlockOffset/crcChecksum */
118 z_arm_svc, /* 0x2C */
119 z_arm_debug_monitor, /* 0x30 */
120 (void (*)())image_vector_table, /* 0x34, imageLoadAddress. */
121 z_arm_pendsv, /* 0x38 */
122 #if defined(CONFIG_SYS_CLOCK_EXISTS) && defined(CONFIG_CORTEX_M_SYSTICK_INSTALL_ISR)
123 sys_clock_isr, /* 0x3C */
124 #else
125 z_arm_exc_spurious,
126 #endif
127 };
128 #endif /* CONFIG_NXP_IMXRT_BOOT_HEADER */
129
130 #if CONFIG_USB_DC_NXP_LPCIP3511
131
usb_device_clock_init(void)132 static void usb_device_clock_init(void)
133 {
134 uint8_t usbClockDiv = 1;
135 uint32_t usbClockFreq;
136 usb_phy_config_struct_t phyConfig = {
137 BOARD_USB_PHY_D_CAL,
138 BOARD_USB_PHY_TXCAL45DP,
139 BOARD_USB_PHY_TXCAL45DM,
140 };
141
142 /* Make sure USBHS ram buffer and usb1 phy has power up */
143 POWER_DisablePD(kPDRUNCFG_APD_USBHS_SRAM);
144 POWER_DisablePD(kPDRUNCFG_PPD_USBHS_SRAM);
145 POWER_ApplyPD();
146
147 RESET_PeripheralReset(kUSBHS_PHY_RST_SHIFT_RSTn);
148 RESET_PeripheralReset(kUSBHS_DEVICE_RST_SHIFT_RSTn);
149 RESET_PeripheralReset(kUSBHS_HOST_RST_SHIFT_RSTn);
150 RESET_PeripheralReset(kUSBHS_SRAM_RST_SHIFT_RSTn);
151
152 /* enable usb ip clock */
153 CLOCK_EnableUsbHs0DeviceClock(kOSC_CLK_to_USB_CLK, usbClockDiv);
154 /* save usb ip clock freq*/
155 usbClockFreq = g_xtalFreq / usbClockDiv;
156 CLOCK_SetClkDiv(kCLOCK_DivPfc1Clk, 4);
157 /* enable usb ram clock */
158 CLOCK_EnableClock(kCLOCK_UsbhsSram);
159 /* enable USB PHY PLL clock, the phy bus clock (480MHz) source is same with USB IP */
160 CLOCK_EnableUsbHs0PhyPllClock(kOSC_CLK_to_USB_CLK, usbClockFreq);
161
162 /* USB PHY initialization */
163 USB_EhciPhyInit(kUSB_ControllerLpcIp3511Hs0, BOARD_XTAL_SYS_CLK_HZ, &phyConfig);
164
165 #if defined(FSL_FEATURE_USBHSD_USB_RAM) && (FSL_FEATURE_USBHSD_USB_RAM)
166 for (int i = 0; i < FSL_FEATURE_USBHSD_USB_RAM; i++) {
167 ((uint8_t *)FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS)[i] = 0x00U;
168 }
169 #endif
170
171 /* The following code should run after phy initialization and should wait
172 * some microseconds to make sure utmi clock valid
173 */
174 /* enable usb1 host clock */
175 CLOCK_EnableClock(kCLOCK_UsbhsHost);
176 /* Wait until host_needclk de-asserts */
177 while (SYSCTL0->USB0CLKSTAT & SYSCTL0_USB0CLKSTAT_HOST_NEED_CLKST_MASK) {
178 __ASM("nop");
179 }
180 /* According to reference manual, device mode setting has to be set by access
181 * usb host register
182 */
183 USBHSH->PORTMODE |= USBHSH_PORTMODE_DEV_ENABLE_MASK;
184 /* disable usb1 host clock */
185 CLOCK_DisableClock(kCLOCK_UsbhsHost);
186 }
187
188 #endif
189
soc_reset_hook(void)190 void soc_reset_hook(void)
191 {
192 #ifndef CONFIG_NXP_IMXRT_BOOT_HEADER
193 /*
194 * If boot did not proceed using a boot header, we should not assume
195 * the core is in reset state. Disable the MPU and correctly
196 * set the stack pointer, since we are about to push to
197 * the stack when we call SystemInit
198 */
199 /* Clear stack limit registers */
200 __set_MSPLIM(0);
201 __set_PSPLIM(0);
202 /* Disable MPU */
203 MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
204 /* Set stack pointer */
205 __set_MSP((uint32_t)(z_main_stack + CONFIG_MAIN_STACK_SIZE));
206 #endif /* !CONFIG_NXP_IMXRT_BOOT_HEADER */
207 /* This is provided by the SDK */
208 SystemInit();
209 }
210
211 /* Weak so that board can override with their own clock init routine. */
rt5xx_clock_init(void)212 void __weak rt5xx_clock_init(void)
213 {
214 /* Configure LPOSC 1M */
215 /* Power on LPOSC (1MHz) */
216 POWER_DisablePD(kPDRUNCFG_PD_LPOSC);
217 /* Wait until LPOSC stable */
218 CLOCK_EnableLpOscClk();
219
220 /* Configure FRO clock source */
221 /* Power on FRO (192MHz or 96MHz) */
222 POWER_DisablePD(kPDRUNCFG_PD_FFRO);
223 /* FRO_DIV1 is always enabled and used as Main clock during PLL update. */
224 /* Enable all FRO outputs */
225 CLOCK_EnableFroClk(kCLOCK_FroAllOutEn);
226
227 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
228 /*
229 * Call function flexspi_clock_safe_config() to move FlexSPI clock to a stable
230 * clock source to avoid instruction/data fetch issue when updating PLL and Main
231 * clock if XIP(execute code on FLEXSPI memory).
232 */
233 flexspi_clock_safe_config();
234 #endif
235
236 /* Let CPU run on FRO with divider 2 for safe switching. */
237 CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 2);
238 CLOCK_AttachClk(kFRO_DIV1_to_MAIN_CLK);
239
240 /* Configure SYSOSC clock source. */
241 /* Power on SYSXTAL */
242 POWER_DisablePD(kPDRUNCFG_PD_SYSXTAL);
243 /* Updated XTAL oscillator settling time */
244 POWER_UpdateOscSettlingTime(BOARD_SYSOSC_SETTLING_US);
245 /* Enable system OSC */
246 CLOCK_EnableSysOscClk(true, true, BOARD_SYSOSC_SETTLING_US);
247 /* Sets external XTAL OSC freq */
248 CLOCK_SetXtalFreq(BOARD_XTAL_SYS_CLK_HZ);
249
250 /* Configure SysPLL0 clock source. */
251 CLOCK_InitSysPll(&g_sysPllConfig_clock_init);
252 /* Enable MAIN PLL clock */
253 CLOCK_InitSysPfd(kCLOCK_Pfd0, 24);
254 /* Enable AUX0 PLL clock */
255 CLOCK_InitSysPfd(kCLOCK_Pfd2, 24);
256
257 /* Configure Audio PLL clock source. */
258 CLOCK_InitAudioPll(&g_audioPllConfig_clock_init);
259 /* Enable Audio PLL clock */
260 CLOCK_InitAudioPfd(kCLOCK_Pfd0, 26);
261
262 /* Set SYSCPUAHBCLKDIV divider to value 2 */
263 CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 2U);
264
265 /* Setup FRG0 clock */
266 CLOCK_SetFRGClock(&g_frg0Config_clock_init);
267 /* Setup FRG12 clock */
268 CLOCK_SetFRGClock(&g_frg12Config_clock_init);
269
270 /* Set up clock selectors - Attach clocks to the peripheries. */
271 /* Switch MAIN_CLK to MAIN_PLL */
272 CLOCK_AttachClk(kMAIN_PLL_to_MAIN_CLK);
273 /* Switch SYSTICK_CLK to MAIN_CLK_DIV */
274 CLOCK_AttachClk(kMAIN_CLK_DIV_to_SYSTICK_CLK);
275 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_usart, okay)
276 #ifdef CONFIG_FLEXCOMM0_CLK_SRC_FRG
277 /* Switch FLEXCOMM0 to FRG */
278 CLOCK_AttachClk(kFRG_to_FLEXCOMM0);
279 #elif defined(CONFIG_FLEXCOMM0_CLK_SRC_FRO)
280 CLOCK_AttachClk(kFRO_DIV4_to_FLEXCOMM0);
281 #endif
282 #endif
283 #if CONFIG_USB_DC_NXP_LPCIP3511
284 usb_device_clock_init();
285 #endif
286
287 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_i2s, okay) && CONFIG_I2S)
288 /* attach AUDIO PLL clock to FLEXCOMM1 (I2S_PDM) */
289 CLOCK_AttachClk(kAUDIO_PLL_to_FLEXCOMM0);
290 #endif
291
292 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm1), nxp_lpc_i2s, okay) && CONFIG_I2S)
293 /* attach AUDIO PLL clock to FLEXCOMM1 (I2S1) */
294 CLOCK_AttachClk(kAUDIO_PLL_to_FLEXCOMM1);
295 #endif
296 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm3), nxp_lpc_i2s, okay) && CONFIG_I2S)
297 /* attach AUDIO PLL clock to FLEXCOMM3 (I2S3) */
298 CLOCK_AttachClk(kAUDIO_PLL_to_FLEXCOMM3);
299 #endif
300
301 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm4), nxp_lpc_i2c, okay)
302 /* Switch FLEXCOMM4 to FRO_DIV4 */
303 CLOCK_AttachClk(kFRO_DIV4_to_FLEXCOMM4);
304 #endif
305 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(i3c0), nxp_mcux_i3c, okay)
306 /* Attach main clock to I3C */
307 CLOCK_AttachClk(kMAIN_CLK_to_I3C_CLK);
308 CLOCK_AttachClk(kLPOSC_to_I3C_TC_CLK);
309
310 CLOCK_SetClkDiv(kCLOCK_DivI3cClk,
311 DT_PROP(DT_NODELABEL(i3c0), clk_divider));
312 CLOCK_SetClkDiv(kCLOCK_DivI3cSlowClk,
313 DT_PROP(DT_NODELABEL(i3c0), clk_divider_slow));
314 CLOCK_SetClkDiv(kCLOCK_DivI3cTcClk,
315 DT_PROP(DT_NODELABEL(i3c0), clk_divider_tc));
316 #endif
317 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(hs_spi1), nxp_lpc_spi, okay)
318 CLOCK_AttachClk(kFRO_DIV4_to_FLEXCOMM16);
319 #endif
320 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm12), nxp_lpc_usart, okay)
321 /* Switch FLEXCOMM12 to FRG */
322 CLOCK_AttachClk(kFRG_to_FLEXCOMM12);
323 #endif
324 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm12), nxp_lpc_spi, okay)
325 /* Switch FLEXCOMM12 to FRG */
326 CLOCK_AttachClk(kFRG_to_FLEXCOMM12);
327 #endif
328 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pmic_i2c), nxp_lpc_i2c, okay)
329 CLOCK_AttachClk(kFRO_DIV4_to_FLEXCOMM15);
330 #endif
331 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lcdif), nxp_dcnano_lcdif, okay) && CONFIG_DISPLAY
332 POWER_DisablePD(kPDRUNCFG_APD_DCNANO_SRAM);
333 POWER_DisablePD(kPDRUNCFG_PPD_DCNANO_SRAM);
334 POWER_ApplyPD();
335
336 CLOCK_AttachClk(kAUX0_PLL_to_DCPIXEL_CLK);
337 /* Note- pixel clock follows formula
338 * (height + VSW + VFP + VBP) * (width + HSW + HFP + HBP) * frame rate.
339 * this means the clock divider will vary depending on
340 * the attached display.
341 *
342 * The root clock used here is the AUX0 PLL (PLL0 PFD2).
343 */
344 CLOCK_SetClkDiv(
345 kCLOCK_DivDcPixelClk,
346 ((CLOCK_GetSysPfdFreq(kCLOCK_Pfd2) /
347 DT_PROP(DT_CHILD(DT_NODELABEL(lcdif), display_timings), clock_frequency)) +
348 1));
349
350 CLOCK_EnableClock(kCLOCK_DisplayCtrl);
351 RESET_ClearPeripheralReset(kDISP_CTRL_RST_SHIFT_RSTn);
352
353 CLOCK_EnableClock(kCLOCK_AxiSwitch);
354 RESET_ClearPeripheralReset(kAXI_SWITCH_RST_SHIFT_RSTn);
355 #if defined(CONFIG_MEMC) && DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexspi2), nxp_imx_flexspi, okay)
356 /* Enable write-through for FlexSPI1 space */
357 CACHE64_POLSEL0->REG1_TOP = 0x27FFFC00U;
358 CACHE64_POLSEL0->POLSEL = 0x11U;
359 #endif
360 #endif
361
362 /* Switch CLKOUT to FRO_DIV2 */
363 CLOCK_AttachClk(kFRO_DIV2_to_CLKOUT);
364
365 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usdhc0)) && CONFIG_IMX_USDHC
366 /* Make sure USDHC ram buffer has been power up*/
367 POWER_DisablePD(kPDRUNCFG_APD_USDHC0_SRAM);
368 POWER_DisablePD(kPDRUNCFG_PPD_USDHC0_SRAM);
369 POWER_DisablePD(kPDRUNCFG_PD_LPOSC);
370 POWER_ApplyPD();
371
372 /* usdhc depend on 32K clock also */
373 CLOCK_AttachClk(kLPOSC_DIV32_to_32KHZWAKE_CLK);
374 CLOCK_AttachClk(kAUX0_PLL_to_SDIO0_CLK);
375 CLOCK_SetClkDiv(kCLOCK_DivSdio0Clk, 1);
376 CLOCK_EnableClock(kCLOCK_Sdio0);
377 RESET_PeripheralReset(kSDIO0_RST_SHIFT_RSTn);
378 #endif
379
380 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(smartdma)) && CONFIG_DMA_MCUX_SMARTDMA
381 /* Power up SMARTDMA ram */
382 POWER_DisablePD(kPDRUNCFG_APD_SMARTDMA_SRAM);
383 POWER_DisablePD(kPDRUNCFG_PPD_SMARTDMA_SRAM);
384 POWER_ApplyPD();
385
386 RESET_ClearPeripheralReset(kSMART_DMA_RST_SHIFT_RSTn);
387 CLOCK_EnableClock(kCLOCK_Smartdma);
388 #endif
389
390 DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP)
391
392 /* Set up dividers. */
393 /* Set AUDIOPLLCLKDIV divider to value 15 */
394 CLOCK_SetClkDiv(kCLOCK_DivAudioPllClk, 15U);
395 /* Set FRGPLLCLKDIV divider to value 11 */
396 CLOCK_SetClkDiv(kCLOCK_DivPLLFRGClk, 11U);
397 /* Set SYSTICKFCLKDIV divider to value 2 */
398 CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 2U);
399 /* Set PFC0DIV divider to value 2 */
400 CLOCK_SetClkDiv(kCLOCK_DivPfc0Clk, 2U);
401 /* Set PFC1DIV divider to value 4 */
402 CLOCK_SetClkDiv(kCLOCK_DivPfc1Clk, 4U);
403 /* Set CLKOUTFCLKDIV divider to value 100 */
404 CLOCK_SetClkDiv(kCLOCK_DivClockOut, 100U);
405
406 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
407 /*
408 * Call function flexspi_setup_clock() to set user configured clock source/divider
409 * for FlexSPI.
410 */
411 flexspi_setup_clock(FLEXSPI0, 0U, 2U);
412 #endif
413
414 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexspi2), nxp_imx_flexspi, okay)
415 /* Power up FlexSPI1 SRAM */
416 POWER_DisablePD(kPDRUNCFG_APD_FLEXSPI1_SRAM);
417 POWER_DisablePD(kPDRUNCFG_PPD_FLEXSPI1_SRAM);
418 POWER_ApplyPD();
419 /* Setup clock frequency for FlexSPI1 */
420 CLOCK_AttachClk(kMAIN_CLK_to_FLEXSPI1_CLK);
421 CLOCK_SetClkDiv(kCLOCK_DivFlexspi1Clk, 1);
422 /* Reset peripheral module */
423 RESET_PeripheralReset(kFLEXSPI1_RST_SHIFT_RSTn);
424 #endif
425
426 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpadc0), nxp_lpc_lpadc, okay)
427 SYSCTL0->PDRUNCFG0_CLR = SYSCTL0_PDRUNCFG0_ADC_PD_MASK;
428 SYSCTL0->PDRUNCFG0_CLR = SYSCTL0_PDRUNCFG0_ADC_LP_MASK;
429 RESET_PeripheralReset(kADC0_RST_SHIFT_RSTn);
430 CLOCK_AttachClk(kFRO_DIV4_to_ADC_CLK);
431 CLOCK_SetClkDiv(kCLOCK_DivAdcClk, 1);
432 #endif
433
434 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(dmic0), nxp_dmic, okay)
435 /* Using the Audio PLL as input clock leads to better clock dividers
436 * for typical PCM sample rates ({8,16,24,32,48,96} kHz.
437 */
438 /* DMIC source from audio pll, divider 8, 24.576M/8=3.072MHZ
439 * Select Audio PLL as clock source. This should produce a bit clock
440 * of 3.072MHZ
441 */
442 CLOCK_AttachClk(kAUDIO_PLL_to_DMIC);
443 CLOCK_SetClkDiv(kCLOCK_DivDmicClk, 8);
444
445 #endif
446
447 /* Set SystemCoreClock variable. */
448 SystemCoreClock = CLOCK_INIT_CORE_CLOCK;
449
450 /* Set main clock to FRO as deep sleep clock by default. */
451 POWER_SetDeepSleepClock(kDeepSleepClk_Fro);
452
453 #if CONFIG_AUDIO_CODEC_WM8904
454 /* attach AUDIO PLL clock to MCLK */
455 CLOCK_AttachClk(kAUDIO_PLL_to_MCLK_CLK);
456 CLOCK_SetClkDiv(kCLOCK_DivMclkClk, 1);
457 SYSCTL1->MCLKPINDIR = SYSCTL1_MCLKPINDIR_MCLKPINDIR_MASK;
458 #endif
459 }
460
461 #if CONFIG_MIPI_DSI
462 /* Weak so board can override this function */
imxrt_pre_init_display_interface(void)463 void __weak imxrt_pre_init_display_interface(void)
464 {
465 /* Assert MIPI DPHY reset. */
466 RESET_SetPeripheralReset(kMIPI_DSI_PHY_RST_SHIFT_RSTn);
467 POWER_DisablePD(kPDRUNCFG_APD_MIPIDSI_SRAM);
468 POWER_DisablePD(kPDRUNCFG_PPD_MIPIDSI_SRAM);
469 POWER_DisablePD(kPDRUNCFG_PD_MIPIDSI);
470 POWER_ApplyPD();
471
472 /* RxClkEsc max 60MHz, TxClkEsc 12 to 20MHz. */
473 CLOCK_AttachClk(kFRO_DIV1_to_MIPI_DPHYESC_CLK);
474 /* RxClkEsc = 192MHz / 4 = 48MHz. */
475 CLOCK_SetClkDiv(kCLOCK_DivDphyEscRxClk, 4);
476 /* TxClkEsc = 192MHz / 4 / 3 = 16MHz. */
477 CLOCK_SetClkDiv(kCLOCK_DivDphyEscTxClk, 3);
478
479 /*
480 * The DPHY bit clock must be fast enough to send out the pixels,
481 * it should be larger than:
482 *
483 * (Pixel clock * bit per output pixel) / number of MIPI data lane
484 *
485 * DPHY supports up to 895.1MHz bit clock.
486 * We set the divider of the PFD3 output of the SYSPLL, which has a
487 * fixed multiplied of 18, and use this output frequency for the DPHY.
488 */
489
490 #ifdef CONFIG_MIPI_DPHY_CLK_SRC_AUX1_PLL
491 /* Note: AUX1 PLL clock is system pll clock * 18 / pfd.
492 * system pll clock is configured at 528MHz by default.
493 */
494 CLOCK_AttachClk(kAUX1_PLL_to_MIPI_DPHY_CLK);
495 CLOCK_InitSysPfd(kCLOCK_Pfd3,
496 ((CLOCK_GetSysPllFreq() * 18ull) /
497 ((unsigned long long)(DT_PROP(DT_NODELABEL(mipi_dsi), phy_clock)))));
498 CLOCK_SetClkDiv(kCLOCK_DivDphyClk, 1);
499 #elif defined(CONFIG_MIPI_DPHY_CLK_SRC_FRO)
500 CLOCK_AttachClk(kFRO_DIV1_to_MIPI_DPHY_CLK);
501 CLOCK_SetClkDiv(kCLOCK_DivDphyClk,
502 (CLK_FRO_CLK / DT_PROP(DT_NODELABEL(mipi_dsi), phy_clock)));
503 #endif
504 /* Clear DSI control reset (Note that DPHY reset is cleared later)*/
505 RESET_ClearPeripheralReset(kMIPI_DSI_CTRL_RST_SHIFT_RSTn);
506 }
507
imxrt_post_init_display_interface(void)508 void __weak imxrt_post_init_display_interface(void)
509 {
510 /* Deassert MIPI DPHY reset. */
511 RESET_ClearPeripheralReset(kMIPI_DSI_PHY_RST_SHIFT_RSTn);
512 }
513
imxrt_deinit_display_interface(void)514 void __weak imxrt_deinit_display_interface(void)
515 {
516 /* Assert MIPI DPHY and DSI reset */
517 RESET_SetPeripheralReset(kMIPI_DSI_PHY_RST_SHIFT_RSTn);
518 RESET_SetPeripheralReset(kMIPI_DSI_CTRL_RST_SHIFT_RSTn);
519 /* Remove clock from DPHY */
520 CLOCK_AttachClk(kNONE_to_MIPI_DPHY_CLK);
521 }
522
523 #endif
524
525 extern void rt5xx_power_init(void);
526
527 /**
528 *
529 * @brief Perform basic hardware initialization
530 *
531 * Initialize the interrupt controller device drivers.
532 * Also initialize the timer device driver, if required.
533 */
soc_early_init_hook(void)534 void soc_early_init_hook(void)
535 {
536 /* Initialize clocks with tool generated code */
537 rt5xx_clock_init();
538
539 #ifndef CONFIG_IMXRT5XX_CODE_CACHE
540 CACHE64_DisableCache(CACHE64_CTRL0);
541 #endif
542
543 /* Some ROM versions may have errata leaving these pins in a non-reset state,
544 * which can often cause power leakage on most expected board designs,
545 * restore the reset state here and leave the pin configuration up to board/user DT
546 */
547 IOPCTL->PIO[1][15] = 0;
548 IOPCTL->PIO[3][28] = 0;
549 IOPCTL->PIO[3][29] = 0;
550 #ifdef CONFIG_PM
551 rt5xx_power_init();
552 #endif
553
554 }
555