1 /*
2 * Copyright 2024 NXP
3 * SPDX-License-Identifier: Apache-2.0
4 */
5 #include <zephyr/init.h>
6 #include <zephyr/device.h>
7 #include <zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h>
8 #include <fsl_clock.h>
9 #include <fsl_spc.h>
10 #include <soc.h>
11 #if CONFIG_USB_DC_NXP_EHCI
12 #include "usb_phy.h"
13 #include "usb.h"
14
15 /* USB PHY condfiguration */
16 #define BOARD_USB_PHY_D_CAL (0x04U)
17 #define BOARD_USB_PHY_TXCAL45DP (0x07U)
18 #define BOARD_USB_PHY_TXCAL45DM (0x07U)
19
20 usb_phy_config_struct_t usbPhyConfig = {
21 BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
22 };
23 #endif
24
25 /* Board xtal frequency in Hz */
26 #define BOARD_XTAL0_CLK_HZ 24000000U
27 /* Core clock frequency: 150MHz */
28 #define CLOCK_INIT_CORE_CLOCK 150000000U
29 /* System clock frequency. */
30 extern uint32_t SystemCoreClock;
31
32 /* Update Active mode voltage for OverDrive mode. */
power_mode_od(void)33 void power_mode_od(void)
34 {
35 /* Set the DCDC VDD regulator to 1.2 V voltage level */
36 spc_active_mode_dcdc_option_t opt = {
37 .DCDCVoltage = kSPC_DCDC_OverdriveVoltage,
38 .DCDCDriveStrength = kSPC_DCDC_NormalDriveStrength,
39 };
40 SPC_SetActiveModeDCDCRegulatorConfig(SPC0, &opt);
41
42 /* Set the LDO_CORE VDD regulator to 1.2 V voltage level */
43 spc_active_mode_core_ldo_option_t ldo_opt = {
44 .CoreLDOVoltage = kSPC_CoreLDO_OverDriveVoltage,
45 .CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength,
46 };
47 SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldo_opt);
48
49 /* Specifies the 1.2V operating voltage for the SRAM's read/write timing margin */
50 spc_sram_voltage_config_t cfg = {
51 .operateVoltage = kSPC_sramOperateAt1P2V,
52 .requestVoltageUpdate = true,
53 };
54 SPC_SetSRAMOperateVoltage(SPC0, &cfg);
55 }
56
57 #if CONFIG_FLASH_MCUX_FLEXSPI_NOR || CONFIG_FLASH_MCUX_FLEXSPI_XIP
enable_cache64(void)58 __ramfunc static void enable_cache64(void)
59 {
60 /* Make sure the FlexSPI clock is enabled before configuring the FlexSPI cache. */
61 SYSCON->AHBCLKCTRLSET[0] |= SYSCON_AHBCLKCTRL0_FLEXSPI_MASK;
62
63 /* Set command to invalidate all ways and write GO bit to initiate command */
64 CACHE64_CTRL0->CCR = CACHE64_CTRL_CCR_INVW1_MASK | CACHE64_CTRL_CCR_INVW0_MASK;
65 CACHE64_CTRL0->CCR |= CACHE64_CTRL_CCR_GO_MASK;
66 /* Wait until the command completes */
67 while ((CACHE64_CTRL0->CCR & CACHE64_CTRL_CCR_GO_MASK) != 0U) {
68 }
69 /* Enable cache, enable write buffer */
70 CACHE64_CTRL0->CCR = (CACHE64_CTRL_CCR_ENWRBUF_MASK | CACHE64_CTRL_CCR_ENCACHE_MASK);
71
72 /* configure reg0, reg1 to cover the whole FlexSPI
73 * reg 0 covers the space where Zephyr resides in case of XIP from FlexSPI
74 * reg 1 covers the storage space in case of XIP from FlexSPI
75 */
76 CACHE64_POLSEL0->REG0_TOP = 0x7FFC00;
77 CACHE64_POLSEL0->REG1_TOP = 0x0;
78 CACHE64_POLSEL0->POLSEL =
79 (CACHE64_POLSEL_POLSEL_REG0_POLICY(1) | CACHE64_POLSEL_POLSEL_REG1_POLICY(0) |
80 CACHE64_POLSEL_POLSEL_REG2_POLICY(0));
81
82 __ISB();
83 __DSB();
84 }
85 #endif
86
frdm_mcxn947_init(void)87 static int frdm_mcxn947_init(void)
88 {
89 power_mode_od();
90
91 /* Enable SCG clock */
92 CLOCK_EnableClock(kCLOCK_Scg);
93
94 /* FRO OSC setup - begin, enable the FRO for safety switching */
95
96 /* Switch to FRO 12M first to ensure we can change the clock setting */
97 CLOCK_AttachClk(kFRO12M_to_MAIN_CLK);
98
99 /* Configure Flash wait-states to support 1.2V voltage level and 150000000Hz frequency */
100 FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x3U));
101
102 /* Enable FRO HF(48MHz) output */
103 CLOCK_SetupFROHFClocking(48000000U);
104
105 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
106 /* Call function flexspi_clock_safe_config() to move FleXSPI clock to a stable
107 * clock source when updating the PLL if in XIP (execute code from FlexSPI memory
108 */
109 flexspi_clock_safe_config();
110 #endif
111
112 /* Set up PLL0 */
113 const pll_setup_t pll0Setup = {
114 .pllctrl = SCG_APLLCTRL_SOURCE(1U) | SCG_APLLCTRL_SELI(27U) |
115 SCG_APLLCTRL_SELP(13U),
116 .pllndiv = SCG_APLLNDIV_NDIV(8U),
117 .pllpdiv = SCG_APLLPDIV_PDIV(1U),
118 .pllmdiv = SCG_APLLMDIV_MDIV(50U),
119 .pllRate = 150000000U
120 };
121 /* Configure PLL0 to the desired values */
122 CLOCK_SetPLL0Freq(&pll0Setup);
123 /* PLL0 Monitor is disabled */
124 CLOCK_SetPll0MonitorMode(kSCG_Pll0MonitorDisable);
125
126 /* Switch MAIN_CLK to PLL0 */
127 CLOCK_AttachClk(kPLL0_to_MAIN_CLK);
128
129 /* Set AHBCLKDIV divider to value 1 */
130 CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U);
131
132 CLOCK_SetupExtClocking(BOARD_XTAL0_CLK_HZ);
133
134 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcan0))
135 /* Set up PLL1 for 80 MHz FlexCAN clock */
136 const pll_setup_t pll1Setup = {
137 .pllctrl = SCG_SPLLCTRL_SOURCE(1U) | SCG_SPLLCTRL_SELI(27U) |
138 SCG_SPLLCTRL_SELP(13U),
139 .pllndiv = SCG_SPLLNDIV_NDIV(3U),
140 .pllpdiv = SCG_SPLLPDIV_PDIV(1U),
141 .pllmdiv = SCG_SPLLMDIV_MDIV(10U),
142 .pllRate = 80000000U
143 };
144
145 /* Configure PLL1 to the desired values */
146 CLOCK_SetPLL1Freq(&pll1Setup);
147 /* PLL1 Monitor is disabled */
148 CLOCK_SetPll1MonitorMode(kSCG_Pll1MonitorDisable);
149 /* Set PLL1 CLK0 divider to value 1 */
150 CLOCK_SetClkDiv(kCLOCK_DivPLL1Clk0, 1U);
151 #endif
152
153 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcomm1))
154 CLOCK_SetClkDiv(kCLOCK_DivFlexcom1Clk, 1u);
155 CLOCK_AttachClk(kFRO12M_to_FLEXCOMM1);
156 #endif
157
158 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcomm2))
159 CLOCK_SetClkDiv(kCLOCK_DivFlexcom2Clk, 1u);
160 CLOCK_AttachClk(kFRO12M_to_FLEXCOMM2);
161 #endif
162
163 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcomm4))
164 CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u);
165 CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4);
166 #endif
167
168 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcomm7))
169 CLOCK_SetClkDiv(kCLOCK_DivFlexcom7Clk, 1u);
170 CLOCK_AttachClk(kFRO12M_to_FLEXCOMM7);
171 #endif
172
173 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(os_timer))
174 CLOCK_AttachClk(kCLK_1M_to_OSTIMER);
175 #endif
176
177 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio0))
178 CLOCK_EnableClock(kCLOCK_Gpio0);
179 #endif
180
181 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio1))
182 CLOCK_EnableClock(kCLOCK_Gpio1);
183 #endif
184
185 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio2))
186 CLOCK_EnableClock(kCLOCK_Gpio2);
187 #endif
188
189 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio3))
190 CLOCK_EnableClock(kCLOCK_Gpio3);
191 #endif
192
193 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio4))
194 CLOCK_EnableClock(kCLOCK_Gpio4);
195 #endif
196
197 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dac0))
198 SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlDac0);
199 CLOCK_SetClkDiv(kCLOCK_DivDac0Clk, 1u);
200 CLOCK_AttachClk(kFRO_HF_to_DAC0);
201
202 CLOCK_EnableClock(kCLOCK_Dac0);
203 #endif
204
205 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dac1))
206 SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlDac1);
207 CLOCK_SetClkDiv(kCLOCK_DivDac1Clk, 1u);
208 CLOCK_AttachClk(kFRO_HF_to_DAC1);
209
210 CLOCK_EnableClock(kCLOCK_Dac1);
211 #endif
212
213 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(enet))
214 CLOCK_AttachClk(kNONE_to_ENETRMII);
215 CLOCK_EnableClock(kCLOCK_Enet);
216 SYSCON0->PRESETCTRL2 = SYSCON_PRESETCTRL2_ENET_RST_MASK;
217 SYSCON0->PRESETCTRL2 &= ~SYSCON_PRESETCTRL2_ENET_RST_MASK;
218 /* rmii selection for this board */
219 SYSCON->ENET_PHY_INTF_SEL = SYSCON_ENET_PHY_INTF_SEL_PHY_SEL(1);
220 #endif
221
222 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(wwdt0))
223 CLOCK_SetClkDiv(kCLOCK_DivWdt0Clk, 1u);
224 #endif
225
226 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer0))
227 CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1U);
228 CLOCK_AttachClk(kPLL0_to_CTIMER0);
229 #endif
230
231 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer1))
232 CLOCK_SetClkDiv(kCLOCK_DivCtimer1Clk, 1U);
233 CLOCK_AttachClk(kPLL0_to_CTIMER1);
234 #endif
235
236 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer2))
237 CLOCK_SetClkDiv(kCLOCK_DivCtimer2Clk, 1U);
238 CLOCK_AttachClk(kPLL0_to_CTIMER2);
239 #endif
240
241 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer3))
242 CLOCK_SetClkDiv(kCLOCK_DivCtimer3Clk, 1U);
243 CLOCK_AttachClk(kPLL0_to_CTIMER3);
244 #endif
245
246 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer4))
247 CLOCK_SetClkDiv(kCLOCK_DivCtimer4Clk, 1U);
248 CLOCK_AttachClk(kPLL0_to_CTIMER4);
249 #endif
250
251 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcan0))
252 CLOCK_SetClkDiv(kCLOCK_DivFlexcan0Clk, 1U);
253 CLOCK_AttachClk(kPLL1_CLK0_to_FLEXCAN0);
254 #endif
255
256 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usdhc0))
257 CLOCK_SetClkDiv(kCLOCK_DivUSdhcClk, 1u);
258 CLOCK_AttachClk(kFRO_HF_to_USDHC);
259 #endif
260
261 #if CONFIG_FLASH_MCUX_FLEXSPI_NOR || CONFIG_FLASH_MCUX_FLEXSPI_XIP
262 /* Setup the FlexSPI clock */
263 flexspi_clock_set_freq(MCUX_FLEXSPI_CLK,
264 DT_PROP(DT_NODELABEL(w25q64jvssiq), spi_max_frequency));
265 enable_cache64();
266 #endif
267
268 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(smartdma))
269 CLOCK_EnableClock(kCLOCK_Smartdma);
270 RESET_PeripheralReset(kSMART_DMA_RST_SHIFT_RSTn);
271 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(video_sdma))
272 /* Drive CLKOUT from main clock, divided by 25 to yield 6MHz clock
273 * The camera will use this clock signal to generate
274 * PCLK, HSYNC, and VSYNC
275 */
276 CLOCK_AttachClk(kMAIN_CLK_to_CLKOUT);
277 CLOCK_SetClkDiv(kCLOCK_DivClkOut, 25U);
278 #endif
279 #endif
280
281 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(vref))
282 CLOCK_EnableClock(kCLOCK_Vref);
283 SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlVref);
284 #endif
285
286 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpadc0))
287 CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 1U);
288 CLOCK_AttachClk(kFRO_HF_to_ADC0);
289 #endif
290
291 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usb1)) && (CONFIG_USB_DC_NXP_EHCI || CONFIG_UDC_NXP_EHCI)
292 SPC0->ACTIVE_VDELAY = 0x0500;
293 /* Change the power DCDC to 1.8v (By default, DCDC is 1.8V), CORELDO to 1.1v (By default,
294 * CORELDO is 1.0V)
295 */
296 SPC0->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK;
297 SPC0->ACTIVE_CFG |= SPC_ACTIVE_CFG_DCDC_VDD_LVL(0x3) | SPC_ACTIVE_CFG_CORELDO_VDD_LVL(0x3) |
298 SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK | SPC_ACTIVE_CFG_DCDC_VDD_DS(0x2u);
299 /* Wait until it is done */
300 while (SPC0->SC & SPC_SC_BUSY_MASK) {
301 };
302 if (0u == (SCG0->LDOCSR & SCG_LDOCSR_LDOEN_MASK)) {
303 SCG0->TRIM_LOCK = 0x5a5a0001U;
304 SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
305 /* wait LDO ready */
306 while (0U == (SCG0->LDOCSR & SCG_LDOCSR_VOUT_OK_MASK)) {
307 };
308 }
309 SYSCON->AHBCLKCTRLSET[2] |= SYSCON_AHBCLKCTRL2_USB_HS_MASK |
310 SYSCON_AHBCLKCTRL2_USB_HS_PHY_MASK;
311 SCG0->SOSCCFG &= ~(SCG_SOSCCFG_RANGE_MASK | SCG_SOSCCFG_EREFS_MASK);
312 /* xtal = 20 ~ 30MHz */
313 SCG0->SOSCCFG = (1U << SCG_SOSCCFG_RANGE_SHIFT) | (1U << SCG_SOSCCFG_EREFS_SHIFT);
314 SCG0->SOSCCSR |= SCG_SOSCCSR_SOSCEN_MASK;
315 while (1) {
316 if (SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) {
317 break;
318 }
319 }
320 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK |
321 SYSCON_CLOCK_CTRL_CLKIN_ENA_FM_USBH_LPT_MASK;
322 CLOCK_EnableClock(kCLOCK_UsbHs);
323 CLOCK_EnableClock(kCLOCK_UsbHsPhy);
324 CLOCK_EnableUsbhsPhyPllClock(kCLOCK_Usbphy480M, BOARD_XTAL0_CLK_HZ);
325 CLOCK_EnableUsbhsClock();
326 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usb1)) && CONFIG_USB_DC_NXP_EHCI
327 USB_EhciPhyInit(kUSB_ControllerEhci0, BOARD_XTAL0_CLK_HZ, &usbPhyConfig);
328 #endif
329 #endif
330
331 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpcmp0))
332 CLOCK_SetClkDiv(kCLOCK_DivCmp0FClk, 1U);
333 CLOCK_AttachClk(kFRO12M_to_CMP0F);
334 SPC_EnableActiveModeAnalogModules(SPC0, (kSPC_controlCmp0 | kSPC_controlCmp0Dac));
335 #endif
336
337 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lptmr0))
338
339 /*
340 * Clock Select Decides what input source the lptmr will clock from
341 *
342 * 0 <- 12MHz FRO
343 * 1 <- 16K FRO
344 * 2 <- 32K OSC
345 * 3 <- Output from the OSC_SYS
346 */
347 #if DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x0
348 CLOCK_SetupClockCtrl(kCLOCK_FRO12MHZ_ENA);
349 #elif DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x1
350 CLOCK_SetupClk16KClocking(kCLOCK_Clk16KToVsys);
351 #elif DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x2
352 CLOCK_SetupOsc32KClocking(kCLOCK_Osc32kToVsys);
353 #elif DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x3
354 /* Value here should not exceed 25MHZ when using lptmr */
355 CLOCK_SetupExtClocking(MHZ(24));
356 CLOCK_SetupClockCtrl(kCLOCK_CLKIN_ENA_FM_USBH_LPT);
357 #endif /* DT_PROP(DT_NODELABEL(lptmr0), clk_source) */
358
359 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lptmr0)) */
360
361 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexio0))
362 CLOCK_SetClkDiv(kCLOCK_DivFlexioClk, 1u);
363 CLOCK_AttachClk(kPLL0_to_FLEXIO);
364 #endif
365
366 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i3c1), okay)
367 /* Enable 1MHz clock. */
368 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK;
369
370 CLOCK_SetClkDiv(kCLOCK_DivI3c1FClk, DT_PROP(DT_NODELABEL(i3c1), clk_divider));
371 CLOCK_SetClkDiv(kCLOCK_DivI3c1FClkS, DT_PROP(DT_NODELABEL(i3c1), clk_divider_slow));
372 CLOCK_SetClkDiv(kCLOCK_DivI3c1FClkStc, DT_PROP(DT_NODELABEL(i3c1), clk_divider_tc));
373
374 /* Attach PLL0 clock to I3C, 150MHz / 6 = 25MHz. */
375 CLOCK_AttachClk(kPLL0_to_I3C1FCLK);
376 CLOCK_AttachClk(kCLK_1M_to_I3C1FCLKS);
377 CLOCK_AttachClk(kI3C1FCLK_to_I3C1FCLKSTC);
378 #endif
379
380 #if DT_NODE_HAS_STATUS(DT_NODELABEL(sc_timer), okay)
381 /* attach FRO HF to SCT */
382 CLOCK_SetClkDiv(kCLOCK_DivSctClk, 1u);
383 CLOCK_AttachClk(kFRO_HF_to_SCT);
384 #endif
385
386 /* Set SystemCoreClock variable. */
387 SystemCoreClock = CLOCK_INIT_CORE_CLOCK;
388
389 return 0;
390 }
391
392 SYS_INIT(frdm_mcxn947_init, PRE_KERNEL_1, CONFIG_BOARD_INIT_PRIORITY);
393