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 
12 /* Core clock frequency: 150MHz */
13 #define CLOCK_INIT_CORE_CLOCK            960000000U
14 #define BOARD_BOOTCLOCKFRO96M_CORE_CLOCK 960000000U
15 /* System clock frequency. */
16 extern uint32_t SystemCoreClock;
17 
board_early_init_hook(void)18 void board_early_init_hook(void)
19 {
20 	uint32_t coreFreq;
21 	spc_active_mode_core_ldo_option_t ldoOption;
22 	spc_sram_voltage_config_t sramOption;
23 
24 	/* Get the CPU Core frequency */
25 	coreFreq = CLOCK_GetCoreSysClkFreq();
26 
27 	/* The flow of increasing voltage and frequency */
28 	if (coreFreq <= BOARD_BOOTCLOCKFRO96M_CORE_CLOCK) {
29 		/* Set the LDO_CORE VDD regulator level */
30 		ldoOption.CoreLDOVoltage = kSPC_CoreLDO_NormalVoltage;
31 		ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength;
32 		(void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption);
33 		/* Configure Flash to support different voltage level and frequency */
34 		FMU0->FCTRL =
35 			(FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x2U));
36 		/* Specifies the operating voltage for the SRAM's read/write timing margin */
37 		sramOption.operateVoltage = kSPC_sramOperateAt1P1V;
38 		sramOption.requestVoltageUpdate = true;
39 		(void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption);
40 	}
41 
42 	CLOCK_SetupFROHFClocking(96000000U); /*!< Enable FRO HF(96MHz) output */
43 
44 	CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */
45 
46 	CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /* !< Switch MAIN_CLK to FRO_HF */
47 
48 	/* The flow of decreasing voltage and frequency */
49 	if (coreFreq > BOARD_BOOTCLOCKFRO96M_CORE_CLOCK) {
50 		/* Configure Flash to support different voltage level and frequency */
51 		FMU0->FCTRL =
52 			(FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x2U));
53 		/* Specifies the operating voltage for the SRAM's read/write timing margin */
54 		sramOption.operateVoltage = kSPC_sramOperateAt1P1V;
55 		sramOption.requestVoltageUpdate = true;
56 		(void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption);
57 		/* Set the LDO_CORE VDD regulator level */
58 		ldoOption.CoreLDOVoltage = kSPC_CoreLDO_NormalVoltage;
59 		ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength;
60 		(void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption);
61 	}
62 
63 	/*!< Set up clock selectors - Attach clocks to the peripheries */
64 
65 	/*!< Set up dividers */
66 	CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U);     /* !< Set AHBCLKDIV divider to value 1 */
67 	CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */
68 
69 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(porta))
70 	RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn);
71 #endif
72 
73 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(portb))
74 	RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn);
75 #endif
76 
77 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(portc))
78 	RESET_ReleasePeripheralReset(kPORT2_RST_SHIFT_RSTn);
79 #endif
80 
81 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(portd))
82 	RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn);
83 #endif
84 
85 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(porte))
86 	RESET_ReleasePeripheralReset(kPORT4_RST_SHIFT_RSTn);
87 #endif
88 
89 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio0))
90 	RESET_ReleasePeripheralReset(kGPIO0_RST_SHIFT_RSTn);
91 	CLOCK_EnableClock(kCLOCK_GateGPIO0);
92 #endif
93 
94 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio1))
95 	RESET_ReleasePeripheralReset(kGPIO1_RST_SHIFT_RSTn);
96 	CLOCK_EnableClock(kCLOCK_GateGPIO1);
97 #endif
98 
99 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio2))
100 	RESET_ReleasePeripheralReset(kGPIO2_RST_SHIFT_RSTn);
101 	CLOCK_EnableClock(kCLOCK_GateGPIO2);
102 #endif
103 
104 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio3))
105 	RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn);
106 	CLOCK_EnableClock(kCLOCK_GateGPIO3);
107 #endif
108 
109 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio4))
110 	RESET_ReleasePeripheralReset(kGPIO4_RST_SHIFT_RSTn);
111 	CLOCK_EnableClock(kCLOCK_GateGPIO4);
112 #endif
113 
114 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpuart0))
115 	CLOCK_SetClockDiv(kCLOCK_DivLPUART0, 1u);
116 	CLOCK_AttachClk(kFRO12M_to_LPUART0);
117 #endif
118 
119 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpuart1))
120 	CLOCK_SetClockDiv(kCLOCK_DivLPUART1, 1u);
121 	CLOCK_AttachClk(kFRO12M_to_LPUART1);
122 #endif
123 
124 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer0))
125 	CLOCK_SetClockDiv(kCLOCK_DivCTIMER0, 1u);
126 	CLOCK_AttachClk(kFRO_HF_to_CTIMER0);
127 #endif
128 
129 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer1))
130 	CLOCK_SetClockDiv(kCLOCK_DivCTIMER1, 1u);
131 	CLOCK_AttachClk(kFRO_HF_to_CTIMER1);
132 #endif
133 
134 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer2))
135 	CLOCK_SetClockDiv(kCLOCK_DivCTIMER2, 1u);
136 	CLOCK_AttachClk(kFRO_HF_to_CTIMER2);
137 #endif
138 
139 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer3))
140 	CLOCK_SetClockDiv(kCLOCK_DivCTIMER3, 1u);
141 	CLOCK_AttachClk(kFRO_HF_to_CTIMER3);
142 #endif
143 
144 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer4))
145 	CLOCK_SetClockDiv(kCLOCK_DivCTIMER4, 1u);
146 	CLOCK_AttachClk(kFRO_HF_to_CTIMER4);
147 #endif
148 
149 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dac0))
150 	SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlDac0);
151 	CLOCK_SetClockDiv(kCLOCK_DivDAC0, 1u);
152 	CLOCK_AttachClk(kFRO12M_to_DAC0);
153 
154 	CLOCK_EnableClock(kCLOCK_GateDAC0);
155 #endif
156 
157 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcan0))
158 	CLOCK_SetClockDiv(kCLOCK_DivFLEXCAN0, 1U);
159 	CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U);
160 	CLOCK_AttachClk(kFRO_HF_DIV_to_FLEXCAN0);
161 #endif
162 
163 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexio0))
164 	CLOCK_SetClockDiv(kCLOCK_DivFLEXIO0, 1u);
165 	CLOCK_AttachClk(kFRO_HF_to_FLEXIO0);
166 #endif
167 
168 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpadc0))
169 	CLOCK_SetClockDiv(kCLOCK_DivADC0, 1u);
170 	CLOCK_AttachClk(kFRO12M_to_ADC0);
171 
172 	CLOCK_EnableClock(kCLOCK_GateADC0);
173 #endif
174 
175 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpcmp0))
176 	CLOCK_AttachClk(kFRO12M_to_CMP0);
177 	CLOCK_SetClockDiv(kCLOCK_DivCMP0_FUNC, 1U);
178 	SPC_EnableActiveModeAnalogModules(SPC0, (kSPC_controlCmp0 | kSPC_controlCmp0Dac));
179 #endif
180 
181 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c0))
182 	CLOCK_SetClockDiv(kCLOCK_DivLPI2C0, 1u);
183 	CLOCK_AttachClk(kFRO12M_to_LPI2C0);
184 #endif
185 
186 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c1))
187 	CLOCK_SetClockDiv(kCLOCK_DivLPI2C1, 1u);
188 	CLOCK_AttachClk(kFRO12M_to_LPI2C1);
189 #endif
190 
191 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c2))
192 	CLOCK_SetClockDiv(kCLOCK_DivLPI2C2, 1u);
193 	CLOCK_AttachClk(kFRO12M_to_LPI2C2);
194 #endif
195 
196 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c3))
197 	CLOCK_SetClockDiv(kCLOCK_DivLPI2C3, 1u);
198 	CLOCK_AttachClk(kFRO12M_to_LPI2C3);
199 #endif
200 
201 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpspi0))
202 	/* Configure input clock to be able to reach the datasheet specified band rate. */
203 	CLOCK_SetClockDiv(kCLOCK_DivLPSPI0, 1u);
204 	CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI0);
205 #endif
206 
207 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpspi1))
208 	/* Configure input clock to be able to reach the datasheet specified band rate. */
209 	CLOCK_SetClockDiv(kCLOCK_DivLPSPI1, 1u);
210 	CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI1);
211 #endif
212 
213 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lptmr0))
214 
215 /*
216  * Clock Select Decides what input source the lptmr will clock from
217  *
218  * 0 <- Reserved
219  * 1 <- 16K FRO
220  * 2 <- Reserved
221  * 3 <- Combination of clocks configured in MRCC_LPTMR0_CLKSEL[MUX] field
222  */
223 #if DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x1
224 	CLOCK_SetupFRO16KClocking(kCLKE_16K_SYSTEM | kCLKE_16K_COREMAIN);
225 #elif DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x3
226 	CLOCK_SetClockDiv(kCLOCK_DivLPTMR0, 1u);
227 	CLOCK_AttachClk(kFRO12M_to_LPTMR0);
228 #endif /* DT_PROP(DT_NODELABEL(lptmr0), clk_source) */
229 
230 #endif
231 
232 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usb))
233 	RESET_PeripheralReset(kUSB0_RST_SHIFT_RSTn);
234 	CLOCK_EnableUsbfsClock();
235 #endif
236 
237 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(wwdt0))
238 	CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1u);
239 #endif
240 
241 	/* Set SystemCoreClock variable. */
242 	SystemCoreClock = CLOCK_INIT_CORE_CLOCK;
243 }
244