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