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