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