1 /*
2 * Copyright 2021,2024 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_imx_ccm_rev2
8 #include <errno.h>
9 #include <zephyr/drivers/clock_control.h>
10 #include <zephyr/dt-bindings/clock/imx_ccm_rev2.h>
11 #include <fsl_clock.h>
12
13 #define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(clock_control);
16
mcux_ccm_on(const struct device * dev,clock_control_subsys_t sub_system)17 static int mcux_ccm_on(const struct device *dev,
18 clock_control_subsys_t sub_system)
19 {
20 uint32_t clock_name = (uintptr_t)sub_system;
21 uint32_t peripheral, instance;
22
23 peripheral = (clock_name & IMX_CCM_PERIPHERAL_MASK);
24 instance = (clock_name & IMX_CCM_INSTANCE_MASK);
25 switch (peripheral) {
26 #ifdef CONFIG_ETH_NXP_ENET
27
28 #ifdef CONFIG_SOC_MIMX9352
29 #define ENET1G_CLOCK kCLOCK_Enet1
30 #else
31 #define ENET_CLOCK kCLOCK_Enet
32 #define ENET1G_CLOCK kCLOCK_Enet_1g
33 #endif
34 #ifdef ENET_CLOCK
35 case IMX_CCM_ENET_CLK:
36 CLOCK_EnableClock(ENET_CLOCK);
37 return 0;
38 #endif
39 case IMX_CCM_ENET1G_CLK:
40 CLOCK_EnableClock(ENET1G_CLOCK);
41 return 0;
42 #endif
43 default:
44 (void)instance;
45 return 0;
46 }
47 }
48
mcux_ccm_off(const struct device * dev,clock_control_subsys_t sub_system)49 static int mcux_ccm_off(const struct device *dev,
50 clock_control_subsys_t sub_system)
51 {
52 return 0;
53 }
54
mcux_ccm_get_subsys_rate(const struct device * dev,clock_control_subsys_t sub_system,uint32_t * rate)55 static int mcux_ccm_get_subsys_rate(const struct device *dev,
56 clock_control_subsys_t sub_system,
57 uint32_t *rate)
58 {
59 uint32_t clock_name = (size_t) sub_system;
60 uint32_t clock_root, peripheral, instance;
61
62 peripheral = (clock_name & IMX_CCM_PERIPHERAL_MASK);
63 instance = (clock_name & IMX_CCM_INSTANCE_MASK);
64 switch (peripheral) {
65 #ifdef CONFIG_I2C_MCUX_LPI2C
66 #if defined(CONFIG_SOC_SERIES_IMXRT118X)
67 case IMX_CCM_LPI2C0102_CLK:
68 clock_root = kCLOCK_Root_Lpi2c0102 + instance;
69 break;
70 #else
71 case IMX_CCM_LPI2C1_CLK:
72 clock_root = kCLOCK_Root_Lpi2c1 + instance;
73 break;
74 #endif
75 #endif
76
77 #ifdef CONFIG_I3C_MCUX
78 case IMX_CCM_I3C1_CLK:
79 case IMX_CCM_I3C2_CLK:
80 clock_root = kCLOCK_Root_I3c1 + instance;
81 break;
82 #endif
83
84 #ifdef CONFIG_SPI_MCUX_LPSPI
85 case IMX_CCM_LPSPI1_CLK:
86 clock_root = kCLOCK_Root_Lpspi1 + instance;
87 break;
88 #endif
89
90 #ifdef CONFIG_UART_MCUX_LPUART
91 #if defined(CONFIG_SOC_SERIES_IMXRT118X)
92 case IMX_CCM_LPUART0102_CLK:
93 case IMX_CCM_LPUART0304_CLK:
94 clock_root = kCLOCK_Root_Lpuart0102 + instance;
95 break;
96 #else
97 case IMX_CCM_LPUART1_CLK:
98 case IMX_CCM_LPUART2_CLK:
99 clock_root = kCLOCK_Root_Lpuart1 + instance;
100 break;
101 #endif
102 #endif
103
104 #if CONFIG_IMX_USDHC
105 case IMX_CCM_USDHC1_CLK:
106 case IMX_CCM_USDHC2_CLK:
107 clock_root = kCLOCK_Root_Usdhc1 + instance;
108 break;
109 #endif
110
111 #ifdef CONFIG_DMA_MCUX_EDMA
112 case IMX_CCM_EDMA_CLK:
113 clock_root = kCLOCK_Root_Bus;
114 break;
115 case IMX_CCM_EDMA_LPSR_CLK:
116 clock_root = kCLOCK_Root_Bus_Lpsr;
117 break;
118 #endif
119
120 #ifdef CONFIG_PWM_MCUX
121 #if defined(CONFIG_SOC_SERIES_IMXRT118X)
122 case IMX_CCM_PWM_CLK:
123 clock_root = kCLOCK_Root_Bus_Aon;
124 break;
125 #else
126 case IMX_CCM_PWM_CLK:
127 clock_root = kCLOCK_Root_Bus;
128 break;
129 #endif /* CONFIG_SOC_SERIES_IMXRT118X */
130 #endif /* CONFIG_PWM_MCUX */
131
132 #ifdef CONFIG_CAN_MCUX_FLEXCAN
133 case IMX_CCM_CAN1_CLK:
134 clock_root = kCLOCK_Root_Can1 + instance;
135 break;
136 #endif
137
138 #ifdef CONFIG_COUNTER_MCUX_GPT
139 case IMX_CCM_GPT_CLK:
140 clock_root = kCLOCK_Root_Gpt1 + instance;
141 break;
142 #endif
143
144 #ifdef CONFIG_I2S_MCUX_SAI
145 case IMX_CCM_SAI1_CLK:
146 clock_root = kCLOCK_Root_Sai1;
147 break;
148 case IMX_CCM_SAI2_CLK:
149 clock_root = kCLOCK_Root_Sai2;
150 break;
151 case IMX_CCM_SAI3_CLK:
152 clock_root = kCLOCK_Root_Sai3;
153 break;
154 case IMX_CCM_SAI4_CLK:
155 clock_root = kCLOCK_Root_Sai4;
156 break;
157 #endif
158
159 #ifdef CONFIG_ETH_NXP_ENET
160 case IMX_CCM_ENET_CLK:
161 case IMX_CCM_ENET1G_CLK:
162 #ifdef CONFIG_SOC_MIMX9352
163 clock_root = kCLOCK_Root_WakeupAxi;
164 #else
165 clock_root = kCLOCK_Root_Bus;
166 #endif
167 break;
168 #endif
169
170 #if defined(CONFIG_SOC_MIMX9352) && defined(CONFIG_DAI_NXP_SAI)
171 case IMX_CCM_SAI1_CLK:
172 case IMX_CCM_SAI2_CLK:
173 case IMX_CCM_SAI3_CLK:
174 clock_root = kCLOCK_Root_Sai1 + instance;
175 uint32_t mux = CLOCK_GetRootClockMux(clock_root);
176 uint32_t divider = CLOCK_GetRootClockDiv(clock_root);
177
178 /* assumption: SAI's SRC is AUDIO_PLL */
179 if (mux != 1) {
180 return -EINVAL;
181 }
182
183 /* assumption: AUDIO_PLL's frequency is 393216000 Hz */
184 *rate = 393216000 / divider;
185
186 return 0;
187 #endif
188 #if defined(CONFIG_COUNTER_MCUX_TPM) || defined(CONFIG_PWM_MCUX_TPM)
189 #if defined(CONFIG_SOC_SERIES_IMXRT118X)
190 case IMX_CCM_TPM_CLK:
191 switch (instance) {
192 case 0:
193 clock_root = kCLOCK_Root_Bus_Aon;
194 break;
195 case 1:
196 clock_root = kCLOCK_Root_Tpm2;
197 break;
198 case 2:
199 clock_root = kCLOCK_Root_Bus_Wakeup;
200 break;
201 default:
202 clock_root = (kCLOCK_Root_Tpm4 + instance - 3);
203 }
204 break;
205 #else
206 case IMX_CCM_TPM_CLK:
207 clock_root = kCLOCK_Root_Tpm1 + instance;
208 break;
209 #endif
210 #endif
211
212 #ifdef CONFIG_MCUX_FLEXIO
213 case IMX_CCM_FLEXIO1_CLK:
214 clock_root = kCLOCK_Root_Flexio1;
215 break;
216 case IMX_CCM_FLEXIO2_CLK:
217 clock_root = kCLOCK_Root_Flexio2;
218 break;
219 #endif
220
221 #if defined(CONFIG_PWM_MCUX_QTMR) || defined(CONFIG_COUNTER_MCUX_QTMR)
222 #if defined(CONFIG_SOC_SERIES_IMXRT118X)
223 case IMX_CCM_QTMR_CLK:
224 clock_root = kCLOCK_Root_Bus_Aon;
225 break;
226 #else
227 case IMX_CCM_QTMR1_CLK:
228 case IMX_CCM_QTMR2_CLK:
229 case IMX_CCM_QTMR3_CLK:
230 case IMX_CCM_QTMR4_CLK:
231 clock_root = kCLOCK_Root_Bus;
232 break;
233 #endif /* CONFIG_SOC_SERIES_IMXRT118X */
234 #endif /* CONFIG_PWM_MCUX_QTMR || CONFIG_COUNTER_MCUX_QTMR */
235
236 #ifdef CONFIG_MEMC_MCUX_FLEXSPI
237 case IMX_CCM_FLEXSPI_CLK:
238 case IMX_CCM_FLEXSPI2_CLK:
239 clock_root = kCLOCK_Root_Flexspi1 + instance;
240 break;
241 #endif
242 #ifdef CONFIG_COUNTER_NXP_PIT
243 case IMX_CCM_PIT_CLK:
244 clock_root = kCLOCK_Root_Bus + instance;
245 break;
246 #endif
247
248 #ifdef CONFIG_ADC_MCUX_LPADC
249 case IMX_CCM_LPADC1_CLK:
250 clock_root = kCLOCK_Root_Adc1 + instance;
251 break;
252 #endif
253
254 #if defined(CONFIG_ETH_NXP_IMX_NETC)
255 case IMX_CCM_NETC_CLK:
256 clock_root = kCLOCK_Root_Netc;
257 break;
258 #endif
259
260 #if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
261 case IMX_CCM_MIPI_CSI2RX_ROOT_CLK:
262 clock_root = kCLOCK_Root_Csi2;
263 break;
264 case IMX_CCM_MIPI_CSI2RX_ESC_CLK:
265 clock_root = kCLOCK_Root_Csi2_Esc;
266 break;
267 case IMX_CCM_MIPI_CSI2RX_UI_CLK:
268 clock_root = kCLOCK_Root_Csi2_Ui;
269 break;
270 #endif
271
272 default:
273 return -EINVAL;
274 }
275 #ifdef CONFIG_SOC_MIMX9352
276 *rate = CLOCK_GetIpFreq(clock_root);
277 #else
278 *rate = CLOCK_GetRootClockFreq(clock_root);
279 #endif
280 return 0;
281 }
282
283 /*
284 * Since this function is used to reclock the FlexSPI when running in
285 * XIP, it must be located in RAM when MEMC driver is enabled.
286 */
287 #ifdef CONFIG_MEMC_MCUX_FLEXSPI
288 #define CCM_SET_FUNC_ATTR __ramfunc
289 #else
290 #define CCM_SET_FUNC_ATTR
291 #endif
292
mcux_ccm_set_subsys_rate(const struct device * dev,clock_control_subsys_t subsys,clock_control_subsys_rate_t rate)293 static int CCM_SET_FUNC_ATTR mcux_ccm_set_subsys_rate(const struct device *dev,
294 clock_control_subsys_t subsys,
295 clock_control_subsys_rate_t rate)
296 {
297 uint32_t clock_name = (uintptr_t)subsys;
298 uint32_t clock_rate = (uintptr_t)rate;
299
300 switch (clock_name) {
301 case IMX_CCM_FLEXSPI_CLK:
302 __fallthrough;
303 case IMX_CCM_FLEXSPI2_CLK:
304 #if (defined(CONFIG_SOC_SERIES_IMXRT11XX) || defined(CONFIG_SOC_SERIES_IMXRT118X)) \
305 && defined(CONFIG_MEMC_MCUX_FLEXSPI)
306 /* The SOC is using the FlexSPI for XIP. Therefore,
307 * the FlexSPI itself must be managed within the function,
308 * which is SOC specific.
309 */
310 return flexspi_clock_set_freq(clock_name, clock_rate);
311 #endif
312
313 #if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX)
314 case IMX_CCM_MIPI_CSI2RX_ROOT_CLK:
315 return mipi_csi2rx_clock_set_freq(kCLOCK_Root_Csi2, clock_rate);
316 case IMX_CCM_MIPI_CSI2RX_UI_CLK:
317 return mipi_csi2rx_clock_set_freq(kCLOCK_Root_Csi2_Ui, clock_rate);
318 case IMX_CCM_MIPI_CSI2RX_ESC_CLK:
319 return mipi_csi2rx_clock_set_freq(kCLOCK_Root_Csi2_Esc, clock_rate);
320 #endif
321
322 default:
323 /* Silence unused variable warning */
324 ARG_UNUSED(clock_rate);
325 return -ENOTSUP;
326 }
327 }
328
329 static DEVICE_API(clock_control, mcux_ccm_driver_api) = {
330 .on = mcux_ccm_on,
331 .off = mcux_ccm_off,
332 .get_rate = mcux_ccm_get_subsys_rate,
333 .set_rate = mcux_ccm_set_subsys_rate,
334 };
335
336 DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, PRE_KERNEL_1,
337 CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
338 &mcux_ccm_driver_api);
339