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