1 /*
2  * Copyright 2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #ifndef _FSL_CLOCK_H_
9 #define _FSL_CLOCK_H_
10 
11 #include "fsl_common.h"
12 
13 /*! @addtogroup clock */
14 /*! @{ */
15 
16 /*! @file */
17 
18 /*******************************************************************************
19  * Configurations
20  ******************************************************************************/
21 
22 /*! @brief Configure whether driver controls clock
23  *
24  * When set to 0, peripheral drivers will enable clock in initialize function
25  * and disable clock in de-initialize function. When set to 1, peripheral
26  * driver will not control the clock, application could control the clock out of
27  * the driver.
28  *
29  * @note All drivers share this feature switcher. If it is set to 1, application
30  * should handle clock enable and disable for all drivers.
31  */
32 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
33 #define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0
34 #endif
35 
36 /*******************************************************************************
37  * Definitions
38  ******************************************************************************/
39 
40 /*! @name Driver version */
41 /*@{*/
42 /*! @brief CLOCK driver version 2.0.0. */
43 #define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
44 /*@}*/
45 
46 /*! @brief External XTAL0 (OSC0/SYSOSC) clock frequency.
47  *
48  * The XTAL0/EXTAL0 (OSC0/SYSOSC) clock frequency in Hz. When the clock is set up, use the
49  * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example,
50  * if XTAL0 is 8 MHz:
51  * @code
52  * CLOCK_InitSysOsc(...);
53  * CLOCK_SetXtal0Freq(80000000);
54  * @endcode
55  *
56  * This is important for the multicore platforms where only one core needs to set up the
57  * OSC0/SYSOSC using CLOCK_InitSysOsc. All other cores need to call the CLOCK_SetXtal0Freq
58  * to get a valid clock frequency.
59  */
60 extern volatile uint32_t g_xtal0Freq;
61 
62 #ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY
63 #define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (72000000UL)
64 #endif
65 
66 /*! @brief Clock ip name array for DMAMUX. */
67 #define DMAMUX_CLOCKS  \
68     {                  \
69         kCLOCK_Dmamux0 \
70     }
71 
72 /*! @brief Clock ip name array for PORT. */
73 #define PORT_CLOCKS                                                          \
74     {                                                                        \
75         kCLOCK_PortA, kCLOCK_PortB, kCLOCK_PortC, kCLOCK_PortD, kCLOCK_PortE \
76     }
77 
78 /*! @brief Clock ip name array for LPI2C. */
79 #define LPI2C_CLOCKS                 \
80     {                                \
81         kCLOCK_Lpi2c0, kCLOCK_Lpi2c1 \
82     }
83 
84 /*! @brief Clock ip name array for FLEXIO. */
85 #define FLEXIO_CLOCKS  \
86     {                  \
87         kCLOCK_Flexio0 \
88     }
89 
90 /*! @brief Clock ip name array for RTC. */
91 #define RTC_CLOCKS  \
92     {               \
93         kCLOCK_Rtc0 \
94     }
95 
96 /*! @brief Clock ip name array for TSI. */
97 #define TSI_CLOCKS  \
98     {               \
99         kCLOCK_Tsi0 \
100     }
101 
102 /*! @brief Clock ip name array for EDMA. */
103 #define EDMA_CLOCKS \
104     {               \
105         kCLOCK_Dma0 \
106     }
107 
108 /*! @brief Clock ip name array for LPUART. */
109 #define LPUART_CLOCKS                                  \
110     {                                                  \
111         kCLOCK_Lpuart0, kCLOCK_Lpuart1, kCLOCK_Lpuart2 \
112     }
113 
114 /*! @brief Clock ip name array for LPTMR. */
115 #define LPTMR_CLOCKS  \
116     {                 \
117         kCLOCK_Lptmr0 \
118     }
119 
120 /*! @brief Clock ip name array for ADC12. */
121 #define ADC12_CLOCKS \
122     {                \
123         kCLOCK_Adc0  \
124     }
125 
126 /*! @brief Clock ip name array for LPSPI. */
127 #define LPSPI_CLOCKS                 \
128     {                                \
129         kCLOCK_Lpspi0, kCLOCK_Lpspi1 \
130     }
131 
132 /*! @brief Clock ip name array for LPIT. */
133 #define LPIT_CLOCKS  \
134     {                \
135         kCLOCK_Lpit0 \
136     }
137 
138 /*! @brief Clock ip name array for CRC. */
139 #define CRC_CLOCKS  \
140     {               \
141         kCLOCK_Crc0 \
142     }
143 
144 /*! @brief Clock ip name array for CMP. */
145 #define CMP_CLOCKS  \
146     {               \
147         kCLOCK_Cmp0 \
148     }
149 
150 /*! @brief Clock ip name array for FLASH. */
151 #define FLASH_CLOCKS  \
152     {                 \
153         kCLOCK_Flash0 \
154     }
155 
156 /*! @brief Clock ip name array for EWM. */
157 #define EWM_CLOCKS  \
158     {               \
159         kCLOCK_Ewm0 \
160     }
161 
162 /*! @brief Clock ip name array for FLEXTMR. */
163 #define FTM_CLOCKS                            \
164     {                                         \
165         kCLOCK_Ftm0, kCLOCK_Ftm1, kCLOCK_Ftm2 \
166     }
167 
168 /*! @brief Clock ip name array for PWT. */
169 #define PWT_CLOCKS  \
170     {               \
171         kCLOCK_Pwt0 \
172     }
173 
174 /*! @brief Clock ip name array for FLEXIO_TRIG0/1 Aync clock. */
175 #define FLEXIOTRIG_CLOCKS                      \
176     {                                          \
177         kCLOCK_FlexioTrig0, kCLOCK_FlexioTrig1 \
178     }
179 
180 /*! @brief Clock ip name array for SCI/UART clock. */
181 #define UART_CLOCKS              \
182     {                            \
183         kCLOCK_Sci0, kCLOCK_Sci1 \
184     }
185 /*!
186  * @brief LPO clock frequency.
187  */
188 #define LPO_CLK_FREQ 128000U
189 
190 /*! @brief Clock name used to get clock frequency. */
191 typedef enum _clock_name
192 {
193     /* ----------------------------- System layer clock -------------------------------*/
194     kCLOCK_CoreSysClk, /*!< Core/system clock                                   */
195     kCLOCK_BusClk,     /*!< Bus clock                                           */
196     kCLOCK_FlashClk,   /*!< Flash clock                                         */
197 
198     /* ------------------------------------ SCG clock ---------------------------------*/
199     kCLOCK_ScgSysOscClk, /*!< SCG system OSC clock. (SYSOSC)                      */
200     kCLOCK_ScgSircClk,   /*!< SCG SIRC clock.                                     */
201     kCLOCK_ScgFircClk,   /*!< SCG FIRC clock.                                     */
202     kCLOCK_ScgLpFllClk,  /*!< SCG low power FLL clock. (LPFLL)                    */
203 
204     kCLOCK_ScgSysOscAsyncDiv2Clk, /*!< SOSCDIV2_CLK.                                   */
205 
206     kCLOCK_ScgSircAsyncDiv2Clk, /*!< SIRCDIV2_CLK.                                   */
207 
208     kCLOCK_ScgFircAsyncDiv2Clk, /*!< FIRCDIV2_CLK.                                   */
209 
210     kCLOCK_ScgLpFllAsyncDiv2Clk, /*!< LPFLLDIV2_CLK.                                   */
211 
212     /* --------------------------------- Other clock ----------------------------------*/
213     kCLOCK_LpoClk, /*!< LPO clock                                           */
214     kCLOCK_ErClk,  /*!< ERCLK. The external reference clock from SCG.       */
215 } clock_name_t;
216 
217 #define kCLOCK_Osc0ErClk       kCLOCK_ErClk
218 #define CLOCK_GetOsc0ErClkFreq CLOCK_GetErClkFreq /*!< For compatible with other MCG platforms. */
219 
220 /*!
221  * @brief Clock source for peripherals that support various clock selections.
222  */
223 typedef enum _clock_ip_src
224 {
225     kCLOCK_IpSrcNoneOrExt   = 0U, /*!< Clock is off or external clock is used. */
226     kCLOCK_IpSrcSysOscAsync = 1U, /*!< System Oscillator async clock.          */
227     kCLOCK_IpSrcSircAsync   = 2U, /*!< Slow IRC async clock.                   */
228     kCLOCK_IpSrcFircAsync   = 3U, /*!< Fast IRC async clock.                   */
229     kCLOCK_IpSrcLpFllAsync  = 5U  /*!< LPFLL async clock.                      */
230 } clock_ip_src_t;
231 
232 /*!
233  * @brief Peripheral clock name difinition used for clock gate, clock source
234  * and clock divider setting. It is defined as the corresponding register address.
235  */
236 typedef enum _clock_ip_name
237 {
238     kCLOCK_IpInvalid = 0U,
239 
240     /* PCC 0 */
241     kCLOCK_Dma0   = 0x40065020U,
242     kCLOCK_Flash0 = 0x40065080U, /*!< Note, the flash clock is always enabled, that is PCC_FLASH[CGC] bit is always 1 in
243                                     this device and writing 0 takes no effect! */
244     kCLOCK_Dmamux0     = 0x40065084U,
245     kCLOCK_Lpspi0      = 0x400650B0U,
246     kCLOCK_Lpspi1      = 0x400650B4U,
247     kCLOCK_Crc0        = 0x400650C8U,
248     kCLOCK_Lpit0       = 0x400650DCU,
249     kCLOCK_Ftm0        = 0x400650E0U,
250     kCLOCK_Ftm1        = 0x400650E4U,
251     kCLOCK_Ftm2        = 0x400650E8U,
252     kCLOCK_Adc0        = 0x400650ECU,
253     kCLOCK_Rtc0        = 0x400650F4U,
254     kCLOCK_Lptmr0      = 0x40065100U,
255     kCLOCK_Tsi0        = 0x40065114U,
256     kCLOCK_PortA       = 0x40065124U,
257     kCLOCK_PortB       = 0x40065128U,
258     kCLOCK_PortC       = 0x4006512CU,
259     kCLOCK_PortD       = 0x40065130U,
260     kCLOCK_PortE       = 0x40065134U,
261     kCLOCK_Pwt0        = 0x40065158U,
262     kCLOCK_Flexio0     = 0x40065168U,
263     kCLOCK_RtcOsc0     = 0x40065180U,
264     kCLOCK_Ewm0        = 0x40065184U,
265     kCLOCK_FlexioTrig0 = 0x40065188U,
266     kCLOCK_FlexioTrig1 = 0x4006518CU,
267     kCLOCK_Lpi2c0      = 0x40065198U,
268     kCLOCK_Lpi2c1      = 0x4006519CU,
269     kCLOCK_Lpuart0     = 0x400651A8U,
270     kCLOCK_Lpuart1     = 0x400651ACU,
271     kCLOCK_Lpuart2     = 0x400651B0U,
272     kCLOCK_Sci0        = 0x400651B4U,
273     kCLOCK_Sci1        = 0x400651B8U,
274     kCLOCK_Cmp0        = 0x400651CCU,
275 } clock_ip_name_t;
276 
277 /*!
278  * @brief SCG status return codes.
279  */
280 enum
281 {
282     kStatus_SCG_Busy       = MAKE_STATUS(kStatusGroup_SCG, 1), /*!< Clock is busy.  */
283     kStatus_SCG_InvalidSrc = MAKE_STATUS(kStatusGroup_SCG, 2)  /*!< Invalid source. */
284 };
285 
286 /*!
287  * @brief SCG system clock type.
288  */
289 typedef enum _scg_sys_clk
290 {
291     kSCG_SysClkSlow, /*!< System slow clock. */
292     kSCG_SysClkCore, /*!< Core clock.        */
293 } scg_sys_clk_t;
294 
295 /*!
296  * @brief SCG system clock source.
297  */
298 typedef enum _scg_sys_clk_src
299 {
300     kSCG_SysClkSrcSysOsc = 1U, /*!< System OSC. */
301     kSCG_SysClkSrcSirc   = 2U, /*!< Slow IRC.   */
302     kSCG_SysClkSrcFirc   = 3U, /*!< Fast IRC.   */
303     kSCG_SysClkSrcLpFll  = 5U, /*!< Low power FLL. */
304 } scg_sys_clk_src_t;
305 
306 /*!
307  * @brief SCG system clock divider value.
308  */
309 typedef enum _scg_sys_clk_div
310 {
311     kSCG_SysClkDivBy1  = 0U,  /*!< Divided by 1.  */
312     kSCG_SysClkDivBy2  = 1U,  /*!< Divided by 2.  */
313     kSCG_SysClkDivBy3  = 2U,  /*!< Divided by 3.  */
314     kSCG_SysClkDivBy4  = 3U,  /*!< Divided by 4.  */
315     kSCG_SysClkDivBy5  = 4U,  /*!< Divided by 5.  */
316     kSCG_SysClkDivBy6  = 5U,  /*!< Divided by 6.  */
317     kSCG_SysClkDivBy7  = 6U,  /*!< Divided by 7.  */
318     kSCG_SysClkDivBy8  = 7U,  /*!< Divided by 8.  */
319     kSCG_SysClkDivBy9  = 8U,  /*!< Divided by 9.  */
320     kSCG_SysClkDivBy10 = 9U,  /*!< Divided by 10. */
321     kSCG_SysClkDivBy11 = 10U, /*!< Divided by 11. */
322     kSCG_SysClkDivBy12 = 11U, /*!< Divided by 12. */
323     kSCG_SysClkDivBy13 = 12U, /*!< Divided by 13. */
324     kSCG_SysClkDivBy14 = 13U, /*!< Divided by 14. */
325     kSCG_SysClkDivBy15 = 14U, /*!< Divided by 15. */
326     kSCG_SysClkDivBy16 = 15U  /*!< Divided by 16. */
327 } scg_sys_clk_div_t;
328 
329 /*!
330  * @brief SCG system clock configuration.
331  */
332 typedef struct _scg_sys_clk_config
333 {
334     uint32_t divSlow : 4; /*!< Slow clock divider, see @ref scg_sys_clk_div_t. */
335     uint32_t : 4;         /*!< Reserved. */
336     uint32_t : 4;         /*!< Reserved. */
337     uint32_t : 4;         /*!< Reserved. */
338     uint32_t divCore : 4; /*!< Core clock divider, see @ref scg_sys_clk_div_t. */
339     uint32_t : 4;         /*!< Reserved. */
340     uint32_t src : 4;     /*!< System clock source, see @ref scg_sys_clk_src_t. */
341     uint32_t : 4;         /*!< reserved. */
342 } scg_sys_clk_config_t;
343 
344 /*!
345  * @brief SCG clock out configuration (CLKOUTSEL).
346  */
347 typedef enum _clock_clkout_src
348 {
349     kClockClkoutSelScgSlow = 0U, /*!< SCG slow clock. */
350     kClockClkoutSelSysOsc  = 1U, /*!< System OSC.     */
351     kClockClkoutSelSirc    = 2U, /*!< Slow IRC.       */
352     kClockClkoutSelFirc    = 3U, /*!< Fast IRC.       */
353     kClockClkoutSelLpFll   = 5U, /*!< Low power FLL.  */
354 } clock_clkout_src_t;
355 
356 /*!
357  * @brief SCG asynchronous clock type.
358  */
359 typedef enum _scg_async_clk
360 {
361     kSCG_AsyncDiv2Clk, /*!< The async clock by DIV2, e.g. SOSCDIV2_CLK, SIRCDIV2_CLK. */
362 } scg_async_clk_t;
363 
364 /*!
365  * @brief SCG asynchronous clock divider value.
366  */
367 typedef enum scg_async_clk_div
368 {
369     kSCG_AsyncClkDisable = 0U, /*!< Clock output is disabled.  */
370     kSCG_AsyncClkDivBy1  = 1U, /*!< Divided by 1.              */
371     kSCG_AsyncClkDivBy2  = 2U, /*!< Divided by 2.              */
372     kSCG_AsyncClkDivBy4  = 3U, /*!< Divided by 4.              */
373     kSCG_AsyncClkDivBy8  = 4U, /*!< Divided by 8.              */
374     kSCG_AsyncClkDivBy16 = 5U, /*!< Divided by 16.             */
375     kSCG_AsyncClkDivBy32 = 6U, /*!< Divided by 32.             */
376     kSCG_AsyncClkDivBy64 = 7U  /*!< Divided by 64.             */
377 } scg_async_clk_div_t;
378 
379 /*!
380  * @brief SCG system OSC monitor mode.
381  */
382 typedef enum _scg_sosc_monitor_mode
383 {
384     kSCG_SysOscMonitorDisable = 0U,                      /*!< Monitor disabled.                          */
385     kSCG_SysOscMonitorInt     = SCG_SOSCCSR_SOSCCM_MASK, /*!< Interrupt when the system OSC error is detected. */
386     kSCG_SysOscMonitorReset =
387         SCG_SOSCCSR_SOSCCM_MASK | SCG_SOSCCSR_SOSCCMRE_MASK /*!< Reset when the system OSC error is detected.     */
388 } scg_sosc_monitor_mode_t;
389 
390 /*! @brief OSC work mode. */
391 typedef enum _scg_sosc_mode
392 {
393     kSCG_SysOscModeExt         = 0U,                                           /*!< Use external clock.   */
394     kSCG_SysOscModeOscLowPower = SCG_SOSCCFG_EREFS_MASK,                       /*!< Oscillator low power. */
395     kSCG_SysOscModeOscHighGain = SCG_SOSCCFG_EREFS_MASK | SCG_SOSCCFG_HGO_MASK /*!< Oscillator high gain. */
396 } scg_sosc_mode_t;
397 
398 /*! @brief OSC enable mode. */
399 enum
400 {
401     kSCG_SysOscEnable           = SCG_SOSCCSR_SOSCEN_MASK,     /*!< Enable OSC clock. */
402     kSCG_SysOscEnableInStop     = SCG_SOSCCSR_SOSCSTEN_MASK,   /*!< Enable OSC in stop mode. */
403     kSCG_SysOscEnableInLowPower = SCG_SOSCCSR_SOSCLPEN_MASK,   /*!< Enable OSC in low power mode. */
404     kSCG_SysOscEnableErClk      = SCG_SOSCCSR_SOSCERCLKEN_MASK /*!< Enable OSCERCLK. */
405 };
406 
407 /*!
408  * @brief SCG system OSC configuration.
409  */
410 typedef struct _scg_sosc_config
411 {
412     uint32_t freq;                       /*!< System OSC frequency.                    */
413     scg_sosc_monitor_mode_t monitorMode; /*!< Clock monitor mode selected.     */
414     uint8_t enableMode;                  /*!< Enable mode, OR'ed value of _scg_sosc_enable_mode.  */
415 
416     scg_async_clk_div_t div2; /*!< SOSCDIV2 value.                          */
417 
418     scg_sosc_mode_t workMode; /*!< OSC work mode.                           */
419 } scg_sosc_config_t;
420 
421 /*!
422  * @brief SCG slow IRC clock frequency range.
423  */
424 typedef enum _scg_sirc_range
425 {
426     kSCG_SircRangeLow, /*!< Slow IRC low range clock (2 MHz, 4 MHz for i.MX 7 ULP).  */
427     kSCG_SircRangeHigh /*!< Slow IRC high range clock (8 MHz, 16 MHz for i.MX 7 ULP). */
428 } scg_sirc_range_t;
429 
430 /*! @brief SIRC enable mode. */
431 enum
432 {
433     kSCG_SircEnable           = SCG_SIRCCSR_SIRCEN_MASK,   /*!< Enable SIRC clock.             */
434     kSCG_SircEnableInStop     = SCG_SIRCCSR_SIRCSTEN_MASK, /*!< Enable SIRC in stop mode.      */
435     kSCG_SircEnableInLowPower = SCG_SIRCCSR_SIRCLPEN_MASK  /*!< Enable SIRC in low power mode. */
436 };
437 
438 /*!
439  * @brief SCG slow IRC clock configuration.
440  */
441 typedef struct _scg_sirc_config
442 {
443     uint32_t enableMode;      /*!< Enable mode, OR'ed value of _scg_sirc_enable_mode. */
444     scg_async_clk_div_t div2; /*!< SIRCDIV2 value.                          */
445 
446     scg_sirc_range_t range; /*!< Slow IRC frequency range.                */
447 } scg_sirc_config_t;
448 
449 /*!
450  * @brief SCG fast IRC trim mode.
451  */
452 typedef enum _scg_firc_trim_mode
453 {
454     kSCG_FircTrimNonUpdate = SCG_FIRCCSR_FIRCTREN_MASK,
455     /*!< FIRC trim enable but not enable trim value update. In this mode, the
456      trim value is fixed to the initialized value which is defined by
457      trimCoar and trimFine in configure structure \ref scg_firc_trim_config_t.*/
458 
459     kSCG_FircTrimUpdate = SCG_FIRCCSR_FIRCTREN_MASK | SCG_FIRCCSR_FIRCTRUP_MASK
460     /*!< FIRC trim enable and trim value update enable. In this mode, the trim
461      value is auto update. */
462 
463 } scg_firc_trim_mode_t;
464 
465 /*!
466  * @brief SCG fast IRC trim predivided value for system OSC.
467  */
468 typedef enum _scg_firc_trim_div
469 {
470     kSCG_FircTrimDivBy1,    /*!< Divided by 1.    */
471     kSCG_FircTrimDivBy128,  /*!< Divided by 128.  */
472     kSCG_FircTrimDivBy256,  /*!< Divided by 256.  */
473     kSCG_FircTrimDivBy512,  /*!< Divided by 512.  */
474     kSCG_FircTrimDivBy1024, /*!< Divided by 1024. */
475     kSCG_FircTrimDivBy2048  /*!< Divided by 2048. */
476 } scg_firc_trim_div_t;
477 
478 /*!
479  * @brief SCG fast IRC trim source.
480  */
481 typedef enum _scg_firc_trim_src
482 {
483     kSCG_FircTrimSrcSysOsc = 2U, /*!< System OSC.                 */
484 } scg_firc_trim_src_t;
485 
486 /*!
487  * @brief SCG fast IRC clock trim configuration.
488  */
489 typedef struct _scg_firc_trim_config
490 {
491     scg_firc_trim_mode_t trimMode; /*!< FIRC trim mode.                       */
492     scg_firc_trim_src_t trimSrc;   /*!< Trim source.                          */
493     scg_firc_trim_div_t trimDiv;   /*!< Trim predivided value for the system OSC.  */
494 
495     uint8_t trimCoar; /*!< Trim coarse value; Irrelevant if trimMode is kSCG_FircTrimUpdate. */
496     uint8_t trimFine; /*!< Trim fine value; Irrelevant if trimMode is kSCG_FircTrimUpdate. */
497 } scg_firc_trim_config_t;
498 
499 /*!
500  * @brief SCG fast IRC clock frequency range.
501  */
502 typedef enum _scg_firc_range
503 {
504     kSCG_FircRange48M, /*!< Fast IRC is trimmed to 48 MHz.  */
505 } scg_firc_range_t;
506 
507 /*! @brief FIRC enable mode. */
508 enum
509 {
510     kSCG_FircEnable           = SCG_FIRCCSR_FIRCEN_MASK,    /*!< Enable FIRC clock.             */
511     kSCG_FircEnableInStop     = SCG_FIRCCSR_FIRCSTEN_MASK,  /*!< Enable FIRC in stop mode.      */
512     kSCG_FircEnableInLowPower = SCG_FIRCCSR_FIRCLPEN_MASK,  /*!< Enable FIRC in low power mode. */
513     kSCG_FircDisableRegulator = SCG_FIRCCSR_FIRCREGOFF_MASK /*!< Disable regulator.             */
514 };
515 
516 /*!
517  * @brief SCG fast IRC clock configuration.
518  */
519 typedef struct _scg_firc_config_t
520 {
521     uint32_t enableMode; /*!< Enable mode, OR'ed value of _scg_firc_enable_mode. */
522 
523     scg_async_clk_div_t div2; /*!< FIRCDIV2 value.                          */
524 
525     scg_firc_range_t range; /*!< Fast IRC frequency range.                 */
526 
527     const scg_firc_trim_config_t *trimConfig; /*!< Pointer to the FIRC trim configuration; set NULL to disable trim. */
528 } scg_firc_config_t;
529 
530 /*! @brief LPFLL enable mode. */
531 enum
532 {
533     kSCG_LpFllEnable = SCG_LPFLLCSR_LPFLLEN_MASK, /*!< Enable LPFLL clock.             */
534 };
535 
536 /*!
537  * @brief SCG LPFLL clock frequency range.
538  */
539 typedef enum _scg_lpfll_range
540 {
541     kSCG_LpFllRange48M, /*!< LPFLL is trimmed to 48MHz.  */
542     kSCG_LpFllRange72M, /*!< LPFLL is trimmed to 72MHz.  */
543     kSCG_LpFllRange96M, /*!< LPFLL is trimmed to 96MHz.  */
544     kSCG_LpFllRange120M /*!< LPFLL is trimmed to 120MHz. */
545 } scg_lpfll_range_t;
546 
547 /*!
548  * @brief SCG LPFLL trim mode.
549  */
550 typedef enum _scg_lpfll_trim_mode
551 {
552     kSCG_LpFllTrimNonUpdate = SCG_LPFLLCSR_LPFLLTREN_MASK,
553     /*!< LPFLL trim is enabled but the trim value update is not enabled. In this mode, the
554      trim value is fixed to the initialized value, which is defined by the Member variable trimValue
555      in the structure @ref scg_lpfll_trim_config_t.*/
556 
557     kSCG_LpFllTrimUpdate = SCG_LPFLLCSR_LPFLLTREN_MASK | SCG_LPFLLCSR_LPFLLTRUP_MASK
558     /*!< FIRC trim is enabled and trim value update is enabled. In this mode, the trim
559      value is automatically updated. */
560 } scg_lpfll_trim_mode_t;
561 
562 /*!
563  * @brief SCG LPFLL trim source.
564  */
565 typedef enum _scg_lpfll_trim_src
566 {
567     kSCG_LpFllTrimSrcSirc   = 0U, /*!< SIRC.                 */
568     kSCG_LpFllTrimSrcFirc   = 1U, /*!< FIRC.                 */
569     kSCG_LpFllTrimSrcSysOsc = 2U, /*!< System OSC.           */
570     kSCG_LpFllTrimSrcRtcOsc = 3U, /*!< RTC OSC (32.768 kHz). */
571 } scg_lpfll_trim_src_t;
572 
573 /*!
574  * @brief SCG LPFLL lock mode.
575  */
576 typedef enum _scg_lpfll_lock_mode
577 {
578     kSCG_LpFllLock1Lsb = 0U, /*!< Lock with 1 LSB. */
579     kSCG_LpFllLock2Lsb = 1U  /*!< Lock with 2 LSB. */
580 } scg_lpfll_lock_mode_t;
581 
582 /*!
583  * @brief SCG LPFLL clock trim configuration.
584  */
585 typedef struct _scg_lpfll_trim_config
586 {
587     scg_lpfll_trim_mode_t trimMode; /*!< Trim mode.            */
588     scg_lpfll_lock_mode_t lockMode; /*!< Lock mode; Irrelevant if the trimMode is kSCG_LpFllTrimNonUpdate. */
589 
590     scg_lpfll_trim_src_t trimSrc; /*!< Trim source.          */
591     uint8_t trimDiv;              /*!< Trim predivideds value, which can be 0 ~ 31.
592                                     [ Trim source frequency / (trimDiv + 1) ] must be 2 MHz or 32768 Hz. */
593 
594     uint8_t trimValue; /*!< Trim value; Irrelevant if trimMode is the kSCG_LpFllTrimUpdate. */
595 } scg_lpfll_trim_config_t;
596 
597 /*!
598  * @brief SCG low power FLL configuration.
599  */
600 typedef struct _scg_lpfll_config
601 {
602     uint8_t enableMode; /*!< Enable mode, OR'ed value of _scg_lpfll_enable_mode */
603 
604     scg_async_clk_div_t div2; /*!< LPFLLDIV2 value.                          */
605 
606     scg_lpfll_range_t range; /*!< LPFLL frequency range.                     */
607 
608     const scg_lpfll_trim_config_t *trimConfig; /*!< Trim configuration; set NULL to disable trim. */
609 } scg_lpfll_config_t;
610 
611 /*******************************************************************************
612  * API
613  ******************************************************************************/
614 
615 #if defined(__cplusplus)
616 extern "C" {
617 #endif /* __cplusplus */
618 
619 /*!
620  * @brief Enable the clock for specific IP.
621  *
622  * @param name  Which clock to enable, see \ref clock_ip_name_t.
623  */
CLOCK_EnableClock(clock_ip_name_t name)624 static inline void CLOCK_EnableClock(clock_ip_name_t name)
625 {
626     assert((*(volatile uint32_t *)((uint32_t)name)) & PCC_CLKCFG_PR_MASK);
627 
628     (*(volatile uint32_t *)((uint32_t)name)) |= PCC_CLKCFG_CGC_MASK;
629 }
630 
631 /*!
632  * @brief Disable the clock for specific IP.
633  *
634  * @param name  Which clock to disable, see \ref clock_ip_name_t.
635  */
CLOCK_DisableClock(clock_ip_name_t name)636 static inline void CLOCK_DisableClock(clock_ip_name_t name)
637 {
638     assert((*(volatile uint32_t *)((uint32_t)name)) & PCC_CLKCFG_PR_MASK);
639 
640     (*(volatile uint32_t *)((uint32_t)name)) &= ~PCC_CLKCFG_CGC_MASK;
641 }
642 
643 /*!
644  * @brief Set the clock source for specific IP module.
645  *
646  * Set the clock source for specific IP, not all modules need to set the
647  * clock source, should only use this function for the modules need source
648  * setting.
649  *
650  * @param name Which peripheral to check, see \ref clock_ip_name_t.
651  * @param src Clock source to set.
652  */
CLOCK_SetIpSrc(clock_ip_name_t name,clock_ip_src_t src)653 static inline void CLOCK_SetIpSrc(clock_ip_name_t name, clock_ip_src_t src)
654 {
655     uint32_t reg = (*(volatile uint32_t *)((uint32_t)name));
656 
657     assert(reg & PCC_CLKCFG_PR_MASK);
658 
659     reg = (reg & ~PCC_CLKCFG_PCS_MASK) | PCC_CLKCFG_PCS(src);
660 
661     /*
662      * If clock is already enabled, first disable it, then set the clock
663      * source and re-enable it.
664      */
665     (*(volatile uint32_t *)((uint32_t)name)) = reg & ~PCC_CLKCFG_CGC_MASK;
666     (*(volatile uint32_t *)((uint32_t)name)) = reg;
667 }
668 
669 /*!
670  * @brief Set the clock source and divider for specific IP module.
671  *
672  * Set the clock source and divider for specific IP, not all modules need to
673  * set the clock source and divider, should only use this function for the
674  * modules need source and divider setting.
675  *
676  * Divider output clock = Divider input clock x [(fracValue+1)/(divValue+1)]).
677  *
678  * @param name Which peripheral to check, see \ref clock_ip_name_t.
679  * @param src Clock source to set.
680  * @param divValue  The divider value.
681  * @param fracValue The fraction multiply value.
682  */
CLOCK_SetIpSrcDiv(clock_ip_name_t name,clock_ip_src_t src,uint16_t divValue,uint8_t fracValue)683 static inline void CLOCK_SetIpSrcDiv(clock_ip_name_t name, clock_ip_src_t src, uint16_t divValue, uint8_t fracValue)
684 {
685     uint32_t reg = (*(volatile uint32_t *)(uint32_t)name);
686 
687     assert((reg & PCC_CLKCFG_PR_MASK) != 0UL);
688 
689     reg = (reg & ~(PCC_CLKCFG_PCS_MASK | PCC_CLKCFG_FRAC_MASK | PCC_CLKCFG_PCD_MASK)) | PCC_CLKCFG_PCS(src) |
690           PCC_CLKCFG_PCD(divValue) | PCC_CLKCFG_FRAC(fracValue);
691 
692     /*
693      * If clock is already enabled, first disable it, then set the clock
694      * source and re-enable it.
695      */
696     (*(volatile uint32_t *)(uint32_t)name) = reg & ~PCC_CLKCFG_CGC_MASK;
697     (*(volatile uint32_t *)(uint32_t)name) = reg;
698 }
699 
700 /*!
701  * @brief Gets the clock frequency for a specific clock name.
702  *
703  * This function checks the current clock configurations and then calculates
704  * the clock frequency for a specific clock name defined in clock_name_t.
705  *
706  * @param clockName Clock names defined in clock_name_t
707  * @return Clock frequency value in hertz
708  */
709 uint32_t CLOCK_GetFreq(clock_name_t clockName);
710 
711 /*!
712  * @brief Get the core clock or system clock frequency.
713  *
714  * @return Clock frequency in Hz.
715  */
716 uint32_t CLOCK_GetCoreSysClkFreq(void);
717 
718 /*!
719  * @brief Get the bus clock frequency.
720  *
721  * @return Clock frequency in Hz.
722  */
723 uint32_t CLOCK_GetBusClkFreq(void);
724 
725 /*!
726  * @brief Get the flash clock frequency.
727  *
728  * @return Clock frequency in Hz.
729  */
730 uint32_t CLOCK_GetFlashClkFreq(void);
731 
732 /*!
733  * @brief Get the external reference clock frequency (ERCLK).
734  *
735  * @return Clock frequency in Hz.
736  */
737 uint32_t CLOCK_GetErClkFreq(void);
738 
739 /*!
740  * @brief Gets the clock frequency for a specific IP module.
741  *
742  * This function gets the IP module clock frequency based on PCC registers. It is
743  * only used for the IP modules which could select clock source by PCC[PCS].
744  *
745  * @param name Which peripheral to get, see \ref clock_ip_name_t.
746  * @return Clock frequency value in hertz
747  */
748 uint32_t CLOCK_GetIpFreq(clock_ip_name_t name);
749 
750 /*!
751  * @name MCU System Clock.
752  * @{
753  */
754 
755 /*!
756  * @brief Gets the SCG system clock frequency.
757  *
758  * This function gets the SCG system clock frequency. These clocks are used for
759  * core, platform, external, and bus clock domains.
760  *
761  * @param type     Which type of clock to get, core clock or slow clock.
762  * @return  Clock frequency.
763  */
764 uint32_t CLOCK_GetSysClkFreq(scg_sys_clk_t type);
765 
766 /*!
767  * @brief Sets the system clock configuration for VLPR mode.
768  *
769  * This function sets the system clock configuration for VLPR mode.
770  *
771  * @param config Pointer to the configuration.
772  */
CLOCK_SetVlprModeSysClkConfig(const scg_sys_clk_config_t * config)773 static inline void CLOCK_SetVlprModeSysClkConfig(const scg_sys_clk_config_t *config)
774 {
775     assert(config);
776     union
777     {
778         const uint32_t *configInt;
779         const scg_sys_clk_config_t *configPtr;
780     } Config;
781 
782     Config.configPtr = config;
783     SCG->VCCR        = *(Config.configInt);
784 }
785 
786 /*!
787  * @brief Sets the system clock configuration for RUN mode.
788  *
789  * This function sets the system clock configuration for RUN mode.
790  *
791  * @param config Pointer to the configuration.
792  */
CLOCK_SetRunModeSysClkConfig(const scg_sys_clk_config_t * config)793 static inline void CLOCK_SetRunModeSysClkConfig(const scg_sys_clk_config_t *config)
794 {
795     assert(config);
796     union
797     {
798         const uint32_t *configInt;
799         const scg_sys_clk_config_t *configPtr;
800     } Config;
801 
802     Config.configPtr = config;
803     SCG->RCCR        = *(Config.configInt);
804 }
805 
806 /*!
807  * @brief Sets the system clock configuration for HSRUN mode.
808  *
809  * This function sets the system clock configuration for HSRUN mode.
810  *
811  * @param config Pointer to the configuration.
812  */
CLOCK_SetHsrunModeSysClkConfig(const scg_sys_clk_config_t * config)813 static inline void CLOCK_SetHsrunModeSysClkConfig(const scg_sys_clk_config_t *config)
814 {
815     assert(config);
816     union
817     {
818         const uint32_t *configInt;
819         const scg_sys_clk_config_t *configPtr;
820     } Config;
821 
822     Config.configPtr = config;
823     SCG->HCCR        = *(Config.configInt);
824 }
825 
826 /*!
827  * @brief Gets the system clock configuration in the current power mode.
828  *
829  * This function gets the system configuration in the current power mode.
830  *
831  * @param config Pointer to the configuration.
832  */
CLOCK_GetCurSysClkConfig(scg_sys_clk_config_t * config)833 static inline void CLOCK_GetCurSysClkConfig(scg_sys_clk_config_t *config)
834 {
835     assert(config);
836     union
837     {
838         uint32_t *configInt;
839         scg_sys_clk_config_t *configPtr;
840     } Config;
841 
842     Config.configPtr    = config;
843     *(Config.configInt) = SCG->CSR;
844 }
845 
846 /*!
847  * @brief Sets the clock out selection.
848  *
849  * This function sets the clock out selection (CLKOUTSEL).
850  *
851  * @param setting The selection to set.
852  * @return  The current clock out selection.
853  */
CLOCK_SetClkOutSel(clock_clkout_src_t setting)854 static inline void CLOCK_SetClkOutSel(clock_clkout_src_t setting)
855 {
856     SCG->CLKOUTCNFG = SCG_CLKOUTCNFG_CLKOUTSEL(setting);
857 }
858 /* @} */
859 
860 /*!
861  * @name SCG System OSC Clock.
862  * @{
863  */
864 
865 /*!
866  * @brief Initializes the SCG system OSC.
867  *
868  * This function enables the SCG system OSC clock according to the
869  * configuration.
870  *
871  * @param config   Pointer to the configuration structure.
872  * @retval kStatus_Success System OSC is initialized.
873  * @retval kStatus_SCG_Busy System OSC has been enabled and is used by the system clock.
874  * @retval kStatus_ReadOnly System OSC control register is locked.
875  *
876  * @note This function can't detect whether the system OSC has been enabled and
877  * used by an IP.
878  */
879 status_t CLOCK_InitSysOsc(const scg_sosc_config_t *config);
880 
881 /*!
882  * @brief De-initializes the SCG system OSC.
883  *
884  * This function disables the SCG system OSC clock.
885  *
886  * @retval kStatus_Success System OSC is deinitialized.
887  * @retval kStatus_SCG_Busy System OSC is used by the system clock.
888  * @retval kStatus_ReadOnly System OSC control register is locked.
889  *
890  * @note This function can't detect whether the system OSC is used by an IP.
891  */
892 status_t CLOCK_DeinitSysOsc(void);
893 
894 /*!
895  * @brief Set the asynchronous clock divider.
896  *
897  * @param asyncClk Which asynchronous clock to configure.
898  * @param divider The divider value to set.
899  *
900  * @note There might be glitch when changing the asynchronous divider, so make sure
901  * the asynchronous clock is not used while changing divider.
902  */
CLOCK_SetSysOscAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)903 static inline void CLOCK_SetSysOscAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
904 {
905     uint32_t reg = SCG->SOSCDIV;
906 
907     switch (asyncClk)
908     {
909         case kSCG_AsyncDiv2Clk:
910             reg = (reg & ~SCG_SOSCDIV_SOSCDIV2_MASK) | SCG_SOSCDIV_SOSCDIV2(divider);
911             break;
912         default:
913             /* All the cases have been listed above, the default clause should not be reached. */
914             assert(false);
915             break;
916     }
917 
918     SCG->SOSCDIV = reg;
919 }
920 
921 /*!
922  * @brief Gets the SCG system OSC clock frequency (SYSOSC).
923  *
924  * @return  Clock frequency; If the clock is invalid, returns 0.
925  */
926 uint32_t CLOCK_GetSysOscFreq(void);
927 
928 /*!
929  * @brief Gets the SCG asynchronous clock frequency from the system OSC.
930  *
931  * @param type     The asynchronous clock type.
932  * @return  Clock frequency; If the clock is invalid, returns 0.
933  */
934 uint32_t CLOCK_GetSysOscAsyncFreq(scg_async_clk_t type);
935 
936 /*!
937  * @brief Checks whether the system OSC clock error occurs.
938  *
939  * @return  True if the error occurs, false if not.
940  */
CLOCK_IsSysOscErr(void)941 static inline bool CLOCK_IsSysOscErr(void)
942 {
943     return (bool)(SCG->SOSCCSR & SCG_SOSCCSR_SOSCERR_MASK);
944 }
945 
946 /*!
947  * @brief Clears the system OSC clock error.
948  */
CLOCK_ClearSysOscErr(void)949 static inline void CLOCK_ClearSysOscErr(void)
950 {
951     SCG->SOSCCSR |= SCG_SOSCCSR_SOSCERR_MASK;
952 }
953 
954 /*!
955  * @brief Sets the system OSC monitor mode.
956  *
957  * This function sets the system OSC monitor mode. The mode can be disabled,
958  * it can generate an interrupt when the error is disabled, or reset when the error is detected.
959  *
960  * @param mode Monitor mode to set.
961  */
CLOCK_SetSysOscMonitorMode(scg_sosc_monitor_mode_t mode)962 static inline void CLOCK_SetSysOscMonitorMode(scg_sosc_monitor_mode_t mode)
963 {
964     uint32_t reg = SCG->SOSCCSR;
965 
966     reg &= ~(SCG_SOSCCSR_SOSCCM_MASK | SCG_SOSCCSR_SOSCCMRE_MASK);
967 
968     reg |= (uint32_t)mode;
969 
970     SCG->SOSCCSR = reg;
971 }
972 
973 /*!
974  * @brief Checks whether the system OSC clock is valid.
975  *
976  * @return  True if clock is valid, false if not.
977  */
CLOCK_IsSysOscValid(void)978 static inline bool CLOCK_IsSysOscValid(void)
979 {
980     return (bool)(SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK);
981 }
982 /* @} */
983 
984 /*!
985  * @name SCG Slow IRC Clock.
986  * @{
987  */
988 
989 /*!
990  * @brief Initializes the SCG slow IRC clock.
991  *
992  * This function enables the SCG slow IRC clock according to the
993  * configuration.
994  *
995  * @param config   Pointer to the configuration structure.
996  * @retval kStatus_Success SIRC is initialized.
997  * @retval kStatus_SCG_Busy SIRC has been enabled and is used by system clock.
998  * @retval kStatus_ReadOnly SIRC control register is locked.
999  *
1000  * @note This function can't detect whether the system OSC has been enabled and
1001  * used by an IP.
1002  */
1003 status_t CLOCK_InitSirc(const scg_sirc_config_t *config);
1004 
1005 /*!
1006  * @brief De-initializes the SCG slow IRC.
1007  *
1008  * This function disables the SCG slow IRC.
1009  *
1010  * @retval kStatus_Success SIRC is deinitialized.
1011  * @retval kStatus_SCG_Busy SIRC is used by system clock.
1012  * @retval kStatus_ReadOnly SIRC control register is locked.
1013  *
1014  * @note This function can't detect whether the SIRC is used by an IP.
1015  */
1016 status_t CLOCK_DeinitSirc(void);
1017 
1018 /*!
1019  * @brief Set the asynchronous clock divider.
1020  *
1021  * @param asyncClk Which asynchronous clock to configure.
1022  * @param divider The divider value to set.
1023  *
1024  * @note There might be glitch when changing the asynchronous divider, so make sure
1025  * the asynchronous clock is not used while changing divider.
1026  */
CLOCK_SetSircAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)1027 static inline void CLOCK_SetSircAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
1028 {
1029     uint32_t reg = SCG->SIRCDIV;
1030 
1031     switch (asyncClk)
1032     {
1033         case kSCG_AsyncDiv2Clk:
1034             reg = (reg & ~SCG_SIRCDIV_SIRCDIV2_MASK) | SCG_SIRCDIV_SIRCDIV2(divider);
1035             break;
1036         default:
1037             /* All the cases have been listed above, the default clause should not be reached. */
1038             assert(false);
1039             break;
1040     }
1041 
1042     SCG->SIRCDIV = reg;
1043 }
1044 
1045 /*!
1046  * @brief Gets the SCG SIRC clock frequency.
1047  *
1048  * @return  Clock frequency; If the clock is invalid, returns 0.
1049  */
1050 uint32_t CLOCK_GetSircFreq(void);
1051 
1052 /*!
1053  * @brief Gets the SCG asynchronous clock frequency from the SIRC.
1054  *
1055  * @param type     The asynchronous clock type.
1056  * @return  Clock frequency; If the clock is invalid, returns 0.
1057  */
1058 uint32_t CLOCK_GetSircAsyncFreq(scg_async_clk_t type);
1059 
1060 /*!
1061  * @brief Checks whether the SIRC clock is valid.
1062  *
1063  * @return  True if clock is valid, false if not.
1064  */
CLOCK_IsSircValid(void)1065 static inline bool CLOCK_IsSircValid(void)
1066 {
1067     return (bool)(SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK);
1068 }
1069 /* @} */
1070 
1071 /*!
1072  * @name SCG Fast IRC Clock.
1073  * @{
1074  */
1075 
1076 /*!
1077  * @brief Initializes the SCG fast IRC clock.
1078  *
1079  * This function enables the SCG fast IRC clock according to the configuration.
1080  *
1081  * @param config   Pointer to the configuration structure.
1082  * @retval kStatus_Success FIRC is initialized.
1083  * @retval kStatus_SCG_Busy FIRC has been enabled and is used by the system clock.
1084  * @retval kStatus_ReadOnly FIRC control register is locked.
1085  *
1086  * @note This function can't detect whether the FIRC has been enabled and
1087  * used by an IP.
1088  */
1089 status_t CLOCK_InitFirc(const scg_firc_config_t *config);
1090 
1091 /*!
1092  * @brief De-initializes the SCG fast IRC.
1093  *
1094  * This function disables the SCG fast IRC.
1095  *
1096  * @retval kStatus_Success FIRC is deinitialized.
1097  * @retval kStatus_SCG_Busy FIRC is used by the system clock.
1098  * @retval kStatus_ReadOnly FIRC control register is locked.
1099  *
1100  * @note This function can't detect whether the FIRC is used by an IP.
1101  */
1102 status_t CLOCK_DeinitFirc(void);
1103 
1104 /*!
1105  * @brief Set the asynchronous clock divider.
1106  *
1107  * @param asyncClk Which asynchronous clock to configure.
1108  * @param divider The divider value to set.
1109  *
1110  * @note There might be glitch when changing the asynchronous divider, so make sure
1111  * the asynchronous clock is not used while changing divider.
1112  */
CLOCK_SetFircAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)1113 static inline void CLOCK_SetFircAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
1114 {
1115     uint32_t reg = SCG->FIRCDIV;
1116 
1117     switch (asyncClk)
1118     {
1119         case kSCG_AsyncDiv2Clk:
1120             reg = (reg & ~SCG_FIRCDIV_FIRCDIV2_MASK) | SCG_FIRCDIV_FIRCDIV2(divider);
1121             break;
1122         default:
1123             /* All the cases have been listed above, the default clause should not be reached. */
1124             assert(false);
1125             break;
1126     }
1127 
1128     SCG->FIRCDIV = reg;
1129 }
1130 
1131 /*!
1132  * @brief Gets the SCG FIRC clock frequency.
1133  *
1134  * @return  Clock frequency; If the clock is invalid, returns 0.
1135  */
1136 uint32_t CLOCK_GetFircFreq(void);
1137 
1138 /*!
1139  * @brief Gets the SCG asynchronous clock frequency from the FIRC.
1140  *
1141  * @param type     The asynchronous clock type.
1142  * @return  Clock frequency; If the clock is invalid, returns 0.
1143  */
1144 uint32_t CLOCK_GetFircAsyncFreq(scg_async_clk_t type);
1145 
1146 /*!
1147  * @brief Checks whether the FIRC clock error occurs.
1148  *
1149  * @return  True if the error occurs, false if not.
1150  */
CLOCK_IsFircErr(void)1151 static inline bool CLOCK_IsFircErr(void)
1152 {
1153     return (bool)(SCG->FIRCCSR & SCG_FIRCCSR_FIRCERR_MASK);
1154 }
1155 
1156 /*!
1157  * @brief Clears the FIRC clock error.
1158  */
CLOCK_ClearFircErr(void)1159 static inline void CLOCK_ClearFircErr(void)
1160 {
1161     SCG->FIRCCSR |= SCG_FIRCCSR_FIRCERR_MASK;
1162 }
1163 
1164 /*!
1165  * @brief Checks whether the FIRC clock is valid.
1166  *
1167  * @return  True if clock is valid, false if not.
1168  */
CLOCK_IsFircValid(void)1169 static inline bool CLOCK_IsFircValid(void)
1170 {
1171     return (bool)(SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK);
1172 }
1173 /* @} */
1174 
1175 /*!
1176  * @name SCG Low Power FLL Clock.
1177  * @{
1178  */
1179 /*!
1180  * @brief Initializes the SCG LPFLL clock.
1181  *
1182  * This function enables the SCG LPFLL clock according to the configuration.
1183  *
1184  * @param config   Pointer to the configuration structure.
1185  * @retval kStatus_Success LPFLL is initialized.
1186  * @retval kStatus_SCG_Busy LPFLL has been enabled and is used by the system clock.
1187  * @retval kStatus_ReadOnly LPFLL control register is locked.
1188  *
1189  * @note This function can't detect whether the LPFLL has been enabled and
1190  * used by an IP.
1191  */
1192 status_t CLOCK_InitLpFll(const scg_lpfll_config_t *config);
1193 
1194 /*!
1195  * @brief De-initializes the SCG LPFLL.
1196  *
1197  * This function disables the SCG LPFLL.
1198  *
1199  * @retval kStatus_Success LPFLL is deinitialized.
1200  * @retval kStatus_SCG_Busy LPFLL is used by the system clock.
1201  * @retval kStatus_ReadOnly LPFLL control register is locked.
1202  *
1203  * @note This function can't detect whether the LPFLL is used by an IP.
1204  */
1205 status_t CLOCK_DeinitLpFll(void);
1206 
1207 /*!
1208  * @brief Set the asynchronous clock divider.
1209  *
1210  * @param asyncClk Which asynchronous clock to configure.
1211  * @param divider The divider value to set.
1212  *
1213  * @note There might be glitch when changing the asynchronous divider, so make sure
1214  * the asynchronous clock is not used while changing divider.
1215  */
CLOCK_SetLpFllAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)1216 static inline void CLOCK_SetLpFllAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
1217 {
1218     uint32_t reg = SCG->LPFLLDIV;
1219 
1220     switch (asyncClk)
1221     {
1222         case kSCG_AsyncDiv2Clk:
1223             reg = (reg & ~SCG_LPFLLDIV_LPFLLDIV2_MASK) | SCG_LPFLLDIV_LPFLLDIV2(divider);
1224             break;
1225         default:
1226             /* All the cases have been listed above, the default clause should not be reached. */
1227             assert(false);
1228             break;
1229     }
1230 
1231     SCG->LPFLLDIV = reg;
1232 }
1233 
1234 /*!
1235  * @brief Gets the SCG LPFLL clock frequency.
1236  *
1237  * @return  Clock frequency in Hz; If the clock is invalid, returns 0.
1238  */
1239 uint32_t CLOCK_GetLpFllFreq(void);
1240 
1241 /*!
1242  * @brief Gets the SCG asynchronous clock frequency from the LPFLL.
1243  *
1244  * @param type     The asynchronous clock type.
1245  * @return  Clock frequency in Hz; If the clock is invalid, returns 0.
1246  */
1247 uint32_t CLOCK_GetLpFllAsyncFreq(scg_async_clk_t type);
1248 
1249 /*!
1250  * @brief Checks whether the LPFLL clock is valid.
1251  *
1252  * @return  True if the clock is valid, false if not.
1253  */
CLOCK_IsLpFllValid(void)1254 static inline bool CLOCK_IsLpFllValid(void)
1255 {
1256     return (bool)(SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLVLD_MASK);
1257 }
1258 /* @} */
1259 
1260 /*!
1261  * @name External clock frequency
1262  * @{
1263  */
1264 
1265 /*!
1266  * @brief Sets the XTAL0 frequency based on board settings.
1267  *
1268  * @param freq The XTAL0/EXTAL0 input clock frequency in Hz.
1269  */
CLOCK_SetXtal0Freq(uint32_t freq)1270 static inline void CLOCK_SetXtal0Freq(uint32_t freq)
1271 {
1272     g_xtal0Freq = freq;
1273 }
1274 
1275 /* @} */
1276 
1277 #if defined(__cplusplus)
1278 }
1279 #endif /* __cplusplus */
1280 
1281 /*! @} */
1282 
1283 #endif /* _FSL_CLOCK_H_ */
1284