aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1011/drivers/fsl_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1011/drivers/fsl_clock.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1011/drivers/fsl_clock.c1202
1 files changed, 1202 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1011/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1011/drivers/fsl_clock.c
new file mode 100644
index 000000000..7a7fc944c
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1011/drivers/fsl_clock.c
@@ -0,0 +1,1202 @@
1/*
2 * Copyright 2019 - 2020 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include "fsl_clock.h"
9/* Component ID definition, used by tools. */
10#ifndef FSL_COMPONENT_ID
11#define FSL_COMPONENT_ID "platform.drivers.clock"
12#endif
13
14/*******************************************************************************
15 * Definitions
16 ******************************************************************************/
17/* To make full use of CM7 hardware FPU, use double instead of uint64_t in clock driver to
18achieve better performance, it is depend on the IDE Floating point settings, if double precision is selected
19in IDE, clock_64b_t will switch to double type automatically. only support IAR and MDK here */
20#if __FPU_USED
21
22#if (defined(__ICCARM__))
23
24#if (__ARMVFP__ >= __ARMFPV5__) && \
25 (__ARM_FP == 0xE) /*0xe implies support for half, single and double precision operations*/
26typedef double clock_64b_t;
27#else
28typedef uint64_t clock_64b_t;
29#endif
30
31#elif (defined(__GNUC__))
32
33#if (__ARM_FP == 0xE) /*0xe implies support for half, single and double precision operations*/
34typedef double clock_64b_t;
35#else
36typedef uint64_t clock_64b_t;
37#endif
38
39#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
40
41#if defined __TARGET_FPU_FPV5_D16
42typedef double clock_64b_t;
43#else
44typedef uint64_t clock_64b_t;
45#endif
46
47#else
48typedef uint64_t clock_64b_t;
49#endif
50
51#else
52typedef uint64_t clock_64b_t;
53#endif
54
55/*******************************************************************************
56 * Variables
57 ******************************************************************************/
58
59/* External XTAL (OSC) clock frequency. */
60volatile uint32_t g_xtalFreq;
61/* External RTC XTAL clock frequency. */
62volatile uint32_t g_rtcXtalFreq;
63
64/*******************************************************************************
65 * Prototypes
66 ******************************************************************************/
67
68/*!
69 * @brief Get the periph clock frequency.
70 *
71 * @return Periph clock frequency in Hz.
72 */
73static uint32_t CLOCK_GetPeriphClkFreq(void);
74
75/*!
76 * @brief Get the periph clock2 frequency.
77 *
78 * @return Periph clock2 frequency in Hz.
79 */
80static uint32_t CLOCK_GetPeriphClk2Freq(void);
81
82/*!
83 * @brief Get Flexspi selection frequency.
84 *
85 * @return Flexspi selection frequency in Hz.
86 */
87static uint32_t CLOCK_GetFlexspiSelFreq(void);
88
89/*!
90 * @brief Get the frequency of PLL USB1 software clock.
91 *
92 * @return The frequency of PLL USB1 software clock.
93 */
94static uint32_t CLOCK_GetPllUsb1SWFreq(void);
95/*******************************************************************************
96 * Code
97 ******************************************************************************/
98
99static uint32_t CLOCK_GetPeriphClkFreq(void)
100{
101 uint32_t freq;
102
103 /* Periph_clk2_clk ---> Periph_clk */
104 if ((CCM->CBCDR & CCM_CBCDR_PERIPH_CLK_SEL_MASK) != 0UL)
105 {
106 switch (CCM->CBCMR & CCM_CBCMR_PERIPH_CLK2_SEL_MASK)
107 {
108 /* Pll3_sw_clk ---> Periph_clk2_clk ---> Periph_clk */
109 case CCM_CBCMR_PERIPH_CLK2_SEL(0U):
110 freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
111 break;
112
113 /* Osc_clk ---> Periph_clk2_clk ---> Periph_clk */
114 case CCM_CBCMR_PERIPH_CLK2_SEL(1U):
115 freq = CLOCK_GetOscFreq();
116 break;
117
118 case CCM_CBCMR_PERIPH_CLK2_SEL(2U):
119 freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
120 break;
121
122 case CCM_CBCMR_PERIPH_CLK2_SEL(3U):
123 default:
124 freq = 0U;
125 break;
126 }
127 }
128 /* Pre_Periph_clk ---> Periph_clk */
129 else
130 {
131 switch (CCM->CBCMR & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
132 {
133 /* PLL2 */
134 case CCM_CBCMR_PRE_PERIPH_CLK_SEL(0U):
135 freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
136 break;
137
138 /* PLL3 PFD3 */
139 case CCM_CBCMR_PRE_PERIPH_CLK_SEL(1U):
140 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd3);
141 break;
142
143 /* PLL2 PFD3 */
144 case CCM_CBCMR_PRE_PERIPH_CLK_SEL(2U):
145 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd3);
146 break;
147
148 /* PLL6 divided(/1) */
149 case CCM_CBCMR_PRE_PERIPH_CLK_SEL(3U):
150 freq = 500000000U;
151 break;
152
153 default:
154 freq = 0U;
155 break;
156 }
157 }
158
159 return freq;
160}
161
162static uint32_t CLOCK_GetPllUsb1SWFreq(void)
163{
164 uint32_t freq;
165
166 switch ((CCM->CCSR & CCM_CCSR_PLL3_SW_CLK_SEL_MASK) >> CCM_CCSR_PLL3_SW_CLK_SEL_SHIFT)
167 {
168 case 0:
169 {
170 freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
171 break;
172 }
173 case 1:
174 {
175 freq = 24000000UL;
176 break;
177 }
178 default:
179 freq = 0UL;
180 break;
181 }
182
183 return freq;
184}
185
186static uint32_t CLOCK_GetPeriphClk2Freq(void)
187{
188 uint32_t freq;
189
190 switch (CCM->CBCMR & CCM_CBCMR_PERIPH_CLK2_SEL_MASK)
191 {
192 /* Pll3_sw_clk ---> Periph_clk2_clk ---> Periph_clk */
193 case CCM_CBCMR_PERIPH_CLK2_SEL(0U):
194 freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
195 break;
196
197 /* Osc_clk ---> Periph_clk2_clk ---> Periph_clk */
198 case CCM_CBCMR_PERIPH_CLK2_SEL(1U):
199 freq = CLOCK_GetOscFreq();
200 break;
201
202 case CCM_CBCMR_PERIPH_CLK2_SEL(2U):
203 freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
204 break;
205
206 case CCM_CBCMR_PERIPH_CLK2_SEL(3U):
207 default:
208 freq = 0U;
209 break;
210 }
211
212 return freq;
213}
214
215static uint32_t CLOCK_GetFlexspiSelFreq(void)
216{
217 uint32_t freq;
218
219 switch ((CCM->CSCMR1 & CCM_CSCMR1_FLEXSPI_CLK_SEL_MASK) >> CCM_CSCMR1_FLEXSPI_CLK_SEL_SHIFT)
220 {
221 case 0:
222 freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
223 break;
224 case 1:
225 freq = CLOCK_GetPllUsb1SWFreq();
226 break;
227 case 2:
228 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
229 break;
230 case 3:
231 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd0);
232 break;
233 default:
234 freq = 0UL;
235 break;
236 }
237
238 return freq;
239}
240
241/*!
242 * brief Initialize the external 24MHz clock.
243 *
244 * This function supports two modes:
245 * 1. Use external crystal oscillator.
246 * 2. Bypass the external crystal oscillator, using input source clock directly.
247 *
248 * After this function, please call ref CLOCK_SetXtal0Freq to inform clock driver
249 * the external clock frequency.
250 *
251 * param bypassXtalOsc Pass in true to bypass the external crystal oscillator.
252 * note This device does not support bypass external crystal oscillator, so
253 * the input parameter should always be false.
254 */
255void CLOCK_InitExternalClk(bool bypassXtalOsc)
256{
257 /* This device does not support bypass XTAL OSC. */
258 assert(!bypassXtalOsc);
259
260 CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power up */
261 while ((XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_MASK) == 0UL)
262 {
263 }
264 CCM_ANALOG->MISC0_SET = (uint32_t)CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; /* detect freq */
265 while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_OSC_XTALOK_MASK) == 0UL)
266 {
267 }
268 CCM_ANALOG->MISC0_CLR = (uint32_t)CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK;
269}
270
271/*!
272 * brief Deinitialize the external 24MHz clock.
273 *
274 * This function disables the external 24MHz clock.
275 *
276 * After this function, please call ref CLOCK_SetXtal0Freq to set external clock
277 * frequency to 0.
278 */
279void CLOCK_DeinitExternalClk(void)
280{
281 CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power down */
282}
283
284/*!
285 * brief Switch the OSC.
286 *
287 * This function switches the OSC source for SoC.
288 *
289 * param osc OSC source to switch to.
290 */
291void CLOCK_SwitchOsc(clock_osc_t osc)
292{
293 if (osc == kCLOCK_RcOsc)
294 {
295 XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_SET_OSC_SEL_MASK;
296 }
297 else
298 {
299 XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_MASK;
300 }
301}
302
303/*!
304 * brief Initialize the RC oscillator 24MHz clock.
305 */
306void CLOCK_InitRcOsc24M(void)
307{
308 XTALOSC24M->LOWPWR_CTRL |= XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK;
309}
310
311/*!
312 * brief Power down the RCOSC 24M clock.
313 */
314void CLOCK_DeinitRcOsc24M(void)
315{
316 XTALOSC24M->LOWPWR_CTRL &= ~XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK;
317}
318
319/*!
320 * brief Gets the AHB clock frequency.
321 *
322 * return The AHB clock frequency value in hertz.
323 */
324uint32_t CLOCK_GetCoreFreq(void)
325{
326 return CLOCK_GetPeriphClkFreq() / (((CCM->CBCDR & CCM_CBCDR_AHB_PODF_MASK) >> CCM_CBCDR_AHB_PODF_SHIFT) + 1U);
327}
328
329/*!
330 * brief Gets the IPG clock frequency.
331 *
332 * return The IPG clock frequency value in hertz.
333 */
334uint32_t CLOCK_GetIpgFreq(void)
335{
336 return CLOCK_GetCoreFreq() / (((CCM->CBCDR & CCM_CBCDR_IPG_PODF_MASK) >> CCM_CBCDR_IPG_PODF_SHIFT) + 1U);
337}
338
339/*!
340 * brief Gets the PER clock frequency.
341 *
342 * return The PER clock frequency value in hertz.
343 */
344uint32_t CLOCK_GetPerClkFreq(void)
345{
346 uint32_t freq;
347
348 /* Osc_clk ---> PER Clock*/
349 if ((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK) != 0UL)
350 {
351 freq = CLOCK_GetOscFreq();
352 }
353 /* Periph_clk ---> AHB Clock ---> IPG Clock ---> PER Clock */
354 else
355 {
356 freq = CLOCK_GetIpgFreq();
357 }
358
359 freq /= (((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_PODF_MASK) >> CCM_CSCMR1_PERCLK_PODF_SHIFT) + 1U);
360
361 return freq;
362}
363
364/*!
365 * brief Gets the clock frequency for a specific clock name.
366 *
367 * This function checks the current clock configurations and then calculates
368 * the clock frequency for a specific clock name defined in clock_name_t.
369 *
370 * param clockName Clock names defined in clock_name_t
371 * return Clock frequency value in hertz
372 */
373uint32_t CLOCK_GetFreq(clock_name_t name)
374{
375 uint32_t freq;
376
377 switch (name)
378 {
379 case kCLOCK_CpuClk:
380 case kCLOCK_CoreClk:
381 freq = CLOCK_GetCoreFreq();
382 break;
383
384 case kCLOCK_IpgClk:
385 freq = CLOCK_GetIpgFreq();
386 break;
387
388 case kCLOCK_PerClk:
389 freq = CLOCK_GetPerClkFreq();
390 break;
391
392 case kCLOCK_OscClk:
393 freq = CLOCK_GetOscFreq();
394 break;
395 case kCLOCK_RtcClk:
396 freq = CLOCK_GetRtcFreq();
397 break;
398 case kCLOCK_Usb1PllClk:
399 freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
400 break;
401 case kCLOCK_Usb1PllPfd0Clk:
402 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd0);
403 break;
404 case kCLOCK_Usb1PllPfd1Clk:
405 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1);
406 break;
407 case kCLOCK_Usb1PllPfd2Clk:
408 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd2);
409 break;
410 case kCLOCK_Usb1PllPfd3Clk:
411 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd3);
412 break;
413 case kCLOCK_Usb1SwClk:
414 freq = CLOCK_GetPllUsb1SWFreq();
415 break;
416 case kCLOCK_Usb1Sw60MClk:
417 freq = CLOCK_GetPllUsb1SWFreq() / 8UL;
418 break;
419 case kCLOCK_Usb1Sw80MClk:
420 freq = CLOCK_GetPllUsb1SWFreq() / 6UL;
421 break;
422 case kCLOCK_SysPllClk:
423 freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
424 break;
425 case kCLOCK_SysPllPfd0Clk:
426 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0);
427 break;
428 case kCLOCK_SysPllPfd1Clk:
429 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd1);
430 break;
431 case kCLOCK_SysPllPfd2Clk:
432 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
433 break;
434 case kCLOCK_SysPllPfd3Clk:
435 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd3);
436 break;
437 case kCLOCK_EnetPll500MClk:
438 freq = CLOCK_GetPllFreq(kCLOCK_PllEnet500M);
439 break;
440 case kCLOCK_AudioPllClk:
441 freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
442 break;
443 default:
444 freq = 0U;
445 break;
446 }
447
448 return freq;
449}
450
451/*!
452 * brief Gets the frequency of selected clock root.
453 *
454 * param clockRoot The clock root used to get the frequency, please refer to @ref clock_root_t.
455 * return The frequency of selected clock root.
456 */
457uint32_t CLOCK_GetClockRootFreq(clock_root_t clockRoot)
458{
459 const clock_name_t clockRootSourceArray[][4] = CLOCK_ROOT_SOUCE;
460 const clock_mux_t clockRootMuxTupleArray[] = CLOCK_ROOT_MUX_TUPLE;
461 const clock_div_t clockRootDivTupleArray[][2] = CLOCK_ROOT_DIV_TUPLE;
462 uint32_t freq = 0UL;
463 clock_mux_t clockRootMuxTuple = clockRootMuxTupleArray[(uint8_t)clockRoot];
464 clock_div_t clockRootPreDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][0];
465 clock_div_t clockRootPostDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][1];
466 uint32_t clockRootMuxValue = (CCM_TUPLE_REG(CCM, clockRootMuxTuple) & CCM_TUPLE_MASK(clockRootMuxTuple)) >>
467 CCM_TUPLE_SHIFT(clockRootMuxTuple);
468 clock_name_t clockSourceName;
469
470 clockSourceName = clockRootSourceArray[(uint8_t)clockRoot][clockRootMuxValue];
471
472 assert(clockSourceName != kCLOCK_NoneName);
473
474 if (clockSourceName == kCLOCK_PeriphClk2)
475 {
476 freq = CLOCK_GetPeriphClk2Freq();
477 }
478 else if (clockSourceName == kCLOCK_FlexspiSel)
479 {
480 freq = CLOCK_GetFlexspiSelFreq();
481 }
482 else
483 {
484 freq = CLOCK_GetFreq(clockSourceName);
485 }
486
487 if (clockRootPreDivTuple != kCLOCK_NonePreDiv)
488 {
489 freq /= ((CCM_TUPLE_REG(CCM, clockRootPreDivTuple) & CCM_TUPLE_MASK(clockRootPreDivTuple)) >>
490 CCM_TUPLE_SHIFT(clockRootPreDivTuple)) +
491 1UL;
492 }
493
494 freq /= ((CCM_TUPLE_REG(CCM, clockRootPostDivTuple) & CCM_TUPLE_MASK(clockRootPostDivTuple)) >>
495 CCM_TUPLE_SHIFT(clockRootPostDivTuple)) +
496 1UL;
497
498 return freq;
499}
500
501/*! brief Enable USB HS clock.
502 *
503 * This function only enables the access to USB HS prepheral, upper layer
504 * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY
505 * clock to use USB HS.
506 *
507 * param src USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused.
508 * param freq USB HS does not care about the clock source, so this parameter is ignored.
509 * retval true The clock is set successfully.
510 * retval false The clock source is invalid to get proper USB HS clock.
511 */
512bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq)
513{
514 uint32_t i;
515 CCM->CCGR6 |= CCM_CCGR6_CG0_MASK;
516 USB->USBCMD |= USBHS_USBCMD_RST_MASK;
517
518 /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/
519 for (i = 0; i < 400000UL; i++)
520 {
521 __ASM("nop");
522 }
523 PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) |
524 (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK);
525 return true;
526}
527
528/*! brief Enable USB HS PHY PLL clock.
529 *
530 * This function enables the internal 480MHz USB PHY PLL clock.
531 *
532 * param src USB HS PHY PLL clock source.
533 * param freq The frequency specified by src.
534 * retval true The clock is set successfully.
535 * retval false The clock source is invalid to get proper USB HS clock.
536 */
537bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
538{
539 const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U};
540 if ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_ENABLE_MASK) != 0UL)
541 {
542 CCM_ANALOG->PLL_USB1 |= CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK;
543 }
544 else
545 {
546 CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll);
547 }
548 USBPHY->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */
549 USBPHY->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK;
550
551 USBPHY->PWD = 0;
552 USBPHY->CTRL |= USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK | USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK |
553 USBPHY_CTRL_ENUTMILEVEL2_MASK | USBPHY_CTRL_ENUTMILEVEL3_MASK;
554 return true;
555}
556
557/*! brief Disable USB HS PHY PLL clock.
558 *
559 * This function disables USB HS PHY PLL clock.
560 */
561void CLOCK_DisableUsbhs0PhyPllClock(void)
562{
563 CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK;
564 USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
565}
566
567/*!
568 * brief Initialize the System PLL.
569 *
570 * This function initializes the System PLL with specific settings
571 *
572 * param config Configuration to set to PLL.
573 */
574void CLOCK_InitSysPll(const clock_sys_pll_config_t *config)
575{
576 /* Bypass PLL first */
577 CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK)) |
578 CCM_ANALOG_PLL_SYS_BYPASS_MASK | CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC(config->src);
579
580 CCM_ANALOG->PLL_SYS =
581 (CCM_ANALOG->PLL_SYS & (~(CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK | CCM_ANALOG_PLL_SYS_POWERDOWN_MASK))) |
582 CCM_ANALOG_PLL_SYS_ENABLE_MASK | CCM_ANALOG_PLL_SYS_DIV_SELECT(config->loopDivider);
583
584 /* Initialize the fractional mode */
585 CCM_ANALOG->PLL_SYS_NUM = CCM_ANALOG_PLL_SYS_NUM_A(config->numerator);
586 CCM_ANALOG->PLL_SYS_DENOM = CCM_ANALOG_PLL_SYS_DENOM_B(config->denominator);
587
588 /* Initialize the spread spectrum mode */
589 CCM_ANALOG->PLL_SYS_SS = CCM_ANALOG_PLL_SYS_SS_STEP(config->ss_step) |
590 CCM_ANALOG_PLL_SYS_SS_ENABLE(config->ss_enable) |
591 CCM_ANALOG_PLL_SYS_SS_STOP(config->ss_stop);
592
593 while ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_LOCK_MASK) == 0UL)
594 {
595 }
596
597 /* Disable Bypass */
598 CCM_ANALOG->PLL_SYS &= ~CCM_ANALOG_PLL_SYS_BYPASS_MASK;
599}
600
601/*!
602 * brief De-initialize the System PLL.
603 */
604void CLOCK_DeinitSysPll(void)
605{
606 CCM_ANALOG->PLL_SYS = CCM_ANALOG_PLL_SYS_POWERDOWN_MASK;
607}
608
609/*!
610 * brief Initialize the USB1 PLL.
611 *
612 * This function initializes the USB1 PLL with specific settings
613 *
614 * param config Configuration to set to PLL.
615 */
616void CLOCK_InitUsb1Pll(const clock_usb_pll_config_t *config)
617{
618 /* Bypass PLL first */
619 CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) |
620 CCM_ANALOG_PLL_USB1_BYPASS_MASK | CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC(config->src);
621
622 CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK)) |
623 CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK |
624 CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider);
625
626 while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0UL)
627 {
628 }
629
630 /* Disable Bypass */
631 CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_BYPASS_MASK;
632}
633
634/*!
635 * brief Deinitialize the USB1 PLL.
636 */
637void CLOCK_DeinitUsb1Pll(void)
638{
639 CCM_ANALOG->PLL_USB1 = 0U;
640}
641
642/*!
643 * brief Initializes the Audio PLL.
644 *
645 * This function initializes the Audio PLL with specific settings
646 *
647 * param config Configuration to set to PLL.
648 */
649void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config)
650{
651 uint32_t pllAudio;
652 uint32_t misc2 = 0;
653
654 /* Bypass PLL first */
655 CCM_ANALOG->PLL_AUDIO = (CCM_ANALOG->PLL_AUDIO & (~CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC_MASK)) |
656 CCM_ANALOG_PLL_AUDIO_BYPASS_MASK | CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC(config->src);
657
658 CCM_ANALOG->PLL_AUDIO_NUM = CCM_ANALOG_PLL_AUDIO_NUM_A(config->numerator);
659 CCM_ANALOG->PLL_AUDIO_DENOM = CCM_ANALOG_PLL_AUDIO_DENOM_B(config->denominator);
660
661 /*
662 * Set post divider:
663 *
664 * ------------------------------------------------------------------------
665 * | config->postDivider | PLL_AUDIO[POST_DIV_SELECT] | MISC2[AUDIO_DIV] |
666 * ------------------------------------------------------------------------
667 * | 1 | 2 | 0 |
668 * ------------------------------------------------------------------------
669 * | 2 | 1 | 0 |
670 * ------------------------------------------------------------------------
671 * | 4 | 2 | 3 |
672 * ------------------------------------------------------------------------
673 * | 8 | 1 | 3 |
674 * ------------------------------------------------------------------------
675 * | 16 | 0 | 3 |
676 * ------------------------------------------------------------------------
677 */
678 pllAudio =
679 (CCM_ANALOG->PLL_AUDIO & (~(CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK | CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK))) |
680 CCM_ANALOG_PLL_AUDIO_ENABLE_MASK | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(config->loopDivider);
681
682 switch (config->postDivider)
683 {
684 case 16:
685 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0);
686 misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
687 break;
688
689 case 8:
690 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1);
691 misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
692 break;
693
694 case 4:
695 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
696 misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
697 break;
698
699 case 2:
700 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1);
701 break;
702
703 default:
704 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
705 break;
706 }
707
708 CCM_ANALOG->MISC2 =
709 (CCM_ANALOG->MISC2 & ~(CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK)) | misc2;
710
711 CCM_ANALOG->PLL_AUDIO = pllAudio;
712
713 while ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK_MASK) == 0UL)
714 {
715 }
716
717 /* Disable Bypass */
718 CCM_ANALOG->PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_BYPASS_MASK;
719}
720
721/*!
722 * brief De-initialize the Audio PLL.
723 */
724void CLOCK_DeinitAudioPll(void)
725{
726 CCM_ANALOG->PLL_AUDIO = CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK;
727}
728
729/*!
730 * brief Initialize the ENET PLL.
731 *
732 * This function initializes the ENET PLL with specific settings.
733 *
734 * param config Configuration to set to PLL.
735 */
736void CLOCK_InitEnetPll(const clock_enet_pll_config_t *config)
737{
738 uint32_t enet_pll = 0;
739
740 CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC_MASK)) |
741 CCM_ANALOG_PLL_ENET_BYPASS_MASK | CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC(config->src);
742
743 if (config->enableClkOutput500M)
744 {
745 enet_pll |= CCM_ANALOG_PLL_ENET_ENET_500M_REF_EN_MASK;
746 }
747
748 CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_POWERDOWN_MASK)) | enet_pll;
749
750 /* Wait for stable */
751 while ((CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_LOCK_MASK) == 0UL)
752 {
753 }
754
755 /* Disable Bypass */
756 CCM_ANALOG->PLL_ENET &= ~CCM_ANALOG_PLL_ENET_BYPASS_MASK;
757}
758
759/*!
760 * brief Deinitialize the ENET PLL.
761 *
762 * This function disables the ENET PLL.
763 */
764void CLOCK_DeinitEnetPll(void)
765{
766 CCM_ANALOG->PLL_ENET = CCM_ANALOG_PLL_ENET_POWERDOWN_MASK;
767}
768
769/*!
770 * brief Get current PLL output frequency.
771 *
772 * This function get current output frequency of specific PLL
773 *
774 * param pll pll name to get frequency.
775 * return The PLL output frequency in hertz.
776 */
777uint32_t CLOCK_GetPllFreq(clock_pll_t pll)
778{
779 uint32_t freq;
780 uint32_t divSelect;
781 clock_64b_t freqTmp;
782
783 /* check if PLL is enabled */
784 if (!CLOCK_IsPllEnabled(CCM_ANALOG, pll))
785 {
786 return 0U;
787 }
788
789 /* get pll reference clock */
790 freq = CLOCK_GetPllBypassRefClk(CCM_ANALOG, pll);
791
792 /* check if pll is bypassed */
793 if (CLOCK_IsPllBypassed(CCM_ANALOG, pll))
794 {
795 return freq;
796 }
797
798 switch (pll)
799 {
800 case kCLOCK_PllSys:
801 /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
802 freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_SYS_NUM)));
803 freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_SYS_DENOM));
804
805 if ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK) != 0UL)
806 {
807 freq *= 22U;
808 }
809 else
810 {
811 freq *= 20U;
812 }
813
814 freq += (uint32_t)freqTmp;
815 break;
816
817 case kCLOCK_PllUsb1:
818 freq = (freq * (((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK) != 0UL) ? 22U : 20U));
819 break;
820
821 case kCLOCK_PllAudio:
822 /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
823 divSelect =
824 (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_AUDIO_DIV_SELECT_SHIFT;
825
826 freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_NUM)));
827 freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_DENOM));
828
829 freq = freq * divSelect + (uint32_t)freqTmp;
830
831 /* AUDIO PLL output = PLL output frequency / POSTDIV. */
832
833 /*
834 * Post divider:
835 *
836 * PLL_AUDIO[POST_DIV_SELECT]:
837 * 0x00: 4
838 * 0x01: 2
839 * 0x02: 1
840 *
841 * MISC2[AUDO_DIV]:
842 * 0x00: 1
843 * 0x01: 2
844 * 0x02: 1
845 * 0x03: 4
846 */
847 switch (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT_MASK)
848 {
849 case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0U):
850 freq = freq >> 2U;
851 break;
852
853 case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1U):
854 freq = freq >> 1U;
855 break;
856
857 default:
858 /* Add comment to avoid MISRA C-2012 rule 16.4 */
859 break;
860 }
861
862 switch (CCM_ANALOG->MISC2 & (CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK))
863 {
864 case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1):
865 freq >>= 2U;
866 break;
867
868 case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1):
869 freq >>= 1U;
870 break;
871
872 default:
873 /* Add comment to avoid MISRA C-2012 rule 16.4 */
874 break;
875 }
876 break;
877
878 case kCLOCK_PllEnet500M:
879 /* PLL6 is fixed at 25MHz. */
880 freq = 500000000UL;
881 break;
882
883 default:
884 freq = 0U;
885 break;
886 }
887
888 return freq;
889}
890
891/*!
892 * brief Initialize the System PLL PFD.
893 *
894 * This function initializes the System PLL PFD. During new value setting,
895 * the clock output is disabled to prevent glitch.
896 *
897 * param pfd Which PFD clock to enable.
898 * param pfdFrac The PFD FRAC value.
899 * note It is recommended that PFD settings are kept between 12-35.
900 */
901void CLOCK_InitSysPfd(clock_pfd_t pfd, uint8_t pfdFrac)
902{
903 uint32_t pfdIndex = (uint32_t)pfd;
904 uint32_t pfd528;
905
906 pfd528 = CCM_ANALOG->PFD_528 &
907 ~(((uint32_t)((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK | (uint32_t)CCM_ANALOG_PFD_528_PFD0_FRAC_MASK)
908 << (8UL * pfdIndex)));
909
910 /* Disable the clock output first. */
911 CCM_ANALOG->PFD_528 = pfd528 | ((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * pfdIndex));
912
913 /* Set the new value and enable output. */
914 CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex));
915}
916
917/*!
918 * brief De-initialize the System PLL PFD.
919 *
920 * This function disables the System PLL PFD.
921 *
922 * param pfd Which PFD clock to disable.
923 */
924void CLOCK_DeinitSysPfd(clock_pfd_t pfd)
925{
926 CCM_ANALOG->PFD_528 |= (uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * (uint32_t)pfd);
927}
928
929/*!
930 * brief Initialize the USB1 PLL PFD.
931 *
932 * This function initializes the USB1 PLL PFD. During new value setting,
933 * the clock output is disabled to prevent glitch.
934 *
935 * param pfd Which PFD clock to enable.
936 * param pfdFrac The PFD FRAC value.
937 * note It is recommended that PFD settings are kept between 12-35.
938 */
939void CLOCK_InitUsb1Pfd(clock_pfd_t pfd, uint8_t pfdFrac)
940{
941 uint32_t pfdIndex = (uint32_t)pfd;
942 uint32_t pfd480;
943
944 pfd480 = CCM_ANALOG->PFD_480 &
945 ~((uint32_t)((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK | (uint32_t)CCM_ANALOG_PFD_480_PFD0_FRAC_MASK)
946 << (8UL * pfdIndex));
947
948 /* Disable the clock output first. */
949 CCM_ANALOG->PFD_480 = pfd480 | ((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * pfdIndex));
950
951 /* Set the new value and enable output. */
952 CCM_ANALOG->PFD_480 = pfd480 | (CCM_ANALOG_PFD_480_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex));
953}
954
955/*!
956 * brief De-initialize the USB1 PLL PFD.
957 *
958 * This function disables the USB1 PLL PFD.
959 *
960 * param pfd Which PFD clock to disable.
961 */
962void CLOCK_DeinitUsb1Pfd(clock_pfd_t pfd)
963{
964 CCM_ANALOG->PFD_480 |= (uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * (uint32_t)pfd);
965}
966
967/*!
968 * brief Get current System PLL PFD output frequency.
969 *
970 * This function get current output frequency of specific System PLL PFD
971 *
972 * param pfd pfd name to get frequency.
973 * return The PFD output frequency in hertz.
974 */
975uint32_t CLOCK_GetSysPfdFreq(clock_pfd_t pfd)
976{
977 uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
978
979 switch (pfd)
980 {
981 case kCLOCK_Pfd0:
982 freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD0_FRAC_SHIFT);
983 break;
984
985 case kCLOCK_Pfd1:
986 freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD1_FRAC_SHIFT);
987 break;
988
989 case kCLOCK_Pfd2:
990 freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD2_FRAC_SHIFT);
991 break;
992
993 case kCLOCK_Pfd3:
994 freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD3_FRAC_SHIFT);
995 break;
996
997 default:
998 freq = 0U;
999 break;
1000 }
1001 freq *= 18U;
1002
1003 return freq;
1004}
1005
1006/*!
1007 * brief Get current USB1 PLL PFD output frequency.
1008 *
1009 * This function get current output frequency of specific USB1 PLL PFD
1010 *
1011 * param pfd pfd name to get frequency.
1012 * return The PFD output frequency in hertz.
1013 */
1014uint32_t CLOCK_GetUsb1PfdFreq(clock_pfd_t pfd)
1015{
1016 uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
1017
1018 switch (pfd)
1019 {
1020 case kCLOCK_Pfd0:
1021 freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
1022 break;
1023
1024 case kCLOCK_Pfd1:
1025 freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD1_FRAC_SHIFT);
1026 break;
1027
1028 case kCLOCK_Pfd2:
1029 freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD2_FRAC_SHIFT);
1030 break;
1031
1032 case kCLOCK_Pfd3:
1033 freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD3_FRAC_SHIFT);
1034 break;
1035
1036 default:
1037 freq = 0U;
1038 break;
1039 }
1040 freq *= 18U;
1041
1042 return freq;
1043}
1044
1045/*!
1046 * brief Set the clock source and the divider of the clock output1.
1047 *
1048 * param selection The clock source to be output, please refer to clock_output1_selection_t.
1049 * param divider The divider of the output clock signal, please refer to clock_output_divider_t.
1050 */
1051void CLOCK_SetClockOutput1(clock_output1_selection_t selection, clock_output_divider_t divider)
1052{
1053 uint32_t tmp32;
1054
1055 tmp32 = CCM->CCOSR;
1056 if (selection == kCLOCK_DisableClockOutput1)
1057 {
1058 tmp32 &= ~CCM_CCOSR_CLKO1_EN_MASK;
1059 }
1060 else
1061 {
1062 tmp32 |= CCM_CCOSR_CLKO1_EN_MASK;
1063 tmp32 &= ~(CCM_CCOSR_CLKO1_SEL_MASK | CCM_CCOSR_CLKO1_DIV_MASK);
1064 tmp32 |= CCM_CCOSR_CLKO1_SEL(selection) | CCM_CCOSR_CLKO1_DIV(divider);
1065 }
1066 CCM->CCOSR = tmp32;
1067}
1068
1069/*!
1070 * brief Set the clock source and the divider of the clock output2.
1071 *
1072 * param selection The clock source to be output, please refer to clock_output2_selection_t.
1073 * param divider The divider of the output clock signal, please refer to clock_output_divider_t.
1074 */
1075void CLOCK_SetClockOutput2(clock_output2_selection_t selection, clock_output_divider_t divider)
1076{
1077 uint32_t tmp32;
1078
1079 tmp32 = CCM->CCOSR;
1080 if (selection == kCLOCK_DisableClockOutput2)
1081 {
1082 tmp32 &= CCM_CCOSR_CLKO2_EN_MASK;
1083 }
1084 else
1085 {
1086 tmp32 |= CCM_CCOSR_CLKO2_EN_MASK;
1087 tmp32 &= ~(CCM_CCOSR_CLKO2_SEL_MASK | CCM_CCOSR_CLKO2_DIV_MASK);
1088 tmp32 |= CCM_CCOSR_CLKO2_SEL(selection) | CCM_CCOSR_CLKO2_DIV(divider);
1089 }
1090
1091 CCM->CCOSR = tmp32;
1092}
1093
1094/*!
1095 * brief Get the frequency of clock output1 clock signal.
1096 *
1097 * return The frequency of clock output1 clock signal.
1098 */
1099uint32_t CLOCK_GetClockOutCLKO1Freq(void)
1100{
1101 uint32_t freq = 0U;
1102 uint32_t tmp32;
1103
1104 tmp32 = CCM->CCOSR;
1105
1106 if ((tmp32 & CCM_CCOSR_CLKO1_EN_MASK) != 0UL)
1107 {
1108 switch ((tmp32 & CCM_CCOSR_CLKO1_SEL_MASK) >> CCM_CCOSR_CLKO1_SEL_SHIFT)
1109 {
1110 case (uint32_t)kCLOCK_OutputPllUsb1Sw:
1111 freq = CLOCK_GetPllUsb1SWFreq() / 2UL;
1112 break;
1113 case (uint32_t)kCLOCK_OutputPllSys:
1114 freq = CLOCK_GetPllFreq(kCLOCK_PllSys) / 2UL;
1115 break;
1116 case (uint32_t)kCLOCK_OutputPllENET:
1117 freq = CLOCK_GetPllFreq(kCLOCK_PllEnet500M) / 2UL;
1118 break;
1119 case (uint32_t)kCLOCK_OutputCoreClk:
1120 freq = CLOCK_GetCoreFreq();
1121 break;
1122 case (uint32_t)kCLOCK_OutputIpgClk:
1123 freq = CLOCK_GetIpgFreq();
1124 break;
1125 case (uint32_t)kCLOCK_OutputPerClk:
1126 freq = CLOCK_GetPerClkFreq();
1127 break;
1128 case (uint32_t)kCLOCK_OutputPll4MainClk:
1129 freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
1130 break;
1131 default:
1132 /* This branch should never be hit. */
1133 break;
1134 }
1135
1136 freq /= (((tmp32 & CCM_CCOSR_CLKO1_DIV_MASK) >> CCM_CCOSR_CLKO1_DIV_SHIFT) + 1U);
1137 }
1138 else
1139 {
1140 freq = 0UL;
1141 }
1142
1143 return freq;
1144}
1145
1146/*!
1147 * brief Get the frequency of clock output2 clock signal.
1148 *
1149 * return The frequency of clock output2 clock signal.
1150 */
1151uint32_t CLOCK_GetClockOutClkO2Freq(void)
1152{
1153 uint32_t freq = 0U;
1154 uint32_t tmp32;
1155
1156 tmp32 = CCM->CCOSR;
1157
1158 if ((tmp32 & CCM_CCOSR_CLKO2_EN_MASK) != 0UL)
1159 {
1160 switch ((tmp32 & CCM_CCOSR_CLKO2_SEL_MASK) >> CCM_CCOSR_CLKO2_SEL_SHIFT)
1161 {
1162 case (uint32_t)kCLOCK_OutputLpi2cClk:
1163 freq = CLOCK_GetClockRootFreq(kCLOCK_Lpi2cClkRoot);
1164 break;
1165 case (uint32_t)kCLOCK_OutputOscClk:
1166 freq = CLOCK_GetOscFreq();
1167 break;
1168 case (uint32_t)kCLOCK_OutputLpspiClk:
1169 freq = CLOCK_GetClockRootFreq(kCLOCK_LpspiClkRoot);
1170 break;
1171 case (uint32_t)kCLOCK_OutputSai1Clk:
1172 freq = CLOCK_GetClockRootFreq(kCLOCK_Sai1ClkRoot);
1173 break;
1174 case (uint32_t)kCLOCK_OutputSai3Clk:
1175 freq = CLOCK_GetClockRootFreq(kCLOCK_Sai3ClkRoot);
1176 break;
1177 case (uint32_t)kCLOCK_OutputTraceClk:
1178 freq = CLOCK_GetClockRootFreq(kCLOCK_TraceClkRoot);
1179 break;
1180 case (uint32_t)kCLOCK_OutputFlexspiClk:
1181 freq = CLOCK_GetClockRootFreq(kCLOCK_FlexspiClkRoot);
1182 break;
1183 case (uint32_t)kCLOCK_OutputUartClk:
1184 freq = CLOCK_GetClockRootFreq(kCLOCK_UartClkRoot);
1185 break;
1186 case (uint32_t)kCLOCK_OutputSpdif0Clk:
1187 freq = CLOCK_GetClockRootFreq(kCLOCK_SpdifClkRoot);
1188 break;
1189 default:
1190 /* This branch should never be hit. */
1191 break;
1192 }
1193
1194 freq /= (((tmp32 & CCM_CCOSR_CLKO2_DIV_MASK) >> CCM_CCOSR_CLKO2_DIV_SHIFT) + 1U);
1195 }
1196 else
1197 {
1198 freq = 0UL;
1199 }
1200
1201 return freq;
1202}