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