1 /*
2  * Copyright 2022-2024 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/arch/cpu.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/uart.h>
10 #include <zephyr/init.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/linker/sections.h>
13 #include <zephyr/sys/util_macro.h>
14 
15 #include <cortex_m/exception.h>
16 #include <fsl_power.h>
17 #include <fsl_clock.h>
18 #include <fsl_common.h>
19 #include <fsl_device_registers.h>
20 #include "soc.h"
21 #include "flexspi_clock_setup.h"
22 #include "fsl_ocotp.h"
23 #ifdef CONFIG_NXP_RW6XX_BOOT_HEADER
24 extern char z_main_stack[];
25 extern char _flash_used[];
26 
27 extern void z_arm_reset(void);
28 extern void z_arm_nmi(void);
29 extern void z_arm_hard_fault(void);
30 extern void z_arm_mpu_fault(void);
31 extern void z_arm_bus_fault(void);
32 extern void z_arm_usage_fault(void);
33 extern void z_arm_secure_fault(void);
34 extern void z_arm_svc(void);
35 extern void z_arm_debug_monitor(void);
36 extern void z_arm_pendsv(void);
37 extern void sys_clock_isr(void);
38 extern void z_arm_exc_spurious(void);
39 extern void nxp_nbu_init(void);
40 
41 __imx_boot_ivt_section void (*const image_vector_table[])(void) = {
42 	(void (*)())(z_main_stack + CONFIG_MAIN_STACK_SIZE), /* 0x00 */
43 	z_arm_reset,                                         /* 0x04 */
44 	z_arm_nmi,                                           /* 0x08 */
45 	z_arm_hard_fault,                                    /* 0x0C */
46 	z_arm_mpu_fault,                                     /* 0x10 */
47 	z_arm_bus_fault,                                     /* 0x14 */
48 	z_arm_usage_fault,                                   /* 0x18 */
49 #if defined(CONFIG_ARM_SECURE_FIRMWARE)
50 	z_arm_secure_fault, /* 0x1C */
51 #else
52 	z_arm_exc_spurious,
53 #endif                                  /* CONFIG_ARM_SECURE_FIRMWARE */
54 	(void (*)())_flash_used,        /* 0x20, imageLength. */
55 	0,                              /* 0x24, imageType (Plain Image) */
56 	0,                              /* 0x28, authBlockOffset/crcChecksum */
57 	z_arm_svc,                      /* 0x2C */
58 	z_arm_debug_monitor,            /* 0x30 */
59 	(void (*)())image_vector_table, /* 0x34, imageLoadAddress. */
60 	z_arm_pendsv,                   /* 0x38 */
61 #if defined(CONFIG_SYS_CLOCK_EXISTS) && defined(CONFIG_CORTEX_M_SYSTICK_INSTALL_ISR)
62 	sys_clock_isr, /* 0x3C */
63 #else
64 	z_arm_exc_spurious,
65 #endif
66 };
67 #endif /* CONFIG_NXP_RW6XX_BOOT_HEADER */
68 
69 const clock_avpll_config_t avpll_config = {
70 	.ch1Freq = kCLOCK_AvPllChFreq12p288m,
71 	.ch2Freq = kCLOCK_AvPllChFreq64m,
72 	.enableCali = true
73 };
74 
75 /**
76  * @brief Initialize the system clocks and peripheral clocks
77  *
78  * This function is called from the power management code as the
79  * clock needs to be re-initialized on exit from Standby mode. Hence
80  * this function is relocated to RAM.
81  */
clock_init(void)82 __ramfunc void clock_init(void)
83 {
84 	POWER_DisableGDetVSensors();
85 
86 	if ((PMU->CAU_SLP_CTRL & PMU_CAU_SLP_CTRL_SOC_SLP_RDY_MASK) == 0U) {
87 		/* LPOSC not enabled, enable it */
88 		CLOCK_EnableClock(kCLOCK_RefClkCauSlp);
89 	}
90 	if ((SYSCTL2->SOURCE_CLK_GATE & SYSCTL2_SOURCE_CLK_GATE_REFCLK_SYS_CG_MASK) != 0U) {
91 		/* REFCLK_SYS not enabled, enable it */
92 		CLOCK_EnableClock(kCLOCK_RefClkSys);
93 	}
94 
95 	/* Initialize T3 clocks and t3pll_mci_48_60m_irc configured to 48.3MHz */
96 	CLOCK_InitT3RefClk(kCLOCK_T3MciIrc48m);
97 	/* Enable FFRO */
98 	CLOCK_EnableClock(kCLOCK_T3PllMciIrcClk);
99 	/* Enable T3 256M clock and SFRO */
100 	CLOCK_EnableClock(kCLOCK_T3PllMci256mClk);
101 
102 	/* Move FLEXSPI clock source to T3 256m / 4 to avoid instruction/data fetch issue in XIP
103 	 * when updating PLL and main clock.
104 	 */
105 	set_flexspi_clock(FLEXSPI, 6U, 4U);
106 
107 	/* First let M33 run on SOSC */
108 	CLOCK_AttachClk(kSYSOSC_to_MAIN_CLK);
109 	CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1);
110 
111 	/* tcpu_mci_clk configured to 260MHz, tcpu_mci_flexspi_clk 312MHz. */
112 	CLOCK_InitTcpuRefClk(3120000000UL, kCLOCK_TcpuFlexspiDiv10);
113 	/* Enable tcpu_mci_clk 260MHz. Keep tcpu_mci_flexspi_clk gated. */
114 	CLOCK_EnableClock(kCLOCK_TcpuMciClk);
115 
116 	/* tddr_mci_flexspi_clk 320MHz */
117 	CLOCK_InitTddrRefClk(kCLOCK_TddrFlexspiDiv10);
118 	CLOCK_EnableClock(kCLOCK_TddrMciFlexspiClk); /* 320MHz */
119 
120 	/* Enable AUX0 PLL to 260 MHz */
121 	CLOCK_SetClkDiv(kCLOCK_DivAux0PllClk, 1U);
122 
123 	/* Init AVPLL and enable both channels */
124 	CLOCK_InitAvPll(&avpll_config);
125 	CLOCK_SetClkDiv(kCLOCK_DivAudioPllClk, 1U);
126 
127 	/* Configure MainPll to 260MHz, then let CM33 run on Main PLL. */
128 	CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1U);
129 	CLOCK_SetClkDiv(kCLOCK_DivMainPllClk, 1U);
130 	CLOCK_AttachClk(kMAIN_PLL_to_MAIN_CLK);
131 
132 	/* Set SYSTICKFCLKDIV divider to value 1 */
133 	CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 1U);
134 	CLOCK_AttachClk(kSYSTICK_DIV_to_SYSTICK_CLK);
135 
136 	/* Set PLL FRG clock to 20MHz. */
137 	CLOCK_SetClkDiv(kCLOCK_DivPllFrgClk, 13U);
138 
139 	/* Call function set_flexspi_clock() to set flexspi clock source to aux0_pll_clk in XIP. */
140 	set_flexspi_clock(FLEXSPI, 2U, 2U);
141 
142 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(os_timer), nxp_os_timer, okay)
143 	CLOCK_AttachClk(kLPOSC_to_OSTIMER_CLK);
144 #endif
145 
146 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(wwdt), nxp_lpc_wwdt, okay))
147 	CLOCK_AttachClk(kLPOSC_to_WDT0_CLK);
148 #else
149 	/* Allowed to select none if not being used for watchdog to
150 	 * reduce power
151 	 */
152 	CLOCK_AttachClk(kNONE_to_WDT0_CLK);
153 #endif
154 
155 #if defined(CONFIG_ADC_MCUX_GAU) || defined(CONFIG_DAC_MCUX_GAU)
156 	/* Attack clock for GAU and reset */
157 	CLOCK_AttachClk(kMAIN_CLK_to_GAU_CLK);
158 	CLOCK_SetClkDiv(kCLOCK_DivGauClk, 1U);
159 	CLOCK_EnableClock(kCLOCK_Gau);
160 	RESET_PeripheralReset(kGAU_RST_SHIFT_RSTn);
161 #endif /* GAU */
162 
163 /* Any flexcomm can be USART */
164 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_usart, okay)) && CONFIG_SERIAL
165 	CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){0, kCLOCK_FrgPllDiv, 255, 0});
166 	CLOCK_AttachClk(kFRG_to_FLEXCOMM0);
167 #endif
168 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm1), nxp_lpc_usart, okay)) && CONFIG_SERIAL
169 	CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){1, kCLOCK_FrgPllDiv, 255, 0});
170 	CLOCK_AttachClk(kFRG_to_FLEXCOMM1);
171 #endif
172 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm2), nxp_lpc_usart, okay)) && CONFIG_SERIAL
173 	CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){2, kCLOCK_FrgPllDiv, 255, 0});
174 	CLOCK_AttachClk(kFRG_to_FLEXCOMM2);
175 #endif
176 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm3), nxp_lpc_usart, okay)) && CONFIG_SERIAL
177 	CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){3, kCLOCK_FrgPllDiv, 255, 0});
178 	CLOCK_AttachClk(kFRG_to_FLEXCOMM3);
179 #endif
180 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm14), nxp_lpc_usart, okay)) && CONFIG_SERIAL
181 	CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){14, kCLOCK_FrgPllDiv, 255, 0});
182 	CLOCK_AttachClk(kFRG_to_FLEXCOMM14);
183 #endif
184 
185 /* Any flexcomm can be I2C */
186 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_i2c, okay)) && CONFIG_I2C
187 	CLOCK_AttachClk(kSFRO_to_FLEXCOMM0);
188 #endif
189 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm1), nxp_lpc_i2c, okay)) && CONFIG_I2C
190 	CLOCK_AttachClk(kSFRO_to_FLEXCOMM1);
191 #endif
192 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm2), nxp_lpc_i2c, okay)) && CONFIG_I2C
193 	CLOCK_AttachClk(kSFRO_to_FLEXCOMM2);
194 #endif
195 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm3), nxp_lpc_i2c, okay)) && CONFIG_I2C
196 	CLOCK_AttachClk(kSFRO_to_FLEXCOMM3);
197 #endif
198 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm14), nxp_lpc_i2c, okay)) && CONFIG_I2C
199 	CLOCK_AttachClk(kSFRO_to_FLEXCOMM14);
200 #endif
201 
202 /* Clock flexcomms when used as SPI */
203 #ifdef CONFIG_SPI
204 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_spi, okay))
205 	/* Set up Flexcomm0 FRG to clock at 260 MHz from main clock */
206 	const clock_frg_clk_config_t flexcomm0_frg = {0, kCLOCK_FrgMainClk, 255, 0};
207 
208 	CLOCK_SetFRGClock(&flexcomm0_frg);
209 	CLOCK_AttachClk(kFRG_to_FLEXCOMM0);
210 #endif
211 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm1), nxp_lpc_spi, okay))
212 	CLOCK_AttachClk(kSFRO_to_FLEXCOMM1);
213 #endif
214 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm2), nxp_lpc_spi, okay))
215 	CLOCK_AttachClk(kSFRO_to_FLEXCOMM2);
216 #endif
217 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm3), nxp_lpc_spi, okay))
218 	CLOCK_AttachClk(kSFRO_to_FLEXCOMM3);
219 #endif
220 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm14), nxp_lpc_spi, okay))
221 	CLOCK_AttachClk(kSFRO_to_FLEXCOMM14);
222 #endif
223 #endif /* CONFIG_SPI */
224 
225 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmic0)) && CONFIG_AUDIO_DMIC_MCUX
226 	/* Clock DMIC from Audio PLL. PLL output is sourced from AVPLL
227 	 * channel 1, which is clocked at 12.288 MHz. We can divide this
228 	 * by 4 to achieve the desired DMIC bit clk of 3.072 MHz
229 	 */
230 	CLOCK_AttachClk(kAUDIO_PLL_to_DMIC_CLK);
231 	CLOCK_SetClkDiv(kCLOCK_DivDmicClk, 4);
232 #endif
233 
234 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lcdic)) && CONFIG_MIPI_DBI_NXP_LCDIC
235 	CLOCK_AttachClk(kMAIN_CLK_to_LCD_CLK);
236 	RESET_PeripheralReset(kLCDIC_RST_SHIFT_RSTn);
237 #endif
238 
239 #ifdef CONFIG_COUNTER_MCUX_CTIMER
240 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ctimer0), nxp_lpc_ctimer, okay))
241 	CLOCK_AttachClk(kSFRO_to_CTIMER0);
242 #endif
243 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ctimer1), nxp_lpc_ctimer, okay))
244 	CLOCK_AttachClk(kSFRO_to_CTIMER1);
245 #endif
246 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ctimer2), nxp_lpc_ctimer, okay))
247 	CLOCK_AttachClk(kSFRO_to_CTIMER2);
248 #endif
249 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ctimer3), nxp_lpc_ctimer, okay))
250 	CLOCK_AttachClk(kSFRO_to_CTIMER3);
251 #endif
252 #endif /* CONFIG_COUNTER_MCUX_CTIMER */
253 
254 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usb_otg)) && CONFIG_USB_DC_NXP_EHCI
255 	/* Enable system xtal from Analog */
256 	SYSCTL2->ANA_GRP_CTRL |= SYSCTL2_ANA_GRP_CTRL_PU_AG_MASK;
257 	/* reset USB */
258 	RESET_PeripheralReset(kUSB_RST_SHIFT_RSTn);
259 	/* enable usb clock */
260 	CLOCK_EnableClock(kCLOCK_Usb);
261 	/* enable usb phy clock */
262 	CLOCK_EnableUsbhsPhyClock();
263 #endif
264 
265 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(enet)) && CONFIG_NET_L2_ETHERNET
266 	RESET_PeripheralReset(kENET_IPG_RST_SHIFT_RSTn);
267 	RESET_PeripheralReset(kENET_IPG_S_RST_SHIFT_RSTn);
268 #endif
269 
270 }
271 
272 extern void nxp_rw6xx_power_init(void);
273 /**
274  *
275  * @brief Perform basic hardware initialization
276  *
277  * Initialize the interrupt controller device drivers.
278  * Also initialize the timer device driver, if required.
279  */
280 
soc_early_init_hook(void)281 void soc_early_init_hook(void)
282 {
283 #if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(wwdt), nxp_lpc_wwdt, okay))
284 	POWER_EnableResetSource(kPOWER_ResetSourceWdt);
285 #endif
286 
287 #if DT_NODE_HAS_PROP(DT_NODELABEL(pmu), reset_causes_en)
288 #define PMU_RESET_CAUSES_ \
289 	DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(pmu), reset_causes_en, DT_PROP_BY_IDX, (|))
290 #define PMU_RESET_CAUSES \
291 	COND_CODE_0(IS_EMPTY(PMU_RESET_CAUSES_), (PMU_RESET_CAUSES_), (0))
292 #define WDT_RESET \
293 	COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(wwdt), (kPOWER_ResetSourceWdt), (0))
294 #define RESET_CAUSES \
295 	(PMU_RESET_CAUSES | WDT_RESET)
296 #else
297 #define RESET_CAUSES 0
298 #endif
299 
300 	POWER_EnableResetSource(RESET_CAUSES);
301 
302 	/* Initialize clock */
303 	clock_init();
304 
305 #if defined(CONFIG_ADC_MCUX_GAU) || defined(CONFIG_DAC_MCUX_GAU)
306 	POWER_PowerOnGau();
307 #endif
308 #if CONFIG_PM
309 	nxp_rw6xx_power_init();
310 #endif
311 
312 #if defined(CONFIG_BT) || defined(CONFIG_IEEE802154)
313 	nxp_nbu_init();
314 #endif
315 }
316 
soc_reset_hook(void)317 void soc_reset_hook(void)
318 {
319 	/* This is provided by the SDK */
320 	SystemInit();
321 }
322