diff options
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.c | 786 |
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 | */ | ||
44 | uint32_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 | */ | ||
78 | uint32_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 | */ | ||
123 | uint32_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 | */ | ||
168 | uint32_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 | */ | ||
215 | uint32_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 | */ | ||
256 | uint32_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 | */ | ||
332 | void 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 | */ | ||
352 | void 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 | */ | ||
365 | void 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 | */ | ||
385 | void 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 | */ | ||
398 | void 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 | */ | ||
418 | void 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 | */ | ||
429 | void 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 | */ | ||
449 | void 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 | */ | ||
462 | void 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 | */ | ||
482 | void 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 | */ | ||
495 | void 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 | */ | ||
515 | void 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 | */ | ||
528 | void 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 | */ | ||
548 | void 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 | */ | ||
561 | void 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 | */ | ||
603 | uint32_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 | */ | ||
634 | void 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 | */ | ||
676 | uint32_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 | */ | ||
711 | void 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 | */ | ||
729 | void 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 | */ | ||
749 | void 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 | */ | ||
773 | void 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 | } | ||