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