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