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 PLL_MAX_N_DIV 0x100U
24 
25 #define INDEX_SECTOR_TRIM48 ((uint32_t *)0x01000444U)
26 #define INDEX_SECTOR_TRIM96 ((uint32_t *)0x01000430U)
27 /*--------------------------------------------------------------------------
28 !!! If required these #defines can be moved to chip library file
29 ----------------------------------------------------------------------------*/
30 
31 #define PLL_SSCG0_MDEC_VAL_P (0U)                                /* MDEC is in bits  16 downto 0 */
32 #define PLL_SSCG0_MDEC_VAL_M (0x1FFFFUL << PLL_SSCG0_MDEC_VAL_P) /* NDEC is in bits  9 downto 0 */
33 #define PLL_NDEC_VAL_P (0U)                                      /* NDEC is in bits  9:0 */
34 #define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P)
35 #define PLL_PDEC_VAL_P (0U) /* PDEC is in bits 6:0 */
36 #define PLL_PDEC_VAL_M (0x7FUL << PLL_PDEC_VAL_P)
37 
38 #define PLL_MIN_CCO_FREQ_MHZ (75000000U)
39 #define PLL_MAX_CCO_FREQ_MHZ (150000000U)
40 #define PLL_LOWER_IN_LIMIT (4000U) /*!< Minimum PLL input rate */
41 #define PLL_MIN_IN_SSMODE (2000000U)
42 #define PLL_MAX_IN_SSMODE (4000000U)
43 
44 /* Middle of the range values for spread-spectrum */
45 #define PLL_SSCG_MF_FREQ_VALUE 4U
46 #define PLL_SSCG_MC_COMP_VALUE 2U
47 #define PLL_SSCG_MR_DEPTH_VALUE 4U
48 #define PLL_SSCG_DITHER_VALUE 0U
49 
50 /* PLL NDEC reg */
51 #define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)
52 /* PLL PDEC reg */
53 #define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)
54 /* SSCG control0 */
55 #define PLL_SSCG0_MDEC_VAL_SET(value) (((unsigned long)(value) << PLL_SSCG0_MDEC_VAL_P) & PLL_SSCG0_MDEC_VAL_M)
56 
57 /* SSCG control1 */
58 #define PLL_SSCG1_MD_FRACT_P 0U
59 #define PLL_SSCG1_MD_INT_P 11U
60 #define PLL_SSCG1_MD_FRACT_M (0x7FFUL << PLL_SSCG1_MD_FRACT_P)
61 #define PLL_SSCG1_MD_INT_M (0xFFUL << PLL_SSCG1_MD_INT_P)
62 
63 #define PLL_SSCG1_MD_FRACT_SET(value) (((unsigned long)(value) << PLL_SSCG1_MD_FRACT_P) & PLL_SSCG1_MD_FRACT_M)
64 #define PLL_SSCG1_MD_INT_SET(value) (((unsigned long)(value) << PLL_SSCG1_MD_INT_P) & PLL_SSCG1_MD_INT_M)
65 
66 /* Saved value of PLL output rate, computed whenever needed to save run-time
67    computation on each call to retrive the PLL rate. */
68 static uint32_t s_Pll_Freq;
69 
70 /* I2S mclk. */
71 static uint32_t s_I2S_Mclk_Freq = 0U;
72 
73 /** External clock rate on the CLKIN pin in Hz. If not used,
74     set this to 0. Otherwise, set it to the exact rate in Hz this pin is
75     being driven at. */
76 static const uint32_t s_Ext_Clk_Freq = 0U;
77 
78 /*******************************************************************************
79  * Variables
80  ******************************************************************************/
81 
82 /*******************************************************************************
83  * Prototypes
84  ******************************************************************************/
85 /* Find encoded NDEC value for raw N value, max N = NVALMAX */
86 static uint32_t pllEncodeN(uint32_t N);
87 /* Find decoded N value for raw NDEC value */
88 static uint32_t pllDecodeN(uint32_t NDEC);
89 /* Find encoded PDEC value for raw P value, max P = PVALMAX */
90 static uint32_t pllEncodeP(uint32_t P);
91 /* Find decoded P value for raw PDEC value */
92 static uint32_t pllDecodeP(uint32_t PDEC);
93 /* Find encoded MDEC value for raw M value, max M = MVALMAX */
94 static uint32_t pllEncodeM(uint32_t M);
95 /* Find decoded M value for raw MDEC value */
96 static uint32_t pllDecodeM(uint32_t MDEC);
97 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
98 static void pllFindSel(uint32_t M, bool bypassFBDIV2, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
99 /* Get predivider (N) from PLL NDEC setting */
100 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg);
101 /* Get postdivider (P) from PLL PDEC setting */
102 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg);
103 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
104 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg);
105 /* Get the greatest common divisor */
106 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
107 /* Set PLL output based on desired output rate */
108 static pll_error_t CLOCK_GetPllConfig(
109     uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useFeedbackDiv2, bool useSS);
110 /* Update local PLL rate variable */
111 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup);
112 
113 static const uint8_t wdtFreqLookup[32] = {0,  8,  12, 15, 18, 20, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41,
114                                           42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 59, 60, 61};
115 /*******************************************************************************
116  * Code
117  ******************************************************************************/
118 
119 /**
120  * brief	Configure the clock selection muxes.
121  * param	connection	: Clock to be configured.
122  * return	Nothing
123  */
CLOCK_AttachClk(clock_attach_id_t connection)124 void CLOCK_AttachClk(clock_attach_id_t connection)
125 {
126     uint8_t mux;
127     uint8_t sel;
128     uint16_t item;
129     uint32_t tmp32 = (uint32_t)connection;
130     uint32_t i;
131     volatile uint32_t *pClkSel;
132 
133     pClkSel = &(SYSCON->MAINCLKSELA);
134 
135     if (kNONE_to_NONE != connection)
136     {
137         for (i = 0U; i < 2U; i++)
138         {
139             if (tmp32 == 0U)
140             {
141                 break;
142             }
143             item = (uint16_t)GET_ID_ITEM(tmp32);
144             if (item != 0U)
145             {
146                 mux = GET_ID_ITEM_MUX(item);
147                 sel = GET_ID_ITEM_SEL(item);
148                 if (mux == CM_ASYNCAPB)
149                 {
150                     ASYNC_SYSCON->ASYNCAPBCLKSELA = sel;
151                 }
152                 else
153                 {
154                     ((volatile uint32_t *)pClkSel)[mux] = sel;
155                 }
156             }
157             tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
158         }
159     }
160 }
161 
162 /* Return the actual clock attach id */
163 /**
164  * brief   Get the actual clock attach id.
165  * This fuction uses the offset in input attach id, then it reads the actual source value in
166  * the register and combine the offset to obtain an actual attach id.
167  * param   attachId  : Clock attach id to get.
168  * return  Clock source value.
169  */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)170 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
171 {
172     uint8_t mux;
173     uint8_t actualSel;
174     uint32_t tmp32 = (uint32_t)attachId;
175     uint32_t i;
176     uint32_t actualAttachId = 0U;
177     uint32_t selector       = GET_ID_SELECTOR(tmp32);
178     volatile uint32_t *pClkSel;
179 
180     pClkSel = &(SYSCON->MAINCLKSELA);
181 
182     if (kNONE_to_NONE == attachId)
183     {
184         return kNONE_to_NONE;
185     }
186 
187     for (i = 0U; i < 2U; i++)
188     {
189         mux = GET_ID_ITEM_MUX(tmp32);
190         if (tmp32 != 0UL)
191         {
192             if (mux == CM_ASYNCAPB)
193             {
194                 actualSel = (uint8_t)(ASYNC_SYSCON->ASYNCAPBCLKSELA);
195             }
196             else
197             {
198                 actualSel = (uint8_t)(((volatile uint32_t *)pClkSel)[mux]);
199             }
200 
201             /* Consider the combination of two registers */
202             actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
203         }
204         tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!<  pick up next descriptor */
205     }
206 
207     actualAttachId |= selector;
208 
209     return (clock_attach_id_t)actualAttachId;
210 }
211 
212 /**
213  * brief	Setup peripheral clock dividers.
214  * param	div_name	: Clock divider name
215  * param divided_by_value: Value to be divided
216  * param reset :  Whether to reset the divider counter.
217  * return	Nothing
218  */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value,bool reset)219 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
220 {
221     volatile uint32_t *pClkDiv;
222 
223     pClkDiv = &(SYSCON->SYSTICKCLKDIV);
224     if (reset)
225     {
226         ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 29U;
227     }
228     if (divided_by_value == 0UL) /* halt */
229     {
230         ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 30U;
231     }
232     else
233     {
234         ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = (divided_by_value - 1UL);
235     }
236 }
237 
238 /* Set FRO Clocking */
239 /**
240  * brief	Initialize the Core clock to given frequency (12, 48 or 96 MHz).
241  * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
242  * enabled.
243  * param	iFreq	: Desired frequency (must be one of CLK_FRO_12MHZ or CLK_FRO_48MHZ or CLK_FRO_96MHZ)
244  * return	returns success or fail status.
245  */
CLOCK_SetupFROClocking(uint32_t iFreq)246 status_t CLOCK_SetupFROClocking(uint32_t iFreq)
247 {
248     uint32_t usb_adj;
249     if ((iFreq != 12000000U) && (iFreq != 48000000U) && (iFreq != 96000000U))
250     {
251         return kStatus_Fail;
252     }
253     /* Power up the FRO and set this as the base clock */
254     POWER_DisablePD(kPDRUNCFG_PD_FRO_EN);
255     /* back up the value of whether USB adj is selected, in which case we will have a value of 1 else 0 */
256     usb_adj = ((SYSCON->FROCTRL) & SYSCON_FROCTRL_USBCLKADJ_MASK) >> SYSCON_FROCTRL_USBCLKADJ_SHIFT;
257     if (iFreq > 12000000U)
258     {
259         if (iFreq == 96000000U)
260         {
261             SYSCON->FROCTRL = ((SYSCON_FROCTRL_TRIM_MASK | SYSCON_FROCTRL_FREQTRIM_MASK) & *INDEX_SECTOR_TRIM96) |
262                               SYSCON_FROCTRL_SEL(1) | SYSCON_FROCTRL_WRTRIM(1) | SYSCON_FROCTRL_USBCLKADJ(usb_adj) |
263                               SYSCON_FROCTRL_HSPDCLK(1);
264         }
265         else
266         {
267             SYSCON->FROCTRL = ((SYSCON_FROCTRL_TRIM_MASK | SYSCON_FROCTRL_FREQTRIM_MASK) & *INDEX_SECTOR_TRIM48) |
268                               SYSCON_FROCTRL_SEL(0) | SYSCON_FROCTRL_WRTRIM(1) | SYSCON_FROCTRL_USBCLKADJ(usb_adj) |
269                               SYSCON_FROCTRL_HSPDCLK(1);
270         }
271     }
272     else
273     {
274         SYSCON->FROCTRL &= ~SYSCON_FROCTRL_HSPDCLK(1);
275     }
276 
277     return kStatus_Success;
278 }
279 
280 /*! brief	Return Frequency of FRO 12MHz
281  *  return	Frequency of FRO 12MHz
282  */
CLOCK_GetFro12MFreq(void)283 uint32_t CLOCK_GetFro12MFreq(void)
284 {
285     return ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ? 0U : 12000000U;
286 }
287 
288 /*! brief	Return Frequency of External Clock
289  *  return	Frequency of External Clock. If no external clock is used returns 0.
290  */
CLOCK_GetExtClkFreq(void)291 uint32_t CLOCK_GetExtClkFreq(void)
292 {
293     return (s_Ext_Clk_Freq);
294 }
295 /*! brief	Return Frequency of Watchdog Oscillator
296  *  return	Frequency of Watchdog Oscillator
297  */
CLOCK_GetWdtOscFreq(void)298 uint32_t CLOCK_GetWdtOscFreq(void)
299 {
300     uint8_t freq_sel, div_sel;
301     if ((SYSCON->PDRUNCFG[(uint32_t)kPDRUNCFG_PD_WDT_OSC >> 8UL] & (1UL << ((uint32_t)kPDRUNCFG_PD_WDT_OSC & 0xffU))) !=
302         0UL)
303     {
304         return 0UL;
305     }
306     else
307     {
308         div_sel = (uint8_t)(((SYSCON->WDTOSCCTRL & 0x1fU) + 1UL) << 1U);
309         freq_sel =
310             wdtFreqLookup[((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_FREQSEL_MASK) >> SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)];
311         return ((uint32_t)freq_sel * 50000U) / ((uint32_t)div_sel);
312     }
313 }
314 
315 /* Get HF FRO Clk */
316 /*! brief	Return Frequency of High-Freq output of FRO
317  *  return	Frequency of High-Freq output of FRO
318  */
CLOCK_GetFroHfFreq(void)319 uint32_t CLOCK_GetFroHfFreq(void)
320 {
321     if (((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) != 0UL) ||
322         ((SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK) == 0UL))
323     {
324         return 0U;
325     }
326 
327     if ((SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK) != 0UL)
328     {
329         return 96000000U;
330     }
331     else
332     {
333         return 48000000U;
334     }
335 }
336 
337 /*! brief	Return Frequency of PLL
338  *  return	Frequency of PLL
339  */
CLOCK_GetPllOutFreq(void)340 uint32_t CLOCK_GetPllOutFreq(void)
341 {
342     return s_Pll_Freq;
343 }
344 
345 /*! brief	Return Frequency of 32kHz osc
346  *  return	Frequency of 32kHz osc
347  */
CLOCK_GetOsc32KFreq(void)348 uint32_t CLOCK_GetOsc32KFreq(void)
349 {
350     return CLK_RTC_32K_CLK; /* Needs to be corrected to check that RTC Clock is enabled */
351 }
352 /*! brief	Return Frequency of Core System
353  *  return	Frequency of Core System
354  */
CLOCK_GetCoreSysClkFreq(void)355 uint32_t CLOCK_GetCoreSysClkFreq(void)
356 {
357     uint32_t freq = 0U;
358 
359     switch (SYSCON->MAINCLKSELB)
360     {
361         case 0U:
362             if (SYSCON->MAINCLKSELA == 0U)
363             {
364                 freq = CLOCK_GetFro12MFreq();
365             }
366             else if (SYSCON->MAINCLKSELA == 1U)
367             {
368                 freq = CLOCK_GetExtClkFreq();
369             }
370             else if (SYSCON->MAINCLKSELA == 2U)
371             {
372                 freq = CLOCK_GetWdtOscFreq();
373             }
374             else if (SYSCON->MAINCLKSELA == 3U)
375             {
376                 freq = CLOCK_GetFroHfFreq();
377             }
378             else
379             {
380                 /* Add comment to prevent the case of MISRA C-2012 rule 15.7. */
381             }
382             break;
383         case 2U:
384             freq = CLOCK_GetPllOutFreq();
385             break;
386 
387         case 3U:
388             freq = CLOCK_GetOsc32KFreq();
389             break;
390 
391         default:
392             assert(false);
393             break;
394     }
395 
396     return freq;
397 }
398 /*! brief	Return Frequency of I2S MCLK Clock
399  *  return	Frequency of I2S MCLK Clock
400  */
CLOCK_GetI2SMClkFreq(void)401 uint32_t CLOCK_GetI2SMClkFreq(void)
402 {
403     return s_I2S_Mclk_Freq;
404 }
405 
406 /*! brief	Return Frequency of Asynchronous APB Clock
407  *  return	Frequency of Asynchronous APB Clock Clock
408  */
CLOCK_GetAsyncApbClkFreq(void)409 uint32_t CLOCK_GetAsyncApbClkFreq(void)
410 {
411     async_clock_src_t clkSrc;
412     uint32_t clkRate;
413 
414     clkSrc = CLOCK_GetAsyncApbClkSrc();
415 
416     switch (clkSrc)
417     {
418         case kCLOCK_AsyncMainClk:
419             clkRate = CLOCK_GetCoreSysClkFreq();
420             break;
421         case kCLOCK_AsyncFro12Mhz:
422             clkRate = CLK_FRO_12MHZ;
423             break;
424         default:
425             clkRate = 0U;
426             break;
427     }
428 
429     return clkRate;
430 }
431 
432 /* Get FLEXCOMM Clk */
433 /*! brief	Return Frequency of Flexcomm functional Clock
434  *  return	Frequency of Flexcomm functional Clock
435  */
CLOCK_GetFlexCommClkFreq(uint32_t id)436 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
437 {
438     uint32_t freq = 0U;
439 
440     switch (SYSCON->FXCOMCLKSEL[id])
441     {
442         case 0U:
443             freq = CLOCK_GetFro12MFreq();
444             break;
445         case 1U:
446             freq = CLOCK_GetFroHfFreq();
447             break;
448         case 2U:
449             freq = CLOCK_GetPllOutFreq();
450             break;
451         case 3U:
452             freq = CLOCK_GetI2SMClkFreq();
453             break;
454         case 4U:
455             freq = CLOCK_GetFrgClkFreq();
456             break;
457 
458         default:
459             assert(false);
460             break;
461     }
462 
463     return freq;
464 }
465 
466 /* Get ADC Clk */
467 /*! brief	Return Frequency of Adc Clock
468  *  return	Frequency of Adc Clock.
469  */
CLOCK_GetAdcClkFreq(void)470 uint32_t CLOCK_GetAdcClkFreq(void)
471 {
472     uint32_t freq = 0U;
473 
474     switch (SYSCON->ADCCLKSEL)
475     {
476         case 0U:
477             freq = CLOCK_GetCoreSysClkFreq();
478             break;
479         case 1U:
480             freq = CLOCK_GetPllOutFreq();
481             break;
482         case 2U:
483             freq = CLOCK_GetFroHfFreq();
484             break;
485         case 7U:
486             freq = 0U;
487             break;
488         default:
489             assert(false);
490             break;
491     }
492 
493     return freq / ((SYSCON->ADCCLKDIV & 0xffU) + 1U);
494 }
495 
496 /* Get FRG Clk */
497 /*! brief	Return Input frequency for the Fractional baud rate generator
498  *  return	Input Frequency for FRG
499  */
CLOCK_GetFRGInputClock(void)500 uint32_t CLOCK_GetFRGInputClock(void)
501 {
502     uint32_t freq = 0U;
503 
504     switch (SYSCON->FRGCLKSEL)
505     {
506         case 0U:
507             freq = CLOCK_GetCoreSysClkFreq();
508             break;
509         case 1U:
510             freq = CLOCK_GetPllOutFreq();
511             break;
512         case 2U:
513             freq = CLOCK_GetFro12MFreq();
514             break;
515         case 3U:
516             freq = CLOCK_GetFroHfFreq();
517             break;
518 
519         default:
520             assert(false);
521             break;
522     }
523 
524     return freq;
525 }
526 
527 /* Get DMIC Clk */
528 /*! brief  Return Input frequency for the DMIC
529  *  return Input Frequency for DMIC
530  */
CLOCK_GetDmicClkFreq(void)531 uint32_t CLOCK_GetDmicClkFreq(void)
532 {
533     uint32_t freq = 0U;
534 
535     switch (SYSCON->DMICCLKSEL)
536     {
537         case 0U:
538             freq = CLOCK_GetFro12MFreq();
539             break;
540         case 1U:
541             freq = CLOCK_GetFroHfFreq();
542             break;
543         case 2U:
544             freq = CLOCK_GetPllOutFreq();
545             break;
546         case 3U:
547             freq = CLOCK_GetI2SMClkFreq();
548             break;
549         case 4U:
550             freq = CLOCK_GetCoreSysClkFreq();
551             break;
552         case 5U:
553             freq = CLOCK_GetWdtOscFreq();
554             break;
555         default:
556             assert(false);
557             break;
558     }
559 
560     return freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U);
561 }
562 
563 /*! brief	Set output of the Fractional baud rate generator
564  * param	freq	: Desired output frequency
565  * return	Error Code 0 - fail 1 - success
566  */
CLOCK_SetFRGClock(uint32_t freq)567 uint32_t CLOCK_SetFRGClock(uint32_t freq)
568 {
569     uint32_t input = CLOCK_GetFRGInputClock();
570     uint32_t mul;
571 
572     if ((freq > 48000000UL) || (freq > input) || (input / freq >= 2UL))
573     {
574         /* FRG output frequency should be less than equal to 48MHz */
575         return 0;
576     }
577     else
578     {
579         mul             = (uint32_t)((((uint64_t)input - freq) * 256UL) / ((uint64_t)freq));
580         SYSCON->FRGCTRL = (mul << SYSCON_FRGCTRL_MULT_SHIFT) | SYSCON_FRGCTRL_DIV_MASK;
581         return 1;
582     }
583 }
584 
585 /* Get FRG Clk */
586 /*! brief  Return Input frequency for the FRG
587  *  return Input Frequency for FRG
588  */
CLOCK_GetFrgClkFreq(void)589 uint32_t CLOCK_GetFrgClkFreq(void)
590 {
591     uint32_t freq = 0U;
592 
593     if ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK)
594     {
595         freq = (uint32_t)(((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1U)) /
596                           ((SYSCON_FRGCTRL_DIV_MASK + 1U) +
597                            ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)));
598     }
599     else
600     {
601         freq = 0U;
602     }
603 
604     return freq;
605 }
606 
607 /*! brief  Return Frequency of USB
608  *  return Frequency of USB
609  */
CLOCK_GetUsbClkFreq(void)610 uint32_t CLOCK_GetUsbClkFreq(void)
611 {
612     uint32_t freq = 0U;
613 
614     if (SYSCON->USBCLKSEL == 0U)
615     {
616         freq = CLOCK_GetFroHfFreq();
617     }
618     else if (SYSCON->USBCLKSEL == 1U)
619     {
620         freq = CLOCK_GetPllOutFreq();
621     }
622     else
623     {
624         /* Add comment to prevent the case of MISRA C-2012 rule 15.7. */
625     }
626 
627     return freq / ((SYSCON->USBCLKDIV & 0xffU) + 1U);
628 }
629 
630 /*! brief	Return Frequency of selected clock
631  *  return	Frequency of selected clock
632  */
CLOCK_GetFreq(clock_name_t clockName)633 uint32_t CLOCK_GetFreq(clock_name_t clockName)
634 {
635     uint32_t freq;
636     switch (clockName)
637     {
638         case kCLOCK_CoreSysClk:
639             freq = CLOCK_GetCoreSysClkFreq();
640             break;
641         case kCLOCK_BusClk:
642             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
643             break;
644         case kCLOCK_FroHf:
645             freq = CLOCK_GetFroHfFreq();
646             break;
647         case kCLOCK_Fro12M:
648             freq = CLOCK_GetFro12MFreq();
649             break;
650         case kCLOCK_PllOut:
651             freq = CLOCK_GetPllOutFreq();
652             break;
653         case kCLOCK_UsbClk:
654             freq = CLOCK_GetUsbClkFreq();
655             break;
656         case kCLOCK_WdtOsc:
657             freq = CLOCK_GetWdtOscFreq();
658             break;
659         case kCLOCK_Frg:
660             freq = CLOCK_GetFrgClkFreq();
661             break;
662         case kCLOCK_AsyncApbClk:
663             freq = CLOCK_GetAsyncApbClkFreq();
664             break;
665         case kCLOCK_FlexI2S:
666             freq = CLOCK_GetI2SMClkFreq();
667             break;
668         default:
669             freq = 0U;
670             break;
671     }
672 
673     return freq;
674 }
675 
676 /* Set the FLASH wait states for the passed frequency */
677 /**
678  * brief	Set the flash wait states for the input freuqency.
679  * param	iFreq	: Input frequency
680  * return	Nothing
681  */
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)682 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)
683 {
684     if (iFreq <= 12000000U)
685     {
686         CLOCK_SetFLASHAccessCycles(kCLOCK_Flash1Cycle);
687     }
688     else if (iFreq <= 24000000U)
689     {
690         CLOCK_SetFLASHAccessCycles(kCLOCK_Flash2Cycle);
691     }
692     else if (iFreq <= 48000000U)
693     {
694         CLOCK_SetFLASHAccessCycles(kCLOCK_Flash3Cycle);
695     }
696     else if (iFreq <= 72000000U)
697     {
698         CLOCK_SetFLASHAccessCycles(kCLOCK_Flash4Cycle);
699     }
700     else if (iFreq <= 84000000U)
701     {
702         CLOCK_SetFLASHAccessCycles(kCLOCK_Flash5Cycle);
703     }
704     else if (iFreq <= 100000000U)
705     {
706         CLOCK_SetFLASHAccessCycles(kCLOCK_Flash6Cycle);
707     }
708     else
709     {
710         CLOCK_SetFLASHAccessCycles(kCLOCK_Flash7Cycle);
711     }
712 }
713 
714 /* Find encoded NDEC value for raw N value, max N = NVALMAX */
pllEncodeN(uint32_t N)715 static uint32_t pllEncodeN(uint32_t N)
716 {
717     uint32_t x, i;
718 
719     /* Find NDec */
720     switch (N)
721     {
722         case 0U:
723             x = 0x3FFU;
724             break;
725 
726         case 1U:
727             x = 0x302U;
728             break;
729 
730         case 2U:
731             x = 0x202U;
732             break;
733 
734         default:
735             x = 0x080U;
736             for (i = N; i <= NVALMAX; i++)
737             {
738                 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
739             }
740             break;
741     }
742 
743     return x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P);
744 }
745 
746 /* Find decoded N value for raw NDEC value */
pllDecodeN(uint32_t NDEC)747 static uint32_t pllDecodeN(uint32_t NDEC)
748 {
749     uint32_t n, x, i;
750 
751     /* Find NDec */
752     switch (NDEC)
753     {
754         case 0x3FFU:
755             n = 0U;
756             break;
757 
758         case 0x302U:
759             n = 1U;
760             break;
761 
762         case 0x202U:
763             n = 2U;
764             break;
765 
766         default:
767             x = 0x080U;
768             n = 0xFFFFFFFFU;
769             for (i = NVALMAX; i >= 3U; i--)
770             {
771                 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
772                 if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC)
773                 {
774                     /* Decoded value of NDEC */
775                     n = i;
776                     break;
777                 }
778             }
779             break;
780     }
781 
782     return n;
783 }
784 
785 /* Find encoded PDEC value for raw P value, max P = PVALMAX */
pllEncodeP(uint32_t P)786 static uint32_t pllEncodeP(uint32_t P)
787 {
788     uint32_t x, i;
789 
790     /* Find PDec */
791     switch (P)
792     {
793         case 0U:
794             x = 0x7FU;
795             break;
796 
797         case 1U:
798             x = 0x62U;
799             break;
800 
801         case 2U:
802             x = 0x42U;
803             break;
804 
805         default:
806             x = 0x10U;
807             for (i = P; i <= PVALMAX; i++)
808             {
809                 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);
810             }
811             break;
812     }
813 
814     return x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P);
815 }
816 
817 /* Find decoded P value for raw PDEC value */
pllDecodeP(uint32_t PDEC)818 static uint32_t pllDecodeP(uint32_t PDEC)
819 {
820     uint32_t p, x, i;
821 
822     /* Find PDec */
823     switch (PDEC)
824     {
825         case 0x7FU:
826             p = 0U;
827             break;
828 
829         case 0x62U:
830             p = 1U;
831             break;
832 
833         case 0x42U:
834             p = 2U;
835             break;
836 
837         default:
838             x = 0x10U;
839             p = 0xFFFFFFFFU;
840             for (i = PVALMAX; i >= 3U; i--)
841             {
842                 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);
843                 if ((x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P)) == PDEC)
844                 {
845                     /* Decoded value of PDEC */
846                     p = i;
847                     break;
848                 }
849             }
850             break;
851     }
852 
853     return p;
854 }
855 
856 /* Find encoded MDEC value for raw M value, max M = MVALMAX */
pllEncodeM(uint32_t M)857 static uint32_t pllEncodeM(uint32_t M)
858 {
859     uint32_t i, x;
860 
861     /* Find MDec */
862     switch (M)
863     {
864         case 0U:
865             x = 0x1FFFFU;
866             break;
867 
868         case 1U:
869             x = 0x18003U;
870             break;
871 
872         case 2U:
873             x = 0x10003U;
874             break;
875 
876         default:
877             x = 0x04000U;
878             for (i = M; i <= MVALMAX; i++)
879             {
880                 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
881             }
882             break;
883     }
884 
885     return x & (PLL_SSCG0_MDEC_VAL_M >> PLL_SSCG0_MDEC_VAL_P);
886 }
887 
888 /* Find decoded M value for raw MDEC value */
pllDecodeM(uint32_t MDEC)889 static uint32_t pllDecodeM(uint32_t MDEC)
890 {
891     uint32_t m, i, x;
892 
893     /* Find MDec */
894     switch (MDEC)
895     {
896         case 0x1FFFFU:
897             m = 0U;
898             break;
899 
900         case 0x18003U:
901             m = 1U;
902             break;
903 
904         case 0x10003U:
905             m = 2U;
906             break;
907 
908         default:
909             x = 0x04000U;
910             m = 0xFFFFFFFFU;
911             for (i = MVALMAX; i >= 3U; i--)
912             {
913                 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
914                 if ((x & (PLL_SSCG0_MDEC_VAL_M >> PLL_SSCG0_MDEC_VAL_P)) == MDEC)
915                 {
916                     /* Decoded value of MDEC */
917                     m = i;
918                     break;
919                 }
920             }
921             break;
922     }
923 
924     return m;
925 }
926 
927 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
pllFindSel(uint32_t M,bool bypassFBDIV2,uint32_t * pSelP,uint32_t * pSelI,uint32_t * pSelR)928 static void pllFindSel(uint32_t M, bool bypassFBDIV2, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
929 {
930     /* bandwidth: compute selP from Multiplier */
931     if (M < 60U)
932     {
933         *pSelP = (M >> 1U) + 1U;
934     }
935     else
936     {
937         *pSelP = PVALMAX - 1U;
938     }
939 
940     /* bandwidth: compute selI from Multiplier */
941     if (M > 16384U)
942     {
943         *pSelI = 1U;
944     }
945     else if (M > 8192U)
946     {
947         *pSelI = 2U;
948     }
949     else if (M > 2048U)
950     {
951         *pSelI = 4U;
952     }
953     else if (M >= 501U)
954     {
955         *pSelI = 8U;
956     }
957     else if (M >= 60U)
958     {
959         *pSelI = 4U * (1024U / (M + 9U));
960     }
961     else
962     {
963         *pSelI = (M & 0x3CU) + 4U;
964     }
965 
966     if (*pSelI > ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT))
967     {
968         *pSelI = ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT);
969     }
970 
971     *pSelR = 0U;
972 }
973 
974 /* Get predivider (N) from PLL NDEC setting */
findPllPreDiv(uint32_t ctrlReg,uint32_t nDecReg)975 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg)
976 {
977     uint32_t preDiv = 1;
978 
979     /* Direct input is not used? */
980     if ((ctrlReg & (1UL << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT)) == 0U)
981     {
982         /* Decode NDEC value to get (N) pre divider */
983         preDiv = pllDecodeN(nDecReg & 0x3FFU);
984         if (preDiv == 0U)
985         {
986             preDiv = 1U;
987         }
988     }
989 
990     /* Adjusted by 1, directi is used to bypass */
991     return preDiv;
992 }
993 
994 /* Get postdivider (P) from PLL PDEC setting */
findPllPostDiv(uint32_t ctrlReg,uint32_t pDecReg)995 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg)
996 {
997     uint32_t postDiv = 1U;
998 
999     /* Direct input is not used? */
1000     if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0U)
1001     {
1002         /* Decode PDEC value to get (P) post divider */
1003         postDiv = 2U * pllDecodeP(pDecReg & 0x7FU);
1004         if (postDiv == 0U)
1005         {
1006             postDiv = 2U;
1007         }
1008     }
1009 
1010     /* Adjusted by 1, directo is used to bypass */
1011     return postDiv;
1012 }
1013 
1014 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
findPllMMult(uint32_t ctrlReg,uint32_t mDecReg)1015 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)
1016 {
1017     uint32_t mMult = 1U;
1018 
1019     /* Decode MDEC value to get (M) multiplier */
1020     mMult = pllDecodeM(mDecReg & 0x1FFFFU);
1021 
1022     /* Extra multiply by 2 needed? */
1023     if ((ctrlReg & (SYSCON_SYSPLLCTRL_BYPASSCCODIV2_MASK)) == 0U)
1024     {
1025         mMult = mMult << 1U;
1026     }
1027 
1028     if (mMult == 0U)
1029     {
1030         mMult = 1U;
1031     }
1032 
1033     return mMult;
1034 }
1035 
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1036 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1037 {
1038     uint32_t tmp;
1039 
1040     while (n != 0U)
1041     {
1042         tmp = n;
1043         n   = m % n;
1044         m   = tmp;
1045     }
1046 
1047     return m;
1048 }
1049 
1050 /*
1051  * Set PLL output based on desired output rate.
1052  * In this function, the it calculates the PLL setting for output frequency from input clock
1053  * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1054  * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1055  */
CLOCK_GetPllConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useFeedbackDiv2,bool useSS)1056 static pll_error_t CLOCK_GetPllConfigInternal(
1057     uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useFeedbackDiv2, bool useSS)
1058 {
1059     uint32_t nDivOutHz, fccoHz, multFccoDiv;
1060     uint32_t pllPreDivider, pllMultiplier, pllBypassFBDIV2, pllPostDivider;
1061     uint32_t pllDirectInput, pllDirectOutput;
1062     uint32_t pllSelP, pllSelI, pllSelR, bandsel, uplimoff;
1063 
1064     /* Baseline parameters (no input or output dividers) */
1065     pllPreDivider   = 1U; /* 1 implies pre-divider will be disabled */
1066     pllPostDivider  = 0U; /* 0 implies post-divider will be disabled */
1067     pllDirectOutput = 1U;
1068     if (useFeedbackDiv2)
1069     {
1070         /* Using feedback divider for M, so disable bypass */
1071         pllBypassFBDIV2 = 0U;
1072     }
1073     else
1074     {
1075         pllBypassFBDIV2 = 1U;
1076     }
1077     multFccoDiv = (2U - pllBypassFBDIV2);
1078 
1079     /* Verify output rate parameter */
1080     if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1081     {
1082         /* Maximum PLL output with post divider=1 cannot go above this frequency */
1083         return kStatus_PLL_OutputTooHigh;
1084     }
1085     if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1086     {
1087         /* Minmum PLL output with maximum post divider cannot go below this frequency */
1088         return kStatus_PLL_OutputTooLow;
1089     }
1090 
1091     /* If using SS mode, input clock needs to be between 2MHz and 4MHz */
1092     if (useSS)
1093     {
1094         /* Verify input rate parameter */
1095         if (finHz < PLL_MIN_IN_SSMODE)
1096         {
1097             /* Input clock into the PLL cannot be lower than this */
1098             return kStatus_PLL_InputTooLow;
1099         }
1100         /* PLL input in SS mode must be under 4MHz */
1101         pllPreDivider = finHz / ((PLL_MIN_IN_SSMODE + PLL_MAX_IN_SSMODE) / 2U);
1102         if (pllPreDivider > NVALMAX)
1103         {
1104             return kStatus_PLL_InputTooHigh;
1105         }
1106     }
1107     else
1108     {
1109         /* Verify input rate parameter */
1110         if (finHz < PLL_LOWER_IN_LIMIT)
1111         {
1112             /* Input clock into the PLL cannot be lower than this */
1113             return kStatus_PLL_InputTooLow;
1114         }
1115     }
1116 
1117     /* Find the optimal CCO frequency for the output and input that
1118        will keep it inside the PLL CCO range. This may require
1119        tweaking the post-divider for the PLL. */
1120     fccoHz = foutHz;
1121     while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1122     {
1123         /* CCO output is less than minimum CCO range, so the CCO output
1124            needs to be bumped up and the post-divider is used to bring
1125            the PLL output back down. */
1126         pllPostDivider++;
1127         if (pllPostDivider > PVALMAX)
1128         {
1129             return kStatus_PLL_OutsideIntLimit;
1130         }
1131 
1132         /* Target CCO goes up, PLL output goes down */
1133         fccoHz          = foutHz * (pllPostDivider * 2U);
1134         pllDirectOutput = 0U;
1135     }
1136 
1137     /* Determine if a pre-divider is needed to get the best frequency */
1138     if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
1139     {
1140         uint32_t a = FindGreatestCommonDivisor(fccoHz, (multFccoDiv * finHz));
1141 
1142         if (a > 20000U)
1143         {
1144             a = (multFccoDiv * finHz) / a;
1145             if ((a != 0U) && (a < PLL_MAX_N_DIV))
1146             {
1147                 pllPreDivider = a;
1148             }
1149         }
1150     }
1151 
1152     /* Bypass pre-divider hardware if pre-divider is 1 */
1153     if (pllPreDivider > 1U)
1154     {
1155         pllDirectInput = 0U;
1156     }
1157     else
1158     {
1159         pllDirectInput = 1U;
1160     }
1161 
1162     /* Determine PLL multipler */
1163     nDivOutHz     = (finHz / pllPreDivider);
1164     pllMultiplier = (fccoHz / nDivOutHz) / multFccoDiv;
1165 
1166     /* Find optimal values for filter */
1167     if (useSS == false)
1168     {
1169         /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1170         if ((nDivOutHz * ((multFccoDiv * pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1171         {
1172             pllMultiplier++;
1173         }
1174 
1175         /* Setup filtering */
1176         pllFindSel(pllMultiplier, (bool)pllBypassFBDIV2, &pllSelP, &pllSelI, &pllSelR);
1177         bandsel  = 1U;
1178         uplimoff = 0U;
1179 
1180         /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1181         pSetup->syspllssctrl[0] =
1182             (PLL_SSCG0_MDEC_VAL_SET(pllEncodeM(pllMultiplier)) | (1UL << SYSCON_SYSPLLSSCTRL0_SEL_EXT_SHIFT));
1183 
1184         /* Power down SSC, not used */
1185         pSetup->syspllssctrl[1] = (1UL << SYSCON_SYSPLLSSCTRL1_PD_SHIFT);
1186     }
1187     else
1188     {
1189         uint64_t fc;
1190 
1191         /* Filtering will be handled by SSC */
1192         pllSelR  = 0U;
1193         pllSelI  = 0U;
1194         pllSelP  = 0U;
1195         bandsel  = 0U;
1196         uplimoff = 1U;
1197 
1198         /* The PLL multiplier will get very close and slightly under the
1199            desired target frequency. A small fractional component can be
1200            added to fine tune the frequency upwards to the target. */
1201         fc = (((uint64_t)fccoHz % ((uint64_t)multFccoDiv * nDivOutHz)) << 11U) / ((uint64_t)multFccoDiv * nDivOutHz);
1202 
1203         /* MDEC set by SSC */
1204         pSetup->syspllssctrl[0U] = 0U;
1205 
1206         /* Set multiplier */
1207         pSetup->syspllssctrl[1] = PLL_SSCG1_MD_INT_SET(pllMultiplier) | PLL_SSCG1_MD_FRACT_SET((uint32_t)fc);
1208     }
1209 
1210     /* Get encoded values for N (prediv) and P (postdiv) */
1211     pSetup->syspllndec = PLL_NDEC_VAL_SET(pllEncodeN(pllPreDivider));
1212     pSetup->syspllpdec = PLL_PDEC_VAL_SET(pllEncodeP(pllPostDivider));
1213 
1214     /* PLL control */
1215     pSetup->syspllctrl = (pllSelR << SYSCON_SYSPLLCTRL_SELR_SHIFT) |                  /* Filter coefficient */
1216                          (pllSelI << SYSCON_SYSPLLCTRL_SELI_SHIFT) |                  /* Filter coefficient */
1217                          (pllSelP << SYSCON_SYSPLLCTRL_SELP_SHIFT) |                  /* Filter coefficient */
1218                          (0UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT) |                    /* PLL bypass mode disabled */
1219                          (pllBypassFBDIV2 << SYSCON_SYSPLLCTRL_BYPASSCCODIV2_SHIFT) | /* Extra M / 2 divider? */
1220                          (uplimoff << SYSCON_SYSPLLCTRL_UPLIMOFF_SHIFT) |             /* SS/fractional mode disabled */
1221                          (bandsel << SYSCON_SYSPLLCTRL_BANDSEL_SHIFT) |        /* Manual bandwidth selection enabled */
1222                          (pllDirectInput << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT) | /* Bypass pre-divider? */
1223                          (pllDirectOutput << SYSCON_SYSPLLCTRL_DIRECTO_SHIFT); /* Bypass post-divider? */
1224 
1225     return kStatus_PLL_Success;
1226 }
1227 
1228 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1229 /* Alloct the static buffer for cache. */
1230 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1231 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]       = {0};
1232 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]      = {0};
1233 static bool s_UseFeedbackDiv2Cache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {false};
1234 static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]           = {false};
1235 static uint32_t s_PllSetupCacheIdx                                       = 0U;
1236 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1237 
1238 /*
1239  * Calculate the PLL setting values from input clock freq to output freq.
1240  */
CLOCK_GetPllConfig(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useFeedbackDiv2,bool useSS)1241 static pll_error_t CLOCK_GetPllConfig(
1242     uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useFeedbackDiv2, bool useSS)
1243 {
1244     pll_error_t retErr;
1245 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1246     uint32_t i;
1247 
1248     for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1249     {
1250         if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) &&
1251             (useFeedbackDiv2 == s_UseFeedbackDiv2Cache[i]) && (useSS == s_UseSSCache[i]))
1252         {
1253             /* Hit the target in cache buffer. */
1254             pSetup->syspllctrl      = s_PllSetupCacheStruct[i].syspllctrl;
1255             pSetup->syspllndec      = s_PllSetupCacheStruct[i].syspllndec;
1256             pSetup->syspllpdec      = s_PllSetupCacheStruct[i].syspllpdec;
1257             pSetup->syspllssctrl[0] = s_PllSetupCacheStruct[i].syspllssctrl[0];
1258             pSetup->syspllssctrl[1] = s_PllSetupCacheStruct[i].syspllssctrl[1];
1259             retErr                  = kStatus_PLL_Success;
1260             break;
1261         }
1262     }
1263 
1264     if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1265     {
1266         return retErr;
1267     }
1268 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1269 
1270     retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup, useFeedbackDiv2, useSS);
1271 
1272 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1273     /* Cache the most recent calulation result into buffer. */
1274     s_FinHzCache[s_PllSetupCacheIdx]           = finHz;
1275     s_FoutHzCache[s_PllSetupCacheIdx]          = foutHz;
1276     s_UseFeedbackDiv2Cache[s_PllSetupCacheIdx] = useFeedbackDiv2;
1277     s_UseSSCache[s_PllSetupCacheIdx]           = useSS;
1278 
1279     s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllctrl      = pSetup->syspllctrl;
1280     s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllndec      = pSetup->syspllndec;
1281     s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllpdec      = pSetup->syspllpdec;
1282     s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllssctrl[0] = pSetup->syspllssctrl[0];
1283     s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllssctrl[1] = pSetup->syspllssctrl[1];
1284     /* Update the index for next available buffer. */
1285     s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1286 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1287 
1288     return retErr;
1289 }
1290 
1291 /* Update local PLL rate variable */
CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t * pSetup)1292 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup)
1293 {
1294     s_Pll_Freq = CLOCK_GetSystemPLLOutFromSetup(pSetup);
1295 }
1296 
1297 /* Return System PLL input clock rate */
1298 /*! brief	Return System PLL input clock rate
1299  *  return	System PLL input clock rate
1300  */
CLOCK_GetSystemPLLInClockRate(void)1301 uint32_t CLOCK_GetSystemPLLInClockRate(void)
1302 {
1303     uint32_t clkRate = 0U;
1304 
1305     switch ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK))
1306     {
1307         case 0x00U:
1308             clkRate = CLK_FRO_12MHZ;
1309             break;
1310 
1311         case 0x01U:
1312             clkRate = CLOCK_GetExtClkFreq();
1313             break;
1314 
1315         case 0x02U:
1316             clkRate = CLOCK_GetWdtOscFreq();
1317             break;
1318 
1319         case 0x03U:
1320             clkRate = CLOCK_GetOsc32KFreq();
1321             break;
1322 
1323         default:
1324             clkRate = 0U;
1325             break;
1326     }
1327 
1328     return clkRate;
1329 }
1330 
1331 /* Return System PLL output clock rate from setup structure */
1332 /*! brief	Return System PLL output clock rate from setup structure
1333  *  param	pSetup	: Pointer to a PLL setup structure
1334  *  return	System PLL output clock rate calculated from the setup structure
1335  */
CLOCK_GetSystemPLLOutFromSetup(pll_setup_t * pSetup)1336 uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup)
1337 {
1338     uint32_t prediv, postdiv, mMult, inPllRate;
1339     uint64_t workRate;
1340 
1341     /* Get the input clock frequency of PLL. */
1342     inPllRate = CLOCK_GetSystemPLLInClockRate();
1343 
1344     /*
1345      * If the PLL is bypassed, PLL would not be used and the output of PLL module would just be the input clock.
1346      */
1347     if ((pSetup->syspllctrl & (SYSCON_SYSPLLCTRL_BYPASS_MASK)) == 0U)
1348     {
1349         /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1350         /*
1351          * 1. Pre-divider
1352          * Pre-divider is only available when the DIRECTI is disabled.
1353          */
1354         if (0U == (pSetup->syspllctrl & SYSCON_SYSPLLCTRL_DIRECTI_MASK))
1355         {
1356             prediv = findPllPreDiv(pSetup->syspllctrl, pSetup->syspllndec);
1357         }
1358         else
1359         {
1360             prediv = 1U; /* The pre-divider is bypassed. */
1361         }
1362         /* Adjust input clock */
1363         inPllRate = inPllRate / prediv;
1364 
1365         /*
1366          * 2. M divider
1367          * If using the SS, use the multiplier.
1368          */
1369         if ((pSetup->syspllssctrl[1] & (SYSCON_SYSPLLSSCTRL1_PD_MASK)) != 0UL)
1370         {
1371             /* MDEC used for rate */
1372             mMult    = findPllMMult(pSetup->syspllctrl, pSetup->syspllssctrl[0]);
1373             workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1374         }
1375         else
1376         {
1377             uint64_t fract;
1378 
1379             /* SS multipler used for rate */
1380             mMult    = (pSetup->syspllssctrl[1] & PLL_SSCG1_MD_INT_M) >> PLL_SSCG1_MD_INT_P;
1381             workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1382 
1383             /* Adjust by fractional */
1384             fract    = ((uint64_t)(pSetup->syspllssctrl[1]) & PLL_SSCG1_MD_FRACT_M) >> PLL_SSCG1_MD_FRACT_P;
1385             workRate = workRate + ((inPllRate * fract) / 0x800U);
1386         }
1387 
1388         /*
1389          * 3. Post-divider
1390          * Post-divider is only available when the DIRECTO is disabled.
1391          */
1392         if (0U == (pSetup->syspllctrl & SYSCON_SYSPLLCTRL_DIRECTO_MASK))
1393         {
1394             postdiv = findPllPostDiv(pSetup->syspllctrl, pSetup->syspllpdec);
1395         }
1396         else
1397         {
1398             postdiv = 1U; /* The post-divider is bypassed. */
1399         }
1400         workRate = workRate / ((uint64_t)postdiv);
1401     }
1402     else
1403     {
1404         /* In bypass mode */
1405         workRate = (uint64_t)inPllRate;
1406     }
1407 
1408     return (uint32_t)workRate;
1409 }
1410 
1411 /* Set the current PLL Rate */
1412 /*! brief Store the current PLL rate
1413  *  param	rate: Current rate of the PLL
1414  *  return	Nothing
1415  **/
CLOCK_SetStoredPLLClockRate(uint32_t rate)1416 void CLOCK_SetStoredPLLClockRate(uint32_t rate)
1417 {
1418     s_Pll_Freq = rate;
1419 }
1420 
1421 /* Return System PLL output clock rate */
1422 /*! brief	Return System PLL output clock rate
1423  *  param	recompute	: Forces a PLL rate recomputation if true
1424  *  return	System PLL output clock rate
1425  *  note	The PLL rate is cached in the driver in a variable as
1426  *  the rate computation function can take some time to perform. It
1427  *  is recommended to use 'false' with the 'recompute' parameter.
1428  */
CLOCK_GetSystemPLLOutClockRate(bool recompute)1429 uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute)
1430 {
1431     pll_setup_t Setup;
1432     uint32_t rate;
1433 
1434     if ((recompute) || (s_Pll_Freq == 0U))
1435     {
1436         Setup.syspllctrl      = SYSCON->SYSPLLCTRL;
1437         Setup.syspllndec      = SYSCON->SYSPLLNDEC;
1438         Setup.syspllpdec      = SYSCON->SYSPLLPDEC;
1439         Setup.syspllssctrl[0] = SYSCON->SYSPLLSSCTRL0;
1440         Setup.syspllssctrl[1] = SYSCON->SYSPLLSSCTRL1;
1441 
1442         CLOCK_GetSystemPLLOutFromSetupUpdate(&Setup);
1443     }
1444 
1445     rate = s_Pll_Freq;
1446 
1447     return rate;
1448 }
1449 
1450 /* Set PLL output based on the passed PLL setup data */
1451 /*! brief	Set PLL output based on the passed PLL setup data
1452  *  param	pControl	: Pointer to populated PLL control structure to generate setup with
1453  *  param	pSetup		: Pointer to PLL setup structure to be filled
1454  *  return	PLL_ERROR_SUCCESS on success, or PLL setup error code
1455  *  note	Actual frequency for setup may vary from the desired frequency based on the
1456  *  accuracy of input clocks, rounding, non-fractional PLL mode, etc.
1457  */
CLOCK_SetupPLLData(pll_config_t * pControl,pll_setup_t * pSetup)1458 pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup)
1459 {
1460     uint32_t inRate;
1461     bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0U);
1462     bool useFbDiv2;
1463 
1464     pll_error_t pllError;
1465 
1466     /* Determine input rate for the PLL */
1467     if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0UL)
1468     {
1469         inRate = pControl->inputRate;
1470     }
1471     else
1472     {
1473         inRate = CLOCK_GetSystemPLLInClockRate();
1474     }
1475 
1476     if ((pSetup->flags & PLL_SETUPFLAG_USEFEEDBACKDIV2) != 0UL)
1477     {
1478         useFbDiv2 = true;
1479     }
1480     else
1481     {
1482         useFbDiv2 = false;
1483     }
1484 
1485     /* PLL flag options */
1486     pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup, useFbDiv2, useSS);
1487     if ((useSS) && (pllError == kStatus_PLL_Success))
1488     {
1489         /* If using SS mode, then some tweaks are made to the generated setup */
1490         pSetup->syspllssctrl[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
1491         if (pControl->mfDither)
1492         {
1493             pSetup->syspllssctrl[1] |= (1UL << SYSCON_SYSPLLSSCTRL1_DITHER_SHIFT);
1494         }
1495     }
1496 
1497     return pllError;
1498 }
1499 
1500 /* Set PLL output from PLL setup structure */
1501 /*! brief	Set PLL output from PLL setup structure (precise frequency)
1502  * param	pSetup	: Pointer to populated PLL setup structure
1503  * param flagcfg : Flag configuration for PLL config structure
1504  * return	PLL_ERROR_SUCCESS on success, or PLL setup error code
1505  * note	This function will power off the PLL, setup the PLL with the
1506  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1507  * and adjust system voltages to the new PLL rate. The function will not
1508  * alter any source clocks (ie, main systen clock) that may use the PLL,
1509  * so these should be setup prior to and after exiting the function.
1510  */
CLOCK_SetupSystemPLLPrec(pll_setup_t * pSetup,uint32_t flagcfg)1511 pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)
1512 {
1513     /* Power off PLL during setup changes */
1514     POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);
1515 
1516     pSetup->flags = flagcfg;
1517 
1518     /* Write PLL setup data */
1519     SYSCON->SYSPLLCTRL    = pSetup->syspllctrl;
1520     SYSCON->SYSPLLNDEC    = pSetup->syspllndec;
1521     SYSCON->SYSPLLNDEC    = pSetup->syspllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
1522     SYSCON->SYSPLLPDEC    = pSetup->syspllpdec;
1523     SYSCON->SYSPLLPDEC    = pSetup->syspllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
1524     SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0];
1525     SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0] | (1UL << SYSCON_SYSPLLSSCTRL0_MREQ_SHIFT); /* latch */
1526     SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1];
1527     SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1] | (1UL << SYSCON_SYSPLLSSCTRL1_MDREQ_SHIFT); /* latch */
1528 
1529     /* Flags for lock or power on */
1530     if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0UL)
1531     {
1532         /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
1533         uint32_t maxCCO    = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
1534         uint32_t curSSCTRL = SYSCON->SYSPLLSSCTRL0 & ~(1UL << 17U);
1535 
1536         /* Initialize  and power up PLL */
1537         SYSCON->SYSPLLSSCTRL0 = maxCCO;
1538         POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
1539 
1540         /* Set mreq to activate */
1541         SYSCON->SYSPLLSSCTRL0 = maxCCO | (1UL << 17U);
1542 
1543         /* Delay for 72 uSec @ 12Mhz */
1544         SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1545 
1546         /* clear mreq to prepare for restoring mreq */
1547         SYSCON->SYSPLLSSCTRL0 = curSSCTRL;
1548 
1549         /* set original value back and activate */
1550         SYSCON->SYSPLLSSCTRL0 = curSSCTRL | (1UL << 17U);
1551 
1552         /* Enable peripheral states by setting low */
1553         POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
1554     }
1555     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1556     {
1557         while (CLOCK_IsSystemPLLLocked() == false)
1558         {
1559         }
1560     }
1561 
1562     /* Update current programmed PLL rate var */
1563     CLOCK_GetSystemPLLOutFromSetupUpdate(pSetup);
1564 
1565     /* System voltage adjustment, occurs prior to setting main system clock */
1566     if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0UL)
1567     {
1568         POWER_SetVoltageForFreq(s_Pll_Freq);
1569     }
1570 
1571     return kStatus_PLL_Success;
1572 }
1573 
1574 /* Setup PLL Frequency from pre-calculated value */
1575 /**
1576  * brief	Set PLL output from PLL setup structure (precise frequency)
1577  * param	pSetup	: Pointer to populated PLL setup structure
1578  * return	kStatus_PLL_Success on success, or PLL setup error code
1579  * note	This function will power off the PLL, setup the PLL with the
1580  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1581  * and adjust system voltages to the new PLL rate. The function will not
1582  * alter any source clocks (ie, main systen clock) that may use the PLL,
1583  * so these should be setup prior to and after exiting the function.
1584  */
CLOCK_SetPLLFreq(const pll_setup_t * pSetup)1585 pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup)
1586 {
1587     /* Power off PLL during setup changes */
1588     POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);
1589 
1590     /* Write PLL setup data */
1591     SYSCON->SYSPLLCTRL    = pSetup->syspllctrl;
1592     SYSCON->SYSPLLNDEC    = pSetup->syspllndec;
1593     SYSCON->SYSPLLNDEC    = pSetup->syspllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
1594     SYSCON->SYSPLLPDEC    = pSetup->syspllpdec;
1595     SYSCON->SYSPLLPDEC    = pSetup->syspllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
1596     SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0];
1597     SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0] | (1UL << SYSCON_SYSPLLSSCTRL0_MREQ_SHIFT); /* latch */
1598     SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1];
1599     SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1] | (1UL << SYSCON_SYSPLLSSCTRL1_MDREQ_SHIFT); /* latch */
1600 
1601     /* Flags for lock or power on */
1602     if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0UL)
1603     {
1604         /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
1605         uint32_t maxCCO    = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
1606         uint32_t curSSCTRL = SYSCON->SYSPLLSSCTRL0 & ~(1UL << 17U);
1607 
1608         /* Initialize  and power up PLL */
1609         SYSCON->SYSPLLSSCTRL0 = maxCCO;
1610         POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
1611 
1612         /* Set mreq to activate */
1613         SYSCON->SYSPLLSSCTRL0 = maxCCO | (1UL << 17U);
1614 
1615         /* Delay for 72 uSec @ 12Mhz */
1616         SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1617 
1618         /* clear mreq to prepare for restoring mreq */
1619         SYSCON->SYSPLLSSCTRL0 = curSSCTRL;
1620 
1621         /* set original value back and activate */
1622         SYSCON->SYSPLLSSCTRL0 = curSSCTRL | (1UL << 17U);
1623 
1624         /* Enable peripheral states by setting low */
1625         POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
1626     }
1627     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1628     {
1629         while (CLOCK_IsSystemPLLLocked() == false)
1630         {
1631         }
1632     }
1633 
1634     /* Update current programmed PLL rate var */
1635     s_Pll_Freq = pSetup->pllRate;
1636 
1637     return kStatus_PLL_Success;
1638 }
1639 
1640 /* Set System PLL clock based on the input frequency and multiplier */
1641 /*! brief	Set PLL output based on the multiplier and input frequency
1642  * param	multiply_by	: multiplier
1643  * param	input_freq	: Clock input frequency of the PLL
1644  * return	Nothing
1645  * note	Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
1646  * function does not disable or enable PLL power, wait for PLL lock,
1647  * or adjust system voltages. These must be done in the application.
1648  * The function will not alter any source clocks (ie, main systen clock)
1649  * that may use the PLL, so these should be setup prior to and after
1650  * exiting the function.
1651  */
CLOCK_SetupSystemPLLMult(uint32_t multiply_by,uint32_t input_freq)1652 void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq)
1653 {
1654     uint32_t cco_freq = input_freq * multiply_by;
1655     uint32_t pdec     = 1U;
1656     uint32_t selr;
1657     uint32_t seli;
1658     uint32_t selp;
1659     uint32_t mdec, ndec;
1660 
1661     uint32_t directo = SYSCON_SYSPLLCTRL_DIRECTO(1);
1662 
1663     while (cco_freq < 75000000U)
1664     {
1665         multiply_by <<= 1U; /* double value in each iteration */
1666         pdec <<= 1U;        /* correspondingly double pdec to cancel effect of double msel */
1667         cco_freq = input_freq * multiply_by;
1668     }
1669     selr = 0U;
1670     if (multiply_by < 60U)
1671     {
1672         seli = (multiply_by & 0x3cU) + 4U;
1673         selp = (multiply_by >> 1U) + 1U;
1674     }
1675     else
1676     {
1677         selp = 31U;
1678         if (multiply_by > 16384U)
1679         {
1680             seli = 1U;
1681         }
1682         else if (multiply_by > 8192U)
1683         {
1684             seli = 2U;
1685         }
1686         else if (multiply_by > 2048U)
1687         {
1688             seli = 4U;
1689         }
1690         else if (multiply_by >= 501U)
1691         {
1692             seli = 8U;
1693         }
1694         else
1695         {
1696             seli = 4U * (1024U / (multiply_by + 9U));
1697         }
1698     }
1699 
1700     if (pdec > 1U)
1701     {
1702         directo = 0U;        /* use post divider */
1703         pdec    = pdec / 2U; /* Account for minus 1 encoding */
1704                              /* Translate P value */
1705         switch (pdec)
1706         {
1707             case 1U:
1708                 pdec = 0x62U; /* 1  * 2 */
1709                 break;
1710             case 2U:
1711                 pdec = 0x42U; /* 2  * 2 */
1712                 break;
1713             case 4U:
1714                 pdec = 0x02U; /* 4  * 2 */
1715                 break;
1716             case 8U:
1717                 pdec = 0x0bU; /* 8  * 2 */
1718                 break;
1719             case 16U:
1720                 pdec = 0x11U; /* 16 * 2 */
1721                 break;
1722             case 32U:
1723                 pdec = 0x08U; /* 32 * 2 */
1724                 break;
1725             default:
1726                 pdec = 0x08U;
1727                 break;
1728         }
1729     }
1730 
1731     mdec = PLL_SSCG0_MDEC_VAL_SET(pllEncodeM(multiply_by));
1732     ndec = 0x302U; /* pre divide by 1 (hardcoded) */
1733 
1734     SYSCON->SYSPLLCTRL = SYSCON_SYSPLLCTRL_BANDSEL(1) | directo | SYSCON_SYSPLLCTRL_BYPASSCCODIV2(1) |
1735                          (selr << SYSCON_SYSPLLCTRL_SELR_SHIFT) | (seli << SYSCON_SYSPLLCTRL_SELI_SHIFT) |
1736                          (selp << SYSCON_SYSPLLCTRL_SELP_SHIFT);
1737     SYSCON->SYSPLLPDEC = pdec | (1UL << 7U);  /* set Pdec value and assert preq */
1738     SYSCON->SYSPLLNDEC = ndec | (1UL << 10U); /* set Pdec value and assert preq */
1739     SYSCON->SYSPLLSSCTRL0 =
1740         (1UL << 18U) | (1UL << 17U) | mdec; /* select non sscg MDEC value, assert mreq and select mdec value */
1741 }
CLOCK_EnableUsbfs0Clock(clock_usb_src_t src,uint32_t freq)1742 bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq)
1743 {
1744     bool ret = true;
1745 
1746     CLOCK_DisableClock(kCLOCK_Usbd0);
1747 
1748     if (kCLOCK_UsbSrcFro == src)
1749     {
1750         switch (freq)
1751         {
1752             case 96000000U:
1753                 CLOCK_SetClkDiv(kCLOCK_DivUsbClk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
1754                 break;
1755             case 48000000U:
1756                 CLOCK_SetClkDiv(kCLOCK_DivUsbClk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
1757                 break;
1758             default:
1759                 ret = false;
1760                 break;
1761         }
1762         /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
1763         SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
1764                           SYSCON_FROCTRL_USBCLKADJ_MASK;
1765         /* select FRO 96 or 48 MHz */
1766         CLOCK_AttachClk(kFRO_HF_to_USB_CLK);
1767     }
1768     else
1769     {
1770         /*TODO , we only implement FRO as usb clock source*/
1771         ret = false;
1772     }
1773 
1774     CLOCK_EnableClock(kCLOCK_Usbd0);
1775 
1776     return ret;
1777 }
1778