aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MQ6/drivers/fsl_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MQ6/drivers/fsl_clock.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MQ6/drivers/fsl_clock.c967
1 files changed, 967 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MQ6/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MQ6/drivers/fsl_clock.c
new file mode 100644
index 000000000..d7c8b735c
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MQ6/drivers/fsl_clock.c
@@ -0,0 +1,967 @@
1/*
2 * Copyright 2017 - 2019 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7#include "fsl_common.h"
8#include "fsl_clock.h"
9
10/*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13/* Component ID definition, used by tools. */
14#ifndef FSL_COMPONENT_ID
15#define FSL_COMPONENT_ID "platform.drivers.clock"
16#endif
17/*! @brief SSCG PLL FLITER range value */
18#define SSCG_PLL1_FILTER_RANGE (35000000U)
19/*******************************************************************************
20 * Prototypes
21 ******************************************************************************/
22
23/*******************************************************************************
24 * Variables
25 ******************************************************************************/
26
27/*******************************************************************************
28 * Code
29 ******************************************************************************/
30/*!
31 * brief Gets the clock frequency for a specific clock name.
32 *
33 * This function checks the current clock configurations and then calculates
34 * the clock frequency for a specific clock name defined in clock_name_t.
35 *
36 * param clockName Clock names defined in clock_name_t
37 * return Clock frequency value in hertz
38 */
39uint32_t CLOCK_GetFreq(clock_name_t clockName)
40{
41 uint32_t freq;
42
43 switch (clockName)
44 {
45 case kCLOCK_CoreM4Clk:
46 freq = CLOCK_GetCoreM4Freq();
47 break;
48 case kCLOCK_AxiClk:
49 freq = CLOCK_GetAxiFreq();
50 break;
51 case kCLOCK_AhbClk:
52 freq = CLOCK_GetAhbFreq();
53 break;
54 case kCLOCK_IpgClk:
55 freq = CLOCK_GetAhbFreq();
56 break;
57 default:
58 freq = 0U;
59 break;
60 }
61 return freq;
62}
63
64/*!
65 * brief Get the CCM Cortex M4 core frequency.
66 *
67 * return Clock frequency; If the clock is invalid, returns 0.
68 */
69uint32_t CLOCK_GetCoreM4Freq(void)
70{
71 uint32_t freq;
72 uint32_t pre = CLOCK_GetRootPreDivider(kCLOCK_RootM4);
73 uint32_t post = CLOCK_GetRootPostDivider(kCLOCK_RootM4);
74
75 switch (CLOCK_GetRootMux(kCLOCK_RootM4))
76 {
77 case (uint32_t)kCLOCK_M4RootmuxOsc25m:
78 freq = OSC25M_CLK_FREQ;
79 break;
80 case (uint32_t)kCLOCK_M4RootmuxSysPll2Div5:
81 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 5U;
82 break;
83 case (uint32_t)kCLOCK_M4RootmuxSysPll2Div4:
84 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 4U;
85 break;
86 case (uint32_t)kCLOCK_M4RootmuxSysPll1Div3:
87 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / 3U;
88 break;
89 case (uint32_t)kCLOCK_M4RootmuxSysPll1:
90 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl);
91 break;
92 case (uint32_t)kCLOCK_M4RootmuxAudioPll1:
93 freq = CLOCK_GetPllFreq(kCLOCK_AudioPll1Ctrl);
94 break;
95 case (uint32_t)kCLOCK_M4RootmuxVideoPll1:
96 freq = CLOCK_GetPllFreq(kCLOCK_VideoPll1Ctrl);
97 break;
98 case (uint32_t)kCLOCK_M4RootmuxSysPll3:
99 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll3Ctrl);
100 break;
101 default:
102 freq = 0U;
103 break;
104 }
105
106 return freq / pre / post;
107}
108
109/*!
110 * brief Get the CCM Axi bus frequency.
111 *
112 * return Clock frequency; If the clock is invalid, returns 0.
113 */
114uint32_t CLOCK_GetAxiFreq(void)
115{
116 uint32_t freq;
117 uint32_t pre = CLOCK_GetRootPreDivider(kCLOCK_RootAxi);
118 uint32_t post = CLOCK_GetRootPostDivider(kCLOCK_RootAxi);
119
120 switch (CLOCK_GetRootMux(kCLOCK_RootAxi))
121 {
122 case (uint32_t)kCLOCK_AxiRootmuxOsc25m:
123 freq = OSC25M_CLK_FREQ;
124 break;
125 case (uint32_t)kCLOCK_AxiRootmuxSysPll2Div3:
126 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 3U;
127 break;
128 case (uint32_t)kCLOCK_AxiRootmuxSysPll2Div4:
129 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 4U;
130 break;
131 case (uint32_t)kCLOCK_AxiRootmuxSysPll2:
132 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl);
133 break;
134 case (uint32_t)kCLOCK_AxiRootmuxAudioPll1:
135 freq = CLOCK_GetPllFreq(kCLOCK_AudioPll1Ctrl);
136 break;
137 case (uint32_t)kCLOCK_AxiRootmuxVideoPll1:
138 freq = CLOCK_GetPllFreq(kCLOCK_VideoPll1Ctrl);
139 break;
140 case (uint32_t)kCLOCK_AxiRootmuxSysPll1Div8:
141 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / 8U;
142 break;
143 case (uint32_t)kCLOCK_AxiRootmuxSysPll1:
144 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl);
145 break;
146 default:
147 freq = 0U;
148 break;
149 }
150
151 return freq / pre / post;
152}
153
154/*!
155 * brief Get the CCM Ahb bus frequency.
156 *
157 * return Clock frequency; If the clock is invalid, returns 0.
158 */
159uint32_t CLOCK_GetAhbFreq(void)
160{
161 uint32_t freq;
162 uint32_t pre = CLOCK_GetRootPreDivider(kCLOCK_RootAhb);
163 uint32_t post = CLOCK_GetRootPostDivider(kCLOCK_RootAhb);
164
165 switch (CLOCK_GetRootMux(kCLOCK_RootAhb))
166 {
167 case (uint32_t)kCLOCK_AhbRootmuxOsc25m:
168 freq = OSC25M_CLK_FREQ;
169 break;
170 case (uint32_t)kCLOCK_AhbRootmuxSysPll1Div6:
171 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / 6U;
172 break;
173 case (uint32_t)kCLOCK_AhbRootmuxSysPll1Div2:
174 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / 2U;
175 break;
176 case (uint32_t)kCLOCK_AhbRootmuxSysPll1:
177 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl);
178 break;
179 case (uint32_t)kCLOCK_AhbRootmuxSysPll2Div8:
180 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 8U;
181 break;
182 case (uint32_t)kCLOCK_AhbRootmuxSysPll3:
183 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll3Ctrl);
184 break;
185 case (uint32_t)kCLOCK_AhbRootmuxAudioPll1:
186 freq = CLOCK_GetPllFreq(kCLOCK_AudioPll1Ctrl);
187 break;
188 case (uint32_t)kCLOCK_AhbRootmuxVideoPll1:
189 freq = CLOCK_GetPllFreq(kCLOCK_VideoPll1Ctrl);
190 break;
191 default:
192 freq = 0U;
193 break;
194 }
195
196 return freq / pre / post;
197}
198
199/*!
200 * brief Gets PLL reference clock frequency.
201 *
202 * param type fractional pll type.
203
204 * return Clock frequency
205 */
206uint32_t CLOCK_GetPllRefClkFreq(clock_pll_ctrl_t ctrl)
207{
208 uint32_t refClkFreq = 0U;
209 uint8_t clkSel = 0U;
210
211 if (ctrl <= kCLOCK_ArmPllCtrl)
212 {
213 clkSel = (uint8_t)CCM_BIT_FIELD_EXTRACTION(CCM_ANALOG_TUPLE_REG(CCM_ANALOG, ctrl),
214 CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_SEL_MASK,
215 CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_SEL_SHIFT);
216 }
217 else
218 {
219 clkSel = (uint8_t)(CCM_ANALOG_TUPLE_REG(CCM_ANALOG, ctrl) & CCM_ANALOG_SYS_PLL1_CFG0_PLL_REFCLK_SEL_MASK);
220 }
221
222 switch (clkSel)
223 {
224 case (uint8_t)kANALOG_PllRefOsc25M:
225 refClkFreq = OSC25M_CLK_FREQ /
226 (CCM_BIT_FIELD_EXTRACTION(XTALOSC->OSC25M_CTL_CFG, XTALOSC_OSC25M_CTL_CFG_OSC_DIV_MASK,
227 XTALOSC_OSC25M_CTL_CFG_OSC_DIV_SHIFT) +
228 1U);
229 break;
230
231 case (uint8_t)kANALOG_PllRefOsc27M:
232 refClkFreq = OSC27M_CLK_FREQ /
233 (CCM_BIT_FIELD_EXTRACTION(XTALOSC->OSC27M_CTL_CFG, XTALOSC_OSC27M_CTL_CFG_OSC_DIV_MASK,
234 XTALOSC_OSC27M_CTL_CFG_OSC_DIV_SHIFT) +
235 1U);
236 break;
237
238 case (uint8_t)kANALOG_PllRefOscHdmiPhy27M:
239 refClkFreq = HDMI_PHY_27M_FREQ;
240 break;
241
242 case (uint8_t)kANALOG_PllRefClkPN:
243 refClkFreq = CLKPN_FREQ;
244 break;
245 default:
246 refClkFreq = 0U;
247 break;
248 }
249
250 return refClkFreq;
251}
252
253/*!
254 * brief Gets PLL clock frequency.
255 *
256 * param type fractional pll type.
257
258 * return Clock frequency
259 */
260uint32_t CLOCK_GetPllFreq(clock_pll_ctrl_t pll)
261{
262 uint32_t pllFreq = 0U;
263 uint32_t pllRefFreq = 0U;
264 bool sscgPll1Bypass = false;
265 bool sscgPll2Bypass = false;
266 bool fracPllBypass = false;
267
268 pllRefFreq = CLOCK_GetPllRefClkFreq(pll);
269
270 switch (pll)
271 {
272 /* SSCG PLL frequency */
273 case kCLOCK_SystemPll1Ctrl:
274 sscgPll1Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll1InternalPll1BypassCtrl);
275 sscgPll2Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll1InternalPll2BypassCtrl);
276 break;
277 case kCLOCK_SystemPll2Ctrl:
278 sscgPll1Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll2InternalPll1BypassCtrl);
279 sscgPll2Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll2InternalPll2BypassCtrl);
280 break;
281 case kCLOCK_SystemPll3Ctrl:
282 sscgPll1Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll3InternalPll1BypassCtrl);
283 sscgPll2Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll3InternalPll2BypassCtrl);
284 break;
285 case kCLOCK_VideoPll2Ctrl:
286 sscgPll1Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_VideoPll2InternalPll1BypassCtrl);
287 sscgPll2Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_VideoPll2InternalPll2BypassCtrl);
288 break;
289 case kCLOCK_DramPllCtrl:
290 sscgPll1Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_DramPllInternalPll1BypassCtrl);
291 sscgPll2Bypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_DramPllInternalPll2BypassCtrl);
292 break;
293 case kCLOCK_AudioPll1Ctrl:
294 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_AudioPll1BypassCtrl);
295 break;
296 case kCLOCK_AudioPll2Ctrl:
297 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_AudioPll2BypassCtrl);
298 break;
299 case kCLOCK_VideoPll1Ctrl:
300 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_VideoPll1BypassCtrl);
301 break;
302 case kCLOCK_GpuPllCtrl:
303 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_GpuPLLPwrBypassCtrl);
304 break;
305 case kCLOCK_VpuPllCtrl:
306 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_VpuPllPwrBypassCtrl);
307 break;
308 case kCLOCK_ArmPllCtrl:
309 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_ArmPllPwrBypassCtrl);
310 break;
311 default:
312 fracPllBypass = false;
313 break;
314 }
315 if (pll <= kCLOCK_ArmPllCtrl)
316 {
317 if (fracPllBypass)
318 {
319 pllFreq = pllRefFreq;
320 }
321 else
322 {
323 pllFreq = CLOCK_GetFracPllFreq(CCM_ANALOG, pll, pllRefFreq);
324 }
325 }
326 else
327 {
328 if (sscgPll2Bypass)
329 {
330 /* if PLL2 is bypass, return reference clock directly */
331 pllFreq = pllRefFreq;
332 }
333 else
334 {
335 pllFreq = CLOCK_GetSSCGPllFreq(CCM_ANALOG, pll, pllRefFreq, sscgPll1Bypass);
336 }
337 }
338
339 return pllFreq;
340}
341
342/*!
343 * brief Initializes the ANALOG ARM PLL.
344 *
345 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
346 *
347 * note This function can't detect whether the Arm PLL has been enabled and
348 * used by some IPs.
349 */
350void CLOCK_InitArmPll(const ccm_analog_frac_pll_config_t *config)
351{
352 assert(config != NULL);
353
354 /* Disable PLL bypass */
355 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_ArmPllPwrBypassCtrl, false);
356 /* Fractional pll configuration */
357 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_ArmPllCtrl);
358 /* Enable and power up PLL clock. */
359 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_ArmPllClke);
360
361 /* Wait for PLL to be locked. */
362 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_ArmPllCtrl))
363 {
364 }
365}
366
367/*!
368 * brief De-initialize the ARM PLL.
369 */
370void CLOCK_DeinitArmPll(void)
371{
372 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_ArmPllCtrl);
373}
374
375/*!
376 * brief Initializes the ANALOG AUDIO PLL1.
377 *
378 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
379 *
380 * note This function can't detect whether the AUDIO PLL has been enabled and
381 * used by some IPs.
382 */
383void CLOCK_InitAudioPll1(const ccm_analog_frac_pll_config_t *config)
384{
385 assert(config != NULL);
386
387 /* Disable PLL bypass */
388 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_AudioPll1BypassCtrl, false);
389 /* Fractional pll configuration */
390 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_AudioPll1Ctrl);
391 /* Enable and power up PLL clock. */
392 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_AudioPll1Clke);
393
394 /* Wait for PLL to be locked. */
395 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_AudioPll1Ctrl))
396 {
397 }
398}
399
400/*!
401 * brief De-initialize the Audio PLL1.
402 */
403void CLOCK_DeinitAudioPll1(void)
404{
405 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_AudioPll1Ctrl);
406}
407
408/*!
409 * brief Initializes the ANALOG AUDIO PLL2.
410 *
411 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
412 *
413 * note This function can't detect whether the AUDIO PLL has been enabled and
414 * used by some IPs.
415 */
416void CLOCK_InitAudioPll2(const ccm_analog_frac_pll_config_t *config)
417{
418 assert(config != NULL);
419
420 /* Disable PLL bypass */
421 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_AudioPll2BypassCtrl, false);
422 /* Fractional pll configuration */
423 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_AudioPll2Ctrl);
424 /* Enable and power up PLL clock. */
425 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_AudioPll2Clke);
426
427 /* Wait for PLL to be locked. */
428 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_AudioPll2Ctrl))
429 {
430 }
431}
432
433/*!
434 * brief De-initialize the Audio PLL2.
435 */
436void CLOCK_DeinitAudioPll2(void)
437{
438 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_AudioPll2Ctrl);
439}
440
441/*!
442 * brief Initializes the ANALOG VIDEO PLL1.
443 *
444 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
445 *
446 */
447void CLOCK_InitVideoPll1(const ccm_analog_frac_pll_config_t *config)
448{
449 assert(config != NULL);
450
451 /* Disable PLL bypass */
452 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_VideoPll1BypassCtrl, false);
453 /* Fractional pll configuration */
454 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_VideoPll1Ctrl);
455 /* Enable and power up PLL clock. */
456 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_VideoPll1Clke);
457
458 /* Wait for PLL to be locked. */
459 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_VideoPll1Ctrl))
460 {
461 }
462}
463
464/*!
465 * brief De-initialize the Video PLL1.
466 */
467void CLOCK_DeinitVideoPll1(void)
468{
469 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_VideoPll1Ctrl);
470}
471
472/*!
473 * brief Initializes the ANALOG SYS PLL1.
474 *
475 * param config Pointer to the configuration structure(see ref ccm_analog_sscg_pll_config_t enumeration).
476 *
477 * note This function can't detect whether the SYS PLL has been enabled and
478 * used by some IPs.
479 */
480void CLOCK_InitSysPll1(const ccm_analog_sscg_pll_config_t *config)
481{
482 assert(config != NULL);
483
484 /* SSCG PLL configuration */
485 CLOCK_InitSSCGPll(CCM_ANALOG, config, kCLOCK_SystemPll1Ctrl);
486 /* Disable PLL bypass */
487 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll1InternalPll1BypassCtrl, false);
488 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll1InternalPll2BypassCtrl, false);
489 /* Enable and power up PLL clock. */
490 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_SystemPll1Clke);
491
492 /* Wait for PLL to be locked. */
493 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_SystemPll1Ctrl))
494 {
495 }
496}
497
498/*!
499 * brief De-initialize the System PLL1.
500 */
501void CLOCK_DeinitSysPll1(void)
502{
503 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_SystemPll1Ctrl);
504}
505
506/*!
507 * brief Initializes the ANALOG SYS PLL2.
508 *
509 * param config Pointer to the configuration structure(see ref ccm_analog_sscg_pll_config_t enumeration).
510 *
511 * note This function can't detect whether the SYS PLL has been enabled and
512 * used by some IPs.
513 */
514void CLOCK_InitSysPll2(const ccm_analog_sscg_pll_config_t *config)
515{
516 assert(config != NULL);
517
518 /* SSCG PLL configuration */
519 CLOCK_InitSSCGPll(CCM_ANALOG, config, kCLOCK_SystemPll2Ctrl);
520 /* Disable PLL bypass */
521 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll2InternalPll1BypassCtrl, false);
522 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll2InternalPll2BypassCtrl, false);
523 /* Enable and power up PLL clock. */
524 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_SystemPll2Clke);
525
526 /* Wait for PLL to be locked. */
527 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_SystemPll2Ctrl))
528 {
529 }
530}
531
532/*!
533 * brief De-initialize the System PLL2.
534 */
535void CLOCK_DeinitSysPll2(void)
536{
537 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_SystemPll2Ctrl);
538}
539
540/*!
541 * brief Initializes the ANALOG SYS PLL3.
542 *
543 * param config Pointer to the configuration structure(see ref ccm_analog_sscg_pll_config_t enumeration).
544 *
545 * note This function can't detect whether the SYS PLL has been enabled and
546 * used by some IPs.
547 */
548void CLOCK_InitSysPll3(const ccm_analog_sscg_pll_config_t *config)
549{
550 assert(config != NULL);
551
552 /* SSCG PLL configuration */
553 CLOCK_InitSSCGPll(CCM_ANALOG, config, kCLOCK_SystemPll3Ctrl);
554 /* Disable PLL bypass */
555 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll3InternalPll1BypassCtrl, false);
556 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll3InternalPll2BypassCtrl, false);
557 /* Enable and power up PLL clock. */
558 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_SystemPll3Clke);
559
560 /* Wait for PLL to be locked. */
561 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_SystemPll3Ctrl))
562 {
563 }
564}
565
566/*!
567 * brief De-initialize the System PLL3.
568 */
569void CLOCK_DeinitSysPll3(void)
570{
571 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_SystemPll3Ctrl);
572}
573
574/*!
575 * brief Initializes the ANALOG DDR PLL.
576 *
577 * param config Pointer to the configuration structure(see ref ccm_analog_sscg_pll_config_t enumeration).
578 *
579 * note This function can't detect whether the DDR PLL has been enabled and
580 * used by some IPs.
581 */
582void CLOCK_InitDramPll(const ccm_analog_sscg_pll_config_t *config)
583{
584 assert(config != NULL);
585
586 /* init SSCG pll */
587 CLOCK_InitSSCGPll(CCM_ANALOG, config, kCLOCK_DramPllCtrl);
588 /* Disable PLL bypass */
589 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_DramPllInternalPll1BypassCtrl, false);
590 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_DramPllInternalPll2BypassCtrl, false);
591 /* Enable and power up PLL clock. */
592 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_DramPllClke);
593
594 /* make sure DDR is release from reset, DDR1 should be assigned to special domain first */
595 /* trigger the DDR1 power up */
596 GPC->PU_PGC_SW_PUP_REQ |= GPC_PU_PGC_SW_PUP_REQ_DDR1_SW_PUP_REQ_MASK;
597 /* release DDR1 from reset status */
598 SRC->DDRC2_RCR = (SRC->DDRC2_RCR & (~(SRC_DDRC2_RCR_DDRC1_PHY_PWROKIN_MASK | SRC_DDRC2_RCR_DDRC1_PHY_RESET_MASK |
599 SRC_DDRC2_RCR_DDRC2_CORE_RST_MASK | SRC_DDRC2_RCR_DDRC2_PRST_MASK))) |
600 SRC_DDRC2_RCR_DOM_EN_MASK | SRC_DDRC2_RCR_DOMAIN3_MASK | SRC_DDRC2_RCR_DOMAIN2_MASK |
601 SRC_DDRC2_RCR_DOMAIN1_MASK | SRC_DDRC2_RCR_DOMAIN0_MASK;
602
603 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_DramPllCtrl))
604 {
605 }
606}
607
608/*!
609 * brief De-initialize the Dram PLL.
610 */
611void CLOCK_DeinitDramPll(void)
612{
613 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_DramPllCtrl);
614}
615
616/*!
617 * brief Initializes the ANALOG VIDEO PLL2.
618 *
619 * param config Pointer to the configuration structure(see ref ccm_analog_sscg_pll_config_t enumeration).
620 *
621 * note This function can't detect whether the VIDEO PLL has been enabled and
622 * used by some IPs.
623 */
624void CLOCK_InitVideoPll2(const ccm_analog_sscg_pll_config_t *config)
625{
626 assert(config != NULL);
627
628 /* init SSCG pll */
629 CLOCK_InitSSCGPll(CCM_ANALOG, config, kCLOCK_VideoPll2Ctrl);
630
631 /* Disable PLL bypass */
632 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_VideoPll2InternalPll1BypassCtrl, false);
633 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_VideoPll2InternalPll2BypassCtrl, false);
634 /* Enable and power up PLL clock. */
635 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_VideoPll2Clke);
636
637 /* Wait for PLL to be locked. */
638 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_VideoPll2Ctrl))
639 {
640 }
641}
642
643/*!
644 * brief De-initialize the Video PLL2.
645 */
646void CLOCK_DeinitVideoPll2(void)
647{
648 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_VideoPll2Ctrl);
649}
650
651/*!
652 * brief Initializes the ANALOG Fractional PLL.
653 *
654 * param base CCM ANALOG base address.
655 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
656 * param type fractional pll type.
657 *
658 */
659void CLOCK_InitFracPll(CCM_ANALOG_Type *base, const ccm_analog_frac_pll_config_t *config, clock_pll_ctrl_t type)
660{
661 assert(config != NULL);
662 assert((config->refDiv != 0U) && (config->outDiv != 0U));
663 assert((config->outDiv % 2U) == 0U);
664 assert(type <= kCLOCK_ArmPllCtrl);
665
666 uint32_t fracCfg0 = CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) | CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_PD_MASK;
667 uint32_t fracCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, 4U);
668
669 /* power down the fractional PLL first */
670 CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) = fracCfg0;
671
672 CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) =
673 (fracCfg0 &
674 (~(CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_OUTPUT_DIV_VAL_MASK | CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_DIV_VAL_MASK |
675 CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_SEL_MASK | CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_NEWDIV_VAL_MASK))) |
676 (CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_OUTPUT_DIV_VAL((uint32_t)(config->outDiv) / 2U - 1U)) |
677 (CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_DIV_VAL((uint32_t)(config->refDiv) - 1U)) |
678 CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_SEL(config->refSel);
679
680 CCM_ANALOG_TUPLE_REG_OFF(base, type, 4U) =
681 (fracCfg1 &
682 (~(CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_INT_DIV_CTL_MASK | CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_FRAC_DIV_CTL_MASK))) |
683 CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_INT_DIV_CTL(config->intDiv) |
684 CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_FRAC_DIV_CTL(config->fractionDiv);
685
686 /* NEW_DIV_VAL */
687 CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) |= CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_NEWDIV_VAL_MASK;
688
689 /* power up the fractional pll */
690 CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) &= ~CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_PD_MASK;
691
692 /* need to check NEW_DIV_ACK */
693 while ((CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) & CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_NEWDIV_ACK_MASK) == 0U)
694 {
695 }
696}
697
698/*!
699 * brief Gets the ANALOG Fractional PLL clock frequency.
700 *
701 * param base CCM_ANALOG base pointer.
702 * param type fractional pll type.
703 * param fractional pll reference clock frequency
704 *
705 * return Clock frequency
706 */
707uint32_t CLOCK_GetFracPllFreq(CCM_ANALOG_Type *base, clock_pll_ctrl_t type, uint32_t refClkFreq)
708{
709 assert(type <= kCLOCK_ArmPllCtrl);
710
711 uint32_t fracCfg0 = CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U);
712 uint32_t fracCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, 4U);
713 uint64_t fracClk = 0U;
714
715 uint8_t refDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(fracCfg0, CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_DIV_VAL_MASK,
716 CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_DIV_VAL_SHIFT);
717 uint8_t outDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(fracCfg0, CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_OUTPUT_DIV_VAL_MASK,
718 CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_OUTPUT_DIV_VAL_SHIFT);
719 uint32_t fracDiv = CCM_BIT_FIELD_EXTRACTION(fracCfg1, CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_FRAC_DIV_CTL_MASK,
720 CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_FRAC_DIV_CTL_SHIFT);
721 uint8_t intDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(fracCfg1, CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_INT_DIV_CTL_MASK,
722 CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_INT_DIV_CTL_SHIFT);
723
724 refClkFreq /= (uint32_t)refDiv + 1UL;
725 fracClk = (uint64_t)refClkFreq * 8U * (1U + intDiv) + (((uint64_t)refClkFreq * 8U * fracDiv) >> 24U);
726
727 return (uint32_t)(fracClk / (((uint64_t)outDiv + 1U) * 2U));
728}
729
730/*!
731 * brief Initializes the ANALOG SSCG PLL.
732 *
733 * param base CCM ANALOG base address
734 * param config Pointer to the configuration structure(see ref ccm_analog_sscg_pll_config_t enumeration).
735 * param type sscg pll type
736 *
737 */
738void CLOCK_InitSSCGPll(CCM_ANALOG_Type *base, const ccm_analog_sscg_pll_config_t *config, clock_pll_ctrl_t type)
739{
740 assert(config != NULL);
741 assert(config->refDiv1 != 0U);
742 assert(config->refDiv2 != 0U);
743 assert(config->outDiv != 0U);
744 assert(config->loopDivider1 != 0U);
745 assert(config->loopDivider2 != 0U);
746 assert(type >= kCLOCK_SystemPll1Ctrl);
747
748 uint32_t sscgCfg0 = CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) | CCM_ANALOG_SYS_PLL1_CFG0_PLL_PD_MASK;
749 uint32_t sscgCfg2 = CCM_ANALOG_TUPLE_REG_OFF(base, type, 8U);
750 uint32_t pll1Filter = 0U;
751
752 /* power down the SSCG PLL first */
753 CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) = sscgCfg0;
754
755 /* pll mux configuration */
756 CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) =
757 (sscgCfg0 & (~CCM_ANALOG_SYS_PLL1_CFG0_PLL_REFCLK_SEL_MASK)) | config->refSel;
758
759 /* reserve CFG1, spread spectrum */
760
761 /* match the PLL1 input clock range with PLL filter range */
762 if ((CLOCK_GetPllRefClkFreq(type) / (config->refDiv1)) > SSCG_PLL1_FILTER_RANGE)
763 {
764 pll1Filter = 1U;
765 }
766 /* divider configuration */
767 CCM_ANALOG_TUPLE_REG_OFF(base, type, 8U) =
768 (sscgCfg2 &
769 (~(CCM_ANALOG_SYS_PLL1_CFG2_PLL_OUTPUT_DIV_VAL_MASK | CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF2_MASK |
770 CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF1_MASK | CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR2_MASK |
771 CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR1_MASK))) |
772 CCM_ANALOG_SYS_PLL1_CFG2_PLL_OUTPUT_DIV_VAL((uint32_t)(config->outDiv) - 1U) |
773 CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF2(config->loopDivider2 - 1U) |
774 CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF1(config->loopDivider1 - 1U) |
775 CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR2((uint32_t)(config->refDiv2) - 1U) |
776 CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR1((uint32_t)(config->refDiv1) - 1U) | pll1Filter;
777
778 /* power up the SSCG PLL */
779 CCM_ANALOG_TUPLE_REG_OFF(base, type, 0U) &= ~CCM_ANALOG_SYS_PLL1_CFG0_PLL_PD_MASK;
780}
781
782/*!
783 * brief Get the ANALOG SSCG PLL clock frequency.
784 *
785 * param base CCM ANALOG base address.
786 * param type sscg pll type
787 * param pll1Bypass pll1 bypass flag
788 *
789 * return Clock frequency
790 */
791uint32_t CLOCK_GetSSCGPllFreq(CCM_ANALOG_Type *base, clock_pll_ctrl_t type, uint32_t refClkFreq, bool pll1Bypass)
792{
793 assert(type >= kCLOCK_SystemPll1Ctrl);
794
795 uint32_t sscgCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, 4U);
796 uint32_t sscgCfg2 = CCM_ANALOG_TUPLE_REG_OFF(base, type, 8U);
797 uint64_t pll2InputClock = 0U;
798
799 uint8_t refDiv1 = (uint8_t)CCM_BIT_FIELD_EXTRACTION(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR1_MASK,
800 CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR1_SHIFT) +
801 1U;
802 uint8_t refDiv2 = (uint8_t)CCM_BIT_FIELD_EXTRACTION(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR2_MASK,
803 CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR2_SHIFT) +
804 1U;
805 uint8_t divf1 = (uint8_t)CCM_BIT_FIELD_EXTRACTION(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF1_MASK,
806 CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF1_SHIFT) +
807 1U;
808 uint8_t divf2 = (uint8_t)CCM_BIT_FIELD_EXTRACTION(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF2_MASK,
809 CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF2_SHIFT) +
810 1U;
811 uint8_t outDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_OUTPUT_DIV_VAL_MASK,
812 CCM_ANALOG_SYS_PLL1_CFG2_PLL_OUTPUT_DIV_VAL_SHIFT) +
813 1U;
814
815 refClkFreq /= refDiv1;
816
817 if (pll1Bypass)
818 {
819 pll2InputClock = refClkFreq;
820 }
821 else if ((sscgCfg1 & CCM_ANALOG_SYS_PLL1_CFG1_PLL_SSE_MASK) != 0U)
822 {
823 pll2InputClock = (uint64_t)refClkFreq * 8U * divf1 / refDiv2;
824 }
825 else
826 {
827 pll2InputClock = (uint64_t)refClkFreq * 2U * divf1 / refDiv2;
828 }
829
830 return (uint32_t)(pll2InputClock * divf2 / outDiv);
831}
832
833/*!
834 * brief Set root clock divider
835 * Note: The PRE and POST dividers in this function are the actually divider, software will map it to register value
836 *
837 * param ccmRootClk Root control (see ref clock_root_control_t enumeration)
838 * param pre Pre divider value (1-8)
839 * param post Post divider value (1-64)
840 */
841void CLOCK_SetRootDivider(clock_root_control_t ccmRootClk, uint32_t pre, uint32_t post)
842{
843 assert((pre <= 8U) && (pre != 0U));
844 assert((post <= 64U) && (post != 0U));
845
846 CCM_REG(ccmRootClk) = (CCM_REG(ccmRootClk) & (~(CCM_TARGET_ROOT_PRE_PODF_MASK | CCM_TARGET_ROOT_POST_PODF_MASK))) |
847 CCM_TARGET_ROOT_PRE_PODF(pre - 1U) | CCM_TARGET_ROOT_POST_PODF(post - 1U);
848}
849
850/*!
851 * brief Update clock root in one step, for dynamical clock switching
852 * Note: The PRE and POST dividers in this function are the actually divider, software will map it to register value
853 *
854 * param ccmRootClk Root control (see ref clock_root_control_t enumeration)
855 * param root mux value (see ref _ccm_rootmux_xxx enumeration)
856 * param pre Pre divider value (0-7, divider=n+1)
857 * param post Post divider value (0-63, divider=n+1)
858 */
859void CLOCK_UpdateRoot(clock_root_control_t ccmRootClk, uint32_t mux, uint32_t pre, uint32_t post)
860{
861 assert((pre <= 8U) && (pre != 0U));
862 assert((post <= 64U) && (post != 0U));
863
864 CCM_REG(ccmRootClk) =
865 (CCM_REG(ccmRootClk) &
866 (~(CCM_TARGET_ROOT_MUX_MASK | CCM_TARGET_ROOT_PRE_PODF_MASK | CCM_TARGET_ROOT_POST_PODF_MASK))) |
867 CCM_TARGET_ROOT_MUX(mux) | CCM_TARGET_ROOT_PRE_PODF(pre - 1U) | CCM_TARGET_ROOT_POST_PODF(post - 1U);
868}
869
870/*!
871 * brief OSC25M init
872 *
873 * param config osc configuration
874 */
875void CLOCK_InitOSC25M(const osc_config_t *config)
876{
877 assert(config != NULL);
878 assert(config->oscDiv != 0U);
879
880 XTALOSC->OSC25M_CTL_CFG =
881 (XTALOSC->OSC25M_CTL_CFG & (~(XTALOSC_OSC25M_CTL_CFG_OSC_DIV_MASK | XTALOSC_OSC25M_CTL_CFG_OSC_BYPSS_MASK))) |
882 XTALOSC_OSC25M_CTL_CFG_OSC_DIV((uint32_t)(config->oscDiv) - 1U) |
883 XTALOSC_OSC25M_CTL_CFG_OSC_BYPSS(config->oscMode);
884
885 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_OSC25MClke);
886}
887
888/*!
889 * brief OSC25M deinit
890 *
891 */
892void CLOCK_DeinitOSC25M(void)
893{
894 CLOCK_DisableAnalogClock(CCM_ANALOG, kCLOCK_OSC25MClke);
895}
896
897/*!
898 * brief OSC27M init
899 *
900 */
901void CLOCK_InitOSC27M(const osc_config_t *config)
902{
903 assert(config != NULL);
904 assert(config->oscDiv != 0U);
905
906 XTALOSC->OSC27M_CTL_CFG =
907 (XTALOSC->OSC27M_CTL_CFG & (~(XTALOSC_OSC27M_CTL_CFG_OSC_DIV_MASK | XTALOSC_OSC27M_CTL_CFG_OSC_BYPSS_MASK))) |
908 XTALOSC_OSC27M_CTL_CFG_OSC_DIV((uint32_t)(config->oscDiv) - 1U) |
909 XTALOSC_OSC27M_CTL_CFG_OSC_BYPSS(config->oscMode);
910
911 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_OSC27MClke);
912}
913
914/*!
915 * brief OSC27M deinit
916 *
917 * param config osc configuration
918 */
919void CLOCK_DeinitOSC27M(void)
920{
921 CLOCK_DisableAnalogClock(CCM_ANALOG, kCLOCK_OSC27MClke);
922}
923
924/*!
925 * brief Enable CCGR clock gate and root clock gate for each module
926 * User should set specific gate for each module according to the description
927 * of the table of system clocks, gating and override in CCM chapter of
928 * reference manual. Take care of that one module may need to set more than
929 * one clock gate.
930 *
931 * param ccmGate Gate control for each module (see ref clock_ip_name_t enumeration).
932 */
933void CLOCK_EnableClock(clock_ip_name_t ccmGate)
934{
935 uint32_t ccgr = CCM_TUPLE_CCGR(ccmGate);
936 uint32_t rootClk = CCM_TUPLE_ROOT(ccmGate);
937
938 CCM_REG_SET(ccgr) = (uint32_t)kCLOCK_ClockNeededAll;
939 /* if root clock is 0xFFFFU, then skip enable root clock */
940 if (rootClk != 0xFFFFU)
941 {
942 CCM_REG_SET(rootClk) = CCM_TARGET_ROOT_SET_ENABLE_MASK;
943 }
944}
945
946/*!
947 * brief Disable CCGR clock gate for the each module
948 * User should set specific gate for each module according to the description
949 * of the table of system clocks, gating and override in CCM chapter of
950 * reference manual. Take care of that one module may need to set more than
951 * one clock gate.
952 *
953 * param ccmGate Gate control for each module (see ref clock_ip_name_t enumeration).
954 */
955void CLOCK_DisableClock(clock_ip_name_t ccmGate)
956{
957 uint32_t ccgr = CCM_TUPLE_CCGR(ccmGate);
958 uint32_t rootClk = CCM_TUPLE_ROOT(ccmGate);
959
960 CCM_REG(ccgr) = (uint32_t)kCLOCK_ClockNotNeeded;
961
962 /* if root clock is 0xFFFFU, then skip disable root clock */
963 if (rootClk != 0xFFFFU)
964 {
965 CCM_REG_CLR(rootClk) = CCM_TARGET_ROOT_CLR_ENABLE_MASK;
966 }
967}