diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM1/drivers/fsl_clock.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM1/drivers/fsl_clock.c | 792 |
1 files changed, 792 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM1/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM1/drivers/fsl_clock.c new file mode 100644 index 000000000..79e3b833c --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMX8MM1/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 | */ | ||
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_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 | */ | ||
78 | uint32_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 | */ | ||
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_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 | */ | ||
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_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 | */ | ||
338 | void 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 | */ | ||
358 | void 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 | */ | ||
371 | void 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 | */ | ||
391 | void 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 | */ | ||
404 | void 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 | */ | ||
424 | void 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 | */ | ||
435 | void 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 | */ | ||
455 | void 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 | */ | ||
468 | void 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 | */ | ||
488 | void 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 | */ | ||
501 | void 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 | */ | ||
521 | void 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 | */ | ||
534 | void 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 | */ | ||
554 | void 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 | */ | ||
567 | void 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 | */ | ||
609 | uint32_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 | */ | ||
640 | void 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 | */ | ||
682 | uint32_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 | */ | ||
717 | void 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 | */ | ||
735 | void 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 | */ | ||
755 | void 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 | */ | ||
779 | void 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 | } | ||