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