1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2020, 2022 NXP
4  * All rights reserved.
5  *
6  *
7  * SPDX-License-Identifier: BSD-3-Clause
8  */
9 
10 #ifndef _FSL_CLOCK_H_
11 #define _FSL_CLOCK_H_
12 
13 #include "fsl_common.h"
14 
15 /*! @addtogroup clock */
16 /*! @{ */
17 
18 /*! @file */
19 
20 /*******************************************************************************
21  * Configurations
22  ******************************************************************************/
23 
24 /*! @brief Configures whether to check a parameter in a function.
25  *
26  * Some ICS settings must be changed with conditions, for example:
27  *  1. ICSIRCLK settings, such as the source, divider, and the trim value should not change when
28  *     ICSIRCLK is used as a system clock source.
29  *  2. ICS_C7[OSCSEL] should not be changed  when the external reference clock is used
30  *     as a system clock source. For example, in FBE/BELP/PBE modes.
31  *  3. The users should only switch between the supported clock modes.
32  *
33  * ICS functions check the parameter and ICS status before setting, if not allowed
34  * to change, the functions return error. The parameter checking increases code size,
35  * if code size is a critical requirement, change #ICS_CONFIG_CHECK_PARAM to 0 to
36  * disable parameter checking.
37  */
38 #ifndef ICS_CONFIG_CHECK_PARAM
39 #define ICS_CONFIG_CHECK_PARAM 0U
40 #endif
41 
42 /*! @brief Configure whether driver controls clock
43  *
44  * When set to 0, peripheral drivers will enable clock in initialize function
45  * and disable clock in de-initialize function. When set to 1, peripheral
46  * driver will not control the clock, application could control the clock out of
47  * the driver.
48  *
49  * @note All drivers share this feature switcher. If it is set to 1, application
50  * should handle clock enable and disable for all drivers.
51  */
52 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
53 #define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0
54 #endif
55 
56 /*******************************************************************************
57  * Definitions
58  ******************************************************************************/
59 
60 /*! @name Driver version */
61 /*@{*/
62 /*! @brief CLOCK driver version 2.2.3. */
63 #define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 3))
64 /*@}*/
65 
66 /* Definition for delay API in clock driver, users can redefine it to the real application. */
67 #ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY
68 #define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (40000000UL)
69 #endif
70 
71 /*! @brief External XTAL0 (OSC0) clock frequency.
72  *
73  * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the
74  * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example,
75  * if XTAL0 is 8 MHz:
76  * @code
77  * CLOCK_InitOsc0(...);
78  * CLOCK_SetXtal0Freq(80000000)
79  * @endcode
80  *
81  * This is important for the multicore platforms where only one core needs to set up the
82  * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq
83  * to get a valid clock frequency.
84  */
85 extern volatile uint32_t g_xtal0Freq;
86 
87 #if (defined(OSC) && !(defined(OSC0)))
88 #define OSC0 OSC
89 #endif
90 
91 /*! @brief Clock ip name array for UART. */
92 #define UART_CLOCKS                              \
93     {                                            \
94         kCLOCK_Uart0, kCLOCK_Uart1, kCLOCK_Uart2 \
95     }
96 
97 /*! @brief Clock ip name array for ADC16. */
98 #define ADC_CLOCKS  \
99     {               \
100         kCLOCK_Adc0 \
101     }
102 
103 /*! @brief Clock ip name array for IRQ. */
104 #define IRQ_CLOCKS  \
105     {               \
106         kCLOCK_Irq0 \
107     }
108 
109 /*! @brief Clock ip name array for KBI. */
110 #define KBI_CLOCKS               \
111     {                            \
112         kCLOCK_Kbi0, kCLOCK_Kbi1 \
113     }
114 
115 /*! @brief Clock ip name array for SPI. */
116 #define SPI_CLOCKS               \
117     {                            \
118         kCLOCK_Spi0, kCLOCK_Spi1 \
119     }
120 
121 /*! @brief Clock ip name array for I2C. */
122 #define I2C_CLOCKS  \
123     {               \
124         kCLOCK_I2c0 \
125     }
126 
127 /*! @brief Clock ip name array for FTM. */
128 #define FTM_CLOCKS                            \
129     {                                         \
130         kCLOCK_Ftm0, kCLOCK_Ftm1, kCLOCK_Ftm2 \
131     }
132 
133 /*! @brief Clock ip name array for CMP. */
134 #define ACMP_CLOCKS                \
135     {                              \
136         kCLOCK_Acmp0, kCLOCK_Acmp1 \
137     }
138 
139 /*! @brief Clock ip name array for CRC. */
140 #define CRC_CLOCKS   \
141     {                \
142         kCLOCK_Crc0, \
143     }
144 
145 /*! @brief Clock ip name array for PIT. */
146 #define PIT_CLOCKS   \
147     {                \
148         kCLOCK_Pit0, \
149     }
150 
151 /*! @brief Clock ip name array for RTC. */
152 #define RTC_CLOCKS   \
153     {                \
154         kCLOCK_Rtc0, \
155     }
156 
157 /*!
158  * @brief LPO clock frequency.
159  */
160 #define LPO_CLK_FREQ 1000U
161 
162 /*! @brief Clock name used to get clock frequency. */
163 typedef enum _clock_name
164 {
165 
166     /* ----------------------------- System layer clock -------------------------------*/
167     kCLOCK_CoreSysClk, /*!< Core/system clock                                         */
168     kCLOCK_PlatClk,    /*!< Platform clock                                            */
169     kCLOCK_BusClk,     /*!< Bus clock                                                 */
170     kCLOCK_FlashClk,   /*!< Flash clock                                               */
171 
172     /* ---------------------------------- OSC clock -----------------------------------*/
173     kCLOCK_Osc0ErClk, /*!< OSC0 external reference clock (OSC0ERCLK)                 */
174 
175     /* ----------------------------- ICS and ICS-Lite clock ---------------------------*/
176     kCLOCK_ICSFixedFreqClk,   /*!< ICS fixed frequency clock (ICSFFCLK)                      */
177     kCLOCK_ICSInternalRefClk, /*!< ICS internal reference clock (ICSIRCLK)                   */
178     kCLOCK_ICSFllClk,         /*!< ICSFLLCLK                                                 */
179     kCLOCK_ICSOutClk,         /*!< ICS Output clock                                          */
180 
181     /* --------------------------------- Other clock ----------------------------------*/
182     kCLOCK_LpoClk, /*!< LPO clock                                                 */
183 
184 } clock_name_t;
185 
186 /*------------------------------------------------------------------------------
187 
188  clock_gate_t definition:
189 
190  31                              16                              0
191  -----------------------------------------------------------------
192  | SIM_SCGC register offset       |   control bit offset in SCGC |
193  -----------------------------------------------------------------
194 
195  For example, the SDHC clock gate is controlled by SIM_SCGC3[17], the
196  SIM_SCGC3 offset in SIM is 0x1030, then kCLOCK_GateSdhc0 is defined as
197 
198               kCLOCK_GateSdhc0 = (0x1030 << 16) | 17;
199 
200 ------------------------------------------------------------------------------*/
201 
202 #define CLK_GATE_REG_OFFSET_SHIFT 16U
203 #define CLK_GATE_REG_OFFSET_MASK  0xFFFF0000U
204 #define CLK_GATE_BIT_SHIFT_SHIFT  0U
205 #define CLK_GATE_BIT_SHIFT_MASK   0x0000FFFFU
206 
207 #define CLK_GATE_DEFINE(reg_offset, bit_shift)                                  \
208     ((((reg_offset) << CLK_GATE_REG_OFFSET_SHIFT) & CLK_GATE_REG_OFFSET_MASK) | \
209      (((bit_shift) << CLK_GATE_BIT_SHIFT_SHIFT) & CLK_GATE_BIT_SHIFT_MASK))
210 
211 #define CLK_GATE_ABSTRACT_REG_OFFSET(x) (((x)&CLK_GATE_REG_OFFSET_MASK) >> CLK_GATE_REG_OFFSET_SHIFT)
212 #define CLK_GATE_ABSTRACT_BITS_SHIFT(x) (((x)&CLK_GATE_BIT_SHIFT_MASK) >> CLK_GATE_BIT_SHIFT_SHIFT)
213 
214 /*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
215 typedef enum _clock_ip_name
216 {
217     kCLOCK_IpInvalid = 0U,
218 
219     kCLOCK_I2c0 = CLK_GATE_DEFINE(0xCU, 17U),
220 
221     kCLOCK_Uart0 = CLK_GATE_DEFINE(0xCU, 20U),
222     kCLOCK_Uart1 = CLK_GATE_DEFINE(0xCU, 21U),
223     kCLOCK_Uart2 = CLK_GATE_DEFINE(0xCU, 22U),
224 
225     kCLOCK_Acmp0 = CLK_GATE_DEFINE(0xCU, 30U),
226     kCLOCK_Acmp1 = CLK_GATE_DEFINE(0xCU, 31U),
227 
228     kCLOCK_Spi0 = CLK_GATE_DEFINE(0xCU, 18U),
229     kCLOCK_Spi1 = CLK_GATE_DEFINE(0xCU, 19U),
230 
231     kCLOCK_Irq0 = CLK_GATE_DEFINE(0xCU, 27U),
232 
233     kCLOCK_Kbi0 = CLK_GATE_DEFINE(0xCU, 24U),
234     kCLOCK_Kbi1 = CLK_GATE_DEFINE(0xCU, 25U),
235 
236     kCLOCK_Adc0 = CLK_GATE_DEFINE(0xCU, 29U),
237 
238     kCLOCK_Crc0 = CLK_GATE_DEFINE(0xCU, 10U),
239 
240     kCLOCK_Ftm0 = CLK_GATE_DEFINE(0xCU, 5U),
241     kCLOCK_Ftm1 = CLK_GATE_DEFINE(0xCU, 6U),
242     kCLOCK_Ftm2 = CLK_GATE_DEFINE(0xCU, 7U),
243 
244     kCLOCK_Pit0 = CLK_GATE_DEFINE(0xCU, 1U),
245     kCLOCK_Rtc0 = CLK_GATE_DEFINE(0xCU, 0U),
246 } clock_ip_name_t;
247 
248 /*!@brief SIM configuration structure for clock setting. */
249 typedef struct _sim_clock_config
250 {
251     uint32_t busDiv;         /*!< SIM_BUSDIV. */
252     uint8_t busClkPrescaler; /*!< A option prescaler for bus clock */
253 } sim_clock_config_t;
254 
255 /*! @brief OSC work mode. */
256 enum _osc_work_mode
257 {
258     kOSC_ModeExt         = 0U,                                  /*!< OSC source from external clock. */
259     kOSC_ModeOscLowPower = OSC_CR_OSCOS_MASK,                   /*!< Oscillator low freq low power. */
260     kOSC_ModeOscHighGain = OSC_CR_HGO_MASK | OSC_CR_OSCOS_MASK, /*!< Oscillator low freq high gain. */
261 };
262 
263 /*! @brief OSC enable mode. */
264 enum _osc_enable_mode
265 {
266     kOSC_Enable       = OSC_CR_OSCEN_MASK,  /*!< Enable.              */
267     kOSC_EnableInStop = OSC_CR_OSCSTEN_MASK /*!< Enable in stop mode. */
268 };
269 
270 /*!
271  * @brief OSC Initialization Configuration Structure
272  *
273  * Defines the configuration data structure to initialize the OSC.
274  * When porting to a new board, set the following members
275  * according to the board setting:
276  * 1. freq: The external frequency.
277  * 2. workMode: The OSC module mode.
278  * 3. enableMode: The OSC enable mode.
279  */
280 typedef struct _osc_config
281 {
282     uint32_t freq;      /*!< External clock frequency.    */
283     uint8_t workMode;   /*!< OSC work mode setting.       */
284     uint8_t enableMode; /*!< Configuration for OSCERCLK.  */
285 } osc_config_t;
286 
287 /*! @brief ICS FLL reference clock source select. */
288 typedef enum _ics_fll_src
289 {
290     kICS_FllSrcExternal, /*!< External reference clock is selected          */
291     kICS_FllSrcInternal  /*!< The slow internal reference clock is selected */
292 } ics_fll_src_t;
293 
294 /*! @brief ICSOUT clock source. */
295 typedef enum _ics_clkout_src
296 {
297     kICS_ClkOutSrcFll,      /*!< Output of the FLL is selected (reset default)  */
298     kICS_ClkOutSrcInternal, /*!< Internal reference clock is selected, FLL is bypassed */
299     kICS_ClkOutSrcExternal, /*!< External reference clock is selected, FLL is bypassed */
300 } ics_clkout_src_t;
301 
302 /*! @brief ICS status.
303     @anchor _ics_status.
304  */
305 enum
306 {
307     kStatus_ICS_ModeUnreachable = MAKE_STATUS(kStatusGroup_ICS, 0), /*!< Can't switch to target mode. */
308     kStatus_ICS_SourceUsed      = MAKE_STATUS(kStatusGroup_ICS, 1)  /*!< Can't change the clock source because
309                                                                          it is in use. */
310 };
311 
312 /*! @brief ICS internal reference clock (ICSIRCLK) enable mode definition. */
313 enum _ics_irclk_enable_mode
314 {
315     kICS_IrclkDisable      = 0U,                  /*!< ICSIRCLK disable. */
316     kICS_IrclkEnable       = ICS_C1_IRCLKEN_MASK, /*!< ICSIRCLK enable.              */
317     kICS_IrclkEnableInStop = ICS_C1_IREFSTEN_MASK /*!< ICSIRCLK enable in stop mode. */
318 };
319 
320 /*! @brief ICS mode definitions */
321 typedef enum _ics_mode
322 {
323     kICS_ModeFEI = 0U, /*!< FEI   - FLL Engaged Internal         */
324     kICS_ModeFBI,      /*!< FBI   - FLL Bypassed Internal        */
325     kICS_ModeBILP,     /*!< BILP  - Bypassed Low Power Internal  */
326     kICS_ModeFEE,      /*!< FEE   - FLL Engaged External         */
327     kICS_ModeFBE,      /*!< FBE   - FLL Bypassed External        */
328     kICS_ModeBELP,     /*!< BELP  - Bypassed Low Power External  */
329     kICS_ModeError     /*!< Unknown mode                         */
330 } ics_mode_t;
331 
332 /*! @brief ICS configuration structure
333  *
334  * When porting to a new board, set the following members
335  * according to the board setting:
336  * 1. icsMode:  ICS mode
337  * 2. irClkEnableMode: ICSIRCLK enable mode
338  * 3. rDiv: If the FLL uses the external reference clock, set this
339  *    value to ensure that the external reference clock divided by rDiv is
340  *    in the 31.25 kHz to 39.0625 kHz range.
341  * 4. bDiv, this divider determine the ISCOUT clock
342  */
343 typedef struct _ics_config
344 {
345     ics_mode_t icsMode;      /*!< ICS mode.                   */
346     uint8_t irClkEnableMode; /*!< ICSIRCLK enable mode.       */
347     uint8_t rDiv;            /*!< Divider for external reference clock, ICS_C1[RDIV].    */
348     uint8_t bDiv;            /*!< Divider for ICS output clock ICS_C2[BDIV].      */
349 } ics_config_t;
350 
351 /*******************************************************************************
352  * API
353  ******************************************************************************/
354 
355 #if defined(__cplusplus)
356 extern "C" {
357 #endif /* __cplusplus */
358 
359 /*!
360  * @brief Enable the clock for specific IP.
361  *
362  * @param name  Which clock to enable, see \ref clock_ip_name_t.
363  */
CLOCK_EnableClock(clock_ip_name_t name)364 static inline void CLOCK_EnableClock(clock_ip_name_t name)
365 {
366     uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
367     (*(volatile uint32_t *)regAddr) |= (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
368 }
369 
370 /*!
371  * @brief Disable the clock for specific IP.
372  *
373  * @param name  Which clock to disable, see \ref clock_ip_name_t.
374  */
CLOCK_DisableClock(clock_ip_name_t name)375 static inline void CLOCK_DisableClock(clock_ip_name_t name)
376 {
377     uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
378     (*(volatile uint32_t *)regAddr) &= ~(1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
379 }
380 
381 /*!
382  * @brief clock divider
383  *
384  * Set the SIM_BUSDIV.
385  * Carefully configure the SIM_BUSDIV to avoid bus/flash clock frequency higher
386  * than 24MHZ.
387  * @param busDiv bus clock output divider value.
388  */
CLOCK_SetBusClkDiv(uint32_t busDiv)389 static inline void CLOCK_SetBusClkDiv(uint32_t busDiv)
390 {
391     SIM->BUSDIV = SIM_BUSDIV_BUSDIV(busDiv);
392 }
393 
394 /*!
395  * @brief Gets the clock frequency for a specific clock name.
396  *
397  * This function checks the current clock configurations and then calculates
398  * the clock frequency for a specific clock name defined in clock_name_t.
399  * The ICS must be properly configured before using this function.
400  *
401  * @param clockName Clock names defined in clock_name_t
402  * @return Clock frequency value in Hertz
403  */
404 uint32_t CLOCK_GetFreq(clock_name_t clockName);
405 
406 /*!
407  * @brief Get the core clock or system clock frequency.
408  *
409  * @return Clock frequency in Hz.
410  */
411 uint32_t CLOCK_GetCoreSysClkFreq(void);
412 
413 /*!
414  * @brief Get the bus clock frequency.
415  *
416  * @return Clock frequency in Hz.
417  */
418 uint32_t CLOCK_GetBusClkFreq(void);
419 
420 /*!
421  * @brief Get the flash clock frequency.
422  *
423  * @return Clock frequency in Hz.
424  */
425 uint32_t CLOCK_GetFlashClkFreq(void);
426 
427 /*!
428  * @brief Get the OSC0 external reference clock frequency (OSC0ERCLK).
429  *
430  * @return Clock frequency in Hz.
431  */
432 uint32_t CLOCK_GetOsc0ErClkFreq(void);
433 
434 /*!
435  * @brief Set the clock configure in SIM module.
436  *
437  * This function sets system layer clock settings in SIM module.
438  *
439  * @param config Pointer to the configure structure.
440  */
441 void CLOCK_SetSimConfig(sim_clock_config_t const *config);
442 
443 /*!
444  * @brief Set the system clock dividers in SIM to safe value.
445  *
446  * The system level clocks (core clock, bus clock, and flash clock)
447  * must be in allowed ranges. During ICS clock mode switch, the ICS output clock
448  * changes then the system level clocks may be out of range. This function could
449  * be used before ICS mode change, to make sure system level clocks are in allowed
450  * range.
451  *
452  */
CLOCK_SetSimSafeDivs(void)453 static inline void CLOCK_SetSimSafeDivs(void)
454 {
455     SIM->BUSDIV = 0x1U;
456 }
457 
458 /*! @name ICS frequency functions. */
459 /*@{*/
460 
461 /*!
462  * @brief Gets the ICS output clock (ICSOUTCLK) frequency.
463  *
464  * This function gets the ICS output clock frequency in Hz based on the current ICS
465  * register value.
466  *
467  * @return The frequency of ICSOUTCLK.
468  */
469 uint32_t CLOCK_GetICSOutClkFreq(void);
470 
471 /*!
472  * @brief Gets the ICS FLL clock (ICSFLLCLK) frequency.
473  *
474  * This function gets the ICS FLL clock frequency in Hz based on the current ICS
475  * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and
476  * disabled in low power state in other modes.
477  *
478  * @return The frequency of ICSFLLCLK.
479  */
480 uint32_t CLOCK_GetFllFreq(void);
481 
482 /*!
483  * @brief Gets the ICS internal reference clock (ICSIRCLK) frequency.
484  *
485  * This function gets the ICS internal reference clock frequency in Hz based
486  * on the current ICS register value.
487  *
488  * @return The frequency of ICSIRCLK.
489  */
490 uint32_t CLOCK_GetInternalRefClkFreq(void);
491 
492 /*!
493  * @brief Gets the ICS fixed frequency clock (ICSFFCLK) frequency.
494  *
495  * This function gets the ICS fixed frequency clock frequency in Hz based
496  * on the current ICS register value.
497  *
498  * @return The frequency of ICSFFCLK.
499  */
500 uint32_t CLOCK_GetICSFixedFreqClkFreq(void);
501 
502 /*@}*/
503 
504 /*! @name ICS clock configuration. */
505 /*@{*/
506 
507 /*!
508  * @brief Enables or disables the ICS low power.
509  *
510  * Enabling the ICS low power disables the PLL and FLL in bypass modes. In other words,
511  * in FBE and PBE modes, enabling low power sets the ICS to BELP mode. In FBI and
512  * PBI modes, enabling low power sets the ICS to BILP mode.
513  * When disabling the ICS low power, the PLL or FLL are enabled based on ICS settings.
514  *
515  * @param enable True to enable ICS low power, false to disable ICS low power.
516  */
CLOCK_SetLowPowerEnable(bool enable)517 static inline void CLOCK_SetLowPowerEnable(bool enable)
518 {
519     if (enable)
520     {
521         ICS->C2 |= ICS_C2_LP_MASK;
522     }
523     else
524     {
525         ICS->C2 &= (uint8_t)(~ICS_C2_LP_MASK);
526     }
527 }
528 
529 /*!
530  * @brief Configures the Internal Reference clock (ICSIRCLK).
531  *
532  * This function sets the ICSIRCLK base on parameters.
533  * This function also sets whether the \c ICSIRCLK is enabled in stop mode.
534  *
535  * @param enableMode ICSIRCLK enable mode, OR'ed value of _ICS_irclk_enable_mode.
536  * @retval kStatus_ICS_SourceUsed Because the internal reference clock is used as a clock source,
537  * the configuration should not be changed. Otherwise, a glitch occurs.
538  * @retval kStatus_Success ICSIRCLK configuration finished successfully.
539  */
CLOCK_SetInternalRefClkConfig(uint8_t enableMode)540 static inline void CLOCK_SetInternalRefClkConfig(uint8_t enableMode)
541 {
542     /* Set internal reference clock selection. */
543     ICS->C1 = (uint8_t)((ICS->C1 & ~(ICS_C1_IRCLKEN_MASK | ICS_C1_IREFSTEN_MASK)) | (uint8_t)enableMode);
544 }
545 
546 /*!
547  * @brief Set the FLL external reference clock divider value.
548  *
549  * Sets the FLL external reference clock divider value, the register ICS_C1[RDIV].
550  * Resulting frequency must be in the range 31.25KHZ to 39.0625KHZ.
551  *
552  * @param rdiv The FLL external reference clock divider value, ICS_C1[RDIV].
553  */
CLOCK_SetFllExtRefDiv(uint8_t rdiv)554 static inline void CLOCK_SetFllExtRefDiv(uint8_t rdiv)
555 {
556     ICS->C1 = (uint8_t)((ICS->C1 & ~ICS_C1_RDIV_MASK) | ICS_C1_RDIV(rdiv));
557 }
558 
559 /*@}*/
560 
561 /*! @name ICS clock lock monitor functions. */
562 /*@{*/
563 
564 /*!
565  * @brief Sets the OSC0 clock monitor mode.
566  *
567  * This function sets the OSC0 clock monitor mode. See ics_monitor_mode_t for details.
568  *
569  * @param enable True to enable clock monitor, false to disable clock monitor.
570  */
CLOCK_SetOsc0MonitorMode(bool enable)571 static inline void CLOCK_SetOsc0MonitorMode(bool enable)
572 {
573     if (enable)
574     {
575         ICS->C4 |= ICS_C4_CME_MASK;
576     }
577     else
578     {
579         ICS->C4 &= (uint8_t)(~ICS_C4_CME_MASK);
580     }
581 }
582 
583 /*@}*/
584 
585 /*!
586  * @name OSC configuration
587  * @{
588  */
589 
590 /*!
591  * @brief Initializes the OSC0.
592  *
593  * This function initializes the OSC0 according to the board configuration.
594  *
595  * @param  config Pointer to the OSC0 configuration structure.
596  */
597 void CLOCK_InitOsc0(osc_config_t const *config);
598 
599 /*!
600  * @brief Deinitializes the OSC0.
601  *
602  * This function deinitializes the OSC0.
603  */
604 void CLOCK_DeinitOsc0(void);
605 
606 /* @} */
607 
608 /*!
609  * @name External clock frequency
610  * @{
611  */
612 
613 /*!
614  * @brief Sets the XTAL0 frequency based on board settings.
615  *
616  * @param freq The XTAL0/EXTAL0 input clock frequency in Hz.
617  */
CLOCK_SetXtal0Freq(uint32_t freq)618 static inline void CLOCK_SetXtal0Freq(uint32_t freq)
619 {
620     g_xtal0Freq = freq;
621 }
622 
623 /*!
624  * @brief Sets the OSC enable.
625  *
626  * @param enable osc enable mode.
627  */
CLOCK_SetOsc0Enable(uint8_t enable)628 static inline void CLOCK_SetOsc0Enable(uint8_t enable)
629 {
630     OSC0->CR |= (uint8_t)((OSC0->CR & (~(OSC_CR_OSCSTEN_MASK | OSC_CR_OSCEN_MASK))) | enable);
631 }
632 
633 /* @} */
634 
635 /*! @name ICS mode functions. */
636 /*@{*/
637 
638 /*!
639  * @brief Gets the current ICS mode.
640  *
641  * This function checks the ICS registers and determines the current ICS mode.
642  *
643  * @return Current ICS mode or error code; See @ref ics_mode_t.
644  */
645 ics_mode_t CLOCK_GetMode(void);
646 
647 /*!
648  * @brief Sets the ICS to FEI mode.
649  *
650  * This function sets the ICS to FEI mode. If setting to FEI mode fails
651  * from the current mode, this function returns an error.
652  *
653  * @param       bDiv bus clock divider
654  * @retval kStatus_ICS_ModeUnreachable Could not switch to the target mode.
655  * @retval kStatus_Success Switched to the target mode successfully.
656  */
657 status_t CLOCK_SetFeiMode(uint8_t bDiv);
658 
659 /*!
660  * @brief Sets the ICS to FEE mode.
661  *
662  * This function sets the ICS to FEE mode. If setting to FEE mode fails
663  * from the current mode, this function returns an error.
664  *
665  * @param   bDiv bus clock divider
666  * @param   rDiv  FLL reference clock divider setting, RDIV.
667  *
668  * @retval kStatus_ICS_ModeUnreachable Could not switch to the target mode.
669  * @retval kStatus_Success Switched to the target mode successfully.
670  */
671 status_t CLOCK_SetFeeMode(uint8_t bDiv, uint8_t rDiv);
672 
673 /*!
674  * @brief Sets the ICS to FBI mode.
675  *
676  * This function sets the ICS to FBI mode. If setting to FBI mode fails
677  * from the current mode, this function returns an error.
678  *
679  * @param bDiv bus clock divider
680  * @retval kStatus_ICS_ModeUnreachable Could not switch to the target mode.
681  * @retval kStatus_Success Switched to the target mode successfully.s
682  */
683 status_t CLOCK_SetFbiMode(uint8_t bDiv);
684 
685 /*!
686  * @brief Sets the ICS to FBE mode.
687  *
688  * This function sets the ICS to FBE mode. If setting to FBE mode fails
689  * from the current mode, this function returns an error.
690  *
691  * @param   bDiv bus clock divider
692  * @param   rDiv  FLL reference clock divider setting, RDIV.
693  *
694  * @retval kStatus_ICS_ModeUnreachable Could not switch to the target mode.
695  * @retval kStatus_Success Switched to the target mode successfully.
696  */
697 status_t CLOCK_SetFbeMode(uint8_t bDiv, uint8_t rDiv);
698 
699 /*!
700  * @brief Sets the ICS to BILP mode.
701  *
702  * This function sets the ICS to BILP mode. If setting to BILP mode fails
703  * from the current mode, this function returns an error.
704  *
705  * @param   bDiv bus clock divider
706  * @retval kStatus_ICS_ModeUnreachable Could not switch to the target mode.
707  * @retval kStatus_Success Switched to the target mode successfully.
708  */
709 status_t CLOCK_SetBilpMode(uint8_t bDiv);
710 
711 /*!
712  * @brief Sets the ICS to BELP mode.
713  *
714  * This function sets the ICS to BELP mode. If setting to BELP mode fails
715  * from the current mode, this function returns an error.
716  *
717  * @param   bDiv bus clock divider
718  * @retval kStatus_ICS_ModeUnreachable Could not switch to the target mode.
719  * @retval kStatus_Success Switched to the target mode successfully.
720  */
721 status_t CLOCK_SetBelpMode(uint8_t bDiv);
722 
723 /*!
724  * @brief Sets the ICS to FEI mode during system boot up.
725  *
726  * This function sets the ICS to FEI mode from the reset mode. It can also be used to
727  * set up ICS during system boot up.
728  *
729  * @param  bDiv bus clock divider.
730  *
731  * @retval kStatus_ICS_ModeUnreachable Could not switch to the target mode.
732  * @retval kStatus_Success Switched to the target mode successfully.
733  */
734 status_t CLOCK_BootToFeiMode(uint8_t bDiv);
735 
736 /*!
737  * @brief Sets the ICS to FEE mode during system bootup.
738  *
739  * This function sets ICS to FEE mode from the reset mode. It can also be used to
740  * set up the ICS during system boot up.
741  *
742  * @param   bDiv bus clock divider.
743  * @param   rDiv  FLL reference clock divider setting, RDIV.
744  *
745  * @retval kStatus_ICS_ModeUnreachable Could not switch to the target mode.
746  * @retval kStatus_Success Switched to the target mode successfully.
747  */
748 status_t CLOCK_BootToFeeMode(uint8_t bDiv, uint8_t rDiv);
749 
750 /*!
751  * @brief Sets the ICS to BILP mode during system boot up.
752  *
753  * This function sets the ICS to BILP mode from the reset mode. It can also be used to
754  * set up the ICS during system boot up.
755  *
756  * @param   bDiv bus clock divider.
757  * @retval kStatus_ICS_SourceUsed Could not change ICSIRCLK setting.
758  * @retval kStatus_Success Switched to the target mode successfully.
759  */
760 status_t CLOCK_BootToBilpMode(uint8_t bDiv);
761 
762 /*!
763  * @brief Sets the ICS to BELP mode during system boot up.
764  *
765  * This function sets the ICS to BELP mode from the reset mode. It can also be used to
766  * set up the ICS during system boot up.
767  *
768  * @param   bDiv bus clock divider.
769  * @retval kStatus_ICS_ModeUnreachable Could not switch to the target mode.
770  * @retval kStatus_Success Switched to the target mode successfully.
771  */
772 status_t CLOCK_BootToBelpMode(uint8_t bDiv);
773 
774 /*!
775  * @brief Sets the ICS to a target mode.
776  *
777  * This function sets ICS to a target mode defined by the configuration
778  * structure. If switching to the target mode fails, this function
779  * chooses the correct path.
780  *
781  * @param  config Pointer to the target ICS mode configuration structure.
782  * @return Return kStatus_Success if switched successfully; Otherwise, it returns an error code _ICS_status.
783  *
784  * @note If the external clock is used in the target mode, ensure that it is
785  * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this
786  * function.
787  */
788 status_t CLOCK_SetIcsConfig(ics_config_t const *config);
789 
790 /*@}*/
791 
792 #if defined(__cplusplus)
793 }
794 #endif /* __cplusplus */
795 
796 /*! @} */
797 
798 #endif /* _FSL_CLOCK_H_ */
799