1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2020, 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.3.2. */
44 #define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 3, 2))
45 /*@}*/
46 
47 /*! @brief External XTAL0 (OSC0/SYSOSC) clock frequency.
48  *
49  * The XTAL0/EXTAL0 (OSC0/SYSOSC) clock frequency in Hz. When the clock is set up, use the
50  * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example,
51  * if XTAL0 is 8 MHz:
52  * @code
53  * CLOCK_InitSysOsc(...);
54  * CLOCK_SetXtal0Freq(80000000);
55  * @endcode
56  *
57  * This is important for the multicore platforms where only one core needs to set up the
58  * OSC0/SYSOSC using CLOCK_InitSysOsc. All other cores need to call the CLOCK_SetXtal0Freq
59  * to get a valid clock frequency.
60  */
61 extern volatile uint32_t g_xtal0Freq;
62 
63 /* Definition for delay API in clock driver, users can redefine it to the real application. */
64 #ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY
65 #define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (48000000UL)
66 #endif
67 
68 /*! @brief Clock ip name array for DMAMUX. */
69 #define DMAMUX_CLOCKS  \
70     {                  \
71         kCLOCK_Dmamux0 \
72     }
73 
74 /*! @brief Clock ip name array for RTC. */
75 #define RTC_CLOCKS  \
76     {               \
77         kCLOCK_Rtc0 \
78     }
79 
80 /*! @brief Clock ip name array for SAI. */
81 #define SAI_CLOCKS  \
82     {               \
83         kCLOCK_Sai0 \
84     }
85 
86 /*! @brief Clock ip name array for PORT. */
87 #define PORT_CLOCKS                                                          \
88     {                                                                        \
89         kCLOCK_PortA, kCLOCK_PortB, kCLOCK_PortC, kCLOCK_PortD, kCLOCK_PortE \
90     }
91 
92 /*! @brief Clock ip name array for LPI2C. */
93 #define LPI2C_CLOCKS                                \
94     {                                               \
95         kCLOCK_Lpi2c0, kCLOCK_Lpi2c1, kCLOCK_Lpi2c2 \
96     }
97 
98 /*! @brief Clock ip name array for FLEXIO. */
99 #define FLEXIO_CLOCKS  \
100     {                  \
101         kCLOCK_Flexio0 \
102     }
103 
104 /*! @brief Clock ip name array for TSI. */
105 #define TSI_CLOCKS  \
106     {               \
107         kCLOCK_Tsi0 \
108     }
109 
110 /*! @brief Clock ip name array for EMVSIM. */
111 #define EMVSIM_CLOCKS  \
112     {                  \
113         kCLOCK_Emvsim0 \
114     }
115 
116 /*! @brief Clock ip name array for EDMA. */
117 #define EDMA_CLOCKS \
118     {               \
119         kCLOCK_Dma0 \
120     }
121 
122 /*! @brief Clock ip name array for LPUART. */
123 #define LPUART_CLOCKS                                  \
124     {                                                  \
125         kCLOCK_Lpuart0, kCLOCK_Lpuart1, kCLOCK_Lpuart2 \
126     }
127 
128 /*! @brief Clock ip name array for DAC. */
129 #define DAC_CLOCKS  \
130     {               \
131         kCLOCK_Dac0 \
132     }
133 
134 /*! @brief Clock ip name array for LPTMR. */
135 #define LPTMR_CLOCKS                 \
136     {                                \
137         kCLOCK_Lptmr0, kCLOCK_Lptmr1 \
138     }
139 
140 /*! @brief Clock ip name array for ADC16. */
141 #define ADC16_CLOCKS \
142     {                \
143         kCLOCK_Adc0  \
144     }
145 
146 /*! @brief Clock ip name array for INTMUX. */
147 #define INTMUX_CLOCKS  \
148     {                  \
149         kCLOCK_Intmux0 \
150     }
151 
152 /*! @brief Clock ip name array for TRNG. */
153 #define TRNG_CLOCKS  \
154     {                \
155         kCLOCK_Trng0 \
156     }
157 
158 /*! @brief Clock ip name array for LPSPI. */
159 #define LPSPI_CLOCKS                                \
160     {                                               \
161         kCLOCK_Lpspi0, kCLOCK_Lpspi1, kCLOCK_Lpspi2 \
162     }
163 
164 /*! @brief Clock ip name array for VREF. */
165 #define VREF_CLOCKS  \
166     {                \
167         kCLOCK_Vref0 \
168     }
169 
170 /*! @brief Clock ip name array for TPM. */
171 #define TPM_CLOCKS                            \
172     {                                         \
173         kCLOCK_Tpm0, kCLOCK_Tpm1, kCLOCK_Tpm2 \
174     }
175 
176 /*! @brief Clock ip name array for LPIT. */
177 #define LPIT_CLOCKS  \
178     {                \
179         kCLOCK_Lpit0 \
180     }
181 
182 /*! @brief Clock ip name array for CRC. */
183 #define CRC_CLOCKS  \
184     {               \
185         kCLOCK_Crc0 \
186     }
187 
188 /*! @brief Clock ip name array for FLASH. */
189 #define FLASH_CLOCKS  \
190     {                 \
191         kCLOCK_Flash0 \
192     }
193 
194 /*! @brief Clock ip name array for CMP. */
195 #define CMP_CLOCKS               \
196     {                            \
197         kCLOCK_Cmp0, kCLOCK_Cmp1 \
198     }
199 
200 /*!
201  * @brief LPO clock frequency.
202  */
203 #define LPO_CLK_FREQ 1000U
204 
205 /*! @brief Clock name used to get clock frequency. */
206 typedef enum _clock_name
207 {
208 
209     /* ----------------------------- System layer clock -------------------------------*/
210     kCLOCK_CoreSysClk, /*!< Core/system clock                                   */
211     kCLOCK_PlatClk,    /*!< Platform clock                                      */
212     kCLOCK_BusClk,     /*!< Bus clock                                           */
213     kCLOCK_FlexBusClk, /*!< FlexBus clock                                       */
214     kCLOCK_FlashClk,   /*!< Flash clock                                         */
215 
216     /* ------------------------------------ SCG clock ---------------------------------*/
217     kCLOCK_ScgSysOscClk, /*!< SCG system OSC clock. (SYSOSC)                      */
218     kCLOCK_ScgSircClk,   /*!< SCG SIRC clock.                                     */
219     kCLOCK_ScgFircClk,   /*!< SCG FIRC clock.                                     */
220     kCLOCK_ScgSysPllClk, /*!< SCG system PLL clock. (SYSPLL)                      */
221 
222     kCLOCK_ScgSysOscAsyncDiv1Clk, /*!< SOSCDIV1_CLK.                                   */
223     kCLOCK_ScgSysOscAsyncDiv2Clk, /*!< SOSCDIV2_CLK.                                   */
224     kCLOCK_ScgSysOscAsyncDiv3Clk, /*!< SOSCDIV3_CLK.                                   */
225 
226     kCLOCK_ScgSircAsyncDiv1Clk, /*!< SIRCDIV1_CLK.                                   */
227     kCLOCK_ScgSircAsyncDiv2Clk, /*!< SIRCDIV2_CLK.                                   */
228     kCLOCK_ScgSircAsyncDiv3Clk, /*!< SIRCDIV3_CLK.                                   */
229 
230     kCLOCK_ScgFircAsyncDiv1Clk, /*!< FIRCDIV1_CLK.                                   */
231     kCLOCK_ScgFircAsyncDiv2Clk, /*!< FIRCDIV2_CLK.                                   */
232     kCLOCK_ScgFircAsyncDiv3Clk, /*!< FIRCDIV3_CLK.                                   */
233 
234     kCLOCK_ScgSysPllAsyncDiv1Clk, /*!< SPLLDIV1_CLK.                                   */
235     kCLOCK_ScgSysPllAsyncDiv2Clk, /*!< SPLLDIV2_CLK.                                   */
236     kCLOCK_ScgSysPllAsyncDiv3Clk, /*!< SPLLDIV3_CLK.                                   */
237 
238     /* --------------------------------- Other clock ----------------------------------*/
239     kCLOCK_LpoClk,    /*!< LPO clock                                           */
240     kCLOCK_Osc32kClk, /*!< External OSC 32K clock (OSC32KCLK)                  */
241     kCLOCK_ErClk      /*!< ERCLK. The external reference clock from SCG.       */
242 } clock_name_t;
243 
244 #define kCLOCK_Osc0ErClk       kCLOCK_ErClk           /*!< For compatible with other MCG platforms. */
245 #define kCLOCK_Er32kClk        kCLOCK_Osc32kClk       /*!< For compatible with other MCG platforms. */
246 #define CLOCK_GetOsc0ErClkFreq CLOCK_GetErClkFreq     /*!< For compatible with other MCG platforms. */
247 #define CLOCK_GetEr32kClkFreq  CLOCK_GetOsc32kClkFreq /*!< For compatible with other MCG platforms. */
248 
249 /*!
250  * @brief Clock source for peripherals that support various clock selections.
251  */
252 typedef enum _clock_ip_src
253 {
254     kCLOCK_IpSrcNoneOrExt   = 0U, /*!< Clock is off or external clock is used. */
255     kCLOCK_IpSrcSysOscAsync = 1U, /*!< System Oscillator async clock.          */
256     kCLOCK_IpSrcSircAsync   = 2U, /*!< Slow IRC async clock.                   */
257     kCLOCK_IpSrcFircAsync   = 3U, /*!< Fast IRC async clock.                   */
258     kCLOCK_IpSrcSysPllAsync = 6U  /*!< System PLL async clock.                 */
259 } clock_ip_src_t;
260 
261 /*!
262  * @brief Peripheral clock name difinition used for clock gate, clock source
263  * and clock divider setting. It is defined as the corresponding register address.
264  */
265 typedef enum _clock_ip_name
266 {
267     kCLOCK_IpInvalid = 0U,
268 
269     /* PCC 0 */
270     kCLOCK_Dma0    = 0x4007A020U,
271     kCLOCK_Flash0  = 0x4007A080U,
272     kCLOCK_Dmamux0 = 0x4007A084U,
273     kCLOCK_Intmux0 = 0x4007A090U,
274     kCLOCK_Tpm2    = 0x4007A0B8U,
275     kCLOCK_Lpit0   = 0x4007A0C0U,
276     kCLOCK_Lptmr0  = 0x4007A0D0U,
277     kCLOCK_Rtc0    = 0x4007A0E0U,
278     kCLOCK_Lpspi2  = 0x4007A0F8U,
279     kCLOCK_Lpi2c2  = 0x4007A108U,
280     kCLOCK_Lpuart2 = 0x4007A118U,
281     kCLOCK_Sai0    = 0x4007A130U,
282     kCLOCK_Emvsim0 = 0x4007A138U,
283     kCLOCK_Usbfs0  = 0x4007A154U,
284     kCLOCK_PortA   = 0x4007A168U,
285     kCLOCK_PortB   = 0x4007A16CU,
286     kCLOCK_PortC   = 0x4007A170U,
287     kCLOCK_PortD   = 0x4007A174U,
288     kCLOCK_PortE   = 0x4007A178U,
289     kCLOCK_Tsi0    = 0x4007A188U,
290     kCLOCK_Adc0    = 0x4007A198U,
291     kCLOCK_Dac0    = 0x4007A1A8U,
292     kCLOCK_Cmp0    = 0x4007A1B8U,
293     kCLOCK_Vref0   = 0x4007A1C8U,
294     kCLOCK_Crc0    = 0x4007A1E0U,
295 
296     /* PCC 1 */
297     kCLOCK_Trng0   = 0x400FA094U,
298     kCLOCK_Tpm0    = 0x400FA0B0U,
299     kCLOCK_Tpm1    = 0x400FA0B4U,
300     kCLOCK_Lptmr1  = 0x400FA0D4U,
301     kCLOCK_Lpspi0  = 0x400FA0F0U,
302     kCLOCK_Lpspi1  = 0x400FA0F4U,
303     kCLOCK_Lpi2c0  = 0x400FA100U,
304     kCLOCK_Lpi2c1  = 0x400FA104U,
305     kCLOCK_Lpuart0 = 0x400FA110U,
306     kCLOCK_Lpuart1 = 0x400FA114U,
307     kCLOCK_Flexio0 = 0x400FA128U,
308     kCLOCK_Cmp1    = 0x400FA1BCU,
309 } clock_ip_name_t;
310 
311 /*!
312  * @brief SCG status return codes.
313  */
314 enum
315 {
316     kStatus_SCG_Busy       = MAKE_STATUS(kStatusGroup_SCG, 1), /*!< Clock is busy.  */
317     kStatus_SCG_InvalidSrc = MAKE_STATUS(kStatusGroup_SCG, 2)  /*!< Invalid source. */
318 };
319 
320 /*!
321  * @brief SCG system clock type.
322  */
323 typedef enum _scg_sys_clk
324 {
325     kSCG_SysClkSlow, /*!< System slow clock. */
326     kSCG_SysClkCore, /*!< Core clock.        */
327 } scg_sys_clk_t;
328 
329 /*!
330  * @brief SCG system clock source.
331  */
332 typedef enum _scg_sys_clk_src
333 {
334     kSCG_SysClkSrcSysOsc = 1U, /*!< System OSC. */
335     kSCG_SysClkSrcSirc   = 2U, /*!< Slow IRC.   */
336     kSCG_SysClkSrcFirc   = 3U, /*!< Fast IRC.   */
337     kSCG_SysClkSrcSysPll = 6U  /*!< System PLL. */
338 } scg_sys_clk_src_t;
339 
340 /*!
341  * @brief SCG system clock divider value.
342  */
343 typedef enum _scg_sys_clk_div
344 {
345     kSCG_SysClkDivBy1  = 0U,  /*!< Divided by 1.  */
346     kSCG_SysClkDivBy2  = 1U,  /*!< Divided by 2.  */
347     kSCG_SysClkDivBy3  = 2U,  /*!< Divided by 3.  */
348     kSCG_SysClkDivBy4  = 3U,  /*!< Divided by 4.  */
349     kSCG_SysClkDivBy5  = 4U,  /*!< Divided by 5.  */
350     kSCG_SysClkDivBy6  = 5U,  /*!< Divided by 6.  */
351     kSCG_SysClkDivBy7  = 6U,  /*!< Divided by 7.  */
352     kSCG_SysClkDivBy8  = 7U,  /*!< Divided by 8.  */
353     kSCG_SysClkDivBy9  = 8U,  /*!< Divided by 9.  */
354     kSCG_SysClkDivBy10 = 9U,  /*!< Divided by 10. */
355     kSCG_SysClkDivBy11 = 10U, /*!< Divided by 11. */
356     kSCG_SysClkDivBy12 = 11U, /*!< Divided by 12. */
357     kSCG_SysClkDivBy13 = 12U, /*!< Divided by 13. */
358     kSCG_SysClkDivBy14 = 13U, /*!< Divided by 14. */
359     kSCG_SysClkDivBy15 = 14U, /*!< Divided by 15. */
360     kSCG_SysClkDivBy16 = 15U  /*!< Divided by 16. */
361 } scg_sys_clk_div_t;
362 
363 /*!
364  * @brief SCG system clock configuration.
365  */
366 typedef struct _scg_sys_clk_config
367 {
368     uint32_t divSlow : 4; /*!< Slow clock divider, see @ref scg_sys_clk_div_t. */
369     uint32_t : 4;         /*!< Reserved. */
370     uint32_t : 4;         /*!< Reserved. */
371     uint32_t : 4;         /*!< Reserved. */
372     uint32_t divCore : 4; /*!< Core clock divider, see @ref scg_sys_clk_div_t. */
373     uint32_t : 4;         /*!< Reserved. */
374     uint32_t src : 4;     /*!< System clock source, see @ref scg_sys_clk_src_t. */
375     uint32_t : 4;         /*!< reserved. */
376 } scg_sys_clk_config_t;
377 
378 /*!
379  * @brief SCG clock out configuration (CLKOUTSEL).
380  */
381 typedef enum _clock_clkout_src
382 {
383     kClockClkoutSelScgSlow = 0U, /*!< SCG slow clock. */
384     kClockClkoutSelSysOsc  = 1U, /*!< System OSC.     */
385     kClockClkoutSelSirc    = 2U, /*!< Slow IRC.       */
386     kClockClkoutSelFirc    = 3U, /*!< Fast IRC.       */
387     kClockClkoutSelSysPll  = 6U  /*!< System PLL.     */
388 } clock_clkout_src_t;
389 
390 /*!
391  * @brief SCG asynchronous clock type.
392  */
393 typedef enum _scg_async_clk
394 {
395     kSCG_AsyncDiv1Clk, /*!< The async clock by DIV1, e.g. SOSCDIV1_CLK, SIRCDIV1_CLK. */
396     kSCG_AsyncDiv2Clk, /*!< The async clock by DIV2, e.g. SOSCDIV2_CLK, SIRCDIV2_CLK. */
397     kSCG_AsyncDiv3Clk  /*!< The async clock by DIV3, e.g. SOSCDIV3_CLK, SIRCDIV3_CLK. */
398 } scg_async_clk_t;
399 
400 /*!
401  * @brief SCG asynchronous clock divider value.
402  */
403 typedef enum scg_async_clk_div
404 {
405     kSCG_AsyncClkDisable = 0U, /*!< Clock output is disabled.  */
406     kSCG_AsyncClkDivBy1  = 1U, /*!< Divided by 1.              */
407     kSCG_AsyncClkDivBy2  = 2U, /*!< Divided by 2.              */
408     kSCG_AsyncClkDivBy4  = 3U, /*!< Divided by 4.              */
409     kSCG_AsyncClkDivBy8  = 4U, /*!< Divided by 8.              */
410     kSCG_AsyncClkDivBy16 = 5U, /*!< Divided by 16.             */
411     kSCG_AsyncClkDivBy32 = 6U, /*!< Divided by 32.             */
412     kSCG_AsyncClkDivBy64 = 7U  /*!< Divided by 64.             */
413 } scg_async_clk_div_t;
414 
415 /*!
416  * @brief SCG system OSC monitor mode.
417  */
418 typedef enum _scg_sosc_monitor_mode
419 {
420     kSCG_SysOscMonitorDisable = 0U,                      /*!< Monitor disabled.                          */
421     kSCG_SysOscMonitorInt     = SCG_SOSCCSR_SOSCCM_MASK, /*!< Interrupt when the system OSC error is detected. */
422     kSCG_SysOscMonitorReset =
423         SCG_SOSCCSR_SOSCCM_MASK | SCG_SOSCCSR_SOSCCMRE_MASK /*!< Reset when the system OSC error is detected.     */
424 } scg_sosc_monitor_mode_t;
425 
426 /*! @brief Oscillator capacitor load setting.*/
427 enum
428 {
429     kSCG_SysOscCap2P  = SCG_SOSCCFG_SC2P_MASK, /*!< 2  pF capacitor load */
430     kSCG_SysOscCap4P  = SCG_SOSCCFG_SC4P_MASK, /*!< 4  pF capacitor load */
431     kSCG_SysOscCap8P  = SCG_SOSCCFG_SC8P_MASK, /*!< 8  pF capacitor load */
432     kSCG_SysOscCap16P = SCG_SOSCCFG_SC16P_MASK /*!< 16 pF capacitor load */
433 };
434 
435 /*! @brief OSC work mode. */
436 typedef enum _scg_sosc_mode
437 {
438     kSCG_SysOscModeExt         = 0U,                                           /*!< Use external clock.   */
439     kSCG_SysOscModeOscLowPower = SCG_SOSCCFG_EREFS_MASK,                       /*!< Oscillator low power. */
440     kSCG_SysOscModeOscHighGain = SCG_SOSCCFG_EREFS_MASK | SCG_SOSCCFG_HGO_MASK /*!< Oscillator high gain. */
441 } scg_sosc_mode_t;
442 
443 /*! @brief OSC enable mode. */
444 enum
445 {
446     kSCG_SysOscEnable           = SCG_SOSCCSR_SOSCEN_MASK,     /*!< Enable OSC clock. */
447     kSCG_SysOscEnableInStop     = SCG_SOSCCSR_SOSCSTEN_MASK,   /*!< Enable OSC in stop mode. */
448     kSCG_SysOscEnableInLowPower = SCG_SOSCCSR_SOSCLPEN_MASK,   /*!< Enable OSC in low power mode. */
449     kSCG_SysOscEnableErClk      = SCG_SOSCCSR_SOSCERCLKEN_MASK /*!< Enable OSCERCLK. */
450 };
451 
452 /*!
453  * @brief SCG system OSC configuration.
454  */
455 typedef struct _scg_sosc_config
456 {
457     uint32_t freq;                       /*!< System OSC frequency.                    */
458     scg_sosc_monitor_mode_t monitorMode; /*!< Clock monitor mode selected.     */
459     uint8_t enableMode;                  /*!< Enable mode, OR'ed value of _scg_sosc_enable_mode.  */
460 
461     scg_async_clk_div_t div1; /*!< SOSCDIV1 value.                          */
462     scg_async_clk_div_t div2; /*!< SOSCDIV2 value.                          */
463     scg_async_clk_div_t div3; /*!< SOSCDIV3 value.                          */
464 
465     uint32_t capLoad;         /*!< Capacitor load, OR'ed value of _scg_sosc_cap_load. */
466     scg_sosc_mode_t workMode; /*!< OSC work mode.                           */
467 } scg_sosc_config_t;
468 
469 /*!
470  * @brief SCG slow IRC clock frequency range.
471  */
472 typedef enum _scg_sirc_range
473 {
474     kSCG_SircRangeLow, /*!< Slow IRC low range clock (2 MHz, 4 MHz for i.MX 7 ULP).  */
475     kSCG_SircRangeHigh /*!< Slow IRC high range clock (8 MHz, 16 MHz for i.MX 7 ULP). */
476 } scg_sirc_range_t;
477 
478 /*! @brief SIRC enable mode. */
479 enum
480 {
481     kSCG_SircEnable           = SCG_SIRCCSR_SIRCEN_MASK,   /*!< Enable SIRC clock.             */
482     kSCG_SircEnableInStop     = SCG_SIRCCSR_SIRCSTEN_MASK, /*!< Enable SIRC in stop mode.      */
483     kSCG_SircEnableInLowPower = SCG_SIRCCSR_SIRCLPEN_MASK  /*!< Enable SIRC in low power mode. */
484 };
485 
486 /*!
487  * @brief SCG slow IRC clock configuration.
488  */
489 typedef struct _scg_sirc_config
490 {
491     uint32_t enableMode;      /*!< Enable mode, OR'ed value of _scg_sirc_enable_mode. */
492     scg_async_clk_div_t div1; /*!< SIRCDIV1 value.                          */
493     scg_async_clk_div_t div2; /*!< SIRCDIV2 value.                          */
494     scg_async_clk_div_t div3; /*!< SIRCDIV3 value.                          */
495 
496     scg_sirc_range_t range; /*!< Slow IRC frequency range.                */
497 } scg_sirc_config_t;
498 
499 /*!
500  * @brief SCG fast IRC trim mode.
501  */
502 typedef enum _scg_firc_trim_mode
503 {
504     kSCG_FircTrimNonUpdate = SCG_FIRCCSR_FIRCTREN_MASK,
505     /*!< FIRC trim enable but not enable trim value update. In this mode, the
506      trim value is fixed to the initialized value which is defined by
507      trimCoar and trimFine in configure structure \ref scg_firc_trim_config_t.*/
508 
509     kSCG_FircTrimUpdate = SCG_FIRCCSR_FIRCTREN_MASK | SCG_FIRCCSR_FIRCTRUP_MASK
510     /*!< FIRC trim enable and trim value update enable. In this mode, the trim
511      value is auto update. */
512 
513 } scg_firc_trim_mode_t;
514 
515 /*!
516  * @brief SCG fast IRC trim predivided value for system OSC.
517  */
518 typedef enum _scg_firc_trim_div
519 {
520     kSCG_FircTrimDivBy1,    /*!< Divided by 1.    */
521     kSCG_FircTrimDivBy128,  /*!< Divided by 128.  */
522     kSCG_FircTrimDivBy256,  /*!< Divided by 256.  */
523     kSCG_FircTrimDivBy512,  /*!< Divided by 512.  */
524     kSCG_FircTrimDivBy1024, /*!< Divided by 1024. */
525     kSCG_FircTrimDivBy2048  /*!< Divided by 2048. */
526 } scg_firc_trim_div_t;
527 
528 /*!
529  * @brief SCG fast IRC trim source.
530  */
531 typedef enum _scg_firc_trim_src
532 {
533     kSCG_FircTrimSrcUsb0   = 0U, /*!< USB0 start of frame (1kHz). */
534     kSCG_FircTrimSrcSysOsc = 2U, /*!< System OSC.                 */
535 } scg_firc_trim_src_t;
536 
537 /*!
538  * @brief SCG fast IRC clock trim configuration.
539  */
540 typedef struct _scg_firc_trim_config
541 {
542     scg_firc_trim_mode_t trimMode; /*!< FIRC trim mode.                       */
543     scg_firc_trim_src_t trimSrc;   /*!< Trim source.                          */
544     scg_firc_trim_div_t trimDiv;   /*!< Trim predivided value for the system OSC.  */
545 
546     uint8_t trimCoar; /*!< Trim coarse value; Irrelevant if trimMode is kSCG_FircTrimUpdate. */
547     uint8_t trimFine; /*!< Trim fine value; Irrelevant if trimMode is kSCG_FircTrimUpdate. */
548 } scg_firc_trim_config_t;
549 
550 /*!
551  * @brief SCG fast IRC clock frequency range.
552  */
553 typedef enum _scg_firc_range
554 {
555     kSCG_FircRange48M, /*!< Fast IRC is trimmed to 48 MHz.  */
556     kSCG_FircRange52M, /*!< Fast IRC is trimmed to 52 MHz.  */
557     kSCG_FircRange56M, /*!< Fast IRC is trimmed to 56 MHz.  */
558     kSCG_FircRange60M  /*!< Fast IRC is trimmed to 60 MHz.  */
559 } scg_firc_range_t;
560 
561 /*! @brief FIRC enable mode. */
562 enum
563 {
564     kSCG_FircEnable           = SCG_FIRCCSR_FIRCEN_MASK,    /*!< Enable FIRC clock.             */
565     kSCG_FircEnableInStop     = SCG_FIRCCSR_FIRCSTEN_MASK,  /*!< Enable FIRC in stop mode.      */
566     kSCG_FircEnableInLowPower = SCG_FIRCCSR_FIRCLPEN_MASK,  /*!< Enable FIRC in low power mode. */
567     kSCG_FircDisableRegulator = SCG_FIRCCSR_FIRCREGOFF_MASK /*!< Disable regulator.             */
568 };
569 
570 /*!
571  * @brief SCG fast IRC clock configuration.
572  */
573 typedef struct _scg_firc_config_t
574 {
575     uint32_t enableMode; /*!< Enable mode, OR'ed value of _scg_firc_enable_mode. */
576 
577     scg_async_clk_div_t div1; /*!< FIRCDIV1 value.                          */
578     scg_async_clk_div_t div2; /*!< FIRCDIV2 value.                          */
579     scg_async_clk_div_t div3; /*!< FIRCDIV3 value.                          */
580 
581     scg_firc_range_t range; /*!< Fast IRC frequency range.                 */
582 
583     const scg_firc_trim_config_t *trimConfig; /*!< Pointer to the FIRC trim configuration; set NULL to disable trim. */
584 } scg_firc_config_t;
585 
586 /*!
587  * @brief SCG system PLL clock source.
588  */
589 typedef enum _scg_spll_src
590 {
591     kSCG_SysPllSrcSysOsc, /*!< System PLL clock source is system OSC. */
592     kSCG_SysPllSrcFirc    /*!< System PLL clock source is fast IRC.   */
593 } scg_spll_src_t;
594 
595 /*!
596  * @brief SCG system PLL monitor mode.
597  */
598 typedef enum _scg_spll_monitor_mode
599 {
600     kSCG_SysPllMonitorDisable = 0U,                      /*!< Monitor disabled.                          */
601     kSCG_SysPllMonitorInt     = SCG_SPLLCSR_SPLLCM_MASK, /*!< Interrupt when the system PLL error is detected. */
602     kSCG_SysPllMonitorReset =
603         SCG_SPLLCSR_SPLLCM_MASK | SCG_SPLLCSR_SPLLCMRE_MASK /*!< Reset when the system PLL error is detected.     */
604 } scg_spll_monitor_mode_t;
605 
606 /*! @brief SPLL enable mode. */
607 enum
608 {
609     kSCG_SysPllEnable       = SCG_SPLLCSR_SPLLEN_MASK,  /*!< Enable SPLL clock.             */
610     kSCG_SysPllEnableInStop = SCG_SPLLCSR_SPLLSTEN_MASK /*!< Enable SPLL in stop mode.      */
611 };
612 
613 /*!
614  * @brief SCG system PLL configuration.
615  */
616 typedef struct _scg_spll_config
617 {
618     uint8_t enableMode;                  /*!< Enable mode, OR'ed value of _scg_spll_enable_mode */
619     scg_spll_monitor_mode_t monitorMode; /*!< Clock monitor mode selected.     */
620 
621     scg_async_clk_div_t div1; /*!< SPLLDIV1 value.                          */
622     scg_async_clk_div_t div2; /*!< SPLLDIV2 value.                          */
623     scg_async_clk_div_t div3; /*!< SPLLDIV3 value.                          */
624 
625     scg_spll_src_t src; /*!< Clock source.                            */
626     uint8_t prediv;     /*!< PLL reference clock divider.             */
627     uint8_t mult;       /*!< System PLL multiplier.                   */
628 } scg_spll_config_t;
629 
630 /*******************************************************************************
631  * API
632  ******************************************************************************/
633 
634 #if defined(__cplusplus)
635 extern "C" {
636 #endif /* __cplusplus */
637 
638 /*!
639  * @brief Enable the clock for specific IP.
640  *
641  * @param name  Which clock to enable, see \ref clock_ip_name_t.
642  */
CLOCK_EnableClock(clock_ip_name_t name)643 static inline void CLOCK_EnableClock(clock_ip_name_t name)
644 {
645     assert((*(volatile uint32_t *)(uint32_t)name) & PCC_CLKCFG_PR_MASK);
646 
647     (*(volatile uint32_t *)(uint32_t)name) |= PCC_CLKCFG_CGC_MASK;
648 }
649 
650 /*!
651  * @brief Disable the clock for specific IP.
652  *
653  * @param name  Which clock to disable, see \ref clock_ip_name_t.
654  */
CLOCK_DisableClock(clock_ip_name_t name)655 static inline void CLOCK_DisableClock(clock_ip_name_t name)
656 {
657     assert((*(volatile uint32_t *)(uint32_t)name) & PCC_CLKCFG_PR_MASK);
658 
659     (*(volatile uint32_t *)(uint32_t)name) &= ~PCC_CLKCFG_CGC_MASK;
660 }
661 
662 /*!
663  * @brief Check whether the clock is already enabled and configured by
664  * any other core.
665  *
666  * @param name Which peripheral to check, see \ref clock_ip_name_t.
667  * @return True if clock is already enabled, otherwise false.
668  */
CLOCK_IsEnabledByOtherCore(clock_ip_name_t name)669 static inline bool CLOCK_IsEnabledByOtherCore(clock_ip_name_t name)
670 {
671     assert((*(volatile uint32_t *)(uint32_t)name) & PCC_CLKCFG_PR_MASK);
672 
673     return (((*(volatile uint32_t *)(uint32_t)name) & PCC_CLKCFG_INUSE_MASK) != 0UL) ? true : false;
674 }
675 
676 /*!
677  * @brief Set the clock source for specific IP module.
678  *
679  * Set the clock source for specific IP, not all modules need to set the
680  * clock source, should only use this function for the modules need source
681  * setting.
682  *
683  * @param name Which peripheral to check, see \ref clock_ip_name_t.
684  * @param src Clock source to set.
685  */
CLOCK_SetIpSrc(clock_ip_name_t name,clock_ip_src_t src)686 static inline void CLOCK_SetIpSrc(clock_ip_name_t name, clock_ip_src_t src)
687 {
688     uint32_t reg = (*(volatile uint32_t *)(uint32_t)name);
689 
690     assert((reg & PCC_CLKCFG_PR_MASK) != 0UL);
691     assert(0UL == (reg & PCC_CLKCFG_INUSE_MASK)); /* Should not change if clock has been enabled by other core. */
692 
693     reg = (reg & ~PCC_CLKCFG_PCS_MASK) | PCC_CLKCFG_PCS(src);
694 
695     /*
696      * If clock is already enabled, first disable it, then set the clock
697      * source and re-enable it.
698      */
699     (*(volatile uint32_t *)(uint32_t)name) = reg & ~PCC_CLKCFG_CGC_MASK;
700     (*(volatile uint32_t *)(uint32_t)name) = reg;
701 }
702 
703 /*!
704  * @brief Set the clock source and divider for specific IP module.
705  *
706  * Set the clock source and divider for specific IP, not all modules need to
707  * set the clock source and divider, should only use this function for the
708  * modules need source and divider setting.
709  *
710  * Divider output clock = Divider input clock x [(fracValue+1)/(divValue+1)]).
711  *
712  * @param name Which peripheral to check, see \ref clock_ip_name_t.
713  * @param src Clock source to set.
714  * @param divValue  The divider value.
715  * @param fracValue The fraction multiply value.
716  */
CLOCK_SetIpSrcDiv(clock_ip_name_t name,clock_ip_src_t src,uint8_t divValue,uint8_t fracValue)717 static inline void CLOCK_SetIpSrcDiv(clock_ip_name_t name, clock_ip_src_t src, uint8_t divValue, uint8_t fracValue)
718 {
719     uint32_t reg = (*(volatile uint32_t *)(uint32_t)name);
720 
721     assert((reg & PCC_CLKCFG_PR_MASK) != 0UL);
722     assert(0UL == (reg & PCC_CLKCFG_INUSE_MASK)); /* Should not change if clock has been enabled by other core. */
723 
724     reg = (reg & ~(PCC_CLKCFG_PCS_MASK | PCC_CLKCFG_FRAC_MASK | PCC_CLKCFG_PCD_MASK)) | PCC_CLKCFG_PCS(src) |
725           PCC_CLKCFG_PCD(divValue) | PCC_CLKCFG_FRAC(fracValue);
726 
727     /*
728      * If clock is already enabled, first disable it, then set the clock
729      * source and re-enable it.
730      */
731     (*(volatile uint32_t *)(uint32_t)name) = reg & ~PCC_CLKCFG_CGC_MASK;
732     (*(volatile uint32_t *)(uint32_t)name) = reg;
733 }
734 
735 /*!
736  * @brief Gets the clock frequency for a specific clock name.
737  *
738  * This function checks the current clock configurations and then calculates
739  * the clock frequency for a specific clock name defined in clock_name_t.
740  *
741  * @param clockName Clock names defined in clock_name_t
742  * @return Clock frequency value in hertz
743  */
744 uint32_t CLOCK_GetFreq(clock_name_t clockName);
745 
746 /*!
747  * @brief Get the core clock or system clock frequency.
748  *
749  * @return Clock frequency in Hz.
750  */
751 uint32_t CLOCK_GetCoreSysClkFreq(void);
752 
753 /*!
754  * @brief Get the platform clock frequency.
755  *
756  * @return Clock frequency in Hz.
757  */
758 uint32_t CLOCK_GetPlatClkFreq(void);
759 
760 /*!
761  * @brief Get the bus clock frequency.
762  *
763  * @return Clock frequency in Hz.
764  */
765 uint32_t CLOCK_GetBusClkFreq(void);
766 
767 /*!
768  * @brief Get the flash clock frequency.
769  *
770  * @return Clock frequency in Hz.
771  */
772 uint32_t CLOCK_GetFlashClkFreq(void);
773 
774 /*!
775  * @brief Get the OSC 32K clock frequency (OSC32KCLK).
776  *
777  * @return Clock frequency in Hz.
778  */
779 uint32_t CLOCK_GetOsc32kClkFreq(void);
780 
781 /*!
782  * @brief Get the external reference clock frequency (ERCLK).
783  *
784  * @return Clock frequency in Hz.
785  */
786 uint32_t CLOCK_GetErClkFreq(void);
787 
788 /*!
789  * @brief Gets the clock frequency for a specific IP module.
790  *
791  * This function gets the IP module clock frequency based on PCC registers. It is
792  * only used for the IP modules which could select clock source by PCC[PCS].
793  *
794  * @param name Which peripheral to get, see \ref clock_ip_name_t.
795  * @return Clock frequency value in hertz
796  */
797 uint32_t CLOCK_GetIpFreq(clock_ip_name_t name);
798 
799 /*! @brief Enable USB FS clock.
800  *
801  * @param src  USB FS clock source.
802  * @param freq The frequency specified by src.
803  * @retval true The clock is set successfully.
804  * @retval false The clock source is invalid to get proper USB FS clock.
805  */
806 bool CLOCK_EnableUsbfs0Clock(clock_ip_src_t src, uint32_t freq);
807 
808 /*! @brief Disable USB FS clock.
809  *
810  * Disable USB FS clock.
811  */
CLOCK_DisableUsbfs0Clock(void)812 static inline void CLOCK_DisableUsbfs0Clock(void)
813 {
814     CLOCK_DisableClock(kCLOCK_Usbfs0);
815 }
816 
817 /*!
818  * @name MCU System Clock.
819  * @{
820  */
821 
822 /*!
823  * @brief Gets the SCG system clock frequency.
824  *
825  * This function gets the SCG system clock frequency. These clocks are used for
826  * core, platform, external, and bus clock domains.
827  *
828  * @param type     Which type of clock to get, core clock or slow clock.
829  * @return  Clock frequency.
830  */
831 uint32_t CLOCK_GetSysClkFreq(scg_sys_clk_t type);
832 
833 /*!
834  * @brief Sets the system clock configuration for VLPR mode.
835  *
836  * This function sets the system clock configuration for VLPR mode.
837  *
838  * @param config Pointer to the configuration.
839  */
CLOCK_SetVlprModeSysClkConfig(const scg_sys_clk_config_t * config)840 static inline void CLOCK_SetVlprModeSysClkConfig(const scg_sys_clk_config_t *config)
841 {
842     assert(config);
843     union
844     {
845         const uint32_t *configInt;
846         const scg_sys_clk_config_t *configPtr;
847     } Config;
848 
849     Config.configPtr = config;
850     SCG->VCCR        = *(Config.configInt);
851 }
852 
853 /*!
854  * @brief Sets the system clock configuration for RUN mode.
855  *
856  * This function sets the system clock configuration for RUN mode.
857  *
858  * @param config Pointer to the configuration.
859  */
CLOCK_SetRunModeSysClkConfig(const scg_sys_clk_config_t * config)860 static inline void CLOCK_SetRunModeSysClkConfig(const scg_sys_clk_config_t *config)
861 {
862     assert(config);
863     union
864     {
865         const uint32_t *configInt;
866         const scg_sys_clk_config_t *configPtr;
867     } Config;
868 
869     Config.configPtr = config;
870     SCG->RCCR        = *(Config.configInt);
871 }
872 
873 /*!
874  * @brief Sets the system clock configuration for HSRUN mode.
875  *
876  * This function sets the system clock configuration for HSRUN mode.
877  *
878  * @param config Pointer to the configuration.
879  */
CLOCK_SetHsrunModeSysClkConfig(const scg_sys_clk_config_t * config)880 static inline void CLOCK_SetHsrunModeSysClkConfig(const scg_sys_clk_config_t *config)
881 {
882     assert(config);
883     union
884     {
885         const uint32_t *configInt;
886         const scg_sys_clk_config_t *configPtr;
887     } Config;
888 
889     Config.configPtr = config;
890     SCG->HCCR        = *(Config.configInt);
891 }
892 
893 /*!
894  * @brief Gets the system clock configuration in the current power mode.
895  *
896  * This function gets the system configuration in the current power mode.
897  *
898  * @param config Pointer to the configuration.
899  */
CLOCK_GetCurSysClkConfig(scg_sys_clk_config_t * config)900 static inline void CLOCK_GetCurSysClkConfig(scg_sys_clk_config_t *config)
901 {
902     assert(config);
903     union
904     {
905         uint32_t *configInt;
906         scg_sys_clk_config_t *configPtr;
907     } Config;
908 
909     Config.configPtr    = config;
910     *(Config.configInt) = SCG->CSR;
911 }
912 
913 /*!
914  * @brief Sets the clock out selection.
915  *
916  * This function sets the clock out selection (CLKOUTSEL).
917  *
918  * @param setting The selection to set.
919  * @return  The current clock out selection.
920  */
CLOCK_SetClkOutSel(clock_clkout_src_t setting)921 static inline void CLOCK_SetClkOutSel(clock_clkout_src_t setting)
922 {
923     SCG->CLKOUTCNFG = SCG_CLKOUTCNFG_CLKOUTSEL(setting);
924 }
925 /* @} */
926 
927 /*!
928  * @name SCG System OSC Clock.
929  * @{
930  */
931 
932 /*!
933  * @brief Initializes the SCG system OSC.
934  *
935  * This function enables the SCG system OSC clock according to the
936  * configuration.
937  *
938  * @param config   Pointer to the configuration structure.
939  * @retval kStatus_Success System OSC is initialized.
940  * @retval kStatus_SCG_Busy System OSC has been enabled and is used by the system clock.
941  * @retval kStatus_ReadOnly System OSC control register is locked.
942  *
943  * @note This function can't detect whether the system OSC has been enabled and
944  * used by an IP.
945  */
946 status_t CLOCK_InitSysOsc(const scg_sosc_config_t *config);
947 
948 /*!
949  * @brief De-initializes the SCG system OSC.
950  *
951  * This function disables the SCG system OSC clock.
952  *
953  * @retval kStatus_Success System OSC is deinitialized.
954  * @retval kStatus_SCG_Busy System OSC is used by the system clock.
955  * @retval kStatus_ReadOnly System OSC control register is locked.
956  *
957  * @note This function can't detect whether the system OSC is used by an IP.
958  */
959 status_t CLOCK_DeinitSysOsc(void);
960 
961 /*!
962  * @brief Set the asynchronous clock divider.
963  *
964  * @param asyncClk Which asynchronous clock to configure.
965  * @param divider The divider value to set.
966  *
967  * @note There might be glitch when changing the asynchronous divider, so make sure
968  * the asynchronous clock is not used while changing divider.
969  */
CLOCK_SetSysOscAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)970 static inline void CLOCK_SetSysOscAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
971 {
972     uint32_t reg = SCG->SOSCDIV;
973 
974     switch (asyncClk)
975     {
976         case kSCG_AsyncDiv3Clk:
977             reg = (reg & ~SCG_SOSCDIV_SOSCDIV3_MASK) | SCG_SOSCDIV_SOSCDIV3(divider);
978             break;
979         case kSCG_AsyncDiv2Clk:
980             reg = (reg & ~SCG_SOSCDIV_SOSCDIV2_MASK) | SCG_SOSCDIV_SOSCDIV2(divider);
981             break;
982         default:
983             reg = (reg & ~SCG_SOSCDIV_SOSCDIV1_MASK) | SCG_SOSCDIV_SOSCDIV1(divider);
984             break;
985     }
986 
987     SCG->SOSCDIV = reg;
988 }
989 
990 /*!
991  * @brief Gets the SCG system OSC clock frequency (SYSOSC).
992  *
993  * @return  Clock frequency; If the clock is invalid, returns 0.
994  */
995 uint32_t CLOCK_GetSysOscFreq(void);
996 
997 /*!
998  * @brief Gets the SCG asynchronous clock frequency from the system OSC.
999  *
1000  * @param type     The asynchronous clock type.
1001  * @return  Clock frequency; If the clock is invalid, returns 0.
1002  */
1003 uint32_t CLOCK_GetSysOscAsyncFreq(scg_async_clk_t type);
1004 
1005 /*!
1006  * @brief Checks whether the system OSC clock error occurs.
1007  *
1008  * @return  True if the error occurs, false if not.
1009  */
CLOCK_IsSysOscErr(void)1010 static inline bool CLOCK_IsSysOscErr(void)
1011 {
1012     return (bool)(SCG->SOSCCSR & SCG_SOSCCSR_SOSCERR_MASK);
1013 }
1014 
1015 /*!
1016  * @brief Clears the system OSC clock error.
1017  */
CLOCK_ClearSysOscErr(void)1018 static inline void CLOCK_ClearSysOscErr(void)
1019 {
1020     SCG->SOSCCSR |= SCG_SOSCCSR_SOSCERR_MASK;
1021 }
1022 
1023 /*!
1024  * @brief Sets the system OSC monitor mode.
1025  *
1026  * This function sets the system OSC monitor mode. The mode can be disabled,
1027  * it can generate an interrupt when the error is disabled, or reset when the error is detected.
1028  *
1029  * @param mode Monitor mode to set.
1030  */
CLOCK_SetSysOscMonitorMode(scg_sosc_monitor_mode_t mode)1031 static inline void CLOCK_SetSysOscMonitorMode(scg_sosc_monitor_mode_t mode)
1032 {
1033     uint32_t reg = SCG->SOSCCSR;
1034 
1035     reg &= ~(SCG_SOSCCSR_SOSCCM_MASK | SCG_SOSCCSR_SOSCCMRE_MASK);
1036 
1037     reg |= (uint32_t)mode;
1038 
1039     SCG->SOSCCSR = reg;
1040 }
1041 
1042 /*!
1043  * @brief Checks whether the system OSC clock is valid.
1044  *
1045  * @return  True if clock is valid, false if not.
1046  */
CLOCK_IsSysOscValid(void)1047 static inline bool CLOCK_IsSysOscValid(void)
1048 {
1049     return (bool)(SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK);
1050 }
1051 /* @} */
1052 
1053 /*!
1054  * @name SCG Slow IRC Clock.
1055  * @{
1056  */
1057 
1058 /*!
1059  * @brief Initializes the SCG slow IRC clock.
1060  *
1061  * This function enables the SCG slow IRC clock according to the
1062  * configuration.
1063  *
1064  * @param config   Pointer to the configuration structure.
1065  * @retval kStatus_Success SIRC is initialized.
1066  * @retval kStatus_SCG_Busy SIRC has been enabled and is used by system clock.
1067  * @retval kStatus_ReadOnly SIRC control register is locked.
1068  *
1069  * @note This function can't detect whether the system OSC has been enabled and
1070  * used by an IP.
1071  */
1072 status_t CLOCK_InitSirc(const scg_sirc_config_t *config);
1073 
1074 /*!
1075  * @brief De-initializes the SCG slow IRC.
1076  *
1077  * This function disables the SCG slow IRC.
1078  *
1079  * @retval kStatus_Success SIRC is deinitialized.
1080  * @retval kStatus_SCG_Busy SIRC is used by system clock.
1081  * @retval kStatus_ReadOnly SIRC control register is locked.
1082  *
1083  * @note This function can't detect whether the SIRC is used by an IP.
1084  */
1085 status_t CLOCK_DeinitSirc(void);
1086 
1087 /*!
1088  * @brief Set the asynchronous clock divider.
1089  *
1090  * @param asyncClk Which asynchronous clock to configure.
1091  * @param divider The divider value to set.
1092  *
1093  * @note There might be glitch when changing the asynchronous divider, so make sure
1094  * the asynchronous clock is not used while changing divider.
1095  */
CLOCK_SetSircAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)1096 static inline void CLOCK_SetSircAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
1097 {
1098     uint32_t reg = SCG->SIRCDIV;
1099 
1100     switch (asyncClk)
1101     {
1102         case kSCG_AsyncDiv3Clk:
1103             reg = (reg & ~SCG_SIRCDIV_SIRCDIV3_MASK) | SCG_SIRCDIV_SIRCDIV3(divider);
1104             break;
1105         case kSCG_AsyncDiv2Clk:
1106             reg = (reg & ~SCG_SIRCDIV_SIRCDIV2_MASK) | SCG_SIRCDIV_SIRCDIV2(divider);
1107             break;
1108         default:
1109             reg = (reg & ~SCG_SIRCDIV_SIRCDIV1_MASK) | SCG_SIRCDIV_SIRCDIV1(divider);
1110             break;
1111     }
1112 
1113     SCG->SIRCDIV = reg;
1114 }
1115 
1116 /*!
1117  * @brief Gets the SCG SIRC clock frequency.
1118  *
1119  * @return  Clock frequency; If the clock is invalid, returns 0.
1120  */
1121 uint32_t CLOCK_GetSircFreq(void);
1122 
1123 /*!
1124  * @brief Gets the SCG asynchronous clock frequency from the SIRC.
1125  *
1126  * @param type     The asynchronous clock type.
1127  * @return  Clock frequency; If the clock is invalid, returns 0.
1128  */
1129 uint32_t CLOCK_GetSircAsyncFreq(scg_async_clk_t type);
1130 
1131 /*!
1132  * @brief Checks whether the SIRC clock is valid.
1133  *
1134  * @return  True if clock is valid, false if not.
1135  */
CLOCK_IsSircValid(void)1136 static inline bool CLOCK_IsSircValid(void)
1137 {
1138     return (bool)(SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK);
1139 }
1140 /* @} */
1141 
1142 /*!
1143  * @name SCG Fast IRC Clock.
1144  * @{
1145  */
1146 
1147 /*!
1148  * @brief Initializes the SCG fast IRC clock.
1149  *
1150  * This function enables the SCG fast IRC clock according to the configuration.
1151  *
1152  * @param config   Pointer to the configuration structure.
1153  * @retval kStatus_Success FIRC is initialized.
1154  * @retval kStatus_SCG_Busy FIRC has been enabled and is used by the system clock.
1155  * @retval kStatus_ReadOnly FIRC control register is locked.
1156  *
1157  * @note This function can't detect whether the FIRC has been enabled and
1158  * used by an IP.
1159  */
1160 status_t CLOCK_InitFirc(const scg_firc_config_t *config);
1161 
1162 /*!
1163  * @brief De-initializes the SCG fast IRC.
1164  *
1165  * This function disables the SCG fast IRC.
1166  *
1167  * @retval kStatus_Success FIRC is deinitialized.
1168  * @retval kStatus_SCG_Busy FIRC is used by the system clock.
1169  * @retval kStatus_ReadOnly FIRC control register is locked.
1170  *
1171  * @note This function can't detect whether the FIRC is used by an IP.
1172  */
1173 status_t CLOCK_DeinitFirc(void);
1174 
1175 /*!
1176  * @brief Set the asynchronous clock divider.
1177  *
1178  * @param asyncClk Which asynchronous clock to configure.
1179  * @param divider The divider value to set.
1180  *
1181  * @note There might be glitch when changing the asynchronous divider, so make sure
1182  * the asynchronous clock is not used while changing divider.
1183  */
CLOCK_SetFircAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)1184 static inline void CLOCK_SetFircAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
1185 {
1186     uint32_t reg = SCG->FIRCDIV;
1187 
1188     switch (asyncClk)
1189     {
1190         case kSCG_AsyncDiv3Clk:
1191             reg = (reg & ~SCG_FIRCDIV_FIRCDIV3_MASK) | SCG_FIRCDIV_FIRCDIV3(divider);
1192             break;
1193         case kSCG_AsyncDiv2Clk:
1194             reg = (reg & ~SCG_FIRCDIV_FIRCDIV2_MASK) | SCG_FIRCDIV_FIRCDIV2(divider);
1195             break;
1196         default:
1197             reg = (reg & ~SCG_FIRCDIV_FIRCDIV1_MASK) | SCG_FIRCDIV_FIRCDIV1(divider);
1198             break;
1199     }
1200 
1201     SCG->FIRCDIV = reg;
1202 }
1203 
1204 /*!
1205  * @brief Gets the SCG FIRC clock frequency.
1206  *
1207  * @return  Clock frequency; If the clock is invalid, returns 0.
1208  */
1209 uint32_t CLOCK_GetFircFreq(void);
1210 
1211 /*!
1212  * @brief Gets the SCG asynchronous clock frequency from the FIRC.
1213  *
1214  * @param type     The asynchronous clock type.
1215  * @return  Clock frequency; If the clock is invalid, returns 0.
1216  */
1217 uint32_t CLOCK_GetFircAsyncFreq(scg_async_clk_t type);
1218 
1219 /*!
1220  * @brief Checks whether the FIRC clock error occurs.
1221  *
1222  * @return  True if the error occurs, false if not.
1223  */
CLOCK_IsFircErr(void)1224 static inline bool CLOCK_IsFircErr(void)
1225 {
1226     return (bool)(SCG->FIRCCSR & SCG_FIRCCSR_FIRCERR_MASK);
1227 }
1228 
1229 /*!
1230  * @brief Clears the FIRC clock error.
1231  */
CLOCK_ClearFircErr(void)1232 static inline void CLOCK_ClearFircErr(void)
1233 {
1234     SCG->FIRCCSR |= SCG_FIRCCSR_FIRCERR_MASK;
1235 }
1236 
1237 /*!
1238  * @brief Checks whether the FIRC clock is valid.
1239  *
1240  * @return  True if clock is valid, false if not.
1241  */
CLOCK_IsFircValid(void)1242 static inline bool CLOCK_IsFircValid(void)
1243 {
1244     return (bool)(SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK);
1245 }
1246 /* @} */
1247 
1248 /*!
1249  * @name SCG System PLL Clock.
1250  * @{
1251  */
1252 
1253 /*!
1254  * @brief Calculates the MULT and PREDIV for the PLL.
1255  *
1256  * This function calculates the proper MULT and PREDIV to generate the desired PLL
1257  * output frequency with the input reference clock frequency. It returns the closest
1258  * frequency match that the PLL can generate. The corresponding MULT/PREDIV are returned with
1259  * parameters. If the desired frequency is not valid, this function returns 0.
1260  *
1261  * @param refFreq     The input reference clock frequency.
1262  * @param desireFreq  The desired output clock frequency.
1263  * @param mult        The value of MULT.
1264  * @param prediv      The value of PREDIV.
1265  * @return The PLL output frequency with the MULT and PREDIV; If
1266  * the desired frequency can't be generated, this function returns 0U.
1267  */
1268 uint32_t CLOCK_GetSysPllMultDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *mult, uint8_t *prediv);
1269 
1270 /*!
1271  * @brief Initializes the SCG system PLL.
1272  *
1273  * This function enables the SCG system PLL clock according to the
1274  * configuration. The system PLL can use the system OSC or FIRC as
1275  * the clock source. Ensure that the source clock is valid before
1276  * calling this function.
1277  *
1278  * Example code for initializing SPLL clock output:
1279  * @code
1280  * const scg_spll_config_t g_scgSysPllConfig = {.enableMode = kSCG_SysPllEnable,
1281  *                                            .monitorMode = kSCG_SysPllMonitorDisable,
1282  *                                            .div1 = kSCG_AsyncClkDivBy1,
1283  *                                            .div2 = kSCG_AsyncClkDisable,
1284  *                                            .div3 = kSCG_AsyncClkDivBy2,
1285  *                                            .src = kSCG_SysPllSrcFirc,
1286  *                                            .isBypassSelected = false,
1287  *                                            .isPfdSelected = false,
1288  *                                            .prediv = 5U,
1289  *                                            .pfdClkout = kSCG_AuxPllPfd0Clk,
1290  * @endcode
1291  *
1292  * @param config   Pointer to the configuration structure.
1293  * @retval kStatus_Success System PLL is initialized.
1294  * @retval kStatus_SCG_Busy System PLL has been enabled and is used by the system clock.
1295  * @retval kStatus_ReadOnly System PLL control register is locked.
1296  *
1297  * @note This function can't detect whether the system PLL has been enabled and
1298  * used by an IP.
1299  */
1300 status_t CLOCK_InitSysPll(const scg_spll_config_t *config);
1301 
1302 /*!
1303  * @brief De-initializes the SCG system PLL.
1304  *
1305  * This function disables the SCG system PLL.
1306  *
1307  * @retval kStatus_Success system PLL is deinitialized.
1308  * @retval kStatus_SCG_Busy system PLL is used by the system clock.
1309  * @retval kStatus_ReadOnly System PLL control register is locked.
1310  *
1311  * @note This function can't detect whether the system PLL is used by an IP.
1312  */
1313 status_t CLOCK_DeinitSysPll(void);
1314 
1315 /*!
1316  * @brief Set the asynchronous clock divider.
1317  *
1318  * @param asyncClk Which asynchronous clock to configure.
1319  * @param divider The divider value to set.
1320  *
1321  * @note There might be glitch when changing the asynchronous divider, so make sure
1322  * the asynchronous clock is not used while changing divider.
1323  */
CLOCK_SetSysPllAsyncClkDiv(scg_async_clk_t asyncClk,scg_async_clk_div_t divider)1324 static inline void CLOCK_SetSysPllAsyncClkDiv(scg_async_clk_t asyncClk, scg_async_clk_div_t divider)
1325 {
1326     uint32_t reg = SCG->SPLLDIV;
1327 
1328     switch (asyncClk)
1329     {
1330         case kSCG_AsyncDiv3Clk:
1331             reg = (reg & ~SCG_SPLLDIV_SPLLDIV3_MASK) | SCG_SPLLDIV_SPLLDIV3(divider);
1332             break;
1333         case kSCG_AsyncDiv2Clk:
1334             reg = (reg & ~SCG_SPLLDIV_SPLLDIV2_MASK) | SCG_SPLLDIV_SPLLDIV2(divider);
1335             break;
1336         default:
1337             reg = (reg & ~SCG_SPLLDIV_SPLLDIV1_MASK) | SCG_SPLLDIV_SPLLDIV1(divider);
1338             break;
1339     }
1340 
1341     SCG->SPLLDIV = reg;
1342 }
1343 
1344 /*!
1345  * @brief Gets the SCG system PLL clock frequency.
1346  *
1347  * @return  Clock frequency; If the clock is invalid, returns 0.
1348  */
1349 uint32_t CLOCK_GetSysPllFreq(void);
1350 
1351 /*!
1352  * @brief Gets the SCG asynchronous clock frequency from the system PLL.
1353  *
1354  * @param type     The asynchronous clock type.
1355  * @return  Clock frequency; If the clock is invalid, returns 0.
1356  */
1357 uint32_t CLOCK_GetSysPllAsyncFreq(scg_async_clk_t type);
1358 
1359 /*!
1360  * @brief Checks whether the system PLL clock error occurs.
1361  *
1362  * @return  True if an error occurs, false if not.
1363  */
CLOCK_IsSysPllErr(void)1364 static inline bool CLOCK_IsSysPllErr(void)
1365 {
1366     return (bool)(SCG->SPLLCSR & SCG_SPLLCSR_SPLLERR_MASK);
1367 }
1368 
1369 /*!
1370  * @brief Clears the system PLL clock error.
1371  */
CLOCK_ClearSysPllErr(void)1372 static inline void CLOCK_ClearSysPllErr(void)
1373 {
1374     SCG->SPLLCSR |= SCG_SPLLCSR_SPLLERR_MASK;
1375 }
1376 
1377 /*!
1378  * @brief Sets the system PLL monitor mode.
1379  *
1380  * This function sets the system PLL monitor mode. The mode can be disabled.
1381  * It can generate an interrupt when the error is disabled, or reset when the error is detected.
1382  *
1383  * @param mode Monitor mode to set.
1384  */
CLOCK_SetSysPllMonitorMode(scg_spll_monitor_mode_t mode)1385 static inline void CLOCK_SetSysPllMonitorMode(scg_spll_monitor_mode_t mode)
1386 {
1387     uint32_t reg = SCG->SPLLCSR;
1388 
1389     reg &= ~(SCG_SPLLCSR_SPLLCM_MASK | SCG_SPLLCSR_SPLLCMRE_MASK);
1390 
1391     reg |= (uint32_t)mode;
1392 
1393     SCG->SPLLCSR = reg;
1394 }
1395 
1396 /*!
1397  * @brief Checks whether the system PLL clock is valid.
1398  *
1399  * @return  True if the clock is valid, false if not.
1400  */
CLOCK_IsSysPllValid(void)1401 static inline bool CLOCK_IsSysPllValid(void)
1402 {
1403     return (bool)(SCG->SPLLCSR & SCG_SPLLCSR_SPLLVLD_MASK);
1404 }
1405 /* @} */
1406 
1407 /*!
1408  * @name External clock frequency
1409  * @{
1410  */
1411 
1412 /*!
1413  * @brief Sets the XTAL0 frequency based on board settings.
1414  *
1415  * @param freq The XTAL0/EXTAL0 input clock frequency in Hz.
1416  */
CLOCK_SetXtal0Freq(uint32_t freq)1417 static inline void CLOCK_SetXtal0Freq(uint32_t freq)
1418 {
1419     g_xtal0Freq = freq;
1420 }
1421 
1422 /* @} */
1423 
1424 #if defined(__cplusplus)
1425 }
1426 #endif /* __cplusplus */
1427 
1428 /*! @} */
1429 
1430 #endif /* _FSL_CLOCK_H_ */
1431