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