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