1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright (c) 2016 - 2017 , NXP
4  * All rights reserved.
5  *
6  *
7  * SPDX-License-Identifier: BSD-3-Clause
8  */
9 
10 #include "fsl_clock.h"
11 
12 /*******************************************************************************
13  * Definitions
14  ******************************************************************************/
15 
16 #define SCG_SIRC_LOW_RANGE_FREQ 2000000U  /* Slow IRC low range clock frequency. */
17 #define SCG_SIRC_HIGH_RANGE_FREQ 8000000U /* Slow IRC high range clock frequency.   */
18 
19 #define SCG_FIRC_FREQ0 48000000U /* Fast IRC trimed clock frequency(48MHz). */
20 #define SCG_FIRC_FREQ1 52000000U /* Fast IRC trimed clock frequency(52MHz). */
21 #define SCG_FIRC_FREQ2 56000000U /* Fast IRC trimed clock frequency(56MHz). */
22 #define SCG_FIRC_FREQ3 60000000U /* Fast IRC trimed clock frequency(60MHz). */
23 
24 #define SCG_LPFLL_FREQ0 48000000U  /* LPFLL trimed clock frequency(48MHz). */
25 #define SCG_LPFLL_FREQ1 72000000U  /* LPFLL trimed clock frequency(72MHz). */
26 #define SCG_LPFLL_FREQ2 96000000U  /* LPFLL trimed clock frequency(96MHz). */
27 #define SCG_LPFLL_FREQ3 120000000U /* LPFLL trimed clock frequency(120MHz). */
28 
29 #define SCG_CSR_SCS_VAL ((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT)
30 #define SCG_SOSCDIV_SOSCDIV1_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV1_MASK) >> SCG_SOSCDIV_SOSCDIV1_SHIFT)
31 #define SCG_SOSCDIV_SOSCDIV2_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV2_MASK) >> SCG_SOSCDIV_SOSCDIV2_SHIFT)
32 #define SCG_SOSCDIV_SOSCDIV3_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV3_MASK) >> SCG_SOSCDIV_SOSCDIV3_SHIFT)
33 #define SCG_SIRCDIV_SIRCDIV1_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV1_MASK) >> SCG_SIRCDIV_SIRCDIV1_SHIFT)
34 #define SCG_SIRCDIV_SIRCDIV2_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV2_MASK) >> SCG_SIRCDIV_SIRCDIV2_SHIFT)
35 #define SCG_SIRCDIV_SIRCDIV3_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV3_MASK) >> SCG_SIRCDIV_SIRCDIV3_SHIFT)
36 #define SCG_FIRCDIV_FIRCDIV1_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV1_MASK) >> SCG_FIRCDIV_FIRCDIV1_SHIFT)
37 #define SCG_FIRCDIV_FIRCDIV2_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV2_MASK) >> SCG_FIRCDIV_FIRCDIV2_SHIFT)
38 #define SCG_FIRCDIV_FIRCDIV3_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV3_MASK) >> SCG_FIRCDIV_FIRCDIV3_SHIFT)
39 
40 #define SCG_LPFLLDIV_LPFLLDIV1_VAL ((SCG->LPFLLDIV & SCG_LPFLLDIV_LPFLLDIV1_MASK) >> SCG_LPFLLDIV_LPFLLDIV1_SHIFT)
41 #define SCG_LPFLLDIV_LPFLLDIV2_VAL ((SCG->LPFLLDIV & SCG_LPFLLDIV_LPFLLDIV2_MASK) >> SCG_LPFLLDIV_LPFLLDIV2_SHIFT)
42 #define SCG_LPFLLDIV_LPFLLDIV3_VAL ((SCG->LPFLLDIV & SCG_LPFLLDIV_LPFLLDIV3_MASK) >> SCG_LPFLLDIV_LPFLLDIV3_SHIFT)
43 
44 #define SCG_SIRCCFG_RANGE_VAL ((SCG->SIRCCFG & SCG_SIRCCFG_RANGE_MASK) >> SCG_SIRCCFG_RANGE_SHIFT)
45 #define SCG_FIRCCFG_RANGE_VAL ((SCG->FIRCCFG & SCG_FIRCCFG_RANGE_MASK) >> SCG_FIRCCFG_RANGE_SHIFT)
46 
47 #define SCG_LPFLLCFG_FSEL_VAL ((SCG->LPFLLCFG & SCG_LPFLLCFG_FSEL_MASK) >> SCG_LPFLLCFG_FSEL_SHIFT)
48 
49 /* Get the value of each field in PCC register. */
50 #define PCC_PCS_VAL(reg) ((reg & PCC_CLKCFG_PCS_MASK) >> PCC_CLKCFG_PCS_SHIFT)
51 #define PCC_FRAC_VAL(reg) ((reg & PCC_CLKCFG_FRAC_MASK) >> PCC_CLKCFG_FRAC_SHIFT)
52 #define PCC_PCD_VAL(reg) ((reg & PCC_CLKCFG_PCD_MASK) >> PCC_CLKCFG_PCD_SHIFT)
53 
54 /*******************************************************************************
55  * Variables
56  ******************************************************************************/
57 
58 /* External XTAL0 (OSC0) clock frequency. */
59 uint32_t g_xtal0Freq;
60 /* External XTAL32K clock frequency. */
61 uint32_t g_xtal32Freq;
62 
63 /*******************************************************************************
64  * Prototypes
65  ******************************************************************************/
66 
67 /*******************************************************************************
68  * Code
69  ******************************************************************************/
70 
CLOCK_GetOsc32kClkFreq(void)71 uint32_t CLOCK_GetOsc32kClkFreq(void)
72 {
73     assert(g_xtal32Freq);
74     return g_xtal32Freq;
75 }
76 
CLOCK_GetFlashClkFreq(void)77 uint32_t CLOCK_GetFlashClkFreq(void)
78 {
79     return CLOCK_GetSysClkFreq(kSCG_SysClkSlow);
80 }
81 
CLOCK_GetBusClkFreq(void)82 uint32_t CLOCK_GetBusClkFreq(void)
83 {
84     return CLOCK_GetSysClkFreq(kSCG_SysClkSlow);
85 }
86 
CLOCK_GetPlatClkFreq(void)87 uint32_t CLOCK_GetPlatClkFreq(void)
88 {
89     return CLOCK_GetSysClkFreq(kSCG_SysClkCore);
90 }
91 
CLOCK_GetCoreSysClkFreq(void)92 uint32_t CLOCK_GetCoreSysClkFreq(void)
93 {
94     return CLOCK_GetSysClkFreq(kSCG_SysClkCore);
95 }
96 
CLOCK_GetExtClkFreq(void)97 uint32_t CLOCK_GetExtClkFreq(void)
98 {
99     return CLOCK_GetSysClkFreq(kSCG_SysClkExt);
100 }
101 
CLOCK_GetFreq(clock_name_t clockName)102 uint32_t CLOCK_GetFreq(clock_name_t clockName)
103 {
104     uint32_t freq;
105 
106     switch (clockName)
107     {
108         /* System layer clock. */
109         case kCLOCK_CoreSysClk:
110         case kCLOCK_PlatClk:
111             freq = CLOCK_GetSysClkFreq(kSCG_SysClkCore);
112             break;
113         case kCLOCK_BusClk:
114             freq = CLOCK_GetSysClkFreq(kSCG_SysClkBus);
115             break;
116         case kCLOCK_FlashClk:
117             freq = CLOCK_GetSysClkFreq(kSCG_SysClkSlow);
118             break;
119         case kCLOCK_ExtClk:
120             freq = CLOCK_GetSysClkFreq(kSCG_SysClkExt);
121             break;
122         /* Original clock source. */
123         case kCLOCK_ScgSysOscClk:
124             freq = CLOCK_GetSysOscFreq();
125             break;
126         case kCLOCK_ScgSircClk:
127             freq = CLOCK_GetSircFreq();
128             break;
129         case kCLOCK_ScgFircClk:
130             freq = CLOCK_GetFircFreq();
131             break;
132         case kCLOCK_ScgLpFllClk:
133             freq = CLOCK_GetLpFllFreq();
134             break;
135 
136         /* SOSC div clock. */
137         case kCLOCK_ScgSysOscAsyncDiv1Clk:
138             freq = CLOCK_GetSysOscAsyncFreq(kSCG_AsyncDiv1Clk);
139             break;
140         case kCLOCK_ScgSysOscAsyncDiv2Clk:
141             freq = CLOCK_GetSysOscAsyncFreq(kSCG_AsyncDiv2Clk);
142             break;
143         case kCLOCK_ScgSysOscAsyncDiv3Clk:
144             freq = CLOCK_GetSysOscAsyncFreq(kSCG_AsyncDiv3Clk);
145             break;
146 
147         /* SIRC div clock. */
148         case kCLOCK_ScgSircAsyncDiv1Clk:
149             freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv1Clk);
150             break;
151         case kCLOCK_ScgSircAsyncDiv2Clk:
152             freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv2Clk);
153             break;
154         case kCLOCK_ScgSircAsyncDiv3Clk:
155             freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv3Clk);
156             break;
157 
158         /* FIRC div clock. */
159         case kCLOCK_ScgFircAsyncDiv1Clk:
160             freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv1Clk);
161             break;
162         case kCLOCK_ScgFircAsyncDiv2Clk:
163             freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv2Clk);
164             break;
165         case kCLOCK_ScgFircAsyncDiv3Clk:
166             freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv3Clk);
167             break;
168 
169         /* LPFLL div clock. */
170         case kCLOCK_ScgSysLpFllAsyncDiv1Clk:
171             freq = CLOCK_GetLpFllAsyncFreq(kSCG_AsyncDiv1Clk);
172             break;
173         case kCLOCK_ScgSysLpFllAsyncDiv2Clk:
174             freq = CLOCK_GetLpFllAsyncFreq(kSCG_AsyncDiv2Clk);
175             break;
176         case kCLOCK_ScgSysLpFllAsyncDiv3Clk:
177             freq = CLOCK_GetLpFllAsyncFreq(kSCG_AsyncDiv3Clk);
178             break;
179 
180         /* Other clocks. */
181         case kCLOCK_LpoClk:
182             freq = CLOCK_GetLpoClkFreq();
183             break;
184         case kCLOCK_Osc32kClk:
185             freq = CLOCK_GetOsc32kClkFreq();
186             break;
187         default:
188             freq = 0U;
189             break;
190     }
191     return freq;
192 }
193 
CLOCK_GetIpFreq(clock_ip_name_t name)194 uint32_t CLOCK_GetIpFreq(clock_ip_name_t name)
195 {
196     uint32_t reg = (*(volatile uint32_t *)name);
197 
198     scg_async_clk_t asycClk;
199     uint32_t freq;
200 
201     assert(reg & PCC_CLKCFG_PR_MASK);
202 
203     switch (name)
204     {
205         case kCLOCK_Lpit0:
206         case kCLOCK_Lpit1:
207             asycClk = kSCG_AsyncDiv3Clk;
208             break;
209         case kCLOCK_Sdhc0:
210         case kCLOCK_Usb0:
211             asycClk = kSCG_AsyncDiv1Clk;
212             break;
213         default:
214             asycClk = kSCG_AsyncDiv2Clk;
215             break;
216     }
217 
218     switch (PCC_PCS_VAL(reg))
219     {
220         case kCLOCK_IpSrcSysOscAsync:
221             freq = CLOCK_GetSysOscAsyncFreq(asycClk);
222             break;
223         case kCLOCK_IpSrcSircAsync:
224             freq = CLOCK_GetSircAsyncFreq(asycClk);
225             break;
226         case kCLOCK_IpSrcFircAsync:
227             freq = CLOCK_GetFircAsyncFreq(asycClk);
228             break;
229         case kCLOCK_IpSrcLpFllAsync:
230             freq = CLOCK_GetLpFllAsyncFreq(asycClk);
231             break;
232         default: /* kCLOCK_IpSrcNoneOrExt. */
233             freq = 0U;
234             break;
235     }
236 
237     if (0U != (reg & (PCC_CLKCFG_PCD_MASK | PCC_CLKCFG_FRAC_MASK)))
238     {
239         return freq * (PCC_FRAC_VAL(reg) + 1U) / (PCC_PCD_VAL(reg) + 1U);
240     }
241     else
242     {
243         return freq;
244     }
245 }
246 
CLOCK_EnableUsbfs0Clock(clock_usb_src_t src,uint32_t freq)247 bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq)
248 {
249     bool ret = true;
250 
251     CLOCK_SetIpSrc(kCLOCK_Usb0, kCLOCK_IpSrcFircAsync);
252 
253 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
254     /* Enable clock gate. */
255     CLOCK_EnableClock(kCLOCK_Usb0);
256 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
257 
258     USBVREG->CTRL |= USBVREG_CTRL_EN_MASK;
259     USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
260 
261     if (kCLOCK_UsbSrcIrc48M == src)
262     {
263         USB0->CLK_RECOVER_IRC_EN = 0x03U;
264         USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK;
265         USB0->CLK_RECOVER_INT_EN = 0x00U;
266     }
267     return ret;
268 }
269 
CLOCK_GetSysClkFreq(scg_sys_clk_t type)270 uint32_t CLOCK_GetSysClkFreq(scg_sys_clk_t type)
271 {
272     uint32_t freq;
273 
274     scg_sys_clk_config_t sysClkConfig;
275 
276     CLOCK_GetCurSysClkConfig(&sysClkConfig); /* Get the main clock for SoC platform. */
277 
278     switch (sysClkConfig.src)
279     {
280         case kSCG_SysClkSrcSysOsc:
281             freq = CLOCK_GetSysOscFreq();
282             break;
283         case kSCG_SysClkSrcSirc:
284             freq = CLOCK_GetSircFreq();
285             break;
286         case kSCG_SysClkSrcFirc:
287             freq = CLOCK_GetFircFreq();
288             break;
289         case kSCG_SysClkSrcRosc:
290             freq = CLOCK_GetRtcOscFreq();
291             break;
292         case kSCG_SysClkSrcLpFll:
293             freq = CLOCK_GetLpFllFreq();
294             break;
295         default:
296             freq = 0U;
297             break;
298     }
299 
300     freq /= (sysClkConfig.divCore + 1U); /* divided by the DIVCORE firstly. */
301 
302     if (kSCG_SysClkSlow == type)
303     {
304         freq /= (sysClkConfig.divSlow + 1U);
305     }
306     else if (kSCG_SysClkBus == type)
307     {
308         freq /= (sysClkConfig.divBus + 1U);
309     }
310     else if (kSCG_SysClkExt == type)
311     {
312         freq /= (sysClkConfig.divExt + 1U);
313     }
314     else
315     {
316     }
317 
318     return freq;
319 }
320 
CLOCK_InitSysOsc(const scg_sosc_config_t * config)321 status_t CLOCK_InitSysOsc(const scg_sosc_config_t *config)
322 {
323     assert(config);
324     status_t status;
325     uint8_t tmp8;
326 
327     /* De-init the SOSC first. */
328     status = CLOCK_DeinitSysOsc();
329 
330     if (kStatus_Success != status)
331     {
332         return status;
333     }
334 
335     /* Now start to set up OSC clock. */
336     /* Step 1. Setup dividers. */
337     SCG->SOSCDIV =
338         SCG_SOSCDIV_SOSCDIV1(config->div1) | SCG_SOSCDIV_SOSCDIV2(config->div2) | SCG_SOSCDIV_SOSCDIV3(config->div3);
339 
340     /* Step 2. Set OSC configuration. */
341 
342     /* Step 3. Enable clock. */
343     /* SCG->SOSCCSR = SCG_SOSCCSR_SOSCEN_MASK | (config->enableMode); */
344     tmp8 = config->enableMode;
345     tmp8 |= SCG_SOSCCSR_SOSCEN_MASK;
346     SCG->SOSCCSR = tmp8;
347 
348     /* Step 4. Wait for OSC clock to be valid. */
349     while (!(SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK))
350     {
351     }
352 
353     /* Step 5. Enabe monitor. */
354     SCG->SOSCCSR |= (uint32_t)config->monitorMode;
355 
356     return kStatus_Success;
357 }
358 
CLOCK_DeinitSysOsc(void)359 status_t CLOCK_DeinitSysOsc(void)
360 {
361     uint32_t reg = SCG->SOSCCSR;
362 
363     /* If clock is used by system, return error. */
364     if (reg & SCG_SOSCCSR_SOSCSEL_MASK)
365     {
366         return kStatus_SCG_Busy;
367     }
368 
369     /* If configure register is locked, return error. */
370     if (reg & SCG_SOSCCSR_LK_MASK)
371     {
372         return kStatus_ReadOnly;
373     }
374 
375     SCG->SOSCCSR = SCG_SOSCCSR_SOSCERR_MASK;
376 
377     return kStatus_Success;
378 }
379 
CLOCK_GetSysOscFreq(void)380 uint32_t CLOCK_GetSysOscFreq(void)
381 {
382     if (SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) /* System OSC clock is valid. */
383     {
384         /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
385         assert(g_xtal0Freq);
386         return g_xtal0Freq;
387     }
388     else
389     {
390         return 0U;
391     }
392 }
393 
CLOCK_GetSysOscAsyncFreq(scg_async_clk_t type)394 uint32_t CLOCK_GetSysOscAsyncFreq(scg_async_clk_t type)
395 {
396     uint32_t oscFreq = CLOCK_GetSysOscFreq();
397     uint32_t divider = 0U;
398 
399     /* Get divider. */
400     if (oscFreq)
401     {
402         switch (type)
403         {
404             case kSCG_AsyncDiv3Clk: /* SOSCDIV3_CLK. */
405                 divider = SCG_SOSCDIV_SOSCDIV3_VAL;
406                 break;
407             case kSCG_AsyncDiv2Clk: /* SOSCDIV2_CLK. */
408                 divider = SCG_SOSCDIV_SOSCDIV2_VAL;
409                 break;
410             case kSCG_AsyncDiv1Clk: /* SOSCDIV1_CLK. */
411                 divider = SCG_SOSCDIV_SOSCDIV1_VAL;
412                 break;
413             default:
414                 break;
415         }
416     }
417     if (divider)
418     {
419         return oscFreq >> (divider - 1U);
420     }
421     else /* Output disabled. */
422     {
423         return 0U;
424     }
425 }
426 
CLOCK_InitSirc(const scg_sirc_config_t * config)427 status_t CLOCK_InitSirc(const scg_sirc_config_t *config)
428 {
429     assert(config);
430 
431     status_t status;
432 
433     /* De-init the SIRC first. */
434     status = CLOCK_DeinitSirc();
435 
436     if (kStatus_Success != status)
437     {
438         return status;
439     }
440 
441     /* Now start to set up SIRC clock. */
442     /* Step 1. Setup dividers. */
443     SCG->SIRCDIV =
444         SCG_SIRCDIV_SIRCDIV1(config->div1) | SCG_SIRCDIV_SIRCDIV2(config->div2) | SCG_SIRCDIV_SIRCDIV3(config->div3);
445 
446     /* Step 2. Set SIRC configuration. */
447     SCG->SIRCCFG = SCG_SIRCCFG_RANGE(config->range);
448 
449     /* Step 3. Enable clock. */
450     SCG->SIRCCSR = SCG_SIRCCSR_SIRCEN_MASK | config->enableMode;
451 
452     /* Step 4. Wait for SIRC clock to be valid. */
453     while (!(SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK))
454     {
455     }
456 
457     return kStatus_Success;
458 }
459 
CLOCK_DeinitSirc(void)460 status_t CLOCK_DeinitSirc(void)
461 {
462     uint32_t reg = SCG->SIRCCSR;
463 
464     /* If clock is used by system, return error. */
465     if (reg & SCG_SIRCCSR_SIRCSEL_MASK)
466     {
467         return kStatus_SCG_Busy;
468     }
469 
470     /* If configure register is locked, return error. */
471     if (reg & SCG_SIRCCSR_LK_MASK)
472     {
473         return kStatus_ReadOnly;
474     }
475 
476     SCG->SIRCCSR = 0U;
477 
478     return kStatus_Success;
479 }
480 
CLOCK_GetSircFreq(void)481 uint32_t CLOCK_GetSircFreq(void)
482 {
483     static const uint32_t sircFreq[] = {SCG_SIRC_LOW_RANGE_FREQ, SCG_SIRC_HIGH_RANGE_FREQ};
484 
485     if (SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK) /* SIRC is valid. */
486     {
487         return sircFreq[SCG_SIRCCFG_RANGE_VAL];
488     }
489     else
490     {
491         return 0U;
492     }
493 }
494 
CLOCK_GetSircAsyncFreq(scg_async_clk_t type)495 uint32_t CLOCK_GetSircAsyncFreq(scg_async_clk_t type)
496 {
497     uint32_t sircFreq = CLOCK_GetSircFreq();
498     uint32_t divider = 0U;
499 
500     /* Get divider. */
501     if (sircFreq)
502     {
503         switch (type)
504         {
505             case kSCG_AsyncDiv3Clk: /* SIRCDIV3_CLK. */
506                 divider = SCG_SIRCDIV_SIRCDIV3_VAL;
507                 break;
508             case kSCG_AsyncDiv2Clk: /* SIRCDIV2_CLK. */
509                 divider = SCG_SIRCDIV_SIRCDIV2_VAL;
510                 break;
511             case kSCG_AsyncDiv1Clk: /* SIRCDIV2_CLK. */
512                 divider = SCG_SIRCDIV_SIRCDIV1_VAL;
513                 break;
514             default:
515                 break;
516         }
517     }
518     if (divider)
519     {
520         return sircFreq >> (divider - 1U);
521     }
522     else /* Output disabled. */
523     {
524         return 0U;
525     }
526 }
527 
CLOCK_InitFirc(const scg_firc_config_t * config)528 status_t CLOCK_InitFirc(const scg_firc_config_t *config)
529 {
530     assert(config);
531 
532     status_t status;
533 
534     /* De-init the FIRC first. */
535     status = CLOCK_DeinitFirc();
536 
537     if (kStatus_Success != status)
538     {
539         return status;
540     }
541 
542     /* Now start to set up FIRC clock. */
543     /* Step 1. Setup dividers. */
544     SCG->FIRCDIV =
545         SCG_FIRCDIV_FIRCDIV1(config->div1) | SCG_FIRCDIV_FIRCDIV2(config->div2) | SCG_FIRCDIV_FIRCDIV3(config->div3);
546 
547     /* Step 2. Set FIRC configuration. */
548     SCG->FIRCCFG = SCG_FIRCCFG_RANGE(config->range);
549 
550     /* Step 3. Set trimming configuration. */
551     if (config->trimConfig)
552     {
553         SCG->FIRCTCFG =
554             SCG_FIRCTCFG_TRIMDIV(config->trimConfig->trimDiv) | SCG_FIRCTCFG_TRIMSRC(config->trimConfig->trimSrc);
555 
556         /* TODO: Write FIRCSTAT cause bus error: TKT266932. */
557         if (kSCG_FircTrimNonUpdate == config->trimConfig->trimMode)
558         {
559             SCG->FIRCSTAT = SCG_FIRCSTAT_TRIMCOAR(config->trimConfig->trimCoar) |
560                             SCG_FIRCSTAT_TRIMFINE(config->trimConfig->trimFine);
561         }
562 
563         /* trim mode. */
564         SCG->FIRCCSR = config->trimConfig->trimMode;
565 
566         if (SCG->FIRCCSR & SCG_FIRCCSR_FIRCERR_MASK)
567         {
568             return kStatus_Fail;
569         }
570     }
571 
572     /* Step 4. Enable clock. */
573     SCG->FIRCCSR |= (SCG_FIRCCSR_FIRCEN_MASK | SCG_FIRCCSR_FIRCTREN_MASK | config->enableMode);
574 
575     /* Step 5. Wait for FIRC clock to be valid. */
576     while (!(SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK))
577     {
578     }
579 
580     return kStatus_Success;
581 }
582 
CLOCK_DeinitFirc(void)583 status_t CLOCK_DeinitFirc(void)
584 {
585     uint32_t reg = SCG->FIRCCSR;
586 
587     /* If clock is used by system, return error. */
588     if (reg & SCG_FIRCCSR_FIRCSEL_MASK)
589     {
590         return kStatus_SCG_Busy;
591     }
592 
593     /* If configure register is locked, return error. */
594     if (reg & SCG_FIRCCSR_LK_MASK)
595     {
596         return kStatus_ReadOnly;
597     }
598 
599     SCG->FIRCCSR = SCG_FIRCCSR_FIRCERR_MASK;
600 
601     return kStatus_Success;
602 }
603 
CLOCK_GetFircFreq(void)604 uint32_t CLOCK_GetFircFreq(void)
605 {
606     static const uint32_t fircFreq[] = {
607         SCG_FIRC_FREQ0, SCG_FIRC_FREQ1, SCG_FIRC_FREQ2, SCG_FIRC_FREQ3,
608     };
609 
610     if (SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) /* FIRC is valid. */
611     {
612         return fircFreq[SCG_FIRCCFG_RANGE_VAL];
613     }
614     else
615     {
616         return 0U;
617     }
618 }
619 
CLOCK_GetFircAsyncFreq(scg_async_clk_t type)620 uint32_t CLOCK_GetFircAsyncFreq(scg_async_clk_t type)
621 {
622     uint32_t fircFreq = CLOCK_GetFircFreq();
623     uint32_t divider = 0U;
624 
625     /* Get divider. */
626     if (fircFreq)
627     {
628         switch (type)
629         {
630             case kSCG_AsyncDiv3Clk: /* FIRCDIV3_CLK. */
631                 divider = SCG_FIRCDIV_FIRCDIV3_VAL;
632                 break;
633             case kSCG_AsyncDiv2Clk: /* FIRCDIV2_CLK. */
634                 divider = SCG_FIRCDIV_FIRCDIV2_VAL;
635                 break;
636             case kSCG_AsyncDiv1Clk: /* FIRCDIV1_CLK. */
637                 divider = SCG_FIRCDIV_FIRCDIV1_VAL;
638                 break;
639             default:
640                 break;
641         }
642     }
643     if (divider)
644     {
645         return fircFreq >> (divider - 1U);
646     }
647     else /* Output disabled. */
648     {
649         return 0U;
650     }
651 }
652 
CLOCK_GetRtcOscFreq(void)653 uint32_t CLOCK_GetRtcOscFreq(void)
654 {
655     if (SCG->ROSCCSR & SCG_ROSCCSR_ROSCVLD_MASK) /* RTC OSC clock is valid. */
656     {
657         /* Please call CLOCK_SetXtal32Freq base on board setting before using RTC OSC clock. */
658         assert(g_xtal32Freq);
659         return g_xtal32Freq;
660     }
661     else
662     {
663         return 0U;
664     }
665 }
666 
CLOCK_InitLpFll(const scg_lpfll_config_t * config)667 status_t CLOCK_InitLpFll(const scg_lpfll_config_t *config)
668 {
669     assert(config);
670 
671     status_t status;
672 
673     /* De-init the LPFLL first. */
674     status = CLOCK_DeinitLpFll();
675 
676     if (kStatus_Success != status)
677     {
678         return status;
679     }
680 
681     /* Now start to set up LPFLL clock. */
682     /* Step 1. Setup dividers. */
683     SCG->LPFLLDIV = SCG_LPFLLDIV_LPFLLDIV1(config->div1) | SCG_LPFLLDIV_LPFLLDIV2(config->div2) |
684                     SCG_LPFLLDIV_LPFLLDIV3(config->div3);
685 
686     /* Step 2. Set LPFLL configuration. */
687     SCG->LPFLLCFG = SCG_LPFLLCFG_FSEL(config->range);
688 
689     /* Step 3. Set trimming configuration. */
690     if (config->trimConfig)
691     {
692         SCG->LPFLLTCFG = SCG_LPFLLTCFG_TRIMDIV(config->trimConfig->trimDiv) |
693                          SCG_LPFLLTCFG_TRIMSRC(config->trimConfig->trimSrc) |
694                          SCG_LPFLLTCFG_LOCKW2LSB(config->trimConfig->lockMode);
695 
696         if (kSCG_LpFllTrimNonUpdate == config->trimConfig->trimMode)
697         {
698             SCG->LPFLLSTAT = config->trimConfig->trimValue;
699         }
700 
701         /* Trim mode. */
702         SCG->LPFLLCSR = config->trimConfig->trimMode;
703 
704         if (SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLERR_MASK)
705         {
706             return kStatus_Fail;
707         }
708     }
709 
710     /* Step 4. Enable clock. */
711     SCG->LPFLLCSR |= (SCG_LPFLLCSR_LPFLLEN_MASK | config->enableMode);
712 
713     /* Step 5. Wait for LPFLL clock to be valid. */
714     while (!(SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLVLD_MASK))
715     {
716     }
717 
718     /* Step 6. Wait for LPFLL trim lock. */
719     if ((config->trimConfig) && (kSCG_LpFllTrimUpdate == config->trimConfig->trimMode))
720     {
721         while (!(SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLTRMLOCK_MASK))
722         {
723         }
724     }
725 
726     return kStatus_Success;
727 }
728 
CLOCK_DeinitLpFll(void)729 status_t CLOCK_DeinitLpFll(void)
730 {
731     uint32_t reg = SCG->LPFLLCSR;
732 
733     /* If clock is used by system, return error. */
734     if (reg & SCG_LPFLLCSR_LPFLLSEL_MASK)
735     {
736         return kStatus_SCG_Busy;
737     }
738 
739     /* If configure register is locked, return error. */
740     if (reg & SCG_LPFLLCSR_LK_MASK)
741     {
742         return kStatus_ReadOnly;
743     }
744 
745     SCG->LPFLLCSR = SCG_LPFLLCSR_LPFLLERR_MASK;
746 
747     return kStatus_Success;
748 }
749 
CLOCK_GetLpFllFreq(void)750 uint32_t CLOCK_GetLpFllFreq(void)
751 {
752     static const uint32_t lpfllFreq[] = {
753         SCG_LPFLL_FREQ0, SCG_LPFLL_FREQ1, SCG_LPFLL_FREQ2, SCG_LPFLL_FREQ3,
754     };
755 
756     if (SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLVLD_MASK) /* LPFLL is valid. */
757     {
758         return lpfllFreq[SCG_LPFLLCFG_FSEL_VAL];
759     }
760     else
761     {
762         return 0U;
763     }
764 }
765 
CLOCK_GetLpFllAsyncFreq(scg_async_clk_t type)766 uint32_t CLOCK_GetLpFllAsyncFreq(scg_async_clk_t type)
767 {
768     uint32_t lpfllFreq = CLOCK_GetLpFllFreq();
769     uint32_t divider = 0U;
770 
771     /* Get divider. */
772     if (lpfllFreq)
773     {
774         switch (type)
775         {
776             case kSCG_AsyncDiv2Clk: /* LPFLLDIV2_CLK. */
777                 divider = SCG_LPFLLDIV_LPFLLDIV2_VAL;
778                 break;
779             case kSCG_AsyncDiv1Clk: /* LPFLLDIV1_CLK. */
780                 divider = SCG_LPFLLDIV_LPFLLDIV1_VAL;
781                 break;
782             default:
783                 break;
784         }
785     }
786     if (divider)
787     {
788         return lpfllFreq >> (divider - 1U);
789     }
790     else /* Output disabled. */
791     {
792         return 0U;
793     }
794 }
795