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