aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM3/drivers/fsl_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM3/drivers/fsl_clock.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM3/drivers/fsl_clock.c792
1 files changed, 792 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM3/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM3/drivers/fsl_clock.c
new file mode 100644
index 000000000..79e3b833c
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM3/drivers/fsl_clock.c
@@ -0,0 +1,792 @@
1/*
2 * Copyright 2018 - 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
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_CoreM4Clk:
52 freq = CLOCK_GetCoreM4Freq();
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 M4 core frequency.
75 *
76 * return Clock frequency; If the clock is invalid, returns 0.
77 */
78uint32_t CLOCK_GetCoreM4Freq(void)
79{
80 uint32_t freq;
81 uint32_t pre = CLOCK_GetRootPreDivider(kCLOCK_RootM4);
82 uint32_t post = CLOCK_GetRootPostDivider(kCLOCK_RootM4);
83
84 switch (CLOCK_GetRootMux(kCLOCK_RootM4))
85 {
86 case (uint32_t)kCLOCK_M4RootmuxOsc24M:
87 freq = OSC24M_CLK_FREQ;
88 break;
89 case (uint32_t)kCLOCK_M4RootmuxSysPll2Div5:
90 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 5U;
91 break;
92 case (uint32_t)kCLOCK_M4RootmuxSysPll2Div4:
93 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll2Ctrl) / 4U;
94 break;
95 case (uint32_t)kCLOCK_M4RootmuxSysPll1Div3:
96 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / 3U;
97 break;
98 case (uint32_t)kCLOCK_M4RootmuxSysPll1:
99 freq = CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl);
100 break;
101 case (uint32_t)kCLOCK_M4RootmuxAudioPll1:
102 freq = CLOCK_GetPllFreq(kCLOCK_AudioPll1Ctrl);
103 break;
104 case (uint32_t)kCLOCK_M4RootmuxVideoPll1:
105 freq = CLOCK_GetPllFreq(kCLOCK_VideoPll1Ctrl);
106 break;
107 case (uint32_t)kCLOCK_M4RootmuxSysPll3:
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_GpuPllCtrl)
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_GpuPllCtrl:
269 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_GpuPLLPwrBypassCtrl);
270 break;
271 case kCLOCK_VpuPllCtrl:
272 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_VpuPllPwrBypassCtrl);
273 break;
274 case kCLOCK_ArmPllCtrl:
275 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_ArmPllPwrBypassCtrl);
276 break;
277 case kCLOCK_SystemPll1Ctrl:
278 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll1InternalPll1BypassCtrl);
279 break;
280 case kCLOCK_SystemPll2Ctrl:
281 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll2InternalPll1BypassCtrl);
282 break;
283 case kCLOCK_SystemPll3Ctrl:
284 intergerPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_SysPll3InternalPll1BypassCtrl);
285 break;
286 /* Fractional PLL frequency */
287 case kCLOCK_AudioPll1Ctrl:
288 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_AudioPll1BypassCtrl);
289 break;
290 case kCLOCK_AudioPll2Ctrl:
291 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_AudioPll2BypassCtrl);
292 break;
293 case kCLOCK_VideoPll1Ctrl:
294 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_VideoPll1BypassCtrl);
295 break;
296 case kCLOCK_DramPllCtrl:
297 fracPllBypass = CLOCK_IsPllBypassed(CCM_ANALOG, kCLOCK_DramPllInternalPll1BypassCtrl);
298 break;
299 default:
300 fracPllBypass = false;
301 break;
302 }
303 if (pll < kCLOCK_GpuPllCtrl)
304 {
305 if (fracPllBypass)
306 {
307 pllFreq = pllRefFreq;
308 }
309 else
310 {
311 pllFreq = CLOCK_GetFracPllFreq(CCM_ANALOG, pll, pllRefFreq);
312 }
313 }
314 else
315 {
316 if (intergerPllBypass)
317 {
318 /* if PLL is bypass, return reference clock directly */
319 pllFreq = pllRefFreq;
320 }
321 else
322 {
323 pllFreq = CLOCK_GetIntegerPllFreq(CCM_ANALOG, pll, pllRefFreq, false);
324 }
325 }
326
327 return pllFreq;
328}
329
330/*!
331 * brief Initializes the ANALOG ARM PLL.
332 *
333 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
334 *
335 * note This function can't detect whether the Arm PLL has been enabled and
336 * used by some IPs.
337 */
338void CLOCK_InitArmPll(const ccm_analog_integer_pll_config_t *config)
339{
340 assert(config != NULL);
341
342 /* Integer PLL configuration */
343 CLOCK_InitIntegerPll(CCM_ANALOG, config, kCLOCK_ArmPllCtrl);
344 /* Disable PLL bypass */
345 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_ArmPllPwrBypassCtrl, false);
346 /* Enable and power up PLL clock. */
347 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_ArmPllClke);
348
349 /* Wait for PLL to be locked. */
350 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_ArmPllCtrl))
351 {
352 }
353}
354
355/*!
356 * brief De-initialize the ARM PLL.
357 */
358void CLOCK_DeinitArmPll(void)
359{
360 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_ArmPllCtrl);
361}
362
363/*!
364 * brief Initializes the ANALOG AUDIO PLL1.
365 *
366 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
367 *
368 * note This function can't detect whether the AUDIO PLL has been enabled and
369 * used by some IPs.
370 */
371void CLOCK_InitAudioPll1(const ccm_analog_frac_pll_config_t *config)
372{
373 assert(config != NULL);
374
375 /* Disable PLL bypass */
376 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_AudioPll1BypassCtrl, false);
377 /* Fractional pll configuration */
378 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_AudioPll1Ctrl);
379 /* Enable and power up PLL clock. */
380 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_AudioPll1Clke);
381
382 /* Wait for PLL to be locked. */
383 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_AudioPll1Ctrl))
384 {
385 }
386}
387
388/*!
389 * brief De-initialize the Audio PLL1.
390 */
391void CLOCK_DeinitAudioPll1(void)
392{
393 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_AudioPll1Ctrl);
394}
395
396/*!
397 * brief Initializes the ANALOG AUDIO PLL2.
398 *
399 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
400 *
401 * note This function can't detect whether the AUDIO PLL has been enabled and
402 * used by some IPs.
403 */
404void CLOCK_InitAudioPll2(const ccm_analog_frac_pll_config_t *config)
405{
406 assert(config != NULL);
407
408 /* Disable PLL bypass */
409 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_AudioPll2BypassCtrl, false);
410 /* Fractional pll configuration */
411 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_AudioPll2Ctrl);
412 /* Enable and power up PLL clock. */
413 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_AudioPll2Clke);
414
415 /* Wait for PLL to be locked. */
416 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_AudioPll2Ctrl))
417 {
418 }
419}
420
421/*!
422 * brief De-initialize the Audio PLL2.
423 */
424void CLOCK_DeinitAudioPll2(void)
425{
426 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_AudioPll2Ctrl);
427}
428
429/*!
430 * brief Initializes the ANALOG VIDEO PLL1.
431 *
432 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
433 *
434 */
435void CLOCK_InitVideoPll1(const ccm_analog_frac_pll_config_t *config)
436{
437 assert(config != NULL);
438
439 /* Disable PLL bypass */
440 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_VideoPll1BypassCtrl, false);
441 /* Fractional pll configuration */
442 CLOCK_InitFracPll(CCM_ANALOG, config, kCLOCK_VideoPll1Ctrl);
443 /* Enable and power up PLL clock. */
444 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_VideoPll1Clke);
445
446 /* Wait for PLL to be locked. */
447 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_VideoPll1Ctrl))
448 {
449 }
450}
451
452/*!
453 * brief De-initialize the Video PLL1.
454 */
455void CLOCK_DeinitVideoPll1(void)
456{
457 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_VideoPll1Ctrl);
458}
459
460/*!
461 * brief Initializes the ANALOG SYS PLL1.
462 *
463 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
464 *
465 * note This function can't detect whether the SYS PLL has been enabled and
466 * used by some IPs.
467 */
468void CLOCK_InitSysPll1(const ccm_analog_integer_pll_config_t *config)
469{
470 assert(config != NULL);
471
472 /* Integer PLL configuration */
473 CLOCK_InitIntegerPll(CCM_ANALOG, config, kCLOCK_SystemPll1Ctrl);
474 /* Disable PLL bypass */
475 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll1InternalPll1BypassCtrl, false);
476 /* Enable and power up PLL clock. */
477 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_SystemPll1Clke);
478
479 /* Wait for PLL to be locked. */
480 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_SystemPll1Ctrl))
481 {
482 }
483}
484
485/*!
486 * brief De-initialize the System PLL1.
487 */
488void CLOCK_DeinitSysPll1(void)
489{
490 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_SystemPll1Ctrl);
491}
492
493/*!
494 * brief Initializes the ANALOG SYS PLL2.
495 *
496 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
497 *
498 * note This function can't detect whether the SYS PLL has been enabled and
499 * used by some IPs.
500 */
501void CLOCK_InitSysPll2(const ccm_analog_integer_pll_config_t *config)
502{
503 assert(config != NULL);
504
505 /* Integer PLL configuration */
506 CLOCK_InitIntegerPll(CCM_ANALOG, config, kCLOCK_SystemPll2Ctrl);
507 /* Disable PLL bypass */
508 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll2InternalPll1BypassCtrl, false);
509 /* Enable and power up PLL clock. */
510 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_SystemPll2Clke);
511
512 /* Wait for PLL to be locked. */
513 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_SystemPll2Ctrl))
514 {
515 }
516}
517
518/*!
519 * brief De-initialize the System PLL2.
520 */
521void CLOCK_DeinitSysPll2(void)
522{
523 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_SystemPll2Ctrl);
524}
525
526/*!
527 * brief Initializes the ANALOG SYS PLL3.
528 *
529 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
530 *
531 * note This function can't detect whether the SYS PLL has been enabled and
532 * used by some IPs.
533 */
534void CLOCK_InitSysPll3(const ccm_analog_integer_pll_config_t *config)
535{
536 assert(config != NULL);
537
538 /* Integer PLL configuration */
539 CLOCK_InitIntegerPll(CCM_ANALOG, config, kCLOCK_SystemPll3Ctrl);
540 /* Disable PLL bypass */
541 CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_SysPll3InternalPll1BypassCtrl, false);
542 /* Enable and power up PLL clock. */
543 CLOCK_EnableAnalogClock(CCM_ANALOG, kCLOCK_SystemPll3Clke);
544
545 /* Wait for PLL to be locked. */
546 while (!CLOCK_IsPllLocked(CCM_ANALOG, kCLOCK_SystemPll3Ctrl))
547 {
548 }
549}
550
551/*!
552 * brief De-initialize the System PLL3.
553 */
554void CLOCK_DeinitSysPll3(void)
555{
556 CLOCK_PowerDownPll(CCM_ANALOG, kCLOCK_SystemPll3Ctrl);
557}
558
559/*!
560 * brief Initializes the ANALOG Fractional PLL.
561 *
562 * param base CCM ANALOG base address.
563 * param config Pointer to the configuration structure(see ref ccm_analog_frac_pll_config_t enumeration).
564 * param type fractional pll type.
565 *
566 */
567void CLOCK_InitFracPll(CCM_ANALOG_Type *base, const ccm_analog_frac_pll_config_t *config, clock_pll_ctrl_t type)
568{
569 assert(config != NULL);
570 assert((config->mainDiv >= 64U) && (config->mainDiv <= 1023U));
571 assert((config->preDiv >= 1U) && (config->preDiv <= 63U));
572 assert(config->postDiv <= 6U);
573
574 assert(type < kCLOCK_GpuPllCtrl);
575
576 uint32_t fracCfg0 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_GNRL_CTL_Offset) &
577 ~((uint32_t)1 << CCM_ANALOG_AUDIO_PLL1_GEN_CTRL_PLL_RST_SHIFT);
578 uint32_t fracCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL0_Offset);
579 uint32_t fracCfg2 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL1_Offset);
580
581 /* power down the fractional PLL first */
582 CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_GNRL_CTL_Offset) = fracCfg0;
583
584 CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL0_Offset) =
585 (fracCfg1 &
586 (~(CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK | CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK |
587 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK))) |
588 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV(config->mainDiv) |
589 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV(config->preDiv) |
590 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV(config->postDiv);
591
592 CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL1_Offset) =
593 (fracCfg2 & (~(CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_MASK))) |
594 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM(config->dsm);
595
596 /* power up the fractional pll */
597 CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_GNRL_CTL_Offset) |= CCM_ANALOG_AUDIO_PLL1_GEN_CTRL_PLL_RST_MASK;
598}
599
600/*!
601 * brief Gets the ANALOG Fractional PLL clock frequency.
602 *
603 * param base CCM_ANALOG base pointer.
604 * param type fractional pll type.
605 * param fractional pll reference clock frequency
606 *
607 * return Clock frequency
608 */
609uint32_t CLOCK_GetFracPllFreq(CCM_ANALOG_Type *base, clock_pll_ctrl_t type, uint32_t refClkFreq)
610{
611 assert(type < kCLOCK_GpuPllCtrl);
612
613 uint32_t fracCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL0_Offset);
614 uint32_t fracCfg2 = CCM_ANALOG_TUPLE_REG_OFF(base, type, FracPLL_FDIV_CTL1_Offset);
615 uint64_t fracClk = 0U;
616
617 uint32_t mainDiv = CCM_BIT_FIELD_EXTRACTION(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK,
618 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_SHIFT);
619 uint8_t preDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK,
620 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_SHIFT);
621 uint8_t postDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK,
622 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_SHIFT);
623 uint32_t dsm = CCM_BIT_FIELD_EXTRACTION(fracCfg2, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_MASK,
624 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_SHIFT);
625
626 fracClk = (uint64_t)((uint64_t)refClkFreq * ((uint64_t)mainDiv * 65536ULL + dsm) /
627 (65536ULL * (uint32_t)preDiv * (1ULL << postDiv)));
628
629 return (uint32_t)fracClk;
630}
631
632/*!
633 * brief Initializes the ANALOG Integer PLL.
634 *
635 * param base CCM ANALOG base address
636 * param config Pointer to the configuration structure(see ref ccm_analog_integer_pll_config_t enumeration).
637 * param type integer pll type
638 *
639 */
640void CLOCK_InitIntegerPll(CCM_ANALOG_Type *base, const ccm_analog_integer_pll_config_t *config, clock_pll_ctrl_t type)
641{
642 assert(config != NULL);
643 assert((config->mainDiv >= 64U) && (config->mainDiv <= 1023U));
644 assert((config->preDiv >= 1U) && (config->preDiv <= 63U));
645 assert(config->postDiv <= 6U);
646
647 assert(type >= kCLOCK_SystemPll1Ctrl);
648
649 uint32_t integerCfg0 = CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_GNRL_CTL_Offset) &
650 ~((uint32_t)1 << CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_RST_SHIFT);
651 uint32_t integerCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_DIV_CTL_Offset);
652
653 /* power down the Integer PLL first */
654 CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_GNRL_CTL_Offset) = integerCfg0;
655
656 /* pll mux configuration */
657 CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_GNRL_CTL_Offset) =
658 (integerCfg0 & (~CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_MASK)) | config->refSel;
659
660 /* divider configuration */
661 CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_DIV_CTL_Offset) =
662 (integerCfg1 &
663 (~(CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK | CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK |
664 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK))) |
665 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV(config->mainDiv) |
666 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV(config->preDiv) |
667 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV(config->postDiv);
668
669 /* power up the Integer PLL */
670 CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_GNRL_CTL_Offset) |= CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_RST_MASK;
671}
672
673/*!
674 * brief Get the ANALOG Integer PLL clock frequency.
675 *
676 * param base CCM ANALOG base address.
677 * param type integer pll type
678 * param pll1Bypass pll1 bypass flag
679 *
680 * return Clock frequency
681 */
682uint32_t CLOCK_GetIntegerPllFreq(CCM_ANALOG_Type *base, clock_pll_ctrl_t type, uint32_t refClkFreq, bool pll1Bypass)
683{
684 assert(type >= kCLOCK_SystemPll1Ctrl);
685
686 uint32_t integerCfg1 = CCM_ANALOG_TUPLE_REG_OFF(base, type, IntegerPLL_DIV_CTL_Offset);
687 uint64_t pllOutClock = 0U;
688
689 uint32_t mainDiv = CCM_BIT_FIELD_EXTRACTION(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK,
690 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_SHIFT);
691 uint8_t preDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK,
692 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_SHIFT);
693 uint8_t postDiv = (uint8_t)CCM_BIT_FIELD_EXTRACTION(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK,
694 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_SHIFT);
695
696 if (pll1Bypass)
697 {
698 pllOutClock = refClkFreq;
699 }
700
701 else
702 {
703 pllOutClock = (uint64_t)refClkFreq * mainDiv / (((uint64_t)(1U) << postDiv) * preDiv);
704 }
705
706 return (uint32_t)pllOutClock;
707}
708
709/*!
710 * brief Set root clock divider
711 * Note: The PRE and POST dividers in this function are the actually divider, software will map it to register value
712 *
713 * param ccmRootClk Root control (see ref clock_root_control_t enumeration)
714 * param pre Pre divider value (1-8)
715 * param post Post divider value (1-64)
716 */
717void CLOCK_SetRootDivider(clock_root_control_t ccmRootClk, uint32_t pre, uint32_t post)
718{
719 assert((pre <= 8U) && (pre != 0U));
720 assert((post <= 64U) && (post != 0U));
721
722 CCM_REG(ccmRootClk) = (CCM_REG(ccmRootClk) & (~(CCM_TARGET_ROOT_PRE_PODF_MASK | CCM_TARGET_ROOT_POST_PODF_MASK))) |
723 CCM_TARGET_ROOT_PRE_PODF(pre - 1U) | CCM_TARGET_ROOT_POST_PODF(post - 1U);
724}
725
726/*!
727 * brief Update clock root in one step, for dynamical clock switching
728 * Note: The PRE and POST dividers in this function are the actually divider, software will map it to register value
729 *
730 * param ccmRootClk Root control (see ref clock_root_control_t enumeration)
731 * param root mux value (see ref _ccm_rootmux_xxx enumeration)
732 * param pre Pre divider value (0-7, divider=n+1)
733 * param post Post divider value (0-63, divider=n+1)
734 */
735void CLOCK_UpdateRoot(clock_root_control_t ccmRootClk, uint32_t mux, uint32_t pre, uint32_t post)
736{
737 assert((pre <= 8U) && (pre != 0U));
738 assert((post <= 64U) && (post != 0U));
739
740 CCM_REG(ccmRootClk) =
741 (CCM_REG(ccmRootClk) &
742 (~(CCM_TARGET_ROOT_MUX_MASK | CCM_TARGET_ROOT_PRE_PODF_MASK | CCM_TARGET_ROOT_POST_PODF_MASK))) |
743 CCM_TARGET_ROOT_MUX(mux) | CCM_TARGET_ROOT_PRE_PODF(pre - 1U) | CCM_TARGET_ROOT_POST_PODF(post - 1U);
744}
745
746/*!
747 * brief Enable CCGR clock gate and root clock gate for each module
748 * User should set specific gate for each module according to the description
749 * of the table of system clocks, gating and override in CCM chapter of
750 * reference manual. Take care of that one module may need to set more than
751 * one clock gate.
752 *
753 * param ccmGate Gate control for each module (see ref clock_ip_name_t enumeration).
754 */
755void CLOCK_EnableClock(clock_ip_name_t ccmGate)
756{
757 uint32_t ccgr = CCM_TUPLE_CCGR(ccmGate);
758
759 CCM_REG_SET(ccgr) = (uint32_t)kCLOCK_ClockNeededAll;
760#if !(defined(NOT_CONFIG_CLK_ROOT) && NOT_CONFIG_CLK_ROOT)
761 uint32_t rootClk = CCM_TUPLE_ROOT(ccmGate);
762 /* if root clock is 0xFFFFU, then skip enable root clock */
763 if (rootClk != 0xFFFFU)
764 {
765 CCM_REG_SET(rootClk) = CCM_TARGET_ROOT_SET_ENABLE_MASK;
766 }
767#endif
768}
769
770/*!
771 * brief Disable CCGR clock gate for the each module
772 * User should set specific gate for each module according to the description
773 * of the table of system clocks, gating and override in CCM chapter of
774 * reference manual. Take care of that one module may need to set more than
775 * one clock gate.
776 *
777 * param ccmGate Gate control for each module (see ref clock_ip_name_t enumeration).
778 */
779void CLOCK_DisableClock(clock_ip_name_t ccmGate)
780{
781 uint32_t ccgr = CCM_TUPLE_CCGR(ccmGate);
782
783 CCM_REG(ccgr) = (uint32_t)kCLOCK_ClockNotNeeded;
784#if !(defined(NOT_CONFIG_CLK_ROOT) && NOT_CONFIG_CLK_ROOT)
785 uint32_t rootClk = CCM_TUPLE_ROOT(ccmGate);
786 /* if root clock is 0xFFFFU, then skip disable root clock */
787 if (rootClk != 0xFFFFU)
788 {
789 CCM_REG_CLR(rootClk) = CCM_TARGET_ROOT_CLR_ENABLE_MASK;
790 }
791#endif
792}