1 /*
2 * Copyright 2020-2023 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief System/hardware module for nxp_lpc55s69 platform
10 *
11 * This module provides routines to initialize and support board-level
12 * hardware for the nxp_lpc55s69 platform.
13 */
14
15 #include <zephyr/kernel.h>
16 #include <zephyr/device.h>
17 #include <zephyr/init.h>
18 #include <zephyr/logging/log.h>
19 #include <soc.h>
20 #include <zephyr/drivers/uart.h>
21 #include <zephyr/linker/sections.h>
22 #include <zephyr/arch/cpu.h>
23 #include <cortex_m/exception.h>
24 #include <fsl_power.h>
25 #include <fsl_clock.h>
26 #include <fsl_common.h>
27 #include <fsl_device_registers.h>
28 #include <fsl_cache.h>
29
30 LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL);
31
32 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
33 #include "flash_clock_setup.h"
34 #endif
35
36 #if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511
37 #include "usb_phy.h"
38 #include "usb.h"
39 #endif
40
41 /* Core clock frequency: 250105263Hz */
42 #define CLOCK_INIT_CORE_CLOCK 250105263U
43
44 #define SYSTEM_IS_XIP_FLEXSPI() \
45 ((((uint32_t)nxp_rt600_init >= 0x08000000U) && \
46 ((uint32_t)nxp_rt600_init < 0x10000000U)) || \
47 (((uint32_t)nxp_rt600_init >= 0x18000000U) && ((uint32_t)nxp_rt600_init < 0x20000000U)))
48
49 #define CTIMER_CLOCK_SOURCE(node_id) \
50 TO_CTIMER_CLOCK_SOURCE(DT_CLOCKS_CELL(node_id, name), DT_PROP(node_id, clk_source))
51 #define TO_CTIMER_CLOCK_SOURCE(inst, val) TO_CLOCK_ATTACH_ID(inst, val)
52 #define TO_CLOCK_ATTACH_ID(inst, val) CLKCTL1_TUPLE_MUXA(CT32BIT##inst##FCLKSEL_OFFSET, val)
53 #define CTIMER_CLOCK_SETUP(node_id) CLOCK_AttachClk(CTIMER_CLOCK_SOURCE(node_id));
54
55 #ifdef CONFIG_INIT_SYS_PLL
56 const clock_sys_pll_config_t g_sysPllConfig = {.sys_pll_src = kCLOCK_SysPllXtalIn,
57 .numerator = 0,
58 .denominator = 1,
59 .sys_pll_mult = kCLOCK_SysPllMult22};
60 #endif
61
62 #ifdef CONFIG_INIT_AUDIO_PLL
63 const clock_audio_pll_config_t g_audioPllConfig = {.audio_pll_src = kCLOCK_AudioPllXtalIn,
64 .numerator = 5040,
65 .denominator = 27000,
66 .audio_pll_mult = kCLOCK_AudioPllMult22};
67 #endif
68
69 #if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511
70 /* USB PHY condfiguration */
71 #define BOARD_USB_PHY_D_CAL (0x0CU)
72 #define BOARD_USB_PHY_TXCAL45DP (0x06U)
73 #define BOARD_USB_PHY_TXCAL45DM (0x06U)
74 #endif
75
76 /* System clock frequency. */
77 extern uint32_t SystemCoreClock;
78 /* Main stack pointer */
79 extern char z_main_stack[];
80
81 #ifdef CONFIG_NXP_IMXRT_BOOT_HEADER
82 extern char _flash_used[];
83 extern void z_arm_reset(void);
84 extern void z_arm_nmi(void);
85 extern void z_arm_hard_fault(void);
86 extern void z_arm_mpu_fault(void);
87 extern void z_arm_bus_fault(void);
88 extern void z_arm_usage_fault(void);
89 extern void z_arm_secure_fault(void);
90 extern void z_arm_svc(void);
91 extern void z_arm_debug_monitor(void);
92 extern void z_arm_pendsv(void);
93 extern void sys_clock_isr(void);
94 extern void z_arm_exc_spurious(void);
95
96 __imx_boot_ivt_section void (*const image_vector_table[])(void) = {
97 (void (*)())(z_main_stack + CONFIG_MAIN_STACK_SIZE), /* 0x00 */
98 z_arm_reset, /* 0x04 */
99 z_arm_nmi, /* 0x08 */
100 z_arm_hard_fault, /* 0x0C */
101 z_arm_mpu_fault, /* 0x10 */
102 z_arm_bus_fault, /* 0x14 */
103 z_arm_usage_fault, /* 0x18 */
104 #if defined(CONFIG_ARM_SECURE_FIRMWARE)
105 z_arm_secure_fault, /* 0x1C */
106 #else
107 z_arm_exc_spurious,
108 #endif /* CONFIG_ARM_SECURE_FIRMWARE */
109 (void (*)())_flash_used, /* 0x20, imageLength. */
110 0, /* 0x24, imageType (Plain Image) */
111 0, /* 0x28, authBlockOffset/crcChecksum */
112 z_arm_svc, /* 0x2C */
113 z_arm_debug_monitor, /* 0x30 */
114 (void (*)())image_vector_table, /* 0x34, imageLoadAddress. */
115 z_arm_pendsv, /* 0x38 */
116 #if defined(CONFIG_SYS_CLOCK_EXISTS) && defined(CONFIG_CORTEX_M_SYSTICK_INSTALL_ISR)
117 sys_clock_isr, /* 0x3C */
118 #else
119 z_arm_exc_spurious,
120 #endif
121 };
122 #endif /* CONFIG_NXP_IMXRT_BOOT_HEADER */
123
124 #if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511
125
usb_device_clock_init(void)126 static void usb_device_clock_init(void)
127 {
128 uint8_t usbClockDiv = 1;
129 uint32_t usbClockFreq;
130 usb_phy_config_struct_t phyConfig = {
131 BOARD_USB_PHY_D_CAL,
132 BOARD_USB_PHY_TXCAL45DP,
133 BOARD_USB_PHY_TXCAL45DM,
134 };
135
136 /* enable USB IP clock */
137 CLOCK_SetClkDiv(kCLOCK_DivPfc1Clk, 5);
138 CLOCK_AttachClk(kXTALIN_CLK_to_USB_CLK);
139 CLOCK_SetClkDiv(kCLOCK_DivUsbHsFclk, usbClockDiv);
140 CLOCK_EnableUsbhsDeviceClock();
141 RESET_PeripheralReset(kUSBHS_PHY_RST_SHIFT_RSTn);
142 RESET_PeripheralReset(kUSBHS_DEVICE_RST_SHIFT_RSTn);
143 RESET_PeripheralReset(kUSBHS_HOST_RST_SHIFT_RSTn);
144 RESET_PeripheralReset(kUSBHS_SRAM_RST_SHIFT_RSTn);
145 /*Make sure USBHS ram buffer has power up*/
146 POWER_DisablePD(kPDRUNCFG_APD_USBHS_SRAM);
147 POWER_DisablePD(kPDRUNCFG_PPD_USBHS_SRAM);
148 POWER_ApplyPD();
149
150 /* save usb ip clock freq*/
151 usbClockFreq = g_xtalFreq / usbClockDiv;
152 /* enable USB PHY PLL clock, the phy bus clock (480MHz) source is same with USB IP */
153 CLOCK_EnableUsbHs0PhyPllClock(kXTALIN_CLK_to_USB_CLK, usbClockFreq);
154
155 #if defined(FSL_FEATURE_USBHSD_USB_RAM) && (FSL_FEATURE_USBHSD_USB_RAM)
156 for (int i = 0; i < FSL_FEATURE_USBHSD_USB_RAM; i++) {
157 ((uint8_t *)FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS)[i] = 0x00U;
158 }
159 #endif
160 USB_EhciPhyInit(kUSB_ControllerLpcIp3511Hs0, CLK_XTAL_OSC_CLK, &phyConfig);
161
162 /* the following code should run after phy initialization and
163 * should wait some microseconds to make sure utmi clock valid
164 */
165 /* enable usb1 host clock */
166 CLOCK_EnableClock(kCLOCK_UsbhsHost);
167 /* Wait until host_needclk de-asserts */
168 while (SYSCTL0->USBCLKSTAT & SYSCTL0_USBCLKSTAT_HOST_NEED_CLKST_MASK) {
169 __ASM("nop");
170 }
171 /* According to reference mannual, device mode setting has to be set by
172 * access usb host register
173 */
174 USBHSH->PORTMODE |= USBHSH_PORTMODE_DEV_ENABLE_MASK;
175 /* disable usb1 host clock */
176 CLOCK_DisableClock(kCLOCK_UsbhsHost);
177 }
178
179 #endif
180
181 /**
182 * @brief Initialize the system clock
183 */
clock_init(void)184 static ALWAYS_INLINE void clock_init(void)
185 {
186 #ifdef CONFIG_SOC_MIMXRT685S_CM33
187 /* Configure LPOSC clock*/
188 POWER_DisablePD(kPDRUNCFG_PD_LPOSC);
189 /* Configure FFRO clock */
190 POWER_DisablePD(kPDRUNCFG_PD_FFRO);
191 CLOCK_EnableFfroClk(kCLOCK_Ffro48M);
192 /* Configure SFRO clock */
193 POWER_DisablePD(kPDRUNCFG_PD_SFRO);
194 CLOCK_EnableSfroClk();
195
196 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
197 /*
198 * Call function flexspi_clock_safe_config() to move FlexSPI clock to a stable
199 * clock source to avoid instruction/data fetch issue when updating PLL and Main
200 * clock if XIP(execute code on FLEXSPI memory).
201 */
202 flexspi_clock_safe_config();
203 #endif
204
205 /* Let CPU run on FFRO for safe switching. */
206 CLOCK_AttachClk(kFFRO_to_MAIN_CLK);
207
208 /* Configure SYSOSC clock source */
209 POWER_DisablePD(kPDRUNCFG_PD_SYSXTAL);
210 POWER_UpdateOscSettlingTime(CONFIG_SYSOSC_SETTLING_US);
211 CLOCK_EnableSysOscClk(true, true, CONFIG_SYSOSC_SETTLING_US);
212 CLOCK_SetXtalFreq(CONFIG_XTAL_SYS_CLK_HZ);
213
214 #ifdef CONFIG_INIT_SYS_PLL
215 /* Configure SysPLL0 clock source */
216 CLOCK_InitSysPll(&g_sysPllConfig);
217 CLOCK_InitSysPfd(kCLOCK_Pfd0, 19);
218 CLOCK_InitSysPfd(kCLOCK_Pfd2, 24);
219 #endif
220
221 #ifdef CONFIG_INIT_AUDIO_PLL
222 /* Configure Audio PLL clock source */
223 CLOCK_InitAudioPll(&g_audioPllConfig);
224 CLOCK_InitAudioPfd(kCLOCK_Pfd0, 26);
225 CLOCK_SetClkDiv(kCLOCK_DivAudioPllClk, 15U);
226 #endif
227
228 /* Set SYSCPUAHBCLKDIV divider to value 2 */
229 CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 2U);
230
231 /* Set up clock selectors - Attach clocks to the peripheries */
232 CLOCK_AttachClk(kMAIN_PLL_to_MAIN_CLK);
233
234 /* Set up dividers */
235 /* Set PFC0DIV divider to value 2 */
236 CLOCK_SetClkDiv(kCLOCK_DivPfc0Clk, 2U);
237 /* Set FRGPLLCLKDIV divider to value 12 */
238 CLOCK_SetClkDiv(kCLOCK_DivPllFrgClk, 12U);
239
240 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_usart, okay)
241 CLOCK_AttachClk(kSFRO_to_FLEXCOMM0);
242 #endif
243
244 #if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511
245 usb_device_clock_init();
246 #endif
247
248 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm2), nxp_lpc_i2c, okay)
249 CLOCK_AttachClk(kSFRO_to_FLEXCOMM2);
250 #endif
251
252 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pmic_i2c), nxp_lpc_i2c, okay)
253 CLOCK_AttachClk(kFFRO_to_FLEXCOMM15);
254 #endif
255
256 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm4), nxp_lpc_usart, okay)
257 CLOCK_AttachClk(kSFRO_to_FLEXCOMM4);
258 #endif
259
260 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm5), nxp_lpc_spi, okay)
261 CLOCK_AttachClk(kFFRO_to_FLEXCOMM5);
262 #endif
263
264 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm1), nxp_lpc_i2s, okay))
265 /* attach AUDIO PLL clock to FLEXCOMM1 (I2S1) */
266 CLOCK_AttachClk(kAUDIO_PLL_to_FLEXCOMM1);
267 #endif
268 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm3), nxp_lpc_i2s, okay))
269 /* attach AUDIO PLL clock to FLEXCOMM3 (I2S3) */
270 CLOCK_AttachClk(kAUDIO_PLL_to_FLEXCOMM3);
271 #endif
272
273 #if CONFIG_AUDIO_CODEC_WM8904
274 /* attach AUDIO PLL clock to MCLK */
275 CLOCK_AttachClk(kAUDIO_PLL_to_MCLK_CLK);
276 CLOCK_SetClkDiv(kCLOCK_DivMclkClk, 1);
277 SYSCTL1->MCLKPINDIR = SYSCTL1_MCLKPINDIR_MCLKPINDIR_MASK;
278 #endif
279
280 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(wwdt0), nxp_lpc_wwdt, okay))
281 CLOCK_AttachClk(kLPOSC_to_WDT0_CLK);
282 #else
283 /* Allowed to select none if not being used for watchdog to
284 * reduce power
285 */
286 CLOCK_AttachClk(kNONE_to_WDT0_CLK);
287 #endif
288
289 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usdhc0)) && CONFIG_IMX_USDHC
290 /* Make sure USDHC ram buffer has been power up*/
291 POWER_DisablePD(kPDRUNCFG_APD_USDHC0_SRAM);
292 POWER_DisablePD(kPDRUNCFG_PPD_USDHC0_SRAM);
293 POWER_DisablePD(kPDRUNCFG_PD_LPOSC);
294 POWER_ApplyPD();
295
296 /* usdhc depend on 32K clock also */
297 CLOCK_AttachClk(kLPOSC_DIV32_to_32KHZWAKE_CLK);
298 CLOCK_AttachClk(kAUX0_PLL_to_SDIO0_CLK);
299 CLOCK_SetClkDiv(kCLOCK_DivSdio0Clk, 1);
300 CLOCK_EnableClock(kCLOCK_Sdio0);
301 RESET_PeripheralReset(kSDIO0_RST_SHIFT_RSTn);
302 #endif
303
304 DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP)
305 DT_FOREACH_STATUS_OKAY(nxp_ctimer_pwm, CTIMER_CLOCK_SETUP)
306
307 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(i3c0), nxp_mcux_i3c, okay))
308 CLOCK_AttachClk(kFFRO_to_I3C_CLK);
309 CLOCK_AttachClk(kLPOSC_to_I3C_TC_CLK);
310
311 CLOCK_SetClkDiv(kCLOCK_DivI3cClk,
312 DT_PROP(DT_NODELABEL(i3c0), clk_divider));
313 CLOCK_SetClkDiv(kCLOCK_DivI3cSlowClk,
314 DT_PROP(DT_NODELABEL(i3c0), clk_divider_slow));
315 CLOCK_SetClkDiv(kCLOCK_DivI3cTcClk,
316 DT_PROP(DT_NODELABEL(i3c0), clk_divider_tc));
317 #endif
318
319 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpadc0), nxp_lpc_lpadc, okay)
320 SYSCTL0->PDRUNCFG0_CLR = SYSCTL0_PDRUNCFG0_ADC_PD_MASK;
321 SYSCTL0->PDRUNCFG0_CLR = SYSCTL0_PDRUNCFG0_ADC_LP_MASK;
322 RESET_PeripheralReset(kADC0_RST_SHIFT_RSTn);
323 CLOCK_AttachClk(kSFRO_to_ADC_CLK);
324 CLOCK_SetClkDiv(kCLOCK_DivAdcClk, DT_PROP(DT_NODELABEL(lpadc0), clk_divider));
325 #endif
326
327 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(dmic0), nxp_dmic, okay) && CONFIG_INIT_AUDIO_PLL
328 /* Using the Audio PLL as input clock leads to better clock dividers
329 * for typical PCM sample rates ({8,16,24,32,48,96} kHz.
330 */
331 /* DMIC source from audio pll, divider 8, 24.576M/8=3.072MHZ
332 * Select Audio PLL as clock source. This should produce a bit clock
333 * of 3.072MHZ
334 */
335 CLOCK_AttachClk(kAUDIO_PLL_to_DMIC_CLK);
336 CLOCK_SetClkDiv(kCLOCK_DivDmicClk, 8);
337 #endif
338
339 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
340 /*
341 * Call function flexspi_setup_clock() to set user configured clock source/divider
342 * for FlexSPI.
343 */
344 flexspi_setup_clock(FLEXSPI, 1U, 9U);
345 #endif
346
347 /* Set SystemCoreClock variable. */
348 SystemCoreClock = CLOCK_INIT_CORE_CLOCK;
349
350 #endif /* CONFIG_SOC_MIMXRT685S_CM33 */
351 }
352
353 #if (DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usdhc0)) && CONFIG_IMX_USDHC)
354
imxrt_usdhc_pinmux(uint16_t nusdhc,bool init,uint32_t speed,uint32_t strength)355 void imxrt_usdhc_pinmux(uint16_t nusdhc, bool init, uint32_t speed, uint32_t strength)
356 {
357 }
358
imxrt_usdhc_dat3_pull(bool pullup)359 void imxrt_usdhc_dat3_pull(bool pullup)
360 {
361 }
362 #endif
363
364 /**
365 *
366 * @brief Perform basic hardware initialization
367 *
368 * Initialize the interrupt controller device drivers.
369 * Also initialize the timer device driver, if required.
370 */
371
soc_early_init_hook(void)372 void soc_early_init_hook(void)
373 {
374 /* Initialize clock */
375 clock_init();
376
377 #ifndef CONFIG_IMXRT6XX_CODE_CACHE
378 CACHE64_DisableCache(CACHE64);
379 #endif
380 }
381
382 #ifdef CONFIG_SOC_RESET_HOOK
383
soc_reset_hook(void)384 void soc_reset_hook(void)
385 {
386 #ifndef CONFIG_NXP_IMXRT_BOOT_HEADER
387 /*
388 * If boot did not proceed using a boot header, we should not assume
389 * the core is in reset state. Disable the MPU and correctly
390 * set the stack pointer, since we are about to push to
391 * the stack when we call SystemInit
392 */
393 /* Clear stack limit registers */
394 __set_MSPLIM(0);
395 __set_PSPLIM(0);
396 /* Disable MPU */
397 MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
398 /* Set stack pointer */
399 __set_MSP((uint32_t)(z_main_stack + CONFIG_MAIN_STACK_SIZE));
400 #endif /* !CONFIG_NXP_IMXRT_BOOT_HEADER */
401 /* This is provided by the SDK */
402 SystemInit();
403 }
404
405 #endif
406