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_SYSDIV_VAL     ((SIM->CLKDIV1 & SIM_CLKDIV1_SYSDIV_MASK) >> SIM_CLKDIV1_SYSDIV_SHIFT)
72 #define SIM_CLKDIV1_SYSCLKMODE_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_SYSCLKMODE_MASK) >> SIM_CLKDIV1_SYSCLKMODE_SHIFT)
73 #define SIM_SOPT1_OSC32KSEL_VAL    ((SIM->SOPT1 & SIM_SOPT1_OSC32KSEL_MASK) >> SIM_SOPT1_OSC32KSEL_SHIFT)
74 #define SIM_MISC_CTL_AFECLKSEL_VAL ((SIM->MISC_CTL & SIM_MISC_CTL_AFECLKSEL_MASK) >> SIM_MISC_CTL_AFECLKSEL_SHIFT)
75 
76 /* MCG_S_CLKST definition. */
77 enum _mcg_clkout_stat
78 {
79     kMCG_ClkOutStatFll, /* FLL.            */
80     kMCG_ClkOutStatInt, /* Internal clock. */
81     kMCG_ClkOutStatExt, /* External clock. */
82     kMCG_ClkOutStatPll  /* PLL.            */
83 };
84 
85 /* MCG_S_PLLST definition. */
86 enum _mcg_pllst
87 {
88     kMCG_PllstFll, /* FLL is used. */
89     kMCG_PllstPll  /* PLL is used. */
90 };
91 
92 /*******************************************************************************
93  * Variables
94  ******************************************************************************/
95 
96 /* Slow internal reference clock frequency. */
97 static uint32_t s_slowIrcFreq = 32768U;
98 /* Fast internal reference clock frequency. */
99 static uint32_t s_fastIrcFreq = 4000000U;
100 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
101 /* The MCG external PLL clock frequency. */
102 static uint32_t s_extPllFreq = 0U;
103 #endif
104 
105 /* External XTAL0 (OSC0) clock frequency. */
106 volatile uint32_t g_xtal0Freq;
107 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && (FSL_FEATURE_SOC_OSC_COUNT > 1))
108 /* External XTAL1 (OSC1) clock frequency. */
109 volatile uint32_t g_xtal1Freq;
110 #endif /* FSL_FEATURE_SOC_OSC_COUNT > 1 */
111 /* External XTAL32K clock frequency. */
112 volatile uint32_t g_xtal32Freq;
113 
114 /*******************************************************************************
115  * Prototypes
116  ******************************************************************************/
117 
118 /*!
119  * @brief Get the MCG external reference clock frequency.
120  *
121  * Get the current MCG external reference clock frequency in Hz. It is
122  * the frequency select by MCG_C7[OSCSEL]. This is an internal function.
123  *
124  * @return MCG external reference clock frequency in Hz.
125  */
126 static uint32_t CLOCK_GetMcgExtClkFreq(void);
127 
128 /*!
129  * @brief Get the MCG FLL external reference clock frequency.
130  *
131  * Get the current MCG FLL external reference clock frequency in Hz. It is
132  * the frequency after by MCG_C1[FRDIV]. This is an internal function.
133  *
134  * @return MCG FLL external reference clock frequency in Hz.
135  */
136 static uint32_t CLOCK_GetFllExtRefClkFreq(void);
137 
138 /*!
139  * @brief Get the MCG FLL reference clock frequency.
140  *
141  * Get the current MCG FLL reference clock frequency in Hz. It is
142  * the frequency select by MCG_C1[IREFS]. This is an internal function.
143  *
144  * @return MCG FLL reference clock frequency in Hz.
145  */
146 static uint32_t CLOCK_GetFllRefClkFreq(void);
147 
148 /*!
149  * @brief Get the frequency of clock selected by MCG_C2[IRCS].
150  *
151  * This clock's two output:
152  *  1. MCGOUTCLK when MCG_S[CLKST]=0.
153  *  2. MCGIRCLK when MCG_C1[IRCLKEN]=1.
154  *
155  * @return The frequency in Hz.
156  */
157 static uint32_t CLOCK_GetInternalRefClkSelectFreq(void);
158 
159 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
160 /*!
161  * @brief Get the MCG PLL/PLL0 reference clock frequency.
162  *
163  * Get the current MCG PLL/PLL0 reference clock frequency in Hz.
164  * This is an internal function.
165  *
166  * @return MCG PLL/PLL0 reference clock frequency in Hz.
167  */
168 static uint32_t CLOCK_GetPll0RefFreq(void);
169 
170 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
171 /*!
172  * @brief Get the MCG PLL1 reference clock frequency.
173  *
174  * Get the current MCG PLL1 reference clock frequency in Hz.
175  * This is an internal function.
176  *
177  * @return MCG PLL1 reference clock frequency in Hz.
178  */
179 static uint32_t CLOCK_GetPll1RefFreq(void);
180 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
181 
182 #endif /* FSL_FEATURE_MCG_HAS_PLL */
183 
184 /*!
185  * @brief Calculate the RANGE value base on crystal frequency.
186  *
187  * To setup external crystal oscillator, must set the register bits RANGE
188  * base on the crystal frequency. This function returns the RANGE base on the
189  * input frequency. This is an internal function.
190  *
191  * @param freq Crystal frequency in Hz.
192  * @return The RANGE value.
193  */
194 static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq);
195 
196 #ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN
197 /*!
198  * @brief Delay function to wait FLL stable.
199  *
200  * Delay function to wait FLL stable in FEI mode or FEE mode, should wait at least
201  * 1ms. Every time changes FLL setting, should wait this time for FLL stable.
202  */
203 static void CLOCK_FllStableDelay(void);
204 #endif
205 
206 /*******************************************************************************
207  * Code
208  ******************************************************************************/
209 
210 #ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN
CLOCK_FllStableDelay(void)211 static void CLOCK_FllStableDelay(void)
212 {
213     /*
214        Should wait at least 1ms. Because in these modes, the core clock is 100MHz
215        at most, so this function could obtain the 1ms delay.
216      */
217     volatile uint32_t i = 30000U;
218     while (0U != (i--))
219     {
220         __NOP();
221     }
222 }
223 #else  /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */
224 /* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, they have to
225  * create their own CLOCK_FllStableDelay() function in application code. Since the clock functions in this
226  * file would call the CLOCK_FllStableDelay() regardless how it is defined.
227  */
228 extern void CLOCK_FllStableDelay(void);
229 #endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */
230 
CLOCK_GetMcgExtClkFreq(void)231 static uint32_t CLOCK_GetMcgExtClkFreq(void)
232 {
233 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
234     uint32_t freq;
235 
236     switch (MCG_C7_OSCSEL_VAL)
237     {
238         case 0U:
239             /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
240             assert(0U != g_xtal0Freq);
241             freq = g_xtal0Freq;
242             break;
243         case 1U:
244             /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */
245             assert(0U != g_xtal32Freq);
246             freq = g_xtal32Freq;
247             break;
248 #if (defined(FSL_FEATURE_MCG_HAS_IRC_48M) && FSL_FEATURE_MCG_HAS_IRC_48M)
249         case 2U:
250             freq = MCG_INTERNAL_IRC_48M;
251             break;
252 #endif
253         default:
254             freq = 0U;
255             break;
256     }
257 
258     return freq;
259 #else  /* FSL_FEATURE_MCG_USE_OSCSEL */
260     /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
261     assert(0U != g_xtal0Freq);
262     return g_xtal0Freq;
263 #endif /* FSL_FEATURE_MCG_USE_OSCSEL */
264 }
265 
CLOCK_GetFllExtRefClkFreq(void)266 static uint32_t CLOCK_GetFllExtRefClkFreq(void)
267 {
268     /* FllExtRef = McgExtRef / FllExtRefDiv */
269     uint8_t frdiv;
270     uint8_t range;
271 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
272     uint8_t oscsel;
273 #endif /* FSL_FEATURE_MCG_USE_OSCSEL */
274 
275     uint32_t freq = CLOCK_GetMcgExtClkFreq();
276 
277     frdiv = MCG_C1_FRDIV_VAL;
278     freq >>= frdiv;
279 
280     range = MCG_C2_RANGE_VAL;
281 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
282     oscsel = MCG_C7_OSCSEL_VAL;
283 #endif /* FSL_FEATURE_MCG_USE_OSCSEL */
284 
285     /*
286        When should use divider 32, 64, 128, 256, 512, 1024, 1280, 1536.
287        1. MCG_C7[OSCSEL] selects IRC48M.
288        2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0.
289     */
290     if (((0U != range)
291 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
292          && ((uint8_t)kMCG_OscselOsc == oscsel)
293 #endif /* FSL_FEATURE_MCG_USE_OSCSEL */
294              )
295 #if (defined(FSL_FEATURE_MCG_HAS_IRC_48M) && FSL_FEATURE_MCG_HAS_IRC_48M)
296         || ((uint8_t)kMCG_OscselIrc == oscsel)
297 #endif /* FSL_FEATURE_MCG_HAS_IRC_48M */
298     )
299     {
300         switch (frdiv)
301         {
302             case 0:
303             case 1:
304             case 2:
305             case 3:
306             case 4:
307             case 5:
308                 freq >>= 5u;
309                 break;
310 #if (defined(FSL_FEATURE_MCG_FRDIV_SUPPORT_1280) && FSL_FEATURE_MCG_FRDIV_SUPPORT_1280)
311             case 6:
312                 /* 64*20=1280 */
313                 freq /= 20u;
314                 break;
315 #endif /* FSL_FEATURE_MCG_FRDIV_SUPPORT_1280 */
316 #if (defined(FSL_FEATURE_MCG_FRDIV_SUPPORT_1536) && FSL_FEATURE_MCG_FRDIV_SUPPORT_1536)
317             case 7:
318                 /* 128*12=1536 */
319                 freq /= 12u;
320                 break;
321 #endif /* FSL_FEATURE_MCG_FRDIV_SUPPORT_1536 */
322             default:
323                 freq = 0u;
324                 break;
325         }
326     }
327 
328     return freq;
329 }
330 
CLOCK_GetInternalRefClkSelectFreq(void)331 static uint32_t CLOCK_GetInternalRefClkSelectFreq(void)
332 {
333     uint32_t freq;
334 
335     if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL)
336     {
337         /* Slow internal reference clock selected*/
338         freq = s_slowIrcFreq;
339     }
340     else
341     {
342         /* Fast internal reference clock selected*/
343         freq = s_fastIrcFreq >> MCG_SC_FCRDIV_VAL;
344     }
345 
346     return freq;
347 }
348 
CLOCK_GetFllRefClkFreq(void)349 static uint32_t CLOCK_GetFllRefClkFreq(void)
350 {
351     uint32_t freq;
352 
353     /* If use external reference clock. */
354     if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
355     {
356         freq = CLOCK_GetFllExtRefClkFreq();
357     }
358     /* If use internal reference clock. */
359     else
360     {
361         freq = s_slowIrcFreq;
362     }
363 
364     return freq;
365 }
366 
367 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
CLOCK_GetPll0RefFreq(void)368 static uint32_t CLOCK_GetPll0RefFreq(void)
369 {
370 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
371     uint32_t freq;
372 
373     mcg_pll_ref_src_t pllRefSrc = (mcg_pll_ref_src_t)(uint8_t)MCG_C7_PLL32KREFSEL_VAL;
374 
375     switch (pllRefSrc)
376     {
377         case kMCG_PllRefRtc:
378             /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */
379             assert(0U != g_xtal32Freq);
380             freq = g_xtal32Freq;
381             break;
382         case kMCG_PllRefIrc:
383             freq = s_slowIrcFreq;
384             break;
385         case kMCG_PllRefFllRef:
386             freq = CLOCK_GetFllExtRefClkFreq();
387             break;
388         default:
389             freq = 0U;
390             break;
391     }
392 
393     return freq;
394 
395 #else /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
396 
397 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
398     /* Use dedicate source. */
399     uint32_t *const pllExtClkFreq = {&g_xtal0Freq, &g_xtal1Freq};
400 
401     return *pllExtClkFreq[MCG_C5_PLLREFSEL0_VAL];
402 #else  /* FSL_FEATURE_MCG_HAS_PLL1 */
403     /* MCG external reference clock. */
404     return CLOCK_GetMcgExtClkFreq();
405 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
406 
407 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
408 }
409 
410 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
CLOCK_GetPll1RefFreq(void)411 static uint32_t CLOCK_GetPll1RefFreq(void)
412 {
413     /* Use dedicate source. */
414     uint32_t *const pllExtClkFreq = {&g_xtal0Freq, &g_xtal1Freq};
415 
416     return *pllExtClkFreq[MCG_C11_PLLREFSEL1_VAL];
417 }
418 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
419 #endif /* FSL_FEATURE_MCG_HAS_PLL */
420 
CLOCK_GetOscRangeFromFreq(uint32_t freq)421 static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq)
422 {
423     uint8_t range;
424 
425     if (freq <= 39063U)
426     {
427         range = 0U;
428     }
429     else if (freq <= 8000000U)
430     {
431         range = 1U;
432     }
433     else
434     {
435         range = 2U;
436     }
437 
438     return range;
439 }
440 
441 /*!
442  * brief Get the OSC0 external reference clock frequency (OSC0ERCLK).
443  *
444  * return Clock frequency in Hz.
445  */
CLOCK_GetOsc0ErClkFreq(void)446 uint32_t CLOCK_GetOsc0ErClkFreq(void)
447 {
448     uint32_t freq;
449 
450     if ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U)
451     {
452         /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
453         assert(g_xtal0Freq);
454         freq = g_xtal0Freq;
455     }
456     else
457     {
458         freq = 0U;
459     }
460 
461     return freq;
462 }
463 
464 /*!
465  * brief Get the external reference 32K clock frequency (ERCLK32K).
466  *
467  * return Clock frequency in Hz.
468  */
CLOCK_GetEr32kClkFreq(void)469 uint32_t CLOCK_GetEr32kClkFreq(void)
470 {
471     uint32_t freq;
472 
473     switch (SIM_SOPT1_OSC32KSEL_VAL)
474     {
475         case 0U: /* OSC 32k clock  */
476             /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */
477             assert(g_xtal32Freq);
478             freq = g_xtal32Freq;
479             break;
480         case 1U: /* RTC 32k clock  */
481             freq = (CLOCK_GetOsc0ErClkFreq() == 32768U) ? 32768U : 0U;
482             break;
483         case 2U: /* MCG internal reference clock (MCGIRCLK)  */
484             freq = (uint32_t)kCLOCK_McgInternalRefClk;
485             break;
486         case 3U: /* LPO clock      */
487             freq = LPO_CLK_FREQ;
488             break;
489         default:
490             freq = 0U;
491             break;
492     }
493     return freq;
494 }
495 
496 /*!
497  * brief Gets the clock frequency for AFE module.
498  *
499  * This function checks the current mode configurations in MISC_CTL register.
500  *
501  * return Clock frequency value in Hertz
502  */
CLOCK_GetAfeFreq(void)503 uint32_t CLOCK_GetAfeFreq(void)
504 {
505     uint32_t freq;
506 
507     switch (SIM_MISC_CTL_AFECLKSEL_VAL)
508     {
509         case 0U: /* PLL. */
510             freq = CLOCK_GetPll0Freq();
511             break;
512         case 1U: /* FLL. */
513             freq = CLOCK_GetFllFreq();
514             break;
515         case 2U: /* OSC. */
516             freq = CLOCK_GetOsc0ErClkFreq();
517             break;
518         default:
519             freq = 0U;
520             break;
521     }
522     return freq;
523 }
524 
525 /*!
526  * brief Get the platform clock frequency.
527  *
528  * return Clock frequency in Hz.
529  */
CLOCK_GetPlatClkFreq(void)530 uint32_t CLOCK_GetPlatClkFreq(void)
531 {
532     return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_SYSDIV_VAL + 1UL);
533 }
534 
535 /*!
536  * brief Get the flash clock frequency.
537  *
538  * return Clock frequency in Hz.
539  */
CLOCK_GetFlashClkFreq(void)540 uint32_t CLOCK_GetFlashClkFreq(void)
541 {
542     uint32_t freq;
543 
544     freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_SYSDIV_VAL + 1UL);
545     freq /= (SIM_CLKDIV1_SYSCLKMODE_VAL + 1UL);
546 
547     return freq;
548 }
549 
550 /*!
551  * brief Get the bus clock frequency.
552  *
553  * return Clock frequency in Hz.
554  */
CLOCK_GetBusClkFreq(void)555 uint32_t CLOCK_GetBusClkFreq(void)
556 {
557     uint32_t freq;
558 
559     freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_SYSDIV_VAL + 1UL);
560     freq /= (SIM_CLKDIV1_SYSCLKMODE_VAL + 1UL);
561 
562     return freq;
563 }
564 
565 /*!
566  * brief Get the core clock or system clock frequency.
567  *
568  * return Clock frequency in Hz.
569  */
CLOCK_GetCoreSysClkFreq(void)570 uint32_t CLOCK_GetCoreSysClkFreq(void)
571 {
572     return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_SYSDIV_VAL + 1UL);
573 }
574 
575 /*!
576  * brief Gets the clock frequency for a specific clock name.
577  *
578  * This function checks the current clock configurations and then calculates
579  * the clock frequency for a specific clock name defined in clock_name_t.
580  * The MCG must be properly configured before using this function.
581  *
582  * param clockName Clock names defined in clock_name_t
583  * return Clock frequency value in Hertz
584  */
CLOCK_GetFreq(clock_name_t clockName)585 uint32_t CLOCK_GetFreq(clock_name_t clockName)
586 {
587     uint32_t freq;
588 
589     switch (clockName)
590     {
591         case kCLOCK_CoreSysClk:
592         case kCLOCK_PlatClk:
593             freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_SYSDIV_VAL + 1UL);
594             break;
595         case kCLOCK_BusClk:
596             freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_SYSDIV_VAL + 1UL);
597             freq /= (SIM_CLKDIV1_SYSCLKMODE_VAL + 1UL);
598             break;
599         case kCLOCK_FlashClk:
600             freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_SYSDIV_VAL + 1UL);
601             freq /= (SIM_CLKDIV1_SYSCLKMODE_VAL + 1UL);
602             break;
603         case kCLOCK_Er32kClk:
604             freq = CLOCK_GetEr32kClkFreq();
605             break;
606         case kCLOCK_McgFixedFreqClk:
607             freq = CLOCK_GetFixedFreqClkFreq();
608             break;
609         case kCLOCK_McgInternalRefClk:
610             freq = CLOCK_GetInternalRefClkFreq();
611             break;
612         case kCLOCK_McgFllClk:
613             freq = CLOCK_GetFllFreq();
614             break;
615         case kCLOCK_McgPll0Clk:
616             freq = CLOCK_GetPll0Freq();
617             break;
618         case kCLOCK_LpoClk:
619             freq = LPO_CLK_FREQ;
620             break;
621         case kCLOCK_Osc0ErClk:
622             freq = CLOCK_GetOsc0ErClkFreq();
623             break;
624         default:
625             freq = 0U;
626             break;
627     }
628 
629     return freq;
630 }
631 
632 /*!
633  * brief Set the clock configure in SIM module.
634  *
635  * This function sets system layer clock settings in SIM module.
636  *
637  * param config Pointer to the configure structure.
638  */
CLOCK_SetSimConfig(sim_clock_config_t const * config)639 void CLOCK_SetSimConfig(sim_clock_config_t const *config)
640 {
641     SIM->CLKDIV1 = config->clkdiv1;
642     CLOCK_SetEr32kClock(config->er32kSrc);
643 }
644 
645 /*!
646  * brief Gets the MCG output clock (MCGOUTCLK) frequency.
647  *
648  * This function gets the MCG output clock frequency in Hz based on the current MCG
649  * register value.
650  *
651  * return The frequency of MCGOUTCLK.
652  */
CLOCK_GetOutClkFreq(void)653 uint32_t CLOCK_GetOutClkFreq(void)
654 {
655     uint32_t mcgoutclk;
656     uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL;
657 #if ((defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1) || \
658      (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL))
659     uint32_t pllcst = MCG_S2_PLLCST_VAL;
660 #endif
661 
662     switch (clkst)
663     {
664 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
665         case (uint32_t)kMCG_ClkOutStatPll:
666 #if ((defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1) || \
667      (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL))
668             switch (pllcst)
669             {
670 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
671                 case (uint32_t)kMCG_PllClkSelPll1:
672                     mcgoutclk = CLOCK_GetPll1Freq();
673                     break;
674 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
675 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
676                 case (uint32_t)kMCG_PllClkSelExtPll:
677                     mcgoutclk = CLOCK_GetExtPllFreq();
678                     break;
679 #endif /* FSL_FEATURE_MCG_HAS_EXTERNAL_PLL */
680                 case (uint32_t)kMCG_PllClkSelPll0:
681                     mcgoutclk = CLOCK_GetPll0Freq();
682                     break;
683                 default:
684                     mcgoutclk = 0U;
685                     break;
686             }
687 #else  /* (FSL_FEATURE_MCG_HAS_PLL1 || FSL_FEATURE_MCG_HAS_EXTERNAL_PLL */
688             mcgoutclk = CLOCK_GetPll0Freq();
689 #endif /* (FSL_FEATURE_MCG_HAS_PLL1 || FSL_FEATURE_MCG_HAS_EXTERNAL_PLL */
690             break;
691 #endif /* FSL_FEATURE_MCG_HAS_PLL */
692         case (uint32_t)kMCG_ClkOutStatFll:
693             mcgoutclk = CLOCK_GetFllFreq();
694             break;
695         case (uint32_t)kMCG_ClkOutStatInt:
696             mcgoutclk = CLOCK_GetInternalRefClkSelectFreq();
697             break;
698         case (uint32_t)kMCG_ClkOutStatExt:
699             mcgoutclk = CLOCK_GetMcgExtClkFreq();
700             break;
701         default:
702             mcgoutclk = 0U;
703             break;
704     }
705 
706     return mcgoutclk;
707 }
708 
709 /*!
710  * brief Gets the MCG FLL clock (MCGFLLCLK) frequency.
711  *
712  * This function gets the MCG FLL clock frequency in Hz based on the current MCG
713  * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and
714  * disabled in low power state in other modes.
715  *
716  * return The frequency of MCGFLLCLK.
717  */
CLOCK_GetFllFreq(void)718 uint32_t CLOCK_GetFllFreq(void)
719 {
720     static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}};
721 
722     uint8_t drs, dmx32;
723     uint32_t freq;
724     uint32_t ret;
725 
726     /* If FLL is not enabled currently, then return 0U. */
727     if (
728 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
729         (((MCG->C2 & MCG_C2_LP_MASK) != 0U) || ((MCG->S & MCG_S_PLLST_MASK) != 0U))
730 #else
731         0U != (MCG->C2 & MCG_C2_LP_MASK)
732 #endif /* FSL_FEATURE_MCG_HAS_PLL */
733     )
734     {
735         ret = 0U;
736     }
737     else
738     {
739         /* Get FLL reference clock frequency. */
740         freq = CLOCK_GetFllRefClkFreq();
741         if (0U == freq)
742         {
743             ret = freq;
744         }
745         else
746         {
747             drs   = MCG_C4_DRST_DRS_VAL;
748             dmx32 = MCG_C4_DMX32_VAL;
749             ret   = freq * fllFactorTable[drs][dmx32];
750         }
751     }
752 
753     return ret;
754 }
755 
756 /*!
757  * brief Gets the MCG internal reference clock (MCGIRCLK) frequency.
758  *
759  * This function gets the MCG internal reference clock frequency in Hz based
760  * on the current MCG register value.
761  *
762  * return The frequency of MCGIRCLK.
763  */
CLOCK_GetInternalRefClkFreq(void)764 uint32_t CLOCK_GetInternalRefClkFreq(void)
765 {
766     uint32_t freq;
767 
768     /* If MCGIRCLK is gated. */
769     if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK))
770     {
771         freq = 0U;
772     }
773     else
774     {
775         freq = CLOCK_GetInternalRefClkSelectFreq();
776     }
777 
778     return freq;
779 }
780 
781 /*!
782  * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency.
783  *
784  * This function gets the MCG fixed frequency clock frequency in Hz based
785  * on the current MCG register value.
786  *
787  * return The frequency of MCGFFCLK.
788  */
CLOCK_GetFixedFreqClkFreq(void)789 uint32_t CLOCK_GetFixedFreqClkFreq(void)
790 {
791 #if (defined(FSL_FEATURE_MCG_FFCLK_DIV) && (FSL_FEATURE_MCG_FFCLK_DIV > 1))
792     uint32_t freq = CLOCK_GetFllRefClkFreq() / FSL_FEATURE_MCG_FFCLK_DIV;
793 #else  /* FSL_FEATURE_MCG_FFCLK_DIV */
794     uint32_t freq = CLOCK_GetFllRefClkFreq();
795 #endif /* FSL_FEATURE_MCG_FFCLK_DIV */
796     uint32_t ret;
797 
798     /* MCGFFCLK must be no more than MCGOUTCLK/8. */
799     if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq))
800     {
801         ret = freq;
802     }
803     else
804     {
805         ret = 0U;
806     }
807 
808     return ret;
809 }
810 
811 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
812 /*!
813  * brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency.
814  *
815  * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG
816  * register value.
817  *
818  * return The frequency of MCGPLL0CLK.
819  */
CLOCK_GetPll0Freq(void)820 uint32_t CLOCK_GetPll0Freq(void)
821 {
822     uint32_t mcgpll0clk;
823     uint32_t freq;
824 
825 #if ((defined(FSL_FEATURE_MCG_HAS_PLL_PRDIV) && FSL_FEATURE_MCG_HAS_PLL_PRDIV) && \
826      (defined(FSL_FEATURE_MCG_HAS_PLL_VDIV) && FSL_FEATURE_MCG_HAS_PLL_VDIV))
827     uint8_t mcgpll0prdiv;
828     uint8_t mcgpll0vdiv;
829 #endif
830     /* If PLL0 is not enabled, return 0. */
831     if (((MCG->S & MCG_S_LOCK0_MASK)) == 0U)
832     {
833         freq = 0U;
834     }
835     else
836     {
837         mcgpll0clk = CLOCK_GetPll0RefFreq();
838 
839         /*
840          * Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock.
841          * Please call CLOCK_SetXtal1Freq base on board setting before using OSC1 clock.
842          */
843         assert(mcgpll0clk);
844 
845 #if ((defined(FSL_FEATURE_MCG_HAS_PLL_PRDIV) && FSL_FEATURE_MCG_HAS_PLL_PRDIV) && \
846      (defined(FSL_FEATURE_MCG_HAS_PLL_VDIV) && FSL_FEATURE_MCG_HAS_PLL_VDIV))
847         mcgpll0prdiv = ((uint8_t)FSL_FEATURE_MCG_PLL_PRDIV_BASE + MCG_C5_PRDIV0_VAL);
848         mcgpll0clk /= (uint32_t)mcgpll0prdiv;
849         mcgpll0vdiv = ((uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE + MCG_C6_VDIV0_VAL);
850         mcgpll0clk *= (uint32_t)mcgpll0vdiv;
851 
852 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV)
853         mcgpll0clk >>= 1UL;
854 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV */
855         freq = mcgpll0clk;
856 #else  /* FSL_FEATURE_MCG_HAS_PLL_PRDIV && FSL_FEATURE_MCG_HAS_PLL_VDIV) */
857         freq = mcgpll0clk * PLL_FIXED_MULT;
858 #endif /* FSL_FEATURE_MCG_HAS_PLL_PRDIV && FSL_FEATURE_MCG_HAS_PLL_VDIV) */
859     }
860 
861     return freq;
862 }
863 
864 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
865 /*!
866  * brief Gets the MCG PLL1 clock (MCGPLL1CLK) frequency.
867  *
868  * This function gets the MCG PLL1 clock frequency in Hz based on the current MCG
869  * register value.
870  *
871  * return The frequency of MCGPLL1CLK.
872  */
CLOCK_GetPll1Freq(void)873 uint32_t CLOCK_GetPll1Freq(void)
874 {
875     uint32_t mcgpll1clk;
876 
877     /* If PLL1 is not enabled, return 0. */
878     if (!(MCG->S2 & MCG_S2_LOCK1_MASK))
879     {
880         return 0U;
881     }
882 
883     mcgpll1clk = CLOCK_GetPll1RefFreq();
884 
885     /*
886      * Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock.
887      * Please call CLOCK_SetXtal1Freq base on board setting before using OSC1 clock.
888      */
889     assert(mcgpll1clk);
890 
891     mcgpll1clk /= (FSL_FEATURE_MCG_PLL_PRDIV_BASE + MCG_C11_PRDIV1_VAL);
892     mcgpll1clk *= (FSL_FEATURE_MCG_PLL_VDIV_BASE + MCG_C12_VDIV1_VAL);
893 
894 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV)
895     mcgpll1clk >>= 1U;
896 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV */
897     return mcgpll1clk;
898 }
899 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
900 
901 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
902 /*!
903  * brief Gets the MCG external PLL frequency.
904  *
905  * This function gets the MCG external PLL frequency in Hz.
906  *
907  * return The frequency of the MCG external PLL.
908  */
CLOCK_GetExtPllFreq(void)909 uint32_t CLOCK_GetExtPllFreq(void)
910 {
911     return s_extPllFreq;
912 }
913 
914 /*!
915  * brief Sets the MCG external PLL frequency.
916  *
917  * This function sets the MCG external PLL frequency in Hz. The MCG external PLL
918  * frequency is passed to the MCG driver using this function. Call this
919  * function after the external PLL frequency is changed. Otherwise, the APIs, which are used to get
920  * the frequency, may return an incorrect value.
921  *
922  * param The frequency of MCG external PLL.
923  */
CLOCK_SetExtPllFreq(uint32_t freq)924 void CLOCK_SetExtPllFreq(uint32_t freq)
925 {
926     s_extPllFreq = freq;
927 }
928 #endif /* FSL_FEATURE_MCG_HAS_EXTERNAL_PLL */
929 
930 #endif /* FSL_FEATURE_MCG_HAS_PLL */
931 
932 /*!
933  * brief Selects the MCG external reference clock.
934  *
935  * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL],
936  * and waits for the clock source to be stable. Because the external reference
937  * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes.
938  *
939  * param oscsel MCG external reference clock source, MCG_C7[OSCSEL].
940  * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source,
941  * the configuration should not be changed. Otherwise, a glitch occurs.
942  * retval kStatus_Success External reference clock set successfully.
943  */
CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel)944 status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel)
945 {
946 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
947     bool needDelay;
948     uint32_t i;
949 #endif
950 
951 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
952 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
953     /* If change MCG_C7[OSCSEL] and external reference clock is system clock source, return error. */
954     if ((MCG_C7_OSCSEL_VAL != oscsel) && (!(MCG->S & MCG_S_IREFST_MASK)))
955     {
956         return kStatus_MCG_SourceUsed;
957     }
958 #endif /* FSL_FEATURE_MCG_USE_OSCSEL */
959 #endif /* MCG_CONFIG_CHECK_PARAM */
960 
961 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
962     if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel)
963     {
964         /* If change OSCSEL, need to delay, ERR009878. */
965         needDelay = true;
966     }
967     else
968     {
969         needDelay = false;
970     }
971 #endif
972 
973 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
974     MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel);
975     if (needDelay)
976     {
977         /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */
978         i = 1500U;
979         while (0U != (i--))
980         {
981             __NOP();
982         }
983     }
984 #endif
985 
986     return kStatus_Success;
987 }
988 
989 /*!
990  * brief Configures the Internal Reference clock (MCGIRCLK).
991  *
992  * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC
993  * source. If the fast IRC is used, this function sets the fast IRC divider.
994  * This function also sets whether the \c MCGIRCLK is enabled in stop mode.
995  * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result,
996  * using the function in these modes it is not allowed.
997  *
998  * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode.
999  * param ircs       MCGIRCLK clock source, choose fast or slow.
1000  * param fcrdiv     Fast IRC divider setting (\c FCRDIV).
1001  * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source,
1002  * the configuration should not be changed. Otherwise, a glitch occurs.
1003  * retval kStatus_Success MCGIRCLK configuration finished successfully.
1004  */
CLOCK_SetInternalRefClkConfig(uint8_t enableMode,mcg_irc_mode_t ircs,uint8_t fcrdiv)1005 status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv)
1006 {
1007     uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL;
1008     mcg_irc_mode_t curIrcs  = (mcg_irc_mode_t)((uint32_t)MCG_S_IRCST_VAL);
1009     uint8_t curFcrdiv       = MCG_SC_FCRDIV_VAL;
1010 
1011 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1012     /* If MCGIRCLK is used as system clock source. */
1013     if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState)
1014     {
1015         /* If need to change MCGIRCLK source or driver, return error. */
1016         if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs))
1017         {
1018             return kStatus_MCG_SourceUsed;
1019         }
1020     }
1021 #endif
1022 
1023     /* If need to update the FCRDIV. */
1024     if (fcrdiv != curFcrdiv)
1025     {
1026         /* If fast IRC is in use currently, change to slow IRC. */
1027         if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) &&
1028             (kMCG_IrcFast == curIrcs))
1029         {
1030             MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow)));
1031             while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow)
1032             {
1033             }
1034         }
1035         /* Update FCRDIV. */
1036         MCG->SC =
1037             (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv);
1038     }
1039 
1040     /* Set internal reference clock selection. */
1041     MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)));
1042     MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode);
1043 
1044     /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */
1045     if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable)))
1046     {
1047         while (MCG_S_IRCST_VAL != (uint8_t)ircs)
1048         {
1049         }
1050     }
1051 
1052     return kStatus_Success;
1053 }
1054 
1055 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
1056 #if ((defined(FSL_FEATURE_MCG_HAS_PLL_PRDIV) && FSL_FEATURE_MCG_HAS_PLL_PRDIV)) && \
1057     ((defined(FSL_FEATURE_MCG_HAS_PLL_VDIV) && FSL_FEATURE_MCG_HAS_PLL_VDIV))
1058 /*!
1059  * brief Calculates the PLL divider setting for a desired output frequency.
1060  *
1061  * This function calculates the correct reference clock divider (\c PRDIV) and
1062  * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the
1063  * closest frequency match with the corresponding \c PRDIV/VDIV
1064  * returned from parameters. If a desired frequency is not valid, this function
1065  * returns 0.
1066  *
1067  * param refFreq    PLL reference clock frequency.
1068  * param desireFreq Desired PLL output frequency.
1069  * param prdiv      PRDIV value to generate desired PLL frequency.
1070  * param vdiv       VDIV value to generate desired PLL frequency.
1071  * return Closest frequency match that the PLL was able generate.
1072  */
CLOCK_CalcPllDiv(uint32_t refFreq,uint32_t desireFreq,uint8_t * prdiv,uint8_t * vdiv)1073 uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv)
1074 {
1075     uint8_t ret_prdiv;               /* PRDIV to return. */
1076     uint8_t ret_vdiv;                /* VDIV to return.  */
1077     uint8_t prdiv_min;               /* Min PRDIV value to make reference clock in allowed range. */
1078     uint8_t prdiv_max;               /* Max PRDIV value to make reference clock in allowed range. */
1079     uint8_t prdiv_cur;               /* PRDIV value for iteration.    */
1080     uint8_t vdiv_cur;                /* VDIV value for iteration.     */
1081     uint32_t ret_freq = 0U;          /* PLL output frequency to return. */
1082     uint32_t diff     = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */
1083     uint32_t ref_div;                /* Reference frequency after PRDIV. */
1084 
1085     /*
1086        Steps:
1087        1. Get allowed prdiv with such rules:
1088           1). refFreq / prdiv >= FSL_FEATURE_MCG_PLL_REF_MIN.
1089           2). refFreq / prdiv <= FSL_FEATURE_MCG_PLL_REF_MAX.
1090        2. For each allowed prdiv, there are two candidate vdiv values:
1091           1). (desireFreq / (refFreq / prdiv)).
1092           2). (desireFreq / (refFreq / prdiv)) + 1.
1093           If could get the precise desired frequency, return current prdiv and
1094           vdiv directly. Otherwise choose the one which is closer to desired
1095           frequency.
1096      */
1097 
1098     /* Reference frequency is out of range. */
1099     if ((refFreq < (uint32_t)FSL_FEATURE_MCG_PLL_REF_MIN) ||
1100         (refFreq > ((uint32_t)FSL_FEATURE_MCG_PLL_REF_MAX *
1101                     ((uint32_t)FSL_FEATURE_MCG_PLL_PRDIV_MAX + (uint32_t)FSL_FEATURE_MCG_PLL_PRDIV_BASE))))
1102     {
1103         return 0U;
1104     }
1105 
1106     /* refFreq/PRDIV must in a range. First get the allowed PRDIV range. */
1107     prdiv_max = (uint8_t)(refFreq / (uint32_t)FSL_FEATURE_MCG_PLL_REF_MIN);
1108     prdiv_min =
1109         (uint8_t)((refFreq + (uint32_t)FSL_FEATURE_MCG_PLL_REF_MAX - 1U) / (uint32_t)FSL_FEATURE_MCG_PLL_REF_MAX);
1110 
1111 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV)
1112     desireFreq *= 2U;
1113 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV */
1114 
1115     /* PRDIV traversal. */
1116     for (prdiv_cur = prdiv_max; prdiv_cur >= prdiv_min; prdiv_cur--)
1117     {
1118         /* Reference frequency after PRDIV. */
1119         ref_div = refFreq / prdiv_cur;
1120 
1121         vdiv_cur = (uint8_t)(desireFreq / ref_div);
1122 
1123         if ((vdiv_cur < ((uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE - 1U)) ||
1124             (vdiv_cur > (uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE + 31U))
1125         {
1126             /* No VDIV is available with this PRDIV. */
1127             continue;
1128         }
1129 
1130         ret_freq = vdiv_cur * ref_div;
1131 
1132         if (vdiv_cur >= (uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE)
1133         {
1134             if (ret_freq == desireFreq) /* If desire frequency is got. */
1135             {
1136                 *prdiv = prdiv_cur - (uint8_t)FSL_FEATURE_MCG_PLL_PRDIV_BASE;
1137                 *vdiv  = vdiv_cur - (uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE;
1138 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV)
1139                 return ret_freq / 2U;
1140 #else  /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV */
1141                 return ret_freq;
1142 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV */
1143             }
1144             /* New PRDIV/VDIV is closer. */
1145             if (diff > desireFreq - ret_freq)
1146             {
1147                 diff      = desireFreq - ret_freq;
1148                 ret_prdiv = prdiv_cur;
1149                 ret_vdiv  = vdiv_cur;
1150             }
1151         }
1152         vdiv_cur++;
1153         if (vdiv_cur <= ((uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE + 31U))
1154         {
1155             ret_freq += ref_div;
1156             /* New PRDIV/VDIV is closer. */
1157             if (diff > ret_freq - desireFreq)
1158             {
1159                 diff      = ret_freq - desireFreq;
1160                 ret_prdiv = prdiv_cur;
1161                 ret_vdiv  = vdiv_cur;
1162             }
1163         }
1164     }
1165 
1166     if (0xFFFFFFFFU != diff)
1167     {
1168         /* PRDIV/VDIV found. */
1169         *prdiv   = ret_prdiv - (uint8_t)FSL_FEATURE_MCG_PLL_PRDIV_BASE;
1170         *vdiv    = ret_vdiv - (uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE;
1171         ret_freq = (refFreq / ret_prdiv) * ret_vdiv;
1172 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV)
1173         return ret_freq / 2U;
1174 #else  /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV */
1175         return ret_freq;
1176 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_DIV */
1177     }
1178     else
1179     {
1180         /* No proper PRDIV/VDIV found. */
1181         return 0U;
1182     }
1183 }
1184 #endif /* (FSL_FEATURE_MCG_HAS_PLL_PRDIV && FSL_FEATURE_MCG_HAS_PLL_VDIV) */
1185 
1186 /*!
1187  * brief Enables the PLL0 in FLL mode.
1188  *
1189  * This function sets us the PLL0 in FLL mode and reconfigures
1190  * the PLL0. Ensure that the PLL reference
1191  * clock is enabled before calling this function and that the PLL0 is not used as a clock source.
1192  * The function CLOCK_CalcPllDiv gets the correct PLL
1193  * divider values.
1194  *
1195  * param config Pointer to the configuration structure.
1196  */
CLOCK_EnablePll0(mcg_pll_config_t const * config)1197 void CLOCK_EnablePll0(mcg_pll_config_t const *config)
1198 {
1199     assert(config);
1200 
1201     uint8_t mcg_c5 = 0U;
1202 
1203 #if (defined(FSL_FEATURE_MCG_USE_PLLREFSEL) && FSL_FEATURE_MCG_USE_PLLREFSEL)
1204     mcg_c5 |= MCG_C5_PLLREFSEL0(config->refSrc);
1205 #endif
1206 #if ((defined(FSL_FEATURE_MCG_HAS_PLL_PRDIV) && FSL_FEATURE_MCG_HAS_PLL_PRDIV))
1207     mcg_c5 |= MCG_C5_PRDIV0(config->prdiv);
1208 #endif
1209     MCG->C5 = mcg_c5; /* Disable the PLL first. */
1210 
1211 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
1212     MCG->C7 = (uint8_t)((MCG->C7 & ~MCG_C7_PLL32KREFSEL_MASK) | MCG_C7_PLL32KREFSEL(config->refSrc));
1213 #endif
1214 
1215 #if (defined(FSL_FEATURE_MCG_HAS_PLL_VDIV) && FSL_FEATURE_MCG_HAS_PLL_VDIV)
1216     MCG->C6 = (uint8_t)((MCG->C6 & ~MCG_C6_VDIV0_MASK) | MCG_C6_VDIV0(config->vdiv));
1217 #endif /* FSL_FEATURE_MCG_HAS_PLL_VDIV */
1218 
1219     /* Set enable mode. */
1220     MCG->C5 |= ((uint8_t)kMCG_PllEnableIndependent | (uint8_t)config->enableMode);
1221 
1222     /* Wait for PLL lock. */
1223     while (((MCG->S & MCG_S_LOCK0_MASK)) == 0U)
1224     {
1225     }
1226 }
1227 
1228 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
1229 /*!
1230  * brief Enables the PLL1 in FLL mode.
1231  *
1232  * This function sets up the PLL1 in FLL mode and reconfigures
1233  * the PLL1. Ensure that the PLL reference
1234  * clock is enabled and that the PLL1 is not used as a clock source before calling this function.
1235  * The function CLOCK_CalcPllDiv gets the correct PLL
1236  * divider values.
1237  *
1238  * param config Pointer to the configuration structure.
1239  */
CLOCK_EnablePll1(mcg_pll_config_t const * config)1240 void CLOCK_EnablePll1(mcg_pll_config_t const *config)
1241 {
1242     assert(config);
1243 
1244     uint8_t mcg_c11;
1245 
1246     mcg_c11  = MCG->C11 & MCG_C11_PLLCS_MASK;
1247     MCG->C11 = mcg_c11; /* Disable the PLL1. */
1248     MCG->C12 = (MCG->C12 & ~MCG_C12_VDIV1_MASK) | MCG_C12_VDIV1(config->vdiv);
1249     MCG->C11 = mcg_c11 | MCG_C11_PLLREFSEL1(config->refSrc) | MCG_C11_PRDIV1(config->prdiv) |
1250                (uint32_t)kMCG_PllEnableIndependent | (uint32_t)config->enableMode;
1251 
1252     /* Wait for PLL lock. */
1253     while (!(MCG->S2 & MCG_S2_LOCK1_MASK))
1254     {
1255     }
1256 }
1257 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
1258 
1259 #endif /* FSL_FEATURE_MCG_HAS_PLL */
1260 
1261 #if ((defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) || \
1262      (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1))
1263 /*!
1264  * brief Set the PLL selection.
1265  *
1266  * This function sets the PLL selection between PLL0/PLL1/EXTPLL, and waits for
1267  * change finished.
1268  *
1269  * param pllcs The PLL to select.
1270  */
CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs)1271 void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs)
1272 {
1273     MCG->C11 = (uint8_t)(((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs));
1274     while ((uint32_t)pllcs != MCG_S2_PLLCST_VAL)
1275     {
1276     }
1277 }
1278 #endif /* FSL_FEATURE_MCG_HAS_PLL1 || FSL_FEATURE_MCG_HAS_EXTERNAL_PLL */
1279 
1280 /*!
1281  * brief Sets the OSC0 clock monitor mode.
1282  *
1283  * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details.
1284  *
1285  * param mode Monitor mode to set.
1286  */
CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode)1287 void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode)
1288 {
1289     /* Clear the previous flag, MCG_SC[LOCS0]. */
1290     MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK;
1291 
1292     if (kMCG_MonitorNone == mode)
1293     {
1294         MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK;
1295     }
1296     else
1297     {
1298         if (kMCG_MonitorInt == mode)
1299         {
1300             MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK;
1301         }
1302         else
1303         {
1304             MCG->C2 |= MCG_C2_LOCRE0_MASK;
1305         }
1306         MCG->C6 |= MCG_C6_CME0_MASK;
1307     }
1308 }
1309 
1310 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && (FSL_FEATURE_SOC_OSC_COUNT > 1u))
1311 /*!
1312  * brief Sets the OSC1 clock monitor mode.
1313  *
1314  * This function sets the OSC1 clock monitor mode. See ref mcg_monitor_mode_t for details.
1315  *
1316  * param mode Monitor mode to set.
1317  */
CLOCK_SetOsc1MonitorMode(mcg_monitor_mode_t mode)1318 void CLOCK_SetOsc1MonitorMode(mcg_monitor_mode_t mode)
1319 {
1320     /* Clear previous flag. MCG_S2[LOCS2]. */
1321     MCG->S2 = MCG_S2_LOCS2_MASK;
1322 
1323     if (kMCG_MonitorNone == mode)
1324     {
1325         MCG->C12 &= ~MCG_C12_CME2_MASK;
1326     }
1327     else
1328     {
1329         if (kMCG_MonitorInt == mode)
1330         {
1331             MCG->C10 &= ~MCG_C10_LOCRE2_MASK;
1332         }
1333         else
1334         {
1335             MCG->C10 |= MCG_C10_LOCRE2_MASK;
1336         }
1337         MCG->C12 |= MCG_C12_CME2_MASK;
1338     }
1339 }
1340 #endif /* (FSL_FEATURE_SOC_OSC_COUNT > 1u) */
1341 
1342 #if (defined(FSL_FEATURE_MCG_HAS_RTC_32K) && FSL_FEATURE_MCG_HAS_RTC_32K)
1343 /*!
1344  * brief Sets the RTC OSC clock monitor mode.
1345  *
1346  * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details.
1347  *
1348  * param mode Monitor mode to set.
1349  */
CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode)1350 void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode)
1351 {
1352     uint8_t mcg_c8 = MCG->C8;
1353 
1354     mcg_c8 &= ~(uint8_t)(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK);
1355 
1356     if (kMCG_MonitorNone != mode)
1357     {
1358         if (kMCG_MonitorReset == mode)
1359         {
1360             mcg_c8 |= MCG_C8_LOCRE1_MASK;
1361         }
1362         mcg_c8 |= MCG_C8_CME1_MASK;
1363     }
1364     MCG->C8 = mcg_c8;
1365 }
1366 #endif /* FSL_FEATURE_MCG_HAS_RTC_32K */
1367 
1368 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
1369 /*!
1370  * brief Sets the PLL0 clock monitor mode.
1371  *
1372  * This function sets the PLL0 clock monitor mode. See ref mcg_monitor_mode_t for details.
1373  *
1374  * param mode Monitor mode to set.
1375  */
CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode)1376 void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode)
1377 {
1378 #if (defined(FSL_FEATURE_MCG_HAS_LOLRE) && FSL_FEATURE_MCG_HAS_LOLRE)
1379     uint8_t mcg_c8;
1380 #else
1381     assert(mode != kMCG_MonitorReset);
1382 #endif
1383 
1384     /* Clear previous flag. */
1385     MCG->S = MCG_S_LOLS0_MASK;
1386 
1387     if (kMCG_MonitorNone == mode)
1388     {
1389         MCG->C6 &= (uint8_t)(~MCG_C6_LOLIE0_MASK);
1390     }
1391     else
1392     {
1393 #if (defined(FSL_FEATURE_MCG_HAS_LOLRE) && FSL_FEATURE_MCG_HAS_LOLRE)
1394         mcg_c8 = MCG->C8;
1395 
1396 #if (defined(FSL_FEATURE_MCG_HAS_RTC_32K) && FSL_FEATURE_MCG_HAS_RTC_32K)
1397         mcg_c8 &= (uint8_t)(~MCG_C8_LOCS1_MASK);
1398 #endif /* FSL_FEATURE_MCG_HAS_RTC_32K */
1399 
1400         if (kMCG_MonitorInt == mode)
1401         {
1402             mcg_c8 &= (uint8_t)(~MCG_C8_LOLRE_MASK);
1403         }
1404         else
1405         {
1406             mcg_c8 |= MCG_C8_LOLRE_MASK;
1407         }
1408         MCG->C8 = mcg_c8;
1409 #endif /* FSL_FEATURE_MCG_HAS_LOLRE */
1410         MCG->C6 |= MCG_C6_LOLIE0_MASK;
1411     }
1412 }
1413 
1414 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
1415 /*!
1416  * brief Sets the PLL1 clock monitor mode.
1417  *
1418  * This function sets the PLL1 clock monitor mode. See ref mcg_monitor_mode_t for details.
1419  *
1420  * param mode Monitor mode to set.
1421  */
CLOCK_SetPll1MonitorMode(mcg_monitor_mode_t mode)1422 void CLOCK_SetPll1MonitorMode(mcg_monitor_mode_t mode)
1423 {
1424     assert(mode != kMCG_MonitorReset);
1425 
1426     /* Clear previous flag. */
1427     MCG->S2 = MCG_S2_LOLS1_MASK;
1428 
1429     if (kMCG_MonitorNone == mode)
1430     {
1431         MCG->C12 &= ~MCG_C12_LOLIE1_MASK;
1432     }
1433     else
1434     {
1435         MCG->C12 |= MCG_C12_LOLIE1_MASK;
1436     }
1437 }
1438 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
1439 
1440 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
1441 /*!
1442  * brief Sets the external PLL clock monitor mode.
1443  *
1444  * This function ets the external PLL clock monitor mode. See ref mcg_monitor_mode_t
1445  * for details.
1446  *
1447  * param mode Monitor mode to set.
1448  */
CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode)1449 void CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode)
1450 {
1451     uint8_t mcg_c9 = MCG->C9;
1452 
1453     mcg_c9 &= (uint8_t)(~(MCG_C9_PLL_LOCRE_MASK | MCG_C9_PLL_CME_MASK));
1454 
1455     if (kMCG_MonitorNone != mode)
1456     {
1457         if (kMCG_MonitorReset == mode)
1458         {
1459             mcg_c9 |= MCG_C9_PLL_LOCRE_MASK;
1460         }
1461         mcg_c9 |= MCG_C9_PLL_CME_MASK;
1462     }
1463     MCG->C9 = mcg_c9;
1464 }
1465 #endif /* FSL_FEATURE_MCG_HAS_EXTERNAL_PLL */
1466 
1467 #endif /* FSL_FEATURE_MCG_HAS_PLL */
1468 
1469 /*!
1470  * brief Gets the MCG status flags.
1471  *
1472  * This function gets the MCG clock status flags. All status flags are
1473  * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To
1474  * check a specific flag, compare the return value with the flag.
1475  *
1476  * Example:
1477  * code
1478  * To check the clock lost lock status of OSC0 and PLL0.
1479  * uint32_t mcgFlags;
1480  *
1481  * mcgFlags = CLOCK_GetStatusFlags();
1482  *
1483  * if (mcgFlags & kMCG_Osc0LostFlag)
1484  * {
1485  *     OSC0 clock lock lost. Do something.
1486  * }
1487  * if (mcgFlags & kMCG_Pll0LostFlag)
1488  * {
1489  *     PLL0 clock lock lost. Do something.
1490  * }
1491  * endcode
1492  *
1493  * return  Logical OR value of the ref _mcg_status_flags_t.
1494  */
CLOCK_GetStatusFlags(void)1495 uint32_t CLOCK_GetStatusFlags(void)
1496 {
1497     uint32_t ret = 0U;
1498 #if ((defined(FSL_FEATURE_SOC_OSC_COUNT) && FSL_FEATURE_SOC_OSC_COUNT) || \
1499      (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL))
1500     uint8_t mcg_s = MCG->S;
1501 #endif /* (FSL_FEATURE_SOC_OSC_COUNT || FSL_FEATURE_MCG_HAS_PLL) */
1502 #if ((defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1) || \
1503      (defined(FSL_FEATURE_SOC_OSC_COUNT) && (FSL_FEATURE_SOC_OSC_COUNT > 1u)))
1504     uint8_t mcg_s2 = MCG->S2;
1505 #endif /* (FSL_FEATURE_MCG_HAS_PLL1 || (FSL_FEATURE_SOC_OSC_COUNT > 1u)) */
1506 
1507 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && FSL_FEATURE_SOC_OSC_COUNT)
1508     if ((MCG->SC & MCG_SC_LOCS0_MASK) != 0U)
1509     {
1510         ret |= (uint32_t)kMCG_Osc0LostFlag;
1511     }
1512     if ((mcg_s & MCG_S_OSCINIT0_MASK) != 0U)
1513     {
1514         ret |= (uint32_t)kMCG_Osc0InitFlag;
1515     }
1516 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && (FSL_FEATURE_SOC_OSC_COUNT > 1u))
1517     if ((mcg_s2 & MCG_S2_LOCS2_MASK) != 0U)
1518     {
1519         ret |= (uint32_t)kMCG_Osc1LostFlag;
1520     }
1521     if ((mcg_s2 & MCG_S2_OSCINIT1_MASK) != 0U)
1522     {
1523         ret |= (uint32_t)kMCG_Osc1InitFlag;
1524     }
1525 #endif /* (FSL_FEATURE_SOC_OSC_COUNT > 1u) */
1526 #endif /* FSL_FEATURE_SOC_OSC_COUNT */
1527 #if (defined(FSL_FEATURE_MCG_HAS_RTC_32K) && FSL_FEATURE_MCG_HAS_RTC_32K)
1528     if (0U != (MCG->C8 & MCG_C8_LOCS1_MASK))
1529     {
1530         ret |= (uint32_t)kMCG_RtcOscLostFlag;
1531     }
1532 #endif /* FSL_FEATURE_MCG_HAS_RTC_32K */
1533 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
1534     if ((mcg_s & MCG_S_LOLS0_MASK) != 0U)
1535     {
1536         ret |= (uint32_t)kMCG_Pll0LostFlag;
1537     }
1538     if ((mcg_s & MCG_S_LOCK0_MASK) != 0U)
1539     {
1540         ret |= (uint32_t)kMCG_Pll0LockFlag;
1541     }
1542 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
1543     if ((mcg_s2 & MCG_S2_LOLS1_MASK) != 0U)
1544     {
1545         ret |= (uint32_t)kMCG_Pll1LostFlag;
1546     }
1547     if ((mcg_s2 & MCG_S2_LOCK1_MASK) != 0U)
1548     {
1549         ret |= (uint32_t)kMCG_Pll1LockFlag;
1550     }
1551 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
1552 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
1553     if ((MCG->C9 & MCG_C9_EXT_PLL_LOCS_MASK) != 0U)
1554     {
1555         ret |= (uint32_t)kMCG_ExtPllLostFlag;
1556     }
1557 #endif /* FSL_FEATURE_MCG_HAS_EXTERNAL_PLL */
1558 #endif /* FSL_FEATURE_MCG_HAS_PLL */
1559     return ret;
1560 }
1561 
1562 /*!
1563  * brief Clears the MCG status flags.
1564  *
1565  * This function clears the MCG clock lock lost status. The parameter is a logical
1566  * OR value of the flags to clear. See ref _mcg_status_flags_t.
1567  *
1568  * Example:
1569  * code
1570  * To clear the clock lost lock status flags of OSC0 and PLL0.
1571  *
1572  * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag);
1573  * endcode
1574  *
1575  * param mask The status flags to clear. This is a logical OR of members of the
1576  *             enumeration ref _mcg_status_flags_t.
1577  */
CLOCK_ClearStatusFlags(uint32_t mask)1578 void CLOCK_ClearStatusFlags(uint32_t mask)
1579 {
1580 #if ((defined(FSL_FEATURE_MCG_HAS_RTC_32K) && FSL_FEATURE_MCG_HAS_RTC_32K) || \
1581      (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL))
1582     uint8_t reg;
1583 #endif
1584 
1585 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && FSL_FEATURE_SOC_OSC_COUNT)
1586     if ((mask & (uint32_t)kMCG_Osc0LostFlag) != 0UL)
1587     {
1588         MCG->SC &= (uint8_t)(~MCG_SC_ATMF_MASK);
1589     }
1590 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && (FSL_FEATURE_SOC_OSC_COUNT > 1u))
1591     if ((mask & (uint32_t)kMCG_Osc1LostFlag) != 0UL)
1592     {
1593         MCG->S2 = MCG_S2_LOCS2_MASK;
1594     }
1595 #endif /* (FSL_FEATURE_SOC_OSC_COUNT > 1u) */
1596 #endif /* FSL_FEATURE_SOC_OSC_COUNT */
1597 #if (defined(FSL_FEATURE_MCG_HAS_RTC_32K) && FSL_FEATURE_MCG_HAS_RTC_32K)
1598     if (0U != (mask & (uint32_t)kMCG_RtcOscLostFlag))
1599     {
1600         reg     = MCG->C8;
1601         MCG->C8 = reg;
1602     }
1603 #endif /* FSL_FEATURE_MCG_HAS_RTC_32K */
1604 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
1605     if ((mask & (uint32_t)kMCG_Pll0LostFlag) != 0UL)
1606     {
1607         MCG->S = MCG_S_LOLS0_MASK;
1608     }
1609 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
1610     if ((mask & (uint32_t)kMCG_Pll1LostFlag) != 0UL)
1611     {
1612         MCG->S2 = MCG_S2_LOLS1_MASK;
1613     }
1614 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
1615 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
1616     if ((mask & (uint32_t)kMCG_ExtPllLostFlag) != 0UL)
1617     {
1618         reg     = MCG->C9;
1619         MCG->C9 = reg;
1620     }
1621 #endif /* FSL_FEATURE_MCG_HAS_EXTERNAL_PLL */
1622 #endif /* FSL_FEATURE_MCG_HAS_PLL */
1623 }
1624 
1625 /*!
1626  * brief Initializes the OSC0.
1627  *
1628  * This function initializes the OSC0 according to the board configuration.
1629  *
1630  * param  config Pointer to the OSC0 configuration structure.
1631  */
CLOCK_InitOsc0(osc_config_t const * config)1632 void CLOCK_InitOsc0(osc_config_t const *config)
1633 {
1634     uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq);
1635 
1636 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && FSL_FEATURE_SOC_OSC_COUNT)
1637     OSC_SetCapLoad(OSC0, config->capLoad);
1638 #endif /* FSL_FEATURE_SOC_OSC_COUNT */
1639 
1640     MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode);
1641 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && FSL_FEATURE_SOC_OSC_COUNT)
1642     OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig);
1643 #endif /* FSL_FEATURE_SOC_OSC_COUNT */
1644 
1645     if ((kOSC_ModeExt != config->workMode)
1646 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && FSL_FEATURE_SOC_OSC_COUNT)
1647         && ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U)
1648 #endif /* FSL_FEATURE_SOC_OSC_COUNT */
1649     )
1650     {
1651         /* Wait for stable. */
1652         while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
1653         {
1654         }
1655     }
1656 }
1657 
1658 /*!
1659  * brief Deinitializes the OSC0.
1660  *
1661  * This function deinitializes the OSC0.
1662  */
CLOCK_DeinitOsc0(void)1663 void CLOCK_DeinitOsc0(void)
1664 {
1665 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && FSL_FEATURE_SOC_OSC_COUNT)
1666     OSC0->CR = 0U;
1667 #endif /* FSL_FEATURE_SOC_OSC_COUNT */
1668     MCG->C2 &= ~(uint8_t)OSC_MODE_MASK;
1669 }
1670 
1671 #if (defined(FSL_FEATURE_SOC_OSC_COUNT) && (FSL_FEATURE_SOC_OSC_COUNT > 1u))
1672 /*!
1673  * brief Initializes the OSC1.
1674  *
1675  * This function initializes the OSC1 according to the board configuration.
1676  *
1677  * param  config Pointer to the OSC1 configuration structure.
1678  */
CLOCK_InitOsc1(osc_config_t const * config)1679 void CLOCK_InitOsc1(osc_config_t const *config)
1680 {
1681     uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq);
1682 
1683     OSC_SetCapLoad(OSC1, config->capLoad);
1684 
1685     MCG->C10 = ((MCG->C10 & ~OSC_MODE_MASK) | MCG_C10_RANGE1(range) | (uint8_t)config->workMode);
1686     OSC_SetExtRefClkConfig(OSC1, &config->oscerConfig);
1687 
1688     if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK))
1689     {
1690         /* Wait for stable. */
1691         while (!(MCG->S2 & MCG_S2_OSCINIT1_MASK))
1692         {
1693         }
1694     }
1695 }
1696 
1697 /*!
1698  * brief Deinitializes the OSC1.
1699  *
1700  * This function deinitializes the OSC1.
1701  */
CLOCK_DeinitOsc1(void)1702 void CLOCK_DeinitOsc1(void)
1703 {
1704     OSC1->CR = 0U;
1705     MCG->C10 &= ~OSC_MODE_MASK;
1706 }
1707 #endif /* (FSL_FEATURE_SOC_OSC_COUNT > 1U) */
1708 
1709 /*!
1710  * brief Set the Slow IRC frequency based on the trimmed value
1711  *
1712  * param freq The Slow IRC frequency input clock frequency in Hz.
1713  */
CLOCK_SetSlowIrcFreq(uint32_t freq)1714 void CLOCK_SetSlowIrcFreq(uint32_t freq)
1715 {
1716     s_slowIrcFreq = freq;
1717 }
1718 
1719 /*!
1720  * brief Set the Fast IRC frequency based on the trimmed value
1721  *
1722  * param freq The Fast IRC frequency input clock frequency in Hz.
1723  */
CLOCK_SetFastIrcFreq(uint32_t freq)1724 void CLOCK_SetFastIrcFreq(uint32_t freq)
1725 {
1726     s_fastIrcFreq = freq;
1727 }
1728 
1729 /*!
1730  * brief Auto trims the internal reference clock.
1731  *
1732  * This function trims the internal reference clock by using the external clock. If
1733  * successful, it returns the kStatus_Success and the frequency after
1734  * trimming is received in the parameter p actualFreq. If an error occurs,
1735  * the error code is returned.
1736  *
1737  * param extFreq      External clock frequency, which should be a bus clock.
1738  * param desireFreq   Frequency to trim to.
1739  * param actualFreq   Actual frequency after trimming.
1740  * param atms         Trim fast or slow internal reference clock.
1741  * retval kStatus_Success ATM success.
1742  * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM.
1743  * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency.
1744  * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source.
1745  * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming.
1746  */
CLOCK_TrimInternalRefClk(uint32_t extFreq,uint32_t desireFreq,uint32_t * actualFreq,mcg_atm_select_t atms)1747 status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms)
1748 {
1749     uint32_t multi; /* extFreq / desireFreq */
1750     uint32_t actv;  /* Auto trim value. */
1751     uint8_t mcg_sc;
1752     status_t status = kStatus_Success;
1753 
1754     static const uint32_t trimRange[2][2] = {
1755         /*     Min           Max      */
1756         {TRIM_SIRC_MIN, TRIM_SIRC_MAX}, /* Slow IRC. */
1757         {TRIM_FIRC_MIN, TRIM_FIRC_MAX}  /* Fast IRC. */
1758     };
1759 
1760     if ((extFreq > TRIM_REF_CLK_MAX) || (extFreq < TRIM_REF_CLK_MIN))
1761     {
1762         status = kStatus_MCG_AtmBusClockInvalid;
1763     }
1764     /* Check desired frequency range. */
1765     else if ((desireFreq < trimRange[atms][0]) || (desireFreq > trimRange[atms][1]))
1766     {
1767         status = kStatus_MCG_AtmDesiredFreqInvalid;
1768     }
1769     /*
1770        Make sure internal reference clock is not used to generate bus clock.
1771        Here only need to check (MCG_S_IREFST == 1).
1772      */
1773     else if (MCG_S_IREFST(kMCG_FllSrcInternal) == (MCG->S & MCG_S_IREFST_MASK))
1774     {
1775         status = kStatus_MCG_AtmIrcUsed;
1776     }
1777     else
1778     {
1779         multi = extFreq / desireFreq;
1780         actv  = multi * 21U;
1781 
1782         if (kMCG_AtmSel4m == atms)
1783         {
1784             actv *= 128U;
1785         }
1786 
1787         /* Now begin to start trim. */
1788         MCG->ATCVL = (uint8_t)actv;
1789         MCG->ATCVH = (uint8_t)(actv >> 8U);
1790 
1791         mcg_sc = MCG->SC;
1792         mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK);
1793         mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms));
1794         MCG->SC = (mcg_sc | MCG_SC_ATME_MASK);
1795 
1796         /* Wait for MCG finished. */
1797         while (0U != (MCG->SC & MCG_SC_ATME_MASK))
1798         {
1799         }
1800 
1801         /* Error occurs? */
1802         if (0U != (MCG->SC & MCG_SC_ATMF_MASK))
1803         {
1804             /* Clear the failed flag. */
1805             MCG->SC = mcg_sc;
1806             status  = kStatus_MCG_AtmHardwareFail;
1807         }
1808         else
1809         {
1810             *actualFreq = extFreq / multi;
1811 
1812             if (kMCG_AtmSel4m == atms)
1813             {
1814                 s_fastIrcFreq = *actualFreq;
1815             }
1816             else
1817             {
1818                 s_slowIrcFreq = *actualFreq;
1819             }
1820         }
1821     }
1822 
1823     return status;
1824 }
1825 
1826 /*!
1827  * brief Gets the current MCG mode.
1828  *
1829  * This function checks the MCG registers and determines the current MCG mode.
1830  *
1831  * return Current MCG mode or error code; See ref mcg_mode_t.
1832  */
CLOCK_GetMode(void)1833 mcg_mode_t CLOCK_GetMode(void)
1834 {
1835     mcg_mode_t mode = kMCG_ModeError;
1836     uint32_t clkst  = (uint32_t)MCG_S_CLKST_VAL;
1837     uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL;
1838     uint32_t lp     = (uint32_t)MCG_C2_LP_VAL;
1839 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
1840     uint32_t pllst = MCG_S_PLLST_VAL;
1841 #endif /* FSL_FEATURE_MCG_HAS_PLL */
1842 
1843     /*------------------------------------------------------------------
1844                            Mode and Registers
1845     ____________________________________________________________________
1846 
1847       Mode   |   CLKST    |   IREFST   |   PLLST   |      LP
1848     ____________________________________________________________________
1849 
1850       FEI    |  00(FLL)   |   1(INT)   |   0(FLL)  |      X
1851     ____________________________________________________________________
1852 
1853       FEE    |  00(FLL)   |   0(EXT)   |   0(FLL)  |      X
1854     ____________________________________________________________________
1855 
1856       FBE    |  10(EXT)   |   0(EXT)   |   0(FLL)  |   0(NORMAL)
1857     ____________________________________________________________________
1858 
1859       FBI    |  01(INT)   |   1(INT)   |   0(FLL)  |   0(NORMAL)
1860     ____________________________________________________________________
1861 
1862       BLPI   |  01(INT)   |   1(INT)   |   0(FLL)  |   1(LOW POWER)
1863     ____________________________________________________________________
1864 
1865       BLPE   |  10(EXT)   |   0(EXT)   |     X     |   1(LOW POWER)
1866     ____________________________________________________________________
1867 
1868       PEE    |  11(PLL)   |   0(EXT)   |   1(PLL)  |      X
1869     ____________________________________________________________________
1870 
1871       PBE    |  10(EXT)   |   0(EXT)   |   1(PLL)  |   O(NORMAL)
1872     ____________________________________________________________________
1873 
1874       PBI    |  01(INT)   |   1(INT)   |   1(PLL)  |   0(NORMAL)
1875     ____________________________________________________________________
1876 
1877       PEI    |  11(PLL)   |   1(INT)   |   1(PLL)  |      X
1878     ____________________________________________________________________
1879 
1880     ----------------------------------------------------------------------*/
1881 
1882     if (clkst == (uint32_t)kMCG_ClkOutStatFll)
1883     {
1884         if ((uint32_t)kMCG_FllSrcExternal == irefst)
1885         {
1886             mode = kMCG_ModeFEE;
1887         }
1888         else
1889         {
1890             mode = kMCG_ModeFEI;
1891         }
1892     }
1893     else if (clkst == (uint32_t)kMCG_ClkOutStatInt)
1894     {
1895         if (0U != lp)
1896         {
1897             mode = kMCG_ModeBLPI;
1898         }
1899         else
1900         {
1901 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
1902             if (((uint32_t)kMCG_PllstPll) == pllst)
1903             {
1904                 mode = kMCG_ModePBI;
1905             }
1906             else
1907 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
1908             {
1909                 mode = kMCG_ModeFBI;
1910             }
1911         }
1912     }
1913     else if (clkst == (uint32_t)kMCG_ClkOutStatExt)
1914     {
1915         if (0U != lp)
1916         {
1917             mode = kMCG_ModeBLPE;
1918         }
1919         else
1920         {
1921 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
1922             if ((uint32_t)kMCG_PllstPll == pllst)
1923             {
1924                 mode = kMCG_ModePBE;
1925             }
1926             else
1927 #endif /* FSL_FEATURE_MCG_HAS_PLL */
1928             {
1929                 mode = kMCG_ModeFBE;
1930             }
1931         }
1932     }
1933 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
1934     else if (clkst == (uint32_t)kMCG_ClkOutStatPll)
1935     {
1936 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
1937         if ((uint32_t)kMCG_FllSrcInternal == irefst)
1938         {
1939             mode = kMCG_ModePEI;
1940         }
1941         else
1942 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
1943         {
1944             mode = kMCG_ModePEE;
1945         }
1946     }
1947 #endif /* FSL_FEATURE_MCG_HAS_PLL */
1948     else
1949     {
1950         /*do nothing*/
1951     }
1952 
1953     return mode;
1954 }
1955 
1956 /*!
1957  * brief Sets the MCG to FEI mode.
1958  *
1959  * This function sets the MCG to FEI mode. If setting to FEI mode fails
1960  * from the current mode, this function returns an error.
1961  *
1962  * param       dmx32  DMX32 in FEI mode.
1963  * param       drs The DCO range selection.
1964  * param       fllStableDelay Delay function to  ensure that the FLL is stable. Passing
1965  *              NULL does not cause a delay.
1966  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1967  * retval kStatus_Success Switched to the target mode successfully.
1968  * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1969  * to a frequency above 32768 Hz.
1970  */
CLOCK_SetFeiMode(mcg_dmx32_t dmx32,mcg_drs_t drs,void (* fllStableDelay)(void))1971 status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1972 {
1973     uint8_t mcg_c4;
1974     bool change_drs = false;
1975 
1976 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1977     mcg_mode_t mode = CLOCK_GetMode();
1978     if (!((kMCG_ModeFEI == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEE == mode)))
1979     {
1980         return kStatus_MCG_ModeUnreachable;
1981     }
1982 #endif
1983     mcg_c4 = MCG->C4;
1984 
1985     /*
1986        Errata: ERR007993
1987        Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
1988        reference clock source changes, then reset to previous value after
1989        reference clock changes.
1990      */
1991     if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
1992     {
1993         change_drs = true;
1994         /* Change the LSB of DRST_DRS. */
1995         MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
1996     }
1997 
1998     /* Set CLKS and IREFS. */
1999     MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) |
2000                         (MCG_C1_CLKS(kMCG_ClkOutSrcOut)         /* CLKS = 0 */
2001                          | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */
2002 
2003     /* Wait and check status. */
2004     while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL)
2005     {
2006     }
2007 
2008     /* Errata: ERR007993 */
2009     if (change_drs)
2010     {
2011         MCG->C4 = mcg_c4;
2012     }
2013 
2014     /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */
2015     MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
2016                         (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
2017 
2018     /* Check MCG_S[CLKST] */
2019     while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL)
2020     {
2021     }
2022 
2023     /* Wait for FLL stable time. */
2024     if (NULL != fllStableDelay)
2025     {
2026         fllStableDelay();
2027     }
2028 
2029     return kStatus_Success;
2030 }
2031 
2032 /*!
2033  * brief Sets the MCG to FEE mode.
2034  *
2035  * This function sets the MCG to FEE mode. If setting to FEE mode fails
2036  * from the current mode, this function returns an error.
2037  *
2038  * param   frdiv  FLL reference clock divider setting, FRDIV.
2039  * param   dmx32  DMX32 in FEE mode.
2040  * param   drs    The DCO range selection.
2041  * param   fllStableDelay Delay function to make sure FLL is stable. Passing
2042  *          NULL does not cause a delay.
2043  *
2044  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2045  * retval kStatus_Success Switched to the target mode successfully.
2046  */
CLOCK_SetFeeMode(uint8_t frdiv,mcg_dmx32_t dmx32,mcg_drs_t drs,void (* fllStableDelay)(void))2047 status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
2048 {
2049     uint8_t mcg_c4;
2050     bool change_drs = false;
2051 
2052 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2053     mcg_mode_t mode = CLOCK_GetMode();
2054     if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode)))
2055     {
2056         return kStatus_MCG_ModeUnreachable;
2057     }
2058 #endif
2059     mcg_c4 = MCG->C4;
2060 
2061     /*
2062        Errata: ERR007993
2063        Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
2064        reference clock source changes, then reset to previous value after
2065        reference clock changes.
2066      */
2067     if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL)
2068     {
2069         change_drs = true;
2070         /* Change the LSB of DRST_DRS. */
2071         MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
2072     }
2073 
2074     /* Set CLKS and IREFS. */
2075     MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) |
2076                         (MCG_C1_CLKS(kMCG_ClkOutSrcOut)         /* CLKS = 0 */
2077                          | MCG_C1_FRDIV(frdiv)                  /* FRDIV */
2078                          | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */
2079 
2080     /* If use external crystal as clock source, wait for it stable. */
2081 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
2082     if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
2083 #endif
2084     {
2085         if (0U != (MCG->C2 & MCG_C2_EREFS_MASK))
2086         {
2087             while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
2088             {
2089             }
2090         }
2091     }
2092 
2093     /* Wait and check status. */
2094     while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL)
2095     {
2096     }
2097 
2098     /* Errata: ERR007993 */
2099     if (change_drs)
2100     {
2101         MCG->C4 = mcg_c4;
2102     }
2103 
2104     /* Set DRS and DMX32. */
2105     mcg_c4  = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
2106                        (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
2107     MCG->C4 = mcg_c4;
2108 
2109     /* Wait for DRST_DRS update. */
2110     while (MCG->C4 != mcg_c4)
2111     {
2112     }
2113 
2114     /* Check MCG_S[CLKST] */
2115     while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL)
2116     {
2117     }
2118 
2119     /* Wait for FLL stable time. */
2120     if (NULL != fllStableDelay)
2121     {
2122         fllStableDelay();
2123     }
2124 
2125     return kStatus_Success;
2126 }
2127 
2128 /*!
2129  * brief Sets the MCG to FBI mode.
2130  *
2131  * This function sets the MCG to FBI mode. If setting to FBI mode fails
2132  * from the current mode, this function returns an error.
2133  *
2134  * param  dmx32  DMX32 in FBI mode.
2135  * param  drs  The DCO range selection.
2136  * param  fllStableDelay Delay function to make sure FLL is stable. If the FLL
2137  *         is not used in FBI mode, this parameter can be NULL. Passing
2138  *         NULL does not cause a delay.
2139  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2140  * retval kStatus_Success Switched to the target mode successfully.
2141  * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
2142  * to frequency above 32768 Hz.
2143  */
CLOCK_SetFbiMode(mcg_dmx32_t dmx32,mcg_drs_t drs,void (* fllStableDelay)(void))2144 status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
2145 {
2146     uint8_t mcg_c4;
2147     bool change_drs = false;
2148 
2149 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2150     mcg_mode_t mode = CLOCK_GetMode();
2151 
2152     if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode) ||
2153 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
2154           (kMCG_ModePBI == mode) ||
2155 #endif
2156           (kMCG_ModeBLPI == mode)))
2157 
2158     {
2159         return kStatus_MCG_ModeUnreachable;
2160     }
2161 #endif
2162 
2163     mcg_c4 = MCG->C4;
2164 
2165 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
2166     /* Change to FLL mode. */
2167     MCG->C6 &= (uint8_t)(~MCG_C6_PLLS_MASK);
2168     while ((MCG->S & MCG_S_PLLST_MASK) != 0U)
2169     {
2170     }
2171 #endif
2172     MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */
2173 
2174     /*
2175        Errata: ERR007993
2176        Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
2177        reference clock source changes, then reset to previous value after
2178        reference clock changes.
2179      */
2180     if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
2181     {
2182         change_drs = true;
2183         /* Change the LSB of DRST_DRS. */
2184         MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
2185     }
2186 
2187     /* Set CLKS and IREFS. */
2188     MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) |
2189                         (MCG_C1_CLKS(kMCG_ClkOutSrcInternal)    /* CLKS = 1 */
2190                          | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */
2191 
2192     /* Wait and check status. */
2193     while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL)
2194     {
2195     }
2196 
2197     /* Errata: ERR007993 */
2198     if (change_drs)
2199     {
2200         MCG->C4 = mcg_c4;
2201     }
2202 
2203     while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL)
2204     {
2205     }
2206 
2207     MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
2208                         (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
2209 
2210     /* Wait for FLL stable time. */
2211     if (NULL != fllStableDelay)
2212     {
2213         fllStableDelay();
2214     }
2215 
2216     return kStatus_Success;
2217 }
2218 
2219 /*!
2220  * brief Sets the MCG to FBE mode.
2221  *
2222  * This function sets the MCG to FBE mode. If setting to FBE mode fails
2223  * from the current mode, this function returns an error.
2224  *
2225  * param   frdiv  FLL reference clock divider setting, FRDIV.
2226  * param   dmx32  DMX32 in FBE mode.
2227  * param   drs    The DCO range selection.
2228  * param   fllStableDelay Delay function to make sure FLL is stable. If the FLL
2229  *          is not used in FBE mode, this parameter can be NULL. Passing NULL
2230  *          does not cause a delay.
2231  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2232  * retval kStatus_Success Switched to the target mode successfully.
2233  */
CLOCK_SetFbeMode(uint8_t frdiv,mcg_dmx32_t dmx32,mcg_drs_t drs,void (* fllStableDelay)(void))2234 status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
2235 {
2236     uint8_t mcg_c4;
2237     bool change_drs = false;
2238 
2239 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2240     mcg_mode_t mode = CLOCK_GetMode();
2241     if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode) ||
2242 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
2243           (kMCG_ModePBE == mode) ||
2244 #endif
2245           (kMCG_ModeBLPE == mode)))
2246     {
2247         return kStatus_MCG_ModeUnreachable;
2248     }
2249 #endif
2250 
2251 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
2252     /* Change to FLL mode. */
2253     MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK;
2254     while ((MCG->S & MCG_S_PLLST_MASK) != 0U)
2255     {
2256     }
2257 #endif
2258 
2259     /* Set LP bit to enable the FLL */
2260     MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK;
2261 
2262     mcg_c4 = MCG->C4;
2263 
2264     /*
2265        Errata: ERR007993
2266        Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
2267        reference clock source changes, then reset to previous value after
2268        reference clock changes.
2269      */
2270     if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL)
2271     {
2272         change_drs = true;
2273         /* Change the LSB of DRST_DRS. */
2274         MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
2275     }
2276 
2277     /* Set CLKS and IREFS. */
2278     MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) |
2279                         (MCG_C1_CLKS(kMCG_ClkOutSrcExternal)    /* CLKS = 2 */
2280                          | MCG_C1_FRDIV(frdiv)                  /* FRDIV = frdiv */
2281                          | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */
2282 
2283     /* If use external crystal as clock source, wait for it stable. */
2284 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
2285     if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
2286 #endif
2287     {
2288         if (0U != (MCG->C2 & MCG_C2_EREFS_MASK))
2289         {
2290             while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
2291             {
2292             }
2293         }
2294     }
2295 
2296     /* Wait for Reference clock Status bit to clear */
2297     while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL)
2298     {
2299     }
2300 
2301     /* Errata: ERR007993 */
2302     if (change_drs)
2303     {
2304         MCG->C4 = mcg_c4;
2305     }
2306 
2307     /* Set DRST_DRS and DMX32. */
2308     mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
2309                        (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
2310 
2311     /* Wait for clock status bits to show clock source is ext ref clk */
2312     while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL)
2313     {
2314     }
2315 
2316     /* Wait for fll stable time. */
2317     if (NULL != fllStableDelay)
2318     {
2319         fllStableDelay();
2320     }
2321 
2322     return kStatus_Success;
2323 }
2324 
2325 /*!
2326  * brief Sets the MCG to BLPI mode.
2327  *
2328  * This function sets the MCG to BLPI mode. If setting to BLPI mode fails
2329  * from the current mode, this function returns an error.
2330  *
2331  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2332  * retval kStatus_Success Switched to the target mode successfully.
2333  */
CLOCK_SetBlpiMode(void)2334 status_t CLOCK_SetBlpiMode(void)
2335 {
2336 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2337     if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt)
2338     {
2339         return kStatus_MCG_ModeUnreachable;
2340     }
2341 #endif /* MCG_CONFIG_CHECK_PARAM */
2342 
2343     /* Set LP. */
2344     MCG->C2 |= MCG_C2_LP_MASK;
2345 
2346     return kStatus_Success;
2347 }
2348 
2349 /*!
2350  * brief Sets the MCG to BLPE mode.
2351  *
2352  * This function sets the MCG to BLPE mode. If setting to BLPE mode fails
2353  * from the current mode, this function returns an error.
2354  *
2355  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2356  * retval kStatus_Success Switched to the target mode successfully.
2357  */
CLOCK_SetBlpeMode(void)2358 status_t CLOCK_SetBlpeMode(void)
2359 {
2360 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2361     if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt)
2362     {
2363         return kStatus_MCG_ModeUnreachable;
2364     }
2365 #endif
2366 
2367     /* Set LP bit to enter BLPE mode. */
2368     MCG->C2 |= MCG_C2_LP_MASK;
2369 
2370     return kStatus_Success;
2371 }
2372 
2373 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
2374 /*!
2375  * brief Sets the MCG to PBE mode.
2376  *
2377  * This function sets the MCG to PBE mode. If setting to PBE mode fails
2378  * from the current mode, this function returns an error.
2379  *
2380  * param   pllcs  The PLL selection, PLLCS.
2381  * param   config Pointer to the PLL configuration.
2382  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2383  * retval kStatus_Success Switched to the target mode successfully.
2384  *
2385  * note
2386  * 1. The parameter \c pllcs selects the PLL. For platforms with
2387  * only one PLL, the parameter pllcs is kept for interface compatibility.
2388  * 2. The parameter \c config is the PLL configuration structure. On some
2389  * platforms,  it is possible to choose the external PLL directly, which renders the
2390  * configuration structure not necessary. In this case, pass in NULL.
2391  * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL);
2392  */
CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs,mcg_pll_config_t const * config)2393 status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config)
2394 {
2395 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
2396     /* If external PLL is used, then the config could be NULL. */
2397     if (kMCG_PllClkSelExtPll != pllcs)
2398     {
2399 #endif
2400         assert(config);
2401 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
2402     }
2403 #endif
2404 
2405 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
2406 
2407 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2408     /*
2409        This function is designed to change MCG to PBE mode from PEE/BLPE/FBE,
2410        but with this workflow, the source mode could be all modes except PEI/PBI.
2411      */
2412     mcg_mode_t mode = CLOCK_GetMode();
2413 
2414     if ((kMCG_ModePBI == mode) || (kMCG_ModePEI == mode))
2415     {
2416         return kStatus_MCG_ModeUnreachable;
2417     }
2418 #endif
2419     pllcs = pllcs; /* pllcs is not used. */
2420 
2421     /* Clear LP */
2422     MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK); /* Disable lowpower. */
2423 
2424     /* Set CLKS and IREFS. */
2425     MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) |
2426                         (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2      */
2427                          | MCG_C1_FRDIV(config->frdiv)));    /* FRDIV = frdiv */
2428 
2429     /* If use external crystal as clock source, wait for it stable. */
2430 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
2431     if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
2432 #endif
2433     {
2434         if ((MCG->C2 & MCG_C2_EREFS_MASK) != 0U)
2435         {
2436             while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
2437             {
2438             }
2439         }
2440     }
2441 
2442     /* Wait for CLKST clock status bits to show clock source is ext ref clk */
2443     while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
2444            (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt)))
2445     {
2446     }
2447 
2448     /* Set MCG_C7[PLL32KREFSEL] to select PLL reference clock source */
2449     MCG->C7 = (uint8_t)((MCG->C7 & ~MCG_C7_PLL32KREFSEL_MASK) | MCG_C7_PLL32KREFSEL(config->refSrc));
2450 
2451     /* Enable PLL. */
2452     MCG->C6 |= MCG_C6_PLLS_MASK;
2453 
2454     /* Wait for PLLST set and PLL lock. */
2455     while (((MCG->S & (MCG_S_PLLST_MASK | MCG_S_LOCK0_MASK)) != (MCG_S_PLLST_MASK | MCG_S_LOCK0_MASK)))
2456     {
2457     }
2458 
2459 #else /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
2460     /*
2461        This function is designed to change MCG to PBE mode from PEE/BLPE/FBE,
2462        but with this workflow, the source mode could be all modes except PEI/PBI.
2463      */
2464     MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK); /* Disable lowpower. */
2465 
2466     /* Change to use external clock first. */
2467     MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal));
2468 
2469     /* Wait for CLKST clock status bits to show clock source is ext ref clk */
2470     while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
2471            (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt)))
2472     {
2473     }
2474 
2475     /* Disable PLL first, then configure PLL. */
2476     MCG->C6 &= (uint8_t)(~MCG_C6_PLLS_MASK);
2477     while ((MCG->S & MCG_S_PLLST_MASK) != 0U)
2478     {
2479     }
2480 
2481 /* Configure the PLL. */
2482 #if ((defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1) || \
2483      (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL))
2484     if (kMCG_PllClkSelPll0 == pllcs)
2485 #endif
2486     {
2487         CLOCK_EnablePll0(config);
2488     }
2489 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
2490     else if (kMCG_PllClkSelPll1 == pclls)
2491     {
2492         CLOCK_EnablePll1(config);
2493     }
2494 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
2495 
2496     /* Change to PLL mode. */
2497     MCG->C6 |= MCG_C6_PLLS_MASK;
2498 
2499 #if ((defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1) || \
2500      (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL))
2501     MCG->C11 = (uint8_t)(((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs));
2502     while ((uint32_t)pllcs != MCG_S2_PLLCST_VAL)
2503     {
2504     }
2505 #endif
2506 
2507     /* Wait for PLL mode changed. */
2508     while (((MCG->S & MCG_S_PLLST_MASK)) == 0U)
2509     {
2510     }
2511 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
2512 
2513     return kStatus_Success;
2514 }
2515 
2516 /*!
2517  * brief Sets the MCG to PEE mode.
2518  *
2519  * This function sets the MCG to PEE mode.
2520  *
2521  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2522  * retval kStatus_Success Switched to the target mode successfully.
2523  *
2524  * note This function only changes the CLKS to use the PLL/FLL output. If the
2525  *       PRDIV/VDIV are different than in the PBE mode, set them up
2526  *       in PBE mode and wait. When the clock is stable, switch to PEE mode.
2527  */
CLOCK_SetPeeMode(void)2528 status_t CLOCK_SetPeeMode(void)
2529 {
2530 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2531     mcg_mode_t mode = CLOCK_GetMode();
2532     if (kMCG_ModePBE != mode)
2533     {
2534         return kStatus_MCG_ModeUnreachable;
2535     }
2536 #endif
2537 
2538     /* Change to use PLL/FLL output clock first. */
2539     MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut));
2540 
2541     /* Wait for clock status bits to update */
2542     while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll)
2543     {
2544     }
2545 
2546     return kStatus_Success;
2547 }
2548 
2549 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
2550 /*!
2551  * brief Sets the MCG to PBI mode.
2552  *
2553  * This function sets the MCG to PBI mode.
2554  *
2555  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2556  * retval kStatus_Success Switched to the target mode successfully.
2557  */
CLOCK_SetPbiMode(void)2558 status_t CLOCK_SetPbiMode(void)
2559 {
2560 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2561     mcg_mode_t mode = CLOCK_GetMode();
2562 
2563     if (!((kMCG_ModeFBI == mode) || (kMCG_ModePEI == mode) || (kMCG_ModeBLPI == mode) || (kMCG_ModePBI == mode)))
2564     {
2565         return kStatus_MCG_ModeUnreachable;
2566     }
2567 #endif
2568 
2569     /* set PLLS to select PLL */
2570     MCG->C6 |= MCG_C6_PLLS_MASK;
2571     while (0U == (MCG->S & MCG_S_PLLST_MASK))
2572     {
2573     }
2574 
2575     MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK); /* Disable lowpower. */
2576 
2577     /* Set CLKS and IREFS. */
2578     MCG->C1 = ((MCG->C1 & (uint8_t)(~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) |
2579                (uint8_t)(MCG_C1_CLKS(kMCG_ClkOutSrcInternal)    /* CLKS = 1  */
2580                          | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */
2581 
2582     /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */
2583     while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
2584            (MCG_S_IREFST(kMCG_FllSrcInternal) | MCG_S_CLKST(kMCG_ClkOutStatInt)))
2585     {
2586     }
2587 
2588     /* Set MCG_C7[PLL32KREFSEL] to select slow IRC clock source */
2589     MCG->C7 = (MCG->C7 & (uint8_t)(~MCG_C7_PLL32KREFSEL_MASK)) | MCG_C7_PLL32KREFSEL(kMCG_PllRefIrc);
2590 
2591     while (0U == (MCG->S & MCG_S_LOCK0_MASK))
2592     {
2593     }
2594 
2595     return kStatus_Success;
2596 }
2597 
2598 /*!
2599  * brief Sets the MCG to PEI mode.
2600  *
2601  * This function sets the MCG to PEI mode.
2602  *
2603  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2604  * retval kStatus_Success Switched to the target mode successfully.
2605  */
CLOCK_SetPeiMode(void)2606 status_t CLOCK_SetPeiMode(void)
2607 {
2608 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2609     mcg_mode_t mode = CLOCK_GetMode();
2610     if (kMCG_ModePBI != mode)
2611     {
2612         return kStatus_MCG_ModeUnreachable;
2613     }
2614 #endif
2615 
2616     /* Change to use PLL/FLL output clock first. */
2617     MCG->C1 = (MCG->C1 & (uint8_t)(~MCG_C1_CLKS_MASK)) | MCG_C1_CLKS(kMCG_ClkOutSrcOut);
2618 
2619     /* Wait for clock status bits to update */
2620     while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll)
2621     {
2622     }
2623 
2624     return kStatus_Success;
2625 }
2626 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
2627 #endif /* FSL_FEATURE_MCG_HAS_PLL */
2628 
2629 /*!
2630  * brief Switches the MCG to FBE mode from the external mode.
2631  *
2632  * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly.
2633  * The external clock is used as the system clock source and PLL is disabled. However,
2634  * the FLL settings are not configured. This is a lite function with a small code size, which is useful
2635  * during the mode switch. For example, to switch from PEE mode to FEI mode:
2636  *
2637  * code
2638  * CLOCK_ExternalModeToFbeModeQuick();
2639  * CLOCK_SetFeiMode(...);
2640  * endcode
2641  *
2642  * retval kStatus_Success Switched successfully.
2643  * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function.
2644  */
CLOCK_ExternalModeToFbeModeQuick(void)2645 status_t CLOCK_ExternalModeToFbeModeQuick(void)
2646 {
2647 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2648     if ((MCG->S & MCG_S_IREFST_MASK) != 0U)
2649     {
2650         return kStatus_MCG_ModeInvalid;
2651     }
2652 #endif /* MCG_CONFIG_CHECK_PARAM */
2653 
2654     /* Disable low power */
2655     MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK);
2656 
2657     MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal));
2658     while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt)
2659     {
2660     }
2661 
2662 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
2663     /* Disable PLL. */
2664     MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK;
2665     while ((MCG->S & MCG_S_PLLST_MASK) != 0U)
2666     {
2667     }
2668 #endif
2669 
2670     return kStatus_Success;
2671 }
2672 
2673 /*!
2674  * brief Switches the MCG to FBI mode from internal modes.
2675  *
2676  * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly.
2677  * The MCGIRCLK is used as the system clock source and PLL is disabled. However,
2678  * FLL settings are not configured. This is a lite function with a small code size, which is useful
2679  * during the mode switch. For example, to switch from PEI mode to FEE mode:
2680  *
2681  * code
2682  * CLOCK_InternalModeToFbiModeQuick();
2683  * CLOCK_SetFeeMode(...);
2684  * endcode
2685  *
2686  * retval kStatus_Success Switched successfully.
2687  * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function.
2688  */
CLOCK_InternalModeToFbiModeQuick(void)2689 status_t CLOCK_InternalModeToFbiModeQuick(void)
2690 {
2691 #if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2692     if ((MCG->S & MCG_S_IREFST_MASK) == 0U)
2693     {
2694         return kStatus_MCG_ModeInvalid;
2695     }
2696 #endif
2697 
2698     /* Disable low power */
2699     MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK;
2700 
2701     MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal));
2702     while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt)
2703     {
2704     }
2705 
2706 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
2707     /* Disable PLL. */
2708     MCG->C6 &= (uint8_t)(~MCG_C6_PLLS_MASK);
2709     while ((MCG->S & MCG_S_PLLST_MASK) != 0U)
2710     {
2711     }
2712 #endif
2713 
2714     return kStatus_Success;
2715 }
2716 
2717 /*!
2718  * brief Sets the MCG to FEI mode during system boot up.
2719  *
2720  * This function sets the MCG to FEI mode from the reset mode. It can also be used to
2721  * set up MCG during system boot up.
2722  *
2723  * param  dmx32  DMX32 in FEI mode.
2724  * param  drs The DCO range selection.
2725  * param  fllStableDelay Delay function to ensure that the FLL is stable.
2726  *
2727  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2728  * retval kStatus_Success Switched to the target mode successfully.
2729  * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
2730  * to frequency above 32768 Hz.
2731  */
CLOCK_BootToFeiMode(mcg_dmx32_t dmx32,mcg_drs_t drs,void (* fllStableDelay)(void))2732 status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
2733 {
2734 #if (defined(FSL_FEATURE_MCG_RESET_IS_BLPI) && FSL_FEATURE_MCG_RESET_IS_BLPI)
2735     /* If reset mode is BLPI, first disable LP to enter FBI mode. */
2736     MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK);
2737 #endif
2738     return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay);
2739 }
2740 
2741 /*!
2742  * brief Sets the MCG to FEE mode during system bootup.
2743  *
2744  * This function sets MCG to FEE mode from the reset mode. It can also be used to
2745  * set up the MCG during system boot up.
2746  *
2747  * param   oscsel OSC clock select, OSCSEL.
2748  * param   frdiv  FLL reference clock divider setting, FRDIV.
2749  * param   dmx32  DMX32 in FEE mode.
2750  * param   drs    The DCO range selection.
2751  * param   fllStableDelay Delay function to ensure that the FLL is stable.
2752  *
2753  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2754  * retval kStatus_Success Switched to the target mode successfully.
2755  */
CLOCK_BootToFeeMode(mcg_oscsel_t oscsel,uint8_t frdiv,mcg_dmx32_t dmx32,mcg_drs_t drs,void (* fllStableDelay)(void))2756 status_t CLOCK_BootToFeeMode(
2757     mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
2758 {
2759 #if (defined(FSL_FEATURE_MCG_RESET_IS_BLPI) && FSL_FEATURE_MCG_RESET_IS_BLPI)
2760     /* If reset mode is BLPI, first disable LP to enter FBI mode. */
2761     MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK);
2762 #endif
2763 
2764     (void)CLOCK_SetExternalRefClkConfig(oscsel);
2765 
2766     return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay);
2767 }
2768 
2769 /*!
2770  * brief Sets the MCG to BLPI mode during system boot up.
2771  *
2772  * This function sets the MCG to BLPI mode from the reset mode. It can also be used to
2773  * set up the MCG during system boot up.
2774  *
2775  * param  fcrdiv Fast IRC divider, FCRDIV.
2776  * param  ircs   The internal reference clock to select, IRCS.
2777  * param  ircEnableMode  The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode.
2778  *
2779  * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting.
2780  * retval kStatus_Success Switched to the target mode successfully.
2781  */
CLOCK_BootToBlpiMode(uint8_t fcrdiv,mcg_irc_mode_t ircs,uint8_t ircEnableMode)2782 status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode)
2783 {
2784 #if (defined(FSL_FEATURE_MCG_RESET_IS_BLPI) && FSL_FEATURE_MCG_RESET_IS_BLPI)
2785     /* If reset mode is BLPI mode. */
2786     return CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv);
2787 #else
2788     /* If reset mode is FEI mode, set MCGIRCLK and always success. */
2789     (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv);
2790 
2791     /* If reset mode is not BLPI, first enter FBI mode. */
2792     MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal));
2793     while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt)
2794     {
2795     }
2796 
2797     /* Enter BLPI mode. */
2798     MCG->C2 |= MCG_C2_LP_MASK;
2799 
2800     return kStatus_Success;
2801 #endif
2802 }
2803 
2804 /*!
2805  * brief Sets the MCG to BLPE mode during system boot up.
2806  *
2807  * This function sets the MCG to BLPE mode from the reset mode. It can also be used to
2808  * set up the MCG during system boot up.
2809  *
2810  * param  oscsel OSC clock select, MCG_C7[OSCSEL].
2811  *
2812  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2813  * retval kStatus_Success Switched to the target mode successfully.
2814  */
CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel)2815 status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel)
2816 {
2817 #if (defined(FSL_FEATURE_MCG_RESET_IS_BLPI) && FSL_FEATURE_MCG_RESET_IS_BLPI)
2818     /* If reset mode is BLPI, first disable LP to enter FBI mode. */
2819     MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK);
2820 #endif /* FSL_FEATURE_MCG_RESET_IS_BLPI */
2821 
2822     (void)CLOCK_SetExternalRefClkConfig(oscsel);
2823 
2824     /* Set to FBE mode. */
2825     MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) |
2826                         (MCG_C1_CLKS(kMCG_ClkOutSrcExternal)    /* CLKS = 2 */
2827                          | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */
2828 
2829     /* If use external crystal as clock source, wait for it stable. */
2830 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
2831     if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
2832 #endif
2833     {
2834         if (0U != (MCG->C2 & MCG_C2_EREFS_MASK))
2835         {
2836             while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
2837             {
2838             }
2839         }
2840     }
2841 
2842     /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */
2843     while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
2844            (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt)))
2845     {
2846     }
2847 
2848     /* In FBE now, start to enter BLPE. */
2849     MCG->C2 |= MCG_C2_LP_MASK;
2850 
2851     return kStatus_Success;
2852 }
2853 
2854 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
2855 /*!
2856  * brief Sets the MCG to PEE mode during system boot up.
2857  *
2858  * This function sets the MCG to PEE mode from reset mode. It can also be used to
2859  * set up the MCG during system boot up.
2860  *
2861  * param   oscsel OSC clock select, MCG_C7[OSCSEL].
2862  * param   pllcs  The PLL selection, PLLCS.
2863  * param   config Pointer to the PLL configuration.
2864  *
2865  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2866  * retval kStatus_Success Switched to the target mode successfully.
2867  */
CLOCK_BootToPeeMode(mcg_oscsel_t oscsel,mcg_pll_clk_select_t pllcs,mcg_pll_config_t const * config)2868 status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config)
2869 {
2870 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
2871     /* If external PLL is used, then the config could be NULL. */
2872     if (kMCG_PllClkSelExtPll != pllcs)
2873     {
2874 #endif
2875         assert(config);
2876 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
2877     }
2878 #endif
2879 
2880     (void)CLOCK_SetExternalRefClkConfig(oscsel);
2881 
2882     (void)CLOCK_SetPbeMode(pllcs, config);
2883 
2884     /* Change to use PLL output clock. */
2885     MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut));
2886     while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll)
2887     {
2888     }
2889 
2890     return kStatus_Success;
2891 }
2892 
2893 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
2894 /*!
2895  * brief Sets the MCG to PEI mode during sytem boot up.
2896  *
2897  * This function sets the MCG to PEI mode from the reset mode. It can be used to
2898  * set up the MCG during system boot up.
2899  *
2900  * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2901  * retval kStatus_Success Switched to the target mode successfully.
2902  */
CLOCK_BootToPeiMode(void)2903 status_t CLOCK_BootToPeiMode(void)
2904 {
2905     /* set PLLS to select PLL */
2906     MCG->C6 |= MCG_C6_PLLS_MASK;
2907     while (0U == (MCG->S & MCG_S_PLLST_MASK))
2908     {
2909     }
2910 
2911     /* Disable lowpower. */
2912     MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK);
2913 
2914     /* Set MCG_C7[PLL32KREFSEL] to select slow IRC clock source */
2915     MCG->C7 = (uint8_t)((MCG->C7 & ~MCG_C7_PLL32KREFSEL_MASK) | MCG_C7_PLL32KREFSEL(kMCG_PllRefIrc));
2916 
2917     while (((MCG->S & MCG_S_LOCK0_MASK)) == 0U)
2918     {
2919     }
2920 
2921     /* Change to use PLL output clock. */
2922     MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut));
2923     while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll)
2924     {
2925     }
2926 
2927     return kStatus_Success;
2928 }
2929 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
2930 #endif /* FSL_FEATURE_MCG_HAS_PLL */
2931 
2932 /*
2933    The transaction matrix. It defines the path for mode switch, the row is for
2934    current mode and the column is target mode.
2935    For example, switch from FEI to PEE:
2936    1. Current mode FEI, next mode is mcgModeMatrix[FEI][PEE] = FBE, so swith to FBE.
2937    2. Current mode FBE, next mode is mcgModeMatrix[FBE][PEE] = PBE, so swith to PBE.
2938    3. Current mode PBE, next mode is mcgModeMatrix[PBE][PEE] = PEE, so swith to PEE.
2939    Thus the MCG mode has changed from FEI to PEE.
2940  */
2941 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
2942 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
2943 static const mcg_mode_t mcgModeMatrix[10][10] = {
2944     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE,
2945      kMCG_ModeFBI, kMCG_ModeFBI}, /* FEI */
2946     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE,
2947      kMCG_ModeFBI, kMCG_ModeFBI}, /* FBI */
2948     {kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI,
2949      kMCG_ModeFBI, kMCG_ModeFBI}, /* BLPI */
2950     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE,
2951      kMCG_ModeFBI, kMCG_ModeFBI}, /* FEE */
2952     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeBLPE, kMCG_ModePBE, kMCG_ModePBE,
2953      kMCG_ModeFBI, kMCG_ModeFBI}, /* FBE */
2954     {kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeBLPE, kMCG_ModePBE, kMCG_ModePBE,
2955      kMCG_ModeFBE, kMCG_ModeFBE}, /* BLPE */
2956     {kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeBLPE, kMCG_ModePBE, kMCG_ModePEE,
2957      kMCG_ModeFBE, kMCG_ModeFBE}, /* PBE */
2958     {kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE,
2959      kMCG_ModePBE, kMCG_ModePBE}, /* PEE */
2960     {kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI,
2961      kMCG_ModeFBI, kMCG_ModeFBI}, /* PEI */
2962     {kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI,
2963      kMCG_ModePEI, kMCG_ModeFBI} /* PBI */
2964     /*    FEI           FBI           BLPI           FEE           FBE           BLPE           PBE           PEE
2965        PEI           PBI        */
2966 };
2967 #else  /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
2968 static const mcg_mode_t mcgModeMatrix[8][8] = {
2969     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE,
2970      kMCG_ModeFBE}, /* FEI */
2971     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE,
2972      kMCG_ModeFBE}, /* FBI */
2973     {kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI,
2974      kMCG_ModeFBI}, /* BLPI */
2975     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE,
2976      kMCG_ModeFBE}, /* FEE */
2977     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeBLPE, kMCG_ModePBE,
2978      kMCG_ModePBE}, /* FBE */
2979     {kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeBLPE, kMCG_ModePBE,
2980      kMCG_ModePBE}, /* BLPE */
2981     {kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeBLPE, kMCG_ModePBE,
2982      kMCG_ModePEE}, /* PBE */
2983     {kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE,
2984      kMCG_ModePBE} /* PEE */
2985     /*    FEI           FBI           BLPI           FEE           FBE           BLPE           PBE           PEE */
2986 };
2987 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
2988 #else  /* FSL_FEATURE_MCG_HAS_PLL */
2989 static const mcg_mode_t mcgModeMatrix[6][6] = {
2990     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE},  /* FEI */
2991     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE}, /* FBI */
2992     {kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI}, /* BLPI */
2993     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE},  /* FEE */
2994     {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeBLPE}, /* FBE */
2995     {kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeBLPE}, /* BLPE */
2996     /*      FEI           FBI           BLPI          FEE           FBE           BLPE      */
2997 };
2998 #endif /* FSL_FEATURE_MCG_HAS_PLL */
2999 
3000 /*!
3001  * brief Sets the MCG to a target mode.
3002  *
3003  * This function sets MCG to a target mode defined by the configuration
3004  * structure. If switching to the target mode fails, this function
3005  * chooses the correct path.
3006  *
3007  * param  config Pointer to the target MCG mode configuration structure.
3008  * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status.
3009  *
3010  * note If the external clock is used in the target mode, ensure that it is
3011  * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this
3012  * function.
3013  */
CLOCK_SetMcgConfig(const mcg_config_t * config)3014 status_t CLOCK_SetMcgConfig(const mcg_config_t *config)
3015 {
3016     mcg_mode_t next_mode;
3017     status_t status = kStatus_Success;
3018 
3019 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
3020 
3021 #if ((defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1) || \
3022      (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL))
3023     mcg_pll_clk_select_t pllcs = config->pllcs;
3024 #else
3025     mcg_pll_clk_select_t pllcs = kMCG_PllClkSelPll0;
3026 #endif
3027 
3028 #endif /* FSL_FEATURE_MCG_HAS_PLL */
3029 
3030 #if (defined(FSL_FEATURE_MCG_USE_OSCSEL) && FSL_FEATURE_MCG_USE_OSCSEL)
3031     /* If need to change external clock, MCG_C7[OSCSEL]. */
3032     if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel))
3033     {
3034         /* If external clock is in use, change to FEI first. */
3035         if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
3036         {
3037             (void)CLOCK_ExternalModeToFbeModeQuick();
3038             (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL);
3039         }
3040 
3041         (void)CLOCK_SetExternalRefClkConfig(config->oscsel);
3042     }
3043 #endif /* FSL_FEATURE_MCG_USE_OSCSEL */
3044 
3045     /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */
3046     if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt)
3047     {
3048         MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */
3049 
3050 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
3051         if ((MCG->S & MCG_S_PLLST_MASK) != 0U)
3052         {
3053             (void)CLOCK_SetPeiMode();
3054         }
3055         else
3056 #endif
3057         {
3058             (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay);
3059         }
3060     }
3061 
3062     /* Configure MCGIRCLK. */
3063     (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv);
3064 
3065     next_mode = CLOCK_GetMode();
3066 
3067     do
3068     {
3069         next_mode = mcgModeMatrix[next_mode][config->mcgMode];
3070 
3071         switch (next_mode)
3072         {
3073             case kMCG_ModeFEI:
3074                 status = CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay);
3075                 break;
3076             case kMCG_ModeFEE:
3077                 status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay);
3078                 break;
3079             case kMCG_ModeFBI:
3080                 status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL);
3081                 break;
3082             case kMCG_ModeFBE:
3083                 status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL);
3084                 break;
3085             case kMCG_ModeBLPI:
3086                 status = CLOCK_SetBlpiMode();
3087                 break;
3088             case kMCG_ModeBLPE:
3089                 status = CLOCK_SetBlpeMode();
3090                 break;
3091 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
3092             case kMCG_ModePBE:
3093 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
3094                 status = CLOCK_SetPbeMode(pllcs, &config->pll0Config);
3095 #else /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
3096                 /* If target mode is not PBE or PEE, then only need to set CLKS = EXT here. */
3097                 if ((kMCG_ModePEE == config->mcgMode) || (kMCG_ModePBE == config->mcgMode))
3098                 {
3099 #if ((defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1) || \
3100      (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL))
3101                     if (kMCG_PllClkSelPll0 == pllcs)
3102 #endif
3103                     {
3104                         status = CLOCK_SetPbeMode(pllcs, &config->pll0Config);
3105                     }
3106 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
3107                     else if (kMCG_PllClkSelPll1 == pllcs)
3108                     {
3109                         status = CLOCK_SetPbeMode(pllcs, &config->pll1Config);
3110                     }
3111 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
3112 #if (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL)
3113                     else if (kMCG_PllClkSelExtPll == pllcs)
3114                     {
3115                         status = CLOCK_SetPbeMode(pllcs, NULL);
3116                     }
3117 #endif /* FSL_FEATURE_MCG_HAS_EXTERNAL_PLL */
3118 #if ((defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1) || \
3119      (defined(FSL_FEATURE_MCG_HAS_EXTERNAL_PLL) && FSL_FEATURE_MCG_HAS_EXTERNAL_PLL))
3120                     else
3121                     {
3122                         /* Add comment to prevent the case of MISRA C-2012 rule 15.7 */
3123                     }
3124 #endif
3125                 }
3126                 else
3127                 {
3128                     MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal));
3129                     while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt)
3130                     {
3131                     }
3132                 }
3133 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
3134                 break;
3135             case kMCG_ModePEE:
3136                 status = CLOCK_SetPeeMode();
3137                 break;
3138 #if (defined(FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE) && FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE)
3139             case kMCG_ModePBI:
3140                 status = CLOCK_SetPbiMode();
3141                 break;
3142             case kMCG_ModePEI:
3143                 status = CLOCK_SetPeiMode();
3144                 break;
3145 #endif /* FSL_FEATURE_MCG_HAS_PLL_INTERNAL_MODE */
3146 #endif
3147             default:
3148                 assert(false);
3149                 break;
3150         }
3151         if (kStatus_Success != status)
3152         {
3153             break;
3154         }
3155     } while (next_mode != config->mcgMode);
3156 
3157 #if (defined(FSL_FEATURE_MCG_HAS_PLL) && FSL_FEATURE_MCG_HAS_PLL)
3158     if (status == kStatus_Success)
3159     {
3160         if ((config->pll0Config.enableMode & (uint8_t)kMCG_PllEnableIndependent) != 0U)
3161         {
3162             CLOCK_EnablePll0(&config->pll0Config);
3163         }
3164         else
3165         {
3166             MCG->C5 &= ~(uint8_t)kMCG_PllEnableIndependent;
3167         }
3168 #if (defined(FSL_FEATURE_MCG_HAS_PLL1) && FSL_FEATURE_MCG_HAS_PLL1)
3169         if ((config->pll1Config.enableMode & kMCG_PllEnableIndependent) != 0U)
3170         {
3171             CLOCK_EnablePll1(&config->pll1Config);
3172         }
3173         else
3174         {
3175             MCG->C11 &= ~(uint32_t)kMCG_PllEnableIndependent;
3176         }
3177 #endif /* FSL_FEATURE_MCG_HAS_PLL1 */
3178     }
3179 #endif /* FSL_FEATURE_MCG_HAS_PLL */
3180 
3181     return status;
3182 }
3183