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