diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1015/drivers/fsl_clock.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1015/drivers/fsl_clock.c | 1175 |
1 files changed, 1175 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1015/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1015/drivers/fsl_clock.c new file mode 100644 index 000000000..f7077d032 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT1015/drivers/fsl_clock.c | |||
@@ -0,0 +1,1175 @@ | |||
1 | /* | ||
2 | * Copyright 2018-2020 NXP | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * SPDX-License-Identifier: BSD-3-Clause | ||
6 | */ | ||
7 | |||
8 | #include "fsl_clock.h" | ||
9 | /* Component ID definition, used by tools. */ | ||
10 | #ifndef FSL_COMPONENT_ID | ||
11 | #define FSL_COMPONENT_ID "platform.drivers.clock" | ||
12 | #endif | ||
13 | |||
14 | /******************************************************************************* | ||
15 | * Definitions | ||
16 | ******************************************************************************/ | ||
17 | /* To make full use of CM7 hardware FPU, use double instead of uint64_t in clock driver to | ||
18 | achieve better performance, it is depend on the IDE Floating point settings, if double precision is selected | ||
19 | in IDE, clock_64b_t will switch to double type automatically. only support IAR and MDK here */ | ||
20 | #if __FPU_USED | ||
21 | |||
22 | #if (defined(__ICCARM__)) | ||
23 | |||
24 | #if (__ARMVFP__ >= __ARMFPV5__) && \ | ||
25 | (__ARM_FP == 0xE) /*0xe implies support for half, single and double precision operations*/ | ||
26 | typedef double clock_64b_t; | ||
27 | #else | ||
28 | typedef uint64_t clock_64b_t; | ||
29 | #endif | ||
30 | |||
31 | #elif (defined(__GNUC__)) | ||
32 | |||
33 | #if (__ARM_FP == 0xE) /*0xe implies support for half, single and double precision operations*/ | ||
34 | typedef double clock_64b_t; | ||
35 | #else | ||
36 | typedef uint64_t clock_64b_t; | ||
37 | #endif | ||
38 | |||
39 | #elif defined(__CC_ARM) || defined(__ARMCC_VERSION) | ||
40 | |||
41 | #if defined __TARGET_FPU_FPV5_D16 | ||
42 | typedef double clock_64b_t; | ||
43 | #else | ||
44 | typedef uint64_t clock_64b_t; | ||
45 | #endif | ||
46 | |||
47 | #else | ||
48 | typedef uint64_t clock_64b_t; | ||
49 | #endif | ||
50 | |||
51 | #else | ||
52 | typedef uint64_t clock_64b_t; | ||
53 | #endif | ||
54 | |||
55 | /******************************************************************************* | ||
56 | * Variables | ||
57 | ******************************************************************************/ | ||
58 | |||
59 | /* External XTAL (OSC) clock frequency. */ | ||
60 | volatile uint32_t g_xtalFreq; | ||
61 | /* External RTC XTAL clock frequency. */ | ||
62 | volatile uint32_t g_rtcXtalFreq; | ||
63 | |||
64 | /******************************************************************************* | ||
65 | * Prototypes | ||
66 | ******************************************************************************/ | ||
67 | |||
68 | /*! | ||
69 | * @brief Get the periph clock frequency. | ||
70 | * | ||
71 | * @return Periph clock frequency in Hz. | ||
72 | */ | ||
73 | static uint32_t CLOCK_GetPeriphClkFreq(void); | ||
74 | |||
75 | /*! | ||
76 | * @brief Get the frequency of PLL USB1 software clock. | ||
77 | * | ||
78 | * @return The frequency of PLL USB1 software clock. | ||
79 | */ | ||
80 | static uint32_t CLOCK_GetPllUsb1SWFreq(void); | ||
81 | |||
82 | /******************************************************************************* | ||
83 | * Code | ||
84 | ******************************************************************************/ | ||
85 | |||
86 | static uint32_t CLOCK_GetPeriphClkFreq(void) | ||
87 | { | ||
88 | uint32_t freq; | ||
89 | |||
90 | /* Periph_clk2_clk ---> Periph_clk */ | ||
91 | if ((CCM->CBCDR & CCM_CBCDR_PERIPH_CLK_SEL_MASK) != 0UL) | ||
92 | { | ||
93 | switch (CCM->CBCMR & CCM_CBCMR_PERIPH_CLK2_SEL_MASK) | ||
94 | { | ||
95 | /* Pll3_sw_clk ---> Periph_clk2_clk ---> Periph_clk */ | ||
96 | case CCM_CBCMR_PERIPH_CLK2_SEL(0U): | ||
97 | freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1); | ||
98 | break; | ||
99 | |||
100 | /* Osc_clk ---> Periph_clk2_clk ---> Periph_clk */ | ||
101 | case CCM_CBCMR_PERIPH_CLK2_SEL(1U): | ||
102 | freq = CLOCK_GetOscFreq(); | ||
103 | break; | ||
104 | |||
105 | case CCM_CBCMR_PERIPH_CLK2_SEL(2U): | ||
106 | freq = CLOCK_GetPllFreq(kCLOCK_PllSys); | ||
107 | break; | ||
108 | |||
109 | case CCM_CBCMR_PERIPH_CLK2_SEL(3U): | ||
110 | default: | ||
111 | freq = 0U; | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | freq /= (((CCM->CBCDR & CCM_CBCDR_PERIPH_CLK2_PODF_MASK) >> CCM_CBCDR_PERIPH_CLK2_PODF_SHIFT) + 1U); | ||
116 | } | ||
117 | /* Pre_Periph_clk ---> Periph_clk */ | ||
118 | else | ||
119 | { | ||
120 | switch (CCM->CBCMR & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) | ||
121 | { | ||
122 | /* PLL2 */ | ||
123 | case CCM_CBCMR_PRE_PERIPH_CLK_SEL(0U): | ||
124 | freq = CLOCK_GetPllFreq(kCLOCK_PllSys); | ||
125 | break; | ||
126 | |||
127 | /* PLL3 PFD3 */ | ||
128 | case CCM_CBCMR_PRE_PERIPH_CLK_SEL(1U): | ||
129 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd3); | ||
130 | break; | ||
131 | |||
132 | /* PLL2 PFD3 */ | ||
133 | case CCM_CBCMR_PRE_PERIPH_CLK_SEL(2U): | ||
134 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd3); | ||
135 | break; | ||
136 | |||
137 | /* PLL6 divided(/1) */ | ||
138 | case CCM_CBCMR_PRE_PERIPH_CLK_SEL(3U): | ||
139 | freq = 500000000U; | ||
140 | break; | ||
141 | |||
142 | default: | ||
143 | freq = 0U; | ||
144 | break; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | return freq; | ||
149 | } | ||
150 | |||
151 | static uint32_t CLOCK_GetPllUsb1SWFreq(void) | ||
152 | { | ||
153 | uint32_t freq; | ||
154 | |||
155 | switch ((CCM->CCSR & CCM_CCSR_PLL3_SW_CLK_SEL_MASK) >> CCM_CCSR_PLL3_SW_CLK_SEL_SHIFT) | ||
156 | { | ||
157 | case 0: | ||
158 | { | ||
159 | freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1); | ||
160 | break; | ||
161 | } | ||
162 | case 1: | ||
163 | { | ||
164 | freq = 24000000UL; | ||
165 | break; | ||
166 | } | ||
167 | default: | ||
168 | freq = 0UL; | ||
169 | break; | ||
170 | } | ||
171 | |||
172 | return freq; | ||
173 | } | ||
174 | |||
175 | /*! | ||
176 | * brief Initialize the external 24MHz clock. | ||
177 | * | ||
178 | * This function supports two modes: | ||
179 | * 1. Use external crystal oscillator. | ||
180 | * 2. Bypass the external crystal oscillator, using input source clock directly. | ||
181 | * | ||
182 | * After this function, please call ref CLOCK_SetXtal0Freq to inform clock driver | ||
183 | * the external clock frequency. | ||
184 | * | ||
185 | * param bypassXtalOsc Pass in true to bypass the external crystal oscillator. | ||
186 | * note This device does not support bypass external crystal oscillator, so | ||
187 | * the input parameter should always be false. | ||
188 | */ | ||
189 | void CLOCK_InitExternalClk(bool bypassXtalOsc) | ||
190 | { | ||
191 | /* This device does not support bypass XTAL OSC. */ | ||
192 | assert(!bypassXtalOsc); | ||
193 | |||
194 | CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power up */ | ||
195 | while ((XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_MASK) == 0UL) | ||
196 | { | ||
197 | } | ||
198 | CCM_ANALOG->MISC0_SET = (uint32_t)CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; /* detect freq */ | ||
199 | while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_OSC_XTALOK_MASK) == 0UL) | ||
200 | { | ||
201 | } | ||
202 | CCM_ANALOG->MISC0_CLR = (uint32_t)CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; | ||
203 | } | ||
204 | |||
205 | /*! | ||
206 | * brief Deinitialize the external 24MHz clock. | ||
207 | * | ||
208 | * This function disables the external 24MHz clock. | ||
209 | * | ||
210 | * After this function, please call ref CLOCK_SetXtal0Freq to set external clock | ||
211 | * frequency to 0. | ||
212 | */ | ||
213 | void CLOCK_DeinitExternalClk(void) | ||
214 | { | ||
215 | CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power down */ | ||
216 | } | ||
217 | |||
218 | /*! | ||
219 | * brief Switch the OSC. | ||
220 | * | ||
221 | * This function switches the OSC source for SoC. | ||
222 | * | ||
223 | * param osc OSC source to switch to. | ||
224 | */ | ||
225 | void CLOCK_SwitchOsc(clock_osc_t osc) | ||
226 | { | ||
227 | if (osc == kCLOCK_RcOsc) | ||
228 | { | ||
229 | XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_SET_OSC_SEL_MASK; | ||
230 | } | ||
231 | else | ||
232 | { | ||
233 | XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_MASK; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | /*! | ||
238 | * brief Initialize the RC oscillator 24MHz clock. | ||
239 | */ | ||
240 | void CLOCK_InitRcOsc24M(void) | ||
241 | { | ||
242 | XTALOSC24M->LOWPWR_CTRL |= XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK; | ||
243 | } | ||
244 | |||
245 | /*! | ||
246 | * brief Power down the RCOSC 24M clock. | ||
247 | */ | ||
248 | void CLOCK_DeinitRcOsc24M(void) | ||
249 | { | ||
250 | XTALOSC24M->LOWPWR_CTRL &= ~XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK; | ||
251 | } | ||
252 | |||
253 | /*! | ||
254 | * brief Gets the AHB clock frequency. | ||
255 | * | ||
256 | * return The AHB clock frequency value in hertz. | ||
257 | */ | ||
258 | uint32_t CLOCK_GetAhbFreq(void) | ||
259 | { | ||
260 | return CLOCK_GetPeriphClkFreq() / (((CCM->CBCDR & CCM_CBCDR_AHB_PODF_MASK) >> CCM_CBCDR_AHB_PODF_SHIFT) + 1U); | ||
261 | } | ||
262 | |||
263 | /*! | ||
264 | * brief Gets the SEMC clock frequency. | ||
265 | * | ||
266 | * return The SEMC clock frequency value in hertz. | ||
267 | */ | ||
268 | uint32_t CLOCK_GetSemcFreq(void) | ||
269 | { | ||
270 | uint32_t freq; | ||
271 | |||
272 | /* SEMC alternative clock ---> SEMC Clock */ | ||
273 | if ((CCM->CBCDR & CCM_CBCDR_SEMC_CLK_SEL_MASK) != 0UL) | ||
274 | { | ||
275 | /* PLL3 PFD1 ---> SEMC alternative clock ---> SEMC Clock */ | ||
276 | if ((CCM->CBCDR & CCM_CBCDR_SEMC_ALT_CLK_SEL_MASK) != 0UL) | ||
277 | { | ||
278 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1); | ||
279 | } | ||
280 | /* PLL2 PFD2 ---> SEMC alternative clock ---> SEMC Clock */ | ||
281 | else | ||
282 | { | ||
283 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2); | ||
284 | } | ||
285 | } | ||
286 | /* Periph_clk ---> SEMC Clock */ | ||
287 | else | ||
288 | { | ||
289 | freq = CLOCK_GetPeriphClkFreq(); | ||
290 | } | ||
291 | |||
292 | freq /= (((CCM->CBCDR & CCM_CBCDR_SEMC_PODF_MASK) >> CCM_CBCDR_SEMC_PODF_SHIFT) + 1U); | ||
293 | |||
294 | return freq; | ||
295 | } | ||
296 | |||
297 | /*! | ||
298 | * brief Gets the IPG clock frequency. | ||
299 | * | ||
300 | * return The IPG clock frequency value in hertz. | ||
301 | */ | ||
302 | uint32_t CLOCK_GetIpgFreq(void) | ||
303 | { | ||
304 | return CLOCK_GetAhbFreq() / (((CCM->CBCDR & CCM_CBCDR_IPG_PODF_MASK) >> CCM_CBCDR_IPG_PODF_SHIFT) + 1U); | ||
305 | } | ||
306 | |||
307 | /*! | ||
308 | * brief Gets the PER clock frequency. | ||
309 | * | ||
310 | * return The PER clock frequency value in hertz. | ||
311 | */ | ||
312 | uint32_t CLOCK_GetPerClkFreq(void) | ||
313 | { | ||
314 | uint32_t freq; | ||
315 | |||
316 | /* Osc_clk ---> PER Clock*/ | ||
317 | if ((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK) != 0UL) | ||
318 | { | ||
319 | freq = CLOCK_GetOscFreq(); | ||
320 | } | ||
321 | /* Periph_clk ---> AHB Clock ---> IPG Clock ---> PER Clock */ | ||
322 | else | ||
323 | { | ||
324 | freq = CLOCK_GetIpgFreq(); | ||
325 | } | ||
326 | |||
327 | freq /= (((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_PODF_MASK) >> CCM_CSCMR1_PERCLK_PODF_SHIFT) + 1U); | ||
328 | |||
329 | return freq; | ||
330 | } | ||
331 | |||
332 | /*! | ||
333 | * brief Gets the clock frequency for a specific clock name. | ||
334 | * | ||
335 | * This function checks the current clock configurations and then calculates | ||
336 | * the clock frequency for a specific clock name defined in clock_name_t. | ||
337 | * | ||
338 | * param clockName Clock names defined in clock_name_t | ||
339 | * return Clock frequency value in hertz | ||
340 | */ | ||
341 | uint32_t CLOCK_GetFreq(clock_name_t name) | ||
342 | { | ||
343 | uint32_t freq; | ||
344 | |||
345 | switch (name) | ||
346 | { | ||
347 | case kCLOCK_CpuClk: | ||
348 | case kCLOCK_AhbClk: | ||
349 | freq = CLOCK_GetAhbFreq(); | ||
350 | break; | ||
351 | |||
352 | case kCLOCK_SemcClk: | ||
353 | freq = CLOCK_GetSemcFreq(); | ||
354 | break; | ||
355 | |||
356 | case kCLOCK_IpgClk: | ||
357 | freq = CLOCK_GetIpgFreq(); | ||
358 | break; | ||
359 | |||
360 | case kCLOCK_PerClk: | ||
361 | freq = CLOCK_GetPerClkFreq(); | ||
362 | break; | ||
363 | |||
364 | case kCLOCK_OscClk: | ||
365 | freq = CLOCK_GetOscFreq(); | ||
366 | break; | ||
367 | case kCLOCK_RtcClk: | ||
368 | freq = CLOCK_GetRtcFreq(); | ||
369 | break; | ||
370 | case kCLOCK_Usb1PllClk: | ||
371 | freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1); | ||
372 | break; | ||
373 | case kCLOCK_Usb1PllPfd0Clk: | ||
374 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd0); | ||
375 | break; | ||
376 | case kCLOCK_Usb1PllPfd1Clk: | ||
377 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1); | ||
378 | break; | ||
379 | case kCLOCK_Usb1PllPfd2Clk: | ||
380 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd2); | ||
381 | break; | ||
382 | case kCLOCK_Usb1PllPfd3Clk: | ||
383 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd3); | ||
384 | break; | ||
385 | case kCLOCK_Usb1SwClk: | ||
386 | freq = CLOCK_GetPllUsb1SWFreq(); | ||
387 | break; | ||
388 | case kCLOCK_Usb1Sw60MClk: | ||
389 | freq = CLOCK_GetPllUsb1SWFreq() / 8UL; | ||
390 | break; | ||
391 | case kCLOCK_Usb1Sw80MClk: | ||
392 | freq = CLOCK_GetPllUsb1SWFreq() / 6UL; | ||
393 | break; | ||
394 | case kCLOCK_SysPllClk: | ||
395 | freq = CLOCK_GetPllFreq(kCLOCK_PllSys); | ||
396 | break; | ||
397 | case kCLOCK_SysPllPfd0Clk: | ||
398 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0); | ||
399 | break; | ||
400 | case kCLOCK_SysPllPfd1Clk: | ||
401 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd1); | ||
402 | break; | ||
403 | case kCLOCK_SysPllPfd2Clk: | ||
404 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2); | ||
405 | break; | ||
406 | case kCLOCK_SysPllPfd3Clk: | ||
407 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd3); | ||
408 | break; | ||
409 | case kCLOCK_EnetPll500MClk: | ||
410 | freq = CLOCK_GetPllFreq(kCLOCK_PllEnet500M); | ||
411 | break; | ||
412 | case kCLOCK_AudioPllClk: | ||
413 | freq = CLOCK_GetPllFreq(kCLOCK_PllAudio); | ||
414 | break; | ||
415 | default: | ||
416 | freq = 0U; | ||
417 | break; | ||
418 | } | ||
419 | |||
420 | return freq; | ||
421 | } | ||
422 | |||
423 | /*! | ||
424 | * brief Gets the frequency of selected clock root. | ||
425 | * | ||
426 | * param clockRoot The clock root used to get the frequency, please refer to @ref clock_root_t. | ||
427 | * return The frequency of selected clock root. | ||
428 | */ | ||
429 | uint32_t CLOCK_GetClockRootFreq(clock_root_t clockRoot) | ||
430 | { | ||
431 | const clock_name_t clockRootSourceArray[][4] = CLOCK_ROOT_SOUCE; | ||
432 | const clock_mux_t clockRootMuxTupleArray[] = CLOCK_ROOT_MUX_TUPLE; | ||
433 | const clock_div_t clockRootDivTupleArray[][2] = CLOCK_ROOT_DIV_TUPLE; | ||
434 | uint32_t freq = 0UL; | ||
435 | clock_mux_t clockRootMuxTuple = clockRootMuxTupleArray[(uint8_t)clockRoot]; | ||
436 | clock_div_t clockRootPreDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][0]; | ||
437 | clock_div_t clockRootPostDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][1]; | ||
438 | uint32_t clockRootMuxValue = (CCM_TUPLE_REG(CCM, clockRootMuxTuple) & CCM_TUPLE_MASK(clockRootMuxTuple)) >> | ||
439 | CCM_TUPLE_SHIFT(clockRootMuxTuple); | ||
440 | clock_name_t clockSourceName; | ||
441 | |||
442 | clockSourceName = clockRootSourceArray[(uint8_t)clockRoot][clockRootMuxValue]; | ||
443 | |||
444 | assert(clockSourceName != kCLOCK_NoneName); | ||
445 | |||
446 | freq = CLOCK_GetFreq(clockSourceName); | ||
447 | |||
448 | if (clockRootPreDivTuple != kCLOCK_NonePreDiv) | ||
449 | { | ||
450 | freq /= ((CCM_TUPLE_REG(CCM, clockRootPreDivTuple) & CCM_TUPLE_MASK(clockRootPreDivTuple)) >> | ||
451 | CCM_TUPLE_SHIFT(clockRootPreDivTuple)) + | ||
452 | 1UL; | ||
453 | } | ||
454 | |||
455 | freq /= ((CCM_TUPLE_REG(CCM, clockRootPostDivTuple) & CCM_TUPLE_MASK(clockRootPostDivTuple)) >> | ||
456 | CCM_TUPLE_SHIFT(clockRootPostDivTuple)) + | ||
457 | 1UL; | ||
458 | |||
459 | return freq; | ||
460 | } | ||
461 | |||
462 | /*! brief Enable USB HS clock. | ||
463 | * | ||
464 | * This function only enables the access to USB HS prepheral, upper layer | ||
465 | * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY | ||
466 | * clock to use USB HS. | ||
467 | * | ||
468 | * param src USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused. | ||
469 | * param freq USB HS does not care about the clock source, so this parameter is ignored. | ||
470 | * retval true The clock is set successfully. | ||
471 | * retval false The clock source is invalid to get proper USB HS clock. | ||
472 | */ | ||
473 | bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) | ||
474 | { | ||
475 | uint32_t i; | ||
476 | CCM->CCGR6 |= CCM_CCGR6_CG0_MASK; | ||
477 | USB->USBCMD |= USBHS_USBCMD_RST_MASK; | ||
478 | |||
479 | /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/ | ||
480 | for (i = 0; i < 400000UL; i++) | ||
481 | { | ||
482 | __ASM("nop"); | ||
483 | } | ||
484 | PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) | | ||
485 | (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK); | ||
486 | return true; | ||
487 | } | ||
488 | |||
489 | /*! brief Enable USB HS PHY PLL clock. | ||
490 | * | ||
491 | * This function enables the internal 480MHz USB PHY PLL clock. | ||
492 | * | ||
493 | * param src USB HS PHY PLL clock source. | ||
494 | * param freq The frequency specified by src. | ||
495 | * retval true The clock is set successfully. | ||
496 | * retval false The clock source is invalid to get proper USB HS clock. | ||
497 | */ | ||
498 | bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq) | ||
499 | { | ||
500 | const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U}; | ||
501 | if ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_ENABLE_MASK) != 0UL) | ||
502 | { | ||
503 | CCM_ANALOG->PLL_USB1 |= CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK; | ||
504 | } | ||
505 | else | ||
506 | { | ||
507 | CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll); | ||
508 | } | ||
509 | USBPHY->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */ | ||
510 | USBPHY->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK; | ||
511 | |||
512 | USBPHY->PWD = 0; | ||
513 | USBPHY->CTRL |= USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK | USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | | ||
514 | USBPHY_CTRL_ENUTMILEVEL2_MASK | USBPHY_CTRL_ENUTMILEVEL3_MASK; | ||
515 | return true; | ||
516 | } | ||
517 | |||
518 | /*! brief Disable USB HS PHY PLL clock. | ||
519 | * | ||
520 | * This function disables USB HS PHY PLL clock. | ||
521 | */ | ||
522 | void CLOCK_DisableUsbhs0PhyPllClock(void) | ||
523 | { | ||
524 | CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK; | ||
525 | USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */ | ||
526 | } | ||
527 | |||
528 | /*! | ||
529 | * brief Initialize the System PLL. | ||
530 | * | ||
531 | * This function initializes the System PLL with specific settings | ||
532 | * | ||
533 | * param config Configuration to set to PLL. | ||
534 | */ | ||
535 | void CLOCK_InitSysPll(const clock_sys_pll_config_t *config) | ||
536 | { | ||
537 | /* Bypass PLL first */ | ||
538 | CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK)) | | ||
539 | CCM_ANALOG_PLL_SYS_BYPASS_MASK | CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC(config->src); | ||
540 | |||
541 | CCM_ANALOG->PLL_SYS = | ||
542 | (CCM_ANALOG->PLL_SYS & (~(CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK | CCM_ANALOG_PLL_SYS_POWERDOWN_MASK))) | | ||
543 | CCM_ANALOG_PLL_SYS_ENABLE_MASK | CCM_ANALOG_PLL_SYS_DIV_SELECT(config->loopDivider); | ||
544 | |||
545 | /* Initialize the fractional mode */ | ||
546 | CCM_ANALOG->PLL_SYS_NUM = CCM_ANALOG_PLL_SYS_NUM_A(config->numerator); | ||
547 | CCM_ANALOG->PLL_SYS_DENOM = CCM_ANALOG_PLL_SYS_DENOM_B(config->denominator); | ||
548 | |||
549 | /* Initialize the spread spectrum mode */ | ||
550 | CCM_ANALOG->PLL_SYS_SS = CCM_ANALOG_PLL_SYS_SS_STEP(config->ss_step) | | ||
551 | CCM_ANALOG_PLL_SYS_SS_ENABLE(config->ss_enable) | | ||
552 | CCM_ANALOG_PLL_SYS_SS_STOP(config->ss_stop); | ||
553 | |||
554 | while ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_LOCK_MASK) == 0UL) | ||
555 | { | ||
556 | } | ||
557 | |||
558 | /* Disable Bypass */ | ||
559 | CCM_ANALOG->PLL_SYS &= ~CCM_ANALOG_PLL_SYS_BYPASS_MASK; | ||
560 | } | ||
561 | |||
562 | /*! | ||
563 | * brief De-initialize the System PLL. | ||
564 | */ | ||
565 | void CLOCK_DeinitSysPll(void) | ||
566 | { | ||
567 | CCM_ANALOG->PLL_SYS = CCM_ANALOG_PLL_SYS_POWERDOWN_MASK; | ||
568 | } | ||
569 | |||
570 | /*! | ||
571 | * brief Initialize the USB1 PLL. | ||
572 | * | ||
573 | * This function initializes the USB1 PLL with specific settings | ||
574 | * | ||
575 | * param config Configuration to set to PLL. | ||
576 | */ | ||
577 | void CLOCK_InitUsb1Pll(const clock_usb_pll_config_t *config) | ||
578 | { | ||
579 | /* Bypass PLL first */ | ||
580 | CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) | | ||
581 | CCM_ANALOG_PLL_USB1_BYPASS_MASK | CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC(config->src); | ||
582 | |||
583 | CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK)) | | ||
584 | CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK | | ||
585 | CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider); | ||
586 | |||
587 | while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0UL) | ||
588 | { | ||
589 | } | ||
590 | |||
591 | /* Disable Bypass */ | ||
592 | CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_BYPASS_MASK; | ||
593 | } | ||
594 | |||
595 | /*! | ||
596 | * brief Deinitialize the USB1 PLL. | ||
597 | */ | ||
598 | void CLOCK_DeinitUsb1Pll(void) | ||
599 | { | ||
600 | CCM_ANALOG->PLL_USB1 = 0U; | ||
601 | } | ||
602 | |||
603 | /*! | ||
604 | * brief Initializes the Audio PLL. | ||
605 | * | ||
606 | * This function initializes the Audio PLL with specific settings | ||
607 | * | ||
608 | * param config Configuration to set to PLL. | ||
609 | */ | ||
610 | void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config) | ||
611 | { | ||
612 | uint32_t pllAudio; | ||
613 | uint32_t misc2 = 0; | ||
614 | |||
615 | /* Bypass PLL first */ | ||
616 | CCM_ANALOG->PLL_AUDIO = (CCM_ANALOG->PLL_AUDIO & (~CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC_MASK)) | | ||
617 | CCM_ANALOG_PLL_AUDIO_BYPASS_MASK | CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC(config->src); | ||
618 | |||
619 | CCM_ANALOG->PLL_AUDIO_NUM = CCM_ANALOG_PLL_AUDIO_NUM_A(config->numerator); | ||
620 | CCM_ANALOG->PLL_AUDIO_DENOM = CCM_ANALOG_PLL_AUDIO_DENOM_B(config->denominator); | ||
621 | |||
622 | /* | ||
623 | * Set post divider: | ||
624 | * | ||
625 | * ------------------------------------------------------------------------ | ||
626 | * | config->postDivider | PLL_AUDIO[POST_DIV_SELECT] | MISC2[AUDIO_DIV] | | ||
627 | * ------------------------------------------------------------------------ | ||
628 | * | 1 | 2 | 0 | | ||
629 | * ------------------------------------------------------------------------ | ||
630 | * | 2 | 1 | 0 | | ||
631 | * ------------------------------------------------------------------------ | ||
632 | * | 4 | 2 | 3 | | ||
633 | * ------------------------------------------------------------------------ | ||
634 | * | 8 | 1 | 3 | | ||
635 | * ------------------------------------------------------------------------ | ||
636 | * | 16 | 0 | 3 | | ||
637 | * ------------------------------------------------------------------------ | ||
638 | */ | ||
639 | pllAudio = | ||
640 | (CCM_ANALOG->PLL_AUDIO & (~(CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK | CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK))) | | ||
641 | CCM_ANALOG_PLL_AUDIO_ENABLE_MASK | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(config->loopDivider); | ||
642 | |||
643 | switch (config->postDivider) | ||
644 | { | ||
645 | case 16: | ||
646 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0); | ||
647 | misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; | ||
648 | break; | ||
649 | |||
650 | case 8: | ||
651 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1); | ||
652 | misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; | ||
653 | break; | ||
654 | |||
655 | case 4: | ||
656 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2); | ||
657 | misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; | ||
658 | break; | ||
659 | |||
660 | case 2: | ||
661 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1); | ||
662 | break; | ||
663 | |||
664 | default: | ||
665 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2); | ||
666 | break; | ||
667 | } | ||
668 | |||
669 | CCM_ANALOG->MISC2 = | ||
670 | (CCM_ANALOG->MISC2 & ~(CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK)) | misc2; | ||
671 | |||
672 | CCM_ANALOG->PLL_AUDIO = pllAudio; | ||
673 | |||
674 | while ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK_MASK) == 0UL) | ||
675 | { | ||
676 | } | ||
677 | |||
678 | /* Disable Bypass */ | ||
679 | CCM_ANALOG->PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_BYPASS_MASK; | ||
680 | } | ||
681 | |||
682 | /*! | ||
683 | * brief De-initialize the Audio PLL. | ||
684 | */ | ||
685 | void CLOCK_DeinitAudioPll(void) | ||
686 | { | ||
687 | CCM_ANALOG->PLL_AUDIO = CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK; | ||
688 | } | ||
689 | |||
690 | /*! | ||
691 | * brief Initialize the ENET PLL. | ||
692 | * | ||
693 | * This function initializes the ENET PLL with specific settings. | ||
694 | * | ||
695 | * param config Configuration to set to PLL. | ||
696 | */ | ||
697 | void CLOCK_InitEnetPll(const clock_enet_pll_config_t *config) | ||
698 | { | ||
699 | uint32_t enet_pll = 0; | ||
700 | |||
701 | CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC_MASK)) | | ||
702 | CCM_ANALOG_PLL_ENET_BYPASS_MASK | CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC(config->src); | ||
703 | |||
704 | if (config->enableClkOutput500M) | ||
705 | { | ||
706 | enet_pll |= CCM_ANALOG_PLL_ENET_ENET_500M_REF_EN_MASK; | ||
707 | } | ||
708 | |||
709 | CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_POWERDOWN_MASK)) | enet_pll; | ||
710 | |||
711 | /* Wait for stable */ | ||
712 | while ((CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_LOCK_MASK) == 0UL) | ||
713 | { | ||
714 | } | ||
715 | |||
716 | /* Disable Bypass */ | ||
717 | CCM_ANALOG->PLL_ENET &= ~CCM_ANALOG_PLL_ENET_BYPASS_MASK; | ||
718 | } | ||
719 | |||
720 | /*! | ||
721 | * brief Deinitialize the ENET PLL. | ||
722 | * | ||
723 | * This function disables the ENET PLL. | ||
724 | */ | ||
725 | void CLOCK_DeinitEnetPll(void) | ||
726 | { | ||
727 | CCM_ANALOG->PLL_ENET = CCM_ANALOG_PLL_ENET_POWERDOWN_MASK; | ||
728 | } | ||
729 | |||
730 | /*! | ||
731 | * brief Get current PLL output frequency. | ||
732 | * | ||
733 | * This function get current output frequency of specific PLL | ||
734 | * | ||
735 | * param pll pll name to get frequency. | ||
736 | * return The PLL output frequency in hertz. | ||
737 | */ | ||
738 | uint32_t CLOCK_GetPllFreq(clock_pll_t pll) | ||
739 | { | ||
740 | uint32_t freq; | ||
741 | uint32_t divSelect; | ||
742 | clock_64b_t freqTmp; | ||
743 | |||
744 | /* check if PLL is enabled */ | ||
745 | if (!CLOCK_IsPllEnabled(CCM_ANALOG, pll)) | ||
746 | { | ||
747 | return 0U; | ||
748 | } | ||
749 | |||
750 | /* get pll reference clock */ | ||
751 | freq = CLOCK_GetPllBypassRefClk(CCM_ANALOG, pll); | ||
752 | |||
753 | /* check if pll is bypassed */ | ||
754 | if (CLOCK_IsPllBypassed(CCM_ANALOG, pll)) | ||
755 | { | ||
756 | return freq; | ||
757 | } | ||
758 | |||
759 | switch (pll) | ||
760 | { | ||
761 | case kCLOCK_PllSys: | ||
762 | /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */ | ||
763 | freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_SYS_NUM))); | ||
764 | freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_SYS_DENOM)); | ||
765 | |||
766 | if ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK) != 0UL) | ||
767 | { | ||
768 | freq *= 22U; | ||
769 | } | ||
770 | else | ||
771 | { | ||
772 | freq *= 20U; | ||
773 | } | ||
774 | |||
775 | freq += (uint32_t)freqTmp; | ||
776 | break; | ||
777 | |||
778 | case kCLOCK_PllUsb1: | ||
779 | freq = (freq * (((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK) != 0UL) ? 22U : 20U)); | ||
780 | break; | ||
781 | |||
782 | case kCLOCK_PllAudio: | ||
783 | /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */ | ||
784 | divSelect = | ||
785 | (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_AUDIO_DIV_SELECT_SHIFT; | ||
786 | |||
787 | freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_NUM))); | ||
788 | freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_DENOM)); | ||
789 | |||
790 | freq = freq * divSelect + (uint32_t)freqTmp; | ||
791 | |||
792 | /* AUDIO PLL output = PLL output frequency / POSTDIV. */ | ||
793 | |||
794 | /* | ||
795 | * Post divider: | ||
796 | * | ||
797 | * PLL_AUDIO[POST_DIV_SELECT]: | ||
798 | * 0x00: 4 | ||
799 | * 0x01: 2 | ||
800 | * 0x02: 1 | ||
801 | * | ||
802 | * MISC2[AUDO_DIV]: | ||
803 | * 0x00: 1 | ||
804 | * 0x01: 2 | ||
805 | * 0x02: 1 | ||
806 | * 0x03: 4 | ||
807 | */ | ||
808 | switch (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT_MASK) | ||
809 | { | ||
810 | case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0U): | ||
811 | freq = freq >> 2U; | ||
812 | break; | ||
813 | |||
814 | case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1U): | ||
815 | freq = freq >> 1U; | ||
816 | break; | ||
817 | |||
818 | case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2U): | ||
819 | freq = freq >> 0U; | ||
820 | break; | ||
821 | |||
822 | default: | ||
823 | assert(false); | ||
824 | break; | ||
825 | } | ||
826 | |||
827 | switch (CCM_ANALOG->MISC2 & (CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK)) | ||
828 | { | ||
829 | case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1): | ||
830 | freq >>= 2U; | ||
831 | break; | ||
832 | |||
833 | case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1): | ||
834 | freq >>= 1U; | ||
835 | break; | ||
836 | |||
837 | case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(0): | ||
838 | case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(0): | ||
839 | freq >>= 0U; | ||
840 | break; | ||
841 | |||
842 | default: | ||
843 | assert(false); | ||
844 | break; | ||
845 | } | ||
846 | break; | ||
847 | |||
848 | case kCLOCK_PllEnet500M: | ||
849 | /* PLL6 is fixed at 25MHz. */ | ||
850 | freq = 500000000UL; | ||
851 | break; | ||
852 | |||
853 | default: | ||
854 | freq = 0U; | ||
855 | break; | ||
856 | } | ||
857 | |||
858 | return freq; | ||
859 | } | ||
860 | |||
861 | /*! | ||
862 | * brief Initialize the System PLL PFD. | ||
863 | * | ||
864 | * This function initializes the System PLL PFD. During new value setting, | ||
865 | * the clock output is disabled to prevent glitch. | ||
866 | * | ||
867 | * param pfd Which PFD clock to enable. | ||
868 | * param pfdFrac The PFD FRAC value. | ||
869 | * note It is recommended that PFD settings are kept between 12-35. | ||
870 | */ | ||
871 | void CLOCK_InitSysPfd(clock_pfd_t pfd, uint8_t pfdFrac) | ||
872 | { | ||
873 | uint32_t pfdIndex = (uint32_t)pfd; | ||
874 | uint32_t pfd528; | ||
875 | |||
876 | pfd528 = CCM_ANALOG->PFD_528 & | ||
877 | ~(((uint32_t)((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK | (uint32_t)CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) | ||
878 | << (8UL * pfdIndex))); | ||
879 | |||
880 | /* Disable the clock output first. */ | ||
881 | CCM_ANALOG->PFD_528 = pfd528 | ((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); | ||
882 | |||
883 | /* Set the new value and enable output. */ | ||
884 | CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex)); | ||
885 | } | ||
886 | |||
887 | /*! | ||
888 | * brief De-initialize the System PLL PFD. | ||
889 | * | ||
890 | * This function disables the System PLL PFD. | ||
891 | * | ||
892 | * param pfd Which PFD clock to disable. | ||
893 | */ | ||
894 | void CLOCK_DeinitSysPfd(clock_pfd_t pfd) | ||
895 | { | ||
896 | CCM_ANALOG->PFD_528 |= (uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * (uint32_t)pfd); | ||
897 | } | ||
898 | |||
899 | /*! | ||
900 | * brief Initialize the USB1 PLL PFD. | ||
901 | * | ||
902 | * This function initializes the USB1 PLL PFD. During new value setting, | ||
903 | * the clock output is disabled to prevent glitch. | ||
904 | * | ||
905 | * param pfd Which PFD clock to enable. | ||
906 | * param pfdFrac The PFD FRAC value. | ||
907 | * note It is recommended that PFD settings are kept between 12-35. | ||
908 | */ | ||
909 | void CLOCK_InitUsb1Pfd(clock_pfd_t pfd, uint8_t pfdFrac) | ||
910 | { | ||
911 | uint32_t pfdIndex = (uint32_t)pfd; | ||
912 | uint32_t pfd480; | ||
913 | |||
914 | pfd480 = CCM_ANALOG->PFD_480 & | ||
915 | ~((uint32_t)((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK | (uint32_t)CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) | ||
916 | << (8UL * pfdIndex)); | ||
917 | |||
918 | /* Disable the clock output first. */ | ||
919 | CCM_ANALOG->PFD_480 = pfd480 | ((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); | ||
920 | |||
921 | /* Set the new value and enable output. */ | ||
922 | CCM_ANALOG->PFD_480 = pfd480 | (CCM_ANALOG_PFD_480_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex)); | ||
923 | } | ||
924 | |||
925 | /*! | ||
926 | * brief De-initialize the USB1 PLL PFD. | ||
927 | * | ||
928 | * This function disables the USB1 PLL PFD. | ||
929 | * | ||
930 | * param pfd Which PFD clock to disable. | ||
931 | */ | ||
932 | void CLOCK_DeinitUsb1Pfd(clock_pfd_t pfd) | ||
933 | { | ||
934 | CCM_ANALOG->PFD_480 |= (uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * (uint32_t)pfd); | ||
935 | } | ||
936 | |||
937 | /*! | ||
938 | * brief Get current System PLL PFD output frequency. | ||
939 | * | ||
940 | * This function get current output frequency of specific System PLL PFD | ||
941 | * | ||
942 | * param pfd pfd name to get frequency. | ||
943 | * return The PFD output frequency in hertz. | ||
944 | */ | ||
945 | uint32_t CLOCK_GetSysPfdFreq(clock_pfd_t pfd) | ||
946 | { | ||
947 | uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllSys); | ||
948 | |||
949 | switch (pfd) | ||
950 | { | ||
951 | case kCLOCK_Pfd0: | ||
952 | freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD0_FRAC_SHIFT); | ||
953 | break; | ||
954 | |||
955 | case kCLOCK_Pfd1: | ||
956 | freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD1_FRAC_SHIFT); | ||
957 | break; | ||
958 | |||
959 | case kCLOCK_Pfd2: | ||
960 | freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD2_FRAC_SHIFT); | ||
961 | break; | ||
962 | |||
963 | case kCLOCK_Pfd3: | ||
964 | freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD3_FRAC_SHIFT); | ||
965 | break; | ||
966 | |||
967 | default: | ||
968 | freq = 0U; | ||
969 | break; | ||
970 | } | ||
971 | freq *= 18U; | ||
972 | |||
973 | return freq; | ||
974 | } | ||
975 | |||
976 | /*! | ||
977 | * brief Get current USB1 PLL PFD output frequency. | ||
978 | * | ||
979 | * This function get current output frequency of specific USB1 PLL PFD | ||
980 | * | ||
981 | * param pfd pfd name to get frequency. | ||
982 | * return The PFD output frequency in hertz. | ||
983 | */ | ||
984 | uint32_t CLOCK_GetUsb1PfdFreq(clock_pfd_t pfd) | ||
985 | { | ||
986 | uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1); | ||
987 | |||
988 | switch (pfd) | ||
989 | { | ||
990 | case kCLOCK_Pfd0: | ||
991 | freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT); | ||
992 | break; | ||
993 | |||
994 | case kCLOCK_Pfd1: | ||
995 | freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD1_FRAC_SHIFT); | ||
996 | break; | ||
997 | |||
998 | case kCLOCK_Pfd2: | ||
999 | freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD2_FRAC_SHIFT); | ||
1000 | break; | ||
1001 | |||
1002 | case kCLOCK_Pfd3: | ||
1003 | freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD3_FRAC_SHIFT); | ||
1004 | break; | ||
1005 | |||
1006 | default: | ||
1007 | freq = 0U; | ||
1008 | break; | ||
1009 | } | ||
1010 | freq *= 18U; | ||
1011 | |||
1012 | return freq; | ||
1013 | } | ||
1014 | |||
1015 | /*! | ||
1016 | * brief Set the clock source and the divider of the clock output1. | ||
1017 | * | ||
1018 | * param selection The clock source to be output, please refer to clock_output1_selection_t. | ||
1019 | * param divider The divider of the output clock signal, please refer to clock_output_divider_t. | ||
1020 | */ | ||
1021 | void CLOCK_SetClockOutput1(clock_output1_selection_t selection, clock_output_divider_t divider) | ||
1022 | { | ||
1023 | uint32_t tmp32; | ||
1024 | |||
1025 | tmp32 = CCM->CCOSR; | ||
1026 | if (selection == kCLOCK_DisableClockOutput1) | ||
1027 | { | ||
1028 | tmp32 &= ~CCM_CCOSR_CLKO1_EN_MASK; | ||
1029 | } | ||
1030 | else | ||
1031 | { | ||
1032 | tmp32 |= CCM_CCOSR_CLKO1_EN_MASK; | ||
1033 | tmp32 &= ~(CCM_CCOSR_CLKO1_SEL_MASK | CCM_CCOSR_CLKO1_DIV_MASK); | ||
1034 | tmp32 |= CCM_CCOSR_CLKO1_SEL(selection) | CCM_CCOSR_CLKO1_DIV(divider); | ||
1035 | } | ||
1036 | CCM->CCOSR = tmp32; | ||
1037 | } | ||
1038 | |||
1039 | /*! | ||
1040 | * brief Set the clock source and the divider of the clock output2. | ||
1041 | * | ||
1042 | * param selection The clock source to be output, please refer to clock_output2_selection_t. | ||
1043 | * param divider The divider of the output clock signal, please refer to clock_output_divider_t. | ||
1044 | */ | ||
1045 | void CLOCK_SetClockOutput2(clock_output2_selection_t selection, clock_output_divider_t divider) | ||
1046 | { | ||
1047 | uint32_t tmp32; | ||
1048 | |||
1049 | tmp32 = CCM->CCOSR; | ||
1050 | if (selection == kCLOCK_DisableClockOutput2) | ||
1051 | { | ||
1052 | tmp32 &= CCM_CCOSR_CLKO2_EN_MASK; | ||
1053 | } | ||
1054 | else | ||
1055 | { | ||
1056 | tmp32 |= CCM_CCOSR_CLKO2_EN_MASK; | ||
1057 | tmp32 &= ~(CCM_CCOSR_CLKO2_SEL_MASK | CCM_CCOSR_CLKO2_DIV_MASK); | ||
1058 | tmp32 |= CCM_CCOSR_CLKO2_SEL(selection) | CCM_CCOSR_CLKO2_DIV(divider); | ||
1059 | } | ||
1060 | |||
1061 | CCM->CCOSR = tmp32; | ||
1062 | } | ||
1063 | |||
1064 | /*! | ||
1065 | * brief Get the frequency of clock output1 clock signal. | ||
1066 | * | ||
1067 | * return The frequency of clock output1 clock signal. | ||
1068 | */ | ||
1069 | uint32_t CLOCK_GetClockOutCLKO1Freq(void) | ||
1070 | { | ||
1071 | uint32_t freq = 0U; | ||
1072 | uint32_t tmp32; | ||
1073 | |||
1074 | tmp32 = CCM->CCOSR; | ||
1075 | |||
1076 | if ((tmp32 & CCM_CCOSR_CLKO1_EN_MASK) != 0UL) | ||
1077 | { | ||
1078 | switch ((tmp32 & CCM_CCOSR_CLKO1_SEL_MASK) >> CCM_CCOSR_CLKO1_SEL_SHIFT) | ||
1079 | { | ||
1080 | case (uint32_t)kCLOCK_OutputPllUsb1Sw: | ||
1081 | freq = CLOCK_GetPllUsb1SWFreq() / 2UL; | ||
1082 | break; | ||
1083 | case (uint32_t)kCLOCK_OutputPllSys: | ||
1084 | freq = CLOCK_GetPllFreq(kCLOCK_PllSys) / 2UL; | ||
1085 | break; | ||
1086 | case (uint32_t)kCLOCK_OutputPllENET: | ||
1087 | freq = CLOCK_GetPllFreq(kCLOCK_PllEnet500M) / 2UL; | ||
1088 | break; | ||
1089 | case (uint32_t)kCLOCK_OutputAhbClk: | ||
1090 | freq = CLOCK_GetAhbFreq(); | ||
1091 | break; | ||
1092 | case (uint32_t)kCLOCK_OutputIpgClk: | ||
1093 | freq = CLOCK_GetIpgFreq(); | ||
1094 | break; | ||
1095 | case (uint32_t)kCLOCK_OutputPerClk: | ||
1096 | freq = CLOCK_GetPerClkFreq(); | ||
1097 | break; | ||
1098 | case (uint32_t)kCLOCK_OutputPll4MainClk: | ||
1099 | freq = CLOCK_GetPllFreq(kCLOCK_PllAudio); | ||
1100 | break; | ||
1101 | default: | ||
1102 | /* This branch should never be hit. */ | ||
1103 | break; | ||
1104 | } | ||
1105 | |||
1106 | freq /= (((tmp32 & CCM_CCOSR_CLKO1_DIV_MASK) >> CCM_CCOSR_CLKO1_DIV_SHIFT) + 1U); | ||
1107 | } | ||
1108 | else | ||
1109 | { | ||
1110 | freq = 0UL; | ||
1111 | } | ||
1112 | |||
1113 | return freq; | ||
1114 | } | ||
1115 | |||
1116 | /*! | ||
1117 | * brief Get the frequency of clock output2 clock signal. | ||
1118 | * | ||
1119 | * return The frequency of clock output2 clock signal. | ||
1120 | */ | ||
1121 | uint32_t CLOCK_GetClockOutClkO2Freq(void) | ||
1122 | { | ||
1123 | uint32_t freq = 0U; | ||
1124 | uint32_t tmp32; | ||
1125 | |||
1126 | tmp32 = CCM->CCOSR; | ||
1127 | |||
1128 | if ((tmp32 & CCM_CCOSR_CLKO2_EN_MASK) != 0UL) | ||
1129 | { | ||
1130 | switch ((tmp32 & CCM_CCOSR_CLKO2_SEL_MASK) >> CCM_CCOSR_CLKO2_SEL_SHIFT) | ||
1131 | { | ||
1132 | case (uint32_t)kCLOCK_OutputLpi2cClk: | ||
1133 | freq = CLOCK_GetClockRootFreq(kCLOCK_Lpi2cClkRoot); | ||
1134 | break; | ||
1135 | case (uint32_t)kCLOCK_OutputOscClk: | ||
1136 | freq = CLOCK_GetOscFreq(); | ||
1137 | break; | ||
1138 | case (uint32_t)kCLOCK_OutputLpspiClk: | ||
1139 | freq = CLOCK_GetClockRootFreq(kCLOCK_LpspiClkRoot); | ||
1140 | break; | ||
1141 | case (uint32_t)kCLOCK_OutputSai1Clk: | ||
1142 | freq = CLOCK_GetClockRootFreq(kCLOCK_Sai1ClkRoot); | ||
1143 | break; | ||
1144 | case (uint32_t)kCLOCK_OutputSai2Clk: | ||
1145 | freq = CLOCK_GetClockRootFreq(kCLOCK_Sai2ClkRoot); | ||
1146 | break; | ||
1147 | case (uint32_t)kCLOCK_OutputSai3Clk: | ||
1148 | freq = CLOCK_GetClockRootFreq(kCLOCK_Sai3ClkRoot); | ||
1149 | break; | ||
1150 | case (uint32_t)kCLOCK_OutputTraceClk: | ||
1151 | freq = CLOCK_GetClockRootFreq(kCLOCK_TraceClkRoot); | ||
1152 | break; | ||
1153 | case (uint32_t)kCLOCK_OutputFlexspiClk: | ||
1154 | freq = CLOCK_GetClockRootFreq(kCLOCK_FlexspiClkRoot); | ||
1155 | break; | ||
1156 | case (uint32_t)kCLOCK_OutputUartClk: | ||
1157 | freq = CLOCK_GetClockRootFreq(kCLOCK_UartClkRoot); | ||
1158 | break; | ||
1159 | case (uint32_t)kCLOCK_OutputSpdif0Clk: | ||
1160 | freq = CLOCK_GetClockRootFreq(kCLOCK_SpdifClkRoot); | ||
1161 | break; | ||
1162 | default: | ||
1163 | /* This branch should never be hit. */ | ||
1164 | break; | ||
1165 | } | ||
1166 | |||
1167 | freq /= (((tmp32 & CCM_CCOSR_CLKO2_DIV_MASK) >> CCM_CCOSR_CLKO2_DIV_SHIFT) + 1U); | ||
1168 | } | ||
1169 | else | ||
1170 | { | ||
1171 | freq = 0UL; | ||
1172 | } | ||
1173 | |||
1174 | return freq; | ||
1175 | } | ||