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