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