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