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