aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/driver_clock.cmake16
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/driver_reset.cmake14
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/fsl_clock.c2630
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/fsl_clock.h1754
4 files changed, 4414 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/driver_clock.cmake b/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/driver_clock.cmake
new file mode 100644
index 000000000..154d6a23a
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/driver_clock.cmake
@@ -0,0 +1,16 @@
1if(NOT DRIVER_CLOCK_INCLUDED)
2
3 set(DRIVER_CLOCK_INCLUDED true CACHE BOOL "driver_clock component is included.")
4
5 target_sources(${MCUX_SDK_PROJECT_NAME} PRIVATE
6 ${CMAKE_CURRENT_LIST_DIR}/fsl_clock.c
7 )
8
9 target_include_directories(${MCUX_SDK_PROJECT_NAME} PRIVATE
10 ${CMAKE_CURRENT_LIST_DIR}/.
11 )
12
13
14 include(driver_common)
15
16endif() \ No newline at end of file
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/driver_reset.cmake b/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/driver_reset.cmake
new file mode 100644
index 000000000..989530f6f
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/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/MK28FA15/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/fsl_clock.c
new file mode 100644
index 000000000..4a18696e4
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/fsl_clock.c
@@ -0,0 +1,2630 @@
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_OUTDIV3_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV3_MASK) >> SIM_CLKDIV1_OUTDIV3_SHIFT)
74#define SIM_CLKDIV1_OUTDIV4_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT)
75#define SIM_SOPT1_OSC32KSEL_VAL ((SIM->SOPT1 & SIM_SOPT1_OSC32KSEL_MASK) >> SIM_SOPT1_OSC32KSEL_SHIFT)
76#define SIM_SOPT2_PLLFLLSEL_VAL ((SIM->SOPT2 & SIM_SOPT2_PLLFLLSEL_MASK) >> SIM_SOPT2_PLLFLLSEL_SHIFT)
77#define SIM_CLKDIV3_PLLFLLDIV_VAL ((SIM->CLKDIV3 & SIM_CLKDIV3_PLLFLLDIV_MASK) >> SIM_CLKDIV3_PLLFLLDIV_SHIFT)
78#define SIM_CLKDIV3_PLLFLLFRAC_VAL ((SIM->CLKDIV3 & SIM_CLKDIV3_PLLFLLFRAC_MASK) >> SIM_CLKDIV3_PLLFLLFRAC_SHIFT)
79
80/* MCG_S_CLKST definition. */
81enum _mcg_clkout_stat
82{
83 kMCG_ClkOutStatFll, /* FLL. */
84 kMCG_ClkOutStatInt, /* Internal clock. */
85 kMCG_ClkOutStatExt, /* External clock. */
86 kMCG_ClkOutStatPll /* PLL. */
87};
88
89/* MCG_S_PLLST definition. */
90enum _mcg_pllst
91{
92 kMCG_PllstFll, /* FLL is used. */
93 kMCG_PllstPll /* PLL is used. */
94};
95
96/*******************************************************************************
97 * Variables
98 ******************************************************************************/
99
100/* Slow internal reference clock frequency. */
101static uint32_t s_slowIrcFreq = 32768U;
102/* Fast internal reference clock frequency. */
103static uint32_t s_fastIrcFreq = 4000000U;
104/* The MCG external PLL clock frequency. */
105static uint32_t s_extPllFreq = 0U;
106
107/* External XTAL0 (OSC0) clock frequency. */
108volatile uint32_t g_xtal0Freq;
109/* External XTAL32K clock frequency. */
110volatile uint32_t g_xtal32Freq;
111
112/*******************************************************************************
113 * Prototypes
114 ******************************************************************************/
115
116/*!
117 * @brief Get the MCG external reference clock frequency.
118 *
119 * Get the current MCG external reference clock frequency in Hz. It is
120 * the frequency select by MCG_C7[OSCSEL]. This is an internal function.
121 *
122 * @return MCG external reference clock frequency in Hz.
123 */
124static uint32_t CLOCK_GetMcgExtClkFreq(void);
125
126/*!
127 * @brief Get the MCG FLL external reference clock frequency.
128 *
129 * Get the current MCG FLL external reference clock frequency in Hz. It is
130 * the frequency after by MCG_C1[FRDIV]. This is an internal function.
131 *
132 * @return MCG FLL external reference clock frequency in Hz.
133 */
134static uint32_t CLOCK_GetFllExtRefClkFreq(void);
135
136/*!
137 * @brief Get the MCG FLL reference clock frequency.
138 *
139 * Get the current MCG FLL reference clock frequency in Hz. It is
140 * the frequency select by MCG_C1[IREFS]. This is an internal function.
141 *
142 * @return MCG FLL reference clock frequency in Hz.
143 */
144static uint32_t CLOCK_GetFllRefClkFreq(void);
145
146/*!
147 * @brief Get the frequency of clock selected by MCG_C2[IRCS].
148 *
149 * This clock's two output:
150 * 1. MCGOUTCLK when MCG_S[CLKST]=0.
151 * 2. MCGIRCLK when MCG_C1[IRCLKEN]=1.
152 *
153 * @return The frequency in Hz.
154 */
155static uint32_t CLOCK_GetInternalRefClkSelectFreq(void);
156
157/*!
158 * @brief Get the MCG PLL/PLL0 reference clock frequency.
159 *
160 * Get the current MCG PLL/PLL0 reference clock frequency in Hz.
161 * This is an internal function.
162 *
163 * @return MCG PLL/PLL0 reference clock frequency in Hz.
164 */
165static uint32_t CLOCK_GetPll0RefFreq(void);
166
167/*!
168 * @brief Calculate the RANGE value base on crystal frequency.
169 *
170 * To setup external crystal oscillator, must set the register bits RANGE
171 * base on the crystal frequency. This function returns the RANGE base on the
172 * input frequency. This is an internal function.
173 *
174 * @param freq Crystal frequency in Hz.
175 * @return The RANGE value.
176 */
177static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq);
178
179#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN
180/*!
181 * @brief Delay function to wait FLL stable.
182 *
183 * Delay function to wait FLL stable in FEI mode or FEE mode, should wait at least
184 * 1ms. Every time changes FLL setting, should wait this time for FLL stable.
185 */
186static void CLOCK_FllStableDelay(void);
187#endif
188
189/*******************************************************************************
190 * Code
191 ******************************************************************************/
192
193#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN
194static void CLOCK_FllStableDelay(void)
195{
196 /*
197 Should wait at least 1ms. Because in these modes, the core clock is 100MHz
198 at most, so this function could obtain the 1ms delay.
199 */
200 volatile uint32_t i = 30000U;
201 while (0U != (i--))
202 {
203 __NOP();
204 }
205}
206#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */
207/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to
208 * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this
209 * file would call the CLOCK_FllStableDelay() regardless how it is defined.
210 */
211extern void CLOCK_FllStableDelay(void);
212#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */
213
214static uint32_t CLOCK_GetMcgExtClkFreq(void)
215{
216 uint32_t freq;
217
218 switch (MCG_C7_OSCSEL_VAL)
219 {
220 case 0U:
221 /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
222 assert(0U != g_xtal0Freq);
223 freq = g_xtal0Freq;
224 break;
225 case 1U:
226 /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */
227 assert(0U != g_xtal32Freq);
228 freq = g_xtal32Freq;
229 break;
230 case 2U:
231 freq = MCG_INTERNAL_IRC_48M;
232 break;
233 default:
234 freq = 0U;
235 break;
236 }
237
238 return freq;
239}
240
241static uint32_t CLOCK_GetFllExtRefClkFreq(void)
242{
243 /* FllExtRef = McgExtRef / FllExtRefDiv */
244 uint8_t frdiv;
245 uint8_t range;
246 uint8_t oscsel;
247
248 uint32_t freq = CLOCK_GetMcgExtClkFreq();
249
250 frdiv = MCG_C1_FRDIV_VAL;
251 freq >>= frdiv;
252
253 range = MCG_C2_RANGE_VAL;
254 oscsel = MCG_C7_OSCSEL_VAL;
255
256 /*
257 When should use divider 32, 64, 128, 256, 512, 1024, 1280, 1536.
258 1. MCG_C7[OSCSEL] selects IRC48M.
259 2. MCG_C7[OSCSEL] selects OSC0 and MCG_C2[RANGE] is not 0.
260 */
261 if (((0U != range) && ((uint8_t)kMCG_OscselOsc == oscsel)) || ((uint8_t)kMCG_OscselIrc == oscsel))
262 {
263 switch (frdiv)
264 {
265 case 0:
266 case 1:
267 case 2:
268 case 3:
269 case 4:
270 case 5:
271 freq >>= 5u;
272 break;
273 case 6:
274 /* 64*20=1280 */
275 freq /= 20u;
276 break;
277 case 7:
278 /* 128*12=1536 */
279 freq /= 12u;
280 break;
281 default:
282 freq = 0u;
283 break;
284 }
285 }
286
287 return freq;
288}
289
290static uint32_t CLOCK_GetInternalRefClkSelectFreq(void)
291{
292 uint32_t freq;
293
294 if ((uint8_t)kMCG_IrcSlow == MCG_S_IRCST_VAL)
295 {
296 /* Slow internal reference clock selected*/
297 freq = s_slowIrcFreq;
298 }
299 else
300 {
301 /* Fast internal reference clock selected*/
302 freq = s_fastIrcFreq >> MCG_SC_FCRDIV_VAL;
303 }
304
305 return freq;
306}
307
308static uint32_t CLOCK_GetFllRefClkFreq(void)
309{
310 uint32_t freq;
311
312 /* If use external reference clock. */
313 if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
314 {
315 freq = CLOCK_GetFllExtRefClkFreq();
316 }
317 /* If use internal reference clock. */
318 else
319 {
320 freq = s_slowIrcFreq;
321 }
322
323 return freq;
324}
325
326static uint32_t CLOCK_GetPll0RefFreq(void)
327{
328 /* MCG external reference clock. */
329 return CLOCK_GetMcgExtClkFreq();
330}
331
332static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq)
333{
334 uint8_t range;
335
336 if (freq <= 39063U)
337 {
338 range = 0U;
339 }
340 else if (freq <= 8000000U)
341 {
342 range = 1U;
343 }
344 else
345 {
346 range = 2U;
347 }
348
349 return range;
350}
351
352/*!
353 * brief Get the OSC0 external reference undivided clock frequency (OSC0ERCLK_UNDIV).
354 *
355 * return Clock frequency in Hz.
356 */
357uint32_t CLOCK_GetOsc0ErClkUndivFreq(void)
358{
359 uint32_t freq;
360 if ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U)
361 {
362 /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
363 assert(g_xtal0Freq);
364 freq = g_xtal0Freq;
365 }
366 else
367 {
368 freq = 0U;
369 }
370 return freq;
371}
372
373uint32_t CLOCK_GetOsc0ErClkDivFreq(void)
374{
375 uint32_t freq;
376 uint8_t temp;
377 if ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U)
378 {
379 /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
380 assert(g_xtal0Freq);
381 temp = OSC0->DIV & OSC_DIV_ERPS_MASK;
382 freq = g_xtal0Freq >> ((temp) >> OSC_DIV_ERPS_SHIFT);
383 }
384 else
385 {
386 freq = 0U;
387 }
388 return freq;
389}
390
391/*!
392 * brief Get the external reference 32K clock frequency (ERCLK32K).
393 *
394 * return Clock frequency in Hz.
395 */
396uint32_t CLOCK_GetEr32kClkFreq(void)
397{
398 uint32_t freq;
399
400 switch (SIM_SOPT1_OSC32KSEL_VAL)
401 {
402 case 0U: /* OSC 32k clock */
403 freq = (CLOCK_GetOsc0ErClkUndivFreq() == 32768U) ? 32768U : 0U;
404 break;
405 case 2U: /* RTC 32k clock */
406 /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */
407 assert(g_xtal32Freq);
408 freq = g_xtal32Freq;
409 break;
410 case 3U: /* LPO clock */
411 freq = LPO_CLK_FREQ;
412 break;
413 default:
414 freq = 0U;
415 break;
416 }
417 return freq;
418}
419
420/*!
421 * brief Get the output clock frequency selected by SIM[PLLFLLSEL].
422 *
423 * return Clock frequency in Hz.
424 */
425uint32_t CLOCK_GetPllFllSelClkFreq(void)
426{
427 uint32_t freq;
428
429 switch (SIM_SOPT2_PLLFLLSEL_VAL)
430 {
431 case 0U: /* FLL. */
432 freq = CLOCK_GetFllFreq();
433 break;
434 case 1U: /* PLL. */
435 freq = CLOCK_GetPll0Freq();
436 break;
437 case 2U: /* USB1 PFD. */
438 freq = CLOCK_GetExtPllFreq();
439 break;
440 case 3U: /* MCG IRC48M. */
441 freq = MCG_INTERNAL_IRC_48M;
442 break;
443 default:
444 freq = 0U;
445 break;
446 }
447
448 freq *= (SIM_CLKDIV3_PLLFLLFRAC_VAL + 1U);
449 freq /= (SIM_CLKDIV3_PLLFLLDIV_VAL + 1U);
450 return freq;
451}
452
453/*!
454 * brief Get the OSC0 external reference clock frequency (OSC0ERCLK).
455 *
456 * return Clock frequency in Hz.
457 */
458uint32_t CLOCK_GetOsc0ErClkFreq(void)
459{
460 return CLOCK_GetOsc0ErClkDivFreq();
461}
462
463/*!
464 * brief Get the platform clock frequency.
465 *
466 * return Clock frequency in Hz.
467 */
468uint32_t CLOCK_GetPlatClkFreq(void)
469{
470 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1UL);
471}
472
473/*!
474 * brief Get the flash clock frequency.
475 *
476 * return Clock frequency in Hz.
477 */
478uint32_t CLOCK_GetFlashClkFreq(void)
479{
480 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1UL);
481}
482
483/*!
484 * brief Get the flexbus clock frequency.
485 *
486 * return Clock frequency in Hz.
487 */
488uint32_t CLOCK_GetFlexBusClkFreq(void)
489{
490 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV3_VAL + 1UL);
491}
492
493/*!
494 * brief Get the bus clock frequency.
495 *
496 * return Clock frequency in Hz.
497 */
498uint32_t CLOCK_GetBusClkFreq(void)
499{
500 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1UL);
501}
502
503/*!
504 * brief Get the core clock or system clock frequency.
505 *
506 * return Clock frequency in Hz.
507 */
508uint32_t CLOCK_GetCoreSysClkFreq(void)
509{
510 return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1UL);
511}
512
513/*!
514 * brief Gets the clock frequency for a specific clock name.
515 *
516 * This function checks the current clock configurations and then calculates
517 * the clock frequency for a specific clock name defined in clock_name_t.
518 * The MCG must be properly configured before using this function.
519 *
520 * param clockName Clock names defined in clock_name_t
521 * return Clock frequency value in Hertz
522 */
523uint32_t CLOCK_GetFreq(clock_name_t clockName)
524{
525 uint32_t freq;
526
527 switch (clockName)
528 {
529 case kCLOCK_CoreSysClk:
530 case kCLOCK_PlatClk:
531 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1UL);
532 break;
533 case kCLOCK_BusClk:
534 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV2_VAL + 1UL);
535 break;
536 case kCLOCK_FlexBusClk:
537 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV3_VAL + 1UL);
538 break;
539 case kCLOCK_FlashClk:
540 freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV4_VAL + 1UL);
541 break;
542 case kCLOCK_PllFllSelClk:
543 freq = CLOCK_GetPllFllSelClkFreq();
544 break;
545 case kCLOCK_Er32kClk:
546 freq = CLOCK_GetEr32kClkFreq();
547 break;
548 case kCLOCK_Osc0ErClk:
549 freq = CLOCK_GetOsc0ErClkDivFreq();
550 break;
551 case kCLOCK_Osc0ErClkUndiv:
552 freq = CLOCK_GetOsc0ErClkUndivFreq();
553 break;
554 case kCLOCK_McgFixedFreqClk:
555 freq = CLOCK_GetFixedFreqClkFreq();
556 break;
557 case kCLOCK_McgInternalRefClk:
558 freq = CLOCK_GetInternalRefClkFreq();
559 break;
560 case kCLOCK_McgFllClk:
561 freq = CLOCK_GetFllFreq();
562 break;
563 case kCLOCK_McgPll0Clk:
564 freq = CLOCK_GetPll0Freq();
565 break;
566 case kCLOCK_McgIrc48MClk:
567 freq = MCG_INTERNAL_IRC_48M;
568 break;
569 case kCLOCK_LpoClk:
570 freq = LPO_CLK_FREQ;
571 break;
572 default:
573 freq = 0U;
574 break;
575 }
576
577 return freq;
578}
579
580/*!
581 * brief Set the clock configure in SIM module.
582 *
583 * This function sets system layer clock settings in SIM module.
584 *
585 * param config Pointer to the configure structure.
586 */
587void CLOCK_SetSimConfig(sim_clock_config_t const *config)
588{
589 SIM->CLKDIV1 = config->clkdiv1;
590 CLOCK_SetPllFllSelClock(config->pllFllSel, config->pllFllDiv, config->pllFllFrac);
591 CLOCK_SetEr32kClock(config->er32kSrc);
592}
593
594/*! brief Enable USB FS clock.
595 *
596 * param src USB FS clock source.
597 * param freq The frequency specified by src.
598 * retval true The clock is set successfully.
599 * retval false The clock source is invalid to get proper USB FS clock.
600 */
601bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq)
602{
603 bool ret = true;
604
605 CLOCK_DisableClock(kCLOCK_Usbfs0);
606
607 if (kCLOCK_UsbSrcExt == src)
608 {
609 SIM->SOPT2 &= ~SIM_SOPT2_USBSRC_MASK;
610 }
611 else
612 {
613 switch (freq)
614 {
615 case 120000000U:
616 SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(4) | SIM_CLKDIV2_USBFRAC(1);
617 break;
618 case 96000000U:
619 SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(1) | SIM_CLKDIV2_USBFRAC(0);
620 break;
621 case 72000000U:
622 SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC(1);
623 break;
624 case 48000000U:
625 SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0) | SIM_CLKDIV2_USBFRAC(0);
626 break;
627 default:
628 ret = false;
629 break;
630 }
631
632 SIM->SOPT2 = ((SIM->SOPT2 & ~(SIM_SOPT2_PLLFLLSEL_MASK | SIM_SOPT2_USBSRC_MASK)) | (uint32_t)src);
633 }
634
635 CLOCK_EnableClock(kCLOCK_Usbfs0);
636
637 if (kCLOCK_UsbSrcIrc48M == src)
638 {
639 USB0->CLK_RECOVER_IRC_EN = 0x03U;
640 USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK;
641 }
642 return ret;
643}
644
645/*! brief Enable USB HS clock.
646 *
647 * param src USB HS clock source.
648 * param freq The frequency specified by src.
649 * retval true The clock is set successfully.
650 * retval false The clock source is invalid to get proper USB HS clock.
651 */
652bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq)
653{
654 /* Source and freq are not used for USB HS. */
655 src = src;
656 freq = freq;
657
658 SIM->SCGC3 |= SIM_SCGC3_USBHS_MASK;
659
660 SIM->USBPHYCTL = ((SIM->USBPHYCTL & ~(SIM_USBPHYCTL_USB3VOUTTRG_MASK)) | SIM_USBPHYCTL_USB3VOUTTRG(6U) /* 3.310V */
661 | SIM_USBPHYCTL_USBVREGSEL_MASK); /* VREG_IN1 */
662
663 USBPHY->PLL_SIC |= USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* Enable USB clock output from USB PHY PLL */
664
665 return true;
666}
667
668void CLOCK_DisableUsbhs0Clock(void)
669{
670 USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK; /* Disable USB clock output from USB PHY PLL */
671 SIM->SCGC3 &= ~SIM_SCGC3_USBHS_MASK;
672}
673
674/*! brief Enable USB hs0PhyPll clock.
675 *
676 * param src USB HS clock source.
677 * param freq The frequency specified by src.
678 * retval true The clock is set successfully.
679 * retval false The clock source is invalid to get proper USB HS clock.
680 */
681bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
682{
683 volatile uint32_t i;
684 uint32_t phyPllDiv = 0U;
685
686 /*
687 * In order to bring up the internal 480MHz USB PLL clock, should make sure:
688 * 1. 32kHz IRC clock enable by setting IRCLKEN bit in MCG_C1 register.
689 * 2. External reference clock enable on XTAL by setting ERCLKEN bit in OSC_CR register.
690 */
691 assert(MCG->C1 & MCG_C1_IRCLKEN_MASK);
692 assert((MCG->C2 & MCG_C2_IRCS_MASK) == 0U);
693 assert(OSC0->CR & OSC_CR_ERCLKEN_MASK);
694
695 if (24000000U == freq)
696 {
697 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);
698 }
699 else if (16000000U == freq)
700 {
701 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);
702 }
703 else if (12000000U == freq)
704 {
705 phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);
706 }
707 else
708 {
709 return false;
710 }
711
712 /* Source and freq are not used for USB HS. */
713 src = src;
714
715 SIM->SCGC3 |= SIM_SCGC3_USBHSPHY_MASK;
716 SIM->SOPT2 |= SIM_SOPT2_USBREGEN_MASK;
717
718 i = 500000U;
719 while ((i--) != 0UL)
720 {
721 __NOP();
722 }
723
724 USBPHY->TRIM_OVERRIDE_EN = 0x01U; /* Override the trim. */
725 USBPHY->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */
726 USBPHY->PLL_SIC |= USBPHY_PLL_SIC_PLL_POWER_MASK; /* power up PLL */
727 USBPHY->PLL_SIC = (USBPHY->PLL_SIC & ~USBPHY_PLL_SIC_PLL_DIV_SEL_MASK) | phyPllDiv;
728 USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_BYPASS_MASK; /* Clear bypass bit */
729 USBPHY->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK; /* Clear to 0U to run clocks */
730
731 /* Wait for lock. */
732 while ((USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK) == 0UL)
733 {
734 }
735
736 return true;
737}
738
739void CLOCK_DisableUsbhs0PhyPllClock(void)
740{
741 USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
742 USBPHY->PLL_SIC &= ~USBPHY_PLL_SIC_PLL_POWER_MASK; /* Power down PLL */
743 SIM->SOPT2 &= ~SIM_SOPT2_USBREGEN_MASK;
744 SIM->SCGC3 &= ~SIM_SCGC3_USBHSPHY_MASK;
745}
746
747void CLOCK_EnableUsbhs0PfdClock(uint8_t frac, clock_usb_pfd_src_t src)
748{
749 assert((frac <= 35U) && (frac >= 18U));
750 uint32_t fracFreq = (480000U * 18U / frac) * 1000U;
751
752 USBPHY->ANACTRL = (USBPHY->ANACTRL & ~(USBPHY_ANACTRL_PFD_FRAC_MASK | USBPHY_ANACTRL_PFD_CLK_SEL_MASK)) |
753 (USBPHY_ANACTRL_PFD_FRAC(frac) | USBPHY_ANACTRL_PFD_CLK_SEL(src));
754
755 USBPHY->ANACTRL &= ~USBPHY_ANACTRL_PFD_CLKGATE_MASK;
756 while ((USBPHY->ANACTRL & USBPHY_ANACTRL_PFD_STABLE_MASK) == 0U)
757 {
758 }
759
760 if (kCLOCK_UsbPfdSrcExt == src)
761 {
762 s_extPllFreq = g_xtal0Freq;
763 }
764 else if (kCLOCK_UsbPfdSrcFracDivBy4 == src)
765 {
766 s_extPllFreq = fracFreq / 4U;
767 }
768 else if (kCLOCK_UsbPfdSrcFracDivBy2 == src)
769 {
770 s_extPllFreq = fracFreq / 2U;
771 }
772 else
773 {
774 s_extPllFreq = fracFreq;
775 }
776}
777
778void CLOCK_DisableUsbhs0PfdClock(void)
779{
780 USBPHY->ANACTRL |= USBPHY_ANACTRL_PFD_CLKGATE_MASK;
781 s_extPllFreq = 0U;
782}
783
784/*!
785 * brief Gets the MCG output clock (MCGOUTCLK) frequency.
786 *
787 * This function gets the MCG output clock frequency in Hz based on the current MCG
788 * register value.
789 *
790 * return The frequency of MCGOUTCLK.
791 */
792uint32_t CLOCK_GetOutClkFreq(void)
793{
794 uint32_t mcgoutclk;
795 uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL;
796 uint32_t pllcst = MCG_S2_PLLCST_VAL;
797
798 switch (clkst)
799 {
800 case (uint32_t)kMCG_ClkOutStatPll:
801 switch (pllcst)
802 {
803 case (uint32_t)kMCG_PllClkSelExtPll:
804 mcgoutclk = CLOCK_GetExtPllFreq();
805 break;
806 case (uint32_t)kMCG_PllClkSelPll0:
807 mcgoutclk = CLOCK_GetPll0Freq();
808 break;
809 default:
810 mcgoutclk = 0U;
811 break;
812 }
813 break;
814 case (uint32_t)kMCG_ClkOutStatFll:
815 mcgoutclk = CLOCK_GetFllFreq();
816 break;
817 case (uint32_t)kMCG_ClkOutStatInt:
818 mcgoutclk = CLOCK_GetInternalRefClkSelectFreq();
819 break;
820 case (uint32_t)kMCG_ClkOutStatExt:
821 mcgoutclk = CLOCK_GetMcgExtClkFreq();
822 break;
823 default:
824 mcgoutclk = 0U;
825 break;
826 }
827
828 return mcgoutclk;
829}
830
831/*!
832 * brief Gets the MCG FLL clock (MCGFLLCLK) frequency.
833 *
834 * This function gets the MCG FLL clock frequency in Hz based on the current MCG
835 * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and
836 * disabled in low power state in other modes.
837 *
838 * return The frequency of MCGFLLCLK.
839 */
840uint32_t CLOCK_GetFllFreq(void)
841{
842 static const uint16_t fllFactorTable[4][2] = {{640, 732}, {1280, 1464}, {1920, 2197}, {2560, 2929}};
843
844 uint8_t drs, dmx32;
845 uint32_t freq;
846 uint32_t ret;
847
848 /* If FLL is not enabled currently, then return 0U. */
849 if ((((MCG->C2 & MCG_C2_LP_MASK) != 0U) || ((MCG->S & MCG_S_PLLST_MASK) != 0U)))
850 {
851 ret = 0U;
852 }
853 else
854 {
855 /* Get FLL reference clock frequency. */
856 freq = CLOCK_GetFllRefClkFreq();
857 if (0U == freq)
858 {
859 ret = freq;
860 }
861 else
862 {
863 drs = MCG_C4_DRST_DRS_VAL;
864 dmx32 = MCG_C4_DMX32_VAL;
865 ret = freq * fllFactorTable[drs][dmx32];
866 }
867 }
868
869 return ret;
870}
871
872/*!
873 * brief Gets the MCG internal reference clock (MCGIRCLK) frequency.
874 *
875 * This function gets the MCG internal reference clock frequency in Hz based
876 * on the current MCG register value.
877 *
878 * return The frequency of MCGIRCLK.
879 */
880uint32_t CLOCK_GetInternalRefClkFreq(void)
881{
882 uint32_t freq;
883
884 /* If MCGIRCLK is gated. */
885 if (0U == (MCG->C1 & MCG_C1_IRCLKEN_MASK))
886 {
887 freq = 0U;
888 }
889 else
890 {
891 freq = CLOCK_GetInternalRefClkSelectFreq();
892 }
893
894 return freq;
895}
896
897/*!
898 * brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency.
899 *
900 * This function gets the MCG fixed frequency clock frequency in Hz based
901 * on the current MCG register value.
902 *
903 * return The frequency of MCGFFCLK.
904 */
905uint32_t CLOCK_GetFixedFreqClkFreq(void)
906{
907 uint32_t freq = CLOCK_GetFllRefClkFreq();
908 uint32_t ret;
909
910 /* MCGFFCLK must be no more than MCGOUTCLK/8. */
911 if ((freq <= (CLOCK_GetOutClkFreq() / 8U)) && (0U != freq))
912 {
913 ret = freq;
914 }
915 else
916 {
917 ret = 0U;
918 }
919
920 return ret;
921}
922
923/*!
924 * brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency.
925 *
926 * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG
927 * register value.
928 *
929 * return The frequency of MCGPLL0CLK.
930 */
931uint32_t CLOCK_GetPll0Freq(void)
932{
933 uint32_t mcgpll0clk;
934 uint32_t freq;
935
936 uint8_t mcgpll0prdiv;
937 uint8_t mcgpll0vdiv;
938 /* If PLL0 is not enabled, return 0. */
939 if (((MCG->S & MCG_S_LOCK0_MASK)) == 0U)
940 {
941 freq = 0U;
942 }
943 else
944 {
945 mcgpll0clk = CLOCK_GetPll0RefFreq();
946
947 /*
948 * Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock.
949 * Please call CLOCK_SetXtal1Freq base on board setting before using OSC1 clock.
950 */
951 assert(mcgpll0clk);
952
953 mcgpll0prdiv = ((uint8_t)FSL_FEATURE_MCG_PLL_PRDIV_BASE + MCG_C5_PRDIV0_VAL);
954 mcgpll0clk /= (uint32_t)mcgpll0prdiv;
955 mcgpll0vdiv = ((uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE + MCG_C6_VDIV0_VAL);
956 mcgpll0clk *= (uint32_t)mcgpll0vdiv;
957
958 mcgpll0clk >>= 1UL;
959 freq = mcgpll0clk;
960 }
961
962 return freq;
963}
964
965/*!
966 * brief Gets the MCG external PLL frequency.
967 *
968 * This function gets the MCG external PLL frequency in Hz.
969 *
970 * return The frequency of the MCG external PLL.
971 */
972uint32_t CLOCK_GetExtPllFreq(void)
973{
974 return s_extPllFreq;
975}
976
977/*!
978 * brief Sets the MCG external PLL frequency.
979 *
980 * This function sets the MCG external PLL frequency in Hz. The MCG external PLL
981 * frequency is passed to the MCG driver using this function. Call this
982 * function after the external PLL frequency is changed. Otherwise, the APIs, which are used to get
983 * the frequency, may return an incorrect value.
984 *
985 * param The frequency of MCG external PLL.
986 */
987void CLOCK_SetExtPllFreq(uint32_t freq)
988{
989 s_extPllFreq = freq;
990}
991
992/*!
993 * brief Selects the MCG external reference clock.
994 *
995 * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL],
996 * and waits for the clock source to be stable. Because the external reference
997 * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes.
998 *
999 * param oscsel MCG external reference clock source, MCG_C7[OSCSEL].
1000 * retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source,
1001 * the configuration should not be changed. Otherwise, a glitch occurs.
1002 * retval kStatus_Success External reference clock set successfully.
1003 */
1004status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel)
1005{
1006 bool needDelay;
1007 uint32_t i;
1008
1009#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1010 /* If change MCG_C7[OSCSEL] and external reference clock is system clock source, return error. */
1011 if ((MCG_C7_OSCSEL_VAL != oscsel) && (!(MCG->S & MCG_S_IREFST_MASK)))
1012 {
1013 return kStatus_MCG_SourceUsed;
1014 }
1015#endif /* MCG_CONFIG_CHECK_PARAM */
1016
1017 if (MCG_C7_OSCSEL_VAL != (uint8_t)oscsel)
1018 {
1019 /* If change OSCSEL, need to delay, ERR009878. */
1020 needDelay = true;
1021 }
1022 else
1023 {
1024 needDelay = false;
1025 }
1026
1027 MCG->C7 = (uint8_t)(MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel);
1028 if (needDelay)
1029 {
1030 /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */
1031 i = 1500U;
1032 while (0U != (i--))
1033 {
1034 __NOP();
1035 }
1036 }
1037
1038 return kStatus_Success;
1039}
1040
1041/*!
1042 * brief Configures the Internal Reference clock (MCGIRCLK).
1043 *
1044 * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC
1045 * source. If the fast IRC is used, this function sets the fast IRC divider.
1046 * This function also sets whether the \c MCGIRCLK is enabled in stop mode.
1047 * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result,
1048 * using the function in these modes it is not allowed.
1049 *
1050 * param enableMode MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode.
1051 * param ircs MCGIRCLK clock source, choose fast or slow.
1052 * param fcrdiv Fast IRC divider setting (\c FCRDIV).
1053 * retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source,
1054 * the configuration should not be changed. Otherwise, a glitch occurs.
1055 * retval kStatus_Success MCGIRCLK configuration finished successfully.
1056 */
1057status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv)
1058{
1059 uint32_t mcgOutClkState = (uint32_t)MCG_S_CLKST_VAL;
1060 mcg_irc_mode_t curIrcs = (mcg_irc_mode_t)((uint32_t)MCG_S_IRCST_VAL);
1061 uint8_t curFcrdiv = MCG_SC_FCRDIV_VAL;
1062
1063#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1064 /* If MCGIRCLK is used as system clock source. */
1065 if ((uint32_t)kMCG_ClkOutStatInt == mcgOutClkState)
1066 {
1067 /* If need to change MCGIRCLK source or driver, return error. */
1068 if (((kMCG_IrcFast == curIrcs) && (fcrdiv != curFcrdiv)) || (ircs != curIrcs))
1069 {
1070 return kStatus_MCG_SourceUsed;
1071 }
1072 }
1073#endif
1074
1075 /* If need to update the FCRDIV. */
1076 if (fcrdiv != curFcrdiv)
1077 {
1078 /* If fast IRC is in use currently, change to slow IRC. */
1079 if (((0U != (MCG->C1 & MCG_C1_IRCLKEN_MASK)) || (mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt)) &&
1080 (kMCG_IrcFast == curIrcs))
1081 {
1082 MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(kMCG_IrcSlow)));
1083 while (MCG_S_IRCST_VAL != (uint8_t)kMCG_IrcSlow)
1084 {
1085 }
1086 }
1087 /* Update FCRDIV. */
1088 MCG->SC =
1089 (uint8_t)(MCG->SC & ~(MCG_SC_FCRDIV_MASK | MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK)) | MCG_SC_FCRDIV(fcrdiv);
1090 }
1091
1092 /* Set internal reference clock selection. */
1093 MCG->C2 = (uint8_t)((MCG->C2 & ~MCG_C2_IRCS_MASK) | (MCG_C2_IRCS(ircs)));
1094 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK)) | (uint8_t)enableMode);
1095
1096 /* If MCGIRCLK is used, need to wait for MCG_S_IRCST. */
1097 if ((mcgOutClkState == (uint32_t)kMCG_ClkOutStatInt) || (0U != (enableMode & (uint32_t)kMCG_IrclkEnable)))
1098 {
1099 while (MCG_S_IRCST_VAL != (uint8_t)ircs)
1100 {
1101 }
1102 }
1103
1104 return kStatus_Success;
1105}
1106
1107/*!
1108 * brief Calculates the PLL divider setting for a desired output frequency.
1109 *
1110 * This function calculates the correct reference clock divider (\c PRDIV) and
1111 * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the
1112 * closest frequency match with the corresponding \c PRDIV/VDIV
1113 * returned from parameters. If a desired frequency is not valid, this function
1114 * returns 0.
1115 *
1116 * param refFreq PLL reference clock frequency.
1117 * param desireFreq Desired PLL output frequency.
1118 * param prdiv PRDIV value to generate desired PLL frequency.
1119 * param vdiv VDIV value to generate desired PLL frequency.
1120 * return Closest frequency match that the PLL was able generate.
1121 */
1122uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv)
1123{
1124 uint8_t ret_prdiv; /* PRDIV to return. */
1125 uint8_t ret_vdiv; /* VDIV to return. */
1126 uint8_t prdiv_min; /* Min PRDIV value to make reference clock in allowed range. */
1127 uint8_t prdiv_max; /* Max PRDIV value to make reference clock in allowed range. */
1128 uint8_t prdiv_cur; /* PRDIV value for iteration. */
1129 uint8_t vdiv_cur; /* VDIV value for iteration. */
1130 uint32_t ret_freq = 0U; /* PLL output frequency to return. */
1131 uint32_t diff = 0xFFFFFFFFU; /* Difference between desireFreq and return frequency. */
1132 uint32_t ref_div; /* Reference frequency after PRDIV. */
1133
1134 /*
1135 Steps:
1136 1. Get allowed prdiv with such rules:
1137 1). refFreq / prdiv >= FSL_FEATURE_MCG_PLL_REF_MIN.
1138 2). refFreq / prdiv <= FSL_FEATURE_MCG_PLL_REF_MAX.
1139 2. For each allowed prdiv, there are two candidate vdiv values:
1140 1). (desireFreq / (refFreq / prdiv)).
1141 2). (desireFreq / (refFreq / prdiv)) + 1.
1142 If could get the precise desired frequency, return current prdiv and
1143 vdiv directly. Otherwise choose the one which is closer to desired
1144 frequency.
1145 */
1146
1147 /* Reference frequency is out of range. */
1148 if ((refFreq < (uint32_t)FSL_FEATURE_MCG_PLL_REF_MIN) ||
1149 (refFreq > ((uint32_t)FSL_FEATURE_MCG_PLL_REF_MAX *
1150 ((uint32_t)FSL_FEATURE_MCG_PLL_PRDIV_MAX + (uint32_t)FSL_FEATURE_MCG_PLL_PRDIV_BASE))))
1151 {
1152 return 0U;
1153 }
1154
1155 /* refFreq/PRDIV must in a range. First get the allowed PRDIV range. */
1156 prdiv_max = (uint8_t)(refFreq / (uint32_t)FSL_FEATURE_MCG_PLL_REF_MIN);
1157 prdiv_min =
1158 (uint8_t)((refFreq + (uint32_t)FSL_FEATURE_MCG_PLL_REF_MAX - 1U) / (uint32_t)FSL_FEATURE_MCG_PLL_REF_MAX);
1159
1160 desireFreq *= 2U;
1161
1162 /* PRDIV traversal. */
1163 for (prdiv_cur = prdiv_max; prdiv_cur >= prdiv_min; prdiv_cur--)
1164 {
1165 /* Reference frequency after PRDIV. */
1166 ref_div = refFreq / prdiv_cur;
1167
1168 vdiv_cur = (uint8_t)(desireFreq / ref_div);
1169
1170 if ((vdiv_cur < ((uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE - 1U)) ||
1171 (vdiv_cur > (uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE + 31U))
1172 {
1173 /* No VDIV is available with this PRDIV. */
1174 continue;
1175 }
1176
1177 ret_freq = vdiv_cur * ref_div;
1178
1179 if (vdiv_cur >= (uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE)
1180 {
1181 if (ret_freq == desireFreq) /* If desire frequency is got. */
1182 {
1183 *prdiv = prdiv_cur - (uint8_t)FSL_FEATURE_MCG_PLL_PRDIV_BASE;
1184 *vdiv = vdiv_cur - (uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE;
1185 return ret_freq / 2U;
1186 }
1187 /* New PRDIV/VDIV is closer. */
1188 if (diff > desireFreq - ret_freq)
1189 {
1190 diff = desireFreq - ret_freq;
1191 ret_prdiv = prdiv_cur;
1192 ret_vdiv = vdiv_cur;
1193 }
1194 }
1195 vdiv_cur++;
1196 if (vdiv_cur <= ((uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE + 31U))
1197 {
1198 ret_freq += ref_div;
1199 /* New PRDIV/VDIV is closer. */
1200 if (diff > ret_freq - desireFreq)
1201 {
1202 diff = ret_freq - desireFreq;
1203 ret_prdiv = prdiv_cur;
1204 ret_vdiv = vdiv_cur;
1205 }
1206 }
1207 }
1208
1209 if (0xFFFFFFFFU != diff)
1210 {
1211 /* PRDIV/VDIV found. */
1212 *prdiv = ret_prdiv - (uint8_t)FSL_FEATURE_MCG_PLL_PRDIV_BASE;
1213 *vdiv = ret_vdiv - (uint8_t)FSL_FEATURE_MCG_PLL_VDIV_BASE;
1214 ret_freq = (refFreq / ret_prdiv) * ret_vdiv;
1215 return ret_freq / 2U;
1216 }
1217 else
1218 {
1219 /* No proper PRDIV/VDIV found. */
1220 return 0U;
1221 }
1222}
1223
1224/*!
1225 * brief Enables the PLL0 in FLL mode.
1226 *
1227 * This function sets us the PLL0 in FLL mode and reconfigures
1228 * the PLL0. Ensure that the PLL reference
1229 * clock is enabled before calling this function and that the PLL0 is not used as a clock source.
1230 * The function CLOCK_CalcPllDiv gets the correct PLL
1231 * divider values.
1232 *
1233 * param config Pointer to the configuration structure.
1234 */
1235void CLOCK_EnablePll0(mcg_pll_config_t const *config)
1236{
1237 assert(config);
1238
1239 uint8_t mcg_c5 = 0U;
1240
1241 mcg_c5 |= MCG_C5_PRDIV0(config->prdiv);
1242 MCG->C5 = mcg_c5; /* Disable the PLL first. */
1243
1244 MCG->C6 = (uint8_t)((MCG->C6 & ~MCG_C6_VDIV0_MASK) | MCG_C6_VDIV0(config->vdiv));
1245
1246 /* Set enable mode. */
1247 MCG->C5 |= ((uint8_t)kMCG_PllEnableIndependent | (uint8_t)config->enableMode);
1248
1249 /* Wait for PLL lock. */
1250 while (((MCG->S & MCG_S_LOCK0_MASK)) == 0U)
1251 {
1252 }
1253}
1254
1255/*!
1256 * brief Set the PLL selection.
1257 *
1258 * This function sets the PLL selection between PLL0/PLL1/EXTPLL, and waits for
1259 * change finished.
1260 *
1261 * param pllcs The PLL to select.
1262 */
1263void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs)
1264{
1265 MCG->C11 = (uint8_t)(((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs));
1266 while ((uint32_t)pllcs != MCG_S2_PLLCST_VAL)
1267 {
1268 }
1269}
1270
1271/*!
1272 * brief Sets the OSC0 clock monitor mode.
1273 *
1274 * This function sets the OSC0 clock monitor mode. See ref mcg_monitor_mode_t for details.
1275 *
1276 * param mode Monitor mode to set.
1277 */
1278void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode)
1279{
1280 /* Clear the previous flag, MCG_SC[LOCS0]. */
1281 MCG->SC &= ~(uint8_t)MCG_SC_ATMF_MASK;
1282
1283 if (kMCG_MonitorNone == mode)
1284 {
1285 MCG->C6 &= ~(uint8_t)MCG_C6_CME0_MASK;
1286 }
1287 else
1288 {
1289 if (kMCG_MonitorInt == mode)
1290 {
1291 MCG->C2 &= ~(uint8_t)MCG_C2_LOCRE0_MASK;
1292 }
1293 else
1294 {
1295 MCG->C2 |= MCG_C2_LOCRE0_MASK;
1296 }
1297 MCG->C6 |= MCG_C6_CME0_MASK;
1298 }
1299}
1300
1301/*!
1302 * brief Sets the RTC OSC clock monitor mode.
1303 *
1304 * This function sets the RTC OSC clock monitor mode. See ref mcg_monitor_mode_t for details.
1305 *
1306 * param mode Monitor mode to set.
1307 */
1308void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode)
1309{
1310 uint8_t mcg_c8 = MCG->C8;
1311
1312 mcg_c8 &= ~(uint8_t)(MCG_C8_CME1_MASK | MCG_C8_LOCRE1_MASK);
1313
1314 if (kMCG_MonitorNone != mode)
1315 {
1316 if (kMCG_MonitorReset == mode)
1317 {
1318 mcg_c8 |= MCG_C8_LOCRE1_MASK;
1319 }
1320 mcg_c8 |= MCG_C8_CME1_MASK;
1321 }
1322 MCG->C8 = mcg_c8;
1323}
1324
1325/*!
1326 * brief Sets the PLL0 clock monitor mode.
1327 *
1328 * This function sets the PLL0 clock monitor mode. See ref mcg_monitor_mode_t for details.
1329 *
1330 * param mode Monitor mode to set.
1331 */
1332void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode)
1333{
1334 uint8_t mcg_c8;
1335
1336 /* Clear previous flag. */
1337 MCG->S = MCG_S_LOLS0_MASK;
1338
1339 if (kMCG_MonitorNone == mode)
1340 {
1341 MCG->C6 &= (uint8_t)(~MCG_C6_LOLIE0_MASK);
1342 }
1343 else
1344 {
1345 mcg_c8 = MCG->C8;
1346
1347 mcg_c8 &= (uint8_t)(~MCG_C8_LOCS1_MASK);
1348
1349 if (kMCG_MonitorInt == mode)
1350 {
1351 mcg_c8 &= (uint8_t)(~MCG_C8_LOLRE_MASK);
1352 }
1353 else
1354 {
1355 mcg_c8 |= MCG_C8_LOLRE_MASK;
1356 }
1357 MCG->C8 = mcg_c8;
1358 MCG->C6 |= MCG_C6_LOLIE0_MASK;
1359 }
1360}
1361
1362/*!
1363 * brief Sets the external PLL clock monitor mode.
1364 *
1365 * This function ets the external PLL clock monitor mode. See ref mcg_monitor_mode_t
1366 * for details.
1367 *
1368 * param mode Monitor mode to set.
1369 */
1370void CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode)
1371{
1372 uint8_t mcg_c9 = MCG->C9;
1373
1374 mcg_c9 &= (uint8_t)(~(MCG_C9_PLL_LOCRE_MASK | MCG_C9_PLL_CME_MASK));
1375
1376 if (kMCG_MonitorNone != mode)
1377 {
1378 if (kMCG_MonitorReset == mode)
1379 {
1380 mcg_c9 |= MCG_C9_PLL_LOCRE_MASK;
1381 }
1382 mcg_c9 |= MCG_C9_PLL_CME_MASK;
1383 }
1384 MCG->C9 = mcg_c9;
1385}
1386
1387/*!
1388 * brief Gets the MCG status flags.
1389 *
1390 * This function gets the MCG clock status flags. All status flags are
1391 * returned as a logical OR of the enumeration ref _mcg_status_flags_t. To
1392 * check a specific flag, compare the return value with the flag.
1393 *
1394 * Example:
1395 * code
1396 * To check the clock lost lock status of OSC0 and PLL0.
1397 * uint32_t mcgFlags;
1398 *
1399 * mcgFlags = CLOCK_GetStatusFlags();
1400 *
1401 * if (mcgFlags & kMCG_Osc0LostFlag)
1402 * {
1403 * OSC0 clock lock lost. Do something.
1404 * }
1405 * if (mcgFlags & kMCG_Pll0LostFlag)
1406 * {
1407 * PLL0 clock lock lost. Do something.
1408 * }
1409 * endcode
1410 *
1411 * return Logical OR value of the ref _mcg_status_flags_t.
1412 */
1413uint32_t CLOCK_GetStatusFlags(void)
1414{
1415 uint32_t ret = 0U;
1416 uint8_t mcg_s = MCG->S;
1417
1418 if ((MCG->SC & MCG_SC_LOCS0_MASK) != 0U)
1419 {
1420 ret |= (uint32_t)kMCG_Osc0LostFlag;
1421 }
1422 if ((mcg_s & MCG_S_OSCINIT0_MASK) != 0U)
1423 {
1424 ret |= (uint32_t)kMCG_Osc0InitFlag;
1425 }
1426 if (0U != (MCG->C8 & MCG_C8_LOCS1_MASK))
1427 {
1428 ret |= (uint32_t)kMCG_RtcOscLostFlag;
1429 }
1430 if ((mcg_s & MCG_S_LOLS0_MASK) != 0U)
1431 {
1432 ret |= (uint32_t)kMCG_Pll0LostFlag;
1433 }
1434 if ((mcg_s & MCG_S_LOCK0_MASK) != 0U)
1435 {
1436 ret |= (uint32_t)kMCG_Pll0LockFlag;
1437 }
1438 if ((MCG->C9 & MCG_C9_EXT_PLL_LOCS_MASK) != 0U)
1439 {
1440 ret |= (uint32_t)kMCG_ExtPllLostFlag;
1441 }
1442 return ret;
1443}
1444
1445/*!
1446 * brief Clears the MCG status flags.
1447 *
1448 * This function clears the MCG clock lock lost status. The parameter is a logical
1449 * OR value of the flags to clear. See ref _mcg_status_flags_t.
1450 *
1451 * Example:
1452 * code
1453 * To clear the clock lost lock status flags of OSC0 and PLL0.
1454 *
1455 * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag);
1456 * endcode
1457 *
1458 * param mask The status flags to clear. This is a logical OR of members of the
1459 * enumeration ref _mcg_status_flags_t.
1460 */
1461void CLOCK_ClearStatusFlags(uint32_t mask)
1462{
1463 uint8_t reg;
1464
1465 if ((mask & (uint32_t)kMCG_Osc0LostFlag) != 0UL)
1466 {
1467 MCG->SC &= (uint8_t)(~MCG_SC_ATMF_MASK);
1468 }
1469 if (0U != (mask & (uint32_t)kMCG_RtcOscLostFlag))
1470 {
1471 reg = MCG->C8;
1472 MCG->C8 = reg;
1473 }
1474 if ((mask & (uint32_t)kMCG_Pll0LostFlag) != 0UL)
1475 {
1476 MCG->S = MCG_S_LOLS0_MASK;
1477 }
1478 if ((mask & (uint32_t)kMCG_ExtPllLostFlag) != 0UL)
1479 {
1480 reg = MCG->C9;
1481 MCG->C9 = reg;
1482 }
1483}
1484
1485/*!
1486 * brief Initializes the OSC0.
1487 *
1488 * This function initializes the OSC0 according to the board configuration.
1489 *
1490 * param config Pointer to the OSC0 configuration structure.
1491 */
1492void CLOCK_InitOsc0(osc_config_t const *config)
1493{
1494 uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq);
1495
1496 OSC_SetCapLoad(OSC0, config->capLoad);
1497
1498 MCG->C2 = (uint8_t)((MCG->C2 & ~OSC_MODE_MASK) | MCG_C2_RANGE(range) | (uint8_t)config->workMode);
1499 OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig);
1500
1501 if ((kOSC_ModeExt != config->workMode) && ((OSC0->CR & OSC_CR_ERCLKEN_MASK) != 0U))
1502 {
1503 /* Wait for stable. */
1504 while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
1505 {
1506 }
1507 }
1508}
1509
1510/*!
1511 * brief Deinitializes the OSC0.
1512 *
1513 * This function deinitializes the OSC0.
1514 */
1515void CLOCK_DeinitOsc0(void)
1516{
1517 OSC0->CR = 0U;
1518 MCG->C2 &= ~(uint8_t)OSC_MODE_MASK;
1519}
1520
1521/*!
1522 * brief Set the Slow IRC frequency based on the trimmed value
1523 *
1524 * param freq The Slow IRC frequency input clock frequency in Hz.
1525 */
1526void CLOCK_SetSlowIrcFreq(uint32_t freq)
1527{
1528 s_slowIrcFreq = freq;
1529}
1530
1531/*!
1532 * brief Set the Fast IRC frequency based on the trimmed value
1533 *
1534 * param freq The Fast IRC frequency input clock frequency in Hz.
1535 */
1536void CLOCK_SetFastIrcFreq(uint32_t freq)
1537{
1538 s_fastIrcFreq = freq;
1539}
1540
1541/*!
1542 * brief Auto trims the internal reference clock.
1543 *
1544 * This function trims the internal reference clock by using the external clock. If
1545 * successful, it returns the kStatus_Success and the frequency after
1546 * trimming is received in the parameter p actualFreq. If an error occurs,
1547 * the error code is returned.
1548 *
1549 * param extFreq External clock frequency, which should be a bus clock.
1550 * param desireFreq Frequency to trim to.
1551 * param actualFreq Actual frequency after trimming.
1552 * param atms Trim fast or slow internal reference clock.
1553 * retval kStatus_Success ATM success.
1554 * retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM.
1555 * retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency.
1556 * retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source.
1557 * retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming.
1558 */
1559status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms)
1560{
1561 uint32_t multi; /* extFreq / desireFreq */
1562 uint32_t actv; /* Auto trim value. */
1563 uint8_t mcg_sc;
1564 status_t status = kStatus_Success;
1565
1566 static const uint32_t trimRange[2][2] = {
1567 /* Min Max */
1568 {TRIM_SIRC_MIN, TRIM_SIRC_MAX}, /* Slow IRC. */
1569 {TRIM_FIRC_MIN, TRIM_FIRC_MAX} /* Fast IRC. */
1570 };
1571
1572 if ((extFreq > TRIM_REF_CLK_MAX) || (extFreq < TRIM_REF_CLK_MIN))
1573 {
1574 status = kStatus_MCG_AtmBusClockInvalid;
1575 }
1576 /* Check desired frequency range. */
1577 else if ((desireFreq < trimRange[atms][0]) || (desireFreq > trimRange[atms][1]))
1578 {
1579 status = kStatus_MCG_AtmDesiredFreqInvalid;
1580 }
1581 /*
1582 Make sure internal reference clock is not used to generate bus clock.
1583 Here only need to check (MCG_S_IREFST == 1).
1584 */
1585 else if (MCG_S_IREFST(kMCG_FllSrcInternal) == (MCG->S & MCG_S_IREFST_MASK))
1586 {
1587 status = kStatus_MCG_AtmIrcUsed;
1588 }
1589 else
1590 {
1591 multi = extFreq / desireFreq;
1592 actv = multi * 21U;
1593
1594 if (kMCG_AtmSel4m == atms)
1595 {
1596 actv *= 128U;
1597 }
1598
1599 /* Now begin to start trim. */
1600 MCG->ATCVL = (uint8_t)actv;
1601 MCG->ATCVH = (uint8_t)(actv >> 8U);
1602
1603 mcg_sc = MCG->SC;
1604 mcg_sc &= ~(uint8_t)(MCG_SC_ATMS_MASK | MCG_SC_LOCS0_MASK);
1605 mcg_sc |= (MCG_SC_ATMF_MASK | MCG_SC_ATMS(atms));
1606 MCG->SC = (mcg_sc | MCG_SC_ATME_MASK);
1607
1608 /* Wait for MCG finished. */
1609 while (0U != (MCG->SC & MCG_SC_ATME_MASK))
1610 {
1611 }
1612
1613 /* Error occurs? */
1614 if (0U != (MCG->SC & MCG_SC_ATMF_MASK))
1615 {
1616 /* Clear the failed flag. */
1617 MCG->SC = mcg_sc;
1618 status = kStatus_MCG_AtmHardwareFail;
1619 }
1620 else
1621 {
1622 *actualFreq = extFreq / multi;
1623
1624 if (kMCG_AtmSel4m == atms)
1625 {
1626 s_fastIrcFreq = *actualFreq;
1627 }
1628 else
1629 {
1630 s_slowIrcFreq = *actualFreq;
1631 }
1632 }
1633 }
1634
1635 return status;
1636}
1637
1638/*!
1639 * brief Gets the current MCG mode.
1640 *
1641 * This function checks the MCG registers and determines the current MCG mode.
1642 *
1643 * return Current MCG mode or error code; See ref mcg_mode_t.
1644 */
1645mcg_mode_t CLOCK_GetMode(void)
1646{
1647 mcg_mode_t mode = kMCG_ModeError;
1648 uint32_t clkst = (uint32_t)MCG_S_CLKST_VAL;
1649 uint32_t irefst = (uint32_t)MCG_S_IREFST_VAL;
1650 uint32_t lp = (uint32_t)MCG_C2_LP_VAL;
1651 uint32_t pllst = MCG_S_PLLST_VAL;
1652
1653 /*------------------------------------------------------------------
1654 Mode and Registers
1655 ____________________________________________________________________
1656
1657 Mode | CLKST | IREFST | PLLST | LP
1658 ____________________________________________________________________
1659
1660 FEI | 00(FLL) | 1(INT) | 0(FLL) | X
1661 ____________________________________________________________________
1662
1663 FEE | 00(FLL) | 0(EXT) | 0(FLL) | X
1664 ____________________________________________________________________
1665
1666 FBE | 10(EXT) | 0(EXT) | 0(FLL) | 0(NORMAL)
1667 ____________________________________________________________________
1668
1669 FBI | 01(INT) | 1(INT) | 0(FLL) | 0(NORMAL)
1670 ____________________________________________________________________
1671
1672 BLPI | 01(INT) | 1(INT) | 0(FLL) | 1(LOW POWER)
1673 ____________________________________________________________________
1674
1675 BLPE | 10(EXT) | 0(EXT) | X | 1(LOW POWER)
1676 ____________________________________________________________________
1677
1678 PEE | 11(PLL) | 0(EXT) | 1(PLL) | X
1679 ____________________________________________________________________
1680
1681 PBE | 10(EXT) | 0(EXT) | 1(PLL) | O(NORMAL)
1682 ____________________________________________________________________
1683
1684 PBI | 01(INT) | 1(INT) | 1(PLL) | 0(NORMAL)
1685 ____________________________________________________________________
1686
1687 PEI | 11(PLL) | 1(INT) | 1(PLL) | X
1688 ____________________________________________________________________
1689
1690 ----------------------------------------------------------------------*/
1691
1692 if (clkst == (uint32_t)kMCG_ClkOutStatFll)
1693 {
1694 if ((uint32_t)kMCG_FllSrcExternal == irefst)
1695 {
1696 mode = kMCG_ModeFEE;
1697 }
1698 else
1699 {
1700 mode = kMCG_ModeFEI;
1701 }
1702 }
1703 else if (clkst == (uint32_t)kMCG_ClkOutStatInt)
1704 {
1705 if (0U != lp)
1706 {
1707 mode = kMCG_ModeBLPI;
1708 }
1709 else
1710 {
1711 {
1712 mode = kMCG_ModeFBI;
1713 }
1714 }
1715 }
1716 else if (clkst == (uint32_t)kMCG_ClkOutStatExt)
1717 {
1718 if (0U != lp)
1719 {
1720 mode = kMCG_ModeBLPE;
1721 }
1722 else
1723 {
1724 if ((uint32_t)kMCG_PllstPll == pllst)
1725 {
1726 mode = kMCG_ModePBE;
1727 }
1728 else
1729 {
1730 mode = kMCG_ModeFBE;
1731 }
1732 }
1733 }
1734 else if (clkst == (uint32_t)kMCG_ClkOutStatPll)
1735 {
1736 {
1737 mode = kMCG_ModePEE;
1738 }
1739 }
1740 else
1741 {
1742 /*do nothing*/
1743 }
1744
1745 return mode;
1746}
1747
1748/*!
1749 * brief Sets the MCG to FEI mode.
1750 *
1751 * This function sets the MCG to FEI mode. If setting to FEI mode fails
1752 * from the current mode, this function returns an error.
1753 *
1754 * param dmx32 DMX32 in FEI mode.
1755 * param drs The DCO range selection.
1756 * param fllStableDelay Delay function to ensure that the FLL is stable. Passing
1757 * NULL does not cause a delay.
1758 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1759 * retval kStatus_Success Switched to the target mode successfully.
1760 * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1761 * to a frequency above 32768 Hz.
1762 */
1763status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1764{
1765 uint8_t mcg_c4;
1766 bool change_drs = false;
1767
1768#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1769 mcg_mode_t mode = CLOCK_GetMode();
1770 if (!((kMCG_ModeFEI == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEE == mode)))
1771 {
1772 return kStatus_MCG_ModeUnreachable;
1773 }
1774#endif
1775 mcg_c4 = MCG->C4;
1776
1777 /*
1778 Errata: ERR007993
1779 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
1780 reference clock source changes, then reset to previous value after
1781 reference clock changes.
1782 */
1783 if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
1784 {
1785 change_drs = true;
1786 /* Change the LSB of DRST_DRS. */
1787 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
1788 }
1789
1790 /* Set CLKS and IREFS. */
1791 MCG->C1 = (uint8_t)(((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK))) |
1792 (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */
1793 | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */
1794
1795 /* Wait and check status. */
1796 while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL)
1797 {
1798 }
1799
1800 /* Errata: ERR007993 */
1801 if (change_drs)
1802 {
1803 MCG->C4 = mcg_c4;
1804 }
1805
1806 /* In FEI mode, the MCG_C4[DMX32] is set to 0U. */
1807 MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
1808 (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
1809
1810 /* Check MCG_S[CLKST] */
1811 while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL)
1812 {
1813 }
1814
1815 /* Wait for FLL stable time. */
1816 if (NULL != fllStableDelay)
1817 {
1818 fllStableDelay();
1819 }
1820
1821 return kStatus_Success;
1822}
1823
1824/*!
1825 * brief Sets the MCG to FEE mode.
1826 *
1827 * This function sets the MCG to FEE mode. If setting to FEE mode fails
1828 * from the current mode, this function returns an error.
1829 *
1830 * param frdiv FLL reference clock divider setting, FRDIV.
1831 * param dmx32 DMX32 in FEE mode.
1832 * param drs The DCO range selection.
1833 * param fllStableDelay Delay function to make sure FLL is stable. Passing
1834 * NULL does not cause a delay.
1835 *
1836 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1837 * retval kStatus_Success Switched to the target mode successfully.
1838 */
1839status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1840{
1841 uint8_t mcg_c4;
1842 bool change_drs = false;
1843
1844#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1845 mcg_mode_t mode = CLOCK_GetMode();
1846 if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode)))
1847 {
1848 return kStatus_MCG_ModeUnreachable;
1849 }
1850#endif
1851 mcg_c4 = MCG->C4;
1852
1853 /*
1854 Errata: ERR007993
1855 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
1856 reference clock source changes, then reset to previous value after
1857 reference clock changes.
1858 */
1859 if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL)
1860 {
1861 change_drs = true;
1862 /* Change the LSB of DRST_DRS. */
1863 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
1864 }
1865
1866 /* Set CLKS and IREFS. */
1867 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) |
1868 (MCG_C1_CLKS(kMCG_ClkOutSrcOut) /* CLKS = 0 */
1869 | MCG_C1_FRDIV(frdiv) /* FRDIV */
1870 | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */
1871
1872 /* If use external crystal as clock source, wait for it stable. */
1873 if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
1874 {
1875 if (0U != (MCG->C2 & MCG_C2_EREFS_MASK))
1876 {
1877 while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
1878 {
1879 }
1880 }
1881 }
1882
1883 /* Wait and check status. */
1884 while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL)
1885 {
1886 }
1887
1888 /* Errata: ERR007993 */
1889 if (change_drs)
1890 {
1891 MCG->C4 = mcg_c4;
1892 }
1893
1894 /* Set DRS and DMX32. */
1895 mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
1896 (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
1897 MCG->C4 = mcg_c4;
1898
1899 /* Wait for DRST_DRS update. */
1900 while (MCG->C4 != mcg_c4)
1901 {
1902 }
1903
1904 /* Check MCG_S[CLKST] */
1905 while ((uint8_t)kMCG_ClkOutStatFll != MCG_S_CLKST_VAL)
1906 {
1907 }
1908
1909 /* Wait for FLL stable time. */
1910 if (NULL != fllStableDelay)
1911 {
1912 fllStableDelay();
1913 }
1914
1915 return kStatus_Success;
1916}
1917
1918/*!
1919 * brief Sets the MCG to FBI mode.
1920 *
1921 * This function sets the MCG to FBI mode. If setting to FBI mode fails
1922 * from the current mode, this function returns an error.
1923 *
1924 * param dmx32 DMX32 in FBI mode.
1925 * param drs The DCO range selection.
1926 * param fllStableDelay Delay function to make sure FLL is stable. If the FLL
1927 * is not used in FBI mode, this parameter can be NULL. Passing
1928 * NULL does not cause a delay.
1929 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1930 * retval kStatus_Success Switched to the target mode successfully.
1931 * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1932 * to frequency above 32768 Hz.
1933 */
1934status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
1935{
1936 uint8_t mcg_c4;
1937 bool change_drs = false;
1938
1939#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
1940 mcg_mode_t mode = CLOCK_GetMode();
1941
1942 if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode) ||
1943 (kMCG_ModeBLPI == mode)))
1944
1945 {
1946 return kStatus_MCG_ModeUnreachable;
1947 }
1948#endif
1949
1950 mcg_c4 = MCG->C4;
1951
1952 MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */
1953
1954 /*
1955 Errata: ERR007993
1956 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
1957 reference clock source changes, then reset to previous value after
1958 reference clock changes.
1959 */
1960 if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
1961 {
1962 change_drs = true;
1963 /* Change the LSB of DRST_DRS. */
1964 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
1965 }
1966
1967 /* Set CLKS and IREFS. */
1968 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) |
1969 (MCG_C1_CLKS(kMCG_ClkOutSrcInternal) /* CLKS = 1 */
1970 | MCG_C1_IREFS(kMCG_FllSrcInternal))); /* IREFS = 1 */
1971
1972 /* Wait and check status. */
1973 while ((uint8_t)kMCG_FllSrcInternal != MCG_S_IREFST_VAL)
1974 {
1975 }
1976
1977 /* Errata: ERR007993 */
1978 if (change_drs)
1979 {
1980 MCG->C4 = mcg_c4;
1981 }
1982
1983 while ((uint8_t)kMCG_ClkOutStatInt != MCG_S_CLKST_VAL)
1984 {
1985 }
1986
1987 MCG->C4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
1988 (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
1989
1990 /* Wait for FLL stable time. */
1991 if (NULL != fllStableDelay)
1992 {
1993 fllStableDelay();
1994 }
1995
1996 return kStatus_Success;
1997}
1998
1999/*!
2000 * brief Sets the MCG to FBE mode.
2001 *
2002 * This function sets the MCG to FBE mode. If setting to FBE mode fails
2003 * from the current mode, this function returns an error.
2004 *
2005 * param frdiv FLL reference clock divider setting, FRDIV.
2006 * param dmx32 DMX32 in FBE mode.
2007 * param drs The DCO range selection.
2008 * param fllStableDelay Delay function to make sure FLL is stable. If the FLL
2009 * is not used in FBE mode, this parameter can be NULL. Passing NULL
2010 * does not cause a delay.
2011 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2012 * retval kStatus_Success Switched to the target mode successfully.
2013 */
2014status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
2015{
2016 uint8_t mcg_c4;
2017 bool change_drs = false;
2018
2019#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2020 mcg_mode_t mode = CLOCK_GetMode();
2021 if (!((kMCG_ModeFEE == mode) || (kMCG_ModeFBI == mode) || (kMCG_ModeFBE == mode) || (kMCG_ModeFEI == mode) ||
2022 (kMCG_ModePBE == mode) || (kMCG_ModeBLPE == mode)))
2023 {
2024 return kStatus_MCG_ModeUnreachable;
2025 }
2026#endif
2027
2028 /* Change to FLL mode. */
2029 MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK;
2030 while ((MCG->S & MCG_S_PLLST_MASK) != 0U)
2031 {
2032 }
2033
2034 /* Set LP bit to enable the FLL */
2035 MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK;
2036
2037 mcg_c4 = MCG->C4;
2038
2039 /*
2040 Errata: ERR007993
2041 Workaround: Invert MCG_C4[DMX32] or change MCG_C4[DRST_DRS] before
2042 reference clock source changes, then reset to previous value after
2043 reference clock changes.
2044 */
2045 if ((uint8_t)kMCG_FllSrcInternal == MCG_S_IREFST_VAL)
2046 {
2047 change_drs = true;
2048 /* Change the LSB of DRST_DRS. */
2049 MCG->C4 ^= (1U << MCG_C4_DRST_DRS_SHIFT);
2050 }
2051
2052 /* Set CLKS and IREFS. */
2053 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK)) |
2054 (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */
2055 | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */
2056 | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */
2057
2058 /* If use external crystal as clock source, wait for it stable. */
2059 if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
2060 {
2061 if (0U != (MCG->C2 & MCG_C2_EREFS_MASK))
2062 {
2063 while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
2064 {
2065 }
2066 }
2067 }
2068
2069 /* Wait for Reference clock Status bit to clear */
2070 while ((uint8_t)kMCG_FllSrcExternal != MCG_S_IREFST_VAL)
2071 {
2072 }
2073
2074 /* Errata: ERR007993 */
2075 if (change_drs)
2076 {
2077 MCG->C4 = mcg_c4;
2078 }
2079
2080 /* Set DRST_DRS and DMX32. */
2081 mcg_c4 = (uint8_t)((mcg_c4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) |
2082 (MCG_C4_DMX32(dmx32) | MCG_C4_DRST_DRS(drs)));
2083
2084 /* Wait for clock status bits to show clock source is ext ref clk */
2085 while ((uint8_t)kMCG_ClkOutStatExt != MCG_S_CLKST_VAL)
2086 {
2087 }
2088
2089 /* Wait for fll stable time. */
2090 if (NULL != fllStableDelay)
2091 {
2092 fllStableDelay();
2093 }
2094
2095 return kStatus_Success;
2096}
2097
2098/*!
2099 * brief Sets the MCG to BLPI mode.
2100 *
2101 * This function sets the MCG to BLPI mode. If setting to BLPI mode fails
2102 * from the current mode, this function returns an error.
2103 *
2104 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2105 * retval kStatus_Success Switched to the target mode successfully.
2106 */
2107status_t CLOCK_SetBlpiMode(void)
2108{
2109#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2110 if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt)
2111 {
2112 return kStatus_MCG_ModeUnreachable;
2113 }
2114#endif /* MCG_CONFIG_CHECK_PARAM */
2115
2116 /* Set LP. */
2117 MCG->C2 |= MCG_C2_LP_MASK;
2118
2119 return kStatus_Success;
2120}
2121
2122/*!
2123 * brief Sets the MCG to BLPE mode.
2124 *
2125 * This function sets the MCG to BLPE mode. If setting to BLPE mode fails
2126 * from the current mode, this function returns an error.
2127 *
2128 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2129 * retval kStatus_Success Switched to the target mode successfully.
2130 */
2131status_t CLOCK_SetBlpeMode(void)
2132{
2133#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2134 if (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt)
2135 {
2136 return kStatus_MCG_ModeUnreachable;
2137 }
2138#endif
2139
2140 /* Set LP bit to enter BLPE mode. */
2141 MCG->C2 |= MCG_C2_LP_MASK;
2142
2143 return kStatus_Success;
2144}
2145
2146/*!
2147 * brief Sets the MCG to PBE mode.
2148 *
2149 * This function sets the MCG to PBE mode. If setting to PBE mode fails
2150 * from the current mode, this function returns an error.
2151 *
2152 * param pllcs The PLL selection, PLLCS.
2153 * param config Pointer to the PLL configuration.
2154 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2155 * retval kStatus_Success Switched to the target mode successfully.
2156 *
2157 * note
2158 * 1. The parameter \c pllcs selects the PLL. For platforms with
2159 * only one PLL, the parameter pllcs is kept for interface compatibility.
2160 * 2. The parameter \c config is the PLL configuration structure. On some
2161 * platforms, it is possible to choose the external PLL directly, which renders the
2162 * configuration structure not necessary. In this case, pass in NULL.
2163 * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL);
2164 */
2165status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config)
2166{
2167 /* If external PLL is used, then the config could be NULL. */
2168 if (kMCG_PllClkSelExtPll != pllcs)
2169 {
2170 assert(config);
2171 }
2172
2173 /*
2174 This function is designed to change MCG to PBE mode from PEE/BLPE/FBE,
2175 but with this workflow, the source mode could be all modes except PEI/PBI.
2176 */
2177 MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK); /* Disable lowpower. */
2178
2179 /* Change to use external clock first. */
2180 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal));
2181
2182 /* Wait for CLKST clock status bits to show clock source is ext ref clk */
2183 while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
2184 (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt)))
2185 {
2186 }
2187
2188 /* Disable PLL first, then configure PLL. */
2189 MCG->C6 &= (uint8_t)(~MCG_C6_PLLS_MASK);
2190 while ((MCG->S & MCG_S_PLLST_MASK) != 0U)
2191 {
2192 }
2193
2194 /* Configure the PLL. */
2195 if (kMCG_PllClkSelPll0 == pllcs)
2196 {
2197 CLOCK_EnablePll0(config);
2198 }
2199
2200 /* Change to PLL mode. */
2201 MCG->C6 |= MCG_C6_PLLS_MASK;
2202
2203 MCG->C11 = (uint8_t)(((MCG->C11 & ~MCG_C11_PLLCS_MASK)) | MCG_C11_PLLCS(pllcs));
2204 while ((uint32_t)pllcs != MCG_S2_PLLCST_VAL)
2205 {
2206 }
2207
2208 /* Wait for PLL mode changed. */
2209 while (((MCG->S & MCG_S_PLLST_MASK)) == 0U)
2210 {
2211 }
2212
2213 return kStatus_Success;
2214}
2215
2216/*!
2217 * brief Sets the MCG to PEE mode.
2218 *
2219 * This function sets the MCG to PEE mode.
2220 *
2221 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2222 * retval kStatus_Success Switched to the target mode successfully.
2223 *
2224 * note This function only changes the CLKS to use the PLL/FLL output. If the
2225 * PRDIV/VDIV are different than in the PBE mode, set them up
2226 * in PBE mode and wait. When the clock is stable, switch to PEE mode.
2227 */
2228status_t CLOCK_SetPeeMode(void)
2229{
2230#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2231 mcg_mode_t mode = CLOCK_GetMode();
2232 if (kMCG_ModePBE != mode)
2233 {
2234 return kStatus_MCG_ModeUnreachable;
2235 }
2236#endif
2237
2238 /* Change to use PLL/FLL output clock first. */
2239 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut));
2240
2241 /* Wait for clock status bits to update */
2242 while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll)
2243 {
2244 }
2245
2246 return kStatus_Success;
2247}
2248
2249/*!
2250 * brief Switches the MCG to FBE mode from the external mode.
2251 *
2252 * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly.
2253 * The external clock is used as the system clock source and PLL is disabled. However,
2254 * the FLL settings are not configured. This is a lite function with a small code size, which is useful
2255 * during the mode switch. For example, to switch from PEE mode to FEI mode:
2256 *
2257 * code
2258 * CLOCK_ExternalModeToFbeModeQuick();
2259 * CLOCK_SetFeiMode(...);
2260 * endcode
2261 *
2262 * retval kStatus_Success Switched successfully.
2263 * retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function.
2264 */
2265status_t CLOCK_ExternalModeToFbeModeQuick(void)
2266{
2267#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2268 if ((MCG->S & MCG_S_IREFST_MASK) != 0U)
2269 {
2270 return kStatus_MCG_ModeInvalid;
2271 }
2272#endif /* MCG_CONFIG_CHECK_PARAM */
2273
2274 /* Disable low power */
2275 MCG->C2 &= (uint8_t)(~MCG_C2_LP_MASK);
2276
2277 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal));
2278 while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt)
2279 {
2280 }
2281
2282 /* Disable PLL. */
2283 MCG->C6 &= ~(uint8_t)MCG_C6_PLLS_MASK;
2284 while ((MCG->S & MCG_S_PLLST_MASK) != 0U)
2285 {
2286 }
2287
2288 return kStatus_Success;
2289}
2290
2291/*!
2292 * brief Switches the MCG to FBI mode from internal modes.
2293 *
2294 * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly.
2295 * The MCGIRCLK is used as the system clock source and PLL is disabled. However,
2296 * FLL settings are not configured. This is a lite function with a small code size, which is useful
2297 * during the mode switch. For example, to switch from PEI mode to FEE mode:
2298 *
2299 * code
2300 * CLOCK_InternalModeToFbiModeQuick();
2301 * CLOCK_SetFeeMode(...);
2302 * endcode
2303 *
2304 * retval kStatus_Success Switched successfully.
2305 * retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function.
2306 */
2307status_t CLOCK_InternalModeToFbiModeQuick(void)
2308{
2309#if (defined(MCG_CONFIG_CHECK_PARAM) && MCG_CONFIG_CHECK_PARAM)
2310 if ((MCG->S & MCG_S_IREFST_MASK) == 0U)
2311 {
2312 return kStatus_MCG_ModeInvalid;
2313 }
2314#endif
2315
2316 /* Disable low power */
2317 MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK;
2318
2319 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal));
2320 while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt)
2321 {
2322 }
2323
2324 return kStatus_Success;
2325}
2326
2327/*!
2328 * brief Sets the MCG to FEI mode during system boot up.
2329 *
2330 * This function sets the MCG to FEI mode from the reset mode. It can also be used to
2331 * set up MCG during system boot up.
2332 *
2333 * param dmx32 DMX32 in FEI mode.
2334 * param drs The DCO range selection.
2335 * param fllStableDelay Delay function to ensure that the FLL is stable.
2336 *
2337 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2338 * retval kStatus_Success Switched to the target mode successfully.
2339 * note If p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
2340 * to frequency above 32768 Hz.
2341 */
2342status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
2343{
2344 return CLOCK_SetFeiMode(dmx32, drs, fllStableDelay);
2345}
2346
2347/*!
2348 * brief Sets the MCG to FEE mode during system bootup.
2349 *
2350 * This function sets MCG to FEE mode from the reset mode. It can also be used to
2351 * set up the MCG during system boot up.
2352 *
2353 * param oscsel OSC clock select, OSCSEL.
2354 * param frdiv FLL reference clock divider setting, FRDIV.
2355 * param dmx32 DMX32 in FEE mode.
2356 * param drs The DCO range selection.
2357 * param fllStableDelay Delay function to ensure that the FLL is stable.
2358 *
2359 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2360 * retval kStatus_Success Switched to the target mode successfully.
2361 */
2362status_t CLOCK_BootToFeeMode(
2363 mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void))
2364{
2365 (void)CLOCK_SetExternalRefClkConfig(oscsel);
2366
2367 return CLOCK_SetFeeMode(frdiv, dmx32, drs, fllStableDelay);
2368}
2369
2370/*!
2371 * brief Sets the MCG to BLPI mode during system boot up.
2372 *
2373 * This function sets the MCG to BLPI mode from the reset mode. It can also be used to
2374 * set up the MCG during system boot up.
2375 *
2376 * param fcrdiv Fast IRC divider, FCRDIV.
2377 * param ircs The internal reference clock to select, IRCS.
2378 * param ircEnableMode The MCGIRCLK enable mode, OR'ed value of ref _mcg_irclk_enable_mode.
2379 *
2380 * retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting.
2381 * retval kStatus_Success Switched to the target mode successfully.
2382 */
2383status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode)
2384{
2385 /* If reset mode is FEI mode, set MCGIRCLK and always success. */
2386 (void)CLOCK_SetInternalRefClkConfig(ircEnableMode, ircs, fcrdiv);
2387
2388 /* If reset mode is not BLPI, first enter FBI mode. */
2389 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcInternal));
2390 while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatInt)
2391 {
2392 }
2393
2394 /* Enter BLPI mode. */
2395 MCG->C2 |= MCG_C2_LP_MASK;
2396
2397 return kStatus_Success;
2398}
2399
2400/*!
2401 * brief Sets the MCG to BLPE mode during system boot up.
2402 *
2403 * This function sets the MCG to BLPE mode from the reset mode. It can also be used to
2404 * set up the MCG during system boot up.
2405 *
2406 * param oscsel OSC clock select, MCG_C7[OSCSEL].
2407 *
2408 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2409 * retval kStatus_Success Switched to the target mode successfully.
2410 */
2411status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel)
2412{
2413 (void)CLOCK_SetExternalRefClkConfig(oscsel);
2414
2415 /* Set to FBE mode. */
2416 MCG->C1 = (uint8_t)((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) |
2417 (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */
2418 | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */
2419
2420 /* If use external crystal as clock source, wait for it stable. */
2421 if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK))
2422 {
2423 if (0U != (MCG->C2 & MCG_C2_EREFS_MASK))
2424 {
2425 while (0U == (MCG->S & MCG_S_OSCINIT0_MASK))
2426 {
2427 }
2428 }
2429 }
2430
2431 /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */
2432 while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) !=
2433 (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt)))
2434 {
2435 }
2436
2437 /* In FBE now, start to enter BLPE. */
2438 MCG->C2 |= MCG_C2_LP_MASK;
2439
2440 return kStatus_Success;
2441}
2442
2443/*!
2444 * brief Sets the MCG to PEE mode during system boot up.
2445 *
2446 * This function sets the MCG to PEE mode from reset mode. It can also be used to
2447 * set up the MCG during system boot up.
2448 *
2449 * param oscsel OSC clock select, MCG_C7[OSCSEL].
2450 * param pllcs The PLL selection, PLLCS.
2451 * param config Pointer to the PLL configuration.
2452 *
2453 * retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
2454 * retval kStatus_Success Switched to the target mode successfully.
2455 */
2456status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config)
2457{
2458 /* If external PLL is used, then the config could be NULL. */
2459 if (kMCG_PllClkSelExtPll != pllcs)
2460 {
2461 assert(config);
2462 }
2463
2464 (void)CLOCK_SetExternalRefClkConfig(oscsel);
2465
2466 (void)CLOCK_SetPbeMode(pllcs, config);
2467
2468 /* Change to use PLL output clock. */
2469 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcOut));
2470 while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatPll)
2471 {
2472 }
2473
2474 return kStatus_Success;
2475}
2476
2477/*
2478 The transaction matrix. It defines the path for mode switch, the row is for
2479 current mode and the column is target mode.
2480 For example, switch from FEI to PEE:
2481 1. Current mode FEI, next mode is mcgModeMatrix[FEI][PEE] = FBE, so swith to FBE.
2482 2. Current mode FBE, next mode is mcgModeMatrix[FBE][PEE] = PBE, so swith to PBE.
2483 3. Current mode PBE, next mode is mcgModeMatrix[PBE][PEE] = PEE, so swith to PEE.
2484 Thus the MCG mode has changed from FEI to PEE.
2485 */
2486static const mcg_mode_t mcgModeMatrix[8][8] = {
2487 {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE,
2488 kMCG_ModeFBE}, /* FEI */
2489 {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE,
2490 kMCG_ModeFBE}, /* FBI */
2491 {kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeBLPI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFBI,
2492 kMCG_ModeFBI}, /* BLPI */
2493 {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE,
2494 kMCG_ModeFBE}, /* FEE */
2495 {kMCG_ModeFEI, kMCG_ModeFBI, kMCG_ModeFBI, kMCG_ModeFEE, kMCG_ModeFBE, kMCG_ModeBLPE, kMCG_ModePBE,
2496 kMCG_ModePBE}, /* FBE */
2497 {kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeBLPE, kMCG_ModePBE,
2498 kMCG_ModePBE}, /* BLPE */
2499 {kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeFBE, kMCG_ModeBLPE, kMCG_ModePBE,
2500 kMCG_ModePEE}, /* PBE */
2501 {kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE, kMCG_ModePBE,
2502 kMCG_ModePBE} /* PEE */
2503 /* FEI FBI BLPI FEE FBE BLPE PBE PEE */
2504};
2505
2506/*!
2507 * brief Sets the MCG to a target mode.
2508 *
2509 * This function sets MCG to a target mode defined by the configuration
2510 * structure. If switching to the target mode fails, this function
2511 * chooses the correct path.
2512 *
2513 * param config Pointer to the target MCG mode configuration structure.
2514 * return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status.
2515 *
2516 * note If the external clock is used in the target mode, ensure that it is
2517 * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this
2518 * function.
2519 */
2520status_t CLOCK_SetMcgConfig(const mcg_config_t *config)
2521{
2522 mcg_mode_t next_mode;
2523 status_t status = kStatus_Success;
2524
2525 mcg_pll_clk_select_t pllcs = config->pllcs;
2526
2527 /* If need to change external clock, MCG_C7[OSCSEL]. */
2528 if (MCG_C7_OSCSEL_VAL != (uint8_t)(config->oscsel))
2529 {
2530 /* If external clock is in use, change to FEI first. */
2531 if ((uint8_t)kMCG_FllSrcExternal == MCG_S_IREFST_VAL)
2532 {
2533 (void)CLOCK_ExternalModeToFbeModeQuick();
2534 (void)CLOCK_SetFeiMode(config->dmx32, config->drs, NULL);
2535 }
2536
2537 (void)CLOCK_SetExternalRefClkConfig(config->oscsel);
2538 }
2539
2540 /* Re-configure MCGIRCLK, if MCGIRCLK is used as system clock source, then change to FEI/PEI first. */
2541 if (MCG_S_CLKST_VAL == (uint8_t)kMCG_ClkOutStatInt)
2542 {
2543 MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK; /* Disable lowpower. */
2544
2545 {
2546 (void)CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay);
2547 }
2548 }
2549
2550 /* Configure MCGIRCLK. */
2551 (void)CLOCK_SetInternalRefClkConfig(config->irclkEnableMode, config->ircs, config->fcrdiv);
2552
2553 next_mode = CLOCK_GetMode();
2554
2555 do
2556 {
2557 next_mode = mcgModeMatrix[next_mode][config->mcgMode];
2558
2559 switch (next_mode)
2560 {
2561 case kMCG_ModeFEI:
2562 status = CLOCK_SetFeiMode(config->dmx32, config->drs, CLOCK_FllStableDelay);
2563 break;
2564 case kMCG_ModeFEE:
2565 status = CLOCK_SetFeeMode(config->frdiv, config->dmx32, config->drs, CLOCK_FllStableDelay);
2566 break;
2567 case kMCG_ModeFBI:
2568 status = CLOCK_SetFbiMode(config->dmx32, config->drs, NULL);
2569 break;
2570 case kMCG_ModeFBE:
2571 status = CLOCK_SetFbeMode(config->frdiv, config->dmx32, config->drs, NULL);
2572 break;
2573 case kMCG_ModeBLPI:
2574 status = CLOCK_SetBlpiMode();
2575 break;
2576 case kMCG_ModeBLPE:
2577 status = CLOCK_SetBlpeMode();
2578 break;
2579 case kMCG_ModePBE:
2580 /* If target mode is not PBE or PEE, then only need to set CLKS = EXT here. */
2581 if ((kMCG_ModePEE == config->mcgMode) || (kMCG_ModePBE == config->mcgMode))
2582 {
2583 if (kMCG_PllClkSelPll0 == pllcs)
2584 {
2585 status = CLOCK_SetPbeMode(pllcs, &config->pll0Config);
2586 }
2587 else if (kMCG_PllClkSelExtPll == pllcs)
2588 {
2589 status = CLOCK_SetPbeMode(pllcs, NULL);
2590 }
2591 else
2592 {
2593 /* Add comment to prevent the case of MISRA C-2012 rule 15.7 */
2594 }
2595 }
2596 else
2597 {
2598 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCG_ClkOutSrcExternal));
2599 while (MCG_S_CLKST_VAL != (uint8_t)kMCG_ClkOutStatExt)
2600 {
2601 }
2602 }
2603 break;
2604 case kMCG_ModePEE:
2605 status = CLOCK_SetPeeMode();
2606 break;
2607 default:
2608 assert(false);
2609 break;
2610 }
2611 if (kStatus_Success != status)
2612 {
2613 break;
2614 }
2615 } while (next_mode != config->mcgMode);
2616
2617 if (status == kStatus_Success)
2618 {
2619 if ((config->pll0Config.enableMode & (uint8_t)kMCG_PllEnableIndependent) != 0U)
2620 {
2621 CLOCK_EnablePll0(&config->pll0Config);
2622 }
2623 else
2624 {
2625 MCG->C5 &= ~(uint8_t)kMCG_PllEnableIndependent;
2626 }
2627 }
2628
2629 return status;
2630}
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/fsl_clock.h b/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/fsl_clock.h
new file mode 100644
index 000000000..d5caee78e
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MK28FA15/drivers/fsl_clock.h
@@ -0,0 +1,1754 @@
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.2. */
62#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 5, 2))
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 (150000000UL)
104#endif
105/*! @brief Clock ip name array for DMAMUX. */
106#define DMAMUX_CLOCKS \
107 { \
108 kCLOCK_Dmamux0 \
109 }
110
111/*! @brief Clock ip name array for RTC. */
112#define RTC_CLOCKS \
113 { \
114 kCLOCK_Rtc0 \
115 }
116
117/*! @brief Clock ip name array for SAI. */
118#define SAI_CLOCKS \
119 { \
120 kCLOCK_Sai0, kCLOCK_Sai1 \
121 }
122
123/*! @brief Clock ip name array for PORT. */
124#define PORT_CLOCKS \
125 { \
126 kCLOCK_PortA, kCLOCK_PortB, kCLOCK_PortC, kCLOCK_PortD, kCLOCK_PortE \
127 }
128
129/*! @brief Clock ip name array for FLEXBUS. */
130#define FLEXBUS_CLOCKS \
131 { \
132 kCLOCK_Flexbus0 \
133 }
134
135/*! @brief Clock ip name array for EWM. */
136#define EWM_CLOCKS \
137 { \
138 kCLOCK_Ewm0 \
139 }
140
141/*! @brief Clock ip name array for PIT. */
142#define PIT_CLOCKS \
143 { \
144 kCLOCK_Pit0 \
145 }
146
147/*! @brief Clock ip name array for DSPI. */
148#define DSPI_CLOCKS \
149 { \
150 kCLOCK_Spi0, kCLOCK_Spi1, kCLOCK_Spi2, kCLOCK_Spi3 \
151 }
152
153/*! @brief Clock ip name array for QSPI. */
154#define QSPI_CLOCKS \
155 { \
156 kCLOCK_Qspi0 \
157 }
158
159/*! @brief Clock ip name array for LPTMR. */
160#define LPTMR_CLOCKS \
161 { \
162 kCLOCK_Lptmr0, kCLOCK_Lptmr1 \
163 }
164
165/*! @brief Clock ip name array for SDHC. */
166#define SDHC_CLOCKS \
167 { \
168 kCLOCK_Sdhc0 \
169 }
170
171/*! @brief Clock ip name array for FTM. */
172#define FTM_CLOCKS \
173 { \
174 kCLOCK_Ftm0, kCLOCK_Ftm1, kCLOCK_Ftm2, kCLOCK_Ftm3 \
175 }
176
177/*! @brief Clock ip name array for EDMA. */
178#define EDMA_CLOCKS \
179 { \
180 kCLOCK_Dma0 \
181 }
182
183/*! @brief Clock ip name array for LPUART. */
184#define LPUART_CLOCKS \
185 { \
186 kCLOCK_Lpuart0, kCLOCK_Lpuart1, kCLOCK_Lpuart2, kCLOCK_Lpuart3, kCLOCK_Lpuart4 \
187 }
188
189/*! @brief Clock ip name array for DAC. */
190#define DAC_CLOCKS \
191 { \
192 kCLOCK_Dac0 \
193 }
194
195/*! @brief Clock ip name array for ADC16. */
196#define ADC16_CLOCKS \
197 { \
198 kCLOCK_Adc0 \
199 }
200
201/*! @brief Clock ip name array for SDRAM. */
202#define SDRAM_CLOCKS \
203 { \
204 kCLOCK_Sdramc0 \
205 }
206
207/*! @brief Clock ip name array for TRNG. */
208#define TRNG_CLOCKS \
209 { \
210 kCLOCK_Trng0 \
211 }
212
213/*! @brief Clock ip name array for USBHS. */
214#define USBHS_CLOCKS \
215 { \
216 kCLOCK_Usbhs \
217 }
218
219/*! @brief Clock ip name array for USBHSPHY. */
220#define USBHSPHY_CLOCKS \
221 { \
222 kCLOCK_Usbhsphy \
223 }
224
225/*! @brief Clock ip name array for USBHSDCD. */
226#define USBHSDCD_CLOCKS \
227 { \
228 kCLOCK_Usbhsdcd \
229 }
230
231/*! @brief Clock ip name array for MPU. */
232#define SYSMPU_CLOCKS \
233 { \
234 kCLOCK_Sysmpu0 \
235 }
236
237/*! @brief Clock ip name array for FLEXIO. */
238#define FLEXIO_CLOCKS \
239 { \
240 kCLOCK_Flexio0 \
241 }
242
243/*! @brief Clock ip name array for VREF. */
244#define VREF_CLOCKS \
245 { \
246 kCLOCK_Vref0 \
247 }
248
249/*! @brief Clock ip name array for CMT. */
250#define CMT_CLOCKS \
251 { \
252 kCLOCK_Cmt0 \
253 }
254
255/*! @brief Clock ip name array for TPM. */
256#define TPM_CLOCKS \
257 { \
258 kCLOCK_IpInvalid, kCLOCK_Tpm1, kCLOCK_Tpm2 \
259 }
260
261/*! @brief Clock ip name array for TSI. */
262#define TSI_CLOCKS \
263 { \
264 kCLOCK_Tsi0 \
265 }
266
267/*! @brief Clock ip name array for CRC. */
268#define CRC_CLOCKS \
269 { \
270 kCLOCK_Crc0 \
271 }
272
273/*! @brief Clock ip name array for I2C. */
274#define I2C_CLOCKS \
275 { \
276 kCLOCK_I2c0, kCLOCK_I2c1, kCLOCK_I2c2, kCLOCK_I2c3 \
277 }
278
279/*! @brief Clock ip name array for PDB. */
280#define PDB_CLOCKS \
281 { \
282 kCLOCK_Pdb0 \
283 }
284
285/*! @brief Clock ip name array for FTF. */
286#define FTF_CLOCKS \
287 { \
288 kCLOCK_Ftf0 \
289 }
290
291/*! @brief Clock ip name array for CMP. */
292#define CMP_CLOCKS \
293 { \
294 kCLOCK_Cmp0, kCLOCK_Cmp1 \
295 }
296
297/*!
298 * @brief LPO clock frequency.
299 */
300#define LPO_CLK_FREQ 1000U
301
302/*! @brief Peripherals clock source definition. */
303#define SYS_CLK kCLOCK_CoreSysClk
304#define BUS_CLK kCLOCK_BusClk
305
306#define I2C0_CLK_SRC BUS_CLK
307#define I2C1_CLK_SRC BUS_CLK
308#define I2C2_CLK_SRC BUS_CLK
309#define I2C3_CLK_SRC BUS_CLK
310#define DSPI0_CLK_SRC BUS_CLK
311#define DSPI1_CLK_SRC BUS_CLK
312#define DSPI2_CLK_SRC BUS_CLK
313#define DSPI3_CLK_SRC BUS_CLK
314
315/*! @brief Clock name used to get clock frequency. */
316typedef enum _clock_name
317{
318
319 /* ----------------------------- System layer clock -------------------------------*/
320 kCLOCK_CoreSysClk, /*!< Core/system clock */
321 kCLOCK_PlatClk, /*!< Platform clock */
322 kCLOCK_BusClk, /*!< Bus clock */
323 kCLOCK_FlexBusClk, /*!< FlexBus clock */
324 kCLOCK_FlashClk, /*!< Flash clock */
325 kCLOCK_FastPeriphClk, /*!< Fast peripheral clock */
326 kCLOCK_PllFllSelClk, /*!< The clock after SIM[PLLFLLSEL]. */
327
328 /* ---------------------------------- OSC clock -----------------------------------*/
329 kCLOCK_Er32kClk, /*!< External reference 32K clock (ERCLK32K) */
330 kCLOCK_Osc0ErClk, /*!< OSC0 external reference clock (OSC0ERCLK) */
331 kCLOCK_Osc1ErClk, /*!< OSC1 external reference clock (OSC1ERCLK) */
332 kCLOCK_Osc0ErClkUndiv, /*!< OSC0 external reference undivided clock(OSC0ERCLK_UNDIV). */
333
334 /* ----------------------------- MCG and MCG-Lite clock ---------------------------*/
335 kCLOCK_McgFixedFreqClk, /*!< MCG fixed frequency clock (MCGFFCLK) */
336 kCLOCK_McgInternalRefClk, /*!< MCG internal reference clock (MCGIRCLK) */
337 kCLOCK_McgFllClk, /*!< MCGFLLCLK */
338 kCLOCK_McgPll0Clk, /*!< MCGPLL0CLK */
339 kCLOCK_McgPll1Clk, /*!< MCGPLL1CLK */
340 kCLOCK_McgExtPllClk, /*!< EXT_PLLCLK */
341 kCLOCK_McgPeriphClk, /*!< MCG peripheral clock (MCGPCLK) */
342 kCLOCK_McgIrc48MClk, /*!< MCG IRC48M clock */
343
344 /* --------------------------------- Other clock ----------------------------------*/
345 kCLOCK_LpoClk, /*!< LPO clock */
346
347} clock_name_t;
348
349/*! @brief USB clock source definition. */
350typedef enum _clock_usb_src
351{
352 kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0. */
353 kCLOCK_UsbSrcUsbPfd = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(2U), /*!< Use USBPFDCLK. */
354 kCLOCK_UsbSrcIrc48M = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(3U), /*!< Use IRC48M. */
355 kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U), /*!< Use USB_CLKIN. */
356 kCLOCK_UsbSrcUnused = (int)0xFFFFFFFFU, /*!< Used when the function does not
357 care the clock source. */
358} clock_usb_src_t;
359/*------------------------------------------------------------------------------
360
361 clock_gate_t definition:
362
363 31 16 0
364 -----------------------------------------------------------------
365 | SIM_SCGC register offset | control bit offset in SCGC |
366 -----------------------------------------------------------------
367
368 For example, the SDHC clock gate is controlled by SIM_SCGC3[17], the
369 SIM_SCGC3 offset in SIM is 0x1030, then kClockGateSdhc0 is defined as
370
371 kClockGateSdhc0 = (0x1030 << 16) | 17;
372
373------------------------------------------------------------------------------*/
374
375#define CLK_GATE_REG_OFFSET_SHIFT 16U
376#define CLK_GATE_REG_OFFSET_MASK 0xFFFF0000U
377#define CLK_GATE_BIT_SHIFT_SHIFT 0U
378#define CLK_GATE_BIT_SHIFT_MASK 0x0000FFFFU
379
380#define CLK_GATE_DEFINE(reg_offset, bit_shift) \
381 ((((reg_offset) << CLK_GATE_REG_OFFSET_SHIFT) & CLK_GATE_REG_OFFSET_MASK) | \
382 (((bit_shift) << CLK_GATE_BIT_SHIFT_SHIFT) & CLK_GATE_BIT_SHIFT_MASK))
383
384#define CLK_GATE_ABSTRACT_REG_OFFSET(x) (((x)&CLK_GATE_REG_OFFSET_MASK) >> CLK_GATE_REG_OFFSET_SHIFT)
385#define CLK_GATE_ABSTRACT_BITS_SHIFT(x) (((x)&CLK_GATE_BIT_SHIFT_MASK) >> CLK_GATE_BIT_SHIFT_SHIFT)
386
387/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
388typedef enum _clock_ip_name
389{
390 kCLOCK_IpInvalid = 0U,
391 kCLOCK_I2c2 = CLK_GATE_DEFINE(0x1028U, 6U),
392 kCLOCK_I2c3 = CLK_GATE_DEFINE(0x1028U, 7U),
393
394 kCLOCK_Lpuart0 = CLK_GATE_DEFINE(0x102CU, 4U),
395 kCLOCK_Lpuart1 = CLK_GATE_DEFINE(0x102CU, 5U),
396 kCLOCK_Lpuart2 = CLK_GATE_DEFINE(0x102CU, 6U),
397 kCLOCK_Lpuart3 = CLK_GATE_DEFINE(0x102CU, 7U),
398 kCLOCK_Tpm1 = CLK_GATE_DEFINE(0x102CU, 9U),
399 kCLOCK_Tpm2 = CLK_GATE_DEFINE(0x102CU, 10U),
400 kCLOCK_Dac0 = CLK_GATE_DEFINE(0x102CU, 12U),
401 kCLOCK_Lpuart4 = CLK_GATE_DEFINE(0x102CU, 22U),
402 kCLOCK_Qspi0 = CLK_GATE_DEFINE(0x102CU, 26U),
403 kCLOCK_Flexio0 = CLK_GATE_DEFINE(0x102CU, 31U),
404
405 kCLOCK_Trng0 = CLK_GATE_DEFINE(0x1030U, 0U),
406 kCLOCK_Usbhs = CLK_GATE_DEFINE(0x1030U, 1U),
407 kCLOCK_Usbhsphy = CLK_GATE_DEFINE(0x1030U, 2U),
408 kCLOCK_Usbhsdcd = CLK_GATE_DEFINE(0x1030U, 3U),
409 kCLOCK_Spi2 = CLK_GATE_DEFINE(0x1030U, 12U),
410 kCLOCK_Spi3 = CLK_GATE_DEFINE(0x1030U, 13U),
411 kCLOCK_Sai1 = CLK_GATE_DEFINE(0x1030U, 15U),
412 kCLOCK_Sdhc0 = CLK_GATE_DEFINE(0x1030U, 17U),
413 kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x1030U, 24U),
414 kCLOCK_Ftm3 = CLK_GATE_DEFINE(0x1030U, 25U),
415
416 kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U),
417 kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U),
418 kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U),
419 kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U),
420 kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U),
421 kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U),
422 kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U),
423 kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U),
424
425 kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U),
426 kCLOCK_Lptmr1 = CLK_GATE_DEFINE(0x1038U, 4U),
427 kCLOCK_Tsi0 = CLK_GATE_DEFINE(0x1038U, 5U),
428 kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U),
429 kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U),
430 kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U),
431 kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U),
432 kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U),
433
434 kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U),
435 kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U),
436 kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U),
437 kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U),
438 kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U),
439 kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U),
440 kCLOCK_Usbdcd0 = CLK_GATE_DEFINE(0x103CU, 21U),
441 kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U),
442 kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U),
443 kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U),
444 kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U),
445 kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U),
446 kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U),
447
448 kCLOCK_Flexbus0 = CLK_GATE_DEFINE(0x1040U, 0U),
449 kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U),
450 kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U),
451 kCLOCK_Sdramc0 = CLK_GATE_DEFINE(0x1040U, 3U),
452} clock_ip_name_t;
453
454/*! @brief Source of the USB HS PHY. */
455typedef enum _clock_usb_phy_src
456{
457 kCLOCK_UsbPhySrcExt = 0U, /*!< Use external crystal. */
458} clock_usb_phy_src_t;
459
460/*! @brief Source of the USB HS PFD clock (USB1PFDCLK) */
461typedef enum _clock_usb_pfd_src
462{
463 kCLOCK_UsbPfdSrcExt = 0U, /*!< Use external crystal. */
464 kCLOCK_UsbPfdSrcFracDivBy4 = 1U, /*!< Use PFD_FRAC output divided by 4. */
465 kCLOCK_UsbPfdSrcFracDivBy2 = 2U, /*!< Use PFD_FRAC output divided by 2. */
466 kCLOCK_UsbPfdSrcFrac = 3U, /*!< Use PFD_FRAC output. */
467} clock_usb_pfd_src_t;
468
469/*!@brief SIM configuration structure for clock setting. */
470typedef struct _sim_clock_config
471{
472 uint8_t pllFllSel; /*!< PLL/FLL/IRC48M selection. */
473 uint8_t pllFllDiv; /*!< PLLFLLSEL clock divider divisor. */
474 uint8_t pllFllFrac; /*!< PLLFLLSEL clock divider fraction. */
475 uint8_t er32kSrc; /*!< ERCLK32K source selection. */
476 uint32_t clkdiv1; /*!< SIM_CLKDIV1. */
477} sim_clock_config_t;
478
479/*! @brief OSC work mode. */
480typedef enum _osc_mode
481{
482 kOSC_ModeExt = 0U, /*!< Use an external clock. */
483#if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK)))
484 kOSC_ModeOscLowPower = MCG_C2_EREFS_MASK, /*!< Oscillator low power. */
485#else
486 kOSC_ModeOscLowPower = MCG_C2_EREFS0_MASK, /*!< Oscillator low power. */
487#endif
488 kOSC_ModeOscHighGain = 0U
489#if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK)))
490 | MCG_C2_EREFS_MASK
491#else
492 | MCG_C2_EREFS0_MASK
493#endif
494#if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK)))
495 | MCG_C2_HGO_MASK, /*!< Oscillator high gain. */
496#else
497 | MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */
498#endif
499} osc_mode_t;
500
501/*! @brief Oscillator capacitor load setting.*/
502enum _osc_cap_load
503{
504 kOSC_Cap2P = OSC_CR_SC2P_MASK, /*!< 2 pF capacitor load */
505 kOSC_Cap4P = OSC_CR_SC4P_MASK, /*!< 4 pF capacitor load */
506 kOSC_Cap8P = OSC_CR_SC8P_MASK, /*!< 8 pF capacitor load */
507 kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */
508};
509
510/*! @brief OSCERCLK enable mode. */
511enum _oscer_enable_mode
512{
513 kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK, /*!< Enable. */
514 kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */
515};
516
517/*! @brief OSC configuration for OSCERCLK. */
518typedef struct _oscer_config
519{
520 uint8_t enableMode; /*!< OSCERCLK enable mode. OR'ed value of @ref _oscer_enable_mode. */
521
522 uint8_t erclkDiv; /*!< Divider for OSCERCLK.*/
523} oscer_config_t;
524
525/*!
526 * @brief OSC Initialization Configuration Structure
527 *
528 * Defines the configuration data structure to initialize the OSC.
529 * When porting to a new board, set the following members
530 * according to the board setting:
531 * 1. freq: The external frequency.
532 * 2. workMode: The OSC module mode.
533 */
534typedef struct _osc_config
535{
536 uint32_t freq; /*!< External clock frequency. */
537 uint8_t capLoad; /*!< Capacitor load setting. */
538 osc_mode_t workMode; /*!< OSC work mode setting. */
539 oscer_config_t oscerConfig; /*!< Configuration for OSCERCLK. */
540} osc_config_t;
541
542/*! @brief MCG FLL reference clock source select. */
543typedef enum _mcg_fll_src
544{
545 kMCG_FllSrcExternal, /*!< External reference clock is selected */
546 kMCG_FllSrcInternal /*!< The slow internal reference clock is selected */
547} mcg_fll_src_t;
548
549/*! @brief MCG internal reference clock select */
550typedef enum _mcg_irc_mode
551{
552 kMCG_IrcSlow, /*!< Slow internal reference clock selected */
553 kMCG_IrcFast /*!< Fast internal reference clock selected */
554} mcg_irc_mode_t;
555
556/*! @brief MCG DCO Maximum Frequency with 32.768 kHz Reference */
557typedef enum _mcg_dmx32
558{
559 kMCG_Dmx32Default, /*!< DCO has a default range of 25% */
560 kMCG_Dmx32Fine /*!< DCO is fine-tuned for maximum frequency with 32.768 kHz reference */
561} mcg_dmx32_t;
562
563/*! @brief MCG DCO range select */
564typedef enum _mcg_drs
565{
566 kMCG_DrsLow, /*!< Low frequency range */
567 kMCG_DrsMid, /*!< Mid frequency range */
568 kMCG_DrsMidHigh, /*!< Mid-High frequency range */
569 kMCG_DrsHigh /*!< High frequency range */
570} mcg_drs_t;
571
572/*! @brief MCG PLL reference clock select */
573typedef enum _mcg_pll_ref_src
574{
575 kMCG_PllRefOsc0, /*!< Selects OSC0 as PLL reference clock */
576 kMCG_PllRefOsc1 /*!< Selects OSC1 as PLL reference clock */
577} mcg_pll_ref_src_t;
578
579/*! @brief MCGOUT clock source. */
580typedef enum _mcg_clkout_src
581{
582 kMCG_ClkOutSrcOut, /*!< Output of the FLL is selected (reset default) */
583 kMCG_ClkOutSrcInternal, /*!< Internal reference clock is selected */
584 kMCG_ClkOutSrcExternal, /*!< External reference clock is selected */
585} mcg_clkout_src_t;
586
587/*! @brief MCG Automatic Trim Machine Select */
588typedef enum _mcg_atm_select
589{
590 kMCG_AtmSel32k, /*!< 32 kHz Internal Reference Clock selected */
591 kMCG_AtmSel4m /*!< 4 MHz Internal Reference Clock selected */
592} mcg_atm_select_t;
593
594/*! @brief MCG OSC Clock Select */
595typedef enum _mcg_oscsel
596{
597 kMCG_OscselOsc, /*!< Selects System Oscillator (OSCCLK) */
598 kMCG_OscselRtc, /*!< Selects 32 kHz RTC Oscillator */
599 kMCG_OscselIrc /*!< Selects 48 MHz IRC Oscillator */
600} mcg_oscsel_t;
601
602/*! @brief MCG PLLCS select */
603typedef enum _mcg_pll_clk_select
604{
605 kMCG_PllClkSelPll0, /*!< PLL0 output clock is selected */
606 kMCG_PllClkSelExtPll /* The external PLL clock is selected */
607} mcg_pll_clk_select_t;
608
609/*! @brief MCG clock monitor mode. */
610typedef enum _mcg_monitor_mode
611{
612 kMCG_MonitorNone, /*!< Clock monitor is disabled. */
613 kMCG_MonitorInt, /*!< Trigger interrupt when clock lost. */
614 kMCG_MonitorReset /*!< System reset when clock lost. */
615} mcg_monitor_mode_t;
616
617/*! @brief MCG status. */
618enum
619{
620 kStatus_MCG_ModeUnreachable = MAKE_STATUS(kStatusGroup_MCG, 0U), /*!< Can't switch to target mode. */
621 kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1U), /*!< Current mode invalid for the specific
622 function. */
623 kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2U), /*!< Invalid bus clock for ATM. */
624 kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3U), /*!< Invalid desired frequency for ATM. */
625 kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4U), /*!< IRC is used when using ATM. */
626 kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5U), /*!< Hardware fail occurs during ATM. */
627 kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6U) /*!< Can't change the clock source because
628 it is in use. */
629};
630
631/*! @brief MCG status flags. */
632enum
633{
634 kMCG_Osc0LostFlag = (1U << 0U), /*!< OSC0 lost. */
635 kMCG_Osc0InitFlag = (1U << 1U), /*!< OSC0 crystal initialized. */
636 kMCG_RtcOscLostFlag = (1U << 4U), /*!< RTC OSC lost. */
637 kMCG_Pll0LostFlag = (1U << 5U), /*!< PLL0 lost. */
638 kMCG_Pll0LockFlag = (1U << 6U), /*!< PLL0 locked. */
639 kMCG_ExtPllLostFlag = (1U << 9U), /*!< External PLL lost. */
640};
641
642/*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */
643enum
644{
645 kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK, /*!< MCGIRCLK enable. */
646 kMCG_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */
647};
648
649/*! @brief MCG PLL clock enable mode definition. */
650enum
651{
652 kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable independent of the
653 MCG clock mode. Generally, the PLL
654 is disabled in FLL modes
655 (FEI/FBI/FEE/FBE). Setting the PLL clock
656 enable independent, enables the
657 PLL in the FLL modes. */
658 kMCG_PllEnableInStop = MCG_C5_PLLSTEN0_MASK /*!< MCGPLLCLK enable in STOP mode. */
659};
660
661/*! @brief MCG mode definitions */
662typedef enum _mcg_mode
663{
664 kMCG_ModeFEI = 0U, /*!< FEI - FLL Engaged Internal */
665 kMCG_ModeFBI, /*!< FBI - FLL Bypassed Internal */
666 kMCG_ModeBLPI, /*!< BLPI - Bypassed Low Power Internal */
667 kMCG_ModeFEE, /*!< FEE - FLL Engaged External */
668 kMCG_ModeFBE, /*!< FBE - FLL Bypassed External */
669 kMCG_ModeBLPE, /*!< BLPE - Bypassed Low Power External */
670 kMCG_ModePBE, /*!< PBE - PLL Bypassed External */
671 kMCG_ModePEE, /*!< PEE - PLL Engaged External */
672 kMCG_ModeError /*!< Unknown mode */
673} mcg_mode_t;
674
675/*! @brief MCG PLL configuration. */
676typedef struct _mcg_pll_config
677{
678 uint8_t enableMode; /*!< Enable mode. OR'ed value of _mcg_pll_enable_mode. */
679 uint8_t prdiv; /*!< Reference divider PRDIV. */
680 uint8_t vdiv; /*!< VCO divider VDIV. */
681} mcg_pll_config_t;
682
683/*! @brief MCG mode change configuration structure
684 *
685 * When porting to a new board, set the following members
686 * according to the board setting:
687 * 1. frdiv: If the FLL uses the external reference clock, set this
688 * value to ensure that the external reference clock divided by frdiv is
689 * in the 31.25 kHz to 39.0625 kHz range.
690 * 2. The PLL reference clock divider PRDIV: PLL reference clock frequency after
691 * PRDIV should be in the FSL_FEATURE_MCG_PLL_REF_MIN to
692 * FSL_FEATURE_MCG_PLL_REF_MAX range.
693 */
694typedef struct _mcg_config
695{
696 mcg_mode_t mcgMode; /*!< MCG mode. */
697
698 /* ----------------------- MCGIRCCLK settings ------------------------ */
699 uint8_t irclkEnableMode; /*!< MCGIRCLK enable mode. */
700 mcg_irc_mode_t ircs; /*!< Source, MCG_C2[IRCS]. */
701 uint8_t fcrdiv; /*!< Divider, MCG_SC[FCRDIV]. */
702
703 /* ------------------------ MCG FLL settings ------------------------- */
704 uint8_t frdiv; /*!< Divider MCG_C1[FRDIV]. */
705 mcg_drs_t drs; /*!< DCO range MCG_C4[DRST_DRS]. */
706 mcg_dmx32_t dmx32; /*!< MCG_C4[DMX32]. */
707 mcg_oscsel_t oscsel; /*!< OSC select MCG_C7[OSCSEL]. */
708
709 /* ------------------------ MCG PLL settings ------------------------- */
710 mcg_pll_config_t pll0Config; /*!< MCGPLL0CLK configuration. */
711
712 mcg_pll_clk_select_t pllcs; /*!< PLL select as output, PLLCS.*/
713
714} mcg_config_t;
715
716/*******************************************************************************
717 * API
718 ******************************************************************************/
719
720#if defined(__cplusplus)
721extern "C" {
722#endif /* __cplusplus */
723
724/*!
725 * @brief Enable the clock for specific IP.
726 *
727 * @param name Which clock to enable, see \ref clock_ip_name_t.
728 */
729static inline void CLOCK_EnableClock(clock_ip_name_t name)
730{
731 uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
732 (*(volatile uint32_t *)regAddr) |= (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
733}
734
735/*!
736 * @brief Disable the clock for specific IP.
737 *
738 * @param name Which clock to disable, see \ref clock_ip_name_t.
739 */
740static inline void CLOCK_DisableClock(clock_ip_name_t name)
741{
742 uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
743 (*(volatile uint32_t *)regAddr) &= ~(1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
744}
745
746/*!
747 * @brief Set ERCLK32K source.
748 *
749 * @param src The value to set ERCLK32K clock source.
750 */
751static inline void CLOCK_SetEr32kClock(uint32_t src)
752{
753 SIM->SOPT1 = ((SIM->SOPT1 & ~SIM_SOPT1_OSC32KSEL_MASK) | SIM_SOPT1_OSC32KSEL(src));
754}
755
756/*!
757 * @brief Set SDHC0 clock source.
758 *
759 * @param src The value to set SDHC0 clock source.
760 */
761static inline void CLOCK_SetSdhc0Clock(uint32_t src)
762{
763 SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_SDHCSRC_MASK) | SIM_SOPT2_SDHCSRC(src));
764}
765
766/*!
767 * @brief Set LPUART clock source.
768 *
769 * @param src The value to set LPUART clock source.
770 */
771static inline void CLOCK_SetLpuartClock(uint32_t src)
772{
773 SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_LPUARTSRC_MASK) | SIM_SOPT2_LPUARTSRC(src));
774}
775
776/*!
777 * @brief Set TPM clock source.
778 *
779 * @param src The value to set TPM clock source.
780 */
781static inline void CLOCK_SetTpmClock(uint32_t src)
782{
783 SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TPMSRC_MASK) | SIM_SOPT2_TPMSRC(src));
784}
785
786/*!
787 * @brief Set FLEXIO clock source.
788 *
789 * @param src The value to set FLEXIO clock source.
790 */
791static inline void CLOCK_SetFlexio0Clock(uint32_t src)
792{
793 SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_FLEXIOSRC_MASK) | SIM_SOPT2_FLEXIOSRC(src));
794}
795
796/*!
797 * @brief Set USB clock source.
798 *
799 * @param src The value to set USB clock source.
800 */
801static inline void CLOCK_SetUsbClock(uint32_t src)
802{
803 SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_USBSRC_MASK) | SIM_SOPT2_USBSRC(src));
804}
805
806/*!
807 * @brief Set debug trace clock source.
808 *
809 * @param src The value to set debug trace clock source.
810 * @param divValue
811 * @param fracValue
812 */
813static inline void CLOCK_SetTraceClock(uint32_t src, uint32_t divValue, uint32_t fracValue)
814{
815 SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TRACECLKSEL_MASK) | SIM_SOPT2_TRACECLKSEL(src));
816 SIM->CLKDIV4 = SIM_CLKDIV4_TRACEDIV(divValue) | SIM_CLKDIV4_TRACEFRAC(fracValue);
817}
818
819/*!
820 * @brief Set PLLFLLSEL clock source.
821 *
822 * @param src The value to set PLLFLLSEL clock source.
823 * @param divValue
824 * @param fracValue
825 */
826static inline void CLOCK_SetPllFllSelClock(uint32_t src, uint32_t divValue, uint32_t fracValue)
827{
828 SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_PLLFLLSEL_MASK) | SIM_SOPT2_PLLFLLSEL(src));
829 SIM->CLKDIV3 = SIM_CLKDIV3_PLLFLLDIV(divValue) | SIM_CLKDIV3_PLLFLLFRAC(fracValue);
830}
831
832/*!
833 * @brief Set CLKOUT source.
834 *
835 * @param src The value to set CLKOUT source.
836 */
837static inline void CLOCK_SetClkOutClock(uint32_t src)
838{
839 SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_CLKOUTSEL_MASK) | SIM_SOPT2_CLKOUTSEL(src));
840}
841
842/*!
843 * @brief Set RTC_CLKOUT source.
844 *
845 * @param src The value to set RTC_CLKOUT source.
846 */
847static inline void CLOCK_SetRtcClkOutClock(uint32_t src)
848{
849 SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_RTCCLKOUTSEL_MASK) | SIM_SOPT2_RTCCLKOUTSEL(src));
850}
851
852/*! @brief Enable USB HS clock.
853 *
854 * @param src USB HS clock source.
855 * @param freq The frequency specified by src.
856 * @retval true The clock is set successfully.
857 * @retval false The clock source is invalid to get proper USB HS clock.
858 */
859bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq);
860
861/*! @brief Disable USB HS clock.
862 *
863 * Disable USB HS clock.
864 *
865 */
866void CLOCK_DisableUsbhs0Clock(void);
867
868/*! @ brief Disable USB hs0 Phy Pll Clock
869 *
870 * Disable USB hs0 Phy Pll Clock
871 */
872void CLOCK_DisableUsbhs0PhyPllClock(void);
873
874/*! Enable USB hs0 Pfd clock
875 *
876 * @param src USB hs0 clock source.
877 * @param frac
878 *
879 */
880void CLOCK_EnableUsbhs0PfdClock(uint8_t frac, clock_usb_pfd_src_t src);
881
882/*! @ brief Disable USB hs0 Pfd Pll Clock
883 *
884 * Disable USB hs0 Pfd Pll Clock
885 */
886void CLOCK_DisableUsbhs0PfdClock(void);
887
888/*! @brief Enable USB FS clock.
889 *
890 * @param src USB FS clock source.
891 * @param freq The frequency specified by src.
892 * @retval true The clock is set successfully.
893 * @retval false The clock source is invalid to get proper USB FS clock.
894 */
895bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq);
896
897/*! @brief Enable USB hs0PhyPll clock.
898 *
899 * @param src USB HS clock source.
900 * @param freq The frequency specified by src.
901 * @retval true The clock is set successfully.
902 * @retval false The clock source is invalid to get proper USB HS clock.
903 */
904bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq);
905
906/*! @brief Disable USB FS clock.
907 *
908 * Disable USB FS clock.
909 */
910static inline void CLOCK_DisableUsbfs0Clock(void)
911{
912 CLOCK_DisableClock(kCLOCK_Usbfs0);
913}
914
915/*!
916 * @brief System clock divider
917 *
918 * Set the SIM_CLKDIV1[OUTDIV1], SIM_CLKDIV1[OUTDIV2], SIM_CLKDIV1[OUTDIV3], SIM_CLKDIV1[OUTDIV4].
919 *
920 * @param outdiv1 Clock 1 output divider value.
921 *
922 * @param outdiv2 Clock 2 output divider value.
923 *
924 * @param outdiv3 Clock 3 output divider value.
925 *
926 * @param outdiv4 Clock 4 output divider value.
927 */
928static inline void CLOCK_SetOutDiv(uint32_t outdiv1, uint32_t outdiv2, uint32_t outdiv3, uint32_t outdiv4)
929{
930 SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(outdiv1) | SIM_CLKDIV1_OUTDIV2(outdiv2) | SIM_CLKDIV1_OUTDIV3(outdiv3) |
931 SIM_CLKDIV1_OUTDIV4(outdiv4);
932}
933
934/*!
935 * @brief Gets the clock frequency for a specific clock name.
936 *
937 * This function checks the current clock configurations and then calculates
938 * the clock frequency for a specific clock name defined in clock_name_t.
939 * The MCG must be properly configured before using this function.
940 *
941 * @param clockName Clock names defined in clock_name_t
942 * @return Clock frequency value in Hertz
943 */
944uint32_t CLOCK_GetFreq(clock_name_t clockName);
945
946/*!
947 * @brief Get the core clock or system clock frequency.
948 *
949 * @return Clock frequency in Hz.
950 */
951uint32_t CLOCK_GetCoreSysClkFreq(void);
952
953/*!
954 * @brief Get the platform clock frequency.
955 *
956 * @return Clock frequency in Hz.
957 */
958uint32_t CLOCK_GetPlatClkFreq(void);
959
960/*!
961 * @brief Get the bus clock frequency.
962 *
963 * @return Clock frequency in Hz.
964 */
965uint32_t CLOCK_GetBusClkFreq(void);
966
967/*!
968 * @brief Get the flexbus clock frequency.
969 *
970 * @return Clock frequency in Hz.
971 */
972uint32_t CLOCK_GetFlexBusClkFreq(void);
973
974/*!
975 * @brief Get the flash clock frequency.
976 *
977 * @return Clock frequency in Hz.
978 */
979uint32_t CLOCK_GetFlashClkFreq(void);
980
981/*!
982 * @brief Get the output clock frequency selected by SIM[PLLFLLSEL].
983 *
984 * @return Clock frequency in Hz.
985 */
986uint32_t CLOCK_GetPllFllSelClkFreq(void);
987
988/*!
989 * @brief Get the external reference 32K clock frequency (ERCLK32K).
990 *
991 * @return Clock frequency in Hz.
992 */
993uint32_t CLOCK_GetEr32kClkFreq(void);
994
995/*!
996 * @brief Get the OSC0 external reference undivided clock frequency (OSC0ERCLK_UNDIV).
997 *
998 * @return Clock frequency in Hz.
999 */
1000uint32_t CLOCK_GetOsc0ErClkUndivFreq(void);
1001
1002/*!
1003 * @brief Get the OSC0 external reference divided clock frequency (OSC0ERCLK_UNDIV).
1004 *
1005 * @return Clock frequency
1006 */
1007uint32_t CLOCK_GetOsc0ErClkDivFreq(void);
1008
1009/*!
1010 * @brief Get the OSC0 external reference clock frequency (OSC0ERCLK).
1011 *
1012 * @return Clock frequency in Hz.
1013 */
1014uint32_t CLOCK_GetOsc0ErClkFreq(void);
1015
1016/*!
1017 * @brief Set the clock configure in SIM module.
1018 *
1019 * This function sets system layer clock settings in SIM module.
1020 */
1021void CLOCK_SetSimConfig(sim_clock_config_t const *config);
1022
1023/*!
1024 * @brief Set the system clock dividers in SIM to safe value.
1025 *
1026 * The system level clocks (core clock, bus clock, flexbus clock and flash clock)
1027 * must be in allowed ranges. During MCG clock mode switch, the MCG output clock
1028 * changes then the system level clocks may be out of range. This function could
1029 * be used before MCG mode change, to make sure system level clocks are in allowed
1030 * range.
1031 *
1032 */
1033static inline void CLOCK_SetSimSafeDivs(void)
1034{
1035 SIM->CLKDIV1 = 0x02260000U;
1036}
1037
1038/*! @name MCG frequency functions. */
1039/*@{*/
1040
1041/*!
1042 * @brief Gets the MCG output clock (MCGOUTCLK) frequency.
1043 *
1044 * This function gets the MCG output clock frequency in Hz based on the current MCG
1045 * register value.
1046 *
1047 * @return The frequency of MCGOUTCLK.
1048 */
1049uint32_t CLOCK_GetOutClkFreq(void);
1050
1051/*!
1052 * @brief Gets the MCG FLL clock (MCGFLLCLK) frequency.
1053 *
1054 * This function gets the MCG FLL clock frequency in Hz based on the current MCG
1055 * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and
1056 * disabled in low power state in other modes.
1057 *
1058 * @return The frequency of MCGFLLCLK.
1059 */
1060uint32_t CLOCK_GetFllFreq(void);
1061
1062/*!
1063 * @brief Gets the MCG internal reference clock (MCGIRCLK) frequency.
1064 *
1065 * This function gets the MCG internal reference clock frequency in Hz based
1066 * on the current MCG register value.
1067 *
1068 * @return The frequency of MCGIRCLK.
1069 */
1070uint32_t CLOCK_GetInternalRefClkFreq(void);
1071
1072/*!
1073 * @brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency.
1074 *
1075 * This function gets the MCG fixed frequency clock frequency in Hz based
1076 * on the current MCG register value.
1077 *
1078 * @return The frequency of MCGFFCLK.
1079 */
1080uint32_t CLOCK_GetFixedFreqClkFreq(void);
1081
1082/*!
1083 * @brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency.
1084 *
1085 * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG
1086 * register value.
1087 *
1088 * @return The frequency of MCGPLL0CLK.
1089 */
1090uint32_t CLOCK_GetPll0Freq(void);
1091
1092/*!
1093 * @brief Gets the MCG external PLL frequency.
1094 *
1095 * This function gets the MCG external PLL frequency in Hz.
1096 *
1097 * @return The frequency of the MCG external PLL.
1098 */
1099uint32_t CLOCK_GetExtPllFreq(void);
1100
1101/*!
1102 * @brief Sets the MCG external PLL frequency.
1103 *
1104 * This function sets the MCG external PLL frequency in Hz. The MCG external PLL
1105 * frequency is passed to the MCG driver using this function. Call this
1106 * function after the external PLL frequency is changed. Otherwise, the APIs, which are used to get
1107 * the frequency, may return an incorrect value.
1108 *
1109 * @param freq The frequency of MCG external PLL.
1110 */
1111void CLOCK_SetExtPllFreq(uint32_t freq);
1112
1113/*@}*/
1114
1115/*! @name MCG clock configuration. */
1116/*@{*/
1117
1118/*!
1119 * @brief Enables or disables the MCG low power.
1120 *
1121 * Enabling the MCG low power disables the PLL and FLL in bypass modes. In other words,
1122 * in FBE and PBE modes, enabling low power sets the MCG to BLPE mode. In FBI and
1123 * PBI modes, enabling low power sets the MCG to BLPI mode.
1124 * When disabling the MCG low power, the PLL or FLL are enabled based on MCG settings.
1125 *
1126 * @param enable True to enable MCG low power, false to disable MCG low power.
1127 */
1128static inline void CLOCK_SetLowPowerEnable(bool enable)
1129{
1130 if (enable)
1131 {
1132 MCG->C2 |= MCG_C2_LP_MASK;
1133 }
1134 else
1135 {
1136 MCG->C2 &= ~(uint8_t)MCG_C2_LP_MASK;
1137 }
1138}
1139
1140/*!
1141 * @brief Configures the Internal Reference clock (MCGIRCLK).
1142 *
1143 * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC
1144 * source. If the fast IRC is used, this function sets the fast IRC divider.
1145 * This function also sets whether the \c MCGIRCLK is enabled in stop mode.
1146 * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result,
1147 * using the function in these modes it is not allowed.
1148 *
1149 * @param enableMode MCGIRCLK enable mode, OR'ed value of _mcg_irclk_enable_mode.
1150 * @param ircs MCGIRCLK clock source, choose fast or slow.
1151 * @param fcrdiv Fast IRC divider setting (\c FCRDIV).
1152 * @retval kStatus_MCG_SourceUsed Because the internal reference clock is used as a clock source,
1153 * the configuration should not be changed. Otherwise, a glitch occurs.
1154 * @retval kStatus_Success MCGIRCLK configuration finished successfully.
1155 */
1156status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv);
1157
1158/*!
1159 * @brief Selects the MCG external reference clock.
1160 *
1161 * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL],
1162 * and waits for the clock source to be stable. Because the external reference
1163 * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes.
1164 *
1165 * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL].
1166 * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source,
1167 * the configuration should not be changed. Otherwise, a glitch occurs.
1168 * @retval kStatus_Success External reference clock set successfully.
1169 */
1170status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel);
1171
1172/*!
1173 * @brief Set the FLL external reference clock divider value.
1174 *
1175 * Sets the FLL external reference clock divider value, the register MCG_C1[FRDIV].
1176 *
1177 * @param frdiv The FLL external reference clock divider value, MCG_C1[FRDIV].
1178 */
1179static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv)
1180{
1181 MCG->C1 = (uint8_t)((MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv));
1182}
1183
1184/*!
1185 * @brief Enables the PLL0 in FLL mode.
1186 *
1187 * This function sets us the PLL0 in FLL mode and reconfigures
1188 * the PLL0. Ensure that the PLL reference
1189 * clock is enabled before calling this function and that the PLL0 is not used as a clock source.
1190 * The function CLOCK_CalcPllDiv gets the correct PLL
1191 * divider values.
1192 *
1193 * @param config Pointer to the configuration structure.
1194 */
1195void CLOCK_EnablePll0(mcg_pll_config_t const *config);
1196
1197/*!
1198 * @brief Disables the PLL0 in FLL mode.
1199 *
1200 * This function disables the PLL0 in FLL mode. It should be used together with the
1201 * @ref CLOCK_EnablePll0.
1202 */
1203static inline void CLOCK_DisablePll0(void)
1204{
1205 MCG->C5 &= (uint8_t)(~(MCG_C5_PLLCLKEN0_MASK | MCG_C5_PLLSTEN0_MASK));
1206}
1207
1208/*!
1209 * @brief Calculates the PLL divider setting for a desired output frequency.
1210 *
1211 * This function calculates the correct reference clock divider (\c PRDIV) and
1212 * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the
1213 * closest frequency match with the corresponding \c PRDIV/VDIV
1214 * returned from parameters. If a desired frequency is not valid, this function
1215 * returns 0.
1216 *
1217 * @param refFreq PLL reference clock frequency.
1218 * @param desireFreq Desired PLL output frequency.
1219 * @param prdiv PRDIV value to generate desired PLL frequency.
1220 * @param vdiv VDIV value to generate desired PLL frequency.
1221 * @return Closest frequency match that the PLL was able generate.
1222 */
1223uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv);
1224
1225/*!
1226 * @brief Set the PLL selection.
1227 *
1228 * This function sets the PLL selection between PLL0/PLL1/EXTPLL, and waits for
1229 * change finished.
1230 *
1231 * @param pllcs The PLL to select.
1232 */
1233void CLOCK_SetPllClkSel(mcg_pll_clk_select_t pllcs);
1234
1235/*@}*/
1236
1237/*! @name MCG clock lock monitor functions. */
1238/*@{*/
1239
1240/*!
1241 * @brief Sets the OSC0 clock monitor mode.
1242 *
1243 * This function sets the OSC0 clock monitor mode. See @ref mcg_monitor_mode_t for details.
1244 *
1245 * @param mode Monitor mode to set.
1246 */
1247void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode);
1248
1249/*!
1250 * @brief Sets the RTC OSC clock monitor mode.
1251 *
1252 * This function sets the RTC OSC clock monitor mode. See @ref mcg_monitor_mode_t for details.
1253 *
1254 * @param mode Monitor mode to set.
1255 */
1256void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode);
1257
1258/*!
1259 * @brief Sets the PLL0 clock monitor mode.
1260 *
1261 * This function sets the PLL0 clock monitor mode. See @ref mcg_monitor_mode_t for details.
1262 *
1263 * @param mode Monitor mode to set.
1264 */
1265void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode);
1266
1267/*!
1268 * @brief Sets the external PLL clock monitor mode.
1269 *
1270 * This function ets the external PLL clock monitor mode. See @ref mcg_monitor_mode_t
1271 * for details.
1272 *
1273 * @param mode Monitor mode to set.
1274 */
1275void CLOCK_SetExtPllMonitorMode(mcg_monitor_mode_t mode);
1276
1277/*!
1278 * @brief Gets the MCG status flags.
1279 *
1280 * This function gets the MCG clock status flags. All status flags are
1281 * returned as a logical OR of the enumeration _mcg_status_flags_t. To
1282 * check a specific flag, compare the return value with the flag.
1283 *
1284 * Example:
1285 * @code
1286 * To check the clock lost lock status of OSC0 and PLL0.
1287 * uint32_t mcgFlags;
1288 *
1289 * mcgFlags = CLOCK_GetStatusFlags();
1290 *
1291 * if (mcgFlags & kMCG_Osc0LostFlag)
1292 * {
1293 * OSC0 clock lock lost. Do something.
1294 * }
1295 * if (mcgFlags & kMCG_Pll0LostFlag)
1296 * {
1297 * PLL0 clock lock lost. Do something.
1298 * }
1299 * @endcode
1300 *
1301 * @return Logical OR value of the _mcg_status_flags_t.
1302 */
1303uint32_t CLOCK_GetStatusFlags(void);
1304
1305/*!
1306 * @brief Clears the MCG status flags.
1307 *
1308 * This function clears the MCG clock lock lost status. The parameter is a logical
1309 * OR value of the flags to clear. See _mcg_status_flags_t.
1310 *
1311 * Example:
1312 * @code
1313 * To clear the clock lost lock status flags of OSC0 and PLL0.
1314 *
1315 * CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag);
1316 * @endcode
1317 *
1318 * @param mask The status flags to clear. This is a logical OR of members of the
1319 * enumeration _mcg_status_flags_t.
1320 */
1321void CLOCK_ClearStatusFlags(uint32_t mask);
1322
1323/*@}*/
1324
1325/*!
1326 * @name OSC configuration
1327 * @{
1328 */
1329
1330/*!
1331 * @brief Configures the OSC external reference clock (OSCERCLK).
1332 *
1333 * This function configures the OSC external reference clock (OSCERCLK).
1334 * This is an example to enable the OSCERCLK in normal and stop modes and also set
1335 * the output divider to 1:
1336 *
1337 @code
1338 oscer_config_t config =
1339 {
1340 .enableMode = kOSC_ErClkEnable | kOSC_ErClkEnableInStop,
1341 .erclkDiv = 1U,
1342 };
1343
1344 OSC_SetExtRefClkConfig(OSC, &config);
1345 @endcode
1346 *
1347 * @param base OSC peripheral address.
1348 * @param config Pointer to the configuration structure.
1349 */
1350static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const *config)
1351{
1352 uint8_t reg = base->CR;
1353
1354 reg &= (uint8_t)(~(OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK));
1355 reg |= config->enableMode;
1356
1357 base->CR = reg;
1358
1359 base->DIV = OSC_DIV_ERPS(config->erclkDiv);
1360}
1361
1362/*!
1363 * @brief Sets the capacitor load configuration for the oscillator.
1364 *
1365 * This function sets the specified capacitors configuration for the oscillator.
1366 * This should be done in the early system level initialization function call
1367 * based on the system configuration.
1368 *
1369 * @param base OSC peripheral address.
1370 * @param capLoad OR'ed value for the capacitor load option, see \ref _osc_cap_load.
1371 *
1372 * Example:
1373 @code
1374 To enable only 2 pF and 8 pF capacitor load, please use like this.
1375 OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P);
1376 @endcode
1377 */
1378static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad)
1379{
1380 uint8_t reg = base->CR;
1381
1382 reg &= (uint8_t)(~(OSC_CR_SC2P_MASK | OSC_CR_SC4P_MASK | OSC_CR_SC8P_MASK | OSC_CR_SC16P_MASK));
1383 reg |= capLoad;
1384
1385 base->CR = reg;
1386}
1387
1388/*!
1389 * @brief Initializes the OSC0.
1390 *
1391 * This function initializes the OSC0 according to the board configuration.
1392 *
1393 * @param config Pointer to the OSC0 configuration structure.
1394 */
1395void CLOCK_InitOsc0(osc_config_t const *config);
1396
1397/*!
1398 * @brief Deinitializes the OSC0.
1399 *
1400 * This function deinitializes the OSC0.
1401 */
1402void CLOCK_DeinitOsc0(void);
1403
1404/* @} */
1405
1406/*!
1407 * @name External clock frequency
1408 * @{
1409 */
1410
1411/*!
1412 * @brief Sets the XTAL0 frequency based on board settings.
1413 *
1414 * @param freq The XTAL0/EXTAL0 input clock frequency in Hz.
1415 */
1416static inline void CLOCK_SetXtal0Freq(uint32_t freq)
1417{
1418 g_xtal0Freq = freq;
1419}
1420
1421/*!
1422 * @brief Sets the XTAL32/RTC_CLKIN frequency based on board settings.
1423 *
1424 * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz.
1425 */
1426static inline void CLOCK_SetXtal32Freq(uint32_t freq)
1427{
1428 g_xtal32Freq = freq;
1429}
1430/* @} */
1431
1432/*!
1433 * @name IRCs frequency
1434 * @{
1435 */
1436
1437/*!
1438 * @brief Set the Slow IRC frequency based on the trimmed value
1439 *
1440 * @param freq The Slow IRC frequency input clock frequency in Hz.
1441 */
1442void CLOCK_SetSlowIrcFreq(uint32_t freq);
1443
1444/*!
1445 * @brief Set the Fast IRC frequency based on the trimmed value
1446 *
1447 * @param freq The Fast IRC frequency input clock frequency in Hz.
1448 */
1449void CLOCK_SetFastIrcFreq(uint32_t freq);
1450/* @} */
1451
1452/*!
1453 * @name MCG auto-trim machine.
1454 * @{
1455 */
1456
1457/*!
1458 * @brief Auto trims the internal reference clock.
1459 *
1460 * This function trims the internal reference clock by using the external clock. If
1461 * successful, it returns the kStatus_Success and the frequency after
1462 * trimming is received in the parameter @p actualFreq. If an error occurs,
1463 * the error code is returned.
1464 *
1465 * @param extFreq External clock frequency, which should be a bus clock.
1466 * @param desireFreq Frequency to trim to.
1467 * @param actualFreq Actual frequency after trimming.
1468 * @param atms Trim fast or slow internal reference clock.
1469 * @retval kStatus_Success ATM success.
1470 * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM.
1471 * @retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency.
1472 * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source.
1473 * @retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming.
1474 */
1475status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms);
1476/* @} */
1477
1478/*! @name MCG mode functions. */
1479/*@{*/
1480
1481/*!
1482 * @brief Gets the current MCG mode.
1483 *
1484 * This function checks the MCG registers and determines the current MCG mode.
1485 *
1486 * @return Current MCG mode or error code; See @ref mcg_mode_t.
1487 */
1488mcg_mode_t CLOCK_GetMode(void);
1489
1490/*!
1491 * @brief Sets the MCG to FEI mode.
1492 *
1493 * This function sets the MCG to FEI mode. If setting to FEI mode fails
1494 * from the current mode, this function returns an error.
1495 *
1496 * @param dmx32 DMX32 in FEI mode.
1497 * @param drs The DCO range selection.
1498 * @param fllStableDelay Delay function to ensure that the FLL is stable. Passing
1499 * NULL does not cause a delay.
1500 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1501 * @retval kStatus_Success Switched to the target mode successfully.
1502 * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1503 * to a frequency above 32768 Hz.
1504 */
1505status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1506
1507/*!
1508 * @brief Sets the MCG to FEE mode.
1509 *
1510 * This function sets the MCG to FEE mode. If setting to FEE mode fails
1511 * from the current mode, this function returns an error.
1512 *
1513 * @param frdiv FLL reference clock divider setting, FRDIV.
1514 * @param dmx32 DMX32 in FEE mode.
1515 * @param drs The DCO range selection.
1516 * @param fllStableDelay Delay function to make sure FLL is stable. Passing
1517 * NULL does not cause a delay.
1518 *
1519 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1520 * @retval kStatus_Success Switched to the target mode successfully.
1521 */
1522status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1523
1524/*!
1525 * @brief Sets the MCG to FBI mode.
1526 *
1527 * This function sets the MCG to FBI mode. If setting to FBI mode fails
1528 * from the current mode, this function returns an error.
1529 *
1530 * @param dmx32 DMX32 in FBI mode.
1531 * @param drs The DCO range selection.
1532 * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL
1533 * is not used in FBI mode, this parameter can be NULL. Passing
1534 * NULL does not cause a delay.
1535 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1536 * @retval kStatus_Success Switched to the target mode successfully.
1537 * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1538 * to frequency above 32768 Hz.
1539 */
1540status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1541
1542/*!
1543 * @brief Sets the MCG to FBE mode.
1544 *
1545 * This function sets the MCG to FBE mode. If setting to FBE mode fails
1546 * from the current mode, this function returns an error.
1547 *
1548 * @param frdiv FLL reference clock divider setting, FRDIV.
1549 * @param dmx32 DMX32 in FBE mode.
1550 * @param drs The DCO range selection.
1551 * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL
1552 * is not used in FBE mode, this parameter can be NULL. Passing NULL
1553 * does not cause a delay.
1554 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1555 * @retval kStatus_Success Switched to the target mode successfully.
1556 */
1557status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1558
1559/*!
1560 * @brief Sets the MCG to BLPI mode.
1561 *
1562 * This function sets the MCG to BLPI mode. If setting to BLPI mode fails
1563 * from the current mode, this function returns an error.
1564 *
1565 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1566 * @retval kStatus_Success Switched to the target mode successfully.
1567 */
1568status_t CLOCK_SetBlpiMode(void);
1569
1570/*!
1571 * @brief Sets the MCG to BLPE mode.
1572 *
1573 * This function sets the MCG to BLPE mode. If setting to BLPE mode fails
1574 * from the current mode, this function returns an error.
1575 *
1576 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1577 * @retval kStatus_Success Switched to the target mode successfully.
1578 */
1579status_t CLOCK_SetBlpeMode(void);
1580
1581/*!
1582 * @brief Sets the MCG to PBE mode.
1583 *
1584 * This function sets the MCG to PBE mode. If setting to PBE mode fails
1585 * from the current mode, this function returns an error.
1586 *
1587 * @param pllcs The PLL selection, PLLCS.
1588 * @param config Pointer to the PLL configuration.
1589 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1590 * @retval kStatus_Success Switched to the target mode successfully.
1591 *
1592 * @note
1593 * 1. The parameter \c pllcs selects the PLL. For platforms with
1594 * only one PLL, the parameter pllcs is kept for interface compatibility.
1595 * 2. The parameter \c config is the PLL configuration structure. On some
1596 * platforms, it is possible to choose the external PLL directly, which renders the
1597 * configuration structure not necessary. In this case, pass in NULL.
1598 * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL);
1599 */
1600status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config);
1601
1602/*!
1603 * @brief Sets the MCG to PEE mode.
1604 *
1605 * This function sets the MCG to PEE mode.
1606 *
1607 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1608 * @retval kStatus_Success Switched to the target mode successfully.
1609 *
1610 * @note This function only changes the CLKS to use the PLL/FLL output. If the
1611 * PRDIV/VDIV are different than in the PBE mode, set them up
1612 * in PBE mode and wait. When the clock is stable, switch to PEE mode.
1613 */
1614status_t CLOCK_SetPeeMode(void);
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/*!
1635 * @brief Switches the MCG to FBI mode from internal modes.
1636 *
1637 * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly.
1638 * The MCGIRCLK is used as the system clock source and PLL is disabled. However,
1639 * FLL settings are not configured. This is a lite function with a small code size, which is useful
1640 * during the mode switch. For example, to switch from PEI mode to FEE mode:
1641 *
1642 * @code
1643 * CLOCK_InternalModeToFbiModeQuick();
1644 * CLOCK_SetFeeMode(...);
1645 * @endcode
1646 *
1647 * @retval kStatus_Success Switched successfully.
1648 * @retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function.
1649 */
1650status_t CLOCK_InternalModeToFbiModeQuick(void);
1651
1652/*!
1653 * @brief Sets the MCG to FEI mode during system boot up.
1654 *
1655 * This function sets the MCG to FEI mode from the reset mode. It can also be used to
1656 * set up MCG during system boot up.
1657 *
1658 * @param dmx32 DMX32 in FEI mode.
1659 * @param drs The DCO range selection.
1660 * @param fllStableDelay Delay function to ensure that the FLL is stable.
1661 *
1662 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1663 * @retval kStatus_Success Switched to the target mode successfully.
1664 * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1665 * to frequency above 32768 Hz.
1666 */
1667status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1668
1669/*!
1670 * @brief Sets the MCG to FEE mode during system bootup.
1671 *
1672 * This function sets MCG to FEE mode from the reset mode. It can also be used to
1673 * set up the MCG during system boot up.
1674 *
1675 * @param oscsel OSC clock select, OSCSEL.
1676 * @param frdiv FLL reference clock divider setting, FRDIV.
1677 * @param dmx32 DMX32 in FEE mode.
1678 * @param drs The DCO range selection.
1679 * @param fllStableDelay Delay function to ensure that the FLL is stable.
1680 *
1681 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1682 * @retval kStatus_Success Switched to the target mode successfully.
1683 */
1684status_t CLOCK_BootToFeeMode(
1685 mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1686
1687/*!
1688 * @brief Sets the MCG to BLPI mode during system boot up.
1689 *
1690 * This function sets the MCG to BLPI mode from the reset mode. It can also be used to
1691 * set up the MCG during system boot up.
1692 *
1693 * @param fcrdiv Fast IRC divider, FCRDIV.
1694 * @param ircs The internal reference clock to select, IRCS.
1695 * @param ircEnableMode The MCGIRCLK enable mode, OR'ed value of _mcg_irclk_enable_mode.
1696 *
1697 * @retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting.
1698 * @retval kStatus_Success Switched to the target mode successfully.
1699 */
1700status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode);
1701
1702/*!
1703 * @brief Sets the MCG to BLPE mode during system boot up.
1704 *
1705 * This function sets the MCG to BLPE mode from the reset mode. It can also be used to
1706 * set up the MCG during system boot up.
1707 *
1708 * @param oscsel OSC clock select, MCG_C7[OSCSEL].
1709 *
1710 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1711 * @retval kStatus_Success Switched to the target mode successfully.
1712 */
1713status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel);
1714
1715/*!
1716 * @brief Sets the MCG to PEE mode during system boot up.
1717 *
1718 * This function sets the MCG to PEE mode from reset mode. It can also be used to
1719 * set up the MCG during system boot up.
1720 *
1721 * @param oscsel OSC clock select, MCG_C7[OSCSEL].
1722 * @param pllcs The PLL selection, PLLCS.
1723 * @param config Pointer to the PLL configuration.
1724 *
1725 * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1726 * @retval kStatus_Success Switched to the target mode successfully.
1727 */
1728status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config);
1729
1730/*!
1731 * @brief Sets the MCG to a target mode.
1732 *
1733 * This function sets MCG to a target mode defined by the configuration
1734 * structure. If switching to the target mode fails, this function
1735 * chooses the correct path.
1736 *
1737 * @param config Pointer to the target MCG mode configuration structure.
1738 * @return Return kStatus_Success if switched successfully; Otherwise, it returns an error code _mcg_status.
1739 *
1740 * @note If the external clock is used in the target mode, ensure that it is
1741 * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this
1742 * function.
1743 */
1744status_t CLOCK_SetMcgConfig(mcg_config_t const *config);
1745
1746/*@}*/
1747
1748#if defined(__cplusplus)
1749}
1750#endif /* __cplusplus */
1751
1752/*! @} */
1753
1754#endif /* _FSL_CLOCK_H_ */