1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2017 , NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef _FSL_CLOCK_H_
10 #define _FSL_CLOCK_H_
11 
12 #include "fsl_common.h"
13 
14 /*! @addtogroup clock */
15 /*! @{ */
16 
17 /*! @file */
18 
19 /*******************************************************************************
20  * Configurations
21  ******************************************************************************/
22 
23 /*! @brief Configure whether driver controls clock
24  *
25  * When set to 0, peripheral drivers will enable clock in initialize function
26  * and disable clock in de-initialize function. When set to 1, peripheral
27  * driver will not control the clock, application could control the clock out of
28  * the driver.
29  *
30  * @note All drivers share this feature switcher. If it is set to 1, application
31  * should handle clock enable and disable for all drivers.
32  */
33 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
34 #define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0
35 #endif
36 
37 /*******************************************************************************
38  * Definitions
39  ******************************************************************************/
40 
41 /*! @name Driver version */
42 /*@{*/
43 /*! @brief CLOCK driver version 2.2.1. */
44 #define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 1))
45 /*@}*/
46 
47 /* Definition for delay API in clock driver, users can redefine it to the real application. */
48 #ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY
49 #define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (120000000UL)
50 #endif
51 
52 /*! @brief External XTAL0 (OSC0/SYSOSC) clock frequency.
53  *
54  * The XTAL0/EXTAL0 (OSC0/SYSOSC) clock frequency in Hz. When the clock is set up, use the
55  * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example,
56  * if XTAL0 is 8 MHz:
57  * @code
58  * CLOCK_InitSysOsc(...);
59  * CLOCK_SetXtal0Freq(80000000);
60  * @endcode
61  *
62  * This is important for the multicore platforms where only one core needs to set up the
63  * OSC0/SYSOSC using CLOCK_InitSysOsc. All other cores need to call the CLOCK_SetXtal0Freq
64  * to get a valid clock frequency.
65  */
66 extern volatile uint32_t g_xtal0Freq;
67 
68 /*! @brief External XTAL32/EXTAL32 clock frequency.
69  *
70  * The XTAL32/EXTAL32 clock frequency in Hz. When the clock is set up, use the
71  * function CLOCK_SetXtal32Freq to set the value in the clock driver.
72  *
73  * This is important for the multicore platforms where only one core needs to set up
74  * the clock. All other cores need to call the CLOCK_SetXtal32Freq
75  * to get a valid clock frequency.
76  */
77 extern volatile uint32_t g_xtal32Freq;
78 
79 /*! @brief Clock ip name array for MAX. */
80 #define MAX_CLOCKS  \
81     {               \
82         kCLOCK_Max0 \
83     }
84 
85 /*! @brief Clock ip name array for EDMA. */
86 #define EDMA_CLOCKS                \
87     {                              \
88         kCLOCK_Edma0, kCLOCK_Edma1 \
89     }
90 
91 /*! @brief Clock ip name array for FLEXBUS. */
92 #define FLEXBUS_CLOCKS \
93     {                  \
94         kCLOCK_Flexbus \
95     }
96 
97 /*! @brief XRDC clock gate number. */
98 #define FSL_CLOCK_XRDC_GATE_COUNT (5U)
99 
100 /*! @brief Clock ip name array for XRDC. */
101 #define XRDC_CLOCKS                                                                           \
102     {                                                                                         \
103         kCLOCK_Xrdc0Mgr, kCLOCK_Xrdc0Pac, kCLOCK_Xrdc0Mrc, kCLOCK_Xrdc0PacB, kCLOCK_Xrdc0MrcB \
104     }
105 
106 /*! @brief Clock ip name array for SEMA42. */
107 #define SEMA42_CLOCKS                  \
108     {                                  \
109         kCLOCK_Sema420, kCLOCK_Sema421 \
110     }
111 
112 /*! @brief Clock ip name array for DMAMUX. */
113 #define DMAMUX_CLOCKS                  \
114     {                                  \
115         kCLOCK_Dmamux0, kCLOCK_Dmamux1 \
116     }
117 
118 /*! @brief Clock ip name array for MU. */
119 #if defined(K32L3A60_cm0plus_SERIES)
120 #define MU_CLOCKS  \
121     {              \
122         kCLOCK_MuB \
123     }
124 #else
125 #define MU_CLOCKS  \
126     {              \
127         kCLOCK_MuA \
128     }
129 #endif
130 
131 /*! @brief Clock ip name array for CRC. */
132 #define CRC_CLOCKS  \
133     {               \
134         kCLOCK_Crc0 \
135     }
136 
137 /*! @brief Clock ip name array for LPIT. */
138 #define LPIT_CLOCKS                \
139     {                              \
140         kCLOCK_Lpit0, kCLOCK_Lpit1 \
141     }
142 
143 /*! @brief Clock ip name array for TPM. */
144 #define TPM_CLOCKS                                         \
145     {                                                      \
146         kCLOCK_Tpm0, kCLOCK_Tpm1, kCLOCK_Tpm2, kCLOCK_Tpm3 \
147     }
148 
149 /*! @brief Clock ip name array for TRNG. */
150 #define TRNG_CLOCKS \
151     {               \
152         kCLOCK_Trng \
153     }
154 
155 /*! @brief Clock ip name array for SMVSIM. */
156 #define EMVSIM_CLOCKS  \
157     {                  \
158         kCLOCK_Emvsim0 \
159     }
160 
161 /*! @brief Clock ip name array for EWM. */
162 #define EWM_CLOCKS  \
163     {               \
164         kCLOCK_Ewm0 \
165     }
166 
167 /*! @brief Clock ip name array for FLEXIO. */
168 #define FLEXIO_CLOCKS  \
169     {                  \
170         kCLOCK_Flexio0 \
171     }
172 
173 /*! @brief Clock ip name array for LPI2C0. */
174 #define LPI2C_CLOCKS                                               \
175     {                                                              \
176         kCLOCK_Lpi2c0, kCLOCK_Lpi2c1, kCLOCK_Lpi2c2, kCLOCK_Lpi2c3 \
177     }
178 
179 /*! @brief Clock ip name array for SAI. */
180 #define SAI_CLOCKS  \
181     {               \
182         kCLOCK_Sai0 \
183     }
184 
185 /*! @brief Clock ip name array for SDHC. */
186 #define USDHC_CLOCKS \
187     {                \
188         kCLOCK_Sdhc0 \
189     }
190 
191 /*! @brief Clock ip name array for LPSPI. */
192 #define LPSPI_CLOCKS                                               \
193     {                                                              \
194         kCLOCK_Lpspi0, kCLOCK_Lpspi1, kCLOCK_Lpspi2, kCLOCK_Lpspi3 \
195     }
196 
197 /*! @brief Clock ip name array for LPUART. */
198 #define LPUART_CLOCKS                                                  \
199     {                                                                  \
200         kCLOCK_Lpuart0, kCLOCK_Lpuart1, kCLOCK_Lpuart2, kCLOCK_Lpuart3 \
201     }
202 
203 /*! @brief Clock ip name array for USB. */
204 #define USB_CLOCKS  \
205     {               \
206         kCLOCK_Usb0 \
207     }
208 
209 /*! @brief Clock ip name array for PORT. */
210 #define PORT_CLOCKS                                                          \
211     {                                                                        \
212         kCLOCK_PortA, kCLOCK_PortB, kCLOCK_PortC, kCLOCK_PortD, kCLOCK_PortE \
213     }
214 
215 /*! @brief Clock ip name array for LPADC. */
216 #define LPADC_CLOCKS  \
217     {                 \
218         kCLOCK_Lpadc0 \
219     }
220 
221 /*! @brief Clock ip name array for DAC. */
222 #define LPDAC_CLOCKS \
223     {                \
224         kCLOCK_Dac0  \
225     }
226 
227 /*! @brief Clock ip name array for INTMUX. */
228 #define INTMUX_CLOCKS                    \
229     {                                    \
230         kCLOCK_IpInvalid, kCLOCK_Intmux0 \
231     }
232 
233 /*! @brief Clock ip name array for EXT. */
234 #define EXT_CLOCKS               \
235     {                            \
236         kCLOCK_Ext0, kCLOCK_Ext1 \
237     }
238 
239 /*! @brief Clock ip name array for VREF. */
240 #define VREF_CLOCKS \
241     {               \
242         kCLOCK_Vref \
243     }
244 
245 /*! @brief Clock ip name array for FGPIO. */
246 #define FGPIO_CLOCKS                                                                          \
247     {                                                                                         \
248         kCLOCK_IpInvalid, kCLOCK_IpInvalid, kCLOCK_IpInvalid, kCLOCK_IpInvalid, kCLOCK_GpioE \
249     }
250 
251 /*! @brief Clock name used to get clock frequency.
252  *
253  * These clocks source would be generated from SCG module.
254  */
255 typedef enum _clock_name
256 {
257     /* ----------------------------- System layer clock -------------------------------*/
258     kCLOCK_CoreSysClk, /*!< Core 0/1 clock. */
259     kCLOCK_SlowClk,    /*!< SLOW_CLK with DIVSLOW. */
260     kCLOCK_PlatClk,    /*!< PLAT_CLK. */
261     kCLOCK_SysClk,     /*!< SYS_CLK. */
262     kCLOCK_BusClk,     /*!< BUS_CLK with DIVBUS. */
263     kCLOCK_ExtClk,     /*!< One clock selection of CLKOUT from main clock after DIVCORE and DIVEXT divider.*/
264 
265     /* ------------------------------------ SCG clock ---------------------------------*/
266     kCLOCK_ScgSysLpFllAsyncDiv1Clk, /*!< LPFLL_DIV1_CLK. */
267     kCLOCK_ScgSysLpFllAsyncDiv2Clk, /*!< LPFLL_DIV1_CLK. */
268     kCLOCK_ScgSysLpFllAsyncDiv3Clk, /*!< LPFLL_DIV1_CLK. */
269 
270     kCLOCK_ScgSircAsyncDiv1Clk, /*!< SIRCDIV1_CLK.                                   */
271     kCLOCK_ScgSircAsyncDiv2Clk, /*!< SIRCDIV2_CLK.                                   */
272     kCLOCK_ScgSircAsyncDiv3Clk, /*!< SIRCDIV3_CLK.                                   */
273 
274     kCLOCK_ScgFircAsyncDiv1Clk, /*!< FIRCDIV1_CLK.                                   */
275     kCLOCK_ScgFircAsyncDiv2Clk, /*!< FIRCDIV2_CLK.                                   */
276     kCLOCK_ScgFircAsyncDiv3Clk, /*!< FIRCDIV3_CLK.                                   */
277 
278     /* For SCG_CLKOUT output */
279     /* kCLOCK_ExtClk, */
280     kCLOCK_ScgSircClk,  /*!< SCG SIRC clock.                                     */
281     kCLOCK_ScgFircClk,  /*!< SCG FIRC clock.                                     */
282     kCLOCK_RtcOscClk,   /*!< RTC OSC clock. */
283     kCLOCK_ScgLpFllClk, /*!< SCG Low-power FLL clock. (LPFLL)                     */
284 
285     /* --------------------------------- Other clock ----------------------------------*/
286     kCLOCK_LpoClk,    /*!< LPO clock                                           */
287     kCLOCK_Osc32kClk, /*!< External OSC 32K clock (OSC32KCLK)                  */
288 } clock_name_t;
289 
290 #define kCLOCK_FlashClk kCLOCK_SlowClk
291 #define LPO_CLK_FREQ 1000U
292 
293 /*!
294  * @brief Clock source for peripherals that support various clock selections.
295  *
296  * These options are for PCC->CLKCFG[PCS].
297  */
298 typedef enum _clock_ip_src
299 {
300     kCLOCK_IpSrcNoneOrExt  = 0U, /*!< Clock is off or external clock is used. */
301     kCLOCK_IpSrcSircAsync  = 2U, /*!< Slow IRC async clock.                   */
302     kCLOCK_IpSrcFircAsync  = 3U, /*!< Fast IRC async clock.                   */
303     kCLOCK_IpSrcLpFllAsync = 6U  /*!< System LPFLL async clock.               */
304 } clock_ip_src_t;
305 
306 /*!
307  * @brief Peripheral clock name difinition used for clock gate, clock source
308  * and clock divider setting. It is defined as the corresponding register address.
309  */
310 #define MAKE_PCC_REGADDR(base, offset) ((base) + (offset))
311 typedef enum _clock_ip_name
312 {
313     kCLOCK_IpInvalid = 0U,
314     /* PCC 0 */
315     kCLOCK_Mscm     = MAKE_PCC_REGADDR(PCC0_BASE, 0x4),
316     kCLOCK_Syspm    = MAKE_PCC_REGADDR(PCC0_BASE, 0xC),
317     kCLOCK_Max0     = MAKE_PCC_REGADDR(PCC0_BASE, 0x10),
318     kCLOCK_Edma0    = MAKE_PCC_REGADDR(PCC0_BASE, 0x20),
319     kCLOCK_Flexbus  = MAKE_PCC_REGADDR(PCC0_BASE, 0x30),
320     kCLOCK_Xrdc0Mgr = MAKE_PCC_REGADDR(PCC0_BASE, 0x50),
321     kCLOCK_Xrdc0Pac = MAKE_PCC_REGADDR(PCC0_BASE, 0x58),
322     kCLOCK_Xrdc0Mrc = MAKE_PCC_REGADDR(PCC0_BASE, 0x5C),
323     kCLOCK_Sema420  = MAKE_PCC_REGADDR(PCC0_BASE, 0x6C),
324     kCLOCK_Dmamux0  = MAKE_PCC_REGADDR(PCC0_BASE, 0x84),
325     kCLOCK_Ewm0     = MAKE_PCC_REGADDR(PCC0_BASE, 0x88),
326     kCLOCK_MuA      = MAKE_PCC_REGADDR(PCC0_BASE, 0x94),
327     kCLOCK_Crc0     = MAKE_PCC_REGADDR(PCC0_BASE, 0xBC),
328     kCLOCK_Lpit0    = MAKE_PCC_REGADDR(PCC0_BASE, 0xC0),
329     kCLOCK_Tpm0     = MAKE_PCC_REGADDR(PCC0_BASE, 0xD4),
330     kCLOCK_Tpm1     = MAKE_PCC_REGADDR(PCC0_BASE, 0xD8),
331     kCLOCK_Tpm2     = MAKE_PCC_REGADDR(PCC0_BASE, 0xDC),
332     kCLOCK_Emvsim0  = MAKE_PCC_REGADDR(PCC0_BASE, 0xE0),
333     kCLOCK_Flexio0  = MAKE_PCC_REGADDR(PCC0_BASE, 0xE4),
334     kCLOCK_Lpi2c0   = MAKE_PCC_REGADDR(PCC0_BASE, 0xE8),
335     kCLOCK_Lpi2c1   = MAKE_PCC_REGADDR(PCC0_BASE, 0xEC),
336     kCLOCK_Lpi2c2   = MAKE_PCC_REGADDR(PCC0_BASE, 0xF0),
337     kCLOCK_Sai0     = MAKE_PCC_REGADDR(PCC0_BASE, 0xF4),
338     kCLOCK_Sdhc0    = MAKE_PCC_REGADDR(PCC0_BASE, 0xF8),
339     kCLOCK_Lpspi0   = MAKE_PCC_REGADDR(PCC0_BASE, 0xFC),
340     kCLOCK_Lpspi1   = MAKE_PCC_REGADDR(PCC0_BASE, 0x100),
341     kCLOCK_Lpspi2   = MAKE_PCC_REGADDR(PCC0_BASE, 0x104),
342     kCLOCK_Lpuart0  = MAKE_PCC_REGADDR(PCC0_BASE, 0x108),
343     kCLOCK_Lpuart1  = MAKE_PCC_REGADDR(PCC0_BASE, 0x10C),
344     kCLOCK_Lpuart2  = MAKE_PCC_REGADDR(PCC0_BASE, 0x110),
345     kCLOCK_Usb0     = MAKE_PCC_REGADDR(PCC0_BASE, 0x114),
346     kCLOCK_PortA    = MAKE_PCC_REGADDR(PCC0_BASE, 0x118),
347     kCLOCK_PortB    = MAKE_PCC_REGADDR(PCC0_BASE, 0x11C),
348     kCLOCK_PortC    = MAKE_PCC_REGADDR(PCC0_BASE, 0x120),
349     kCLOCK_PortD    = MAKE_PCC_REGADDR(PCC0_BASE, 0x124),
350     kCLOCK_Lpadc0   = MAKE_PCC_REGADDR(PCC0_BASE, 0x128),
351     kCLOCK_Dac0     = MAKE_PCC_REGADDR(PCC0_BASE, 0x130),
352     kCLOCK_Vref     = MAKE_PCC_REGADDR(PCC0_BASE, 0x134),
353     kCLOCK_Atx      = MAKE_PCC_REGADDR(PCC0_BASE, 0x138),
354     kCLOCK_Trace    = MAKE_PCC_REGADDR(PCC0_BASE, 0x200),
355     /* PCC1. */
356     kCLOCK_Edma1     = MAKE_PCC_REGADDR(PCC1_BASE, 0x20),
357     kCLOCK_GpioE    = MAKE_PCC_REGADDR(PCC1_BASE, 0x3C),
358     kCLOCK_Xrdc0PacB = MAKE_PCC_REGADDR(PCC1_BASE, 0x58),
359     kCLOCK_Xrdc0MrcB = MAKE_PCC_REGADDR(PCC1_BASE, 0x5C),
360     kCLOCK_Sema421   = MAKE_PCC_REGADDR(PCC1_BASE, 0x6C),
361     kCLOCK_Dmamux1   = MAKE_PCC_REGADDR(PCC1_BASE, 0x84),
362     kCLOCK_Intmux0   = MAKE_PCC_REGADDR(PCC1_BASE, 0x88),
363     kCLOCK_MuB       = MAKE_PCC_REGADDR(PCC1_BASE, 0x90),
364     kCLOCK_Cau3      = MAKE_PCC_REGADDR(PCC1_BASE, 0xA0),
365     kCLOCK_Trng      = MAKE_PCC_REGADDR(PCC1_BASE, 0xA4),
366     kCLOCK_Lpit1     = MAKE_PCC_REGADDR(PCC1_BASE, 0xA8),
367     kCLOCK_Tpm3      = MAKE_PCC_REGADDR(PCC1_BASE, 0xB4),
368     kCLOCK_Lpi2c3    = MAKE_PCC_REGADDR(PCC1_BASE, 0xB8),
369     kCLOCK_Lpspi3    = MAKE_PCC_REGADDR(PCC1_BASE, 0xD4),
370     kCLOCK_Lpuart3   = MAKE_PCC_REGADDR(PCC1_BASE, 0xD8),
371     kCLOCK_PortE     = MAKE_PCC_REGADDR(PCC1_BASE, 0xDC),
372     kCLOCK_Ext0      = MAKE_PCC_REGADDR(PCC1_BASE, 0x200),
373     kCLOCK_Ext1      = MAKE_PCC_REGADDR(PCC1_BASE, 0x204),
374 } clock_ip_name_t;
375 
376 /*!
377  * @brief USB clock source definition.
378  */
379 typedef enum _clock_usb_src
380 {
381     kCLOCK_UsbSrcIrc48M = 1,          /*!< Use IRC48M.    */
382     kCLOCK_UsbSrcUnused = 0xFFFFFFFU, /*!< Used when the function does not
383                                                care the clock source. */
384 } clock_usb_src_t;
385 
386 /*!
387  * @brief SCG status return codes.
388  */
389 enum
390 {
391     kStatus_SCG_Busy       = MAKE_STATUS(kStatusGroup_SCG, 1), /*!< Clock is busy.  */
392     kStatus_SCG_InvalidSrc = MAKE_STATUS(kStatusGroup_SCG, 2)  /*!< Invalid source. */
393 };
394 
395 /*!
396  * @brief SCG system clock type.
397  */
398 typedef enum _scg_sys_clk
399 {
400     kSCG_SysClkSlow, /*!< System slow clock. */
401     kSCG_SysClkBus,  /*!< Bus clock.         */
402     kSCG_SysClkExt,  /*!< External clock.    */
403     kSCG_SysClkCore, /*!< Core clock.        */
404 } scg_sys_clk_t;
405 
406 /*!
407  * @brief SCG system clock source.
408  */
409 typedef enum _scg_sys_clk_src
410 {
411     kSCG_SysClkSrcSirc  = 2U, /*!< Slow IRC.   */
412     kSCG_SysClkSrcFirc  = 3U, /*!< Fast IRC.   */
413     kSCG_SysClkSrcRosc  = 4U, /*!< RTC OSC. */
414     kSCG_SysClkSrcLpFll = 5U, /*!< Low power FLL. */
415 } scg_sys_clk_src_t;
416 
417 /*!
418  * @brief SCG system clock divider value.
419  */
420 typedef enum _scg_sys_clk_div
421 {
422     kSCG_SysClkDivBy1  = 0U,  /*!< Divided by 1.  */
423     kSCG_SysClkDivBy2  = 1U,  /*!< Divided by 2.  */
424     kSCG_SysClkDivBy3  = 2U,  /*!< Divided by 3.  */
425     kSCG_SysClkDivBy4  = 3U,  /*!< Divided by 4.  */
426     kSCG_SysClkDivBy5  = 4U,  /*!< Divided by 5.  */
427     kSCG_SysClkDivBy6  = 5U,  /*!< Divided by 6.  */
428     kSCG_SysClkDivBy7  = 6U,  /*!< Divided by 7.  */
429     kSCG_SysClkDivBy8  = 7U,  /*!< Divided by 8.  */
430     kSCG_SysClkDivBy9  = 8U,  /*!< Divided by 9.  */
431     kSCG_SysClkDivBy10 = 9U,  /*!< Divided by 10. */
432     kSCG_SysClkDivBy11 = 10U, /*!< Divided by 11. */
433     kSCG_SysClkDivBy12 = 11U, /*!< Divided by 12. */
434     kSCG_SysClkDivBy13 = 12U, /*!< Divided by 13. */
435     kSCG_SysClkDivBy14 = 13U, /*!< Divided by 14. */
436     kSCG_SysClkDivBy15 = 14U, /*!< Divided by 15. */
437     kSCG_SysClkDivBy16 = 15U  /*!< Divided by 16. */
438 } scg_sys_clk_div_t;
439 
440 /*!
441  * @brief SCG system clock configuration.
442  */
443 typedef struct _scg_sys_clk_config
444 {
445     uint32_t divSlow : 4; /*!< Slow clock divider, see @ref scg_sys_clk_div_t. */
446     uint32_t divBus : 4;  /*!< Bus clock divider, see @ref scg_sys_clk_div_t.  */
447     uint32_t divExt : 4;  /*!< External clock divider, see @ref scg_sys_clk_div_t.  */
448     uint32_t : 4;         /*!< Reserved. */
449     uint32_t divCore : 4; /*!< Core clock divider, see @ref scg_sys_clk_div_t. */
450     uint32_t : 4;         /*!< Reserved. */
451     uint32_t src : 4;     /*!< System clock source, see @ref scg_sys_clk_src_t. */
452     uint32_t : 4;         /*!< reserved. */
453 } scg_sys_clk_config_t;
454 
455 /*!
456  * @brief SCG clock out configuration (CLKOUTSEL).
457  */
458 typedef enum _clock_clkout_src
459 {
460     kClockClkoutSelScgExt    = 0U, /*!< SCG external clock. */
461     kClockClkoutSelSirc      = 2U, /*!< Slow IRC.       */
462     kClockClkoutSelFirc      = 3U, /*!< Fast IRC.       */
463     kClockClkoutSelScgRtcOsc = 4U, /*!< SCG RTC OSC clock. */
464     kClockClkoutSelLpFll     = 5U, /*!< Low power FLL.  */
465 } clock_clkout_src_t;
466 
467 /*!
468  * @brief SCG asynchronous clock type.
469  */
470 typedef enum _scg_async_clk
471 {
472     kSCG_AsyncDiv1Clk, /*!< The async clock by DIV1, e.g. SOSCDIV1_CLK, SIRCDIV1_CLK. */
473     kSCG_AsyncDiv2Clk, /*!< The async clock by DIV2, e.g. SOSCDIV2_CLK, SIRCDIV2_CLK. */
474     kSCG_AsyncDiv3Clk  /*!< The async clock by DIV3, e.g. SOSCDIV3_CLK, SIRCDIV3_CLK. */
475 } scg_async_clk_t;
476 
477 /*!
478  * @brief SCG asynchronous clock divider value.
479  */
480 typedef enum scg_async_clk_div
481 {
482     kSCG_AsyncClkDisable = 0U, /*!< Clock output is disabled.  */
483     kSCG_AsyncClkDivBy1  = 1U, /*!< Divided by 1.              */
484     kSCG_AsyncClkDivBy2  = 2U, /*!< Divided by 2.              */
485     kSCG_AsyncClkDivBy4  = 3U, /*!< Divided by 4.              */
486     kSCG_AsyncClkDivBy8  = 4U, /*!< Divided by 8.              */
487     kSCG_AsyncClkDivBy16 = 5U, /*!< Divided by 16.             */
488     kSCG_AsyncClkDivBy32 = 6U, /*!< Divided by 32.             */
489     kSCG_AsyncClkDivBy64 = 7U  /*!< Divided by 64.             */
490 } scg_async_clk_div_t;
491 
492 /*!
493  * @brief SCG slow IRC clock frequency range.
494  */
495 typedef enum _scg_sirc_range
496 {
497     kSCG_SircRangeLow, /*!< Slow IRC low range clock (2 MHz, 4 MHz for i.MX 7 ULP).  */
498     kSCG_SircRangeHigh /*!< Slow IRC high range clock (8 MHz, 16 MHz for i.MX 7 ULP). */
499 } scg_sirc_range_t;
500 
501 /*! @brief SIRC enable mode. */
502 enum _scg_sirc_enable_mode
503 {
504     kSCG_SircEnable           = SCG_SIRCCSR_SIRCEN_MASK,   /*!< Enable SIRC clock.             */
505     kSCG_SircEnableInStop     = SCG_SIRCCSR_SIRCSTEN_MASK, /*!< Enable SIRC in stop mode.      */
506     kSCG_SircEnableInLowPower = SCG_SIRCCSR_SIRCLPEN_MASK  /*!< Enable SIRC in low power mode. */
507 };
508 
509 /*!
510  * @brief SCG slow IRC clock configuration.
511  */
512 typedef struct _scg_sirc_config
513 {
514     uint32_t enableMode;      /*!< Enable mode, OR'ed value of _scg_sirc_enable_mode. */
515     scg_async_clk_div_t div1; /*!< SIRCDIV1 value.                          */
516     scg_async_clk_div_t div2; /*!< SIRCDIV2 value.                          */
517     scg_async_clk_div_t div3; /*!< SIRCDIV3 value.                          */
518 
519     scg_sirc_range_t range; /*!< Slow IRC frequency range.                */
520 } scg_sirc_config_t;
521 
522 /*!
523  * @brief SCG fast IRC trim mode.
524  */
525 typedef enum _scg_firc_trim_mode
526 {
527     kSCG_FircTrimNonUpdate = SCG_FIRCCSR_FIRCTREN_MASK,
528     /*!< FIRC trim enable but not enable trim value update. In this mode, the
529      trim value is fixed to the initialized value which is defined by
530      trimCoar and trimFine in configure structure \ref scg_firc_trim_config_t.*/
531 
532     kSCG_FircTrimUpdate = SCG_FIRCCSR_FIRCTREN_MASK | SCG_FIRCCSR_FIRCTRUP_MASK
533     /*!< FIRC trim enable and trim value update enable. In this mode, the trim
534      value is auto update. */
535 
536 } scg_firc_trim_mode_t;
537 
538 /*!
539  * @brief SCG fast IRC trim predivided value for system OSC.
540  */
541 typedef enum _scg_firc_trim_div
542 {
543     kSCG_FircTrimDivBy1,    /*!< Divided by 1.    */
544     kSCG_FircTrimDivBy128,  /*!< Divided by 128.  */
545     kSCG_FircTrimDivBy256,  /*!< Divided by 256.  */
546     kSCG_FircTrimDivBy512,  /*!< Divided by 512.  */
547     kSCG_FircTrimDivBy1024, /*!< Divided by 1024. */
548     kSCG_FircTrimDivBy2048  /*!< Divided by 2048. */
549 } scg_firc_trim_div_t;
550 
551 /*!
552  * @brief SCG fast IRC trim source.
553  */
554 typedef enum _scg_firc_trim_src
555 {
556     kSCG_FircTrimSrcSysOsc = 2U, /*!< System OSC.                 */
557     kSCG_FircTrimSrcRtcOsc = 3U, /*!< RTC OSC (32.768 kHz).       */
558 } scg_firc_trim_src_t;
559 
560 /*!
561  * @brief SCG fast IRC clock trim configuration.
562  */
563 typedef struct _scg_firc_trim_config
564 {
565     scg_firc_trim_mode_t trimMode; /*!< FIRC trim mode.                       */
566     scg_firc_trim_src_t trimSrc;   /*!< Trim source.                          */
567 
568     uint8_t trimCoar; /*!< Trim coarse value; Irrelevant if trimMode is kSCG_FircTrimUpdate. */
569     uint8_t trimFine; /*!< Trim fine value; Irrelevant if trimMode is kSCG_FircTrimUpdate. */
570 } scg_firc_trim_config_t;
571 
572 /*!
573  * @brief SCG fast IRC clock frequency range.
574  */
575 typedef enum _scg_firc_range
576 {
577     kSCG_FircRange48M, /*!< Fast IRC is trimmed to 48 MHz.  */
578     kSCG_FircRange52M, /*!< Fast IRC is trimmed to 52 MHz.  */
579     kSCG_FircRange56M, /*!< Fast IRC is trimmed to 56 MHz.  */
580     kSCG_FircRange60M  /*!< Fast IRC is trimmed to 60 MHz.  */
581 } scg_firc_range_t;
582 
583 /*! @brief FIRC enable mode. */
584 enum _scg_firc_enable_mode
585 {
586     kSCG_FircEnable           = SCG_FIRCCSR_FIRCEN_MASK,    /*!< Enable FIRC clock.             */
587     kSCG_FircEnableInStop     = SCG_FIRCCSR_FIRCSTEN_MASK,  /*!< Enable FIRC in stop mode.      */
588     kSCG_FircEnableInLowPower = SCG_FIRCCSR_FIRCLPEN_MASK,  /*!< Enable FIRC in low power mode. */
589     kSCG_FircDisableRegulator = SCG_FIRCCSR_FIRCREGOFF_MASK /*!< Disable regulator.             */
590 };
591 
592 /*!
593  * @brief SCG fast IRC clock configuration.
594  */
595 typedef struct _scg_firc_config_t
596 {
597     uint32_t enableMode; /*!< Enable mode, OR'ed value of _scg_firc_enable_mode. */
598 
599     scg_async_clk_div_t div1; /*!< FIRCDIV1 value.                          */
600     scg_async_clk_div_t div2; /*!< FIRCDIV2 value.                          */
601     scg_async_clk_div_t div3; /*!< FIRCDIV3 value.                          */
602 
603     scg_firc_range_t range; /*!< Fast IRC frequency range.                 */
604 
605     const scg_firc_trim_config_t *trimConfig; /*!< Pointer to the FIRC trim configuration; set NULL to disable trim. */
606 } scg_firc_config_t;
607 
608 /*! @brief LPFLL enable mode. */
609 enum _scg_lpfll_enable_mode
610 {
611     kSCG_LpFllEnable = SCG_LPFLLCSR_LPFLLEN_MASK, /*!< Enable LPFLL clock.             */
612 };
613 
614 /*!
615  * @brief SCG LPFLL clock frequency range.
616  */
617 typedef enum _scg_lpfll_range
618 {
619     kSCG_LpFllRange48M, /*!< LPFLL is trimmed to 48MHz.  */
620     kSCG_LpFllRange72M, /*!< LPFLL is trimmed to 72MHz.  */
621     kSCG_LpFllRange96M, /*!< LPFLL is trimmed to 96MHz.  */
622     kSCG_LpFllRange120M /*!< LPFLL is trimmed to 120MHz. */
623 } scg_lpfll_range_t;
624 
625 /*!
626  * @brief SCG LPFLL trim mode.
627  */
628 typedef enum _scg_lpfll_trim_mode
629 {
630     kSCG_LpFllTrimNonUpdate = SCG_LPFLLCSR_LPFLLTREN_MASK,
631     /*!< LPFLL trim is enabled but the trim value update is not enabled. In this mode, the
632      trim value is fixed to the initialized value, which is defined by the trimValue
633      in the structure @ref scg_lpfll_trim_config_t.*/
634 
635     kSCG_LpFllTrimUpdate = SCG_LPFLLCSR_LPFLLTREN_MASK | SCG_LPFLLCSR_LPFLLTRUP_MASK
636     /*!< FIRC trim is enabled and trim value update is enabled. In this mode, the trim
637      value is automatically updated. */
638 } scg_lpfll_trim_mode_t;
639 
640 /*!
641  * @brief SCG LPFLL trim source.
642  */
643 typedef enum _scg_lpfll_trim_src
644 {
645     kSCG_LpFllTrimSrcSirc   = 0U, /*!< SIRC.                 */
646     kSCG_LpFllTrimSrcFirc   = 1U, /*!< FIRC.                 */
647     kSCG_LpFllTrimSrcSysOsc = 2U, /*!< System OSC.           */
648     kSCG_LpFllTrimSrcRtcOsc = 3U, /*!< RTC OSC (32.768 kHz). */
649 } scg_lpfll_trim_src_t;
650 
651 /*!
652  * @brief SCG LPFLL lock mode.
653  */
654 typedef enum _scg_lpfll_lock_mode
655 {
656     kSCG_LpFllLock1Lsb = 0U, /*!< Lock with 1 LSB. */
657     kSCG_LpFllLock2Lsb = 1U  /*!< Lock with 2 LSB. */
658 } scg_lpfll_lock_mode_t;
659 
660 /*!
661  * @brief SCG LPFLL clock trim configuration.
662  */
663 typedef struct _scg_lpfll_trim_config
664 {
665     scg_lpfll_trim_mode_t trimMode; /*!< Trim mode.            */
666     scg_lpfll_lock_mode_t lockMode; /*!< Lock mode; Irrelevant if the trimMode is kSCG_LpFllTrimNonUpdate. */
667 
668     scg_lpfll_trim_src_t trimSrc; /*!< Trim source.          */
669     uint8_t trimDiv;              /*!< Trim predivideds value, which can be 0 ~ 31.
670                                     [ Trim source frequency / (trimDiv + 1) ] must be 2 MHz or 32768 Hz. */
671 
672     uint8_t trimValue; /*!< Trim value; Irrelevant if trimMode is the kSCG_LpFllTrimUpdate. */
673 } scg_lpfll_trim_config_t;
674 
675 /*!
676  * @brief SCG low power FLL configuration.
677  */
678 typedef struct _scg_lpfll_config
679 {
680     uint8_t enableMode; /*!< Enable mode, OR'ed value of _scg_lpfll_enable_mode */
681 
682     scg_async_clk_div_t div1; /*!< LPFLLDIV1 value.                          */
683     scg_async_clk_div_t div2; /*!< LPFLLDIV2 value.                          */
684     scg_async_clk_div_t div3; /*!< LPFLLDIV3 value.                          */
685 
686     scg_lpfll_range_t range; /*!< LPFLL frequency range.                     */
687 
688     const scg_lpfll_trim_config_t *trimConfig; /*!< Trim configuration; set NULL to disable trim. */
689 } scg_lpfll_config_t;
690 
691 /*!
692  * @brief SCG RTC OSC monitor mode.
693  */
694 typedef enum _scg_rosc_monitor_mode
695 {
696     kSCG_rtcOscMonitorDisable = 0U,                      /*!< Monitor disable.                          */
697     kSCG_rtcOscMonitorInt     = SCG_ROSCCSR_ROSCCM_MASK, /*!< Interrupt when the RTC OSC error is detected. */
698     kSCG_rtcOscMonitorReset =
699         SCG_ROSCCSR_ROSCCM_MASK | SCG_ROSCCSR_ROSCCMRE_MASK /*!< Reset when the RTC OSC error is detected.     */
700 } scg_rosc_monitor_mode_t;
701 
702 /*!
703  * @brief SCG RTC OSC configuration.
704  */
705 typedef struct _scg_rosc_config
706 {
707     scg_rosc_monitor_mode_t monitorMode; /*!< Clock monitor mode selected.     */
708 } scg_rosc_config_t;
709 
710 /*******************************************************************************
711  * API
712  ******************************************************************************/
713 
714 #if defined(__cplusplus)
715 extern "C" {
716 #endif /* __cplusplus */
717 
718 /*!
719  * @brief Enable the clock for specific IP.
720  *
721  * @param name  Which clock to enable, see enumeration clock_ip_name_t.
722  */
CLOCK_EnableClock(clock_ip_name_t name)723 static inline void CLOCK_EnableClock(clock_ip_name_t name)
724 {
725     assert((*(volatile uint32_t *)(uint32_t)name) & PCC_CLKCFG_PR_MASK);
726 
727     (*(volatile uint32_t *)(uint32_t)name) |= PCC_CLKCFG_CGC_MASK;
728 }
729 
730 /*!
731  * @brief Disable the clock for specific IP.
732  *
733  * @param name  Which clock to disable, see enumeration clock_ip_name_t.
734  */
CLOCK_DisableClock(clock_ip_name_t name)735 static inline void CLOCK_DisableClock(clock_ip_name_t name)
736 {
737     assert((*(volatile uint32_t *)(uint32_t)name) & PCC_CLKCFG_PR_MASK);
738 
739     (*(volatile uint32_t *)(uint32_t)name) &= ~PCC_CLKCFG_CGC_MASK;
740 }
741 
742 /*!
743  * @brief Check whether the clock is already enabled and configured by
744  * any other core.
745  *
746  * @param name Which peripheral to check, see enumeration clock_ip_name_t.
747  * @return True if clock is already enabled, otherwise false.
748  */
CLOCK_IsEnabledByOtherCore(clock_ip_name_t name)749 static inline bool CLOCK_IsEnabledByOtherCore(clock_ip_name_t name)
750 {
751     assert((*(volatile uint32_t *)(uint32_t)name) & PCC_CLKCFG_PR_MASK);
752 
753     return (((*(volatile uint32_t *)(uint32_t)name) & PCC_CLKCFG_INUSE_MASK) != 0UL) ? true : false;
754 }
755 
756 /*!
757  * @brief Set the clock source for specific IP module.
758  *
759  * Set the clock source for specific IP, not all modules need to set the
760  * clock source, should only use this function for the modules need source
761  * setting.
762  *
763  * @param name Which peripheral to check, see enumeration clock_ip_name_t.
764  * @param src Clock source to set.
765  */
CLOCK_SetIpSrc(clock_ip_name_t name,clock_ip_src_t src)766 static inline void CLOCK_SetIpSrc(clock_ip_name_t name, clock_ip_src_t src)
767 {
768     uint32_t reg = (*(volatile uint32_t *)(uint32_t)name);
769 
770     assert(reg & PCC_CLKCFG_PR_MASK);
771     assert(0UL == (reg & PCC_CLKCFG_INUSE_MASK)); /* Should not change if clock has been enabled by other core. */
772 
773     reg = (reg & ~PCC_CLKCFG_PCS_MASK) | PCC_CLKCFG_PCS(src);
774 
775     /*
776      * If clock is already enabled, first disable it, then set the clock
777      * source and re-enable it.
778      */
779     (*(volatile uint32_t *)(uint32_t)name) = reg & ~PCC_CLKCFG_CGC_MASK;
780     (*(volatile uint32_t *)(uint32_t)name) = reg;
781 }
782 
783 /*!
784  * @brief Set the clock source and divider for specific IP module.
785  *
786  * Set the clock source and divider for specific IP, not all modules need to
787  * set the clock source and divider, should only use this function for the
788  * modules need source and divider setting.
789  *
790  * Divider output clock = Divider input clock x [(fracValue+1)/(divValue+1)]).
791  *
792  * @param name Which peripheral to check, see enumeration clock_ip_name_t.
793  * @param src Clock source to set.
794  * @param divValue  The divider value.
795  * @param fracValue The fraction multiply value.
796  */
CLOCK_SetIpSrcDiv(clock_ip_name_t name,clock_ip_src_t src,uint8_t divValue,uint8_t fracValue)797 static inline void CLOCK_SetIpSrcDiv(clock_ip_name_t name, clock_ip_src_t src, uint8_t divValue, uint8_t fracValue)
798 {
799     uint32_t reg = (*(volatile uint32_t *)(uint32_t)name);
800 
801     assert(reg & PCC_CLKCFG_PR_MASK);
802     assert(0UL == (reg & PCC_CLKCFG_INUSE_MASK)); /* Should not change if clock has been enabled by other core. */
803 
804     reg = (reg & ~(PCC_CLKCFG_PCS_MASK | PCC_CLKCFG_FRAC_MASK | PCC_CLKCFG_PCD_MASK)) | PCC_CLKCFG_PCS(src) |
805           PCC_CLKCFG_PCD(divValue) | PCC_CLKCFG_FRAC(fracValue);
806 
807     /*
808      * If clock is already enabled, first disable it, then set the clock
809      * source and re-enable it.
810      */
811     (*(volatile uint32_t *)(uint32_t)name) = reg & ~PCC_CLKCFG_CGC_MASK;
812     (*(volatile uint32_t *)(uint32_t)name) = reg;
813 }
814 
815 /*!
816  * @brief Gets the clock frequency for a specific clock name.
817  *
818  * This function checks the current clock configurations and then calculates
819  * the clock frequency for a specific clock name defined in clock_name_t.
820  *
821  * @param clockName Clock names defined in clock_name_t
822  * @return Clock frequency value in hertz
823  */
824 uint32_t CLOCK_GetFreq(clock_name_t clockName);
825 
826 /*!
827  * @brief Get the core clock or system clock frequency.
828  *
829  * @return Clock frequency in Hz.
830  */
831 uint32_t CLOCK_GetCoreSysClkFreq(void);
832 
833 /*!
834  * @brief Get the platform clock frequency.
835  *
836  * @return Clock frequency in Hz.
837  */
838 uint32_t CLOCK_GetPlatClkFreq(void);
839 
840 /*!
841  * @brief Get the bus clock frequency.
842  *
843  * @return Clock frequency in Hz.
844  */
845 uint32_t CLOCK_GetBusClkFreq(void);
846 
847 /*!
848  * @brief Get the flash clock frequency.
849  *
850  * @return Clock frequency in Hz.
851  */
852 uint32_t CLOCK_GetFlashClkFreq(void);
853 
854 /*!
855  * @brief Get the OSC 32K clock frequency (OSC32KCLK).
856  *
857  * @return Clock frequency in Hz.
858  */
859 uint32_t CLOCK_GetOsc32kClkFreq(void);
860 
861 /*!
862  * @brief Get the external clock frequency (EXTCLK).
863  *
864  * @return Clock frequency in Hz.
865  */
866 uint32_t CLOCK_GetExtClkFreq(void);
867 
868 /*!
869  * @brief Get the LPO clock frequency.
870  *
871  * @return Clock frequency in Hz.
872  */
CLOCK_GetLpoClkFreq(void)873 static inline uint32_t CLOCK_GetLpoClkFreq(void)
874 {
875     return LPO_CLK_FREQ; /* 1k Hz. */
876 }
877 
878 /*!
879  * @brief Gets the functional clock frequency for a specific IP module.
880  *
881  * This function gets the IP module's functional clock frequency based on PCC
882  * registers. It is only used for the IP modules which could select clock source
883  * by PCC[PCS].
884  *
885  * @param name Which peripheral to get, see enumeration clock_ip_name_t.
886  * @return Clock frequency value in Hz
887  */
888 uint32_t CLOCK_GetIpFreq(clock_ip_name_t name);
889 
890 /*!
891  * @brief Enable the RTC Oscillator.
892  *
893  * This function enables the Oscillator for RTC external crystal.
894  *
895  * @param enable Enable the Oscillator or not.
896  */
CLOCK_EnableRtcOsc(bool enable)897 static inline void CLOCK_EnableRtcOsc(bool enable)
898 {
899     if (enable)
900     {
901         RTC->CR |= RTC_CR_OSCE_MASK;
902     }
903     else
904     {
905         RTC->CR &= ~RTC_CR_OSCE_MASK;
906     }
907 }
908 
909 /*! @brief Enable USB FS clock.
910  *
911  * @param src  USB FS clock source.
912  * @param freq The frequency specified by src.
913  * @retval true The clock is set successfully.
914  * @retval false The clock source is invalid to get proper USB FS clock.
915  */
916 bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq);
917 
918 /*! @brief Disable USB FS clock.
919  *
920  * Disable USB FS clock.
921  */
CLOCK_DisableUsbfs0Clock(void)922 static inline void CLOCK_DisableUsbfs0Clock(void)
923 {
924     CLOCK_DisableClock(kCLOCK_Usb0);
925 }
926 
927 /*!
928  * @name MCU System Clock.
929  * @{
930  */
931 
932 /*!
933  * @brief Gets the SCG system clock frequency.
934  *
935  * This function gets the SCG system clock frequency. These clocks are used for
936  * core, platform, external, and bus clock domains.
937  *
938  * @param type     Which type of clock to get, core clock or slow clock.
939  * @return  Clock frequency.
940  */
941 uint32_t CLOCK_GetSysClkFreq(scg_sys_clk_t type);
942 
943 /*!
944  * @brief Sets the system clock configuration for VLPR mode.
945  *
946  * This function sets the system clock configuration for VLPR mode.
947  *
948  * @param config Pointer to the configuration.
949  */
CLOCK_SetVlprModeSysClkConfig(const scg_sys_clk_config_t * config)950 static inline void CLOCK_SetVlprModeSysClkConfig(const scg_sys_clk_config_t *config)
951 {
952     assert(config);
953 
954     SCG->VCCR = *(const uint32_t *)(uint32_t)config;
955 }
956 
957 /*!
958  * @brief Sets the system clock configuration for RUN mode.
959  *
960  * This function sets the system clock configuration for RUN mode.
961  *
962  * @param config Pointer to the configuration.
963  */
CLOCK_SetRunModeSysClkConfig(const scg_sys_clk_config_t * config)964 static inline void CLOCK_SetRunModeSysClkConfig(const scg_sys_clk_config_t *config)
965 {
966     assert(config);
967 
968     SCG->RCCR = *(const uint32_t *)(uint32_t)config;
969 }
970 
971 /*!
972  * @brief Sets the system clock configuration for HSRUN mode.
973  *
974  * This function sets the system clock configuration for HSRUN mode.
975  *
976  * @param config Pointer to the configuration.
977  */
CLOCK_SetHsrunModeSysClkConfig(const scg_sys_clk_config_t * config)978 static inline void CLOCK_SetHsrunModeSysClkConfig(const scg_sys_clk_config_t *config)
979 {
980     assert(config);
981 
982     SCG->HCCR = *(const uint32_t *)(uint32_t)config;
983 }
984 
985 /*!
986  * @brief Gets the system clock configuration in the current power mode.
987  *
988  * This function gets the system configuration in the current power mode.
989  *
990  * @param config Pointer to the configuration.
991  */
CLOCK_GetCurSysClkConfig(scg_sys_clk_config_t * config)992 static inline void CLOCK_GetCurSysClkConfig(scg_sys_clk_config_t *config)
993 {
994     assert(config);
995 
996     *(uint32_t *)(uint32_t)config = SCG->CSR;
997 }
998 
999 /*!
1000  * @brief Sets the clock out selection.
1001  *
1002  * This function sets the clock out selection (CLKOUTSEL).
1003  *
1004  * @param setting The selection to set.
1005  * @return  The current clock out selection.
1006  */
CLOCK_SetClkOutSel(clock_clkout_src_t setting)1007 static inline void CLOCK_SetClkOutSel(clock_clkout_src_t setting)
1008 {
1009     SCG->CLKOUTCNFG = SCG_CLKOUTCNFG_CLKOUTSEL(setting);
1010 }
1011 /* @} */
1012 
1013 /*!
1014  * @name SCG Slow IRC Clock.
1015  * @{
1016  */
1017 
1018 /*!
1019  * @brief Initializes the SCG slow IRC clock.
1020  *
1021  * This function enables the SCG slow IRC clock according to the
1022  * configuration.
1023  *
1024  * @param config   Pointer to the configuration structure.
1025  * @retval kStatus_Success SIRC is initialized.
1026  * @retval kStatus_SCG_Busy SIRC has been enabled and is used by system clock.
1027  * @retval kStatus_ReadOnly SIRC control register is locked.
1028  *
1029  * @note This function can't detect whether the system OSC has been enabled and
1030  * used by an IP.
1031  */
1032 status_t CLOCK_InitSirc(const scg_sirc_config_t *config);
1033 
1034 /*!
1035  * @brief De-initializes the SCG slow IRC.
1036  *
1037  * This function disables the SCG slow IRC.
1038  *
1039  * @retval kStatus_Success SIRC is deinitialized.
1040  * @retval kStatus_SCG_Busy SIRC is used by system clock.
1041  * @retval kStatus_ReadOnly SIRC control register is locked.
1042  *
1043  * @note This function can't detect whether the SIRC is used by an IP.
1044  */
1045 status_t CLOCK_DeinitSirc(void);
1046 
1047 /*!
1048  * @brief Set the asynchronous clock divider.
1049  *
1050  * @param asyncClk Which asynchronous clock to configure.
1051  * @param divider The divider value to set.
1052  *
1053  * @note There might be glitch when changing the asynchronous divider, so make sure
1054  * the asynchronous clock is not used while changing divider.
1055  */
CLOCK_SetSircAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)1056 static inline void CLOCK_SetSircAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
1057 {
1058     uint32_t reg = SCG->SIRCDIV;
1059 
1060     switch (asyncClk)
1061     {
1062         case kSCG_AsyncDiv3Clk:
1063             reg = (reg & ~SCG_SIRCDIV_SIRCDIV3_MASK) | SCG_SIRCDIV_SIRCDIV3(divider);
1064             break;
1065         case kSCG_AsyncDiv2Clk:
1066             reg = (reg & ~SCG_SIRCDIV_SIRCDIV2_MASK) | SCG_SIRCDIV_SIRCDIV2(divider);
1067             break;
1068         default:
1069             reg = (reg & ~SCG_SIRCDIV_SIRCDIV1_MASK) | SCG_SIRCDIV_SIRCDIV1(divider);
1070             break;
1071     }
1072 
1073     SCG->SIRCDIV = reg;
1074 }
1075 
1076 /*!
1077  * @brief Gets the SCG SIRC clock frequency.
1078  *
1079  * @return  Clock frequency; If the clock is invalid, returns 0.
1080  */
1081 uint32_t CLOCK_GetSircFreq(void);
1082 
1083 /*!
1084  * @brief Gets the SCG asynchronous clock frequency from the SIRC.
1085  *
1086  * @param type     The asynchronous clock type.
1087  * @return  Clock frequency; If the clock is invalid, returns 0.
1088  */
1089 uint32_t CLOCK_GetSircAsyncFreq(scg_async_clk_t type);
1090 
1091 /*!
1092  * @brief Checks whether the SIRC clock is valid.
1093  *
1094  * @return  True if clock is valid, false if not.
1095  */
CLOCK_IsSircValid(void)1096 static inline bool CLOCK_IsSircValid(void)
1097 {
1098     return (bool)(SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK);
1099 }
1100 /* @} */
1101 
1102 /*!
1103  * @name SCG Fast IRC Clock.
1104  * @{
1105  */
1106 
1107 /*!
1108  * @brief Initializes the SCG fast IRC clock.
1109  *
1110  * This function enables the SCG fast IRC clock according to the configuration.
1111  *
1112  * @param config   Pointer to the configuration structure.
1113  * @retval kStatus_Success FIRC is initialized.
1114  * @retval kStatus_SCG_Busy FIRC has been enabled and is used by the system clock.
1115  * @retval kStatus_ReadOnly FIRC control register is locked.
1116  *
1117  * @note This function can't detect whether the FIRC has been enabled and
1118  * used by an IP.
1119  */
1120 status_t CLOCK_InitFirc(const scg_firc_config_t *config);
1121 
1122 /*!
1123  * @brief De-initializes the SCG fast IRC.
1124  *
1125  * This function disables the SCG fast IRC.
1126  *
1127  * @retval kStatus_Success FIRC is deinitialized.
1128  * @retval kStatus_SCG_Busy FIRC is used by the system clock.
1129  * @retval kStatus_ReadOnly FIRC control register is locked.
1130  *
1131  * @note This function can't detect whether the FIRC is used by an IP.
1132  */
1133 status_t CLOCK_DeinitFirc(void);
1134 
1135 /*!
1136  * @brief Set the asynchronous clock divider.
1137  *
1138  * @param asyncClk Which asynchronous clock to configure.
1139  * @param divider The divider value to set.
1140  *
1141  * @note There might be glitch when changing the asynchronous divider, so make sure
1142  * the asynchronous clock is not used while changing divider.
1143  */
CLOCK_SetFircAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)1144 static inline void CLOCK_SetFircAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
1145 {
1146     uint32_t reg = SCG->FIRCDIV;
1147 
1148     switch (asyncClk)
1149     {
1150         case kSCG_AsyncDiv3Clk:
1151             reg = (reg & ~SCG_FIRCDIV_FIRCDIV3_MASK) | SCG_FIRCDIV_FIRCDIV3(divider);
1152             break;
1153         case kSCG_AsyncDiv2Clk:
1154             reg = (reg & ~SCG_FIRCDIV_FIRCDIV2_MASK) | SCG_FIRCDIV_FIRCDIV2(divider);
1155             break;
1156         default:
1157             reg = (reg & ~SCG_FIRCDIV_FIRCDIV1_MASK) | SCG_FIRCDIV_FIRCDIV1(divider);
1158             break;
1159     }
1160 
1161     SCG->FIRCDIV = reg;
1162 }
1163 
1164 /*!
1165  * @brief Gets the SCG FIRC clock frequency.
1166  *
1167  * @return  Clock frequency; If the clock is invalid, returns 0.
1168  */
1169 uint32_t CLOCK_GetFircFreq(void);
1170 
1171 /*!
1172  * @brief Gets the SCG asynchronous clock frequency from the FIRC.
1173  *
1174  * @param type     The asynchronous clock type.
1175  * @return  Clock frequency; If the clock is invalid, returns 0.
1176  */
1177 uint32_t CLOCK_GetFircAsyncFreq(scg_async_clk_t type);
1178 
1179 /*!
1180  * @brief Checks whether the FIRC clock error occurs.
1181  *
1182  * @return  True if the error occurs, false if not.
1183  */
CLOCK_IsFircErr(void)1184 static inline bool CLOCK_IsFircErr(void)
1185 {
1186     return (bool)(SCG->FIRCCSR & SCG_FIRCCSR_FIRCERR_MASK);
1187 }
1188 
1189 /*!
1190  * @brief Clears the FIRC clock error.
1191  */
CLOCK_ClearFircErr(void)1192 static inline void CLOCK_ClearFircErr(void)
1193 {
1194     SCG->FIRCCSR |= SCG_FIRCCSR_FIRCERR_MASK;
1195 }
1196 
1197 /*!
1198  * @brief Checks whether the FIRC clock is valid.
1199  *
1200  * @return  True if clock is valid, false if not.
1201  */
CLOCK_IsFircValid(void)1202 static inline bool CLOCK_IsFircValid(void)
1203 {
1204     return (bool)(SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK);
1205 }
1206 /* @} */
1207 
1208 /*!
1209  * @brief Gets the SCG RTC OSC clock frequency.
1210  *
1211  * @return  Clock frequency; If the clock is invalid, returns 0.
1212  */
1213 uint32_t CLOCK_GetRtcOscFreq(void);
1214 
1215 /*!
1216  * @brief Checks whether the RTC OSC clock error occurs.
1217  *
1218  * @return  True if error occurs, false if not.
1219  */
CLOCK_IsRtcOscErr(void)1220 static inline bool CLOCK_IsRtcOscErr(void)
1221 {
1222     return (bool)(SCG->ROSCCSR & SCG_ROSCCSR_ROSCERR_MASK);
1223 }
1224 
1225 /*!
1226  * @brief Clears the RTC OSC clock error.
1227  */
CLOCK_ClearRtcOscErr(void)1228 static inline void CLOCK_ClearRtcOscErr(void)
1229 {
1230     SCG->ROSCCSR |= SCG_ROSCCSR_ROSCERR_MASK;
1231 }
1232 
1233 /*!
1234  * @brief Sets the RTC OSC monitor mode.
1235  *
1236  * This function sets the RTC OSC monitor mode. The mode can be disabled.
1237  * It can generate an interrupt when the error is disabled, or reset when the error is detected.
1238  *
1239  * @param mode Monitor mode to set.
1240  */
CLOCK_SetRtcOscMonitorMode(scg_rosc_monitor_mode_t mode)1241 static inline void CLOCK_SetRtcOscMonitorMode(scg_rosc_monitor_mode_t mode)
1242 {
1243     uint32_t reg = SCG->ROSCCSR;
1244 
1245     reg &= ~(SCG_ROSCCSR_ROSCCM_MASK | SCG_ROSCCSR_ROSCCMRE_MASK);
1246 
1247     reg |= (uint32_t)mode;
1248 
1249     SCG->ROSCCSR = reg;
1250 }
1251 
1252 /*!
1253  * @brief Checks whether the RTC OSC clock is valid.
1254  *
1255  * @return  True if the clock is valid, false if not.
1256  */
CLOCK_IsRtcOscValid(void)1257 static inline bool CLOCK_IsRtcOscValid(void)
1258 {
1259     return (bool)(SCG->ROSCCSR & SCG_ROSCCSR_ROSCVLD_MASK);
1260 }
1261 /* @} */
1262 
1263 /*!
1264  * @name SCG Low Power FLL Clock.
1265  * @{
1266  */
1267 /*!
1268  * @brief Initializes the SCG LPFLL clock.
1269  *
1270  * This function enables the SCG LPFLL clock according to the configuration.
1271  *
1272  * @param config   Pointer to the configuration structure.
1273  * @retval kStatus_Success LPFLL is initialized.
1274  * @retval kStatus_SCG_Busy LPFLL has been enabled and is used by the system clock.
1275  * @retval kStatus_ReadOnly LPFLL control register is locked.
1276  *
1277  * @note This function can't detect whether the LPFLL has been enabled and
1278  * used by an IP.
1279  */
1280 status_t CLOCK_InitLpFll(const scg_lpfll_config_t *config);
1281 
1282 /*!
1283  * @brief De-initializes the SCG LPFLL.
1284  *
1285  * This function disables the SCG LPFLL.
1286  *
1287  * @retval kStatus_Success LPFLL is deinitialized.
1288  * @retval kStatus_SCG_Busy LPFLL is used by the system clock.
1289  * @retval kStatus_ReadOnly LPFLL control register is locked.
1290  *
1291  * @note This function can't detect whether the LPFLL is used by an IP.
1292  */
1293 status_t CLOCK_DeinitLpFll(void);
1294 
1295 /*!
1296  * @brief Set the asynchronous clock divider.
1297  *
1298  * @param asyncClk Which asynchronous clock to configure.
1299  * @param divider The divider value to set.
1300  *
1301  * @note There might be glitch when changing the asynchronous divider, so make sure
1302  * the asynchronous clock is not used while changing divider.
1303  */
CLOCK_SetLpFllAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)1304 static inline void CLOCK_SetLpFllAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
1305 {
1306     uint32_t reg = SCG->LPFLLDIV;
1307 
1308     switch (asyncClk)
1309     {
1310         case kSCG_AsyncDiv2Clk:
1311             reg = (reg & ~SCG_LPFLLDIV_LPFLLDIV2_MASK) | SCG_LPFLLDIV_LPFLLDIV2(divider);
1312             break;
1313         default:
1314             reg = (reg & ~SCG_LPFLLDIV_LPFLLDIV1_MASK) | SCG_LPFLLDIV_LPFLLDIV1(divider);
1315             break;
1316     }
1317 
1318     SCG->LPFLLDIV = reg;
1319 }
1320 
1321 /*!
1322  * @brief Gets the SCG LPFLL clock frequency.
1323  *
1324  * @return  Clock frequency in Hz; If the clock is invalid, returns 0.
1325  */
1326 uint32_t CLOCK_GetLpFllFreq(void);
1327 
1328 /*!
1329  * @brief Gets the SCG asynchronous clock frequency from the LPFLL.
1330  *
1331  * @param type     The asynchronous clock type.
1332  * @return  Clock frequency in Hz; If the clock is invalid, returns 0.
1333  */
1334 uint32_t CLOCK_GetLpFllAsyncFreq(scg_async_clk_t type);
1335 
1336 /*!
1337  * @brief Checks whether the LPFLL clock is valid.
1338  *
1339  * @return  True if the clock is valid, false if not.
1340  */
CLOCK_IsLpFllValid(void)1341 static inline bool CLOCK_IsLpFllValid(void)
1342 {
1343     return (bool)(SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLVLD_MASK);
1344 }
1345 /* @} */
1346 
1347 /*!
1348  * @name External clock frequency
1349  * @{
1350  */
1351 
1352 /*!
1353  * @brief Sets the XTAL0 frequency based on board settings.
1354  *
1355  * @param freq The XTAL0/EXTAL0 input clock frequency in Hz.
1356  */
CLOCK_SetXtal0Freq(uint32_t freq)1357 static inline void CLOCK_SetXtal0Freq(uint32_t freq)
1358 {
1359     g_xtal0Freq = freq;
1360 }
1361 
1362 /*!
1363  * @brief Sets the XTAL32 frequency based on board settings.
1364  *
1365  * @param freq The XTAL32/EXTAL32 input clock frequency in Hz.
1366  */
CLOCK_SetXtal32Freq(uint32_t freq)1367 static inline void CLOCK_SetXtal32Freq(uint32_t freq)
1368 {
1369     g_xtal32Freq = freq;
1370 }
1371 
1372 /* @} */
1373 
1374 #if defined(__cplusplus)
1375 }
1376 #endif /* __cplusplus */
1377 
1378 /*! @} */
1379 
1380 #endif /* _FSL_CLOCK_H_ */
1381