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