1 /*
2  * Copyright 2017-2019 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_clock.h"
9 /*******************************************************************************
10  * Definitions
11  ******************************************************************************/
12 /* Component ID definition, used by tools. */
13 #ifndef FSL_COMPONENT_ID
14 #define FSL_COMPONENT_ID "platform.drivers.clock"
15 #endif
16 #define SYSPLL_MIN_INPUT_FREQ_HZ  (10000000U)  /*!<  Minimum PLL input rate */
17 #define SYSPLL_MAX_INPUT_FREQ_HZ  (25000000U)  /*!<  Maximum PLL input rate */
18 #define SYSPLL_MAX_OUTPUT_FREQ_HZ (100000000U) /*!< Maximum PLL output rate */
19 #define SYSPLL_MIN_FCCO_FREQ_HZ   (156000000U) /*!< Maximum FCCO output rate */
20 #define SYSPLL_MAX_FCCO_FREQ_HZ   (320000000U) /*!< Maximum FCCO output rate */
21 #define SYSOSC_BOUNDARY_FREQ_HZ   (15000000U)  /*!< boundary frequency value */
22 
23 /* External clock rate.
24  * Either external clk in rate or system oscillator frequency.
25  */
26 volatile uint32_t g_Ext_Clk_Freq = 0U;
27 /** watch dog oscillator rate in Hz.*/
28 volatile uint32_t g_Wdt_Osc_Freq = 0U;
29 
30 /*******************************************************************************
31  * Variables
32  ******************************************************************************/
33 
34 /*******************************************************************************
35  * Prototypes
36  ******************************************************************************/
37 /*
38  * @brief   select post divider for system pll according to the target frequency.
39  * @param   outFreq: Value to be output
40  * @return  post divider
41  */
42 static uint32_t findSyestemPllPsel(uint32_t outFreq);
43 
44 /*
45  * @brief   Get FRG input clock frequency.
46  * @param fractional clock register base address.
47  * @return  input clock frequency.
48  */
49 static uint32_t CLOCK_GetFRGInputClkFreq(uint32_t *base);
50 
51 /*
52  * @brief Update clock source.
53  * @param base clock register base address.
54  * @param mask clock source update enable bit mask value.
55  */
56 static void CLOCK_UpdateClkSrc(volatile uint32_t *base, uint32_t mask);
57 
58 /*******************************************************************************
59  * Code
60  ******************************************************************************/
CLOCK_GetFRGInputClkFreq(uint32_t * base)61 static uint32_t CLOCK_GetFRGInputClkFreq(uint32_t *base)
62 {
63     uint32_t sel = CLK_FRG_SEL_REG_MAP(base) & SYSCON_FRG_FRGCLKSEL_SEL_MASK;
64 
65     if (sel == 0U)
66     {
67         return CLOCK_GetFroFreq();
68     }
69     else if (sel == 1U)
70     {
71         return CLOCK_GetMainClkFreq();
72     }
73     else
74     {
75         return CLOCK_GetSystemPLLFreq();
76     }
77 }
78 
CLOCK_SetFRGClkFreq(uint32_t * base,uint32_t freq)79 static bool CLOCK_SetFRGClkFreq(uint32_t *base, uint32_t freq)
80 {
81     assert(freq);
82 
83     uint32_t input = CLOCK_GetFRGInputClkFreq(base);
84     uint32_t mul;
85 
86     if ((freq > input) || (input / freq >= 2U))
87     {
88         return false;
89     }
90 
91     mul = (uint32_t)(((uint64_t)((uint64_t)input - freq) << 8U) / ((uint64_t)freq));
92 
93     CLK_FRG_DIV_REG_MAP(base) = SYSCON_FRG_FRGDIV_DIV_MASK;
94     CLK_FRG_MUL_REG_MAP(base) = SYSCON_FRG_FRGMULT_MULT(mul);
95 
96     return true;
97 }
98 
CLOCK_UpdateClkSrc(volatile uint32_t * base,uint32_t mask)99 static void CLOCK_UpdateClkSrc(volatile uint32_t *base, uint32_t mask)
100 {
101     assert(base);
102 
103     *base &= ~mask;
104     *base |= mask;
105     while ((*base & mask) == 0U)
106     {
107     }
108 }
109 
110 /*! brief Set FRG0 output frequency.
111  * param freq, target output frequency,freq < input and (input / freq) < 2 should be satisfy.
112  * retval true - successfully, false - input argument is invalid.
113  *
114  */
CLOCK_SetFRG0ClkFreq(uint32_t freq)115 bool CLOCK_SetFRG0ClkFreq(uint32_t freq)
116 {
117     return CLOCK_SetFRGClkFreq(((uint32_t *)(uint32_t)(&SYSCON->FRG[0U])), freq);
118 }
119 
120 /*! brief Set FRG1 output frequency.
121  * param freq, target output frequency,freq < input and (input / freq) < 2 should be satisfy.
122  * retval true - successfully, false - input argument is invalid.
123  *
124  */
CLOCK_SetFRG1ClkFreq(uint32_t freq)125 bool CLOCK_SetFRG1ClkFreq(uint32_t freq)
126 {
127     return CLOCK_SetFRGClkFreq(((uint32_t *)(uint32_t)(&SYSCON->FRG[1U])), freq);
128 }
129 
130 /*! brief  Return Frequency of FRG0 Clock.
131  *  return Frequency of FRG0 Clock.
132  */
CLOCK_GetFRG0ClkFreq(void)133 uint32_t CLOCK_GetFRG0ClkFreq(void)
134 {
135     uint32_t temp;
136 
137     temp = CLOCK_GetFRGInputClkFreq((uint32_t *)(uint32_t)(&SYSCON->FRG[0U])) << 8U;
138     return (uint32_t)((uint64_t)(temp) / (((uint64_t)SYSCON->FRG[0U].FRGMULT & SYSCON_FRG_FRGMULT_MULT_MASK) + 256ULL));
139 }
140 
141 /*! brief  Return Frequency of FRG1 Clock.
142  *  return Frequency of FRG1 Clock.
143  */
CLOCK_GetFRG1ClkFreq(void)144 uint32_t CLOCK_GetFRG1ClkFreq(void)
145 {
146     uint32_t temp;
147 
148     temp = (CLOCK_GetFRGInputClkFreq((uint32_t *)(uint32_t)(&SYSCON->FRG[1U])) << 8U);
149     return (uint32_t)(((uint64_t)temp) / (((uint64_t)SYSCON->FRG[1U].FRGMULT & SYSCON_FRG_FRGMULT_MULT_MASK) + 256ULL));
150 }
151 
152 /*! brief  Return Frequency of Main Clock.
153  *  return Frequency of Main Clock.
154  */
CLOCK_GetMainClkFreq(void)155 uint32_t CLOCK_GetMainClkFreq(void)
156 {
157     uint32_t freq = 0U;
158 
159     if ((SYSCON->MAINCLKPLLSEL & SYSCON_MAINCLKPLLSEL_SEL_MASK) == 1U)
160     {
161         return CLOCK_GetSystemPLLFreq();
162     }
163 
164     switch (SYSCON->MAINCLKSEL)
165     {
166         case 0U:
167             freq = CLOCK_GetFroFreq();
168             break;
169 
170         case 1U:
171             freq = CLOCK_GetExtClkFreq();
172             break;
173 
174         case 2U:
175             freq = CLOCK_GetWdtOscFreq();
176             break;
177 
178         case 3U:
179             freq = CLOCK_GetFroFreq() >> 1U;
180             break;
181         default:
182             freq = 0U;
183             break;
184     }
185 
186     return freq;
187 }
188 
189 /*! brief  Return Frequency of FRO.
190  *  return Frequency of FRO.
191  */
CLOCK_GetFroFreq(void)192 uint32_t CLOCK_GetFroFreq(void)
193 {
194     uint32_t froOscSel  = SYSCON->FROOSCCTRL & 3U;
195     uint32_t froOscFreq = 0U;
196 
197     if (froOscSel == 0U)
198     {
199         froOscFreq = 18000000U;
200     }
201     else if (froOscSel == 1U)
202     {
203         froOscFreq = 24000000U;
204     }
205     else
206     {
207         froOscFreq = 30000000U;
208     }
209 
210     if (((SYSCON->FROOSCCTRL & SYSCON_FROOSCCTRL_FRO_DIRECT_MASK) >> SYSCON_FROOSCCTRL_FRO_DIRECT_SHIFT) == 0U)
211     {
212         /* need to check the FAIM low power boot value */
213         froOscFreq /= ((*((volatile uint32_t *)(CLOCK_FAIM_BASE)) & 0x2U) != 0UL) ? 16U : 2U;
214     }
215 
216     return froOscFreq;
217 }
218 
219 /*! brief  Return Frequency of ClockOut
220  *  return Frequency of ClockOut
221  */
CLOCK_GetClockOutClkFreq(void)222 uint32_t CLOCK_GetClockOutClkFreq(void)
223 {
224     uint32_t divider = SYSCON->CLKOUTDIV & 0xffU, freq = 0U;
225 
226     switch (SYSCON->CLKOUTSEL)
227     {
228         case 0U:
229             freq = CLOCK_GetFroFreq();
230             break;
231 
232         case 1U:
233             freq = CLOCK_GetMainClkFreq();
234             break;
235 
236         case 2U:
237             freq = CLOCK_GetSystemPLLFreq();
238             break;
239 
240         case 3U:
241             freq = CLOCK_GetExtClkFreq();
242             break;
243 
244         case 4U:
245             freq = CLOCK_GetWdtOscFreq();
246             break;
247 
248         default:
249             freq = 0U;
250             break;
251     }
252 
253     return divider == 0U ? 0U : (freq / divider);
254 }
255 
256 /*! brief  Return Frequency of UART0
257  *  return Frequency of UART0
258  */
CLOCK_GetUart0ClkFreq(void)259 uint32_t CLOCK_GetUart0ClkFreq(void)
260 {
261     uint32_t freq = 0U;
262 
263     switch (SYSCON->FCLKSEL[0])
264     {
265         case 0U:
266             freq = CLOCK_GetFroFreq();
267             break;
268         case 1U:
269             freq = CLOCK_GetMainClkFreq();
270             break;
271         case 2U:
272             freq = CLOCK_GetFRG0ClkFreq();
273             break;
274         case 3U:
275             freq = CLOCK_GetFRG1ClkFreq();
276             break;
277         case 4U:
278             freq = CLOCK_GetFroFreq() >> 1U;
279             break;
280 
281         default:
282             freq = 0U;
283             break;
284     }
285 
286     return freq;
287 }
288 
289 /*! brief  Return Frequency of UART1
290  *  return Frequency of UART1
291  */
CLOCK_GetUart1ClkFreq(void)292 uint32_t CLOCK_GetUart1ClkFreq(void)
293 {
294     uint32_t freq = 0U;
295 
296     switch (SYSCON->FCLKSEL[1])
297     {
298         case 0U:
299             freq = CLOCK_GetFroFreq();
300             break;
301         case 1U:
302             freq = CLOCK_GetMainClkFreq();
303             break;
304         case 2U:
305             freq = CLOCK_GetFRG0ClkFreq();
306             break;
307         case 3U:
308             freq = CLOCK_GetFRG1ClkFreq();
309             break;
310         case 4U:
311             freq = CLOCK_GetFroFreq() >> 1U;
312             break;
313 
314         default:
315             freq = 0U;
316             break;
317     }
318 
319     return freq;
320 }
321 
322 /*! brief  Return Frequency of UART2
323  *  return Frequency of UART2
324  */
CLOCK_GetUart2ClkFreq(void)325 uint32_t CLOCK_GetUart2ClkFreq(void)
326 {
327     uint32_t freq = 0U;
328 
329     switch (SYSCON->FCLKSEL[2])
330     {
331         case 0U:
332             freq = CLOCK_GetFroFreq();
333             break;
334         case 1U:
335             freq = CLOCK_GetMainClkFreq();
336             break;
337         case 2U:
338             freq = CLOCK_GetFRG0ClkFreq();
339             break;
340         case 3U:
341             freq = CLOCK_GetFRG1ClkFreq();
342             break;
343         case 4U:
344             freq = CLOCK_GetFroFreq() >> 1U;
345             break;
346 
347         default:
348             freq = 0U;
349             break;
350     }
351 
352     return freq;
353 }
354 
355 /*! brief  Return Frequency of UART3
356  *  return Frequency of UART3
357  */
CLOCK_GetUart3ClkFreq(void)358 uint32_t CLOCK_GetUart3ClkFreq(void)
359 {
360     uint32_t freq = 0U;
361 
362     switch (SYSCON->FCLKSEL[3])
363     {
364         case 0U:
365             freq = CLOCK_GetFroFreq();
366             break;
367         case 1U:
368             freq = CLOCK_GetMainClkFreq();
369             break;
370         case 2U:
371             freq = CLOCK_GetFRG0ClkFreq();
372             break;
373         case 3U:
374             freq = CLOCK_GetFRG1ClkFreq();
375             break;
376         case 4U:
377             freq = CLOCK_GetFroFreq() >> 1U;
378             break;
379 
380         default:
381             freq = 0U;
382             break;
383     }
384 
385     return freq;
386 }
387 
388 /*! brief  Return Frequency of UART4
389  *  return Frequency of UART4
390  */
CLOCK_GetUart4ClkFreq(void)391 uint32_t CLOCK_GetUart4ClkFreq(void)
392 {
393     uint32_t freq = 0U;
394 
395     switch (SYSCON->FCLKSEL[4])
396     {
397         case 0U:
398             freq = CLOCK_GetFroFreq();
399             break;
400         case 1U:
401             freq = CLOCK_GetMainClkFreq();
402             break;
403         case 2U:
404             freq = CLOCK_GetFRG0ClkFreq();
405             break;
406         case 3U:
407             freq = CLOCK_GetFRG1ClkFreq();
408             break;
409         case 4U:
410             freq = CLOCK_GetFroFreq() >> 1U;
411             break;
412 
413         default:
414             freq = 0U;
415             break;
416     }
417 
418     return freq;
419 }
420 
421 /*! brief	Return Frequency of selected clock
422  *  return	Frequency of selected clock
423  */
CLOCK_GetFreq(clock_name_t clockName)424 uint32_t CLOCK_GetFreq(clock_name_t clockName)
425 {
426     uint32_t freq;
427 
428     switch (clockName)
429     {
430         case kCLOCK_CoreSysClk:
431             freq = CLOCK_GetCoreSysClkFreq();
432             break;
433         case kCLOCK_MainClk:
434             freq = CLOCK_GetMainClkFreq();
435             break;
436         case kCLOCK_Fro:
437             freq = CLOCK_GetFroFreq();
438             break;
439         case kCLOCK_FroDiv:
440             freq = CLOCK_GetFroFreq() >> 1U;
441             break;
442         case kCLOCK_ExtClk:
443             freq = CLOCK_GetExtClkFreq();
444             break;
445         case kCLOCK_WdtOsc:
446             freq = CLOCK_GetWdtOscFreq();
447             break;
448         case kCLOCK_PllOut:
449             freq = CLOCK_GetSystemPLLFreq();
450             break;
451         case kCLOCK_Frg0:
452             freq = CLOCK_GetFRG0ClkFreq();
453             break;
454         case kCLOCK_Frg1:
455             freq = CLOCK_GetFRG1ClkFreq();
456             break;
457 
458         default:
459             freq = 0U;
460             break;
461     }
462 
463     return freq;
464 }
465 
466 /*! brief  Return System PLL input clock rate
467  *  return System PLL input clock rate
468  */
CLOCK_GetSystemPLLInClockRate(void)469 uint32_t CLOCK_GetSystemPLLInClockRate(void)
470 {
471     uint32_t freq = 0U;
472 
473     switch ((SYSCON->SYSPLLCLKSEL))
474     {
475         /* source from fro div clock */
476         case 0x03U:
477             freq = CLOCK_GetFroFreq() >> 1U;
478             break;
479         /* source from the fro clock */
480         case 0x00U:
481             freq = CLOCK_GetFroFreq();
482             break;
483         /* source from external clock in */
484         case 0x01U:
485             freq = CLOCK_GetExtClkFreq();
486             break;
487         /* source from watchdog oscillator */
488         case 0x02U:
489             freq = CLOCK_GetWdtOscFreq();
490             break;
491 
492         default:
493             freq = 0U;
494             break;
495     }
496 
497     return freq;
498 }
499 
findSyestemPllPsel(uint32_t outFreq)500 static uint32_t findSyestemPllPsel(uint32_t outFreq)
501 {
502     uint32_t pSel = 0U;
503 
504     if (outFreq > (SYSPLL_MIN_FCCO_FREQ_HZ >> 1U))
505     {
506         pSel = 0U;
507     }
508     else if (outFreq > (SYSPLL_MIN_FCCO_FREQ_HZ >> 2U))
509     {
510         pSel = 1U;
511     }
512     else if (outFreq > (SYSPLL_MIN_FCCO_FREQ_HZ >> 3U))
513     {
514         pSel = 2U;
515     }
516     else
517     {
518         pSel = 3U;
519     }
520 
521     return pSel;
522 }
523 
524 /*! brief  System PLL initialize.
525  *  param config System PLL configurations.
526  */
CLOCK_InitSystemPll(const clock_sys_pll_t * config)527 void CLOCK_InitSystemPll(const clock_sys_pll_t *config)
528 {
529     assert(config->targetFreq <= SYSPLL_MAX_OUTPUT_FREQ_HZ);
530 
531     uint32_t mSel = 0U, pSel = 0U, inputFreq = 0U;
532     uint32_t syspllclkseltmp;
533     /* Power off PLL during setup changes */
534     SYSCON->PDRUNCFG |= SYSCON_PDRUNCFG_SYSPLL_PD_MASK;
535 
536     /*set system pll clock source select register */
537     syspllclkseltmp = (SYSCON->SYSPLLCLKSEL & (~SYSCON_SYSPLLCLKSEL_SEL_MASK)) | (uint32_t)(config->src);
538     SYSCON->SYSPLLCLKSEL |= syspllclkseltmp;
539     /* system pll clock source update */
540     CLOCK_UpdateClkSrc((volatile uint32_t *)(&(SYSCON->SYSPLLCLKUEN)), SYSCON_SYSPLLCLKSEL_SEL_MASK);
541 
542     inputFreq = CLOCK_GetSystemPLLInClockRate();
543     assert(inputFreq != 0U);
544 
545     /* calucate the feedback divider value and post divider value*/
546     mSel = config->targetFreq / inputFreq;
547     pSel = findSyestemPllPsel(config->targetFreq);
548 
549     /* configure PSEL and MSEL */
550     SYSCON->SYSPLLCTRL = (SYSCON->SYSPLLCTRL & (~(SYSCON_SYSPLLCTRL_MSEL_MASK | SYSCON_SYSPLLCTRL_PSEL_MASK))) |
551                          SYSCON_SYSPLLCTRL_MSEL(mSel == 0U ? 0U : (mSel - 1U)) | SYSCON_SYSPLLCTRL_PSEL(pSel);
552 
553     /* Power up PLL after setup changes */
554     SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_SYSPLL_PD_MASK;
555 
556     /* wait pll lock */
557     while ((SYSCON->SYSPLLSTAT & SYSCON_SYSPLLSTAT_LOCK_MASK) == 0U)
558     {
559     }
560 }
561 
562 /*! brief  Init external CLK IN, select the CLKIN as the external clock source.
563  * param clkInFreq external clock in frequency.
564  */
CLOCK_InitExtClkin(uint32_t clkInFreq)565 void CLOCK_InitExtClkin(uint32_t clkInFreq)
566 {
567     /* remove the pull up and pull down resistors in the IOCON */
568     IOCON->PIO[IOCON_INDEX_PIO0_1] &= ~IOCON_PIO_MODE_MASK;
569     /* enable the 1 bit functions for CLKIN */
570     SWM0->PINENABLE0 &= ~SWM_PINENABLE0_CLKIN_MASK;
571     /* enable the external clk in */
572     SYSCON->EXTCLKSEL |= SYSCON_EXTCLKSEL_SEL_MASK;
573     /* record the external clock rate */
574     g_Ext_Clk_Freq = clkInFreq;
575 }
576 
577 /*! brief  XTALIN init function
578  *  system oscillator is bypassed, sys_osc_clk is fed driectly from the XTALIN.
579  *  param xtalInFreq XTALIN frequency value
580  *  return Frequency of PLL
581  */
CLOCK_InitXtalin(uint32_t xtalInFreq)582 void CLOCK_InitXtalin(uint32_t xtalInFreq)
583 {
584     /* remove the pull up and pull down resistors in the IOCON */
585     IOCON->PIO[IOCON_INDEX_PIO0_8] &= ~IOCON_PIO_MODE_MASK;
586     /* enable the 1 bit functions for XTALIN and XTALOUT */
587     SWM0->PINENABLE0 &= ~SWM_PINENABLE0_XTALIN_MASK;
588 
589     /* system osc configure */
590     SYSCON->SYSOSCCTRL |= SYSCON_SYSOSCCTRL_BYPASS_MASK;
591     /* external clock select */
592     SYSCON->EXTCLKSEL &= ~SYSCON_EXTCLKSEL_SEL_MASK;
593     /* enable system osc power first */
594     SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_SYSOSC_PD_MASK;
595 
596     /* software delay 500USs */
597     SDK_DelayAtLeastUs(500U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
598 
599     /* record the external clock rate */
600     g_Ext_Clk_Freq = xtalInFreq;
601 }
602 
603 /*! brief	Init SYS OSC
604  * param oscFreq oscillator frequency value.
605  */
CLOCK_InitSysOsc(uint32_t oscFreq)606 void CLOCK_InitSysOsc(uint32_t oscFreq)
607 {
608     uint32_t sysoscctrltmp;
609     /* remove the pull up and pull down resistors in the IOCON */
610     IOCON->PIO[IOCON_INDEX_PIO0_9] &= ~IOCON_PIO_MODE_MASK;
611     IOCON->PIO[IOCON_INDEX_PIO0_8] &= ~IOCON_PIO_MODE_MASK;
612     /* enable the 1 bit functions for XTALIN and XTALOUT */
613     SWM0->PINENABLE0 &= ~(SWM_PINENABLE0_XTALIN_MASK | SWM_PINENABLE0_XTALOUT_MASK);
614 
615     /* system osc configure */
616     sysoscctrltmp = (SYSCON->SYSOSCCTRL & (~(SYSCON_SYSOSCCTRL_BYPASS_MASK | SYSCON_SYSOSCCTRL_FREQRANGE_MASK))) |
617                     (oscFreq > SYSOSC_BOUNDARY_FREQ_HZ ? SYSCON_SYSOSCCTRL_FREQRANGE_MASK : 0U);
618     SYSCON->SYSOSCCTRL |= sysoscctrltmp;
619     /* external clock select */
620     SYSCON->EXTCLKSEL &= ~SYSCON_EXTCLKSEL_SEL_MASK;
621 
622     /* enable system osc power first */
623     SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_SYSOSC_PD_MASK;
624 
625     /* software delay 500USs */
626     SDK_DelayAtLeastUs(500U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
627 
628     /* record the external clock rate */
629     g_Ext_Clk_Freq = oscFreq;
630 }
631 
632 /*! brief  Init watch dog OSC
633  * Any setting of the FREQSEL bits will yield a Fclkana value within 40% of the
634  * listed frequency value. The watchdog oscillator is the clock source with the lowest power
635  * consumption. If accurate timing is required, use the FRO or system oscillator.
636  * The frequency of the watchdog oscillator is undefined after reset. The watchdog
637  * oscillator frequency must be programmed by writing to the WDTOSCCTRL register before
638  * using the watchdog oscillator.
639  * Watchdog osc output frequency = wdtOscFreq / wdtOscDiv, should in range 9.3KHZ to 2.3MHZ.
640  * param wdtOscFreq watch dog analog part output frequency, reference _wdt_analog_output_freq.
641  * param wdtOscDiv watch dog analog part output frequency divider, shoule be a value >= 2U and multiple of 2
642  */
CLOCK_InitWdtOsc(clock_wdt_analog_freq_t wdtOscFreq,uint32_t wdtOscDiv)643 void CLOCK_InitWdtOsc(clock_wdt_analog_freq_t wdtOscFreq, uint32_t wdtOscDiv)
644 {
645     assert(wdtOscDiv >= 2U);
646 
647     uint32_t wdtOscCtrl = SYSCON->WDTOSCCTRL;
648 
649     wdtOscCtrl &= ~(SYSCON_WDTOSCCTRL_DIVSEL_MASK | SYSCON_WDTOSCCTRL_FREQSEL_MASK);
650 
651     wdtOscCtrl |= SYSCON_WDTOSCCTRL_DIVSEL((wdtOscDiv >> 1U) - 1U) |
652                   SYSCON_WDTOSCCTRL_FREQSEL(CLK_WDT_OSC_GET_REG((uint32_t)wdtOscFreq));
653 
654     SYSCON->WDTOSCCTRL = wdtOscCtrl;
655 
656     /* power up watchdog oscillator */
657     SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_WDTOSC_PD_MASK;
658     /* update watch dog oscillator value */
659     g_Wdt_Osc_Freq = CLK_WDT_OSC_GET_FREQ(wdtOscFreq) / wdtOscDiv;
660 }
661 
662 /*! brief  Set main clock reference source.
663  * param src, reference clock_main_clk_src_t to set the main clock source.
664  */
CLOCK_SetMainClkSrc(clock_main_clk_src_t src)665 void CLOCK_SetMainClkSrc(clock_main_clk_src_t src)
666 {
667     uint32_t mainMux = CLK_MAIN_CLK_MUX_GET_MUX(src), mainPreMux = CLK_MAIN_CLK_MUX_GET_PRE_MUX(src);
668 
669     if (((SYSCON->MAINCLKSEL & SYSCON_MAINCLKSEL_SEL_MASK) != mainPreMux) && (mainMux == 0U))
670     {
671         SYSCON->MAINCLKSEL = (SYSCON->MAINCLKSEL & (~SYSCON_MAINCLKSEL_SEL_MASK)) | SYSCON_MAINCLKSEL_SEL(mainPreMux);
672         CLOCK_UpdateClkSrc((volatile uint32_t *)(&(SYSCON->MAINCLKUEN)), SYSCON_MAINCLKUEN_ENA_MASK);
673     }
674 
675     if ((SYSCON->MAINCLKPLLSEL & SYSCON_MAINCLKPLLSEL_SEL_MASK) != mainMux)
676     {
677         SYSCON->MAINCLKPLLSEL =
678             (SYSCON->MAINCLKPLLSEL & (~SYSCON_MAINCLKPLLSEL_SEL_MASK)) | SYSCON_MAINCLKPLLSEL_SEL(mainMux);
679         CLOCK_UpdateClkSrc((volatile uint32_t *)(&(SYSCON->MAINCLKPLLUEN)), SYSCON_MAINCLKPLLUEN_ENA_MASK);
680     }
681 }
682 
683 /*! brief Set FRO clock source
684  * param src, please reference _clock_fro_src definition.
685  *
686  */
CLOCK_SetFroOutClkSrc(clock_fro_src_t src)687 void CLOCK_SetFroOutClkSrc(clock_fro_src_t src)
688 {
689     if ((uint32_t)src != (SYSCON->FROOSCCTRL & SYSCON_FROOSCCTRL_FRO_DIRECT_MASK))
690     {
691         SYSCON->FROOSCCTRL = (SYSCON->FROOSCCTRL & (~SYSCON_FROOSCCTRL_FRO_DIRECT_MASK)) | (uint32_t)src;
692         /* Update clock source */
693         CLOCK_UpdateClkSrc((volatile uint32_t *)(&(SYSCON->FRODIRECTCLKUEN)), SYSCON_FRODIRECTCLKUEN_ENA_MASK);
694     }
695 }
696 
697 /*! brief  Set the flash wait states for the input freuqency.
698  * param   iFreq   : Input frequency
699  */
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)700 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)
701 {
702     uint32_t num_wait_states;
703     if (iFreq <= 24000000UL)
704     {
705         /* [0 - 24 MHz] */
706         num_wait_states = 0UL;
707     }
708     else
709     {
710         /* Above 24 MHz */
711         num_wait_states = 1UL;
712     }
713 
714     FLASH_CTRL->FLASHCFG =
715         ((FLASH_CTRL->FLASHCFG & ~FLASH_CTRL_FLASHCFG_FLASHTIM_MASK) | FLASH_CTRL_FLASHCFG_FLASHTIM(num_wait_states));
716 }
717