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