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