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