1 /*
2  * Copyright 2017, 2024-2025 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_imx_ccm
8 #include <errno.h>
9 #include <zephyr/arch/cpu.h>
10 #include <zephyr/sys/util.h>
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/dt-bindings/clock/imx_ccm.h>
13 #include <fsl_clock.h>
14 
15 #if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
16 #include <main/ipc.h>
17 #endif
18 
19 #define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL
20 #include <zephyr/logging/log.h>
21 LOG_MODULE_REGISTER(clock_control);
22 
23 #if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
24 #define AUD_PLL_DIV_CLK0_LPCG UINT_TO_POINTER(0x59D20000)
25 static sc_ipc_t ipc_handle;
26 #endif
27 
28 #ifdef CONFIG_SPI_NXP_LPSPI
29 static const clock_name_t lpspi_clocks[] = {
30 	kCLOCK_Usb1PllPfd1Clk,
31 	kCLOCK_Usb1PllPfd0Clk,
32 	kCLOCK_SysPllClk,
33 	kCLOCK_SysPllPfd2Clk,
34 };
35 #endif
36 #ifdef CONFIG_UART_MCUX_IUART
37 static const clock_root_control_t uart_clk_root[] = {
38 	kCLOCK_RootUart1,
39 	kCLOCK_RootUart2,
40 	kCLOCK_RootUart3,
41 	kCLOCK_RootUart4,
42 };
43 
44 static const clock_ip_name_t uart_clocks[] = {
45 	kCLOCK_Uart1,
46 	kCLOCK_Uart2,
47 	kCLOCK_Uart3,
48 	kCLOCK_Uart4,
49 };
50 #endif
51 
52 #ifdef CONFIG_UART_MCUX_LPUART
53 
54 #ifdef CONFIG_SOC_MIMX8QM6_ADSP
55 static const clock_ip_name_t lpuart_clocks[] = {
56 	kCLOCK_DMA_Lpuart0,
57 	kCLOCK_DMA_Lpuart1,
58 	kCLOCK_DMA_Lpuart2,
59 	kCLOCK_DMA_Lpuart3,
60 	kCLOCK_DMA_Lpuart4,
61 };
62 
63 static const uint32_t lpuart_rate = MHZ(80);
64 #endif /* CONFIG_SOC_MIMX8QM6_ADSP */
65 
66 #ifdef CONFIG_SOC_MIMX8QX6_ADSP
67 static const clock_ip_name_t lpuart_clocks[] = {
68 	kCLOCK_DMA_Lpuart0,
69 	kCLOCK_DMA_Lpuart1,
70 	kCLOCK_DMA_Lpuart2,
71 	kCLOCK_DMA_Lpuart3,
72 };
73 
74 static const uint32_t lpuart_rate = MHZ(80);
75 #endif /* CONFIG_SOC_MIMX8QX6_ADSP */
76 
77 #endif /* CONFIG_UART_MCUX_LPUART */
78 
79 #ifdef CONFIG_DAI_NXP_SAI
80 #if defined(CONFIG_SOC_MIMX8QX6_ADSP) || defined(CONFIG_SOC_MIMX8QM6_ADSP)
81 static const clock_ip_name_t sai_clocks[] = {
82 	kCLOCK_AUDIO_Sai1,
83 	kCLOCK_AUDIO_Sai2,
84 	kCLOCK_AUDIO_Sai3,
85 };
86 #endif
87 #endif /* CONFIG_DAI_NXP_SAI */
88 
89 #ifdef CONFIG_DAI_NXP_ESAI
90 #if defined(CONFIG_SOC_MIMX8QX6_ADSP) || defined(CONFIG_SOC_MIMX8QM6_ADSP)
91 static const clock_ip_name_t esai_clocks[] = {
92 	kCLOCK_AUDIO_Esai0,
93 	kCLOCK_AUDIO_Esai1,
94 };
95 #endif
96 #endif /* CONFIG_DAI_NXP_ESAI */
97 
98 #if defined(CONFIG_I2C_NXP_II2C)
99 static const clock_ip_name_t i2c_clk_root[] = {
100 	kCLOCK_RootI2c1,
101 	kCLOCK_RootI2c2,
102 	kCLOCK_RootI2c3,
103 	kCLOCK_RootI2c4,
104 #ifdef CONFIG_SOC_MIMX8ML8
105 	kCLOCK_RootI2c5,
106 	kCLOCK_RootI2c6,
107 #endif
108 };
109 #endif
110 
111 #if defined(CONFIG_CAN_MCUX_FLEXCAN) && defined(CONFIG_SOC_MIMX8ML8)
112 static const clock_ip_name_t flexcan_clk_root[] = {
113 	kCLOCK_RootFlexCan1,
114 	kCLOCK_RootFlexCan2,
115 };
116 #endif
117 
mcux_ccm_on(const struct device * dev,clock_control_subsys_t sub_system)118 static int mcux_ccm_on(const struct device *dev,
119 			      clock_control_subsys_t sub_system)
120 {
121 	uint32_t clock_name = (uintptr_t)sub_system;
122 	uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
123 
124 	switch (clock_name) {
125 #ifdef CONFIG_UART_MCUX_IUART
126 	case IMX_CCM_UART1_CLK:
127 	case IMX_CCM_UART2_CLK:
128 	case IMX_CCM_UART3_CLK:
129 	case IMX_CCM_UART4_CLK:
130 		CLOCK_EnableClock(uart_clocks[instance]);
131 		return 0;
132 #endif
133 
134 #if defined(CONFIG_UART_MCUX_LPUART) && defined(CONFIG_SOC_MIMX8QM6_ADSP)
135 	case IMX_CCM_LPUART1_CLK:
136 	case IMX_CCM_LPUART2_CLK:
137 	case IMX_CCM_LPUART3_CLK:
138 	case IMX_CCM_LPUART4_CLK:
139 	case IMX_CCM_LPUART5_CLK:
140 		CLOCK_EnableClock(lpuart_clocks[instance]);
141 		return 0;
142 #endif
143 
144 #if defined(CONFIG_UART_MCUX_LPUART) && defined(CONFIG_SOC_MIMX8QX6_ADSP)
145 	case IMX_CCM_LPUART1_CLK:
146 	case IMX_CCM_LPUART2_CLK:
147 	case IMX_CCM_LPUART3_CLK:
148 	case IMX_CCM_LPUART4_CLK:
149 		CLOCK_EnableClock(lpuart_clocks[instance]);
150 		return 0;
151 #endif
152 
153 #ifdef CONFIG_DAI_NXP_SAI
154 #if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
155 	case IMX_CCM_SAI1_CLK:
156 	case IMX_CCM_SAI2_CLK:
157 	case IMX_CCM_SAI3_CLK:
158 		CLOCK_EnableClock(sai_clocks[instance]);
159 		return 0;
160 #endif
161 #endif /* CONFIG_DAI_NXP_SAI */
162 
163 #ifdef CONFIG_DAI_NXP_ESAI
164 #if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
165 	case IMX_CCM_ESAI0_CLK:
166 	case IMX_CCM_ESAI1_CLK:
167 		CLOCK_EnableClock(esai_clocks[instance]);
168 		return 0;
169 #endif
170 #endif /* CONFIG_DAI_NXP_ESAI */
171 
172 #if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
173 	case IMX_CCM_AUD_PLL_DIV_CLK0:
174 		/* ungate PLL parent */
175 		sc_pm_clock_enable(ipc_handle, SC_R_AUDIO_PLL_0,
176 				   SC_PM_CLK_MISC0, true, false);
177 
178 		/* ungate the clock itself */
179 		CLOCK_SetLpcgGate(AUD_PLL_DIV_CLK0_LPCG, true, false, 0xa);
180 
181 		return 0;
182 #endif
183 
184 #if defined(CONFIG_ETH_NXP_ENET)
185 #ifdef CONFIG_SOC_SERIES_IMX8M
186 #define ENET_CLOCK	kCLOCK_Enet1
187 #else
188 #define ENET_CLOCK	kCLOCK_Enet
189 #endif
190 	case IMX_CCM_ENET_CLK:
191 		CLOCK_EnableClock(ENET_CLOCK);
192 		return 0;
193 #endif
194 	default:
195 		(void)instance;
196 		return 0;
197 	}
198 }
199 
mcux_ccm_off(const struct device * dev,clock_control_subsys_t sub_system)200 static int mcux_ccm_off(const struct device *dev,
201 			       clock_control_subsys_t sub_system)
202 {
203 	uint32_t clock_name = (uintptr_t)sub_system;
204 	uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
205 
206 	switch (clock_name) {
207 #ifdef CONFIG_UART_MCUX_IUART
208 	case IMX_CCM_UART1_CLK:
209 	case IMX_CCM_UART2_CLK:
210 	case IMX_CCM_UART3_CLK:
211 	case IMX_CCM_UART4_CLK:
212 		CLOCK_DisableClock(uart_clocks[instance]);
213 		return 0;
214 #endif
215 
216 #ifdef CONFIG_DAI_NXP_SAI
217 #if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
218 	case IMX_CCM_SAI1_CLK:
219 	case IMX_CCM_SAI2_CLK:
220 	case IMX_CCM_SAI3_CLK:
221 		CLOCK_DisableClock(sai_clocks[instance]);
222 		return 0;
223 #endif
224 #endif /* CONFIG_DAI_NXP_SAI */
225 
226 #ifdef CONFIG_DAI_NXP_ESAI
227 #if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
228 	case IMX_CCM_ESAI0_CLK:
229 	case IMX_CCM_ESAI1_CLK:
230 		CLOCK_DisableClock(esai_clocks[instance]);
231 		return 0;
232 #endif
233 #endif /* CONFIG_DAI_NXP_ESAI */
234 
235 #if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
236 	case IMX_CCM_AUD_PLL_DIV_CLK0:
237 		/* gate the clock itself */
238 		CLOCK_SetLpcgGate(AUD_PLL_DIV_CLK0_LPCG, false, false, 0xa);
239 
240 		/* gate PLL parent */
241 		sc_pm_clock_enable(ipc_handle, SC_R_AUDIO_PLL_0,
242 				   SC_PM_CLK_MISC0, false, false);
243 
244 		return 0;
245 #endif
246 	default:
247 		(void)instance;
248 		return 0;
249 	}
250 }
251 
mcux_ccm_get_subsys_rate(const struct device * dev,clock_control_subsys_t sub_system,uint32_t * rate)252 static int mcux_ccm_get_subsys_rate(const struct device *dev,
253 				    clock_control_subsys_t sub_system,
254 				    uint32_t *rate)
255 {
256 	uint32_t clock_name = (uintptr_t)sub_system;
257 
258 	switch (clock_name) {
259 
260 #ifdef CONFIG_I2C_MCUX_LPI2C
261 	case IMX_CCM_LPI2C_CLK:
262 		if (CLOCK_GetMux(kCLOCK_Lpi2cMux) == 0) {
263 			*rate = CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 8
264 				/ (CLOCK_GetDiv(kCLOCK_Lpi2cDiv) + 1);
265 		} else {
266 			*rate = CLOCK_GetOscFreq()
267 				/ (CLOCK_GetDiv(kCLOCK_Lpi2cDiv) + 1);
268 		}
269 
270 		break;
271 #endif
272 
273 #ifdef CONFIG_SPI_NXP_LPSPI
274 	case IMX_CCM_LPSPI_CLK:
275 	{
276 		uint32_t lpspi_mux = CLOCK_GetMux(kCLOCK_LpspiMux);
277 		clock_name_t lpspi_clock = lpspi_clocks[lpspi_mux];
278 
279 		*rate = CLOCK_GetFreq(lpspi_clock)
280 			/ (CLOCK_GetDiv(kCLOCK_LpspiDiv) + 1);
281 		break;
282 	}
283 #endif
284 
285 #ifdef CONFIG_UART_MCUX_LPUART
286 
287 #if defined(CONFIG_SOC_MIMX8QM6_ADSP)
288 	case IMX_CCM_LPUART1_CLK:
289 	case IMX_CCM_LPUART2_CLK:
290 	case IMX_CCM_LPUART3_CLK:
291 	case IMX_CCM_LPUART4_CLK:
292 	case IMX_CCM_LPUART5_CLK:
293 		uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
294 
295 		CLOCK_SetIpFreq(lpuart_clocks[instance], lpuart_rate);
296 		*rate = CLOCK_GetIpFreq(lpuart_clocks[instance]);
297 		break;
298 
299 #elif defined(CONFIG_SOC_MIMX8QX6_ADSP)
300 	case IMX_CCM_LPUART1_CLK:
301 	case IMX_CCM_LPUART2_CLK:
302 	case IMX_CCM_LPUART3_CLK:
303 	case IMX_CCM_LPUART4_CLK:
304 		uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
305 
306 		CLOCK_SetIpFreq(lpuart_clocks[instance], lpuart_rate);
307 		*rate = CLOCK_GetIpFreq(lpuart_clocks[instance]);
308 		break;
309 
310 #else
311 	case IMX_CCM_LPUART_CLK:
312 		if (CLOCK_GetMux(kCLOCK_UartMux) == 0) {
313 			*rate = CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6
314 				/ (CLOCK_GetDiv(kCLOCK_UartDiv) + 1);
315 		} else {
316 			*rate = CLOCK_GetOscFreq()
317 				/ (CLOCK_GetDiv(kCLOCK_UartDiv) + 1);
318 		}
319 
320 		break;
321 #endif
322 #endif
323 
324 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usdhc1)) && CONFIG_IMX_USDHC
325 	case IMX_CCM_USDHC1_CLK:
326 		*rate = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0) /
327 				(CLOCK_GetDiv(kCLOCK_Usdhc1Div) + 1U);
328 		break;
329 #endif
330 
331 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usdhc2)) && CONFIG_IMX_USDHC
332 	case IMX_CCM_USDHC2_CLK:
333 		*rate = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0) /
334 				(CLOCK_GetDiv(kCLOCK_Usdhc2Div) + 1U);
335 		break;
336 #endif
337 
338 #ifdef CONFIG_DMA_MCUX_EDMA
339 	case IMX_CCM_EDMA_CLK:
340 		*rate = CLOCK_GetIpgFreq();
341 		break;
342 #endif
343 
344 #ifdef CONFIG_PWM_MCUX
345 	case IMX_CCM_PWM_CLK:
346 		*rate = CLOCK_GetIpgFreq();
347 		break;
348 #endif
349 
350 #ifdef CONFIG_ETH_NXP_ENET
351 	case IMX_CCM_ENET_CLK:
352 #ifdef CONFIG_SOC_SERIES_IMX8M
353 		*rate = CLOCK_GetFreq(kCLOCK_EnetIpgClk);
354 #else
355 		*rate = CLOCK_GetIpgFreq();
356 #endif
357 #endif
358 		break;
359 
360 #ifdef CONFIG_PTP_CLOCK_NXP_ENET
361 	case IMX_CCM_ENET_PLL:
362 #if defined(CONFIG_SOC_SERIES_IMXRT10XX)
363 		*rate = CLOCK_GetPllFreq(kCLOCK_PllEnet25M);
364 #else
365 		*rate = CLOCK_GetPllFreq(kCLOCK_PllEnet);
366 #endif
367 		break;
368 #endif
369 
370 #ifdef CONFIG_UART_MCUX_IUART
371 	case IMX_CCM_UART1_CLK:
372 	case IMX_CCM_UART2_CLK:
373 	case IMX_CCM_UART3_CLK:
374 	case IMX_CCM_UART4_CLK:
375 	{
376 		uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
377 		clock_root_control_t clk_root = uart_clk_root[instance];
378 		uint32_t uart_mux = CLOCK_GetRootMux(clk_root);
379 
380 		if (uart_mux == 0) {
381 			*rate = MHZ(24);
382 		} else if (uart_mux == 1) {
383 			*rate = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) /
384 				(CLOCK_GetRootPreDivider(clk_root)) /
385 				(CLOCK_GetRootPostDivider(clk_root)) /
386 				10;
387 		}
388 
389 	} break;
390 #endif
391 
392 #ifdef CONFIG_CAN_MCUX_FLEXCAN
393 #ifdef CONFIG_SOC_MIMX8ML8
394 	case IMX_CCM_CAN1_CLK:
395 	case IMX_CCM_CAN2_CLK:
396 	{
397 		uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
398 		uint32_t can_mux = CLOCK_GetRootMux(flexcan_clk_root[instance]);
399 
400 		if (can_mux == 0) {
401 			*rate = MHZ(24);
402 		} else if (can_mux == 4) { /* SYSTEM_PLL1_CLK */
403 			*rate = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) /
404 				(CLOCK_GetRootPreDivider(flexcan_clk_root[instance])) /
405 				(CLOCK_GetRootPostDivider(flexcan_clk_root[instance]));
406 		}
407 	} break;
408 #else
409 	case IMX_CCM_CAN_CLK:
410 	{
411 		uint32_t can_mux = CLOCK_GetMux(kCLOCK_CanMux);
412 
413 		if (can_mux == 0) {
414 			*rate = CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 8
415 				/ (CLOCK_GetDiv(kCLOCK_CanDiv) + 1);
416 		} else if  (can_mux == 1) {
417 			*rate = CLOCK_GetOscFreq()
418 				/ (CLOCK_GetDiv(kCLOCK_CanDiv) + 1);
419 		} else {
420 			*rate = CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6
421 				/ (CLOCK_GetDiv(kCLOCK_CanDiv) + 1);
422 		}
423 	} break;
424 #endif
425 #endif
426 
427 #ifdef CONFIG_COUNTER_MCUX_GPT
428 	case IMX_CCM_GPT_CLK:
429 		*rate = CLOCK_GetFreq(kCLOCK_PerClk);
430 		break;
431 #ifdef CONFIG_SOC_SERIES_IMX8M
432 	case IMX_CCM_GPT_IPG_CLK:
433 	{
434 		uint32_t mux = CLOCK_GetRootMux(kCLOCK_RootGpt1);
435 
436 		if (mux == 0) {
437 			*rate = OSC24M_CLK_FREQ;
438 		} else {
439 			*rate = 0;
440 		}
441 	} break;
442 #endif
443 #endif
444 
445 #ifdef CONFIG_COUNTER_MCUX_QTMR
446 	case IMX_CCM_QTMR_CLK:
447 		*rate = CLOCK_GetIpgFreq();
448 		break;
449 #endif
450 
451 #ifdef CONFIG_I2S_MCUX_SAI
452 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai1))
453 	case IMX_CCM_SAI1_CLK:
454 		*rate = CLOCK_GetFreq(kCLOCK_AudioPllClk)
455 				/ (CLOCK_GetDiv(kCLOCK_Sai1PreDiv) + 1)
456 				/ (CLOCK_GetDiv(kCLOCK_Sai1Div) + 1);
457 		break;
458 #endif
459 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai2))
460 	case IMX_CCM_SAI2_CLK:
461 		*rate = CLOCK_GetFreq(kCLOCK_AudioPllClk)
462 				/ (CLOCK_GetDiv(kCLOCK_Sai2PreDiv) + 1)
463 				/ (CLOCK_GetDiv(kCLOCK_Sai2Div) + 1);
464 		break;
465 #endif
466 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai3))
467 	case IMX_CCM_SAI3_CLK:
468 		*rate = CLOCK_GetFreq(kCLOCK_AudioPllClk)
469 				/ (CLOCK_GetDiv(kCLOCK_Sai3PreDiv) + 1)
470 				/ (CLOCK_GetDiv(kCLOCK_Sai3Div) + 1);
471 		break;
472 #endif
473 #endif
474 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexspi))
475 	case IMX_CCM_FLEXSPI_CLK:
476 		*rate = CLOCK_GetClockRootFreq(kCLOCK_FlexspiClkRoot);
477 		break;
478 #endif
479 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexspi2))
480 	case IMX_CCM_FLEXSPI2_CLK:
481 		*rate = CLOCK_GetClockRootFreq(kCLOCK_Flexspi2ClkRoot);
482 		break;
483 #endif
484 #ifdef CONFIG_COUNTER_NXP_PIT
485 	case IMX_CCM_PIT_CLK:
486 		*rate = CLOCK_GetFreq(kCLOCK_PerClk);
487 		break;
488 #endif
489 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexio1)) && CONFIG_MCUX_FLEXIO
490 	case IMX_CCM_FLEXIO1_CLK:
491 	{
492 		uint32_t flexio_mux = CLOCK_GetMux(kCLOCK_Flexio1Mux);
493 		uint32_t source_clk_freq = 0;
494 
495 		if (flexio_mux == 0) {
496 			source_clk_freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
497 		} else if (flexio_mux == 1) {
498 			source_clk_freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd2);
499 	#ifdef PLL_VIDEO_OFFSET /* fsl_clock.h */
500 		} else if (flexio_mux == 2) {
501 			source_clk_freq = CLOCK_GetPllFreq(kCLOCK_PllVideo);
502 	#endif
503 		} else {
504 			source_clk_freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
505 		}
506 
507 		*rate = source_clk_freq / (CLOCK_GetDiv(kCLOCK_Flexio1PreDiv) + 1)
508 					/ (CLOCK_GetDiv(kCLOCK_Flexio1Div) + 1);
509 	} break;
510 #endif
511 #if (DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexio2)) \
512 		 || DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexio3))) && CONFIG_MCUX_FLEXIO
513 	case IMX_CCM_FLEXIO2_3_CLK:
514 	{
515 		uint32_t flexio_mux = CLOCK_GetMux(kCLOCK_Flexio2Mux);
516 		uint32_t source_clk_freq = 0;
517 
518 		if (flexio_mux == 0) {
519 			source_clk_freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
520 		} else if (flexio_mux == 1) {
521 			source_clk_freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd2);
522 	#ifdef PLL_VIDEO_OFFSET /* fsl_clock.h */
523 		} else if (flexio_mux == 2) {
524 			source_clk_freq = CLOCK_GetPllFreq(kCLOCK_PllVideo);
525 	#endif
526 		} else {
527 			source_clk_freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
528 		}
529 
530 		*rate = source_clk_freq / (CLOCK_GetDiv(kCLOCK_Flexio2PreDiv) + 1)
531 					/ (CLOCK_GetDiv(kCLOCK_Flexio2Div) + 1);
532 	} break;
533 #endif
534 
535 #ifdef CONFIG_SPI_MCUX_ECSPI
536 	case IMX_CCM_ECSPI1_CLK:
537 		*rate = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) /
538 			(CLOCK_GetRootPreDivider(kCLOCK_RootEcspi1)) /
539 			(CLOCK_GetRootPostDivider(kCLOCK_RootEcspi1));
540 		break;
541 	case IMX_CCM_ECSPI2_CLK:
542 		*rate = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) /
543 			(CLOCK_GetRootPreDivider(kCLOCK_RootEcspi2)) /
544 			(CLOCK_GetRootPostDivider(kCLOCK_RootEcspi2));
545 		break;
546 	case IMX_CCM_ECSPI3_CLK:
547 		*rate = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) /
548 			(CLOCK_GetRootPreDivider(kCLOCK_RootEcspi3)) /
549 			(CLOCK_GetRootPostDivider(kCLOCK_RootEcspi3));
550 		break;
551 #endif /* CONFIG_SPI_MCUX_ECSPI */
552 
553 #if defined(CONFIG_I2C_NXP_II2C)
554 	case IMX_CCM_I2C1_CLK:
555 	case IMX_CCM_I2C2_CLK:
556 	case IMX_CCM_I2C3_CLK:
557 	case IMX_CCM_I2C4_CLK:
558 #ifdef CONFIG_SOC_MIMX8ML8
559 	case IMX_CCM_I2C5_CLK:
560 	case IMX_CCM_I2C6_CLK:
561 #endif
562 	{
563 		uint32_t instance = clock_name & IMX_CCM_INSTANCE_MASK;
564 		uint32_t i2c_mux = CLOCK_GetRootMux(i2c_clk_root[instance]);
565 
566 		if (i2c_mux == 0) {
567 			*rate = MHZ(24);
568 		} else if (i2c_mux == 1) {
569 			*rate = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) /
570 				(CLOCK_GetRootPreDivider(i2c_clk_root[instance])) /
571 				(CLOCK_GetRootPostDivider(i2c_clk_root[instance])) /
572 				5; /* SYSTEM PLL1 DIV5 */
573 		}
574 
575 	} break;
576 #endif
577 	}
578 
579 	return 0;
580 }
581 
582 /*
583  * Since this function is used to reclock the FlexSPI when running in
584  * XIP, it must be located in RAM when MEMC Flexspi driver is enabled.
585  */
586 #ifdef CONFIG_MEMC_MCUX_FLEXSPI
587 #define CCM_SET_FUNC_ATTR __ramfunc
588 #else
589 #define CCM_SET_FUNC_ATTR
590 #endif
591 
mcux_ccm_set_subsys_rate(const struct device * dev,clock_control_subsys_t subsys,clock_control_subsys_rate_t rate)592 static int CCM_SET_FUNC_ATTR mcux_ccm_set_subsys_rate(const struct device *dev,
593 			clock_control_subsys_t subsys,
594 			clock_control_subsys_rate_t rate)
595 {
596 	uint32_t clock_name = (uintptr_t)subsys;
597 	uint32_t clock_rate = (uintptr_t)rate;
598 
599 	switch (clock_name) {
600 	case IMX_CCM_FLEXSPI_CLK:
601 		__fallthrough;
602 	case IMX_CCM_FLEXSPI2_CLK:
603 #if defined(CONFIG_SOC_SERIES_IMXRT10XX) && defined(CONFIG_MEMC_MCUX_FLEXSPI)
604 		/* The SOC is using the FlexSPI for XIP. Therefore,
605 		 * the FlexSPI itself must be managed within the function,
606 		 * which is SOC specific.
607 		 */
608 		return flexspi_clock_set_freq(clock_name, clock_rate);
609 #endif
610 	default:
611 		/* Silence unused variable warning */
612 		ARG_UNUSED(clock_rate);
613 		return -ENOTSUP;
614 	}
615 }
616 
617 
618 
619 static DEVICE_API(clock_control, mcux_ccm_driver_api) = {
620 	.on = mcux_ccm_on,
621 	.off = mcux_ccm_off,
622 	.get_rate = mcux_ccm_get_subsys_rate,
623 	.set_rate = mcux_ccm_set_subsys_rate,
624 };
625 
mcux_ccm_init(const struct device * dev)626 static int mcux_ccm_init(const struct device *dev)
627 {
628 #if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP)
629 	int ret;
630 
631 	ret = sc_ipc_open(&ipc_handle, DT_REG_ADDR(DT_NODELABEL(scu_mu)));
632 	if (ret != SC_ERR_NONE) {
633 		return -ENODEV;
634 	}
635 
636 	CLOCK_Init(ipc_handle);
637 #endif
638 	return 0;
639 }
640 
641 DEVICE_DT_INST_DEFINE(0, mcux_ccm_init, NULL, NULL, NULL,
642 		      PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
643 		      &mcux_ccm_driver_api);
644