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