1 /*
2  * Copyright 2020-2025 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_FAMILY_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_FAMILY_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 #if (defined(FSL_FEATURE_SOC_PORT_COUNT) && (FSL_FEATURE_SOC_PORT_COUNT > 4))
63 	case MCUX_PORT4_CLK:
64 		CLOCK_EnableClock(kCLOCK_GatePORT4);
65 		break;
66 #endif /* defined(FSL_FEATURE_SOC_PORT_COUNT) */
67 #else
68 	case MCUX_PORT0_CLK:
69 		CLOCK_EnableClock(kCLOCK_Port0);
70 		break;
71 	case MCUX_PORT1_CLK:
72 		CLOCK_EnableClock(kCLOCK_Port1);
73 		break;
74 	case MCUX_PORT2_CLK:
75 		CLOCK_EnableClock(kCLOCK_Port2);
76 		break;
77 	case MCUX_PORT3_CLK:
78 		CLOCK_EnableClock(kCLOCK_Port3);
79 		break;
80 	case MCUX_PORT4_CLK:
81 		CLOCK_EnableClock(kCLOCK_Port4);
82 		break;
83 #endif /* defined(CONFIG_SOC_FAMILY_MCXA) */
84 	default:
85 		break;
86 	}
87 #endif /* defined(CONFIG_PINCTRL_NXP_PORT) */
88 
89 #ifdef CONFIG_ETH_NXP_ENET_QOS
90 	if ((uint32_t)sub_system == MCUX_ENET_QOS_CLK) {
91 		CLOCK_EnableClock(kCLOCK_Enet);
92 	}
93 #endif
94 
95 #if defined(CONFIG_CAN_MCUX_FLEXCAN)
96 	switch ((uint32_t)sub_system) {
97 #if defined(CONFIG_SOC_FAMILY_MCXA)
98 	case MCUX_FLEXCAN0_CLK:
99 		CLOCK_EnableClock(kCLOCK_GateFLEXCAN0);
100 		break;
101 #else
102 	case MCUX_FLEXCAN0_CLK:
103 		CLOCK_EnableClock(kCLOCK_Flexcan0);
104 		break;
105 	case MCUX_FLEXCAN1_CLK:
106 		CLOCK_EnableClock(kCLOCK_Flexcan1);
107 		break;
108 #endif /* defined(CONFIG_SOC_FAMILY_MCXA) */
109 	default:
110 		break;
111 	}
112 #endif /* defined(CONFIG_CAN_MCUX_MCAN) */
113 
114 #ifdef CONFIG_ETH_NXP_ENET
115 	if ((uint32_t)sub_system == MCUX_ENET_CLK) {
116 #ifdef CONFIG_SOC_SERIES_RW6XX
117 		CLOCK_EnableClock(kCLOCK_TddrMciEnetClk);
118 		CLOCK_EnableClock(kCLOCK_EnetIpg);
119 		CLOCK_EnableClock(kCLOCK_EnetIpgS);
120 #endif
121 	}
122 #endif
123 
124 #if DT_NODE_HAS_STATUS(DT_NODELABEL(rtc), okay)
125 #if defined(CONFIG_SOC_SERIES_IMXRT5XX) || defined(CONFIG_SOC_SERIES_IMXRT6XX)
126 	CLOCK_EnableOsc32K(true);
127 #elif CONFIG_SOC_FAMILY_MCXN
128 /* 0x0 Clock Select Value Set IRTC to use FRO 16K Clk */
129 #if DT_PROP(DT_NODELABEL(rtc), clock_select) == 0x0
130 	CLOCK_SetupClk16KClocking(kCLOCK_Clk16KToVbat | kCLOCK_Clk16KToMain);
131 /* 0x1 Clock Select Value Set IRTC to use Osc 32K Clk */
132 #elif DT_PROP(DT_NODELABEL(rtc), clock_select) == 0x1
133 	CLOCK_SetupOsc32KClocking(kCLOCK_Osc32kToVbat | kCLOCK_Osc32kToMain);
134 #endif /* DT_PROP(DT_NODELABEL(rtc), clock_select) */
135 	CLOCK_EnableClock(kCLOCK_Rtc0);
136 #endif /* CONFIG_SOC_FAMILY_MCXN */
137 #endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(rtc), okay) */
138 
139 	return 0;
140 }
141 
mcux_lpc_syscon_clock_control_off(const struct device * dev,clock_control_subsys_t sub_system)142 static int mcux_lpc_syscon_clock_control_off(const struct device *dev,
143 					     clock_control_subsys_t sub_system)
144 {
145 	return 0;
146 }
147 
mcux_lpc_syscon_clock_control_get_subsys_rate(const struct device * dev,clock_control_subsys_t sub_system,uint32_t * rate)148 static int mcux_lpc_syscon_clock_control_get_subsys_rate(const struct device *dev,
149 							 clock_control_subsys_t sub_system,
150 							 uint32_t *rate)
151 {
152 	uint32_t clock_name = (uint32_t)sub_system;
153 
154 	switch (clock_name) {
155 
156 #if defined(CONFIG_I2C_MCUX_FLEXCOMM) || defined(CONFIG_SPI_MCUX_FLEXCOMM) ||                      \
157 	defined(CONFIG_UART_MCUX_FLEXCOMM) || defined(CONFIG_I2S_MCUX_FLEXCOMM)
158 	case MCUX_FLEXCOMM0_CLK:
159 		*rate = CLOCK_GetFlexCommClkFreq(0);
160 		break;
161 	case MCUX_FLEXCOMM1_CLK:
162 		*rate = CLOCK_GetFlexCommClkFreq(1);
163 		break;
164 	case MCUX_FLEXCOMM2_CLK:
165 		*rate = CLOCK_GetFlexCommClkFreq(2);
166 		break;
167 	case MCUX_FLEXCOMM3_CLK:
168 		*rate = CLOCK_GetFlexCommClkFreq(3);
169 		break;
170 	case MCUX_FLEXCOMM4_CLK:
171 		*rate = CLOCK_GetFlexCommClkFreq(4);
172 		break;
173 	case MCUX_FLEXCOMM5_CLK:
174 		*rate = CLOCK_GetFlexCommClkFreq(5);
175 		break;
176 	case MCUX_FLEXCOMM6_CLK:
177 		*rate = CLOCK_GetFlexCommClkFreq(6);
178 		break;
179 	case MCUX_FLEXCOMM7_CLK:
180 		*rate = CLOCK_GetFlexCommClkFreq(7);
181 		break;
182 	case MCUX_FLEXCOMM8_CLK:
183 		*rate = CLOCK_GetFlexCommClkFreq(8);
184 		break;
185 	case MCUX_FLEXCOMM9_CLK:
186 		*rate = CLOCK_GetFlexCommClkFreq(9);
187 		break;
188 	case MCUX_FLEXCOMM10_CLK:
189 		*rate = CLOCK_GetFlexCommClkFreq(10);
190 		break;
191 	case MCUX_FLEXCOMM11_CLK:
192 		*rate = CLOCK_GetFlexCommClkFreq(11);
193 		break;
194 	case MCUX_FLEXCOMM12_CLK:
195 		*rate = CLOCK_GetFlexCommClkFreq(12);
196 		break;
197 	case MCUX_FLEXCOMM13_CLK:
198 		*rate = CLOCK_GetFlexCommClkFreq(13);
199 		break;
200 	case MCUX_PMIC_I2C_CLK:
201 		*rate = CLOCK_GetFlexCommClkFreq(15);
202 		break;
203 	case MCUX_HS_SPI_CLK:
204 #if defined(SYSCON_HSLSPICLKSEL_SEL_MASK)
205 		*rate = CLOCK_GetHsLspiClkFreq();
206 #else
207 		*rate = CLOCK_GetFlexCommClkFreq(14);
208 #endif
209 		break;
210 	case MCUX_HS_SPI1_CLK:
211 		*rate = CLOCK_GetFlexCommClkFreq(16);
212 		break;
213 #elif defined(CONFIG_NXP_LP_FLEXCOMM)
214 	case MCUX_FLEXCOMM0_CLK:
215 		*rate = CLOCK_GetLPFlexCommClkFreq(0);
216 		break;
217 	case MCUX_FLEXCOMM1_CLK:
218 		*rate = CLOCK_GetLPFlexCommClkFreq(1);
219 		break;
220 	case MCUX_FLEXCOMM2_CLK:
221 		*rate = CLOCK_GetLPFlexCommClkFreq(2);
222 		break;
223 	case MCUX_FLEXCOMM3_CLK:
224 		*rate = CLOCK_GetLPFlexCommClkFreq(3);
225 		break;
226 	case MCUX_FLEXCOMM4_CLK:
227 		*rate = CLOCK_GetLPFlexCommClkFreq(4);
228 		break;
229 	case MCUX_FLEXCOMM5_CLK:
230 		*rate = CLOCK_GetLPFlexCommClkFreq(5);
231 		break;
232 	case MCUX_FLEXCOMM6_CLK:
233 		*rate = CLOCK_GetLPFlexCommClkFreq(6);
234 		break;
235 	case MCUX_FLEXCOMM7_CLK:
236 		*rate = CLOCK_GetLPFlexCommClkFreq(7);
237 		break;
238 	case MCUX_FLEXCOMM8_CLK:
239 		*rate = CLOCK_GetLPFlexCommClkFreq(8);
240 		break;
241 	case MCUX_FLEXCOMM9_CLK:
242 		*rate = CLOCK_GetLPFlexCommClkFreq(9);
243 		break;
244 
245 	case MCUX_FLEXCOMM10_CLK:
246 		*rate = CLOCK_GetLPFlexCommClkFreq(10);
247 		break;
248 
249 	case MCUX_FLEXCOMM11_CLK:
250 		*rate = CLOCK_GetLPFlexCommClkFreq(11);
251 		break;
252 
253 	case MCUX_FLEXCOMM12_CLK:
254 		*rate = CLOCK_GetLPFlexCommClkFreq(12);
255 		break;
256 
257 	case MCUX_FLEXCOMM13_CLK:
258 		*rate = CLOCK_GetLPFlexCommClkFreq(13);
259 		break;
260 
261 	case MCUX_FLEXCOMM17_CLK:
262 		*rate = CLOCK_GetLPFlexCommClkFreq(17);
263 		break;
264 
265 	case MCUX_FLEXCOMM18_CLK:
266 		*rate = CLOCK_GetLPFlexCommClkFreq(18);
267 		break;
268 
269 	case MCUX_FLEXCOMM19_CLK:
270 		*rate = CLOCK_GetLPFlexCommClkFreq(19);
271 		break;
272 
273 	case MCUX_FLEXCOMM20_CLK:
274 		*rate = CLOCK_GetLPFlexCommClkFreq(20);
275 		break;
276 #endif
277 
278 		/* On RT7xx, flexcomm14 and 16 only can be LPSPI, flexcomm15 only can be I2C. */
279 #if defined(CONFIG_SOC_SERIES_IMXRT7XX) && defined(CONFIG_SOC_FAMILY_NXP_IMXRT)
280 	case MCUX_LPSPI14_CLK:
281 		*rate = CLOCK_GetLPSpiClkFreq(14);
282 		break;
283 	case MCUX_LPI2C15_CLK:
284 		*rate = CLOCK_GetLPI2cClkFreq(15);
285 		break;
286 	case MCUX_LPSPI16_CLK:
287 		*rate = CLOCK_GetLPSpiClkFreq(16);
288 		break;
289 #endif
290 
291 #if (defined(FSL_FEATURE_SOC_USDHC_COUNT) && FSL_FEATURE_SOC_USDHC_COUNT)
292 
293 #if defined(CONFIG_SOC_FAMILY_MCXN)
294 	case MCUX_USDHC1_CLK:
295 		*rate = CLOCK_GetUsdhcClkFreq();
296 		break;
297 #elif defined(CONFIG_SOC_SERIES_IMXRT7XX)
298 	case MCUX_USDHC1_CLK:
299 		*rate = CLOCK_GetUsdhcClkFreq(0);
300 		break;
301 	case MCUX_USDHC2_CLK:
302 		*rate = CLOCK_GetUsdhcClkFreq(1);
303 		break;
304 #else
305 	case MCUX_USDHC1_CLK:
306 		*rate = CLOCK_GetSdioClkFreq(0);
307 		break;
308 	case MCUX_USDHC2_CLK:
309 		*rate = CLOCK_GetSdioClkFreq(1);
310 		break;
311 #endif
312 
313 #endif
314 
315 #if (defined(FSL_FEATURE_SOC_SDIF_COUNT) && (FSL_FEATURE_SOC_SDIF_COUNT)) && CONFIG_MCUX_SDIF
316 	case MCUX_SDIF_CLK:
317 		*rate = CLOCK_GetSdioClkFreq();
318 		break;
319 #endif
320 
321 #if defined(CONFIG_CAN_MCUX_MCAN)
322 	case MCUX_MCAN_CLK:
323 		*rate = CLOCK_GetMCanClkFreq();
324 		break;
325 #endif /* defined(CONFIG_CAN_MCUX_MCAN) */
326 
327 #if defined(CONFIG_COUNTER_MCUX_CTIMER) || defined(CONFIG_PWM_MCUX_CTIMER)
328 	case MCUX_CTIMER0_CLK:
329 		*rate = CLOCK_GetCTimerClkFreq(0);
330 		break;
331 	case MCUX_CTIMER1_CLK:
332 		*rate = CLOCK_GetCTimerClkFreq(1);
333 		break;
334 	case MCUX_CTIMER2_CLK:
335 		*rate = CLOCK_GetCTimerClkFreq(2);
336 		break;
337 	case MCUX_CTIMER3_CLK:
338 		*rate = CLOCK_GetCTimerClkFreq(3);
339 		break;
340 	case MCUX_CTIMER4_CLK:
341 		*rate = CLOCK_GetCTimerClkFreq(4);
342 		break;
343 	case MCUX_CTIMER5_CLK:
344 		*rate = CLOCK_GetCTimerClkFreq(5);
345 		break;
346 	case MCUX_CTIMER6_CLK:
347 		*rate = CLOCK_GetCTimerClkFreq(6);
348 		break;
349 	case MCUX_CTIMER7_CLK:
350 		*rate = CLOCK_GetCTimerClkFreq(7);
351 		break;
352 #endif
353 
354 #if defined(CONFIG_COUNTER_NXP_MRT)
355 	case MCUX_MRT_CLK:
356 #if defined(CONFIG_SOC_SERIES_RW6XX)
357 	case MCUX_FREEMRT_CLK:
358 #endif /* RW */
359 #endif /* MRT */
360 #if defined(CONFIG_PWM_MCUX_SCTIMER)
361 	case MCUX_SCTIMER_CLK:
362 #endif
363 #ifdef CONFIG_SOC_SERIES_RW6XX
364 		/* RW6XX uses core clock for SCTimer, not bus clock */
365 		*rate = CLOCK_GetCoreSysClkFreq();
366 		break;
367 #else
368 	case MCUX_BUS_CLK:
369 		*rate = CLOCK_GetFreq(kCLOCK_BusClk);
370 		break;
371 #endif
372 
373 #if defined(CONFIG_I3C_MCUX)
374 	case MCUX_I3C_CLK:
375 #if CONFIG_SOC_FAMILY_MCXN
376 		*rate = CLOCK_GetI3cClkFreq(0);
377 #elif CONFIG_SOC_FAMILY_MCXA
378 		*rate = CLOCK_GetI3CFClkFreq();
379 #else
380 		*rate = CLOCK_GetI3cClkFreq();
381 #endif
382 		break;
383 #if (FSL_FEATURE_SOC_I3C_COUNT == 2)
384 	case MCUX_I3C2_CLK:
385 #if CONFIG_SOC_FAMILY_MCXN
386 		*rate = CLOCK_GetI3cClkFreq(1);
387 #else
388 		*rate = CLOCK_GetI3cClkFreq();
389 #endif
390 		break;
391 #endif
392 
393 #endif /* CONFIG_I3C_MCUX */
394 
395 #if defined(CONFIG_MIPI_DSI_MCUX_2L)
396 	case MCUX_MIPI_DSI_DPHY_CLK:
397 		*rate = CLOCK_GetMipiDphyClkFreq();
398 		break;
399 	case MCUX_MIPI_DSI_ESC_CLK:
400 		*rate = CLOCK_GetMipiDphyEscTxClkFreq();
401 		break;
402 	case MCUX_LCDIF_PIXEL_CLK:
403 #if defined(CONFIG_SOC_SERIES_IMXRT7XX) && defined(CONFIG_SOC_FAMILY_NXP_IMXRT)
404 		*rate = CLOCK_GetLcdifClkFreq();
405 #else
406 		*rate = CLOCK_GetDcPixelClkFreq();
407 #endif
408 		break;
409 #endif
410 #if defined(CONFIG_AUDIO_DMIC_MCUX)
411 	case MCUX_DMIC_CLK:
412 		*rate = CLOCK_GetDmicClkFreq();
413 		break;
414 #endif
415 #if defined(CONFIG_MEMC_MCUX_FLEXSPI)
416 	case MCUX_FLEXSPI_CLK:
417 #if (FSL_FEATURE_SOC_FLEXSPI_COUNT == 1)
418 		*rate = CLOCK_GetFlexspiClkFreq();
419 #else
420 		*rate = CLOCK_GetFlexspiClkFreq(0);
421 #endif
422 		break;
423 #if (FSL_FEATURE_SOC_FLEXSPI_COUNT == 2)
424 	case MCUX_FLEXSPI2_CLK:
425 		*rate = CLOCK_GetFlexspiClkFreq(1);
426 		break;
427 #endif
428 #endif /* CONFIG_MEMC_MCUX_FLEXSPI */
429 
430 #if defined(CONFIG_I2S_MCUX_SAI)
431 #if defined(CONFIG_SOC_SERIES_IMXRT7XX)
432 	case MCUX_SAI0_CLK:
433 	case MCUX_SAI1_CLK:
434 	case MCUX_SAI2_CLK:
435 		*rate = CLOCK_GetSaiClkFreq();
436 		break;
437 #else
438 	case MCUX_SAI0_CLK:
439 #if (FSL_FEATURE_SOC_I2S_COUNT == 1)
440 		*rate = CLOCK_GetSaiClkFreq();
441 #else
442 		*rate = CLOCK_GetSaiClkFreq(0);
443 #endif
444 		break;
445 #if (FSL_FEATURE_SOC_I2S_COUNT == 2)
446 	case MCUX_SAI1_CLK:
447 		*rate = CLOCK_GetSaiClkFreq(1);
448 		break;
449 #endif
450 #endif /* CONFIG_SOC_SERIES_IMXRT7XX */
451 #endif /* CONFIG_I2S_MCUX_SAI */
452 
453 #ifdef CONFIG_ETH_NXP_ENET_QOS
454 	case MCUX_ENET_QOS_CLK:
455 		*rate = CLOCK_GetFreq(kCLOCK_BusClk);
456 		break;
457 #endif
458 
459 #ifdef CONFIG_ETH_NXP_ENET
460 	case MCUX_ENET_CLK:
461 #ifdef CONFIG_SOC_SERIES_RW6XX
462 		*rate = CLOCK_GetTddrMciEnetClkFreq();
463 #endif
464 		break;
465 #endif
466 
467 #if defined(CONFIG_MIPI_DBI_NXP_LCDIC)
468 	case MCUX_LCDIC_CLK:
469 		*rate = CLOCK_GetLcdClkFreq();
470 		break;
471 #endif
472 
473 #if defined(CONFIG_ADC_MCUX_LPADC)
474 	case MCUX_LPADC1_CLK:
475 #if (FSL_FEATURE_SOC_LPADC_COUNT == 1)
476 		*rate = CLOCK_GetAdcClkFreq();
477 #else
478 		*rate = CLOCK_GetAdcClkFreq(0);
479 #endif
480 		break;
481 #if (FSL_FEATURE_SOC_LPADC_COUNT == 2)
482 	case MCUX_LPADC2_CLK:
483 		*rate = CLOCK_GetAdcClkFreq(1);
484 		break;
485 #endif
486 #endif /* CONFIG_ADC_MCUX_LPADC */
487 
488 #if defined(CONFIG_CAN_MCUX_FLEXCAN)
489 #if defined(CONFIG_SOC_FAMILY_MCXA)
490 	case MCUX_FLEXCAN0_CLK:
491 		*rate = CLOCK_GetFlexcanClkFreq();
492 		break;
493 #else
494 	case MCUX_FLEXCAN0_CLK:
495 		*rate = CLOCK_GetFlexcanClkFreq(0);
496 		break;
497 	case MCUX_FLEXCAN1_CLK:
498 		*rate = CLOCK_GetFlexcanClkFreq(1);
499 		break;
500 #endif /* defined(CONFIG_SOC_FAMILY_MCXA) */
501 #endif /* defined(CONFIG_CAN_MCUX_FLEXCAN) */
502 
503 #if defined(CONFIG_MCUX_FLEXIO)
504 	case MCUX_FLEXIO0_CLK:
505 		*rate = CLOCK_GetFlexioClkFreq();
506 		break;
507 #endif /* defined(CONFIG_MCUX_FLEXIO) */
508 
509 #if defined(CONFIG_I2S_MCUX_FLEXCOMM)
510 	case MCUX_AUDIO_MCLK:
511 		*rate = CLOCK_GetMclkClkFreq();
512 		break;
513 #endif /* defined(CONFIG_I2S_MCUX_FLEXCOMM) */
514 
515 #if (defined(CONFIG_UART_MCUX_LPUART) && CONFIG_SOC_FAMILY_MCXA)
516 	case MCUX_LPUART0_CLK:
517 		*rate = CLOCK_GetLpuartClkFreq(0);
518 		break;
519 	case MCUX_LPUART1_CLK:
520 		*rate = CLOCK_GetLpuartClkFreq(1);
521 		break;
522 	case MCUX_LPUART2_CLK:
523 		*rate = CLOCK_GetLpuartClkFreq(2);
524 		break;
525 	case MCUX_LPUART3_CLK:
526 		*rate = CLOCK_GetLpuartClkFreq(3);
527 		break;
528 	case MCUX_LPUART4_CLK:
529 		*rate = CLOCK_GetLpuartClkFreq(4);
530 		break;
531 #endif /* defined(CONFIG_UART_MCUX_LPUART) */
532 
533 #if (defined(CONFIG_I2C_MCUX_LPI2C) && CONFIG_SOC_FAMILY_MCXA)
534 #if (defined(FSL_FEATURE_SOC_LPI2C_COUNT) && (FSL_FEATURE_SOC_LPI2C_COUNT == 1))
535 	case MCUX_LPI2C0_CLK:
536 		*rate = CLOCK_GetLpi2cClkFreq();
537 		break;
538 #else
539 	case MCUX_LPI2C0_CLK:
540 		*rate = CLOCK_GetLpi2cClkFreq(0);
541 		break;
542 	case MCUX_LPI2C1_CLK:
543 		*rate = CLOCK_GetLpi2cClkFreq(1);
544 		break;
545 	case MCUX_LPI2C2_CLK:
546 		*rate = CLOCK_GetLpi2cClkFreq(2);
547 		break;
548 	case MCUX_LPI2C3_CLK:
549 		*rate = CLOCK_GetLpi2cClkFreq(3);
550 		break;
551 #endif /* defined(FSL_FEATURE_SOC_LPI2C_COUNT) */
552 #endif /* defined(CONFIG_I2C_MCUX_LPI2C) */
553 
554 #if defined(CONFIG_DT_HAS_NXP_XSPI_ENABLED)
555 	case MCUX_XSPI0_CLK:
556 		*rate = CLOCK_GetXspiClkFreq(0);
557 		break;
558 	case MCUX_XSPI1_CLK:
559 		*rate = CLOCK_GetXspiClkFreq(1);
560 		break;
561 	case MCUX_XSPI2_CLK:
562 		*rate = CLOCK_GetXspiClkFreq(2);
563 		break;
564 #endif /* defined(CONFIG_DT_HAS_NXP_XSPI_ENABLED) */
565 
566 #if (defined(CONFIG_SPI_NXP_LPSPI) && CONFIG_SOC_FAMILY_MCXA)
567 	case MCUX_LPSPI0_CLK:
568 		*rate = CLOCK_GetLpspiClkFreq(0);
569 		break;
570 	case MCUX_LPSPI1_CLK:
571 		*rate = CLOCK_GetLpspiClkFreq(1);
572 		break;
573 #endif /* defined(CONFIG_SPI_NXP_LPSPI) */
574 	}
575 
576 	return 0;
577 }
578 
579 #if defined(CONFIG_MEMC)
580 /*
581  * Weak implemenetation of flexspi_clock_set_freq- SOC implementations are
582  * expected to override this
583  */
flexspi_clock_set_freq(uint32_t clock_name,uint32_t freq)584 __weak int flexspi_clock_set_freq(uint32_t clock_name, uint32_t freq)
585 {
586 	ARG_UNUSED(clock_name);
587 	ARG_UNUSED(freq);
588 	return -ENOTSUP;
589 }
590 #endif
591 
592 /*
593  * Since this function is used to reclock the FlexSPI when running in
594  * XIP, it must be located in RAM when MEMC driver is enabled.
595  */
596 #ifdef CONFIG_MEMC
597 #define SYSCON_SET_FUNC_ATTR __ramfunc
598 #else
599 #define SYSCON_SET_FUNC_ATTR
600 #endif
601 
mcux_lpc_syscon_clock_control_set_subsys_rate(const struct device * dev,clock_control_subsys_t subsys,clock_control_subsys_rate_t rate)602 static int SYSCON_SET_FUNC_ATTR mcux_lpc_syscon_clock_control_set_subsys_rate(
603 	const struct device *dev, clock_control_subsys_t subsys, clock_control_subsys_rate_t rate)
604 {
605 	uint32_t clock_name = (uintptr_t)subsys;
606 	uint32_t clock_rate = (uintptr_t)rate;
607 
608 	switch (clock_name) {
609 	case MCUX_FLEXSPI_CLK:
610 #if defined(CONFIG_MEMC)
611 		/* The SOC is using the FlexSPI for XIP. Therefore,
612 		 * the FlexSPI itself must be managed within the function,
613 		 * which is SOC specific.
614 		 */
615 		return flexspi_clock_set_freq(clock_name, clock_rate);
616 #endif
617 #if defined(CONFIG_MIPI_DBI_NXP_LCDIC)
618 	case MCUX_LCDIC_CLK:
619 		/* Set LCDIC clock div */
620 		uint32_t root_rate = (CLOCK_GetLcdClkFreq() *
621 				      ((CLKCTL0->LCDFCLKDIV & CLKCTL0_LCDFCLKDIV_DIV_MASK) + 1));
622 		CLOCK_SetClkDiv(kCLOCK_DivLcdClk, (root_rate / clock_rate));
623 		return 0;
624 #endif
625 	default:
626 		/* Silence unused variable warning */
627 		ARG_UNUSED(clock_rate);
628 		return -ENOTSUP;
629 	}
630 }
631 
mcux_lpc_syscon_clock_control_configure(const struct device * dev,clock_control_subsys_t sub_system,void * data)632 static int mcux_lpc_syscon_clock_control_configure(const struct device *dev,
633 						   clock_control_subsys_t sub_system, void *data)
634 {
635 #ifdef CONFIG_SOC_SERIES_RW6XX
636 #define FLEXCOMM_LP_CLK_DECODE(n) (n & 0x80)
637 	uint32_t clock_name = (uint32_t)sub_system;
638 	int flexcomm_num = -1;
639 
640 	switch (clock_name) {
641 	case MCUX_FLEXCOMM0_CLK:
642 	case MCUX_FLEXCOMM0_LP_CLK:
643 		flexcomm_num = 0;
644 		break;
645 	case MCUX_FLEXCOMM1_CLK:
646 	case MCUX_FLEXCOMM1_LP_CLK:
647 		flexcomm_num = 1;
648 		break;
649 	case MCUX_FLEXCOMM2_CLK:
650 	case MCUX_FLEXCOMM2_LP_CLK:
651 		flexcomm_num = 2;
652 		break;
653 	case MCUX_FLEXCOMM3_CLK:
654 	case MCUX_FLEXCOMM3_LP_CLK:
655 		flexcomm_num = 3;
656 		break;
657 	default:
658 		return -ENOTSUP;
659 	}
660 
661 	if (flexcomm_num >= 0) {
662 		static uint32_t frgclksels[4];
663 		static uint32_t frgctls[4];
664 
665 		if (FLEXCOMM_LP_CLK_DECODE(clock_name)) {
666 			frgclksels[flexcomm_num] = CLKCTL1->FLEXCOMM[flexcomm_num].FRGCLKSEL;
667 			frgctls[flexcomm_num] = CLKCTL1->FLEXCOMM[flexcomm_num].FRGCTL;
668 			CLKCTL1->FLEXCOMM[flexcomm_num].FRGCLKSEL = 0;
669 			CLKCTL1->FLEXCOMM[flexcomm_num].FRGCTL = 0;
670 		} else {
671 			CLKCTL1->FLEXCOMM[flexcomm_num].FRGCLKSEL = frgclksels[flexcomm_num];
672 			CLKCTL1->FLEXCOMM[flexcomm_num].FRGCTL = frgctls[flexcomm_num];
673 		}
674 	}
675 #endif
676 	return 0;
677 }
678 
679 static DEVICE_API(clock_control, mcux_lpc_syscon_api) = {
680 	.on = mcux_lpc_syscon_clock_control_on,
681 	.off = mcux_lpc_syscon_clock_control_off,
682 	.get_rate = mcux_lpc_syscon_clock_control_get_subsys_rate,
683 	.set_rate = mcux_lpc_syscon_clock_control_set_subsys_rate,
684 	.configure = mcux_lpc_syscon_clock_control_configure,
685 };
686 
687 #define LPC_CLOCK_INIT(n)                                                                          \
688                                                                                                    \
689 	DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, NULL, PRE_KERNEL_1,                             \
690 			      CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &mcux_lpc_syscon_api);
691 
692 DT_INST_FOREACH_STATUS_OKAY(LPC_CLOCK_INIT)
693