1 /*
2 * Copyright 2017 - 2020 , NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_clock.h"
9 #include "fsl_power.h"
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "platform.drivers.clock"
16 #endif
17 #define NVALMAX (0x100U)
18 #define PVALMAX (0x20U)
19 #define MVALMAX (0x10000U)
20
21 #define PLL_MAX_N_DIV 0x100U
22
23 /*--------------------------------------------------------------------------
24 !!! If required these #defines can be moved to chip library file
25 ----------------------------------------------------------------------------*/
26
27 #define PLL_SSCG1_MDEC_VAL_P (10U) /* MDEC is in bits 25 downto 10 */
28 #define PLL_SSCG1_MDEC_VAL_M (0xFFFFULL << PLL_SSCG1_MDEC_VAL_P)
29 #define PLL_NDEC_VAL_P (0U) /* NDEC is in bits 9:0 */
30 #define PLL_NDEC_VAL_M (0xFFUL << PLL_NDEC_VAL_P)
31 #define PLL_PDEC_VAL_P (0U) /*!< PDEC is in bits 6:0 */
32 #define PLL_PDEC_VAL_M (0x1FUL << PLL_PDEC_VAL_P)
33
34 #define PLL_MIN_CCO_FREQ_MHZ (275000000U)
35 #define PLL_MAX_CCO_FREQ_MHZ (550000000U)
36 #define PLL_LOWER_IN_LIMIT (2000U) /*!< Minimum PLL input rate */
37 #define PLL_HIGHER_IN_LIMIT (150000000U) /*!< Maximum PLL input rate */
38 #define PLL_MIN_IN_SSMODE (3000000U)
39 #define PLL_MAX_IN_SSMODE \
40 (100000000U) /*!< Not find the value in UM, Just use the maximum frequency which device support */
41
42 /* PLL NDEC reg */
43 #define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)
44 /* PLL PDEC reg */
45 #define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)
46 /* SSCG control1 */
47 #define PLL_SSCG1_MDEC_VAL_SET(value) (((uint64_t)(value) << PLL_SSCG1_MDEC_VAL_P) & PLL_SSCG1_MDEC_VAL_M)
48
49 /* PLL0 SSCG control1 */
50 #define PLL0_SSCG_MD_FRACT_P 0U
51 #define PLL0_SSCG_MD_INT_P 25U
52 #define PLL0_SSCG_MD_FRACT_M (0x1FFFFFFUL << PLL0_SSCG_MD_FRACT_P)
53 #define PLL0_SSCG_MD_INT_M ((uint64_t)0xFFUL << PLL0_SSCG_MD_INT_P)
54
55 #define PLL0_SSCG_MD_FRACT_SET(value) (((uint64_t)(value) << PLL0_SSCG_MD_FRACT_P) & PLL0_SSCG_MD_FRACT_M)
56 #define PLL0_SSCG_MD_INT_SET(value) (((uint64_t)(value) << PLL0_SSCG_MD_INT_P) & PLL0_SSCG_MD_INT_M)
57
58 /* Peripheral FLASH_NMPA base address */
59 #define FLASH_NMPA_BASE (0x3FC00u)
60 /* Return values from Config (N-2) page of flash */
61 #define GET_HFXO_TRIM() (*(uint32_t *)(FLASH_NMPA_BASE + 0xC0U)) // (0x3FCC0)
62 #define GET_32KXO_TRIM() (*(uint32_t *)(FLASH_NMPA_BASE + 0xC4U)) // (0x3FCC4)
63
64 #define XO_SLAVE_EN (1)
65
66 /* Saved value of PLL output rate, computed whenever needed to save run-time
67 computation on each call to retrive the PLL rate. */
68 static uint32_t s_Pll0_Freq;
69 static uint32_t s_Pll1_Freq;
70
71 /** External clock rate on the CLKIN pin in Hz. If not used,
72 set this to 0. Otherwise, set it to the exact rate in Hz this pin is
73 being driven at. */
74 static uint32_t s_Ext_Clk_Freq = 16000000U;
75 static uint32_t s_I2S_Mclk_Freq = 0U;
76
77 /*******************************************************************************
78 * Variables
79 ******************************************************************************/
80
81 /*******************************************************************************
82 * Prototypes
83 ******************************************************************************/
84 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
85 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
86 /* Get predivider (N) from PLL0 NDEC setting */
87 static uint32_t findPll0PreDiv(void);
88 /* Get predivider (N) from PLL1 NDEC setting */
89 static uint32_t findPll1PreDiv(void);
90 /* Get postdivider (P) from PLL0 PDEC setting */
91 static uint32_t findPll0PostDiv(void);
92 /* Get postdivider (P) from PLL1 PDEC setting. */
93 static uint32_t findPll1PostDiv(void);
94 /* Get multiplier (M) from PLL0 MDEC and SSCG settings */
95 static float findPll0MMult(void);
96 /* Get multiplier (M) from PLL1 MDEC. */
97 static uint32_t findPll1MMult(void);
98 /* Get the greatest common divisor */
99 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
100 /* Set PLL output based on desired output rate */
101 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS);
102 /* Update local PLL rate variable */
103 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup);
104 /* Update local PLL1 rate variable */
105 static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup);
106 /* Compensate for discontinuity in the capacitor banks */
107 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity);
108 /* Enables and sets LDO for High Frequency crystal oscillator */
109 static void CLOCK_SetXtalHfLdo(void);
110
111 /*******************************************************************************
112 * Code
113 ******************************************************************************/
114
115 /* Clock Selection for IP */
116 /**
117 * brief Configure the clock selection muxes.
118 * param connection : Clock to be configured.
119 * return Nothing
120 */
CLOCK_AttachClk(clock_attach_id_t connection)121 void CLOCK_AttachClk(clock_attach_id_t connection)
122 {
123 uint16_t mux;
124 uint8_t sel;
125 uint16_t item;
126 uint32_t tmp32 = (uint32_t)connection;
127 uint32_t i;
128 volatile uint32_t *pClkSel;
129
130 pClkSel = &(SYSCON->SYSTICKCLKSEL0);
131
132 if (kNONE_to_NONE != connection)
133 {
134 for (i = 0U; i < 2U; i++)
135 {
136 if (tmp32 == 0U)
137 {
138 break;
139 }
140 item = (uint16_t)GET_ID_ITEM(tmp32);
141 if (item != 0U)
142 {
143 mux = (uint16_t)GET_ID_ITEM_MUX(item);
144 sel = (uint8_t)GET_ID_ITEM_SEL(item);
145 if (mux == CM_RTCOSC32KCLKSEL)
146 {
147 PMC->RTCOSC32K = (PMC->RTCOSC32K & ~PMC_RTCOSC32K_SEL_MASK) | PMC_RTCOSC32K_SEL(sel);
148 }
149 else if (mux == CM_OSTIMERCLKSEL)
150 {
151 PMC->OSEVENTTIMER =
152 (PMC->OSEVENTTIMER & ~PMC_OSEVENTTIMER_SELCLOCK_MASK) | PMC_OSEVENTTIMER_SELCLOCK(sel);
153 }
154 else
155 {
156 ((volatile uint32_t *)pClkSel)[mux] = sel;
157 }
158 }
159 tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
160 }
161 }
162 }
163
164 /* Return the actual clock attach id */
165 /**
166 * brief Get the actual clock attach id.
167 * This fuction uses the offset in input attach id, then it reads the actual source value in
168 * the register and combine the offset to obtain an actual attach id.
169 * param attachId : Clock attach id to get.
170 * return Clock source value.
171 */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)172 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
173 {
174 uint16_t mux;
175 uint32_t actualSel;
176 uint32_t tmp32 = (uint32_t)attachId;
177 uint32_t i;
178 uint32_t actualAttachId = 0U;
179 uint32_t selector = GET_ID_SELECTOR(tmp32);
180 volatile uint32_t *pClkSel;
181
182 pClkSel = &(SYSCON->SYSTICKCLKSEL0);
183
184 if (kNONE_to_NONE == attachId)
185 {
186 return kNONE_to_NONE;
187 }
188
189 for (i = 0U; i < 2U; i++)
190 {
191 mux = (uint16_t)GET_ID_ITEM_MUX(tmp32);
192 if (tmp32 != 0UL)
193 {
194 if (mux == CM_RTCOSC32KCLKSEL)
195 {
196 actualSel = ((PMC->RTCOSC32K) & PMC_RTCOSC32K_SEL_MASK) >> PMC_RTCOSC32K_SEL_SHIFT;
197 }
198 else if (mux == CM_OSTIMERCLKSEL)
199 {
200 actualSel = ((PMC->OSEVENTTIMER) & PMC_OSEVENTTIMER_SELCLOCK_MASK) >> PMC_OSEVENTTIMER_SELCLOCK_SHIFT;
201 }
202 else
203 {
204 actualSel = (uint32_t)((volatile uint32_t *)pClkSel)[mux];
205 }
206
207 /* Consider the combination of two registers */
208 actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
209 }
210 tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */
211 }
212
213 actualAttachId |= selector;
214
215 return (clock_attach_id_t)actualAttachId;
216 }
217
218 /* Set IP Clock Divider */
219 /**
220 * brief Setup peripheral clock dividers.
221 * param div_name : Clock divider name
222 * param divided_by_value: Value to be divided
223 * param reset : Whether to reset the divider counter.
224 * return Nothing
225 */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value,bool reset)226 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
227 {
228 volatile uint32_t *pClkDiv;
229
230 pClkDiv = &(SYSCON->SYSTICKCLKDIV[0]);
231 if ((div_name >= kCLOCK_DivFlexFrg0) && (div_name <= kCLOCK_DivFlexFrg7))
232 {
233 /*!< Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1+ MULT /DIV), DIV = 0xFF */
234 ((volatile uint32_t *)pClkDiv)[(uint8_t)div_name] =
235 SYSCON_FRGCTRL_DIV_MASK | SYSCON_FRGCTRL_MULT(divided_by_value);
236 }
237 else
238 {
239 if (reset)
240 {
241 ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] = 1UL << 29U;
242 }
243 if (divided_by_value == 0U) /*!< halt */
244 {
245 ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] = 1UL << 30U;
246 }
247 else
248 {
249 ((volatile uint32_t *)pClkDiv)[(uint16_t)div_name] = (divided_by_value - 1U);
250 }
251 }
252 }
253
254 /* Set FRO Clocking */
255 /**
256 * brief Initialize the Core clock to given frequency (12, 48 or 96 MHz).
257 * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
258 * enabled.
259 * param iFreq : Desired frequency (must be one of #CLK_FRO_12MHZ or #CLK_FRO_48MHZ or #CLK_FRO_96MHZ)
260 * return returns success or fail status.
261 */
CLOCK_SetupFROClocking(uint32_t iFreq)262 status_t CLOCK_SetupFROClocking(uint32_t iFreq)
263 {
264 if ((iFreq != 12000000U) && (iFreq != 96000000U))
265 {
266 return kStatus_Fail;
267 }
268 /* Enable Analog Control module */
269 SYSCON->PRESETCTRLCLR[2] = SYSCON_PRESETCTRL2_ANACTRL_RST_MASK;
270 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_ANALOG_CTRL_MASK;
271
272 /* Initialize FRO192 trim */
273 CLOCK_FroHfTrim();
274
275 /* Power up the FRO192M */
276 POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
277
278 if (iFreq == 96000000U)
279 {
280 ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_96MHZCLK(1);
281 }
282 /* always enable
283 else if (iFreq == 48000000U)
284 {
285 ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_48MHZCLK(1);
286 }*/
287 else
288 {
289 ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_ENA_12MHZCLK(1);
290 }
291 return kStatus_Success;
292 }
293
294 /* Set the FLASH wait states for the passed frequency */
295 /**
296 * brief Set the flash wait states for the input freuqency.
297 * param iFreq: Input frequency
298 * return Nothing
299 */
300 typedef struct
301 {
302 uint32_t waitstate;
303 uint32_t freqMax;
304 } WaitStateInterval_t;
305
306 /* clang-format off */
307 /* Wait state if frequency is inferior to the one specified */
308 static const WaitStateInterval_t IntervalList[] = {
309 {0, 11000000},
310 {1, 22000000},
311 {2, 33000000},
312 {3, 44000000},
313 {4, 55000000},
314 {5, 66000000},
315 {6, 77000000},
316 {7, 88000000},
317 {8, 100000000},
318 {9, 115000000},
319 {10, 130000000},
320 {11, 150000000} /* Maximum allowed frequency (150 MHz) */
321 };
322 /* clang-format on */
323
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz)324 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t system_freq_hz)
325 {
326 /* Flash Controller & FMC internal number of Wait States (minus 1) */
327 uint32_t num_wait_states = 15UL; /* Default to the maximum number of wait states */
328 uint32_t prefetch_enable_mask = SYSCON->FMCCR & SYSCON_FMCCR_PREFEN_MASK;
329
330 for (size_t cnt = 0; cnt < (sizeof(IntervalList) / sizeof(WaitStateInterval_t)); cnt++)
331 {
332 if (system_freq_hz <= IntervalList[cnt].freqMax)
333 {
334 num_wait_states = IntervalList[cnt].waitstate;
335 break;
336 }
337 }
338
339 /* Adjust FMC waiting time cycles (num_wait_states) */
340 SYSCON->FMCCR = (SYSCON->FMCCR & 0xFFFF0FFFUL) | ((num_wait_states & 0xFUL) << 12UL);
341
342 /*The prefetch bit must be disabled before any flash commands*/
343 SYSCON->FMCCR &= ~SYSCON_FMCCR_PREFEN_MASK;
344
345 FLASH->INTSTAT_CLR = 0xF; /* Clear all status flags */
346
347 FLASH->DATAW[0] = (FLASH->DATAW[0] & 0xFFFFFFF0UL) | (num_wait_states & 0xFUL);
348
349 FLASH->CMD = 0x2; /* CMD_SET_READ_MODE */
350
351 /* Wait until the cmd is completed (without error) */
352 while ((FLASH->INTSTAT & FLASH_INTSTAT_DONE_MASK) == 0UL)
353 {
354 }
355
356 /* restore prefetch enable */
357 SYSCON->FMCCR |= prefetch_enable_mask;
358 }
359
360 /* Set EXT OSC Clk */
361 /**
362 * brief Initialize the external osc clock to given frequency.
363 * param iFreq : Desired frequency (must be equal to exact rate in Hz)
364 * return returns success or fail status.
365 */
CLOCK_SetupExtClocking(uint32_t iFreq)366 status_t CLOCK_SetupExtClocking(uint32_t iFreq)
367 {
368 if (iFreq >= 32000000U)
369 {
370 return kStatus_Fail;
371 }
372 /* Turn on power for crystal 32 MHz */
373 POWER_DisablePD(kPDRUNCFG_PD_XTALHF);
374 POWER_DisablePD(kPDRUNCFG_PD_LDOXTALHF);
375 /* Enable clock_in clock for clock module. */
376 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK;
377
378 /* Wait for external osc clock to be valid. */
379 while((ANACTRL->XO32M_STATUS & ANACTRL_XO32M_STATUS_XO_READY_MASK) == 0U)
380 {
381 }
382
383 s_Ext_Clk_Freq = iFreq;
384 return kStatus_Success;
385 }
386
387 /* Set I2S MCLK Clk */
388 /**
389 * brief Initialize the I2S MCLK clock to given frequency.
390 * param iFreq : Desired frequency (must be equal to exact rate in Hz)
391 * return returns success or fail status.
392 */
CLOCK_SetupI2SMClkClocking(uint32_t iFreq)393 status_t CLOCK_SetupI2SMClkClocking(uint32_t iFreq)
394 {
395 s_I2S_Mclk_Freq = iFreq;
396 return kStatus_Success;
397 }
398
399 /* Get CLOCK OUT Clk */
400 /*! brief Return Frequency of ClockOut
401 * return Frequency of ClockOut
402 */
CLOCK_GetClockOutClkFreq(void)403 uint32_t CLOCK_GetClockOutClkFreq(void)
404 {
405 uint32_t freq = 0U;
406
407 switch (SYSCON->CLKOUTSEL)
408 {
409 case 0U:
410 freq = CLOCK_GetCoreSysClkFreq();
411 break;
412
413 case 1U:
414 freq = CLOCK_GetPll0OutFreq();
415 break;
416
417 case 2U:
418 freq = CLOCK_GetExtClkFreq();
419 break;
420
421 case 3U:
422 freq = CLOCK_GetFroHfFreq();
423 break;
424
425 case 4U:
426 freq = CLOCK_GetFro1MFreq();
427 break;
428
429 case 5U:
430 freq = CLOCK_GetPll1OutFreq();
431 break;
432
433 case 6U:
434 freq = CLOCK_GetOsc32KFreq();
435 break;
436
437 case 7U:
438 freq = 0U;
439 break;
440
441 default:
442 freq = 0U;
443 break;
444 }
445 return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
446 }
447
448 /* Get CAN Clk */
449 /*! brief Return Frequency of Can Clock
450 * return Frequency of Can.
451 */
CLOCK_GetMCanClkFreq(void)452 uint32_t CLOCK_GetMCanClkFreq(void)
453 {
454 uint32_t freq = 0U;
455
456 switch (SYSCON->CANCLKSEL)
457 {
458 case 0U:
459 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CANCLKDIV & SYSCON_CANCLKDIV_DIV_MASK) + 1U);
460 break;
461 case 1U:
462 freq = CLOCK_GetFro1MFreq();
463 break;
464 case 2U:
465 freq = CLOCK_GetOsc32KFreq();
466 break;
467 case 7U:
468 freq = 0U;
469 break;
470
471 default:
472 freq = 0U;
473 break;
474 }
475
476 return freq;
477 }
478
479 /* Get ADC Clk */
480 /*! brief Return Frequency of Adc Clock
481 * return Frequency of Adc.
482 */
CLOCK_GetAdcClkFreq(uint32_t id)483 uint32_t CLOCK_GetAdcClkFreq(uint32_t id)
484 {
485 uint32_t freq = 0U;
486 uint32_t div = 0U;
487
488 switch ((id == 0U) ? (SYSCON->ADC0CLKSEL) : (SYSCON->ADC1CLKSEL))
489 {
490 case 0U:
491 freq = CLOCK_GetCoreSysClkFreq();
492 break;
493 case 1U:
494 freq = CLOCK_GetPll0OutFreq();
495 break;
496 case 2U:
497 freq = CLOCK_GetFroHfFreq();
498 break;
499 default:
500 freq = 0U;
501 break;
502 }
503
504 div = ((id == 0U) ? ((SYSCON->ADC0CLKDIV & SYSCON_ADC0CLKDIV_DIV_MASK) + 1U) :
505 ((SYSCON->ADC1CLKDIV & SYSCON_ADC1CLKDIV_DIV_MASK) + 1U));
506
507 return freq / div;
508 }
509
510 /* Get USB0 Clk */
511 /*! brief Return Frequency of Usb0 Clock
512 * return Frequency of Usb0 Clock.
513 */
CLOCK_GetUsb0ClkFreq(void)514 uint32_t CLOCK_GetUsb0ClkFreq(void)
515 {
516 uint32_t freq = 0U;
517
518 switch (SYSCON->USB0CLKSEL)
519 {
520 case 0U:
521 freq = CLOCK_GetCoreSysClkFreq();
522 break;
523 case 1U:
524 freq = CLOCK_GetPll0OutFreq();
525 break;
526 case 3U:
527 freq = CLOCK_GetFroHfFreq();
528 break;
529 case 5U:
530 freq = CLOCK_GetPll1OutFreq();
531 break;
532 case 7U:
533 freq = 0U;
534 break;
535
536 default:
537 freq = 0U;
538 break;
539 }
540
541 return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);
542 }
543
544 /* Get MCLK Clk */
545 /*! brief Return Frequency of MClk Clock
546 * return Frequency of MClk Clock.
547 */
CLOCK_GetMclkClkFreq(void)548 uint32_t CLOCK_GetMclkClkFreq(void)
549 {
550 uint32_t freq = 0U;
551
552 switch (SYSCON->MCLKCLKSEL)
553 {
554 case 0U:
555 freq = CLOCK_GetFroHfFreq();
556 break;
557 case 1U:
558 freq = CLOCK_GetPll0OutFreq();
559 break;
560 case 7U:
561 freq = 0U;
562 break;
563
564 default:
565 freq = 0U;
566 break;
567 }
568
569 return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);
570 }
571
572 /* Get SCTIMER Clk */
573 /*! brief Return Frequency of SCTimer Clock
574 * return Frequency of SCTimer Clock.
575 */
CLOCK_GetSctClkFreq(void)576 uint32_t CLOCK_GetSctClkFreq(void)
577 {
578 uint32_t freq = 0U;
579
580 switch (SYSCON->SCTCLKSEL)
581 {
582 case 0U:
583 freq = CLOCK_GetCoreSysClkFreq();
584 break;
585 case 1U:
586 freq = CLOCK_GetPll0OutFreq();
587 break;
588 case 2U:
589 freq = CLOCK_GetExtClkFreq();
590 break;
591 case 3U:
592 freq = CLOCK_GetFroHfFreq();
593 break;
594 case 4U:
595 freq = CLOCK_GetPll1OutFreq();
596 break;
597 case 5U:
598 freq = CLOCK_GetI2SMClkFreq();
599 break;
600 case 7U:
601 freq = 0U;
602 break;
603
604 default:
605 freq = 0U;
606 break;
607 }
608
609 return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
610 }
611
612 /* Get FRO 12M Clk */
613 /*! brief Return Frequency of FRO 12MHz
614 * return Frequency of FRO 12MHz
615 */
CLOCK_GetFro12MFreq(void)616 uint32_t CLOCK_GetFro12MFreq(void)
617 {
618 return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U;
619 }
620
621 /* Get FRO 1M Clk */
622 /*! brief Return Frequency of FRO 1MHz
623 * return Frequency of FRO 1MHz
624 */
CLOCK_GetFro1MFreq(void)625 uint32_t CLOCK_GetFro1MFreq(void)
626 {
627 return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U;
628 }
629
630 /* Get EXT OSC Clk */
631 /*! brief Return Frequency of External Clock
632 * return Frequency of External Clock. If no external clock is used returns 0.
633 */
CLOCK_GetExtClkFreq(void)634 uint32_t CLOCK_GetExtClkFreq(void)
635 {
636 return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? s_Ext_Clk_Freq : 0U;
637 }
638
639 /* Get WATCH DOG Clk */
640 /*! brief Return Frequency of Watchdog
641 * return Frequency of Watchdog
642 */
CLOCK_GetWdtClkFreq(void)643 uint32_t CLOCK_GetWdtClkFreq(void)
644 {
645 return CLOCK_GetFro1MFreq() / ((SYSCON->WDTCLKDIV & SYSCON_WDTCLKDIV_DIV_MASK) + 1U);
646 }
647
648 /* Get HF FRO Clk */
649 /*! brief Return Frequency of High-Freq output of FRO
650 * return Frequency of High-Freq output of FRO
651 */
CLOCK_GetFroHfFreq(void)652 uint32_t CLOCK_GetFroHfFreq(void)
653 {
654 return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U;
655 }
656
657 /* Get SYSTEM PLL Clk */
658 /*! brief Return Frequency of PLL
659 * return Frequency of PLL
660 */
CLOCK_GetPll0OutFreq(void)661 uint32_t CLOCK_GetPll0OutFreq(void)
662 {
663 return s_Pll0_Freq;
664 }
665
666 /* Get USB PLL Clk */
667 /*! brief Return Frequency of USB PLL
668 * return Frequency of PLL
669 */
CLOCK_GetPll1OutFreq(void)670 uint32_t CLOCK_GetPll1OutFreq(void)
671 {
672 return s_Pll1_Freq;
673 }
674
675 /* Get RTC OSC Clk */
676 /*! brief Return Frequency of 32kHz osc
677 * return Frequency of 32kHz osc
678 */
CLOCK_GetOsc32KFreq(void)679 uint32_t CLOCK_GetOsc32KFreq(void)
680 {
681 return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
682 (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
683 CLK_RTC_32K_CLK :
684 ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
685 ((PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK) != 0UL)) ?
686 CLK_RTC_32K_CLK :
687 0UL;
688 }
689
690 /* Get Flexcomm 32K Clk */
691 /*! brief Return Frequency of Flexcomm 32kHz
692 * return Frequency of Flexcomm 32kHz
693 */
CLOCK_GetFC32KFreq(void)694 uint32_t CLOCK_GetFC32KFreq(void)
695 {
696 return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) &&
697 (0UL == (SYSCON->FC32KCLKSEL & SYSCON_FC32KCLKSEL_FC32KCLKSEL_MASK))) ?
698 CLK_RTC_32K_CLK :
699 ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) &&
700 ((SYSCON->FC32KCLKSEL & SYSCON_FC32KCLKSEL_FC32KCLKSEL_MASK) != 0UL)) ?
701 CLK_RTC_32K_CLK :
702 0UL;
703 }
704
705 /* Get MAIN Clk */
706 /*! brief Return Frequency of Core System
707 * return Frequency of Core System
708 */
CLOCK_GetCoreSysClkFreq(void)709 uint32_t CLOCK_GetCoreSysClkFreq(void)
710 {
711 uint32_t freq = 0U;
712
713 switch (SYSCON->MAINCLKSELB)
714 {
715 case 0U:
716 if (SYSCON->MAINCLKSELA == 0U)
717 {
718 freq = CLOCK_GetFro12MFreq();
719 }
720 else if (SYSCON->MAINCLKSELA == 1U)
721 {
722 freq = CLOCK_GetExtClkFreq();
723 }
724 else if (SYSCON->MAINCLKSELA == 2U)
725 {
726 freq = CLOCK_GetFro1MFreq();
727 }
728 else if (SYSCON->MAINCLKSELA == 3U)
729 {
730 freq = CLOCK_GetFroHfFreq();
731 }
732 else
733 {
734 /* Added comments to avoid the violation of MISRA C-2012 rule 15.7 */
735 }
736 break;
737 case 1U:
738 freq = CLOCK_GetPll0OutFreq();
739 break;
740 case 2U:
741 freq = CLOCK_GetPll1OutFreq();
742 break;
743
744 case 3U:
745 freq = CLOCK_GetOsc32KFreq();
746 break;
747
748 default:
749 freq = 0U;
750 break;
751 }
752
753 return freq;
754 }
755
756 /* Get I2S MCLK Clk */
757 /*! brief Return Frequency of I2S MCLK Clock
758 * return Frequency of I2S MCLK Clock
759 */
CLOCK_GetI2SMClkFreq(void)760 uint32_t CLOCK_GetI2SMClkFreq(void)
761 {
762 return s_I2S_Mclk_Freq;
763 }
764
765 /* Get PLLClkDiv Clk */
CLOCK_GetPllClkDivFreq(void)766 uint32_t CLOCK_GetPllClkDivFreq(void)
767 {
768 uint32_t freq = 0U;
769
770 switch (SYSCON->PLLCLKDIVSEL)
771 {
772 case 0U:
773 freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLLCLKDIV & SYSCON_PLLCLKDIV_DIV_MASK) + 1U);
774 break;
775 case 1U:
776 freq = CLOCK_GetPll1OutFreq() /
777 ((SYSCON->PLLCLKDIV & SYSCON_PLLCLKDIV_DIV_MASK) + 1U); // register name should be checked
778 break;
779 default:
780 freq = 0U;
781 break;
782 }
783 /* todo: pll_clk_div = pll_clk/div*/
784 return freq;
785 }
786
787 /* Get FRG Clk */
CLOCK_GetFrgFreq(uint32_t id)788 uint32_t CLOCK_GetFrgFreq(uint32_t id)
789 {
790 uint32_t freq = 0U;
791
792 switch (SYSCON->FRGCLKSEL[id])
793 {
794 case 0U:
795 freq = CLOCK_GetCoreSysClkFreq();
796 break;
797 case 1U:
798 freq = CLOCK_GetPllClkDivFreq();
799 break;
800 case 2U:
801 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
802 break;
803 default:
804 freq = 0U;
805 break;
806 }
807 return (uint32_t)(((uint64_t)freq * (SYSCON_FRGCTRL_DIV_MASK + 1U)) /
808 ((SYSCON_FRGCTRL_DIV_MASK + 1U) +
809 ((SYSCON->FRGCTRL[id] & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)));
810 }
811
812 /* Get FLEXCOMM Clk */
CLOCK_GetFlexCommClkFreq(uint32_t id)813 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
814 {
815 uint32_t freq = 0U;
816
817 switch (SYSCON->FCCLKSEL[id])
818 {
819 case 0U:
820 freq = CLOCK_GetCoreSysClkFreq();
821 break;
822 case 1U:
823 freq = CLOCK_GetFrgFreq(id);
824 break;
825 case 2U:
826 freq = CLOCK_GetFro12MFreq();
827 break;
828 case 3U:
829 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
830 break;
831 case 4U:
832 freq = CLOCK_GetFro1MFreq();
833 break;
834 case 5U:
835 freq = CLOCK_GetI2SMClkFreq();
836 break;
837 case 6U:
838 freq = CLOCK_GetOsc32KFreq();
839 break;
840 case 7U:
841 freq = 0U;
842 break;
843
844 default:
845 freq = 0U;
846 break;
847 }
848
849 return freq / ((SYSCON->FLEXCOMMCLKDIV[id] & 0xffU) + 1U);
850 }
851
852 /* Get HS_LPSI Clk */
CLOCK_GetHsLspiClkFreq(void)853 uint32_t CLOCK_GetHsLspiClkFreq(void)
854 {
855 uint32_t freq = 0U;
856
857 switch (SYSCON->HSSPICLKSEL)
858 {
859 case 0U:
860 freq = CLOCK_GetCoreSysClkFreq();
861 break;
862 case 1U:
863 freq = CLOCK_GetPll0OutFreq() / ((SYSCON->PLLCLKDIV & 0xffU) + 1U);
864 break;
865 case 2U:
866 freq = CLOCK_GetFro12MFreq();
867 break;
868 case 3U:
869 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFDIV & 0xffU) + 1U);
870 break;
871 case 4U:
872 freq = CLOCK_GetFro1MFreq();
873 break;
874 case 6U:
875 freq = CLOCK_GetOsc32KFreq();
876 break;
877 case 7U:
878 freq = 0U;
879 break;
880
881 default:
882 freq = 0U;
883 break;
884 }
885
886 return freq;
887 }
888
889 /* Get CTimer Clk */
890 /*! brief Return Frequency of CTimer functional Clock
891 * return Frequency of CTimer functional Clock
892 */
CLOCK_GetCTimerClkFreq(uint32_t id)893 uint32_t CLOCK_GetCTimerClkFreq(uint32_t id)
894 {
895 uint32_t freq = 0U;
896
897 switch (SYSCON->CTIMERCLKSEL[id])
898 {
899 case 0U:
900 freq = CLOCK_GetCoreSysClkFreq();
901 break;
902 case 1U:
903 freq = CLOCK_GetPll0OutFreq();
904 break;
905 case 2U:
906 freq = CLOCK_GetPll1OutFreq();
907 break;
908 case 3U:
909 freq = CLOCK_GetFroHfFreq();
910 break;
911 case 4U:
912 freq = CLOCK_GetFro1MFreq();
913 break;
914 case 5U:
915 freq = CLOCK_GetI2SMClkFreq();
916 break;
917 case 6U:
918 freq = CLOCK_GetOsc32KFreq();
919 break;
920 case 7U:
921 freq = 0U;
922 break;
923
924 default:
925 freq = 0U;
926 break;
927 }
928
929 return freq / ((SYSCON->CTIMERCLKDIV[id] & 0xffU) + 1U);
930 }
931
932 /* Get Systick Clk */
933 /*! brief Return Frequency of SystickClock
934 * return Frequency of Systick Clock
935 */
CLOCK_GetSystickClkFreq(void)936 uint32_t CLOCK_GetSystickClkFreq(void)
937 {
938 uint32_t freq = 0U;
939
940 switch (SYSCON->SYSTICKCLKSEL0)
941 {
942 case 0U:
943 /*Niobe4mini just has one SYSTICKSEL and SYSTICKDIV register, Fix coverity problem in this way temporarily
944 */
945 freq = CLOCK_GetCoreSysClkFreq() / (((SYSCON->SYSTICKCLKDIV[0]) & 0xffU) + 1U);
946 break;
947 case 1U:
948 freq = CLOCK_GetFro1MFreq();
949 break;
950 case 2U:
951 freq = CLOCK_GetOsc32KFreq();
952 break;
953 case 7U:
954 freq = 0U;
955 break;
956
957 default:
958 freq = 0U;
959 break;
960 }
961
962 return freq;
963 }
964
965 /* Get DAC Clk */
966 /*! brief Return Frequency of DAC Clock
967 * return Frequency of DAC.
968 */
CLOCK_GetDacClkFreq(uint32_t id)969 uint32_t CLOCK_GetDacClkFreq(uint32_t id)
970 {
971 uint32_t freq = 0U;
972
973 switch (SYSCON->DAC[id].CLKSEL)
974 {
975 case 0U:
976 freq = CLOCK_GetCoreSysClkFreq();
977 break;
978 case 1U:
979 freq = CLOCK_GetPll0OutFreq();
980 break;
981 case 3U:
982 freq = CLOCK_GetFroHfFreq();
983 break;
984 case 4U:
985 freq = CLOCK_GetFro12MFreq();
986 break;
987 case 5U:
988 freq = CLOCK_GetPll1OutFreq();
989 break;
990 case 6U:
991 freq = CLOCK_GetFro1MFreq();
992 break;
993 default:
994 freq = 0U;
995 break;
996 }
997
998 return freq / ((SYSCON->DAC[id].CLKDIV & SYSCON_DAC_CLKDIV_DIV_MASK) + 1U);
999 }
1000
1001 /* Get FlexSpi Clk */
1002 /*! brief Return Frequency of FlexSpi clock
1003 * return Frequency of FlexSpi Clock
1004 */
CLOCK_GetFlexSpiClkFreq(void)1005 uint32_t CLOCK_GetFlexSpiClkFreq(void)
1006 {
1007 uint32_t freq = 0U;
1008
1009 switch (SYSCON->FLEXSPICLKSEL)
1010 {
1011 case 0U:
1012 freq = CLOCK_GetCoreSysClkFreq();
1013 break;
1014 case 1U:
1015 freq = CLOCK_GetPll0OutFreq();
1016 break;
1017 case 3U:
1018 freq = CLOCK_GetFroHfFreq();
1019 break;
1020 case 5U:
1021 freq = CLOCK_GetPll1OutFreq();
1022 break;
1023 case 7U:
1024 freq = 0U;
1025 break;
1026 default:
1027 freq = 0U;
1028 break;
1029 }
1030
1031 return freq / ((SYSCON->FLEXSPICLKDIV & SYSCON_FLEXSPICLKDIV_DIV_MASK) + 1U);
1032 }
1033
1034 /* Get DMIC Clk */
1035 /*! brief Return Frequency of DMIC clock
1036 * return Frequency of DMIC Clock
1037 */
CLOCK_GetDmicClkFreq(void)1038 uint32_t CLOCK_GetDmicClkFreq(void)
1039 {
1040 uint32_t freq = 0U;
1041
1042 switch (SYSCON->DMICFCLKSEL)
1043 {
1044 case 0U:
1045 freq = CLOCK_GetCoreSysClkFreq();
1046 break;
1047 case 1U:
1048 freq = CLOCK_GetPll0OutFreq();
1049 break;
1050 case 2U:
1051 freq = CLOCK_GetExtClkFreq();
1052 break;
1053 case 3U:
1054 freq = CLOCK_GetFroHfFreq();
1055 break;
1056 case 4U:
1057 freq = CLOCK_GetPll1OutFreq();
1058 break;
1059 case 5U:
1060 freq = CLOCK_GetI2SMClkFreq();
1061 break;
1062 default:
1063 freq = 0U;
1064 break;
1065 }
1066
1067 return freq / ((SYSCON->DMICFCLKDIV & SYSCON_DMICFCLKDIV_DIV_MASK) + 1U);
1068 }
1069
1070 /* Get I3C function Clk */
1071 /*! brief Return Frequency of I3C function clock
1072 * return Frequency of I3C function Clock
1073 */
CLOCK_GetI3cClkFreq(void)1074 uint32_t CLOCK_GetI3cClkFreq(void)
1075 {
1076 uint32_t freq = 0U;
1077
1078 switch (SYSCON->I3CFCLKSEL)
1079 {
1080 case 0U:
1081 freq = CLOCK_GetCoreSysClkFreq();
1082 break;
1083 case 1U:
1084 freq = CLOCK_GetPllClkDivFreq();
1085 break;
1086 default:
1087 freq = 0U;
1088 break;
1089 }
1090
1091 return freq / ((SYSCON->I3CFCLKDIV & SYSCON_I3CFCLKDIV_DIV_MASK) + 1U);
1092 }
1093
1094 /* Get I3C function slow TC Clk */
1095 /*! brief Return Frequency of I3C function Slow TC clock
1096 * return Frequency of I3C function slow TC Clock
1097 */
CLOCK_GetI3cSTCClkFreq(void)1098 uint32_t CLOCK_GetI3cSTCClkFreq(void)
1099 {
1100 uint32_t freq = 0U;
1101
1102 switch (SYSCON->I3CFCLKSTCSEL)
1103 {
1104 case 0U:
1105 freq = CLOCK_GetI3cClkFreq();
1106 break;
1107 case 1U:
1108 freq = CLOCK_GetFro1MFreq();
1109 break;
1110 default:
1111 freq = 0U;
1112 break;
1113 }
1114
1115 return freq / ((SYSCON->I3CFCLKSTCDIV & SYSCON_I3CFCLKSTCDIV_DIV_MASK) + 1U);
1116 }
1117
1118 /* Get I3C function slow Clk */
1119 /*! brief Return Frequency of I3C function Slow clock
1120 * return Frequency of I3C function slow Clock
1121 */
CLOCK_GetI3cSClkFreq(void)1122 uint32_t CLOCK_GetI3cSClkFreq(void)
1123 {
1124 uint32_t freq = 0U;
1125
1126 switch (SYSCON->I3CFCLKSSEL)
1127 {
1128 case 0U:
1129 freq = CLOCK_GetFro1MFreq();
1130 break;
1131 default:
1132 freq = 0U;
1133 break;
1134 }
1135
1136 return freq / ((SYSCON->I3CFCLKSDIV & SYSCON_I3CFCLKSDIV_DIV_MASK) + 1U);
1137 }
1138
1139 /* Get IP Clk */
1140 /*! brief Return Frequency of selected clock
1141 * return Frequency of selected clock
1142 */
CLOCK_GetFreq(clock_name_t clockName)1143 uint32_t CLOCK_GetFreq(clock_name_t clockName)
1144 {
1145 uint32_t freq;
1146 switch (clockName)
1147 {
1148 case kCLOCK_CoreSysClk:
1149 freq = CLOCK_GetCoreSysClkFreq();
1150 break;
1151 case kCLOCK_BusClk:
1152 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
1153 break;
1154 case kCLOCK_ClockOut:
1155 freq = CLOCK_GetClockOutClkFreq();
1156 break;
1157 case kCLOCK_Pll1Out:
1158 freq = CLOCK_GetPll1OutFreq();
1159 break;
1160 case kCLOCK_Mclk:
1161 freq = CLOCK_GetMclkClkFreq();
1162 break;
1163 case kCLOCK_FroHf:
1164 freq = CLOCK_GetFroHfFreq();
1165 break;
1166 case kCLOCK_Fro12M:
1167 freq = CLOCK_GetFro12MFreq();
1168 break;
1169 case kCLOCK_Fro1M:
1170 freq = CLOCK_GetFro1MFreq();
1171 break;
1172 case kCLOCK_ExtClk:
1173 freq = CLOCK_GetExtClkFreq();
1174 break;
1175 case kCLOCK_Pll0Out:
1176 freq = CLOCK_GetPll0OutFreq();
1177 break;
1178 case kCLOCK_FlexI2S:
1179 freq = CLOCK_GetI2SMClkFreq();
1180 break;
1181 default:
1182 freq = 0U;
1183 break;
1184 }
1185 return freq;
1186 }
1187
1188 /* 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)1189 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
1190 {
1191 uint32_t seli, selp;
1192 /* bandwidth: compute selP from Multiplier */
1193 if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1194 {
1195 selp = (M >> 2U) + 1U;
1196 if (selp >= 31U)
1197 {
1198 selp = 31U;
1199 }
1200 *pSelP = selp;
1201
1202 if (M >= 8000UL)
1203 {
1204 seli = 1UL;
1205 }
1206 else if (M >= 122UL)
1207 {
1208 seli = (uint32_t)(8000UL / M); /*floor(8000/M) */
1209 }
1210 else
1211 {
1212 seli = 2UL * ((uint32_t)(M / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
1213 }
1214
1215 if (seli >= 63UL)
1216 {
1217 seli = 63UL;
1218 }
1219 *pSelI = seli;
1220
1221 *pSelR = 0UL;
1222 }
1223 else
1224 {
1225 /* Note: If the spread spectrum mode, choose N to ensure 3 MHz < Fin/N < 5 MHz */
1226 *pSelP = 3U;
1227 *pSelI = 4U;
1228 *pSelR = 4U;
1229 }
1230 }
1231
1232 /* Get predivider (N) from PLL0 NDEC setting */
findPll0PreDiv(void)1233 static uint32_t findPll0PreDiv(void)
1234 {
1235 uint32_t preDiv = 1UL;
1236
1237 /* Direct input is not used? */
1238 if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPREDIV_MASK) == 0UL)
1239 {
1240 preDiv = SYSCON->PLL0NDEC & SYSCON_PLL0NDEC_NDIV_MASK;
1241 if (preDiv == 0UL)
1242 {
1243 preDiv = 1UL;
1244 }
1245 }
1246 return preDiv;
1247 }
1248
1249 /* Get predivider (N) from PLL1 NDEC setting */
findPll1PreDiv(void)1250 static uint32_t findPll1PreDiv(void)
1251 {
1252 uint32_t preDiv = 1UL;
1253
1254 /* Direct input is not used? */
1255 if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL)
1256 {
1257 preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK;
1258 if (preDiv == 0UL)
1259 {
1260 preDiv = 1UL;
1261 }
1262 }
1263 return preDiv;
1264 }
1265
1266 /* Get postdivider (P) from PLL0 PDEC setting */
findPll0PostDiv(void)1267 static uint32_t findPll0PostDiv(void)
1268 {
1269 uint32_t postDiv = 1UL;
1270
1271 if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1272 {
1273 if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1274 {
1275 postDiv = SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK;
1276 }
1277 else
1278 {
1279 postDiv = 2UL * (SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK);
1280 }
1281 if (postDiv == 0UL)
1282 {
1283 postDiv = 2UL;
1284 }
1285 }
1286 return postDiv;
1287 }
1288
1289 /* Get postdivider (P) from PLL1 PDEC setting. */
findPll1PostDiv(void)1290 static uint32_t findPll1PostDiv(void)
1291 {
1292 uint32_t postDiv = 1UL;
1293
1294 if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV_MASK) == 0UL)
1295 {
1296 if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
1297 {
1298 postDiv = SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK;
1299 }
1300 else
1301 {
1302 postDiv = 2UL * (SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK);
1303 }
1304 if (postDiv == 0UL)
1305 {
1306 postDiv = 2UL;
1307 }
1308 }
1309
1310 return postDiv;
1311 }
1312
1313 /* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
findPll0MMult(void)1314 static float findPll0MMult(void)
1315 {
1316 float mMult = 1.0F;
1317 float mMult_fract;
1318 uint32_t mMult_int;
1319
1320 if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL)
1321 {
1322 mMult =
1323 (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT);
1324 }
1325 else
1326 {
1327 mMult_int = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U);
1328 mMult_int = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL0_SSCG_MD_INT_P);
1329 mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL0_SSCG_MD_FRACT_M) /
1330 (float)(uint32_t)(1UL << PLL0_SSCG_MD_INT_P));
1331 mMult = (float)mMult_int + mMult_fract;
1332 }
1333 if (0ULL == ((uint64_t)mMult))
1334 {
1335 mMult = 1.0F;
1336 }
1337 return mMult;
1338 }
1339
1340 /* Get multiplier (M) from PLL1 MDEC. */
findPll1MMult(void)1341 static uint32_t findPll1MMult(void)
1342 {
1343 uint32_t mMult = 1UL;
1344
1345 mMult = SYSCON->PLL1MDEC & SYSCON_PLL1MDEC_MDIV_MASK;
1346
1347 if (mMult == 0UL)
1348 {
1349 mMult = 1UL;
1350 }
1351
1352 return mMult;
1353 }
1354
1355 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1356 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1357 {
1358 uint32_t tmp;
1359
1360 while (n != 0U)
1361 {
1362 tmp = n;
1363 n = m % n;
1364 m = tmp;
1365 }
1366
1367 return m;
1368 }
1369
1370 /*
1371 * Set PLL0 output based on desired output rate.
1372 * In this function, the it calculates the PLL0 setting for output frequency from input clock
1373 * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1374 * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1375 */
CLOCK_GetPll0ConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1376 static pll_error_t CLOCK_GetPll0ConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1377 {
1378 uint32_t nDivOutHz, fccoHz;
1379 uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
1380 uint32_t pllDirectInput, pllDirectOutput;
1381 uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
1382
1383 /* Baseline parameters (no input or output dividers) */
1384 pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */
1385 pllPostDivider = 1U; /* 1 implies post-divider will be disabled */
1386 pllDirectOutput = 1U;
1387
1388 /* Verify output rate parameter */
1389 if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1390 {
1391 /* Maximum PLL output with post divider=1 cannot go above this frequency */
1392 return kStatus_PLL_OutputTooHigh;
1393 }
1394 if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1395 {
1396 /* Minmum PLL output with maximum post divider cannot go below this frequency */
1397 return kStatus_PLL_OutputTooLow;
1398 }
1399
1400 /* If using SS mode, input clock needs to be between 3MHz and 20MHz */
1401 if (useSS)
1402 {
1403 /* Verify input rate parameter */
1404 if (finHz < PLL_MIN_IN_SSMODE)
1405 {
1406 /* Input clock into the PLL cannot be lower than this */
1407 return kStatus_PLL_InputTooLow;
1408 }
1409 /* PLL input in SS mode must be under 20MHz */
1410 if (finHz > (PLL_MAX_IN_SSMODE * NVALMAX))
1411 {
1412 return kStatus_PLL_InputTooHigh;
1413 }
1414 }
1415 else
1416 {
1417 /* Verify input rate parameter */
1418 if (finHz < PLL_LOWER_IN_LIMIT)
1419 {
1420 /* Input clock into the PLL cannot be lower than this */
1421 return kStatus_PLL_InputTooLow;
1422 }
1423 if (finHz > PLL_HIGHER_IN_LIMIT)
1424 {
1425 /* Input clock into the PLL cannot be higher than this */
1426 return kStatus_PLL_InputTooHigh;
1427 }
1428 }
1429
1430 /* Find the optimal CCO frequency for the output and input that
1431 will keep it inside the PLL CCO range. This may require
1432 tweaking the post-divider for the PLL. */
1433 fccoHz = foutHz;
1434 while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1435 {
1436 /* CCO output is less than minimum CCO range, so the CCO output
1437 needs to be bumped up and the post-divider is used to bring
1438 the PLL output back down. */
1439 pllPostDivider++;
1440 if (pllPostDivider > PVALMAX)
1441 {
1442 return kStatus_PLL_OutsideIntLimit;
1443 }
1444
1445 /* Target CCO goes up, PLL output goes down */
1446 /* divide-by-2 divider in the post-divider is always work*/
1447 fccoHz = foutHz * (pllPostDivider * 2U);
1448 pllDirectOutput = 0U;
1449 }
1450
1451 /* Determine if a pre-divider is needed to get the best frequency */
1452 if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz) && (useSS == false))
1453 {
1454 uint32_t a = FindGreatestCommonDivisor(fccoHz, finHz);
1455
1456 if (a > PLL_LOWER_IN_LIMIT)
1457 {
1458 a = finHz / a;
1459 if ((a != 0U) && (a < PLL_MAX_N_DIV))
1460 {
1461 pllPreDivider = a;
1462 }
1463 }
1464 }
1465
1466 /* Bypass pre-divider hardware if pre-divider is 1 */
1467 if (pllPreDivider > 1U)
1468 {
1469 pllDirectInput = 0U;
1470 }
1471 else
1472 {
1473 pllDirectInput = 1U;
1474 }
1475
1476 /* Determine PLL multipler */
1477 nDivOutHz = (finHz / pllPreDivider);
1478 pllMultiplier = (fccoHz / nDivOutHz);
1479
1480 /* Find optimal values for filter */
1481 if (useSS == false)
1482 {
1483 /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1484 if ((nDivOutHz * ((pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1485 {
1486 pllMultiplier++;
1487 }
1488
1489 /* Setup filtering */
1490 pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
1491 uplimoff = 0U;
1492
1493 /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1494 pSetup->pllsscg[1] =
1495 (uint32_t)((PLL_SSCG1_MDEC_VAL_SET(pllMultiplier)) | (1UL << SYSCON_PLL0SSCG1_SEL_EXT_SHIFT));
1496 }
1497 else
1498 {
1499 uint64_t fc;
1500
1501 /* Filtering will be handled by SSC */
1502 pllSelR = 0UL;
1503 pllSelI = 0UL;
1504 pllSelP = 0UL;
1505 uplimoff = 1U;
1506
1507 /* The PLL multiplier will get very close and slightly under the
1508 desired target frequency. A small fractional component can be
1509 added to fine tune the frequency upwards to the target. */
1510 fc = ((uint64_t)(uint32_t)(fccoHz % nDivOutHz) << 25UL) / nDivOutHz;
1511
1512 /* Set multiplier */
1513 pSetup->pllsscg[0] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) | PLL0_SSCG_MD_FRACT_SET((uint32_t)fc));
1514 pSetup->pllsscg[1] = (uint32_t)(PLL0_SSCG_MD_INT_SET(pllMultiplier) >> 32U);
1515 }
1516
1517 /* Get encoded values for N (prediv) and P (postdiv) */
1518 pSetup->pllndec = PLL_NDEC_VAL_SET(pllPreDivider);
1519 pSetup->pllpdec = PLL_PDEC_VAL_SET(pllPostDivider);
1520
1521 /* PLL control */
1522 pSetup->pllctrl = (pllSelR << SYSCON_PLL0CTRL_SELR_SHIFT) | /* Filter coefficient */
1523 (pllSelI << SYSCON_PLL0CTRL_SELI_SHIFT) | /* Filter coefficient */
1524 (pllSelP << SYSCON_PLL0CTRL_SELP_SHIFT) | /* Filter coefficient */
1525 (0UL << SYSCON_PLL0CTRL_BYPASSPLL_SHIFT) | /* PLL bypass mode disabled */
1526 (uplimoff << SYSCON_PLL0CTRL_LIMUPOFF_SHIFT) | /* SS/fractional mode disabled */
1527 (pllDirectInput << SYSCON_PLL0CTRL_BYPASSPREDIV_SHIFT) | /* Bypass pre-divider? */
1528 (pllDirectOutput << SYSCON_PLL0CTRL_BYPASSPOSTDIV_SHIFT) | /* Bypass post-divider? */
1529 (1UL << SYSCON_PLL0CTRL_CLKEN_SHIFT); /* Ensure the PLL clock output */
1530
1531 return kStatus_PLL_Success;
1532 }
1533
1534 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1535 /* Alloct the static buffer for cache. */
1536 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1537 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1538 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1539 static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {false};
1540 static uint32_t s_PllSetupCacheIdx = 0U;
1541 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1542
1543 /*
1544 * Calculate the PLL setting values from input clock freq to output freq.
1545 */
CLOCK_GetPll0Config(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup,bool useSS)1546 static pll_error_t CLOCK_GetPll0Config(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useSS)
1547 {
1548 pll_error_t retErr;
1549 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1550 uint32_t i;
1551
1552 for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1553 {
1554 if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && (useSS == s_UseSSCache[i]))
1555 {
1556 /* Hit the target in cache buffer. */
1557 pSetup->pllctrl = s_PllSetupCacheStruct[i].pllctrl;
1558 pSetup->pllndec = s_PllSetupCacheStruct[i].pllndec;
1559 pSetup->pllpdec = s_PllSetupCacheStruct[i].pllpdec;
1560 pSetup->pllsscg[0] = s_PllSetupCacheStruct[i].pllsscg[0];
1561 pSetup->pllsscg[1] = s_PllSetupCacheStruct[i].pllsscg[1];
1562 retErr = kStatus_PLL_Success;
1563 break;
1564 }
1565 }
1566
1567 if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1568 {
1569 return retErr;
1570 }
1571 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1572
1573 retErr = CLOCK_GetPll0ConfigInternal(finHz, foutHz, pSetup, useSS);
1574
1575 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1576 /* Cache the most recent calulation result into buffer. */
1577 s_FinHzCache[s_PllSetupCacheIdx] = finHz;
1578 s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1579 s_UseSSCache[s_PllSetupCacheIdx] = useSS;
1580
1581 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl = pSetup->pllctrl;
1582 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec = pSetup->pllndec;
1583 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec = pSetup->pllpdec;
1584 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[0] = pSetup->pllsscg[0];
1585 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllsscg[1] = pSetup->pllsscg[1];
1586 /* Update the index for next available buffer. */
1587 s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1588 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1589
1590 return retErr;
1591 }
1592
1593 /* Update local PLL rate variable */
CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t * pSetup)1594 static void CLOCK_GetPLL0OutFromSetupUpdate(pll_setup_t *pSetup)
1595 {
1596 s_Pll0_Freq = CLOCK_GetPLL0OutFromSetup(pSetup);
1597 }
1598
1599 /* Update local PLL1 rate variable */
CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t * pSetup)1600 static void CLOCK_GetPLL1OutFromSetupUpdate(pll_setup_t *pSetup)
1601 {
1602 s_Pll1_Freq = CLOCK_GetPLL1OutFromSetup(pSetup);
1603 }
1604
1605 /* Return System PLL input clock rate */
1606 /*! brief Return PLL0 input clock rate
1607 * return PLL0 input clock rate
1608 */
CLOCK_GetPLL0InClockRate(void)1609 uint32_t CLOCK_GetPLL0InClockRate(void)
1610 {
1611 uint32_t clkRate = 0U;
1612
1613 switch ((SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK))
1614 {
1615 case 0x00U:
1616 clkRate = CLK_FRO_12MHZ;
1617 break;
1618
1619 case 0x01U:
1620 clkRate = CLOCK_GetExtClkFreq();
1621 break;
1622
1623 case 0x02U:
1624 clkRate = CLOCK_GetFro1MFreq();
1625 break;
1626
1627 case 0x03U:
1628 clkRate = CLOCK_GetOsc32KFreq();
1629 break;
1630
1631 default:
1632 clkRate = 0U;
1633 break;
1634 }
1635
1636 return clkRate;
1637 }
1638
1639 /* Return PLL1 input clock rate */
CLOCK_GetPLL1InClockRate(void)1640 uint32_t CLOCK_GetPLL1InClockRate(void)
1641 {
1642 uint32_t clkRate = 0U;
1643
1644 switch ((SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK))
1645 {
1646 case 0x00U:
1647 clkRate = CLK_FRO_12MHZ;
1648 break;
1649
1650 case 0x01U:
1651 clkRate = CLOCK_GetExtClkFreq();
1652 break;
1653
1654 case 0x02U:
1655 clkRate = CLOCK_GetFro1MFreq();
1656 break;
1657
1658 case 0x03U:
1659 clkRate = CLOCK_GetOsc32KFreq();
1660 break;
1661
1662 default:
1663 clkRate = 0U;
1664 break;
1665 }
1666
1667 return clkRate;
1668 }
1669
1670 /* Return PLL0 output clock rate from setup structure */
1671 /*! brief Return PLL0 output clock rate from setup structure
1672 * param pSetup : Pointer to a PLL setup structure
1673 * return PLL0 output clock rate the setup structure will generate
1674 */
CLOCK_GetPLL0OutFromSetup(pll_setup_t * pSetup)1675 uint32_t CLOCK_GetPLL0OutFromSetup(pll_setup_t *pSetup)
1676 {
1677 uint32_t clkRate = 0;
1678 uint32_t prediv, postdiv;
1679 float workRate = 0.0F;
1680
1681 /* Get the input clock frequency of PLL. */
1682 clkRate = CLOCK_GetPLL0InClockRate();
1683
1684 if (((pSetup->pllctrl & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) &&
1685 ((pSetup->pllctrl & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) &&
1686 ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) &&
1687 ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL))
1688 {
1689 prediv = findPll0PreDiv();
1690 postdiv = findPll0PostDiv();
1691 /* Adjust input clock */
1692 clkRate = clkRate / prediv;
1693 /* MDEC used for rate */
1694 workRate = (float)clkRate * (float)findPll0MMult();
1695 workRate /= (float)postdiv;
1696 }
1697
1698 return (uint32_t)workRate;
1699 }
1700
1701 /* Return PLL1 output clock rate from setup structure */
1702 /*! brief Return PLL1 output clock rate from setup structure
1703 * param pSetup : Pointer to a PLL setup structure
1704 * return PLL0 output clock rate the setup structure will generate
1705 */
CLOCK_GetPLL1OutFromSetup(pll_setup_t * pSetup)1706 uint32_t CLOCK_GetPLL1OutFromSetup(pll_setup_t *pSetup)
1707 {
1708 uint32_t clkRate = 0;
1709 uint32_t prediv, postdiv;
1710 uint32_t workRate = 0UL;
1711
1712 /* Get the input clock frequency of PLL. */
1713 clkRate = CLOCK_GetPLL1InClockRate();
1714
1715 if (((pSetup->pllctrl & SYSCON_PLL1CTRL_BYPASSPLL_MASK) == 0UL) &&
1716 ((pSetup->pllctrl & SYSCON_PLL1CTRL_CLKEN_MASK) != 0UL) &&
1717 ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL1_MASK) == 0UL))
1718 {
1719 prediv = findPll1PreDiv();
1720 postdiv = findPll1PostDiv();
1721 /* Adjust input clock */
1722 clkRate = clkRate / prediv;
1723 /* MDEC used for rate */
1724 workRate = clkRate * findPll1MMult();
1725 workRate /= postdiv;
1726 }
1727
1728 return workRate;
1729 }
1730
1731 /* Set the current PLL0 Rate */
1732 /*! brief Store the current PLL rate
1733 * param rate: Current rate of the PLL
1734 * return Nothing
1735 **/
CLOCK_SetStoredPLL0ClockRate(uint32_t rate)1736 void CLOCK_SetStoredPLL0ClockRate(uint32_t rate)
1737 {
1738 s_Pll0_Freq = rate;
1739 }
1740
1741 /* Return PLL0 output clock rate */
1742 /*! brief Return PLL0 output clock rate
1743 * param recompute : Forces a PLL rate recomputation if true
1744 * return PLL0 output clock rate
1745 * note The PLL rate is cached in the driver in a variable as
1746 * the rate computation function can take some time to perform. It
1747 * is recommended to use 'false' with the 'recompute' parameter.
1748 */
CLOCK_GetPLL0OutClockRate(bool recompute)1749 uint32_t CLOCK_GetPLL0OutClockRate(bool recompute)
1750 {
1751 pll_setup_t Setup;
1752 uint32_t rate;
1753
1754 if ((recompute) || (s_Pll0_Freq == 0U))
1755 {
1756 Setup.pllctrl = SYSCON->PLL0CTRL;
1757 Setup.pllndec = SYSCON->PLL0NDEC;
1758 Setup.pllpdec = SYSCON->PLL0PDEC;
1759 Setup.pllsscg[0] = SYSCON->PLL0SSCG0;
1760 Setup.pllsscg[1] = SYSCON->PLL0SSCG1;
1761
1762 CLOCK_GetPLL0OutFromSetupUpdate(&Setup);
1763 }
1764
1765 rate = s_Pll0_Freq;
1766
1767 return rate;
1768 }
1769
1770 /*! brief Return PLL1 output clock rate
1771 * param recompute : Forces a PLL rate recomputation if true
1772 * return PLL1 output clock rate
1773 * note The PLL rate is cached in the driver in a variable as
1774 * the rate computation function can take some time to perform. It
1775 * is recommended to use 'false' with the 'recompute' parameter.
1776 */
CLOCK_GetPLL1OutClockRate(bool recompute)1777 uint32_t CLOCK_GetPLL1OutClockRate(bool recompute)
1778 {
1779 pll_setup_t Setup;
1780 uint32_t rate;
1781
1782 if ((recompute) || (s_Pll1_Freq == 0U))
1783 {
1784 Setup.pllctrl = SYSCON->PLL1CTRL;
1785 Setup.pllndec = SYSCON->PLL1NDEC;
1786 Setup.pllpdec = SYSCON->PLL1PDEC;
1787 Setup.pllmdec = SYSCON->PLL1MDEC;
1788 CLOCK_GetPLL1OutFromSetupUpdate(&Setup);
1789 }
1790
1791 rate = s_Pll1_Freq;
1792
1793 return rate;
1794 }
1795
1796 /* Set PLL0 output based on the passed PLL setup data */
1797 /*! brief Set PLL output based on the passed PLL setup data
1798 * param pControl : Pointer to populated PLL control structure to generate setup with
1799 * param pSetup : Pointer to PLL setup structure to be filled
1800 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
1801 * note Actual frequency for setup may vary from the desired frequency based on the
1802 * accuracy of input clocks, rounding, non-fractional PLL mode, etc.
1803 */
CLOCK_SetupPLL0Data(pll_config_t * pControl,pll_setup_t * pSetup)1804 pll_error_t CLOCK_SetupPLL0Data(pll_config_t *pControl, pll_setup_t *pSetup)
1805 {
1806 uint32_t inRate;
1807 bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0UL);
1808
1809 pll_error_t pllError;
1810
1811 /* Determine input rate for the PLL */
1812 if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0UL)
1813 {
1814 inRate = pControl->inputRate;
1815 }
1816 else
1817 {
1818 inRate = CLOCK_GetPLL0InClockRate();
1819 }
1820
1821 /* PLL flag options */
1822 pllError = CLOCK_GetPll0Config(inRate, pControl->desiredRate, pSetup, useSS);
1823 if ((useSS) && (pllError == kStatus_PLL_Success))
1824 {
1825 /* If using SS mode, then some tweaks are made to the generated setup */
1826 pSetup->pllsscg[1] |= (uint32_t)pControl->ss_mf | (uint32_t)pControl->ss_mr | (uint32_t)pControl->ss_mc;
1827 if (pControl->mfDither)
1828 {
1829 pSetup->pllsscg[1] |= (1UL << SYSCON_PLL0SSCG1_DITHER_SHIFT);
1830 }
1831 }
1832
1833 return pllError;
1834 }
1835
1836 /* Set PLL0 output from PLL setup structure */
1837 /*! brief Set PLL output from PLL setup structure (precise frequency)
1838 * param pSetup : Pointer to populated PLL setup structure
1839 * param flagcfg : Flag configuration for PLL config structure
1840 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
1841 * note This function will power off the PLL, setup the PLL with the
1842 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1843 * and adjust system voltages to the new PLL rate. The function will not
1844 * alter any source clocks (ie, main systen clock) that may use the PLL,
1845 * so these should be setup prior to and after exiting the function.
1846 */
CLOCK_SetupPLL0Prec(pll_setup_t * pSetup,uint32_t flagcfg)1847 pll_error_t CLOCK_SetupPLL0Prec(pll_setup_t *pSetup, uint32_t flagcfg)
1848 {
1849 uint32_t inRate, clkRate, prediv;
1850 uint32_t pll_lock_wait_time = 0U;
1851 uint32_t max_pll_lock_wait_time = 0U;
1852 /* Power off PLL during setup changes */
1853 POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1854 POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1855
1856 pSetup->flags = flagcfg;
1857
1858 /* Write PLL setup data */
1859 SYSCON->PLL0CTRL = pSetup->pllctrl;
1860 SYSCON->PLL0NDEC = pSetup->pllndec;
1861 SYSCON->PLL0NDEC = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1862 SYSCON->PLL0PDEC = pSetup->pllpdec;
1863 SYSCON->PLL0PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1864 SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1865 SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1866 SYSCON->PLL0SSCG1 =
1867 pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT); /* latch */
1868
1869 POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1870 POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1871
1872 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1873 {
1874 if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1875 {
1876 inRate = CLOCK_GetPLL0InClockRate();
1877 prediv = findPll0PreDiv();
1878 /* Adjust input clock */
1879 clkRate = inRate / prediv;
1880
1881 /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is stable.
1882 The lock bit could be used to shorten the wait time when freq<20MHZ */
1883 max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1884
1885 if (clkRate < 20000000UL)
1886 {
1887 pll_lock_wait_time = 0U;
1888 while ((CLOCK_IsPLL0Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1889 {
1890 pll_lock_wait_time += 100U;
1891 SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1892 }
1893 }
1894 else
1895 {
1896 SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1897 }
1898 }
1899 else /* spread spectrum mode */
1900 {
1901 SDK_DelayAtLeastUs(6000U,
1902 SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval to
1903 insure the PLL will be stable */
1904 }
1905 }
1906
1907 /* Update current programmed PLL rate var */
1908 CLOCK_GetPLL0OutFromSetupUpdate(pSetup);
1909
1910 /* System voltage adjustment, occurs prior to setting main system clock */
1911 if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0UL)
1912 {
1913 POWER_SetVoltageForFreq(s_Pll0_Freq);
1914 }
1915
1916 return kStatus_PLL_Success;
1917 }
1918
1919 /* Setup PLL Frequency from pre-calculated value */
1920 /**
1921 * brief Set PLL0 output from PLL setup structure (precise frequency)
1922 * param pSetup : Pointer to populated PLL setup structure
1923 * return kStatus_PLL_Success on success, or PLL setup error code
1924 * note This function will power off the PLL, setup the PLL with the
1925 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
1926 * and adjust system voltages to the new PLL rate. The function will not
1927 * alter any source clocks (ie, main systen clock) that may use the PLL,
1928 * so these should be setup prior to and after exiting the function.
1929 */
CLOCK_SetPLL0Freq(const pll_setup_t * pSetup)1930 pll_error_t CLOCK_SetPLL0Freq(const pll_setup_t *pSetup)
1931 {
1932 uint32_t inRate, clkRate, prediv;
1933 uint32_t pll_lock_wait_time = 0U;
1934 uint32_t max_pll_lock_wait_time = 0U;
1935 /* Power off PLL during setup changes */
1936 POWER_EnablePD(kPDRUNCFG_PD_PLL0);
1937 POWER_EnablePD(kPDRUNCFG_PD_PLL0_SSCG);
1938
1939 /* Write PLL setup data */
1940 SYSCON->PLL0CTRL = pSetup->pllctrl;
1941 SYSCON->PLL0NDEC = pSetup->pllndec;
1942 SYSCON->PLL0NDEC = pSetup->pllndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* latch */
1943 SYSCON->PLL0PDEC = pSetup->pllpdec;
1944 SYSCON->PLL0PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* latch */
1945 SYSCON->PLL0SSCG0 = pSetup->pllsscg[0];
1946 SYSCON->PLL0SSCG1 = pSetup->pllsscg[1];
1947 SYSCON->PLL0SSCG1 =
1948 pSetup->pllsscg[1] | (1UL << SYSCON_PLL0SSCG1_MD_REQ_SHIFT) | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* latch */
1949
1950 POWER_DisablePD(kPDRUNCFG_PD_PLL0);
1951 POWER_DisablePD(kPDRUNCFG_PD_PLL0_SSCG);
1952
1953 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
1954 {
1955 if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL) /* normal mode */
1956 {
1957 inRate = CLOCK_GetPLL0InClockRate();
1958 prediv = findPll0PreDiv();
1959 /* Adjust input clock */
1960 clkRate = inRate / prediv;
1961
1962 /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is
1963 stable. The lock bit could be used to shorten the wait time when freq<20MHZ */
1964 max_pll_lock_wait_time = 500U + (400000000U / clkRate);
1965
1966 if (clkRate < 20000000UL)
1967 {
1968 pll_lock_wait_time = 0U;
1969 while ((CLOCK_IsPLL0Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
1970 {
1971 pll_lock_wait_time += 100U;
1972 SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1973 }
1974 }
1975 else
1976 {
1977 SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1978 }
1979 }
1980 else /* spread spectrum mode */
1981 {
1982 SDK_DelayAtLeastUs(6000U,
1983 SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* software should use a 6 ms time interval
1984 to insure the PLL will be stable */
1985 }
1986 }
1987
1988 /* Update current programmed PLL rate var */
1989 s_Pll0_Freq = pSetup->pllRate;
1990
1991 return kStatus_PLL_Success;
1992 }
1993
1994 /* Setup PLL1 Frequency from pre-calculated value */
1995 /**
1996 * brief Set PLL1 output from PLL setup structure (precise frequency)
1997 * param pSetup : Pointer to populated PLL setup structure
1998 * return kStatus_PLL_Success on success, or PLL setup error code
1999 * note This function will power off the PLL, setup the PLL with the
2000 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2001 * and adjust system voltages to the new PLL rate. The function will not
2002 * alter any source clocks (ie, main systen clock) that may use the PLL,
2003 * so these should be setup prior to and after exiting the function.
2004 */
CLOCK_SetPLL1Freq(const pll_setup_t * pSetup)2005 pll_error_t CLOCK_SetPLL1Freq(const pll_setup_t *pSetup)
2006 {
2007 uint32_t inRate, clkRate, prediv;
2008 uint32_t pll_lock_wait_time = 0U;
2009 uint32_t max_pll_lock_wait_time = 0U;
2010 /* Power off PLL during setup changes */
2011 POWER_EnablePD(kPDRUNCFG_PD_PLL1);
2012
2013 /* Write PLL setup data */
2014 SYSCON->PLL1CTRL = pSetup->pllctrl;
2015 SYSCON->PLL1NDEC = pSetup->pllndec;
2016 SYSCON->PLL1NDEC = pSetup->pllndec | (1UL << SYSCON_PLL1NDEC_NREQ_SHIFT); /* latch */
2017 SYSCON->PLL1PDEC = pSetup->pllpdec;
2018 SYSCON->PLL1PDEC = pSetup->pllpdec | (1UL << SYSCON_PLL1PDEC_PREQ_SHIFT); /* latch */
2019 SYSCON->PLL1MDEC = pSetup->pllmdec;
2020 SYSCON->PLL1MDEC = pSetup->pllmdec | (1UL << SYSCON_PLL1MDEC_MREQ_SHIFT); /* latch */
2021
2022 POWER_DisablePD(kPDRUNCFG_PD_PLL1);
2023
2024 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2025 {
2026 inRate = CLOCK_GetPLL1InClockRate();
2027 prediv = findPll1PreDiv();
2028 /* Adjust input clock */
2029 clkRate = inRate / prediv;
2030
2031 /* Need wait at least (500us + 400/Fref) (Fref in Hz result in s) to ensure the PLL is stable.
2032 The lock bit could be used to shorten the wait time when freq<20MHZ */
2033 max_pll_lock_wait_time = 500U + (400000000U / clkRate);
2034
2035 if (clkRate < 20000000UL)
2036 {
2037 pll_lock_wait_time = 0U;
2038 while ((CLOCK_IsPLL1Locked() == false) && (pll_lock_wait_time < max_pll_lock_wait_time))
2039 {
2040 pll_lock_wait_time += 100U;
2041 SDK_DelayAtLeastUs(100U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2042 }
2043 }
2044 else
2045 {
2046 SDK_DelayAtLeastUs(max_pll_lock_wait_time, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2047 }
2048 }
2049
2050 /* Update current programmed PLL rate var */
2051 s_Pll1_Freq = pSetup->pllRate;
2052
2053 return kStatus_PLL_Success;
2054 }
2055
2056 /* Set PLL0 clock based on the input frequency and multiplier */
2057 /*! brief Set PLL0 output based on the multiplier and input frequency
2058 * param multiply_by : multiplier
2059 * param input_freq : Clock input frequency of the PLL
2060 * return Nothing
2061 * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
2062 * function does not disable or enable PLL power, wait for PLL lock,
2063 * or adjust system voltages. These must be done in the application.
2064 * The function will not alter any source clocks (ie, main systen clock)
2065 * that may use the PLL, so these should be setup prior to and after
2066 * exiting the function.
2067 */
CLOCK_SetupPLL0Mult(uint32_t multiply_by,uint32_t input_freq)2068 void CLOCK_SetupPLL0Mult(uint32_t multiply_by, uint32_t input_freq)
2069 {
2070 uint32_t cco_freq = input_freq * multiply_by;
2071 uint32_t pdec = 1U;
2072 uint32_t selr;
2073 uint32_t seli;
2074 uint32_t selp;
2075 uint32_t mdec, ndec;
2076
2077 while (cco_freq < 275000000U)
2078 {
2079 multiply_by <<= 1U; /* double value in each iteration */
2080 pdec <<= 1U; /* correspondingly double pdec to cancel effect of double msel */
2081 cco_freq = input_freq * multiply_by;
2082 }
2083
2084 selr = 0U;
2085
2086 if (multiply_by >= 8000UL)
2087 {
2088 seli = 1UL;
2089 }
2090 else if (multiply_by >= 122UL)
2091 {
2092 seli = (uint32_t)(8000UL / multiply_by); /*floor(8000/M) */
2093 }
2094 else
2095 {
2096 seli = 2UL * ((uint32_t)(multiply_by / 4UL)) + 3UL; /* 2*floor(M/4) + 3 */
2097 }
2098
2099 if (seli >= 63U)
2100 {
2101 seli = 63U;
2102 }
2103
2104 {
2105 selp = 31U;
2106 }
2107
2108 if (pdec > 1U)
2109 {
2110 pdec = pdec / 2U; /* Account for minus 1 encoding */
2111 /* Translate P value */
2112 }
2113
2114 mdec = (uint32_t)PLL_SSCG1_MDEC_VAL_SET(multiply_by);
2115 ndec = 0x1U; /* pre divide by 1 (hardcoded) */
2116
2117 SYSCON->PLL0CTRL = SYSCON_PLL0CTRL_CLKEN_MASK | SYSCON_PLL0CTRL_BYPASSPOSTDIV(0) |
2118 SYSCON_PLL0CTRL_BYPASSPOSTDIV2(0) | (selr << SYSCON_PLL0CTRL_SELR_SHIFT) |
2119 (seli << SYSCON_PLL0CTRL_SELI_SHIFT) | (selp << SYSCON_PLL0CTRL_SELP_SHIFT);
2120 SYSCON->PLL0PDEC = pdec | (1UL << SYSCON_PLL0PDEC_PREQ_SHIFT); /* set Pdec value and assert preq */
2121 SYSCON->PLL0NDEC = ndec | (1UL << SYSCON_PLL0NDEC_NREQ_SHIFT); /* set Pdec value and assert preq */
2122 SYSCON->PLL0SSCG1 = mdec | (1UL << SYSCON_PLL0SSCG1_MREQ_SHIFT); /* select non sscg MDEC value, assert
2123 mreq and select mdec value */
2124 }
2125
2126 /* Enable USB DEVICE FULL SPEED clock */
2127 /*! brief Enable USB Device FS clock.
2128 * param src : clock source
2129 * param freq: clock frequency
2130 * Enable USB Device Full Speed clock.
2131 */
CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src,uint32_t freq)2132 bool CLOCK_EnableUsbfs0DeviceClock(clock_usbfs_src_t src, uint32_t freq)
2133 {
2134 bool ret = true;
2135
2136 CLOCK_DisableClock(kCLOCK_Usbd0);
2137
2138 if (kCLOCK_UsbfsSrcFro == src)
2139 {
2140 switch (freq)
2141 {
2142 case 96000000U:
2143 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2144 break;
2145
2146 default:
2147 ret = false;
2148 break;
2149 }
2150 /* Turn ON FRO HF */
2151 POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
2152 /* Enable FRO 96MHz output */
2153 ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
2154 /* Select FRO 96 or 48 MHz */
2155 CLOCK_AttachClk(kFRO_HF_to_USB0);
2156 }
2157 else
2158 {
2159 /*!< Configure XTAL32M */
2160 POWER_DisablePD(kPDRUNCFG_PD_XTALHF); /* Ensure XTAL32M is powered */
2161 POWER_DisablePD(kPDRUNCFG_PD_LDOXTALHF); /* Ensure XTAL32M is powered */
2162 (void)CLOCK_SetupExtClocking(16000000U); /* Enable clk_in clock */
2163 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clk_in from XTAL32M clock */
2164 ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system */
2165
2166 /*!< Set up PLL1 */
2167 POWER_DisablePD(kPDRUNCFG_PD_PLL1);
2168 CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
2169 const pll_setup_t pll1Setup = {
2170 .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
2171 .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
2172 .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
2173 .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
2174 .pllRate = 48000000U,
2175 .flags = PLL_SETUPFLAG_WAITLOCK};
2176 (void)CLOCK_SetPLL1Freq(&pll1Setup);
2177
2178 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2179 CLOCK_AttachClk(kPLL1_to_USB0);
2180 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2181 }
2182 CLOCK_EnableClock(kCLOCK_Usbd0);
2183
2184 return ret;
2185 }
2186
2187 /* Enable USB HOST FULL SPEED clock */
2188 /*! brief Enable USB HOST FS clock.
2189 * param src : clock source
2190 * param freq: clock frequency
2191 * Enable USB HOST Full Speed clock.
2192 */
CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src,uint32_t freq)2193 bool CLOCK_EnableUsbfs0HostClock(clock_usbfs_src_t src, uint32_t freq)
2194 {
2195 bool ret = true;
2196
2197 if (kCLOCK_UsbfsSrcFro == src)
2198 {
2199 switch (freq)
2200 {
2201 case 96000000U:
2202 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2203 break;
2204
2205 default:
2206 ret = false;
2207 break;
2208 }
2209 /* Turn ON FRO HF */
2210 POWER_DisablePD(kPDRUNCFG_PD_FRO192M);
2211 /* Enable FRO 96MHz output */
2212 ANACTRL->FRO192M_CTRL = ANACTRL->FRO192M_CTRL | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
2213 /* Select FRO 96 MHz */
2214 CLOCK_AttachClk(kFRO_HF_to_USB0);
2215 }
2216 else
2217 {
2218 /*!< Configure XTAL32M */
2219 POWER_DisablePD(kPDRUNCFG_PD_XTALHF); /* Ensure XTAL32M is powered */
2220 POWER_DisablePD(kPDRUNCFG_PD_LDOXTALHF); /* Ensure XTAL32M is powered */
2221 (void)CLOCK_SetupExtClocking(16000000U); /* Enable clk_in clock */
2222 SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /* Enable clk_in from XTAL32M clock */
2223 ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK; /* Enable clk_in to system */
2224
2225 /*!< Set up PLL1 */
2226 POWER_DisablePD(kPDRUNCFG_PD_PLL1);
2227 CLOCK_AttachClk(kEXT_CLK_to_PLL1); /*!< Switch PLL1CLKSEL to EXT_CLK */
2228 const pll_setup_t pll1Setup = {
2229 .pllctrl = SYSCON_PLL1CTRL_CLKEN_MASK | SYSCON_PLL1CTRL_SELI(19U) | SYSCON_PLL1CTRL_SELP(9U),
2230 .pllndec = SYSCON_PLL1NDEC_NDIV(1U),
2231 .pllpdec = SYSCON_PLL1PDEC_PDIV(5U),
2232 .pllmdec = SYSCON_PLL1MDEC_MDIV(30U),
2233 .pllRate = 48000000U,
2234 .flags = PLL_SETUPFLAG_WAITLOCK};
2235 (void)CLOCK_SetPLL1Freq(&pll1Setup);
2236
2237 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2238 CLOCK_AttachClk(kPLL1_to_USB0);
2239 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2240 }
2241 CLOCK_EnableClock(kCLOCK_Usbhmr0);
2242 CLOCK_EnableClock(kCLOCK_Usbhsl0);
2243
2244 return ret;
2245 }
2246
2247 /*! @brief Enable the OSTIMER 32k clock.
2248 * @return Nothing
2249 */
CLOCK_EnableOstimer32kClock(void)2250 void CLOCK_EnableOstimer32kClock(void)
2251 {
2252 PMC->OSEVENTTIMER |= PMC_OSEVENTTIMER_CLOCKENABLE_MASK;
2253 }
2254
2255 /* Sets board-specific trim values for High Frequency crystal oscillator */
2256 /*! brief Sets board-specific trim values for High Frequency crystal oscillator.
2257 * param pi32_hfXtalIecLoadpF_x100 : Load capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
2258 * becomes 120 param pi32_hfXtalPPcbParCappF_x100 : PCB +ve parasitic capacitance, pF x 100. For
2259 * example, 6pF becomes 600, 1.2pF becomes 120 param pi32_hfXtalNPcbParCappF_x100 : PCB -ve parasitic
2260 * capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF becomes 120 return none note Following
2261 * default Values can be used: pi32_32MfXtalIecLoadpF_x100 Load capacitance, pF x 100 : 600
2262 * pi32_32MfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100 : 20
2263 * pi32_32MfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100 : 40 Sets board-specific trim
2264 * values for High Frequency crystal oscillator.
2265 */
CLOCK_XtalHfCapabankTrim(int32_t pi32_hfXtalIecLoadpF_x100,int32_t pi32_hfXtalPPcbParCappF_x100,int32_t pi32_hfXtalNPcbParCappF_x100)2266 void CLOCK_XtalHfCapabankTrim(int32_t pi32_hfXtalIecLoadpF_x100,
2267 int32_t pi32_hfXtalPPcbParCappF_x100,
2268 int32_t pi32_hfXtalNPcbParCappF_x100)
2269 {
2270 uint32_t u32XOTrimValue;
2271 uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF, u8XOSlave;
2272 int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
2273 int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
2274 uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
2275 uint32_t u32RegVal;
2276
2277 /* Enable and set LDO, if not already done */
2278 CLOCK_SetXtalHfLdo();
2279 /* Get Cal values from Flash */
2280 u32XOTrimValue = GET_HFXO_TRIM();
2281 /* Check validity and apply */
2282 if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15) & 1UL)))
2283 {
2284 /* These fields are 7 bits, unsigned */
2285 u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1) & 0x7fUL);
2286 u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8) & 0x7fUL);
2287 u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16) & 0x7fUL);
2288 u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23) & 0x7fUL);
2289 /* This field is 1 bit */
2290 u8XOSlave = (uint8_t)((u32XOTrimValue >> 30) & 0x1UL);
2291 /* Linear fit coefficients calculation */
2292 iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
2293 ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
2294 iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
2295 ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
2296 }
2297 else
2298 {
2299 iaXin_x4 = 20; // gain in LSB/pF
2300 ibXin = -9; // offset in LSB
2301 iaXout_x4 = 20; // gain in LSB/pF
2302 ibXout = -13; // offset in LSB
2303 u8XOSlave = 0;
2304 }
2305 /* In & out load cap calculation with derating */
2306 iXOCapInpF_x100 =
2307 (int32_t)(2 * pi32_hfXtalIecLoadpF_x100 - pi32_hfXtalNPcbParCappF_x100 + 39 * (XO_SLAVE_EN - (int8_t)u8XOSlave) - 15);
2308 iXOCapOutpF_x100 = 2 * pi32_hfXtalIecLoadpF_x100 - pi32_hfXtalPPcbParCappF_x100 - 21;
2309 /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
2310 u8XOCapInCtrl = (uint8_t)(int32_t)((((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400));
2311 u8XOCapOutCtrl = (uint8_t)(int32_t)((((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400));
2312 /* Read register and clear fields to be written */
2313 u32RegVal = ANACTRL->XO32M_CTRL;
2314 u32RegVal &= ~(ANACTRL_XO32M_CTRL_OSC_CAP_IN_MASK | ANACTRL_XO32M_CTRL_OSC_CAP_OUT_MASK);
2315 /* Configuration of 32 MHz XO output buffers */
2316 #if (XO_SLAVE_EN == 0)
2317 u32RegVal &= ~(ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK);
2318 #else
2319 u32RegVal |= ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK;
2320 #endif
2321 /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
2322 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_IN_SHIFT;
2323 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_OUT_SHIFT;
2324 /* Write back to register */
2325 ANACTRL->XO32M_CTRL = u32RegVal;
2326 }
2327
2328 /* Sets board-specific trim values for 32kHz XTAL */
2329 /*! brief Sets board-specific trim values for 32kHz XTAL.
2330 * param pi32_32kfXtalIecLoadpF_x100 : Load capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF
2331 * becomes 120 param pi32_32kfXtalPPcbParCappF_x100 : PCB +ve parasitic capacitance, pF x 100. For
2332 * example, 6pF becomes 600, 1.2pF becomes 120 param pi32_32kfXtalNPcbParCappF_x100 : PCB -ve parasitic
2333 * capacitance, pF x 100. For example, 6pF becomes 600, 1.2pF becomes 120 return none note Following
2334 * default Values can be used: pi32_32kfXtalIecLoadpF_x100 Load capacitance, pF x 100 : 600
2335 * pi32_32kfXtalPPcbParCappF_x100 PCB +ve parasitic capacitance, pF x 100 : 40
2336 * pi32_32kfXtalNPcbParCappF_x100 PCB -ve parasitic capacitance, pF x 100 : 40 Sets board-specific trim
2337 * values for 32kHz XTAL.
2338 */
CLOCK_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,int32_t pi32_32kfXtalPPcbParCappF_x100,int32_t pi32_32kfXtalNPcbParCappF_x100)2339 void CLOCK_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,
2340 int32_t pi32_32kfXtalPPcbParCappF_x100,
2341 int32_t pi32_32kfXtalNPcbParCappF_x100)
2342 {
2343 uint32_t u32XOTrimValue;
2344 uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF;
2345 int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
2346 int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
2347 uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
2348 uint32_t u32RegVal;
2349 /* Get Cal values from Flash */
2350 u32XOTrimValue = GET_32KXO_TRIM();
2351 /* check validity and apply */
2352 if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15) & 1UL)))
2353 {
2354 /* These fields are 7 bits, unsigned */
2355 u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1) & 0x7fUL);
2356 u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8) & 0x7fUL);
2357 u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16) & 0x7fUL);
2358 u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23) & 0x7fUL);
2359 /* Linear fit coefficients calculation */
2360 iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
2361 ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
2362 iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
2363 ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
2364 }
2365 else
2366 {
2367 iaXin_x4 = 16; // gain in LSB/pF
2368 ibXin = 12; // offset in LSB
2369 iaXout_x4 = 16; // gain in LSB/pF
2370 ibXout = 11; // offset in LSB
2371 }
2372
2373 /* In & out load cap calculation with derating */
2374 iXOCapInpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalNPcbParCappF_x100 - 130;
2375 iXOCapOutpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalPPcbParCappF_x100 - 41;
2376
2377 /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
2378 u8XOCapInCtrl = (uint8_t)(int32_t)((((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400));
2379 u8XOCapOutCtrl = (uint8_t)(int32_t)((((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400));
2380
2381 /* Read register and clear fields to be written */
2382 u32RegVal = PMC->XTAL32K;
2383 u32RegVal &= ~(PMC_XTAL32K_CAPBANKIN_MASK | PMC_XTAL32K_CAPBANKOUT_MASK);
2384
2385 /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
2386 u32RegVal |= (uint32_t)(CLOCK_u8OscCapConvert(u8XOCapInCtrl, 23)) << PMC_XTAL32K_CAPBANKIN_SHIFT;
2387 u32RegVal |= (uint32_t)(CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 23)) << PMC_XTAL32K_CAPBANKOUT_SHIFT;
2388
2389 /* Write back to register */
2390 PMC->XTAL32K = u32RegVal;
2391 }
2392
2393 /* Enables and sets LDO for High Frequency crystal oscillator. */
2394 /*! brief Enables and sets LDO for High Frequency crystal oscillator.
2395 * return none
2396 * Sets Enables and sets LDO for High Frequency crystal oscillator.
2397 */
CLOCK_SetXtalHfLdo(void)2398 static void CLOCK_SetXtalHfLdo(void)
2399 {
2400 uint32_t temp;
2401 const uint32_t u32Mask =
2402 (ANACTRL_LDO_XO32M_VOUT_MASK | ANACTRL_LDO_XO32M_IBIAS_MASK | ANACTRL_LDO_XO32M_STABMODE_MASK);
2403
2404 const uint32_t u32Value =
2405 (ANACTRL_LDO_XO32M_VOUT(0x5) | ANACTRL_LDO_XO32M_IBIAS(0x2) | ANACTRL_LDO_XO32M_STABMODE(0x1));
2406
2407 /* Enable & set-up XTAL 32 MHz clock LDO */
2408 temp = ANACTRL->LDO_XO32M;
2409
2410 if ((temp & u32Mask) != u32Value)
2411 {
2412 temp &= ~u32Mask;
2413
2414 /*
2415 * Enable the XTAL32M LDO
2416 * Adjust the output voltage level, 0x5 for 1.1V
2417 * Adjust the biasing current, 0x2 value
2418 * Stability configuration, 0x1 default mode
2419 */
2420 temp |= u32Value;
2421
2422 ANACTRL->LDO_XO32M = temp;
2423
2424 /* Delay for LDO to be up */
2425 // CLOCK_uDelay(20);
2426 }
2427
2428 /* Enable LDO XO32M */
2429 PMC->PDRUNCFGCLR0 = PMC_PDRUNCFG0_PDEN_LDOXTALHF_MASK;
2430 }
2431
2432 /**
2433 * @brief
2434 * @param
2435 * @return
2436 */
CLOCK_u8OscCapConvert(uint8_t u8OscCap,uint8_t u8CapBankDiscontinuity)2437 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity)
2438 {
2439 /* Compensate for discontinuity in the capacitor banks */
2440 if (u8OscCap < 64U)
2441 {
2442 if (u8OscCap >= u8CapBankDiscontinuity)
2443 {
2444 u8OscCap -= u8CapBankDiscontinuity;
2445 }
2446 else
2447 {
2448 u8OscCap = 0;
2449 }
2450 }
2451 else
2452 {
2453 if (u8OscCap <= (127U - u8CapBankDiscontinuity))
2454 {
2455 u8OscCap += u8CapBankDiscontinuity;
2456 }
2457 else
2458 {
2459 u8OscCap = 127;
2460 }
2461 }
2462 return u8OscCap;
2463 }
2464
2465 /*!
2466 * brief Initialize the trim value for FRO HF .
2467 */
CLOCK_FroHfTrim(void)2468 void CLOCK_FroHfTrim(void)
2469 {
2470 volatile unsigned int Fro192mCtrlEfuse = 0;
2471 Fro192mCtrlEfuse = ANACTRL->FRO192M_CTRL;
2472 ANACTRL->ANALOG_CTRL_CFG = ANACTRL->ANALOG_CTRL_CFG | ANACTRL_ANALOG_CTRL_CFG_FRO192M_TRIM_SRC_MASK;
2473 ANACTRL->FRO192M_CTRL = ANACTRL_FRO192M_CTRL_WRTRIM_MASK | Fro192mCtrlEfuse;
2474 }
2475