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 configuration */
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 
board_early_init_hook(void)87 void board_early_init_hook(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(sai0)) || DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai1))
135 	/* < Set up PLL1 */
136 	const pll_setup_t pll1_Setup = {
137 		.pllctrl = SCG_SPLLCTRL_SOURCE(1U) | SCG_SPLLCTRL_SELI(3U) |
138 				 SCG_SPLLCTRL_SELP(1U),
139 		.pllndiv = SCG_SPLLNDIV_NDIV(25U),
140 		.pllpdiv = SCG_SPLLPDIV_PDIV(10U),
141 		.pllmdiv = SCG_SPLLMDIV_MDIV(256U),
142 		.pllRate = 24576000U};
143 
144 	/* Configure PLL1 to the desired values */
145 	CLOCK_SetPLL1Freq(&pll1_Setup);
146 	/* Set PLL1 CLK0 divider to value 1 */
147 	CLOCK_SetClkDiv(kCLOCK_DivPLL1Clk0, 1U);
148 #endif
149 
150 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcomm1))
151 	/* Configure input clock to be able to reach the datasheet specified SPI band rate. */
152 	CLOCK_SetClkDiv(kCLOCK_DivFlexcom1Clk, 1u);
153 	CLOCK_AttachClk(kFRO_HF_DIV_to_FLEXCOMM1);
154 #endif
155 
156 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcomm2))
157 	/* Configure input clock to be able to reach the datasheet specified SPI band rate. */
158 	CLOCK_SetClkDiv(kCLOCK_DivFlexcom2Clk, 1u);
159 	CLOCK_AttachClk(kFRO_HF_DIV_to_FLEXCOMM2);
160 #endif
161 
162 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcomm4))
163 	/* Configure input clock to be able to reach the datasheet specified SPI band rate. */
164 	CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u);
165 	CLOCK_AttachClk(kFRO_HF_DIV_to_FLEXCOMM4);
166 #endif
167 
168 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcomm7))
169 	/* Configure input clock to be able to reach the datasheet specified SPI band rate. */
170 	CLOCK_SetClkDiv(kCLOCK_DivFlexcom7Clk, 1u);
171 	CLOCK_AttachClk(kFRO_HF_DIV_to_FLEXCOMM7);
172 #endif
173 
174 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(os_timer))
175 	CLOCK_AttachClk(kCLK_1M_to_OSTIMER);
176 #endif
177 
178 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio0))
179 	CLOCK_EnableClock(kCLOCK_Gpio0);
180 #endif
181 
182 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio1))
183 	CLOCK_EnableClock(kCLOCK_Gpio1);
184 #endif
185 
186 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio2))
187 	CLOCK_EnableClock(kCLOCK_Gpio2);
188 #endif
189 
190 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio3))
191 	CLOCK_EnableClock(kCLOCK_Gpio3);
192 #endif
193 
194 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio4))
195 	CLOCK_EnableClock(kCLOCK_Gpio4);
196 #endif
197 
198 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dac0))
199 	SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlDac0);
200 	CLOCK_SetClkDiv(kCLOCK_DivDac0Clk, 1u);
201 	CLOCK_AttachClk(kFRO_HF_to_DAC0);
202 
203 	CLOCK_EnableClock(kCLOCK_Dac0);
204 #endif
205 
206 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dac1))
207 	SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlDac1);
208 	CLOCK_SetClkDiv(kCLOCK_DivDac1Clk, 1u);
209 	CLOCK_AttachClk(kFRO_HF_to_DAC1);
210 
211 	CLOCK_EnableClock(kCLOCK_Dac1);
212 #endif
213 
214 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(enet))
215 	CLOCK_AttachClk(kNONE_to_ENETRMII);
216 	CLOCK_EnableClock(kCLOCK_Enet);
217 	SYSCON0->PRESETCTRL2 = SYSCON_PRESETCTRL2_ENET_RST_MASK;
218 	SYSCON0->PRESETCTRL2 &= ~SYSCON_PRESETCTRL2_ENET_RST_MASK;
219 	/* rmii selection for this board */
220 	SYSCON->ENET_PHY_INTF_SEL = SYSCON_ENET_PHY_INTF_SEL_PHY_SEL(1);
221 #endif
222 
223 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(wwdt0))
224 	CLOCK_SetClkDiv(kCLOCK_DivWdt0Clk, 1u);
225 #endif
226 
227 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer0))
228 	CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1U);
229 	CLOCK_AttachClk(kPLL0_to_CTIMER0);
230 #endif
231 
232 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer1))
233 	CLOCK_SetClkDiv(kCLOCK_DivCtimer1Clk, 1U);
234 	CLOCK_AttachClk(kPLL0_to_CTIMER1);
235 #endif
236 
237 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer2))
238 	CLOCK_SetClkDiv(kCLOCK_DivCtimer2Clk, 1U);
239 	CLOCK_AttachClk(kPLL0_to_CTIMER2);
240 #endif
241 
242 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer3))
243 	CLOCK_SetClkDiv(kCLOCK_DivCtimer3Clk, 1U);
244 	CLOCK_AttachClk(kPLL0_to_CTIMER3);
245 #endif
246 
247 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer4))
248 	CLOCK_SetClkDiv(kCLOCK_DivCtimer4Clk, 1U);
249 	CLOCK_AttachClk(kPLL0_to_CTIMER4);
250 #endif
251 
252 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcan0))
253 	CLOCK_SetClkDiv(kCLOCK_DivFlexcan0Clk, 1U);
254 	CLOCK_AttachClk(kFRO_HF_to_FLEXCAN0);
255 #endif
256 
257 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usdhc0))
258 	CLOCK_SetClkDiv(kCLOCK_DivUSdhcClk, 1u);
259 	CLOCK_AttachClk(kFRO_HF_to_USDHC);
260 #endif
261 
262 #if CONFIG_FLASH_MCUX_FLEXSPI_NOR || CONFIG_FLASH_MCUX_FLEXSPI_XIP
263 	/* Setup the FlexSPI clock */
264 	flexspi_clock_set_freq(MCUX_FLEXSPI_CLK,
265 			       DT_PROP(DT_NODELABEL(w25q64jvssiq), spi_max_frequency));
266 	enable_cache64();
267 #endif
268 
269 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(smartdma))
270 	CLOCK_EnableClock(kCLOCK_Smartdma);
271 	RESET_PeripheralReset(kSMART_DMA_RST_SHIFT_RSTn);
272 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(video_sdma))
273 	/* Drive CLKOUT from main clock, divided by 25 to yield 6MHz clock
274 	 * The camera will use this clock signal to generate
275 	 * PCLK, HSYNC, and VSYNC
276 	 */
277 	CLOCK_AttachClk(kMAIN_CLK_to_CLKOUT);
278 	CLOCK_SetClkDiv(kCLOCK_DivClkOut, 25U);
279 #endif
280 #endif
281 
282 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(vref))
283 	CLOCK_EnableClock(kCLOCK_Vref);
284 	SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlVref);
285 #endif
286 
287 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpadc0))
288 	CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 1U);
289 	CLOCK_AttachClk(kFRO_HF_to_ADC0);
290 #endif
291 
292 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usb1)) && (CONFIG_USB_DC_NXP_EHCI || CONFIG_UDC_NXP_EHCI)
293 	SPC0->ACTIVE_VDELAY = 0x0500;
294 	/* Change the power DCDC to 1.8v (By default, DCDC is 1.8V), CORELDO to 1.1v (By default,
295 	 * CORELDO is 1.0V)
296 	 */
297 	SPC0->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK;
298 	SPC0->ACTIVE_CFG |= SPC_ACTIVE_CFG_DCDC_VDD_LVL(0x3) | SPC_ACTIVE_CFG_CORELDO_VDD_LVL(0x3) |
299 			    SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK | SPC_ACTIVE_CFG_DCDC_VDD_DS(0x2u);
300 	/* Wait until it is done */
301 	while (SPC0->SC & SPC_SC_BUSY_MASK) {
302 	};
303 	if (0u == (SCG0->LDOCSR & SCG_LDOCSR_LDOEN_MASK)) {
304 		SCG0->TRIM_LOCK = 0x5a5a0001U;
305 		SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
306 		/* wait LDO ready */
307 		while (0U == (SCG0->LDOCSR & SCG_LDOCSR_VOUT_OK_MASK)) {
308 		};
309 	}
310 	SYSCON->AHBCLKCTRLSET[2] |= SYSCON_AHBCLKCTRL2_USB_HS_MASK |
311 				    SYSCON_AHBCLKCTRL2_USB_HS_PHY_MASK;
312 	SCG0->SOSCCFG &= ~(SCG_SOSCCFG_RANGE_MASK | SCG_SOSCCFG_EREFS_MASK);
313 	/* xtal = 20 ~ 30MHz */
314 	SCG0->SOSCCFG = (1U << SCG_SOSCCFG_RANGE_SHIFT) | (1U << SCG_SOSCCFG_EREFS_SHIFT);
315 	SCG0->SOSCCSR |= SCG_SOSCCSR_SOSCEN_MASK;
316 	while (1) {
317 		if (SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) {
318 			break;
319 		}
320 	}
321 	SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK |
322 			      SYSCON_CLOCK_CTRL_CLKIN_ENA_FM_USBH_LPT_MASK;
323 	CLOCK_EnableClock(kCLOCK_UsbHs);
324 	CLOCK_EnableClock(kCLOCK_UsbHsPhy);
325 	CLOCK_EnableUsbhsPhyPllClock(kCLOCK_Usbphy480M, BOARD_XTAL0_CLK_HZ);
326 	CLOCK_EnableUsbhsClock();
327 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usb1)) && CONFIG_USB_DC_NXP_EHCI
328 	USB_EhciPhyInit(kUSB_ControllerEhci0, BOARD_XTAL0_CLK_HZ, &usbPhyConfig);
329 #endif
330 #endif
331 
332 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpcmp0))
333 	CLOCK_SetClkDiv(kCLOCK_DivCmp0FClk, 1U);
334 	CLOCK_AttachClk(kFRO12M_to_CMP0F);
335 	SPC_EnableActiveModeAnalogModules(SPC0, (kSPC_controlCmp0 | kSPC_controlCmp0Dac));
336 #endif
337 
338 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lptmr0))
339 
340 /*
341  * Clock Select Decides what input source the lptmr will clock from
342  *
343  * 0 <- 12MHz FRO
344  * 1 <- 16K FRO
345  * 2 <- 32K OSC
346  * 3 <- Output from the OSC_SYS
347  */
348 #if DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x0
349 	CLOCK_SetupClockCtrl(kCLOCK_FRO12MHZ_ENA);
350 #elif DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x1
351 	CLOCK_SetupClk16KClocking(kCLOCK_Clk16KToVsys);
352 #elif DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x2
353 	CLOCK_SetupOsc32KClocking(kCLOCK_Osc32kToVsys);
354 #elif DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x3
355 	/* Value here should not exceed 25MHZ when using lptmr */
356 	CLOCK_SetupExtClocking(MHZ(24));
357 	CLOCK_SetupClockCtrl(kCLOCK_CLKIN_ENA_FM_USBH_LPT);
358 #endif /* DT_PROP(DT_NODELABEL(lptmr0), clk_source) */
359 
360 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lptmr0)) */
361 
362 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexio0))
363 	CLOCK_SetClkDiv(kCLOCK_DivFlexioClk, 1u);
364 	CLOCK_AttachClk(kPLL0_to_FLEXIO);
365 #endif
366 
367 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i3c1), okay)
368 	/* Enable 1MHz clock. */
369 	SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK;
370 
371 	CLOCK_SetClkDiv(kCLOCK_DivI3c1FClk, DT_PROP(DT_NODELABEL(i3c1), clk_divider));
372 	CLOCK_SetClkDiv(kCLOCK_DivI3c1FClkS, DT_PROP(DT_NODELABEL(i3c1), clk_divider_slow));
373 	CLOCK_SetClkDiv(kCLOCK_DivI3c1FClkStc, DT_PROP(DT_NODELABEL(i3c1), clk_divider_tc));
374 
375 	/* Attach PLL0 clock to I3C, 150MHz / 6 = 25MHz. */
376 	CLOCK_AttachClk(kPLL0_to_I3C1FCLK);
377 	CLOCK_AttachClk(kCLK_1M_to_I3C1FCLKS);
378 	CLOCK_AttachClk(kI3C1FCLK_to_I3C1FCLKSTC);
379 #endif
380 
381 #if DT_NODE_HAS_STATUS(DT_NODELABEL(sc_timer), okay)
382 	/* attach FRO HF to SCT */
383 	CLOCK_SetClkDiv(kCLOCK_DivSctClk, 1u);
384 	CLOCK_AttachClk(kFRO_HF_to_SCT);
385 #endif
386 
387 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai0))
388 	CLOCK_SetClkDiv(kCLOCK_DivSai0Clk, 1u);
389 	CLOCK_AttachClk(kPLL1_CLK0_to_SAI0);
390 	CLOCK_EnableClock(kCLOCK_Sai0);
391 #endif
392 
393 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai1))
394 	CLOCK_SetClkDiv(kCLOCK_DivSai1Clk, 1u);
395 	CLOCK_AttachClk(kPLL1_CLK0_to_SAI1);
396 	CLOCK_EnableClock(kCLOCK_Sai1);
397 #endif
398 
399 	/* Set SystemCoreClock variable. */
400 	SystemCoreClock = CLOCK_INIT_CORE_CLOCK;
401 }
402