1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2019, NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_clock.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.clock"
18 #endif
19 
20 #define SCG_SIRC_LOW_RANGE_FREQ 2000000U  /* Slow IRC low range clock frequency. */
21 #define SCG_SIRC_HIGH_RANGE_FREQ 8000000U /* Slow IRC high range clock frequency.   */
22 
23 #define SCG_FIRC_FREQ0 48000000U /* Fast IRC trimed clock frequency(48MHz). */
24 #define SCG_FIRC_FREQ1 52000000U /* Fast IRC trimed clock frequency(52MHz). */
25 #define SCG_FIRC_FREQ2 56000000U /* Fast IRC trimed clock frequency(56MHz). */
26 #define SCG_FIRC_FREQ3 60000000U /* Fast IRC trimed clock frequency(60MHz). */
27 
28 /*
29  * System PLL base divider value, it is the PLL reference clock divider
30  * value when SCG_SPLLCFG[PREDIV]=0.
31  */
32 #define SCG_SPLL_PREDIV_BASE_VALUE 1U
33 
34 /*
35  * System PLL base multiplier value, it is the PLL multiplier value
36  * when SCG_SPLLCFG[MULT]=0.
37  */
38 #define SCG_SPLL_MULT_BASE_VALUE 16U
39 
40 #define SCG_SPLL_PREDIV_MAX_VALUE 7U /* Max value of SCG_SPLLCFG[PREDIV]. */
41 #define SCG_SPLL_MULT_MAX_VALUE 31U  /* Max value of SCG_SPLLCFG[MULT].   */
42 
43 /*
44  * System PLL reference clock after SCG_SPLLCFG[PREDIV] should be in
45  * the range of SCG_SPLL_REF_MIN to SCG_SPLL_REF_MAX.
46  */
47 #define SCG_SPLL_REF_MIN 8000000UL
48 #define SCG_SPLL_REF_MAX 32000000UL
49 
50 #define SCG_CSR_SCS_VAL ((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT)
51 #define SCG_SOSCDIV_SOSCDIV1_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV1_MASK) >> SCG_SOSCDIV_SOSCDIV1_SHIFT)
52 #define SCG_SOSCDIV_SOSCDIV2_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV2_MASK) >> SCG_SOSCDIV_SOSCDIV2_SHIFT)
53 #define SCG_SOSCDIV_SOSCDIV3_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV3_MASK) >> SCG_SOSCDIV_SOSCDIV3_SHIFT)
54 #define SCG_SIRCDIV_SIRCDIV1_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV1_MASK) >> SCG_SIRCDIV_SIRCDIV1_SHIFT)
55 #define SCG_SIRCDIV_SIRCDIV2_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV2_MASK) >> SCG_SIRCDIV_SIRCDIV2_SHIFT)
56 #define SCG_SIRCDIV_SIRCDIV3_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV3_MASK) >> SCG_SIRCDIV_SIRCDIV3_SHIFT)
57 #define SCG_FIRCDIV_FIRCDIV1_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV1_MASK) >> SCG_FIRCDIV_FIRCDIV1_SHIFT)
58 #define SCG_FIRCDIV_FIRCDIV2_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV2_MASK) >> SCG_FIRCDIV_FIRCDIV2_SHIFT)
59 #define SCG_FIRCDIV_FIRCDIV3_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV3_MASK) >> SCG_FIRCDIV_FIRCDIV3_SHIFT)
60 
61 #define SCG_SPLLDIV_SPLLDIV1_VAL ((SCG->SPLLDIV & SCG_SPLLDIV_SPLLDIV1_MASK) >> SCG_SPLLDIV_SPLLDIV1_SHIFT)
62 #define SCG_SPLLDIV_SPLLDIV2_VAL ((SCG->SPLLDIV & SCG_SPLLDIV_SPLLDIV2_MASK) >> SCG_SPLLDIV_SPLLDIV2_SHIFT)
63 #define SCG_SPLLDIV_SPLLDIV3_VAL ((SCG->SPLLDIV & SCG_SPLLDIV_SPLLDIV3_MASK) >> SCG_SPLLDIV_SPLLDIV3_SHIFT)
64 
65 #define SCG_SIRCCFG_RANGE_VAL ((SCG->SIRCCFG & SCG_SIRCCFG_RANGE_MASK) >> SCG_SIRCCFG_RANGE_SHIFT)
66 #define SCG_FIRCCFG_RANGE_VAL ((SCG->FIRCCFG & SCG_FIRCCFG_RANGE_MASK) >> SCG_FIRCCFG_RANGE_SHIFT)
67 
68 #define SCG_SPLLCFG_PREDIV_VAL ((SCG->SPLLCFG & SCG_SPLLCFG_PREDIV_MASK) >> SCG_SPLLCFG_PREDIV_SHIFT)
69 #define SCG_SPLLCFG_MULT_VAL ((SCG->SPLLCFG & SCG_SPLLCFG_MULT_MASK) >> SCG_SPLLCFG_MULT_SHIFT)
70 
71 #define PCC_PCS_VAL(reg) (((reg)&PCC_CLKCFG_PCS_MASK) >> PCC_CLKCFG_PCS_SHIFT)
72 #define PCC_FRAC_VAL(reg) (((reg)&PCC_CLKCFG_FRAC_MASK) >> PCC_CLKCFG_FRAC_SHIFT)
73 #define PCC_PCD_VAL(reg) (((reg)&PCC_CLKCFG_PCD_MASK) >> PCC_CLKCFG_PCD_SHIFT)
74 
75 /*******************************************************************************
76  * Variables
77  ******************************************************************************/
78 
79 /* External XTAL0 (OSC0) clock frequency. */
80 volatile uint32_t g_xtal0Freq;
81 
82 /*******************************************************************************
83  * Prototypes
84  ******************************************************************************/
85 
86 /*!
87  * @brief Get the common System PLL frequency for both RAW SPLL output and SPLL PFD output.
88  *
89  * The "raw" SPLL output is the clkout divided by postdiv1-2 of SAPLL.
90  * The "common" System PLL frequency is the common part for both RAW SPLL and SPLL PFD output.
91  * That is the frequency calculated based on the clock source which passes through POSTDIV & MULT.
92  * "Common" SPLL Frequency = Divided Reference Frequency * MULT
93  *
94  * @return  Clock frequency; If the clock is invalid, returns 0.
95  */
96 static uint32_t CLOCK_GetSysPllCommonFreq(void);
97 
98 /*******************************************************************************
99  * Code
100  ******************************************************************************/
101 
102 /*!
103  * brief Get the external reference clock frequency (ERCLK).
104  *
105  * return Clock frequency in Hz.
106  */
CLOCK_GetErClkFreq(void)107 uint32_t CLOCK_GetErClkFreq(void)
108 {
109     uint32_t freq;
110 
111     if ((SCG->SOSCCSR & SCG_SOSCCSR_SOSCEN_MASK) != 0UL)
112     {
113         /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
114         assert(g_xtal0Freq);
115         freq = g_xtal0Freq;
116     }
117     else
118     {
119         freq = 0U;
120     }
121 
122     return freq;
123 }
124 
125 /*!
126  * brief Get the OSC 32K clock frequency (OSC32KCLK).
127  *
128  * return Clock frequency in Hz.
129  */
CLOCK_GetOsc32kClkFreq(void)130 uint32_t CLOCK_GetOsc32kClkFreq(void)
131 {
132     return (CLOCK_GetErClkFreq() == 32768U) ? 32768U : 0U;
133 }
134 
135 /*!
136  * brief Get the flash clock frequency.
137  *
138  * return Clock frequency in Hz.
139  */
CLOCK_GetFlashClkFreq(void)140 uint32_t CLOCK_GetFlashClkFreq(void)
141 {
142     return CLOCK_GetSysClkFreq(kSCG_SysClkSlow);
143 }
144 
145 /*!
146  * brief Get the bus clock frequency.
147  *
148  * return Clock frequency in Hz.
149  */
CLOCK_GetBusClkFreq(void)150 uint32_t CLOCK_GetBusClkFreq(void)
151 {
152     return CLOCK_GetSysClkFreq(kSCG_SysClkSlow);
153 }
154 
155 /*!
156  * brief Get the platform clock frequency.
157  *
158  * return Clock frequency in Hz.
159  */
CLOCK_GetPlatClkFreq(void)160 uint32_t CLOCK_GetPlatClkFreq(void)
161 {
162     return CLOCK_GetSysClkFreq(kSCG_SysClkCore);
163 }
164 
165 /*!
166  * brief Get the core clock or system clock frequency.
167  *
168  * return Clock frequency in Hz.
169  */
CLOCK_GetCoreSysClkFreq(void)170 uint32_t CLOCK_GetCoreSysClkFreq(void)
171 {
172     return CLOCK_GetSysClkFreq(kSCG_SysClkCore);
173 }
174 
175 /*!
176  * brief Gets the clock frequency for a specific clock name.
177  *
178  * This function checks the current clock configurations and then calculates
179  * the clock frequency for a specific clock name defined in clock_name_t.
180  *
181  * param clockName Clock names defined in clock_name_t
182  * return Clock frequency value in hertz
183  */
CLOCK_GetFreq(clock_name_t clockName)184 uint32_t CLOCK_GetFreq(clock_name_t clockName)
185 {
186     uint32_t freq;
187 
188     switch (clockName)
189     {
190         case kCLOCK_CoreSysClk:
191         case kCLOCK_PlatClk:
192             freq = CLOCK_GetSysClkFreq(kSCG_SysClkCore);
193             break;
194         case kCLOCK_BusClk:
195         case kCLOCK_FlashClk:
196             freq = CLOCK_GetSysClkFreq(kSCG_SysClkSlow);
197             break;
198         case kCLOCK_ScgSysOscClk:
199             freq = CLOCK_GetSysOscFreq();
200             break;
201         case kCLOCK_ScgSircClk:
202             freq = CLOCK_GetSircFreq();
203             break;
204         case kCLOCK_ScgFircClk:
205             freq = CLOCK_GetFircFreq();
206             break;
207         case kCLOCK_ScgSysPllClk:
208             freq = CLOCK_GetSysPllFreq();
209             break;
210         case kCLOCK_ScgSysOscAsyncDiv1Clk:
211             freq = CLOCK_GetSysOscAsyncFreq(kSCG_AsyncDiv1Clk);
212             break;
213         case kCLOCK_ScgSysOscAsyncDiv2Clk:
214             freq = CLOCK_GetSysOscAsyncFreq(kSCG_AsyncDiv2Clk);
215             break;
216         case kCLOCK_ScgSysOscAsyncDiv3Clk:
217             freq = CLOCK_GetSysOscAsyncFreq(kSCG_AsyncDiv3Clk);
218             break;
219         case kCLOCK_ScgSircAsyncDiv1Clk:
220             freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv1Clk);
221             break;
222         case kCLOCK_ScgSircAsyncDiv2Clk:
223             freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv2Clk);
224             break;
225         case kCLOCK_ScgSircAsyncDiv3Clk:
226             freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv3Clk);
227             break;
228         case kCLOCK_ScgFircAsyncDiv1Clk:
229             freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv1Clk);
230             break;
231         case kCLOCK_ScgFircAsyncDiv2Clk:
232             freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv2Clk);
233             break;
234         case kCLOCK_ScgFircAsyncDiv3Clk:
235             freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv3Clk);
236             break;
237         case kCLOCK_ScgSysPllAsyncDiv1Clk:
238             freq = CLOCK_GetSysPllAsyncFreq(kSCG_AsyncDiv1Clk);
239             break;
240         case kCLOCK_ScgSysPllAsyncDiv2Clk:
241             freq = CLOCK_GetSysPllAsyncFreq(kSCG_AsyncDiv2Clk);
242             break;
243         case kCLOCK_ScgSysPllAsyncDiv3Clk:
244             freq = CLOCK_GetSysPllAsyncFreq(kSCG_AsyncDiv3Clk);
245             break;
246         case kCLOCK_LpoClk:
247             freq = LPO_CLK_FREQ;
248             break;
249         case kCLOCK_Osc32kClk:
250             freq = (CLOCK_GetErClkFreq() == 32768U) ? 32768U : 0U;
251             break;
252         case kCLOCK_ErClk:
253             freq = CLOCK_GetErClkFreq();
254             break;
255         default:
256             freq = 0U;
257             break;
258     }
259     return freq;
260 }
261 
262 /*!
263  * brief Gets the clock frequency for a specific IP module.
264  *
265  * This function gets the IP module clock frequency based on PCC registers. It is
266  * only used for the IP modules which could select clock source by PCC[PCS].
267  *
268  * param name Which peripheral to get, see \ref clock_ip_name_t.
269  * return Clock frequency value in hertz
270  */
CLOCK_GetIpFreq(clock_ip_name_t name)271 uint32_t CLOCK_GetIpFreq(clock_ip_name_t name)
272 {
273     uint32_t reg = (*(volatile uint32_t *)(uint32_t)name);
274 
275     scg_async_clk_t asycClk;
276     uint32_t freq;
277     uint32_t ret;
278 
279     assert(reg & PCC_CLKCFG_PR_MASK);
280 
281     /* USB uses SCG DIV1 clock, others use SCG DIV3 clock. */
282     if (kCLOCK_Usbfs0 == name)
283     {
284         asycClk = kSCG_AsyncDiv1Clk;
285     }
286     else
287     {
288         asycClk = kSCG_AsyncDiv3Clk;
289     }
290 
291     switch (PCC_PCS_VAL(reg))
292     {
293         case (uint32_t)kCLOCK_IpSrcSysOscAsync:
294             freq = CLOCK_GetSysOscAsyncFreq(asycClk);
295             break;
296         case (uint32_t)kCLOCK_IpSrcSircAsync:
297             freq = CLOCK_GetSircAsyncFreq(asycClk);
298             break;
299         case (uint32_t)kCLOCK_IpSrcFircAsync:
300             freq = CLOCK_GetFircAsyncFreq(asycClk);
301             break;
302         case (uint32_t)kCLOCK_IpSrcSysPllAsync:
303             freq = CLOCK_GetSysPllAsyncFreq(asycClk);
304             break;
305         default:
306             freq = 0U;
307             break;
308     }
309 
310     if ((reg & (PCC_CLKCFG_PCD_MASK | PCC_CLKCFG_FRAC_MASK)) != 0UL)
311     {
312         ret = freq * (PCC_FRAC_VAL(reg) + 1U) / (PCC_PCD_VAL(reg) + 1U);
313     }
314     else
315     {
316         ret = freq;
317     }
318 
319     return ret;
320 }
321 
322 /*! brief Enable USB FS clock.
323  *
324  * param src  USB FS clock source.
325  * param freq The frequency specified by src.
326  * retval true The clock is set successfully.
327  * retval false The clock source is invalid to get proper USB FS clock.
328  */
CLOCK_EnableUsbfs0Clock(clock_ip_src_t src,uint32_t freq)329 bool CLOCK_EnableUsbfs0Clock(clock_ip_src_t src, uint32_t freq)
330 {
331     bool ret = true;
332 
333     CLOCK_DisableClock(kCLOCK_Usbfs0);
334 
335     if (kCLOCK_IpSrcNoneOrExt == src)
336     {
337         CLOCK_SetIpSrc(kCLOCK_Usbfs0, kCLOCK_IpSrcNoneOrExt);
338     }
339     else
340     {
341         switch (freq)
342         {
343             case 120000000U:
344                 CLOCK_SetIpSrcDiv(kCLOCK_Usbfs0, src, 4U, 1U);
345                 break;
346             case 96000000U:
347                 CLOCK_SetIpSrcDiv(kCLOCK_Usbfs0, src, 1U, 0U);
348                 break;
349             case 72000000U:
350                 CLOCK_SetIpSrcDiv(kCLOCK_Usbfs0, src, 2U, 1U);
351                 break;
352             case 48000000U:
353                 CLOCK_SetIpSrcDiv(kCLOCK_Usbfs0, src, 0U, 0U);
354                 break;
355             default:
356                 ret = false;
357                 break;
358         }
359     }
360 
361     CLOCK_EnableClock(kCLOCK_Usbfs0);
362 
363     return ret;
364 }
365 
366 /*!
367  * brief Gets the SCG system clock frequency.
368  *
369  * This function gets the SCG system clock frequency. These clocks are used for
370  * core, platform, external, and bus clock domains.
371  *
372  * param type     Which type of clock to get, core clock or slow clock.
373  * return  Clock frequency.
374  */
CLOCK_GetSysClkFreq(scg_sys_clk_t type)375 uint32_t CLOCK_GetSysClkFreq(scg_sys_clk_t type)
376 {
377     uint32_t freq;
378 
379     scg_sys_clk_config_t sysClkConfig;
380 
381     CLOCK_GetCurSysClkConfig(&sysClkConfig); /* Get the main clock for SoC platform. */
382 
383     switch (sysClkConfig.src)
384     {
385         case (uint8_t)kSCG_SysClkSrcSysOsc:
386             freq = CLOCK_GetSysOscFreq();
387             break;
388         case (uint8_t)kSCG_SysClkSrcSirc:
389             freq = CLOCK_GetSircFreq();
390             break;
391         case (uint8_t)kSCG_SysClkSrcFirc:
392             freq = CLOCK_GetFircFreq();
393             break;
394         case (uint8_t)kSCG_SysClkSrcSysPll:
395             freq = CLOCK_GetSysPllFreq();
396             break;
397         default:
398             freq = 0U;
399             break;
400     }
401 
402     freq /= ((uint32_t)sysClkConfig.divCore + 1UL); /* divided by the DIVCORE firstly. */
403 
404     if (kSCG_SysClkSlow == type)
405     {
406         freq /= ((uint32_t)sysClkConfig.divSlow + 1UL);
407     }
408     else
409     {
410         /* Add comment to prevent the case of MISRA C-2012 rule 15.7 */
411     }
412 
413     return freq;
414 }
415 
416 /*!
417  * brief Initializes the SCG system OSC.
418  *
419  * This function enables the SCG system OSC clock according to the
420  * configuration.
421  *
422  * param config   Pointer to the configuration structure.
423  * retval kStatus_Success System OSC is initialized.
424  * retval kStatus_SCG_Busy System OSC has been enabled and is used by the system clock.
425  * retval kStatus_ReadOnly System OSC control register is locked.
426  *
427  * note This function can't detect whether the system OSC has been enabled and
428  * used by an IP.
429  */
CLOCK_InitSysOsc(const scg_sosc_config_t * config)430 status_t CLOCK_InitSysOsc(const scg_sosc_config_t *config)
431 {
432     assert(config);
433     uint8_t range = 0U; /* SCG_SOSCCFG[RANGE] */
434     status_t status;
435     uint8_t tmp8;
436 
437     /* If crystal oscillator used, need to get RANGE value base on frequency. */
438     if (kSCG_SysOscModeExt != config->workMode)
439     {
440         if ((config->freq >= 32768U) && (config->freq <= 40000U))
441         {
442             range = 1U;
443         }
444         else if ((config->freq >= 1000000U) && (config->freq <= 8000000U))
445         {
446             range = 2U;
447         }
448         else if ((config->freq >= 8000000U) && (config->freq <= 32000000U))
449         {
450             range = 3U;
451         }
452         else
453         {
454             return kStatus_InvalidArgument;
455         }
456     }
457 
458     /* De-init the SOSC first. */
459     status = CLOCK_DeinitSysOsc();
460 
461     if (kStatus_Success != status)
462     {
463         return status;
464     }
465 
466     /* Now start to set up OSC clock. */
467     /* Step 1. Setup dividers. */
468     SCG->SOSCDIV =
469         SCG_SOSCDIV_SOSCDIV1(config->div1) | SCG_SOSCDIV_SOSCDIV2(config->div2) | SCG_SOSCDIV_SOSCDIV3(config->div3);
470 
471     /* Step 2. Set OSC configuration. */
472     SCG->SOSCCFG = config->capLoad | (uint32_t)config->workMode | SCG_SOSCCFG_RANGE(range);
473 
474     /* Step 3. Enable clock. */
475     /* SCG->SOSCCSR = SCG_SOSCCSR_SOSCEN_MASK | (config->enableMode); */
476     tmp8 = config->enableMode;
477     tmp8 |= SCG_SOSCCSR_SOSCEN_MASK;
478     SCG->SOSCCSR = tmp8;
479 
480     /* Step 4. Wait for OSC clock to be valid. */
481     while (0UL == (SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK))
482     {
483     }
484 
485     /* Step 5. Enabe monitor. */
486     SCG->SOSCCSR |= (uint32_t)config->monitorMode;
487 
488     return kStatus_Success;
489 }
490 
491 /*!
492  * brief De-initializes the SCG system OSC.
493  *
494  * This function disables the SCG system OSC clock.
495  *
496  * retval kStatus_Success System OSC is deinitialized.
497  * retval kStatus_SCG_Busy System OSC is used by the system clock.
498  * retval kStatus_ReadOnly System OSC control register is locked.
499  *
500  * note This function can't detect whether the system OSC is used by an IP.
501  */
CLOCK_DeinitSysOsc(void)502 status_t CLOCK_DeinitSysOsc(void)
503 {
504     uint32_t reg = SCG->SOSCCSR;
505     status_t status;
506 
507     /* If clock is used by system, return error. */
508     if ((reg & SCG_SOSCCSR_SOSCSEL_MASK) != 0UL)
509     {
510         status = kStatus_SCG_Busy;
511     }
512 
513     /* If configure register is locked, return error. */
514     else if ((reg & SCG_SOSCCSR_LK_MASK) != 0UL)
515     {
516         status = kStatus_ReadOnly;
517     }
518     else
519     {
520         SCG->SOSCCSR = SCG_SOSCCSR_SOSCERR_MASK;
521         status       = kStatus_Success;
522     }
523 
524     return status;
525 }
526 
527 /*!
528  * brief Gets the SCG system OSC clock frequency (SYSOSC).
529  *
530  * return  Clock frequency; If the clock is invalid, returns 0.
531  */
CLOCK_GetSysOscFreq(void)532 uint32_t CLOCK_GetSysOscFreq(void)
533 {
534     uint32_t freq;
535 
536     if ((SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) != 0UL) /* System OSC clock is valid. */
537     {
538         /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
539         assert(g_xtal0Freq);
540         freq = g_xtal0Freq;
541     }
542     else
543     {
544         freq = 0U;
545     }
546 
547     return freq;
548 }
549 
550 /*!
551  * brief Gets the SCG asynchronous clock frequency from the system OSC.
552  *
553  * param type     The asynchronous clock type.
554  * return  Clock frequency; If the clock is invalid, returns 0.
555  */
CLOCK_GetSysOscAsyncFreq(scg_async_clk_t type)556 uint32_t CLOCK_GetSysOscAsyncFreq(scg_async_clk_t type)
557 {
558     uint32_t oscFreq = CLOCK_GetSysOscFreq();
559     uint32_t divider = 0U;
560     uint32_t freq;
561 
562     /* Get divider. */
563     if (oscFreq != 0UL)
564     {
565         switch (type)
566         {
567             case kSCG_AsyncDiv3Clk: /* SOSCDIV3_CLK. */
568                 divider = SCG_SOSCDIV_SOSCDIV3_VAL;
569                 break;
570             case kSCG_AsyncDiv2Clk: /* SOSCDIV2_CLK. */
571                 divider = SCG_SOSCDIV_SOSCDIV2_VAL;
572                 break;
573             case kSCG_AsyncDiv1Clk: /* SOSCDIV1_CLK. */
574                 divider = SCG_SOSCDIV_SOSCDIV1_VAL;
575                 break;
576             default:
577                 divider = 0U;
578                 break;
579         }
580     }
581     if (divider != 0U)
582     {
583         freq = (oscFreq >> (divider - 1U));
584     }
585     else /* Output disabled. */
586     {
587         freq = 0U;
588     }
589 
590     return freq;
591 }
592 
593 /*!
594  * brief Initializes the SCG slow IRC clock.
595  *
596  * This function enables the SCG slow IRC clock according to the
597  * configuration.
598  *
599  * param config   Pointer to the configuration structure.
600  * retval kStatus_Success SIRC is initialized.
601  * retval kStatus_SCG_Busy SIRC has been enabled and is used by system clock.
602  * retval kStatus_ReadOnly SIRC control register is locked.
603  *
604  * note This function can't detect whether the system OSC has been enabled and
605  * used by an IP.
606  */
CLOCK_InitSirc(const scg_sirc_config_t * config)607 status_t CLOCK_InitSirc(const scg_sirc_config_t *config)
608 {
609     assert(config);
610 
611     status_t status;
612 
613     /* De-init the SIRC first. */
614     status = CLOCK_DeinitSirc();
615 
616     if (status == kStatus_Success)
617     {
618         /* Now start to set up SIRC clock. */
619         /* Step 1. Setup dividers. */
620         SCG->SIRCDIV = SCG_SIRCDIV_SIRCDIV1(config->div1) | SCG_SIRCDIV_SIRCDIV2(config->div2) |
621                        SCG_SIRCDIV_SIRCDIV3(config->div3);
622 
623         /* Step 2. Set SIRC configuration. */
624         SCG->SIRCCFG = SCG_SIRCCFG_RANGE(config->range);
625 
626         /* Step 3. Enable clock. */
627         SCG->SIRCCSR = SCG_SIRCCSR_SIRCEN_MASK | config->enableMode;
628 
629         /* Step 4. Wait for SIRC clock to be valid. */
630         while (0UL == (SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK))
631         {
632         }
633     }
634 
635     return status;
636 }
637 
638 /*!
639  * brief De-initializes the SCG slow IRC.
640  *
641  * This function disables the SCG slow IRC.
642  *
643  * retval kStatus_Success SIRC is deinitialized.
644  * retval kStatus_SCG_Busy SIRC is used by system clock.
645  * retval kStatus_ReadOnly SIRC control register is locked.
646  *
647  * note This function can't detect whether the SIRC is used by an IP.
648  */
CLOCK_DeinitSirc(void)649 status_t CLOCK_DeinitSirc(void)
650 {
651     uint32_t reg = SCG->SIRCCSR;
652     status_t status;
653 
654     /* If clock is used by system, return error. */
655     if ((reg & SCG_SIRCCSR_SIRCSEL_MASK) != 0UL)
656     {
657         status = kStatus_SCG_Busy;
658     }
659     /* If configure register is locked, return error. */
660     else if ((reg & SCG_SIRCCSR_LK_MASK) != 0UL)
661     {
662         status = kStatus_ReadOnly;
663     }
664     else
665     {
666         SCG->SIRCCSR = 0U;
667         status       = kStatus_Success;
668     }
669 
670     return status;
671 }
672 
673 /*!
674  * brief Gets the SCG SIRC clock frequency.
675  *
676  * return  Clock frequency; If the clock is invalid, returns 0.
677  */
CLOCK_GetSircFreq(void)678 uint32_t CLOCK_GetSircFreq(void)
679 {
680     static const uint32_t sircFreq[] = {SCG_SIRC_LOW_RANGE_FREQ, SCG_SIRC_HIGH_RANGE_FREQ};
681     uint32_t freq;
682 
683     if ((SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK) != 0UL) /* SIRC is valid. */
684     {
685         freq = sircFreq[SCG_SIRCCFG_RANGE_VAL];
686     }
687     else
688     {
689         freq = 0U;
690     }
691 
692     return freq;
693 }
694 
695 /*!
696  * brief Gets the SCG asynchronous clock frequency from the SIRC.
697  *
698  * param type     The asynchronous clock type.
699  * return  Clock frequency; If the clock is invalid, returns 0.
700  */
CLOCK_GetSircAsyncFreq(scg_async_clk_t type)701 uint32_t CLOCK_GetSircAsyncFreq(scg_async_clk_t type)
702 {
703     uint32_t sircFreq = CLOCK_GetSircFreq();
704     uint32_t divider  = 0U;
705     uint32_t freq;
706 
707     /* Get divider. */
708     if (sircFreq != 0UL)
709     {
710         switch (type)
711         {
712             case kSCG_AsyncDiv3Clk: /* SIRCDIV3_CLK. */
713                 divider = SCG_SIRCDIV_SIRCDIV3_VAL;
714                 break;
715             case kSCG_AsyncDiv2Clk: /* SIRCDIV2_CLK. */
716                 divider = SCG_SIRCDIV_SIRCDIV2_VAL;
717                 break;
718             case kSCG_AsyncDiv1Clk: /* SIRCDIV2_CLK. */
719                 divider = SCG_SIRCDIV_SIRCDIV1_VAL;
720                 break;
721             default:
722                 divider = 0U;
723                 break;
724         }
725     }
726     if (divider != 0UL)
727     {
728         freq = (sircFreq >> (divider - 1U));
729     }
730     else /* Output disabled. */
731     {
732         freq = 0U;
733     }
734 
735     return freq;
736 }
737 
738 /*!
739  * brief Initializes the SCG fast IRC clock.
740  *
741  * This function enables the SCG fast IRC clock according to the configuration.
742  *
743  * param config   Pointer to the configuration structure.
744  * retval kStatus_Success FIRC is initialized.
745  * retval kStatus_SCG_Busy FIRC has been enabled and is used by the system clock.
746  * retval kStatus_ReadOnly FIRC control register is locked.
747  *
748  * note This function can't detect whether the FIRC has been enabled and
749  * used by an IP.
750  */
CLOCK_InitFirc(const scg_firc_config_t * config)751 status_t CLOCK_InitFirc(const scg_firc_config_t *config)
752 {
753     assert(config);
754 
755     status_t status;
756 
757     /* De-init the FIRC first. */
758     status = CLOCK_DeinitFirc();
759 
760     if (kStatus_Success != status)
761     {
762         return status;
763     }
764 
765     /* Now start to set up FIRC clock. */
766     /* Step 1. Setup dividers. */
767     SCG->FIRCDIV =
768         SCG_FIRCDIV_FIRCDIV1(config->div1) | SCG_FIRCDIV_FIRCDIV2(config->div2) | SCG_FIRCDIV_FIRCDIV3(config->div3);
769 
770     /* Step 2. Set FIRC configuration. */
771     SCG->FIRCCFG = SCG_FIRCCFG_RANGE(config->range);
772 
773     /* Step 3. Set trimming configuration. */
774     if ((config->trimConfig) != NULL)
775     {
776         SCG->FIRCTCFG =
777             SCG_FIRCTCFG_TRIMDIV(config->trimConfig->trimDiv) | SCG_FIRCTCFG_TRIMSRC(config->trimConfig->trimSrc);
778 
779         /* TODO: Write FIRCSTAT cause bus error: TKT266932. */
780         if (kSCG_FircTrimNonUpdate == config->trimConfig->trimMode)
781         {
782             SCG->FIRCSTAT = SCG_FIRCSTAT_TRIMCOAR(config->trimConfig->trimCoar) |
783                             SCG_FIRCSTAT_TRIMFINE(config->trimConfig->trimFine);
784         }
785 
786         /* trim mode. */
787         SCG->FIRCCSR = (uint32_t)(config->trimConfig->trimMode);
788 
789         if ((SCG->FIRCCSR & SCG_FIRCCSR_FIRCERR_MASK) != 0UL)
790         {
791             return kStatus_Fail;
792         }
793     }
794 
795     /* Step 4. Enable clock. */
796     SCG->FIRCCSR |= (SCG_FIRCCSR_FIRCEN_MASK | config->enableMode);
797 
798     /* Step 5. Wait for FIRC clock to be valid. */
799     while (0UL == (SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK))
800     {
801     }
802 
803     return kStatus_Success;
804 }
805 
806 /*!
807  * brief De-initializes the SCG fast IRC.
808  *
809  * This function disables the SCG fast IRC.
810  *
811  * retval kStatus_Success FIRC is deinitialized.
812  * retval kStatus_SCG_Busy FIRC is used by the system clock.
813  * retval kStatus_ReadOnly FIRC control register is locked.
814  *
815  * note This function can't detect whether the FIRC is used by an IP.
816  */
CLOCK_DeinitFirc(void)817 status_t CLOCK_DeinitFirc(void)
818 {
819     uint32_t reg    = SCG->FIRCCSR;
820     status_t status = kStatus_Success;
821 
822     /* If clock is used by system, return error. */
823     if ((reg & SCG_FIRCCSR_FIRCSEL_MASK) != 0UL)
824     {
825         status = kStatus_SCG_Busy;
826     }
827     /* If configure register is locked, return error. */
828     else if ((reg & SCG_FIRCCSR_LK_MASK) != 0UL)
829     {
830         status = kStatus_ReadOnly;
831     }
832     else
833     {
834         SCG->FIRCCSR = SCG_FIRCCSR_FIRCERR_MASK;
835     }
836 
837     return status;
838 }
839 
840 /*!
841  * brief Gets the SCG FIRC clock frequency.
842  *
843  * return  Clock frequency; If the clock is invalid, returns 0.
844  */
CLOCK_GetFircFreq(void)845 uint32_t CLOCK_GetFircFreq(void)
846 {
847     uint32_t freq;
848 
849     static const uint32_t fircFreq[] = {
850         SCG_FIRC_FREQ0,
851         SCG_FIRC_FREQ1,
852         SCG_FIRC_FREQ2,
853         SCG_FIRC_FREQ3,
854     };
855 
856     if ((SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) != 0UL) /* FIRC is valid. */
857     {
858         freq = fircFreq[SCG_FIRCCFG_RANGE_VAL];
859     }
860     else
861     {
862         freq = 0U;
863     }
864 
865     return freq;
866 }
867 
868 /*!
869  * brief Gets the SCG asynchronous clock frequency from the FIRC.
870  *
871  * param type     The asynchronous clock type.
872  * return  Clock frequency; If the clock is invalid, returns 0.
873  */
CLOCK_GetFircAsyncFreq(scg_async_clk_t type)874 uint32_t CLOCK_GetFircAsyncFreq(scg_async_clk_t type)
875 {
876     uint32_t fircFreq = CLOCK_GetFircFreq();
877     uint32_t divider  = 0U;
878     uint32_t freq;
879 
880     /* Get divider. */
881     if (fircFreq != 0UL)
882     {
883         switch (type)
884         {
885             case kSCG_AsyncDiv3Clk: /* FIRCDIV3_CLK. */
886                 divider = SCG_FIRCDIV_FIRCDIV3_VAL;
887                 break;
888             case kSCG_AsyncDiv2Clk: /* FIRCDIV2_CLK. */
889                 divider = SCG_FIRCDIV_FIRCDIV2_VAL;
890                 break;
891             case kSCG_AsyncDiv1Clk: /* FIRCDIV1_CLK. */
892                 divider = SCG_FIRCDIV_FIRCDIV1_VAL;
893                 break;
894             default:
895                 divider = 0U;
896                 break;
897         }
898     }
899     if (divider != 0U)
900     {
901         freq = (fircFreq >> (divider - 1U));
902     }
903     else /* Output disabled. */
904     {
905         freq = 0U;
906     }
907 
908     return freq;
909 }
910 
911 /*!
912  * brief Calculates the MULT and PREDIV for the PLL.
913  *
914  * This function calculates the proper MULT and PREDIV to generate the desired PLL
915  * output frequency with the input reference clock frequency. It returns the closest
916  * frequency match that the PLL can generate. The corresponding MULT/PREDIV are returned with
917  * parameters. If the desired frequency is not valid, this function returns 0.
918  *
919  * param refFreq     The input reference clock frequency.
920  * param desireFreq  The desired output clock frequency.
921  * param mult        The value of MULT.
922  * param prediv      The value of PREDIV.
923  * return The PLL output frequency with the MULT and PREDIV; If
924  * the desired frequency can't be generated, this function returns 0U.
925  */
CLOCK_GetSysPllMultDiv(uint32_t refFreq,uint32_t desireFreq,uint8_t * mult,uint8_t * prediv)926 uint32_t CLOCK_GetSysPllMultDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *mult, uint8_t *prediv)
927 {
928     uint8_t ret_prediv;              /* PREDIV to return */
929     uint8_t ret_mult;                /* MULT to return */
930     uint8_t prediv_min;              /* Minimal PREDIV value to make reference clock in allowed range. */
931     uint8_t prediv_max;              /* Max PREDIV value to make reference clock in allowed range. */
932     uint8_t prediv_cur;              /* PREDIV value for iteration. */
933     uint8_t mult_cur;                /* MULT value for iteration. */
934     uint32_t ret_freq = 0U;          /* Output frequency to return .*/
935     uint32_t diff     = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */
936     uint32_t ref_div;                /* Reference frequency after PREDIV. */
937 
938     /*
939      * Steps:
940      * 1. Get allowed prediv with such rules:
941      *    1). refFreq / prediv >= SCG_PLL_REF_MIN.
942      *    2). refFreq / prediv <= SCG_PLL_REF_MAX.
943      * 2. For each allowed prediv, there are two candidate mult values:
944      *    1). (desireFreq / (refFreq / prediv)).
945      *    2). (desireFreq / (refFreq / prediv)) + 1.
946      *    If could get the precise desired frequency, return current prediv and
947      *    mult directly. Otherwise choose the one which is closer to desired
948      *    frequency.
949      */
950 
951     /* Reference frequency is out of range. */
952     if ((refFreq < SCG_SPLL_REF_MIN) ||
953         (refFreq > (SCG_SPLL_REF_MAX * (SCG_SPLL_PREDIV_MAX_VALUE + SCG_SPLL_PREDIV_BASE_VALUE))))
954     {
955         return 0U;
956     }
957 
958     /* refFreq/PREDIV must in a range. First get the allowed PREDIV range. */
959     prediv_max = (uint8_t)(refFreq / SCG_SPLL_REF_MIN);
960     prediv_min = (uint8_t)((refFreq + SCG_SPLL_REF_MAX - 1UL) / SCG_SPLL_REF_MAX);
961 
962     desireFreq *= 2U;
963 
964     /* PREDIV traversal. */
965     for (prediv_cur = prediv_max; prediv_cur >= prediv_min; prediv_cur--)
966     {
967         /*
968          * For each PREDIV, the available MULT is (desireFreq*PREDIV/refFreq)
969          * or (desireFreq*PREDIV/refFreq + 1U). This function chooses the closer
970          * one.
971          */
972         /* Reference frequency after PREDIV. */
973         ref_div = refFreq / prediv_cur;
974 
975         mult_cur = (uint8_t)(desireFreq / ref_div);
976 
977         if ((mult_cur < SCG_SPLL_MULT_BASE_VALUE - 1U) ||
978             (mult_cur > SCG_SPLL_MULT_BASE_VALUE + SCG_SPLL_MULT_MAX_VALUE))
979         {
980             /* No MULT is available with this PREDIV. */
981             continue;
982         }
983 
984         ret_freq = mult_cur * ref_div;
985 
986         if (mult_cur >= SCG_SPLL_MULT_BASE_VALUE)
987         {
988             if (ret_freq == desireFreq) /* If desire frequency is got. */
989             {
990                 *prediv = prediv_cur - SCG_SPLL_PREDIV_BASE_VALUE;
991                 *mult   = mult_cur - SCG_SPLL_MULT_BASE_VALUE;
992                 return ret_freq / 2U;
993             }
994             if (diff > desireFreq - ret_freq) /* New PRDIV/VDIV is closer. */
995             {
996                 diff       = desireFreq - ret_freq;
997                 ret_prediv = prediv_cur;
998                 ret_mult   = mult_cur;
999             }
1000         }
1001         mult_cur++;
1002         if (mult_cur <= (SCG_SPLL_MULT_BASE_VALUE + SCG_SPLL_MULT_MAX_VALUE))
1003         {
1004             ret_freq += ref_div;
1005             if (diff > ret_freq - desireFreq) /* New PRDIV/VDIV is closer. */
1006             {
1007                 diff       = ret_freq - desireFreq;
1008                 ret_prediv = prediv_cur;
1009                 ret_mult   = mult_cur;
1010             }
1011         }
1012     }
1013 
1014     if (0xFFFFFFFFU != diff)
1015     {
1016         /* PREDIV/MULT found. */
1017         *prediv = ret_prediv - SCG_SPLL_PREDIV_BASE_VALUE;
1018         *mult   = ret_mult - SCG_SPLL_MULT_BASE_VALUE;
1019         return ((refFreq / ret_prediv) * ret_mult) / 2U;
1020     }
1021     else
1022     {
1023         return 0U; /* No proper PREDIV/MULT found. */
1024     }
1025 }
1026 
1027 /*!
1028  * brief Initializes the SCG system PLL.
1029  *
1030  * This function enables the SCG system PLL clock according to the
1031  * configuration. The system PLL can use the system OSC or FIRC as
1032  * the clock source. Ensure that the source clock is valid before
1033  * calling this function.
1034  *
1035  * Example code for initializing SPLL clock output:
1036  * code
1037  * const scg_spll_config_t g_scgSysPllConfig = {.enableMode = kSCG_SysPllEnable,
1038  *                                            .monitorMode = kSCG_SysPllMonitorDisable,
1039  *                                            .div1 = kSCG_AsyncClkDivBy1,
1040  *                                            .div2 = kSCG_AsyncClkDisable,
1041  *                                            .div3 = kSCG_AsyncClkDivBy2,
1042  *                                            .src = kSCG_SysPllSrcFirc,
1043  *                                            .isBypassSelected = false,
1044  *                                            .isPfdSelected = false,
1045  *                                            .prediv = 5U,
1046  *                                            .pfdClkout = kSCG_AuxPllPfd0Clk,
1047  * endcode
1048  *
1049  * param config   Pointer to the configuration structure.
1050  * retval kStatus_Success System PLL is initialized.
1051  * retval kStatus_SCG_Busy System PLL has been enabled and is used by the system clock.
1052  * retval kStatus_ReadOnly System PLL control register is locked.
1053  *
1054  * note This function can't detect whether the system PLL has been enabled and
1055  * used by an IP.
1056  */
CLOCK_InitSysPll(const scg_spll_config_t * config)1057 status_t CLOCK_InitSysPll(const scg_spll_config_t *config)
1058 {
1059     assert(config);
1060 
1061     status_t status;
1062 
1063     /* De-init the SPLL first. */
1064     status = CLOCK_DeinitSysPll();
1065 
1066     if (kStatus_Success != status)
1067     {
1068         return status;
1069     }
1070 
1071     /* Now start to set up PLL clock. */
1072     /* Step 1. Setup dividers. */
1073     SCG->SPLLDIV =
1074         SCG_SPLLDIV_SPLLDIV1(config->div1) | SCG_SPLLDIV_SPLLDIV2(config->div2) | SCG_SPLLDIV_SPLLDIV3(config->div3);
1075 
1076     /* Step 2. Set PLL configuration. */
1077     SCG->SPLLCFG =
1078         SCG_SPLLCFG_SOURCE(config->src) | SCG_SPLLCFG_PREDIV(config->prediv) | SCG_SPLLCFG_MULT(config->mult);
1079 
1080     /* Step 3. Enable clock. */
1081     SCG->SPLLCSR = (uint32_t)SCG_SPLLCSR_SPLLEN_MASK | config->enableMode;
1082 
1083     /* Step 4. Wait for PLL clock to be valid. */
1084     while (0UL == (SCG->SPLLCSR & SCG_SPLLCSR_SPLLVLD_MASK))
1085     {
1086     }
1087 
1088     /* Step 5. Enabe monitor. */
1089     SCG->SPLLCSR |= (uint32_t)config->monitorMode;
1090 
1091     return kStatus_Success;
1092 }
1093 
1094 /*!
1095  * brief De-initializes the SCG system PLL.
1096  *
1097  * This function disables the SCG system PLL.
1098  *
1099  * retval kStatus_Success system PLL is deinitialized.
1100  * retval kStatus_SCG_Busy system PLL is used by the system clock.
1101  * retval kStatus_ReadOnly System PLL control register is locked.
1102  *
1103  * note This function can't detect whether the system PLL is used by an IP.
1104  */
CLOCK_DeinitSysPll(void)1105 status_t CLOCK_DeinitSysPll(void)
1106 {
1107     uint32_t reg = SCG->SPLLCSR;
1108     status_t status;
1109 
1110     /* If clock is used by system, return error. */
1111     if ((reg & SCG_SPLLCSR_SPLLSEL_MASK) != 0UL)
1112     {
1113         status = kStatus_SCG_Busy;
1114     }
1115     /* If configure register is locked, return error. */
1116     else if ((reg & SCG_SPLLCSR_LK_MASK) != 0UL)
1117     {
1118         status = kStatus_ReadOnly;
1119     }
1120     else
1121     {
1122         /* Deinit and clear the error. */
1123         SCG->SPLLCSR = SCG_SPLLCSR_SPLLERR_MASK;
1124         status       = kStatus_Success;
1125     }
1126 
1127     return status;
1128 }
1129 
CLOCK_GetSysPllCommonFreq(void)1130 static uint32_t CLOCK_GetSysPllCommonFreq(void)
1131 {
1132     uint32_t freq = 0U;
1133 
1134     if ((SCG->SPLLCFG & SCG_SPLLCFG_SOURCE_MASK) != 0UL) /* If use FIRC */
1135     {
1136         freq = CLOCK_GetFircFreq();
1137     }
1138     else /* Use System OSC. */
1139     {
1140         freq = CLOCK_GetSysOscFreq();
1141     }
1142 
1143     if (freq != 0UL) /* If source is valid. */
1144     {
1145         freq /= (SCG_SPLLCFG_PREDIV_VAL + SCG_SPLL_PREDIV_BASE_VALUE); /* Pre-divider. */
1146         freq *= (SCG_SPLLCFG_MULT_VAL + SCG_SPLL_MULT_BASE_VALUE);     /* Multiplier. */
1147     }
1148 
1149     return freq;
1150 }
1151 
1152 /*!
1153  * brief Gets the SCG system PLL clock frequency.
1154  *
1155  * return  Clock frequency; If the clock is invalid, returns 0.
1156  */
CLOCK_GetSysPllFreq(void)1157 uint32_t CLOCK_GetSysPllFreq(void)
1158 {
1159     uint32_t freq;
1160 
1161     if ((SCG->SPLLCSR & SCG_SPLLCSR_SPLLVLD_MASK) != 0UL) /* System PLL is valid. */
1162     {
1163         freq = CLOCK_GetSysPllCommonFreq();
1164 
1165         return freq >> 1U;
1166     }
1167     else
1168     {
1169         return 0U;
1170     }
1171 }
1172 
1173 /*!
1174  * brief Gets the SCG asynchronous clock frequency from the system PLL.
1175  *
1176  * param type     The asynchronous clock type.
1177  * return  Clock frequency; If the clock is invalid, returns 0.
1178  */
CLOCK_GetSysPllAsyncFreq(scg_async_clk_t type)1179 uint32_t CLOCK_GetSysPllAsyncFreq(scg_async_clk_t type)
1180 {
1181     uint32_t pllFreq = CLOCK_GetSysPllFreq();
1182     uint32_t divider = 0U;
1183     uint32_t freq;
1184 
1185     /* Get divider. */
1186     if (pllFreq != 0UL)
1187     {
1188         switch (type)
1189         {
1190             case kSCG_AsyncDiv3Clk: /* SPLLDIV3_CLK. */
1191                 divider = SCG_SPLLDIV_SPLLDIV3_VAL;
1192                 break;
1193             case kSCG_AsyncDiv2Clk: /* SPLLDIV2_CLK. */
1194                 divider = SCG_SPLLDIV_SPLLDIV2_VAL;
1195                 break;
1196             case kSCG_AsyncDiv1Clk: /* SPLLDIV1_CLK. */
1197                 divider = SCG_SPLLDIV_SPLLDIV1_VAL;
1198                 break;
1199             default:
1200                 divider = 0U;
1201                 break;
1202         }
1203     }
1204     if (divider != 0UL)
1205     {
1206         freq = (pllFreq >> (divider - 1U));
1207     }
1208     else /* Output disabled. */
1209     {
1210         freq = 0U;
1211     }
1212 
1213     return freq;
1214 }
1215