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