diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/LPC54S018/drivers/fsl_clock.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/devices/LPC54S018/drivers/fsl_clock.c | 2827 |
1 files changed, 2827 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/LPC54S018/drivers/fsl_clock.c b/lib/chibios-contrib/ext/mcux-sdk/devices/LPC54S018/drivers/fsl_clock.c new file mode 100644 index 000000000..a3f6362d2 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/LPC54S018/drivers/fsl_clock.c | |||
@@ -0,0 +1,2827 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, Freescale Semiconductor, Inc. | ||
3 | * Copyright 2016 - 2020 , NXP | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * | ||
7 | * SPDX-License-Identifier: BSD-3-Clause | ||
8 | */ | ||
9 | |||
10 | #include "fsl_clock.h" | ||
11 | #include "fsl_power.h" | ||
12 | /******************************************************************************* | ||
13 | * Definitions | ||
14 | ******************************************************************************/ | ||
15 | /* Component ID definition, used by tools. */ | ||
16 | #ifndef FSL_COMPONENT_ID | ||
17 | #define FSL_COMPONENT_ID "platform.drivers.clock" | ||
18 | #endif | ||
19 | #define NVALMAX (0x100U) | ||
20 | #define PVALMAX (0x20U) | ||
21 | #define MVALMAX (0x8000U) | ||
22 | |||
23 | #define USB_NVALMAX (0x4U) | ||
24 | #define USB_PVALMAX (0x8U) | ||
25 | #define USB_MVALMAX (0x100U) | ||
26 | |||
27 | #define PLL_MAX_N_DIV 0x100U | ||
28 | #define USB_PLL_MAX_N_DIV 0x100U | ||
29 | |||
30 | #define PLL_MDEC_VAL_P (0U) /*!< MDEC is in bits 16 downto 0 */ | ||
31 | #define PLL_MDEC_VAL_M (0x1FFFFUL << PLL_MDEC_VAL_P) /*!< NDEC is in bits 9 downto 0 */ | ||
32 | #define PLL_NDEC_VAL_P (0U) /*!< NDEC is in bits 9:0 */ | ||
33 | #define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P) | ||
34 | #define PLL_PDEC_VAL_P (0U) /*!< PDEC is in bits 6:0 */ | ||
35 | #define PLL_PDEC_VAL_M (0x7FUL << PLL_PDEC_VAL_P) | ||
36 | |||
37 | #define PLL_MIN_CCO_FREQ_MHZ (275000000U) | ||
38 | #define PLL_MAX_CCO_FREQ_MHZ (550000000U) | ||
39 | #define PLL_LOWER_IN_LIMIT (4000U) /*!< Minimum PLL input rate */ | ||
40 | #define PLL_MIN_IN_SSMODE (2000000U) | ||
41 | #define PLL_MAX_IN_SSMODE (4000000U) | ||
42 | |||
43 | /*!< Middle of the range values for spread-spectrum */ | ||
44 | #define PLL_SSCG_MF_FREQ_VALUE 4U | ||
45 | #define PLL_SSCG_MC_COMP_VALUE 2U | ||
46 | #define PLL_SSCG_MR_DEPTH_VALUE 4U | ||
47 | #define PLL_SSCG_DITHER_VALUE 0U | ||
48 | |||
49 | /*!< USB PLL CCO MAX AND MIN FREQ */ | ||
50 | #define USB_PLL_MIN_CCO_FREQ_MHZ (156000000U) | ||
51 | #define USB_PLL_MAX_CCO_FREQ_MHZ (320000000U) | ||
52 | #define USB_PLL_LOWER_IN_LIMIT (1000000U) /*!< Minimum PLL input rate */ | ||
53 | |||
54 | #define USB_PLL_MSEL_VAL_P (0U) /*!< MSEL is in bits 7 downto 0 */ | ||
55 | #define USB_PLL_MSEL_VAL_M (0xFFU) | ||
56 | #define USB_PLL_PSEL_VAL_P (8U) /*!< PDEC is in bits 9:8 */ | ||
57 | #define USB_PLL_PSEL_VAL_M (0x3U) | ||
58 | #define USB_PLL_NSEL_VAL_P (10U) /*!< NDEC is in bits 11:10 */ | ||
59 | #define USB_PLL_NSEL_VAL_M (0x3U) | ||
60 | |||
61 | /*!< SWITCH USB POSTDIVIDER FOR REGITSER WRITING */ | ||
62 | #define SWITCH_USB_PSEL(x) \ | ||
63 | (((x) == 0x0U) ? 0x1U : ((x) == 0x1U) ? 0x02U : ((x) == 0x2U) ? 0x4U : ((x) == 3U) ? 0x8U : 0U) | ||
64 | |||
65 | /*!< SYS PLL NDEC reg */ | ||
66 | #define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M) | ||
67 | /*!< SYS PLL PDEC reg */ | ||
68 | #define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M) | ||
69 | /*!< SYS PLL MDEC reg */ | ||
70 | #define PLL_MDEC_VAL_SET(value) (((unsigned long)(value) << PLL_MDEC_VAL_P) & PLL_MDEC_VAL_M) | ||
71 | |||
72 | /*!< SYS PLL NSEL reg */ | ||
73 | #define USB_PLL_NSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_NSEL_VAL_M) << USB_PLL_NSEL_VAL_P) | ||
74 | /*!< SYS PLL PSEL reg */ | ||
75 | #define USB_PLL_PSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_PSEL_VAL_M) << USB_PLL_PSEL_VAL_P) | ||
76 | /*!< SYS PLL MSEL reg */ | ||
77 | #define USB_PLL_MSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_MSEL_VAL_M) << USB_PLL_MSEL_VAL_P) | ||
78 | |||
79 | /*!< FRAC control */ | ||
80 | #define AUDIO_PLL_FRACT_MD_P (0U) | ||
81 | #define AUDIO_PLL_FRACT_MD_INT_P (15U) | ||
82 | #define AUDIO_PLL_FRACT_MD_M (0x7FFFUL << AUDIO_PLL_FRACT_MD_P) | ||
83 | #define AUDIO_PLL_FRACT_MD_INT_M (0x7FUL << AUDIO_PLL_FRACT_MD_INT_P) | ||
84 | |||
85 | #define AUDIO_PLL_MD_FRACT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_P) & PLL_FRAC_MD_FRACT_M) | ||
86 | #define AUDIO_PLL_MD_INT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_INT_P) & AUDIO_PLL_FRACT_MD_INT_M) | ||
87 | |||
88 | /* Saved value of PLL output rate, computed whenever needed to save run-time | ||
89 | computation on each call to retrive the PLL rate. */ | ||
90 | static uint32_t s_Pll_Freq; | ||
91 | static uint32_t s_Usb_Pll_Freq; | ||
92 | static uint32_t s_Audio_Pll_Freq; | ||
93 | |||
94 | /** External clock rate on the CLKIN pin in Hz. If not used, | ||
95 | set this to 0. Otherwise, set it to the exact rate in Hz this pin is | ||
96 | being driven at. */ | ||
97 | static const uint32_t g_I2S_Mclk_Freq = 0U; | ||
98 | static const uint32_t g_Ext_Clk_Freq = 12000000U; | ||
99 | static const uint32_t g_Lcd_Clk_In_Freq = 0U; | ||
100 | |||
101 | /******************************************************************************* | ||
102 | * Variables | ||
103 | ******************************************************************************/ | ||
104 | |||
105 | /******************************************************************************* | ||
106 | * Prototypes | ||
107 | ******************************************************************************/ | ||
108 | /* Find encoded NDEC value for raw N value, max N = NVALMAX */ | ||
109 | static uint32_t pllEncodeN(uint32_t N); | ||
110 | /* Find decoded N value for raw NDEC value */ | ||
111 | static uint32_t pllDecodeN(uint32_t NDEC); | ||
112 | /* Find encoded PDEC value for raw P value, max P = PVALMAX */ | ||
113 | static uint32_t pllEncodeP(uint32_t P); | ||
114 | /* Find decoded P value for raw PDEC value */ | ||
115 | static uint32_t pllDecodeP(uint32_t PDEC); | ||
116 | /* Find encoded MDEC value for raw M value, max M = MVALMAX */ | ||
117 | static uint32_t pllEncodeM(uint32_t M); | ||
118 | /* Find decoded M value for raw MDEC value */ | ||
119 | static uint32_t pllDecodeM(uint32_t MDEC); | ||
120 | /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */ | ||
121 | static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR); | ||
122 | /* Get predivider (N) from PLL NDEC setting */ | ||
123 | static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg); | ||
124 | /* Get postdivider (P) from PLL PDEC setting */ | ||
125 | static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg); | ||
126 | /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */ | ||
127 | static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg); | ||
128 | /* Convert the binary to fractional part */ | ||
129 | static double Binary2Fractional(uint32_t binaryPart); | ||
130 | /* Calculate the powerTimes' power of 2 */ | ||
131 | static uint32_t power2Cal(uint32_t powerTimes); | ||
132 | /* Get the greatest common divisor */ | ||
133 | static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n); | ||
134 | /* Set PLL output based on desired output rate */ | ||
135 | static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup); | ||
136 | |||
137 | /* Update local PLL rate variable */ | ||
138 | static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup); | ||
139 | static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup); | ||
140 | |||
141 | /*! | ||
142 | * @brief Set fro clock frequency. | ||
143 | * Due to LPC540xx 0A silicon and LPC540xx 1B silicon have different ROM addresses for set fro | ||
144 | * frequency api, so add this api to get rom version. | ||
145 | * @param base romVersion pointer to recieve rom version. | ||
146 | */ | ||
147 | #if defined(FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) && \ | ||
148 | (FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) | ||
149 | static uint32_t CLOCK_GetRomVersion(uint8_t *romVersion); | ||
150 | #endif | ||
151 | |||
152 | static const uint8_t wdtFreqLookup[32] = {0, 8, 12, 15, 18, 20, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41, | ||
153 | 42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 59, 60, 61}; | ||
154 | /******************************************************************************* | ||
155 | * Code | ||
156 | ******************************************************************************/ | ||
157 | #if defined(FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) && \ | ||
158 | (FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) | ||
159 | static uint32_t CLOCK_GetRomVersion(uint8_t *romVersion) | ||
160 | { | ||
161 | uint32_t command[5] = {0U}, result[4] = {0U}; | ||
162 | |||
163 | command[0] = 55U; | ||
164 | result[0] = 0; | ||
165 | result[1] = 0; | ||
166 | ((void (*)(uint32_t cmd[5], uint32_t stat[4]))FSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION)(command, result); | ||
167 | |||
168 | *romVersion = (uint8_t)(result[1]); | ||
169 | |||
170 | return result[0]; | ||
171 | } | ||
172 | #endif | ||
173 | |||
174 | /** | ||
175 | * brief | ||
176 | * Initialize the Core clock to given frequency (12, 48 or 96 MHz), this API is implememnt in ROM code. | ||
177 | * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed | ||
178 | * output is enabled. | ||
179 | * Usage: CLOCK_SetupFROClocking(frequency), (frequency must be one of 12, 48 or 96 MHz) | ||
180 | * Note: Need to make sure ROM and OTP has power(PDRUNCFG0[17,29]= 0U) before calling this API since this API is | ||
181 | * implemented in ROM code and the FROHF TRIM value is stored in OTP | ||
182 | * | ||
183 | * param froFreq target fro frequency. | ||
184 | * return Nothing | ||
185 | */ | ||
186 | |||
187 | void CLOCK_SetupFROClocking(uint32_t froFreq) | ||
188 | { | ||
189 | uint32_t froRomAddr = 0U; | ||
190 | #if defined(FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) && \ | ||
191 | (FSL_FROHF_SETTING_API_ADDRESS_DETERMINE_BY_ROM_VERSION) | ||
192 | uint8_t romVersion = 0U; | ||
193 | |||
194 | if (CLOCK_GetRomVersion(&romVersion) == (uint32_t)kStatus_Success) | ||
195 | { | ||
196 | if (romVersion == FSL_ROM_VERSION_1B) | ||
197 | { | ||
198 | froRomAddr = FSL_ROM_VERSION_1B_FRO_SETTING_ADDR; | ||
199 | } | ||
200 | else | ||
201 | { | ||
202 | froRomAddr = FSL_ROM_VERSION_0A_FRO_SETTING_ADDR; | ||
203 | } | ||
204 | |||
205 | (*((void (*)(uint32_t funcname))(froRomAddr)))(froFreq); | ||
206 | } | ||
207 | #else | ||
208 | froRomAddr = FSL_ROM_VERSION_0A_FRO_SETTING_ADDR; | ||
209 | |||
210 | (*((void (*)(uint32_t))(froRomAddr)))(froFreq); | ||
211 | #endif | ||
212 | } | ||
213 | |||
214 | /* Clock Selection for IP */ | ||
215 | /** | ||
216 | * brief Configure the clock selection muxes. | ||
217 | * param connection : Clock to be configured. | ||
218 | * return Nothing | ||
219 | */ | ||
220 | void CLOCK_AttachClk(clock_attach_id_t connection) | ||
221 | { | ||
222 | uint8_t mux; | ||
223 | uint8_t sel; | ||
224 | uint16_t item; | ||
225 | uint32_t tmp32 = (uint32_t)connection; | ||
226 | uint32_t i; | ||
227 | volatile uint32_t *pClkSel; | ||
228 | |||
229 | pClkSel = &(SYSCON->STICKCLKSEL); | ||
230 | |||
231 | if (kNONE_to_NONE != connection) | ||
232 | { | ||
233 | for (i = 0U; i < 2U; i++) | ||
234 | { | ||
235 | if (tmp32 == 0U) | ||
236 | { | ||
237 | break; | ||
238 | } | ||
239 | item = (uint16_t)GET_ID_ITEM(tmp32); | ||
240 | if (item != 0UL) | ||
241 | { | ||
242 | mux = GET_ID_ITEM_MUX(item); | ||
243 | sel = GET_ID_ITEM_SEL(item); | ||
244 | if (mux == CM_ASYNCAPB) | ||
245 | { | ||
246 | SYSCON->ASYNCAPBCTRL = SYSCON_ASYNCAPBCTRL_ENABLE(1); | ||
247 | ASYNC_SYSCON->ASYNCAPBCLKSELA = sel; | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | ((volatile uint32_t *)pClkSel)[mux] = sel; | ||
252 | } | ||
253 | } | ||
254 | tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */ | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | |||
259 | /* Return the actual clock attach id */ | ||
260 | /** | ||
261 | * brief Get the actual clock attach id. | ||
262 | * This fuction uses the offset in input attach id, then it reads the actual source value in | ||
263 | * the register and combine the offset to obtain an actual attach id. | ||
264 | * param attachId : Clock attach id to get. | ||
265 | * return Clock source value. | ||
266 | */ | ||
267 | clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId) | ||
268 | { | ||
269 | uint8_t mux; | ||
270 | uint8_t actualSel; | ||
271 | uint32_t tmp32 = (uint32_t)attachId; | ||
272 | uint32_t i; | ||
273 | uint32_t actualAttachId = 0U; | ||
274 | uint32_t selector = GET_ID_SELECTOR(tmp32); | ||
275 | volatile uint32_t *pClkSel; | ||
276 | |||
277 | pClkSel = &(SYSCON->STICKCLKSEL); | ||
278 | |||
279 | if (kNONE_to_NONE == attachId) | ||
280 | { | ||
281 | return kNONE_to_NONE; | ||
282 | } | ||
283 | |||
284 | for (i = 0U; i < 2U; i++) | ||
285 | { | ||
286 | mux = GET_ID_ITEM_MUX(tmp32); | ||
287 | if (tmp32 != 0UL) | ||
288 | { | ||
289 | if (mux == CM_ASYNCAPB) | ||
290 | { | ||
291 | actualSel = (uint8_t)(ASYNC_SYSCON->ASYNCAPBCLKSELA); | ||
292 | } | ||
293 | else | ||
294 | { | ||
295 | actualSel = (uint8_t)(((volatile uint32_t *)pClkSel)[mux]); | ||
296 | } | ||
297 | |||
298 | /* Consider the combination of two registers */ | ||
299 | actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i); | ||
300 | } | ||
301 | tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */ | ||
302 | } | ||
303 | |||
304 | actualAttachId |= selector; | ||
305 | |||
306 | return (clock_attach_id_t)actualAttachId; | ||
307 | } | ||
308 | |||
309 | /* Set IP Clock Divider */ | ||
310 | /** | ||
311 | * brief Setup peripheral clock dividers. | ||
312 | * param div_name : Clock divider name | ||
313 | * param divided_by_value: Value to be divided | ||
314 | * param reset : Whether to reset the divider counter. | ||
315 | * return Nothing | ||
316 | */ | ||
317 | void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset) | ||
318 | { | ||
319 | volatile uint32_t *pClkDiv; | ||
320 | |||
321 | pClkDiv = &(SYSCON->SYSTICKCLKDIV); | ||
322 | if (reset) | ||
323 | { | ||
324 | ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 29U; | ||
325 | } | ||
326 | if (divided_by_value == 0U) /*!< halt */ | ||
327 | { | ||
328 | ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 30U; | ||
329 | } | ||
330 | else | ||
331 | { | ||
332 | ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = (divided_by_value - 1U); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | /* Get CLOCK OUT Clk */ | ||
337 | /*! brief Return Frequency of ClockOut | ||
338 | * return Frequency of ClockOut | ||
339 | */ | ||
340 | uint32_t CLOCK_GetClockOutClkFreq(void) | ||
341 | { | ||
342 | uint32_t freq = 0U; | ||
343 | |||
344 | switch (SYSCON->CLKOUTSELA) | ||
345 | { | ||
346 | case 0U: | ||
347 | freq = CLOCK_GetCoreSysClkFreq(); | ||
348 | break; | ||
349 | |||
350 | case 1U: | ||
351 | freq = CLOCK_GetExtClkFreq(); | ||
352 | break; | ||
353 | |||
354 | case 2U: | ||
355 | freq = CLOCK_GetWdtOscFreq(); | ||
356 | break; | ||
357 | |||
358 | case 3U: | ||
359 | freq = CLOCK_GetFroHfFreq(); | ||
360 | break; | ||
361 | |||
362 | case 4U: | ||
363 | freq = CLOCK_GetPllOutFreq(); | ||
364 | break; | ||
365 | |||
366 | case 5U: | ||
367 | freq = CLOCK_GetUsbPllOutFreq(); | ||
368 | break; | ||
369 | |||
370 | case 6U: | ||
371 | freq = CLOCK_GetAudioPllOutFreq(); | ||
372 | break; | ||
373 | |||
374 | case 7U: | ||
375 | freq = CLOCK_GetOsc32KFreq(); | ||
376 | break; | ||
377 | |||
378 | default: | ||
379 | freq = 0U; | ||
380 | break; | ||
381 | } | ||
382 | return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U); | ||
383 | } | ||
384 | |||
385 | /* Get SPIFI Clk */ | ||
386 | /*! brief Return Frequency of Spifi Clock | ||
387 | * return Frequency of Spifi. | ||
388 | */ | ||
389 | uint32_t CLOCK_GetSpifiClkFreq(void) | ||
390 | { | ||
391 | uint32_t freq = 0U; | ||
392 | |||
393 | switch (SYSCON->SPIFICLKSEL) | ||
394 | { | ||
395 | case 0U: | ||
396 | freq = CLOCK_GetCoreSysClkFreq(); | ||
397 | break; | ||
398 | case 1U: | ||
399 | freq = CLOCK_GetPllOutFreq(); | ||
400 | break; | ||
401 | case 2U: | ||
402 | freq = CLOCK_GetUsbPllOutFreq(); | ||
403 | break; | ||
404 | case 3U: | ||
405 | freq = CLOCK_GetFroHfFreq(); | ||
406 | break; | ||
407 | case 4U: | ||
408 | freq = CLOCK_GetAudioPllOutFreq(); | ||
409 | break; | ||
410 | case 7U: | ||
411 | freq = 0U; | ||
412 | break; | ||
413 | default: | ||
414 | freq = 0U; | ||
415 | break; | ||
416 | } | ||
417 | |||
418 | return freq / ((SYSCON->SPIFICLKDIV & 0xffU) + 1U); | ||
419 | } | ||
420 | |||
421 | /* Get ADC Clk */ | ||
422 | /*! brief Return Frequency of Adc Clock | ||
423 | * return Frequency of Adc Clock. | ||
424 | */ | ||
425 | uint32_t CLOCK_GetAdcClkFreq(void) | ||
426 | { | ||
427 | uint32_t freq = 0U; | ||
428 | |||
429 | switch (SYSCON->ADCCLKSEL) | ||
430 | { | ||
431 | case 0U: | ||
432 | freq = CLOCK_GetFroHfFreq(); | ||
433 | break; | ||
434 | case 1U: | ||
435 | freq = CLOCK_GetPllOutFreq(); | ||
436 | break; | ||
437 | case 2U: | ||
438 | freq = CLOCK_GetUsbPllOutFreq(); | ||
439 | break; | ||
440 | case 3U: | ||
441 | freq = CLOCK_GetAudioPllOutFreq(); | ||
442 | break; | ||
443 | case 7U: | ||
444 | freq = 0U; | ||
445 | break; | ||
446 | default: | ||
447 | freq = 0U; | ||
448 | break; | ||
449 | } | ||
450 | |||
451 | return freq / ((SYSCON->ADCCLKDIV & 0xffU) + 1U); | ||
452 | } | ||
453 | |||
454 | /* Get USB0 Clk */ | ||
455 | /*! brief Return Frequency of Usb0 Clock | ||
456 | * return Frequency of Usb0 Clock. | ||
457 | */ | ||
458 | uint32_t CLOCK_GetUsb0ClkFreq(void) | ||
459 | { | ||
460 | uint32_t freq = 0U; | ||
461 | |||
462 | switch (SYSCON->USB0CLKSEL) | ||
463 | { | ||
464 | case 0U: | ||
465 | freq = CLOCK_GetFroHfFreq(); | ||
466 | break; | ||
467 | case 1U: | ||
468 | freq = CLOCK_GetPllOutFreq(); | ||
469 | break; | ||
470 | case 2U: | ||
471 | freq = CLOCK_GetUsbPllOutFreq(); | ||
472 | break; | ||
473 | case 7U: | ||
474 | freq = 0U; | ||
475 | break; | ||
476 | |||
477 | default: | ||
478 | freq = 0U; | ||
479 | break; | ||
480 | } | ||
481 | |||
482 | return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U); | ||
483 | } | ||
484 | |||
485 | /* Get USB1 Clk */ | ||
486 | /*! brief Return Frequency of Usb1 Clock | ||
487 | * return Frequency of Usb1 Clock. | ||
488 | */ | ||
489 | uint32_t CLOCK_GetUsb1ClkFreq(void) | ||
490 | { | ||
491 | uint32_t freq = 0U; | ||
492 | |||
493 | switch (SYSCON->USB1CLKSEL) | ||
494 | { | ||
495 | case 0U: | ||
496 | freq = CLOCK_GetCoreSysClkFreq(); | ||
497 | break; | ||
498 | case 1U: | ||
499 | freq = CLOCK_GetPllOutFreq(); | ||
500 | break; | ||
501 | case 2U: | ||
502 | freq = CLOCK_GetUsbPllOutFreq(); | ||
503 | break; | ||
504 | case 7U: | ||
505 | freq = 0U; | ||
506 | break; | ||
507 | |||
508 | default: | ||
509 | freq = 0U; | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | return freq / ((SYSCON->USB1CLKDIV & 0xffU) + 1U); | ||
514 | } | ||
515 | |||
516 | /* Get MCLK Clk */ | ||
517 | /*! brief Return Frequency of MClk Clock | ||
518 | * return Frequency of MClk Clock. | ||
519 | */ | ||
520 | uint32_t CLOCK_GetMclkClkFreq(void) | ||
521 | { | ||
522 | uint32_t freq = 0U; | ||
523 | |||
524 | switch (SYSCON->MCLKCLKSEL) | ||
525 | { | ||
526 | case 0U: | ||
527 | freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffu) + 1U); | ||
528 | break; | ||
529 | case 1U: | ||
530 | freq = CLOCK_GetAudioPllOutFreq(); | ||
531 | break; | ||
532 | case 7U: | ||
533 | freq = 0U; | ||
534 | break; | ||
535 | |||
536 | default: | ||
537 | freq = 0U; | ||
538 | break; | ||
539 | } | ||
540 | |||
541 | return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U); | ||
542 | } | ||
543 | |||
544 | /* Get SCTIMER Clk */ | ||
545 | /*! brief Return Frequency of SCTimer Clock | ||
546 | * return Frequency of SCTimer Clock. | ||
547 | */ | ||
548 | uint32_t CLOCK_GetSctClkFreq(void) | ||
549 | { | ||
550 | uint32_t freq = 0U; | ||
551 | |||
552 | switch (SYSCON->SCTCLKSEL) | ||
553 | { | ||
554 | case 0U: | ||
555 | freq = CLOCK_GetCoreSysClkFreq(); | ||
556 | break; | ||
557 | case 1U: | ||
558 | freq = CLOCK_GetPllOutFreq(); | ||
559 | break; | ||
560 | case 2U: | ||
561 | freq = CLOCK_GetFroHfFreq(); | ||
562 | break; | ||
563 | case 3U: | ||
564 | freq = CLOCK_GetAudioPllOutFreq(); | ||
565 | break; | ||
566 | case 7U: | ||
567 | freq = 0U; | ||
568 | break; | ||
569 | |||
570 | default: | ||
571 | freq = 0U; | ||
572 | break; | ||
573 | } | ||
574 | |||
575 | return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U); | ||
576 | } | ||
577 | |||
578 | /* Get SDIO Clk */ | ||
579 | /*! brief Return Frequency of SDIO Clock | ||
580 | * return Frequency of SDIO Clock. | ||
581 | */ | ||
582 | uint32_t CLOCK_GetSdioClkFreq(void) | ||
583 | { | ||
584 | uint32_t freq = 0U; | ||
585 | |||
586 | switch (SYSCON->SDIOCLKSEL) | ||
587 | { | ||
588 | case 0U: | ||
589 | freq = CLOCK_GetCoreSysClkFreq(); | ||
590 | break; | ||
591 | case 1U: | ||
592 | freq = CLOCK_GetPllOutFreq(); | ||
593 | break; | ||
594 | case 2U: | ||
595 | freq = CLOCK_GetUsbPllOutFreq(); | ||
596 | break; | ||
597 | case 3U: | ||
598 | freq = CLOCK_GetFroHfFreq(); | ||
599 | break; | ||
600 | case 4U: | ||
601 | freq = CLOCK_GetAudioPllOutFreq(); | ||
602 | break; | ||
603 | case 7U: | ||
604 | freq = 0U; | ||
605 | break; | ||
606 | default: | ||
607 | freq = 0U; | ||
608 | break; | ||
609 | } | ||
610 | |||
611 | return freq / ((SYSCON->SDIOCLKDIV & 0xffU) + 1U); | ||
612 | } | ||
613 | |||
614 | /* Get LCD Clk */ | ||
615 | /*! brief Return Frequency of LCD Clock | ||
616 | * return Frequency of LCD Clock. | ||
617 | */ | ||
618 | uint32_t CLOCK_GetLcdClkFreq(void) | ||
619 | { | ||
620 | uint32_t freq = 0U; | ||
621 | |||
622 | switch (SYSCON->LCDCLKSEL) | ||
623 | { | ||
624 | case 0U: | ||
625 | freq = CLOCK_GetCoreSysClkFreq(); | ||
626 | break; | ||
627 | case 1U: | ||
628 | freq = CLOCK_GetLcdClkIn(); | ||
629 | break; | ||
630 | case 2U: | ||
631 | freq = CLOCK_GetFroHfFreq(); | ||
632 | break; | ||
633 | case 3U: | ||
634 | freq = 0U; | ||
635 | break; | ||
636 | |||
637 | default: | ||
638 | freq = 0U; | ||
639 | break; | ||
640 | } | ||
641 | |||
642 | return freq / ((SYSCON->LCDCLKDIV & 0xffU) + 1U); | ||
643 | } | ||
644 | |||
645 | /* Get LCD CLK IN Clk */ | ||
646 | /*! brief Return Frequency of LCD CLKIN Clock | ||
647 | * return Frequency of LCD CLKIN Clock. | ||
648 | */ | ||
649 | uint32_t CLOCK_GetLcdClkIn(void) | ||
650 | { | ||
651 | return g_Lcd_Clk_In_Freq; | ||
652 | } | ||
653 | |||
654 | /* Get FRO 12M Clk */ | ||
655 | /*! brief Return Frequency of FRO 12MHz | ||
656 | * return Frequency of FRO 12MHz | ||
657 | */ | ||
658 | uint32_t CLOCK_GetFro12MFreq(void) | ||
659 | { | ||
660 | return ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ? 0U : 12000000U; | ||
661 | } | ||
662 | |||
663 | /* Get EXT OSC Clk */ | ||
664 | /*! brief Return Frequency of External Clock | ||
665 | * return Frequency of External Clock. If no external clock is used returns 0. | ||
666 | */ | ||
667 | uint32_t CLOCK_GetExtClkFreq(void) | ||
668 | { | ||
669 | return g_Ext_Clk_Freq; | ||
670 | } | ||
671 | |||
672 | /* Get WATCH DOG Clk */ | ||
673 | /*! brief Return Frequency of Watchdog Oscillator | ||
674 | * return Frequency of Watchdog Oscillator | ||
675 | */ | ||
676 | uint32_t CLOCK_GetWdtOscFreq(void) | ||
677 | { | ||
678 | uint8_t freq_sel, div_sel; | ||
679 | if ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_WDT_OSC_MASK) != 0UL) | ||
680 | { | ||
681 | return 0U; | ||
682 | } | ||
683 | else | ||
684 | { | ||
685 | div_sel = (uint8_t)(((SYSCON->WDTOSCCTRL & 0x1fU) + 1U) << 1U); | ||
686 | freq_sel = | ||
687 | wdtFreqLookup[((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_FREQSEL_MASK) >> SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)]; | ||
688 | return ((uint32_t)freq_sel * 50000U) / ((uint32_t)div_sel); | ||
689 | } | ||
690 | } | ||
691 | |||
692 | /* Get HF FRO Clk */ | ||
693 | /*! brief Return Frequency of High-Freq output of FRO | ||
694 | * return Frequency of High-Freq output of FRO | ||
695 | */ | ||
696 | uint32_t CLOCK_GetFroHfFreq(void) | ||
697 | { | ||
698 | if (((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) || | ||
699 | (0UL == (SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK))) | ||
700 | { | ||
701 | return 0U; | ||
702 | } | ||
703 | |||
704 | if ((SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK) != 0UL) | ||
705 | { | ||
706 | return 96000000U; | ||
707 | } | ||
708 | else | ||
709 | { | ||
710 | return 48000000U; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | /* Get SYSTEM PLL Clk */ | ||
715 | /*! brief Return Frequency of PLL | ||
716 | * return Frequency of PLL | ||
717 | */ | ||
718 | uint32_t CLOCK_GetPllOutFreq(void) | ||
719 | { | ||
720 | return s_Pll_Freq; | ||
721 | } | ||
722 | |||
723 | /* Get AUDIO PLL Clk */ | ||
724 | /*! brief Return Frequency of AUDIO PLL | ||
725 | * return Frequency of PLL | ||
726 | */ | ||
727 | uint32_t CLOCK_GetAudioPllOutFreq(void) | ||
728 | { | ||
729 | return s_Audio_Pll_Freq; | ||
730 | } | ||
731 | |||
732 | /* Get USB PLL Clk */ | ||
733 | /*! brief Return Frequency of USB PLL | ||
734 | * return Frequency of PLL | ||
735 | */ | ||
736 | uint32_t CLOCK_GetUsbPllOutFreq(void) | ||
737 | { | ||
738 | return s_Usb_Pll_Freq; | ||
739 | } | ||
740 | |||
741 | /* Get RTC OSC Clk */ | ||
742 | /*! brief Return Frequency of 32kHz osc | ||
743 | * return Frequency of 32kHz osc | ||
744 | */ | ||
745 | uint32_t CLOCK_GetOsc32KFreq(void) | ||
746 | { | ||
747 | return CLK_RTC_32K_CLK; /* Needs to be corrected to check that RTC Clock is enabled */ | ||
748 | } | ||
749 | |||
750 | /* Get MAIN Clk */ | ||
751 | /*! brief Return Frequency of Core System | ||
752 | * return Frequency of Core System | ||
753 | */ | ||
754 | uint32_t CLOCK_GetCoreSysClkFreq(void) | ||
755 | { | ||
756 | uint32_t freq = 0U; | ||
757 | |||
758 | switch (SYSCON->MAINCLKSELB) | ||
759 | { | ||
760 | case 0U: | ||
761 | if (SYSCON->MAINCLKSELA == 0U) | ||
762 | { | ||
763 | freq = CLOCK_GetFro12MFreq(); | ||
764 | } | ||
765 | else if (SYSCON->MAINCLKSELA == 1U) | ||
766 | { | ||
767 | freq = CLOCK_GetExtClkFreq(); | ||
768 | } | ||
769 | else if (SYSCON->MAINCLKSELA == 2U) | ||
770 | { | ||
771 | freq = CLOCK_GetWdtOscFreq(); | ||
772 | } | ||
773 | else if (SYSCON->MAINCLKSELA == 3U) | ||
774 | { | ||
775 | freq = CLOCK_GetFroHfFreq(); | ||
776 | } | ||
777 | else | ||
778 | { | ||
779 | /* Add comment to prevent the case of rule 15.7. */ | ||
780 | } | ||
781 | break; | ||
782 | case 2U: | ||
783 | freq = CLOCK_GetPllOutFreq(); | ||
784 | break; | ||
785 | |||
786 | case 3U: | ||
787 | freq = CLOCK_GetOsc32KFreq(); | ||
788 | break; | ||
789 | |||
790 | default: | ||
791 | freq = 0U; | ||
792 | break; | ||
793 | } | ||
794 | |||
795 | return freq; | ||
796 | } | ||
797 | |||
798 | /* Get I2S MCLK Clk */ | ||
799 | /*! brief Return Frequency of I2S MCLK Clock | ||
800 | * return Frequency of I2S MCLK Clock | ||
801 | */ | ||
802 | uint32_t CLOCK_GetI2SMClkFreq(void) | ||
803 | { | ||
804 | return g_I2S_Mclk_Freq; | ||
805 | } | ||
806 | |||
807 | /* Get ASYNC APB Clk */ | ||
808 | /*! brief Return Frequency of Asynchronous APB Clock | ||
809 | * return Frequency of Asynchronous APB Clock Clock | ||
810 | */ | ||
811 | uint32_t CLOCK_GetAsyncApbClkFreq(void) | ||
812 | { | ||
813 | async_clock_src_t clkSrc; | ||
814 | uint32_t clkRate; | ||
815 | |||
816 | clkSrc = CLOCK_GetAsyncApbClkSrc(); | ||
817 | |||
818 | switch (clkSrc) | ||
819 | { | ||
820 | case kCLOCK_AsyncMainClk: | ||
821 | clkRate = CLOCK_GetCoreSysClkFreq(); | ||
822 | break; | ||
823 | case kCLOCK_AsyncFro12Mhz: | ||
824 | clkRate = CLK_FRO_12MHZ; | ||
825 | break; | ||
826 | default: | ||
827 | clkRate = 0U; | ||
828 | break; | ||
829 | } | ||
830 | |||
831 | return clkRate; | ||
832 | } | ||
833 | |||
834 | /* Get MCAN Clk */ | ||
835 | /*! brief Return Frequency of MCAN Clock | ||
836 | * param MCanSel : 0U: MCAN0; 1U: MCAN1 | ||
837 | * return Frequency of MCAN Clock | ||
838 | */ | ||
839 | uint32_t CLOCK_GetMCanClkFreq(uint32_t MCanSel) | ||
840 | { | ||
841 | uint32_t freq = 0U; | ||
842 | switch (MCanSel) | ||
843 | { | ||
844 | case 0U: | ||
845 | freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN0CLKDIV & 0xffU) + 1U); | ||
846 | break; | ||
847 | case 1U: | ||
848 | freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN1CLKDIV & 0xffU) + 1U); | ||
849 | break; | ||
850 | |||
851 | default: | ||
852 | freq = 0U; | ||
853 | break; | ||
854 | } | ||
855 | |||
856 | return freq; | ||
857 | } | ||
858 | |||
859 | /* Get FLEXCOMM Clk */ | ||
860 | /*! brief Return Frequency of Flexcomm functional Clock | ||
861 | * return Frequency of Flexcomm functional Clock | ||
862 | */ | ||
863 | uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id) | ||
864 | { | ||
865 | uint32_t freq = 0U; | ||
866 | |||
867 | if (id != 10U) | ||
868 | { | ||
869 | switch (SYSCON->FCLKSEL[id]) | ||
870 | { | ||
871 | case 0U: | ||
872 | freq = CLOCK_GetFro12MFreq(); | ||
873 | break; | ||
874 | case 1U: | ||
875 | freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffu) + 1U); | ||
876 | break; | ||
877 | case 2U: | ||
878 | freq = CLOCK_GetAudioPllOutFreq(); | ||
879 | break; | ||
880 | case 3U: | ||
881 | freq = CLOCK_GetI2SMClkFreq(); | ||
882 | break; | ||
883 | case 4U: | ||
884 | freq = CLOCK_GetFrgClkFreq(); | ||
885 | break; | ||
886 | |||
887 | default: | ||
888 | freq = 0U; | ||
889 | break; | ||
890 | } | ||
891 | } | ||
892 | else | ||
893 | { | ||
894 | switch (SYSCON->FCLKSEL10) | ||
895 | { | ||
896 | case 0U: | ||
897 | freq = CLOCK_GetCoreSysClkFreq(); | ||
898 | break; | ||
899 | case 1U: | ||
900 | freq = CLOCK_GetPllOutFreq(); | ||
901 | break; | ||
902 | case 2U: | ||
903 | freq = CLOCK_GetUsbPllOutFreq(); | ||
904 | break; | ||
905 | case 3U: | ||
906 | freq = CLOCK_GetFroHfFreq(); | ||
907 | break; | ||
908 | case 4U: | ||
909 | freq = CLOCK_GetAudioPllOutFreq(); | ||
910 | break; | ||
911 | default: | ||
912 | freq = 0U; | ||
913 | break; | ||
914 | } | ||
915 | } | ||
916 | |||
917 | return freq; | ||
918 | } | ||
919 | |||
920 | /* Get FRG Clk */ | ||
921 | uint32_t CLOCK_GetFRGInputClock(void) | ||
922 | { | ||
923 | uint32_t freq = 0U; | ||
924 | |||
925 | switch (SYSCON->FRGCLKSEL) | ||
926 | { | ||
927 | case 0U: | ||
928 | freq = CLOCK_GetCoreSysClkFreq(); | ||
929 | break; | ||
930 | case 1U: | ||
931 | freq = CLOCK_GetPllOutFreq(); | ||
932 | break; | ||
933 | case 2U: | ||
934 | freq = CLOCK_GetFro12MFreq(); | ||
935 | break; | ||
936 | case 3U: | ||
937 | freq = CLOCK_GetFroHfFreq(); | ||
938 | break; | ||
939 | |||
940 | default: | ||
941 | freq = 0U; | ||
942 | break; | ||
943 | } | ||
944 | |||
945 | return freq; | ||
946 | } | ||
947 | |||
948 | /* Get FRG Clk */ | ||
949 | /*! brief Return Frequency of frg | ||
950 | * return Frequency of FRG | ||
951 | */ | ||
952 | uint32_t CLOCK_GetFrgClkFreq(void) | ||
953 | { | ||
954 | uint32_t freq = 0U; | ||
955 | |||
956 | if ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK) | ||
957 | { | ||
958 | freq = (uint32_t)(((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1U)) / | ||
959 | ((SYSCON_FRGCTRL_DIV_MASK + 1U) + | ||
960 | ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT))); | ||
961 | } | ||
962 | else | ||
963 | { | ||
964 | freq = 0U; | ||
965 | } | ||
966 | |||
967 | return freq; | ||
968 | } | ||
969 | |||
970 | /* Get FRG Clk */ | ||
971 | /*! brief Return Frequency of dmic | ||
972 | * return Frequency of DMIC | ||
973 | */ | ||
974 | uint32_t CLOCK_GetDmicClkFreq(void) | ||
975 | { | ||
976 | uint32_t freq = 0U; | ||
977 | |||
978 | switch (SYSCON->DMICCLKSEL) | ||
979 | { | ||
980 | case 0U: | ||
981 | freq = CLOCK_GetFro12MFreq(); | ||
982 | break; | ||
983 | case 1U: | ||
984 | freq = CLOCK_GetFroHfFreq(); | ||
985 | break; | ||
986 | case 2U: | ||
987 | freq = CLOCK_GetPllOutFreq(); | ||
988 | break; | ||
989 | case 3U: | ||
990 | freq = CLOCK_GetI2SMClkFreq(); | ||
991 | break; | ||
992 | case 4U: | ||
993 | freq = CLOCK_GetCoreSysClkFreq(); | ||
994 | break; | ||
995 | case 5U: | ||
996 | freq = CLOCK_GetWdtOscFreq(); | ||
997 | break; | ||
998 | default: | ||
999 | freq = 0U; | ||
1000 | break; | ||
1001 | } | ||
1002 | |||
1003 | return freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U); | ||
1004 | ; | ||
1005 | } | ||
1006 | |||
1007 | /* Set FRG Clk */ | ||
1008 | uint32_t CLOCK_SetFRGClock(uint32_t freq) | ||
1009 | { | ||
1010 | assert(0UL != freq); | ||
1011 | |||
1012 | uint32_t input = CLOCK_GetFRGInputClock(); | ||
1013 | uint32_t mul; | ||
1014 | |||
1015 | if ((freq > 48000000U) || (freq > input) || (input / freq >= 2U)) | ||
1016 | { | ||
1017 | /* FRG output frequency should be less than equal to 48MHz */ | ||
1018 | return 0U; | ||
1019 | } | ||
1020 | else | ||
1021 | { | ||
1022 | mul = (uint32_t)((((uint64_t)input - freq) * 256U) / ((uint64_t)freq)); | ||
1023 | SYSCON->FRGCTRL = (mul << SYSCON_FRGCTRL_MULT_SHIFT) | SYSCON_FRGCTRL_DIV_MASK; | ||
1024 | return 1U; | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | /* Set IP Clk */ | ||
1029 | /*! brief Return Frequency of selected clock | ||
1030 | * return Frequency of selected clock | ||
1031 | */ | ||
1032 | uint32_t CLOCK_GetFreq(clock_name_t clockName) | ||
1033 | { | ||
1034 | uint32_t freq; | ||
1035 | switch (clockName) | ||
1036 | { | ||
1037 | case kCLOCK_CoreSysClk: | ||
1038 | freq = CLOCK_GetCoreSysClkFreq(); | ||
1039 | break; | ||
1040 | case kCLOCK_BusClk: | ||
1041 | freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U); | ||
1042 | break; | ||
1043 | case kCLOCK_ClockOut: | ||
1044 | freq = CLOCK_GetClockOutClkFreq(); | ||
1045 | break; | ||
1046 | case kCLOCK_Mclk: | ||
1047 | freq = CLOCK_GetMclkClkFreq(); | ||
1048 | break; | ||
1049 | case kCLOCK_FroHf: | ||
1050 | freq = CLOCK_GetFroHfFreq(); | ||
1051 | break; | ||
1052 | case kCLOCK_Fro12M: | ||
1053 | freq = CLOCK_GetFro12MFreq(); | ||
1054 | break; | ||
1055 | case kCLOCK_ExtClk: | ||
1056 | freq = CLOCK_GetExtClkFreq(); | ||
1057 | break; | ||
1058 | case kCLOCK_PllOut: | ||
1059 | freq = CLOCK_GetPllOutFreq(); | ||
1060 | break; | ||
1061 | case kCLOCK_WdtOsc: | ||
1062 | freq = CLOCK_GetWdtOscFreq(); | ||
1063 | break; | ||
1064 | case kCLOCK_Frg: | ||
1065 | freq = CLOCK_GetFrgClkFreq(); | ||
1066 | break; | ||
1067 | |||
1068 | case kCLOCK_AsyncApbClk: | ||
1069 | freq = CLOCK_GetAsyncApbClkFreq(); | ||
1070 | break; | ||
1071 | default: | ||
1072 | freq = 0U; | ||
1073 | break; | ||
1074 | } | ||
1075 | |||
1076 | return freq; | ||
1077 | } | ||
1078 | |||
1079 | /* Find encoded NDEC value for raw N value, max N = NVALMAX */ | ||
1080 | static uint32_t pllEncodeN(uint32_t N) | ||
1081 | { | ||
1082 | uint32_t x, i; | ||
1083 | |||
1084 | /* Find NDec */ | ||
1085 | switch (N) | ||
1086 | { | ||
1087 | case 0U: | ||
1088 | x = 0x3FFU; | ||
1089 | break; | ||
1090 | |||
1091 | case 1U: | ||
1092 | x = 0x302U; | ||
1093 | break; | ||
1094 | |||
1095 | case 2U: | ||
1096 | x = 0x202U; | ||
1097 | break; | ||
1098 | |||
1099 | default: | ||
1100 | x = 0x080U; | ||
1101 | for (i = N; i <= NVALMAX; i++) | ||
1102 | { | ||
1103 | x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU); | ||
1104 | } | ||
1105 | break; | ||
1106 | } | ||
1107 | |||
1108 | return x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P); | ||
1109 | } | ||
1110 | |||
1111 | /* Find decoded N value for raw NDEC value */ | ||
1112 | static uint32_t pllDecodeN(uint32_t NDEC) | ||
1113 | { | ||
1114 | uint32_t n, x, i; | ||
1115 | |||
1116 | /* Find NDec */ | ||
1117 | switch (NDEC) | ||
1118 | { | ||
1119 | case 0x3FFU: | ||
1120 | n = 0U; | ||
1121 | break; | ||
1122 | |||
1123 | case 0x302U: | ||
1124 | n = 1U; | ||
1125 | break; | ||
1126 | |||
1127 | case 0x202U: | ||
1128 | n = 2U; | ||
1129 | break; | ||
1130 | |||
1131 | default: | ||
1132 | x = 0x080U; | ||
1133 | n = 0xFFFFFFFFU; | ||
1134 | for (i = NVALMAX; i >= 3U; i--) | ||
1135 | { | ||
1136 | x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU); | ||
1137 | if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC) | ||
1138 | { | ||
1139 | /* Decoded value of NDEC */ | ||
1140 | n = i; | ||
1141 | break; | ||
1142 | } | ||
1143 | } | ||
1144 | break; | ||
1145 | } | ||
1146 | |||
1147 | return n; | ||
1148 | } | ||
1149 | |||
1150 | /* Find encoded PDEC value for raw P value, max P = PVALMAX */ | ||
1151 | static uint32_t pllEncodeP(uint32_t P) | ||
1152 | { | ||
1153 | uint32_t x, i; | ||
1154 | |||
1155 | /* Find PDec */ | ||
1156 | switch (P) | ||
1157 | { | ||
1158 | case 0U: | ||
1159 | x = 0x7FU; | ||
1160 | break; | ||
1161 | |||
1162 | case 1U: | ||
1163 | x = 0x62U; | ||
1164 | break; | ||
1165 | |||
1166 | case 2U: | ||
1167 | x = 0x42U; | ||
1168 | break; | ||
1169 | |||
1170 | default: | ||
1171 | x = 0x10U; | ||
1172 | for (i = P; i <= PVALMAX; i++) | ||
1173 | { | ||
1174 | x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU); | ||
1175 | } | ||
1176 | break; | ||
1177 | } | ||
1178 | |||
1179 | return x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P); | ||
1180 | } | ||
1181 | |||
1182 | /* Find decoded P value for raw PDEC value */ | ||
1183 | static uint32_t pllDecodeP(uint32_t PDEC) | ||
1184 | { | ||
1185 | uint32_t p, x, i; | ||
1186 | |||
1187 | /* Find PDec */ | ||
1188 | switch (PDEC) | ||
1189 | { | ||
1190 | case 0x7FU: | ||
1191 | p = 0U; | ||
1192 | break; | ||
1193 | |||
1194 | case 0x62U: | ||
1195 | p = 1U; | ||
1196 | break; | ||
1197 | |||
1198 | case 0x42U: | ||
1199 | p = 2U; | ||
1200 | break; | ||
1201 | |||
1202 | default: | ||
1203 | x = 0x10U; | ||
1204 | p = 0xFFFFFFFFU; | ||
1205 | for (i = PVALMAX; i >= 3U; i--) | ||
1206 | { | ||
1207 | x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU); | ||
1208 | if ((x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P)) == PDEC) | ||
1209 | { | ||
1210 | /* Decoded value of PDEC */ | ||
1211 | p = i; | ||
1212 | break; | ||
1213 | } | ||
1214 | } | ||
1215 | break; | ||
1216 | } | ||
1217 | |||
1218 | return p; | ||
1219 | } | ||
1220 | |||
1221 | /* Find encoded MDEC value for raw M value, max M = MVALMAX */ | ||
1222 | static uint32_t pllEncodeM(uint32_t M) | ||
1223 | { | ||
1224 | uint32_t i, x; | ||
1225 | |||
1226 | /* Find MDec */ | ||
1227 | switch (M) | ||
1228 | { | ||
1229 | case 0U: | ||
1230 | x = 0x1FFFFU; | ||
1231 | break; | ||
1232 | |||
1233 | case 1U: | ||
1234 | x = 0x18003U; | ||
1235 | break; | ||
1236 | |||
1237 | case 2U: | ||
1238 | x = 0x10003U; | ||
1239 | break; | ||
1240 | |||
1241 | default: | ||
1242 | x = 0x04000U; | ||
1243 | for (i = M; i <= MVALMAX; i++) | ||
1244 | { | ||
1245 | x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU); | ||
1246 | } | ||
1247 | break; | ||
1248 | } | ||
1249 | |||
1250 | return x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P); | ||
1251 | } | ||
1252 | |||
1253 | /* Find decoded M value for raw MDEC value */ | ||
1254 | static uint32_t pllDecodeM(uint32_t MDEC) | ||
1255 | { | ||
1256 | uint32_t m, i, x; | ||
1257 | |||
1258 | /* Find MDec */ | ||
1259 | switch (MDEC) | ||
1260 | { | ||
1261 | case 0x1FFFFU: | ||
1262 | m = 0U; | ||
1263 | break; | ||
1264 | |||
1265 | case 0x18003U: | ||
1266 | m = 1U; | ||
1267 | break; | ||
1268 | |||
1269 | case 0x10003U: | ||
1270 | m = 2U; | ||
1271 | break; | ||
1272 | |||
1273 | default: | ||
1274 | x = 0x04000U; | ||
1275 | m = 0xFFFFFFFFU; | ||
1276 | for (i = MVALMAX; i >= 3U; i--) | ||
1277 | { | ||
1278 | x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU); | ||
1279 | if ((x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P)) == MDEC) | ||
1280 | { | ||
1281 | /* Decoded value of MDEC */ | ||
1282 | m = i; | ||
1283 | break; | ||
1284 | } | ||
1285 | } | ||
1286 | break; | ||
1287 | } | ||
1288 | |||
1289 | return m; | ||
1290 | } | ||
1291 | |||
1292 | /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */ | ||
1293 | static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR) | ||
1294 | { | ||
1295 | /* bandwidth: compute selP from Multiplier */ | ||
1296 | if (M < 60U) | ||
1297 | { | ||
1298 | *pSelP = (M >> 1U) + 1U; | ||
1299 | } | ||
1300 | else | ||
1301 | { | ||
1302 | *pSelP = PVALMAX - 1U; | ||
1303 | } | ||
1304 | |||
1305 | /* bandwidth: compute selI from Multiplier */ | ||
1306 | if (M > 16384U) | ||
1307 | { | ||
1308 | *pSelI = 1U; | ||
1309 | } | ||
1310 | else if (M > 8192U) | ||
1311 | { | ||
1312 | *pSelI = 2U; | ||
1313 | } | ||
1314 | else if (M > 2048U) | ||
1315 | { | ||
1316 | *pSelI = 4U; | ||
1317 | } | ||
1318 | else if (M >= 501U) | ||
1319 | { | ||
1320 | *pSelI = 8U; | ||
1321 | } | ||
1322 | else if (M >= 60U) | ||
1323 | { | ||
1324 | *pSelI = 4U * (1024U / (M + 9U)); | ||
1325 | } | ||
1326 | else | ||
1327 | { | ||
1328 | *pSelI = (M & 0x3CU) + 4U; | ||
1329 | } | ||
1330 | |||
1331 | if (*pSelI > ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT)) | ||
1332 | { | ||
1333 | *pSelI = ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT); | ||
1334 | } | ||
1335 | |||
1336 | *pSelR = 0U; | ||
1337 | } | ||
1338 | |||
1339 | /* Get predivider (N) from PLL NDEC setting */ | ||
1340 | static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg) | ||
1341 | { | ||
1342 | uint32_t preDiv = 1; | ||
1343 | |||
1344 | /* Direct input is not used? */ | ||
1345 | if ((ctrlReg & (1UL << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT)) == 0U) | ||
1346 | { | ||
1347 | /* Decode NDEC value to get (N) pre divider */ | ||
1348 | preDiv = pllDecodeN(nDecReg & 0x3FFU); | ||
1349 | if (preDiv == 0U) | ||
1350 | { | ||
1351 | preDiv = 1U; | ||
1352 | } | ||
1353 | } | ||
1354 | |||
1355 | /* Adjusted by 1, directi is used to bypass */ | ||
1356 | return preDiv; | ||
1357 | } | ||
1358 | |||
1359 | /* Get postdivider (P) from PLL PDEC setting */ | ||
1360 | static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg) | ||
1361 | { | ||
1362 | uint32_t postDiv = 1U; | ||
1363 | |||
1364 | /* Direct input is not used? */ | ||
1365 | if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0U) | ||
1366 | { | ||
1367 | /* Decode PDEC value to get (P) post divider */ | ||
1368 | postDiv = 2U * pllDecodeP(pDecReg & 0x7FU); | ||
1369 | if (postDiv == 0U) | ||
1370 | { | ||
1371 | postDiv = 2U; | ||
1372 | } | ||
1373 | } | ||
1374 | |||
1375 | /* Adjusted by 1, directo is used to bypass */ | ||
1376 | return postDiv; | ||
1377 | } | ||
1378 | |||
1379 | /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */ | ||
1380 | static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg) | ||
1381 | { | ||
1382 | uint32_t mMult = 1U; | ||
1383 | |||
1384 | /* Decode MDEC value to get (M) multiplier */ | ||
1385 | mMult = pllDecodeM(mDecReg & 0x1FFFFU); | ||
1386 | |||
1387 | if (mMult == 0U) | ||
1388 | { | ||
1389 | mMult = 1U; | ||
1390 | } | ||
1391 | |||
1392 | return mMult; | ||
1393 | } | ||
1394 | |||
1395 | /* Calculate the powerTimes' power of 2 */ | ||
1396 | static uint32_t power2Cal(uint32_t powerTimes) | ||
1397 | { | ||
1398 | uint32_t ret = 1U; | ||
1399 | uint32_t i; | ||
1400 | for (i = 0; i < powerTimes; i++) | ||
1401 | { | ||
1402 | ret *= 2U; | ||
1403 | } | ||
1404 | |||
1405 | return ret; | ||
1406 | } | ||
1407 | |||
1408 | /* Convert the binary to fractional part */ | ||
1409 | static double Binary2Fractional(uint32_t binaryPart) | ||
1410 | { | ||
1411 | double fractional = 0.0; | ||
1412 | for (uint32_t i = 0U; i <= 14U; i++) | ||
1413 | { | ||
1414 | fractional += (double)(uint32_t)((binaryPart >> i) & 0x1U) / (double)(uint32_t)power2Cal(15U - i); | ||
1415 | } | ||
1416 | return fractional; | ||
1417 | } | ||
1418 | |||
1419 | /* Find greatest common divisor between m and n */ | ||
1420 | static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n) | ||
1421 | { | ||
1422 | uint32_t tmp32; | ||
1423 | |||
1424 | while (n != 0U) | ||
1425 | { | ||
1426 | tmp32 = n; | ||
1427 | n = m % n; | ||
1428 | m = tmp32; | ||
1429 | } | ||
1430 | |||
1431 | return m; | ||
1432 | } | ||
1433 | |||
1434 | /* | ||
1435 | * Set PLL output based on desired output rate. | ||
1436 | * In this function, the it calculates the PLL setting for output frequency from input clock | ||
1437 | * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently. | ||
1438 | * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function. | ||
1439 | */ | ||
1440 | static pll_error_t CLOCK_GetPllConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup) | ||
1441 | { | ||
1442 | uint32_t nDivOutHz, fccoHz, multFccoDiv; | ||
1443 | uint32_t pllPreDivider, pllMultiplier, pllPostDivider; | ||
1444 | uint32_t pllDirectInput, pllDirectOutput; | ||
1445 | uint32_t pllSelP, pllSelI, pllSelR, uplimoff; | ||
1446 | |||
1447 | /* Baseline parameters (no input or output dividers) */ | ||
1448 | pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */ | ||
1449 | pllPostDivider = 0U; /* 0 implies post-divider will be disabled */ | ||
1450 | pllDirectOutput = 1U; | ||
1451 | multFccoDiv = 2U; | ||
1452 | |||
1453 | /* Verify output rate parameter */ | ||
1454 | if (foutHz > PLL_MAX_CCO_FREQ_MHZ) | ||
1455 | { | ||
1456 | /* Maximum PLL output with post divider=1 cannot go above this frequency */ | ||
1457 | return kStatus_PLL_OutputTooHigh; | ||
1458 | } | ||
1459 | if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U))) | ||
1460 | { | ||
1461 | /* Minmum PLL output with maximum post divider cannot go below this frequency */ | ||
1462 | return kStatus_PLL_OutputTooLow; | ||
1463 | } | ||
1464 | |||
1465 | /* Verify input rate parameter */ | ||
1466 | if (finHz < PLL_LOWER_IN_LIMIT) | ||
1467 | { | ||
1468 | /* Input clock into the PLL cannot be lower than this */ | ||
1469 | return kStatus_PLL_InputTooLow; | ||
1470 | } | ||
1471 | |||
1472 | /* Find the optimal CCO frequency for the output and input that | ||
1473 | will keep it inside the PLL CCO range. This may require | ||
1474 | tweaking the post-divider for the PLL. */ | ||
1475 | fccoHz = foutHz; | ||
1476 | while (fccoHz < PLL_MIN_CCO_FREQ_MHZ) | ||
1477 | { | ||
1478 | /* CCO output is less than minimum CCO range, so the CCO output | ||
1479 | needs to be bumped up and the post-divider is used to bring | ||
1480 | the PLL output back down. */ | ||
1481 | pllPostDivider++; | ||
1482 | if (pllPostDivider > PVALMAX) | ||
1483 | { | ||
1484 | return kStatus_PLL_OutsideIntLimit; | ||
1485 | } | ||
1486 | |||
1487 | /* Target CCO goes up, PLL output goes down */ | ||
1488 | fccoHz = foutHz * (pllPostDivider * 2U); | ||
1489 | pllDirectOutput = 0U; | ||
1490 | } | ||
1491 | |||
1492 | /* Determine if a pre-divider is needed to get the best frequency */ | ||
1493 | if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz)) | ||
1494 | { | ||
1495 | uint32_t a = FindGreatestCommonDivisor(fccoHz, (multFccoDiv * finHz)); | ||
1496 | |||
1497 | if (a > 20000U) | ||
1498 | { | ||
1499 | a = (multFccoDiv * finHz) / a; | ||
1500 | if ((a != 0U) && (a < PLL_MAX_N_DIV)) | ||
1501 | { | ||
1502 | pllPreDivider = a; | ||
1503 | } | ||
1504 | } | ||
1505 | } | ||
1506 | |||
1507 | /* Bypass pre-divider hardware if pre-divider is 1 */ | ||
1508 | if (pllPreDivider > 1U) | ||
1509 | { | ||
1510 | pllDirectInput = 0U; | ||
1511 | } | ||
1512 | else | ||
1513 | { | ||
1514 | pllDirectInput = 1U; | ||
1515 | } | ||
1516 | |||
1517 | /* Determine PLL multipler */ | ||
1518 | nDivOutHz = (finHz / pllPreDivider); | ||
1519 | pllMultiplier = (fccoHz / nDivOutHz) / multFccoDiv; | ||
1520 | |||
1521 | /* Find optimal values for filter */ | ||
1522 | /* Will bumping up M by 1 get us closer to the desired CCO frequency? */ | ||
1523 | if ((nDivOutHz * ((multFccoDiv * pllMultiplier * 2U) + 1U)) < (fccoHz * 2U)) | ||
1524 | { | ||
1525 | pllMultiplier++; | ||
1526 | } | ||
1527 | |||
1528 | /* Setup filtering */ | ||
1529 | pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR); | ||
1530 | uplimoff = 0U; | ||
1531 | |||
1532 | /* Get encoded value for M (mult) and use manual filter, disable SS mode */ | ||
1533 | pSetup->pllmdec = PLL_MDEC_VAL_SET(pllEncodeM(pllMultiplier)); | ||
1534 | |||
1535 | /* Get encoded values for N (prediv) and P (postdiv) */ | ||
1536 | pSetup->pllndec = PLL_NDEC_VAL_SET(pllEncodeN(pllPreDivider)); | ||
1537 | pSetup->pllpdec = PLL_PDEC_VAL_SET(pllEncodeP(pllPostDivider)); | ||
1538 | |||
1539 | /* PLL control */ | ||
1540 | pSetup->pllctrl = (pllSelR << SYSCON_SYSPLLCTRL_SELR_SHIFT) | /* Filter coefficient */ | ||
1541 | (pllSelI << SYSCON_SYSPLLCTRL_SELI_SHIFT) | /* Filter coefficient */ | ||
1542 | (pllSelP << SYSCON_SYSPLLCTRL_SELP_SHIFT) | /* Filter coefficient */ | ||
1543 | (0UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT) | /* PLL bypass mode disabled */ | ||
1544 | (uplimoff << SYSCON_SYSPLLCTRL_UPLIMOFF_SHIFT) | /* SS/fractional mode disabled */ | ||
1545 | (pllDirectInput << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT) | /* Bypass pre-divider? */ | ||
1546 | (pllDirectOutput << SYSCON_SYSPLLCTRL_DIRECTO_SHIFT); /* Bypass post-divider? */ | ||
1547 | |||
1548 | return kStatus_PLL_Success; | ||
1549 | } | ||
1550 | |||
1551 | #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) | ||
1552 | /* Alloct the static buffer for cache. */ | ||
1553 | static pll_setup_t gPllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]; | ||
1554 | static uint32_t gFinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0}; | ||
1555 | static uint32_t gFoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0}; | ||
1556 | static uint32_t gPllSetupCacheIdx = 0U; | ||
1557 | #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */ | ||
1558 | |||
1559 | /* | ||
1560 | * Calculate the PLL setting values from input clock freq to output freq. | ||
1561 | */ | ||
1562 | static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup) | ||
1563 | { | ||
1564 | pll_error_t retErr; | ||
1565 | #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) | ||
1566 | uint32_t i; | ||
1567 | |||
1568 | for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++) | ||
1569 | { | ||
1570 | if ((finHz == gFinHzCache[i]) && (foutHz == gFoutHzCache[i])) | ||
1571 | { | ||
1572 | /* Hit the target in cache buffer. */ | ||
1573 | pSetup->pllctrl = gPllSetupCacheStruct[i].pllctrl; | ||
1574 | pSetup->pllndec = gPllSetupCacheStruct[i].pllndec; | ||
1575 | pSetup->pllpdec = gPllSetupCacheStruct[i].pllpdec; | ||
1576 | pSetup->pllmdec = gPllSetupCacheStruct[i].pllmdec; | ||
1577 | retErr = kStatus_PLL_Success; | ||
1578 | break; | ||
1579 | } | ||
1580 | } | ||
1581 | |||
1582 | if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) | ||
1583 | { | ||
1584 | return retErr; | ||
1585 | } | ||
1586 | #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */ | ||
1587 | |||
1588 | /* No cache or did not hit the cache. */ | ||
1589 | retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup); | ||
1590 | |||
1591 | #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) | ||
1592 | if (kStatus_PLL_Success == retErr) | ||
1593 | { | ||
1594 | /* Cache the most recent calulation result into buffer. */ | ||
1595 | gFinHzCache[gPllSetupCacheIdx] = finHz; | ||
1596 | gFoutHzCache[gPllSetupCacheIdx] = foutHz; | ||
1597 | |||
1598 | gPllSetupCacheStruct[gPllSetupCacheIdx].pllctrl = pSetup->pllctrl; | ||
1599 | gPllSetupCacheStruct[gPllSetupCacheIdx].pllndec = pSetup->pllndec; | ||
1600 | gPllSetupCacheStruct[gPllSetupCacheIdx].pllpdec = pSetup->pllpdec; | ||
1601 | gPllSetupCacheStruct[gPllSetupCacheIdx].pllmdec = pSetup->pllmdec; | ||
1602 | /* Update the index for next available buffer. */ | ||
1603 | gPllSetupCacheIdx = (gPllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; | ||
1604 | } | ||
1605 | #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */ | ||
1606 | |||
1607 | return retErr; | ||
1608 | } | ||
1609 | |||
1610 | /* Update SYSTEM PLL rate variable */ | ||
1611 | static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup) | ||
1612 | { | ||
1613 | s_Pll_Freq = CLOCK_GetSystemPLLOutFromSetup(pSetup); | ||
1614 | } | ||
1615 | |||
1616 | /* Update AUDIO PLL rate variable */ | ||
1617 | static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup) | ||
1618 | { | ||
1619 | s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromSetup(pSetup); | ||
1620 | } | ||
1621 | |||
1622 | /* Update AUDIO Fractional PLL rate variable */ | ||
1623 | static void CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t *pSetup) | ||
1624 | { | ||
1625 | s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromFractSetup(pSetup); | ||
1626 | } | ||
1627 | |||
1628 | /* Update USB PLL rate variable */ | ||
1629 | static void CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t *pSetup) | ||
1630 | { | ||
1631 | s_Usb_Pll_Freq = CLOCK_GetUsbPLLOutFromSetup(pSetup); | ||
1632 | } | ||
1633 | |||
1634 | /* Return System PLL input clock rate */ | ||
1635 | /*! brief Return System PLL input clock rate | ||
1636 | * return System PLL input clock rate | ||
1637 | */ | ||
1638 | uint32_t CLOCK_GetSystemPLLInClockRate(void) | ||
1639 | { | ||
1640 | uint32_t clkRate = 0U; | ||
1641 | |||
1642 | switch ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK)) | ||
1643 | { | ||
1644 | case 0x00U: | ||
1645 | clkRate = CLK_FRO_12MHZ; | ||
1646 | break; | ||
1647 | |||
1648 | case 0x01U: | ||
1649 | clkRate = CLOCK_GetExtClkFreq(); | ||
1650 | break; | ||
1651 | |||
1652 | case 0x02U: | ||
1653 | clkRate = CLOCK_GetWdtOscFreq(); | ||
1654 | break; | ||
1655 | |||
1656 | case 0x03U: | ||
1657 | clkRate = CLOCK_GetOsc32KFreq(); | ||
1658 | break; | ||
1659 | |||
1660 | default: | ||
1661 | clkRate = 0U; | ||
1662 | break; | ||
1663 | } | ||
1664 | |||
1665 | return clkRate; | ||
1666 | } | ||
1667 | |||
1668 | /* Return Audio PLL input clock rate */ | ||
1669 | /*! brief Return Audio PLL input clock rate | ||
1670 | * return Audio PLL input clock rate | ||
1671 | */ | ||
1672 | uint32_t CLOCK_GetAudioPLLInClockRate(void) | ||
1673 | { | ||
1674 | uint32_t clkRate = 0U; | ||
1675 | |||
1676 | switch ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK)) | ||
1677 | { | ||
1678 | case 0x00U: | ||
1679 | clkRate = CLK_FRO_12MHZ; | ||
1680 | break; | ||
1681 | |||
1682 | case 0x01U: | ||
1683 | clkRate = CLOCK_GetExtClkFreq(); | ||
1684 | break; | ||
1685 | |||
1686 | default: | ||
1687 | clkRate = 0U; | ||
1688 | break; | ||
1689 | } | ||
1690 | |||
1691 | return clkRate; | ||
1692 | } | ||
1693 | |||
1694 | /* Return System PLL output clock rate from setup structure */ | ||
1695 | /*! brief Return System PLL output clock rate from setup structure | ||
1696 | * param pSetup : Pointer to a PLL setup structure | ||
1697 | * return System PLL output clock rate the setup structure will generate | ||
1698 | */ | ||
1699 | uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup) | ||
1700 | { | ||
1701 | uint32_t prediv, postdiv, mMult, inPllRate; | ||
1702 | uint64_t workRate; | ||
1703 | |||
1704 | inPllRate = CLOCK_GetSystemPLLInClockRate(); | ||
1705 | /* If the PLL is bypassed, PLL would not be used and the output of PLL module would just be the input clock*/ | ||
1706 | if ((pSetup->pllctrl & (SYSCON_SYSPLLCTRL_BYPASS_MASK)) == 0U) | ||
1707 | { | ||
1708 | /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */ | ||
1709 | /* | ||
1710 | * 1. Pre-divider | ||
1711 | * Pre-divider is only available when the DIRECTI is disabled. | ||
1712 | */ | ||
1713 | if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTI_MASK)) | ||
1714 | { | ||
1715 | prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec); | ||
1716 | } | ||
1717 | else | ||
1718 | { | ||
1719 | prediv = 1U; /* The pre-divider is bypassed. */ | ||
1720 | } | ||
1721 | /* | ||
1722 | * 2. Post-divider | ||
1723 | * Post-divider is only available when the DIRECTO is disabled. | ||
1724 | */ | ||
1725 | if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTO_MASK)) | ||
1726 | { | ||
1727 | postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec); | ||
1728 | } | ||
1729 | else | ||
1730 | { | ||
1731 | postdiv = 1U; /* The post-divider is bypassed. */ | ||
1732 | } | ||
1733 | /* Adjust input clock */ | ||
1734 | inPllRate = inPllRate / prediv; | ||
1735 | |||
1736 | /* MDEC used for rate */ | ||
1737 | mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec); | ||
1738 | workRate = (uint64_t)inPllRate * (uint64_t)mMult; | ||
1739 | |||
1740 | workRate = workRate / ((uint64_t)postdiv); | ||
1741 | workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/ | ||
1742 | } | ||
1743 | else | ||
1744 | { | ||
1745 | /* In bypass mode */ | ||
1746 | workRate = (uint64_t)inPllRate; | ||
1747 | } | ||
1748 | |||
1749 | return (uint32_t)workRate; | ||
1750 | } | ||
1751 | |||
1752 | /* Return Usb PLL output clock rate from setup structure */ | ||
1753 | /*! brief Return System USB PLL output clock rate from setup structure | ||
1754 | * param pSetup : Pointer to a PLL setup structure | ||
1755 | * return System PLL output clock rate the setup structure will generate | ||
1756 | */ | ||
1757 | uint32_t CLOCK_GetUsbPLLOutFromSetup(const usb_pll_setup_t *pSetup) | ||
1758 | { | ||
1759 | uint32_t nsel, psel, msel, inPllRate; | ||
1760 | uint64_t workRate; | ||
1761 | inPllRate = CLOCK_GetExtClkFreq(); | ||
1762 | msel = pSetup->msel; | ||
1763 | psel = pSetup->psel; | ||
1764 | nsel = pSetup->nsel; | ||
1765 | |||
1766 | /* Make sure the PSEL is correct. */ | ||
1767 | if (0U == SWITCH_USB_PSEL(psel)) | ||
1768 | { | ||
1769 | return 0UL; | ||
1770 | } | ||
1771 | |||
1772 | if (pSetup->fbsel) | ||
1773 | { | ||
1774 | /*integer_mode: Fout = M*(Fin/N), Fcco = 2*P*M*(Fin/N) */ | ||
1775 | workRate = ((uint64_t)inPllRate) * ((uint64_t)msel + 1U) / ((uint64_t)nsel + 1U); | ||
1776 | } | ||
1777 | else | ||
1778 | { | ||
1779 | /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */ | ||
1780 | workRate = ((uint64_t)inPllRate / ((uint64_t)nsel + 1U)) * (msel + 1U) / (2U * SWITCH_USB_PSEL(psel)); | ||
1781 | } | ||
1782 | |||
1783 | return (uint32_t)workRate; | ||
1784 | } | ||
1785 | |||
1786 | /* Return Audio PLL output clock rate from setup structure */ | ||
1787 | /*! brief Return System AUDIO PLL output clock rate from setup structure | ||
1788 | * param pSetup : Pointer to a PLL setup structure | ||
1789 | * return System PLL output clock rate the setup structure will generate | ||
1790 | */ | ||
1791 | uint32_t CLOCK_GetAudioPLLOutFromSetup(pll_setup_t *pSetup) | ||
1792 | { | ||
1793 | uint32_t prediv, postdiv, mMult, inPllRate; | ||
1794 | uint64_t workRate; | ||
1795 | |||
1796 | inPllRate = CLOCK_GetAudioPLLInClockRate(); | ||
1797 | if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U) | ||
1798 | { | ||
1799 | /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */ | ||
1800 | /* | ||
1801 | * 1. Pre-divider | ||
1802 | * Pre-divider is only available when the DIRECTI is disabled. | ||
1803 | */ | ||
1804 | if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK)) | ||
1805 | { | ||
1806 | prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec); | ||
1807 | } | ||
1808 | else | ||
1809 | { | ||
1810 | prediv = 1U; /* The pre-divider is bypassed. */ | ||
1811 | } | ||
1812 | /* | ||
1813 | * 2. Post-divider | ||
1814 | * Post-divider is only available when the DIRECTO is disabled. | ||
1815 | */ | ||
1816 | if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK)) | ||
1817 | { | ||
1818 | postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec); | ||
1819 | } | ||
1820 | else | ||
1821 | { | ||
1822 | postdiv = 1U; /* The post-divider is bypassed. */ | ||
1823 | } | ||
1824 | /* Adjust input clock */ | ||
1825 | inPllRate = inPllRate / prediv; | ||
1826 | |||
1827 | /* MDEC used for rate */ | ||
1828 | mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec); | ||
1829 | workRate = (uint64_t)inPllRate * (uint64_t)mMult; | ||
1830 | |||
1831 | workRate = workRate / ((uint64_t)postdiv); | ||
1832 | workRate = workRate * 2U; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/ | ||
1833 | } | ||
1834 | else | ||
1835 | { | ||
1836 | /* In bypass mode */ | ||
1837 | workRate = (uint64_t)inPllRate; | ||
1838 | } | ||
1839 | |||
1840 | return (uint32_t)workRate; | ||
1841 | } | ||
1842 | |||
1843 | /* Return Audio PLL output clock rate from audio fractioanl setup structure */ | ||
1844 | /*! brief Return System AUDIO PLL output clock rate from audio fractioanl setup structure | ||
1845 | * param pSetup : Pointer to a PLL setup structure | ||
1846 | * return System PLL output clock rate the setup structure will generate | ||
1847 | */ | ||
1848 | uint32_t CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t *pSetup) | ||
1849 | { | ||
1850 | uint32_t prediv, postdiv, inPllRate; | ||
1851 | double workRate, mMultFactional; | ||
1852 | |||
1853 | inPllRate = CLOCK_GetAudioPLLInClockRate(); | ||
1854 | if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U) | ||
1855 | { | ||
1856 | /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */ | ||
1857 | /* | ||
1858 | * 1. Pre-divider | ||
1859 | * Pre-divider is only available when the DIRECTI is disabled. | ||
1860 | */ | ||
1861 | if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK)) | ||
1862 | { | ||
1863 | prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec); | ||
1864 | } | ||
1865 | else | ||
1866 | { | ||
1867 | prediv = 1U; /* The pre-divider is bypassed. */ | ||
1868 | } | ||
1869 | /* | ||
1870 | * 2. Post-divider | ||
1871 | * Post-divider is only available when the DIRECTO is disabled. | ||
1872 | */ | ||
1873 | if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK)) | ||
1874 | { | ||
1875 | postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec); | ||
1876 | } | ||
1877 | else | ||
1878 | { | ||
1879 | postdiv = 1U; /* The post-divider is bypassed. */ | ||
1880 | } | ||
1881 | /* Adjust input clock */ | ||
1882 | inPllRate = inPllRate / prediv; | ||
1883 | |||
1884 | mMultFactional = (double)(uint32_t)(pSetup->audpllfrac >> 15) + | ||
1885 | (double)(uint32_t)Binary2Fractional(pSetup->audpllfrac & 0x7FFFU); | ||
1886 | workRate = (double)inPllRate * (double)mMultFactional; | ||
1887 | |||
1888 | workRate = workRate / ((double)postdiv); | ||
1889 | workRate = workRate * 2.0; /* SYS PLL hardware cco is divide by 2 before to M-DIVIDER*/ | ||
1890 | } | ||
1891 | else | ||
1892 | { | ||
1893 | /* In bypass mode */ | ||
1894 | workRate = (double)(uint64_t)inPllRate; | ||
1895 | } | ||
1896 | |||
1897 | return (uint32_t)workRate; | ||
1898 | } | ||
1899 | |||
1900 | /* Set the current PLL Rate */ | ||
1901 | /*! brief Store the current PLL rate | ||
1902 | * param rate: Current rate of the PLL | ||
1903 | * return Nothing | ||
1904 | **/ | ||
1905 | void CLOCK_SetStoredPLLClockRate(uint32_t rate) | ||
1906 | { | ||
1907 | s_Pll_Freq = rate; | ||
1908 | } | ||
1909 | |||
1910 | /* Set the current Audio PLL Rate */ | ||
1911 | /*! brief Store the current AUDIO PLL rate | ||
1912 | * param rate: Current rate of the PLL | ||
1913 | * return Nothing | ||
1914 | **/ | ||
1915 | void CLOCK_SetStoredAudioPLLClockRate(uint32_t rate) | ||
1916 | { | ||
1917 | s_Audio_Pll_Freq = rate; | ||
1918 | } | ||
1919 | |||
1920 | /* Set the current Usb PLL Rate */ | ||
1921 | void CLOCK_SetStoredUsbPLLClockRate(uint32_t rate) | ||
1922 | { | ||
1923 | s_Usb_Pll_Freq = rate; | ||
1924 | } | ||
1925 | |||
1926 | /* Return System PLL output clock rate */ | ||
1927 | /*! brief Return System PLL output clock rate | ||
1928 | * param recompute : Forces a PLL rate recomputation if true | ||
1929 | * return System PLL output clock rate | ||
1930 | * note The PLL rate is cached in the driver in a variable as | ||
1931 | * the rate computation function can take some time to perform. It | ||
1932 | * is recommended to use 'false' with the 'recompute' parameter. | ||
1933 | */ | ||
1934 | uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute) | ||
1935 | { | ||
1936 | pll_setup_t Setup; | ||
1937 | uint32_t rate; | ||
1938 | |||
1939 | if ((recompute) || (s_Pll_Freq == 0U)) | ||
1940 | { | ||
1941 | Setup.pllctrl = SYSCON->SYSPLLCTRL; | ||
1942 | Setup.pllndec = SYSCON->SYSPLLNDEC; | ||
1943 | Setup.pllpdec = SYSCON->SYSPLLPDEC; | ||
1944 | Setup.pllmdec = SYSCON->SYSPLLMDEC; | ||
1945 | |||
1946 | CLOCK_GetSystemPLLOutFromSetupUpdate(&Setup); | ||
1947 | } | ||
1948 | |||
1949 | rate = s_Pll_Freq; | ||
1950 | |||
1951 | return rate; | ||
1952 | } | ||
1953 | |||
1954 | /* Return AUDIO PLL output clock rate */ | ||
1955 | /*! brief Return System AUDIO PLL output clock rate | ||
1956 | * param recompute : Forces a AUDIO PLL rate recomputation if true | ||
1957 | * return System AUDIO PLL output clock rate | ||
1958 | * note The AUDIO PLL rate is cached in the driver in a variable as | ||
1959 | * the rate computation function can take some time to perform. It | ||
1960 | * is recommended to use 'false' with the 'recompute' parameter. | ||
1961 | */ | ||
1962 | uint32_t CLOCK_GetAudioPLLOutClockRate(bool recompute) | ||
1963 | { | ||
1964 | pll_setup_t Setup; | ||
1965 | uint32_t rate; | ||
1966 | |||
1967 | if ((recompute) || (s_Audio_Pll_Freq == 0U)) | ||
1968 | { | ||
1969 | Setup.pllctrl = SYSCON->AUDPLLCTRL; | ||
1970 | Setup.pllndec = SYSCON->AUDPLLNDEC; | ||
1971 | Setup.pllpdec = SYSCON->AUDPLLPDEC; | ||
1972 | Setup.pllmdec = SYSCON->AUDPLLMDEC; | ||
1973 | |||
1974 | CLOCK_GetAudioPLLOutFromSetupUpdate(&Setup); | ||
1975 | } | ||
1976 | |||
1977 | rate = s_Audio_Pll_Freq; | ||
1978 | return rate; | ||
1979 | } | ||
1980 | |||
1981 | /* Return USB PLL output clock rate */ | ||
1982 | uint32_t CLOCK_GetUsbPLLOutClockRate(bool recompute) | ||
1983 | { | ||
1984 | usb_pll_setup_t Setup; | ||
1985 | uint32_t rate; | ||
1986 | |||
1987 | if ((recompute) || (s_Usb_Pll_Freq == 0U)) | ||
1988 | { | ||
1989 | Setup.msel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_MSEL_SHIFT) & SYSCON_USBPLLCTRL_MSEL_MASK); | ||
1990 | Setup.psel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_PSEL_SHIFT) & SYSCON_USBPLLCTRL_PSEL_MASK); | ||
1991 | Setup.nsel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_NSEL_SHIFT) & SYSCON_USBPLLCTRL_NSEL_MASK); | ||
1992 | Setup.fbsel = (((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_FBSEL_SHIFT) & SYSCON_USBPLLCTRL_FBSEL_MASK) != 0UL); | ||
1993 | Setup.bypass = | ||
1994 | (((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_BYPASS_SHIFT) & SYSCON_USBPLLCTRL_BYPASS_MASK) != 0UL); | ||
1995 | Setup.direct = | ||
1996 | (((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_DIRECT_SHIFT) & SYSCON_USBPLLCTRL_DIRECT_MASK) != 0UL); | ||
1997 | CLOCK_GetUsbPLLOutFromSetupUpdate(&Setup); | ||
1998 | } | ||
1999 | |||
2000 | rate = s_Usb_Pll_Freq; | ||
2001 | return rate; | ||
2002 | } | ||
2003 | |||
2004 | /* Set PLL output based on the passed PLL setup data */ | ||
2005 | /*! brief Set PLL output based on the passed PLL setup data | ||
2006 | * param pControl : Pointer to populated PLL control structure to generate setup with | ||
2007 | * param pSetup : Pointer to PLL setup structure to be filled | ||
2008 | * return PLL_ERROR_SUCCESS on success, or PLL setup error code | ||
2009 | * note Actual frequency for setup may vary from the desired frequency based on the | ||
2010 | * accuracy of input clocks, rounding, non-fractional PLL mode, etc. | ||
2011 | */ | ||
2012 | pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup) | ||
2013 | { | ||
2014 | uint32_t inRate; | ||
2015 | pll_error_t pllError; | ||
2016 | |||
2017 | /* Determine input rate for the PLL */ | ||
2018 | if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U) | ||
2019 | { | ||
2020 | inRate = pControl->inputRate; | ||
2021 | } | ||
2022 | else | ||
2023 | { | ||
2024 | inRate = CLOCK_GetSystemPLLInClockRate(); | ||
2025 | } | ||
2026 | |||
2027 | /* PLL flag options */ | ||
2028 | pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup); | ||
2029 | pSetup->pllRate = pControl->desiredRate; | ||
2030 | return pllError; | ||
2031 | } | ||
2032 | |||
2033 | /* Set PLL output from PLL setup structure */ | ||
2034 | /*! brief Set PLL output from PLL setup structure (precise frequency) | ||
2035 | * param pSetup : Pointer to populated PLL setup structure | ||
2036 | * param flagcfg : Flag configuration for PLL config structure | ||
2037 | * return PLL_ERROR_SUCCESS on success, or PLL setup error code | ||
2038 | * note This function will power off the PLL, setup the PLL with the | ||
2039 | * new setup data, and then optionally powerup the PLL, wait for PLL lock, | ||
2040 | * and adjust system voltages to the new PLL rate. The function will not | ||
2041 | * alter any source clocks (ie, main systen clock) that may use the PLL, | ||
2042 | * so these should be setup prior to and after exiting the function. | ||
2043 | */ | ||
2044 | pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg) | ||
2045 | { | ||
2046 | if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U) | ||
2047 | { | ||
2048 | /* Turn on the ext clock if system pll input select clk_in */ | ||
2049 | CLOCK_Enable_SysOsc(true); | ||
2050 | } | ||
2051 | /* Enable power for PLLs */ | ||
2052 | POWER_SetPLL(); | ||
2053 | /* Power off PLL during setup changes */ | ||
2054 | POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0); | ||
2055 | |||
2056 | pSetup->flags = flagcfg; | ||
2057 | |||
2058 | /* Write PLL setup data */ | ||
2059 | SYSCON->SYSPLLCTRL = pSetup->pllctrl; | ||
2060 | SYSCON->SYSPLLNDEC = pSetup->pllndec; | ||
2061 | SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */ | ||
2062 | SYSCON->SYSPLLPDEC = pSetup->pllpdec; | ||
2063 | SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */ | ||
2064 | SYSCON->SYSPLLMDEC = pSetup->pllmdec; | ||
2065 | SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */ | ||
2066 | |||
2067 | /* Flags for lock or power on */ | ||
2068 | if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U) | ||
2069 | { | ||
2070 | /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */ | ||
2071 | uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/ | ||
2072 | uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U); | ||
2073 | |||
2074 | /* Initialize and power up PLL */ | ||
2075 | SYSCON->SYSPLLMDEC = maxCCO; | ||
2076 | POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0); | ||
2077 | |||
2078 | /* Set mreq to activate */ | ||
2079 | SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U); | ||
2080 | |||
2081 | /* Delay for 72 uSec @ 12Mhz */ | ||
2082 | SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2083 | |||
2084 | /* clear mreq to prepare for restoring mreq */ | ||
2085 | SYSCON->SYSPLLMDEC = curSSCTRL; | ||
2086 | |||
2087 | /* set original value back and activate */ | ||
2088 | SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U); | ||
2089 | |||
2090 | /* Enable peripheral states by setting low */ | ||
2091 | POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0); | ||
2092 | } | ||
2093 | if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U) | ||
2094 | { | ||
2095 | while (CLOCK_IsSystemPLLLocked() == false) | ||
2096 | { | ||
2097 | } | ||
2098 | } | ||
2099 | |||
2100 | /* Update current programmed PLL rate var */ | ||
2101 | CLOCK_GetSystemPLLOutFromSetupUpdate(pSetup); | ||
2102 | |||
2103 | /* System voltage adjustment, occurs prior to setting main system clock */ | ||
2104 | if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0U) | ||
2105 | { | ||
2106 | POWER_SetVoltageForFreq(s_Pll_Freq); | ||
2107 | } | ||
2108 | |||
2109 | return kStatus_PLL_Success; | ||
2110 | } | ||
2111 | |||
2112 | /* Set AUDIO PLL output from AUDIO PLL setup structure */ | ||
2113 | /*! brief Set AUDIO PLL output from AUDIOPLL setup structure (precise frequency) | ||
2114 | * param pSetup : Pointer to populated PLL setup structure | ||
2115 | * param flagcfg : Flag configuration for PLL config structure | ||
2116 | * return PLL_ERROR_SUCCESS on success, or PLL setup error code | ||
2117 | * note This function will power off the PLL, setup the PLL with the | ||
2118 | * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock, | ||
2119 | * and adjust system voltages to the new AUDIOPLL rate. The function will not | ||
2120 | * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL, | ||
2121 | * so these should be setup prior to and after exiting the function. | ||
2122 | */ | ||
2123 | pll_error_t CLOCK_SetupAudioPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg) | ||
2124 | { | ||
2125 | if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U) | ||
2126 | { | ||
2127 | /* Turn on the ext clock if system pll input select clk_in */ | ||
2128 | CLOCK_Enable_SysOsc(true); | ||
2129 | } | ||
2130 | /* Enable power VD3 for PLLs */ | ||
2131 | POWER_SetPLL(); | ||
2132 | /* Power off PLL during setup changes */ | ||
2133 | POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL); | ||
2134 | |||
2135 | pSetup->flags = flagcfg; | ||
2136 | |||
2137 | /* Write PLL setup data */ | ||
2138 | SYSCON->AUDPLLCTRL = pSetup->pllctrl; | ||
2139 | SYSCON->AUDPLLNDEC = pSetup->pllndec; | ||
2140 | SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */ | ||
2141 | SYSCON->AUDPLLPDEC = pSetup->pllpdec; | ||
2142 | SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */ | ||
2143 | SYSCON->AUDPLLMDEC = pSetup->pllmdec; | ||
2144 | SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */ | ||
2145 | SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1); /* disable fractional function */ | ||
2146 | |||
2147 | /* Flags for lock or power on */ | ||
2148 | if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U) | ||
2149 | { | ||
2150 | /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */ | ||
2151 | uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/ | ||
2152 | uint32_t curSSCTRL = SYSCON->AUDPLLMDEC & ~(1UL << 17U); | ||
2153 | |||
2154 | /* Initialize and power up PLL */ | ||
2155 | SYSCON->AUDPLLMDEC = maxCCO; | ||
2156 | POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL); | ||
2157 | |||
2158 | /* Set mreq to activate */ | ||
2159 | SYSCON->AUDPLLMDEC = maxCCO | (1UL << 17U); | ||
2160 | |||
2161 | /* Delay for 72 uSec @ 12Mhz */ | ||
2162 | SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2163 | |||
2164 | /* clear mreq to prepare for restoring mreq */ | ||
2165 | SYSCON->AUDPLLMDEC = curSSCTRL; | ||
2166 | |||
2167 | /* set original value back and activate */ | ||
2168 | SYSCON->AUDPLLMDEC = curSSCTRL | (1UL << 17U); | ||
2169 | |||
2170 | /* Enable peripheral states by setting low */ | ||
2171 | POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL); | ||
2172 | } | ||
2173 | if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U) | ||
2174 | { | ||
2175 | while (CLOCK_IsAudioPLLLocked() == false) | ||
2176 | { | ||
2177 | } | ||
2178 | } | ||
2179 | |||
2180 | /* Update current programmed PLL rate var */ | ||
2181 | CLOCK_GetAudioPLLOutFromSetupUpdate(pSetup); | ||
2182 | |||
2183 | return kStatus_PLL_Success; | ||
2184 | } | ||
2185 | |||
2186 | /* Set AUDIO PLL output from AUDIO PLL fractional setup structure */ | ||
2187 | /*! brief Set AUDIO PLL output from AUDIOPLL setup structure using the Audio Fractional divider register(precise | ||
2188 | * frequency) | ||
2189 | * param pSetup : Pointer to populated PLL setup structure | ||
2190 | * param flagcfg : Flag configuration for PLL config structure | ||
2191 | * return PLL_ERROR_SUCCESS on success, or PLL setup error code | ||
2192 | * note This function will power off the PLL, setup the PLL with the | ||
2193 | * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock, | ||
2194 | * and adjust system voltages to the new AUDIOPLL rate. The function will not | ||
2195 | * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL, | ||
2196 | * so these should be setup prior to and after exiting the function. | ||
2197 | */ | ||
2198 | pll_error_t CLOCK_SetupAudioPLLPrecFract(pll_setup_t *pSetup, uint32_t flagcfg) | ||
2199 | { | ||
2200 | if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U) | ||
2201 | { | ||
2202 | /* Turn on the ext clock if system pll input select clk_in */ | ||
2203 | CLOCK_Enable_SysOsc(true); | ||
2204 | } | ||
2205 | /* Enable power VD3 for PLLs */ | ||
2206 | POWER_SetPLL(); | ||
2207 | /* Power off PLL during setup changes */ | ||
2208 | POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL); | ||
2209 | |||
2210 | pSetup->flags = flagcfg; | ||
2211 | |||
2212 | /* Write PLL setup data */ | ||
2213 | SYSCON->AUDPLLCTRL = pSetup->pllctrl; | ||
2214 | SYSCON->AUDPLLNDEC = pSetup->pllndec; | ||
2215 | SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */ | ||
2216 | SYSCON->AUDPLLPDEC = pSetup->pllpdec; | ||
2217 | SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */ | ||
2218 | SYSCON->AUDPLLMDEC = pSetup->pllmdec; | ||
2219 | SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(0); /* enable fractional function */ | ||
2220 | SYSCON->AUDPLLFRAC = pSetup->audpllfrac; | ||
2221 | SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT); | ||
2222 | |||
2223 | /* Enable peripheral states by setting low */ | ||
2224 | POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL); | ||
2225 | |||
2226 | if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U) | ||
2227 | { | ||
2228 | while (CLOCK_IsAudioPLLLocked() == false) | ||
2229 | { | ||
2230 | } | ||
2231 | } | ||
2232 | |||
2233 | /* Update current programmed PLL rate var */ | ||
2234 | CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pSetup); | ||
2235 | |||
2236 | return kStatus_PLL_Success; | ||
2237 | } | ||
2238 | |||
2239 | /* Set Audio PLL output based on the passed Audio PLL setup data */ | ||
2240 | /*! brief Set AUDIO PLL output based on the passed AUDIO PLL setup data | ||
2241 | * param pControl : Pointer to populated PLL control structure to generate setup with | ||
2242 | * param pSetup : Pointer to PLL setup structure to be filled | ||
2243 | * return PLL_ERROR_SUCCESS on success, or PLL setup error code | ||
2244 | * note Actual frequency for setup may vary from the desired frequency based on the | ||
2245 | * accuracy of input clocks, rounding, non-fractional PLL mode, etc. | ||
2246 | */ | ||
2247 | pll_error_t CLOCK_SetupAudioPLLData(pll_config_t *pControl, pll_setup_t *pSetup) | ||
2248 | { | ||
2249 | uint32_t inRate; | ||
2250 | pll_error_t pllError; | ||
2251 | |||
2252 | /* Determine input rate for the PLL */ | ||
2253 | if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U) | ||
2254 | { | ||
2255 | inRate = pControl->inputRate; | ||
2256 | } | ||
2257 | else | ||
2258 | { | ||
2259 | inRate = CLOCK_GetAudioPLLInClockRate(); | ||
2260 | } | ||
2261 | |||
2262 | /* PLL flag options */ | ||
2263 | pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup); | ||
2264 | pSetup->pllRate = pControl->desiredRate; | ||
2265 | return pllError; | ||
2266 | } | ||
2267 | |||
2268 | /* Setup PLL Frequency from pre-calculated value */ | ||
2269 | /** | ||
2270 | * brief Set PLL output from PLL setup structure (precise frequency) | ||
2271 | * param pSetup : Pointer to populated PLL setup structure | ||
2272 | * return kStatus_PLL_Success on success, or PLL setup error code | ||
2273 | * note This function will power off the PLL, setup the PLL with the | ||
2274 | * new setup data, and then optionally powerup the PLL, wait for PLL lock, | ||
2275 | * and adjust system voltages to the new PLL rate. The function will not | ||
2276 | * alter any source clocks (ie, main systen clock) that may use the PLL, | ||
2277 | * so these should be setup prior to and after exiting the function. | ||
2278 | */ | ||
2279 | pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup) | ||
2280 | { | ||
2281 | if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U) | ||
2282 | { | ||
2283 | /* Turn on the ext clock if system pll input select clk_in */ | ||
2284 | CLOCK_Enable_SysOsc(true); | ||
2285 | } | ||
2286 | /* Enable power VD3 for PLLs */ | ||
2287 | POWER_SetPLL(); | ||
2288 | /* Power off PLL during setup changes */ | ||
2289 | POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0); | ||
2290 | |||
2291 | /* Write PLL setup data */ | ||
2292 | SYSCON->SYSPLLCTRL = pSetup->pllctrl; | ||
2293 | SYSCON->SYSPLLNDEC = pSetup->pllndec; | ||
2294 | SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */ | ||
2295 | SYSCON->SYSPLLPDEC = pSetup->pllpdec; | ||
2296 | SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */ | ||
2297 | SYSCON->SYSPLLMDEC = pSetup->pllmdec; | ||
2298 | SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */ | ||
2299 | |||
2300 | /* Flags for lock or power on */ | ||
2301 | if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U) | ||
2302 | { | ||
2303 | /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */ | ||
2304 | uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/ | ||
2305 | uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U); | ||
2306 | |||
2307 | /* Initialize and power up PLL */ | ||
2308 | SYSCON->SYSPLLMDEC = maxCCO; | ||
2309 | POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0); | ||
2310 | |||
2311 | /* Set mreq to activate */ | ||
2312 | SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U); | ||
2313 | |||
2314 | /* Delay for 72 uSec @ 12Mhz */ | ||
2315 | SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2316 | |||
2317 | /* clear mreq to prepare for restoring mreq */ | ||
2318 | SYSCON->SYSPLLMDEC = curSSCTRL; | ||
2319 | |||
2320 | /* set original value back and activate */ | ||
2321 | SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U); | ||
2322 | |||
2323 | /* Enable peripheral states by setting low */ | ||
2324 | POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0); | ||
2325 | } | ||
2326 | if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U) | ||
2327 | { | ||
2328 | while (CLOCK_IsSystemPLLLocked() == false) | ||
2329 | { | ||
2330 | } | ||
2331 | } | ||
2332 | |||
2333 | /* Update current programmed PLL rate var */ | ||
2334 | s_Pll_Freq = pSetup->pllRate; | ||
2335 | |||
2336 | return kStatus_PLL_Success; | ||
2337 | } | ||
2338 | |||
2339 | /* Setup Audio PLL Frequency from pre-calculated value */ | ||
2340 | /** | ||
2341 | * brief Set Audio PLL output from Audio PLL setup structure (precise frequency) | ||
2342 | * param pSetup : Pointer to populated PLL setup structure | ||
2343 | * return kStatus_PLL_Success on success, or Audio PLL setup error code | ||
2344 | * note This function will power off the PLL, setup the Audio PLL with the | ||
2345 | * new setup data, and then optionally powerup the PLL, wait for Audio PLL lock, | ||
2346 | * and adjust system voltages to the new PLL rate. The function will not | ||
2347 | * alter any source clocks (ie, main systen clock) that may use the Audio PLL, | ||
2348 | * so these should be setup prior to and after exiting the function. | ||
2349 | */ | ||
2350 | pll_error_t CLOCK_SetAudioPLLFreq(const pll_setup_t *pSetup) | ||
2351 | { | ||
2352 | if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U) | ||
2353 | { | ||
2354 | /* Turn on the ext clock if system pll input select clk_in */ | ||
2355 | CLOCK_Enable_SysOsc(true); | ||
2356 | } | ||
2357 | /* Enable power VD3 for PLLs */ | ||
2358 | POWER_SetPLL(); | ||
2359 | /* Power off Audio PLL during setup changes */ | ||
2360 | POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL); | ||
2361 | |||
2362 | /* Write Audio PLL setup data */ | ||
2363 | SYSCON->AUDPLLCTRL = pSetup->pllctrl; | ||
2364 | SYSCON->AUDPLLFRAC = pSetup->audpllfrac; | ||
2365 | SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT); /* latch */ | ||
2366 | SYSCON->AUDPLLNDEC = pSetup->pllndec; | ||
2367 | SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_AUDPLLNDEC_NREQ_SHIFT); /* latch */ | ||
2368 | SYSCON->AUDPLLPDEC = pSetup->pllpdec; | ||
2369 | SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_AUDPLLPDEC_PREQ_SHIFT); /* latch */ | ||
2370 | SYSCON->AUDPLLMDEC = pSetup->pllmdec; | ||
2371 | SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_AUDPLLMDEC_MREQ_SHIFT); /* latch */ | ||
2372 | SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1); /* disable fractional function */ | ||
2373 | |||
2374 | /* Flags for lock or power on */ | ||
2375 | if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U) | ||
2376 | { | ||
2377 | /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */ | ||
2378 | uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/ | ||
2379 | uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U); | ||
2380 | |||
2381 | /* Initialize and power up PLL */ | ||
2382 | SYSCON->SYSPLLMDEC = maxCCO; | ||
2383 | POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL); | ||
2384 | |||
2385 | /* Set mreq to activate */ | ||
2386 | SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U); | ||
2387 | |||
2388 | /* Delay for 72 uSec @ 12Mhz */ | ||
2389 | SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2390 | |||
2391 | /* clear mreq to prepare for restoring mreq */ | ||
2392 | SYSCON->SYSPLLMDEC = curSSCTRL; | ||
2393 | |||
2394 | /* set original value back and activate */ | ||
2395 | SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U); | ||
2396 | |||
2397 | /* Enable peripheral states by setting low */ | ||
2398 | POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL); | ||
2399 | } | ||
2400 | if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U) | ||
2401 | { | ||
2402 | while (CLOCK_IsAudioPLLLocked() == false) | ||
2403 | { | ||
2404 | } | ||
2405 | } | ||
2406 | |||
2407 | /* Update current programmed PLL rate var */ | ||
2408 | s_Audio_Pll_Freq = pSetup->pllRate; | ||
2409 | |||
2410 | return kStatus_PLL_Success; | ||
2411 | } | ||
2412 | |||
2413 | /* Setup USB PLL Frequency from pre-calculated value */ | ||
2414 | /** | ||
2415 | * brief Set USB PLL output from USB PLL setup structure (precise frequency) | ||
2416 | * param pSetup : Pointer to populated USB PLL setup structure | ||
2417 | * return kStatus_PLL_Success on success, or USB PLL setup error code | ||
2418 | * note This function will power off the USB PLL, setup the PLL with the | ||
2419 | * new setup data, and then optionally powerup the USB PLL, wait for USB PLL lock, | ||
2420 | * and adjust system voltages to the new USB PLL rate. The function will not | ||
2421 | * alter any source clocks (ie, usb pll clock) that may use the USB PLL, | ||
2422 | * so these should be setup prior to and after exiting the function. | ||
2423 | */ | ||
2424 | pll_error_t CLOCK_SetUsbPLLFreq(const usb_pll_setup_t *pSetup) | ||
2425 | { | ||
2426 | uint32_t usbpllctrl, fccoHz; | ||
2427 | uint8_t msel, psel, nsel; | ||
2428 | bool pllDirectInput, pllDirectOutput, pllfbsel; | ||
2429 | |||
2430 | msel = pSetup->msel; | ||
2431 | psel = pSetup->psel; | ||
2432 | nsel = pSetup->nsel; | ||
2433 | pllDirectOutput = pSetup->direct; | ||
2434 | pllDirectInput = pSetup->bypass; | ||
2435 | pllfbsel = pSetup->fbsel; | ||
2436 | |||
2437 | /* Input clock into the PLL cannot be lower than this */ | ||
2438 | if (pSetup->inputRate < USB_PLL_LOWER_IN_LIMIT) | ||
2439 | { | ||
2440 | return kStatus_PLL_InputTooLow; | ||
2441 | } | ||
2442 | |||
2443 | if (pllfbsel) | ||
2444 | { | ||
2445 | /*integer_mode: Fout = M*(Fin/N), Fcco = 2*P*M*(Fin/N) */ | ||
2446 | fccoHz = (pSetup->inputRate / ((uint32_t)nsel + 1U)) * 2U * (msel + 1U) * SWITCH_USB_PSEL(psel); | ||
2447 | |||
2448 | /* USB PLL CCO out rate cannot be lower than this */ | ||
2449 | if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ) | ||
2450 | { | ||
2451 | return kStatus_PLL_CCOTooLow; | ||
2452 | } | ||
2453 | /* USB PLL CCO out rate cannot be Higher than this */ | ||
2454 | if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ) | ||
2455 | { | ||
2456 | return kStatus_PLL_CCOTooHigh; | ||
2457 | } | ||
2458 | } | ||
2459 | else | ||
2460 | { | ||
2461 | /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */ | ||
2462 | fccoHz = pSetup->inputRate / ((uint32_t)nsel + 1U) * (msel + 1U); | ||
2463 | |||
2464 | /* USB PLL CCO out rate cannot be lower than this */ | ||
2465 | if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ) | ||
2466 | { | ||
2467 | return kStatus_PLL_CCOTooLow; | ||
2468 | } | ||
2469 | /* USB PLL CCO out rate cannot be Higher than this */ | ||
2470 | if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ) | ||
2471 | { | ||
2472 | return kStatus_PLL_CCOTooHigh; | ||
2473 | } | ||
2474 | } | ||
2475 | |||
2476 | /* If configure the USB HOST clock, VD5 power for USB PHY should be enable | ||
2477 | before the PLL is working */ | ||
2478 | /* Turn on the ext clock for usb pll input */ | ||
2479 | CLOCK_Enable_SysOsc(true); | ||
2480 | |||
2481 | /* Enable power VD3 for PLLs */ | ||
2482 | POWER_SetPLL(); | ||
2483 | |||
2484 | /* Power on the VD5 for USB PHY */ | ||
2485 | POWER_SetUsbPhy(); | ||
2486 | |||
2487 | /* Power off USB PLL during setup changes */ | ||
2488 | POWER_EnablePD(kPDRUNCFG_PD_USB_PLL); | ||
2489 | |||
2490 | /* Write USB PLL setup data */ | ||
2491 | usbpllctrl = USB_PLL_NSEL_VAL_SET(nsel) | /* NSEL VALUE */ | ||
2492 | USB_PLL_PSEL_VAL_SET(psel) | /* PSEL VALUE */ | ||
2493 | USB_PLL_MSEL_VAL_SET(msel) | /* MSEL VALUE */ | ||
2494 | (uint32_t)pllDirectInput << SYSCON_USBPLLCTRL_BYPASS_SHIFT | /* BYPASS DISABLE */ | ||
2495 | (uint32_t)pllDirectOutput << SYSCON_USBPLLCTRL_DIRECT_SHIFT | /* DIRECTO DISABLE */ | ||
2496 | (uint32_t)pllfbsel << SYSCON_USBPLLCTRL_FBSEL_SHIFT; /* FBSEL SELECT */ | ||
2497 | |||
2498 | SYSCON->USBPLLCTRL = usbpllctrl; | ||
2499 | |||
2500 | POWER_DisablePD(kPDRUNCFG_PD_USB_PLL); | ||
2501 | |||
2502 | /* Delay for 72 uSec @ 12Mhz for the usb pll to lock */ | ||
2503 | SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2504 | if (false == pllDirectInput) | ||
2505 | { | ||
2506 | while (CLOCK_IsUsbPLLLocked() == false) | ||
2507 | { | ||
2508 | } | ||
2509 | } | ||
2510 | CLOCK_GetUsbPLLOutFromSetupUpdate(pSetup); | ||
2511 | return kStatus_PLL_Success; | ||
2512 | } | ||
2513 | |||
2514 | /* Set System PLL clock based on the input frequency and multiplier */ | ||
2515 | /*! brief Set PLL output based on the multiplier and input frequency | ||
2516 | * param multiply_by : multiplier | ||
2517 | * param input_freq : Clock input frequency of the PLL | ||
2518 | * return Nothing | ||
2519 | * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this | ||
2520 | * function does not disable or enable PLL power, wait for PLL lock, | ||
2521 | * or adjust system voltages. These must be done in the application. | ||
2522 | * The function will not alter any source clocks (ie, main systen clock) | ||
2523 | * that may use the PLL, so these should be setup prior to and after | ||
2524 | * exiting the function. | ||
2525 | */ | ||
2526 | void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq) | ||
2527 | { | ||
2528 | uint32_t cco_freq = input_freq * multiply_by; | ||
2529 | uint32_t pdec = 1U; | ||
2530 | uint32_t selr; | ||
2531 | uint32_t seli; | ||
2532 | uint32_t selp; | ||
2533 | uint32_t mdec, ndec; | ||
2534 | |||
2535 | uint32_t directo = SYSCON_SYSPLLCTRL_DIRECTO(1); | ||
2536 | |||
2537 | while (cco_freq < 275000000U) | ||
2538 | { | ||
2539 | multiply_by <<= 1U; /* double value in each iteration */ | ||
2540 | pdec <<= 1U; /* correspondingly double pdec to cancel effect of double msel */ | ||
2541 | cco_freq = input_freq * multiply_by; | ||
2542 | } | ||
2543 | selr = 0U; | ||
2544 | if (multiply_by < 60U) | ||
2545 | { | ||
2546 | seli = (multiply_by & 0x3cU) + 4U; | ||
2547 | selp = (multiply_by >> 1U) + 1U; | ||
2548 | } | ||
2549 | else | ||
2550 | { | ||
2551 | selp = 31U; | ||
2552 | if (multiply_by > 16384U) | ||
2553 | { | ||
2554 | seli = 1U; | ||
2555 | } | ||
2556 | else if (multiply_by > 8192U) | ||
2557 | { | ||
2558 | seli = 2U; | ||
2559 | } | ||
2560 | else if (multiply_by > 2048U) | ||
2561 | { | ||
2562 | seli = 4U; | ||
2563 | } | ||
2564 | else if (multiply_by >= 501U) | ||
2565 | { | ||
2566 | seli = 8U; | ||
2567 | } | ||
2568 | else | ||
2569 | { | ||
2570 | seli = 4U * (1024U / (multiply_by + 9U)); | ||
2571 | } | ||
2572 | } | ||
2573 | |||
2574 | if (pdec > 1U) | ||
2575 | { | ||
2576 | directo = 0U; /* use post divider */ | ||
2577 | pdec = pdec / 2U; /* Account for minus 1 encoding */ | ||
2578 | /* Translate P value */ | ||
2579 | switch (pdec) | ||
2580 | { | ||
2581 | case 1U: | ||
2582 | pdec = 0x62U; /* 1 * 2 */ | ||
2583 | break; | ||
2584 | case 2U: | ||
2585 | pdec = 0x42U; /* 2 * 2 */ | ||
2586 | break; | ||
2587 | case 4U: | ||
2588 | pdec = 0x02U; /* 4 * 2 */ | ||
2589 | break; | ||
2590 | case 8U: | ||
2591 | pdec = 0x0bU; /* 8 * 2 */ | ||
2592 | break; | ||
2593 | case 16U: | ||
2594 | pdec = 0x11U; /* 16 * 2 */ | ||
2595 | break; | ||
2596 | case 32U: | ||
2597 | pdec = 0x08U; /* 32 * 2 */ | ||
2598 | break; | ||
2599 | default: | ||
2600 | pdec = 0x08U; | ||
2601 | break; | ||
2602 | } | ||
2603 | } | ||
2604 | |||
2605 | mdec = PLL_MDEC_VAL_SET(pllEncodeM(multiply_by)); | ||
2606 | ndec = 0x302U; /* pre divide by 1 (hardcoded) */ | ||
2607 | |||
2608 | SYSCON->SYSPLLCTRL = directo | (selr << SYSCON_SYSPLLCTRL_SELR_SHIFT) | (seli << SYSCON_SYSPLLCTRL_SELI_SHIFT) | | ||
2609 | (selp << SYSCON_SYSPLLCTRL_SELP_SHIFT); | ||
2610 | SYSCON->SYSPLLPDEC = pdec | (1U << 7U); /* set Pdec value and assert preq */ | ||
2611 | SYSCON->SYSPLLNDEC = ndec | (1UL << 10U); /* set Pdec value and assert preq */ | ||
2612 | SYSCON->SYSPLLMDEC = (1UL << 17U) | mdec; /* select non sscg MDEC value, assert mreq and select mdec value */ | ||
2613 | } | ||
2614 | |||
2615 | /* Enable USB DEVICE FULL SPEED clock */ | ||
2616 | /*! brief Enable USB Device FS clock. | ||
2617 | * param src : clock source | ||
2618 | * param freq: clock frequency | ||
2619 | * Enable USB Device Full Speed clock. | ||
2620 | */ | ||
2621 | bool CLOCK_EnableUsbfs0DeviceClock(clock_usb_src_t src, uint32_t freq) | ||
2622 | { | ||
2623 | bool ret = true; | ||
2624 | |||
2625 | CLOCK_DisableClock(kCLOCK_Usbd0); | ||
2626 | |||
2627 | if (kCLOCK_UsbSrcFro == src) | ||
2628 | { | ||
2629 | switch (freq) | ||
2630 | { | ||
2631 | case 96000000U: | ||
2632 | CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */ | ||
2633 | break; | ||
2634 | |||
2635 | case 48000000U: | ||
2636 | CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */ | ||
2637 | break; | ||
2638 | |||
2639 | default: | ||
2640 | ret = false; | ||
2641 | break; | ||
2642 | } | ||
2643 | /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */ | ||
2644 | SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK | | ||
2645 | SYSCON_FROCTRL_USBCLKADJ_MASK; | ||
2646 | /* Select FRO 96 or 48 MHz */ | ||
2647 | CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); | ||
2648 | } | ||
2649 | else | ||
2650 | { | ||
2651 | /*Set the USB PLL as the Usb0 CLK*/ | ||
2652 | POWER_DisablePD(kPDRUNCFG_PD_USB_PLL); | ||
2653 | |||
2654 | usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U}; | ||
2655 | |||
2656 | (void)CLOCK_SetUsbPLLFreq(&pll_setup); | ||
2657 | CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false); | ||
2658 | CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK); | ||
2659 | SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2660 | } | ||
2661 | CLOCK_EnableClock(kCLOCK_Usbd0); | ||
2662 | CLOCK_EnableClock(kCLOCK_UsbRam1); | ||
2663 | |||
2664 | return ret; | ||
2665 | } | ||
2666 | |||
2667 | /* Enable USB HOST FULL SPEED clock */ | ||
2668 | /*! brief Enable USB HOST FS clock. | ||
2669 | * param src : clock source | ||
2670 | * param freq: clock frequency | ||
2671 | * Enable USB HOST Full Speed clock. | ||
2672 | */ | ||
2673 | bool CLOCK_EnableUsbfs0HostClock(clock_usb_src_t src, uint32_t freq) | ||
2674 | { | ||
2675 | bool ret = true; | ||
2676 | |||
2677 | CLOCK_DisableClock(kCLOCK_Usbhmr0); | ||
2678 | CLOCK_DisableClock(kCLOCK_Usbhsl0); | ||
2679 | |||
2680 | if (kCLOCK_UsbSrcFro == src) | ||
2681 | { | ||
2682 | switch (freq) | ||
2683 | { | ||
2684 | case 96000000U: | ||
2685 | CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */ | ||
2686 | break; | ||
2687 | |||
2688 | case 48000000U: | ||
2689 | CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */ | ||
2690 | break; | ||
2691 | |||
2692 | default: | ||
2693 | ret = false; | ||
2694 | break; | ||
2695 | } | ||
2696 | /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */ | ||
2697 | SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK | | ||
2698 | SYSCON_FROCTRL_USBCLKADJ_MASK; | ||
2699 | /* Select FRO 96 or 48 MHz */ | ||
2700 | CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); | ||
2701 | } | ||
2702 | else | ||
2703 | { | ||
2704 | /*Set the USB PLL as the Usb0 CLK*/ | ||
2705 | POWER_DisablePD(kPDRUNCFG_PD_USB_PLL); | ||
2706 | |||
2707 | usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U}; | ||
2708 | |||
2709 | (void)CLOCK_SetUsbPLLFreq(&pll_setup); | ||
2710 | CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false); | ||
2711 | CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK); | ||
2712 | SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2713 | } | ||
2714 | CLOCK_EnableClock(kCLOCK_Usbhmr0); | ||
2715 | CLOCK_EnableClock(kCLOCK_Usbhsl0); | ||
2716 | CLOCK_EnableClock(kCLOCK_UsbRam1); | ||
2717 | |||
2718 | return ret; | ||
2719 | } | ||
2720 | |||
2721 | /* Enable USB DEVICE HIGH SPEED clock */ | ||
2722 | /*! brief Enable USB Device HS clock. | ||
2723 | * param src : clock source | ||
2724 | * param freq: clock frequency | ||
2725 | * Enable USB Device High Speed clock. | ||
2726 | */ | ||
2727 | bool CLOCK_EnableUsbhs0DeviceClock(clock_usb_src_t src, uint32_t freq) | ||
2728 | { | ||
2729 | bool ret = true; | ||
2730 | CLOCK_DisableClock(kCLOCK_Usbd1); | ||
2731 | /* Power on the VD5 for USB PHY */ | ||
2732 | POWER_SetUsbPhy(); | ||
2733 | if (kCLOCK_UsbSrcFro == src) | ||
2734 | { | ||
2735 | switch (freq) | ||
2736 | { | ||
2737 | case 96000000U: | ||
2738 | CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */ | ||
2739 | break; | ||
2740 | |||
2741 | case 48000000U: | ||
2742 | CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */ | ||
2743 | break; | ||
2744 | |||
2745 | default: | ||
2746 | ret = false; | ||
2747 | break; | ||
2748 | } | ||
2749 | /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */ | ||
2750 | SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK | | ||
2751 | SYSCON_FROCTRL_USBCLKADJ_MASK; | ||
2752 | /* Select FRO 96 or 48 MHz */ | ||
2753 | CLOCK_AttachClk(kFRO_HF_to_USB1_CLK); | ||
2754 | } | ||
2755 | else | ||
2756 | { | ||
2757 | SDK_DelayAtLeastUs(50, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2758 | usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U}; | ||
2759 | |||
2760 | (void)CLOCK_SetUsbPLLFreq(&pll_setup); | ||
2761 | |||
2762 | /* Select USB PLL output as USB clock src */ | ||
2763 | CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false); | ||
2764 | CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK); | ||
2765 | } | ||
2766 | |||
2767 | SDK_DelayAtLeastUs(50, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2768 | /* Enable USB1D and USB1RAM */ | ||
2769 | CLOCK_EnableClock(kCLOCK_Usbd1); | ||
2770 | CLOCK_EnableClock(kCLOCK_UsbRam1); | ||
2771 | POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */ | ||
2772 | return ret; | ||
2773 | } | ||
2774 | |||
2775 | /* Enable USB HOST HIGH SPEED clock */ | ||
2776 | /*! brief Enable USB HOST HS clock. | ||
2777 | * param src : clock source | ||
2778 | * param freq: clock frequency | ||
2779 | * Enable USB HOST High Speed clock. | ||
2780 | */ | ||
2781 | bool CLOCK_EnableUsbhs0HostClock(clock_usb_src_t src, uint32_t freq) | ||
2782 | { | ||
2783 | bool ret = true; | ||
2784 | CLOCK_DisableClock(kCLOCK_Usbh1); | ||
2785 | /* Power on the VD5 for USB PHY */ | ||
2786 | POWER_SetUsbPhy(); | ||
2787 | if (kCLOCK_UsbSrcFro == src) | ||
2788 | { | ||
2789 | switch (freq) | ||
2790 | { | ||
2791 | case 96000000U: | ||
2792 | CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2U, false); /*!< Div by 2 to get 48MHz, no divider reset */ | ||
2793 | break; | ||
2794 | |||
2795 | case 48000000U: | ||
2796 | CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false); /*!< Div by 1 to get 48MHz, no divider reset */ | ||
2797 | break; | ||
2798 | |||
2799 | default: | ||
2800 | ret = false; | ||
2801 | break; | ||
2802 | } | ||
2803 | /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */ | ||
2804 | SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK | | ||
2805 | SYSCON_FROCTRL_USBCLKADJ_MASK; | ||
2806 | /* Select FRO 96 or 48 MHz */ | ||
2807 | CLOCK_AttachClk(kFRO_HF_to_USB1_CLK); | ||
2808 | } | ||
2809 | else | ||
2810 | { | ||
2811 | SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2812 | usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U}; | ||
2813 | |||
2814 | (void)CLOCK_SetUsbPLLFreq(&pll_setup); | ||
2815 | |||
2816 | /* Select USB PLL output as USB clock src */ | ||
2817 | CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false); | ||
2818 | CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK); | ||
2819 | } | ||
2820 | |||
2821 | SDK_DelayAtLeastUs(50, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); | ||
2822 | /* Enable USBh1 and USB1RAM */ | ||
2823 | CLOCK_EnableClock(kCLOCK_Usbh1); | ||
2824 | CLOCK_EnableClock(kCLOCK_UsbRam1); | ||
2825 | POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */ | ||
2826 | return ret; | ||
2827 | } | ||