1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright (c) 2016 - 2017 , NXP
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without modification,
7  * are permitted provided that the following conditions are met:
8  *
9  * o Redistributions of source code must retain the above copyright notice, this list
10  *   of conditions and the following disclaimer.
11  *
12  * o Redistributions in binary form must reproduce the above copyright notice, this
13  *   list of conditions and the following disclaimer in the documentation and/or
14  *   other materials provided with the distribution.
15  *
16  * o Neither the name of copyright holder nor the names of its
17  *   contributors may be used to endorse or promote products derived from this
18  *   software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef _FSL_CLOCK_H_
33 #define _FSL_CLOCK_H_
34 
35 #include "fsl_common.h"
36 
37 /*! @addtogroup clock */
38 /*! @{ */
39 
40 /*! @file */
41 
42 /*******************************************************************************
43  * Configurations
44  ******************************************************************************/
45 
46 /*! @brief Configures whether to check a parameter in a function.
47  *
48  * Some MCG settings must be changed with conditions, for example:
49  *  1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when
50  *     MCGIRCLK is used as a system clock source.
51  *  2. MCG_C7[OSCSEL] should not be changed  when the external reference clock is used
52  *     as a system clock source. For example, in FBE/BLPE/PBE modes.
53  *  3. The users should only switch between the supported clock modes.
54  *
55  * MCG functions check the parameter and MCG status before setting, if not allowed
56  * to change, the functions return error. The parameter checking increases code size,
57  * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to
58  * disable parameter checking.
59  */
60 #ifndef MCG_CONFIG_CHECK_PARAM
61 #define MCG_CONFIG_CHECK_PARAM 0U
62 #endif
63 
64 /*! @brief Configure whether driver controls clock
65  *
66  * When set to 0, peripheral drivers will enable clock in initialize function
67  * and disable clock in de-initialize function. When set to 1, peripheral
68  * driver will not control the clock, application could contol the clock out of
69  * the driver.
70  *
71  * @note All drivers share this feature switcher. If it is set to 1, application
72  * should handle clock enable and disable for all drivers.
73  */
74 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
75 #define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0
76 #endif
77 
78 /*******************************************************************************
79  * Definitions
80  ******************************************************************************/
81 
82 /*! @name Driver version */
83 /*@{*/
84 /*! @brief CLOCK driver version 2.2.1. */
85 #define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 1))
86 /*@}*/
87 
88 /*! @brief External XTAL0 (OSC0) clock frequency.
89  *
90  * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the
91  * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example,
92  * if XTAL0 is 8 MHz:
93  * @code
94  * CLOCK_InitOsc0(...); // Set up the OSC0
95  * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver.
96  * @endcode
97  *
98  * This is important for the multicore platforms where only one core needs to set up the
99  * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq
100  * to get a valid clock frequency.
101  */
102 extern uint32_t g_xtal0Freq;
103 
104 /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency.
105  *
106  * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz. When the clock is set up, use the
107  * function CLOCK_SetXtal32Freq to set the value in the clock driver.
108  *
109  * This is important for the multicore platforms where only one core needs to set up
110  * the clock. All other cores need to call the CLOCK_SetXtal32Freq
111  * to get a valid clock frequency.
112  */
113 extern uint32_t g_xtal32Freq;
114 
115 #if (defined(OSC) && !(defined(OSC0)))
116 #define OSC0 OSC
117 #endif
118 
119 /*! @brief Clock ip name array for DMAMUX. */
120 #define DMAMUX_CLOCKS  \
121     {                  \
122         kCLOCK_Dmamux0 \
123     }
124 
125 /*! @brief Clock ip name array for RTC. */
126 #define RTC_CLOCKS  \
127     {               \
128         kCLOCK_Rtc0 \
129     }
130 
131 /*! @brief Clock ip name array for SAI. */
132 #define SAI_CLOCKS  \
133     {               \
134         kCLOCK_Sai0 \
135     }
136 
137 /*! @brief Clock ip name array for PORT. */
138 #define PORT_CLOCKS                                                          \
139     {                                                                        \
140         kCLOCK_PortA, kCLOCK_PortB, kCLOCK_PortC, kCLOCK_PortD, kCLOCK_PortE \
141     }
142 
143 /*! @brief Clock ip name array for EWM. */
144 #define EWM_CLOCKS  \
145     {               \
146         kCLOCK_Ewm0 \
147     }
148 
149 /*! @brief Clock ip name array for PIT. */
150 #define PIT_CLOCKS  \
151     {               \
152         kCLOCK_Pit0 \
153     }
154 
155 /*! @brief Clock ip name array for DSPI. */
156 #define DSPI_CLOCKS              \
157     {                            \
158         kCLOCK_Spi0, kCLOCK_Spi1 \
159     }
160 
161 /*! @brief Clock ip name array for LPTMR. */
162 #define LPTMR_CLOCKS  \
163     {                 \
164         kCLOCK_Lptmr0 \
165     }
166 
167 /*! @brief Clock ip name array for FTM. */
168 #define FTM_CLOCKS                            \
169     {                                         \
170         kCLOCK_Ftm0, kCLOCK_Ftm1, kCLOCK_Ftm2 \
171     }
172 
173 /*! @brief Clock ip name array for EDMA. */
174 #define EDMA_CLOCKS \
175     {               \
176         kCLOCK_Dma0 \
177     }
178 
179 /*! @brief Clock ip name array for ADC16. */
180 #define ADC16_CLOCKS \
181     {                \
182         kCLOCK_Adc0  \
183     }
184 
185 /*! @brief Clock ip name array for CMT. */
186 #define CMT_CLOCKS  \
187     {               \
188         kCLOCK_Cmt0 \
189     }
190 
191 /*! @brief Clock ip name array for UART. */
192 #define UART_CLOCKS                              \
193     {                                            \
194         kCLOCK_Uart0, kCLOCK_Uart1, kCLOCK_Uart2 \
195     }
196 
197 /*! @brief Clock ip name array for RNGA. */
198 #define RNGA_CLOCKS  \
199     {                \
200         kCLOCK_Rnga0 \
201     }
202 
203 /*! @brief Clock ip name array for CRC. */
204 #define CRC_CLOCKS  \
205     {               \
206         kCLOCK_Crc0 \
207     }
208 
209 /*! @brief Clock ip name array for I2C. */
210 #define I2C_CLOCKS               \
211     {                            \
212         kCLOCK_I2c0, kCLOCK_I2c1 \
213     }
214 
215 /*! @brief Clock ip name array for PDB. */
216 #define PDB_CLOCKS  \
217     {               \
218         kCLOCK_Pdb0 \
219     }
220 
221 /*! @brief Clock ip name array for CMP. */
222 #define CMP_CLOCKS               \
223     {                            \
224         kCLOCK_Cmp0, kCLOCK_Cmp1 \
225     }
226 
227 /*! @brief Clock ip name array for FTF. */
228 #define FTF_CLOCKS  \
229     {               \
230         kCLOCK_Ftf0 \
231     }
232 
233 /*!
234  * @brief LPO clock frequency.
235  */
236 #define LPO_CLK_FREQ 1000U
237 
238 /*! @brief Peripherals clock source definition. */
239 #define SYS_CLK kCLOCK_CoreSysClk
240 #define BUS_CLK kCLOCK_BusClk
241 #define FAST_CLK kCLOCK_FastPeriphClk
242 
243 #define I2C0_CLK_SRC BUS_CLK
244 #define I2C1_CLK_SRC BUS_CLK
245 #define DSPI0_CLK_SRC BUS_CLK
246 #define DSPI1_CLK_SRC BUS_CLK
247 #define UART0_CLK_SRC SYS_CLK
248 #define UART1_CLK_SRC SYS_CLK
249 #define UART2_CLK_SRC BUS_CLK
250 
251 /*! @brief Clock name used to get clock frequency. */
252 typedef enum _clock_name
253 {
254 
255     /* ----------------------------- System layer clock -------------------------------*/
256     kCLOCK_CoreSysClk,   /*!< Core/system clock                                         */
257     kCLOCK_PlatClk,      /*!< Platform clock                                            */
258     kCLOCK_BusClk,       /*!< Bus clock                                                 */
259     kCLOCK_FlashClk,     /*!< Flash clock                                               */
260     kCLOCK_PllFllSelClk, /*!< The clock after SIM[PLLFLLSEL].                           */
261 
262     /* ---------------------------------- OSC clock -----------------------------------*/
263     kCLOCK_Er32kClk,  /*!< External reference 32K clock (ERCLK32K)                   */
264     kCLOCK_Osc0ErClk, /*!< OSC0 external reference clock (OSC0ERCLK)                 */
265 
266     /* ----------------------------- MCG and MCG-Lite clock ---------------------------*/
267     kCLOCK_McgFixedFreqClk,   /*!< MCG fixed frequency clock (MCGFFCLK)                      */
268     kCLOCK_McgInternalRefClk, /*!< MCG internal reference clock (MCGIRCLK)                   */
269     kCLOCK_McgFllClk,         /*!< MCGFLLCLK                                                 */
270     kCLOCK_McgPll0Clk,        /*!< MCGPLL0CLK                                                */
271     kCLOCK_McgPll1Clk,        /*!< MCGPLL1CLK                                                */
272     kCLOCK_McgExtPllClk,      /*!< EXT_PLLCLK                                                */
273     kCLOCK_McgPeriphClk,      /*!< MCG peripheral clock (MCGPCLK)                            */
274 
275     /* --------------------------------- Other clock ----------------------------------*/
276     kCLOCK_LpoClk, /*!< LPO clock                                                 */
277 
278 } clock_name_t;
279 
280 /*! @brief USB clock source definition. */
281 typedef enum _clock_usb_src
282 {
283     kCLOCK_UsbSrcPll0 = SIM_SOPT2_USBSRC(1U) | SIM_SOPT2_PLLFLLSEL(1U), /*!< Use PLL0.      */
284     kCLOCK_UsbSrcExt = SIM_SOPT2_USBSRC(0U)                             /*!< Use USB_CLKIN. */
285 } clock_usb_src_t;
286 /*------------------------------------------------------------------------------
287 
288  clock_gate_t definition:
289 
290  31                              16                              0
291  -----------------------------------------------------------------
292  | SIM_SCGC register offset       |   control bit offset in SCGC |
293  -----------------------------------------------------------------
294 
295  For example, the SDHC clock gate is controlled by SIM_SCGC3[17], the
296  SIM_SCGC3 offset in SIM is 0x1030, then kCLOCK_GateSdhc0 is defined as
297 
298               kCLOCK_GateSdhc0 = (0x1030 << 16) | 17;
299 
300 ------------------------------------------------------------------------------*/
301 
302 #define CLK_GATE_REG_OFFSET_SHIFT 16U
303 #define CLK_GATE_REG_OFFSET_MASK 0xFFFF0000U
304 #define CLK_GATE_BIT_SHIFT_SHIFT 0U
305 #define CLK_GATE_BIT_SHIFT_MASK 0x0000FFFFU
306 
307 #define CLK_GATE_DEFINE(reg_offset, bit_shift)                                  \
308     ((((reg_offset) << CLK_GATE_REG_OFFSET_SHIFT) & CLK_GATE_REG_OFFSET_MASK) | \
309      (((bit_shift) << CLK_GATE_BIT_SHIFT_SHIFT) & CLK_GATE_BIT_SHIFT_MASK))
310 
311 #define CLK_GATE_ABSTRACT_REG_OFFSET(x) (((x)&CLK_GATE_REG_OFFSET_MASK) >> CLK_GATE_REG_OFFSET_SHIFT)
312 #define CLK_GATE_ABSTRACT_BITS_SHIFT(x) (((x)&CLK_GATE_BIT_SHIFT_MASK) >> CLK_GATE_BIT_SHIFT_SHIFT)
313 
314 /*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
315 typedef enum _clock_ip_name
316 {
317     kCLOCK_IpInvalid = 0U,
318 
319     kCLOCK_Ewm0 = CLK_GATE_DEFINE(0x1034U, 1U),
320     kCLOCK_Cmt0 = CLK_GATE_DEFINE(0x1034U, 2U),
321     kCLOCK_I2c0 = CLK_GATE_DEFINE(0x1034U, 6U),
322     kCLOCK_I2c1 = CLK_GATE_DEFINE(0x1034U, 7U),
323     kCLOCK_Uart0 = CLK_GATE_DEFINE(0x1034U, 10U),
324     kCLOCK_Uart1 = CLK_GATE_DEFINE(0x1034U, 11U),
325     kCLOCK_Uart2 = CLK_GATE_DEFINE(0x1034U, 12U),
326     kCLOCK_Usbfs0 = CLK_GATE_DEFINE(0x1034U, 18U),
327     kCLOCK_Cmp0 = CLK_GATE_DEFINE(0x1034U, 19U),
328     kCLOCK_Cmp1 = CLK_GATE_DEFINE(0x1034U, 19U),
329     kCLOCK_Vref0 = CLK_GATE_DEFINE(0x1034U, 20U),
330 
331     kCLOCK_Lptmr0 = CLK_GATE_DEFINE(0x1038U, 0U),
332     kCLOCK_PortA = CLK_GATE_DEFINE(0x1038U, 9U),
333     kCLOCK_PortB = CLK_GATE_DEFINE(0x1038U, 10U),
334     kCLOCK_PortC = CLK_GATE_DEFINE(0x1038U, 11U),
335     kCLOCK_PortD = CLK_GATE_DEFINE(0x1038U, 12U),
336     kCLOCK_PortE = CLK_GATE_DEFINE(0x1038U, 13U),
337 
338     kCLOCK_Ftf0 = CLK_GATE_DEFINE(0x103CU, 0U),
339     kCLOCK_Dmamux0 = CLK_GATE_DEFINE(0x103CU, 1U),
340     kCLOCK_Rnga0 = CLK_GATE_DEFINE(0x103CU, 9U),
341     kCLOCK_Spi0 = CLK_GATE_DEFINE(0x103CU, 12U),
342     kCLOCK_Spi1 = CLK_GATE_DEFINE(0x103CU, 13U),
343     kCLOCK_Sai0 = CLK_GATE_DEFINE(0x103CU, 15U),
344     kCLOCK_Crc0 = CLK_GATE_DEFINE(0x103CU, 18U),
345     kCLOCK_Usbdcd0 = CLK_GATE_DEFINE(0x103CU, 21U),
346     kCLOCK_Pdb0 = CLK_GATE_DEFINE(0x103CU, 22U),
347     kCLOCK_Pit0 = CLK_GATE_DEFINE(0x103CU, 23U),
348     kCLOCK_Ftm0 = CLK_GATE_DEFINE(0x103CU, 24U),
349     kCLOCK_Ftm1 = CLK_GATE_DEFINE(0x103CU, 25U),
350     kCLOCK_Ftm2 = CLK_GATE_DEFINE(0x103CU, 26U),
351     kCLOCK_Adc0 = CLK_GATE_DEFINE(0x103CU, 27U),
352     kCLOCK_Rtc0 = CLK_GATE_DEFINE(0x103CU, 29U),
353     kCLOCK_Dac0 = CLK_GATE_DEFINE(0x103CU, 31U),
354 
355     kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U),
356 } clock_ip_name_t;
357 
358 /*!@brief SIM configuration structure for clock setting. */
359 typedef struct _sim_clock_config
360 {
361     uint8_t pllFllSel; /*!< PLL/FLL/IRC48M selection.    */
362     uint8_t er32kSrc;  /*!< ERCLK32K source selection.   */
363     uint32_t clkdiv1;  /*!< SIM_CLKDIV1.                 */
364 } sim_clock_config_t;
365 
366 /*! @brief OSC work mode. */
367 typedef enum _osc_mode
368 {
369     kOSC_ModeExt = 0U, /*!< Use an external clock.   */
370 #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK)))
371     kOSC_ModeOscLowPower = MCG_C2_EREFS_MASK, /*!< Oscillator low power. */
372 #else
373     kOSC_ModeOscLowPower = MCG_C2_EREFS0_MASK, /*!< Oscillator low power. */
374 #endif
375     kOSC_ModeOscHighGain = 0U
376 #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK)))
377                            |
378                            MCG_C2_EREFS_MASK
379 #else
380                            |
381                            MCG_C2_EREFS0_MASK
382 #endif
383 #if (defined(MCG_C2_HGO_MASK) && !(defined(MCG_C2_HGO0_MASK)))
384                            |
385                            MCG_C2_HGO_MASK, /*!< Oscillator high gain. */
386 #else
387                            |
388                            MCG_C2_HGO0_MASK, /*!< Oscillator high gain. */
389 #endif
390 } osc_mode_t;
391 
392 /*! @brief Oscillator capacitor load setting.*/
393 enum _osc_cap_load
394 {
395     kOSC_Cap2P = OSC_CR_SC2P_MASK,  /*!< 2  pF capacitor load */
396     kOSC_Cap4P = OSC_CR_SC4P_MASK,  /*!< 4  pF capacitor load */
397     kOSC_Cap8P = OSC_CR_SC8P_MASK,  /*!< 8  pF capacitor load */
398     kOSC_Cap16P = OSC_CR_SC16P_MASK /*!< 16 pF capacitor load */
399 };
400 
401 /*! @brief OSCERCLK enable mode. */
402 enum _oscer_enable_mode
403 {
404     kOSC_ErClkEnable = OSC_CR_ERCLKEN_MASK,       /*!< Enable.              */
405     kOSC_ErClkEnableInStop = OSC_CR_EREFSTEN_MASK /*!< Enable in stop mode. */
406 };
407 
408 /*! @brief OSC configuration for OSCERCLK. */
409 typedef struct _oscer_config
410 {
411     uint8_t enableMode; /*!< OSCERCLK enable mode. OR'ed value of @ref _oscer_enable_mode. */
412 
413 } oscer_config_t;
414 
415 /*!
416  * @brief OSC Initialization Configuration Structure
417  *
418  * Defines the configuration data structure to initialize the OSC.
419  * When porting to a new board, set the following members
420  * according to the board setting:
421  * 1. freq: The external frequency.
422  * 2. workMode: The OSC module mode.
423  */
424 typedef struct _osc_config
425 {
426     uint32_t freq;              /*!< External clock frequency.    */
427     uint8_t capLoad;            /*!< Capacitor load setting.      */
428     osc_mode_t workMode;        /*!< OSC work mode setting.       */
429     oscer_config_t oscerConfig; /*!< Configuration for OSCERCLK.  */
430 } osc_config_t;
431 
432 /*! @brief MCG FLL reference clock source select. */
433 typedef enum _mcg_fll_src
434 {
435     kMCG_FllSrcExternal, /*!< External reference clock is selected          */
436     kMCG_FllSrcInternal  /*!< The slow internal reference clock is selected */
437 } mcg_fll_src_t;
438 
439 /*! @brief MCG internal reference clock select */
440 typedef enum _mcg_irc_mode
441 {
442     kMCG_IrcSlow, /*!< Slow internal reference clock selected */
443     kMCG_IrcFast  /*!< Fast internal reference clock selected */
444 } mcg_irc_mode_t;
445 
446 /*! @brief MCG DCO Maximum Frequency with 32.768 kHz Reference */
447 typedef enum _mcg_dmx32
448 {
449     kMCG_Dmx32Default, /*!< DCO has a default range of 25% */
450     kMCG_Dmx32Fine     /*!< DCO is fine-tuned for maximum frequency with 32.768 kHz reference */
451 } mcg_dmx32_t;
452 
453 /*! @brief MCG DCO range select */
454 typedef enum _mcg_drs
455 {
456     kMCG_DrsLow,     /*!< Low frequency range       */
457     kMCG_DrsMid,     /*!< Mid frequency range       */
458     kMCG_DrsMidHigh, /*!< Mid-High frequency range  */
459     kMCG_DrsHigh     /*!< High frequency range      */
460 } mcg_drs_t;
461 
462 /*! @brief MCG PLL reference clock select */
463 typedef enum _mcg_pll_ref_src
464 {
465     kMCG_PllRefOsc0, /*!< Selects OSC0 as PLL reference clock                 */
466     kMCG_PllRefOsc1  /*!< Selects OSC1 as PLL reference clock                 */
467 } mcg_pll_ref_src_t;
468 
469 /*! @brief MCGOUT clock source. */
470 typedef enum _mcg_clkout_src
471 {
472     kMCG_ClkOutSrcOut,      /*!< Output of the FLL is selected (reset default)  */
473     kMCG_ClkOutSrcInternal, /*!< Internal reference clock is selected           */
474     kMCG_ClkOutSrcExternal, /*!< External reference clock is selected           */
475 } mcg_clkout_src_t;
476 
477 /*! @brief MCG Automatic Trim Machine Select */
478 typedef enum _mcg_atm_select
479 {
480     kMCG_AtmSel32k, /*!< 32 kHz Internal Reference Clock selected  */
481     kMCG_AtmSel4m   /*!< 4 MHz Internal Reference Clock selected   */
482 } mcg_atm_select_t;
483 
484 /*! @brief MCG OSC Clock Select */
485 typedef enum _mcg_oscsel
486 {
487     kMCG_OscselOsc, /*!< Selects System Oscillator (OSCCLK) */
488     kMCG_OscselRtc, /*!< Selects 32 kHz RTC Oscillator      */
489 } mcg_oscsel_t;
490 
491 /*! @brief MCG PLLCS select */
492 typedef enum _mcg_pll_clk_select
493 {
494     kMCG_PllClkSelPll0, /*!< PLL0 output clock is selected  */
495     kMCG_PllClkSelPll1  /* PLL1 output clock is selected    */
496 } mcg_pll_clk_select_t;
497 
498 /*! @brief MCG clock monitor mode. */
499 typedef enum _mcg_monitor_mode
500 {
501     kMCG_MonitorNone, /*!< Clock monitor is disabled.         */
502     kMCG_MonitorInt,  /*!< Trigger interrupt when clock lost. */
503     kMCG_MonitorReset /*!< System reset when clock lost.      */
504 } mcg_monitor_mode_t;
505 
506 /*! @brief MCG status. */
507 enum _mcg_status
508 {
509     kStatus_MCG_ModeUnreachable = MAKE_STATUS(kStatusGroup_MCG, 0),       /*!< Can't switch to target mode. */
510     kStatus_MCG_ModeInvalid = MAKE_STATUS(kStatusGroup_MCG, 1),           /*!< Current mode invalid for the specific
511                                                                                function. */
512     kStatus_MCG_AtmBusClockInvalid = MAKE_STATUS(kStatusGroup_MCG, 2),    /*!< Invalid bus clock for ATM. */
513     kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */
514     kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4),            /*!< IRC is used when using ATM. */
515     kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5),       /*!< Hardware fail occurs during ATM. */
516     kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6)             /*!< Can't change the clock source because
517                                                                                it is in use. */
518 };
519 
520 /*! @brief MCG status flags. */
521 enum _mcg_status_flags_t
522 {
523     kMCG_Osc0LostFlag = (1U << 0U),   /*!< OSC0 lost.         */
524     kMCG_Osc0InitFlag = (1U << 1U),   /*!< OSC0 crystal initialized. */
525     kMCG_RtcOscLostFlag = (1U << 4U), /*!< RTC OSC lost.      */
526     kMCG_Pll0LostFlag = (1U << 5U),   /*!< PLL0 lost.         */
527     kMCG_Pll0LockFlag = (1U << 6U),   /*!< PLL0 locked.       */
528 };
529 
530 /*! @brief MCG internal reference clock (MCGIRCLK) enable mode definition. */
531 enum _mcg_irclk_enable_mode
532 {
533     kMCG_IrclkEnable = MCG_C1_IRCLKEN_MASK,       /*!< MCGIRCLK enable.              */
534     kMCG_IrclkEnableInStop = MCG_C1_IREFSTEN_MASK /*!< MCGIRCLK enable in stop mode. */
535 };
536 
537 /*! @brief MCG PLL clock enable mode definition. */
538 enum _mcg_pll_enable_mode
539 {
540     kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable independent of the
541                                                            MCG clock mode. Generally, the PLL
542                                                            is disabled in FLL modes
543                                                            (FEI/FBI/FEE/FBE). Setting the PLL clock
544                                                            enable independent, enables the
545                                                            PLL in the FLL modes.          */
546     kMCG_PllEnableInStop = MCG_C5_PLLSTEN0_MASK        /*!< MCGPLLCLK enable in STOP mode. */
547 };
548 
549 /*! @brief MCG mode definitions */
550 typedef enum _mcg_mode
551 {
552     kMCG_ModeFEI = 0U, /*!< FEI   - FLL Engaged Internal         */
553     kMCG_ModeFBI,      /*!< FBI   - FLL Bypassed Internal        */
554     kMCG_ModeBLPI,     /*!< BLPI  - Bypassed Low Power Internal  */
555     kMCG_ModeFEE,      /*!< FEE   - FLL Engaged External         */
556     kMCG_ModeFBE,      /*!< FBE   - FLL Bypassed External        */
557     kMCG_ModeBLPE,     /*!< BLPE  - Bypassed Low Power External  */
558     kMCG_ModePBE,      /*!< PBE   - PLL Bypassed External        */
559     kMCG_ModePEE,      /*!< PEE   - PLL Engaged External         */
560     kMCG_ModeError     /*!< Unknown mode                         */
561 } mcg_mode_t;
562 
563 /*! @brief MCG PLL configuration. */
564 typedef struct _mcg_pll_config
565 {
566     uint8_t enableMode; /*!< Enable mode. OR'ed value of @ref _mcg_pll_enable_mode. */
567     uint8_t prdiv;      /*!< Reference divider PRDIV.    */
568     uint8_t vdiv;       /*!< VCO divider VDIV.           */
569 } mcg_pll_config_t;
570 
571 /*! @brief MCG mode change configuration structure
572  *
573  * When porting to a new board, set the following members
574  * according to the board setting:
575  * 1. frdiv: If the FLL uses the external reference clock, set this
576  *    value to ensure that the external reference clock divided by frdiv is
577  *    in the 31.25 kHz to 39.0625 kHz range.
578  * 2. The PLL reference clock divider PRDIV: PLL reference clock frequency after
579  *    PRDIV should be in the FSL_FEATURE_MCG_PLL_REF_MIN to
580  *    FSL_FEATURE_MCG_PLL_REF_MAX range.
581  */
582 typedef struct _mcg_config
583 {
584     mcg_mode_t mcgMode; /*!< MCG mode.                   */
585 
586     /* ----------------------- MCGIRCCLK settings ------------------------ */
587     uint8_t irclkEnableMode; /*!< MCGIRCLK enable mode.       */
588     mcg_irc_mode_t ircs;     /*!< Source, MCG_C2[IRCS].       */
589     uint8_t fcrdiv;          /*!< Divider, MCG_SC[FCRDIV].    */
590 
591     /* ------------------------ MCG FLL settings ------------------------- */
592     uint8_t frdiv;       /*!< Divider MCG_C1[FRDIV].      */
593     mcg_drs_t drs;       /*!< DCO range MCG_C4[DRST_DRS]. */
594     mcg_dmx32_t dmx32;   /*!< MCG_C4[DMX32].              */
595     mcg_oscsel_t oscsel; /*!< OSC select MCG_C7[OSCSEL].  */
596 
597     /* ------------------------ MCG PLL settings ------------------------- */
598     mcg_pll_config_t pll0Config; /*!< MCGPLL0CLK configuration.   */
599 
600 } mcg_config_t;
601 
602 /*******************************************************************************
603  * API
604  ******************************************************************************/
605 
606 #if defined(__cplusplus)
607 extern "C" {
608 #endif /* __cplusplus */
609 
610 /*!
611  * @brief Enable the clock for specific IP.
612  *
613  * @param name  Which clock to enable, see \ref clock_ip_name_t.
614  */
CLOCK_EnableClock(clock_ip_name_t name)615 static inline void CLOCK_EnableClock(clock_ip_name_t name)
616 {
617     uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
618     (*(volatile uint32_t *)regAddr) |= (1U << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
619 }
620 
621 /*!
622  * @brief Disable the clock for specific IP.
623  *
624  * @param name  Which clock to disable, see \ref clock_ip_name_t.
625  */
CLOCK_DisableClock(clock_ip_name_t name)626 static inline void CLOCK_DisableClock(clock_ip_name_t name)
627 {
628     uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
629     (*(volatile uint32_t *)regAddr) &= ~(1U << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
630 }
631 
632 /*!
633  * @brief Set ERCLK32K source.
634  *
635  * @param src The value to set ERCLK32K clock source.
636  */
CLOCK_SetEr32kClock(uint32_t src)637 static inline void CLOCK_SetEr32kClock(uint32_t src)
638 {
639     SIM->SOPT1 = ((SIM->SOPT1 & ~SIM_SOPT1_OSC32KSEL_MASK) | SIM_SOPT1_OSC32KSEL(src));
640 }
641 
642 /*!
643  * @brief Set debug trace clock source.
644  *
645  * @param src The value to set debug trace clock source.
646  */
CLOCK_SetTraceClock(uint32_t src)647 static inline void CLOCK_SetTraceClock(uint32_t src)
648 {
649     SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_TRACECLKSEL_MASK) | SIM_SOPT2_TRACECLKSEL(src));
650 }
651 
652 /*!
653  * @brief Set PLLFLLSEL clock source.
654  *
655  * @param src The value to set PLLFLLSEL clock source.
656  */
CLOCK_SetPllFllSelClock(uint32_t src)657 static inline void CLOCK_SetPllFllSelClock(uint32_t src)
658 {
659     SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_PLLFLLSEL_MASK) | SIM_SOPT2_PLLFLLSEL(src));
660 }
661 
662 /*!
663  * @brief Set CLKOUT source.
664  *
665  * @param src The value to set CLKOUT source.
666  */
CLOCK_SetClkOutClock(uint32_t src)667 static inline void CLOCK_SetClkOutClock(uint32_t src)
668 {
669     SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_CLKOUTSEL_MASK) | SIM_SOPT2_CLKOUTSEL(src));
670 }
671 
672 /*!
673  * @brief Set RTC_CLKOUT source.
674  *
675  * @param src The value to set RTC_CLKOUT source.
676  */
CLOCK_SetRtcClkOutClock(uint32_t src)677 static inline void CLOCK_SetRtcClkOutClock(uint32_t src)
678 {
679     SIM->SOPT2 = ((SIM->SOPT2 & ~SIM_SOPT2_RTCCLKOUTSEL_MASK) | SIM_SOPT2_RTCCLKOUTSEL(src));
680 }
681 
682 /*! @brief Enable USB FS clock.
683  *
684  * @param src  USB FS clock source.
685  * @param freq The frequency specified by src.
686  * @retval true The clock is set successfully.
687  * @retval false The clock source is invalid to get proper USB FS clock.
688  */
689 bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq);
690 
691 /*! @brief Disable USB FS clock.
692  *
693  * Disable USB FS clock.
694  */
CLOCK_DisableUsbfs0Clock(void)695 static inline void CLOCK_DisableUsbfs0Clock(void)
696 {
697     CLOCK_DisableClock(kCLOCK_Usbfs0);
698 }
699 
700 /*!
701  * @brief System clock divider
702  *
703  * Set the SIM_CLKDIV1[OUTDIV1], SIM_CLKDIV1[OUTDIV2], SIM_CLKDIV1[OUTDIV4].
704  *
705  * @param outdiv1 Clock 1 output divider value.
706  *
707  * @param outdiv2 Clock 2 output divider value.
708  *
709  * @param outdiv4 Clock 4 output divider value.
710  */
CLOCK_SetOutDiv(uint32_t outdiv1,uint32_t outdiv2,uint32_t outdiv4)711 static inline void CLOCK_SetOutDiv(uint32_t outdiv1, uint32_t outdiv2, uint32_t outdiv4)
712 {
713     SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(outdiv1) | SIM_CLKDIV1_OUTDIV2(outdiv2) | SIM_CLKDIV1_OUTDIV4(outdiv4);
714 }
715 
716 /*!
717  * @brief Gets the clock frequency for a specific clock name.
718  *
719  * This function checks the current clock configurations and then calculates
720  * the clock frequency for a specific clock name defined in clock_name_t.
721  * The MCG must be properly configured before using this function.
722  *
723  * @param clockName Clock names defined in clock_name_t
724  * @return Clock frequency value in Hertz
725  */
726 uint32_t CLOCK_GetFreq(clock_name_t clockName);
727 
728 /*!
729  * @brief Get the core clock or system clock frequency.
730  *
731  * @return Clock frequency in Hz.
732  */
733 uint32_t CLOCK_GetCoreSysClkFreq(void);
734 
735 /*!
736  * @brief Get the platform clock frequency.
737  *
738  * @return Clock frequency in Hz.
739  */
740 uint32_t CLOCK_GetPlatClkFreq(void);
741 
742 /*!
743  * @brief Get the bus clock frequency.
744  *
745  * @return Clock frequency in Hz.
746  */
747 uint32_t CLOCK_GetBusClkFreq(void);
748 
749 /*!
750  * @brief Get the flash clock frequency.
751  *
752  * @return Clock frequency in Hz.
753  */
754 uint32_t CLOCK_GetFlashClkFreq(void);
755 
756 /*!
757  * @brief Get the output clock frequency selected by SIM[PLLFLLSEL].
758  *
759  * @return Clock frequency in Hz.
760  */
761 uint32_t CLOCK_GetPllFllSelClkFreq(void);
762 
763 /*!
764  * @brief Get the external reference 32K clock frequency (ERCLK32K).
765  *
766  * @return Clock frequency in Hz.
767  */
768 uint32_t CLOCK_GetEr32kClkFreq(void);
769 
770 /*!
771  * @brief Get the OSC0 external reference clock frequency (OSC0ERCLK).
772  *
773  * @return Clock frequency in Hz.
774  */
775 uint32_t CLOCK_GetOsc0ErClkFreq(void);
776 
777 /*!
778  * @brief Set the clock configure in SIM module.
779  *
780  * This function sets system layer clock settings in SIM module.
781  *
782  * @param config Pointer to the configure structure.
783  */
784 void CLOCK_SetSimConfig(sim_clock_config_t const *config);
785 
786 /*!
787  * @brief Set the system clock dividers in SIM to safe value.
788  *
789  * The system level clocks (core clock, bus clock, flexbus clock and flash clock)
790  * must be in allowed ranges. During MCG clock mode switch, the MCG output clock
791  * changes then the system level clocks may be out of range. This function could
792  * be used before MCG mode change, to make sure system level clocks are in allowed
793  * range.
794  *
795  * @param config Pointer to the configure structure.
796  */
CLOCK_SetSimSafeDivs(void)797 static inline void CLOCK_SetSimSafeDivs(void)
798 {
799     SIM->CLKDIV1 = 0x00010000U;
800 }
801 
802 /*! @name MCG frequency functions. */
803 /*@{*/
804 
805 /*!
806  * @brief Gets the MCG output clock (MCGOUTCLK) frequency.
807  *
808  * This function gets the MCG output clock frequency in Hz based on the current MCG
809  * register value.
810  *
811  * @return The frequency of MCGOUTCLK.
812  */
813 uint32_t CLOCK_GetOutClkFreq(void);
814 
815 /*!
816  * @brief Gets the MCG FLL clock (MCGFLLCLK) frequency.
817  *
818  * This function gets the MCG FLL clock frequency in Hz based on the current MCG
819  * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and
820  * disabled in low power state in other modes.
821  *
822  * @return The frequency of MCGFLLCLK.
823  */
824 uint32_t CLOCK_GetFllFreq(void);
825 
826 /*!
827  * @brief Gets the MCG internal reference clock (MCGIRCLK) frequency.
828  *
829  * This function gets the MCG internal reference clock frequency in Hz based
830  * on the current MCG register value.
831  *
832  * @return The frequency of MCGIRCLK.
833  */
834 uint32_t CLOCK_GetInternalRefClkFreq(void);
835 
836 /*!
837  * @brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency.
838  *
839  * This function gets the MCG fixed frequency clock frequency in Hz based
840  * on the current MCG register value.
841  *
842  * @return The frequency of MCGFFCLK.
843  */
844 uint32_t CLOCK_GetFixedFreqClkFreq(void);
845 
846 /*!
847  * @brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency.
848  *
849  * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG
850  * register value.
851  *
852  * @return The frequency of MCGPLL0CLK.
853  */
854 uint32_t CLOCK_GetPll0Freq(void);
855 
856 /*@}*/
857 
858 /*! @name MCG clock configuration. */
859 /*@{*/
860 
861 /*!
862  * @brief Enables or disables the MCG low power.
863  *
864  * Enabling the MCG low power disables the PLL and FLL in bypass modes. In other words,
865  * in FBE and PBE modes, enabling low power sets the MCG to BLPE mode. In FBI and
866  * PBI modes, enabling low power sets the MCG to BLPI mode.
867  * When disabling the MCG low power, the PLL or FLL are enabled based on MCG settings.
868  *
869  * @param enable True to enable MCG low power, false to disable MCG low power.
870  */
CLOCK_SetLowPowerEnable(bool enable)871 static inline void CLOCK_SetLowPowerEnable(bool enable)
872 {
873     if (enable)
874     {
875         MCG->C2 |= MCG_C2_LP_MASK;
876     }
877     else
878     {
879         MCG->C2 &= ~MCG_C2_LP_MASK;
880     }
881 }
882 
883 /*!
884  * @brief Configures the Internal Reference clock (MCGIRCLK).
885  *
886  * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC
887  * source. If the fast IRC is used, this function sets the fast IRC divider.
888  * This function also sets whether the \c MCGIRCLK is enabled in stop mode.
889  * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result,
890  * using the function in these modes it is not allowed.
891  *
892  * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode.
893  * @param ircs       MCGIRCLK clock source, choose fast or slow.
894  * @param fcrdiv     Fast IRC divider setting (\c FCRDIV).
895  * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source,
896  * the confuration should not be changed. Otherwise, a glitch occurs.
897  * @retval kStatus_Success MCGIRCLK configuration finished successfully.
898  */
899 status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv);
900 
901 /*!
902  * @brief Selects the MCG external reference clock.
903  *
904  * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL],
905  * and waits for the clock source to be stable. Because the external reference
906  * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes.
907  *
908  * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL].
909  * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source,
910  * the confuration should not be changed. Otherwise, a glitch occurs.
911  * @retval kStatus_Success External reference clock set successfully.
912  */
913 status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel);
914 
915 /*!
916  * @brief Set the FLL external reference clock divider value.
917  *
918  * Sets the FLL external reference clock divider value, the register MCG_C1[FRDIV].
919  *
920  * @param frdiv The FLL external reference clock divider value, MCG_C1[FRDIV].
921  */
CLOCK_SetFllExtRefDiv(uint8_t frdiv)922 static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv)
923 {
924     MCG->C1 = (MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv);
925 }
926 
927 /*!
928  * @brief Enables the PLL0 in FLL mode.
929  *
930  * This function sets us the PLL0 in FLL mode and reconfigures
931  * the PLL0. Ensure that the PLL reference
932  * clock is enabled before calling this function and that the PLL0 is not used as a clock source.
933  * The function CLOCK_CalcPllDiv gets the correct PLL
934  * divider values.
935  *
936  * @param config Pointer to the configuration structure.
937  */
938 void CLOCK_EnablePll0(mcg_pll_config_t const *config);
939 
940 /*!
941  * @brief Disables the PLL0 in FLL mode.
942  *
943  * This function disables the PLL0 in FLL mode. It should be used together with the
944  * @ref CLOCK_EnablePll0.
945  */
CLOCK_DisablePll0(void)946 static inline void CLOCK_DisablePll0(void)
947 {
948     MCG->C5 &= ~(MCG_C5_PLLCLKEN0_MASK | MCG_C5_PLLSTEN0_MASK);
949 }
950 
951 /*!
952  * @brief Calculates the PLL divider setting for a desired output frequency.
953  *
954  * This function calculates the correct reference clock divider (\c PRDIV) and
955  * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the
956  * closest frequency match with the corresponding \c PRDIV/VDIV
957  * returned from parameters. If a desired frequency is not valid, this function
958  * returns 0.
959  *
960  * @param refFreq    PLL reference clock frequency.
961  * @param desireFreq Desired PLL output frequency.
962  * @param prdiv      PRDIV value to generate desired PLL frequency.
963  * @param vdiv       VDIV value to generate desired PLL frequency.
964  * @return Closest frequency match that the PLL was able generate.
965  */
966 uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv);
967 
968 /*@}*/
969 
970 /*! @name MCG clock lock monitor functions. */
971 /*@{*/
972 
973 /*!
974  * @brief Sets the OSC0 clock monitor mode.
975  *
976  * This function sets the OSC0 clock monitor mode. See @ref mcg_monitor_mode_t for details.
977  *
978  * @param mode Monitor mode to set.
979  */
980 void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode);
981 
982 /*!
983  * @brief Sets the RTC OSC clock monitor mode.
984  *
985  * This function sets the RTC OSC clock monitor mode. See @ref mcg_monitor_mode_t for details.
986  *
987  * @param mode Monitor mode to set.
988  */
989 void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode);
990 
991 /*!
992  * @brief Sets the PLL0 clock monitor mode.
993  *
994  * This function sets the PLL0 clock monitor mode. See @ref mcg_monitor_mode_t for details.
995  *
996  * @param mode Monitor mode to set.
997  */
998 void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode);
999 
1000 /*!
1001  * @brief Gets the MCG status flags.
1002  *
1003  * This function gets the MCG clock status flags. All status flags are
1004  * returned as a logical OR of the enumeration @ref _mcg_status_flags_t. To
1005  * check a specific flag, compare the return value with the flag.
1006  *
1007  * Example:
1008  * @code
1009    // To check the clock lost lock status of OSC0 and PLL0.
1010    uint32_t mcgFlags;
1011 
1012    mcgFlags = CLOCK_GetStatusFlags();
1013 
1014    if (mcgFlags & kMCG_Osc0LostFlag)
1015    {
1016        // OSC0 clock lock lost. Do something.
1017    }
1018    if (mcgFlags & kMCG_Pll0LostFlag)
1019    {
1020        // PLL0 clock lock lost. Do something.
1021    }
1022    @endcode
1023  *
1024  * @return  Logical OR value of the @ref _mcg_status_flags_t.
1025  */
1026 uint32_t CLOCK_GetStatusFlags(void);
1027 
1028 /*!
1029  * @brief Clears the MCG status flags.
1030  *
1031  * This function clears the MCG clock lock lost status. The parameter is a logical
1032  * OR value of the flags to clear. See @ref _mcg_status_flags_t.
1033  *
1034  * Example:
1035  * @code
1036    // To clear the clock lost lock status flags of OSC0 and PLL0.
1037 
1038    CLOCK_ClearStatusFlags(kMCG_Osc0LostFlag | kMCG_Pll0LostFlag);
1039    @endcode
1040  *
1041  * @param mask The status flags to clear. This is a logical OR of members of the
1042  *             enumeration @ref _mcg_status_flags_t.
1043  */
1044 void CLOCK_ClearStatusFlags(uint32_t mask);
1045 
1046 /*@}*/
1047 
1048 /*!
1049  * @name OSC configuration
1050  * @{
1051  */
1052 
1053 /*!
1054  * @brief Configures the OSC external reference clock (OSCERCLK).
1055  *
1056  * This function configures the OSC external reference clock (OSCERCLK).
1057  * This is an example to enable the OSCERCLK in normal and stop modes and also set
1058  * the output divider to 1:
1059  *
1060    @code
1061    oscer_config_t config =
1062    {
1063        .enableMode = kOSC_ErClkEnable | kOSC_ErClkEnableInStop,
1064        .erclkDiv   = 1U,
1065    };
1066 
1067    OSC_SetExtRefClkConfig(OSC, &config);
1068    @endcode
1069  *
1070  * @param base   OSC peripheral address.
1071  * @param config Pointer to the configuration structure.
1072  */
OSC_SetExtRefClkConfig(OSC_Type * base,oscer_config_t const * config)1073 static inline void OSC_SetExtRefClkConfig(OSC_Type *base, oscer_config_t const *config)
1074 {
1075     uint8_t reg = base->CR;
1076 
1077     reg &= ~(OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK);
1078     reg |= config->enableMode;
1079 
1080     base->CR = reg;
1081 }
1082 
1083 /*!
1084  * @brief Sets the capacitor load configuration for the oscillator.
1085  *
1086  * This function sets the specified capacitors configuration for the oscillator.
1087  * This should be done in the early system level initialization function call
1088  * based on the system configuration.
1089  *
1090  * @param base   OSC peripheral address.
1091  * @param capLoad OR'ed value for the capacitor load option, see \ref _osc_cap_load.
1092  *
1093  * Example:
1094    @code
1095    // To enable only 2 pF and 8 pF capacitor load, please use like this.
1096    OSC_SetCapLoad(OSC, kOSC_Cap2P | kOSC_Cap8P);
1097    @endcode
1098  */
OSC_SetCapLoad(OSC_Type * base,uint8_t capLoad)1099 static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad)
1100 {
1101     uint8_t reg = base->CR;
1102 
1103     reg &= ~(OSC_CR_SC2P_MASK | OSC_CR_SC4P_MASK | OSC_CR_SC8P_MASK | OSC_CR_SC16P_MASK);
1104     reg |= capLoad;
1105 
1106     base->CR = reg;
1107 }
1108 
1109 /*!
1110  * @brief Initializes the OSC0.
1111  *
1112  * This function initializes the OSC0 according to the board configuration.
1113  *
1114  * @param  config Pointer to the OSC0 configuration structure.
1115  */
1116 void CLOCK_InitOsc0(osc_config_t const *config);
1117 
1118 /*!
1119  * @brief Deinitializes the OSC0.
1120  *
1121  * This function deinitializes the OSC0.
1122  */
1123 void CLOCK_DeinitOsc0(void);
1124 
1125 /* @} */
1126 
1127 /*!
1128  * @name External clock frequency
1129  * @{
1130  */
1131 
1132 /*!
1133  * @brief Sets the XTAL0 frequency based on board settings.
1134  *
1135  * @param freq The XTAL0/EXTAL0 input clock frequency in Hz.
1136  */
CLOCK_SetXtal0Freq(uint32_t freq)1137 static inline void CLOCK_SetXtal0Freq(uint32_t freq)
1138 {
1139     g_xtal0Freq = freq;
1140 }
1141 
1142 /*!
1143  * @brief Sets the XTAL32/RTC_CLKIN frequency based on board settings.
1144  *
1145  * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz.
1146  */
CLOCK_SetXtal32Freq(uint32_t freq)1147 static inline void CLOCK_SetXtal32Freq(uint32_t freq)
1148 {
1149     g_xtal32Freq = freq;
1150 }
1151 /* @} */
1152 
1153 /*!
1154  * @name MCG auto-trim machine.
1155  * @{
1156  */
1157 
1158 /*!
1159  * @brief Auto trims the internal reference clock.
1160  *
1161  * This function trims the internal reference clock by using the external clock. If
1162  * successful, it returns the kStatus_Success and the frequency after
1163  * trimming is received in the parameter @p actualFreq. If an error occurs,
1164  * the error code is returned.
1165  *
1166  * @param extFreq      External clock frequency, which should be a bus clock.
1167  * @param desireFreq   Frequency to trim to.
1168  * @param actualFreq   Actual frequency after trimming.
1169  * @param atms         Trim fast or slow internal reference clock.
1170  * @retval kStatus_Success ATM success.
1171  * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM.
1172  * @retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency.
1173  * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source.
1174  * @retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming.
1175  */
1176 status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms);
1177 /* @} */
1178 
1179 /*! @name MCG mode functions. */
1180 /*@{*/
1181 
1182 /*!
1183  * @brief Gets the current MCG mode.
1184  *
1185  * This function checks the MCG registers and determines the current MCG mode.
1186  *
1187  * @return Current MCG mode or error code; See @ref mcg_mode_t.
1188  */
1189 mcg_mode_t CLOCK_GetMode(void);
1190 
1191 /*!
1192  * @brief Sets the MCG to FEI mode.
1193  *
1194  * This function sets the MCG to FEI mode. If setting to FEI mode fails
1195  * from the current mode, this function returns an error.
1196  *
1197  * @param       dmx32  DMX32 in FEI mode.
1198  * @param       drs The DCO range selection.
1199  * @param       fllStableDelay Delay function to  ensure that the FLL is stable. Passing
1200  *              NULL does not cause a delay.
1201  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1202  * @retval kStatus_Success Switched to the target mode successfully.
1203  * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1204  * to a frequency above 32768 Hz.
1205  */
1206 status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1207 
1208 /*!
1209  * @brief Sets the MCG to FEE mode.
1210  *
1211  * This function sets the MCG to FEE mode. If setting to FEE mode fails
1212  * from the current mode, this function returns an error.
1213  *
1214  * @param   frdiv  FLL reference clock divider setting, FRDIV.
1215  * @param   dmx32  DMX32 in FEE mode.
1216  * @param   drs    The DCO range selection.
1217  * @param   fllStableDelay Delay function to make sure FLL is stable. Passing
1218  *          NULL does not cause a delay.
1219  *
1220  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1221  * @retval kStatus_Success Switched to the target mode successfully.
1222  */
1223 status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1224 
1225 /*!
1226  * @brief Sets the MCG to FBI mode.
1227  *
1228  * This function sets the MCG to FBI mode. If setting to FBI mode fails
1229  * from the current mode, this function returns an error.
1230  *
1231  * @param  dmx32  DMX32 in FBI mode.
1232  * @param  drs  The DCO range selection.
1233  * @param  fllStableDelay Delay function to make sure FLL is stable. If the FLL
1234  *         is not used in FBI mode, this parameter can be NULL. Passing
1235  *         NULL does not cause a delay.
1236  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1237  * @retval kStatus_Success Switched to the target mode successfully.
1238  * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1239  * to frequency above 32768 Hz.
1240  */
1241 status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1242 
1243 /*!
1244  * @brief Sets the MCG to FBE mode.
1245  *
1246  * This function sets the MCG to FBE mode. If setting to FBE mode fails
1247  * from the current mode, this function returns an error.
1248  *
1249  * @param   frdiv  FLL reference clock divider setting, FRDIV.
1250  * @param   dmx32  DMX32 in FBE mode.
1251  * @param   drs    The DCO range selection.
1252  * @param   fllStableDelay Delay function to make sure FLL is stable. If the FLL
1253  *          is not used in FBE mode, this parameter can be NULL. Passing NULL
1254  *          does not cause a delay.
1255  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1256  * @retval kStatus_Success Switched to the target mode successfully.
1257  */
1258 status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1259 
1260 /*!
1261  * @brief Sets the MCG to BLPI mode.
1262  *
1263  * This function sets the MCG to BLPI mode. If setting to BLPI mode fails
1264  * from the current mode, this function returns an error.
1265  *
1266  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1267  * @retval kStatus_Success Switched to the target mode successfully.
1268  */
1269 status_t CLOCK_SetBlpiMode(void);
1270 
1271 /*!
1272  * @brief Sets the MCG to BLPE mode.
1273  *
1274  * This function sets the MCG to BLPE mode. If setting to BLPE mode fails
1275  * from the current mode, this function returns an error.
1276  *
1277  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1278  * @retval kStatus_Success Switched to the target mode successfully.
1279  */
1280 status_t CLOCK_SetBlpeMode(void);
1281 
1282 /*!
1283  * @brief Sets the MCG to PBE mode.
1284  *
1285  * This function sets the MCG to PBE mode. If setting to PBE mode fails
1286  * from the current mode, this function returns an error.
1287  *
1288  * @param   pllcs  The PLL selection, PLLCS.
1289  * @param   config Pointer to the PLL configuration.
1290  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1291  * @retval kStatus_Success Switched to the target mode successfully.
1292  *
1293  * @note
1294  * 1. The parameter \c pllcs selects the PLL. For platforms with
1295  * only one PLL, the parameter pllcs is kept for interface compatibility.
1296  * 2. The parameter \c config is the PLL configuration structure. On some
1297  * platforms,  it is possible to choose the external PLL directly, which renders the
1298  * configuration structure not necessary. In this case, pass in NULL.
1299  * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL);
1300  */
1301 status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config);
1302 
1303 /*!
1304  * @brief Sets the MCG to PEE mode.
1305  *
1306  * This function sets the MCG to PEE mode.
1307  *
1308  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1309  * @retval kStatus_Success Switched to the target mode successfully.
1310  *
1311  * @note This function only changes the CLKS to use the PLL/FLL output. If the
1312  *       PRDIV/VDIV are different than in the PBE mode, set them up
1313  *       in PBE mode and wait. When the clock is stable, switch to PEE mode.
1314  */
1315 status_t CLOCK_SetPeeMode(void);
1316 
1317 /*!
1318  * @brief Switches the MCG to FBE mode from the external mode.
1319  *
1320  * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly.
1321  * The external clock is used as the system clock souce and PLL is disabled. However,
1322  * the FLL settings are not configured. This is a lite function with a small code size, which is useful
1323  * during the mode switch. For example, to switch from PEE mode to FEI mode:
1324  *
1325  * @code
1326  * CLOCK_ExternalModeToFbeModeQuick();
1327  * CLOCK_SetFeiMode(...);
1328  * @endcode
1329  *
1330  * @retval kStatus_Success Switched successfully.
1331  * @retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function.
1332  */
1333 status_t CLOCK_ExternalModeToFbeModeQuick(void);
1334 
1335 /*!
1336  * @brief Switches the MCG to FBI mode from internal modes.
1337  *
1338  * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly.
1339  * The MCGIRCLK is used as the system clock souce and PLL is disabled. However,
1340  * FLL settings are not configured. This is a lite function with a small code size, which is useful
1341  * during the mode switch. For example, to switch from PEI mode to FEE mode:
1342  *
1343  * @code
1344  * CLOCK_InternalModeToFbiModeQuick();
1345  * CLOCK_SetFeeMode(...);
1346  * @endcode
1347  *
1348  * @retval kStatus_Success Switched successfully.
1349  * @retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function.
1350  */
1351 status_t CLOCK_InternalModeToFbiModeQuick(void);
1352 
1353 /*!
1354  * @brief Sets the MCG to FEI mode during system boot up.
1355  *
1356  * This function sets the MCG to FEI mode from the reset mode. It can also be used to
1357  * set up MCG during system boot up.
1358  *
1359  * @param  dmx32  DMX32 in FEI mode.
1360  * @param  drs The DCO range selection.
1361  * @param  fllStableDelay Delay function to ensure that the FLL is stable.
1362  *
1363  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1364  * @retval kStatus_Success Switched to the target mode successfully.
1365  * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed
1366  * to frequency above 32768 Hz.
1367  */
1368 status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1369 
1370 /*!
1371  * @brief Sets the MCG to FEE mode during system bootup.
1372  *
1373  * This function sets MCG to FEE mode from the reset mode. It can also be used to
1374  * set up the MCG during system boot up.
1375  *
1376  * @param   oscsel OSC clock select, OSCSEL.
1377  * @param   frdiv  FLL reference clock divider setting, FRDIV.
1378  * @param   dmx32  DMX32 in FEE mode.
1379  * @param   drs    The DCO range selection.
1380  * @param   fllStableDelay Delay function to ensure that the FLL is stable.
1381  *
1382  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1383  * @retval kStatus_Success Switched to the target mode successfully.
1384  */
1385 status_t CLOCK_BootToFeeMode(
1386     mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void));
1387 
1388 /*!
1389  * @brief Sets the MCG to BLPI mode during system boot up.
1390  *
1391  * This function sets the MCG to BLPI mode from the reset mode. It can also be used to
1392  * set up the MCG during sytem boot up.
1393  *
1394  * @param  fcrdiv Fast IRC divider, FCRDIV.
1395  * @param  ircs   The internal reference clock to select, IRCS.
1396  * @param  ircEnableMode  The MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode.
1397  *
1398  * @retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting.
1399  * @retval kStatus_Success Switched to the target mode successfully.
1400  */
1401 status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode);
1402 
1403 /*!
1404  * @brief Sets the MCG to BLPE mode during sytem boot up.
1405  *
1406  * This function sets the MCG to BLPE mode from the reset mode. It can also be used to
1407  * set up the MCG during sytem boot up.
1408  *
1409  * @param  oscsel OSC clock select, MCG_C7[OSCSEL].
1410  *
1411  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1412  * @retval kStatus_Success Switched to the target mode successfully.
1413  */
1414 status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel);
1415 
1416 /*!
1417  * @brief Sets the MCG to PEE mode during system boot up.
1418  *
1419  * This function sets the MCG to PEE mode from reset mode. It can also be used to
1420  * set up the MCG during system boot up.
1421  *
1422  * @param   oscsel OSC clock select, MCG_C7[OSCSEL].
1423  * @param   pllcs  The PLL selection, PLLCS.
1424  * @param   config Pointer to the PLL configuration.
1425  *
1426  * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode.
1427  * @retval kStatus_Success Switched to the target mode successfully.
1428  */
1429 status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config);
1430 
1431 /*!
1432  * @brief Sets the MCG to a target mode.
1433  *
1434  * This function sets MCG to a target mode defined by the configuration
1435  * structure. If switching to the target mode fails, this function
1436  * chooses the correct path.
1437  *
1438  * @param  config Pointer to the target MCG mode configuration structure.
1439  * @return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status.
1440  *
1441  * @note If the external clock is used in the target mode, ensure that it is
1442  * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this
1443  * function.
1444  */
1445 status_t CLOCK_SetMcgConfig(mcg_config_t const *config);
1446 
1447 /*@}*/
1448 
1449 #if defined(__cplusplus)
1450 }
1451 #endif /* __cplusplus */
1452 
1453 /*! @} */
1454 
1455 #endif /* _FSL_CLOCK_H_ */
1456