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