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