1 /*
2 * Copyright 2020-2024 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_lpc_syscon
8 #include <errno.h>
9 #include <zephyr/drivers/clock_control.h>
10 #include <zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h>
11 #include <soc.h>
12 #include <fsl_clock.h>
13
14 #define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(clock_control);
17
mcux_lpc_syscon_clock_control_on(const struct device * dev,clock_control_subsys_t sub_system)18 static int mcux_lpc_syscon_clock_control_on(const struct device *dev,
19 clock_control_subsys_t sub_system)
20 {
21 #if defined(CONFIG_CAN_MCUX_MCAN)
22 if ((uint32_t)sub_system == MCUX_MCAN_CLK) {
23 CLOCK_EnableClock(kCLOCK_Mcan);
24 }
25 #endif /* defined(CONFIG_CAN_MCUX_MCAN) */
26 #if defined(CONFIG_COUNTER_NXP_MRT)
27 if ((uint32_t)sub_system == MCUX_MRT_CLK) {
28 #if defined(CONFIG_SOC_FAMILY_LPC) || defined(CONFIG_SOC_SERIES_RW6XX) ||\
29 defined(CONFIG_SOC_SERIES_MCXN)
30 CLOCK_EnableClock(kCLOCK_Mrt);
31 #elif defined(CONFIG_SOC_FAMILY_NXP_IMXRT)
32 CLOCK_EnableClock(kCLOCK_Mrt0);
33 #endif
34 }
35 #if defined(CONFIG_SOC_SERIES_RW6XX)
36 if ((uint32_t)sub_system == MCUX_FREEMRT_CLK) {
37 CLOCK_EnableClock(kCLOCK_FreeMrt);
38 }
39 #endif
40 #endif /* defined(CONFIG_COUNTER_NXP_MRT) */
41 #if defined(CONFIG_MIPI_DBI_NXP_LCDIC)
42 if ((uint32_t)sub_system == MCUX_LCDIC_CLK) {
43 CLOCK_EnableClock(kCLOCK_Lcdic);
44 }
45 #endif
46
47 #if defined(CONFIG_PINCTRL_NXP_PORT)
48 switch ((uint32_t)sub_system) {
49 #if defined(CONFIG_SOC_SERIES_MCXA)
50 case MCUX_PORT0_CLK:
51 CLOCK_EnableClock(kCLOCK_GatePORT0);
52 break;
53 case MCUX_PORT1_CLK:
54 CLOCK_EnableClock(kCLOCK_GatePORT1);
55 break;
56 case MCUX_PORT2_CLK:
57 CLOCK_EnableClock(kCLOCK_GatePORT2);
58 break;
59 case MCUX_PORT3_CLK:
60 CLOCK_EnableClock(kCLOCK_GatePORT3);
61 break;
62 case MCUX_PORT4_CLK:
63 CLOCK_EnableClock(kCLOCK_GatePORT4);
64 break;
65 #else
66 case MCUX_PORT0_CLK:
67 CLOCK_EnableClock(kCLOCK_Port0);
68 break;
69 case MCUX_PORT1_CLK:
70 CLOCK_EnableClock(kCLOCK_Port1);
71 break;
72 case MCUX_PORT2_CLK:
73 CLOCK_EnableClock(kCLOCK_Port2);
74 break;
75 case MCUX_PORT3_CLK:
76 CLOCK_EnableClock(kCLOCK_Port3);
77 break;
78 case MCUX_PORT4_CLK:
79 CLOCK_EnableClock(kCLOCK_Port4);
80 break;
81 #endif /* defined(CONFIG_SOC_SERIES_MCXA) */
82 default:
83 break;
84 }
85 #endif /* defined(CONFIG_PINCTRL_NXP_PORT) */
86
87 #ifdef CONFIG_ETH_NXP_ENET_QOS
88 if ((uint32_t)sub_system == MCUX_ENET_QOS_CLK) {
89 CLOCK_EnableClock(kCLOCK_Enet);
90 }
91 #endif
92
93 #if defined(CONFIG_CAN_MCUX_FLEXCAN)
94 switch ((uint32_t)sub_system) {
95 case MCUX_FLEXCAN0_CLK:
96 CLOCK_EnableClock(kCLOCK_Flexcan0);
97 break;
98 case MCUX_FLEXCAN1_CLK:
99 CLOCK_EnableClock(kCLOCK_Flexcan1);
100 break;
101 default:
102 break;
103 }
104 #endif /* defined(CONFIG_CAN_MCUX_MCAN) */
105
106 #ifdef CONFIG_ETH_NXP_ENET
107 if ((uint32_t)sub_system == MCUX_ENET_CLK) {
108 #ifdef CONFIG_SOC_SERIES_RW6XX
109 CLOCK_EnableClock(kCLOCK_TddrMciEnetClk);
110 CLOCK_EnableClock(kCLOCK_EnetIpg);
111 CLOCK_EnableClock(kCLOCK_EnetIpgS);
112 #endif
113 }
114 #endif
115
116 #if DT_NODE_HAS_STATUS(DT_NODELABEL(rtc), okay)
117 #if CONFIG_SOC_SERIES_IMXRT5XX
118 CLOCK_EnableOsc32K(true);
119 #elif CONFIG_SOC_SERIES_IMXRT6XX
120 /* No configuration */
121 #else /* !CONFIG_SOC_SERIES_IMXRT5XX | !CONFIG_SOC_SERIES_IMXRT6XX */
122 /* 0x0 Clock Select Value Set IRTC to use FRO 16K Clk */
123 #if DT_PROP(DT_NODELABEL(rtc), clock_select) == 0x0
124 CLOCK_SetupClk16KClocking(kCLOCK_Clk16KToVbat | kCLOCK_Clk16KToMain);
125 /* 0x1 Clock Select Value Set IRTC to use Osc 32K Clk */
126 #elif DT_PROP(DT_NODELABEL(rtc), clock_select) == 0x1
127 CLOCK_SetupOsc32KClocking(kCLOCK_Osc32kToVbat | kCLOCK_Osc32kToMain);
128 #endif /* DT_PROP(DT_NODELABEL(rtc), clock_select) */
129 CLOCK_EnableClock(kCLOCK_Rtc0);
130 #endif /* CONFIG_SOC_SERIES_IMXRT5XX */
131 #endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(rtc), okay) */
132
133 return 0;
134 }
135
mcux_lpc_syscon_clock_control_off(const struct device * dev,clock_control_subsys_t sub_system)136 static int mcux_lpc_syscon_clock_control_off(const struct device *dev,
137 clock_control_subsys_t sub_system)
138 {
139 return 0;
140 }
141
mcux_lpc_syscon_clock_control_get_subsys_rate(const struct device * dev,clock_control_subsys_t sub_system,uint32_t * rate)142 static int mcux_lpc_syscon_clock_control_get_subsys_rate(const struct device *dev,
143 clock_control_subsys_t sub_system,
144 uint32_t *rate)
145 {
146 uint32_t clock_name = (uint32_t)sub_system;
147
148 switch (clock_name) {
149
150 #if defined(CONFIG_I2C_MCUX_FLEXCOMM) || defined(CONFIG_SPI_MCUX_FLEXCOMM) || \
151 defined(CONFIG_UART_MCUX_FLEXCOMM)
152 case MCUX_FLEXCOMM0_CLK:
153 *rate = CLOCK_GetFlexCommClkFreq(0);
154 break;
155 case MCUX_FLEXCOMM1_CLK:
156 *rate = CLOCK_GetFlexCommClkFreq(1);
157 break;
158 case MCUX_FLEXCOMM2_CLK:
159 *rate = CLOCK_GetFlexCommClkFreq(2);
160 break;
161 case MCUX_FLEXCOMM3_CLK:
162 *rate = CLOCK_GetFlexCommClkFreq(3);
163 break;
164 case MCUX_FLEXCOMM4_CLK:
165 *rate = CLOCK_GetFlexCommClkFreq(4);
166 break;
167 case MCUX_FLEXCOMM5_CLK:
168 *rate = CLOCK_GetFlexCommClkFreq(5);
169 break;
170 case MCUX_FLEXCOMM6_CLK:
171 *rate = CLOCK_GetFlexCommClkFreq(6);
172 break;
173 case MCUX_FLEXCOMM7_CLK:
174 *rate = CLOCK_GetFlexCommClkFreq(7);
175 break;
176 case MCUX_FLEXCOMM8_CLK:
177 *rate = CLOCK_GetFlexCommClkFreq(8);
178 break;
179 case MCUX_FLEXCOMM9_CLK:
180 *rate = CLOCK_GetFlexCommClkFreq(9);
181 break;
182 case MCUX_FLEXCOMM10_CLK:
183 *rate = CLOCK_GetFlexCommClkFreq(10);
184 break;
185 case MCUX_FLEXCOMM11_CLK:
186 *rate = CLOCK_GetFlexCommClkFreq(11);
187 break;
188 case MCUX_FLEXCOMM12_CLK:
189 *rate = CLOCK_GetFlexCommClkFreq(12);
190 break;
191 case MCUX_FLEXCOMM13_CLK:
192 *rate = CLOCK_GetFlexCommClkFreq(13);
193 break;
194 case MCUX_PMIC_I2C_CLK:
195 *rate = CLOCK_GetFlexCommClkFreq(15);
196 break;
197 case MCUX_HS_SPI_CLK:
198 #if defined(SYSCON_HSLSPICLKSEL_SEL_MASK)
199 *rate = CLOCK_GetHsLspiClkFreq();
200 #else
201 *rate = CLOCK_GetFlexCommClkFreq(14);
202 #endif
203 break;
204 case MCUX_HS_SPI1_CLK:
205 *rate = CLOCK_GetFlexCommClkFreq(16);
206 break;
207 #elif defined(CONFIG_NXP_LP_FLEXCOMM)
208 case MCUX_FLEXCOMM0_CLK:
209 *rate = CLOCK_GetLPFlexCommClkFreq(0);
210 break;
211 case MCUX_FLEXCOMM1_CLK:
212 *rate = CLOCK_GetLPFlexCommClkFreq(1);
213 break;
214 case MCUX_FLEXCOMM2_CLK:
215 *rate = CLOCK_GetLPFlexCommClkFreq(2);
216 break;
217 case MCUX_FLEXCOMM3_CLK:
218 *rate = CLOCK_GetLPFlexCommClkFreq(3);
219 break;
220 case MCUX_FLEXCOMM4_CLK:
221 *rate = CLOCK_GetLPFlexCommClkFreq(4);
222 break;
223 case MCUX_FLEXCOMM5_CLK:
224 *rate = CLOCK_GetLPFlexCommClkFreq(5);
225 break;
226 case MCUX_FLEXCOMM6_CLK:
227 *rate = CLOCK_GetLPFlexCommClkFreq(6);
228 break;
229 case MCUX_FLEXCOMM7_CLK:
230 *rate = CLOCK_GetLPFlexCommClkFreq(7);
231 break;
232 case MCUX_FLEXCOMM8_CLK:
233 *rate = CLOCK_GetLPFlexCommClkFreq(8);
234 break;
235 case MCUX_FLEXCOMM9_CLK:
236 *rate = CLOCK_GetLPFlexCommClkFreq(9);
237 break;
238
239 #endif
240
241 #if (defined(FSL_FEATURE_SOC_USDHC_COUNT) && FSL_FEATURE_SOC_USDHC_COUNT)
242
243 #if CONFIG_SOC_SERIES_MCXN
244 case MCUX_USDHC1_CLK:
245 *rate = CLOCK_GetUsdhcClkFreq();
246 break;
247 #else
248 case MCUX_USDHC1_CLK:
249 *rate = CLOCK_GetSdioClkFreq(0);
250 break;
251 case MCUX_USDHC2_CLK:
252 *rate = CLOCK_GetSdioClkFreq(1);
253 break;
254 #endif
255
256 #endif
257
258 #if (defined(FSL_FEATURE_SOC_SDIF_COUNT) && (FSL_FEATURE_SOC_SDIF_COUNT)) && CONFIG_MCUX_SDIF
259 case MCUX_SDIF_CLK:
260 *rate = CLOCK_GetSdioClkFreq();
261 break;
262 #endif
263
264 #if defined(CONFIG_CAN_MCUX_MCAN)
265 case MCUX_MCAN_CLK:
266 *rate = CLOCK_GetMCanClkFreq();
267 break;
268 #endif /* defined(CONFIG_CAN_MCUX_MCAN) */
269
270 #if defined(CONFIG_COUNTER_MCUX_CTIMER) || defined(CONFIG_PWM_MCUX_CTIMER)
271 case MCUX_CTIMER0_CLK:
272 *rate = CLOCK_GetCTimerClkFreq(0);
273 break;
274 case MCUX_CTIMER1_CLK:
275 *rate = CLOCK_GetCTimerClkFreq(1);
276 break;
277 case MCUX_CTIMER2_CLK:
278 *rate = CLOCK_GetCTimerClkFreq(2);
279 break;
280 case MCUX_CTIMER3_CLK:
281 *rate = CLOCK_GetCTimerClkFreq(3);
282 break;
283 case MCUX_CTIMER4_CLK:
284 *rate = CLOCK_GetCTimerClkFreq(4);
285 break;
286 #endif
287
288 #if defined(CONFIG_COUNTER_NXP_MRT)
289 case MCUX_MRT_CLK:
290 #if defined(CONFIG_SOC_SERIES_RW6XX)
291 case MCUX_FREEMRT_CLK:
292 #endif /* RW */
293 #endif /* MRT */
294 #if defined(CONFIG_PWM_MCUX_SCTIMER)
295 case MCUX_SCTIMER_CLK:
296 #endif
297 #ifdef CONFIG_SOC_SERIES_RW6XX
298 /* RW6XX uses core clock for SCTimer, not bus clock */
299 *rate = CLOCK_GetCoreSysClkFreq();
300 break;
301 #else
302 case MCUX_BUS_CLK:
303 *rate = CLOCK_GetFreq(kCLOCK_BusClk);
304 break;
305 #endif
306
307 #if defined(CONFIG_I3C_MCUX)
308 case MCUX_I3C_CLK:
309 #if CONFIG_SOC_SERIES_MCXN
310 *rate = CLOCK_GetI3cClkFreq(0);
311 #else
312 *rate = CLOCK_GetI3cClkFreq();
313 #endif
314 break;
315 #if (FSL_FEATURE_SOC_I3C_COUNT == 2)
316 case MCUX_I3C2_CLK:
317 #if CONFIG_SOC_SERIES_MCXN
318 *rate = CLOCK_GetI3cClkFreq(1);
319 #else
320 *rate = CLOCK_GetI3cClkFreq();
321 #endif
322 break;
323 #endif
324
325 #endif /* CONFIG_I3C_MCUX */
326
327 #if defined(CONFIG_MIPI_DSI_MCUX_2L)
328 case MCUX_MIPI_DSI_DPHY_CLK:
329 *rate = CLOCK_GetMipiDphyClkFreq();
330 break;
331 case MCUX_MIPI_DSI_ESC_CLK:
332 *rate = CLOCK_GetMipiDphyEscTxClkFreq();
333 break;
334 case MCUX_LCDIF_PIXEL_CLK:
335 *rate = CLOCK_GetDcPixelClkFreq();
336 break;
337 #endif
338 #if defined(CONFIG_AUDIO_DMIC_MCUX)
339 case MCUX_DMIC_CLK:
340 *rate = CLOCK_GetDmicClkFreq();
341 break;
342 #endif
343 #if defined(CONFIG_MEMC_MCUX_FLEXSPI)
344 case MCUX_FLEXSPI_CLK:
345 #if (FSL_FEATURE_SOC_FLEXSPI_COUNT == 1)
346 *rate = CLOCK_GetFlexspiClkFreq();
347 #else
348 *rate = CLOCK_GetFlexspiClkFreq(0);
349 #endif
350 break;
351 #if (FSL_FEATURE_SOC_FLEXSPI_COUNT == 2)
352 case MCUX_FLEXSPI2_CLK:
353 *rate = CLOCK_GetFlexspiClkFreq(1);
354 break;
355 #endif
356 #endif /* CONFIG_MEMC_MCUX_FLEXSPI */
357
358 #ifdef CONFIG_ETH_NXP_ENET_QOS
359 case MCUX_ENET_QOS_CLK:
360 *rate = CLOCK_GetFreq(kCLOCK_BusClk);
361 break;
362 #endif
363
364 #ifdef CONFIG_ETH_NXP_ENET
365 case MCUX_ENET_CLK:
366 #ifdef CONFIG_SOC_SERIES_RW6XX
367 *rate = CLOCK_GetTddrMciEnetClkFreq();
368 #endif
369 break;
370 #endif
371
372 #if defined(CONFIG_MIPI_DBI_NXP_LCDIC)
373 case MCUX_LCDIC_CLK:
374 *rate = CLOCK_GetLcdClkFreq();
375 break;
376 #endif
377
378 #if defined(CONFIG_ADC_MCUX_LPADC)
379 case MCUX_LPADC1_CLK:
380 #if (FSL_FEATURE_SOC_LPADC_COUNT == 1)
381 *rate = CLOCK_GetAdcClkFreq();
382 #else
383 *rate = CLOCK_GetAdcClkFreq(0);
384 #endif
385 break;
386 #if (FSL_FEATURE_SOC_LPADC_COUNT == 2)
387 case MCUX_LPADC2_CLK:
388 *rate = CLOCK_GetAdcClkFreq(1);
389 break;
390 #endif
391 #endif /* CONFIG_ADC_MCUX_LPADC */
392
393 #if defined(CONFIG_CAN_MCUX_FLEXCAN)
394 case MCUX_FLEXCAN0_CLK:
395 *rate = CLOCK_GetFlexcanClkFreq(0);
396 break;
397 case MCUX_FLEXCAN1_CLK:
398 *rate = CLOCK_GetFlexcanClkFreq(1);
399 break;
400 #endif /* defined(CONFIG_CAN_MCUX_FLEXCAN) */
401
402 #if defined(CONFIG_MCUX_FLEXIO)
403 case MCUX_FLEXIO0_CLK:
404 *rate = CLOCK_GetFlexioClkFreq();
405 break;
406 #endif /* defined(CONFIG_MCUX_FLEXIO) */
407
408 #if defined(CONFIG_I2S_MCUX_FLEXCOMM)
409 case MCUX_AUDIO_MCLK:
410 *rate = CLOCK_GetMclkClkFreq();
411 break;
412 #endif /* defined(CONFIG_I2S_MCUX_FLEXCOMM) */
413
414 #if (defined(CONFIG_UART_MCUX_LPUART) && CONFIG_SOC_SERIES_MCXA)
415 case MCUX_LPUART0_CLK:
416 *rate = CLOCK_GetLpuartClkFreq(0);
417 break;
418 case MCUX_LPUART1_CLK:
419 *rate = CLOCK_GetLpuartClkFreq(1);
420 break;
421 case MCUX_LPUART2_CLK:
422 *rate = CLOCK_GetLpuartClkFreq(2);
423 break;
424 case MCUX_LPUART3_CLK:
425 *rate = CLOCK_GetLpuartClkFreq(3);
426 break;
427 case MCUX_LPUART4_CLK:
428 *rate = CLOCK_GetLpuartClkFreq(4);
429 break;
430 #endif /* defined(CONFIG_UART_MCUX_LPUART) */
431
432 #if (defined(CONFIG_I2C_MCUX_LPI2C) && CONFIG_SOC_SERIES_MCXA)
433 case MCUX_LPI2C0_CLK:
434 *rate = CLOCK_GetLpi2cClkFreq(0);
435 break;
436 case MCUX_LPI2C1_CLK:
437 *rate = CLOCK_GetLpi2cClkFreq(1);
438 break;
439 case MCUX_LPI2C2_CLK:
440 *rate = CLOCK_GetLpi2cClkFreq(2);
441 break;
442 case MCUX_LPI2C3_CLK:
443 *rate = CLOCK_GetLpi2cClkFreq(3);
444 break;
445 #endif /* defined(CONFIG_I2C_MCUX_LPI2C) */
446 }
447
448 return 0;
449 }
450
451 #if defined(CONFIG_MEMC)
452 /*
453 * Weak implemenetation of flexspi_clock_set_freq- SOC implementations are
454 * expected to override this
455 */
flexspi_clock_set_freq(uint32_t clock_name,uint32_t freq)456 __weak int flexspi_clock_set_freq(uint32_t clock_name, uint32_t freq)
457 {
458 ARG_UNUSED(clock_name);
459 ARG_UNUSED(freq);
460 return -ENOTSUP;
461 }
462 #endif
463
464 /*
465 * Since this function is used to reclock the FlexSPI when running in
466 * XIP, it must be located in RAM when MEMC driver is enabled.
467 */
468 #ifdef CONFIG_MEMC
469 #define SYSCON_SET_FUNC_ATTR __ramfunc
470 #else
471 #define SYSCON_SET_FUNC_ATTR
472 #endif
473
mcux_lpc_syscon_clock_control_set_subsys_rate(const struct device * dev,clock_control_subsys_t subsys,clock_control_subsys_rate_t rate)474 static int SYSCON_SET_FUNC_ATTR mcux_lpc_syscon_clock_control_set_subsys_rate(
475 const struct device *dev, clock_control_subsys_t subsys, clock_control_subsys_rate_t rate)
476 {
477 uint32_t clock_name = (uintptr_t)subsys;
478 uint32_t clock_rate = (uintptr_t)rate;
479
480 switch (clock_name) {
481 case MCUX_FLEXSPI_CLK:
482 #if defined(CONFIG_MEMC)
483 /* The SOC is using the FlexSPI for XIP. Therefore,
484 * the FlexSPI itself must be managed within the function,
485 * which is SOC specific.
486 */
487 return flexspi_clock_set_freq(clock_name, clock_rate);
488 #endif
489 #if defined(CONFIG_MIPI_DBI_NXP_LCDIC)
490 case MCUX_LCDIC_CLK:
491 /* Set LCDIC clock div */
492 uint32_t root_rate = (CLOCK_GetLcdClkFreq() *
493 ((CLKCTL0->LCDFCLKDIV & CLKCTL0_LCDFCLKDIV_DIV_MASK) + 1));
494 CLOCK_SetClkDiv(kCLOCK_DivLcdClk, (root_rate / clock_rate));
495 return 0;
496 #endif
497 default:
498 /* Silence unused variable warning */
499 ARG_UNUSED(clock_rate);
500 return -ENOTSUP;
501 }
502 }
503
504 static DEVICE_API(clock_control, mcux_lpc_syscon_api) = {
505 .on = mcux_lpc_syscon_clock_control_on,
506 .off = mcux_lpc_syscon_clock_control_off,
507 .get_rate = mcux_lpc_syscon_clock_control_get_subsys_rate,
508 .set_rate = mcux_lpc_syscon_clock_control_set_subsys_rate,
509 };
510
511 #define LPC_CLOCK_INIT(n) \
512 \
513 DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, NULL, PRE_KERNEL_1, \
514 CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &mcux_lpc_syscon_api);
515
516 DT_INST_FOREACH_STATUS_OKAY(LPC_CLOCK_INIT)
517