1 /*
2  * Copyright 2017 - 2020 , 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 /* Peripheral FLASH_NMPA base address */
59 #define FLASH_NMPA_BASE (0x3FC00u)
60 /* Return values from Config (N-2) page of flash */
61 #define GET_HFXO_TRIM()  (*(uint32_t *)(FLASH_NMPA_BASE + 0xC0U)) // (0x3FCC0)
62 #define GET_32KXO_TRIM() (*(uint32_t *)(FLASH_NMPA_BASE + 0xC4U)) // (0x3FCC4)
63 
64 #define XO_SLAVE_EN (1)
65 
66 /* Saved value of PLL output rate, computed whenever needed to save run-time
67    computation on each call to retrive the PLL rate. */
68 static uint32_t s_Pll0_Freq;
69 static uint32_t s_Pll1_Freq;
70 
71 /** External clock rate on the CLKIN pin in Hz. If not used,
72     set this to 0. Otherwise, set it to the exact rate in Hz this pin is
73     being driven at. */
74 static uint32_t s_Ext_Clk_Freq  = 16000000U;
75 static uint32_t s_I2S_Mclk_Freq = 0U;
76 
77 /*******************************************************************************
78  * Variables
79  ******************************************************************************/
80 
81 /*******************************************************************************
82  * Prototypes
83  ******************************************************************************/
84 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
85 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
86 /* Get predivider (N) from PLL0 NDEC setting */
87 static uint32_t findPll0PreDiv(void);
88 /* Get predivider (N) from PLL1 NDEC setting */
89 static uint32_t findPll1PreDiv(void);
90 /* Get postdivider (P) from PLL0 PDEC setting */
91 static uint32_t findPll0PostDiv(void);
92 /* Get postdivider (P) from PLL1 PDEC setting. */
93 static uint32_t findPll1PostDiv(void);
94 /* Get multiplier (M) from PLL0 MDEC and SSCG settings */
95 static float findPll0MMult(void);
96 /* Get multiplier (M) from PLL1 MDEC. */
97 static uint32_t findPll1MMult(void);
98 /* Get the greatest common divisor */
99 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
100 /* Set PLL output based on desired output rate */
101 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS);
102 /* Update local PLL rate variable */
103 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup);
104 /* Update local PLL1 rate variable */
105 static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup);
106 /* Compensate for discontinuity in the capacitor banks */
107 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity);
108 /* Enables and sets LDO for High Frequency crystal oscillator */
109 static void CLOCK_SetXtalHfLdo(void);
110 
111 /*******************************************************************************
112  * Code
113  ******************************************************************************/
114 
115 /* Clock Selection for IP */
116 /**
117  * brief   Configure the clock selection muxes.
118  * param   connection  : Clock to be configured.
119  * return  Nothing
120  */
CLOCK_AttachClk(clock_attach_id_t connection)121 void CLOCK_AttachClk(clock_attach_id_t connection)
122 {
123     uint16_t mux;
124     uint8_t sel;
125     uint16_t item;
126     uint32_t tmp32 = (uint32_t)connection;
127     uint32_t i;
128     volatile uint32_t *pClkSel;
129 
130     pClkSel = &(SYSCON->SYSTICKCLKSEL0);
131 
132     if (kNONE_to_NONE != connection)
133     {
134         for (i = 0U; i < 2U; i++)
135         {
136             if (tmp32 == 0U)
137             {
138                 break;
139             }
140             item = (uint16_t)GET_ID_ITEM(tmp32);
141             if (item != 0U)
142             {
143                 mux = (uint16_t)GET_ID_ITEM_MUX(item);
144                 sel = (uint8_t)GET_ID_ITEM_SEL(item);
145                 if (mux == CM_RTCOSC32KCLKSEL)
146                 {
147                     PMC->RTCOSC32K = (PMC->RTCOSC32K & ~PMC_RTCOSC32K_SEL_MASK) | PMC_RTCOSC32K_SEL(sel);
148                 }
149                 else if (mux == CM_OSTIMERCLKSEL)
150                 {
151                     PMC->OSEVENTTIMER =
152                         (PMC->OSEVENTTIMER & ~PMC_OSEVENTTIMER_SELCLOCK_MASK) | PMC_OSEVENTTIMER_SELCLOCK(sel);
153                 }
154                 else
155                 {
156                     ((volatile uint32_t *)pClkSel)[mux] = sel;
157                 }
158             }
159             tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
160         }
161     }
162 }
163 
164 /* Return the actual clock attach id */
165 /**
166  * brief   Get the actual clock attach id.
167  * This fuction uses the offset in input attach id, then it reads the actual source value in
168  * the register and combine the offset to obtain an actual attach id.
169  * param   attachId  : Clock attach id to get.
170  * return  Clock source value.
171  */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)172 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
173 {
174     uint16_t mux;
175     uint32_t actualSel;
176     uint32_t tmp32 = (uint32_t)attachId;
177     uint32_t i;
178     uint32_t actualAttachId = 0U;
179     uint32_t selector       = GET_ID_SELECTOR(tmp32);
180     volatile uint32_t *pClkSel;
181 
182     pClkSel = &(SYSCON->SYSTICKCLKSEL0);
183 
184     if (kNONE_to_NONE == attachId)
185     {
186         return kNONE_to_NONE;
187     }
188 
189     for (i = 0U; i < 2U; i++)
190     {
191         mux = (uint16_t)GET_ID_ITEM_MUX(tmp32);
192         if (tmp32 != 0UL)
193         {
194             if (mux == CM_RTCOSC32KCLKSEL)
195             {
196                 actualSel = ((PMC->RTCOSC32K) & PMC_RTCOSC32K_SEL_MASK) >> PMC_RTCOSC32K_SEL_SHIFT;
197             }
198             else if (mux == CM_OSTIMERCLKSEL)
199             {
200                 actualSel = ((PMC->OSEVENTTIMER) & PMC_OSEVENTTIMER_SELCLOCK_MASK) >> PMC_OSEVENTTIMER_SELCLOCK_SHIFT;
201             }
202             else
203             {
204                 actualSel = (uint32_t)((volatile uint32_t *)pClkSel)[mux];
205             }
206 
207             /* Consider the combination of two registers */
208             actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
209         }
210         tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!<  pick up next descriptor */
211     }
212 
213     actualAttachId |= selector;
214 
215     return (clock_attach_id_t)actualAttachId;
216 }
217 
218 /* Set IP Clock Divider */
219 /**
220  * brief   Setup peripheral clock dividers.
221  * param   div_name    : Clock divider name
222  * param divided_by_value: Value to be divided
223  * param reset :  Whether to reset the divider counter.
224  * return  Nothing
225  */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value,bool reset)226 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
227 {
228     volatile uint32_t *pClkDiv;
229 
230     pClkDiv = &(SYSCON->SYSTICKCLKDIV[0]);
231     if ((div_name >= kCLOCK_DivFlexFrg0) && (div_name <= kCLOCK_DivFlexFrg7))
232     {
233         /*!<  Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1+ MULT /DIV), DIV = 0xFF */
234         ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] =
235             SYSCON_FRGCTRL_DIV_MASK | SYSCON_FRGCTRL_MULT(divided_by_value);
236     }
237     else
238     {
239         if (reset)
240         {
241             ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] = 1UL << 29U;
242         }
243         if (divided_by_value == 0U) /*!<  halt */
244         {
245             ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] = 1UL << 30U;
246         }
247         else
248         {
249             ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] = (divided_by_value - 1U);
250         }
251     }
252 }
253 
254 /* Set FRO Clocking */
255 /**
256  * brief   Initialize the Core clock to given frequency (12, 48 or 96 MHz).
257  * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
258  * enabled.
259  * param   iFreq   : Desired frequency (must be one of #CLK_FRO_12MHZ or #CLK_FRO_48MHZ or #CLK_FRO_96MHZ)
260  * return  returns success or fail status.
261  */
CLOCK_SetupFROClocking(uint32_t iFreq)262 status_t CLOCK_SetupFROClocking(uint32_t iFreq)
263 {
264     if ((iFreq != 12000000U) && (iFreq != 96000000U))
265     {
266         return kStatus_Fail;
267     }
268     /* Enable Analog Control module */
269     SYSCON->PRESETCTRLCLR[2] = SYSCON_PRESETCTRL2_ANACTRL_RST_MASK;
270     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL_MASK;
271 
272     /* Initialize FRO192 trim */
273     CLOCK_FroHfTrim();
274 
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  */
300 typedef struct
301 {
302     uint32_t waitstate;
303     uint32_t freqMax;
304 } WaitStateInterval_t;
305 
306 /* clang-format off */
307 /* Wait state if frequency is inferior to the one specified */
308 static const WaitStateInterval_t IntervalList[] = {
309     {0, 11000000},
310     {1, 22000000},
311     {2, 33000000},
312     {3, 44000000},
313     {4, 55000000},
314     {5, 66000000},
315     {6, 77000000},
316     {7, 88000000},
317     {8, 100000000},
318     {11, 130000000},
319     {12, 150000000} /* Maximum allowed frequency (150 MHz) */
320 };
321 /* clang-format on */
322 
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz)323 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz)
324 {
325     /* Flash Controller & FMC internal number of Wait States (minus 1) */
326     uint32_t num_wait_states = 15UL; /* Default to the maximum number of wait states */
327 
328     for (size_t cnt = 0; cnt < (sizeof(IntervalList) / sizeof(WaitStateInterval_t)); cnt++)
329     {
330         if (system_freq_hz <= IntervalList[cnt].freqMax)
331         {
332             num_wait_states = IntervalList[cnt].waitstate;
333             break;
334         }
335     }
336 
337     FLASH->INTSTAT_CLR = 0xF; /* Clear all status flags */
338 
339     FLASH->DATAW[0] = (FLASH->DATAW[0] & 0xFFFFFFF0UL) | (num_wait_states & 0xFUL);
340 
341     FLASH->CMD = 0x2; /* CMD_SET_READ_MODE */
342 
343     /* Wait until the cmd is completed (without error) */
344     while ((FLASH->INTSTAT & FLASH_INTSTAT_DONE_MASK) == 0UL)
345     {
346     }
347 
348     /* Adjust FMC waiting time cycles (num_wait_states) */
349     SYSCON->FMCCR = (SYSCON->FMCCR & 0xFFFF0FFFUL) | ((num_wait_states & 0xFUL) << 12UL);
350 }
351 
352 /* Set EXT OSC Clk */
353 /**
354  * brief   Initialize the external osc clock to given frequency.
355  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
356  * return  returns success or fail status.
357  */
CLOCK_SetupExtClocking(uint32_t iFreq)358 status_t CLOCK_SetupExtClocking(uint32_t iFreq)
359 {
360     if (iFreq >= 32000000U)
361     {
362         return kStatus_Fail;
363     }
364     /* Turn on power for crystal 32 MHz */
365     POWER_DisablePD(kPDRUNCFG_PD_XTALHF);
366     POWER_DisablePD(kPDRUNCFG_PD_LDOXTALHF);
367     /* Enable clock_in clock for clock module. */
368     SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;
369 
370     s_Ext_Clk_Freq = iFreq;
371     return kStatus_Success;
372 }
373 
374 /* Set I2S MCLK Clk */
375 /**
376  * brief   Initialize the I2S MCLK clock to given frequency.
377  * param   iFreq   : Desired frequency (must be equal to exact rate in Hz)
378  * return  returns success or fail status.
379  */
CLOCK_SetupI2SMClkClocking(uint32_t iFreq)380 status_t CLOCK_SetupI2SMClkClocking(uint32_t iFreq)
381 {
382     s_I2S_Mclk_Freq = iFreq;
383     return kStatus_Success;
384 }
385 
386 /* Get CLOCK OUT Clk */
387 /*! brief  Return Frequency of ClockOut
388  *  return Frequency of ClockOut
389  */
CLOCK_GetClockOutClkFreq(void)390 uint32_t CLOCK_GetClockOutClkFreq(void)
391 {
392     uint32_t freq = 0U;
393 
394     switch (SYSCON->CLKOUTSEL)
395     {
396         case 0U:
397             freq = CLOCK_GetCoreSysClkFreq();
398             break;
399 
400         case 1U:
401             freq = CLOCK_GetPll0OutFreq();
402             break;
403 
404         case 2U:
405             freq = CLOCK_GetExtClkFreq();
406             break;
407 
408         case 3U:
409             freq = CLOCK_GetFroHfFreq();
410             break;
411 
412         case 4U:
413             freq = CLOCK_GetFro1MFreq();
414             break;
415 
416         case 5U:
417             freq = CLOCK_GetPll1OutFreq();
418             break;
419 
420         case 6U:
421             freq = CLOCK_GetOsc32KFreq();
422             break;
423 
424         case 7U:
425             freq = 0U;
426             break;
427 
428         default:
429             freq = 0U;
430             break;
431     }
432     return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
433 }
434 
435 /* Get CAN Clk */
436 /*! brief  Return Frequency of Can Clock
437  *  return Frequency of Can.
438  */
CLOCK_GetMCanClkFreq(void)439 uint32_t CLOCK_GetMCanClkFreq(void)
440 {
441     uint32_t freq = 0U;
442 
443     switch (SYSCON->CANCLKSEL)
444     {
445         case 0U:
446             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CANCLKDIV & SYSCON_CANCLKDIV_DIV_MASK) + 1U);
447             break;
448         case 1U:
449             freq = CLOCK_GetFro1MFreq();
450             break;
451         case 2U:
452             freq = CLOCK_GetOsc32KFreq();
453             break;
454         case 7U:
455             freq = 0U;
456             break;
457 
458         default:
459             freq = 0U;
460             break;
461     }
462 
463     return freq;
464 }
465 
466 /* Get ADC Clk */
467 /*! brief  Return Frequency of Adc Clock
468  *  return Frequency of Adc.
469  */
CLOCK_GetAdcClkFreq(uint32_t id)470 uint32_t CLOCK_GetAdcClkFreq(uint32_t id)
471 {
472     uint32_t freq = 0U;
473     uint32_t div  = 0U;
474 
475     switch ((id == 0) ? (SYSCON->ADC0CLKSEL) : (SYSCON->ADC1CLKSEL))
476     {
477         case 0U:
478             freq = CLOCK_GetCoreSysClkFreq();
479             break;
480         case 1U:
481             freq = CLOCK_GetPll0OutFreq();
482             break;
483         case 2U:
484             freq = CLOCK_GetFroHfFreq();
485             break;
486         default:
487             freq = 0U;
488             break;
489     }
490 
491     div = ((id == 0) ? ((SYSCON->ADC0CLKDIV & SYSCON_ADC0CLKDIV_DIV_MASK) + 1U) :
492                        ((SYSCON->ADC1CLKDIV & SYSCON_ADC1CLKDIV_DIV_MASK) + 1U));
493 
494     return freq / div;
495 }
496 
497 /* Get USB0 Clk */
498 /*! brief  Return Frequency of Usb0 Clock
499  *  return Frequency of Usb0 Clock.
500  */
CLOCK_GetUsb0ClkFreq(void)501 uint32_t CLOCK_GetUsb0ClkFreq(void)
502 {
503     uint32_t freq = 0U;
504 
505     switch (SYSCON->USB0CLKSEL)
506     {
507         case 0U:
508             freq = CLOCK_GetCoreSysClkFreq();
509             break;
510         case 1U:
511             freq = CLOCK_GetPll0OutFreq();
512             break;
513         case 3U:
514             freq = CLOCK_GetFroHfFreq();
515             break;
516         case 5U:
517             freq = CLOCK_GetPll1OutFreq();
518             break;
519         case 7U:
520             freq = 0U;
521             break;
522 
523         default:
524             freq = 0U;
525             break;
526     }
527 
528     return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);
529 }
530 
531 /* Get MCLK Clk */
532 /*! brief  Return Frequency of MClk Clock
533  *  return Frequency of MClk Clock.
534  */
CLOCK_GetMclkClkFreq(void)535 uint32_t CLOCK_GetMclkClkFreq(void)
536 {
537     uint32_t freq = 0U;
538 
539     switch (SYSCON->MCLKCLKSEL)
540     {
541         case 0U:
542             freq = CLOCK_GetFroHfFreq();
543             break;
544         case 1U:
545             freq = CLOCK_GetPll0OutFreq();
546             break;
547         case 7U:
548             freq = 0U;
549             break;
550 
551         default:
552             freq = 0U;
553             break;
554     }
555 
556     return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);
557 }
558 
559 /* Get SCTIMER Clk */
560 /*! brief  Return Frequency of SCTimer Clock
561  *  return Frequency of SCTimer Clock.
562  */
CLOCK_GetSctClkFreq(void)563 uint32_t CLOCK_GetSctClkFreq(void)
564 {
565     uint32_t freq = 0U;
566 
567     switch (SYSCON->SCTCLKSEL)
568     {
569         case 0U:
570             freq = CLOCK_GetCoreSysClkFreq();
571             break;
572         case 1U:
573             freq = CLOCK_GetPll0OutFreq();
574             break;
575         case 2U:
576             freq = CLOCK_GetExtClkFreq();
577             break;
578         case 3U:
579             freq = CLOCK_GetFroHfFreq();
580             break;
581         case 4U:
582             freq = CLOCK_GetPll1OutFreq();
583             break;
584         case 5U:
585             freq = CLOCK_GetI2SMClkFreq();
586             break;
587         case 7U:
588             freq = 0U;
589             break;
590 
591         default:
592             freq = 0U;
593             break;
594     }
595 
596     return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
597 }
598 
599 /* Get FRO 12M Clk */
600 /*! brief  Return Frequency of FRO 12MHz
601  *  return Frequency of FRO 12MHz
602  */
CLOCK_GetFro12MFreq(void)603 uint32_t CLOCK_GetFro12MFreq(void)
604 {
605     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U;
606 }
607 
608 /* Get FRO 1M Clk */
609 /*! brief  Return Frequency of FRO 1MHz
610  *  return Frequency of FRO 1MHz
611  */
CLOCK_GetFro1MFreq(void)612 uint32_t CLOCK_GetFro1MFreq(void)
613 {
614     return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U;
615 }
616 
617 /* Get EXT OSC Clk */
618 /*! brief  Return Frequency of External Clock
619  *  return Frequency of External Clock. If no external clock is used returns 0.
620  */
CLOCK_GetExtClkFreq(void)621 uint32_t CLOCK_GetExtClkFreq(void)
622 {
623     return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
624 }
625 
626 /* Get WATCH DOG Clk */
627 /*! brief  Return Frequency of Watchdog
628  *  return Frequency of Watchdog
629  */
CLOCK_GetWdtClkFreq(void)630 uint32_t CLOCK_GetWdtClkFreq(void)
631 {
632     return CLOCK_GetFro1MFreq() / ((SYSCON->WDTCLKDIV & SYSCON_WDTCLKDIV_DIV_MASK) + 1U);
633 }
634 
635 /* Get HF FRO Clk */
636 /*! brief  Return Frequency of High-Freq output of FRO
637  *  return Frequency of High-Freq output of FRO
638  */
CLOCK_GetFroHfFreq(void)639 uint32_t CLOCK_GetFroHfFreq(void)
640 {
641     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U;
642 }
643 
644 /* Get SYSTEM PLL Clk */
645 /*! brief  Return Frequency of PLL
646  *  return Frequency of PLL
647  */
CLOCK_GetPll0OutFreq(void)648 uint32_t CLOCK_GetPll0OutFreq(void)
649 {
650     return s_Pll0_Freq;
651 }
652 
653 /* Get USB PLL Clk */
654 /*! brief  Return Frequency of USB PLL
655  *  return Frequency of PLL
656  */
CLOCK_GetPll1OutFreq(void)657 uint32_t CLOCK_GetPll1OutFreq(void)
658 {
659     return s_Pll1_Freq;
660 }
661 
662 /* Get RTC OSC Clk */
663 /*! brief  Return Frequency of 32kHz osc
664  *  return Frequency of 32kHz osc
665  */
CLOCK_GetOsc32KFreq(void)666 uint32_t CLOCK_GetOsc32KFreq(void)
667 {
668     return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
669             (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
670                CLK_RTC_32K_CLK :
671                ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
672                 ((PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK) != 0UL)) ?
673                CLK_RTC_32K_CLK :
674                0UL;
675 }
676 
677 /* Get Flexcomm 32K Clk */
678 /*! brief  Return Frequency of Flexcomm 32kHz
679  *  return Frequency of Flexcomm 32kHz
680  */
CLOCK_GetFC32KFreq(void)681 uint32_t CLOCK_GetFC32KFreq(void)
682 {
683     return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
684             (0UL == (SYSCON->FC32KCLKSEL & SYSCON_FC32KCLKSEL_FC32KCLKSEL_MASK))) ?
685                CLK_RTC_32K_CLK :
686                ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
687                 ((SYSCON->FC32KCLKSEL & SYSCON_FC32KCLKSEL_FC32KCLKSEL_MASK) != 0UL)) ?
688                CLK_RTC_32K_CLK :
689                0UL;
690 }
691 
692 /* Get MAIN Clk */
693 /*! brief  Return Frequency of Core System
694  *  return Frequency of Core System
695  */
CLOCK_GetCoreSysClkFreq(void)696 uint32_t CLOCK_GetCoreSysClkFreq(void)
697 {
698     uint32_t freq = 0U;
699 
700     switch (SYSCON->MAINCLKSELB)
701     {
702         case 0U:
703             if (SYSCON->MAINCLKSELA == 0U)
704             {
705                 freq = CLOCK_GetFro12MFreq();
706             }
707             else if (SYSCON->MAINCLKSELA == 1U)
708             {
709                 freq = CLOCK_GetExtClkFreq();
710             }
711             else if (SYSCON->MAINCLKSELA == 2U)
712             {
713                 freq = CLOCK_GetFro1MFreq();
714             }
715             else if (SYSCON->MAINCLKSELA == 3U)
716             {
717                 freq = CLOCK_GetFroHfFreq();
718             }
719             else
720             {
721                 /* Added comments to avoid the violation of MISRA C-2012 rule 15.7 */
722             }
723             break;
724         case 1U:
725             freq = CLOCK_GetPll0OutFreq();
726             break;
727         case 2U:
728             freq = CLOCK_GetPll1OutFreq();
729             break;
730 
731         case 3U:
732             freq = CLOCK_GetOsc32KFreq();
733             break;
734 
735         default:
736             freq = 0U;
737             break;
738     }
739 
740     return freq;
741 }
742 
743 /* Get I2S MCLK Clk */
744 /*! brief  Return Frequency of I2S MCLK Clock
745  *  return Frequency of I2S MCLK Clock
746  */
CLOCK_GetI2SMClkFreq(void)747 uint32_t CLOCK_GetI2SMClkFreq(void)
748 {
749     return s_I2S_Mclk_Freq;
750 }
751 
752 /* Get PLLClkDiv Clk */
CLOCK_GetPllClkDivFreq(void)753 uint32_t CLOCK_GetPllClkDivFreq(void)
754 {
755     uint32_t freq = 0U;
756 
757     switch (SYSCON->PLLCLKDIVSEL)
758     {
759         case 0U:
760             freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLLCLKDIV & SYSCON_PLLCLKDIV_DIV_MASK) + 1U);
761             break;
762         case 1U:
763             freq = CLOCK_GetPll1OutFreq() /
764                    ((SYSCON->PLLCLKDIV & SYSCON_PLLCLKDIV_DIV_MASK) + 1U); // register name should be checked
765             break;
766         default:
767             freq = 0U;
768             break;
769     }
770     /* todo: pll_clk_div = pll_clk/div*/
771     return freq;
772 }
773 
774 /* Get FRG Clk */
CLOCK_GetFrgFreq(uint32_t id)775 uint32_t CLOCK_GetFrgFreq(uint32_t id)
776 {
777     uint32_t freq = 0U;
778 
779     switch (SYSCON->FRGCLKSEL[id])
780     {
781         case 0U:
782             freq = CLOCK_GetCoreSysClkFreq();
783             break;
784         case 1U:
785             freq = CLOCK_GetPllClkDivFreq();
786             break;
787         case 2U:
788             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
789             break;
790         default:
791             freq = 0U;
792             break;
793     }
794     return (uint32_t)(((uint64_t)freq * (SYSCON_FRGCTRL_DIV_MASK + 1U)) /
795                       ((SYSCON_FRGCTRL_DIV_MASK + 1U) +
796                        ((SYSCON->FRGCTRL[id] & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)));
797 }
798 
799 /* Get FLEXCOMM Clk */
CLOCK_GetFlexCommClkFreq(uint32_t id)800 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
801 {
802     uint32_t freq = 0U;
803 
804     switch (SYSCON->FCCLKSEL[id])
805     {
806         case 0U:
807             freq = CLOCK_GetCoreSysClkFreq();
808             break;
809         case 1U:
810             freq = CLOCK_GetFrgFreq(id);
811             break;
812         case 2U:
813             freq = CLOCK_GetFro12MFreq();
814             break;
815         case 3U:
816             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
817             break;
818         case 4U:
819             freq = CLOCK_GetFro1MFreq();
820             break;
821         case 5U:
822             freq = CLOCK_GetI2SMClkFreq();
823             break;
824         case 6U:
825             freq = CLOCK_GetOsc32KFreq();
826             break;
827         case 7U:
828             freq = 0U;
829             break;
830 
831         default:
832             freq = 0U;
833             break;
834     }
835 
836     return freq / ((SYSCON->FLEXCOMMCLKDIV[id] & 0xffU) + 1U);
837 }
838 
839 /* Get HS_LPSI Clk */
CLOCK_GetHsLspiClkFreq(void)840 uint32_t CLOCK_GetHsLspiClkFreq(void)
841 {
842     uint32_t freq = 0U;
843 
844     switch (SYSCON->HSSPICLKSEL)
845     {
846         case 0U:
847             freq = CLOCK_GetCoreSysClkFreq();
848             break;
849         case 1U:
850             freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLLCLKDIV & 0xffU) + 1U);
851             break;
852         case 2U:
853             freq = CLOCK_GetFro12MFreq();
854             break;
855         case 3U:
856             freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
857             break;
858         case 4U:
859             freq = CLOCK_GetFro1MFreq();
860             break;
861         case 6U:
862             freq = CLOCK_GetOsc32KFreq();
863             break;
864         case 7U:
865             freq = 0U;
866             break;
867 
868         default:
869             freq = 0U;
870             break;
871     }
872 
873     return freq;
874 }
875 
876 /* Get CTimer Clk */
877 /*! brief  Return Frequency of CTimer functional Clock
878  *  return Frequency of CTimer functional Clock
879  */
CLOCK_GetCTimerClkFreq(uint32_t id)880 uint32_t CLOCK_GetCTimerClkFreq(uint32_t id)
881 {
882     uint32_t freq = 0U;
883 
884     switch (SYSCON->CTIMERCLKSEL[id])
885     {
886         case 0U:
887             freq = CLOCK_GetCoreSysClkFreq();
888             break;
889         case 1U:
890             freq = CLOCK_GetPll0OutFreq();
891             break;
892         case 2U:
893             freq = CLOCK_GetPll1OutFreq();
894             break;
895         case 3U:
896             freq = CLOCK_GetFroHfFreq();
897             break;
898         case 4U:
899             freq = CLOCK_GetFro1MFreq();
900             break;
901         case 5U:
902             freq = CLOCK_GetI2SMClkFreq();
903             break;
904         case 6U:
905             freq = CLOCK_GetOsc32KFreq();
906             break;
907         case 7U:
908             freq = 0U;
909             break;
910 
911         default:
912             freq = 0U;
913             break;
914     }
915 
916     return freq / ((SYSCON->CTIMERCLKDIV[id] & 0xffU) + 1U);
917 }
918 
919 /* Get Systick Clk */
920 /*! brief  Return Frequency of SystickClock
921  *  return Frequency of Systick Clock
922  */
CLOCK_GetSystickClkFreq(void)923 uint32_t CLOCK_GetSystickClkFreq(void)
924 {
925     uint32_t freq = 0U;
926 
927     switch (SYSCON->SYSTICKCLKSEL0)
928     {
929         case 0U:
930             /*Niobe4mini just has one SYSTICKSEL and SYSTICKDIV register, Fix coverity problem in this way temporarily
931              */
932             freq = CLOCK_GetCoreSysClkFreq() / (((SYSCON->SYSTICKCLKDIV[0]) & 0xffU) + 1U);
933             break;
934         case 1U:
935             freq = CLOCK_GetFro1MFreq();
936             break;
937         case 2U:
938             freq = CLOCK_GetOsc32KFreq();
939             break;
940         case 7U:
941             freq = 0U;
942             break;
943 
944         default:
945             freq = 0U;
946             break;
947     }
948 
949     return freq;
950 }
951 
952 /* Get DAC Clk */
953 /*! brief  Return Frequency of DAC Clock
954  *  return Frequency of DAC.
955  */
CLOCK_GetDacClkFreq(uint32_t id)956 uint32_t CLOCK_GetDacClkFreq(uint32_t id)
957 {
958     uint32_t freq = 0U;
959 
960     switch (SYSCON->DAC[id].CLKSEL)
961     {
962         case 0U:
963             freq = CLOCK_GetCoreSysClkFreq();
964             break;
965         case 1U:
966             freq = CLOCK_GetPll0OutFreq();
967             break;
968         case 3U:
969             freq = CLOCK_GetFroHfFreq();
970             break;
971         case 4U:
972             freq = CLOCK_GetFro12MFreq();
973             break;
974         case 5U:
975             freq = CLOCK_GetPll1OutFreq();
976             break;
977         case 6U:
978             freq = CLOCK_GetFro1MFreq();
979             break;
980         default:
981             freq = 0U;
982             break;
983     }
984 
985     return freq / ((SYSCON->DAC[id].CLKDIV & SYSCON_DAC_CLKDIV_DIV_MASK) + 1U);
986 }
987 
988 /* Get FlexSpi Clk */
989 /*! brief  Return Frequency of FlexSpi clock
990  *  return Frequency of FlexSpi Clock
991  */
CLOCK_GetFlexSpiClkFreq(void)992 uint32_t CLOCK_GetFlexSpiClkFreq(void)
993 {
994     uint32_t freq = 0U;
995 
996     switch (SYSCON->FLEXSPICLKSEL)
997     {
998         case 0U:
999             freq = CLOCK_GetCoreSysClkFreq();
1000             break;
1001         case 1U:
1002             freq = CLOCK_GetPll0OutFreq();
1003             break;
1004         case 3U:
1005             freq = CLOCK_GetFroHfFreq();
1006             break;
1007         case 5U:
1008             freq = CLOCK_GetPll1OutFreq();
1009             break;
1010         case 7U:
1011             freq = 0U;
1012             break;
1013         default:
1014             freq = 0U;
1015             break;
1016     }
1017 
1018     return freq / ((SYSCON->FLEXSPICLKDIV & SYSCON_FLEXSPICLKDIV_DIV_MASK) + 1U);
1019 }
1020 
1021 /* Get DMIC Clk */
1022 /*! brief  Return Frequency of DMIC clock
1023  *  return Frequency of DMIC Clock
1024  */
CLOCK_GetDmicClkFreq(void)1025 uint32_t CLOCK_GetDmicClkFreq(void)
1026 {
1027     uint32_t freq = 0U;
1028 
1029     switch (SYSCON->DMICFCLKSEL)
1030     {
1031         case 0U:
1032             freq = CLOCK_GetCoreSysClkFreq();
1033             break;
1034         case 1U:
1035             freq = CLOCK_GetPll0OutFreq();
1036             break;
1037         case 2U:
1038             freq = CLOCK_GetExtClkFreq();
1039             break;
1040         case 3U:
1041             freq = CLOCK_GetFroHfFreq();
1042             break;
1043         case 4U:
1044             freq = CLOCK_GetPll1OutFreq();
1045             break;
1046         case 5U:
1047             freq = CLOCK_GetI2SMClkFreq();
1048             break;
1049         default:
1050             freq = 0U;
1051             break;
1052     }
1053 
1054     return freq / ((SYSCON->DMICFCLKDIV & SYSCON_DMICFCLKDIV_DIV_MASK) + 1U);
1055 }
1056 
1057 /* Get I3C function Clk */
1058 /*! brief  Return Frequency of I3C function clock
1059  *  return Frequency of I3C function Clock
1060  */
CLOCK_GetI3cClkFreq(void)1061 uint32_t CLOCK_GetI3cClkFreq(void)
1062 {
1063     uint32_t freq = 0U;
1064 
1065     switch (SYSCON->I3CFCLKSEL)
1066     {
1067         case 0U:
1068             freq = CLOCK_GetCoreSysClkFreq();
1069             break;
1070         case 1U:
1071             freq = CLOCK_GetPllClkDivFreq();
1072             break;
1073         default:
1074             freq = 0U;
1075             break;
1076     }
1077 
1078     return freq / ((SYSCON->I3CFCLKDIV & SYSCON_I3CFCLKDIV_DIV_MASK) + 1U);
1079 }
1080 
1081 /* Get I3C function slow TC Clk */
1082 /*! brief  Return Frequency of I3C function Slow TC clock
1083  *  return Frequency of I3C function slow TC Clock
1084  */
CLOCK_GetI3cSTCClkFreq(void)1085 uint32_t CLOCK_GetI3cSTCClkFreq(void)
1086 {
1087     uint32_t freq = 0U;
1088 
1089     switch (SYSCON->I3CFCLKSTCSEL)
1090     {
1091         case 0U:
1092             freq = CLOCK_GetI3cClkFreq();
1093             break;
1094         case 1U:
1095             freq = CLOCK_GetFro1MFreq();
1096             break;
1097         default:
1098             freq = 0U;
1099             break;
1100     }
1101 
1102     return freq / ((SYSCON->I3CFCLKSTCDIV & SYSCON_I3CFCLKSTCDIV_DIV_MASK) + 1U);
1103 }
1104 
1105 /* Get I3C function slow Clk */
1106 /*! brief  Return Frequency of I3C function Slow clock
1107  *  return Frequency of I3C function slow Clock
1108  */
CLOCK_GetI3cSClkFreq(void)1109 uint32_t CLOCK_GetI3cSClkFreq(void)
1110 {
1111     uint32_t freq = 0U;
1112 
1113     switch (SYSCON->I3CFCLKSSEL)
1114     {
1115         case 0U:
1116             freq = CLOCK_GetFro1MFreq();
1117             break;
1118         default:
1119             freq = 0U;
1120             break;
1121     }
1122 
1123     return freq / ((SYSCON->I3CFCLKSDIV & SYSCON_I3CFCLKSDIV_DIV_MASK) + 1U);
1124 }
1125 
1126 /* Get IP Clk */
1127 /*! brief  Return Frequency of selected clock
1128  *  return Frequency of selected clock
1129  */
CLOCK_GetFreq(clock_name_t clockName)1130 uint32_t CLOCK_GetFreq(clock_name_t clockName)
1131 {
1132     uint32_t freq;
1133     switch (clockName)
1134     {
1135         case kCLOCK_CoreSysClk:
1136             freq = CLOCK_GetCoreSysClkFreq();
1137             break;
1138         case kCLOCK_BusClk:
1139             freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
1140             break;
1141         case kCLOCK_ClockOut:
1142             freq = CLOCK_GetClockOutClkFreq();
1143             break;
1144         case kCLOCK_Pll1Out:
1145             freq = CLOCK_GetPll1OutFreq();
1146             break;
1147         case kCLOCK_Mclk:
1148             freq = CLOCK_GetMclkClkFreq();
1149             break;
1150         case kCLOCK_FroHf:
1151             freq = CLOCK_GetFroHfFreq();
1152             break;
1153         case kCLOCK_Fro12M:
1154             freq = CLOCK_GetFro12MFreq();
1155             break;
1156         case kCLOCK_Fro1M:
1157             freq = CLOCK_GetFro1MFreq();
1158             break;
1159         case kCLOCK_ExtClk:
1160             freq = CLOCK_GetExtClkFreq();
1161             break;
1162         case kCLOCK_Pll0Out:
1163             freq = CLOCK_GetPll0OutFreq();
1164             break;
1165         case kCLOCK_FlexI2S:
1166             freq = CLOCK_GetI2SMClkFreq();
1167             break;
1168         default:
1169             freq = 0U;
1170             break;
1171     }
1172     return freq;
1173 }
1174 
1175 /* 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)1176 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
1177 {
1178     uint32_t seli, selp;
1179     /* bandwidth: compute selP from Multiplier */
1180     if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) != 0UL) /* normal mode */
1181     {
1182         selp = (M >> 2U) + 1U;
1183         if (selp >= 31U)
1184         {
1185             selp = 31U;
1186         }
1187         *pSelP = selp;
1188 
1189         if (M >= 8000UL)
1190         {
1191             seli = 1UL;
1192         }
1193         else if (M >= 122UL)
1194         {
1195             seli = (uint32_t)(8000UL / M); /*floor(8000/M) */
1196         }
1197         else
1198         {
1199             seli = 2UL * ((uint32_t)(M / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
1200         }
1201 
1202         if (seli >= 63UL)
1203         {
1204             seli = 63UL;
1205         }
1206         *pSelI = seli;
1207 
1208         *pSelR = 0UL;
1209     }
1210     else
1211     {
1212         /* Note: If the spread spectrum mode, choose N to ensure 3 MHz < Fin/N < 5 MHz */
1213         *pSelP = 3U;
1214         *pSelI = 4U;
1215         *pSelR = 4U;
1216     }
1217 }
1218 
1219 /* Get predivider (N) from PLL0 NDEC setting */
findPll0PreDiv(void)1220 static uint32_t findPll0PreDiv(void)
1221 {
1222     uint32_t preDiv = 1UL;
1223 
1224     /* Direct input is not used? */
1225     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPREDIV_MASK) == 0UL)
1226     {
1227         preDiv = SYSCON->PLL0NDEC & SYSCON_PLL0NDEC_NDIV_MASK;
1228         if (preDiv == 0UL)
1229         {
1230             preDiv = 1UL;
1231         }
1232     }
1233     return preDiv;
1234 }
1235 
1236 /* Get predivider (N) from PLL1 NDEC setting */
findPll1PreDiv(void)1237 static uint32_t findPll1PreDiv(void)
1238 {
1239     uint32_t preDiv = 1UL;
1240 
1241     /* Direct input is not used? */
1242     if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL)
1243     {
1244         preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK;
1245         if (preDiv == 0UL)
1246         {
1247             preDiv = 1UL;
1248         }
1249     }
1250     return preDiv;
1251 }
1252 
1253 /* Get postdivider (P) from PLL0 PDEC setting */
findPll0PostDiv(void)1254 static uint32_t findPll0PostDiv(void)
1255 {
1256     uint32_t postDiv = 1UL;
1257 
1258     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1259     {
1260         if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1261         {
1262             postDiv = SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK;
1263         }
1264         else
1265         {
1266             postDiv = 2UL * (SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK);
1267         }
1268         if (postDiv == 0UL)
1269         {
1270             postDiv = 2UL;
1271         }
1272     }
1273     return postDiv;
1274 }
1275 
1276 /* Get postdivider (P) from PLL1 PDEC setting. */
findPll1PostDiv(void)1277 static uint32_t findPll1PostDiv(void)
1278 {
1279     uint32_t postDiv = 1UL;
1280 
1281     if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1282     {
1283         if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1284         {
1285             postDiv = SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK;
1286         }
1287         else
1288         {
1289             postDiv = 2UL * (SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK);
1290         }
1291         if (postDiv == 0UL)
1292         {
1293             postDiv = 2UL;
1294         }
1295     }
1296 
1297     return postDiv;
1298 }
1299 
1300 /* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
findPll0MMult(void)1301 static float findPll0MMult(void)
1302 {
1303     float mMult = 1.0F;
1304     float mMult_fract;
1305     uint32_t mMult_int;
1306 
1307     if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL)
1308     {
1309         mMult =
1310             (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT);
1311     }
1312     else
1313     {
1314         mMult_int   = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U);
1315         mMult_int   = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL0_SSCG_MD_INT_P);
1316         mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL0_SSCG_MD_FRACT_M) /
1317                        (float)(uint32_t)(1UL << PLL0_SSCG_MD_INT_P));
1318         mMult       = (float)mMult_int + mMult_fract;
1319     }
1320     if (0ULL == ((uint64_t)mMult))
1321     {
1322         mMult = 1.0F;
1323     }
1324     return mMult;
1325 }
1326 
1327 /* Get multiplier (M) from PLL1 MDEC. */
findPll1MMult(void)1328 static uint32_t findPll1MMult(void)
1329 {
1330     uint32_t mMult = 1UL;
1331 
1332     mMult = SYSCON->PLL1MDEC & SYSCON_PLL1MDEC_MDIV_MASK;
1333 
1334     if (mMult == 0UL)
1335     {
1336         mMult = 1UL;
1337     }
1338 
1339     return mMult;
1340 }
1341 
1342 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1343 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1344 {
1345     uint32_t tmp;
1346 
1347     while (n != 0U)
1348     {
1349         tmp = n;
1350         n   = m % n;
1351         m   = tmp;
1352     }
1353 
1354     return m;
1355 }
1356 
1357 /*
1358  * Set PLL0 output based on desired output rate.
1359  * In this function, the it calculates the PLL0 setting for output frequency from input clock
1360  * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1361  * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1362  */
CLOCK_GetPll0ConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1363 static pll_error_t CLOCK_GetPll0ConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1364 {
1365     uint32_t nDivOutHz, fccoHz;
1366     uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
1367     uint32_t pllDirectInput, pllDirectOutput;
1368     uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
1369 
1370     /* Baseline parameters (no input or output dividers) */
1371     pllPreDivider   = 1U; /* 1 implies pre-divider will be disabled */
1372     pllPostDivider  = 1U; /* 1 implies post-divider will be disabled */
1373     pllDirectOutput = 1U;
1374 
1375     /* Verify output rate parameter */
1376     if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1377     {
1378         /* Maximum PLL output with post divider=1 cannot go above this frequency */
1379         return kStatus_PLL_OutputTooHigh;
1380     }
1381     if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1382     {
1383         /* Minmum PLL output with maximum post divider cannot go below this frequency */
1384         return kStatus_PLL_OutputTooLow;
1385     }
1386 
1387     /* If using SS mode, input clock needs to be between 3MHz and 20MHz */
1388     if (useSS)
1389     {
1390         /* Verify input rate parameter */
1391         if (finHz < PLL_MIN_IN_SSMODE)
1392         {
1393             /* Input clock into the PLL cannot be lower than this */
1394             return kStatus_PLL_InputTooLow;
1395         }
1396         /* PLL input in SS mode must be under 20MHz */
1397         if (finHz > (PLL_MAX_IN_SSMODE * NVALMAX))
1398         {
1399             return kStatus_PLL_InputTooHigh;
1400         }
1401     }
1402     else
1403     {
1404         /* Verify input rate parameter */
1405         if (finHz < PLL_LOWER_IN_LIMIT)
1406         {
1407             /* Input clock into the PLL cannot be lower than this */
1408             return kStatus_PLL_InputTooLow;
1409         }
1410         if (finHz > PLL_HIGHER_IN_LIMIT)
1411         {
1412             /* Input clock into the PLL cannot be higher than this */
1413             return kStatus_PLL_InputTooHigh;
1414         }
1415     }
1416 
1417     /* Find the optimal CCO frequency for the output and input that
1418        will keep it inside the PLL CCO range. This may require
1419        tweaking the post-divider for the PLL. */
1420     fccoHz = foutHz;
1421     while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1422     {
1423         /* CCO output is less than minimum CCO range, so the CCO output
1424            needs to be bumped up and the post-divider is used to bring
1425            the PLL output back down. */
1426         pllPostDivider++;
1427         if (pllPostDivider > PVALMAX)
1428         {
1429             return kStatus_PLL_OutsideIntLimit;
1430         }
1431 
1432         /* Target CCO goes up, PLL output goes down */
1433         /* divide-by-2 divider in the post-divider is always work*/
1434         fccoHz          = foutHz * (pllPostDivider * 2U);
1435         pllDirectOutput = 0U;
1436     }
1437 
1438     /* Determine if a pre-divider is needed to get the best frequency */
1439     if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
1440     {
1441         uint32_t a = FindGreatestCommonDivisor(fccoHz, finHz);
1442 
1443         if (a > PLL_LOWER_IN_LIMIT)
1444         {
1445             a = finHz / a;
1446             if ((a != 0U) && (a < PLL_MAX_N_DIV))
1447             {
1448                 pllPreDivider = a;
1449             }
1450         }
1451     }
1452 
1453     /* Bypass pre-divider hardware if pre-divider is 1 */
1454     if (pllPreDivider > 1U)
1455     {
1456         pllDirectInput = 0U;
1457     }
1458     else
1459     {
1460         pllDirectInput = 1U;
1461     }
1462 
1463     /* Determine PLL multipler */
1464     nDivOutHz     = (finHz / pllPreDivider);
1465     pllMultiplier = (fccoHz / nDivOutHz);
1466 
1467     /* Find optimal values for filter */
1468     if (useSS == false)
1469     {
1470         /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1471         if ((nDivOutHz * ((pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1472         {
1473             pllMultiplier++;
1474         }
1475 
1476         /* Setup filtering */
1477         pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
1478         uplimoff = 0U;
1479 
1480         /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1481         pSetup->pllsscg[1] =
1482             (uint32_t)((PLL_SSCG1_MDEC_VAL_SET(pllMultiplier)) | (1UL << SYSCON_PLL0SSCG1_SEL_EXT_SHIFT));
1483     }
1484     else
1485     {
1486         uint64_t fc;
1487 
1488         /* Filtering will be handled by SSC */
1489         pllSelR  = 0UL;
1490         pllSelI  = 0UL;
1491         pllSelP  = 0UL;
1492         uplimoff = 1U;
1493 
1494         /* The PLL multiplier will get very close and slightly under the
1495            desired target frequency. A small fractional component can be
1496            added to fine tune the frequency upwards to the target. */
1497         fc = ((uint64_t)(uint32_t)(fccoHz % nDivOutHz) << 25UL) / nDivOutHz;
1498 
1499         /* Set multiplier */
1500         pSetup->pllsscg[0] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) | PLL0_SSCG_MD_FRACT_SET((uint32_t)fc));
1501         pSetup->pllsscg[1] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) >> 32U);
1502     }
1503 
1504     /* Get encoded values for N (prediv) and P (postdiv) */
1505     pSetup->pllndec = PLL_NDEC_VAL_SET(pllPreDivider);
1506     pSetup->pllpdec = PLL_PDEC_VAL_SET(pllPostDivider);
1507 
1508     /* PLL control */
1509     pSetup->pllctrl = (pllSelR << SYSCON_PLL0CTRL_SELR_SHIFT) |                  /* Filter coefficient */
1510                       (pllSelI << SYSCON_PLL0CTRL_SELI_SHIFT) |                  /* Filter coefficient */
1511                       (pllSelP << SYSCON_PLL0CTRL_SELP_SHIFT) |                  /* Filter coefficient */
1512                       (0UL << SYSCON_PLL0CTRL_BYPASSPLL_SHIFT) |                 /* PLL bypass mode disabled */
1513                       (uplimoff << SYSCON_PLL0CTRL_LIMUPOFF_SHIFT) |             /* SS/fractional mode disabled */
1514                       (pllDirectInput << SYSCON_PLL0CTRL_BYPASSPREDIV_SHIFT) |   /* Bypass pre-divider? */
1515                       (pllDirectOutput << SYSCON_PLL0CTRL_BYPASSPOSTDIV_SHIFT) | /* Bypass post-divider? */
1516                       (1UL << SYSCON_PLL0CTRL_CLKEN_SHIFT);                      /* Ensure the PLL clock output */
1517 
1518     return kStatus_PLL_Success;
1519 }
1520 
1521 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1522 /* Alloct the static buffer for cache. */
1523 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1524 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]  = {0};
1525 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1526 static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]      = {false};
1527 static uint32_t s_PllSetupCacheIdx                                  = 0U;
1528 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1529 
1530 /*
1531  * Calculate the PLL setting values from input clock freq to output freq.
1532  */
CLOCK_GetPll0Config(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1533 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1534 {
1535     pll_error_t retErr;
1536 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1537     uint32_t i;
1538 
1539     for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1540     {
1541         if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && (useSS == s_UseSSCache[i]))
1542         {
1543             /* Hit the target in cache buffer. */
1544             pSetup->pllctrl    = s_PllSetupCacheStruct[i].pllctrl;
1545             pSetup->pllndec    = s_PllSetupCacheStruct[i].pllndec;
1546             pSetup->pllpdec    = s_PllSetupCacheStruct[i].pllpdec;
1547             pSetup->pllsscg[0] = s_PllSetupCacheStruct[i].pllsscg[0];
1548             pSetup->pllsscg[1] = s_PllSetupCacheStruct[i].pllsscg[1];
1549             retErr             = kStatus_PLL_Success;
1550             break;
1551         }
1552     }
1553 
1554     if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1555     {
1556         return retErr;
1557     }
1558 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1559 
1560     retErr = CLOCK_GetPll0ConfigInternal(finHz, foutHz, pSetup, useSS);
1561 
1562 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1563     /* Cache the most recent calulation result into buffer. */
1564     s_FinHzCache[s_PllSetupCacheIdx]  = finHz;
1565     s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1566     s_UseSSCache[s_PllSetupCacheIdx]  = useSS;
1567 
1568     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl    = pSetup->pllctrl;
1569     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec    = pSetup->pllndec;
1570     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec    = pSetup->pllpdec;
1571     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[0] = pSetup->pllsscg[0];
1572     s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[1] = pSetup->pllsscg[1];
1573     /* Update the index for next available buffer. */
1574     s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1575 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1576 
1577     return retErr;
1578 }
1579 
1580 /* Update local PLL rate variable */
CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t * pSetup)1581 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup)
1582 {
1583     s_Pll0_Freq = CLOCK_GetPLL0OutFromSetup(pSetup);
1584 }
1585 
1586 /* Update local PLL1 rate variable */
CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t * pSetup)1587 static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup)
1588 {
1589     s_Pll1_Freq = CLOCK_GetPLL1OutFromSetup(pSetup);
1590 }
1591 
1592 /* Return System PLL input clock rate */
1593 /*! brief    Return  PLL0 input clock rate
1594  *  return    PLL0 input clock rate
1595  */
CLOCK_GetPLL0InClockRate(void)1596 uint32_t CLOCK_GetPLL0InClockRate(void)
1597 {
1598     uint32_t clkRate = 0U;
1599 
1600     switch ((SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK))
1601     {
1602         case 0x00U:
1603             clkRate = CLK_FRO_12MHZ;
1604             break;
1605 
1606         case 0x01U:
1607             clkRate = CLOCK_GetExtClkFreq();
1608             break;
1609 
1610         case 0x02U:
1611             clkRate = CLOCK_GetFro1MFreq();
1612             break;
1613 
1614         case 0x03U:
1615             clkRate = CLOCK_GetOsc32KFreq();
1616             break;
1617 
1618         default:
1619             clkRate = 0U;
1620             break;
1621     }
1622 
1623     return clkRate;
1624 }
1625 
1626 /* Return PLL1 input clock rate */
CLOCK_GetPLL1InClockRate(void)1627 uint32_t CLOCK_GetPLL1InClockRate(void)
1628 {
1629     uint32_t clkRate = 0U;
1630 
1631     switch ((SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK))
1632     {
1633         case 0x00U:
1634             clkRate = CLK_FRO_12MHZ;
1635             break;
1636 
1637         case 0x01U:
1638             clkRate = CLOCK_GetExtClkFreq();
1639             break;
1640 
1641         case 0x02U:
1642             clkRate = CLOCK_GetFro1MFreq();
1643             break;
1644 
1645         case 0x03U:
1646             clkRate = CLOCK_GetOsc32KFreq();
1647             break;
1648 
1649         default:
1650             clkRate = 0U;
1651             break;
1652     }
1653 
1654     return clkRate;
1655 }
1656 
1657 /* Return PLL0 output clock rate from setup structure */
1658 /*! brief    Return PLL0 output clock rate from setup structure
1659  *  param    pSetup : Pointer to a PLL setup structure
1660  *  return   PLL0 output clock rate the setup structure will generate
1661  */
CLOCK_GetPLL0OutFromSetup(pll_setup_t * pSetup)1662 uint32_t CLOCK_GetPLL0OutFromSetup(pll_setup_t *pSetup)
1663 {
1664     uint32_t clkRate = 0;
1665     uint32_t prediv, postdiv;
1666     float workRate = 0.0F;
1667 
1668     /* Get the input clock frequency of PLL. */
1669     clkRate = CLOCK_GetPLL0InClockRate();
1670 
1671     if (((pSetup->pllctrl & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) &&
1672         ((pSetup->pllctrl & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) &&
1673         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) &&
1674         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL))
1675     {
1676         prediv  = findPll0PreDiv();
1677         postdiv = findPll0PostDiv();
1678         /* Adjust input clock */
1679         clkRate = clkRate / prediv;
1680         /* MDEC used for rate */
1681         workRate = (float)clkRate * (float)findPll0MMult();
1682         workRate /= (float)postdiv;
1683     }
1684 
1685     return (uint32_t)workRate;
1686 }
1687 
1688 /* Return PLL1 output clock rate from setup structure */
1689 /*! brief    Return PLL1 output clock rate from setup structure
1690  *  param    pSetup : Pointer to a PLL setup structure
1691  *  return   PLL0 output clock rate the setup structure will generate
1692  */
CLOCK_GetPLL1OutFromSetup(pll_setup_t * pSetup)1693 uint32_t CLOCK_GetPLL1OutFromSetup(pll_setup_t *pSetup)
1694 {
1695     uint32_t clkRate = 0;
1696     uint32_t prediv, postdiv;
1697     uint32_t workRate = 0UL;
1698 
1699     /* Get the input clock frequency of PLL. */
1700     clkRate = CLOCK_GetPLL1InClockRate();
1701 
1702     if (((pSetup->pllctrl & SYSCON_PLL1CTRL_BYPASSPLL_MASK) == 0UL) &&
1703         ((pSetup->pllctrl & SYSCON_PLL1CTRL_CLKEN_MASK) != 0UL) &&
1704         ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL1_MASK) == 0UL))
1705     {
1706         prediv  = findPll1PreDiv();
1707         postdiv = findPll1PostDiv();
1708         /* Adjust input clock */
1709         clkRate = clkRate / prediv;
1710         /* MDEC used for rate */
1711         workRate = clkRate * findPll1MMult();
1712         workRate /= postdiv;
1713     }
1714 
1715     return workRate;
1716 }
1717 
1718 /* Set the current PLL0 Rate */
1719 /*! brief Store the current PLL rate
1720  *  param    rate: Current rate of the PLL
1721  *  return   Nothing
1722  **/
CLOCK_SetStoredPLL0ClockRate(uint32_t rate)1723 void CLOCK_SetStoredPLL0ClockRate(uint32_t rate)
1724 {
1725     s_Pll0_Freq = rate;
1726 }
1727 
1728 /* Return PLL0 output clock rate */
1729 /*! brief    Return  PLL0 output clock rate
1730  *  param    recompute   : Forces a PLL rate recomputation if true
1731  *  return    PLL0 output clock rate
1732  *  note The PLL rate is cached in the driver in a variable as
1733  *  the rate computation function can take some time to perform. It
1734  *  is recommended to use 'false' with the 'recompute' parameter.
1735  */
CLOCK_GetPLL0OutClockRate(bool recompute)1736 uint32_t CLOCK_GetPLL0OutClockRate(bool recompute)
1737 {
1738     pll_setup_t Setup;
1739     uint32_t rate;
1740 
1741     if ((recompute) || (s_Pll0_Freq == 0U))
1742     {
1743         Setup.pllctrl    = SYSCON->PLL0CTRL;
1744         Setup.pllndec    = SYSCON->PLL0NDEC;
1745         Setup.pllpdec    = SYSCON->PLL0PDEC;
1746         Setup.pllsscg[0] = SYSCON->PLL0SSCG0;
1747         Setup.pllsscg[1] = SYSCON->PLL0SSCG1;
1748 
1749         CLOCK_GetPLL0OutFromSetupUpdate(&Setup);
1750     }
1751 
1752     rate = s_Pll0_Freq;
1753 
1754     return rate;
1755 }
1756 
1757 /*! brief    Return  PLL1 output clock rate
1758  *  param    recompute   : Forces a PLL rate recomputation if true
1759  *  return    PLL1 output clock rate
1760  *  note The PLL rate is cached in the driver in a variable as
1761  *  the rate computation function can take some time to perform. It
1762  *  is recommended to use 'false' with the 'recompute' parameter.
1763  */
CLOCK_GetPLL1OutClockRate(bool recompute)1764 uint32_t CLOCK_GetPLL1OutClockRate(bool recompute)
1765 {
1766     pll_setup_t Setup;
1767     uint32_t rate;
1768 
1769     if ((recompute) || (s_Pll1_Freq == 0U))
1770     {
1771         Setup.pllctrl = SYSCON->PLL1CTRL;
1772         Setup.pllndec = SYSCON->PLL1NDEC;
1773         Setup.pllpdec = SYSCON->PLL1PDEC;
1774         Setup.pllmdec = SYSCON->PLL1MDEC;
1775         CLOCK_GetPLL1OutFromSetupUpdate(&Setup);
1776     }
1777 
1778     rate = s_Pll1_Freq;
1779 
1780     return rate;
1781 }
1782 
1783 /* Set PLL0 output based on the passed PLL setup data */
1784 /*! brief    Set PLL output based on the passed PLL setup data
1785  *  param    pControl    : Pointer to populated PLL control structure to generate setup with
1786  *  param    pSetup      : Pointer to PLL setup structure to be filled
1787  *  return   PLL_ERROR_SUCCESS on success, or PLL setup error code
1788  *  note Actual frequency for setup may vary from the desired frequency based on the
1789  *  accuracy of input clocks, rounding, non-fractional PLL mode, etc.
1790  */
CLOCK_SetupPLL0Data(pll_config_t * pControl,pll_setup_t * pSetup)1791 pll_error_t CLOCK_SetupPLL0Data(pll_config_t *pControl, pll_setup_t *pSetup)
1792 {
1793     uint32_t inRate;
1794     bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0UL);
1795 
1796     pll_error_t pllError;
1797 
1798     /* Determine input rate for the PLL */
1799     if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0UL)
1800     {
1801         inRate = pControl->inputRate;
1802     }
1803     else
1804     {
1805         inRate = CLOCK_GetPLL0InClockRate();
1806     }
1807 
1808     /* PLL flag options */
1809     pllError = CLOCK_GetPll0Config(inRate, pControl->desiredRate, pSetup, useSS);
1810     if ((useSS) && (pllError == kStatus_PLL_Success))
1811     {
1812         /* If using SS mode, then some tweaks are made to the generated setup */
1813         pSetup->pllsscg[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
1814         if (pControl->mfDither)
1815         {
1816             pSetup->pllsscg[1] |= (1UL << SYSCON_PLL0SSCG1_DITHER_SHIFT);
1817         }
1818     }
1819 
1820     return pllError;
1821 }
1822 
1823 /* Set PLL0 output from PLL setup structure */
1824 /*! brief    Set PLL output from PLL setup structure (precise frequency)
1825  * param pSetup  : Pointer to populated PLL setup structure
1826  * param flagcfg : Flag configuration for PLL config structure
1827  * return    PLL_ERROR_SUCCESS on success, or PLL setup error code
1828  * note  This function will power off the PLL, setup the PLL with the
1829  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1830  * and adjust system voltages to the new PLL rate. The function will not
1831  * alter any source clocks (ie, main systen clock) that may use the PLL,
1832  * so these should be setup prior to and after exiting the function.
1833  */
CLOCK_SetupPLL0Prec(pll_setup_t * pSetup,uint32_t flagcfg)1834 pll_error_t CLOCK_SetupPLL0Prec(pll_setup_t *pSetup, uint32_t flagcfg)
1835 {
1836     uint32_t inRate, clkRate, prediv;
1837 
1838     /* Power off PLL during setup changes */
1839     POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1840     POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1841 
1842     pSetup->flags = flagcfg;
1843 
1844     /* Write PLL setup data */
1845     SYSCON->PLL0CTRL  = pSetup->pllctrl;
1846     SYSCON->PLL0NDEC  = pSetup->pllndec;
1847     SYSCON->PLL0NDEC  = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1848     SYSCON->PLL0PDEC  = pSetup->pllpdec;
1849     SYSCON->PLL0PDEC  = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1850     SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1851     SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1852     SYSCON->PLL0SSCG1 =
1853         pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT); /* latch */
1854 
1855     POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1856     POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1857 
1858     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1859     {
1860         if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) != 0UL) /* normal mode */
1861         {
1862             inRate = CLOCK_GetPLL0InClockRate();
1863             prediv = findPll0PreDiv();
1864             /* Adjust input clock */
1865             clkRate = inRate / prediv;
1866             /* The lock signal is only reliable between fref[2] :100 kHz to 20 MHz. */
1867             if ((clkRate >= 100000UL) && (clkRate <= 20000000UL))
1868             {
1869                 while (CLOCK_IsPLL0Locked() == false)
1870                 {
1871                 }
1872             }
1873             else
1874             {
1875                 SDK_DelayAtLeastUs(6000U,
1876                                    SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
1877                                                                                to insure the PLL will be stable */
1878             }
1879         }
1880         else /* spread spectrum mode */
1881         {
1882             SDK_DelayAtLeastUs(6000U,
1883                                SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
1884                                                                            insure the PLL will be stable */
1885         }
1886     }
1887 
1888     /* Update current programmed PLL rate var */
1889     CLOCK_GetPLL0OutFromSetupUpdate(pSetup);
1890 
1891     /* System voltage adjustment, occurs prior to setting main system clock */
1892     if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0UL)
1893     {
1894         POWER_SetVoltageForFreq(s_Pll0_Freq);
1895     }
1896 
1897     return kStatus_PLL_Success;
1898 }
1899 
1900 /* Setup PLL Frequency from pre-calculated value */
1901 /**
1902  * brief Set PLL0 output from PLL setup structure (precise frequency)
1903  * param pSetup  : Pointer to populated PLL setup structure
1904  * return    kStatus_PLL_Success on success, or PLL setup error code
1905  * note  This function will power off the PLL, setup the PLL with the
1906  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1907  * and adjust system voltages to the new PLL rate. The function will not
1908  * alter any source clocks (ie, main systen clock) that may use the PLL,
1909  * so these should be setup prior to and after exiting the function.
1910  */
CLOCK_SetPLL0Freq(const pll_setup_t * pSetup)1911 pll_error_t CLOCK_SetPLL0Freq(const pll_setup_t *pSetup)
1912 {
1913     uint32_t inRate, clkRate, prediv;
1914     /* Power off PLL during setup changes */
1915     POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1916     POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1917 
1918     /* Write PLL setup data */
1919     SYSCON->PLL0CTRL  = pSetup->pllctrl;
1920     SYSCON->PLL0NDEC  = pSetup->pllndec;
1921     SYSCON->PLL0NDEC  = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1922     SYSCON->PLL0PDEC  = pSetup->pllpdec;
1923     SYSCON->PLL0PDEC  = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1924     SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1925     SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1926     SYSCON->PLL0SSCG1 =
1927         pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* latch */
1928 
1929     POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1930     POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1931 
1932     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1933     {
1934         if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) != 0UL) /* normal mode */
1935         {
1936             inRate = CLOCK_GetPLL0InClockRate();
1937             prediv = findPll0PreDiv();
1938             /* Adjust input clock */
1939             clkRate = inRate / prediv;
1940             /* The lock signal is only reliable between fref[2] :100 kHz to 20 MHz. */
1941             if ((clkRate >= 100000UL) && (clkRate <= 20000000UL))
1942             {
1943                 while (CLOCK_IsPLL0Locked() == false)
1944                 {
1945                 }
1946             }
1947             else
1948             {
1949                 SDK_DelayAtLeastUs(6000U,
1950                                    SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
1951                                                                                to insure the PLL will be stable */
1952             }
1953         }
1954         else /* spread spectrum mode */
1955         {
1956             SDK_DelayAtLeastUs(6000U,
1957                                SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
1958                                                                            insure the PLL will be stable */
1959         }
1960     }
1961 
1962     /* Update current programmed PLL rate var */
1963     s_Pll0_Freq = pSetup->pllRate;
1964 
1965     return kStatus_PLL_Success;
1966 }
1967 
1968 /* Setup PLL1 Frequency from pre-calculated value */
1969 /**
1970  * brief Set PLL1 output from PLL setup structure (precise frequency)
1971  * param pSetup  : Pointer to populated PLL setup structure
1972  * return    kStatus_PLL_Success on success, or PLL setup error code
1973  * note  This function will power off the PLL, setup the PLL with the
1974  * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1975  * and adjust system voltages to the new PLL rate. The function will not
1976  * alter any source clocks (ie, main systen clock) that may use the PLL,
1977  * so these should be setup prior to and after exiting the function.
1978  */
CLOCK_SetPLL1Freq(const pll_setup_t * pSetup)1979 pll_error_t CLOCK_SetPLL1Freq(const pll_setup_t *pSetup)
1980 {
1981     uint32_t inRate, clkRate, prediv;
1982     /* Power off PLL during setup changes */
1983     POWER_EnablePD(kPDRUNCFG_PD_PLL1);
1984 
1985     /* Write PLL setup data */
1986     SYSCON->PLL1CTRL = pSetup->pllctrl;
1987     SYSCON->PLL1NDEC = pSetup->pllndec;
1988     SYSCON->PLL1NDEC = pSetup->pllndec | (1UL << SYSCON_PLL1NDEC_NREQ_SHIFT); /* latch */
1989     SYSCON->PLL1PDEC = pSetup->pllpdec;
1990     SYSCON->PLL1PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL1PDEC_PREQ_SHIFT); /* latch */
1991     SYSCON->PLL1MDEC = pSetup->pllmdec;
1992     SYSCON->PLL1MDEC = pSetup->pllmdec | (1UL << SYSCON_PLL1MDEC_MREQ_SHIFT); /* latch */
1993 
1994     POWER_DisablePD(kPDRUNCFG_PD_PLL1);
1995 
1996     if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0UL)
1997     {
1998         inRate = CLOCK_GetPLL1InClockRate();
1999         prediv = findPll1PreDiv();
2000         /* Adjust input clock */
2001         clkRate = inRate / prediv;
2002         /* The lock signal is only reliable between fref[2] :100 kHz to 20 MHz. */
2003         if ((clkRate >= 100000UL) && (clkRate <= 20000000UL))
2004         {
2005             while (CLOCK_IsPLL1Locked() == false)
2006             {
2007             }
2008         }
2009         else
2010         {
2011             SDK_DelayAtLeastUs(6000U,
2012                                SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
2013                                                                            insure the PLL will be stable */
2014         }
2015     }
2016 
2017     /* Update current programmed PLL rate var */
2018     s_Pll1_Freq = pSetup->pllRate;
2019 
2020     return kStatus_PLL_Success;
2021 }
2022 
2023 /* Set PLL0 clock based on the input frequency and multiplier */
2024 /*! brief    Set PLL0 output based on the multiplier and input frequency
2025  * param multiply_by : multiplier
2026  * param input_freq  : Clock input frequency of the PLL
2027  * return    Nothing
2028  * note  Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
2029  * function does not disable or enable PLL power, wait for PLL lock,
2030  * or adjust system voltages. These must be done in the application.
2031  * The function will not alter any source clocks (ie, main systen clock)
2032  * that may use the PLL, so these should be setup prior to and after
2033  * exiting the function.
2034  */
CLOCK_SetupPLL0Mult(uint32_t multiply_by,uint32_t input_freq)2035 void CLOCK_SetupPLL0Mult(uint32_t multiply_by, uint32_t input_freq)
2036 {
2037     uint32_t cco_freq = input_freq * multiply_by;
2038     uint32_t pdec     = 1U;
2039     uint32_t selr;
2040     uint32_t seli;
2041     uint32_t selp;
2042     uint32_t mdec, ndec;
2043 
2044     while (cco_freq < 275000000U)
2045     {
2046         multiply_by <<= 1U; /* double value in each iteration */
2047         pdec <<= 1U;        /* correspondingly double pdec to cancel effect of double msel */
2048         cco_freq = input_freq * multiply_by;
2049     }
2050 
2051     selr = 0U;
2052 
2053     if (multiply_by >= 8000UL)
2054     {
2055         seli = 1UL;
2056     }
2057     else if (multiply_by >= 122UL)
2058     {
2059         seli = (uint32_t)(8000UL / multiply_by); /*floor(8000/M) */
2060     }
2061     else
2062     {
2063         seli = 2UL * ((uint32_t)(multiply_by / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
2064     }
2065 
2066     if (seli >= 63U)
2067     {
2068         seli = 63U;
2069     }
2070 
2071     {
2072         selp = 31U;
2073     }
2074 
2075     if (pdec > 1U)
2076     {
2077         pdec = pdec / 2U; /* Account for minus 1 encoding */
2078                           /* Translate P value */
2079     }
2080 
2081     mdec = (uint32_t)PLL_SSCG1_MDEC_VAL_SET(multiply_by);
2082     ndec = 0x1U; /* pre divide by 1 (hardcoded) */
2083 
2084     SYSCON->PLL0CTRL = SYSCON_PLL0CTRL_CLKEN_MASK | SYSCON_PLL0CTRL_BYPASSPOSTDIV(0) |
2085                        SYSCON_PLL0CTRL_BYPASSPOSTDIV2(0) | (selr << SYSCON_PLL0CTRL_SELR_SHIFT) |
2086                        (seli << SYSCON_PLL0CTRL_SELI_SHIFT) | (selp << SYSCON_PLL0CTRL_SELP_SHIFT);
2087     SYSCON->PLL0PDEC = pdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* set Pdec value and assert preq */
2088     SYSCON->PLL0NDEC = ndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* set Pdec value and assert preq */
2089     SYSCON->PLL0SSCG1 =
2090         mdec | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* select non sscg MDEC value, assert mreq and select mdec value */
2091 }
2092 
2093 /* Enable USB DEVICE FULL SPEED clock */
2094 /*! brief Enable USB Device FS clock.
2095  * param src : clock source
2096  * param freq: clock frequency
2097  * Enable USB Device Full Speed clock.
2098  */
CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src,uint32_t freq)2099 bool CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src, uint32_t freq)
2100 {
2101     bool ret = true;
2102 
2103     CLOCK_DisableClock(kCLOCK_Usbd0);
2104 
2105     if (kCLOCK_UsbfsSrcFro == src)
2106     {
2107         switch (freq)
2108         {
2109             case 96000000U:
2110                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2111                 break;
2112 
2113             default:
2114                 ret = false;
2115                 break;
2116         }
2117         /* Turn ON FRO HF */
2118         POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
2119         /* Enable FRO 96MHz output */
2120         ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
2121         /* Select FRO 96 or 48 MHz */
2122         CLOCK_AttachClk(kFRO_HF_to_USB0);
2123     }
2124     else
2125     {
2126         /*!< Configure XTAL32M */
2127         POWER_DisablePD(kPDRUNCFG_PD_XTALHF);                                 /* Ensure XTAL32M is powered */
2128         POWER_DisablePD(kPDRUNCFG_PD_LDOXTALHF);                              /* Ensure XTAL32M is powered */
2129         (void)CLOCK_SetupExtClocking(16000000U);                              /* Enable clk_in clock */
2130         SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;               /* Enable clk_in from XTAL32M clock  */
2131         ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system  */
2132 
2133         /*!< Set up PLL1 */
2134         POWER_DisablePD(kPDRUNCFG_PD_PLL1);
2135         CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
2136         const pll_setup_t pll1Setup = {
2137             .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
2138             .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
2139             .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
2140             .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
2141             .pllRate = 48000000U,
2142             .flags   = PLL_SETUPFLAG_WAITLOCK};
2143         (void)CLOCK_SetPLL1Freq(&pll1Setup);
2144 
2145         CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2146         CLOCK_AttachClk(kPLL1_to_USB0);
2147         SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2148     }
2149     CLOCK_EnableClock(kCLOCK_Usbd0);
2150 
2151     return ret;
2152 }
2153 
2154 /* Enable USB HOST FULL SPEED clock */
2155 /*! brief Enable USB HOST FS clock.
2156  * param src : clock source
2157  * param freq: clock frequency
2158  * Enable USB HOST Full Speed clock.
2159  */
CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src,uint32_t freq)2160 bool CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src, uint32_t freq)
2161 {
2162     bool ret = true;
2163 
2164     if (kCLOCK_UsbfsSrcFro == src)
2165     {
2166         switch (freq)
2167         {
2168             case 96000000U:
2169                 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2170                 break;
2171 
2172             default:
2173                 ret = false;
2174                 break;
2175         }
2176         /* Turn ON FRO HF */
2177         POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
2178         /* Enable FRO 96MHz output */
2179         ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
2180         /* Select FRO 96 MHz */
2181         CLOCK_AttachClk(kFRO_HF_to_USB0);
2182     }
2183     else
2184     {
2185         /*!< Configure XTAL32M */
2186         POWER_DisablePD(kPDRUNCFG_PD_XTALHF);                                 /* Ensure XTAL32M is powered */
2187         POWER_DisablePD(kPDRUNCFG_PD_LDOXTALHF);                              /* Ensure XTAL32M is powered */
2188         (void)CLOCK_SetupExtClocking(16000000U);                              /* Enable clk_in clock */
2189         SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;               /* Enable clk_in from XTAL32M clock  */
2190         ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system  */
2191 
2192         /*!< Set up PLL1 */
2193         POWER_DisablePD(kPDRUNCFG_PD_PLL1);
2194         CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
2195         const pll_setup_t pll1Setup = {
2196             .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
2197             .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
2198             .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
2199             .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
2200             .pllRate = 48000000U,
2201             .flags   = PLL_SETUPFLAG_WAITLOCK};
2202         (void)CLOCK_SetPLL1Freq(&pll1Setup);
2203 
2204         CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2205         CLOCK_AttachClk(kPLL1_to_USB0);
2206         SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2207     }
2208     CLOCK_EnableClock(kCLOCK_Usbhmr0);
2209     CLOCK_EnableClock(kCLOCK_Usbhsl0);
2210 
2211     return ret;
2212 }
2213 
2214 /*! @brief Enable the OSTIMER 32k clock.
2215  *  @return  Nothing
2216  */
CLOCK_EnableOstimer32kClock(void)2217 void CLOCK_EnableOstimer32kClock(void)
2218 {
2219     PMC->OSEVENTTIMER |= PMC_OSEVENTTIMER_CLOCKENABLE_MASK;
2220 }
2221 
2222 /* Sets board-specific trim values for High Frequency crystal oscillator */
2223 /*! brief Sets board-specific trim values for High Frequency crystal oscillator.
2224  * param pi32_hfXtalIecLoadpF_x100 : Load capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF becomes 120
2225  * param pi32_hfXtalPPcbParCappF_x100 : PCB +ve parasitic capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
2226  * becomes 120
2227  * param pi32_hfXtalNPcbParCappF_x100 : PCB -ve parasitic capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
2228  * becomes 120
2229  * return   none
2230  * note     Following default Values can be used:
2231  *          pi32_32MfXtalIecLoadpF_x100 Load capacitance, pF x 100 : 600
2232  *          pi32_32MfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100 : 20
2233  *          pi32_32MfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100 : 40
2234  * Sets board-specific trim values for High Frequency crystal oscillator.
2235  */
CLOCK_XtalHfCapabankTrim(int32_t pi32_hfXtalIecLoadpF_x100,int32_t pi32_hfXtalPPcbParCappF_x100,int32_t pi32_hfXtalNPcbParCappF_x100)2236 void CLOCK_XtalHfCapabankTrim(int32_t pi32_hfXtalIecLoadpF_x100,
2237                               int32_t pi32_hfXtalPPcbParCappF_x100,
2238                               int32_t pi32_hfXtalNPcbParCappF_x100)
2239 {
2240     uint32_t u32XOTrimValue;
2241     uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF, u8XOSlave;
2242     int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
2243     int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
2244     uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
2245     uint32_t u32RegVal;
2246 
2247     /* Enable and set LDO, if not already done */
2248     CLOCK_SetXtalHfLdo();
2249     /* Get Cal values from Flash */
2250     u32XOTrimValue = GET_HFXO_TRIM();
2251     /* Check validity and apply */
2252     if ((u32XOTrimValue & 1) && ((u32XOTrimValue >> 15) & 1))
2253     {
2254         /* These fields are 7 bits, unsigned */
2255         u8IECXinCapCal6pF  = (u32XOTrimValue >> 1) & 0x7f;
2256         u8IECXinCapCal8pF  = (u32XOTrimValue >> 8) & 0x7f;
2257         u8IECXoutCapCal6pF = (u32XOTrimValue >> 16) & 0x7f;
2258         u8IECXoutCapCal8pF = (u32XOTrimValue >> 23) & 0x7f;
2259         /* This field is 1 bit */
2260         u8XOSlave = (u32XOTrimValue >> 30) & 0x1;
2261         /* Linear fit coefficients calculation */
2262         iaXin_x4  = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
2263         ibXin     = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
2264         iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
2265         ibXout    = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
2266     }
2267     else
2268     {
2269         iaXin_x4  = 20;  // gain in LSB/pF
2270         ibXin     = -9;  // offset in LSB
2271         iaXout_x4 = 20;  // gain in LSB/pF
2272         ibXout    = -13; // offset in LSB
2273         u8XOSlave = 0;
2274     }
2275     /* In & out load cap calculation with derating */
2276     iXOCapInpF_x100 =
2277         2 * pi32_hfXtalIecLoadpF_x100 - pi32_hfXtalNPcbParCappF_x100 + 39 * (XO_SLAVE_EN - u8XOSlave) - 15;
2278     iXOCapOutpF_x100 = 2 * pi32_hfXtalIecLoadpF_x100 - pi32_hfXtalPPcbParCappF_x100 - 21;
2279     /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
2280     u8XOCapInCtrl  = (uint8_t)(((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400);
2281     u8XOCapOutCtrl = (uint8_t)(((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400);
2282     /* Read register and clear fields to be written */
2283     u32RegVal = ANACTRL->XO32M_CTRL;
2284     u32RegVal &= ~(ANACTRL_XO32M_CTRL_OSC_CAP_IN_MASK | ANACTRL_XO32M_CTRL_OSC_CAP_OUT_MASK);
2285     /* Configuration of 32 MHz XO output buffers */
2286 #if (XO_SLAVE_EN == 0)
2287     u32RegVal &= ~(ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK);
2288 #else
2289     u32RegVal |= ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK;
2290 #endif
2291     /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
2292     u32RegVal |= CLOCK_u8OscCapConvert(u8XOCapInCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_IN_SHIFT;
2293     u32RegVal |= CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_OUT_SHIFT;
2294     /* Write back to register */
2295     ANACTRL->XO32M_CTRL = u32RegVal;
2296 }
2297 
2298 /* Sets board-specific trim values for 32kHz XTAL */
2299 /*! brief Sets board-specific trim values for 32kHz XTAL.
2300  * param pi32_32kfXtalIecLoadpF_x100 : Load capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF becomes 120
2301  * param pi32_32kfXtalPPcbParCappF_x100 : PCB +ve parasitic capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
2302  * becomes 120
2303  * param pi32_32kfXtalNPcbParCappF_x100 : PCB -ve parasitic capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
2304  * becomes 120
2305  * return   none
2306  * note     Following default Values can be used:
2307  *          pi32_32kfXtalIecLoadpF_x100 Load capacitance, pF x 100 : 600
2308  *          pi32_32kfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100 : 40
2309  *          pi32_32kfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100 : 40
2310  * Sets board-specific trim values for 32kHz XTAL.
2311  */
CLOCK_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,int32_t pi32_32kfXtalPPcbParCappF_x100,int32_t pi32_32kfXtalNPcbParCappF_x100)2312 void CLOCK_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,
2313                                  int32_t pi32_32kfXtalPPcbParCappF_x100,
2314                                  int32_t pi32_32kfXtalNPcbParCappF_x100)
2315 {
2316     uint32_t u32XOTrimValue;
2317     uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF;
2318     int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
2319     int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
2320     uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
2321     uint32_t u32RegVal;
2322     /* Get Cal values from Flash */
2323     u32XOTrimValue = GET_32KXO_TRIM();
2324     /* check validity and apply */
2325     if ((u32XOTrimValue & 1) && ((u32XOTrimValue >> 15) & 1))
2326     {
2327         /* These fields are 7 bits, unsigned */
2328         u8IECXinCapCal6pF  = (u32XOTrimValue >> 1) & 0x7f;
2329         u8IECXinCapCal8pF  = (u32XOTrimValue >> 8) & 0x7f;
2330         u8IECXoutCapCal6pF = (u32XOTrimValue >> 16) & 0x7f;
2331         u8IECXoutCapCal8pF = (u32XOTrimValue >> 23) & 0x7f;
2332         /* Linear fit coefficients calculation */
2333         iaXin_x4  = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
2334         ibXin     = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
2335         iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
2336         ibXout    = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
2337     }
2338     else
2339     {
2340         iaXin_x4  = 16; // gain in LSB/pF
2341         ibXin     = 12; // offset in LSB
2342         iaXout_x4 = 16; // gain in LSB/pF
2343         ibXout    = 11; // offset in LSB
2344     }
2345 
2346     /* In & out load cap calculation with derating */
2347     iXOCapInpF_x100  = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalNPcbParCappF_x100 - 130;
2348     iXOCapOutpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalPPcbParCappF_x100 - 41;
2349 
2350     /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
2351     u8XOCapInCtrl  = (uint8_t)(((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400);
2352     u8XOCapOutCtrl = (uint8_t)(((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400);
2353 
2354     /* Read register and clear fields to be written */
2355     u32RegVal = PMC->XTAL32K;
2356     u32RegVal &= ~(PMC_XTAL32K_CAPBANKIN_MASK | PMC_XTAL32K_CAPBANKOUT_MASK);
2357 
2358     /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
2359     u32RegVal |= CLOCK_u8OscCapConvert(u8XOCapInCtrl, 23) << PMC_XTAL32K_CAPBANKIN_SHIFT;
2360     u32RegVal |= CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 23) << PMC_XTAL32K_CAPBANKOUT_SHIFT;
2361 
2362     /* Write back to register */
2363     PMC->XTAL32K = u32RegVal;
2364 }
2365 
2366 /* Enables and sets LDO for High Frequency crystal oscillator. */
2367 /*! brief Enables and sets LDO for High Frequency crystal oscillator.
2368  * return   none
2369  * Sets Enables and sets LDO for High Frequency crystal oscillator.
2370  */
CLOCK_SetXtalHfLdo(void)2371 void CLOCK_SetXtalHfLdo(void)
2372 {
2373     uint32_t temp;
2374     const uint32_t u32Mask =
2375         (ANACTRL_LDO_XO32M_VOUT_MASK | ANACTRL_LDO_XO32M_IBIAS_MASK | ANACTRL_LDO_XO32M_STABMODE_MASK);
2376 
2377     const uint32_t u32Value =
2378         (ANACTRL_LDO_XO32M_VOUT(0x5) | ANACTRL_LDO_XO32M_IBIAS(0x2) | ANACTRL_LDO_XO32M_STABMODE(0x1));
2379 
2380     /* Enable & set-up XTAL 32 MHz clock LDO */
2381     temp = ANACTRL->LDO_XO32M;
2382 
2383     if ((temp & u32Mask) != u32Value)
2384     {
2385         temp &= ~u32Mask;
2386 
2387         /*
2388          * Enable the XTAL32M LDO
2389          * Adjust the output voltage level, 0x5 for 1.1V
2390          * Adjust the biasing current, 0x2 value
2391          * Stability configuration, 0x1 default mode
2392          */
2393         temp |= u32Value;
2394 
2395         ANACTRL->LDO_XO32M = temp;
2396 
2397         /* Delay for LDO to be up */
2398         // CLOCK_uDelay(20);
2399     }
2400 
2401     /* Enable LDO XO32M */
2402     PMC->PDRUNCFGCLR0 = PMC_PDRUNCFG0_PDEN_LDOXTALHF_MASK;
2403 }
2404 
2405 /**
2406  * @brief
2407  * @param
2408  * @return
2409  */
CLOCK_u8OscCapConvert(uint8_t u8OscCap,uint8_t u8CapBankDiscontinuity)2410 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity)
2411 {
2412     /* Compensate for discontinuity in the capacitor banks */
2413     if (u8OscCap < 64)
2414     {
2415         if (u8OscCap >= u8CapBankDiscontinuity)
2416         {
2417             u8OscCap -= u8CapBankDiscontinuity;
2418         }
2419         else
2420         {
2421             u8OscCap = 0;
2422         }
2423     }
2424     else
2425     {
2426         if (u8OscCap <= (127 - u8CapBankDiscontinuity))
2427         {
2428             u8OscCap += u8CapBankDiscontinuity;
2429         }
2430         else
2431         {
2432             u8OscCap = 127;
2433         }
2434     }
2435     return u8OscCap;
2436 }
2437 
2438 /*!
2439  * brief  Initialize the trim value for FRO HF .
2440  */
CLOCK_FroHfTrim(void)2441 void CLOCK_FroHfTrim(void)
2442 {
2443     volatile unsigned int Fro192mCtrlEfuse = 0;
2444     Fro192mCtrlEfuse                       = ANACTRL->FRO192M_CTRL;
2445     ANACTRL->ANALOG_CTRL_CFG               = ANACTRL->ANALOG_CTRL_CFG | ANACTRL_ANALOG_CTRL_CFG_FRO192M_TRIM_SRC_MASK;
2446     ANACTRL->FRO192M_CTRL                  = ANACTRL_FRO192M_CTRL_WRTRIM_MASK | Fro192mCtrlEfuse;
2447 }
2448