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