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