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