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