aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1062/drivers/fsl_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1062/drivers/fsl_clock.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1062/drivers/fsl_clock.c1526
1 files changed, 1526 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1062/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1062/drivers/fsl_clock.c
new file mode 100644
index 000000000..181c766b4
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1062/drivers/fsl_clock.c
@@ -0,0 +1,1526 @@
1/*
2 * Copyright 2018 - 2019 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 frequency of PLL USB1 software clock.
77 *
78 * @return The frequency of PLL USB1 software clock.
79 */
80static uint32_t CLOCK_GetPllUsb1SWFreq(void);
81
82/*******************************************************************************
83 * Code
84 ******************************************************************************/
85
86static uint32_t CLOCK_GetPeriphClkFreq(void)
87{
88 uint32_t freq;
89
90 /* Periph_clk2_clk ---> Periph_clk */
91 if ((CCM->CBCDR & CCM_CBCDR_PERIPH_CLK_SEL_MASK) != 0U)
92 {
93 switch (CCM->CBCMR & CCM_CBCMR_PERIPH_CLK2_SEL_MASK)
94 {
95 /* Pll3_sw_clk ---> Periph_clk2_clk ---> Periph_clk */
96 case CCM_CBCMR_PERIPH_CLK2_SEL(0U):
97 freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
98 break;
99
100 /* Osc_clk ---> Periph_clk2_clk ---> Periph_clk */
101 case CCM_CBCMR_PERIPH_CLK2_SEL(1U):
102 freq = CLOCK_GetOscFreq();
103 break;
104
105 case CCM_CBCMR_PERIPH_CLK2_SEL(2U):
106 freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
107 break;
108
109 case CCM_CBCMR_PERIPH_CLK2_SEL(3U):
110 default:
111 freq = 0U;
112 break;
113 }
114
115 freq /= (((CCM->CBCDR & CCM_CBCDR_PERIPH_CLK2_PODF_MASK) >> CCM_CBCDR_PERIPH_CLK2_PODF_SHIFT) + 1U);
116 }
117 /* Pre_Periph_clk ---> Periph_clk */
118 else
119 {
120 switch (CCM->CBCMR & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
121 {
122 /* PLL2 ---> Pre_Periph_clk ---> Periph_clk */
123 case CCM_CBCMR_PRE_PERIPH_CLK_SEL(0U):
124 freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
125 break;
126
127 /* PLL2 PFD2 ---> Pre_Periph_clk ---> Periph_clk */
128 case CCM_CBCMR_PRE_PERIPH_CLK_SEL(1U):
129 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
130 break;
131
132 /* PLL2 PFD0 ---> Pre_Periph_clk ---> Periph_clk */
133 case CCM_CBCMR_PRE_PERIPH_CLK_SEL(2U):
134 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0);
135 break;
136
137 /* PLL1 divided(/2) ---> Pre_Periph_clk ---> Periph_clk */
138 case CCM_CBCMR_PRE_PERIPH_CLK_SEL(3U):
139 freq = CLOCK_GetPllFreq(kCLOCK_PllArm) /
140 (((CCM->CACRR & CCM_CACRR_ARM_PODF_MASK) >> CCM_CACRR_ARM_PODF_SHIFT) + 1U);
141 break;
142
143 default:
144 freq = 0U;
145 break;
146 }
147 }
148
149 return freq;
150}
151
152static uint32_t CLOCK_GetPllUsb1SWFreq(void)
153{
154 uint32_t freq;
155
156 switch ((CCM->CCSR & CCM_CCSR_PLL3_SW_CLK_SEL_MASK) >> CCM_CCSR_PLL3_SW_CLK_SEL_SHIFT)
157 {
158 case 0:
159 {
160 freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
161 break;
162 }
163 case 1:
164 {
165 freq = 24000000UL;
166 break;
167 }
168 default:
169 freq = 0UL;
170 break;
171 }
172
173 return freq;
174}
175
176/*!
177 * brief Initialize the external 24MHz clock.
178 *
179 * This function supports two modes:
180 * 1. Use external crystal oscillator.
181 * 2. Bypass the external crystal oscillator, using input source clock directly.
182 *
183 * After this function, please call ref CLOCK_SetXtal0Freq to inform clock driver
184 * the external clock frequency.
185 *
186 * param bypassXtalOsc Pass in true to bypass the external crystal oscillator.
187 * note This device does not support bypass external crystal oscillator, so
188 * the input parameter should always be false.
189 */
190void CLOCK_InitExternalClk(bool bypassXtalOsc)
191{
192 /* This device does not support bypass XTAL OSC. */
193 assert(!bypassXtalOsc);
194
195 CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power up */
196 while ((XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_MASK) == 0U)
197 {
198 }
199 CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; /* detect freq */
200 while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_OSC_XTALOK_MASK) == 0UL)
201 {
202 }
203 CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK;
204}
205
206/*!
207 * brief Deinitialize the external 24MHz clock.
208 *
209 * This function disables the external 24MHz clock.
210 *
211 * After this function, please call ref CLOCK_SetXtal0Freq to set external clock
212 * frequency to 0.
213 */
214void CLOCK_DeinitExternalClk(void)
215{
216 CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power down */
217}
218
219/*!
220 * brief Switch the OSC.
221 *
222 * This function switches the OSC source for SoC.
223 *
224 * param osc OSC source to switch to.
225 */
226void CLOCK_SwitchOsc(clock_osc_t osc)
227{
228 if (osc == kCLOCK_RcOsc)
229 {
230 XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_SET_OSC_SEL_MASK;
231 }
232 else
233 {
234 XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_MASK;
235 }
236}
237
238/*!
239 * brief Initialize the RC oscillator 24MHz clock.
240 */
241void CLOCK_InitRcOsc24M(void)
242{
243 XTALOSC24M->LOWPWR_CTRL |= XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK;
244}
245
246/*!
247 * brief Power down the RCOSC 24M clock.
248 */
249void CLOCK_DeinitRcOsc24M(void)
250{
251 XTALOSC24M->LOWPWR_CTRL &= ~XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK;
252}
253
254/*!
255 * brief Gets the AHB clock frequency.
256 *
257 * return The AHB clock frequency value in hertz.
258 */
259uint32_t CLOCK_GetAhbFreq(void)
260{
261 return CLOCK_GetPeriphClkFreq() / (((CCM->CBCDR & CCM_CBCDR_AHB_PODF_MASK) >> CCM_CBCDR_AHB_PODF_SHIFT) + 1U);
262}
263
264/*!
265 * brief Gets the SEMC clock frequency.
266 *
267 * return The SEMC clock frequency value in hertz.
268 */
269uint32_t CLOCK_GetSemcFreq(void)
270{
271 uint32_t freq;
272
273 /* SEMC alternative clock ---> SEMC Clock */
274 if ((CCM->CBCDR & CCM_CBCDR_SEMC_CLK_SEL_MASK) != 0U)
275 {
276 /* PLL3 PFD1 ---> SEMC alternative clock ---> SEMC Clock */
277 if ((CCM->CBCDR & CCM_CBCDR_SEMC_ALT_CLK_SEL_MASK) != 0U)
278 {
279 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1);
280 }
281 /* PLL2 PFD2 ---> SEMC alternative clock ---> SEMC Clock */
282 else
283 {
284 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
285 }
286 }
287 /* Periph_clk ---> SEMC Clock */
288 else
289 {
290 freq = CLOCK_GetPeriphClkFreq();
291 }
292
293 freq /= (((CCM->CBCDR & CCM_CBCDR_SEMC_PODF_MASK) >> CCM_CBCDR_SEMC_PODF_SHIFT) + 1U);
294
295 return freq;
296}
297
298/*!
299 * brief Gets the IPG clock frequency.
300 *
301 * return The IPG clock frequency value in hertz.
302 */
303uint32_t CLOCK_GetIpgFreq(void)
304{
305 return CLOCK_GetAhbFreq() / (((CCM->CBCDR & CCM_CBCDR_IPG_PODF_MASK) >> CCM_CBCDR_IPG_PODF_SHIFT) + 1U);
306}
307
308/*!
309 * brief Gets the PER clock frequency.
310 *
311 * return The PER clock frequency value in hertz.
312 */
313uint32_t CLOCK_GetPerClkFreq(void)
314{
315 uint32_t freq;
316
317 /* Osc_clk ---> PER Clock*/
318 if ((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK) != 0U)
319 {
320 freq = CLOCK_GetOscFreq();
321 }
322 /* Periph_clk ---> AHB Clock ---> IPG Clock ---> PER Clock */
323 else
324 {
325 freq = CLOCK_GetIpgFreq();
326 }
327
328 freq /= (((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_PODF_MASK) >> CCM_CSCMR1_PERCLK_PODF_SHIFT) + 1U);
329
330 return freq;
331}
332
333/*!
334 * brief Gets the clock frequency for a specific clock name.
335 *
336 * This function checks the current clock configurations and then calculates
337 * the clock frequency for a specific clock name defined in clock_name_t.
338 *
339 * param clockName Clock names defined in clock_name_t
340 * return Clock frequency value in hertz
341 */
342uint32_t CLOCK_GetFreq(clock_name_t name)
343{
344 uint32_t freq;
345
346 switch (name)
347 {
348 case kCLOCK_CpuClk:
349 case kCLOCK_AhbClk:
350 freq = CLOCK_GetAhbFreq();
351 break;
352
353 case kCLOCK_SemcClk:
354 freq = CLOCK_GetSemcFreq();
355 break;
356
357 case kCLOCK_IpgClk:
358 freq = CLOCK_GetIpgFreq();
359 break;
360
361 case kCLOCK_PerClk:
362 freq = CLOCK_GetPerClkFreq();
363 break;
364
365 case kCLOCK_OscClk:
366 freq = CLOCK_GetOscFreq();
367 break;
368 case kCLOCK_RtcClk:
369 freq = CLOCK_GetRtcFreq();
370 break;
371 case kCLOCK_ArmPllClk:
372 freq = CLOCK_GetPllFreq(kCLOCK_PllArm);
373 break;
374 case kCLOCK_Usb1PllClk:
375 freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
376 break;
377 case kCLOCK_Usb1PllPfd0Clk:
378 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd0);
379 break;
380 case kCLOCK_Usb1PllPfd1Clk:
381 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1);
382 break;
383 case kCLOCK_Usb1PllPfd2Clk:
384 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd2);
385 break;
386 case kCLOCK_Usb1PllPfd3Clk:
387 freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd3);
388 break;
389 case kCLOCK_Usb1SwClk:
390 freq = CLOCK_GetPllUsb1SWFreq();
391 break;
392 case kCLOCK_Usb1Sw120MClk:
393 freq = CLOCK_GetPllUsb1SWFreq() / 4UL;
394 break;
395 case kCLOCK_Usb1Sw60MClk:
396 freq = CLOCK_GetPllUsb1SWFreq() / 8UL;
397 break;
398 case kCLOCK_Usb1Sw80MClk:
399 freq = CLOCK_GetPllUsb1SWFreq() / 6UL;
400 break;
401 case kCLOCK_Usb2PllClk:
402 freq = CLOCK_GetPllFreq(kCLOCK_PllUsb2);
403 break;
404 case kCLOCK_SysPllClk:
405 freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
406 break;
407 case kCLOCK_SysPllPfd0Clk:
408 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0);
409 break;
410 case kCLOCK_SysPllPfd1Clk:
411 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd1);
412 break;
413 case kCLOCK_SysPllPfd2Clk:
414 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
415 break;
416 case kCLOCK_SysPllPfd3Clk:
417 freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd3);
418 break;
419 case kCLOCK_EnetPll0Clk:
420 freq = CLOCK_GetPllFreq(kCLOCK_PllEnet);
421 break;
422 case kCLOCK_EnetPll1Clk:
423 freq = CLOCK_GetPllFreq(kCLOCK_PllEnet2);
424 break;
425 case kCLOCK_EnetPll2Clk:
426 freq = CLOCK_GetPllFreq(kCLOCK_PllEnet25M);
427 break;
428 case kCLOCK_AudioPllClk:
429 freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
430 break;
431 case kCLOCK_VideoPllClk:
432 freq = CLOCK_GetPllFreq(kCLOCK_PllVideo);
433 break;
434 default:
435 freq = 0U;
436 break;
437 }
438
439 return freq;
440}
441
442/*!
443 * brief Gets the frequency of selected clock root.
444 *
445 * param clockRoot The clock root used to get the frequency, please refer to @ref clock_root_t.
446 * return The frequency of selected clock root.
447 */
448uint32_t CLOCK_GetClockRootFreq(clock_root_t clockRoot)
449{
450 const clock_name_t clockRootSourceArray[][6] = CLOCK_ROOT_SOUCE;
451 const clock_mux_t clockRootMuxTupleArray[] = CLOCK_ROOT_MUX_TUPLE;
452 const clock_div_t clockRootDivTupleArray[][2] = CLOCK_ROOT_DIV_TUPLE;
453 uint32_t freq = 0UL;
454 clock_mux_t clockRootMuxTuple = clockRootMuxTupleArray[(uint8_t)clockRoot];
455 clock_div_t clockRootPreDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][0];
456 clock_div_t clockRootPostDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][1];
457 uint32_t clockRootMuxValue = (CCM_TUPLE_REG(CCM, clockRootMuxTuple) & CCM_TUPLE_MASK(clockRootMuxTuple)) >>
458 CCM_TUPLE_SHIFT(clockRootMuxTuple);
459 clock_name_t clockSourceName;
460
461 clockSourceName = clockRootSourceArray[(uint8_t)clockRoot][clockRootMuxValue];
462
463 assert(clockSourceName != kCLOCK_NoneName);
464
465 freq = CLOCK_GetFreq(clockSourceName);
466
467 if (clockRootPreDivTuple != kCLOCK_NonePreDiv)
468 {
469 freq /= ((CCM_TUPLE_REG(CCM, clockRootPreDivTuple) & CCM_TUPLE_MASK(clockRootPreDivTuple)) >>
470 CCM_TUPLE_SHIFT(clockRootPreDivTuple)) +
471 1UL;
472 }
473
474 freq /= ((CCM_TUPLE_REG(CCM, clockRootPostDivTuple) & CCM_TUPLE_MASK(clockRootPostDivTuple)) >>
475 CCM_TUPLE_SHIFT(clockRootPostDivTuple)) +
476 1UL;
477
478 return freq;
479}
480
481/*! brief Enable USB HS clock.
482 *
483 * This function only enables the access to USB HS prepheral, upper layer
484 * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY
485 * clock to use USB HS.
486 *
487 * param src USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused.
488 * param freq USB HS does not care about the clock source, so this parameter is ignored.
489 * retval true The clock is set successfully.
490 * retval false The clock source is invalid to get proper USB HS clock.
491 */
492bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq)
493{
494 uint32_t i;
495 CCM->CCGR6 |= CCM_CCGR6_CG0_MASK;
496 USB1->USBCMD |= USBHS_USBCMD_RST_MASK;
497
498 /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/
499 for (i = 0; i < 400000U; i++)
500 {
501 __ASM("nop");
502 }
503 PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) |
504 (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK);
505 return true;
506}
507
508/*! brief Enable USB HS clock.
509 *
510 * This function only enables the access to USB HS prepheral, upper layer
511 * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY
512 * clock to use USB HS.
513 *
514 * param src USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused.
515 * param freq USB HS does not care about the clock source, so this parameter is ignored.
516 * retval true The clock is set successfully.
517 * retval false The clock source is invalid to get proper USB HS clock.
518 */
519bool CLOCK_EnableUsbhs1Clock(clock_usb_src_t src, uint32_t freq)
520{
521 uint32_t i = 0;
522 CCM->CCGR6 |= CCM_CCGR6_CG0_MASK;
523 USB2->USBCMD |= USBHS_USBCMD_RST_MASK;
524
525 /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/
526 for (i = 0; i < 400000U; i++)
527 {
528 __ASM("nop");
529 }
530 PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) |
531 (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK);
532 return true;
533}
534
535/*! brief Enable USB HS PHY PLL clock.
536 *
537 * This function enables the internal 480MHz USB PHY PLL clock.
538 *
539 * param src USB HS PHY PLL clock source.
540 * param freq The frequency specified by src.
541 * retval true The clock is set successfully.
542 * retval false The clock source is invalid to get proper USB HS clock.
543 */
544bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
545{
546 const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U};
547 if ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_ENABLE_MASK) != 0U)
548 {
549 CCM_ANALOG->PLL_USB1 |= CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK;
550 }
551 else
552 {
553 CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll);
554 }
555 USBPHY1->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */
556 USBPHY1->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK;
557
558 USBPHY1->PWD = 0;
559 USBPHY1->CTRL |= USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK | USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK |
560 USBPHY_CTRL_ENUTMILEVEL2_MASK | USBPHY_CTRL_ENUTMILEVEL3_MASK;
561 return true;
562}
563
564/*! brief Disable USB HS PHY PLL clock.
565 *
566 * This function disables USB HS PHY PLL clock.
567 */
568void CLOCK_DisableUsbhs0PhyPllClock(void)
569{
570 CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK;
571 USBPHY1->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
572}
573
574/*!
575 * brief Initialize the ARM PLL.
576 *
577 * This function initialize the ARM PLL with specific settings
578 *
579 * param config configuration to set to PLL.
580 */
581void CLOCK_InitArmPll(const clock_arm_pll_config_t *config)
582{
583 /* Bypass PLL first */
584 CCM_ANALOG->PLL_ARM = (CCM_ANALOG->PLL_ARM & (~CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_MASK)) |
585 CCM_ANALOG_PLL_ARM_BYPASS_MASK | CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC(config->src);
586
587 CCM_ANALOG->PLL_ARM =
588 (CCM_ANALOG->PLL_ARM & (~(CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK | CCM_ANALOG_PLL_ARM_POWERDOWN_MASK))) |
589 CCM_ANALOG_PLL_ARM_ENABLE_MASK | CCM_ANALOG_PLL_ARM_DIV_SELECT(config->loopDivider);
590
591 while ((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_LOCK_MASK) == 0UL)
592 {
593 }
594
595 /* Disable Bypass */
596 CCM_ANALOG->PLL_ARM &= ~CCM_ANALOG_PLL_ARM_BYPASS_MASK;
597}
598
599/*!
600 * brief De-initialize the ARM PLL.
601 */
602void CLOCK_DeinitArmPll(void)
603{
604 CCM_ANALOG->PLL_ARM = CCM_ANALOG_PLL_ARM_POWERDOWN_MASK;
605}
606
607/*!
608 * brief Initialize the System PLL.
609 *
610 * This function initializes the System PLL with specific settings
611 *
612 * param config Configuration to set to PLL.
613 */
614void CLOCK_InitSysPll(const clock_sys_pll_config_t *config)
615{
616 /* Bypass PLL first */
617 CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK)) |
618 CCM_ANALOG_PLL_SYS_BYPASS_MASK | CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC(config->src);
619
620 CCM_ANALOG->PLL_SYS =
621 (CCM_ANALOG->PLL_SYS & (~(CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK | CCM_ANALOG_PLL_SYS_POWERDOWN_MASK))) |
622 CCM_ANALOG_PLL_SYS_ENABLE_MASK | CCM_ANALOG_PLL_SYS_DIV_SELECT(config->loopDivider);
623
624 /* Initialize the fractional mode */
625 CCM_ANALOG->PLL_SYS_NUM = CCM_ANALOG_PLL_SYS_NUM_A(config->numerator);
626 CCM_ANALOG->PLL_SYS_DENOM = CCM_ANALOG_PLL_SYS_DENOM_B(config->denominator);
627
628 /* Initialize the spread spectrum mode */
629 CCM_ANALOG->PLL_SYS_SS = CCM_ANALOG_PLL_SYS_SS_STEP(config->ss_step) |
630 CCM_ANALOG_PLL_SYS_SS_ENABLE(config->ss_enable) |
631 CCM_ANALOG_PLL_SYS_SS_STOP(config->ss_stop);
632
633 while ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_LOCK_MASK) == 0UL)
634 {
635 }
636
637 /* Disable Bypass */
638 CCM_ANALOG->PLL_SYS &= ~CCM_ANALOG_PLL_SYS_BYPASS_MASK;
639}
640
641/*!
642 * brief De-initialize the System PLL.
643 */
644void CLOCK_DeinitSysPll(void)
645{
646 CCM_ANALOG->PLL_SYS = CCM_ANALOG_PLL_SYS_POWERDOWN_MASK;
647}
648
649/*!
650 * brief Initialize the USB1 PLL.
651 *
652 * This function initializes the USB1 PLL with specific settings
653 *
654 * param config Configuration to set to PLL.
655 */
656void CLOCK_InitUsb1Pll(const clock_usb_pll_config_t *config)
657{
658 /* Bypass PLL first */
659 CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) |
660 CCM_ANALOG_PLL_USB1_BYPASS_MASK | CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC(config->src);
661
662 CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK)) |
663 CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK |
664 CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider);
665
666 while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0UL)
667 {
668 }
669
670 /* Disable Bypass */
671 CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_BYPASS_MASK;
672}
673
674/*!
675 * brief Deinitialize the USB1 PLL.
676 */
677void CLOCK_DeinitUsb1Pll(void)
678{
679 CCM_ANALOG->PLL_USB1 = 0U;
680}
681
682/*!
683 * brief Initialize the USB2 PLL.
684 *
685 * This function initializes the USB2 PLL with specific settings
686 *
687 * param config Configuration to set to PLL.
688 */
689void CLOCK_InitUsb2Pll(const clock_usb_pll_config_t *config)
690{
691 /* Bypass PLL first */
692 CCM_ANALOG->PLL_USB2 = (CCM_ANALOG->PLL_USB2 & (~CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC_MASK)) |
693 CCM_ANALOG_PLL_USB2_BYPASS_MASK | CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC(config->src);
694
695 CCM_ANALOG->PLL_USB2 = (CCM_ANALOG->PLL_USB2 & (~CCM_ANALOG_PLL_USB2_DIV_SELECT_MASK)) |
696 CCM_ANALOG_PLL_USB2_ENABLE_MASK | CCM_ANALOG_PLL_USB2_POWER_MASK |
697 CCM_ANALOG_PLL_USB2_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB2_DIV_SELECT(config->loopDivider);
698
699 while ((CCM_ANALOG->PLL_USB2 & CCM_ANALOG_PLL_USB2_LOCK_MASK) == 0UL)
700 {
701 }
702
703 /* Disable Bypass */
704 CCM_ANALOG->PLL_USB2 &= ~CCM_ANALOG_PLL_USB2_BYPASS_MASK;
705}
706
707/*!
708 * brief Deinitialize the USB2 PLL.
709 */
710void CLOCK_DeinitUsb2Pll(void)
711{
712 CCM_ANALOG->PLL_USB2 = 0U;
713}
714
715/*!
716 * brief Initializes the Audio PLL.
717 *
718 * This function initializes the Audio PLL with specific settings
719 *
720 * param config Configuration to set to PLL.
721 */
722void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config)
723{
724 uint32_t pllAudio;
725 uint32_t misc2 = 0;
726
727 /* Bypass PLL first */
728 CCM_ANALOG->PLL_AUDIO = (CCM_ANALOG->PLL_AUDIO & (~CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC_MASK)) |
729 CCM_ANALOG_PLL_AUDIO_BYPASS_MASK | CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC(config->src);
730
731 CCM_ANALOG->PLL_AUDIO_NUM = CCM_ANALOG_PLL_AUDIO_NUM_A(config->numerator);
732 CCM_ANALOG->PLL_AUDIO_DENOM = CCM_ANALOG_PLL_AUDIO_DENOM_B(config->denominator);
733
734 /*
735 * Set post divider:
736 *
737 * ------------------------------------------------------------------------
738 * | config->postDivider | PLL_AUDIO[POST_DIV_SELECT] | MISC2[AUDIO_DIV] |
739 * ------------------------------------------------------------------------
740 * | 1 | 2 | 0 |
741 * ------------------------------------------------------------------------
742 * | 2 | 1 | 0 |
743 * ------------------------------------------------------------------------
744 * | 4 | 2 | 3 |
745 * ------------------------------------------------------------------------
746 * | 8 | 1 | 3 |
747 * ------------------------------------------------------------------------
748 * | 16 | 0 | 3 |
749 * ------------------------------------------------------------------------
750 */
751 pllAudio =
752 (CCM_ANALOG->PLL_AUDIO & (~(CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK | CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK))) |
753 CCM_ANALOG_PLL_AUDIO_ENABLE_MASK | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(config->loopDivider);
754
755 switch (config->postDivider)
756 {
757 case 16:
758 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0);
759 misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
760 break;
761
762 case 8:
763 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1);
764 misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
765 break;
766
767 case 4:
768 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
769 misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
770 break;
771
772 case 2:
773 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1);
774 break;
775
776 default:
777 pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
778 break;
779 }
780
781 CCM_ANALOG->MISC2 =
782 (CCM_ANALOG->MISC2 & ~(CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK)) | misc2;
783
784 CCM_ANALOG->PLL_AUDIO = pllAudio;
785
786 while ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK_MASK) == 0UL)
787 {
788 }
789
790 /* Disable Bypass */
791 CCM_ANALOG->PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_BYPASS_MASK;
792}
793
794/*!
795 * brief De-initialize the Audio PLL.
796 */
797void CLOCK_DeinitAudioPll(void)
798{
799 CCM_ANALOG->PLL_AUDIO = (uint32_t)CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK;
800}
801
802/*!
803 * brief Initialize the video PLL.
804 *
805 * This function configures the Video PLL with specific settings
806 *
807 * param config configuration to set to PLL.
808 */
809void CLOCK_InitVideoPll(const clock_video_pll_config_t *config)
810{
811 uint32_t pllVideo;
812 uint32_t misc2 = 0;
813
814 /* Bypass PLL first */
815 CCM_ANALOG->PLL_VIDEO = (CCM_ANALOG->PLL_VIDEO & (~CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC_MASK)) |
816 CCM_ANALOG_PLL_VIDEO_BYPASS_MASK | CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC(config->src);
817
818 CCM_ANALOG->PLL_VIDEO_NUM = CCM_ANALOG_PLL_VIDEO_NUM_A(config->numerator);
819 CCM_ANALOG->PLL_VIDEO_DENOM = CCM_ANALOG_PLL_VIDEO_DENOM_B(config->denominator);
820
821 /*
822 * Set post divider:
823 *
824 * ------------------------------------------------------------------------
825 * | config->postDivider | PLL_VIDEO[POST_DIV_SELECT] | MISC2[VIDEO_DIV] |
826 * ------------------------------------------------------------------------
827 * | 1 | 2 | 0 |
828 * ------------------------------------------------------------------------
829 * | 2 | 1 | 0 |
830 * ------------------------------------------------------------------------
831 * | 4 | 2 | 3 |
832 * ------------------------------------------------------------------------
833 * | 8 | 1 | 3 |
834 * ------------------------------------------------------------------------
835 * | 16 | 0 | 3 |
836 * ------------------------------------------------------------------------
837 */
838 pllVideo =
839 (CCM_ANALOG->PLL_VIDEO & (~(CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK | CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK))) |
840 CCM_ANALOG_PLL_VIDEO_ENABLE_MASK | CCM_ANALOG_PLL_VIDEO_DIV_SELECT(config->loopDivider);
841
842 switch (config->postDivider)
843 {
844 case 16:
845 pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(0);
846 misc2 = CCM_ANALOG_MISC2_VIDEO_DIV(3);
847 break;
848
849 case 8:
850 pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1);
851 misc2 = CCM_ANALOG_MISC2_VIDEO_DIV(3);
852 break;
853
854 case 4:
855 pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(2);
856 misc2 = CCM_ANALOG_MISC2_VIDEO_DIV(3);
857 break;
858
859 case 2:
860 pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1);
861 break;
862
863 default:
864 pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(2);
865 break;
866 }
867
868 CCM_ANALOG->MISC2 = (CCM_ANALOG->MISC2 & ~CCM_ANALOG_MISC2_VIDEO_DIV_MASK) | misc2;
869
870 CCM_ANALOG->PLL_VIDEO = pllVideo;
871
872 while ((CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_LOCK_MASK) == 0UL)
873 {
874 }
875
876 /* Disable Bypass */
877 CCM_ANALOG->PLL_VIDEO &= ~CCM_ANALOG_PLL_VIDEO_BYPASS_MASK;
878}
879
880/*!
881 * brief De-initialize the Video PLL.
882 */
883void CLOCK_DeinitVideoPll(void)
884{
885 CCM_ANALOG->PLL_VIDEO = CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK;
886}
887
888/*!
889 * brief Initialize the ENET PLL.
890 *
891 * This function initializes the ENET PLL with specific settings.
892 *
893 * param config Configuration to set to PLL.
894 */
895void CLOCK_InitEnetPll(const clock_enet_pll_config_t *config)
896{
897 uint32_t enet_pll = CCM_ANALOG_PLL_ENET_DIV_SELECT(config->loopDivider) |
898 CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT(config->loopDivider1);
899
900 CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC_MASK)) |
901 CCM_ANALOG_PLL_ENET_BYPASS_MASK | CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC(config->src);
902
903 if (config->enableClkOutput)
904 {
905 enet_pll |= CCM_ANALOG_PLL_ENET_ENABLE_MASK;
906 }
907
908 if (config->enableClkOutput1)
909 {
910 enet_pll |= CCM_ANALOG_PLL_ENET_ENET2_REF_EN_MASK;
911 }
912
913 if (config->enableClkOutput25M)
914 {
915 enet_pll |= CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_MASK;
916 }
917
918 CCM_ANALOG->PLL_ENET =
919 (CCM_ANALOG->PLL_ENET & (~(CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK | CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_MASK |
920 CCM_ANALOG_PLL_ENET_POWERDOWN_MASK))) |
921 enet_pll;
922
923 /* Wait for stable */
924 while ((CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_LOCK_MASK) == 0UL)
925 {
926 }
927
928 /* Disable Bypass */
929 CCM_ANALOG->PLL_ENET &= ~CCM_ANALOG_PLL_ENET_BYPASS_MASK;
930}
931
932/*!
933 * brief Deinitialize the ENET PLL.
934 *
935 * This function disables the ENET PLL.
936 */
937void CLOCK_DeinitEnetPll(void)
938{
939 CCM_ANALOG->PLL_ENET = CCM_ANALOG_PLL_ENET_POWERDOWN_MASK;
940}
941
942/*!
943 * brief Get current PLL output frequency.
944 *
945 * This function get current output frequency of specific PLL
946 *
947 * param pll pll name to get frequency.
948 * return The PLL output frequency in hertz.
949 */
950uint32_t CLOCK_GetPllFreq(clock_pll_t pll)
951{
952 uint32_t freq;
953 uint32_t divSelect;
954 clock_64b_t freqTmp;
955
956 const uint32_t enetRefClkFreq[] = {
957 25000000U, /* 25M */
958 50000000U, /* 50M */
959 100000000U, /* 100M */
960 125000000U /* 125M */
961 };
962
963 /* check if PLL is enabled */
964 if (!CLOCK_IsPllEnabled(CCM_ANALOG, pll))
965 {
966 return 0U;
967 }
968
969 /* get pll reference clock */
970 freq = CLOCK_GetPllBypassRefClk(CCM_ANALOG, pll);
971
972 /* check if pll is bypassed */
973 if (CLOCK_IsPllBypassed(CCM_ANALOG, pll))
974 {
975 return freq;
976 }
977
978 switch (pll)
979 {
980 case kCLOCK_PllArm:
981 freq = ((freq * ((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK) >>
982 CCM_ANALOG_PLL_ARM_DIV_SELECT_SHIFT)) >>
983 1U);
984 break;
985 case kCLOCK_PllSys:
986 /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
987 freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_SYS_NUM)));
988 freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_SYS_DENOM));
989
990 if ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK) != 0U)
991 {
992 freq *= 22U;
993 }
994 else
995 {
996 freq *= 20U;
997 }
998
999 freq += (uint32_t)freqTmp;
1000 break;
1001
1002 case kCLOCK_PllUsb1:
1003 freq = (freq * (((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK) != 0UL) ? 22U : 20U));
1004 break;
1005
1006 case kCLOCK_PllAudio:
1007 /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
1008 divSelect =
1009 (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_AUDIO_DIV_SELECT_SHIFT;
1010
1011 freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_NUM)));
1012 freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_DENOM));
1013
1014 freq = freq * divSelect + (uint32_t)freqTmp;
1015
1016 /* AUDIO PLL output = PLL output frequency / POSTDIV. */
1017
1018 /*
1019 * Post divider:
1020 *
1021 * PLL_AUDIO[POST_DIV_SELECT]:
1022 * 0x00: 4
1023 * 0x01: 2
1024 * 0x02: 1
1025 *
1026 * MISC2[AUDO_DIV]:
1027 * 0x00: 1
1028 * 0x01: 2
1029 * 0x02: 1
1030 * 0x03: 4
1031 */
1032 switch (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT_MASK)
1033 {
1034 case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0U):
1035 freq = freq >> 2U;
1036 break;
1037
1038 case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1U):
1039 freq = freq >> 1U;
1040 break;
1041
1042 case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2U):
1043 freq = freq >> 0U;
1044 break;
1045
1046 default:
1047 assert(false);
1048 break;
1049 }
1050
1051 switch (CCM_ANALOG->MISC2 & (CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK))
1052 {
1053 case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1):
1054 freq >>= 2U;
1055 break;
1056
1057 case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1):
1058 freq >>= 1U;
1059 break;
1060
1061 case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(0):
1062 case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(0):
1063 freq >>= 0U;
1064 break;
1065
1066 default:
1067 assert(false);
1068 break;
1069 }
1070 break;
1071
1072 case kCLOCK_PllVideo:
1073 /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
1074 divSelect =
1075 (CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_VIDEO_DIV_SELECT_SHIFT;
1076
1077 freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_VIDEO_NUM)));
1078 freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_VIDEO_DENOM));
1079 freq = freq * divSelect + (uint32_t)freqTmp;
1080
1081 /* VIDEO PLL output = PLL output frequency / POSTDIV. */
1082
1083 /*
1084 * Post divider:
1085 *
1086 * PLL_VIDEO[POST_DIV_SELECT]:
1087 * 0x00: 4
1088 * 0x01: 2
1089 * 0x02: 1
1090 *
1091 * MISC2[VIDEO_DIV]:
1092 * 0x00: 1
1093 * 0x01: 2
1094 * 0x02: 1
1095 * 0x03: 4
1096 */
1097 switch (CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT_MASK)
1098 {
1099 case CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(0U):
1100 freq = freq >> 2U;
1101 break;
1102
1103 case CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1U):
1104 freq = freq >> 1U;
1105 break;
1106
1107 case CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(2U):
1108 freq = freq >> 0U;
1109 break;
1110
1111 default:
1112 assert(false);
1113 break;
1114 }
1115
1116 switch (CCM_ANALOG->MISC2 & CCM_ANALOG_MISC2_VIDEO_DIV_MASK)
1117 {
1118 case CCM_ANALOG_MISC2_VIDEO_DIV(3U):
1119 freq >>= 2U;
1120 break;
1121
1122 case CCM_ANALOG_MISC2_VIDEO_DIV(1U):
1123 freq >>= 1U;
1124 break;
1125
1126 case CCM_ANALOG_MISC2_VIDEO_DIV(0U):
1127 case CCM_ANALOG_MISC2_VIDEO_DIV(2U):
1128 freq >>= 0U;
1129 break;
1130
1131 default:
1132 assert(false);
1133 break;
1134 }
1135 break;
1136 case kCLOCK_PllEnet:
1137 divSelect =
1138 (CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_ENET_DIV_SELECT_SHIFT;
1139 freq = enetRefClkFreq[divSelect];
1140 break;
1141
1142 case kCLOCK_PllEnet2:
1143 divSelect = (CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_MASK) >>
1144 CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_SHIFT;
1145 freq = enetRefClkFreq[divSelect];
1146 break;
1147
1148 case kCLOCK_PllEnet25M:
1149 /* ref_enetpll1 if fixed at 25MHz. */
1150 freq = 25000000UL;
1151 break;
1152
1153 case kCLOCK_PllUsb2:
1154 freq = (freq * (((CCM_ANALOG->PLL_USB2 & CCM_ANALOG_PLL_USB2_DIV_SELECT_MASK) != 0U) ? 22U : 20U));
1155 break;
1156 default:
1157 freq = 0U;
1158 break;
1159 }
1160
1161 return freq;
1162}
1163
1164/*!
1165 * brief Initialize the System PLL PFD.
1166 *
1167 * This function initializes the System PLL PFD. During new value setting,
1168 * the clock output is disabled to prevent glitch.
1169 *
1170 * param pfd Which PFD clock to enable.
1171 * param pfdFrac The PFD FRAC value.
1172 * note It is recommended that PFD settings are kept between 12-35.
1173 */
1174void CLOCK_InitSysPfd(clock_pfd_t pfd, uint8_t pfdFrac)
1175{
1176 uint32_t pfdIndex = (uint32_t)pfd;
1177 uint32_t pfd528;
1178
1179 pfd528 = CCM_ANALOG->PFD_528 &
1180 ~(((uint32_t)((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK | CCM_ANALOG_PFD_528_PFD0_FRAC_MASK)
1181 << (8UL * pfdIndex)));
1182
1183 /* Disable the clock output first. */
1184 CCM_ANALOG->PFD_528 = pfd528 | ((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * pfdIndex));
1185
1186 /* Set the new value and enable output. */
1187 CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex));
1188}
1189
1190/*!
1191 * brief De-initialize the System PLL PFD.
1192 *
1193 * This function disables the System PLL PFD.
1194 *
1195 * param pfd Which PFD clock to disable.
1196 */
1197void CLOCK_DeinitSysPfd(clock_pfd_t pfd)
1198{
1199 CCM_ANALOG->PFD_528 |= (uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8U * (uint8_t)pfd);
1200}
1201
1202/*!
1203 * brief Initialize the USB1 PLL PFD.
1204 *
1205 * This function initializes the USB1 PLL PFD. During new value setting,
1206 * the clock output is disabled to prevent glitch.
1207 *
1208 * param pfd Which PFD clock to enable.
1209 * param pfdFrac The PFD FRAC value.
1210 * note It is recommended that PFD settings are kept between 12-35.
1211 */
1212void CLOCK_InitUsb1Pfd(clock_pfd_t pfd, uint8_t pfdFrac)
1213{
1214 uint32_t pfdIndex = (uint32_t)pfd;
1215 uint32_t pfd480;
1216
1217 pfd480 = CCM_ANALOG->PFD_480 &
1218 ~(((uint32_t)((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK | CCM_ANALOG_PFD_480_PFD0_FRAC_MASK)
1219 << (8UL * pfdIndex)));
1220
1221 /* Disable the clock output first. */
1222 CCM_ANALOG->PFD_480 = pfd480 | ((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * pfdIndex));
1223
1224 /* Set the new value and enable output. */
1225 CCM_ANALOG->PFD_480 = pfd480 | (CCM_ANALOG_PFD_480_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex));
1226}
1227
1228/*!
1229 * brief De-initialize the USB1 PLL PFD.
1230 *
1231 * This function disables the USB1 PLL PFD.
1232 *
1233 * param pfd Which PFD clock to disable.
1234 */
1235void CLOCK_DeinitUsb1Pfd(clock_pfd_t pfd)
1236{
1237 CCM_ANALOG->PFD_480 |= (uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * (uint8_t)pfd);
1238}
1239
1240/*!
1241 * brief Get current System PLL PFD output frequency.
1242 *
1243 * This function get current output frequency of specific System PLL PFD
1244 *
1245 * param pfd pfd name to get frequency.
1246 * return The PFD output frequency in hertz.
1247 */
1248uint32_t CLOCK_GetSysPfdFreq(clock_pfd_t pfd)
1249{
1250 uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
1251
1252 switch (pfd)
1253 {
1254 case kCLOCK_Pfd0:
1255 freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD0_FRAC_SHIFT);
1256 break;
1257
1258 case kCLOCK_Pfd1:
1259 freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD1_FRAC_SHIFT);
1260 break;
1261
1262 case kCLOCK_Pfd2:
1263 freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD2_FRAC_SHIFT);
1264 break;
1265
1266 case kCLOCK_Pfd3:
1267 freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD3_FRAC_SHIFT);
1268 break;
1269
1270 default:
1271 freq = 0U;
1272 break;
1273 }
1274 freq *= 18U;
1275
1276 return freq;
1277}
1278
1279/*!
1280 * brief Get current USB1 PLL PFD output frequency.
1281 *
1282 * This function get current output frequency of specific USB1 PLL PFD
1283 *
1284 * param pfd pfd name to get frequency.
1285 * return The PFD output frequency in hertz.
1286 */
1287uint32_t CLOCK_GetUsb1PfdFreq(clock_pfd_t pfd)
1288{
1289 uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
1290
1291 switch (pfd)
1292 {
1293 case kCLOCK_Pfd0:
1294 freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
1295 break;
1296
1297 case kCLOCK_Pfd1:
1298 freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD1_FRAC_SHIFT);
1299 break;
1300
1301 case kCLOCK_Pfd2:
1302 freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD2_FRAC_SHIFT);
1303 break;
1304
1305 case kCLOCK_Pfd3:
1306 freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD3_FRAC_SHIFT);
1307 break;
1308
1309 default:
1310 freq = 0U;
1311 break;
1312 }
1313 freq *= 18U;
1314
1315 return freq;
1316}
1317
1318/*! brief Enable USB HS PHY PLL clock.
1319 *
1320 * This function enables the internal 480MHz USB PHY PLL clock.
1321 *
1322 * param src USB HS PHY PLL clock source.
1323 * param freq The frequency specified by src.
1324 * retval true The clock is set successfully.
1325 * retval false The clock source is invalid to get proper USB HS clock.
1326 */
1327bool CLOCK_EnableUsbhs1PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
1328{
1329 const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U};
1330 CLOCK_InitUsb2Pll(&g_ccmConfigUsbPll);
1331 USBPHY2->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */
1332 USBPHY2->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK;
1333
1334 USBPHY2->PWD = 0;
1335 USBPHY2->CTRL |= USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK | USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK |
1336 USBPHY_CTRL_ENUTMILEVEL2_MASK | USBPHY_CTRL_ENUTMILEVEL3_MASK;
1337
1338 return true;
1339}
1340
1341/*! brief Disable USB HS PHY PLL clock.
1342 *
1343 * This function disables USB HS PHY PLL clock.
1344 */
1345void CLOCK_DisableUsbhs1PhyPllClock(void)
1346{
1347 CCM_ANALOG->PLL_USB2 &= ~CCM_ANALOG_PLL_USB2_EN_USB_CLKS_MASK;
1348 USBPHY2->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
1349}
1350
1351/*!
1352 * brief Set the clock source and the divider of the clock output1.
1353 *
1354 * param selection The clock source to be output, please refer to clock_output1_selection_t.
1355 * param divider The divider of the output clock signal, please refer to clock_output_divider_t.
1356 */
1357void CLOCK_SetClockOutput1(clock_output1_selection_t selection, clock_output_divider_t divider)
1358{
1359 uint32_t tmp32;
1360
1361 tmp32 = CCM->CCOSR;
1362 if (selection == kCLOCK_DisableClockOutput1)
1363 {
1364 tmp32 &= ~CCM_CCOSR_CLKO1_EN_MASK;
1365 }
1366 else
1367 {
1368 tmp32 |= CCM_CCOSR_CLKO1_EN_MASK;
1369 tmp32 &= ~(CCM_CCOSR_CLKO1_SEL_MASK | CCM_CCOSR_CLKO1_DIV_MASK);
1370 tmp32 |= CCM_CCOSR_CLKO1_SEL(selection) | CCM_CCOSR_CLKO1_DIV(divider);
1371 }
1372 CCM->CCOSR = tmp32;
1373}
1374
1375/*!
1376 * brief Set the clock source and the divider of the clock output2.
1377 *
1378 * param selection The clock source to be output, please refer to clock_output2_selection_t.
1379 * param divider The divider of the output clock signal, please refer to clock_output_divider_t.
1380 */
1381void CLOCK_SetClockOutput2(clock_output2_selection_t selection, clock_output_divider_t divider)
1382{
1383 uint32_t tmp32;
1384
1385 tmp32 = CCM->CCOSR;
1386 if (selection == kCLOCK_DisableClockOutput2)
1387 {
1388 tmp32 &= CCM_CCOSR_CLKO2_EN_MASK;
1389 }
1390 else
1391 {
1392 tmp32 |= CCM_CCOSR_CLKO2_EN_MASK;
1393 tmp32 &= ~(CCM_CCOSR_CLKO2_SEL_MASK | CCM_CCOSR_CLKO2_DIV_MASK);
1394 tmp32 |= CCM_CCOSR_CLKO2_SEL(selection) | CCM_CCOSR_CLKO2_DIV(divider);
1395 }
1396
1397 CCM->CCOSR = tmp32;
1398}
1399
1400/*!
1401 * brief Get the frequency of clock output1 clock signal.
1402 *
1403 * return The frequency of clock output1 clock signal.
1404 */
1405uint32_t CLOCK_GetClockOutCLKO1Freq(void)
1406{
1407 uint32_t freq = 0U;
1408 uint32_t tmp32;
1409
1410 tmp32 = CCM->CCOSR;
1411
1412 if ((tmp32 & CCM_CCOSR_CLKO1_EN_MASK) != 0UL)
1413 {
1414 switch ((tmp32 & CCM_CCOSR_CLKO1_SEL_MASK) >> CCM_CCOSR_CLKO1_SEL_SHIFT)
1415 {
1416 case (uint32_t)kCLOCK_OutputPllUsb1:
1417 freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 2U;
1418 break;
1419 case (uint32_t)kCLOCK_OutputPllSys:
1420 freq = CLOCK_GetPllFreq(kCLOCK_PllSys) / 2U;
1421 break;
1422 case (uint32_t)kCLOCK_OutputPllVideo:
1423 freq = CLOCK_GetPllFreq(kCLOCK_PllVideo) / 2U;
1424 break;
1425 case (uint32_t)kCLOCK_OutputSemcClk:
1426 freq = CLOCK_GetSemcFreq();
1427 break;
1428 case (uint32_t)kCLOCK_OutputLcdifPixClk:
1429 freq = CLOCK_GetClockRootFreq(kCLOCK_LcdifClkRoot);
1430 break;
1431 case (uint32_t)kCLOCK_OutputAhbClk:
1432 freq = CLOCK_GetAhbFreq();
1433 break;
1434 case (uint32_t)kCLOCK_OutputIpgClk:
1435 freq = CLOCK_GetIpgFreq();
1436 break;
1437 case (uint32_t)kCLOCK_OutputPerClk:
1438 freq = CLOCK_GetPerClkFreq();
1439 break;
1440 case (uint32_t)kCLOCK_OutputCkilSyncClk:
1441 freq = CLOCK_GetRtcFreq();
1442 break;
1443 case (uint32_t)kCLOCK_OutputPll4MainClk:
1444 freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
1445 break;
1446 default:
1447 /* This branch should never be hit. */
1448 break;
1449 }
1450
1451 freq /= (((tmp32 & CCM_CCOSR_CLKO1_DIV_MASK) >> CCM_CCOSR_CLKO1_DIV_SHIFT) + 1U);
1452 }
1453 else
1454 {
1455 freq = 0UL;
1456 }
1457
1458 return freq;
1459}
1460
1461/*!
1462 * brief Get the frequency of clock output2 clock signal.
1463 *
1464 * return The frequency of clock output2 clock signal.
1465 */
1466uint32_t CLOCK_GetClockOutClkO2Freq(void)
1467{
1468 uint32_t freq = 0U;
1469 uint32_t tmp32;
1470
1471 tmp32 = CCM->CCOSR;
1472
1473 if ((tmp32 & CCM_CCOSR_CLKO2_EN_MASK) != 0UL)
1474 {
1475 switch ((tmp32 & CCM_CCOSR_CLKO2_SEL_MASK) >> CCM_CCOSR_CLKO2_SEL_SHIFT)
1476 {
1477 case (uint32_t)kCLOCK_OutputUsdhc1Clk:
1478 freq = CLOCK_GetClockRootFreq(kCLOCK_Usdhc1ClkRoot);
1479 break;
1480 case (uint32_t)kCLOCK_OutputLpi2cClk:
1481 freq = CLOCK_GetClockRootFreq(kCLOCK_Lpi2cClkRoot);
1482 break;
1483 case (uint32_t)kCLOCK_OutputCsiClk:
1484 freq = CLOCK_GetClockRootFreq(kCLOCK_CsiClkRoot);
1485 break;
1486 case (uint32_t)kCLOCK_OutputOscClk:
1487 freq = CLOCK_GetOscFreq();
1488 break;
1489 case (uint32_t)kCLOCK_OutputUsdhc2Clk:
1490 freq = CLOCK_GetClockRootFreq(kCLOCK_Usdhc2ClkRoot);
1491 break;
1492 case (uint32_t)kCLOCK_OutputSai1Clk:
1493 freq = CLOCK_GetClockRootFreq(kCLOCK_Sai1ClkRoot);
1494 break;
1495 case (uint32_t)kCLOCK_OutputSai2Clk:
1496 freq = CLOCK_GetClockRootFreq(kCLOCK_Sai2ClkRoot);
1497 break;
1498 case (uint32_t)kCLOCK_OutputSai3Clk:
1499 freq = CLOCK_GetClockRootFreq(kCLOCK_Sai3ClkRoot);
1500 break;
1501 case (uint32_t)kCLOCK_OutputCanClk:
1502 freq = CLOCK_GetClockRootFreq(kCLOCK_CanClkRoot);
1503 break;
1504 case (uint32_t)kCLOCK_OutputFlexspiClk:
1505 freq = CLOCK_GetClockRootFreq(kCLOCK_FlexspiClkRoot);
1506 break;
1507 case (uint32_t)kCLOCK_OutputUartClk:
1508 freq = CLOCK_GetClockRootFreq(kCLOCK_UartClkRoot);
1509 break;
1510 case (uint32_t)kCLOCK_OutputSpdif0Clk:
1511 freq = CLOCK_GetClockRootFreq(kCLOCK_SpdifClkRoot);
1512 break;
1513 default:
1514 /* This branch should never be hit. */
1515 break;
1516 }
1517
1518 freq /= (((tmp32 & CCM_CCOSR_CLKO2_DIV_MASK) >> CCM_CCOSR_CLKO2_DIV_SHIFT) + 1U);
1519 }
1520 else
1521 {
1522 freq = 0UL;
1523 }
1524
1525 return freq;
1526}