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
frdm_mcxa156_init(void)18 static int frdm_mcxa156_init(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(ctimer0))
120 CLOCK_SetClockDiv(kCLOCK_DivCTIMER0, 1u);
121 CLOCK_AttachClk(kFRO_HF_to_CTIMER0);
122 #endif
123
124 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer1))
125 CLOCK_SetClockDiv(kCLOCK_DivCTIMER1, 1u);
126 CLOCK_AttachClk(kFRO_HF_to_CTIMER1);
127 #endif
128
129 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer2))
130 CLOCK_SetClockDiv(kCLOCK_DivCTIMER2, 1u);
131 CLOCK_AttachClk(kFRO_HF_to_CTIMER2);
132 #endif
133
134 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer3))
135 CLOCK_SetClockDiv(kCLOCK_DivCTIMER3, 1u);
136 CLOCK_AttachClk(kFRO_HF_to_CTIMER3);
137 #endif
138
139 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ctimer4))
140 CLOCK_SetClockDiv(kCLOCK_DivCTIMER4, 1u);
141 CLOCK_AttachClk(kFRO_HF_to_CTIMER4);
142 #endif
143
144 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dac0))
145 SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlDac0);
146 CLOCK_SetClockDiv(kCLOCK_DivDAC0, 1u);
147 CLOCK_AttachClk(kFRO12M_to_DAC0);
148
149 CLOCK_EnableClock(kCLOCK_GateDAC0);
150 #endif
151
152 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpadc0))
153 CLOCK_SetClockDiv(kCLOCK_DivADC0, 1u);
154 CLOCK_AttachClk(kFRO12M_to_ADC0);
155
156 CLOCK_EnableClock(kCLOCK_GateADC0);
157 #endif
158
159 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpcmp0))
160 CLOCK_AttachClk(kFRO12M_to_CMP0);
161 CLOCK_SetClockDiv(kCLOCK_DivCMP0_FUNC, 1U);
162 SPC_EnableActiveModeAnalogModules(SPC0, (kSPC_controlCmp0 | kSPC_controlCmp0Dac));
163 #endif
164
165 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c0))
166 CLOCK_SetClockDiv(kCLOCK_DivLPI2C0, 1u);
167 CLOCK_AttachClk(kFRO12M_to_LPI2C0);
168 #endif
169
170 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c1))
171 CLOCK_SetClockDiv(kCLOCK_DivLPI2C1, 1u);
172 CLOCK_AttachClk(kFRO12M_to_LPI2C1);
173 #endif
174
175 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c2))
176 CLOCK_SetClockDiv(kCLOCK_DivLPI2C2, 1u);
177 CLOCK_AttachClk(kFRO12M_to_LPI2C2);
178 #endif
179
180 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpi2c3))
181 CLOCK_SetClockDiv(kCLOCK_DivLPI2C3, 1u);
182 CLOCK_AttachClk(kFRO12M_to_LPI2C3);
183 #endif
184
185 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lptmr0))
186
187 /*
188 * Clock Select Decides what input source the lptmr will clock from
189 *
190 * 0 <- Reserved
191 * 1 <- 16K FRO
192 * 2 <- Reserved
193 * 3 <- Combination of clocks configured in MRCC_LPTMR0_CLKSEL[MUX] field
194 */
195 #if DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x1
196 CLOCK_SetupFRO16KClocking(kCLKE_16K_SYSTEM | kCLKE_16K_COREMAIN);
197 #elif DT_PROP(DT_NODELABEL(lptmr0), clk_source) == 0x3
198 CLOCK_SetClockDiv(kCLOCK_DivLPTMR0, 1u);
199 CLOCK_AttachClk(kFRO12M_to_LPTMR0);
200 #endif /* DT_PROP(DT_NODELABEL(lptmr0), clk_source) */
201
202 #endif
203
204 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usb))
205 RESET_PeripheralReset(kUSB0_RST_SHIFT_RSTn);
206 CLOCK_EnableUsbfsClock();
207 #endif
208
209 /* Set SystemCoreClock variable. */
210 SystemCoreClock = CLOCK_INIT_CORE_CLOCK;
211
212 return 0;
213 }
214
215 SYS_INIT(frdm_mcxa156_init, PRE_KERNEL_1, CONFIG_BOARD_INIT_PRIORITY);
216