1 | /* |
2 | * Copyright 2018 - 2021 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) != 0U) |
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 ---> Pre_Periph_clk ---> Periph_clk */ |
123 | case CCM_CBCMR_PRE_PERIPH_CLK_SEL(0U): |
124 | freq = CLOCK_GetPllFreq(kCLOCK_PllSys); |
125 | break; |
126 | |
127 | /* PLL2 PFD2 ---> Pre_Periph_clk ---> Periph_clk */ |
128 | case CCM_CBCMR_PRE_PERIPH_CLK_SEL(1U): |
129 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2); |
130 | break; |
131 | |
132 | /* PLL2 PFD0 ---> Pre_Periph_clk ---> Periph_clk */ |
133 | case CCM_CBCMR_PRE_PERIPH_CLK_SEL(2U): |
134 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0); |
135 | break; |
136 | |
137 | /* PLL1 divided(/2) ---> Pre_Periph_clk ---> Periph_clk */ |
138 | case CCM_CBCMR_PRE_PERIPH_CLK_SEL(3U): |
139 | freq = CLOCK_GetPllFreq(kCLOCK_PllArm) / |
140 | (((CCM->CACRR & CCM_CACRR_ARM_PODF_MASK) >> CCM_CACRR_ARM_PODF_SHIFT) + 1U); |
141 | break; |
142 | |
143 | default: |
144 | freq = 0U; |
145 | break; |
146 | } |
147 | } |
148 | |
149 | return freq; |
150 | } |
151 | |
152 | static uint32_t CLOCK_GetPllUsb1SWFreq(void) |
153 | { |
154 | uint32_t freq; |
155 | |
156 | switch ((CCM->CCSR & CCM_CCSR_PLL3_SW_CLK_SEL_MASK) >> CCM_CCSR_PLL3_SW_CLK_SEL_SHIFT) |
157 | { |
158 | case 0: |
159 | { |
160 | freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1); |
161 | break; |
162 | } |
163 | case 1: |
164 | { |
165 | freq = 24000000UL; |
166 | break; |
167 | } |
168 | default: |
169 | freq = 0UL; |
170 | break; |
171 | } |
172 | |
173 | return freq; |
174 | } |
175 | |
176 | /*! |
177 | * brief Initialize the external 24MHz clock. |
178 | * |
179 | * This function supports two modes: |
180 | * 1. Use external crystal oscillator. |
181 | * 2. Bypass the external crystal oscillator, using input source clock directly. |
182 | * |
183 | * After this function, please call ref CLOCK_SetXtal0Freq to inform clock driver |
184 | * the external clock frequency. |
185 | * |
186 | * param bypassXtalOsc Pass in true to bypass the external crystal oscillator. |
187 | * note This device does not support bypass external crystal oscillator, so |
188 | * the input parameter should always be false. |
189 | */ |
190 | void CLOCK_InitExternalClk(bool bypassXtalOsc) |
191 | { |
192 | /* This device does not support bypass XTAL OSC. */ |
193 | assert(!bypassXtalOsc); |
194 | |
195 | CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power up */ |
196 | while ((XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_MASK) == 0U) |
197 | { |
198 | } |
199 | CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; /* detect freq */ |
200 | while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_OSC_XTALOK_MASK) == 0UL) |
201 | { |
202 | } |
203 | CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; |
204 | } |
205 | |
206 | /*! |
207 | * brief Deinitialize the external 24MHz clock. |
208 | * |
209 | * This function disables the external 24MHz clock. |
210 | * |
211 | * After this function, please call ref CLOCK_SetXtal0Freq to set external clock |
212 | * frequency to 0. |
213 | */ |
214 | void CLOCK_DeinitExternalClk(void) |
215 | { |
216 | CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power down */ |
217 | } |
218 | |
219 | /*! |
220 | * brief Switch the OSC. |
221 | * |
222 | * This function switches the OSC source for SoC. |
223 | * |
224 | * param osc OSC source to switch to. |
225 | */ |
226 | void CLOCK_SwitchOsc(clock_osc_t osc) |
227 | { |
228 | if (osc == kCLOCK_RcOsc) |
229 | { |
230 | XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_SET_OSC_SEL_MASK; |
231 | } |
232 | else |
233 | { |
234 | XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_MASK; |
235 | } |
236 | } |
237 | |
238 | /*! |
239 | * brief Initialize the RC oscillator 24MHz clock. |
240 | */ |
241 | void CLOCK_InitRcOsc24M(void) |
242 | { |
243 | XTALOSC24M->LOWPWR_CTRL |= XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK; |
244 | } |
245 | |
246 | /*! |
247 | * brief Power down the RCOSC 24M clock. |
248 | */ |
249 | void CLOCK_DeinitRcOsc24M(void) |
250 | { |
251 | XTALOSC24M->LOWPWR_CTRL &= ~XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK; |
252 | } |
253 | |
254 | /*! |
255 | * brief Gets the AHB clock frequency. |
256 | * |
257 | * return The AHB clock frequency value in hertz. |
258 | */ |
259 | uint32_t CLOCK_GetAhbFreq(void) |
260 | { |
261 | return CLOCK_GetPeriphClkFreq() / (((CCM->CBCDR & CCM_CBCDR_AHB_PODF_MASK) >> CCM_CBCDR_AHB_PODF_SHIFT) + 1U); |
262 | } |
263 | |
264 | /*! |
265 | * brief Gets the SEMC clock frequency. |
266 | * |
267 | * return The SEMC clock frequency value in hertz. |
268 | */ |
269 | uint32_t CLOCK_GetSemcFreq(void) |
270 | { |
271 | uint32_t freq; |
272 | |
273 | /* SEMC alternative clock ---> SEMC Clock */ |
274 | if ((CCM->CBCDR & CCM_CBCDR_SEMC_CLK_SEL_MASK) != 0U) |
275 | { |
276 | /* PLL3 PFD1 ---> SEMC alternative clock ---> SEMC Clock */ |
277 | if ((CCM->CBCDR & CCM_CBCDR_SEMC_ALT_CLK_SEL_MASK) != 0U) |
278 | { |
279 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1); |
280 | } |
281 | /* PLL2 PFD2 ---> SEMC alternative clock ---> SEMC Clock */ |
282 | else |
283 | { |
284 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2); |
285 | } |
286 | } |
287 | /* Periph_clk ---> SEMC Clock */ |
288 | else |
289 | { |
290 | freq = CLOCK_GetPeriphClkFreq(); |
291 | } |
292 | |
293 | freq /= (((CCM->CBCDR & CCM_CBCDR_SEMC_PODF_MASK) >> CCM_CBCDR_SEMC_PODF_SHIFT) + 1U); |
294 | |
295 | return freq; |
296 | } |
297 | |
298 | /*! |
299 | * brief Gets the IPG clock frequency. |
300 | * |
301 | * return The IPG clock frequency value in hertz. |
302 | */ |
303 | uint32_t CLOCK_GetIpgFreq(void) |
304 | { |
305 | return CLOCK_GetAhbFreq() / (((CCM->CBCDR & CCM_CBCDR_IPG_PODF_MASK) >> CCM_CBCDR_IPG_PODF_SHIFT) + 1U); |
306 | } |
307 | |
308 | /*! |
309 | * brief Gets the PER clock frequency. |
310 | * |
311 | * return The PER clock frequency value in hertz. |
312 | */ |
313 | uint32_t CLOCK_GetPerClkFreq(void) |
314 | { |
315 | uint32_t freq; |
316 | |
317 | /* Osc_clk ---> PER Clock*/ |
318 | if ((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK) != 0U) |
319 | { |
320 | freq = CLOCK_GetOscFreq(); |
321 | } |
322 | /* Periph_clk ---> AHB Clock ---> IPG Clock ---> PER Clock */ |
323 | else |
324 | { |
325 | freq = CLOCK_GetIpgFreq(); |
326 | } |
327 | |
328 | freq /= (((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_PODF_MASK) >> CCM_CSCMR1_PERCLK_PODF_SHIFT) + 1U); |
329 | |
330 | return freq; |
331 | } |
332 | |
333 | /*! |
334 | * brief Gets the clock frequency for a specific clock name. |
335 | * |
336 | * This function checks the current clock configurations and then calculates |
337 | * the clock frequency for a specific clock name defined in clock_name_t. |
338 | * |
339 | * param clockName Clock names defined in clock_name_t |
340 | * return Clock frequency value in hertz |
341 | */ |
342 | uint32_t CLOCK_GetFreq(clock_name_t name) |
343 | { |
344 | uint32_t freq; |
345 | |
346 | switch (name) |
347 | { |
348 | case kCLOCK_CpuClk: |
349 | case kCLOCK_AhbClk: |
350 | freq = CLOCK_GetAhbFreq(); |
351 | break; |
352 | |
353 | case kCLOCK_SemcClk: |
354 | freq = CLOCK_GetSemcFreq(); |
355 | break; |
356 | |
357 | case kCLOCK_IpgClk: |
358 | freq = CLOCK_GetIpgFreq(); |
359 | break; |
360 | |
361 | case kCLOCK_PerClk: |
362 | freq = CLOCK_GetPerClkFreq(); |
363 | break; |
364 | |
365 | case kCLOCK_OscClk: |
366 | freq = CLOCK_GetOscFreq(); |
367 | break; |
368 | case kCLOCK_RtcClk: |
369 | freq = CLOCK_GetRtcFreq(); |
370 | break; |
371 | case kCLOCK_ArmPllClk: |
372 | freq = CLOCK_GetPllFreq(kCLOCK_PllArm); |
373 | break; |
374 | case kCLOCK_Usb1PllClk: |
375 | freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1); |
376 | break; |
377 | case kCLOCK_Usb1PllPfd0Clk: |
378 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd0); |
379 | break; |
380 | case kCLOCK_Usb1PllPfd1Clk: |
381 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1); |
382 | break; |
383 | case kCLOCK_Usb1PllPfd2Clk: |
384 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd2); |
385 | break; |
386 | case kCLOCK_Usb1PllPfd3Clk: |
387 | freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd3); |
388 | break; |
389 | case kCLOCK_Usb1SwClk: |
390 | freq = CLOCK_GetPllUsb1SWFreq(); |
391 | break; |
392 | case kCLOCK_Usb1Sw120MClk: |
393 | freq = CLOCK_GetPllUsb1SWFreq() / 4UL; |
394 | break; |
395 | case kCLOCK_Usb1Sw60MClk: |
396 | freq = CLOCK_GetPllUsb1SWFreq() / 8UL; |
397 | break; |
398 | case kCLOCK_Usb1Sw80MClk: |
399 | freq = CLOCK_GetPllUsb1SWFreq() / 6UL; |
400 | break; |
401 | case kCLOCK_Usb2PllClk: |
402 | freq = CLOCK_GetPllFreq(kCLOCK_PllUsb2); |
403 | break; |
404 | case kCLOCK_SysPllClk: |
405 | freq = CLOCK_GetPllFreq(kCLOCK_PllSys); |
406 | break; |
407 | case kCLOCK_SysPllPfd0Clk: |
408 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0); |
409 | break; |
410 | case kCLOCK_SysPllPfd1Clk: |
411 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd1); |
412 | break; |
413 | case kCLOCK_SysPllPfd2Clk: |
414 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2); |
415 | break; |
416 | case kCLOCK_SysPllPfd3Clk: |
417 | freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd3); |
418 | break; |
419 | case kCLOCK_EnetPll0Clk: |
420 | freq = CLOCK_GetPllFreq(kCLOCK_PllEnet); |
421 | break; |
422 | case kCLOCK_EnetPll1Clk: |
423 | freq = CLOCK_GetPllFreq(kCLOCK_PllEnet2); |
424 | break; |
425 | case kCLOCK_EnetPll2Clk: |
426 | freq = CLOCK_GetPllFreq(kCLOCK_PllEnet25M); |
427 | break; |
428 | case kCLOCK_AudioPllClk: |
429 | freq = CLOCK_GetPllFreq(kCLOCK_PllAudio); |
430 | break; |
431 | case kCLOCK_VideoPllClk: |
432 | freq = CLOCK_GetPllFreq(kCLOCK_PllVideo); |
433 | break; |
434 | default: |
435 | freq = 0U; |
436 | break; |
437 | } |
438 | |
439 | return freq; |
440 | } |
441 | |
442 | /*! |
443 | * brief Gets the frequency of selected clock root. |
444 | * |
445 | * param clockRoot The clock root used to get the frequency, please refer to @ref clock_root_t. |
446 | * return The frequency of selected clock root. |
447 | */ |
448 | uint32_t CLOCK_GetClockRootFreq(clock_root_t clockRoot) |
449 | { |
450 | static const clock_name_t clockRootSourceArray[][6] = CLOCK_ROOT_SOUCE; |
451 | static const clock_mux_t clockRootMuxTupleArray[] = CLOCK_ROOT_MUX_TUPLE; |
452 | static const clock_div_t clockRootDivTupleArray[][2] = CLOCK_ROOT_DIV_TUPLE; |
453 | uint32_t freq = 0UL; |
454 | clock_mux_t clockRootMuxTuple = clockRootMuxTupleArray[(uint8_t)clockRoot]; |
455 | clock_div_t clockRootPreDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][0]; |
456 | clock_div_t clockRootPostDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][1]; |
457 | uint32_t clockRootMuxValue = (CCM_TUPLE_REG(CCM, clockRootMuxTuple) & CCM_TUPLE_MASK(clockRootMuxTuple)) >> |
458 | CCM_TUPLE_SHIFT(clockRootMuxTuple); |
459 | clock_name_t clockSourceName; |
460 | |
461 | clockSourceName = clockRootSourceArray[(uint8_t)clockRoot][clockRootMuxValue]; |
462 | |
463 | assert(clockSourceName != kCLOCK_NoneName); |
464 | |
465 | freq = CLOCK_GetFreq(clockSourceName); |
466 | |
467 | if (clockRootPreDivTuple != kCLOCK_NonePreDiv) |
468 | { |
469 | freq /= ((CCM_TUPLE_REG(CCM, clockRootPreDivTuple) & CCM_TUPLE_MASK(clockRootPreDivTuple)) >> |
470 | CCM_TUPLE_SHIFT(clockRootPreDivTuple)) + |
471 | 1UL; |
472 | } |
473 | |
474 | freq /= ((CCM_TUPLE_REG(CCM, clockRootPostDivTuple) & CCM_TUPLE_MASK(clockRootPostDivTuple)) >> |
475 | CCM_TUPLE_SHIFT(clockRootPostDivTuple)) + |
476 | 1UL; |
477 | |
478 | return freq; |
479 | } |
480 | |
481 | /*! brief Enable USB HS clock. |
482 | * |
483 | * This function only enables the access to USB HS prepheral, upper layer |
484 | * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY |
485 | * clock to use USB HS. |
486 | * |
487 | * param src USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused. |
488 | * param freq USB HS does not care about the clock source, so this parameter is ignored. |
489 | * retval true The clock is set successfully. |
490 | * retval false The clock source is invalid to get proper USB HS clock. |
491 | */ |
492 | bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) |
493 | { |
494 | uint32_t i; |
495 | CCM->CCGR6 |= CCM_CCGR6_CG0_MASK; |
496 | USB1->USBCMD |= USBHS_USBCMD_RST_MASK; |
497 | |
498 | /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/ |
499 | for (i = 0; i < 400000U; i++) |
500 | { |
501 | __ASM("nop"); |
502 | } |
503 | PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) | |
504 | (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK); |
505 | return true; |
506 | } |
507 | |
508 | /*! brief Enable USB HS clock. |
509 | * |
510 | * This function only enables the access to USB HS prepheral, upper layer |
511 | * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY |
512 | * clock to use USB HS. |
513 | * |
514 | * param src USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused. |
515 | * param freq USB HS does not care about the clock source, so this parameter is ignored. |
516 | * retval true The clock is set successfully. |
517 | * retval false The clock source is invalid to get proper USB HS clock. |
518 | */ |
519 | bool CLOCK_EnableUsbhs1Clock(clock_usb_src_t src, uint32_t freq) |
520 | { |
521 | uint32_t i = 0; |
522 | CCM->CCGR6 |= CCM_CCGR6_CG0_MASK; |
523 | USB2->USBCMD |= USBHS_USBCMD_RST_MASK; |
524 | |
525 | /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/ |
526 | for (i = 0; i < 400000U; i++) |
527 | { |
528 | __ASM("nop"); |
529 | } |
530 | PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) | |
531 | (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK); |
532 | return true; |
533 | } |
534 | |
535 | /*! brief Enable USB HS PHY PLL clock. |
536 | * |
537 | * This function enables the internal 480MHz USB PHY PLL clock. |
538 | * |
539 | * param src USB HS PHY PLL clock source. |
540 | * param freq The frequency specified by src. |
541 | * retval true The clock is set successfully. |
542 | * retval false The clock source is invalid to get proper USB HS clock. |
543 | */ |
544 | bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq) |
545 | { |
546 | static const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U}; |
547 | if ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_ENABLE_MASK) != 0U) |
548 | { |
549 | CCM_ANALOG->PLL_USB1 |= CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK; |
550 | } |
551 | else |
552 | { |
553 | CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll); |
554 | } |
555 | USBPHY1->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */ |
556 | USBPHY1->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK; |
557 | |
558 | USBPHY1->PWD = 0; |
559 | USBPHY1->CTRL |= USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK | USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | |
560 | USBPHY_CTRL_ENUTMILEVEL2_MASK | USBPHY_CTRL_ENUTMILEVEL3_MASK; |
561 | return true; |
562 | } |
563 | |
564 | /*! brief Disable USB HS PHY PLL clock. |
565 | * |
566 | * This function disables USB HS PHY PLL clock. |
567 | */ |
568 | void CLOCK_DisableUsbhs0PhyPllClock(void) |
569 | { |
570 | CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK; |
571 | USBPHY1->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */ |
572 | } |
573 | |
574 | /*! |
575 | * brief Initialize the ARM PLL. |
576 | * |
577 | * This function initialize the ARM PLL with specific settings |
578 | * |
579 | * param config configuration to set to PLL. |
580 | */ |
581 | void CLOCK_InitArmPll(const clock_arm_pll_config_t *config) |
582 | { |
583 | /* Bypass PLL first */ |
584 | CCM_ANALOG->PLL_ARM = (CCM_ANALOG->PLL_ARM & (~CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_MASK)) | |
585 | CCM_ANALOG_PLL_ARM_BYPASS_MASK | CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC(config->src); |
586 | |
587 | CCM_ANALOG->PLL_ARM = |
588 | (CCM_ANALOG->PLL_ARM & (~(CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK | CCM_ANALOG_PLL_ARM_POWERDOWN_MASK))) | |
589 | CCM_ANALOG_PLL_ARM_ENABLE_MASK | CCM_ANALOG_PLL_ARM_DIV_SELECT(config->loopDivider); |
590 | |
591 | while ((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_LOCK_MASK) == 0UL) |
592 | { |
593 | } |
594 | |
595 | /* Disable Bypass */ |
596 | CCM_ANALOG->PLL_ARM &= ~CCM_ANALOG_PLL_ARM_BYPASS_MASK; |
597 | } |
598 | |
599 | /*! |
600 | * brief De-initialize the ARM PLL. |
601 | */ |
602 | void CLOCK_DeinitArmPll(void) |
603 | { |
604 | CCM_ANALOG->PLL_ARM = CCM_ANALOG_PLL_ARM_POWERDOWN_MASK; |
605 | } |
606 | |
607 | /*! |
608 | * brief Initialize the System PLL. |
609 | * |
610 | * This function initializes the System PLL with specific settings |
611 | * |
612 | * param config Configuration to set to PLL. |
613 | */ |
614 | void CLOCK_InitSysPll(const clock_sys_pll_config_t *config) |
615 | { |
616 | /* Bypass PLL first */ |
617 | CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK)) | |
618 | CCM_ANALOG_PLL_SYS_BYPASS_MASK | CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC(config->src); |
619 | |
620 | CCM_ANALOG->PLL_SYS = |
621 | (CCM_ANALOG->PLL_SYS & (~(CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK | CCM_ANALOG_PLL_SYS_POWERDOWN_MASK))) | |
622 | CCM_ANALOG_PLL_SYS_ENABLE_MASK | CCM_ANALOG_PLL_SYS_DIV_SELECT(config->loopDivider); |
623 | |
624 | /* Initialize the fractional mode */ |
625 | CCM_ANALOG->PLL_SYS_NUM = CCM_ANALOG_PLL_SYS_NUM_A(config->numerator); |
626 | CCM_ANALOG->PLL_SYS_DENOM = CCM_ANALOG_PLL_SYS_DENOM_B(config->denominator); |
627 | |
628 | /* Initialize the spread spectrum mode */ |
629 | CCM_ANALOG->PLL_SYS_SS = CCM_ANALOG_PLL_SYS_SS_STEP(config->ss_step) | |
630 | CCM_ANALOG_PLL_SYS_SS_ENABLE(config->ss_enable) | |
631 | CCM_ANALOG_PLL_SYS_SS_STOP(config->ss_stop); |
632 | |
633 | while ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_LOCK_MASK) == 0UL) |
634 | { |
635 | } |
636 | |
637 | /* Disable Bypass */ |
638 | CCM_ANALOG->PLL_SYS &= ~CCM_ANALOG_PLL_SYS_BYPASS_MASK; |
639 | } |
640 | |
641 | /*! |
642 | * brief De-initialize the System PLL. |
643 | */ |
644 | void CLOCK_DeinitSysPll(void) |
645 | { |
646 | CCM_ANALOG->PLL_SYS = CCM_ANALOG_PLL_SYS_POWERDOWN_MASK; |
647 | } |
648 | |
649 | /*! |
650 | * brief Initialize the USB1 PLL. |
651 | * |
652 | * This function initializes the USB1 PLL with specific settings |
653 | * |
654 | * param config Configuration to set to PLL. |
655 | */ |
656 | void CLOCK_InitUsb1Pll(const clock_usb_pll_config_t *config) |
657 | { |
658 | /* Bypass PLL first */ |
659 | CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) | |
660 | CCM_ANALOG_PLL_USB1_BYPASS_MASK | CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC(config->src); |
661 | |
662 | CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK)) | |
663 | CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK | |
664 | CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider); |
665 | |
666 | while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0UL) |
667 | { |
668 | } |
669 | |
670 | /* Disable Bypass */ |
671 | CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_BYPASS_MASK; |
672 | } |
673 | |
674 | /*! |
675 | * brief Deinitialize the USB1 PLL. |
676 | */ |
677 | void CLOCK_DeinitUsb1Pll(void) |
678 | { |
679 | CCM_ANALOG->PLL_USB1 = 0U; |
680 | } |
681 | |
682 | /*! |
683 | * brief Initialize the USB2 PLL. |
684 | * |
685 | * This function initializes the USB2 PLL with specific settings |
686 | * |
687 | * param config Configuration to set to PLL. |
688 | */ |
689 | void CLOCK_InitUsb2Pll(const clock_usb_pll_config_t *config) |
690 | { |
691 | /* Bypass PLL first */ |
692 | CCM_ANALOG->PLL_USB2 = (CCM_ANALOG->PLL_USB2 & (~CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC_MASK)) | |
693 | CCM_ANALOG_PLL_USB2_BYPASS_MASK | CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC(config->src); |
694 | |
695 | CCM_ANALOG->PLL_USB2 = (CCM_ANALOG->PLL_USB2 & (~CCM_ANALOG_PLL_USB2_DIV_SELECT_MASK)) | |
696 | CCM_ANALOG_PLL_USB2_ENABLE_MASK | CCM_ANALOG_PLL_USB2_POWER_MASK | |
697 | CCM_ANALOG_PLL_USB2_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB2_DIV_SELECT(config->loopDivider); |
698 | |
699 | while ((CCM_ANALOG->PLL_USB2 & CCM_ANALOG_PLL_USB2_LOCK_MASK) == 0UL) |
700 | { |
701 | } |
702 | |
703 | /* Disable Bypass */ |
704 | CCM_ANALOG->PLL_USB2 &= ~CCM_ANALOG_PLL_USB2_BYPASS_MASK; |
705 | } |
706 | |
707 | /*! |
708 | * brief Deinitialize the USB2 PLL. |
709 | */ |
710 | void CLOCK_DeinitUsb2Pll(void) |
711 | { |
712 | CCM_ANALOG->PLL_USB2 = 0U; |
713 | } |
714 | |
715 | /*! |
716 | * brief Initializes the Audio PLL. |
717 | * |
718 | * This function initializes the Audio PLL with specific settings |
719 | * |
720 | * param config Configuration to set to PLL. |
721 | */ |
722 | void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config) |
723 | { |
724 | uint32_t pllAudio; |
725 | uint32_t misc2 = 0; |
726 | |
727 | /* Bypass PLL first */ |
728 | CCM_ANALOG->PLL_AUDIO = (CCM_ANALOG->PLL_AUDIO & (~CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC_MASK)) | |
729 | CCM_ANALOG_PLL_AUDIO_BYPASS_MASK | CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC(config->src); |
730 | |
731 | CCM_ANALOG->PLL_AUDIO_NUM = CCM_ANALOG_PLL_AUDIO_NUM_A(config->numerator); |
732 | CCM_ANALOG->PLL_AUDIO_DENOM = CCM_ANALOG_PLL_AUDIO_DENOM_B(config->denominator); |
733 | |
734 | /* |
735 | * Set post divider: |
736 | * |
737 | * ------------------------------------------------------------------------ |
738 | * | config->postDivider | PLL_AUDIO[POST_DIV_SELECT] | MISC2[AUDIO_DIV] | |
739 | * ------------------------------------------------------------------------ |
740 | * | 1 | 2 | 0 | |
741 | * ------------------------------------------------------------------------ |
742 | * | 2 | 1 | 0 | |
743 | * ------------------------------------------------------------------------ |
744 | * | 4 | 2 | 3 | |
745 | * ------------------------------------------------------------------------ |
746 | * | 8 | 1 | 3 | |
747 | * ------------------------------------------------------------------------ |
748 | * | 16 | 0 | 3 | |
749 | * ------------------------------------------------------------------------ |
750 | */ |
751 | pllAudio = |
752 | (CCM_ANALOG->PLL_AUDIO & (~(CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK | CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK))) | |
753 | CCM_ANALOG_PLL_AUDIO_ENABLE_MASK | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(config->loopDivider); |
754 | |
755 | switch (config->postDivider) |
756 | { |
757 | case 16: |
758 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0); |
759 | misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; |
760 | break; |
761 | |
762 | case 8: |
763 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1); |
764 | misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; |
765 | break; |
766 | |
767 | case 4: |
768 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2); |
769 | misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; |
770 | break; |
771 | |
772 | case 2: |
773 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1); |
774 | break; |
775 | |
776 | default: |
777 | pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2); |
778 | break; |
779 | } |
780 | |
781 | CCM_ANALOG->MISC2 = |
782 | (CCM_ANALOG->MISC2 & ~(CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK)) | misc2; |
783 | |
784 | CCM_ANALOG->PLL_AUDIO = pllAudio; |
785 | |
786 | while ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK_MASK) == 0UL) |
787 | { |
788 | } |
789 | |
790 | /* Disable Bypass */ |
791 | CCM_ANALOG->PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_BYPASS_MASK; |
792 | } |
793 | |
794 | /*! |
795 | * brief De-initialize the Audio PLL. |
796 | */ |
797 | void CLOCK_DeinitAudioPll(void) |
798 | { |
799 | CCM_ANALOG->PLL_AUDIO = (uint32_t)CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK; |
800 | } |
801 | |
802 | /*! |
803 | * brief Initialize the video PLL. |
804 | * |
805 | * This function configures the Video PLL with specific settings |
806 | * |
807 | * param config configuration to set to PLL. |
808 | */ |
809 | void CLOCK_InitVideoPll(const clock_video_pll_config_t *config) |
810 | { |
811 | uint32_t pllVideo; |
812 | uint32_t misc2 = 0; |
813 | |
814 | /* Bypass PLL first */ |
815 | CCM_ANALOG->PLL_VIDEO = (CCM_ANALOG->PLL_VIDEO & (~CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC_MASK)) | |
816 | CCM_ANALOG_PLL_VIDEO_BYPASS_MASK | CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC(config->src); |
817 | |
818 | CCM_ANALOG->PLL_VIDEO_NUM = CCM_ANALOG_PLL_VIDEO_NUM_A(config->numerator); |
819 | CCM_ANALOG->PLL_VIDEO_DENOM = CCM_ANALOG_PLL_VIDEO_DENOM_B(config->denominator); |
820 | |
821 | /* |
822 | * Set post divider: |
823 | * |
824 | * ------------------------------------------------------------------------ |
825 | * | config->postDivider | PLL_VIDEO[POST_DIV_SELECT] | MISC2[VIDEO_DIV] | |
826 | * ------------------------------------------------------------------------ |
827 | * | 1 | 2 | 0 | |
828 | * ------------------------------------------------------------------------ |
829 | * | 2 | 1 | 0 | |
830 | * ------------------------------------------------------------------------ |
831 | * | 4 | 2 | 3 | |
832 | * ------------------------------------------------------------------------ |
833 | * | 8 | 1 | 3 | |
834 | * ------------------------------------------------------------------------ |
835 | * | 16 | 0 | 3 | |
836 | * ------------------------------------------------------------------------ |
837 | */ |
838 | pllVideo = |
839 | (CCM_ANALOG->PLL_VIDEO & (~(CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK | CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK))) | |
840 | CCM_ANALOG_PLL_VIDEO_ENABLE_MASK | CCM_ANALOG_PLL_VIDEO_DIV_SELECT(config->loopDivider); |
841 | |
842 | switch (config->postDivider) |
843 | { |
844 | case 16: |
845 | pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(0); |
846 | misc2 = CCM_ANALOG_MISC2_VIDEO_DIV(3); |
847 | break; |
848 | |
849 | case 8: |
850 | pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1); |
851 | misc2 = CCM_ANALOG_MISC2_VIDEO_DIV(3); |
852 | break; |
853 | |
854 | case 4: |
855 | pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(2); |
856 | misc2 = CCM_ANALOG_MISC2_VIDEO_DIV(3); |
857 | break; |
858 | |
859 | case 2: |
860 | pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1); |
861 | break; |
862 | |
863 | default: |
864 | pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(2); |
865 | break; |
866 | } |
867 | |
868 | CCM_ANALOG->MISC2 = (CCM_ANALOG->MISC2 & ~CCM_ANALOG_MISC2_VIDEO_DIV_MASK) | misc2; |
869 | |
870 | CCM_ANALOG->PLL_VIDEO = pllVideo; |
871 | |
872 | while ((CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_LOCK_MASK) == 0UL) |
873 | { |
874 | } |
875 | |
876 | /* Disable Bypass */ |
877 | CCM_ANALOG->PLL_VIDEO &= ~CCM_ANALOG_PLL_VIDEO_BYPASS_MASK; |
878 | } |
879 | |
880 | /*! |
881 | * brief De-initialize the Video PLL. |
882 | */ |
883 | void CLOCK_DeinitVideoPll(void) |
884 | { |
885 | CCM_ANALOG->PLL_VIDEO = CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK; |
886 | } |
887 | |
888 | /*! |
889 | * brief Initialize the ENET PLL. |
890 | * |
891 | * This function initializes the ENET PLL with specific settings. |
892 | * |
893 | * param config Configuration to set to PLL. |
894 | */ |
895 | void CLOCK_InitEnetPll(const clock_enet_pll_config_t *config) |
896 | { |
897 | uint32_t enet_pll = CCM_ANALOG_PLL_ENET_DIV_SELECT(config->loopDivider) | |
898 | CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT(config->loopDivider1); |
899 | |
900 | CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC_MASK)) | |
901 | CCM_ANALOG_PLL_ENET_BYPASS_MASK | CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC(config->src); |
902 | |
903 | if (config->enableClkOutput) |
904 | { |
905 | enet_pll |= CCM_ANALOG_PLL_ENET_ENABLE_MASK; |
906 | } |
907 | |
908 | if (config->enableClkOutput1) |
909 | { |
910 | enet_pll |= CCM_ANALOG_PLL_ENET_ENET2_REF_EN_MASK; |
911 | } |
912 | |
913 | if (config->enableClkOutput25M) |
914 | { |
915 | enet_pll |= CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_MASK; |
916 | } |
917 | |
918 | CCM_ANALOG->PLL_ENET = |
919 | (CCM_ANALOG->PLL_ENET & (~(CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK | CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_MASK | |
920 | CCM_ANALOG_PLL_ENET_POWERDOWN_MASK))) | |
921 | enet_pll; |
922 | |
923 | /* Wait for stable */ |
924 | while ((CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_LOCK_MASK) == 0UL) |
925 | { |
926 | } |
927 | |
928 | /* Disable Bypass */ |
929 | CCM_ANALOG->PLL_ENET &= ~CCM_ANALOG_PLL_ENET_BYPASS_MASK; |
930 | } |
931 | |
932 | /*! |
933 | * brief Deinitialize the ENET PLL. |
934 | * |
935 | * This function disables the ENET PLL. |
936 | */ |
937 | void CLOCK_DeinitEnetPll(void) |
938 | { |
939 | CCM_ANALOG->PLL_ENET = CCM_ANALOG_PLL_ENET_POWERDOWN_MASK; |
940 | } |
941 | |
942 | /*! |
943 | * brief Get current PLL output frequency. |
944 | * |
945 | * This function get current output frequency of specific PLL |
946 | * |
947 | * param pll pll name to get frequency. |
948 | * return The PLL output frequency in hertz. |
949 | */ |
950 | uint32_t CLOCK_GetPllFreq(clock_pll_t pll) |
951 | { |
952 | uint32_t freq; |
953 | uint32_t divSelect; |
954 | clock_64b_t freqTmp; |
955 | |
956 | static const uint32_t enetRefClkFreq[] = { |
957 | 25000000U, /* 25M */ |
958 | 50000000U, /* 50M */ |
959 | 100000000U, /* 100M */ |
960 | 125000000U /* 125M */ |
961 | }; |
962 | |
963 | /* check if PLL is enabled */ |
964 | if (!CLOCK_IsPllEnabled(CCM_ANALOG, pll)) |
965 | { |
966 | return 0U; |
967 | } |
968 | |
969 | /* get pll reference clock */ |
970 | freq = CLOCK_GetPllBypassRefClk(CCM_ANALOG, pll); |
971 | |
972 | /* check if pll is bypassed */ |
973 | if (CLOCK_IsPllBypassed(CCM_ANALOG, pll)) |
974 | { |
975 | return freq; |
976 | } |
977 | |
978 | switch (pll) |
979 | { |
980 | case kCLOCK_PllArm: |
981 | freq = ((freq * ((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK) >> |
982 | CCM_ANALOG_PLL_ARM_DIV_SELECT_SHIFT)) >> |
983 | 1U); |
984 | break; |
985 | case kCLOCK_PllSys: |
986 | /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */ |
987 | freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_SYS_NUM))); |
988 | freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_SYS_DENOM)); |
989 | |
990 | if ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK) != 0U) |
991 | { |
992 | freq *= 22U; |
993 | } |
994 | else |
995 | { |
996 | freq *= 20U; |
997 | } |
998 | |
999 | freq += (uint32_t)freqTmp; |
1000 | break; |
1001 | |
1002 | case kCLOCK_PllUsb1: |
1003 | freq = (freq * (((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK) != 0UL) ? 22U : 20U)); |
1004 | break; |
1005 | |
1006 | case kCLOCK_PllAudio: |
1007 | /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */ |
1008 | divSelect = |
1009 | (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_AUDIO_DIV_SELECT_SHIFT; |
1010 | |
1011 | freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_NUM))); |
1012 | freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_DENOM)); |
1013 | |
1014 | freq = freq * divSelect + (uint32_t)freqTmp; |
1015 | |
1016 | /* AUDIO PLL output = PLL output frequency / POSTDIV. */ |
1017 | |
1018 | /* |
1019 | * Post divider: |
1020 | * |
1021 | * PLL_AUDIO[POST_DIV_SELECT]: |
1022 | * 0x00: 4 |
1023 | * 0x01: 2 |
1024 | * 0x02: 1 |
1025 | * |
1026 | * MISC2[AUDO_DIV]: |
1027 | * 0x00: 1 |
1028 | * 0x01: 2 |
1029 | * 0x02: 1 |
1030 | * 0x03: 4 |
1031 | */ |
1032 | switch (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT_MASK) |
1033 | { |
1034 | case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0U): |
1035 | freq = freq >> 2U; |
1036 | break; |
1037 | |
1038 | case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1U): |
1039 | freq = freq >> 1U; |
1040 | break; |
1041 | |
1042 | case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2U): |
1043 | freq = freq >> 0U; |
1044 | break; |
1045 | |
1046 | default: |
1047 | assert(false); |
1048 | break; |
1049 | } |
1050 | |
1051 | switch (CCM_ANALOG->MISC2 & (CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK)) |
1052 | { |
1053 | case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1): |
1054 | freq >>= 2U; |
1055 | break; |
1056 | |
1057 | case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1): |
1058 | freq >>= 1U; |
1059 | break; |
1060 | |
1061 | case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(0): |
1062 | case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(0): |
1063 | freq >>= 0U; |
1064 | break; |
1065 | |
1066 | default: |
1067 | assert(false); |
1068 | break; |
1069 | } |
1070 | break; |
1071 | |
1072 | case kCLOCK_PllVideo: |
1073 | /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */ |
1074 | divSelect = |
1075 | (CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_VIDEO_DIV_SELECT_SHIFT; |
1076 | |
1077 | freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_VIDEO_NUM))); |
1078 | freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_VIDEO_DENOM)); |
1079 | freq = freq * divSelect + (uint32_t)freqTmp; |
1080 | |
1081 | /* VIDEO PLL output = PLL output frequency / POSTDIV. */ |
1082 | |
1083 | /* |
1084 | * Post divider: |
1085 | * |
1086 | * PLL_VIDEO[POST_DIV_SELECT]: |
1087 | * 0x00: 4 |
1088 | * 0x01: 2 |
1089 | * 0x02: 1 |
1090 | * |
1091 | * MISC2[VIDEO_DIV]: |
1092 | * 0x00: 1 |
1093 | * 0x01: 2 |
1094 | * 0x02: 1 |
1095 | * 0x03: 4 |
1096 | */ |
1097 | switch (CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT_MASK) |
1098 | { |
1099 | case CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(0U): |
1100 | freq = freq >> 2U; |
1101 | break; |
1102 | |
1103 | case CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1U): |
1104 | freq = freq >> 1U; |
1105 | break; |
1106 | |
1107 | case CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(2U): |
1108 | freq = freq >> 0U; |
1109 | break; |
1110 | |
1111 | default: |
1112 | assert(false); |
1113 | break; |
1114 | } |
1115 | |
1116 | switch (CCM_ANALOG->MISC2 & CCM_ANALOG_MISC2_VIDEO_DIV_MASK) |
1117 | { |
1118 | case CCM_ANALOG_MISC2_VIDEO_DIV(3U): |
1119 | freq >>= 2U; |
1120 | break; |
1121 | |
1122 | case CCM_ANALOG_MISC2_VIDEO_DIV(1U): |
1123 | freq >>= 1U; |
1124 | break; |
1125 | |
1126 | case CCM_ANALOG_MISC2_VIDEO_DIV(0U): |
1127 | case CCM_ANALOG_MISC2_VIDEO_DIV(2U): |
1128 | freq >>= 0U; |
1129 | break; |
1130 | |
1131 | default: |
1132 | assert(false); |
1133 | break; |
1134 | } |
1135 | break; |
1136 | case kCLOCK_PllEnet: |
1137 | divSelect = |
1138 | (CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_ENET_DIV_SELECT_SHIFT; |
1139 | freq = enetRefClkFreq[divSelect]; |
1140 | break; |
1141 | |
1142 | case kCLOCK_PllEnet2: |
1143 | divSelect = (CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_MASK) >> |
1144 | CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_SHIFT; |
1145 | freq = enetRefClkFreq[divSelect]; |
1146 | break; |
1147 | |
1148 | case kCLOCK_PllEnet25M: |
1149 | /* ref_enetpll1 if fixed at 25MHz. */ |
1150 | freq = 25000000UL; |
1151 | break; |
1152 | |
1153 | case kCLOCK_PllUsb2: |
1154 | freq = (freq * (((CCM_ANALOG->PLL_USB2 & CCM_ANALOG_PLL_USB2_DIV_SELECT_MASK) != 0U) ? 22U : 20U)); |
1155 | break; |
1156 | default: |
1157 | freq = 0U; |
1158 | break; |
1159 | } |
1160 | |
1161 | return freq; |
1162 | } |
1163 | |
1164 | /*! |
1165 | * brief Initialize the System PLL PFD. |
1166 | * |
1167 | * This function initializes the System PLL PFD. During new value setting, |
1168 | * the clock output is disabled to prevent glitch. |
1169 | * |
1170 | * param pfd Which PFD clock to enable. |
1171 | * param pfdFrac The PFD FRAC value. |
1172 | * note It is recommended that PFD settings are kept between 12-35. |
1173 | */ |
1174 | void CLOCK_InitSysPfd(clock_pfd_t pfd, uint8_t pfdFrac) |
1175 | { |
1176 | uint32_t pfdIndex = (uint32_t)pfd; |
1177 | uint32_t pfd528; |
1178 | |
1179 | pfd528 = CCM_ANALOG->PFD_528 & |
1180 | ~(((uint32_t)((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK | CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) |
1181 | << (8UL * pfdIndex))); |
1182 | |
1183 | /* Disable the clock output first. */ |
1184 | CCM_ANALOG->PFD_528 = pfd528 | ((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); |
1185 | |
1186 | /* Set the new value and enable output. */ |
1187 | CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex)); |
1188 | } |
1189 | |
1190 | /*! |
1191 | * brief De-initialize the System PLL PFD. |
1192 | * |
1193 | * This function disables the System PLL PFD. |
1194 | * |
1195 | * param pfd Which PFD clock to disable. |
1196 | */ |
1197 | void CLOCK_DeinitSysPfd(clock_pfd_t pfd) |
1198 | { |
1199 | CCM_ANALOG->PFD_528 |= (uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8U * (uint8_t)pfd); |
1200 | } |
1201 | |
1202 | /*! |
1203 | * brief Check if Sys PFD is enabled |
1204 | * |
1205 | * param pfd PFD control name |
1206 | * return PFD bypass status. |
1207 | * - true: power on. |
1208 | * - false: power off. |
1209 | */ |
1210 | bool CLOCK_IsSysPfdEnabled(clock_pfd_t pfd) |
1211 | { |
1212 | return ((CCM_ANALOG->PFD_528 & (uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * (uint8_t)pfd)) == 0U); |
1213 | } |
1214 | |
1215 | /*! |
1216 | * brief Initialize the USB1 PLL PFD. |
1217 | * |
1218 | * This function initializes the USB1 PLL PFD. During new value setting, |
1219 | * the clock output is disabled to prevent glitch. |
1220 | * |
1221 | * param pfd Which PFD clock to enable. |
1222 | * param pfdFrac The PFD FRAC value. |
1223 | * note It is recommended that PFD settings are kept between 12-35. |
1224 | */ |
1225 | void CLOCK_InitUsb1Pfd(clock_pfd_t pfd, uint8_t pfdFrac) |
1226 | { |
1227 | uint32_t pfdIndex = (uint32_t)pfd; |
1228 | uint32_t pfd480; |
1229 | |
1230 | pfd480 = CCM_ANALOG->PFD_480 & |
1231 | ~(((uint32_t)((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK | CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) |
1232 | << (8UL * pfdIndex))); |
1233 | |
1234 | /* Disable the clock output first. */ |
1235 | CCM_ANALOG->PFD_480 = pfd480 | ((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); |
1236 | |
1237 | /* Set the new value and enable output. */ |
1238 | CCM_ANALOG->PFD_480 = pfd480 | (CCM_ANALOG_PFD_480_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex)); |
1239 | } |
1240 | |
1241 | /*! |
1242 | * brief De-initialize the USB1 PLL PFD. |
1243 | * |
1244 | * This function disables the USB1 PLL PFD. |
1245 | * |
1246 | * param pfd Which PFD clock to disable. |
1247 | */ |
1248 | void CLOCK_DeinitUsb1Pfd(clock_pfd_t pfd) |
1249 | { |
1250 | CCM_ANALOG->PFD_480 |= (uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * (uint8_t)pfd); |
1251 | } |
1252 | |
1253 | /*! |
1254 | * brief Check if Usb1 PFD is enabled |
1255 | * |
1256 | * param pfd PFD control name. |
1257 | * return PFD bypass status. |
1258 | * - true: power on. |
1259 | * - false: power off. |
1260 | */ |
1261 | bool CLOCK_IsUsb1PfdEnabled(clock_pfd_t pfd) |
1262 | { |
1263 | return ((CCM_ANALOG->PFD_480 & (uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * (uint8_t)pfd)) == 0U); |
1264 | } |
1265 | |
1266 | /*! |
1267 | * brief Get current System PLL PFD output frequency. |
1268 | * |
1269 | * This function get current output frequency of specific System PLL PFD |
1270 | * |
1271 | * param pfd pfd name to get frequency. |
1272 | * return The PFD output frequency in hertz. |
1273 | */ |
1274 | uint32_t CLOCK_GetSysPfdFreq(clock_pfd_t pfd) |
1275 | { |
1276 | uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllSys); |
1277 | |
1278 | switch (pfd) |
1279 | { |
1280 | case kCLOCK_Pfd0: |
1281 | freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD0_FRAC_SHIFT); |
1282 | break; |
1283 | |
1284 | case kCLOCK_Pfd1: |
1285 | freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD1_FRAC_SHIFT); |
1286 | break; |
1287 | |
1288 | case kCLOCK_Pfd2: |
1289 | freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD2_FRAC_SHIFT); |
1290 | break; |
1291 | |
1292 | case kCLOCK_Pfd3: |
1293 | freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD3_FRAC_SHIFT); |
1294 | break; |
1295 | |
1296 | default: |
1297 | freq = 0U; |
1298 | break; |
1299 | } |
1300 | freq *= 18U; |
1301 | |
1302 | return freq; |
1303 | } |
1304 | |
1305 | /*! |
1306 | * brief Get current USB1 PLL PFD output frequency. |
1307 | * |
1308 | * This function get current output frequency of specific USB1 PLL PFD |
1309 | * |
1310 | * param pfd pfd name to get frequency. |
1311 | * return The PFD output frequency in hertz. |
1312 | */ |
1313 | uint32_t CLOCK_GetUsb1PfdFreq(clock_pfd_t pfd) |
1314 | { |
1315 | uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1); |
1316 | |
1317 | switch (pfd) |
1318 | { |
1319 | case kCLOCK_Pfd0: |
1320 | freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT); |
1321 | break; |
1322 | |
1323 | case kCLOCK_Pfd1: |
1324 | freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD1_FRAC_SHIFT); |
1325 | break; |
1326 | |
1327 | case kCLOCK_Pfd2: |
1328 | freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD2_FRAC_SHIFT); |
1329 | break; |
1330 | |
1331 | case kCLOCK_Pfd3: |
1332 | freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD3_FRAC_SHIFT); |
1333 | break; |
1334 | |
1335 | default: |
1336 | freq = 0U; |
1337 | break; |
1338 | } |
1339 | freq *= 18U; |
1340 | |
1341 | return freq; |
1342 | } |
1343 | |
1344 | /*! brief Enable USB HS PHY PLL clock. |
1345 | * |
1346 | * This function enables the internal 480MHz USB PHY PLL clock. |
1347 | * |
1348 | * param src USB HS PHY PLL clock source. |
1349 | * param freq The frequency specified by src. |
1350 | * retval true The clock is set successfully. |
1351 | * retval false The clock source is invalid to get proper USB HS clock. |
1352 | */ |
1353 | bool CLOCK_EnableUsbhs1PhyPllClock(clock_usb_phy_src_t src, uint32_t freq) |
1354 | { |
1355 | static const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U}; |
1356 | CLOCK_InitUsb2Pll(&g_ccmConfigUsbPll); |
1357 | USBPHY2->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */ |
1358 | USBPHY2->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK; |
1359 | |
1360 | USBPHY2->PWD = 0; |
1361 | USBPHY2->CTRL |= USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK | USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | |
1362 | USBPHY_CTRL_ENUTMILEVEL2_MASK | USBPHY_CTRL_ENUTMILEVEL3_MASK; |
1363 | |
1364 | return true; |
1365 | } |
1366 | |
1367 | /*! brief Disable USB HS PHY PLL clock. |
1368 | * |
1369 | * This function disables USB HS PHY PLL clock. |
1370 | */ |
1371 | void CLOCK_DisableUsbhs1PhyPllClock(void) |
1372 | { |
1373 | CCM_ANALOG->PLL_USB2 &= ~CCM_ANALOG_PLL_USB2_EN_USB_CLKS_MASK; |
1374 | USBPHY2->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */ |
1375 | } |
1376 | |
1377 | /*! |
1378 | * brief Set the clock source and the divider of the clock output1. |
1379 | * |
1380 | * param selection The clock source to be output, please refer to clock_output1_selection_t. |
1381 | * param divider The divider of the output clock signal, please refer to clock_output_divider_t. |
1382 | */ |
1383 | void CLOCK_SetClockOutput1(clock_output1_selection_t selection, clock_output_divider_t divider) |
1384 | { |
1385 | uint32_t tmp32; |
1386 | |
1387 | tmp32 = CCM->CCOSR; |
1388 | if (selection == kCLOCK_DisableClockOutput1) |
1389 | { |
1390 | tmp32 &= ~CCM_CCOSR_CLKO1_EN_MASK; |
1391 | } |
1392 | else |
1393 | { |
1394 | tmp32 |= CCM_CCOSR_CLKO1_EN_MASK; |
1395 | tmp32 &= ~(CCM_CCOSR_CLKO1_SEL_MASK | CCM_CCOSR_CLKO1_DIV_MASK); |
1396 | tmp32 |= CCM_CCOSR_CLKO1_SEL(selection) | CCM_CCOSR_CLKO1_DIV(divider); |
1397 | } |
1398 | CCM->CCOSR = tmp32; |
1399 | } |
1400 | |
1401 | /*! |
1402 | * brief Set the clock source and the divider of the clock output2. |
1403 | * |
1404 | * param selection The clock source to be output, please refer to clock_output2_selection_t. |
1405 | * param divider The divider of the output clock signal, please refer to clock_output_divider_t. |
1406 | */ |
1407 | void CLOCK_SetClockOutput2(clock_output2_selection_t selection, clock_output_divider_t divider) |
1408 | { |
1409 | uint32_t tmp32; |
1410 | |
1411 | tmp32 = CCM->CCOSR; |
1412 | if (selection == kCLOCK_DisableClockOutput2) |
1413 | { |
1414 | tmp32 &= CCM_CCOSR_CLKO2_EN_MASK; |
1415 | } |
1416 | else |
1417 | { |
1418 | tmp32 |= CCM_CCOSR_CLKO2_EN_MASK; |
1419 | tmp32 &= ~(CCM_CCOSR_CLKO2_SEL_MASK | CCM_CCOSR_CLKO2_DIV_MASK); |
1420 | tmp32 |= CCM_CCOSR_CLKO2_SEL(selection) | CCM_CCOSR_CLKO2_DIV(divider); |
1421 | } |
1422 | |
1423 | CCM->CCOSR = tmp32; |
1424 | } |
1425 | |
1426 | /*! |
1427 | * brief Get the frequency of clock output1 clock signal. |
1428 | * |
1429 | * return The frequency of clock output1 clock signal. |
1430 | */ |
1431 | uint32_t CLOCK_GetClockOutCLKO1Freq(void) |
1432 | { |
1433 | uint32_t freq = 0U; |
1434 | uint32_t tmp32; |
1435 | |
1436 | tmp32 = CCM->CCOSR; |
1437 | |
1438 | if ((tmp32 & CCM_CCOSR_CLKO1_EN_MASK) != 0UL) |
1439 | { |
1440 | switch ((tmp32 & CCM_CCOSR_CLKO1_SEL_MASK) >> CCM_CCOSR_CLKO1_SEL_SHIFT) |
1441 | { |
1442 | case (uint32_t)kCLOCK_OutputPllUsb1: |
1443 | freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 2U; |
1444 | break; |
1445 | case (uint32_t)kCLOCK_OutputPllSys: |
1446 | freq = CLOCK_GetPllFreq(kCLOCK_PllSys) / 2U; |
1447 | break; |
1448 | case (uint32_t)kCLOCK_OutputPllVideo: |
1449 | freq = CLOCK_GetPllFreq(kCLOCK_PllVideo) / 2U; |
1450 | break; |
1451 | case (uint32_t)kCLOCK_OutputSemcClk: |
1452 | freq = CLOCK_GetSemcFreq(); |
1453 | break; |
1454 | case (uint32_t)kCLOCK_OutputLcdifPixClk: |
1455 | freq = CLOCK_GetClockRootFreq(kCLOCK_LcdifClkRoot); |
1456 | break; |
1457 | case (uint32_t)kCLOCK_OutputAhbClk: |
1458 | freq = CLOCK_GetAhbFreq(); |
1459 | break; |
1460 | case (uint32_t)kCLOCK_OutputIpgClk: |
1461 | freq = CLOCK_GetIpgFreq(); |
1462 | break; |
1463 | case (uint32_t)kCLOCK_OutputPerClk: |
1464 | freq = CLOCK_GetPerClkFreq(); |
1465 | break; |
1466 | case (uint32_t)kCLOCK_OutputCkilSyncClk: |
1467 | freq = CLOCK_GetRtcFreq(); |
1468 | break; |
1469 | case (uint32_t)kCLOCK_OutputPll4MainClk: |
1470 | freq = CLOCK_GetPllFreq(kCLOCK_PllAudio); |
1471 | break; |
1472 | default: |
1473 | /* This branch should never be hit. */ |
1474 | break; |
1475 | } |
1476 | |
1477 | freq /= (((tmp32 & CCM_CCOSR_CLKO1_DIV_MASK) >> CCM_CCOSR_CLKO1_DIV_SHIFT) + 1U); |
1478 | } |
1479 | else |
1480 | { |
1481 | freq = 0UL; |
1482 | } |
1483 | |
1484 | return freq; |
1485 | } |
1486 | |
1487 | /*! |
1488 | * brief Get the frequency of clock output2 clock signal. |
1489 | * |
1490 | * return The frequency of clock output2 clock signal. |
1491 | */ |
1492 | uint32_t CLOCK_GetClockOutClkO2Freq(void) |
1493 | { |
1494 | uint32_t freq = 0U; |
1495 | uint32_t tmp32; |
1496 | |
1497 | tmp32 = CCM->CCOSR; |
1498 | |
1499 | if ((tmp32 & CCM_CCOSR_CLKO2_EN_MASK) != 0UL) |
1500 | { |
1501 | switch ((tmp32 & CCM_CCOSR_CLKO2_SEL_MASK) >> CCM_CCOSR_CLKO2_SEL_SHIFT) |
1502 | { |
1503 | case (uint32_t)kCLOCK_OutputUsdhc1Clk: |
1504 | freq = CLOCK_GetClockRootFreq(kCLOCK_Usdhc1ClkRoot); |
1505 | break; |
1506 | case (uint32_t)kCLOCK_OutputLpi2cClk: |
1507 | freq = CLOCK_GetClockRootFreq(kCLOCK_Lpi2cClkRoot); |
1508 | break; |
1509 | case (uint32_t)kCLOCK_OutputCsiClk: |
1510 | freq = CLOCK_GetClockRootFreq(kCLOCK_CsiClkRoot); |
1511 | break; |
1512 | case (uint32_t)kCLOCK_OutputOscClk: |
1513 | freq = CLOCK_GetOscFreq(); |
1514 | break; |
1515 | case (uint32_t)kCLOCK_OutputUsdhc2Clk: |
1516 | freq = CLOCK_GetClockRootFreq(kCLOCK_Usdhc2ClkRoot); |
1517 | break; |
1518 | case (uint32_t)kCLOCK_OutputSai1Clk: |
1519 | freq = CLOCK_GetClockRootFreq(kCLOCK_Sai1ClkRoot); |
1520 | break; |
1521 | case (uint32_t)kCLOCK_OutputSai2Clk: |
1522 | freq = CLOCK_GetClockRootFreq(kCLOCK_Sai2ClkRoot); |
1523 | break; |
1524 | case (uint32_t)kCLOCK_OutputSai3Clk: |
1525 | freq = CLOCK_GetClockRootFreq(kCLOCK_Sai3ClkRoot); |
1526 | break; |
1527 | case (uint32_t)kCLOCK_OutputCanClk: |
1528 | freq = CLOCK_GetClockRootFreq(kCLOCK_CanClkRoot); |
1529 | break; |
1530 | case (uint32_t)kCLOCK_OutputFlexspiClk: |
1531 | freq = CLOCK_GetClockRootFreq(kCLOCK_FlexspiClkRoot); |
1532 | break; |
1533 | case (uint32_t)kCLOCK_OutputUartClk: |
1534 | freq = CLOCK_GetClockRootFreq(kCLOCK_UartClkRoot); |
1535 | break; |
1536 | case (uint32_t)kCLOCK_OutputSpdif0Clk: |
1537 | freq = CLOCK_GetClockRootFreq(kCLOCK_SpdifClkRoot); |
1538 | break; |
1539 | default: |
1540 | /* This branch should never be hit. */ |
1541 | break; |
1542 | } |
1543 | |
1544 | freq /= (((tmp32 & CCM_CCOSR_CLKO2_DIV_MASK) >> CCM_CCOSR_CLKO2_DIV_SHIFT) + 1U); |
1545 | } |
1546 | else |
1547 | { |
1548 | freq = 0UL; |
1549 | } |
1550 | |
1551 | return freq; |
1552 | } |
1553 | |