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