1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016 - 2019 , NXP
4 * All rights reserved.
5 *
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 */
9
10 #include "fsl_clock.h"
11 #include "fsl_power.h"
12 /*******************************************************************************
13 * Definitions
14 ******************************************************************************/
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.clock"
18 #endif
19 #define NVALMAX (0x100U)
20 #define PVALMAX (0x20U)
21 #define MVALMAX (0x8000U)
22
23 #define USB_NVALMAX (0x4U)
24 #define USB_PVALMAX (0x8U)
25 #define USB_MVALMAX (0x100U)
26
27 #define PLL_MAX_N_DIV 0x100U
28 #define USB_PLL_MAX_N_DIV 0x100U
29
30 #define PLL_MDEC_VAL_P (0U) /*!< MDEC is in bits 16 downto 0 */
31 #define PLL_MDEC_VAL_M (0x1FFFFUL << PLL_MDEC_VAL_P) /*!< NDEC is in bits 9 downto 0 */
32 #define PLL_NDEC_VAL_P (0U) /*!< NDEC is in bits 9:0 */
33 #define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P)
34 #define PLL_PDEC_VAL_P (0U) /*!< PDEC is in bits 6:0 */
35 #define PLL_PDEC_VAL_M (0x7FUL << PLL_PDEC_VAL_P)
36
37 #define PLL_MIN_CCO_FREQ_MHZ (275000000U)
38 #define PLL_MAX_CCO_FREQ_MHZ (550000000U)
39 #define PLL_LOWER_IN_LIMIT (4000U) /*!< Minimum PLL input rate */
40 #define PLL_MIN_IN_SSMODE (2000000U)
41 #define PLL_MAX_IN_SSMODE (4000000U)
42
43 /*!< Middle of the range values for spread-spectrum */
44 #define PLL_SSCG_MF_FREQ_VALUE 4U
45 #define PLL_SSCG_MC_COMP_VALUE 2U
46 #define PLL_SSCG_MR_DEPTH_VALUE 4U
47 #define PLL_SSCG_DITHER_VALUE 0U
48
49 /*!< USB PLL CCO MAX AND MIN FREQ */
50 #define USB_PLL_MIN_CCO_FREQ_MHZ (156000000U)
51 #define USB_PLL_MAX_CCO_FREQ_MHZ (320000000U)
52 #define USB_PLL_LOWER_IN_LIMIT (1000000U) /*!< Minimum PLL input rate */
53
54 #define USB_PLL_MSEL_VAL_P (0U) /*!< MSEL is in bits 7 downto 0 */
55 #define USB_PLL_MSEL_VAL_M (0xFFU)
56 #define USB_PLL_PSEL_VAL_P (8U) /*!< PDEC is in bits 9:8 */
57 #define USB_PLL_PSEL_VAL_M (0x3U)
58 #define USB_PLL_NSEL_VAL_P (10U) /*!< NDEC is in bits 11:10 */
59 #define USB_PLL_NSEL_VAL_M (0x3U)
60
61 /*!< SYS PLL NDEC reg */
62 #define PLL_NDEC_VAL_SET(value) (((unsigned long)(value) << PLL_NDEC_VAL_P) & PLL_NDEC_VAL_M)
63 /*!< SYS PLL PDEC reg */
64 #define PLL_PDEC_VAL_SET(value) (((unsigned long)(value) << PLL_PDEC_VAL_P) & PLL_PDEC_VAL_M)
65 /*!< SYS PLL MDEC reg */
66 #define PLL_MDEC_VAL_SET(value) (((unsigned long)(value) << PLL_MDEC_VAL_P) & PLL_MDEC_VAL_M)
67
68 /*!< SYS PLL NSEL reg */
69 #define USB_PLL_NSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_NSEL_VAL_M) << USB_PLL_NSEL_VAL_P)
70 /*!< SYS PLL PSEL reg */
71 #define USB_PLL_PSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_PSEL_VAL_M) << USB_PLL_PSEL_VAL_P)
72 /*!< SYS PLL MSEL reg */
73 #define USB_PLL_MSEL_VAL_SET(value) (((unsigned long)(value)&USB_PLL_MSEL_VAL_M) << USB_PLL_MSEL_VAL_P)
74
75 /*!< FRAC control */
76 #define AUDIO_PLL_FRACT_MD_P (0U)
77 #define AUDIO_PLL_FRACT_MD_INT_P (15U)
78 #define AUDIO_PLL_FRACT_MD_M (0x7FFFUL << AUDIO_PLL_FRACT_MD_P)
79 #define AUDIO_PLL_FRACT_MD_INT_M (0x7FUL << AUDIO_PLL_FRACT_MD_INT_P)
80
81 #define AUDIO_PLL_MD_FRACT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_P) & PLL_FRAC_MD_FRACT_M)
82 #define AUDIO_PLL_MD_INT_SET(value) (((unsigned long)(value) << AUDIO_PLL_FRACT_MD_INT_P) & AUDIO_PLL_FRACT_MD_INT_M)
83
84 /* Saved value of PLL output rate, computed whenever needed to save run-time
85 computation on each call to retrive the PLL rate. */
86 static uint32_t s_Pll_Freq;
87 static uint32_t s_Usb_Pll_Freq;
88 static uint32_t s_Audio_Pll_Freq;
89
90 /** External clock rate on the CLKIN pin in Hz. If not used,
91 set this to 0. Otherwise, set it to the exact rate in Hz this pin is
92 being driven at. */
93 static const uint32_t s_I2S_Mclk_Freq = 0U;
94 static const uint32_t s_Ext_Clk_Freq = 12000000U;
95 static const uint32_t s_Lcd_Clk_In_Freq = 0U;
96
97 /*******************************************************************************
98 * Variables
99 ******************************************************************************/
100
101 /*******************************************************************************
102 * Prototypes
103 ******************************************************************************/
104 /* Find encoded NDEC value for raw N value, max N = NVALMAX */
105 static uint32_t pllEncodeN(uint32_t N);
106 /* Find decoded N value for raw NDEC value */
107 static uint32_t pllDecodeN(uint32_t NDEC);
108 /* Find encoded PDEC value for raw P value, max P = PVALMAX */
109 static uint32_t pllEncodeP(uint32_t P);
110 /* Find decoded P value for raw PDEC value */
111 static uint32_t pllDecodeP(uint32_t PDEC);
112 /* Find encoded MDEC value for raw M value, max M = MVALMAX */
113 static uint32_t pllEncodeM(uint32_t M);
114 /* Find decoded M value for raw MDEC value */
115 static uint32_t pllDecodeM(uint32_t MDEC);
116 /* Find SELP, SELI, and SELR values for raw M value, max M = MVALMAX */
117 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR);
118 /* Get predivider (N) from PLL NDEC setting */
119 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg);
120 /* Get postdivider (P) from PLL PDEC setting */
121 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg);
122 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
123 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg);
124 /* Convert the binary to fractional part */
125 static double Binary2Fractional(uint32_t binaryPart);
126 /* Get the greatest common divisor */
127 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n);
128 /* Set PLL output based on desired output rate */
129 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup);
130
131 /* Update local PLL rate variable */
132 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup);
133 static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup);
134
135 static const uint8_t wdtFreqLookup[32] = {0, 8, 12, 15, 18, 20, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41,
136 42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 59, 60, 61};
137 /*******************************************************************************
138 * Code
139 ******************************************************************************/
140
141 /* Clock Selection for IP */
142 /**
143 * brief Configure the clock selection muxes.
144 * param connection : Clock to be configured.
145 * return Nothing
146 */
CLOCK_AttachClk(clock_attach_id_t connection)147 void CLOCK_AttachClk(clock_attach_id_t connection)
148 {
149 uint8_t mux;
150 uint8_t sel;
151 uint16_t item;
152 uint32_t tmp32 = (uint32_t)connection;
153 uint32_t i;
154 volatile uint32_t *pClkSel;
155
156 pClkSel = &(SYSCON->MAINCLKSELA);
157
158 if (kNONE_to_NONE != connection)
159 {
160 for (i = 0U; i < 2U; i++)
161 {
162 if (tmp32 == 0U)
163 {
164 break;
165 }
166 item = (uint16_t)GET_ID_ITEM(tmp32);
167 if (0U != item)
168 {
169 mux = GET_ID_ITEM_MUX(item);
170 sel = GET_ID_ITEM_SEL(item);
171 if (mux == CM_ASYNCAPB)
172 {
173 SYSCON->ASYNCAPBCTRL = SYSCON_ASYNCAPBCTRL_ENABLE(1);
174 ASYNC_SYSCON->ASYNCAPBCLKSELA = sel;
175 }
176 else
177 {
178 ((volatile uint32_t *)pClkSel)[mux] = sel;
179 }
180 }
181 tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */
182 }
183 }
184 }
185
186 /* Return the actual clock attach id */
187 /**
188 * brief Get the actual clock attach id.
189 * This fuction uses the offset in input attach id, then it reads the actual source value in
190 * the register and combine the offset to obtain an actual attach id.
191 * param attachId : Clock attach id to get.
192 * return Clock source value.
193 */
CLOCK_GetClockAttachId(clock_attach_id_t attachId)194 clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId)
195 {
196 uint8_t mux;
197 uint32_t actualSel;
198 uint32_t tmp32 = (uint32_t)attachId;
199 uint32_t i;
200 uint32_t actualAttachId = 0U;
201 uint32_t selector = GET_ID_SELECTOR(tmp32);
202 volatile uint32_t *pClkSel;
203
204 pClkSel = &(SYSCON->MAINCLKSELA);
205
206 if (kNONE_to_NONE == attachId)
207 {
208 return kNONE_to_NONE;
209 }
210
211 for (i = 0U; i < 2U; i++)
212 {
213 mux = GET_ID_ITEM_MUX(tmp32);
214 if (0U != tmp32)
215 {
216 if (mux == CM_ASYNCAPB)
217 {
218 actualSel = ASYNC_SYSCON->ASYNCAPBCLKSELA;
219 }
220 else
221 {
222 actualSel = ((volatile uint32_t *)pClkSel)[mux];
223 }
224
225 /* Consider the combination of two registers */
226 actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i);
227 }
228 tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */
229 }
230
231 actualAttachId |= selector;
232
233 return (clock_attach_id_t)actualAttachId;
234 }
235
236 /* Set IP Clock Divider */
237 /**
238 * brief Setup peripheral clock dividers.
239 * param div_name : Clock divider name
240 * param divided_by_value: Value to be divided
241 * param reset : Whether to reset the divider counter.
242 * return Nothing
243 */
CLOCK_SetClkDiv(clock_div_name_t div_name,uint32_t divided_by_value,bool reset)244 void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
245 {
246 volatile uint32_t *pClkDiv;
247
248 pClkDiv = &(SYSCON->SYSTICKCLKDIV);
249 if (reset)
250 {
251 ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 29U;
252 }
253 if (divided_by_value == 0U) /*!< halt */
254 {
255 ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = 1UL << 30U;
256 }
257 else
258 {
259 ((volatile uint32_t *)pClkDiv)[(uint32_t)div_name] = (divided_by_value - 1U);
260 }
261 }
262
263 /* Set FRO Clocking */
264 /**
265 * brief Initialize the Core clock to given frequency (12, 48 or 96 MHz).
266 * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is
267 * enabled.
268 * param iFreq : Desired frequency (must be one of #CLK_FRO_12MHZ or #CLK_FRO_48MHZ or #CLK_FRO_96MHZ)
269 * return returns success or fail status.
270 */
CLOCK_SetupFROClocking(uint32_t iFreq)271 status_t CLOCK_SetupFROClocking(uint32_t iFreq)
272 {
273 uint32_t usb_adj;
274 if ((iFreq != 12000000U) && (iFreq != 48000000U) && (iFreq != 96000000U))
275 {
276 return kStatus_Fail;
277 }
278 /* Power up the FRO and set this as the base clock */
279 POWER_DisablePD(kPDRUNCFG_PD_FRO_EN);
280 /* back up the value of whether USB adj is selected, in which case we will have a value of 1 else 0 */
281 usb_adj = ((SYSCON->FROCTRL) & SYSCON_FROCTRL_USBCLKADJ_MASK) >> SYSCON_FROCTRL_USBCLKADJ_SHIFT;
282
283 if (iFreq > 12000000U)
284 {
285 /* Call ROM API to set FRO */
286 set_fro_frequency(iFreq);
287 if (iFreq == 96000000U)
288 {
289 SYSCON->FROCTRL |= (SYSCON_FROCTRL_SEL(1) | SYSCON_FROCTRL_WRTRIM(1) | SYSCON_FROCTRL_USBCLKADJ(usb_adj) |
290 SYSCON_FROCTRL_HSPDCLK(1));
291 }
292 else
293 {
294 SYSCON->FROCTRL |= (SYSCON_FROCTRL_SEL(0) | SYSCON_FROCTRL_WRTRIM(1) | SYSCON_FROCTRL_USBCLKADJ(usb_adj) |
295 SYSCON_FROCTRL_HSPDCLK(1));
296 }
297 }
298 else
299 {
300 SYSCON->FROCTRL &= ~SYSCON_FROCTRL_HSPDCLK(1);
301 }
302
303 return kStatus_Success;
304 }
305
306 /* Get CLOCK OUT Clk */
307 /*! brief Return Frequency of ClockOut
308 * return Frequency of ClockOut
309 */
CLOCK_GetClockOutClkFreq(void)310 uint32_t CLOCK_GetClockOutClkFreq(void)
311 {
312 uint32_t freq = 0U;
313
314 switch (SYSCON->CLKOUTSELA)
315 {
316 case 0U:
317 freq = CLOCK_GetCoreSysClkFreq();
318 break;
319
320 case 1U:
321 freq = CLOCK_GetExtClkFreq();
322 break;
323
324 case 2U:
325 freq = CLOCK_GetWdtOscFreq();
326 break;
327
328 case 3U:
329 freq = CLOCK_GetFroHfFreq();
330 break;
331
332 case 4U:
333 freq = CLOCK_GetPllOutFreq();
334 break;
335
336 case 5U:
337 freq = CLOCK_GetUsbPllOutFreq();
338 break;
339
340 case 6U:
341 freq = CLOCK_GetAudioPllOutFreq();
342 break;
343
344 case 7U:
345 freq = CLOCK_GetOsc32KFreq();
346 break;
347
348 default:
349 freq = 0U;
350 break;
351 }
352 return freq / ((SYSCON->CLKOUTDIV & 0xffU) + 1U);
353 }
354
355 /* Get SPIFI Clk */
356 /*! brief Return Frequency of Spifi Clock
357 * return Frequency of Spifi.
358 */
CLOCK_GetSpifiClkFreq(void)359 uint32_t CLOCK_GetSpifiClkFreq(void)
360 {
361 uint32_t freq = 0U;
362
363 switch (SYSCON->SPIFICLKSEL)
364 {
365 case 0U:
366 freq = CLOCK_GetCoreSysClkFreq();
367 break;
368 case 1U:
369 freq = CLOCK_GetPllOutFreq();
370 break;
371 case 2U:
372 freq = CLOCK_GetUsbPllOutFreq();
373 break;
374 case 3U:
375 freq = CLOCK_GetFroHfFreq();
376 break;
377 case 4U:
378 freq = CLOCK_GetAudioPllOutFreq();
379 break;
380 case 7U:
381 freq = 0U;
382 break;
383 default:
384 freq = 0U;
385 break;
386 }
387
388 return freq / ((SYSCON->SPIFICLKDIV & 0xffU) + 1U);
389 }
390
391 /* Get ADC Clk */
392 /*! brief Return Frequency of Adc Clock
393 * return Frequency of Adc Clock.
394 */
CLOCK_GetAdcClkFreq(void)395 uint32_t CLOCK_GetAdcClkFreq(void)
396 {
397 uint32_t freq = 0U;
398
399 switch (SYSCON->ADCCLKSEL)
400 {
401 case 0U:
402 freq = CLOCK_GetFroHfFreq();
403 break;
404 case 1U:
405 freq = CLOCK_GetPllOutFreq();
406 break;
407 case 2U:
408 freq = CLOCK_GetUsbPllOutFreq();
409 break;
410 case 3U:
411 freq = CLOCK_GetAudioPllOutFreq();
412 break;
413 case 7U:
414 freq = 0U;
415 break;
416 default:
417 freq = 0U;
418 break;
419 }
420
421 return freq / ((SYSCON->ADCCLKDIV & 0xffU) + 1U);
422 }
423
424 /* Get USB0 Clk */
425 /*! brief Return Frequency of Usb0 Clock
426 * return Frequency of Usb0 Clock.
427 */
CLOCK_GetUsb0ClkFreq(void)428 uint32_t CLOCK_GetUsb0ClkFreq(void)
429 {
430 uint32_t freq = 0U;
431
432 switch (SYSCON->USB0CLKSEL)
433 {
434 case 0U:
435 freq = CLOCK_GetFroHfFreq();
436 break;
437 case 1U:
438 freq = CLOCK_GetPllOutFreq();
439 break;
440 case 2U:
441 freq = CLOCK_GetUsbPllOutFreq();
442 break;
443 case 7U:
444 freq = 0U;
445 break;
446
447 default:
448 freq = 0U;
449 break;
450 }
451
452 return freq / ((SYSCON->USB0CLKDIV & 0xffU) + 1U);
453 }
454
455 /* Get USB1 Clk */
456 /*! brief Return Frequency of Usb1 Clock
457 * return Frequency of Usb1 Clock.
458 */
CLOCK_GetUsb1ClkFreq(void)459 uint32_t CLOCK_GetUsb1ClkFreq(void)
460 {
461 uint32_t freq = 0U;
462
463 switch (SYSCON->USB1CLKSEL)
464 {
465 case 0U:
466 freq = CLOCK_GetCoreSysClkFreq();
467 break;
468 case 1U:
469 freq = CLOCK_GetPllOutFreq();
470 break;
471 case 2U:
472 freq = CLOCK_GetUsbPllOutFreq();
473 break;
474 case 7U:
475 freq = 0U;
476 break;
477
478 default:
479 freq = 0U;
480 break;
481 }
482
483 return freq / ((SYSCON->USB1CLKDIV & 0xffU) + 1U);
484 }
485
486 /* Get MCLK Clk */
487 /*! brief Return Frequency of MClk Clock
488 * return Frequency of MClk Clock.
489 */
CLOCK_GetMclkClkFreq(void)490 uint32_t CLOCK_GetMclkClkFreq(void)
491 {
492 uint32_t freq = 0U;
493
494 switch (SYSCON->MCLKCLKSEL)
495 {
496 case 0U:
497 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFCLKDIV & 0xffu) + 1U);
498 break;
499 case 1U:
500 freq = CLOCK_GetAudioPllOutFreq();
501 break;
502 case 7U:
503 freq = 0U;
504 break;
505
506 default:
507 freq = 0U;
508 break;
509 }
510
511 return freq / ((SYSCON->MCLKDIV & 0xffU) + 1U);
512 }
513
514 /* Get SCTIMER Clk */
515 /*! brief Return Frequency of SCTimer Clock
516 * return Frequency of SCTimer Clock.
517 */
CLOCK_GetSctClkFreq(void)518 uint32_t CLOCK_GetSctClkFreq(void)
519 {
520 uint32_t freq = 0U;
521
522 switch (SYSCON->SCTCLKSEL)
523 {
524 case 0U:
525 freq = CLOCK_GetCoreSysClkFreq();
526 break;
527 case 1U:
528 freq = CLOCK_GetPllOutFreq();
529 break;
530 case 2U:
531 freq = CLOCK_GetFroHfFreq();
532 break;
533 case 3U:
534 freq = CLOCK_GetAudioPllOutFreq();
535 break;
536 case 7U:
537 freq = 0U;
538 break;
539
540 default:
541 freq = 0U;
542 break;
543 }
544
545 return freq / ((SYSCON->SCTCLKDIV & 0xffU) + 1U);
546 }
547
548 /* Get SDIO Clk */
549 /*! brief Return Frequency of SDIO Clock
550 * return Frequency of SDIO Clock.
551 */
CLOCK_GetSdioClkFreq(void)552 uint32_t CLOCK_GetSdioClkFreq(void)
553 {
554 uint32_t freq = 0U;
555
556 switch (SYSCON->SDIOCLKSEL)
557 {
558 case 0U:
559 freq = CLOCK_GetCoreSysClkFreq();
560 break;
561 case 1U:
562 freq = CLOCK_GetPllOutFreq();
563 break;
564 case 2U:
565 freq = CLOCK_GetUsbPllOutFreq();
566 break;
567 case 3U:
568 freq = CLOCK_GetFroHfFreq();
569 break;
570 case 4U:
571 freq = CLOCK_GetAudioPllOutFreq();
572 break;
573 case 7U:
574 freq = 0U;
575 break;
576 default:
577 freq = 0U;
578 break;
579 }
580
581 return freq / ((SYSCON->SDIOCLKDIV & 0xffU) + 1U);
582 }
583
584 /* Get LCD Clk */
585 /*! brief Return Frequency of LCD Clock
586 * return Frequency of LCD Clock.
587 */
CLOCK_GetLcdClkFreq(void)588 uint32_t CLOCK_GetLcdClkFreq(void)
589 {
590 uint32_t freq = 0U;
591
592 switch (SYSCON->LCDCLKSEL)
593 {
594 case 0U:
595 freq = CLOCK_GetCoreSysClkFreq();
596 break;
597 case 1U:
598 freq = CLOCK_GetLcdClkIn();
599 break;
600 case 2U:
601 freq = CLOCK_GetFroHfFreq();
602 break;
603 case 3U:
604 freq = 0U;
605 break;
606
607 default:
608 freq = 0U;
609 break;
610 }
611
612 return freq / ((SYSCON->LCDCLKDIV & 0xffU) + 1U);
613 }
614
615 /* Get LCD CLK IN Clk */
616 /*! brief Return Frequency of LCD CLKIN Clock
617 * return Frequency of LCD CLKIN Clock.
618 */
CLOCK_GetLcdClkIn(void)619 uint32_t CLOCK_GetLcdClkIn(void)
620 {
621 return s_Lcd_Clk_In_Freq;
622 }
623
624 /* Get FRO 12M Clk */
625 /*! brief Return Frequency of FRO 12MHz
626 * return Frequency of FRO 12MHz
627 */
CLOCK_GetFro12MFreq(void)628 uint32_t CLOCK_GetFro12MFreq(void)
629 {
630 return (0U != (SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK)) ? 0U : 12000000U;
631 }
632
633 /* Get EXT OSC Clk */
634 /*! brief Return Frequency of External Clock
635 * return Frequency of External Clock. If no external clock is used returns 0.
636 */
CLOCK_GetExtClkFreq(void)637 uint32_t CLOCK_GetExtClkFreq(void)
638 {
639 return s_Ext_Clk_Freq;
640 }
641
642 /* Get WATCH DOG Clk */
643 /*! brief Return Frequency of Watchdog Oscillator
644 * return Frequency of Watchdog Oscillator
645 */
CLOCK_GetWdtOscFreq(void)646 uint32_t CLOCK_GetWdtOscFreq(void)
647 {
648 uint8_t freq_sel, div_sel;
649 if (0U != (SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_WDT_OSC_MASK))
650 {
651 return 0U;
652 }
653 else
654 {
655 div_sel = (uint8_t)(((SYSCON->WDTOSCCTRL & 0x1fU) + 1U) << 1U);
656 freq_sel =
657 wdtFreqLookup[((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_FREQSEL_MASK) >> SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)];
658 return ((uint32_t)freq_sel * 50000U) / ((uint32_t)div_sel);
659 }
660 }
661
662 /* Get HF FRO Clk */
663 /*! brief Return Frequency of High-Freq output of FRO
664 * return Frequency of High-Freq output of FRO
665 */
CLOCK_GetFroHfFreq(void)666 uint32_t CLOCK_GetFroHfFreq(void)
667 {
668 uint32_t freq;
669
670 if ((0U != (SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK)) ||
671 (0U == (SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK)))
672 {
673 freq = 0U;
674 }
675 else
676 {
677 if (0U != (SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK))
678 {
679 freq = 96000000U;
680 }
681 else
682 {
683 freq = 48000000U;
684 }
685 }
686
687 return freq;
688 }
689
690 /* Get SYSTEM PLL Clk */
691 /*! brief Return Frequency of PLL
692 * return Frequency of PLL
693 */
CLOCK_GetPllOutFreq(void)694 uint32_t CLOCK_GetPllOutFreq(void)
695 {
696 return s_Pll_Freq;
697 }
698
699 /* Get AUDIO PLL Clk */
700 /*! brief Return Frequency of AUDIO PLL
701 * return Frequency of PLL
702 */
CLOCK_GetAudioPllOutFreq(void)703 uint32_t CLOCK_GetAudioPllOutFreq(void)
704 {
705 return s_Audio_Pll_Freq;
706 }
707
708 /* Get USB PLL Clk */
709 /*! brief Return Frequency of USB PLL
710 * return Frequency of PLL
711 */
CLOCK_GetUsbPllOutFreq(void)712 uint32_t CLOCK_GetUsbPllOutFreq(void)
713 {
714 return s_Usb_Pll_Freq;
715 }
716
717 /* Get RTC OSC Clk */
718 /*! brief Return Frequency of 32kHz osc
719 * return Frequency of 32kHz osc
720 */
CLOCK_GetOsc32KFreq(void)721 uint32_t CLOCK_GetOsc32KFreq(void)
722 {
723 return CLK_RTC_32K_CLK; /* Needs to be corrected to check that RTC Clock is enabled */
724 }
725
726 /* Get MAIN Clk */
727 /*! brief Return Frequency of Core System
728 * return Frequency of Core System
729 */
CLOCK_GetCoreSysClkFreq(void)730 uint32_t CLOCK_GetCoreSysClkFreq(void)
731 {
732 uint32_t freq = 0U;
733
734 switch (SYSCON->MAINCLKSELB)
735 {
736 case 0U:
737 if (SYSCON->MAINCLKSELA == 0U)
738 {
739 freq = CLOCK_GetFro12MFreq();
740 }
741 else if (SYSCON->MAINCLKSELA == 1U)
742 {
743 freq = CLOCK_GetExtClkFreq();
744 }
745 else if (SYSCON->MAINCLKSELA == 2U)
746 {
747 freq = CLOCK_GetWdtOscFreq();
748 }
749 else if (SYSCON->MAINCLKSELA == 3U)
750 {
751 freq = CLOCK_GetFroHfFreq();
752 }
753 else
754 {
755 /* For MISRA C-2012 Rule 15.7 */
756 }
757 break;
758 case 2U:
759 freq = CLOCK_GetPllOutFreq();
760 break;
761
762 case 3U:
763 freq = CLOCK_GetOsc32KFreq();
764 break;
765
766 default:
767 freq = 0U;
768 break;
769 }
770
771 return freq;
772 }
773
774 /* Get I2S MCLK Clk */
775 /*! brief Return Frequency of I2S MCLK Clock
776 * return Frequency of I2S MCLK Clock
777 */
CLOCK_GetI2SMClkFreq(void)778 uint32_t CLOCK_GetI2SMClkFreq(void)
779 {
780 return s_I2S_Mclk_Freq;
781 }
782
783 /* Get ASYNC APB Clk */
784 /*! brief Return Frequency of Asynchronous APB Clock
785 * return Frequency of Asynchronous APB Clock Clock
786 */
CLOCK_GetAsyncApbClkFreq(void)787 uint32_t CLOCK_GetAsyncApbClkFreq(void)
788 {
789 async_clock_src_t clkSrc;
790 uint32_t clkRate;
791
792 clkSrc = CLOCK_GetAsyncApbClkSrc();
793
794 switch (clkSrc)
795 {
796 case kCLOCK_AsyncMainClk:
797 clkRate = CLOCK_GetCoreSysClkFreq();
798 break;
799 case kCLOCK_AsyncFro12Mhz:
800 clkRate = CLK_FRO_12MHZ;
801 break;
802 default:
803 clkRate = 0U;
804 break;
805 }
806
807 return clkRate;
808 }
809
810 /* Get MCAN Clk */
811 /*! brief Return Frequency of MCAN Clock
812 * param MCanSel : 0U: MCAN0; 1U: MCAN1
813 * return Frequency of MCAN Clock
814 */
CLOCK_GetMCanClkFreq(uint32_t MCanSel)815 uint32_t CLOCK_GetMCanClkFreq(uint32_t MCanSel)
816 {
817 uint32_t freq = 0U;
818 switch (MCanSel)
819 {
820 case 0U:
821 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN0CLKDIV & 0xffU) + 1U);
822 break;
823 case 1U:
824 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->CAN1CLKDIV & 0xffU) + 1U);
825 break;
826
827 default:
828 freq = 0U;
829 break;
830 }
831
832 return freq;
833 }
834
835 /* Get FLEXCOMM Clk */
836 /*! brief Return Frequency of Flexcomm functional Clock
837 * return Frequency of Flexcomm functional Clock
838 */
CLOCK_GetFlexCommClkFreq(uint32_t id)839 uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id)
840 {
841 uint32_t freq = 0U;
842
843 switch (SYSCON->FCLKSEL[id])
844 {
845 case 0U:
846 freq = CLOCK_GetFro12MFreq();
847 break;
848 case 1U:
849 freq = CLOCK_GetFroHfFreq() / ((SYSCON->FROHFCLKDIV & SYSCON_FROHFCLKDIV_DIV_MASK) + 1U);
850 break;
851 case 2U:
852 freq = CLOCK_GetPllOutFreq();
853 break;
854 case 3U:
855 freq = CLOCK_GetI2SMClkFreq();
856 break;
857 case 4U:
858 freq = CLOCK_GetFrgClkFreq();
859 break;
860
861 default:
862 freq = 0U;
863 break;
864 }
865
866 return freq;
867 }
868
869 /* Get FRG Clk */
CLOCK_GetFRGInputClock(void)870 uint32_t CLOCK_GetFRGInputClock(void)
871 {
872 uint32_t freq = 0U;
873
874 switch (SYSCON->FRGCLKSEL)
875 {
876 case 0U:
877 freq = CLOCK_GetCoreSysClkFreq();
878 break;
879 case 1U:
880 freq = CLOCK_GetPllOutFreq();
881 break;
882 case 2U:
883 freq = CLOCK_GetFro12MFreq();
884 break;
885 case 3U:
886 freq = CLOCK_GetFroHfFreq();
887 break;
888
889 default:
890 freq = 0U;
891 break;
892 }
893
894 return freq;
895 }
896
897 /* Get FRG Clk */
898 /*! brief Return Frequency of frg
899 * return Frequency of FRG
900 */
CLOCK_GetFrgClkFreq(void)901 uint32_t CLOCK_GetFrgClkFreq(void)
902 {
903 uint32_t freq = 0U;
904
905 if ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK)
906 {
907 freq = (uint32_t)(((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1U)) /
908 ((SYSCON_FRGCTRL_DIV_MASK + 1U) +
909 ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)));
910 }
911 else
912 {
913 freq = 0U;
914 }
915
916 return freq;
917 }
918
919 /* Get DMIC Clk */
920 /*! brief Return Frequency of dmic
921 * return Frequency of DMIC
922 */
CLOCK_GetDmicClkFreq(void)923 uint32_t CLOCK_GetDmicClkFreq(void)
924 {
925 uint32_t freq = 0U;
926
927 switch (SYSCON->DMICCLKSEL)
928 {
929 case 0U:
930 freq = CLOCK_GetFro12MFreq();
931 break;
932 case 1U:
933 freq = CLOCK_GetFroHfFreq();
934 break;
935 case 2U:
936 freq = CLOCK_GetPllOutFreq();
937 break;
938 case 3U:
939 freq = CLOCK_GetI2SMClkFreq();
940 break;
941 case 4U:
942 freq = CLOCK_GetCoreSysClkFreq();
943 break;
944 case 5U:
945 freq = CLOCK_GetWdtOscFreq();
946 break;
947 default:
948 freq = 0U;
949 break;
950 }
951
952 return freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U);
953 }
954
955 /* Set FRG Clk */
CLOCK_SetFRGClock(uint32_t freq)956 uint32_t CLOCK_SetFRGClock(uint32_t freq)
957 {
958 assert(0U != freq);
959
960 uint32_t input = CLOCK_GetFRGInputClock();
961 uint32_t mul;
962 uint32_t ret;
963
964 if ((freq > 48000000U) || (freq > input) || (input / freq >= 2U))
965 {
966 /* FRG output frequency should be less than equal to 48MHz */
967 ret = 0U;
968 }
969 else
970 {
971 mul = (uint32_t)((((uint64_t)input - freq) * 256ULL) / ((uint64_t)freq));
972 SYSCON->FRGCTRL = (mul << SYSCON_FRGCTRL_MULT_SHIFT) | SYSCON_FRGCTRL_DIV_MASK;
973 ret = 1U;
974 }
975
976 return ret;
977 }
978
979 /* Set IP Clk */
980 /*! brief Return Frequency of selected clock
981 * return Frequency of selected clock
982 */
CLOCK_GetFreq(clock_name_t clockName)983 uint32_t CLOCK_GetFreq(clock_name_t clockName)
984 {
985 uint32_t freq;
986 switch (clockName)
987 {
988 case kCLOCK_CoreSysClk:
989 freq = CLOCK_GetCoreSysClkFreq();
990 break;
991 case kCLOCK_BusClk:
992 freq = CLOCK_GetCoreSysClkFreq() / ((SYSCON->AHBCLKDIV & 0xffU) + 1U);
993 break;
994 case kCLOCK_ClockOut:
995 freq = CLOCK_GetClockOutClkFreq();
996 break;
997 case kCLOCK_Mclk:
998 freq = CLOCK_GetMclkClkFreq();
999 break;
1000 case kCLOCK_FroHf:
1001 freq = CLOCK_GetFroHfFreq();
1002 break;
1003 case kCLOCK_Fro12M:
1004 freq = CLOCK_GetFro12MFreq();
1005 break;
1006 case kCLOCK_ExtClk:
1007 freq = CLOCK_GetExtClkFreq();
1008 break;
1009 case kCLOCK_PllOut:
1010 freq = CLOCK_GetPllOutFreq();
1011 break;
1012 case kCLOCK_WdtOsc:
1013 freq = CLOCK_GetWdtOscFreq();
1014 break;
1015 case kCLOCK_Frg:
1016 freq = CLOCK_GetFrgClkFreq();
1017 break;
1018 case kCLOCK_AsyncApbClk:
1019 freq = CLOCK_GetAsyncApbClkFreq();
1020 break;
1021 case kCLOCK_FlexI2S:
1022 freq = CLOCK_GetI2SMClkFreq();
1023 break;
1024 default:
1025 freq = 0U;
1026 break;
1027 }
1028
1029 return freq;
1030 }
1031
1032 /* Set the FLASH wait states for the passed frequency */
1033 /**
1034 * brief Set the flash wait states for the input freuqency.
1035 * param iFreq : Input frequency
1036 * return Nothing
1037 */
CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)1038 void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq)
1039 {
1040 if (iFreq <= 12000000U)
1041 {
1042 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash1Cycle);
1043 }
1044 else if (iFreq <= 24000000U)
1045 {
1046 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash2Cycle);
1047 }
1048 else if (iFreq <= 36000000U)
1049 {
1050 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash3Cycle);
1051 }
1052 else if (iFreq <= 60000000U)
1053 {
1054 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash4Cycle);
1055 }
1056 else if (iFreq <= 96000000U)
1057 {
1058 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash5Cycle);
1059 }
1060 else if (iFreq <= 120000000U)
1061 {
1062 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash6Cycle);
1063 }
1064 else if (iFreq <= 144000000U)
1065 {
1066 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash7Cycle);
1067 }
1068 else if (iFreq <= 168000000U)
1069 {
1070 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash8Cycle);
1071 }
1072 else
1073 {
1074 CLOCK_SetFLASHAccessCycles(kCLOCK_Flash9Cycle);
1075 }
1076 }
1077
1078 /* Find encoded NDEC value for raw N value, max N = NVALMAX */
pllEncodeN(uint32_t N)1079 static uint32_t pllEncodeN(uint32_t N)
1080 {
1081 uint32_t x, i;
1082
1083 /* Find NDec */
1084 switch (N)
1085 {
1086 case 0U:
1087 x = 0x3FFU;
1088 break;
1089
1090 case 1U:
1091 x = 0x302U;
1092 break;
1093
1094 case 2U:
1095 x = 0x202U;
1096 break;
1097
1098 default:
1099 x = 0x080U;
1100 for (i = N; i <= NVALMAX; i++)
1101 {
1102 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
1103 }
1104 break;
1105 }
1106
1107 return x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P);
1108 }
1109
1110 /* Find decoded N value for raw NDEC value */
pllDecodeN(uint32_t NDEC)1111 static uint32_t pllDecodeN(uint32_t NDEC)
1112 {
1113 uint32_t n, x, i;
1114
1115 /* Find NDec */
1116 switch (NDEC)
1117 {
1118 case 0x3FFU:
1119 n = 0U;
1120 break;
1121
1122 case 0x302U:
1123 n = 1U;
1124 break;
1125
1126 case 0x202U:
1127 n = 2U;
1128 break;
1129
1130 default:
1131 x = 0x080U;
1132 n = 0xFFFFFFFFU;
1133 for (i = NVALMAX; (i >= 3U); i--)
1134 {
1135 x = (((x ^ (x >> 2U) ^ (x >> 3U) ^ (x >> 4U)) & 1U) << 7U) | ((x >> 1U) & 0x7FU);
1136 if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC)
1137 {
1138 /* Decoded value of NDEC */
1139 n = i;
1140 break;
1141 }
1142 }
1143 break;
1144 }
1145
1146 return n;
1147 }
1148
1149 /* Find encoded PDEC value for raw P value, max P = PVALMAX */
pllEncodeP(uint32_t P)1150 static uint32_t pllEncodeP(uint32_t P)
1151 {
1152 uint32_t x, i;
1153
1154 /* Find PDec */
1155 switch (P)
1156 {
1157 case 0U:
1158 x = 0x7FU;
1159 break;
1160
1161 case 1U:
1162 x = 0x62U;
1163 break;
1164
1165 case 2U:
1166 x = 0x42U;
1167 break;
1168
1169 default:
1170 x = 0x10U;
1171 for (i = P; i <= PVALMAX; i++)
1172 {
1173 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);
1174 }
1175 break;
1176 }
1177
1178 return x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P);
1179 }
1180
1181 /* Find decoded P value for raw PDEC value */
pllDecodeP(uint32_t PDEC)1182 static uint32_t pllDecodeP(uint32_t PDEC)
1183 {
1184 uint32_t p, x, i;
1185
1186 /* Find PDec */
1187 switch (PDEC)
1188 {
1189 case 0x7FU:
1190 p = 0U;
1191 break;
1192
1193 case 0x62U:
1194 p = 1U;
1195 break;
1196
1197 case 0x42U:
1198 p = 2U;
1199 break;
1200
1201 default:
1202 x = 0x10U;
1203 p = 0xFFFFFFFFU;
1204 for (i = PVALMAX; (i >= 3U); i--)
1205 {
1206 x = (((x ^ (x >> 2U)) & 1U) << 4U) | ((x >> 1U) & 0xFU);
1207 if ((x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P)) == PDEC)
1208 {
1209 /* Decoded value of PDEC */
1210 p = i;
1211 break;
1212 }
1213 }
1214 break;
1215 }
1216
1217 return p;
1218 }
1219
1220 /* Find encoded MDEC value for raw M value, max M = MVALMAX */
pllEncodeM(uint32_t M)1221 static uint32_t pllEncodeM(uint32_t M)
1222 {
1223 uint32_t i, x;
1224
1225 /* Find MDec */
1226 switch (M)
1227 {
1228 case 0U:
1229 x = 0x1FFFFU;
1230 break;
1231
1232 case 1U:
1233 x = 0x18003U;
1234 break;
1235
1236 case 2U:
1237 x = 0x10003U;
1238 break;
1239
1240 default:
1241 x = 0x04000U;
1242 for (i = M; i <= MVALMAX; i++)
1243 {
1244 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
1245 }
1246 break;
1247 }
1248
1249 return x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P);
1250 }
1251
1252 /* Find decoded M value for raw MDEC value */
pllDecodeM(uint32_t MDEC)1253 static uint32_t pllDecodeM(uint32_t MDEC)
1254 {
1255 uint32_t m, i, x;
1256
1257 /* Find MDec */
1258 switch (MDEC)
1259 {
1260 case 0x1FFFFU:
1261 m = 0U;
1262 break;
1263
1264 case 0x18003U:
1265 m = 1U;
1266 break;
1267
1268 case 0x10003U:
1269 m = 2U;
1270 break;
1271
1272 default:
1273 x = 0x04000U;
1274 m = 0xFFFFFFFFU;
1275 for (i = MVALMAX; (i >= 3U); i--)
1276 {
1277 x = (((x ^ (x >> 1U)) & 1U) << 14U) | ((x >> 1U) & 0x3FFFU);
1278 if ((x & (PLL_MDEC_VAL_M >> PLL_MDEC_VAL_P)) == MDEC)
1279 {
1280 /* Decoded value of MDEC */
1281 m = i;
1282 break;
1283 }
1284 }
1285 break;
1286 }
1287
1288 return m;
1289 }
1290
1291 /* 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)1292 static void pllFindSel(uint32_t M, uint32_t *pSelP, uint32_t *pSelI, uint32_t *pSelR)
1293 {
1294 /* bandwidth: compute selP from Multiplier */
1295 if (M < 60U)
1296 {
1297 *pSelP = (M >> 1U) + 1U;
1298 }
1299 else
1300 {
1301 *pSelP = PVALMAX - 1U;
1302 }
1303
1304 /* bandwidth: compute selI from Multiplier */
1305 if (M > 16384U)
1306 {
1307 *pSelI = 1U;
1308 }
1309 else if (M > 8192U)
1310 {
1311 *pSelI = 2U;
1312 }
1313 else if (M > 2048U)
1314 {
1315 *pSelI = 4U;
1316 }
1317 else if (M >= 501U)
1318 {
1319 *pSelI = 8U;
1320 }
1321 else if (M >= 60U)
1322 {
1323 *pSelI = 4U * (1024U / (M + 9U));
1324 }
1325 else
1326 {
1327 *pSelI = (M & 0x3CU) + 4U;
1328 }
1329
1330 if (*pSelI > ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT))
1331 {
1332 *pSelI = ((0x3FUL << SYSCON_SYSPLLCTRL_SELI_SHIFT) >> SYSCON_SYSPLLCTRL_SELI_SHIFT);
1333 }
1334
1335 *pSelR = 0U;
1336 }
1337
1338 /* Get predivider (N) from PLL NDEC setting */
findPllPreDiv(uint32_t ctrlReg,uint32_t nDecReg)1339 static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg)
1340 {
1341 uint32_t preDiv = 1;
1342
1343 /* Direct input is not used? */
1344 if ((ctrlReg & (1UL << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT)) == 0U)
1345 {
1346 /* Decode NDEC value to get (N) pre divider */
1347 preDiv = pllDecodeN(nDecReg & 0x3FFU);
1348 if (preDiv == 0U)
1349 {
1350 preDiv = 1U;
1351 }
1352 }
1353
1354 /* Adjusted by 1, directi is used to bypass */
1355 return preDiv;
1356 }
1357
1358 /* Get postdivider (P) from PLL PDEC setting */
findPllPostDiv(uint32_t ctrlReg,uint32_t pDecReg)1359 static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg)
1360 {
1361 uint32_t postDiv = 1U;
1362
1363 /* Direct input is not used? */
1364 if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0U)
1365 {
1366 /* Decode PDEC value to get (P) post divider */
1367 postDiv = 2U * pllDecodeP(pDecReg & 0x7FU);
1368 if (postDiv == 0U)
1369 {
1370 postDiv = 2U;
1371 }
1372 }
1373
1374 /* Adjusted by 1, directo is used to bypass */
1375 return postDiv;
1376 }
1377
1378 /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
findPllMMult(uint32_t ctrlReg,uint32_t mDecReg)1379 static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)
1380 {
1381 uint32_t mMult = 1U;
1382
1383 /* Decode MDEC value to get (M) multiplier */
1384 mMult = pllDecodeM(mDecReg & 0x1FFFFU);
1385
1386 if (mMult == 0U)
1387 {
1388 mMult = 1U;
1389 }
1390
1391 return mMult;
1392 }
1393
1394 /* Convert the binary to fractional part */
Binary2Fractional(uint32_t binaryPart)1395 static double Binary2Fractional(uint32_t binaryPart)
1396 {
1397 double fractional = 0.0;
1398 for (uint32_t i = 0U; i <= 14U; i++)
1399 {
1400 fractional += (double)(uint32_t)((binaryPart >> i) & 0x1UL) / (double)(uint32_t)(1UL << (15U - i));
1401 }
1402 return fractional;
1403 }
1404
1405 /* Find greatest common divisor between m and n */
FindGreatestCommonDivisor(uint32_t m,uint32_t n)1406 static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n)
1407 {
1408 uint32_t tmp;
1409
1410 while (n != 0U)
1411 {
1412 tmp = n;
1413 n = m % n;
1414 m = tmp;
1415 }
1416
1417 return m;
1418 }
1419
1420 /*
1421 * Set PLL output based on desired output rate.
1422 * In this function, the it calculates the PLL setting for output frequency from input clock
1423 * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently.
1424 * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function.
1425 */
CLOCK_GetPllConfigInternal(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup)1426 static pll_error_t CLOCK_GetPllConfigInternal(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)
1427 {
1428 uint32_t nDivOutHz, fccoHz, multFccoDiv;
1429 uint32_t pllPreDivider, pllMultiplier, pllPostDivider;
1430 uint32_t pllDirectInput, pllDirectOutput;
1431 uint32_t pllSelP, pllSelI, pllSelR, uplimoff;
1432
1433 /* Baseline parameters (no input or output dividers) */
1434 pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */
1435 pllPostDivider = 0U; /* 0 implies post-divider will be disabled */
1436 pllDirectOutput = 1U;
1437 multFccoDiv = 2U;
1438
1439 /* Verify output rate parameter */
1440 if (foutHz > PLL_MAX_CCO_FREQ_MHZ)
1441 {
1442 /* Maximum PLL output with post divider=1 cannot go above this frequency */
1443 return kStatus_PLL_OutputTooHigh;
1444 }
1445 if (foutHz < (PLL_MIN_CCO_FREQ_MHZ / (PVALMAX << 1U)))
1446 {
1447 /* Minmum PLL output with maximum post divider cannot go below this frequency */
1448 return kStatus_PLL_OutputTooLow;
1449 }
1450
1451 /* Verify input rate parameter */
1452 if (finHz < PLL_LOWER_IN_LIMIT)
1453 {
1454 /* Input clock into the PLL cannot be lower than this */
1455 return kStatus_PLL_InputTooLow;
1456 }
1457
1458 /* Find the optimal CCO frequency for the output and input that
1459 will keep it inside the PLL CCO range. This may require
1460 tweaking the post-divider for the PLL. */
1461 fccoHz = foutHz;
1462 while (fccoHz < PLL_MIN_CCO_FREQ_MHZ)
1463 {
1464 /* CCO output is less than minimum CCO range, so the CCO output
1465 needs to be bumped up and the post-divider is used to bring
1466 the PLL output back down. */
1467 pllPostDivider++;
1468 if (pllPostDivider > PVALMAX)
1469 {
1470 return kStatus_PLL_OutsideIntLimit;
1471 }
1472
1473 /* Target CCO goes up, PLL output goes down */
1474 fccoHz = foutHz * (pllPostDivider * 2U);
1475 pllDirectOutput = 0U;
1476 }
1477
1478 /* Determine if a pre-divider is needed to get the best frequency */
1479 if ((finHz > PLL_LOWER_IN_LIMIT) && (fccoHz >= finHz))
1480 {
1481 uint32_t a = FindGreatestCommonDivisor(fccoHz, (multFccoDiv * finHz));
1482
1483 if (a > 20000U)
1484 {
1485 a = (multFccoDiv * finHz) / a;
1486 if ((a != 0U) && (a < PLL_MAX_N_DIV))
1487 {
1488 pllPreDivider = a;
1489 }
1490 }
1491 }
1492
1493 /* Bypass pre-divider hardware if pre-divider is 1 */
1494 if (pllPreDivider > 1U)
1495 {
1496 pllDirectInput = 0U;
1497 }
1498 else
1499 {
1500 pllDirectInput = 1U;
1501 }
1502
1503 /* Determine PLL multipler */
1504 nDivOutHz = (finHz / pllPreDivider);
1505 pllMultiplier = (fccoHz / nDivOutHz) / multFccoDiv;
1506
1507 /* Find optimal values for filter */
1508 /* Will bumping up M by 1 get us closer to the desired CCO frequency? */
1509 if ((nDivOutHz * ((multFccoDiv * pllMultiplier * 2U) + 1U)) < (fccoHz * 2U))
1510 {
1511 pllMultiplier++;
1512 }
1513
1514 /* Setup filtering */
1515 pllFindSel(pllMultiplier, &pllSelP, &pllSelI, &pllSelR);
1516 uplimoff = 0U;
1517
1518 /* Get encoded value for M (mult) and use manual filter, disable SS mode */
1519 pSetup->pllmdec = PLL_MDEC_VAL_SET(pllEncodeM(pllMultiplier));
1520
1521 /* Get encoded values for N (prediv) and P (postdiv) */
1522 pSetup->pllndec = PLL_NDEC_VAL_SET(pllEncodeN(pllPreDivider));
1523 pSetup->pllpdec = PLL_PDEC_VAL_SET(pllEncodeP(pllPostDivider));
1524
1525 /* PLL control */
1526 pSetup->pllctrl = (pllSelR << SYSCON_SYSPLLCTRL_SELR_SHIFT) | /* Filter coefficient */
1527 (pllSelI << SYSCON_SYSPLLCTRL_SELI_SHIFT) | /* Filter coefficient */
1528 (pllSelP << SYSCON_SYSPLLCTRL_SELP_SHIFT) | /* Filter coefficient */
1529 (0UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT) | /* PLL bypass mode disabled */
1530 (uplimoff << SYSCON_SYSPLLCTRL_UPLIMOFF_SHIFT) | /* SS/fractional mode disabled */
1531 (pllDirectInput << SYSCON_SYSPLLCTRL_DIRECTI_SHIFT) | /* Bypass pre-divider? */
1532 (pllDirectOutput << SYSCON_SYSPLLCTRL_DIRECTO_SHIFT); /* Bypass post-divider? */
1533
1534 return kStatus_PLL_Success;
1535 }
1536
1537 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1538 /* Alloct the static buffer for cache. */
1539 static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT];
1540 static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1541 static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0};
1542 static uint32_t s_PllSetupCacheIdx = 0U;
1543 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1544
1545 /*
1546 * Calculate the PLL setting values from input clock freq to output freq.
1547 */
CLOCK_GetPllConfig(uint32_t finHz,uint32_t foutHz,pll_setup_t * pSetup)1548 static pll_error_t CLOCK_GetPllConfig(uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup)
1549 {
1550 pll_error_t retErr;
1551 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1552 uint32_t i;
1553
1554 for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++)
1555 {
1556 if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]))
1557 {
1558 /* Hit the target in cache buffer. */
1559 pSetup->pllctrl = s_PllSetupCacheStruct[i].pllctrl;
1560 pSetup->pllndec = s_PllSetupCacheStruct[i].pllndec;
1561 pSetup->pllpdec = s_PllSetupCacheStruct[i].pllpdec;
1562 pSetup->pllmdec = s_PllSetupCacheStruct[i].pllmdec;
1563 retErr = kStatus_PLL_Success;
1564 break;
1565 }
1566 }
1567
1568 if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1569 {
1570 return retErr;
1571 }
1572 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1573
1574 /* No cache or did not hit the cache. */
1575 retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup);
1576
1577 #if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT)
1578 if (kStatus_PLL_Success == retErr)
1579 {
1580 /* Cache the most recent calulation result into buffer. */
1581 s_FinHzCache[s_PllSetupCacheIdx] = finHz;
1582 s_FoutHzCache[s_PllSetupCacheIdx] = foutHz;
1583
1584 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllctrl = pSetup->pllctrl;
1585 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllndec = pSetup->pllndec;
1586 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllpdec = pSetup->pllpdec;
1587 s_PllSetupCacheStruct[s_PllSetupCacheIdx].pllmdec = pSetup->pllmdec;
1588 /* Update the index for next available buffer. */
1589 s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT;
1590 }
1591 #endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */
1592
1593 return retErr;
1594 }
1595
1596 /* Update SYSTEM PLL rate variable */
CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t * pSetup)1597 static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup)
1598 {
1599 s_Pll_Freq = CLOCK_GetSystemPLLOutFromSetup(pSetup);
1600 }
1601
1602 /* Update AUDIO PLL rate variable */
CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t * pSetup)1603 static void CLOCK_GetAudioPLLOutFromSetupUpdate(pll_setup_t *pSetup)
1604 {
1605 s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromSetup(pSetup);
1606 }
1607
1608 /* Update AUDIO Fractional PLL rate variable */
CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t * pSetup)1609 static void CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pll_setup_t *pSetup)
1610 {
1611 s_Audio_Pll_Freq = CLOCK_GetAudioPLLOutFromFractSetup(pSetup);
1612 }
1613
1614 /* Update USB PLL rate variable */
CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t * pSetup)1615 static void CLOCK_GetUsbPLLOutFromSetupUpdate(const usb_pll_setup_t *pSetup)
1616 {
1617 s_Usb_Pll_Freq = CLOCK_GetUsbPLLOutFromSetup(pSetup);
1618 }
1619
1620 /* Return System PLL input clock rate */
1621 /*! brief Return System PLL input clock rate
1622 * return System PLL input clock rate
1623 */
CLOCK_GetSystemPLLInClockRate(void)1624 uint32_t CLOCK_GetSystemPLLInClockRate(void)
1625 {
1626 uint32_t clkRate = 0U;
1627
1628 switch ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK))
1629 {
1630 case 0x00U:
1631 clkRate = CLK_FRO_12MHZ;
1632 break;
1633
1634 case 0x01U:
1635 clkRate = CLOCK_GetExtClkFreq();
1636 break;
1637
1638 case 0x02U:
1639 clkRate = CLOCK_GetWdtOscFreq();
1640 break;
1641
1642 case 0x03U:
1643 clkRate = CLOCK_GetOsc32KFreq();
1644 break;
1645
1646 default:
1647 clkRate = 0U;
1648 break;
1649 }
1650
1651 return clkRate;
1652 }
1653
1654 /* Return Audio PLL input clock rate */
1655 /*! brief Return Audio PLL input clock rate
1656 * return Audio PLL input clock rate
1657 */
CLOCK_GetAudioPLLInClockRate(void)1658 uint32_t CLOCK_GetAudioPLLInClockRate(void)
1659 {
1660 uint32_t clkRate = 0U;
1661
1662 switch ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK))
1663 {
1664 case 0x00U:
1665 clkRate = CLK_FRO_12MHZ;
1666 break;
1667
1668 case 0x01U:
1669 clkRate = CLOCK_GetExtClkFreq();
1670 break;
1671
1672 default:
1673 clkRate = 0U;
1674 break;
1675 }
1676
1677 return clkRate;
1678 }
1679
1680 /* Return System PLL output clock rate from setup structure */
1681 /*! brief Return System PLL output clock rate from setup structure
1682 * param pSetup : Pointer to a PLL setup structure
1683 * return System PLL output clock rate the setup structure will generate
1684 */
CLOCK_GetSystemPLLOutFromSetup(pll_setup_t * pSetup)1685 uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup)
1686 {
1687 uint32_t prediv, postdiv, mMult, inPllRate;
1688 uint64_t workRate;
1689
1690 inPllRate = CLOCK_GetSystemPLLInClockRate();
1691 /* If the PLL is bypassed, PLL would not be used and the output of PLL module would just be the input clock*/
1692 if ((pSetup->pllctrl & (SYSCON_SYSPLLCTRL_BYPASS_MASK)) == 0U)
1693 {
1694 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1695 /*
1696 * 1. Pre-divider
1697 * Pre-divider is only available when the DIRECTI is disabled.
1698 */
1699 if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTI_MASK))
1700 {
1701 prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);
1702 }
1703 else
1704 {
1705 prediv = 1U; /* The pre-divider is bypassed. */
1706 }
1707 /*
1708 * 2. Post-divider
1709 * Post-divider is only available when the DIRECTO is disabled.
1710 */
1711 if (0U == (pSetup->pllctrl & SYSCON_SYSPLLCTRL_DIRECTO_MASK))
1712 {
1713 postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);
1714 }
1715 else
1716 {
1717 postdiv = 1U; /* The post-divider is bypassed. */
1718 }
1719 /* Adjust input clock */
1720 inPllRate = inPllRate / prediv;
1721
1722 /* MDEC used for rate */
1723 mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);
1724 workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1725
1726 workRate = workRate / ((uint64_t)postdiv);
1727 workRate = workRate * 2U; /* SYS PLL hardware cco is divided by 2 before the M-DIVIDER*/
1728 }
1729 else
1730 {
1731 /* In bypass mode */
1732 workRate = (uint64_t)inPllRate;
1733 }
1734
1735 return (uint32_t)workRate;
1736 }
1737
1738 /* Return Usb PLL output clock rate from setup structure */
1739 /*! brief Return System USB PLL output clock rate from setup structure
1740 * param pSetup : Pointer to a PLL setup structure
1741 * return System PLL output clock rate the setup structure will generate
1742 */
CLOCK_GetUsbPLLOutFromSetup(const usb_pll_setup_t * pSetup)1743 uint32_t CLOCK_GetUsbPLLOutFromSetup(const usb_pll_setup_t *pSetup)
1744 {
1745 uint32_t nsel, psel, msel, inPllRate;
1746 uint64_t workRate;
1747 inPllRate = CLOCK_GetExtClkFreq();
1748 msel = pSetup->msel;
1749 psel = pSetup->psel;
1750 nsel = pSetup->nsel;
1751
1752 if (pSetup->fbsel)
1753 {
1754 /*integer_mode: Fout = M*(Fin/N), Fcco = 2*P*M*(Fin/N) */
1755 workRate = (uint64_t)(inPllRate) * (msel + 1ULL) / (nsel + 1ULL);
1756 }
1757 else
1758 {
1759 /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */
1760 workRate = ((uint64_t)inPllRate / (nsel + 1ULL)) * (msel + 1ULL) / (2U * (1UL << (psel & 3U)));
1761 }
1762
1763 return (uint32_t)workRate;
1764 }
1765
1766 /* Return Audio PLL output clock rate from setup structure */
1767 /*! brief Return System AUDIO PLL output clock rate from setup structure
1768 * param pSetup : Pointer to a PLL setup structure
1769 * return System PLL output clock rate the setup structure will generate
1770 */
CLOCK_GetAudioPLLOutFromSetup(pll_setup_t * pSetup)1771 uint32_t CLOCK_GetAudioPLLOutFromSetup(pll_setup_t *pSetup)
1772 {
1773 uint32_t prediv, postdiv, mMult, inPllRate;
1774 uint64_t workRate;
1775
1776 inPllRate = CLOCK_GetAudioPLLInClockRate();
1777 if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)
1778 {
1779 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1780 /*
1781 * 1. Pre-divider
1782 * Pre-divider is only available when the DIRECTI is disabled.
1783 */
1784 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))
1785 {
1786 prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);
1787 }
1788 else
1789 {
1790 prediv = 1U; /* The pre-divider is bypassed. */
1791 }
1792 /*
1793 * 2. Post-divider
1794 * Post-divider is only available when the DIRECTO is disabled.
1795 */
1796 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))
1797 {
1798 postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);
1799 }
1800 else
1801 {
1802 postdiv = 1U; /* The post-divider is bypassed. */
1803 }
1804 /* Adjust input clock */
1805 inPllRate = inPllRate / prediv;
1806
1807 /* MDEC used for rate */
1808 mMult = findPllMMult(pSetup->pllctrl, pSetup->pllmdec);
1809 workRate = (uint64_t)inPllRate * (uint64_t)mMult;
1810
1811 workRate = workRate / ((uint64_t)postdiv);
1812 workRate = workRate * 2U; /* SYS PLL hardware cco is divided by 2 before the M-DIVIDER*/
1813 }
1814 else
1815 {
1816 /* In bypass mode */
1817 workRate = (uint64_t)inPllRate;
1818 }
1819
1820 return (uint32_t)workRate;
1821 }
1822
1823 /* Return Audio PLL output clock rate from audio fractioanl setup structure */
1824 /*! brief Return System AUDIO PLL output clock rate from audio fractioanl setup structure
1825 * param pSetup : Pointer to a PLL setup structure
1826 * return System PLL output clock rate the setup structure will generate
1827 */
CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t * pSetup)1828 uint32_t CLOCK_GetAudioPLLOutFromFractSetup(pll_setup_t *pSetup)
1829 {
1830 uint32_t prediv, postdiv, inPllRate;
1831 double workRate, mMultFactional;
1832
1833 inPllRate = CLOCK_GetAudioPLLInClockRate();
1834 if ((pSetup->pllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U)
1835 {
1836 /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */
1837 /*
1838 * 1. Pre-divider
1839 * Pre-divider is only available when the DIRECTI is disabled.
1840 */
1841 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTI_MASK))
1842 {
1843 prediv = findPllPreDiv(pSetup->pllctrl, pSetup->pllndec);
1844 }
1845 else
1846 {
1847 prediv = 1U; /* The pre-divider is bypassed. */
1848 }
1849 /*
1850 * 2. Post-divider
1851 * Post-divider is only available when the DIRECTO is disabled.
1852 */
1853 if (0U == (pSetup->pllctrl & SYSCON_AUDPLLCTRL_DIRECTO_MASK))
1854 {
1855 postdiv = findPllPostDiv(pSetup->pllctrl, pSetup->pllpdec);
1856 }
1857 else
1858 {
1859 postdiv = 1U; /* The post-divider is bypassed. */
1860 }
1861 /* Adjust input clock */
1862 inPllRate = inPllRate / prediv;
1863
1864 mMultFactional =
1865 (double)(uint32_t)(pSetup->audpllfrac >> 15U) + (double)Binary2Fractional(pSetup->audpllfrac & 0x7FFFU);
1866 workRate = (double)inPllRate * (double)mMultFactional;
1867
1868 workRate = workRate / ((double)postdiv);
1869 workRate = workRate * 2.0; /* SYS PLL hardware cco is divided by 2 before the M-DIVIDER*/
1870 }
1871 else
1872 {
1873 /* In bypass mode */
1874 workRate = (double)inPllRate;
1875 }
1876
1877 return (uint32_t)workRate;
1878 }
1879
1880 /* Set the current PLL Rate */
1881 /*! brief Store the current PLL rate
1882 * param rate: Current rate of the PLL
1883 * return Nothing
1884 **/
CLOCK_SetStoredPLLClockRate(uint32_t rate)1885 void CLOCK_SetStoredPLLClockRate(uint32_t rate)
1886 {
1887 s_Pll_Freq = rate;
1888 }
1889
1890 /* Set the current Audio PLL Rate */
1891 /*! brief Store the current AUDIO PLL rate
1892 * param rate: Current rate of the PLL
1893 * return Nothing
1894 **/
CLOCK_SetStoredAudioPLLClockRate(uint32_t rate)1895 void CLOCK_SetStoredAudioPLLClockRate(uint32_t rate)
1896 {
1897 s_Audio_Pll_Freq = rate;
1898 }
1899
1900 /* Set the current Usb PLL Rate */
CLOCK_SetStoredUsbPLLClockRate(uint32_t rate)1901 void CLOCK_SetStoredUsbPLLClockRate(uint32_t rate)
1902 {
1903 s_Usb_Pll_Freq = rate;
1904 }
1905
1906 /* Return System PLL output clock rate */
1907 /*! brief Return System PLL output clock rate
1908 * param recompute : Forces a PLL rate recomputation if true
1909 * return System PLL output clock rate
1910 * note The PLL rate is cached in the driver in a variable as
1911 * the rate computation function can take some time to perform. It
1912 * is recommended to use 'false' with the 'recompute' parameter.
1913 */
CLOCK_GetSystemPLLOutClockRate(bool recompute)1914 uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute)
1915 {
1916 pll_setup_t Setup;
1917 uint32_t rate;
1918
1919 if ((recompute) || (s_Pll_Freq == 0U))
1920 {
1921 Setup.pllctrl = SYSCON->SYSPLLCTRL;
1922 Setup.pllndec = SYSCON->SYSPLLNDEC;
1923 Setup.pllpdec = SYSCON->SYSPLLPDEC;
1924 Setup.pllmdec = SYSCON->SYSPLLMDEC;
1925
1926 CLOCK_GetSystemPLLOutFromSetupUpdate(&Setup);
1927 }
1928
1929 rate = s_Pll_Freq;
1930
1931 return rate;
1932 }
1933
1934 /* Return AUDIO PLL output clock rate */
1935 /*! brief Return System AUDIO PLL output clock rate
1936 * param recompute : Forces a AUDIO PLL rate recomputation if true
1937 * return System AUDIO PLL output clock rate
1938 * note The AUDIO PLL rate is cached in the driver in a variable as
1939 * the rate computation function can take some time to perform. It
1940 * is recommended to use 'false' with the 'recompute' parameter.
1941 */
CLOCK_GetAudioPLLOutClockRate(bool recompute)1942 uint32_t CLOCK_GetAudioPLLOutClockRate(bool recompute)
1943 {
1944 pll_setup_t Setup;
1945 uint32_t rate;
1946
1947 if ((recompute) || (s_Audio_Pll_Freq == 0U))
1948 {
1949 Setup.pllctrl = SYSCON->AUDPLLCTRL;
1950 Setup.pllndec = SYSCON->AUDPLLNDEC;
1951 Setup.pllpdec = SYSCON->AUDPLLPDEC;
1952 Setup.pllmdec = SYSCON->AUDPLLMDEC;
1953
1954 CLOCK_GetAudioPLLOutFromSetupUpdate(&Setup);
1955 }
1956
1957 rate = s_Audio_Pll_Freq;
1958 return rate;
1959 }
1960
1961 /* Return USB PLL output clock rate */
CLOCK_GetUsbPLLOutClockRate(bool recompute)1962 uint32_t CLOCK_GetUsbPLLOutClockRate(bool recompute)
1963 {
1964 usb_pll_setup_t Setup;
1965 uint32_t rate;
1966
1967 if ((recompute) || (s_Usb_Pll_Freq == 0U))
1968 {
1969 Setup.msel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_MSEL_SHIFT) & SYSCON_USBPLLCTRL_MSEL_MASK);
1970 Setup.psel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_PSEL_SHIFT) & SYSCON_USBPLLCTRL_PSEL_MASK);
1971 Setup.nsel = (uint8_t)((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_NSEL_SHIFT) & SYSCON_USBPLLCTRL_NSEL_MASK);
1972 Setup.fbsel = (0UL != ((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_FBSEL_SHIFT) & SYSCON_USBPLLCTRL_FBSEL_MASK));
1973 Setup.bypass =
1974 (0UL != ((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_BYPASS_SHIFT) & SYSCON_USBPLLCTRL_BYPASS_MASK));
1975 Setup.direct =
1976 (0UL != ((SYSCON->USBPLLCTRL >> SYSCON_USBPLLCTRL_DIRECT_SHIFT) & SYSCON_USBPLLCTRL_DIRECT_MASK));
1977 CLOCK_GetUsbPLLOutFromSetupUpdate(&Setup);
1978 }
1979
1980 rate = s_Usb_Pll_Freq;
1981 return rate;
1982 }
1983
1984 /* Set PLL output based on the passed PLL setup data */
1985 /*! brief Set PLL output based on the passed PLL setup data
1986 * param pControl : Pointer to populated PLL control structure to generate setup with
1987 * param pSetup : Pointer to PLL setup structure to be filled
1988 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
1989 * note Actual frequency for setup may vary from the desired frequency based on the
1990 * accuracy of input clocks, rounding, non-fractional PLL mode, etc.
1991 */
CLOCK_SetupPLLData(pll_config_t * pControl,pll_setup_t * pSetup)1992 pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup)
1993 {
1994 uint32_t inRate;
1995 pll_error_t pllError;
1996
1997 /* Determine input rate for the PLL */
1998 if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)
1999 {
2000 inRate = pControl->inputRate;
2001 }
2002 else
2003 {
2004 inRate = CLOCK_GetSystemPLLInClockRate();
2005 }
2006
2007 /* PLL flag options */
2008 pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup);
2009 pSetup->pllRate = pControl->desiredRate;
2010 return pllError;
2011 }
2012
2013 /* Set PLL output from PLL setup structure */
2014 /*! brief Set PLL output from PLL setup structure (precise frequency)
2015 * param pSetup : Pointer to populated PLL setup structure
2016 * param flagcfg : Flag configuration for PLL config structure
2017 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
2018 * note This function will power off the PLL, setup the PLL with the
2019 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2020 * and adjust system voltages to the new PLL rate. The function will not
2021 * alter any source clocks (ie, main systen clock) that may use the PLL,
2022 * so these should be setup prior to and after exiting the function.
2023 */
CLOCK_SetupSystemPLLPrec(pll_setup_t * pSetup,uint32_t flagcfg)2024 pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)
2025 {
2026 if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U)
2027 {
2028 /* Turn on the ext clock if system pll input select clk_in */
2029 CLOCK_Enable_SysOsc(true);
2030 }
2031 /* Enable power for PLLs */
2032 POWER_SetPLL();
2033 /* Power off PLL during setup changes */
2034 POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);
2035 /*!< Set FLASH waitstates for core */
2036 CLOCK_SetFLASHAccessCyclesForFreq(pSetup->pllRate);
2037 pSetup->flags = flagcfg;
2038
2039 /* Write PLL setup data */
2040 SYSCON->SYSPLLCTRL = pSetup->pllctrl;
2041 SYSCON->SYSPLLNDEC = pSetup->pllndec;
2042 SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
2043 SYSCON->SYSPLLPDEC = pSetup->pllpdec;
2044 SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
2045 SYSCON->SYSPLLMDEC = pSetup->pllmdec;
2046 SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */
2047
2048 /* Flags for lock or power on */
2049 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)
2050 {
2051 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
2052 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
2053 uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);
2054
2055 /* Initialize and power up PLL */
2056 SYSCON->SYSPLLMDEC = maxCCO;
2057 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
2058
2059 /* Set mreq to activate */
2060 SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);
2061
2062 /* Delay for 72 uSec @ 12Mhz */
2063 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2064
2065 /* clear mreq to prepare for restoring mreq */
2066 SYSCON->SYSPLLMDEC = curSSCTRL;
2067
2068 /* set original value back and activate */
2069 SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);
2070
2071 /* Enable peripheral states by setting low */
2072 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
2073 }
2074 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2075 {
2076 while (CLOCK_IsSystemPLLLocked() == false)
2077 {
2078 }
2079 }
2080
2081 /* Update current programmed PLL rate var */
2082 CLOCK_GetSystemPLLOutFromSetupUpdate(pSetup);
2083
2084 /* System voltage adjustment, occurs prior to setting main system clock */
2085 if ((pSetup->flags & PLL_SETUPFLAG_ADGVOLT) != 0U)
2086 {
2087 POWER_SetVoltageForFreq(s_Pll_Freq);
2088 }
2089
2090 return kStatus_PLL_Success;
2091 }
2092
2093 /* Set AUDIO PLL output from AUDIO PLL setup structure */
2094 /*! brief Set AUDIO PLL output from AUDIOPLL setup structure (precise frequency)
2095 * param pSetup : Pointer to populated PLL setup structure
2096 * param flagcfg : Flag configuration for PLL config structure
2097 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
2098 * note This function will power off the PLL, setup the PLL with the
2099 * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock,
2100 * and adjust system voltages to the new AUDIOPLL rate. The function will not
2101 * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL,
2102 * so these should be setup prior to and after exiting the function.
2103 */
CLOCK_SetupAudioPLLPrec(pll_setup_t * pSetup,uint32_t flagcfg)2104 pll_error_t CLOCK_SetupAudioPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg)
2105 {
2106 if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)
2107 {
2108 /* Turn on the ext clock if system pll input select clk_in */
2109 CLOCK_Enable_SysOsc(true);
2110 }
2111 /* Enable power VD3 for PLLs */
2112 POWER_SetPLL();
2113 /* Power off PLL during setup changes */
2114 POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);
2115
2116 pSetup->flags = flagcfg;
2117
2118 /* Write PLL setup data */
2119 SYSCON->AUDPLLCTRL = pSetup->pllctrl;
2120 SYSCON->AUDPLLNDEC = pSetup->pllndec;
2121 SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
2122 SYSCON->AUDPLLPDEC = pSetup->pllpdec;
2123 SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
2124 SYSCON->AUDPLLMDEC = pSetup->pllmdec;
2125 SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */
2126 SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1); /* disable fractional function */
2127
2128 /* Flags for lock or power on */
2129 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)
2130 {
2131 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
2132 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
2133 uint32_t curSSCTRL = SYSCON->AUDPLLMDEC & ~(1UL << 17U);
2134
2135 /* Initialize and power up PLL */
2136 SYSCON->AUDPLLMDEC = maxCCO;
2137 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2138
2139 /* Set mreq to activate */
2140 SYSCON->AUDPLLMDEC = maxCCO | (1UL << 17U);
2141
2142 /* Delay for 72 uSec @ 12Mhz */
2143 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2144
2145 /* clear mreq to prepare for restoring mreq */
2146 SYSCON->AUDPLLMDEC = curSSCTRL;
2147
2148 /* set original value back and activate */
2149 SYSCON->AUDPLLMDEC = curSSCTRL | (1UL << 17U);
2150
2151 /* Enable peripheral states by setting low */
2152 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2153 }
2154 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2155 {
2156 while (CLOCK_IsAudioPLLLocked() == false)
2157 {
2158 }
2159 }
2160
2161 /* Update current programmed PLL rate var */
2162 CLOCK_GetAudioPLLOutFromSetupUpdate(pSetup);
2163
2164 return kStatus_PLL_Success;
2165 }
2166
2167 /* Set AUDIO PLL output from AUDIO PLL fractional setup structure */
2168 /*! brief Set AUDIO PLL output from AUDIOPLL setup structure using the Audio Fractional divider register(precise
2169 * frequency)
2170 * param pSetup : Pointer to populated PLL setup structure
2171 * param flagcfg : Flag configuration for PLL config structure
2172 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
2173 * note This function will power off the PLL, setup the PLL with the
2174 * new setup data, and then optionally powerup the AUDIO PLL, wait for PLL lock,
2175 * and adjust system voltages to the new AUDIOPLL rate. The function will not
2176 * alter any source clocks (ie, main systen clock) that may use the AUDIO PLL,
2177 * so these should be setup prior to and after exiting the function.
2178 */
CLOCK_SetupAudioPLLPrecFract(pll_setup_t * pSetup,uint32_t flagcfg)2179 pll_error_t CLOCK_SetupAudioPLLPrecFract(pll_setup_t *pSetup, uint32_t flagcfg)
2180 {
2181 if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)
2182 {
2183 /* Turn on the ext clock if system pll input select clk_in */
2184 CLOCK_Enable_SysOsc(true);
2185 }
2186 /* Enable power VD3 for PLLs */
2187 POWER_SetPLL();
2188 /* Power off PLL during setup changes */
2189 POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);
2190
2191 pSetup->flags = flagcfg;
2192
2193 /* Write PLL setup data */
2194 SYSCON->AUDPLLCTRL = pSetup->pllctrl;
2195 SYSCON->AUDPLLNDEC = pSetup->pllndec;
2196 SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
2197 SYSCON->AUDPLLPDEC = pSetup->pllpdec;
2198 SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
2199 SYSCON->AUDPLLMDEC = pSetup->pllmdec;
2200 SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(0); /* enable fractional function */
2201 SYSCON->AUDPLLFRAC = pSetup->audpllfrac;
2202 SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT);
2203
2204 /* Enable peripheral states by setting low */
2205 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2206
2207 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2208 {
2209 while (CLOCK_IsAudioPLLLocked() == false)
2210 {
2211 }
2212 }
2213
2214 /* Update current programmed PLL rate var */
2215 CLOCK_GetAudioPLLOutFromAudioFracSetupUpdate(pSetup);
2216
2217 return kStatus_PLL_Success;
2218 }
2219
2220 /* Set Audio PLL output based on the passed Audio PLL setup data */
2221 /*! brief Set AUDIO PLL output based on the passed AUDIO PLL setup data
2222 * param pControl : Pointer to populated PLL control structure to generate setup with
2223 * param pSetup : Pointer to PLL setup structure to be filled
2224 * return PLL_ERROR_SUCCESS on success, or PLL setup error code
2225 * note Actual frequency for setup may vary from the desired frequency based on the
2226 * accuracy of input clocks, rounding, non-fractional PLL mode, etc.
2227 */
CLOCK_SetupAudioPLLData(pll_config_t * pControl,pll_setup_t * pSetup)2228 pll_error_t CLOCK_SetupAudioPLLData(pll_config_t *pControl, pll_setup_t *pSetup)
2229 {
2230 uint32_t inRate;
2231 pll_error_t pllError;
2232
2233 /* Determine input rate for the PLL */
2234 if ((pControl->flags & PLL_CONFIGFLAG_USEINRATE) != 0U)
2235 {
2236 inRate = pControl->inputRate;
2237 }
2238 else
2239 {
2240 inRate = CLOCK_GetAudioPLLInClockRate();
2241 }
2242
2243 /* PLL flag options */
2244 pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup);
2245 pSetup->pllRate = pControl->desiredRate;
2246 return pllError;
2247 }
2248
2249 /* Setup PLL Frequency from pre-calculated value */
2250 /**
2251 * brief Set PLL output from PLL setup structure (precise frequency)
2252 * param pSetup : Pointer to populated PLL setup structure
2253 * return kStatus_PLL_Success on success, or PLL setup error code
2254 * note This function will power off the PLL, setup the PLL with the
2255 * new setup data, and then optionally powerup the PLL, wait for PLL lock,
2256 * and adjust system voltages to the new PLL rate. The function will not
2257 * alter any source clocks (ie, main systen clock) that may use the PLL,
2258 * so these should be setup prior to and after exiting the function.
2259 */
CLOCK_SetPLLFreq(const pll_setup_t * pSetup)2260 pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup)
2261 {
2262 if ((SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK) == 0x01U)
2263 {
2264 /* Turn on the ext clock if system pll input select clk_in */
2265 CLOCK_Enable_SysOsc(true);
2266 }
2267 /* Enable power VD3 for PLLs */
2268 POWER_SetPLL();
2269 /* Power off PLL during setup changes */
2270 POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0);
2271
2272 /* Write PLL setup data */
2273 SYSCON->SYSPLLCTRL = pSetup->pllctrl;
2274 SYSCON->SYSPLLNDEC = pSetup->pllndec;
2275 SYSCON->SYSPLLNDEC = pSetup->pllndec | (1UL << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */
2276 SYSCON->SYSPLLPDEC = pSetup->pllpdec;
2277 SYSCON->SYSPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */
2278 SYSCON->SYSPLLMDEC = pSetup->pllmdec;
2279 SYSCON->SYSPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_SYSPLLMDEC_MREQ_SHIFT); /* latch */
2280
2281 /* Flags for lock or power on */
2282 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)
2283 {
2284 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
2285 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
2286 uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);
2287
2288 /* Initialize and power up PLL */
2289 SYSCON->SYSPLLMDEC = maxCCO;
2290 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
2291
2292 /* Set mreq to activate */
2293 SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);
2294
2295 /* Delay for 72 uSec @ 12Mhz */
2296 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2297
2298 /* clear mreq to prepare for restoring mreq */
2299 SYSCON->SYSPLLMDEC = curSSCTRL;
2300
2301 /* set original value back and activate */
2302 SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);
2303
2304 /* Enable peripheral states by setting low */
2305 POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0);
2306 }
2307 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2308 {
2309 while (CLOCK_IsSystemPLLLocked() == false)
2310 {
2311 }
2312 }
2313
2314 /* Update current programmed PLL rate var */
2315 s_Pll_Freq = pSetup->pllRate;
2316
2317 return kStatus_PLL_Success;
2318 }
2319
2320 /* Setup Audio PLL Frequency from pre-calculated value */
2321 /**
2322 * brief Set Audio PLL output from Audio PLL setup structure (precise frequency)
2323 * param pSetup : Pointer to populated PLL setup structure
2324 * return kStatus_PLL_Success on success, or Audio PLL setup error code
2325 * note This function will power off the PLL, setup the Audio PLL with the
2326 * new setup data, and then optionally powerup the PLL, wait for Audio PLL lock,
2327 * and adjust system voltages to the new PLL rate. The function will not
2328 * alter any source clocks (ie, main systen clock) that may use the Audio PLL,
2329 * so these should be setup prior to and after exiting the function.
2330 */
CLOCK_SetAudioPLLFreq(const pll_setup_t * pSetup)2331 pll_error_t CLOCK_SetAudioPLLFreq(const pll_setup_t *pSetup)
2332 {
2333 if ((SYSCON->AUDPLLCLKSEL & SYSCON_AUDPLLCLKSEL_SEL_MASK) == 0x01U)
2334 {
2335 /* Turn on the ext clock if system pll input select clk_in */
2336 CLOCK_Enable_SysOsc(true);
2337 }
2338 /* Enable power VD3 for PLLs */
2339 POWER_SetPLL();
2340 /* Power off Audio PLL during setup changes */
2341 POWER_EnablePD(kPDRUNCFG_PD_AUDIO_PLL);
2342
2343 /* Write Audio PLL setup data */
2344 SYSCON->AUDPLLCTRL = pSetup->pllctrl;
2345 SYSCON->AUDPLLFRAC = pSetup->audpllfrac;
2346 SYSCON->AUDPLLFRAC = pSetup->audpllfrac | (1UL << SYSCON_AUDPLLFRAC_REQ_SHIFT); /* latch */
2347 SYSCON->AUDPLLNDEC = pSetup->pllndec;
2348 SYSCON->AUDPLLNDEC = pSetup->pllndec | (1UL << SYSCON_AUDPLLNDEC_NREQ_SHIFT); /* latch */
2349 SYSCON->AUDPLLPDEC = pSetup->pllpdec;
2350 SYSCON->AUDPLLPDEC = pSetup->pllpdec | (1UL << SYSCON_AUDPLLPDEC_PREQ_SHIFT); /* latch */
2351 SYSCON->AUDPLLMDEC = pSetup->pllmdec;
2352 SYSCON->AUDPLLMDEC = pSetup->pllmdec | (1UL << SYSCON_AUDPLLMDEC_MREQ_SHIFT); /* latch */
2353 SYSCON->AUDPLLFRAC = SYSCON_AUDPLLFRAC_SEL_EXT(1); /* disable fractional function */
2354
2355 /* Flags for lock or power on */
2356 if ((pSetup->flags & (PLL_SETUPFLAG_POWERUP | PLL_SETUPFLAG_WAITLOCK)) != 0U)
2357 {
2358 /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */
2359 uint32_t maxCCO = (1UL << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/
2360 uint32_t curSSCTRL = SYSCON->SYSPLLMDEC & ~(1UL << 17U);
2361
2362 /* Initialize and power up PLL */
2363 SYSCON->SYSPLLMDEC = maxCCO;
2364 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2365
2366 /* Set mreq to activate */
2367 SYSCON->SYSPLLMDEC = maxCCO | (1UL << 17U);
2368
2369 /* Delay for 72 uSec @ 12Mhz */
2370 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2371
2372 /* clear mreq to prepare for restoring mreq */
2373 SYSCON->SYSPLLMDEC = curSSCTRL;
2374
2375 /* set original value back and activate */
2376 SYSCON->SYSPLLMDEC = curSSCTRL | (1UL << 17U);
2377
2378 /* Enable peripheral states by setting low */
2379 POWER_DisablePD(kPDRUNCFG_PD_AUDIO_PLL);
2380 }
2381 if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U)
2382 {
2383 while (CLOCK_IsAudioPLLLocked() == false)
2384 {
2385 }
2386 }
2387
2388 /* Update current programmed PLL rate var */
2389 s_Audio_Pll_Freq = pSetup->pllRate;
2390
2391 return kStatus_PLL_Success;
2392 }
2393
2394 /* Setup USB PLL Frequency from pre-calculated value */
2395 /**
2396 * brief Set USB PLL output from USB PLL setup structure (precise frequency)
2397 * param pSetup : Pointer to populated USB PLL setup structure
2398 * return kStatus_PLL_Success on success, or USB PLL setup error code
2399 * note This function will power off the USB PLL, setup the PLL with the
2400 * new setup data, and then optionally powerup the USB PLL, wait for USB PLL lock,
2401 * and adjust system voltages to the new USB PLL rate. The function will not
2402 * alter any source clocks (ie, usb pll clock) that may use the USB PLL,
2403 * so these should be setup prior to and after exiting the function.
2404 */
CLOCK_SetUsbPLLFreq(const usb_pll_setup_t * pSetup)2405 pll_error_t CLOCK_SetUsbPLLFreq(const usb_pll_setup_t *pSetup)
2406 {
2407 uint32_t usbpllctrl, fccoHz;
2408 uint8_t msel, psel, nsel;
2409 bool pllDirectInput, pllDirectOutput, pllfbsel;
2410
2411 msel = pSetup->msel;
2412 psel = pSetup->psel;
2413 nsel = pSetup->nsel;
2414 pllDirectOutput = pSetup->direct;
2415 pllDirectInput = pSetup->bypass;
2416 pllfbsel = pSetup->fbsel;
2417
2418 /* Input clock into the PLL cannot be lower than this */
2419 if (pSetup->inputRate < USB_PLL_LOWER_IN_LIMIT)
2420 {
2421 return kStatus_PLL_InputTooLow;
2422 }
2423
2424 if (pllfbsel)
2425 {
2426 /*integer_mode: Fout = M*(Fin/N), Fcco = 2*P*M*(Fin/N) */
2427 fccoHz = (pSetup->inputRate / (nsel + 1UL)) * 2UL * (msel + 1UL) * (1UL << (psel & 3U));
2428
2429 /* USB PLL CCO out rate cannot be lower than this */
2430 if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ)
2431 {
2432 return kStatus_PLL_CCOTooLow;
2433 }
2434 /* USB PLL CCO out rate cannot be Higher than this */
2435 if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ)
2436 {
2437 return kStatus_PLL_CCOTooHigh;
2438 }
2439 }
2440 else
2441 {
2442 /* non integer_mode: Fout = M*(Fin/N)/(2*P), Fcco = M * (Fin/N) */
2443 fccoHz = pSetup->inputRate / (nsel + 1UL) * (msel + 1UL);
2444
2445 /* USB PLL CCO out rate cannot be lower than this */
2446 if (fccoHz < USB_PLL_MIN_CCO_FREQ_MHZ)
2447 {
2448 return kStatus_PLL_CCOTooLow;
2449 }
2450 /* USB PLL CCO out rate cannot be Higher than this */
2451 if (fccoHz > USB_PLL_MAX_CCO_FREQ_MHZ)
2452 {
2453 return kStatus_PLL_CCOTooHigh;
2454 }
2455 }
2456
2457 /* If configure the USB HOST clock, VD5 power for USB PHY should be enable
2458 before the PLL is working */
2459 /* Turn on the ext clock for usb pll input */
2460 CLOCK_Enable_SysOsc(true);
2461
2462 /* Enable power VD3 for PLLs */
2463 POWER_SetPLL();
2464
2465 /* Power on the VD5 for USB PHY */
2466 POWER_SetUsbPhy();
2467
2468 /* Power off USB PLL during setup changes */
2469 POWER_EnablePD(kPDRUNCFG_PD_USB_PLL);
2470
2471 /* Write USB PLL setup data */
2472 usbpllctrl = USB_PLL_NSEL_VAL_SET(nsel) | /* NSEL VALUE */
2473 USB_PLL_PSEL_VAL_SET(psel) | /* PSEL VALUE */
2474 USB_PLL_MSEL_VAL_SET(msel) | /* MSEL VALUE */
2475 (uint32_t)pllDirectInput << SYSCON_USBPLLCTRL_BYPASS_SHIFT | /* BYPASS DISABLE */
2476 (uint32_t)pllDirectOutput << SYSCON_USBPLLCTRL_DIRECT_SHIFT | /* DIRECTO DISABLE */
2477 (uint32_t)pllfbsel << SYSCON_USBPLLCTRL_FBSEL_SHIFT; /* FBSEL SELECT */
2478
2479 SYSCON->USBPLLCTRL = usbpllctrl;
2480
2481 POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);
2482
2483 /* Delay for 72 uSec @ 12Mhz for the usb pll to lock */
2484 SDK_DelayAtLeastUs(72U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2485 if (false == pllDirectInput)
2486 {
2487 while (CLOCK_IsUsbPLLLocked() == false)
2488 {
2489 }
2490 }
2491 CLOCK_GetUsbPLLOutFromSetupUpdate(pSetup);
2492 return kStatus_PLL_Success;
2493 }
2494
2495 /* Set System PLL clock based on the input frequency and multiplier */
2496 /*! brief Set PLL output based on the multiplier and input frequency
2497 * param multiply_by : multiplier
2498 * param input_freq : Clock input frequency of the PLL
2499 * return Nothing
2500 * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
2501 * function does not disable or enable PLL power, wait for PLL lock,
2502 * or adjust system voltages. These must be done in the application.
2503 * The function will not alter any source clocks (ie, main systen clock)
2504 * that may use the PLL, so these should be setup prior to and after
2505 * exiting the function.
2506 */
CLOCK_SetupSystemPLLMult(uint32_t multiply_by,uint32_t input_freq)2507 void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq)
2508 {
2509 uint32_t cco_freq = input_freq * multiply_by;
2510 uint32_t pdec = 1U;
2511 uint32_t selr;
2512 uint32_t seli;
2513 uint32_t selp;
2514 uint32_t mdec, ndec;
2515
2516 uint32_t directo = SYSCON_SYSPLLCTRL_DIRECTO(1);
2517
2518 while (cco_freq < 275000000U)
2519 {
2520 multiply_by <<= 1U; /* double value in each iteration */
2521 pdec <<= 1U; /* correspondingly double pdec to cancel effect of double msel */
2522 cco_freq = input_freq * multiply_by;
2523 }
2524 selr = 0U;
2525 if (multiply_by < 60U)
2526 {
2527 seli = (multiply_by & 0x3cU) + 4U;
2528 selp = (multiply_by >> 1U) + 1U;
2529 }
2530 else
2531 {
2532 selp = 31U;
2533 if (multiply_by > 16384U)
2534 {
2535 seli = 1U;
2536 }
2537 else if (multiply_by > 8192U)
2538 {
2539 seli = 2U;
2540 }
2541 else if (multiply_by > 2048U)
2542 {
2543 seli = 4U;
2544 }
2545 else if (multiply_by >= 501U)
2546 {
2547 seli = 8U;
2548 }
2549 else
2550 {
2551 seli = 4U * (1024U / (multiply_by + 9U));
2552 }
2553 }
2554
2555 if (pdec > 1U)
2556 {
2557 directo = 0U; /* use post divider */
2558 pdec = pdec / 2U; /* Account for minus 1 encoding */
2559 /* Translate P value */
2560 switch (pdec)
2561 {
2562 case 1U:
2563 pdec = 0x62U; /* 1 * 2 */
2564 break;
2565 case 2U:
2566 pdec = 0x42U; /* 2 * 2 */
2567 break;
2568 case 4U:
2569 pdec = 0x02U; /* 4 * 2 */
2570 break;
2571 case 8U:
2572 pdec = 0x0bU; /* 8 * 2 */
2573 break;
2574 case 16U:
2575 pdec = 0x11U; /* 16 * 2 */
2576 break;
2577 case 32U:
2578 pdec = 0x08U; /* 32 * 2 */
2579 break;
2580 default:
2581 pdec = 0x08U;
2582 break;
2583 }
2584 }
2585
2586 mdec = PLL_MDEC_VAL_SET(pllEncodeM(multiply_by));
2587 ndec = 0x302U; /* pre divided by 1 (hardcoded) */
2588
2589 SYSCON->SYSPLLCTRL = directo | (selr << SYSCON_SYSPLLCTRL_SELR_SHIFT) | (seli << SYSCON_SYSPLLCTRL_SELI_SHIFT) |
2590 (selp << SYSCON_SYSPLLCTRL_SELP_SHIFT);
2591 SYSCON->SYSPLLPDEC = pdec | (1UL << 7U); /* set Pdec value and assert preq */
2592 SYSCON->SYSPLLNDEC = ndec | (1UL << 10U); /* set Pdec value and assert preq */
2593 SYSCON->SYSPLLMDEC = (1UL << 17U) | mdec; /* select non sscg MDEC value, assert mreq and select mdec value */
2594 }
2595
2596 /* Enable USB DEVICE FULL SPEED clock */
2597 /*! brief Enable USB Device FS clock.
2598 * param src : clock source
2599 * param freq: clock frequency
2600 * Enable USB Device Full Speed clock.
2601 */
CLOCK_EnableUsbfs0DeviceClock(clock_usb_src_t src,uint32_t freq)2602 bool CLOCK_EnableUsbfs0DeviceClock(clock_usb_src_t src, uint32_t freq)
2603 {
2604 bool ret = true;
2605
2606 CLOCK_DisableClock(kCLOCK_Usbd0);
2607
2608 if (kCLOCK_UsbSrcFro == src)
2609 {
2610 switch (freq)
2611 {
2612 case 96000000U:
2613 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2614 break;
2615
2616 case 48000000U:
2617 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
2618 break;
2619
2620 default:
2621 ret = false;
2622 break;
2623 }
2624 /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
2625 SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
2626 SYSCON_FROCTRL_USBCLKADJ_MASK;
2627 /* Select FRO 96 or 48 MHz */
2628 CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
2629 }
2630 else
2631 {
2632 /*Set the USB PLL as the Usb0 CLK*/
2633 POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);
2634
2635 usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};
2636
2637 (void)CLOCK_SetUsbPLLFreq(&pll_setup);
2638 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2639 CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK);
2640 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2641 }
2642 CLOCK_EnableClock(kCLOCK_Usbd0);
2643 CLOCK_EnableClock(kCLOCK_UsbRam1);
2644
2645 return ret;
2646 }
2647
2648 /* Enable USB HOST FULL SPEED clock */
2649 /*! brief Enable USB HOST FS clock.
2650 * param src : clock source
2651 * param freq: clock frequency
2652 * Enable USB HOST Full Speed clock.
2653 */
CLOCK_EnableUsbfs0HostClock(clock_usb_src_t src,uint32_t freq)2654 bool CLOCK_EnableUsbfs0HostClock(clock_usb_src_t src, uint32_t freq)
2655 {
2656 bool ret = true;
2657
2658 CLOCK_DisableClock(kCLOCK_Usbhmr0);
2659 CLOCK_DisableClock(kCLOCK_Usbhsl0);
2660
2661 if (kCLOCK_UsbSrcFro == src)
2662 {
2663 switch (freq)
2664 {
2665 case 96000000U:
2666 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2667 break;
2668
2669 case 48000000U:
2670 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
2671 break;
2672
2673 default:
2674 ret = false;
2675 break;
2676 }
2677 /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
2678 SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
2679 SYSCON_FROCTRL_USBCLKADJ_MASK;
2680 /* Select FRO 96 or 48 MHz */
2681 CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
2682 }
2683 else
2684 {
2685 /*Set the USB PLL as the Usb0 CLK*/
2686 POWER_DisablePD(kPDRUNCFG_PD_USB_PLL);
2687
2688 usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};
2689
2690 (void)CLOCK_SetUsbPLLFreq(&pll_setup);
2691 CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1U, false);
2692 CLOCK_AttachClk(kUSB_PLL_to_USB0_CLK);
2693 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2694 }
2695 CLOCK_EnableClock(kCLOCK_Usbhmr0);
2696 CLOCK_EnableClock(kCLOCK_Usbhsl0);
2697 CLOCK_EnableClock(kCLOCK_UsbRam1);
2698
2699 return ret;
2700 }
2701
2702 /* Enable USB DEVICE HIGH SPEED clock */
2703 /*! brief Enable USB Device HS clock.
2704 * param src : clock source
2705 * param freq: clock frequency
2706 * Enable USB Device High Speed clock.
2707 */
CLOCK_EnableUsbhs0DeviceClock(clock_usb_src_t src,uint32_t freq)2708 bool CLOCK_EnableUsbhs0DeviceClock(clock_usb_src_t src, uint32_t freq)
2709 {
2710 bool ret = true;
2711 CLOCK_DisableClock(kCLOCK_Usbd1);
2712 /* Power on the VD5 for USB PHY */
2713 POWER_SetUsbPhy();
2714 if (kCLOCK_UsbSrcFro == src)
2715 {
2716 switch (freq)
2717 {
2718 case 96000000U:
2719 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2720 break;
2721
2722 case 48000000U:
2723 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
2724 break;
2725
2726 default:
2727 ret = false;
2728 break;
2729 }
2730 /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
2731 SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
2732 SYSCON_FROCTRL_USBCLKADJ_MASK;
2733 /* Select FRO 96 or 48 MHz */
2734 CLOCK_AttachClk(kFRO_HF_to_USB1_CLK);
2735 }
2736 else
2737 {
2738 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2739 usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};
2740
2741 (void)CLOCK_SetUsbPLLFreq(&pll_setup);
2742
2743 /* Select USB PLL output as USB clock src */
2744 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false);
2745 CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK);
2746 }
2747
2748 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2749 /* Enable USB1D and USB1RAM */
2750 CLOCK_EnableClock(kCLOCK_Usbd1);
2751 CLOCK_EnableClock(kCLOCK_UsbRam1);
2752 POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */
2753 return ret;
2754 }
2755
2756 /* Enable USB HOST HIGH SPEED clock */
2757 /*! brief Enable USB HOST HS clock.
2758 * param src : clock source
2759 * param freq: clock frequency
2760 * Enable USB HOST High Speed clock.
2761 */
CLOCK_EnableUsbhs0HostClock(clock_usb_src_t src,uint32_t freq)2762 bool CLOCK_EnableUsbhs0HostClock(clock_usb_src_t src, uint32_t freq)
2763 {
2764 bool ret = true;
2765 CLOCK_DisableClock(kCLOCK_Usbh1);
2766 /* Power on the VD5 for USB PHY */
2767 POWER_SetUsbPhy();
2768 if (kCLOCK_UsbSrcFro == src)
2769 {
2770 switch (freq)
2771 {
2772 case 96000000U:
2773 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 2, false); /*!< Div by 2 to get 48MHz, no divider reset */
2774 break;
2775
2776 case 48000000U:
2777 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1, false); /*!< Div by 1 to get 48MHz, no divider reset */
2778 break;
2779
2780 default:
2781 ret = false;
2782 break;
2783 }
2784 /* Turn ON FRO HF and let it adjust TRIM value based on USB SOF */
2785 SYSCON->FROCTRL = (SYSCON->FROCTRL & ~((0x01UL << 15U) | (0xFUL << 26U))) | SYSCON_FROCTRL_HSPDCLK_MASK |
2786 SYSCON_FROCTRL_USBCLKADJ_MASK;
2787 /* Select FRO 96 or 48 MHz */
2788 CLOCK_AttachClk(kFRO_HF_to_USB1_CLK);
2789 }
2790 else
2791 {
2792 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2793 usb_pll_setup_t pll_setup = {0x3FU, 0x01U, 0x03U, false, false, false, 12000000U};
2794
2795 (void)CLOCK_SetUsbPLLFreq(&pll_setup);
2796
2797 /* Select USB PLL output as USB clock src */
2798 CLOCK_SetClkDiv(kCLOCK_DivUsb1Clk, 1U, false);
2799 CLOCK_AttachClk(kUSB_PLL_to_USB1_CLK);
2800 }
2801
2802 SDK_DelayAtLeastUs(50U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
2803 /* Enable USBh1 and USB1RAM */
2804 CLOCK_EnableClock(kCLOCK_Usbh1);
2805 CLOCK_EnableClock(kCLOCK_UsbRam1);
2806 POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /* Turn on power for USB PHY */
2807 return ret;
2808 }
2809