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