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