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 #endif
20 
21 /* Board xtal frequency in Hz */
22 #define BOARD_XTAL0_CLK_HZ                        24000000U
23 /* Core clock frequency: 150MHz */
24 #define CLOCK_INIT_CORE_CLOCK                     150000000U
25 /* System clock frequency. */
26 extern uint32_t SystemCoreClock;
27 
enable_lpcac(void)28 __ramfunc static void enable_lpcac(void)
29 {
30 	SYSCON->LPCAC_CTRL |= SYSCON_LPCAC_CTRL_CLR_LPCAC_MASK;
31 	SYSCON->LPCAC_CTRL &= ~(SYSCON_LPCAC_CTRL_CLR_LPCAC_MASK |
32 				SYSCON_LPCAC_CTRL_DIS_LPCAC_MASK);
33 }
34 
35 /* Update Active mode voltage for OverDrive mode. */
power_mode_od(void)36 void power_mode_od(void)
37 {
38 	/* Set the DCDC VDD regulator to 1.2 V voltage level */
39 	spc_active_mode_dcdc_option_t opt = {
40 		.DCDCVoltage       = kSPC_DCDC_OverdriveVoltage,
41 		.DCDCDriveStrength = kSPC_DCDC_NormalDriveStrength,
42 	};
43 	SPC_SetActiveModeDCDCRegulatorConfig(SPC0, &opt);
44 
45 	/* Set the LDO_CORE VDD regulator to 1.2 V voltage level */
46 	spc_active_mode_core_ldo_option_t ldo_opt = {
47 		.CoreLDOVoltage       = kSPC_CoreLDO_OverDriveVoltage,
48 		.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength,
49 	};
50 	SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldo_opt);
51 
52 	/* Specifies the 1.2V operating voltage for the SRAM's read/write timing margin */
53 	spc_sram_voltage_config_t cfg = {
54 		.operateVoltage       = kSPC_sramOperateAt1P2V,
55 		.requestVoltageUpdate = true,
56 	};
57 	SPC_SetSRAMOperateVoltage(SPC0, &cfg);
58 }
59 
frdm_mcxn947_init(void)60 static int frdm_mcxn947_init(void)
61 {
62 	enable_lpcac();
63 
64 	power_mode_od();
65 
66 	/* Enable SCG clock */
67 	CLOCK_EnableClock(kCLOCK_Scg);
68 
69 	/* FRO OSC setup - begin, enable the FRO for safety switching */
70 
71 	/* Switch to FRO 12M first to ensure we can change the clock setting */
72 	CLOCK_AttachClk(kFRO12M_to_MAIN_CLK);
73 
74 	/* Configure Flash wait-states to support 1.2V voltage level and 150000000Hz frequency */
75 	FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x3U));
76 
77 	/* Enable FRO HF(48MHz) output */
78 	CLOCK_SetupFROHFClocking(48000000U);
79 
80 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
81 	/* Call function flexspi_clock_safe_config() to move FleXSPI clock to a stable
82 	 * clock source when updating the PLL if in XIP (execute code from FlexSPI memory
83 	 */
84 	flexspi_clock_safe_config();
85 #endif
86 
87 	/* Set up PLL0 */
88 	const pll_setup_t pll0Setup = {
89 		.pllctrl = SCG_APLLCTRL_SOURCE(1U) | SCG_APLLCTRL_SELI(27U) |
90 			   SCG_APLLCTRL_SELP(13U),
91 		.pllndiv = SCG_APLLNDIV_NDIV(8U),
92 		.pllpdiv = SCG_APLLPDIV_PDIV(1U),
93 		.pllmdiv = SCG_APLLMDIV_MDIV(50U),
94 		.pllRate = 150000000U
95 	};
96 	/* Configure PLL0 to the desired values */
97 	CLOCK_SetPLL0Freq(&pll0Setup);
98 	/* PLL0 Monitor is disabled */
99 	CLOCK_SetPll0MonitorMode(kSCG_Pll0MonitorDisable);
100 
101 	/* Switch MAIN_CLK to PLL0 */
102 	CLOCK_AttachClk(kPLL0_to_MAIN_CLK);
103 
104 	/* Set AHBCLKDIV divider to value 1 */
105 	CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U);
106 
107 	CLOCK_SetupExtClocking(BOARD_XTAL0_CLK_HZ);
108 
109 #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan0), okay)
110 	/* Set up PLL1 for 80 MHz FlexCAN clock */
111 	const pll_setup_t pll1Setup = {
112 		.pllctrl = SCG_SPLLCTRL_SOURCE(1U) | SCG_SPLLCTRL_SELI(27U) |
113 			   SCG_SPLLCTRL_SELP(13U),
114 		.pllndiv = SCG_SPLLNDIV_NDIV(3U),
115 		.pllpdiv = SCG_SPLLPDIV_PDIV(1U),
116 		.pllmdiv = SCG_SPLLMDIV_MDIV(10U),
117 		.pllRate = 80000000U
118 	};
119 
120 	/* Configure PLL1 to the desired values */
121 	CLOCK_SetPLL1Freq(&pll1Setup);
122 	/* PLL1 Monitor is disabled */
123 	CLOCK_SetPll1MonitorMode(kSCG_Pll1MonitorDisable);
124 	/* Set PLL1 CLK0 divider to value 1 */
125 	CLOCK_SetClkDiv(kCLOCK_DivPLL1Clk0, 1U);
126 #endif
127 
128 #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcomm1), okay)
129 	CLOCK_SetClkDiv(kCLOCK_DivFlexcom1Clk, 1u);
130 	CLOCK_AttachClk(kFRO12M_to_FLEXCOMM1);
131 #endif
132 
133 #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcomm2), okay)
134 	CLOCK_SetClkDiv(kCLOCK_DivFlexcom2Clk, 1u);
135 	CLOCK_AttachClk(kFRO12M_to_FLEXCOMM2);
136 #endif
137 
138 #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcomm4), okay)
139 	CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u);
140 	CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4);
141 #endif
142 
143 #if DT_NODE_HAS_STATUS(DT_NODELABEL(os_timer), okay)
144 	CLOCK_AttachClk(kCLK_1M_to_OSTIMER);
145 #endif
146 
147 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio0), okay)
148 	CLOCK_EnableClock(kCLOCK_Gpio0);
149 #endif
150 
151 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
152 	CLOCK_EnableClock(kCLOCK_Gpio1);
153 #endif
154 
155 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio2), okay)
156 	CLOCK_EnableClock(kCLOCK_Gpio2);
157 #endif
158 
159 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio3), okay)
160 	CLOCK_EnableClock(kCLOCK_Gpio3);
161 #endif
162 
163 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio4), okay)
164 	CLOCK_EnableClock(kCLOCK_Gpio4);
165 #endif
166 
167 #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio5), okay)
168 	CLOCK_EnableClock(kCLOCK_Gpio5);
169 #endif
170 
171 #if DT_NODE_HAS_STATUS(DT_NODELABEL(dac0), okay)
172 	SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlDac0);
173 	CLOCK_SetClkDiv(kCLOCK_DivDac0Clk, 1u);
174 	CLOCK_AttachClk(kFRO_HF_to_DAC0);
175 
176 	CLOCK_EnableClock(kCLOCK_Dac0);
177 #endif
178 
179 #if DT_NODE_HAS_STATUS(DT_NODELABEL(dac1), okay)
180 	SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlDac1);
181 	CLOCK_SetClkDiv(kCLOCK_DivDac1Clk, 1u);
182 	CLOCK_AttachClk(kFRO_HF_to_DAC1);
183 
184 	CLOCK_EnableClock(kCLOCK_Dac1);
185 #endif
186 
187 #if DT_NODE_HAS_STATUS(DT_NODELABEL(enet), okay)
188 	CLOCK_AttachClk(kNONE_to_ENETRMII);
189 	CLOCK_EnableClock(kCLOCK_Enet);
190 	SYSCON0->PRESETCTRL2 = SYSCON_PRESETCTRL2_ENET_RST_MASK;
191 	SYSCON0->PRESETCTRL2 &= ~SYSCON_PRESETCTRL2_ENET_RST_MASK;
192 	/* rmii selection for this board */
193 	SYSCON->ENET_PHY_INTF_SEL = SYSCON_ENET_PHY_INTF_SEL_PHY_SEL(1);
194 #endif
195 
196 #if DT_NODE_HAS_STATUS(DT_NODELABEL(wwdt0), okay)
197 	CLOCK_SetClkDiv(kCLOCK_DivWdt0Clk, 1u);
198 #endif
199 
200 #if DT_NODE_HAS_STATUS(DT_NODELABEL(ctimer0), okay)
201 	CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1U);
202 	CLOCK_AttachClk(kPLL0_to_CTIMER0);
203 #endif
204 
205 #if DT_NODE_HAS_STATUS(DT_NODELABEL(ctimer1), okay)
206 	CLOCK_SetClkDiv(kCLOCK_DivCtimer1Clk, 1U);
207 	CLOCK_AttachClk(kPLL0_to_CTIMER1);
208 #endif
209 
210 #if DT_NODE_HAS_STATUS(DT_NODELABEL(ctimer2), okay)
211 	CLOCK_SetClkDiv(kCLOCK_DivCtimer2Clk, 1U);
212 	CLOCK_AttachClk(kPLL0_to_CTIMER2);
213 #endif
214 
215 #if DT_NODE_HAS_STATUS(DT_NODELABEL(ctimer3), okay)
216 	CLOCK_SetClkDiv(kCLOCK_DivCtimer3Clk, 1U);
217 	CLOCK_AttachClk(kPLL0_to_CTIMER3);
218 #endif
219 
220 #if DT_NODE_HAS_STATUS(DT_NODELABEL(ctimer4), okay)
221 	CLOCK_SetClkDiv(kCLOCK_DivCtimer4Clk, 1U);
222 	CLOCK_AttachClk(kPLL0_to_CTIMER4);
223 #endif
224 
225 #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan0), okay)
226 	CLOCK_SetClkDiv(kCLOCK_DivFlexcan0Clk, 1U);
227 	CLOCK_AttachClk(kPLL1_CLK0_to_FLEXCAN0);
228 #endif
229 
230 #if DT_NODE_HAS_STATUS(DT_NODELABEL(usdhc0), okay)
231 	CLOCK_SetClkDiv(kCLOCK_DivUSdhcClk, 1u);
232 	CLOCK_AttachClk(kFRO_HF_to_USDHC);
233 #endif
234 
235 #if CONFIG_FLASH_MCUX_FLEXSPI_NOR
236 	/* We downclock the FlexSPI to 50MHz, it will be set to the
237 	 * optimum speed supported by the Flash device during FLEXSPI
238 	 * Init
239 	 */
240 	flexspi_clock_set_freq(MCUX_FLEXSPI_CLK, MHZ(50));
241 #endif
242 
243 #if DT_NODE_HAS_STATUS(DT_NODELABEL(vref), okay)
244 	CLOCK_EnableClock(kCLOCK_Vref);
245 	SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlVref);
246 #endif
247 
248 #if DT_NODE_HAS_STATUS(DT_NODELABEL(lpadc0), okay)
249 	CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 1U);
250 	CLOCK_AttachClk(kFRO_HF_to_ADC0);
251 #endif
252 
253 #if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) && CONFIG_USB_DC_NXP_EHCI
254 	usb_phy_config_struct_t usbPhyConfig = {
255 		BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
256 	};
257 
258 	SPC0->ACTIVE_VDELAY = 0x0500;
259 	/* Change the power DCDC to 1.8v (By default, DCDC is 1.8V), CORELDO to 1.1v (By default,
260 	 * CORELDO is 1.0V)
261 	 */
262 	SPC0->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK;
263 	SPC0->ACTIVE_CFG |= SPC_ACTIVE_CFG_DCDC_VDD_LVL(0x3) | SPC_ACTIVE_CFG_CORELDO_VDD_LVL(0x3) |
264 			    SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK | SPC_ACTIVE_CFG_DCDC_VDD_DS(0x2u);
265 	/* Wait until it is done */
266 	while (SPC0->SC & SPC_SC_BUSY_MASK) {
267 	};
268 	if (0u == (SCG0->LDOCSR & SCG_LDOCSR_LDOEN_MASK)) {
269 		SCG0->TRIM_LOCK = 0x5a5a0001U;
270 		SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK;
271 		/* wait LDO ready */
272 		while (0U == (SCG0->LDOCSR & SCG_LDOCSR_VOUT_OK_MASK)) {
273 		};
274 	}
275 	SYSCON->AHBCLKCTRLSET[2] |= SYSCON_AHBCLKCTRL2_USB_HS_MASK |
276 				    SYSCON_AHBCLKCTRL2_USB_HS_PHY_MASK;
277 	SCG0->SOSCCFG &= ~(SCG_SOSCCFG_RANGE_MASK | SCG_SOSCCFG_EREFS_MASK);
278 	/* xtal = 20 ~ 30MHz */
279 	SCG0->SOSCCFG = (1U << SCG_SOSCCFG_RANGE_SHIFT) | (1U << SCG_SOSCCFG_EREFS_SHIFT);
280 	SCG0->SOSCCSR |= SCG_SOSCCSR_SOSCEN_MASK;
281 	while (1) {
282 		if (SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) {
283 			break;
284 		}
285 	}
286 	SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK |
287 			      SYSCON_CLOCK_CTRL_CLKIN_ENA_FM_USBH_LPT_MASK;
288 	CLOCK_EnableClock(kCLOCK_UsbHs);
289 	CLOCK_EnableClock(kCLOCK_UsbHsPhy);
290 	CLOCK_EnableUsbhsPhyPllClock(kCLOCK_Usbphy480M, BOARD_XTAL0_CLK_HZ);
291 	CLOCK_EnableUsbhsClock();
292 	USB_EhciPhyInit(kUSB_ControllerEhci0, BOARD_XTAL0_CLK_HZ, &usbPhyConfig);
293 #endif
294 
295 #if DT_NODE_HAS_STATUS(DT_NODELABEL(lpcmp0), okay)
296 	CLOCK_SetClkDiv(kCLOCK_DivCmp0FClk, 1U);
297 	CLOCK_AttachClk(kFRO12M_to_CMP0F);
298 	SPC_EnableActiveModeAnalogModules(SPC0, (kSPC_controlCmp0 | kSPC_controlCmp0Dac));
299 #endif
300 
301 #if DT_NODE_HAS_STATUS(DT_NODELABEL(lptmr0), okay)
302 	CLOCK_SetupClk16KClocking(kCLOCK_Clk16KToVsys);
303 #endif
304 
305 #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexio0), okay)
306 	CLOCK_SetClkDiv(kCLOCK_DivFlexioClk, 1u);
307 	CLOCK_AttachClk(kPLL0_to_FLEXIO);
308 #endif
309 
310 	/* Set SystemCoreClock variable. */
311 	SystemCoreClock = CLOCK_INIT_CORE_CLOCK;
312 
313 	return 0;
314 }
315 
316 SYS_INIT(frdm_mcxn947_init, PRE_KERNEL_1, CONFIG_BOARD_INIT_PRIORITY);
317