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