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