aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/devices/MK02F12810/drivers/fsl_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MK02F12810/drivers/fsl_clock.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MK02F12810/drivers/fsl_clock.c1814
1 files changed, 1814 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MK02F12810/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MK02F12810/drivers/fsl_clock.c
new file mode 100644
index 000000000..5d2e50aad
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MK02F12810/drivers/fsl_clock.c
@@ -0,0 +1,1814 @@
1/*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016 - 2020, 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
15/* Component ID definition, used by tools. */
16#ifndef FSL_COMPONENT_ID
17#define FSL_COMPONENT_ID "platform.drivers.clock"
18#endif
19
20/* Macro definition remap workaround. */
21#if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK)))
22#define MCG_C2_EREFS0_MASK MCG_C2_EREFS_MASK
23#endif
24#if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK)))
25#define MCG_C2_HGO0_MASK MCG_C2_HGO_MASK
26#endif
27#if (defined(MCG_C2_RANGE_MASK) && !(defined(MCG_C2_RANGE0_MASK)))
28#define MCG_C2_RANGE0_MASK MCG_C2_RANGE_MASK
29#endif
30#if (defined(MCG_C6_CME_MASK) && !(defined(MCG_C6_CME0_MASK)))
31#define MCG_C6_CME0_MASK MCG_C6_CME_MASK
32#endif
33
34/* PLL fixed multiplier when there is not PRDIV and VDIV. */
35#define PLL_FIXED_MULT (375U)
36/* Max frequency of the reference clock used for internal clock trim. */
37#define TRIM_REF_CLK_MIN (8000000U)
38/* Min frequency of the reference clock used for internal clock trim. */
39#define TRIM_REF_CLK_MAX (16000000U)
40/* Max trim value of fast internal reference clock. */
41#define TRIM_FIRC_MAX (5000000U)
42/* Min trim value of fast internal reference clock. */
43#define TRIM_FIRC_MIN (3000000U)
44/* Max trim value of fast internal reference clock. */
45#define TRIM_SIRC_MAX (39063U)
46/* Min trim value of fast internal reference clock. */
47#define TRIM_SIRC_MIN (31250U)
48
49#define MCG_S_IRCST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_IRCST_MASK) >> (uint32_t)MCG_S_IRCST_SHIFT)
50#define MCG_S_CLKST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_CLKST_MASK) >> (uint32_t)MCG_S_CLKST_SHIFT)
51#define MCG_S_IREFST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_IREFST_MASK) >> (uint32_t)MCG_S_IREFST_SHIFT)
52#define MCG_S_PLLST_VAL (((uint32_t)MCG->S & (uint32_t)MCG_S_PLLST_MASK) >> (uint32_t)MCG_S_PLLST_SHIFT)
53#define MCG_C1_FRDIV_VAL ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT)
54#define MCG_C2_LP_VAL (((uint32_t)MCG->C2 & (uint32_t)MCG_C2_LP_MASK) >> (uint32_t)MCG_C2_LP_SHIFT)
55#define MCG_C2_RANGE_VAL ((MCG->C2 & MCG_C2_RANGE_MASK) >> MCG_C2_RANGE_SHIFT)
56#define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT)
57#define MCG_S2_PLLCST_VAL (((uint32_t)MCG->S2 & (uint32_t)MCG_S2_PLLCST_MASK) >> (uint32_t)MCG_S2_PLLCST_SHIFT)
58#define MCG_C7_OSCSEL_VAL ((MCG->C7 & MCG_C7_OSCSEL_MASK) >> MCG_C7_OSCSEL_SHIFT)
59#define MCG_C4_DMX32_VAL ((MCG->C4 & MCG_C4_DMX32_MASK) >> MCG_C4_DMX32_SHIFT)
60#define MCG_C4_DRST_DRS_VAL ((MCG->C4 & MCG_C4_DRST_DRS_MASK) >> MCG_C4_DRST_DRS_SHIFT)
61#define MCG_C7_PLL32KREFSEL_VAL ((MCG->C7 & MCG_C7_PLL32KREFSEL_MASK) >> MCG_C7_PLL32KREFSEL_SHIFT)
62#define MCG_C5_PLLREFSEL0_VAL ((MCG->C5 & MCG_C5_PLLREFSEL0_MASK) >> MCG_C5_PLLREFSEL0_SHIFT)
63#define MCG_C11_PLLREFSEL1_VAL ((MCG->C11 & MCG_C11_PLLREFSEL1_MASK) >> MCG_C11_PLLREFSEL1_SHIFT)
64#define MCG_C11_PRDIV1_VAL ((MCG->C11 & MCG_C11_PRDIV1_MASK) >> MCG_C11_PRDIV1_SHIFT)
65#define MCG_C12_VDIV1_VAL ((MCG->C12 & MCG_C12_VDIV1_MASK) >> MCG_C12_VDIV1_SHIFT)
66#define MCG_C5_PRDIV0_VAL ((uint8_t)(MCG->C5 & MCG_C5_PRDIV0_MASK) >> MCG_C5_PRDIV0_SHIFT)
67#define MCG_C6_VDIV0_VAL ((uint8_t)(MCG->C6 & MCG_C6_VDIV0_MASK) >> MCG_C6_VDIV0_SHIFT)
68
69#define OSC_MODE_MASK (MCG_C2_EREFS0_MASK | MCG_C2_HGO0_MASK | MCG_C2_RANGE0_MASK)
70
71#define SIM_CLKDIV1_OUTDIV1_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT)
72#define SIM_CLKDIV1_OUTDIV2_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> SIM_CLKDIV1_OUTDIV2_SHIFT)
73#define SIM_CLKDIV1_OUTDIV4_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT)
74#define SIM_SOPT1_OSC32KSEL_VAL ((SIM->SOPT1 & SIM_SOPT1_OSC32KSEL_MASK) >> SIM_SOPT1_OSC32KSEL_SHIFT)
75#define SIM_SOPT2_PLLFLLSEL_VAL ((SIM->SOPT2 & SIM_SOPT2_PLLFLLSEL_MASK) >> SIM_SOPT2_PLLFLLSEL_SHIFT)
76
77/* MCG_S_CLKST definition. */
78enum _mcg_clkout_stat
79{
80 kMCG_ClkOutStatFll, /* FLL. */
81 kMCG_ClkOutStatInt, /* Internal clock. */
82 kMCG_ClkOutStatExt, /* External clock. */
83 kMCG_ClkOutStatPll /* PLL. */
84};
85
86/* MCG_S_PLLST definition. */
87enum _mcg_pllst
88{
89 kMCG_PllstFll, /* FLL is used. */
90 kMCG_PllstPll /* PLL is used. */
91};
92
93/*******************************************************************************
94 * Variables
95 ******************************************************************************/
96
97/* Slow internal reference clock frequency. */
98static uint32_t s_slowIrcFreq = 32768U;
99/* Fast internal reference clock frequency. */
100static uint32_t s_fastIrcFreq = 4000000U;
101
102/* External XTAL0 (OSC0) clock frequency. */
103volatile uint32_t g_xtal0Freq;
104/* External XTAL32K clock frequency. */
105volatile uint32_t g_xtal32Freq;
106
107/*******************************************************************************
108 * Prototypes
109 ******************************************************************************/
110
111/*!
112 * @brief Get the MCG external reference clock frequency.
113 *
114 * Get the current MCG external reference clock frequency in Hz. It is
115 * the frequency select by MCG_C7[OSCSEL]. This is an internal function.
116 *
117 * @return MCG external reference clock frequency in Hz.
118 */
119static uint32_t CLOCK_GetMcgExtClkFreq(void);
120
121/*!
122 * @brief Get the MCG FLL external reference clock frequency.
123 *
124 * Get the current MCG FLL external reference clock frequency in Hz. It is
125 * the frequency after by MCG_C1[FRDIV]. This is an internal function.
126 *
127 * @return MCG FLL external reference clock frequency in Hz.
128 */
129static uint32_t CLOCK_GetFllExtRefClkFreq(void);
130
131/*!
132 * @brief Get the MCG FLL reference clock frequency.
133 *
134 * Get the current MCG FLL reference clock frequency in Hz. It is
135 * the frequency select by MCG_C1[IREFS]. This is an internal function.
136 *
137 * @return MCG FLL reference clock frequency in Hz.
138 */
139static uint32_t CLOCK_GetFllRefClkFreq(void);
140
141/*!
142 * @brief Get the frequency of clock selected by MCG_C2[IRCS].
143 *
144 * This clock's two output:
145 * 1. MCGOUTCLK when MCG_S[CLKST]=0.
146 * 2. MCGIRCLK when MCG_C1[IRCLKEN]=1.
147 *
148 * @return The frequency in Hz.
149 */
150static uint32_t CLOCK_GetInternalRefClkSelectFreq(void);
151
152/*!
153 * @brief Calculate the RANGE value base on crystal frequency.
154 *
155 * To setup external crystal oscillator, must set the register bits RANGE
156 * base on the crystal frequency. This function returns the RANGE base on the
157 * input frequency. This is an internal function.
158 *
159 * @param freq Crystal frequency in Hz.
160 * @return The RANGE value.
161 */
162static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq);
163
164#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN
165/*!
166 * @brief Delay function to wait FLL stable.
167 *
168 * Delay function to wait FLL stable in FEI mode or FEE mode, should wait at least
169 * 1ms. Every time changes FLL setting, should wait this time for FLL stable.
170 */
171static void CLOCK_FllStableDelay(void);
172#endif
173
174/*******************************************************************************
175 * Code
176 ******************************************************************************/
177
178#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN
179static void CLOCK_FllStableDelay(void)
180{
181 /*
182 Should wait at least 1ms. Because in these modes, the core clock is 100MHz
183 at most, so this function could obtain the 1ms delay.
184 */
185 volatile uint32_t i = 30000U;
186 while (0U != (i--))
187 {
188 __NOP();
189 }
190}
191#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */
192/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to
193 * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this
194 * file would call the CLOCK_FllStableDelay() regardless how it is defined.
195 */
196extern void CLOCK_FllStableDelay(void);
197#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */
198
199static uint32_t CLOCK_GetMcgExtClkFreq(void)
200{
201 uint32_t freq;
202
203 switch (MCG_C7_OSCSEL_VAL)
204 {
205 case 0U:
206 /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
207 assert(0U != g_xtal0Freq);
208 freq = g_xtal0Freq;
209 break;
210 case 1U:
211 /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */
212 assert(0U != g_xtal32Freq);
213 freq = g_xtal32Freq;
214 break;
215 case 2U:
216 freq = MCG_INTERNAL_IRC_48M;
217 break;
218 default:
219 freq = 0U;
220 break;
221 }
222
223 return freq;
224}
225
226static uint32_t CLOCK_GetFllExtRefClkFreq(void)
227{
228 /* FllExtRef = McgExtRef / FllExtRefDiv */
229 uint8_t frdiv;
230 uint8_t range;
231 uint8_t oscsel;
232
233 uint32_t freq = CLOCK_GetMcgExtClkFreq();
234
235 frdiv = MCG_C1_FRDIV_VAL;
236 freq >>= frdiv;
237
238 range = MCG_C2_RANGE_VAL;
239 oscsel = MCG_C7_OSCSEL_VAL;
240
241 /*
242 When should use divider 32, 64, 128, 256, 512, 1024, 1280, 1536.
243 1. MCG_C7[OSCSEL] selects IRC48M.
244 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0.
245 */
246 if (((0U != range) && ((uint8_t)kMCG_OscselOsc == oscsel)) || ((uint8_t)kMCG_OscselIrc == oscsel))
247 {
248 switch (frdiv)
249 {
250 case 0:
251 case 1:
252 case 2:
253 case 3:
254 case 4:
255 case 5:
256 freq >>= 5u;
257 break;
258 case 6:
259 /* 64*20=1280 */
260 freq /= 20u;
261 break;
262 case 7:
263 /* 128*12=1536 */
264 freq /= 12u;
265 break;
266 default:
267 freq = 0u;
268 break;
269 }
270 }
271
272 return freq;
273}
274
275static uint32_t CLOCK_GetInternalRefClkSelectFreq(void)
276{
277 uint32_t freq;
278
279 if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL)
280 {
281 /* Slow internal reference clock selected*/
282 freq = s_slowIrcFreq;
283 }
284 else
285 {
286 /* Fast internal reference clock selected*/
287 freq = s_fastIrcFreq >> MCG_SC_FCRDIV_VAL;
288 }
289
290 return freq;
291}
292
293static uint32_t CLOCK_GetFllRefClkFreq(void)
294{
295 uint32_t freq;
296
297 /* If use external reference clock. */
298 if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
299 {
300 freq = CLOCK_GetFllExtRefClkFreq();
301 }
302 /* If use internal reference clock. */
303 else
304 {
305 freq = s_slowIrcFreq;
306 }
307
308 return freq;
309}
310
311static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq)
312{
313 uint8_t range;
314
315 if (freq <= 39063U)
316 {
317 range = 0U;
318 }
319 else if (freq <= 8000000U)
320 {
321 range = 1U;
322 }
323 else
324 {
325 range = 2U;
326 }
327
328 return range;
329}
330
331/*!
332 * brief Get the OSC0 external reference undivided clock frequency (OSC0ERCLK_UNDIV).
333 *
334 * return Clock frequency in Hz.
335 */
336uint32_t CLOCK_GetOsc0ErClkUndivFreq(void)
337{
338 if ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U)
339 {
340 /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
341 assert(g_xtal0Freq);
342 return g_xtal0Freq;
343 }
344 else
345 {
346 return 0U;
347 }
348}
349
350/*!
351 * brief Get the OSC0 external reference divided clock frequency.
352 *
353 * return Clock frequency in Hz.
354 */
355uint32_t CLOCK_GetOsc0ErClkDivFreq(void)
356{
357 uint32_t freq;
358 uint8_t temp;
359 if ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U)
360 {
361 /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
362 assert(g_xtal0Freq);
363 temp = OSC0->DIV & OSC_DIV_ERPS_MASK;
364 freq = g_xtal0Freq >> ((temp) >> OSC_DIV_ERPS_SHIFT);
365 }
366 else
367 {
368 freq = 0U;
369 }
370 return freq;
371}
372
373/*!
374 * brief Get the external reference 32K clock frequency (ERCLK32K).
375 *
376 * return Clock frequency in Hz.
377 */
378uint32_t CLOCK_GetEr32kClkFreq(void)
379{
380 uint32_t freq;
381
382 switch (SIM_SOPT1_OSC32KSEL_VAL)
383 {
384 case 0U: /* OSC 32k clock */
385 freq = (CLOCK_GetOsc0ErClkUndivFreq() == 32768U) ? 32768U : 0U;
386 break;
387 case 3U: /* LPO clock */
388 freq = LPO_CLK_FREQ;
389 break;
390 default:
391 freq = 0U;
392 break;
393 }
394 return freq;
395}
396
397/*!
398 * brief Get the output clock frequency selected by SIM[PLLFLLSEL].
399 *
400 * return Clock frequency in Hz.
401 */
402uint32_t CLOCK_GetPllFllSelClkFreq(void)
403{
404 uint32_t freq;
405
406 switch (SIM_SOPT2_PLLFLLSEL_VAL)
407 {
408 case 0U: /* FLL. */
409 freq = CLOCK_GetFllFreq();
410 break;
411 case 3U: /* MCG IRC48M. */
412 freq = MCG_INTERNAL_IRC_48M;
413 break;
414 default:
415 freq = 0U;
416 break;
417 }
418
419 return freq;
420}
421
422/*!
423 * brief Get the OSC0 external reference clock frequency (OSC0ERCLK).
424 *
425 * return Clock frequency in Hz.
426 */
427uint32_t CLOCK_GetOsc0ErClkFreq(void)
428{
429 return CLOCK_GetOsc0ErClkDivFreq();
430}
431
432/*!
433 * brief Get the platform clock frequency.
434 *
435 * return Clock frequency in Hz.
436 */
437uint32_t CLOCK_GetPlatClkFreq(void)
438{
439 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1UL);
440}
441
442/*!
443 * brief Get the flash clock frequency.
444 *
445 * return Clock frequency in Hz.
446 */
447uint32_t CLOCK_GetFlashClkFreq(void)
448{
449 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1UL);
450}
451
452/*!
453 * brief Get the bus clock frequency.
454 *
455 * return Clock frequency in Hz.
456 */
457uint32_t CLOCK_GetBusClkFreq(void)
458{
459 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1UL);
460}
461
462/*!
463 * brief Get the core clock or system clock frequency.
464 *
465 * return Clock frequency in Hz.
466 */
467uint32_t CLOCK_GetCoreSysClkFreq(void)
468{
469 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1UL);
470}
471
472/*!
473 * brief Gets the clock frequency for a specific clock name.
474 *
475 * This function checks the current clock configurations and then calculates
476 * the clock frequency for a specific clock name defined in clock_name_t.
477 * The MCG must be properly configured before using this function.
478 *
479 * param clockName Clock names defined in clock_name_t
480 * return Clock frequency value in Hertz
481 */
482uint32_t CLOCK_GetFreq(clock_name_t clockName)
483{
484 uint32_t freq;
485
486 switch (clockName)
487 {
488 case kCLOCK_CoreSysClk:
489 case kCLOCK_PlatClk:
490 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1UL);
491 break;
492 case kCLOCK_BusClk:
493 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1UL);
494 break;
495 case kCLOCK_FlashClk:
496 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1UL);
497 break;
498 case kCLOCK_PllFllSelClk:
499 freq = CLOCK_GetPllFllSelClkFreq();
500 break;
501 case kCLOCK_Er32kClk:
502 freq = CLOCK_GetEr32kClkFreq();
503 break;
504 case kCLOCK_McgFixedFreqClk:
505 freq = CLOCK_GetFixedFreqClkFreq();
506 break;
507 case kCLOCK_McgInternalRefClk:
508 freq = CLOCK_GetInternalRefClkFreq();
509 break;
510 case kCLOCK_McgFllClk:
511 freq = CLOCK_GetFllFreq();
512 break;
513 case kCLOCK_McgIrc48MClk:
514 freq = MCG_INTERNAL_IRC_48M;
515 break;
516 case kCLOCK_LpoClk:
517 freq = LPO_CLK_FREQ;
518 break;
519 case kCLOCK_Osc0ErClkUndiv:
520 freq = CLOCK_GetOsc0ErClkUndivFreq();
521 break;
522 case kCLOCK_Osc0ErClk:
523 freq = CLOCK_GetOsc0ErClkDivFreq();
524 break;
525 default:
526 freq = 0U;
527 break;
528 }
529
530 return freq;
531}
532
533/*!
534 * brief Set the clock configure in SIM module.
535 *
536 * This function sets system layer clock settings in SIM module.
537 *
538 * param config Pointer to the configure structure.
539 */
540void CLOCK_SetSimConfig(sim_clock_config_t const *config)
541{
542 SIM->CLKDIV1 = config->clkdiv1;
543 CLOCK_SetPllFllSelClock(config->pllFllSel);
544 CLOCK_SetEr32kClock(config->er32kSrc);
545}
546
547/*!
548 * brief Gets the MCG output clock (MCGOUTCLK) frequency.
549 *
550 * This function gets the MCG output clock frequency in Hz based on the current MCG
551 * register value.
552 *
553 * return The frequency of MCGOUTCLK.
554 */
555uint32_t CLOCK_GetOutClkFreq(void)
556{
557 uint32_t mcgoutclk;
558 uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL;
559
560 switch (clkst)
561 {
562 case (uint32_t)kMCG_ClkOutStatFll:
563 mcgoutclk = CLOCK_GetFllFreq();
564 break;
565 case (uint32_t)kMCG_ClkOutStatInt:
566 mcgoutclk = CLOCK_GetInternalRefClkSelectFreq();
567 break;
568 case (uint32_t)kMCG_ClkOutStatExt:
569 mcgoutclk = CLOCK_GetMcgExtClkFreq();
570 break;
571 default:
572 mcgoutclk = 0U;
573 break;
574 }
575
576 return mcgoutclk;
577}
578
579/*!
580 * brief Gets the MCG FLL clock (MCGFLLCLK) frequency.
581 *
582 * This function gets the MCG FLL clock frequency in Hz based on the current MCG
583 * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and
584 * disabled in low power state in other modes.
585 *
586 * return The frequency of MCGFLLCLK.
587 */
588uint32_t CLOCK_GetFllFreq(void)
589{
590 static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}};
591
592 uint8_t drs, dmx32;
593 uint32_t freq;
594 uint32_t ret;
595
596 /* If FLL is not enabled currently, then return 0U. */
597 if (0U != (MCG->C2 & MCG_C2_LP_MASK))
598 {
599 ret = 0U;
600 }
601 else
602 {
603 /* Get FLL reference clock frequency. */
604 freq = CLOCK_GetFllRefClkFreq();
605 if (0U == freq)
606 {
607 ret = freq;
608 }
609 else
610 {
611 drs = MCG_C4_DRST_DRS_VAL;
612 dmx32 = MCG_C4_DMX32_VAL;
613 ret = freq * fllFactorTable[drs][dmx32];
614 }
615 }
616
617 return ret;
618}
619
620/*!
621 * brief Gets the MCG internal reference clock (MCGIRCLK) frequency.
622 *
623 * This function gets the MCG internal reference clock frequency in Hz based
624 * on the current MCG register value.
625 *
626 * return The frequency of MCGIRCLK.
627 */
628uint32_t CLOCK_GetInternalRefClkFreq(void)
629{
630 uint32_t freq;
631
632 /* If MCGIRCLK is gated. */
633 if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK))
634 {
635 freq = 0U;
636 }
637 else
638 {
639 freq = CLOCK_GetInternalRefClkSelectFreq();
640 }
641
642 return freq;
643}
644
645/*!
646 * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency.
647 *
648 * This function gets the MCG fixed frequency clock frequency in Hz based
649 * on the current MCG register value.
650 *
651 * return The frequency of MCGFFCLK.
652 */
653uint32_t CLOCK_GetFixedFreqClkFreq(void)
654{
655 uint32_t freq = CLOCK_GetFllRefClkFreq();
656 uint32_t ret;
657
658 /* MCGFFCLK must be no more than MCGOUTCLK/8. */
659 if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq))
660 {
661 ret = freq;
662 }
663 else
664 {
665 ret = 0U;
666 }
667
668 return ret;
669}
670
671/*!
672 * brief Selects the MCG external reference clock.
673 *
674 * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL],
675 * and waits for the clock source to be stable. Because the external reference
676 * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes.
677 *
678 * param oscsel MCG external reference clock source, MCG_C7[OSCSEL].
679 * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source,
680 * the configuration should not be changed. Otherwise, a glitch occurs.
681 * retval kStatus_Success External reference clock set successfully.
682 */
683status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel)
684{
685 bool needDelay;
686 uint32_t i;
687
688#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
689 /* If change MCG_C7[OSCSEL] and external reference clock is system clock source, return error. */
690 if ((MCG_C7_OSCSEL_VAL != oscsel) && (!(MCG->S & MCG_S_IREFST_MASK)))
691 {
692 return kStatus_MCG_SourceUsed;
693 }
694#endif /* MCG_CONFIG_CHECK_PARAM */
695
696 if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel)
697 {
698 /* If change OSCSEL, need to delay, ERR009878. */
699 needDelay = true;
700 }
701 else
702 {
703 needDelay = false;
704 }
705
706 MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel);
707 if (needDelay)
708 {
709 /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */
710 i = 1500U;
711 while (0U != (i--))
712 {
713 __NOP();
714 }
715 }
716
717 return kStatus_Success;
718}
719
720/*!
721 * brief Configures the Internal Reference clock (MCGIRCLK).
722 *
723 * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC
724 * source. If the fast IRC is used, this function sets the fast IRC divider.
725 * This function also sets whether the \c MCGIRCLK is enabled in stop mode.
726 * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result,
727 * using the function in these modes it is not allowed.
728 *
729 * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode.
730 * param ircs MCGIRCLK clock source, choose fast or slow.
731 * param fcrdiv Fast IRC divider setting (\c FCRDIV).
732 * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source,
733 * the configuration should not be changed. Otherwise, a glitch occurs.
734 * retval kStatus_Success MCGIRCLK configuration finished successfully.
735 */
736status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv)
737{
738 uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL;
739 mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)((uint32_t)MCG_S_IRCST_VAL);
740 uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL;
741
742#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
743 /* If MCGIRCLK is used as system clock source. */
744 if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState)
745 {
746 /* If need to change MCGIRCLK source or driver, return error. */
747 if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs))
748 {
749 return kStatus_MCG_SourceUsed;
750 }
751 }
752#endif
753
754 /* If need to update the FCRDIV. */
755 if (fcrdiv != curFcrdiv)
756 {
757 /* If fast IRC is in use currently, change to slow IRC. */
758 if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) &&
759 (kMCG_IrcFast == curIrcs))
760 {
761 MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow)));
762 while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow)
763 {
764 }
765 }
766 /* Update FCRDIV. */
767 MCG->SC =
768 (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv);
769 }
770
771 /* Set internal reference clock selection. */
772 MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)));
773 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode);
774
775 /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */
776 if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable)))
777 {
778 while (MCG_S_IRCST_VAL != (uint8_t)ircs)
779 {
780 }
781 }
782
783 return kStatus_Success;
784}
785
786/*!
787 * brief Sets the OSC0 clock monitor mode.
788 *
789 * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details.
790 *
791 * param mode Monitor mode to set.
792 */
793void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode)
794{
795 /* Clear the previous flag, MCG_SC[LOCS0]. */
796 MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK;
797
798 if (kMCG_MonitorNone == mode)
799 {
800 MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK;
801 }
802 else
803 {
804 if (kMCG_MonitorInt == mode)
805 {
806 MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK;
807 }
808 else
809 {
810 MCG->C2 |= MCG_C2_LOCRE0_MASK;
811 }
812 MCG->C6 |= MCG_C6_CME0_MASK;
813 }
814}
815
816/*!
817 * brief Gets the MCG status flags.
818 *
819 * This function gets the MCG clock status flags. All status flags are
820 * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To
821 * check a specific flag, compare the return value with the flag.
822 *
823 * Example:
824 * code
825 * To check the clock lost lock status of OSC0 and PLL0.
826 * uint32_t mcgFlags;
827 *
828 * mcgFlags = CLOCK_GetStatusFlags();
829 *
830 * if (mcgFlags & kMCG_Osc0LostFlag)
831 * {
832 * OSC0 clock lock lost. Do something.
833 * }
834 * if (mcgFlags & kMCG_Pll0LostFlag)
835 * {
836 * PLL0 clock lock lost. Do something.
837 * }
838 * endcode
839 *
840 * return Logical OR value of the ref _mcg_status_flags_t.
841 */
842uint32_t CLOCK_GetStatusFlags(void)
843{
844 uint32_t ret = 0U;
845 uint8_t mcg_s = MCG->S;
846
847 if ((MCG->SC & MCG_SC_LOCS0_MASK) != 0U)
848 {
849 ret |= (uint32_t)kMCG_Osc0LostFlag;
850 }
851 if ((mcg_s & MCG_S_OSCINIT0_MASK) != 0U)
852 {
853 ret |= (uint32_t)kMCG_Osc0InitFlag;
854 }
855 return ret;
856}
857
858/*!
859 * brief Clears the MCG status flags.
860 *
861 * This function clears the MCG clock lock lost status. The parameter is a logical
862 * OR value of the flags to clear. See ref _mcg_status_flags_t.
863 *
864 * Example:
865 * code
866 * To clear the clock lost lock status flags of OSC0 and PLL0.
867 *
868 * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag);
869 * endcode
870 *
871 * param mask The status flags to clear. This is a logical OR of members of the
872 * enumeration ref _mcg_status_flags_t.
873 */
874void CLOCK_ClearStatusFlags(uint32_t mask)
875{
876 if ((mask & (uint32_t)kMCG_Osc0LostFlag) != 0UL)
877 {
878 MCG->SC &= (uint8_t)(~MCG_SC_ATMF_MASK);
879 }
880}
881
882/*!
883 * brief Initializes the OSC0.
884 *
885 * This function initializes the OSC0 according to the board configuration.
886 *
887 * param config Pointer to the OSC0 configuration structure.
888 */
889void CLOCK_InitOsc0(osc_config_t const *config)
890{
891 uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq);
892
893 OSC_SetCapLoad(OSC0, config->capLoad);
894
895 MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode);
896 OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig);
897
898 if ((kOSC_ModeExt != config->workMode) && ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U))
899 {
900 /* Wait for stable. */
901 while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
902 {
903 }
904 }
905}
906
907/*!
908 * brief Deinitializes the OSC0.
909 *
910 * This function deinitializes the OSC0.
911 */
912void CLOCK_DeinitOsc0(void)
913{
914 OSC0->CR = 0U;
915 MCG->C2 &= ~(uint8_t)OSC_MODE_MASK;
916}
917
918/*!
919 * brief Set the Slow IRC frequency based on the trimmed value
920 *
921 * param freq The Slow IRC frequency input clock frequency in Hz.
922 */
923void CLOCK_SetSlowIrcFreq(uint32_t freq)
924{
925 s_slowIrcFreq = freq;
926}
927
928/*!
929 * brief Set the Fast IRC frequency based on the trimmed value
930 *
931 * param freq The Fast IRC frequency input clock frequency in Hz.
932 */
933void CLOCK_SetFastIrcFreq(uint32_t freq)
934{
935 s_fastIrcFreq = freq;
936}
937
938/*!
939 * brief Auto trims the internal reference clock.
940 *
941 * This function trims the internal reference clock by using the external clock. If
942 * successful, it returns the kStatus_Success and the frequency after
943 * trimming is received in the parameter p actualFreq. If an error occurs,
944 * the error code is returned.
945 *
946 * param extFreq External clock frequency, which should be a bus clock.
947 * param desireFreq Frequency to trim to.
948 * param actualFreq Actual frequency after trimming.
949 * param atms Trim fast or slow internal reference clock.
950 * retval kStatus_Success ATM success.
951 * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM.
952 * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency.
953 * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source.
954 * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming.
955 */
956status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms)
957{
958 uint32_t multi; /* extFreq / desireFreq */
959 uint32_t actv; /* Auto trim value. */
960 uint8_t mcg_sc;
961 status_t status = kStatus_Success;
962
963 static const uint32_t trimRange[2][2] = {
964 /* Min Max */
965 {TRIM_SIRC_MIN, TRIM_SIRC_MAX}, /* Slow IRC. */
966 {TRIM_FIRC_MIN, TRIM_FIRC_MAX} /* Fast IRC. */
967 };
968
969 if ((extFreq > TRIM_REF_CLK_MAX) || (extFreq < TRIM_REF_CLK_MIN))
970 {
971 status = kStatus_MCG_AtmBusClockInvalid;
972 }
973 /* Check desired frequency range. */
974 else if ((desireFreq < trimRange[atms][0]) || (desireFreq > trimRange[atms][1]))
975 {
976 status = kStatus_MCG_AtmDesiredFreqInvalid;
977 }
978 /*
979 Make sure internal reference clock is not used to generate bus clock.
980 Here only need to check (MCG_S_IREFST == 1).
981 */
982 else if (MCG_S_IREFST(kMCG_FllSrcInternal) == (MCG->S & MCG_S_IREFST_MASK))
983 {
984 status = kStatus_MCG_AtmIrcUsed;
985 }
986 else
987 {
988 multi = extFreq / desireFreq;
989 actv = multi * 21U;
990
991 if (kMCG_AtmSel4m == atms)
992 {
993 actv *= 128U;
994 }
995
996 /* Now begin to start trim. */
997 MCG->ATCVL = (uint8_t)actv;
998 MCG->ATCVH = (uint8_t)(actv >> 8U);
999
1000 mcg_sc = MCG->SC;
1001 mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK);
1002 mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms));
1003 MCG->SC = (mcg_sc | MCG_SC_ATME_MASK);
1004
1005 /* Wait for MCG finished. */
1006 while (0U != (MCG->SC & MCG_SC_ATME_MASK))
1007 {
1008 }
1009
1010 /* Error occurs? */
1011 if (0U != (MCG->SC & MCG_SC_ATMF_MASK))
1012 {
1013 /* Clear the failed flag. */
1014 MCG->SC = mcg_sc;
1015 status = kStatus_MCG_AtmHardwareFail;
1016 }
1017 else
1018 {
1019 *actualFreq = extFreq / multi;
1020
1021 if (kMCG_AtmSel4m == atms)
1022 {
1023 s_fastIrcFreq = *actualFreq;
1024 }
1025 else
1026 {
1027 s_slowIrcFreq = *actualFreq;
1028 }
1029 }
1030 }
1031
1032 return status;
1033}
1034
1035/*!
1036 * brief Gets the current MCG mode.
1037 *
1038 * This function checks the MCG registers and determines the current MCG mode.
1039 *
1040 * return Current MCG mode or error code; See ref mcg_mode_t.
1041 */
1042mcg_mode_t CLOCK_GetMode(void)
1043{
1044 mcg_mode_t mode = kMCG_ModeError;
1045 uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL;
1046 uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL;
1047 uint32_t lp = (uint32_t)MCG_C2_LP_VAL;
1048
1049 /*------------------------------------------------------------------
1050 Mode and Registers
1051 ____________________________________________________________________
1052
1053 Mode | CLKST | IREFST | PLLST | LP
1054 ____________________________________________________________________
1055
1056 FEI | 00(FLL) | 1(INT) | 0(FLL) | X
1057 ____________________________________________________________________
1058
1059 FEE | 00(FLL) | 0(EXT) | 0(FLL) | X
1060 ____________________________________________________________________
1061
1062 FBE | 10(EXT) | 0(EXT) | 0(FLL) | 0(NORMAL)
1063 ____________________________________________________________________
1064
1065 FBI | 01(INT) | 1(INT) | 0(FLL) | 0(NORMAL)
1066 ____________________________________________________________________
1067
1068 BLPI | 01(INT) | 1(INT) | 0(FLL) | 1(LOW POWER)
1069 ____________________________________________________________________
1070
1071 BLPE | 10(EXT) | 0(EXT) | X | 1(LOW POWER)
1072 ____________________________________________________________________
1073
1074 PEE | 11(PLL) | 0(EXT) | 1(PLL) | X
1075 ____________________________________________________________________
1076
1077 PBE | 10(EXT) | 0(EXT) | 1(PLL) | O(NORMAL)
1078 ____________________________________________________________________
1079
1080 PBI | 01(INT) | 1(INT) | 1(PLL) | 0(NORMAL)
1081 ____________________________________________________________________
1082
1083 PEI | 11(PLL) | 1(INT) | 1(PLL) | X
1084 ____________________________________________________________________
1085
1086 ----------------------------------------------------------------------*/
1087
1088 if (clkst == (uint32_t)kMCG_ClkOutStatFll)
1089 {
1090 if ((uint32_t)kMCG_FllSrcExternal == irefst)
1091 {
1092 mode = kMCG_ModeFEE;
1093 }
1094 else
1095 {
1096 mode = kMCG_ModeFEI;
1097 }
1098 }
1099 else if (clkst == (uint32_t)kMCG_ClkOutStatInt)
1100 {
1101 if (0U != lp)
1102 {
1103 mode = kMCG_ModeBLPI;
1104 }
1105 else
1106 {
1107 {
1108 mode = kMCG_ModeFBI;
1109 }
1110 }
1111 }
1112 else if (clkst == (uint32_t)kMCG_ClkOutStatExt)
1113 {
1114 if (0U != lp)
1115 {
1116 mode = kMCG_ModeBLPE;
1117 }
1118 else
1119 {
1120 {
1121 mode = kMCG_ModeFBE;
1122 }
1123 }
1124 }
1125 else
1126 {
1127 /*do nothing*/
1128 }
1129
1130 return mode;
1131}
1132
1133/*!
1134 * brief Sets the MCG to FEI mode.
1135 *
1136 * This function sets the MCG to FEI mode. If setting to FEI mode fails
1137 * from the current mode, this function returns an error.
1138 *
1139 * param dmx32 DMX32 in FEI mode.
1140 * param drs The DCO range selection.
1141 * param fllStableDelay Delay function to ensure that the FLL is stable. Passing
1142 * NULL does not cause a delay.
1143 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1144 * retval kStatus_Success Switched to the target mode successfully.
1145 * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1146 * to a frequency above 32768 Hz.
1147 */
1148status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1149{
1150 uint8_t mcg_c4;
1151 bool change_drs = false;
1152
1153#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1154 mcg_mode_t mode = CLOCK_GetMode();
1155 if (!((kMCG_ModeFEI == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEE == mode)))
1156 {
1157 return kStatus_MCG_ModeUnreachable;
1158 }
1159#endif
1160 mcg_c4 = MCG->C4;
1161
1162 /*
1163 Errata: ERR007993
1164 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
1165 reference clock source changes, then reset to previous value after
1166 reference clock changes.
1167 */
1168 if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
1169 {
1170 change_drs = true;
1171 /* Change the LSB of DRST_DRS. */
1172 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
1173 }
1174
1175 /* Set CLKS and IREFS. */
1176 MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) |
1177 (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */
1178 | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */
1179
1180 /* Wait and check status. */
1181 while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL)
1182 {
1183 }
1184
1185 /* Errata: ERR007993 */
1186 if (change_drs)
1187 {
1188 MCG->C4 = mcg_c4;
1189 }
1190
1191 /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */
1192 MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
1193 (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
1194
1195 /* Check MCG_S[CLKST] */
1196 while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL)
1197 {
1198 }
1199
1200 /* Wait for FLL stable time. */
1201 if (NULL != fllStableDelay)
1202 {
1203 fllStableDelay();
1204 }
1205
1206 return kStatus_Success;
1207}
1208
1209/*!
1210 * brief Sets the MCG to FEE mode.
1211 *
1212 * This function sets the MCG to FEE mode. If setting to FEE mode fails
1213 * from the current mode, this function returns an error.
1214 *
1215 * param frdiv FLL reference clock divider setting, FRDIV.
1216 * param dmx32 DMX32 in FEE mode.
1217 * param drs The DCO range selection.
1218 * param fllStableDelay Delay function to make sure FLL is stable. Passing
1219 * NULL does not cause a delay.
1220 *
1221 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1222 * retval kStatus_Success Switched to the target mode successfully.
1223 */
1224status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1225{
1226 uint8_t mcg_c4;
1227 bool change_drs = false;
1228
1229#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1230 mcg_mode_t mode = CLOCK_GetMode();
1231 if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode)))
1232 {
1233 return kStatus_MCG_ModeUnreachable;
1234 }
1235#endif
1236 mcg_c4 = MCG->C4;
1237
1238 /*
1239 Errata: ERR007993
1240 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
1241 reference clock source changes, then reset to previous value after
1242 reference clock changes.
1243 */
1244 if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL)
1245 {
1246 change_drs = true;
1247 /* Change the LSB of DRST_DRS. */
1248 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
1249 }
1250
1251 /* Set CLKS and IREFS. */
1252 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) |
1253 (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */
1254 | MCG_C1_FRDIV(frdiv) /* FRDIV */
1255 | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */
1256
1257 /* If use external crystal as clock source, wait for it stable. */
1258 if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
1259 {
1260 if (0U != (MCG->C2 & MCG_C2_EREFS_MASK))
1261 {
1262 while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
1263 {
1264 }
1265 }
1266 }
1267
1268 /* Wait and check status. */
1269 while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL)
1270 {
1271 }
1272
1273 /* Errata: ERR007993 */
1274 if (change_drs)
1275 {
1276 MCG->C4 = mcg_c4;
1277 }
1278
1279 /* Set DRS and DMX32. */
1280 mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
1281 (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
1282 MCG->C4 = mcg_c4;
1283
1284 /* Wait for DRST_DRS update. */
1285 while (MCG->C4 != mcg_c4)
1286 {
1287 }
1288
1289 /* Check MCG_S[CLKST] */
1290 while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL)
1291 {
1292 }
1293
1294 /* Wait for FLL stable time. */
1295 if (NULL != fllStableDelay)
1296 {
1297 fllStableDelay();
1298 }
1299
1300 return kStatus_Success;
1301}
1302
1303/*!
1304 * brief Sets the MCG to FBI mode.
1305 *
1306 * This function sets the MCG to FBI mode. If setting to FBI mode fails
1307 * from the current mode, this function returns an error.
1308 *
1309 * param dmx32 DMX32 in FBI mode.
1310 * param drs The DCO range selection.
1311 * param fllStableDelay Delay function to make sure FLL is stable. If the FLL
1312 * is not used in FBI mode, this parameter can be NULL. Passing
1313 * NULL does not cause a delay.
1314 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1315 * retval kStatus_Success Switched to the target mode successfully.
1316 * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1317 * to frequency above 32768 Hz.
1318 */
1319status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1320{
1321 uint8_t mcg_c4;
1322 bool change_drs = false;
1323
1324#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1325 mcg_mode_t mode = CLOCK_GetMode();
1326
1327 if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode) ||
1328 (kMCG_ModeBLPI == mode)))
1329
1330 {
1331 return kStatus_MCG_ModeUnreachable;
1332 }
1333#endif
1334
1335 mcg_c4 = MCG->C4;
1336
1337 MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */
1338
1339 /*
1340 Errata: ERR007993
1341 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
1342 reference clock source changes, then reset to previous value after
1343 reference clock changes.
1344 */
1345 if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
1346 {
1347 change_drs = true;
1348 /* Change the LSB of DRST_DRS. */
1349 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
1350 }
1351
1352 /* Set CLKS and IREFS. */
1353 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) |
1354 (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */
1355 | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */
1356
1357 /* Wait and check status. */
1358 while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL)
1359 {
1360 }
1361
1362 /* Errata: ERR007993 */
1363 if (change_drs)
1364 {
1365 MCG->C4 = mcg_c4;
1366 }
1367
1368 while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL)
1369 {
1370 }
1371
1372 MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
1373 (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
1374
1375 /* Wait for FLL stable time. */
1376 if (NULL != fllStableDelay)
1377 {
1378 fllStableDelay();
1379 }
1380
1381 return kStatus_Success;
1382}
1383
1384/*!
1385 * brief Sets the MCG to FBE mode.
1386 *
1387 * This function sets the MCG to FBE mode. If setting to FBE mode fails
1388 * from the current mode, this function returns an error.
1389 *
1390 * param frdiv FLL reference clock divider setting, FRDIV.
1391 * param dmx32 DMX32 in FBE mode.
1392 * param drs The DCO range selection.
1393 * param fllStableDelay Delay function to make sure FLL is stable. If the FLL
1394 * is not used in FBE mode, this parameter can be NULL. Passing NULL
1395 * does not cause a delay.
1396 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1397 * retval kStatus_Success Switched to the target mode successfully.
1398 */
1399status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1400{
1401 uint8_t mcg_c4;
1402 bool change_drs = false;
1403
1404#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1405 mcg_mode_t mode = CLOCK_GetMode();
1406 if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode) ||
1407 (kMCG_ModeBLPE == mode)))
1408 {
1409 return kStatus_MCG_ModeUnreachable;
1410 }
1411#endif
1412
1413 /* Set LP bit to enable the FLL */
1414 MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK;
1415
1416 mcg_c4 = MCG->C4;
1417
1418 /*
1419 Errata: ERR007993
1420 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
1421 reference clock source changes, then reset to previous value after
1422 reference clock changes.
1423 */
1424 if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL)
1425 {
1426 change_drs = true;
1427 /* Change the LSB of DRST_DRS. */
1428 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
1429 }
1430
1431 /* Set CLKS and IREFS. */
1432 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) |
1433 (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */
1434 | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */
1435 | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */
1436
1437 /* If use external crystal as clock source, wait for it stable. */
1438 if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
1439 {
1440 if (0U != (MCG->C2 & MCG_C2_EREFS_MASK))
1441 {
1442 while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
1443 {
1444 }
1445 }
1446 }
1447
1448 /* Wait for Reference clock Status bit to clear */
1449 while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL)
1450 {
1451 }
1452
1453 /* Errata: ERR007993 */
1454 if (change_drs)
1455 {
1456 MCG->C4 = mcg_c4;
1457 }
1458
1459 /* Set DRST_DRS and DMX32. */
1460 mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
1461 (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
1462
1463 /* Wait for clock status bits to show clock source is ext ref clk */
1464 while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL)
1465 {
1466 }
1467
1468 /* Wait for fll stable time. */
1469 if (NULL != fllStableDelay)
1470 {
1471 fllStableDelay();
1472 }
1473
1474 return kStatus_Success;
1475}
1476
1477/*!
1478 * brief Sets the MCG to BLPI mode.
1479 *
1480 * This function sets the MCG to BLPI mode. If setting to BLPI mode fails
1481 * from the current mode, this function returns an error.
1482 *
1483 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1484 * retval kStatus_Success Switched to the target mode successfully.
1485 */
1486status_t CLOCK_SetBlpiMode(void)
1487{
1488#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1489 if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt)
1490 {
1491 return kStatus_MCG_ModeUnreachable;
1492 }
1493#endif /* MCG_CONFIG_CHECK_PARAM */
1494
1495 /* Set LP. */
1496 MCG->C2 |= MCG_C2_LP_MASK;
1497
1498 return kStatus_Success;
1499}
1500
1501/*!
1502 * brief Sets the MCG to BLPE mode.
1503 *
1504 * This function sets the MCG to BLPE mode. If setting to BLPE mode fails
1505 * from the current mode, this function returns an error.
1506 *
1507 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1508 * retval kStatus_Success Switched to the target mode successfully.
1509 */
1510status_t CLOCK_SetBlpeMode(void)
1511{
1512#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1513 if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt)
1514 {
1515 return kStatus_MCG_ModeUnreachable;
1516 }
1517#endif
1518
1519 /* Set LP bit to enter BLPE mode. */
1520 MCG->C2 |= MCG_C2_LP_MASK;
1521
1522 return kStatus_Success;
1523}
1524
1525/*!
1526 * brief Switches the MCG to FBE mode from the external mode.
1527 *
1528 * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly.
1529 * The external clock is used as the system clock source and PLL is disabled. However,
1530 * the FLL settings are not configured. This is a lite function with a small code size, which is useful
1531 * during the mode switch. For example, to switch from PEE mode to FEI mode:
1532 *
1533 * code
1534 * CLOCK_ExternalModeToFbeModeQuick();
1535 * CLOCK_SetFeiMode(...);
1536 * endcode
1537 *
1538 * retval kStatus_Success Switched successfully.
1539 * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function.
1540 */
1541status_t CLOCK_ExternalModeToFbeModeQuick(void)
1542{
1543#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1544 if ((MCG->S & MCG_S_IREFST_MASK) != 0U)
1545 {
1546 return kStatus_MCG_ModeInvalid;
1547 }
1548#endif /* MCG_CONFIG_CHECK_PARAM */
1549
1550 /* Disable low power */
1551 MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK);
1552
1553 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal));
1554 while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt)
1555 {
1556 }
1557
1558 return kStatus_Success;
1559}
1560
1561/*!
1562 * brief Switches the MCG to FBI mode from internal modes.
1563 *
1564 * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly.
1565 * The MCGIRCLK is used as the system clock source and PLL is disabled. However,
1566 * FLL settings are not configured. This is a lite function with a small code size, which is useful
1567 * during the mode switch. For example, to switch from PEI mode to FEE mode:
1568 *
1569 * code
1570 * CLOCK_InternalModeToFbiModeQuick();
1571 * CLOCK_SetFeeMode(...);
1572 * endcode
1573 *
1574 * retval kStatus_Success Switched successfully.
1575 * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function.
1576 */
1577status_t CLOCK_InternalModeToFbiModeQuick(void)
1578{
1579#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1580 if ((MCG->S & MCG_S_IREFST_MASK) == 0U)
1581 {
1582 return kStatus_MCG_ModeInvalid;
1583 }
1584#endif
1585
1586 /* Disable low power */
1587 MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK;
1588
1589 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal));
1590 while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt)
1591 {
1592 }
1593
1594 return kStatus_Success;
1595}
1596
1597/*!
1598 * brief Sets the MCG to FEI mode during system boot up.
1599 *
1600 * This function sets the MCG to FEI mode from the reset mode. It can also be used to
1601 * set up MCG during system boot up.
1602 *
1603 * param dmx32 DMX32 in FEI mode.
1604 * param drs The DCO range selection.
1605 * param fllStableDelay Delay function to ensure that the FLL is stable.
1606 *
1607 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1608 * retval kStatus_Success Switched to the target mode successfully.
1609 * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1610 * to frequency above 32768 Hz.
1611 */
1612status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1613{
1614 return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay);
1615}
1616
1617/*!
1618 * brief Sets the MCG to FEE mode during system bootup.
1619 *
1620 * This function sets MCG to FEE mode from the reset mode. It can also be used to
1621 * set up the MCG during system boot up.
1622 *
1623 * param oscsel OSC clock select, OSCSEL.
1624 * param frdiv FLL reference clock divider setting, FRDIV.
1625 * param dmx32 DMX32 in FEE mode.
1626 * param drs The DCO range selection.
1627 * param fllStableDelay Delay function to ensure that the FLL is stable.
1628 *
1629 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1630 * retval kStatus_Success Switched to the target mode successfully.
1631 */
1632status_t CLOCK_BootToFeeMode(
1633 mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1634{
1635 (void)CLOCK_SetExternalRefClkConfig(oscsel);
1636
1637 return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay);
1638}
1639
1640/*!
1641 * brief Sets the MCG to BLPI mode during system boot up.
1642 *
1643 * This function sets the MCG to BLPI mode from the reset mode. It can also be used to
1644 * set up the MCG during system boot up.
1645 *
1646 * param fcrdiv Fast IRC divider, FCRDIV.
1647 * param ircs The internal reference clock to select, IRCS.
1648 * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode.
1649 *
1650 * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting.
1651 * retval kStatus_Success Switched to the target mode successfully.
1652 */
1653status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode)
1654{
1655 /* If reset mode is FEI mode, set MCGIRCLK and always success. */
1656 (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv);
1657
1658 /* If reset mode is not BLPI, first enter FBI mode. */
1659 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal));
1660 while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt)
1661 {
1662 }
1663
1664 /* Enter BLPI mode. */
1665 MCG->C2 |= MCG_C2_LP_MASK;
1666
1667 return kStatus_Success;
1668}
1669
1670/*!
1671 * brief Sets the MCG to BLPE mode during system boot up.
1672 *
1673 * This function sets the MCG to BLPE mode from the reset mode. It can also be used to
1674 * set up the MCG during system boot up.
1675 *
1676 * param oscsel OSC clock select, MCG_C7[OSCSEL].
1677 *
1678 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1679 * retval kStatus_Success Switched to the target mode successfully.
1680 */
1681status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel)
1682{
1683 (void)CLOCK_SetExternalRefClkConfig(oscsel);
1684
1685 /* Set to FBE mode. */
1686 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) |
1687 (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */
1688 | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */
1689
1690 /* If use external crystal as clock source, wait for it stable. */
1691 if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
1692 {
1693 if (0U != (MCG->C2 & MCG_C2_EREFS_MASK))
1694 {
1695 while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
1696 {
1697 }
1698 }
1699 }
1700
1701 /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */
1702 while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
1703 (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt)))
1704 {
1705 }
1706
1707 /* In FBE now, start to enter BLPE. */
1708 MCG->C2 |= MCG_C2_LP_MASK;
1709
1710 return kStatus_Success;
1711}
1712
1713/*
1714 The transaction matrix. It defines the path for mode switch, the row is for
1715 current mode and the column is target mode.
1716 For example, switch from FEI to PEE:
1717 1. Current mode FEI, next mode is mcgModeMatrix[FEI][PEE] = FBE, so swith to FBE.
1718 2. Current mode FBE, next mode is mcgModeMatrix[FBE][PEE] = PBE, so swith to PBE.
1719 3. Current mode PBE, next mode is mcgModeMatrix[PBE][PEE] = PEE, so swith to PEE.
1720 Thus the MCG mode has changed from FEI to PEE.
1721 */
1722static const mcg_mode_t mcgModeMatrix[6][6] = {
1723 {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE}, /* FEI */
1724 {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE}, /* FBI */
1725 {kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI}, /* BLPI */
1726 {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE}, /* FEE */
1727 {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeBLPE}, /* FBE */
1728 {kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeBLPE}, /* BLPE */
1729 /* FEI FBI BLPI FEE FBE BLPE */
1730};
1731
1732/*!
1733 * brief Sets the MCG to a target mode.
1734 *
1735 * This function sets MCG to a target mode defined by the configuration
1736 * structure. If switching to the target mode fails, this function
1737 * chooses the correct path.
1738 *
1739 * param config Pointer to the target MCG mode configuration structure.
1740 * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status.
1741 *
1742 * note If the external clock is used in the target mode, ensure that it is
1743 * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this
1744 * function.
1745 */
1746status_t CLOCK_SetMcgConfig(const mcg_config_t *config)
1747{
1748 mcg_mode_t next_mode;
1749 status_t status = kStatus_Success;
1750
1751 /* If need to change external clock, MCG_C7[OSCSEL]. */
1752 if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel))
1753 {
1754 /* If external clock is in use, change to FEI first. */
1755 if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
1756 {
1757 (void)CLOCK_ExternalModeToFbeModeQuick();
1758 (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL);
1759 }
1760
1761 (void)CLOCK_SetExternalRefClkConfig(config->oscsel);
1762 }
1763
1764 /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */
1765 if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt)
1766 {
1767 MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */
1768
1769 {
1770 (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay);
1771 }
1772 }
1773
1774 /* Configure MCGIRCLK. */
1775 (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv);
1776
1777 next_mode = CLOCK_GetMode();
1778
1779 do
1780 {
1781 next_mode = mcgModeMatrix[next_mode][config->mcgMode];
1782
1783 switch (next_mode)
1784 {
1785 case kMCG_ModeFEI:
1786 status = CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay);
1787 break;
1788 case kMCG_ModeFEE:
1789 status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay);
1790 break;
1791 case kMCG_ModeFBI:
1792 status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL);
1793 break;
1794 case kMCG_ModeFBE:
1795 status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL);
1796 break;
1797 case kMCG_ModeBLPI:
1798 status = CLOCK_SetBlpiMode();
1799 break;
1800 case kMCG_ModeBLPE:
1801 status = CLOCK_SetBlpeMode();
1802 break;
1803 default:
1804 assert(false);
1805 break;
1806 }
1807 if (kStatus_Success != status)
1808 {
1809 break;
1810 }
1811 } while (next_mode != config->mcgMode);
1812
1813 return status;
1814}