aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MN2/drivers/fsl_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MN2/drivers/fsl_clock.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MN2/drivers/fsl_clock.c786
1 files changed, 786 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MN2/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MN2/drivers/fsl_clock.c
new file mode 100644
index 000000000..6fc2f2232
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MN2/drivers/fsl_clock.c
@@ -0,0 +1,786 @@
1/*
2 * Copyright 2018 - 2020 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
18#define FracPLL_GNRL_CTL_Offset (0U)
19#define FracPLL_FDIV_CTL0_Offset (4U)
20#define FracPLL_FDIV_CTL1_Offset (8U)
21
22#define IntegerPLL_GNRL_CTL_Offset (0U)
23#define IntegerPLL_DIV_CTL_Offset (4U)
24/*******************************************************************************
25 * Prototypes
26 ******************************************************************************/
27
28/*******************************************************************************
29 * Variables
30 ******************************************************************************/
31
32/*******************************************************************************
33 * Code
34 ******************************************************************************/
35/*!
36 * brief Gets the clock frequency for a specific clock name.
37 *
38 * This function checks the current clock configurations and then calculates
39 * the clock frequency for a specific clock name defined in clock_name_t.
40 *
41 * param clockName Clock names defined in clock_name_t
42 * return Clock frequency value in hertz
43 */
44uint32_t CLOCK_GetFreq(clock_name_t clockName)
45{
46 uint32_t freq;
47 uint32_t temp;
48
49 switch (clockName)
50 {
51 case kCLOCK_CoreM7Clk:
52 freq = CLOCK_GetCoreM7Freq();
53 break;
54 case kCLOCK_AxiClk:
55 freq = CLOCK_GetAxiFreq();
56 break;
57 case kCLOCK_AhbClk:
58 freq = CLOCK_GetAhbFreq();
59 break;
60 case kCLOCK_IpgClk:
61 {
62 temp = CLOCK_GetAhbFreq();
63 freq = temp / CLOCK_GetRootPostDivider(kCLOCK_RootIpg);
64 break;
65 }
66 default:
67 freq = 0U;
68 break;
69 }
70 return freq;
71}
72
73/*!
74 * brief Get the CCM Cortex M7 core frequency.
75 *
76 * return Clock frequency; If the clock is invalid, returns 0.
77 */
78uint32_t CLOCK_GetCoreM7Freq(void)
79{
80 uint32_t freq;
81 uint32_t pre = CLOCK_GetRootPreDivider(kCLOCK_RootM7);
82 uint32_t post = CLOCK_GetRootPostDivider(kCLOCK_RootM7);
83
84 switch (CLOCK_GetRootMux(kCLOCK_RootM7))
85 {
86 case (uint32_t)kCLOCK_M7RootmuxOsc24M:
87 freq = OSC24M_CLK_FREQ;
88 break;
89 case (uint32_t)kCLOCK_M7RootmuxSysPll2Div5:
90 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 5U;
91 break;
92 case (uint32_t)kCLOCK_M7RootmuxSysPll2Div4:
93 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 4U;
94 break;
95 case (uint32_t)kCLOCK_M7RootmuxSysPll1Div3:
96 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / 3U;
97 break;
98 case (uint32_t)kCLOCK_M7RootmuxSysPll1:
99 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl);
100 break;
101 case (uint32_t)kCLOCK_M7RootmuxAudioPll1:
102 freq = CLOCK_GetPllFreq(kCLOCK_AudioPll1Ctrl);
103 break;
104 case (uint32_t)kCLOCK_M7RootmuxVideoPll1:
105 freq = CLOCK_GetPllFreq(kCLOCK_VideoPll1Ctrl);
106 break;
107 case (uint32_t)kCLOCK_M7RootmuxSysPll3:
108 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll3Ctrl);
109 break;
110 default:
111 freq = 0U;
112 break;
113 }
114
115 return freq / pre / post;
116}
117
118/*!
119 * brief Get the CCM Axi bus frequency.
120 *
121 * return Clock frequency; If the clock is invalid, returns 0.
122 */
123uint32_t CLOCK_GetAxiFreq(void)
124{
125 uint32_t freq;
126 uint32_t pre = CLOCK_GetRootPreDivider(kCLOCK_RootAxi);
127 uint32_t post = CLOCK_GetRootPostDivider(kCLOCK_RootAxi);
128
129 switch (CLOCK_GetRootMux(kCLOCK_RootAxi))
130 {
131 case (uint32_t)kCLOCK_AxiRootmuxOsc24M:
132 freq = OSC24M_CLK_FREQ;
133 break;
134 case (uint32_t)kCLOCK_AxiRootmuxSysPll2Div3:
135 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 3U;
136 break;
137 case (uint32_t)kCLOCK_AxiRootmuxSysPll2Div4:
138 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 4U;
139 break;
140 case (uint32_t)kCLOCK_AxiRootmuxSysPll2:
141 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl);
142 break;
143 case (uint32_t)kCLOCK_AxiRootmuxAudioPll1:
144 freq = CLOCK_GetPllFreq(kCLOCK_AudioPll1Ctrl);
145 break;
146 case (uint32_t)kCLOCK_AxiRootmuxVideoPll1:
147 freq = CLOCK_GetPllFreq(kCLOCK_VideoPll1Ctrl);
148 break;
149 case (uint32_t)kCLOCK_AxiRootmuxSysPll1Div8:
150 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / 8UL;
151 break;
152 case (uint32_t)kCLOCK_AxiRootmuxSysPll1:
153 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl);
154 break;
155 default:
156 freq = 0U;
157 break;
158 }
159
160 return freq / pre / post;
161}
162
163/*!
164 * brief Get the CCM Ahb bus frequency.
165 *
166 * return Clock frequency; If the clock is invalid, returns 0.
167 */
168uint32_t CLOCK_GetAhbFreq(void)
169{
170 uint32_t freq;
171 uint32_t pre = CLOCK_GetRootPreDivider(kCLOCK_RootAhb);
172 uint32_t post = CLOCK_GetRootPostDivider(kCLOCK_RootAhb);
173
174 switch (CLOCK_GetRootMux(kCLOCK_RootAhb))
175 {
176 case (uint32_t)kCLOCK_AhbRootmuxOsc24M:
177 freq = OSC24M_CLK_FREQ;
178 break;
179 case (uint32_t)kCLOCK_AhbRootmuxSysPll1Div6:
180 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / 6U;
181 break;
182 case (uint32_t)kCLOCK_AhbRootmuxSysPll1Div2:
183 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / 2U;
184 break;
185 case (uint32_t)kCLOCK_AhbRootmuxSysPll1:
186 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl);
187 break;
188 case (uint32_t)kCLOCK_AhbRootmuxSysPll2Div8:
189 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 8U;
190 break;
191 case (uint32_t)kCLOCK_AhbRootmuxSysPll3:
192 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll3Ctrl);
193 break;
194 case (uint32_t)kCLOCK_AhbRootmuxAudioPll1:
195 freq = CLOCK_GetPllFreq(kCLOCK_AudioPll1Ctrl);
196 break;
197 case (uint32_t)kCLOCK_AhbRootmuxVideoPll1:
198 freq = CLOCK_GetPllFreq(kCLOCK_VideoPll1Ctrl);
199 break;
200 default:
201 freq = 0U;
202 break;
203 }
204
205 return freq / pre / post;
206}
207
208/*!
209 * brief Gets PLL reference clock frequency.
210 *
211 * param type fractional pll type.
212
213 * return Clock frequency
214 */
215uint32_t CLOCK_GetPllRefClkFreq(clock_pll_ctrl_t ctrl)
216{
217 uint32_t refClkFreq = 0U;
218 uint8_t clkSel = 0U;
219
220 if (ctrl < kCLOCK_ArmPllCtrl)
221 {
222 clkSel =
223 (uint8_t)((CCM_ANALOG_TUPLE_REG(CCM_ANALOG, ctrl) & CCM_ANALOG_AUDIO_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_MASK));
224 }
225 else
226 {
227 clkSel = (uint8_t)(CCM_ANALOG_TUPLE_REG(CCM_ANALOG, ctrl) & CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_MASK);
228 }
229
230 switch (clkSel)
231 {
232 case kANALOG_PllRefOsc24M:
233 refClkFreq = OSC24M_CLK_FREQ;
234 break;
235
236 case kANALOG_PllPadClk:
237 /* The value of PAD CLK need user to define according to the actual condition. */
238 refClkFreq = CLKPAD_FREQ;
239 break;
240
241 default:
242 refClkFreq = 0U;
243 break;
244 }
245
246 return refClkFreq;
247}
248
249/*!
250 * brief Gets PLL clock frequency.
251 *
252 * param type fractional pll type.
253
254 * return Clock frequency
255 */
256uint32_t CLOCK_GetPllFreq(clock_pll_ctrl_t pll)
257{
258 uint32_t pllFreq = 0U;
259 uint32_t pllRefFreq = 0U;
260 bool intergerPllBypass = false;
261 bool fracPllBypass = false;
262
263 pllRefFreq = CLOCK_GetPllRefClkFreq(pll);
264
265 switch (pll)
266 {
267 /* Integer PLL frequency */
268 case kCLOCK_ArmPllCtrl:
269 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_ArmPllPwrBypassCtrl);
270 break;
271 case kCLOCK_SystemPll1Ctrl:
272 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll1InternalPll1BypassCtrl);
273 break;
274 case kCLOCK_SystemPll2Ctrl:
275 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll2InternalPll1BypassCtrl);
276 break;
277 case kCLOCK_SystemPll3Ctrl:
278 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll3InternalPll1BypassCtrl);
279 break;
280 /* Fractional PLL frequency */
281 case kCLOCK_AudioPll1Ctrl:
282 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_AudioPll1BypassCtrl);
283 break;
284 case kCLOCK_AudioPll2Ctrl:
285 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_AudioPll2BypassCtrl);
286 break;
287 case kCLOCK_VideoPll1Ctrl:
288 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_VideoPll1BypassCtrl);
289 break;
290 case kCLOCK_DramPllCtrl:
291 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_DramPllInternalPll1BypassCtrl);
292 break;
293 default:
294 fracPllBypass = false;
295 break;
296 }
297 if (pll < kCLOCK_ArmPllCtrl)
298 {
299 if (fracPllBypass)
300 {
301 pllFreq = pllRefFreq;
302 }
303 else
304 {
305 pllFreq = CLOCK_GetFracPllFreq(CCM_ANALOG, pll, pllRefFreq);
306 }
307 }
308 else
309 {
310 if (intergerPllBypass)
311 {
312 /* if PLL is bypass, return reference clock directly */
313 pllFreq = pllRefFreq;
314 }
315 else
316 {
317 pllFreq = CLOCK_GetIntegerPllFreq(CCM_ANALOG, pll, pllRefFreq, false);
318 }
319 }
320
321 return (uint32_t)pllFreq;
322}
323
324/*!
325 * brief Initializes the ANALOG ARM PLL.
326 *
327 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
328 *
329 * note This function can't detect whether the Arm PLL has been enabled and
330 * used by some IPs.
331 */
332void CLOCK_InitArmPll(const ccm_analog_integer_pll_config_t *config)
333{
334 assert(config != NULL);
335
336 /* Integer PLL configuration */
337 CLOCK_InitIntegerPll(CCM_ANALOG, config, kCLOCK_ArmPllCtrl);
338 /* Disable PLL bypass */
339 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_ArmPllPwrBypassCtrl, false);
340 /* Enable and power up PLL clock. */
341 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_ArmPllClke);
342
343 /* Wait for PLL to be locked. */
344 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_ArmPllCtrl))
345 {
346 }
347}
348
349/*!
350 * brief De-initialize the ARM PLL.
351 */
352void CLOCK_DeinitArmPll(void)
353{
354 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_ArmPllCtrl);
355}
356
357/*!
358 * brief Initializes the ANALOG AUDIO PLL1.
359 *
360 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
361 *
362 * note This function can't detect whether the AUDIO PLL has been enabled and
363 * used by some IPs.
364 */
365void CLOCK_InitAudioPll1(const ccm_analog_frac_pll_config_t *config)
366{
367 assert(config != NULL);
368
369 /* Disable PLL bypass */
370 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_AudioPll1BypassCtrl, false);
371 /* Fractional pll configuration */
372 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_AudioPll1Ctrl);
373 /* Enable and power up PLL clock. */
374 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_AudioPll1Clke);
375
376 /* Wait for PLL to be locked. */
377 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_AudioPll1Ctrl))
378 {
379 }
380}
381
382/*!
383 * brief De-initialize the Audio PLL1.
384 */
385void CLOCK_DeinitAudioPll1(void)
386{
387 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_AudioPll1Ctrl);
388}
389
390/*!
391 * brief Initializes the ANALOG AUDIO PLL2.
392 *
393 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
394 *
395 * note This function can't detect whether the AUDIO PLL has been enabled and
396 * used by some IPs.
397 */
398void CLOCK_InitAudioPll2(const ccm_analog_frac_pll_config_t *config)
399{
400 assert(config != NULL);
401
402 /* Disable PLL bypass */
403 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_AudioPll2BypassCtrl, false);
404 /* Fractional pll configuration */
405 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_AudioPll2Ctrl);
406 /* Enable and power up PLL clock. */
407 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_AudioPll2Clke);
408
409 /* Wait for PLL to be locked. */
410 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_AudioPll2Ctrl))
411 {
412 }
413}
414
415/*!
416 * brief De-initialize the Audio PLL2.
417 */
418void CLOCK_DeinitAudioPll2(void)
419{
420 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_AudioPll2Ctrl);
421}
422
423/*!
424 * brief Initializes the ANALOG VIDEO PLL1.
425 *
426 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
427 *
428 */
429void CLOCK_InitVideoPll1(const ccm_analog_frac_pll_config_t *config)
430{
431 assert(config != NULL);
432
433 /* Disable PLL bypass */
434 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_VideoPll1BypassCtrl, false);
435 /* Fractional pll configuration */
436 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_VideoPll1Ctrl);
437 /* Enable and power up PLL clock. */
438 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_VideoPll1Clke);
439
440 /* Wait for PLL to be locked. */
441 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_VideoPll1Ctrl))
442 {
443 }
444}
445
446/*!
447 * brief De-initialize the Video PLL1.
448 */
449void CLOCK_DeinitVideoPll1(void)
450{
451 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_VideoPll1Ctrl);
452}
453
454/*!
455 * brief Initializes the ANALOG SYS PLL1.
456 *
457 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
458 *
459 * note This function can't detect whether the SYS PLL has been enabled and
460 * used by some IPs.
461 */
462void CLOCK_InitSysPll1(const ccm_analog_integer_pll_config_t *config)
463{
464 assert(config != NULL);
465
466 /* Integer PLL configuration */
467 CLOCK_InitIntegerPll(CCM_ANALOG, config, kCLOCK_SystemPll1Ctrl);
468 /* Disable PLL bypass */
469 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll1InternalPll1BypassCtrl, false);
470 /* Enable and power up PLL clock. */
471 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_SystemPll1Clke);
472
473 /* Wait for PLL to be locked. */
474 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_SystemPll1Ctrl))
475 {
476 }
477}
478
479/*!
480 * brief De-initialize the System PLL1.
481 */
482void CLOCK_DeinitSysPll1(void)
483{
484 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_SystemPll1Ctrl);
485}
486
487/*!
488 * brief Initializes the ANALOG SYS PLL2.
489 *
490 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
491 *
492 * note This function can't detect whether the SYS PLL has been enabled and
493 * used by some IPs.
494 */
495void CLOCK_InitSysPll2(const ccm_analog_integer_pll_config_t *config)
496{
497 assert(config != NULL);
498
499 /* Integer PLL configuration */
500 CLOCK_InitIntegerPll(CCM_ANALOG, config, kCLOCK_SystemPll2Ctrl);
501 /* Disable PLL bypass */
502 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll2InternalPll1BypassCtrl, false);
503 /* Enable and power up PLL clock. */
504 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_SystemPll2Clke);
505
506 /* Wait for PLL to be locked. */
507 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_SystemPll2Ctrl))
508 {
509 }
510}
511
512/*!
513 * brief De-initialize the System PLL2.
514 */
515void CLOCK_DeinitSysPll2(void)
516{
517 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_SystemPll2Ctrl);
518}
519
520/*!
521 * brief Initializes the ANALOG SYS PLL3.
522 *
523 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
524 *
525 * note This function can't detect whether the SYS PLL has been enabled and
526 * used by some IPs.
527 */
528void CLOCK_InitSysPll3(const ccm_analog_integer_pll_config_t *config)
529{
530 assert(config != NULL);
531
532 /* Integer PLL configuration */
533 CLOCK_InitIntegerPll(CCM_ANALOG, config, kCLOCK_SystemPll3Ctrl);
534 /* Disable PLL bypass */
535 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll3InternalPll1BypassCtrl, false);
536 /* Enable and power up PLL clock. */
537 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_SystemPll3Clke);
538
539 /* Wait for PLL to be locked. */
540 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_SystemPll3Ctrl))
541 {
542 }
543}
544
545/*!
546 * brief De-initialize the System PLL3.
547 */
548void CLOCK_DeinitSysPll3(void)
549{
550 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_SystemPll3Ctrl);
551}
552
553/*!
554 * brief Initializes the ANALOG Fractional PLL.
555 *
556 * param base CCM ANALOG base address.
557 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
558 * param type fractional pll type.
559 *
560 */
561void CLOCK_InitFracPll(CCM_ANALOG_Type *base, const ccm_analog_frac_pll_config_t *config, clock_pll_ctrl_t type)
562{
563 assert(config != NULL);
564 assert((config->mainDiv >= 64U) && (config->mainDiv <= 1023U));
565 assert((config->preDiv >= 1U) && (config->preDiv <= 63U));
566 assert(config->postDiv <= 6U);
567
568 assert(type < kCLOCK_ArmPllCtrl);
569
570 uint32_t fracCfg0 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_GNRL_CTL_Offset) &
571 ~((uint32_t)1 << CCM_ANALOG_AUDIO_PLL1_GEN_CTRL_PLL_RST_SHIFT);
572 uint32_t fracCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL0_Offset);
573 uint32_t fracCfg2 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL1_Offset);
574
575 /* power down the fractional PLL first */
576 CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_GNRL_CTL_Offset) = fracCfg0;
577
578 CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL0_Offset) =
579 (fracCfg1 &
580 (~(CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK | CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK |
581 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK))) |
582 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV(config->mainDiv) |
583 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV(config->preDiv) |
584 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV(config->postDiv);
585
586 CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL1_Offset) =
587 (fracCfg2 & (~(CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_MASK))) |
588 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM(config->dsm);
589
590 /* power up the fractional pll */
591 CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_GNRL_CTL_Offset) |= CCM_ANALOG_AUDIO_PLL1_GEN_CTRL_PLL_RST_MASK;
592}
593
594/*!
595 * brief Gets the ANALOG Fractional PLL clock frequency.
596 *
597 * param base CCM_ANALOG base pointer.
598 * param type fractional pll type.
599 * param fractional pll reference clock frequency
600 *
601 * return Clock frequency
602 */
603uint32_t CLOCK_GetFracPllFreq(CCM_ANALOG_Type *base, clock_pll_ctrl_t type, uint32_t refClkFreq)
604{
605 assert(type < kCLOCK_ArmPllCtrl);
606
607 uint32_t fracCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL0_Offset);
608 uint32_t fracCfg2 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL1_Offset);
609 uint64_t fracClk = 0U;
610
611 uint32_t mainDiv = CCM_BIT_FIELD_EXTRACTION(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK,
612 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_SHIFT);
613 uint8_t preDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK,
614 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_SHIFT);
615 uint8_t postDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK,
616 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_SHIFT);
617 uint32_t dsm = CCM_BIT_FIELD_EXTRACTION(fracCfg2, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_MASK,
618 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_SHIFT);
619
620 fracClk = (uint64_t)((uint64_t)refClkFreq * ((uint64_t)mainDiv * 65536ULL + dsm) /
621 (65536ULL * (uint32_t)preDiv * (1ULL << postDiv)));
622
623 return (uint32_t)fracClk;
624}
625
626/*!
627 * brief Initializes the ANALOG Integer PLL.
628 *
629 * param base CCM ANALOG base address
630 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
631 * param type integer pll type
632 *
633 */
634void CLOCK_InitIntegerPll(CCM_ANALOG_Type *base, const ccm_analog_integer_pll_config_t *config, clock_pll_ctrl_t type)
635{
636 assert(config != NULL);
637 assert((config->mainDiv >= 64U) && (config->mainDiv <= 1023U));
638 assert((config->preDiv >= 1U) && (config->preDiv <= 63U));
639 assert(config->postDiv <= 6U);
640
641 assert(type >= kCLOCK_SystemPll1Ctrl);
642
643 uint32_t integerCfg0 = CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_GNRL_CTL_Offset) &
644 ~((uint32_t)1 << CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_RST_SHIFT);
645 uint32_t integerCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_DIV_CTL_Offset);
646
647 /* power down the Integer PLL first */
648 CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_GNRL_CTL_Offset) = integerCfg0;
649
650 /* pll mux configuration */
651 CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_GNRL_CTL_Offset) =
652 (integerCfg0 & (~CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_MASK)) | config->refSel;
653
654 /* divider configuration */
655 CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_DIV_CTL_Offset) =
656 (integerCfg1 &
657 (~(CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK | CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK |
658 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK))) |
659 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV(config->mainDiv) |
660 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV(config->preDiv) |
661 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV(config->postDiv);
662
663 /* power up the Integer PLL */
664 CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_GNRL_CTL_Offset) |= CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_RST_MASK;
665}
666
667/*!
668 * brief Get the ANALOG Integer PLL clock frequency.
669 *
670 * param base CCM ANALOG base address.
671 * param type integer pll type
672 * param pll1Bypass pll1 bypass flag
673 *
674 * return Clock frequency
675 */
676uint32_t CLOCK_GetIntegerPllFreq(CCM_ANALOG_Type *base, clock_pll_ctrl_t type, uint32_t refClkFreq, bool pll1Bypass)
677{
678 assert(type >= kCLOCK_SystemPll1Ctrl);
679
680 uint32_t integerCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_DIV_CTL_Offset);
681 uint64_t pllOutClock = 0U;
682
683 uint32_t mainDiv = CCM_BIT_FIELD_EXTRACTION(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK,
684 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_SHIFT);
685 uint8_t preDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK,
686 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_SHIFT);
687 uint8_t postDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK,
688 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_SHIFT);
689
690 if (pll1Bypass)
691 {
692 pllOutClock = refClkFreq;
693 }
694
695 else
696 {
697 pllOutClock = (uint64_t)refClkFreq * mainDiv / (((uint64_t)(1U) << postDiv) * preDiv);
698 }
699
700 return (uint32_t)pllOutClock;
701}
702
703/*!
704 * brief Set root clock divider
705 * Note: The PRE and POST dividers in this function are the actually divider, software will map it to register value
706 *
707 * param ccmRootClk Root control (see ref clock_root_control_t enumeration)
708 * param pre Pre divider value (1-8)
709 * param post Post divider value (1-64)
710 */
711void CLOCK_SetRootDivider(clock_root_control_t ccmRootClk, uint32_t pre, uint32_t post)
712{
713 assert((pre <= 8U) && (pre != 0U));
714 assert((post <= 64U) && (post != 0U));
715
716 CCM_REG(ccmRootClk) = (CCM_REG(ccmRootClk) & (~(CCM_TARGET_ROOT_PRE_PODF_MASK | CCM_TARGET_ROOT_POST_PODF_MASK))) |
717 CCM_TARGET_ROOT_PRE_PODF(pre - 1U) | CCM_TARGET_ROOT_POST_PODF(post - 1U);
718}
719
720/*!
721 * brief Update clock root in one step, for dynamical clock switching
722 * Note: The PRE and POST dividers in this function are the actually divider, software will map it to register value
723 *
724 * param ccmRootClk Root control (see ref clock_root_control_t enumeration)
725 * param root mux value (see ref _ccm_rootmux_xxx enumeration)
726 * param pre Pre divider value (0-7, divider=n+1)
727 * param post Post divider value (0-63, divider=n+1)
728 */
729void CLOCK_UpdateRoot(clock_root_control_t ccmRootClk, uint32_t mux, uint32_t pre, uint32_t post)
730{
731 assert((pre <= 8U) && (pre != 0U));
732 assert((post <= 64U) && (post != 0U));
733
734 CCM_REG(ccmRootClk) =
735 (CCM_REG(ccmRootClk) &
736 (~(CCM_TARGET_ROOT_MUX_MASK | CCM_TARGET_ROOT_PRE_PODF_MASK | CCM_TARGET_ROOT_POST_PODF_MASK))) |
737 CCM_TARGET_ROOT_MUX(mux) | CCM_TARGET_ROOT_PRE_PODF(pre - 1U) | CCM_TARGET_ROOT_POST_PODF(post - 1U);
738}
739
740/*!
741 * brief Enable CCGR clock gate and root clock gate for each module
742 * User should set specific gate for each module according to the description
743 * of the table of system clocks, gating and override in CCM chapter of
744 * reference manual. Take care of that one module may need to set more than
745 * one clock gate.
746 *
747 * param ccmGate Gate control for each module (see ref clock_ip_name_t enumeration).
748 */
749void CLOCK_EnableClock(clock_ip_name_t ccmGate)
750{
751 uint32_t ccgr = CCM_TUPLE_CCGR(ccmGate);
752
753 CCM_REG_SET(ccgr) = (uint32_t)kCLOCK_ClockNeededAll;
754#if !(defined(NOT_CONFIG_CLK_ROOT) && NOT_CONFIG_CLK_ROOT)
755 uint32_t rootClk = CCM_TUPLE_ROOT(ccmGate);
756 /* if root clock is 0xFFFFU, then skip enable root clock */
757 if (rootClk != 0xFFFFU)
758 {
759 CCM_REG_SET(rootClk) = CCM_TARGET_ROOT_SET_ENABLE_MASK;
760 }
761#endif
762}
763
764/*!
765 * brief Disable CCGR clock gate for the each module
766 * User should set specific gate for each module according to the description
767 * of the table of system clocks, gating and override in CCM chapter of
768 * reference manual. Take care of that one module may need to set more than
769 * one clock gate.
770 *
771 * param ccmGate Gate control for each module (see ref clock_ip_name_t enumeration).
772 */
773void CLOCK_DisableClock(clock_ip_name_t ccmGate)
774{
775 uint32_t ccgr = CCM_TUPLE_CCGR(ccmGate);
776
777 CCM_REG(ccgr) = (uint32_t)kCLOCK_ClockNotNeeded;
778#if !(defined(NOT_CONFIG_CLK_ROOT) && NOT_CONFIG_CLK_ROOT)
779 uint32_t rootClk = CCM_TUPLE_ROOT(ccmGate);
780 /* if root clock is 0xFFFFU, then skip disable root clock */
781 if (rootClk != 0xFFFFU)
782 {
783 CCM_REG_CLR(rootClk) = CCM_TARGET_ROOT_CLR_ENABLE_MASK;
784 }
785#endif
786}