1 /*
2  * Copyright 2017 - 2021 , NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_clock.h"
9 #include "fsl_power.h"
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "platform.drivers.clock"
16 #endif
17 #define NVALMAX (0x100U)
18 #define PVALMAX (0x20U)
19 #define MVALMAX (0x10000U)
20 
21 #define PLL_MAX_N_DIV 0x100U
22 
23 /*--------------------------------------------------------------------------
24 !!! If required these #defines can be moved to chip library file
25 ----------------------------------------------------------------------------*/
26 
27 #define PLL_SSCG1_MDEC_VAL_P (10U) /* MDEC is in bits  25 downto 10 */
28 #define PLL_SSCG1_MDEC_VAL_M (0xFFFFULL << PLL_SSCG1_MDEC_VAL_P)
29 #define PLL_NDEC_VAL_P       (0U) /* NDEC is in bits  9:0 */
30 #define PLL_NDEC_VAL_M       (0xFFUL << PLL_NDEC_VAL_P)
31 #define PLL_PDEC_VAL_P       (0U) /*!<  PDEC is in bits 6:0 */
32 #define PLL_PDEC_VAL_M       (0x1FUL << PLL_PDEC_VAL_P)
33 
34 #define PLL_MIN_CCO_FREQ_MHZ (275000000U)
35 #define PLL_MAX_CCO_FREQ_MHZ (550000000U)
36 #define PLL_LOWER_IN_LIMIT   (2000U)     /*!<  Minimum PLL input rate */
37 #define PLL_HIGHER_IN_LIMIT  (96000000U) /*!<  Maximum PLL input rate */
38 #define PLL_MIN_IN_SSMODE    (3000000U)
39 #define PLL_MAX_IN_SSMODE \
40     (100000000U) /*!<  Not find the value in UM, Just use the maximum frequency which device support */
41 
42 /* PLL NDEC reg */
43 #define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)
44 /* PLL PDEC reg */
45 #define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)
46 /* SSCG control1 */
47 #define PLL_SSCG1_MDEC_VAL_SET(value) (((uint64_t)(value) << PLL_SSCG1_MDEC_VAL_P) & PLL_SSCG1_MDEC_VAL_M)
48 
49 /* PLL0 SSCG control1 */
50 #define PLL0_SSCG_MD_FRACT_P 0U
51 #define PLL0_SSCG_MD_INT_P   25U
52 #define PLL0_SSCG_MD_FRACT_M (0x1FFFFFFUL << PLL0_SSCG_MD_FRACT_P)
53 #define PLL0_SSCG_MD_INT_M   ((uint64_t)0xFFUL << PLL0_SSCG_MD_INT_P)
54 
55 #define PLL0_SSCG_MD_FRACT_SET(value) (((uint64_t)(value) << PLL0_SSCG_MD_FRACT_P) & PLL0_SSCG_MD_FRACT_M)
56 #define PLL0_SSCG_MD_INT_SET(value)   (((uint64_t)(value) << PLL0_SSCG_MD_INT_P) & PLL0_SSCG_MD_INT_M)
57 
58 /* Saved value of PLL output rate, computed whenever needed to save run-time
59    computation on each call to retrive the PLL rate. */
60 static uint32_t s_Pll0_Freq;
61 static uint32_t s_Pll1_Freq;
62 
63 /** External clock rate on the CLKIN pin in Hz. If not used,
64     set this to 0. Otherwise, set it to the exact rate in Hz this pin is
65     being driven at. */
66 static uint32_t s_Ext_Clk_Freq   = 16000000U;
67 static uint32_t s_I2S_Mclk_Freq  = 0U;
68 static uint32_t s_PLU_ClkIn_Freq = 0U;
69 
70 /*******************************************************************************
71  * Variables
72  ******************************************************************************/
73 
74 /*******************************************************************************
75  * Prototypes
76  ******************************************************************************/
77 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
78 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
79 /* Get predivider (N) from PLL0 NDEC setting */
80 static uint32_t findPll0PreDiv(void);
81 /* Get predivider (N) from PLL1 NDEC setting */
82 static uint32_t findPll1PreDiv(void);
83 /* Get postdivider (P) from PLL0 PDEC setting */
84 static uint32_t findPll0PostDiv(void);
85 /* Get postdivider (P) from PLL1 PDEC setting. */
86 static uint32_t findPll1PostDiv(void);
87 /* Get multiplier (M) from PLL0 MDEC and SSCG settings */
88 static float findPll0MMult(void);
89 /* Get multiplier (M) from PLL1 MDEC. */
90 static uint32_t findPll1MMult(void);
91 /* Get the greatest common divisor */
92 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
93 /* Set PLL output based on desired output rate */
94 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS);
95 /* Update local PLL rate variable */
96 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup);
97 /* Update local PLL1 rate variable */
98 static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup);
99 
100 /*******************************************************************************
101  * Code
102  ******************************************************************************/
103 
104 /* Clock Selection for IP */
105 /**
106  * brief   Configure the clock selection muxes.
107  * param   connection  : Clock to be configured.
108  * return  Nothing
109  */
CLOCK_AttachClk(clock_attach_id_t connection)110 void CLOCK_AttachClk(clock_attach_id_t connection)
111 {
112     uint8_t mux;
113     uint8_t sel;
114     uint16_t item;
115     uint32_t tmp32 = (uint32_t)connection;
116     uint32_t i;
117     volatile uint32_t *pClkSel;
118 
119     pClkSel = &(SYSCON->SYSTICKCLKSELX[0]);
120 
121     if (kNONE_to_NONE != connection)
122     {
123         for (i = 0U; i < 2U; i++)
124         {
125             if (tmp32 == 0U)
126             {
127                 break;
128             }
129             item = (uint16_t)GET_ID_ITEM(tmp32);
130             if (item != 0U)
131             {
132                 mux = (uint8_t)GET_ID_ITEM_MUX(item);
133                 sel = (uint8_t)GET_ID_ITEM_SEL(item);
134                 if (mux == CM_RTCOSC32KCLKSEL)
135                 {
136                     PMC->RTCOSC32K = (PMC->RTCOSC32K & ~PMC_RTCOSC32K_SEL_MASK) | PMC_RTCOSC32K_SEL(sel);
137                 }
138                 else if (mux == CM_OSTIMERCLKSEL)
139                 {
140                     PMC->OSTIMERr = (PMC->OSTIMERr & ~PMC_OSTIMER_OSTIMERCLKSEL_MASK) | PMC_OSTIMER_OSTIMERCLKSEL(sel);
141                 }
142                 else
143                 {
144                     pClkSel[mux] = sel;
145                 }
146             }
147             tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
148         }
149     }
150 }
151 
152 /* Return the actual clock attach id */
153 /**
154  * brief   Get the actual clock attach id.
155  * This fuction uses the offset in input attach id, then it reads the actual source value in
156  * the register and combine the offset to obtain an actual attach id.
157  * param   attachId  : Clock attach id to get.
158  * return  Clock source value.
159  */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)160 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
161 {
162     uint8_t mux;
163     uint32_t actualSel;
164     uint32_t tmp32 = (uint32_t)attachId;
165     uint32_t i;
166     uint32_t actualAttachId = 0U;
167     uint32_t selector       = GET_ID_SELECTOR(tmp32);
168     volatile uint32_t *pClkSel;
169 
170     pClkSel = &(SYSCON->SYSTICKCLKSELX[0]);
171 
172     if (kNONE_to_NONE == attachId)
173     {
174         return kNONE_to_NONE;
175     }
176 
177     for (i = 0U; i < 2U; i++)
178     {
179         mux = (uint8_t)GET_ID_ITEM_MUX(tmp32);
180         if (tmp32 != 0UL)
181         {
182             if (mux == CM_RTCOSC32KCLKSEL)
183             {
184                 actualSel = ((PMC->RTCOSC32K) & PMC_RTCOSC32K_SEL_MASK) >> PMC_RTCOSC32K_SEL_SHIFT;
185             }
186             else if (mux == CM_OSTIMERCLKSEL)
187             {
188                 actualSel = ((PMC->OSTIMERr) & PMC_OSTIMER_OSTIMERCLKSEL_MASK) >> PMC_OSTIMER_OSTIMERCLKSEL_SHIFT;
189             }
190             else
191             {
192                 actualSel = pClkSel[mux];
193             }
194 
195             /* Consider the combination of two registers */
196             actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
197         }
198         tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!<  pick up next descriptor */
199     }
200 
201     actualAttachId |= selector;
202 
203     return (clock_attach_id_t)actualAttachId;
204 }
205 
206 /* Set IP Clock Divider */
207 /**
208  * brief   Setup peripheral clock dividers.
209  * param   div_name    : Clock divider name
210  * param divided_by_value: Value to be divided
211  * param reset :  Whether to reset the divider counter.
212  * return  Nothing
213  */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value,bool reset)214 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
215 {
216     volatile uint32_t *pClkDiv;
217 
218     pClkDiv = &(SYSCON->SYSTICKCLKDIV0);
219 
220     if ((div_name >= kCLOCK_DivFlexFrg0) && (div_name <= kCLOCK_DivFlexFrg7))
221     {
222         /*!<  Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1+ MULT /DIV), DIV = 0xFF */
223         ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] =
224             SYSCON_FLEXFRG0CTRL_DIV_MASK | SYSCON_FLEXFRG0CTRL_MULT(divided_by_value);
225     }
226     else
227     {
228         if (reset)
229         {
230             ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 29U;
231         }
232         if (divided_by_value == 0U) /*!<  halt */
233         {
234             ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = 1UL << 30U;
235         }
236         else
237         {
238             ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] = (divided_by_value - 1U);
239         }
240     }
241 }
242 
243 /* Set RTC 1KHz Clock Divider */
244 /**
245  * brief   Setup rtc 1khz clock divider.
246  * param divided_by_value: Value to be divided
247  * return  Nothing
248  */
CLOCK_SetRtc1khzClkDiv(uint32_t divided_by_value)249 void CLOCK_SetRtc1khzClkDiv(uint32_t divided_by_value)
250 {
251     PMC->RTCOSC32K =
252         (PMC->RTCOSC32K & ~PMC_RTCOSC32K_CLK1KHZDIV_MASK) | PMC_RTCOSC32K_CLK1KHZDIV(divided_by_value - 28U);
253 }
254 
255 /* Set RTC 1KHz Clock Divider */
256 /**
257  * brief   Setup rtc 1hz clock divider.
258  * param divided_by_value: Value to be divided
259  * return  Nothing
260  */
CLOCK_SetRtc1hzClkDiv(uint32_t divided_by_value)261 void CLOCK_SetRtc1hzClkDiv(uint32_t divided_by_value)
262 {
263     if (divided_by_value == 0U) /*!<  halt */
264     {
265         PMC->RTCOSC32K |= (1UL << PMC_RTCOSC32K_CLK1HZDIVHALT_SHIFT);
266     }
267     else
268     {
269         PMC->RTCOSC32K =
270             (PMC->RTCOSC32K & ~PMC_RTCOSC32K_CLK1HZDIV_MASK) | PMC_RTCOSC32K_CLK1HZDIV(divided_by_value - 31744U);
271     }
272 }
273 
274 /* Set FRO Clocking */
275 /**
276  * brief   Initialize the Core clock to given frequency (12, 48 or 96 MHz).
277  * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
278  * enabled.
279  * param   iFreq   : Desired frequency (must be one of #CLK_FRO_12MHZ or #CLK_FRO_48MHZ or #CLK_FRO_96MHZ)
280  * return  returns success or fail status.
281  */
CLOCK_SetupFROClocking(uint32_t iFreq)282 status_t CLOCK_SetupFROClocking(uint32_t iFreq)
283 {
284     if ((iFreq != 12000000U) && (iFreq != 96000000U))
285     {
286         return kStatus_Fail;
287     }
288     /* Enable Analog Control module */
289     SYSCON->PRESETCTRLCLR[2] = (1UL << SYSCON_PRESETCTRL2_ANALOG_CTRL_RST_SHIFT);
290     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL_MASK;
291     /* Power up the FRO192M */
292     POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
293 
294     if (iFreq == 96000000U)
295     {
296         ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_96MHZCLK(1);
297     }
298     /* always enable
299     else if (iFreq == 48000000U)
300     {
301         ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_48MHZCLK(1);
302     }*/
303     else
304     {
305         ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_12MHZCLK(1);
306     }
307     return kStatus_Success;
308 }
309 
310 /* Set the FLASH wait states for the passed frequency */
311 /**
312  * brief    Set the flash wait states for the input freuqency.
313  * param    iFreq: Input frequency
314  * return    Nothing
315  */
316 typedef struct
317 {
318     uint32_t waitstate;
319     uint32_t freqMax;
320 } WaitStateInterval_t;
321 
322 /* clang-format off */
323 /* Wait state if frequency is inferior to the one specified */
324 static const WaitStateInterval_t IntervalList[] = {
325     {0, 11000000},
326     {1, 22000000},
327     {2, 33000000},
328     {3, 44000000},
329     {4, 55000000},
330     {5, 66000000},
331     {6, 84000000},
332     {7, 96000000} /* Maximum allowed frequency (96 MHz) */
333 };
334 /* clang-format on */
335 
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz)336 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz)
337 {
338     /* Flash Controller & FMC internal number of Wait States (minus 1) */
339     uint32_t num_wait_states      = 15UL; /* Default to the maximum number of wait states */
340     uint32_t prefetch_enable_mask = SYSCON->FMCCR & SYSCON_FMCCR_PREFEN_MASK;
341 
342     for (size_t cnt = 0; cnt < (sizeof(IntervalList) / sizeof(WaitStateInterval_t)); cnt++)
343     {
344         if (system_freq_hz <= IntervalList[cnt].freqMax)
345         {
346             num_wait_states = IntervalList[cnt].waitstate;
347             break;
348         }
349     }
350 
351     /*The prefetch bit must be disabled before any flash commands*/
352     SYSCON->FMCCR &= ~SYSCON_FMCCR_PREFEN_MASK;
353 
354     FLASH->INT_CLR_STATUS = 0x1F; /* Clear all status flags */
355 
356     FLASH->DATAW[0] = (FLASH->DATAW[0] & 0xFFFFFFF0UL) |
357                       (num_wait_states & (SYSCON_FMCCR_FLASHTIM_MASK >> SYSCON_FMCCR_FLASHTIM_SHIFT));
358 
359     FLASH->CMD = 0x2; /* CMD_SET_READ_MODE */
360 
361     /* Wait until the cmd is completed (without error) */
362     while ((FLASH->INT_STATUS & FLASH_INT_STATUS_DONE_MASK) == 0UL)
363     {
364     }
365 
366     /* Adjust FMC waiting time cycles (num_wait_states) */
367     SYSCON->FMCCR = (SYSCON->FMCCR & ~SYSCON_FMCCR_FLASHTIM_MASK) |
368                     ((num_wait_states << SYSCON_FMCCR_FLASHTIM_SHIFT) & SYSCON_FMCCR_FLASHTIM_MASK);
369 
370     /* restore prefetch enable */
371     SYSCON->FMCCR |= prefetch_enable_mask;
372 }
373 
374 /* Set EXT OSC Clk */
375 /**
376  * brief   Initialize the external osc clock to given frequency.
377  * Crystal oscillator with an operating frequency of 12 MHz to 32 MHz.
378  * Option for external clock input (bypass mode) for clock frequencies of up to 25 MHz.
379  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
380  * return  returns success or fail status.
381  */
CLOCK_SetupExtClocking(uint32_t iFreq)382 status_t CLOCK_SetupExtClocking(uint32_t iFreq)
383 {
384     if (iFreq > 32000000U)
385     {
386         return kStatus_Fail;
387     }
388     /* Turn on power for crystal 32 MHz */
389     POWER_DisablePD(kPDRUNCFG_PD_XTAL32M);
390     POWER_DisablePD(kPDRUNCFG_PD_LDOXO32M);
391     /* Enable clock_in clock for clock module. */
392     SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;
393 
394     /* Wait for external osc clock to be valid. */
395     while((ANACTRL->XO32M_STATUS & ANACTRL_XO32M_STATUS_XO_READY_MASK) == 0U)
396     {
397     }
398 
399     s_Ext_Clk_Freq = iFreq;
400     return kStatus_Success;
401 }
402 
403 /* Set I2S MCLK Clk */
404 /**
405  * brief   Initialize the I2S MCLK clock to given frequency.
406  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
407  * return  returns success or fail status.
408  */
CLOCK_SetupI2SMClkClocking(uint32_t iFreq)409 status_t CLOCK_SetupI2SMClkClocking(uint32_t iFreq)
410 {
411     s_I2S_Mclk_Freq = iFreq;
412     return kStatus_Success;
413 }
414 
415 /* Set PLU CLKIN Clk */
416 /**
417  * brief   Initialize the PLU CLKIN clock to given frequency.
418  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
419  * return  returns success or fail status.
420  */
CLOCK_SetupPLUClkInClocking(uint32_t iFreq)421 status_t CLOCK_SetupPLUClkInClocking(uint32_t iFreq)
422 {
423     s_PLU_ClkIn_Freq = iFreq;
424     return kStatus_Success;
425 }
426 
427 /* Get CLOCK OUT Clk */
428 /*! brief  Return Frequency of ClockOut
429  *  return Frequency of ClockOut
430  */
CLOCK_GetClockOutClkFreq(void)431 uint32_t CLOCK_GetClockOutClkFreq(void)
432 {
433     uint32_t freq = 0U;
434 
435     switch (SYSCON->CLKOUTSEL)
436     {
437         case 0U:
438             freq = CLOCK_GetCoreSysClkFreq();
439             break;
440 
441         case 1U:
442             freq = CLOCK_GetPll0OutFreq();
443             break;
444 
445         case 2U:
446             freq = CLOCK_GetExtClkFreq();
447             break;
448 
449         case 3U:
450             freq = CLOCK_GetFroHfFreq();
451             break;
452 
453         case 4U:
454             freq = CLOCK_GetFro1MFreq();
455             break;
456 
457         case 5U:
458             freq = CLOCK_GetPll1OutFreq();
459             break;
460 
461         case 6U:
462             freq = CLOCK_GetOsc32KFreq();
463             break;
464 
465         case 7U:
466             freq = 0U;
467             break;
468 
469         default:
470             freq = 0U;
471             break;
472     }
473     return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
474 }
475 
476 /* Get CAN Clk */
477 /*! brief  Return Frequency of Can Clock
478  *  return Frequency of Can.
479  */
CLOCK_GetMCanClkFreq(void)480 uint32_t CLOCK_GetMCanClkFreq(void)
481 {
482     uint32_t freq = 0U;
483 
484     switch (SYSCON->CANCLKSEL)
485     {
486         case 0U:
487             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CANCLKDIV & SYSCON_CANCLKDIV_DIV_MASK) + 1U);
488             break;
489         case 1U:
490             freq = CLOCK_GetFro1MFreq();
491             break;
492         case 2U:
493             freq = CLOCK_GetOsc32KFreq();
494             break;
495         case 7U:
496             freq = 0U;
497             break;
498 
499         default:
500             freq = 0U;
501             break;
502     }
503 
504     return freq;
505 }
506 
507 /* Get ADC Clk */
508 /*! brief  Return Frequency of Adc Clock
509  *  return Frequency of Adc.
510  */
CLOCK_GetAdcClkFreq(void)511 uint32_t CLOCK_GetAdcClkFreq(void)
512 {
513     uint32_t freq = 0U;
514 
515     switch (SYSCON->ADCCLKSEL)
516     {
517         case 0U:
518             freq = CLOCK_GetCoreSysClkFreq();
519             break;
520         case 1U:
521             freq = CLOCK_GetPll0OutFreq();
522             break;
523         case 2U:
524             freq = CLOCK_GetFroHfFreq();
525             break;
526         case 7U:
527             freq = 0U;
528             break;
529 
530         default:
531             freq = 0U;
532             break;
533     }
534 
535     return freq / ((SYSCON->ADCCLKDIV & SYSCON_ADCCLKDIV_DIV_MASK) + 1U);
536 }
537 
538 /* Get MCLK Clk */
539 /*! brief  Return Frequency of MClk Clock
540  *  return Frequency of MClk Clock.
541  */
CLOCK_GetMclkClkFreq(void)542 uint32_t CLOCK_GetMclkClkFreq(void)
543 {
544     uint32_t freq = 0U;
545 
546     switch (SYSCON->MCLKCLKSEL)
547     {
548         case 0U:
549             freq = CLOCK_GetFroHfFreq();
550             break;
551         case 1U:
552             freq = CLOCK_GetPll0OutFreq();
553             break;
554         case 7U:
555             freq = 0U;
556             break;
557 
558         default:
559             freq = 0U;
560             break;
561     }
562 
563     return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);
564 }
565 
566 /* Get SCTIMER Clk */
567 /*! brief  Return Frequency of SCTimer Clock
568  *  return Frequency of SCTimer Clock.
569  */
CLOCK_GetSctClkFreq(void)570 uint32_t CLOCK_GetSctClkFreq(void)
571 {
572     uint32_t freq = 0U;
573 
574     switch (SYSCON->SCTCLKSEL)
575     {
576         case 0U:
577             freq = CLOCK_GetCoreSysClkFreq();
578             break;
579         case 1U:
580             freq = CLOCK_GetPll0OutFreq();
581             break;
582         case 2U:
583             freq = CLOCK_GetExtClkFreq();
584             break;
585         case 3U:
586             freq = CLOCK_GetFroHfFreq();
587             break;
588         case 5U:
589             freq = CLOCK_GetI2SMClkFreq();
590             break;
591         case 7U:
592             freq = 0U;
593             break;
594 
595         default:
596             freq = 0U;
597             break;
598     }
599 
600     return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
601 }
602 
603 /* Get FRO 12M Clk */
604 /*! brief  Return Frequency of FRO 12MHz
605  *  return Frequency of FRO 12MHz
606  */
CLOCK_GetFro12MFreq(void)607 uint32_t CLOCK_GetFro12MFreq(void)
608 {
609     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U;
610 }
611 
612 /* Get FRO 1M Clk */
613 /*! brief  Return Frequency of FRO 1MHz
614  *  return Frequency of FRO 1MHz
615  */
CLOCK_GetFro1MFreq(void)616 uint32_t CLOCK_GetFro1MFreq(void)
617 {
618     return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U;
619 }
620 
621 /* Get EXT OSC Clk */
622 /*! brief  Return Frequency of External Clock
623  *  return Frequency of External Clock. If no external clock is used returns 0.
624  */
CLOCK_GetExtClkFreq(void)625 uint32_t CLOCK_GetExtClkFreq(void)
626 {
627     return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
628 }
629 
630 /* Get WATCH DOG Clk */
631 /*! brief  Return Frequency of Watchdog
632  *  return Frequency of Watchdog
633  */
CLOCK_GetWdtClkFreq(void)634 uint32_t CLOCK_GetWdtClkFreq(void)
635 {
636     return CLOCK_GetFro1MFreq() / ((SYSCON->WDTCLKDIV & SYSCON_WDTCLKDIV_DIV_MASK) + 1U);
637 }
638 
639 /* Get HF FRO Clk */
640 /*! brief  Return Frequency of High-Freq output of FRO
641  *  return Frequency of High-Freq output of FRO
642  */
CLOCK_GetFroHfFreq(void)643 uint32_t CLOCK_GetFroHfFreq(void)
644 {
645     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U;
646 }
647 
648 /* Get SYSTEM PLL Clk */
649 /*! brief  Return Frequency of PLL
650  *  return Frequency of PLL
651  */
CLOCK_GetPll0OutFreq(void)652 uint32_t CLOCK_GetPll0OutFreq(void)
653 {
654     return s_Pll0_Freq;
655 }
656 
657 /* Get USB PLL Clk */
658 /*! brief  Return Frequency of USB PLL
659  *  return Frequency of PLL
660  */
CLOCK_GetPll1OutFreq(void)661 uint32_t CLOCK_GetPll1OutFreq(void)
662 {
663     return s_Pll1_Freq;
664 }
665 
666 /* Get RTC OSC Clk */
667 /*! brief  Return Frequency of 32kHz osc
668  *  return Frequency of 32kHz osc
669  */
CLOCK_GetOsc32KFreq(void)670 uint32_t CLOCK_GetOsc32KFreq(void)
671 {
672     return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
673             (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
674                CLK_RTC_32K_CLK :
675                ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
676                 ((PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK) != 0UL)) ?
677                CLK_RTC_32K_CLK :
678                0UL;
679 }
680 
681 /* Get MAIN Clk */
682 /*! brief  Return Frequency of Core System
683  *  return Frequency of Core System
684  */
CLOCK_GetCoreSysClkFreq(void)685 uint32_t CLOCK_GetCoreSysClkFreq(void)
686 {
687     uint32_t freq = 0U;
688 
689     switch (SYSCON->MAINCLKSELB)
690     {
691         case 0U:
692             if (SYSCON->MAINCLKSELA == 0U)
693             {
694                 freq = CLOCK_GetFro12MFreq();
695             }
696             else if (SYSCON->MAINCLKSELA == 1U)
697             {
698                 freq = CLOCK_GetExtClkFreq();
699             }
700             else if (SYSCON->MAINCLKSELA == 2U)
701             {
702                 freq = CLOCK_GetFro1MFreq();
703             }
704             else if (SYSCON->MAINCLKSELA == 3U)
705             {
706                 freq = CLOCK_GetFroHfFreq();
707             }
708             else
709             {
710                 /* Added comments to avoid the violation of MISRA C-2012 rule 15.7 */
711             }
712             break;
713         case 1U:
714             freq = CLOCK_GetPll0OutFreq();
715             break;
716         case 2U:
717             freq = CLOCK_GetPll1OutFreq();
718             break;
719 
720         case 3U:
721             freq = CLOCK_GetOsc32KFreq();
722             break;
723 
724         default:
725             freq = 0U;
726             break;
727     }
728 
729     return freq;
730 }
731 
732 /* Get I2S MCLK Clk */
733 /*! brief  Return Frequency of I2S MCLK Clock
734  *  return Frequency of I2S MCLK Clock
735  */
CLOCK_GetI2SMClkFreq(void)736 uint32_t CLOCK_GetI2SMClkFreq(void)
737 {
738     return s_I2S_Mclk_Freq;
739 }
740 
741 /* Get PLU CLKIN Clk */
742 /*! brief  Return Frequency of PLU CLKIN Clock
743  *  return Frequency of PLU CLKIN Clock
744  */
CLOCK_GetPLUClkInFreq(void)745 uint32_t CLOCK_GetPLUClkInFreq(void)
746 {
747     return s_PLU_ClkIn_Freq;
748 }
749 
750 /* Get FLEXCOMM input clock */
751 /*! brief  Return Frequency of flexcomm input clock
752  *  param  id     : flexcomm instance id
753  *  return Frequency value
754  */
CLOCK_GetFlexCommInputClock(uint32_t id)755 uint32_t CLOCK_GetFlexCommInputClock(uint32_t id)
756 {
757     uint32_t freq = 0U;
758 
759     switch (SYSCON->FCCLKSELX[id])
760     {
761         case 0U:
762             freq = CLOCK_GetCoreSysClkFreq();
763             break;
764         case 1U:
765             freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLL0CLKDIV & 0xffU) + 1U);
766             break;
767         case 2U:
768             freq = CLOCK_GetFro12MFreq();
769             break;
770         case 3U:
771             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
772             break;
773         case 4U:
774             freq = CLOCK_GetFro1MFreq();
775             break;
776         case 5U:
777             freq = CLOCK_GetI2SMClkFreq();
778             break;
779         case 6U:
780             freq = CLOCK_GetOsc32KFreq();
781             break;
782         case 7U:
783             freq = 0U;
784             break;
785 
786         default:
787             freq = 0U;
788             break;
789     }
790 
791     return freq;
792 }
793 
794 /* Get FLEXCOMM Clk */
CLOCK_GetFlexCommClkFreq(uint32_t id)795 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
796 {
797     uint32_t freq   = 0U;
798     uint32_t frgMul = 0U;
799     uint32_t frgDiv = 0U;
800 
801     freq   = CLOCK_GetFlexCommInputClock(id);
802     frgMul = (SYSCON->FLEXFRGXCTRL[id] & SYSCON_FLEXFRG0CTRL_MULT_MASK) >> 8U;
803     frgDiv = SYSCON->FLEXFRGXCTRL[id] & SYSCON_FLEXFRG0CTRL_DIV_MASK;
804     return (uint32_t)(((uint64_t)freq * ((uint64_t)frgDiv + 1ULL)) / (frgMul + frgDiv + 1UL));
805 }
806 
807 /* Get HS_LPSI Clk */
CLOCK_GetHsLspiClkFreq(void)808 uint32_t CLOCK_GetHsLspiClkFreq(void)
809 {
810     uint32_t freq = 0U;
811 
812     switch (SYSCON->HSLSPICLKSEL)
813     {
814         case 0U:
815             freq = CLOCK_GetCoreSysClkFreq();
816             break;
817         case 1U:
818             freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLL0CLKDIV & 0xffU) + 1U);
819             break;
820         case 2U:
821             freq = CLOCK_GetFro12MFreq();
822             break;
823         case 3U:
824             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
825             break;
826         case 4U:
827             freq = CLOCK_GetFro1MFreq();
828             break;
829         case 6U:
830             freq = CLOCK_GetOsc32KFreq();
831             break;
832         case 7U:
833             freq = 0U;
834             break;
835 
836         default:
837             freq = 0U;
838             break;
839     }
840 
841     return freq;
842 }
843 
844 /* Get CTimer Clk */
845 /*! brief  Return Frequency of CTimer functional Clock
846  *  return Frequency of CTimer functional Clock
847  */
CLOCK_GetCTimerClkFreq(uint32_t id)848 uint32_t CLOCK_GetCTimerClkFreq(uint32_t id)
849 {
850     uint32_t freq = 0U;
851 
852     switch (SYSCON->CTIMERCLKSELX[id])
853     {
854         case 0U:
855             freq = CLOCK_GetCoreSysClkFreq();
856             break;
857         case 1U:
858             freq = CLOCK_GetPll0OutFreq();
859             break;
860         case 3U:
861             freq = CLOCK_GetFroHfFreq();
862             break;
863         case 4U:
864             freq = CLOCK_GetFro1MFreq();
865             break;
866         case 5U:
867             freq = CLOCK_GetI2SMClkFreq();
868             break;
869         case 6U:
870             freq = CLOCK_GetOsc32KFreq();
871             break;
872         case 7U:
873             freq = 0U;
874             break;
875 
876         default:
877             freq = 0U;
878             break;
879     }
880 
881     return freq;
882 }
883 
884 /* Get Systick Clk */
885 /*! brief  Return Frequency of SystickClock
886  *  return Frequency of Systick Clock
887  */
CLOCK_GetSystickClkFreq(uint32_t id)888 uint32_t CLOCK_GetSystickClkFreq(uint32_t id)
889 {
890     uint32_t freq = 0U;
891 
892     switch (SYSCON->SYSTICKCLKSELX[id])
893     {
894         case 0U:
895             /*Niobe4mini just has one SYSTICKSEL and SYSTICKDIV register, Fix coverity problem in this way temporarily
896              */
897             freq = CLOCK_GetCoreSysClkFreq() / (((SYSCON->SYSTICKCLKDIV0) & 0xffU) + 1U);
898             break;
899         case 1U:
900             freq = CLOCK_GetFro1MFreq();
901             break;
902         case 2U:
903             freq = CLOCK_GetOsc32KFreq();
904             break;
905         case 7U:
906             freq = 0U;
907             break;
908 
909         default:
910             freq = 0U;
911             break;
912     }
913 
914     return freq;
915 }
916 
917 /* Set FlexComm Clock */
918 /**
919  * brief   Set the flexcomm output frequency.
920  * param   id      : flexcomm instance id
921  *          freq    : output frequency
922  * return  0   : the frequency range is out of range.
923  *          1   : switch successfully.
924  */
CLOCK_SetFlexCommClock(uint32_t id,uint32_t freq)925 uint32_t CLOCK_SetFlexCommClock(uint32_t id, uint32_t freq)
926 {
927     uint32_t input = CLOCK_GetFlexCommClkFreq(id);
928     uint32_t mul;
929 
930     if ((freq > 48000000UL) || (freq > input) || (input / freq >= 2UL))
931     {
932         /* FRG output frequency should be less than equal to 48MHz */
933         return 0UL;
934     }
935     else
936     {
937         mul                      = (uint32_t)((((uint64_t)input - freq) * 256ULL) / ((uint64_t)freq));
938         SYSCON->FLEXFRGXCTRL[id] = (mul << 8U) | 0xFFU;
939         return 1UL;
940     }
941 }
942 
943 /* Get IP Clk */
944 /*! brief  Return Frequency of selected clock
945  *  return Frequency of selected clock
946  */
CLOCK_GetFreq(clock_name_t clockName)947 uint32_t CLOCK_GetFreq(clock_name_t clockName)
948 {
949     uint32_t freq;
950     switch (clockName)
951     {
952         case kCLOCK_CoreSysClk:
953             freq = CLOCK_GetCoreSysClkFreq();
954             break;
955         case kCLOCK_BusClk:
956             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
957             break;
958         case kCLOCK_ClockOut:
959             freq = CLOCK_GetClockOutClkFreq();
960             break;
961         case kCLOCK_Pll1Out:
962             freq = CLOCK_GetPll1OutFreq();
963             break;
964         case kCLOCK_Mclk:
965             freq = CLOCK_GetMclkClkFreq();
966             break;
967         case kCLOCK_FroHf:
968             freq = CLOCK_GetFroHfFreq();
969             break;
970         case kCLOCK_Fro12M:
971             freq = CLOCK_GetFro12MFreq();
972             break;
973         case kCLOCK_Fro1M:
974             freq = CLOCK_GetFro1MFreq();
975             break;
976         case kCLOCK_ExtClk:
977             freq = CLOCK_GetExtClkFreq();
978             break;
979         case kCLOCK_Pll0Out:
980             freq = CLOCK_GetPll0OutFreq();
981             break;
982         case kCLOCK_FlexI2S:
983             freq = CLOCK_GetI2SMClkFreq();
984             break;
985         default:
986             freq = 0U;
987             break;
988     }
989     return freq;
990 }
991 
992 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
pllFindSel(uint32_t M,uint32_t * pSelP,uint32_t * pSelI,uint32_t * pSelR)993 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
994 {
995     uint32_t seli, selp;
996     /* bandwidth: compute selP from Multiplier */
997     if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
998     {
999         selp = (M >> 2U) + 1U;
1000         if (selp >= 31U)
1001         {
1002             selp = 31U;
1003         }
1004         *pSelP = selp;
1005 
1006         if (M >= 8000UL)
1007         {
1008             seli = 1UL;
1009         }
1010         else if (M >= 122UL)
1011         {
1012             seli = (uint32_t)(8000UL / M); /*floor(8000/M) */
1013         }
1014         else
1015         {
1016             seli = 2UL * ((uint32_t)(M / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
1017         }
1018 
1019         if (seli >= 63UL)
1020         {
1021             seli = 63UL;
1022         }
1023         *pSelI = seli;
1024 
1025         *pSelR = 0UL;
1026     }
1027     else
1028     {
1029         /* Note: If the spread spectrum mode, choose N to ensure 3 MHz < Fin/N < 5 MHz */
1030         *pSelP = 3U;
1031         *pSelI = 4U;
1032         *pSelR = 4U;
1033     }
1034 }
1035 
1036 /* Get predivider (N) from PLL0 NDEC setting */
findPll0PreDiv(void)1037 static uint32_t findPll0PreDiv(void)
1038 {
1039     uint32_t preDiv = 1UL;
1040 
1041     /* Direct input is not used? */
1042     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPREDIV_MASK) == 0UL)
1043     {
1044         preDiv = SYSCON->PLL0NDEC & SYSCON_PLL0NDEC_NDIV_MASK;
1045         if (preDiv == 0UL)
1046         {
1047             preDiv = 1UL;
1048         }
1049     }
1050     return preDiv;
1051 }
1052 
1053 /* Get predivider (N) from PLL1 NDEC setting */
findPll1PreDiv(void)1054 static uint32_t findPll1PreDiv(void)
1055 {
1056     uint32_t preDiv = 1UL;
1057 
1058     /* Direct input is not used? */
1059     if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL)
1060     {
1061         preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK;
1062         if (preDiv == 0UL)
1063         {
1064             preDiv = 1UL;
1065         }
1066     }
1067     return preDiv;
1068 }
1069 
1070 /* Get postdivider (P) from PLL0 PDEC setting */
findPll0PostDiv(void)1071 static uint32_t findPll0PostDiv(void)
1072 {
1073     uint32_t postDiv = 1UL;
1074 
1075     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1076     {
1077         if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1078         {
1079             postDiv = SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK;
1080         }
1081         else
1082         {
1083             postDiv = 2UL * (SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK);
1084         }
1085         if (postDiv == 0UL)
1086         {
1087             postDiv = 2UL;
1088         }
1089     }
1090     return postDiv;
1091 }
1092 
1093 /* Get postdivider (P) from PLL1 PDEC setting. */
findPll1PostDiv(void)1094 static uint32_t findPll1PostDiv(void)
1095 {
1096     uint32_t postDiv = 1UL;
1097 
1098     if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1099     {
1100         if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1101         {
1102             postDiv = SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK;
1103         }
1104         else
1105         {
1106             postDiv = 2UL * (SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK);
1107         }
1108         if (postDiv == 0UL)
1109         {
1110             postDiv = 2UL;
1111         }
1112     }
1113 
1114     return postDiv;
1115 }
1116 
1117 /* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
findPll0MMult(void)1118 static float findPll0MMult(void)
1119 {
1120     float mMult = 1.0F;
1121     float mMult_fract;
1122     uint32_t mMult_int;
1123 
1124     if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL)
1125     {
1126         mMult =
1127             (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT);
1128     }
1129     else
1130     {
1131         mMult_int   = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U);
1132         mMult_int   = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL0_SSCG_MD_INT_P);
1133         mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL0_SSCG_MD_FRACT_M) /
1134                        (float)(uint32_t)(1UL << PLL0_SSCG_MD_INT_P));
1135         mMult       = (float)mMult_int + mMult_fract;
1136     }
1137     if (0ULL == ((uint64_t)mMult))
1138     {
1139         mMult = 1.0F;
1140     }
1141     return mMult;
1142 }
1143 
1144 /* Get multiplier (M) from PLL1 MDEC. */
findPll1MMult(void)1145 static uint32_t findPll1MMult(void)
1146 {
1147     uint32_t mMult = 1UL;
1148 
1149     mMult = SYSCON->PLL1MDEC & SYSCON_PLL1MDEC_MDIV_MASK;
1150 
1151     if (mMult == 0UL)
1152     {
1153         mMult = 1UL;
1154     }
1155 
1156     return mMult;
1157 }
1158 
1159 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1160 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1161 {
1162     uint32_t tmp;
1163 
1164     while (n != 0U)
1165     {
1166         tmp = n;
1167         n   = m % n;
1168         m   = tmp;
1169     }
1170 
1171     return m;
1172 }
1173 
1174 /*
1175  * Set PLL0 output based on desired output rate.
1176  * In this function, the it calculates the PLL0 setting for output frequency from input clock
1177  * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1178  * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1179  */
CLOCK_GetPll0ConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1180 static pll_error_t CLOCK_GetPll0ConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1181 {
1182     uint32_t nDivOutHz, fccoHz;
1183     uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
1184     uint32_t pllDirectInput, pllDirectOutput;
1185     uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
1186 
1187     /* Baseline parameters (no input or output dividers) */
1188     pllPreDivider   = 1U; /* 1 implies pre-divider will be disabled */
1189     pllPostDivider  = 1U; /* 1 implies post-divider will be disabled */
1190     pllDirectOutput = 1U;
1191 
1192     /* Verify output rate parameter */
1193     if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1194     {
1195         /* Maximum PLL output with post divider=1 cannot go above this frequency */
1196         return kStatus_PLL_OutputTooHigh;
1197     }
1198     if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1199     {
1200         /* Minmum PLL output with maximum post divider cannot go below this frequency */
1201         return kStatus_PLL_OutputTooLow;
1202     }
1203 
1204     /* If using SS mode, input clock needs to be between 3MHz and 20MHz */
1205     if (useSS)
1206     {
1207         /* Verify input rate parameter */
1208         if (finHz < PLL_MIN_IN_SSMODE)
1209         {
1210             /* Input clock into the PLL cannot be lower than this */
1211             return kStatus_PLL_InputTooLow;
1212         }
1213         /* PLL input in SS mode must be under 20MHz */
1214         if (finHz > (PLL_MAX_IN_SSMODE * NVALMAX))
1215         {
1216             return kStatus_PLL_InputTooHigh;
1217         }
1218     }
1219     else
1220     {
1221         /* Verify input rate parameter */
1222         if (finHz < PLL_LOWER_IN_LIMIT)
1223         {
1224             /* Input clock into the PLL cannot be lower than this */
1225             return kStatus_PLL_InputTooLow;
1226         }
1227         if (finHz > PLL_HIGHER_IN_LIMIT)
1228         {
1229             /* Input clock into the PLL cannot be higher than this */
1230             return kStatus_PLL_InputTooHigh;
1231         }
1232     }
1233 
1234     /* Find the optimal CCO frequency for the output and input that
1235        will keep it inside the PLL CCO range. This may require
1236        tweaking the post-divider for the PLL. */
1237     fccoHz = foutHz;
1238     while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1239     {
1240         /* CCO output is less than minimum CCO range, so the CCO output
1241            needs to be bumped up and the post-divider is used to bring
1242            the PLL output back down. */
1243         pllPostDivider++;
1244         if (pllPostDivider > PVALMAX)
1245         {
1246             return kStatus_PLL_OutsideIntLimit;
1247         }
1248 
1249         /* Target CCO goes up, PLL output goes down */
1250         /* divide-by-2 divider in the post-divider is always work*/
1251         fccoHz          = foutHz * (pllPostDivider * 2U);
1252         pllDirectOutput = 0U;
1253     }
1254 
1255     /* Determine if a pre-divider is needed to get the best frequency */
1256     if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
1257     {
1258         uint32_t a = FindGreatestCommonDivisor(fccoHz, finHz);
1259 
1260         if (a > PLL_LOWER_IN_LIMIT)
1261         {
1262             a = finHz / a;
1263             if ((a != 0U) && (a < PLL_MAX_N_DIV))
1264             {
1265                 pllPreDivider = a;
1266             }
1267         }
1268     }
1269 
1270     /* Bypass pre-divider hardware if pre-divider is 1 */
1271     if (pllPreDivider > 1U)
1272     {
1273         pllDirectInput = 0U;
1274     }
1275     else
1276     {
1277         pllDirectInput = 1U;
1278     }
1279 
1280     /* Determine PLL multipler */
1281     nDivOutHz     = (finHz / pllPreDivider);
1282     pllMultiplier = (fccoHz / nDivOutHz);
1283 
1284     /* Find optimal values for filter */
1285     if (useSS == false)
1286     {
1287         /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1288         if ((nDivOutHz * ((pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1289         {
1290             pllMultiplier++;
1291         }
1292 
1293         /* Setup filtering */
1294         pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
1295         uplimoff = 0U;
1296 
1297         /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1298         pSetup->pllsscg[1] =
1299             (uint32_t)((PLL_SSCG1_MDEC_VAL_SET(pllMultiplier)) | (1UL << SYSCON_PLL0SSCG1_SEL_EXT_SHIFT));
1300     }
1301     else
1302     {
1303         uint64_t fc;
1304 
1305         /* Filtering will be handled by SSC */
1306         pllSelR  = 0UL;
1307         pllSelI  = 0UL;
1308         pllSelP  = 0UL;
1309         uplimoff = 1U;
1310 
1311         /* The PLL multiplier will get very close and slightly under the
1312            desired target frequency. A small fractional component can be
1313            added to fine tune the frequency upwards to the target. */
1314         fc = ((uint64_t)(uint32_t)(fccoHz % nDivOutHz) << 25UL) / nDivOutHz;
1315 
1316         /* Set multiplier */
1317         pSetup->pllsscg[0] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) | PLL0_SSCG_MD_FRACT_SET((uint32_t)fc));
1318         pSetup->pllsscg[1] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) >> 32U);
1319     }
1320 
1321     /* Get encoded values for N (prediv) and P (postdiv) */
1322     pSetup->pllndec = PLL_NDEC_VAL_SET(pllPreDivider);
1323     pSetup->pllpdec = PLL_PDEC_VAL_SET(pllPostDivider);
1324 
1325     /* PLL control */
1326     pSetup->pllctrl = (pllSelR << SYSCON_PLL0CTRL_SELR_SHIFT) |                  /* Filter coefficient */
1327                       (pllSelI << SYSCON_PLL0CTRL_SELI_SHIFT) |                  /* Filter coefficient */
1328                       (pllSelP << SYSCON_PLL0CTRL_SELP_SHIFT) |                  /* Filter coefficient */
1329                       (0UL << SYSCON_PLL0CTRL_BYPASSPLL_SHIFT) |                 /* PLL bypass mode disabled */
1330                       (uplimoff << SYSCON_PLL0CTRL_LIMUPOFF_SHIFT) |             /* SS/fractional mode disabled */
1331                       (pllDirectInput << SYSCON_PLL0CTRL_BYPASSPREDIV_SHIFT) |   /* Bypass pre-divider? */
1332                       (pllDirectOutput << SYSCON_PLL0CTRL_BYPASSPOSTDIV_SHIFT) | /* Bypass post-divider? */
1333                       (1UL << SYSCON_PLL0CTRL_CLKEN_SHIFT);                      /* Ensure the PLL clock output */
1334 
1335     return kStatus_PLL_Success;
1336 }
1337 
1338 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1339 /* Alloct the static buffer for cache. */
1340 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1341 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]  = {0};
1342 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1343 static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]      = {false};
1344 static uint32_t s_PllSetupCacheIdx                                  = 0U;
1345 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1346 
1347 /*
1348  * Calculate the PLL setting values from input clock freq to output freq.
1349  */
CLOCK_GetPll0Config(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1350 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1351 {
1352     pll_error_t retErr;
1353 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1354     uint32_t i;
1355 
1356     for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1357     {
1358         if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && (useSS == s_UseSSCache[i]))
1359         {
1360             /* Hit the target in cache buffer. */
1361             pSetup->pllctrl    = s_PllSetupCacheStruct[i].pllctrl;
1362             pSetup->pllndec    = s_PllSetupCacheStruct[i].pllndec;
1363             pSetup->pllpdec    = s_PllSetupCacheStruct[i].pllpdec;
1364             pSetup->pllsscg[0] = s_PllSetupCacheStruct[i].pllsscg[0];
1365             pSetup->pllsscg[1] = s_PllSetupCacheStruct[i].pllsscg[1];
1366             retErr             = kStatus_PLL_Success;
1367             break;
1368         }
1369     }
1370 
1371     if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1372     {
1373         return retErr;
1374     }
1375 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1376 
1377     retErr = CLOCK_GetPll0ConfigInternal(finHz, foutHz, pSetup, useSS);
1378 
1379 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1380     /* Cache the most recent calulation result into buffer. */
1381     s_FinHzCache[s_PllSetupCacheIdx]  = finHz;
1382     s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1383     s_UseSSCache[s_PllSetupCacheIdx]  = useSS;
1384 
1385     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl    = pSetup->pllctrl;
1386     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec    = pSetup->pllndec;
1387     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec    = pSetup->pllpdec;
1388     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[0] = pSetup->pllsscg[0];
1389     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[1] = pSetup->pllsscg[1];
1390     /* Update the index for next available buffer. */
1391     s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1392 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1393 
1394     return retErr;
1395 }
1396 
1397 /* Update local PLL rate variable */
CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t * pSetup)1398 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup)
1399 {
1400     s_Pll0_Freq = CLOCK_GetPLL0OutFromSetup(pSetup);
1401 }
1402 
1403 /* Update local PLL1 rate variable */
CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t * pSetup)1404 static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup)
1405 {
1406     s_Pll1_Freq = CLOCK_GetPLL1OutFromSetup(pSetup);
1407 }
1408 
1409 /* Return System PLL input clock rate */
1410 /*! brief    Return  PLL0 input clock rate
1411  *  return    PLL0 input clock rate
1412  */
CLOCK_GetPLL0InClockRate(void)1413 uint32_t CLOCK_GetPLL0InClockRate(void)
1414 {
1415     uint32_t clkRate = 0U;
1416 
1417     switch ((SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK))
1418     {
1419         case 0x00U:
1420             clkRate = CLK_FRO_12MHZ;
1421             break;
1422 
1423         case 0x01U:
1424             clkRate = CLOCK_GetExtClkFreq();
1425             break;
1426 
1427         case 0x02U:
1428             clkRate = CLOCK_GetFro1MFreq();
1429             break;
1430 
1431         case 0x03U:
1432             clkRate = CLOCK_GetOsc32KFreq();
1433             break;
1434 
1435         default:
1436             clkRate = 0U;
1437             break;
1438     }
1439 
1440     return clkRate;
1441 }
1442 
1443 /* Return PLL1 input clock rate */
CLOCK_GetPLL1InClockRate(void)1444 uint32_t CLOCK_GetPLL1InClockRate(void)
1445 {
1446     uint32_t clkRate = 0U;
1447 
1448     switch ((SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK))
1449     {
1450         case 0x00U:
1451             clkRate = CLK_FRO_12MHZ;
1452             break;
1453 
1454         case 0x01U:
1455             clkRate = CLOCK_GetExtClkFreq();
1456             break;
1457 
1458         case 0x02U:
1459             clkRate = CLOCK_GetFro1MFreq();
1460             break;
1461 
1462         case 0x03U:
1463             clkRate = CLOCK_GetOsc32KFreq();
1464             break;
1465 
1466         default:
1467             clkRate = 0U;
1468             break;
1469     }
1470 
1471     return clkRate;
1472 }
1473 
1474 /* Return PLL0 output clock rate from setup structure */
1475 /*! brief    Return PLL0 output clock rate from setup structure
1476  *  param    pSetup : Pointer to a PLL setup structure
1477  *  return   PLL0 output clock rate the setup structure will generate
1478  */
CLOCK_GetPLL0OutFromSetup(pll_setup_t * pSetup)1479 uint32_t CLOCK_GetPLL0OutFromSetup(pll_setup_t *pSetup)
1480 {
1481     uint32_t clkRate = 0;
1482     uint32_t prediv, postdiv;
1483     float workRate = 0.0F;
1484 
1485     /* Get the input clock frequency of PLL. */
1486     clkRate = CLOCK_GetPLL0InClockRate();
1487 
1488     if (((pSetup->pllctrl & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) &&
1489         ((pSetup->pllctrl & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) &&
1490         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) &&
1491         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL))
1492     {
1493         prediv  = findPll0PreDiv();
1494         postdiv = findPll0PostDiv();
1495         /* Adjust input clock */
1496         clkRate = clkRate / prediv;
1497         /* MDEC used for rate */
1498         workRate = (float)clkRate * (float)findPll0MMult();
1499         workRate /= (float)postdiv;
1500     }
1501 
1502     return (uint32_t)workRate;
1503 }
1504 
1505 /* Return PLL1 output clock rate from setup structure */
1506 /*! brief    Return PLL1 output clock rate from setup structure
1507  *  param    pSetup : Pointer to a PLL setup structure
1508  *  return   PLL0 output clock rate the setup structure will generate
1509  */
CLOCK_GetPLL1OutFromSetup(pll_setup_t * pSetup)1510 uint32_t CLOCK_GetPLL1OutFromSetup(pll_setup_t *pSetup)
1511 {
1512     uint32_t clkRate = 0;
1513     uint32_t prediv, postdiv;
1514     uint32_t workRate = 0UL;
1515 
1516     /* Get the input clock frequency of PLL. */
1517     clkRate = CLOCK_GetPLL1InClockRate();
1518 
1519     if (((pSetup->pllctrl & SYSCON_PLL1CTRL_BYPASSPLL_MASK) == 0UL) &&
1520         ((pSetup->pllctrl & SYSCON_PLL1CTRL_CLKEN_MASK) != 0UL) &&
1521         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL1_MASK) == 0UL))
1522     {
1523         prediv  = findPll1PreDiv();
1524         postdiv = findPll1PostDiv();
1525         /* Adjust input clock */
1526         clkRate = clkRate / prediv;
1527         /* MDEC used for rate */
1528         workRate = clkRate * findPll1MMult();
1529         workRate /= postdiv;
1530     }
1531 
1532     return workRate;
1533 }
1534 
1535 /* Set the current PLL0 Rate */
1536 /*! brief Store the current PLL rate
1537  *  param    rate: Current rate of the PLL
1538  *  return   Nothing
1539  **/
CLOCK_SetStoredPLL0ClockRate(uint32_t rate)1540 void CLOCK_SetStoredPLL0ClockRate(uint32_t rate)
1541 {
1542     s_Pll0_Freq = rate;
1543 }
1544 
1545 /* Return PLL0 output clock rate */
1546 /*! brief    Return  PLL0 output clock rate
1547  *  param    recompute   : Forces a PLL rate recomputation if true
1548  *  return    PLL0 output clock rate
1549  *  note The PLL rate is cached in the driver in a variable as
1550  *  the rate computation function can take some time to perform. It
1551  *  is recommended to use 'false' with the 'recompute' parameter.
1552  */
CLOCK_GetPLL0OutClockRate(bool recompute)1553 uint32_t CLOCK_GetPLL0OutClockRate(bool recompute)
1554 {
1555     pll_setup_t Setup;
1556     uint32_t rate;
1557 
1558     if ((recompute) || (s_Pll0_Freq == 0U))
1559     {
1560         Setup.pllctrl    = SYSCON->PLL0CTRL;
1561         Setup.pllndec    = SYSCON->PLL0NDEC;
1562         Setup.pllpdec    = SYSCON->PLL0PDEC;
1563         Setup.pllsscg[0] = SYSCON->PLL0SSCG0;
1564         Setup.pllsscg[1] = SYSCON->PLL0SSCG1;
1565 
1566         CLOCK_GetPLL0OutFromSetupUpdate(&Setup);
1567     }
1568 
1569     rate = s_Pll0_Freq;
1570 
1571     return rate;
1572 }
1573 
1574 /*! brief    Return  PLL1 output clock rate
1575  *  param    recompute   : Forces a PLL rate recomputation if true
1576  *  return    PLL1 output clock rate
1577  *  note The PLL rate is cached in the driver in a variable as
1578  *  the rate computation function can take some time to perform. It
1579  *  is recommended to use 'false' with the 'recompute' parameter.
1580  */
CLOCK_GetPLL1OutClockRate(bool recompute)1581 uint32_t CLOCK_GetPLL1OutClockRate(bool recompute)
1582 {
1583     pll_setup_t Setup;
1584     uint32_t rate;
1585 
1586     if ((recompute) || (s_Pll1_Freq == 0U))
1587     {
1588         Setup.pllctrl = SYSCON->PLL1CTRL;
1589         Setup.pllndec = SYSCON->PLL1NDEC;
1590         Setup.pllpdec = SYSCON->PLL1PDEC;
1591         Setup.pllmdec = SYSCON->PLL1MDEC;
1592         CLOCK_GetPLL1OutFromSetupUpdate(&Setup);
1593     }
1594 
1595     rate = s_Pll1_Freq;
1596 
1597     return rate;
1598 }
1599 
1600 /* Set PLL0 output based on the passed PLL setup data */
1601 /*! brief    Set PLL output based on the passed PLL setup data
1602  *  param    pControl    : Pointer to populated PLL control structure to generate setup with
1603  *  param    pSetup      : Pointer to PLL setup structure to be filled
1604  *  return   PLL_ERROR_SUCCESS on success, or PLL setup error code
1605  *  note Actual frequency for setup may vary from the desired frequency based on the
1606  *  accuracy of input clocks, rounding, non-fractional PLL mode, etc.
1607  */
CLOCK_SetupPLL0Data(pll_config_t * pControl,pll_setup_t * pSetup)1608 pll_error_t CLOCK_SetupPLL0Data(pll_config_t *pControl, pll_setup_t *pSetup)
1609 {
1610     uint32_t inRate;
1611     bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0UL);
1612 
1613     pll_error_t pllError;
1614 
1615     /* Determine input rate for the PLL */
1616     if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0UL)
1617     {
1618         inRate = pControl->inputRate;
1619     }
1620     else
1621     {
1622         inRate = CLOCK_GetPLL0InClockRate();
1623     }
1624 
1625     /* PLL flag options */
1626     pllError = CLOCK_GetPll0Config(inRate, pControl->desiredRate, pSetup, useSS);
1627     if ((useSS) && (pllError == kStatus_PLL_Success))
1628     {
1629         /* If using SS mode, then some tweaks are made to the generated setup */
1630         pSetup->pllsscg[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
1631         if (pControl->mfDither)
1632         {
1633             pSetup->pllsscg[1] |= (1UL << SYSCON_PLL0SSCG1_DITHER_SHIFT);
1634         }
1635     }
1636 
1637     return pllError;
1638 }
1639 
1640 /* Set PLL0 output from PLL setup structure */
1641 /*! brief    Set PLL output from PLL setup structure (precise frequency)
1642  * param pSetup  : Pointer to populated PLL setup structure
1643  * param flagcfg : Flag configuration for PLL config structure
1644  * return    PLL_ERROR_SUCCESS on success, or PLL setup error code
1645  * note  This function will power off the PLL, setup the PLL with the
1646  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1647  * and adjust system voltages to the new PLL rate. The function will not
1648  * alter any source clocks (ie, main systen clock) that may use the PLL,
1649  * so these should be setup prior to and after exiting the function.
1650  */
CLOCK_SetupPLL0Prec(pll_setup_t * pSetup,uint32_t flagcfg)1651 pll_error_t CLOCK_SetupPLL0Prec(pll_setup_t *pSetup, uint32_t flagcfg)
1652 {
1653     uint32_t inRate, clkRate, prediv;
1654     uint32_t pll_lock_wait_time     = 0U;
1655     uint32_t max_pll_lock_wait_time = 0U;
1656     /* Power off PLL during setup changes */
1657     POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1658     POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1659 
1660     pSetup->flags = flagcfg;
1661 
1662     /* Write PLL setup data */
1663     SYSCON->PLL0CTRL  = pSetup->pllctrl;
1664     SYSCON->PLL0NDEC  = pSetup->pllndec;
1665     SYSCON->PLL0NDEC  = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1666     SYSCON->PLL0PDEC  = pSetup->pllpdec;
1667     SYSCON->PLL0PDEC  = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1668     SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1669     SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1670     SYSCON->PLL0SSCG1 =
1671         pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT); /* latch */
1672 
1673     POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1674     POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1675 
1676     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1677     {
1678         if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1679         {
1680             inRate = CLOCK_GetPLL0InClockRate();
1681             prediv = findPll0PreDiv();
1682             /* Adjust input clock */
1683             clkRate = inRate / prediv;
1684 
1685             /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is stable.
1686                The lock bit could be used to shorten the wait time when freq<20MHZ */
1687             max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1688 
1689             if (clkRate < 20000000UL)
1690             {
1691                 pll_lock_wait_time = 0U;
1692                 while ((CLOCK_IsPLL0Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1693                 {
1694                     pll_lock_wait_time += 100U;
1695                     SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1696                 }
1697             }
1698             else
1699             {
1700                 SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1701             }
1702         }
1703         else /* spread spectrum mode */
1704         {
1705             SDK_DelayAtLeastUs(6000U,
1706                                SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
1707                                                                            insure the PLL will be stable */
1708         }
1709     }
1710 
1711     /* Update current programmed PLL rate var */
1712     CLOCK_GetPLL0OutFromSetupUpdate(pSetup);
1713 
1714     /* System voltage adjustment, occurs prior to setting main system clock */
1715     if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0UL)
1716     {
1717         POWER_SetVoltageForFreq(s_Pll0_Freq);
1718     }
1719 
1720     return kStatus_PLL_Success;
1721 }
1722 
1723 /* Setup PLL Frequency from pre-calculated value */
1724 /**
1725  * brief Set PLL0 output from PLL setup structure (precise frequency)
1726  * param pSetup  : Pointer to populated PLL setup structure
1727  * return    kStatus_PLL_Success on success, or PLL setup error code
1728  * note  This function will power off the PLL, setup the PLL with the
1729  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1730  * and adjust system voltages to the new PLL rate. The function will not
1731  * alter any source clocks (ie, main systen clock) that may use the PLL,
1732  * so these should be setup prior to and after exiting the function.
1733  */
CLOCK_SetPLL0Freq(const pll_setup_t * pSetup)1734 pll_error_t CLOCK_SetPLL0Freq(const pll_setup_t *pSetup)
1735 {
1736     uint32_t inRate, clkRate, prediv;
1737     uint32_t pll_lock_wait_time     = 0U;
1738     uint32_t max_pll_lock_wait_time = 0U;
1739     /* Power off PLL during setup changes */
1740     POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1741     POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1742 
1743     /* Write PLL setup data */
1744     SYSCON->PLL0CTRL  = pSetup->pllctrl;
1745     SYSCON->PLL0NDEC  = pSetup->pllndec;
1746     SYSCON->PLL0NDEC  = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1747     SYSCON->PLL0PDEC  = pSetup->pllpdec;
1748     SYSCON->PLL0PDEC  = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1749     SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1750     SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1751     SYSCON->PLL0SSCG1 =
1752         pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* latch */
1753 
1754     POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1755     POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1756 
1757     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1758     {
1759         if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1760         {
1761             inRate = CLOCK_GetPLL0InClockRate();
1762             prediv = findPll0PreDiv();
1763             /* Adjust input clock */
1764             clkRate = inRate / prediv;
1765 
1766             /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is
1767                stable. The lock bit could be used to shorten the wait time when freq<20MHZ */
1768             max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1769 
1770             if (clkRate < 20000000UL)
1771             {
1772                 pll_lock_wait_time = 0U;
1773                 while ((CLOCK_IsPLL0Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1774                 {
1775                     pll_lock_wait_time += 100U;
1776                     SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1777                 }
1778             }
1779             else
1780             {
1781                 SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1782             }
1783         }
1784         else /* spread spectrum mode */
1785         {
1786             SDK_DelayAtLeastUs(6000U,
1787                                SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
1788                                                                            to insure the PLL will be stable */
1789         }
1790     }
1791 
1792     /* Update current programmed PLL rate var */
1793     s_Pll0_Freq = pSetup->pllRate;
1794 
1795     return kStatus_PLL_Success;
1796 }
1797 
1798 /* Setup PLL1 Frequency from pre-calculated value */
1799 /**
1800  * brief Set PLL1 output from PLL setup structure (precise frequency)
1801  * param pSetup  : Pointer to populated PLL setup structure
1802  * return    kStatus_PLL_Success on success, or PLL setup error code
1803  * note  This function will power off the PLL, setup the PLL with the
1804  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1805  * and adjust system voltages to the new PLL rate. The function will not
1806  * alter any source clocks (ie, main systen clock) that may use the PLL,
1807  * so these should be setup prior to and after exiting the function.
1808  */
CLOCK_SetPLL1Freq(const pll_setup_t * pSetup)1809 pll_error_t CLOCK_SetPLL1Freq(const pll_setup_t *pSetup)
1810 {
1811     uint32_t inRate, clkRate, prediv;
1812     uint32_t pll_lock_wait_time     = 0U;
1813     uint32_t max_pll_lock_wait_time = 0U;
1814     /* Power off PLL during setup changes */
1815     POWER_EnablePD(kPDRUNCFG_PD_PLL1);
1816 
1817     /* Write PLL setup data */
1818     SYSCON->PLL1CTRL = pSetup->pllctrl;
1819     SYSCON->PLL1NDEC = pSetup->pllndec;
1820     SYSCON->PLL1NDEC = pSetup->pllndec | (1UL << SYSCON_PLL1NDEC_NREQ_SHIFT); /* latch */
1821     SYSCON->PLL1PDEC = pSetup->pllpdec;
1822     SYSCON->PLL1PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL1PDEC_PREQ_SHIFT); /* latch */
1823     SYSCON->PLL1MDEC = pSetup->pllmdec;
1824     SYSCON->PLL1MDEC = pSetup->pllmdec | (1UL << SYSCON_PLL1MDEC_MREQ_SHIFT); /* latch */
1825 
1826     POWER_DisablePD(kPDRUNCFG_PD_PLL1);
1827 
1828     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1829     {
1830         inRate = CLOCK_GetPLL1InClockRate();
1831         prediv = findPll1PreDiv();
1832         /* Adjust input clock */
1833         clkRate = inRate / prediv;
1834 
1835         /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is stable.
1836            The lock bit could be used to shorten the wait time when freq<20MHZ */
1837         max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1838 
1839         if (clkRate < 20000000UL)
1840         {
1841             pll_lock_wait_time = 0U;
1842             while ((CLOCK_IsPLL1Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1843             {
1844                 pll_lock_wait_time += 100U;
1845                 SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1846             }
1847         }
1848         else
1849         {
1850             SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1851         }
1852     }
1853 
1854     /* Update current programmed PLL rate var */
1855     s_Pll1_Freq = pSetup->pllRate;
1856 
1857     return kStatus_PLL_Success;
1858 }
1859 
1860 /* Set PLL0 clock based on the input frequency and multiplier */
1861 /*! brief    Set PLL0 output based on the multiplier and input frequency
1862  * param multiply_by : multiplier
1863  * param input_freq  : Clock input frequency of the PLL
1864  * return    Nothing
1865  * note  Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
1866  * function does not disable or enable PLL power, wait for PLL lock,
1867  * or adjust system voltages. These must be done in the application.
1868  * The function will not alter any source clocks (ie, main systen clock)
1869  * that may use the PLL, so these should be setup prior to and after
1870  * exiting the function.
1871  */
CLOCK_SetupPLL0Mult(uint32_t multiply_by,uint32_t input_freq)1872 void CLOCK_SetupPLL0Mult(uint32_t multiply_by, uint32_t input_freq)
1873 {
1874     uint32_t cco_freq = input_freq * multiply_by;
1875     uint32_t pdec     = 1U;
1876     uint32_t selr;
1877     uint32_t seli;
1878     uint32_t selp;
1879     uint32_t mdec, ndec;
1880 
1881     while (cco_freq < 275000000U)
1882     {
1883         multiply_by <<= 1U; /* double value in each iteration */
1884         pdec <<= 1U;        /* correspondingly double pdec to cancel effect of double msel */
1885         cco_freq = input_freq * multiply_by;
1886     }
1887 
1888     selr = 0U;
1889 
1890     if (multiply_by >= 8000UL)
1891     {
1892         seli = 1UL;
1893     }
1894     else if (multiply_by >= 122UL)
1895     {
1896         seli = (uint32_t)(8000UL / multiply_by); /*floor(8000/M) */
1897     }
1898     else
1899     {
1900         seli = 2UL * ((uint32_t)(multiply_by / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
1901     }
1902 
1903     if (seli >= 63U)
1904     {
1905         seli = 63U;
1906     }
1907 
1908     {
1909         selp = 31U;
1910     }
1911 
1912     if (pdec > 1U)
1913     {
1914         pdec = pdec / 2U; /* Account for minus 1 encoding */
1915                           /* Translate P value */
1916     }
1917 
1918     mdec = (uint32_t)PLL_SSCG1_MDEC_VAL_SET(multiply_by);
1919     ndec = 0x1U; /* pre divide by 1 (hardcoded) */
1920 
1921     SYSCON->PLL0CTRL = SYSCON_PLL0CTRL_CLKEN_MASK | SYSCON_PLL0CTRL_BYPASSPOSTDIV(0) |
1922                        SYSCON_PLL0CTRL_BYPASSPOSTDIV2(0) | (selr << SYSCON_PLL0CTRL_SELR_SHIFT) |
1923                        (seli << SYSCON_PLL0CTRL_SELI_SHIFT) | (selp << SYSCON_PLL0CTRL_SELP_SHIFT);
1924     SYSCON->PLL0PDEC = pdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* set Pdec value and assert preq */
1925     SYSCON->PLL0NDEC = ndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* set Pdec value and assert preq */
1926     SYSCON->PLL0SSCG1 =
1927         mdec | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* select non sscg MDEC value, assert mreq and select mdec value */
1928 }
1929 
1930 /*! @brief Enable the OSTIMER 32k clock.
1931  *  @return  Nothing
1932  */
CLOCK_EnableOstimer32kClock(void)1933 void CLOCK_EnableOstimer32kClock(void)
1934 {
1935     PMC->OSTIMERr |= PMC_OSTIMER_CLOCKENABLE_MASK;
1936 }
1937