1 /*
2  * Copyright 2019-2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_clock.h"
9 #include "fsl_pmu.h"
10 #include "fsl_anatop_ai.h"
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.clock"
14 #endif
15 
16 /*******************************************************************************
17  * Definitions
18  ******************************************************************************/
19 /* To make full use of CM7 hardware FPU, use double instead of uint64_t in clock driver to
20 achieve better performance, it is depend on the IDE Floating point settings, if double precision is selected
21 in IDE, clock_64b_t will switch to double type automatically. only support IAR and MDK here */
22 #if __FPU_USED
23 
24 #if (defined(__ICCARM__))
25 
26 #if (__ARMVFP__ >= __ARMFPV5__) && \
27     (__ARM_FP == 0xE) /*0xe implies support for half, single and double precision operations*/
28 typedef double clock_64b_t;
29 #else
30 typedef uint64_t clock_64b_t;
31 #endif
32 
33 #elif (defined(__GNUC__))
34 
35 #if (__ARM_FP == 0xE) /*0xe implies support for half, single and double precision operations*/
36 typedef double clock_64b_t;
37 #else
38 typedef uint64_t clock_64b_t;
39 #endif
40 
41 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
42 
43 #if defined __TARGET_FPU_FPV5_D16
44 typedef double clock_64b_t;
45 #else
46 typedef uint64_t clock_64b_t;
47 #endif
48 
49 #else
50 typedef uint64_t clock_64b_t;
51 #endif
52 
53 #else
54 typedef uint64_t clock_64b_t;
55 #endif
56 
57 #define PLL_AI_CTRL0_REG     kAI_PLL1G_CTRL0
58 #define PLL_AI_CTRL0_SET_REG kAI_PLL1G_CTRL0_SET
59 #define PLL_AI_CTRL0_CLR_REG kAI_PLL1G_CTRL0_CLR
60 #define PLL_AI_CTRL1_REG     kAI_PLL1G_CTRL1
61 #define PLL_AI_CTRL1_SET_REG kAI_PLL1G_CTRL1_SET
62 #define PLL_AI_CTRL1_CLR_REG kAI_PLL1G_CTRL1_CLR
63 #define PLL_AI_CTRL2_REG     kAI_PLL1G_CTRL2
64 #define PLL_AI_CTRL2_SET_REG kAI_PLL1G_CTRL2_SET
65 #define PLL_AI_CTRL2_CLR_REG kAI_PLL1G_CTRL2_CLR
66 #define PLL_AI_CTRL3_REG     kAI_PLL1G_CTRL3
67 #define PLL_AI_CTRL3_SET_REG kAI_PLL1G_CTRL3_SET
68 #define PLL_AI_CTRL3_CLR_REG kAI_PLL1G_CTRL3_CLR
69 
70 #define PLL_AI_CTRL0_HOLD_RING_OFF_MASK AI_PLL1G_CTRL0_HOLD_RING_OFF_MASK
71 
72 #define PLL_AI_CTRL0_POWER_UP_MASK AI_PLL1G_CTRL0_POWER_UP_MASK
73 
74 #define PLL_AI_CTRL0_ENABLE_MASK AI_PLL1G_CTRL0_ENABLE_MASK
75 
76 #define PLL_AI_CTRL0_BYPASS_MASK AI_PLL1G_CTRL0_BYPASS_MASK
77 
78 #define PLL_AI_CTRL0_PLL_REG_EN_MASK AI_PLL1G_CTRL0_PLL_REG_EN_MASK
79 /*******************************************************************************
80  * Variables
81  ******************************************************************************/
82 
83 /*******************************************************************************
84  * Prototypes
85  ******************************************************************************/
86 static void ANATOP_PllSetPower(anatop_ai_itf_t itf, bool enable);
87 static void ANATOP_PllBypass(anatop_ai_itf_t itf, bool bypass);
88 static void ANATOP_PllEnablePllReg(anatop_ai_itf_t itf, bool enable);
89 static void ANATOP_PllHoldRingOff(anatop_ai_itf_t itf, bool off);
90 static void ANATOP_PllToggleHoldRingOff(anatop_ai_itf_t itf, uint32_t delayUsValue);
91 static void ANATOP_PllEnableClk(anatop_ai_itf_t itf, bool enable);
92 static void ANATOP_PllConfigure(anatop_ai_itf_t itf,
93                                 uint8_t div,
94                                 uint32_t numer,
95                                 uint8_t post_div,
96                                 uint32_t denom,
97                                 const clock_pll_ss_config_t *ss);
98 static void ANATOP_AudioPllGate(bool enable);
99 static void ANATOP_AudioPllSwEnClk(bool enable);
100 static void ANATOP_VideoPllGate(bool enable);
101 static void ANATOP_VideoPllSwEnClk(bool enable);
102 static void ANATOP_SysPll1Gate(bool enable);
103 static void ANATOP_SysPll1Div2En(bool enable);
104 static void ANATOP_SysPll1Div5En(bool enable);
105 static void ANATOP_SysPll1SwEnClk(bool enable);
106 static void ANATOP_SysPll1WaitStable(void);
107 static void ANATOP_PllEnableSs(anatop_ai_itf_t itf, bool enable);
108 #ifndef GET_FREQ_FROM_OBS
109 static uint32_t CLOCK_GetAvPllFreq(clock_pll_t pll);
110 #endif
111 /*******************************************************************************
112  * Code
113  ******************************************************************************/
114 
115 #define ARM_PLL_DIV_SEL_MIN 104
116 #define ARM_PLL_DIV_SEL_MAX 208
117 
CLOCK_InitArmPll(const clock_arm_pll_config_t * config)118 void CLOCK_InitArmPll(const clock_arm_pll_config_t *config)
119 {
120     assert((config->loopDivider <= (uint32_t)ARM_PLL_DIV_SEL_MAX) &&
121            (config->loopDivider >= (uint32_t)ARM_PLL_DIV_SEL_MIN));
122 
123     uint32_t reg;
124 
125     if (((ANADIG_PLL->ARM_PLL_CTRL & ANADIG_PLL_ARM_PLL_CTRL_POWERUP_MASK) != 0UL) &&
126         ((ANADIG_PLL->ARM_PLL_CTRL & ANADIG_PLL_ARM_PLL_CTRL_DIV_SELECT_MASK) ==
127          ANADIG_PLL_ARM_PLL_CTRL_DIV_SELECT(config->loopDivider)) &&
128         ((ANADIG_PLL->ARM_PLL_CTRL & ANADIG_PLL_ARM_PLL_CTRL_POST_DIV_SEL_MASK) ==
129          ANADIG_PLL_ARM_PLL_CTRL_POST_DIV_SEL(config->postDivider)))
130     {
131         /* no need to reconfigure the PLL if all the configuration is the same */
132         if ((ANADIG_PLL->ARM_PLL_CTRL & ANADIG_PLL_ARM_PLL_CTRL_ENABLE_CLK_MASK) == 0UL)
133         {
134             ANADIG_PLL->ARM_PLL_CTRL |= ANADIG_PLL_ARM_PLL_CTRL_ENABLE_CLK_MASK;
135         }
136         if ((ANADIG_PLL->ARM_PLL_CTRL & ANADIG_PLL_ARM_PLL_CTRL_ARM_PLL_GATE_MASK) != 0UL)
137         {
138             ANADIG_PLL->ARM_PLL_CTRL &= ~ANADIG_PLL_ARM_PLL_CTRL_ARM_PLL_GATE_MASK;
139         }
140         return;
141     }
142 
143     PMU_StaticEnablePllLdo(ANADIG_PMU);
144 
145     reg = ANADIG_PLL->ARM_PLL_CTRL & (~ANADIG_PLL_ARM_PLL_CTRL_ARM_PLL_STABLE_MASK);
146     if ((reg & (ANADIG_PLL_ARM_PLL_CTRL_POWERUP_MASK | ANADIG_PLL_ARM_PLL_CTRL_ENABLE_CLK_MASK)) != 0UL)
147     {
148         /* Power down the PLL. */
149         reg &= ~(ANADIG_PLL_ARM_PLL_CTRL_POWERUP_MASK | ANADIG_PLL_ARM_PLL_CTRL_ENABLE_CLK_MASK);
150         reg |= ANADIG_PLL_ARM_PLL_CTRL_ARM_PLL_GATE_MASK;
151         ANADIG_PLL->ARM_PLL_CTRL = reg;
152     }
153 
154     /* Set the configuration. */
155     reg &= ~(ANADIG_PLL_ARM_PLL_CTRL_DIV_SELECT_MASK | ANADIG_PLL_ARM_PLL_CTRL_POST_DIV_SEL_MASK);
156     reg |= (ANADIG_PLL_ARM_PLL_CTRL_DIV_SELECT(config->loopDivider) |
157             ANADIG_PLL_ARM_PLL_CTRL_POST_DIV_SEL(config->postDivider)) |
158            ANADIG_PLL_ARM_PLL_CTRL_ARM_PLL_GATE_MASK | ANADIG_PLL_ARM_PLL_CTRL_POWERUP_MASK |
159            ANADIG_PLL_ARM_PLL_CTRL_HOLD_RING_OFF_MASK;
160     ANADIG_PLL->ARM_PLL_CTRL = reg;
161     __DSB();
162     __ISB();
163     SDK_DelayAtLeastUs(30, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
164 
165     reg &= ~ANADIG_PLL_SYS_PLL2_CTRL_HOLD_RING_OFF_MASK;
166     ANADIG_PLL->ARM_PLL_CTRL = reg;
167     /* Wait for the PLL stable, */
168     while (0U == (ANADIG_PLL->ARM_PLL_CTRL & ANADIG_PLL_ARM_PLL_CTRL_ARM_PLL_STABLE_MASK))
169     {
170     }
171 
172     /* Enable and ungate the clock. */
173     reg |= ANADIG_PLL_ARM_PLL_CTRL_ENABLE_CLK_MASK;
174     reg &= ~ANADIG_PLL_ARM_PLL_CTRL_ARM_PLL_GATE_MASK;
175     ANADIG_PLL->ARM_PLL_CTRL = reg;
176 }
177 
CLOCK_DeinitArmPll(void)178 void CLOCK_DeinitArmPll(void)
179 {
180     uint32_t reg = ANADIG_PLL->ARM_PLL_CTRL & (~ANADIG_PLL_ARM_PLL_CTRL_ARM_PLL_STABLE_MASK);
181 
182     reg &= ~(ANADIG_PLL_ARM_PLL_CTRL_POWERUP_MASK | ANADIG_PLL_ARM_PLL_CTRL_ENABLE_CLK_MASK);
183     reg |= ANADIG_PLL_ARM_PLL_CTRL_ARM_PLL_GATE_MASK;
184     ANADIG_PLL->ARM_PLL_CTRL = reg;
185 }
186 
CLOCK_CalcPllSpreadSpectrum(uint32_t factor,uint32_t range,uint32_t mod,clock_pll_ss_config_t * ss)187 void CLOCK_CalcPllSpreadSpectrum(uint32_t factor, uint32_t range, uint32_t mod, clock_pll_ss_config_t *ss)
188 {
189     assert(ss != NULL);
190 
191     ss->stop = (uint16_t)(factor * range / XTAL_FREQ);
192     ss->step = (uint16_t)((mod << 1UL) * (uint32_t)(ss->stop) / XTAL_FREQ);
193 }
194 
195 /* 528PLL */
CLOCK_InitSysPll2(const clock_sys_pll2_config_t * config)196 void CLOCK_InitSysPll2(const clock_sys_pll2_config_t *config)
197 {
198     uint32_t reg;
199 
200     if ((ANADIG_PLL->SYS_PLL2_CTRL & ANADIG_PLL_SYS_PLL2_CTRL_POWERUP_MASK) != 0UL)
201     {
202         if ((config == NULL) ||
203             ((0UL == (ANADIG_PLL->SYS_PLL2_SS & ANADIG_PLL_SYS_PLL2_SS_ENABLE_MASK)) && (!config->ssEnable)) ||
204             ((ANADIG_PLL_SYS_PLL2_SS_ENABLE(config->ssEnable) | ANADIG_PLL_SYS_PLL2_SS_STOP(config->ss->stop) |
205               ANADIG_PLL_SYS_PLL2_SS_STEP(config->ss->step)) == ANADIG_PLL->SYS_PLL2_SS))
206         {
207             /* no need to reconfigure the PLL if all the configuration is the same */
208             if (0UL == (ANADIG_PLL->SYS_PLL2_CTRL & ANADIG_PLL_SYS_PLL2_CTRL_ENABLE_CLK_MASK))
209             {
210                 ANADIG_PLL->SYS_PLL2_CTRL |= ANADIG_PLL_SYS_PLL2_CTRL_ENABLE_CLK_MASK;
211             }
212 
213             if ((ANADIG_PLL->SYS_PLL2_CTRL & ANADIG_PLL_SYS_PLL2_CTRL_SYS_PLL2_GATE_MASK) != 0UL)
214             {
215                 ANADIG_PLL->SYS_PLL2_CTRL &= ~ANADIG_PLL_SYS_PLL2_CTRL_SYS_PLL2_GATE_MASK;
216             }
217             return;
218         }
219     }
220 
221     PMU_StaticEnablePllLdo(ANADIG_PMU);
222     /* Gate all PFDs */
223     ANADIG_PLL->SYS_PLL2_PFD |=
224         ANADIG_PLL_SYS_PLL2_PFD_PFD0_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL2_PFD_PFD1_DIV1_CLKGATE(1) |
225         ANADIG_PLL_SYS_PLL2_PFD_PFD2_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL2_PFD_PFD3_DIV1_CLKGATE(1);
226 
227     reg = ANADIG_PLL->SYS_PLL2_CTRL;
228     if ((reg & (ANADIG_PLL_SYS_PLL2_CTRL_POWERUP_MASK | ANADIG_PLL_SYS_PLL2_CTRL_ENABLE_CLK_MASK)) != 0UL)
229     {
230         /* Power down the PLL. */
231         reg &= ~(ANADIG_PLL_SYS_PLL2_CTRL_POWERUP_MASK | ANADIG_PLL_SYS_PLL2_CTRL_ENABLE_CLK_MASK);
232         reg |= ANADIG_PLL_SYS_PLL2_CTRL_SYS_PLL2_GATE_MASK;
233         ANADIG_PLL->SYS_PLL2_CTRL = reg;
234     }
235 
236     /* Config PLL */
237     if ((config != NULL) && (config->ssEnable) && (config->ss != NULL))
238     {
239         ANADIG_PLL->SYS_PLL2_MFD = ANADIG_PLL_SYS_PLL2_MFD_MFD(config->mfd);
240         ANADIG_PLL->SYS_PLL2_SS  = (ANADIG_PLL_SYS_PLL2_SS_ENABLE_MASK | ANADIG_PLL_SYS_PLL2_SS_STOP(config->ss->stop) |
241                                    ANADIG_PLL_SYS_PLL2_SS_STEP(config->ss->step));
242     }
243 
244     /* REG_EN = 1, GATE = 1, DIV_SEL = 0, POWERUP = 0 */
245     reg &= ~(ANADIG_PLL_SYS_PLL2_CTRL_PLL_REG_EN_MASK | ANADIG_PLL_SYS_PLL2_CTRL_SYS_PLL2_GATE_MASK);
246     reg |= ANADIG_PLL_SYS_PLL2_CTRL_PLL_REG_EN(1) | ANADIG_PLL_SYS_PLL2_CTRL_SYS_PLL2_GATE(1);
247     ANADIG_PLL->SYS_PLL2_CTRL = reg;
248     /* Wait until LDO is stable */
249     SDK_DelayAtLeastUs(30, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
250 
251     /* REG_EN = 1, GATE = 1, DIV_SEL = 0, POWERUP = 1, HOLDRING_OFF = 1 */
252     reg &= ~(ANADIG_PLL_SYS_PLL2_CTRL_POWERUP_MASK);
253     reg |= ANADIG_PLL_SYS_PLL2_CTRL_POWERUP(1) | ANADIG_PLL_SYS_PLL2_CTRL_HOLD_RING_OFF_MASK;
254     ANADIG_PLL->SYS_PLL2_CTRL = reg;
255     SDK_DelayAtLeastUs(250, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
256 
257     /* REG_EN = 1, GATE = 1, DIV_SEL = 0, POWERUP = 1, HOLDRING_OFF = 0 */
258     reg &= ~ANADIG_PLL_SYS_PLL2_CTRL_HOLD_RING_OFF_MASK;
259     ANADIG_PLL->SYS_PLL2_CTRL = reg;
260     /* Wait for PLL stable */
261     while (ANADIG_PLL_SYS_PLL2_CTRL_SYS_PLL2_STABLE_MASK !=
262            (ANADIG_PLL->SYS_PLL2_CTRL & ANADIG_PLL_SYS_PLL2_CTRL_SYS_PLL2_STABLE_MASK))
263     {
264     }
265 
266     /* REG_EN = 1, GATE = 1, DIV_SEL = 0, POWERUP = 1, HOLDRING_OFF = 0, CLK = 1*/
267     reg |= ANADIG_PLL_SYS_PLL2_CTRL_ENABLE_CLK_MASK;
268     ANADIG_PLL->SYS_PLL2_CTRL = reg;
269 
270     /* REG_EN = 1, GATE = 0, DIV_SEL = 0, POWERUP = 1, HOLDRING_OFF = 0, CLK = 1*/
271     reg &= ~ANADIG_PLL_SYS_PLL2_CTRL_SYS_PLL2_GATE_MASK;
272     ANADIG_PLL->SYS_PLL2_CTRL = reg;
273     ANADIG_PLL->SYS_PLL2_PFD &=
274         ~(ANADIG_PLL_SYS_PLL2_PFD_PFD0_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL2_PFD_PFD1_DIV1_CLKGATE(1) |
275           ANADIG_PLL_SYS_PLL2_PFD_PFD2_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL2_PFD_PFD3_DIV1_CLKGATE(1));
276 }
277 
CLOCK_DeinitSysPll2(void)278 void CLOCK_DeinitSysPll2(void)
279 {
280     ANADIG_PLL->SYS_PLL2_PFD |=
281         ANADIG_PLL_SYS_PLL2_PFD_PFD0_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL2_PFD_PFD1_DIV1_CLKGATE(1) |
282         ANADIG_PLL_SYS_PLL2_PFD_PFD2_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL2_PFD_PFD3_DIV1_CLKGATE(1);
283 
284     ANADIG_PLL->SYS_PLL2_CTRL |= ANADIG_PLL_SYS_PLL2_CTRL_SYS_PLL2_GATE_MASK;
285     ANADIG_PLL->SYS_PLL2_CTRL &= ~(ANADIG_PLL_SYS_PLL2_CTRL_ENABLE_CLK_MASK | ANADIG_PLL_SYS_PLL2_CTRL_POWERUP_MASK |
286                                    ANADIG_PLL_SYS_PLL2_CTRL_PLL_REG_EN_MASK);
287 
288     ANADIG_PLL->SYS_PLL2_SS &= ~ANADIG_PLL_SYS_PLL2_SS_ENABLE_MASK;
289 }
290 
291 /*!
292  * brief Check if Sys PLL2 PFD is enabled
293  *
294  * param pfd PFD control name
295  * return PFD bypass status.
296  *         - true: power on.
297  *         - false: power off.
298  * note Only useful in software control mode.
299  */
CLOCK_IsSysPll2PfdEnabled(clock_pfd_t pfd)300 bool CLOCK_IsSysPll2PfdEnabled(clock_pfd_t pfd)
301 {
302     return ((ANADIG_PLL->SYS_PLL2_PFD & (uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_DIV1_CLKGATE_MASK
303                                             << (8UL * (uint8_t)pfd)) == 0U);
304 }
305 
306 #define PFD_FRAC_MIN 12U
307 #define PFD_FRAC_MAX 35U
CLOCK_InitPfd(clock_pll_t pll,clock_pfd_t pfd,uint8_t frac)308 void CLOCK_InitPfd(clock_pll_t pll, clock_pfd_t pfd, uint8_t frac)
309 {
310     volatile uint32_t *pfdCtrl = NULL, *pfdUpdate = NULL, stable;
311     uint32_t regFracVal;
312     bool pfdGated;
313 
314     assert(frac <= (uint8_t)PFD_FRAC_MAX);
315     assert(frac >= (uint8_t)PFD_FRAC_MIN);
316 
317     switch (pll)
318     {
319         case kCLOCK_PllSys2:
320             pfdCtrl   = &ANADIG_PLL->SYS_PLL2_PFD;
321             pfdUpdate = &ANADIG_PLL->SYS_PLL2_UPDATE;
322             break;
323         case kCLOCK_PllSys3:
324             pfdCtrl   = &ANADIG_PLL->SYS_PLL3_PFD;
325             pfdUpdate = &ANADIG_PLL->SYS_PLL3_UPDATE;
326             break;
327         default:
328             /* Wrong input parameter pll. */
329             assert(false);
330             break;
331     }
332     regFracVal = ((*pfdCtrl) & ((uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_FRAC_MASK << (8UL * (uint32_t)pfd))) >>
333                  (8UL * (uint32_t)pfd);
334     pfdGated =
335         (bool)(((*pfdCtrl) & ((uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_DIV1_CLKGATE_MASK << (8UL * (uint32_t)pfd))) >>
336                (8UL >> (uint32_t)pfd));
337     if ((regFracVal == (uint32_t)frac) && (!pfdGated))
338     {
339         return;
340     }
341 
342     stable = *pfdCtrl & ((uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_STABLE_MASK << (8UL * (uint32_t)pfd));
343     *pfdCtrl |= ((uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_DIV1_CLKGATE_MASK << (8UL * (uint32_t)pfd));
344 
345     /* all pfds support to be updated on-the-fly after corresponding PLL is stable */
346     *pfdCtrl &= ~((uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_FRAC_MASK << (8UL * (uint32_t)pfd));
347     *pfdCtrl |= (ANADIG_PLL_SYS_PLL2_PFD_PFD0_FRAC(frac) << (8UL * (uint32_t)pfd));
348 
349     *pfdUpdate ^= ((uint32_t)ANADIG_PLL_SYS_PLL2_UPDATE_PFD0_UPDATE_MASK << (uint32_t)pfd);
350     *pfdCtrl &= ~((uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_DIV1_CLKGATE_MASK << (8UL * (uint32_t)pfd));
351     /* Wait for stablizing */
352     while (stable == (*pfdCtrl & ((uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_STABLE_MASK << (8UL * (uint32_t)pfd))))
353     {
354     }
355 }
356 
357 /*!
358  * brief De-initialize selected PLL PFD.
359  *
360  * param pll Which PLL of targeting PFD to be operated.
361  * param pfd Which PFD clock to enable.
362  */
CLOCK_DeinitPfd(clock_pll_t pll,clock_pfd_t pfd)363 void CLOCK_DeinitPfd(clock_pll_t pll, clock_pfd_t pfd)
364 {
365     volatile uint32_t *pfdCtrl = NULL;
366 
367     switch (pll)
368     {
369         case kCLOCK_PllSys2:
370         {
371             pfdCtrl = &ANADIG_PLL->SYS_PLL2_PFD;
372             break;
373         }
374         case kCLOCK_PllSys3:
375         {
376             pfdCtrl = &ANADIG_PLL->SYS_PLL3_PFD;
377             break;
378         }
379         default:
380         {
381             /* Wrong input parameter pll. */
382             assert(false);
383             break;
384         }
385     }
386 
387     /* Clock gate the selected pfd. */
388     *pfdCtrl |= ((uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_DIV1_CLKGATE_MASK << (8UL * (uint32_t)pfd));
389 }
390 
391 #ifndef GET_FREQ_FROM_OBS
CLOCK_GetPfdFreq(clock_pll_t pll,clock_pfd_t pfd)392 uint32_t CLOCK_GetPfdFreq(clock_pll_t pll, clock_pfd_t pfd)
393 {
394     uint32_t pllFreq = 0UL, frac = 0UL;
395     assert((pll == kCLOCK_PllSys2) || (pll == kCLOCK_PllSys3));
396 
397     switch (pll)
398     {
399         case kCLOCK_PllSys2:
400             frac    = (ANADIG_PLL->SYS_PLL2_PFD &
401                     ((uint32_t)ANADIG_PLL_SYS_PLL2_PFD_PFD0_FRAC_MASK << (8UL * (uint32_t)pfd)));
402             pllFreq = (uint32_t)SYS_PLL2_FREQ;
403             break;
404         case kCLOCK_PllSys3:
405             frac    = (ANADIG_PLL->SYS_PLL3_PFD &
406                     ((uint32_t)ANADIG_PLL_SYS_PLL3_PFD_PFD0_FRAC_MASK << (8UL * (uint32_t)pfd)));
407             pllFreq = (uint32_t)SYS_PLL3_FREQ;
408             break;
409         default:
410             /* Wrong input parameter pll. */
411             assert(false);
412             break;
413     }
414 
415     frac = frac >> (8UL * (uint32_t)pfd);
416     assert(frac >= (uint32_t)PFD_FRAC_MIN);
417     assert(frac <= (uint32_t)PFD_FRAC_MAX);
418     return ((frac != 0UL) ? (pllFreq / frac * 18UL) : 0UL);
419 }
420 #else
CLOCK_GetPfdFreq(clock_pll_t pll,clock_pfd_t pfd)421 uint32_t CLOCK_GetPfdFreq(clock_pll_t pll, clock_pfd_t pfd)
422 {
423     uint32_t freq = 0;
424     assert((pll == kCLOCK_PllSys2) || (pll == kCLOCK_PllSys3));
425 
426     switch (pll)
427     {
428         case kCLOCK_PllSys2:
429             /* SYS_PLL2_PFD0 OBS index starts from 234 */
430             freq = CLOCK_GetFreqFromObs(pfd + 234, 2);
431             break;
432         case kCLOCK_PllSys3:
433             /* SYS_PLL3_PFD0 OBS index starts from 241 */
434             freq = CLOCK_GetFreqFromObs(pfd + 241, 2);
435             break;
436         default:
437             assert(false);
438     }
439     return freq;
440 }
441 #endif
442 
443 /* 480PLL */
CLOCK_InitSysPll3(void)444 void CLOCK_InitSysPll3(void)
445 {
446     if (0UL != (ANADIG_PLL->SYS_PLL3_CTRL & ANADIG_PLL_SYS_PLL3_CTRL_POWERUP_MASK))
447     {
448         /* no need to reconfigure the PLL if all the configuration is the same */
449         if (0UL == (ANADIG_PLL->SYS_PLL3_CTRL & ANADIG_PLL_SYS_PLL3_CTRL_ENABLE_CLK_MASK))
450         {
451             ANADIG_PLL->SYS_PLL3_CTRL |= ANADIG_PLL_SYS_PLL3_CTRL_ENABLE_CLK_MASK;
452         }
453 
454         if (0UL != (ANADIG_PLL->SYS_PLL3_CTRL & ANADIG_PLL_SYS_PLL3_CTRL_SYS_PLL3_GATE_MASK))
455         {
456             ANADIG_PLL->SYS_PLL3_CTRL &= ~ANADIG_PLL_SYS_PLL3_CTRL_SYS_PLL3_GATE_MASK;
457         }
458         return;
459     }
460 
461     PMU_StaticEnablePllLdo(ANADIG_PMU);
462 
463     /* Gate all PFDs */
464     ANADIG_PLL->SYS_PLL3_PFD |=
465         ANADIG_PLL_SYS_PLL3_PFD_PFD0_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL3_PFD_PFD1_DIV1_CLKGATE(1) |
466         ANADIG_PLL_SYS_PLL3_PFD_PFD2_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL3_PFD_PFD3_DIV1_CLKGATE(1);
467     /*
468      * 1. configure PLL registres
469      * 2. Enable internal LDO
470      * 3. Wait LDO stable
471      * 4. Power up PLL, assert hold_ring_off (only needed for avpll)
472      * 5. At half lock time, de-asserted hold_ring_off (only needed for avpll)
473      * 6. Wait PLL lock
474      * 7. Enable clock output, release pfd_gate
475      */
476     ANADIG_PLL->SYS_PLL3_CTRL |= ANADIG_PLL_SYS_PLL3_CTRL_PLL_REG_EN(1) | ANADIG_PLL_SYS_PLL3_CTRL_SYS_PLL3_GATE(1);
477     SDK_DelayAtLeastUs(30, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
478 
479     ANADIG_PLL->SYS_PLL3_CTRL |= ANADIG_PLL_SYS_PLL3_CTRL_POWERUP(1) | ANADIG_PLL_SYS_PLL3_CTRL_HOLD_RING_OFF_MASK;
480     SDK_DelayAtLeastUs(30, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
481 
482     ANADIG_PLL->SYS_PLL3_CTRL &= ~ANADIG_PLL_SYS_PLL3_CTRL_HOLD_RING_OFF_MASK;
483 
484     /* Wait for PLL stable */
485     while (ANADIG_PLL_SYS_PLL3_CTRL_SYS_PLL3_STABLE_MASK !=
486            (ANADIG_PLL->SYS_PLL3_CTRL & ANADIG_PLL_SYS_PLL3_CTRL_SYS_PLL3_STABLE_MASK))
487     {
488     }
489 
490     ANADIG_PLL->SYS_PLL3_CTRL |= ANADIG_PLL_SYS_PLL3_CTRL_ENABLE_CLK(1) | ANADIG_PLL_SYS_PLL3_CTRL_SYS_PLL3_DIV2(1);
491 
492     ANADIG_PLL->SYS_PLL3_CTRL &= ~ANADIG_PLL_SYS_PLL3_CTRL_SYS_PLL3_GATE_MASK;
493 }
494 
CLOCK_DeinitSysPll3(void)495 void CLOCK_DeinitSysPll3(void)
496 {
497     ANADIG_PLL->SYS_PLL3_PFD |=
498         ANADIG_PLL_SYS_PLL3_PFD_PFD0_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL3_PFD_PFD1_DIV1_CLKGATE(1) |
499         ANADIG_PLL_SYS_PLL3_PFD_PFD2_DIV1_CLKGATE(1) | ANADIG_PLL_SYS_PLL3_PFD_PFD3_DIV1_CLKGATE(1);
500 
501     ANADIG_PLL->SYS_PLL3_CTRL |= ANADIG_PLL_SYS_PLL3_CTRL_SYS_PLL3_GATE_MASK;
502     ANADIG_PLL->SYS_PLL3_CTRL &= ~(ANADIG_PLL_SYS_PLL3_CTRL_ENABLE_CLK_MASK | ANADIG_PLL_SYS_PLL3_CTRL_POWERUP_MASK |
503                                    ANADIG_PLL_SYS_PLL3_CTRL_PLL_REG_EN_MASK);
504 }
505 
506 /*!
507  * brief Check if Sys PLL3 PFD is enabled
508  *
509  * param pfd PFD control name
510  * return PFD bypass status.
511  *         - true: power on.
512  *         - false: power off.
513  * note Only useful in software control mode.
514  */
CLOCK_IsSysPll3PfdEnabled(clock_pfd_t pfd)515 bool CLOCK_IsSysPll3PfdEnabled(clock_pfd_t pfd)
516 {
517     return ((ANADIG_PLL->SYS_PLL3_PFD & (uint32_t)ANADIG_PLL_SYS_PLL3_PFD_PFD0_DIV1_CLKGATE_MASK
518                                             << (8UL * (uint8_t)pfd)) == 0U);
519 }
520 
CLOCK_SetPllBypass(clock_pll_t pll,bool bypass)521 void CLOCK_SetPllBypass(clock_pll_t pll, bool bypass)
522 {
523     switch (pll)
524     {
525         case kCLOCK_PllArm:
526             ANADIG_PLL->ARM_PLL_CTRL = bypass ? (ANADIG_PLL->ARM_PLL_CTRL | ANADIG_PLL_ARM_PLL_CTRL_BYPASS_MASK) :
527                                                 (ANADIG_PLL->ARM_PLL_CTRL & ~ANADIG_PLL_ARM_PLL_CTRL_BYPASS_MASK);
528             break;
529         case kCLOCK_PllSys1:
530             ANATOP_PllBypass(kAI_Itf_1g, bypass);
531             break;
532         case kCLOCK_PllSys2:
533             ANADIG_PLL->SYS_PLL2_CTRL = bypass ? (ANADIG_PLL->SYS_PLL2_CTRL | ANADIG_PLL_SYS_PLL2_CTRL_BYPASS_MASK) :
534                                                  (ANADIG_PLL->SYS_PLL2_CTRL & ~ANADIG_PLL_SYS_PLL2_CTRL_BYPASS_MASK);
535             break;
536         case kCLOCK_PllSys3:
537             ANADIG_PLL->SYS_PLL3_CTRL = bypass ? (ANADIG_PLL->SYS_PLL3_CTRL | ANADIG_PLL_SYS_PLL3_CTRL_BYPASS_MASK) :
538                                                  (ANADIG_PLL->SYS_PLL3_CTRL & ~ANADIG_PLL_SYS_PLL3_CTRL_BYPASS_MASK);
539             break;
540         case kCLOCK_PllAudio:
541             ANATOP_PllBypass(kAI_Itf_Audio, bypass);
542             break;
543         case kCLOCK_PllVideo:
544             ANATOP_PllBypass(kAI_Itf_Video, bypass);
545             break;
546         default:
547             assert(false);
548             break;
549     }
550 }
551 
ANATOP_PllSetPower(anatop_ai_itf_t itf,bool enable)552 static void ANATOP_PllSetPower(anatop_ai_itf_t itf, bool enable)
553 {
554     ANATOP_AI_Write(itf, enable ? PLL_AI_CTRL0_SET_REG : PLL_AI_CTRL0_CLR_REG,
555                     PLL_AI_CTRL0_POWER_UP_MASK | (enable ? PLL_AI_CTRL0_HOLD_RING_OFF_MASK : 0UL));
556 }
557 
ANATOP_PllBypass(anatop_ai_itf_t itf,bool bypass)558 static void ANATOP_PllBypass(anatop_ai_itf_t itf, bool bypass)
559 {
560     ANATOP_AI_Write(itf, bypass ? PLL_AI_CTRL0_SET_REG : PLL_AI_CTRL0_CLR_REG, PLL_AI_CTRL0_BYPASS_MASK);
561 }
562 
ANATOP_PllEnablePllReg(anatop_ai_itf_t itf,bool enable)563 static void ANATOP_PllEnablePllReg(anatop_ai_itf_t itf, bool enable)
564 {
565     ANATOP_AI_Write(itf, enable ? PLL_AI_CTRL0_SET_REG : PLL_AI_CTRL0_CLR_REG, PLL_AI_CTRL0_PLL_REG_EN_MASK);
566 }
567 
ANATOP_PllHoldRingOff(anatop_ai_itf_t itf,bool off)568 static void ANATOP_PllHoldRingOff(anatop_ai_itf_t itf, bool off)
569 {
570     ANATOP_AI_Write(itf, off ? PLL_AI_CTRL0_SET_REG : PLL_AI_CTRL0_CLR_REG, PLL_AI_CTRL0_HOLD_RING_OFF_MASK);
571 }
572 
ANATOP_PllToggleHoldRingOff(anatop_ai_itf_t itf,uint32_t delayUsValue)573 static void ANATOP_PllToggleHoldRingOff(anatop_ai_itf_t itf, uint32_t delayUsValue)
574 {
575     ANATOP_PllHoldRingOff(itf, true);
576     SDK_DelayAtLeastUs(delayUsValue, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
577     ANATOP_PllHoldRingOff(itf, false);
578 }
579 
ANATOP_PllEnableSs(anatop_ai_itf_t itf,bool enable)580 static void ANATOP_PllEnableSs(anatop_ai_itf_t itf, bool enable)
581 {
582     ANATOP_AI_Write(itf, enable ? PLL_AI_CTRL0_SET_REG : PLL_AI_CTRL0_CLR_REG, PLL_AI_CTRL0_ENABLE_MASK);
583 }
584 
ANATOP_PllEnableClk(anatop_ai_itf_t itf,bool enable)585 static void ANATOP_PllEnableClk(anatop_ai_itf_t itf, bool enable)
586 {
587     ANATOP_AI_Write(itf, enable ? PLL_AI_CTRL0_SET_REG : PLL_AI_CTRL0_CLR_REG, PLL_AI_CTRL0_ENABLE_MASK);
588 }
589 
ANATOP_PllConfigure(anatop_ai_itf_t itf,uint8_t div,uint32_t numer,uint8_t post_div,uint32_t denom,const clock_pll_ss_config_t * ss)590 static void ANATOP_PllConfigure(
591     anatop_ai_itf_t itf, uint8_t div, uint32_t numer, uint8_t post_div, uint32_t denom, const clock_pll_ss_config_t *ss)
592 {
593     if (itf != kAI_Itf_1g)
594     {
595         ANATOP_PllSetPower(itf, false);
596     }
597     if (ss != NULL)
598     {
599         ANATOP_AI_Write(itf, PLL_AI_CTRL1_REG,
600                         AUDIO_PLL_SPREAD_SPECTRUM_STEP(ss->step) | AUDIO_PLL_SPREAD_SPECTRUM_STOP(ss->stop) |
601                             AUDIO_PLL_SPREAD_SPECTRUM_ENABLE_MASK);
602     }
603     ANATOP_AI_Write(itf, PLL_AI_CTRL3_REG, denom);
604     ANATOP_AI_Write(itf, PLL_AI_CTRL2_REG, numer);
605     ANATOP_AI_WriteWithMaskShift(itf, PLL_AI_CTRL0_REG, div, 0x7f, 0);
606     if (itf != kAI_Itf_1g)
607     {
608         ANATOP_AI_WriteWithMaskShift(itf, PLL_AI_CTRL0_REG, post_div, 0xE000000UL, 25UL);
609     }
610     ANATOP_PllEnablePllReg(itf, true);
611     SDK_DelayAtLeastUs(100, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
612     ANATOP_PllSetPower(itf, true);
613 }
614 
ANATOP_AudioPllGate(bool enable)615 static void ANATOP_AudioPllGate(bool enable)
616 {
617     if (!enable)
618     {
619         ANADIG_PLL->PLL_AUDIO_CTRL &= ~ANADIG_PLL_PLL_AUDIO_CTRL_PLL_AUDIO_GATE_MASK;
620     }
621     else
622     {
623         ANADIG_PLL->PLL_AUDIO_CTRL |= ANADIG_PLL_PLL_AUDIO_CTRL_PLL_AUDIO_GATE_MASK;
624     }
625 }
626 
ANATOP_AudioPllSwEnClk(bool enable)627 static void ANATOP_AudioPllSwEnClk(bool enable)
628 {
629     if (!enable)
630     {
631         ANADIG_PLL->PLL_AUDIO_CTRL &= ~ANADIG_PLL_PLL_AUDIO_CTRL_ENABLE_CLK_MASK;
632     }
633     else
634     {
635         ANADIG_PLL->PLL_AUDIO_CTRL |= ANADIG_PLL_PLL_AUDIO_CTRL_ENABLE_CLK_MASK;
636     }
637 }
638 
CLOCK_InitAudioPllWithFreq(uint32_t freqInMhz,bool ssEnable,uint32_t ssRange,uint32_t ssMod)639 status_t CLOCK_InitAudioPllWithFreq(uint32_t freqInMhz, bool ssEnable, uint32_t ssRange, uint32_t ssMod)
640 {
641     clock_audio_pll_config_t config = {0};
642     config.ssEnable                 = ssEnable;
643 
644     if (kStatus_Success == CLOCK_CalcAvPllFreq(&config, freqInMhz))
645     {
646         if (config.ssEnable)
647         {
648             clock_pll_ss_config_t ss = {0};
649             CLOCK_CalcPllSpreadSpectrum(config.denominator, ssRange, ssMod, &ss);
650             config.ss = &ss;
651         }
652         CLOCK_InitAudioPll(&config);
653         return kStatus_Success;
654     }
655     return kStatus_Fail;
656 }
657 
CLOCK_InitAudioPll(const clock_audio_pll_config_t * config)658 void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config)
659 {
660     uint32_t reg;
661     bool pllStable = false;
662 
663     PMU_StaticEnablePllLdo(ANADIG_PMU);
664 
665     reg = ANADIG_PLL->PLL_AUDIO_CTRL;
666     if ((reg & (ANADIG_PLL_PLL_AUDIO_CTRL_PLL_AUDIO_STABLE_MASK | ANADIG_PLL_PLL_AUDIO_CTRL_ENABLE_CLK_MASK)) ==
667         (ANADIG_PLL_PLL_AUDIO_CTRL_PLL_AUDIO_STABLE_MASK | ANADIG_PLL_PLL_AUDIO_CTRL_ENABLE_CLK_MASK))
668     {
669         pllStable = true;
670     }
671     /* bypass pll */
672     ANATOP_PllBypass(kAI_Itf_Audio, true);
673 
674     if (pllStable)
675     {
676         /* sw enable clock */
677         ANATOP_AudioPllSwEnClk(false);
678         /* gate clock */
679         ANATOP_AudioPllGate(true);
680         ANATOP_PllEnableClk(kAI_Itf_Audio, false);
681         ANATOP_PllSetPower(kAI_Itf_Audio, false);
682         ANATOP_PllEnablePllReg(kAI_Itf_Audio, false);
683     }
684 
685     ANATOP_AudioPllSwEnClk(true);
686     /* configure pll */
687     ANATOP_PllConfigure(kAI_Itf_Audio, config->loopDivider, config->numerator, config->postDivider, config->denominator,
688                         (config->ssEnable && (config->ss != NULL)) ? config->ss : NULL);
689 
690     /* toggle hold ring off */
691     ANATOP_PllToggleHoldRingOff(kAI_Itf_Audio, 225);
692 
693     /* wait pll stable */
694     do
695     {
696         reg = ANADIG_PLL->PLL_AUDIO_CTRL;
697     } while ((reg & ANADIG_PLL_PLL_AUDIO_CTRL_PLL_AUDIO_STABLE_MASK) !=
698              ANADIG_PLL_PLL_AUDIO_CTRL_PLL_AUDIO_STABLE_MASK); /* wait for PLL locked */
699 
700     /* enabled clock */
701     ANATOP_PllEnableClk(kAI_Itf_Audio, true);
702 
703     /* ungate clock */
704     ANATOP_AudioPllGate(false);
705 
706     ANATOP_PllBypass(kAI_Itf_Audio, false);
707 }
708 
CLOCK_DeinitAudioPll(void)709 void CLOCK_DeinitAudioPll(void)
710 {
711     ANATOP_AudioPllSwEnClk(false);
712     ANATOP_AudioPllGate(true);
713     ANATOP_PllEnableClk(kAI_Itf_Audio, false);
714     ANATOP_PllSetPower(kAI_Itf_Audio, false);
715     ANATOP_PllEnableSs(kAI_Itf_Audio, false);
716     ANATOP_PllEnablePllReg(kAI_Itf_Audio, false);
717 }
718 
CLOCK_GPC_SetAudioPllOutputFreq(const clock_audio_pll_gpc_config_t * config)719 void CLOCK_GPC_SetAudioPllOutputFreq(const clock_audio_pll_gpc_config_t *config)
720 {
721     assert(config != NULL);
722 
723     ANADIG_PLL->PLL_AUDIO_DIV_SELECT  = config->loopDivider;
724     ANADIG_PLL->PLL_AUDIO_NUMERATOR   = config->numerator;
725     ANADIG_PLL->PLL_AUDIO_DENOMINATOR = config->denominator;
726     if ((config->ss != NULL) && config->ssEnable)
727     {
728         ANADIG_PLL->PLL_AUDIO_SS = ANADIG_PLL_PLL_AUDIO_SS_STEP(config->ss->step) |
729                                    ANADIG_PLL_PLL_AUDIO_SS_STOP(config->ss->stop) | ANADIG_PLL_PLL_AUDIO_SS_ENABLE_MASK;
730     }
731 
732     ANADIG_PLL->PLL_AUDIO_CTRL |= ANADIG_PLL_PLL_AUDIO_CTRL_PLL_AUDIO_CONTROL_MODE_MASK;
733 }
734 
ANATOP_VideoPllGate(bool enable)735 static void ANATOP_VideoPllGate(bool enable)
736 {
737     if (!enable)
738     {
739         ANADIG_PLL->PLL_VIDEO_CTRL &= ~ANADIG_PLL_PLL_VIDEO_CTRL_PLL_VIDEO_GATE_MASK;
740     }
741     else
742     {
743         ANADIG_PLL->PLL_VIDEO_CTRL |= ANADIG_PLL_PLL_VIDEO_CTRL_PLL_VIDEO_GATE_MASK;
744     }
745 }
746 
ANATOP_VideoPllSwEnClk(bool enable)747 static void ANATOP_VideoPllSwEnClk(bool enable)
748 {
749     if (!enable)
750     {
751         ANADIG_PLL->PLL_VIDEO_CTRL &= ~ANADIG_PLL_PLL_VIDEO_CTRL_ENABLE_CLK_MASK;
752     }
753     else
754     {
755         ANADIG_PLL->PLL_VIDEO_CTRL |= ANADIG_PLL_PLL_VIDEO_CTRL_ENABLE_CLK_MASK;
756     }
757 }
758 
CLOCK_CalcArmPllFreq(clock_arm_pll_config_t * config,uint32_t freqInMhz)759 status_t CLOCK_CalcArmPllFreq(clock_arm_pll_config_t *config, uint32_t freqInMhz)
760 {
761     assert(config != NULL);
762     uint32_t refFreq = (XTAL_FREQ / 1000000UL) * 104UL; /* MHz */
763     assert((freqInMhz <= refFreq) && (freqInMhz >= 156UL));
764 
765     /*
766      * ARM_PLL  (156Mhz - 2496Mhz configureable )
767      * freqInMhz = osc_freq * loopDivider / (2 * postDivider)
768      *   - loopDivider:  104 - 208
769      *   - postDivider:  0 - 3
770      *   postDivider:
771      *     0 - divide by 2; 1 - divide by 4; 2 - divide by 8; 3 - divide by 1
772      */
773 
774     if (freqInMhz >= refFreq)
775     {
776         config->postDivider = kCLOCK_PllPostDiv1;
777         config->loopDivider = 208;
778     }
779     else if (freqInMhz >= (refFreq >> 1))
780     {
781         config->postDivider = kCLOCK_PllPostDiv1;
782         config->loopDivider = freqInMhz / 12UL;
783     }
784     else if (freqInMhz >= (refFreq >> 2))
785     {
786         config->postDivider = kCLOCK_PllPostDiv2;
787         config->loopDivider = freqInMhz / 6UL;
788     }
789     else if (freqInMhz >= (refFreq >> 3))
790     {
791         config->postDivider = kCLOCK_PllPostDiv4;
792         config->loopDivider = freqInMhz / 3UL;
793     }
794     else if (freqInMhz > (refFreq >> 4))
795     {
796         config->postDivider = kCLOCK_PllPostDiv8;
797         config->loopDivider = 2UL * freqInMhz / 3UL;
798     }
799     else
800     {
801         config->postDivider = kCLOCK_PllPostDiv8;
802         config->loopDivider = 104;
803     }
804     return kStatus_Success;
805 }
806 
CLOCK_InitArmPllWithFreq(uint32_t freqInMhz)807 status_t CLOCK_InitArmPllWithFreq(uint32_t freqInMhz)
808 {
809     clock_arm_pll_config_t config;
810     if (kStatus_Success == CLOCK_CalcArmPllFreq(&config, freqInMhz))
811     {
812         CLOCK_InitArmPll(&config);
813         return kStatus_Success;
814     }
815     return kStatus_Fail;
816 }
817 
CLOCK_CalcAvPllFreq(clock_av_pll_config_t * config,uint32_t freqInMhz)818 status_t CLOCK_CalcAvPllFreq(clock_av_pll_config_t *config, uint32_t freqInMhz)
819 {
820     assert(config != NULL);
821 
822     uint32_t refFreq = (XTAL_FREQ / 1000000UL) * 54UL; /* MHz */
823 
824     assert((freqInMhz <= refFreq) && (freqInMhz > 20UL));
825 
826     /*
827      * AUDIO_PLL/VIDEO_PLL  (20.3125MHZ--- 1300MHZ configureable )
828      * freqInMhz = osc_freq * (loopDivider + numerator / (2^28 - 1) ) / 2^postDivider
829      *   - loopDivider:  27---54
830      *   - postDivider: 0---5
831      *   - numerator is a signed number, 30 bit,  numer[29] is the sign bit, such as +1--->0x00000001; -1---> 0x20000001
832      * such as: div_sel = 27, numer = 0x026EEEEF, post_div =0, fref = 24.0MHZ, output_fre =24.0*(27 + 40824559/(2^28 -
833      * 1))/2^0 = 651.65M such as: div_sel = 33, numer = 0x0F0AAAAA, post_div =0, fref = 19.2MHZ, output_fre =19.2*(33 +
834      * 252357290/(2^28 - 1))/2^0= 651.65M
835      */
836 
837     config->denominator = 0x0FFFFFFF;
838 
839     if (freqInMhz >= refFreq)
840     {
841         config->postDivider = 0;
842         config->loopDivider = 54;
843         config->numerator   = 0;
844     }
845     else if (freqInMhz >= (refFreq >> 1))
846     {
847         config->postDivider = 0;
848         config->loopDivider = (uint8_t)(freqInMhz / 24UL);
849         config->numerator   = (config->denominator / 24UL) * (freqInMhz % 24UL);
850     }
851     else if (freqInMhz >= (refFreq >> 2))
852     {
853         config->postDivider = 1;
854         config->loopDivider = (uint8_t)(freqInMhz / 12UL);
855         config->numerator   = (config->denominator / 12UL) * (freqInMhz % 12UL);
856     }
857     else if (freqInMhz >= (refFreq >> 3))
858     {
859         config->postDivider = 2;
860         config->loopDivider = (uint8_t)(freqInMhz / 6UL);
861         config->numerator   = (config->denominator / 6UL) * (freqInMhz % 6UL);
862     }
863     else if (freqInMhz >= (refFreq >> 4))
864     {
865         config->postDivider = 3;
866         config->loopDivider = (uint8_t)(freqInMhz / 3UL);
867         config->numerator   = (config->denominator / 3UL) * (freqInMhz % 3UL);
868     }
869     else if (freqInMhz >= (refFreq >> 5))
870     {
871         config->postDivider = 4;
872         config->loopDivider = (uint8_t)(freqInMhz * 2UL / 3UL);
873         config->numerator   = (config->denominator * 2UL / 3UL) * (freqInMhz * 2UL % 3UL);
874     }
875     else if (freqInMhz > (refFreq >> 6))
876     {
877         config->postDivider = 5;
878         config->loopDivider = (uint8_t)(freqInMhz * 4UL / 3UL);
879         config->numerator   = (config->denominator * 4UL / 3UL) * (freqInMhz * 4UL % 3UL);
880     }
881     else
882     {
883         return kStatus_Fail;
884     }
885     return kStatus_Success;
886 }
887 
CLOCK_InitVideoPllWithFreq(uint32_t freqInMhz,bool ssEnable,uint32_t ssRange,uint32_t ssMod)888 status_t CLOCK_InitVideoPllWithFreq(uint32_t freqInMhz, bool ssEnable, uint32_t ssRange, uint32_t ssMod)
889 {
890     clock_video_pll_config_t config = {0};
891     config.ssEnable                 = ssEnable;
892 
893     if (kStatus_Success == CLOCK_CalcAvPllFreq(&config, freqInMhz))
894     {
895         if (config.ssEnable)
896         {
897             clock_pll_ss_config_t ss = {0};
898             CLOCK_CalcPllSpreadSpectrum(config.denominator, ssRange, ssMod, &ss);
899             config.ss = &ss;
900         }
901         CLOCK_InitVideoPll(&config);
902         return kStatus_Success;
903     }
904     return kStatus_Fail;
905 }
906 
CLOCK_InitVideoPll(const clock_video_pll_config_t * config)907 void CLOCK_InitVideoPll(const clock_video_pll_config_t *config)
908 {
909     uint32_t reg;
910     bool pllStable = false;
911 
912     PMU_StaticEnablePllLdo(ANADIG_PMU);
913 
914     reg = ANADIG_PLL->PLL_VIDEO_CTRL;
915     if ((reg & (ANADIG_PLL_PLL_VIDEO_CTRL_PLL_VIDEO_STABLE_MASK | ANADIG_PLL_PLL_VIDEO_CTRL_ENABLE_CLK_MASK)) ==
916         (ANADIG_PLL_PLL_VIDEO_CTRL_PLL_VIDEO_STABLE_MASK | ANADIG_PLL_PLL_VIDEO_CTRL_ENABLE_CLK_MASK))
917     {
918         pllStable = true;
919     }
920     /* bypass pll */
921     ANATOP_PllBypass(kAI_Itf_Video, true);
922 
923     if (pllStable)
924     {
925         /* sw enable clock */
926         ANATOP_VideoPllSwEnClk(false);
927         /* gate clock */
928         ANATOP_VideoPllGate(true);
929         ANATOP_PllEnableClk(kAI_Itf_Video, false);
930         ANATOP_PllSetPower(kAI_Itf_Video, false);
931         ANATOP_PllEnablePllReg(kAI_Itf_Video, false);
932     }
933 
934     ANATOP_VideoPllSwEnClk(true);
935     /* configure pll */
936     ANATOP_PllConfigure(kAI_Itf_Video, config->loopDivider, config->numerator, config->postDivider, config->denominator,
937                         (config->ssEnable && (config->ss != NULL)) ? config->ss : NULL);
938 
939     /* toggle hold ring off */
940     ANATOP_PllToggleHoldRingOff(kAI_Itf_Video, 225);
941 
942     /* wait pll stable */
943     do
944     {
945         reg = ANADIG_PLL->PLL_VIDEO_CTRL;
946     } while ((reg & ANADIG_PLL_PLL_VIDEO_CTRL_PLL_VIDEO_STABLE_MASK) !=
947              ANADIG_PLL_PLL_VIDEO_CTRL_PLL_VIDEO_STABLE_MASK); /* wait for PLL locked */
948 
949     /* enabled clock */
950     ANATOP_PllEnableClk(kAI_Itf_Video, true);
951 
952     /* ungate clock */
953     ANATOP_VideoPllGate(false);
954 
955     ANATOP_PllBypass(kAI_Itf_Video, false);
956 }
957 
CLOCK_DeinitVideoPll(void)958 void CLOCK_DeinitVideoPll(void)
959 {
960     ANATOP_VideoPllSwEnClk(false);
961     ANATOP_VideoPllGate(true);
962     ANATOP_PllEnableClk(kAI_Itf_Video, false);
963     ANATOP_PllSetPower(kAI_Itf_Video, false);
964     ANATOP_PllEnableSs(kAI_Itf_Video, false);
965     ANATOP_PllEnablePllReg(kAI_Itf_Video, false);
966 }
967 
CLOCK_GPC_SetVideoPllOutputFreq(const clock_video_pll_gpc_config_t * config)968 void CLOCK_GPC_SetVideoPllOutputFreq(const clock_video_pll_gpc_config_t *config)
969 {
970     assert(config != NULL);
971 
972     ANADIG_PLL->PLL_VIDEO_DIV_SELECT  = config->loopDivider;
973     ANADIG_PLL->PLL_VIDEO_NUMERATOR   = config->numerator;
974     ANADIG_PLL->PLL_VIDEO_DENOMINATOR = config->denominator;
975 
976     if ((config->ss != NULL) && config->ssEnable)
977     {
978         ANADIG_PLL->PLL_VIDEO_SS = ANADIG_PLL_PLL_VIDEO_SS_STEP(config->ss->step) |
979                                    ANADIG_PLL_PLL_VIDEO_SS_STOP(config->ss->stop) | ANADIG_PLL_PLL_VIDEO_SS_ENABLE_MASK;
980     }
981 
982     ANADIG_PLL->PLL_VIDEO_CTRL |= ANADIG_PLL_PLL_VIDEO_CTRL_PLL_VIDEO_CONTROL_MODE_MASK;
983 }
984 
ANATOP_SysPll1Gate(bool enable)985 static void ANATOP_SysPll1Gate(bool enable)
986 {
987     if (!enable)
988     {
989         ANADIG_PLL->SYS_PLL1_CTRL &= ~ANADIG_PLL_SYS_PLL1_CTRL_SYS_PLL1_GATE_MASK;
990     }
991     else
992     {
993         ANADIG_PLL->SYS_PLL1_CTRL |= ANADIG_PLL_SYS_PLL1_CTRL_SYS_PLL1_GATE_MASK;
994     }
995 }
996 
ANATOP_SysPll1Div2En(bool enable)997 static void ANATOP_SysPll1Div2En(bool enable)
998 {
999     if (!enable)
1000     {
1001         ANADIG_PLL->SYS_PLL1_CTRL &= ~ANADIG_PLL_SYS_PLL1_CTRL_SYS_PLL1_DIV2_MASK;
1002     }
1003     else
1004     {
1005         ANADIG_PLL->SYS_PLL1_CTRL |= ANADIG_PLL_SYS_PLL1_CTRL_SYS_PLL1_DIV2_MASK;
1006     }
1007 }
1008 
ANATOP_SysPll1Div5En(bool enable)1009 static void ANATOP_SysPll1Div5En(bool enable)
1010 {
1011     if (!enable)
1012     {
1013         ANADIG_PLL->SYS_PLL1_CTRL &= ~ANADIG_PLL_SYS_PLL1_CTRL_SYS_PLL1_DIV5_MASK;
1014     }
1015     else
1016     {
1017         ANADIG_PLL->SYS_PLL1_CTRL |= ANADIG_PLL_SYS_PLL1_CTRL_SYS_PLL1_DIV5_MASK;
1018     }
1019 }
1020 
ANATOP_SysPll1SwEnClk(bool enable)1021 static void ANATOP_SysPll1SwEnClk(bool enable)
1022 {
1023     if (!enable)
1024     {
1025         ANADIG_PLL->SYS_PLL1_CTRL &= ~ANADIG_PLL_SYS_PLL1_CTRL_ENABLE_CLK_MASK;
1026     }
1027     else
1028     {
1029         ANADIG_PLL->SYS_PLL1_CTRL |= ANADIG_PLL_SYS_PLL1_CTRL_ENABLE_CLK_MASK;
1030     }
1031 }
1032 
ANATOP_SysPll1WaitStable(void)1033 static void ANATOP_SysPll1WaitStable(void)
1034 {
1035     uint32_t reg;
1036     do
1037     {
1038         reg = ANADIG_PLL->SYS_PLL1_CTRL;
1039     } while ((reg & ANADIG_PLL_SYS_PLL1_CTRL_SYS_PLL1_STABLE_MASK) !=
1040              ANADIG_PLL_SYS_PLL1_CTRL_SYS_PLL1_STABLE_MASK); /* wait for PLL locked */
1041 }
1042 
1043 /* 1GPLL */
CLOCK_InitSysPll1(const clock_sys_pll1_config_t * config)1044 void CLOCK_InitSysPll1(const clock_sys_pll1_config_t *config)
1045 {
1046     uint8_t div;
1047     uint32_t numerator, denominator;
1048 
1049     PMU_StaticEnablePllLdo(ANADIG_PMU);
1050     /* bypass pll */
1051     ANATOP_PllBypass(kAI_Itf_1g, true);
1052 
1053     /* sw enable clock */
1054     ANATOP_SysPll1SwEnClk(true);
1055 
1056     denominator = 0x0FFFFFFF;
1057     div         = 41U;
1058     numerator   = 178956970UL;
1059 
1060     /* configure pll */
1061     ANATOP_PllConfigure(kAI_Itf_1g, div, numerator, 0U, denominator,
1062                         (config->ssEnable && (config->ss != NULL)) ? config->ss : NULL);
1063 
1064     /* toggle hold ring off */
1065     ANATOP_PllToggleHoldRingOff(kAI_Itf_1g, 225);
1066 
1067     /* wait pll stable */
1068     ANATOP_SysPll1WaitStable();
1069 
1070     /* enabled clock */
1071     ANATOP_PllEnableClk(kAI_Itf_1g, true);
1072 
1073     /* ungate clock */
1074     ANATOP_SysPll1Gate(false);
1075 
1076     ANATOP_SysPll1Div2En(config->pllDiv2En);
1077     ANATOP_SysPll1Div5En(config->pllDiv5En);
1078 
1079     /* bypass pll */
1080     ANATOP_PllBypass(kAI_Itf_1g, false);
1081 }
1082 
CLOCK_DeinitSysPll1(void)1083 void CLOCK_DeinitSysPll1(void)
1084 {
1085     ANATOP_SysPll1SwEnClk(false);
1086     ANATOP_SysPll1Div2En(false);
1087     ANATOP_SysPll1Div5En(false);
1088     ANATOP_SysPll1Gate(true);
1089     ANATOP_PllEnableClk(kAI_Itf_1g, false);
1090     ANATOP_PllSetPower(kAI_Itf_1g, false);
1091     ANATOP_PllEnableSs(kAI_Itf_1g, false);
1092     ANATOP_PllEnablePllReg(kAI_Itf_1g, false);
1093 }
1094 
CLOCK_GPC_SetSysPll1OutputFreq(const clock_sys_pll1_gpc_config_t * config)1095 void CLOCK_GPC_SetSysPll1OutputFreq(const clock_sys_pll1_gpc_config_t *config)
1096 {
1097     assert(config != NULL);
1098 
1099     ANADIG_PLL->SYS_PLL1_DIV_SELECT  = config->loopDivider;
1100     ANADIG_PLL->SYS_PLL1_NUMERATOR   = config->numerator;
1101     ANADIG_PLL->SYS_PLL1_DENOMINATOR = config->denominator;
1102 
1103     if ((config->ss != NULL) && config->ssEnable)
1104     {
1105         ANADIG_PLL->SYS_PLL1_SS = ANADIG_PLL_SYS_PLL1_SS_STEP(config->ss->step) |
1106                                   ANADIG_PLL_SYS_PLL1_SS_STOP(config->ss->stop) | ANADIG_PLL_SYS_PLL1_SS_ENABLE_MASK;
1107     }
1108 
1109     ANADIG_PLL->SYS_PLL1_CTRL |= ANADIG_PLL_SYS_PLL1_CTRL_SYS_PLL1_CONTROL_MODE_MASK;
1110 }
1111 
CLOCK_OSC_EnableOsc24M(void)1112 void CLOCK_OSC_EnableOsc24M(void)
1113 {
1114     if (0UL == (ANADIG_OSC->OSC_24M_CTRL & ANADIG_OSC_OSC_24M_CTRL_OSC_EN_MASK))
1115     {
1116         ANADIG_OSC->OSC_24M_CTRL |= ANADIG_OSC_OSC_24M_CTRL_OSC_EN_MASK;
1117         while (ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK !=
1118                (ANADIG_OSC->OSC_24M_CTRL & ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK))
1119         {
1120         }
1121     }
1122 }
1123 
1124 /*!
1125  * brief Set the work mode of 24MHz crystal oscillator, the available modes are high gian mode, low power mode, and
1126  * bypass mode.
1127  *
1128  * param workMode The work mode of 24MHz crystal oscillator, please refer to @ref clock_24MOsc_mode_t for details.
1129  */
CLOCK_OSC_SetOsc24MWorkMode(clock_24MOsc_mode_t workMode)1130 void CLOCK_OSC_SetOsc24MWorkMode(clock_24MOsc_mode_t workMode)
1131 {
1132     uint32_t tmp32;
1133 
1134     tmp32 = ANADIG_OSC->OSC_24M_CTRL;
1135     tmp32 &= ~(ANADIG_OSC_OSC_24M_CTRL_LP_EN_MASK | ANADIG_OSC_OSC_24M_CTRL_BYPASS_EN_MASK);
1136     tmp32 |= (((uint32_t)workMode << ANADIG_OSC_OSC_24M_CTRL_BYPASS_EN_SHIFT) &
1137               (ANADIG_OSC_OSC_24M_CTRL_LP_EN_MASK | ANADIG_OSC_OSC_24M_CTRL_BYPASS_EN_MASK));
1138     ANADIG_OSC->OSC_24M_CTRL = tmp32;
1139 }
1140 
1141 /*!
1142  * brief Configure the 16MHz oscillator.
1143  *
1144  * param source Used to select the source for 16MHz RC oscillator, please refer to clock_16MOsc_source_t.
1145  * param enablePowerSave Enable/disable power save mode function at 16MHz OSC.
1146  *          - \b true Enable power save mode function at 16MHz osc.
1147  *          - \b false Disable power save mode function at 16MHz osc.
1148  * param enableClockOut Enable/Disable clock output for 16MHz RCOSC.
1149  *          - \b true Enable clock output for 16MHz RCOSC.
1150  *          - \b false Disable clock output for 16MHz RCOSC.
1151  */
CLOCK_OSC_SetOsc16MConfig(clock_16MOsc_source_t source,bool enablePowerSave,bool enableClockOut)1152 void CLOCK_OSC_SetOsc16MConfig(clock_16MOsc_source_t source, bool enablePowerSave, bool enableClockOut)
1153 {
1154     uint32_t tmp32;
1155 
1156     tmp32 = ANADIG_OSC->OSC_16M_CTRL;
1157     tmp32 &= ~(ANADIG_OSC_OSC_16M_CTRL_EN_IRC4M16M_MASK | ANADIG_OSC_OSC_16M_CTRL_EN_POWER_SAVE_MASK |
1158                ANADIG_OSC_OSC_16M_CTRL_SOURCE_SEL_16M_MASK);
1159     tmp32 |= ANADIG_OSC_OSC_16M_CTRL_EN_IRC4M16M(enableClockOut) |
1160              ANADIG_OSC_OSC_16M_CTRL_EN_POWER_SAVE(enablePowerSave) | ANADIG_OSC_OSC_16M_CTRL_SOURCE_SEL_16M(source);
1161     ANADIG_OSC->OSC_16M_CTRL = tmp32;
1162 }
1163 
1164 /*!
1165  * brief Set the divide value for ref_clk to generate slow clock.
1166  *
1167  * note slow_clk = ref_clk / (divValue + 1), and the recommand divide value is 24.
1168  *
1169  * param divValue The divide value to be set, the available range is 0~63.
1170  */
CLOCK_OSC_SetOscRc400MRefClkDiv(uint8_t divValue)1171 void CLOCK_OSC_SetOscRc400MRefClkDiv(uint8_t divValue)
1172 {
1173     uint32_t tmp32;
1174 
1175     tmp32 = ANATOP_AI_Read(kAI_Itf_400m, kAI_RCOSC400M_CTRL0);
1176     tmp32 = ((tmp32 & ~AI_RCOSC400M_CTRL0_REF_CLK_DIV_MASK) | AI_RCOSC400M_CTRL0_REF_CLK_DIV(divValue));
1177     ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL0, tmp32);
1178 }
1179 
1180 /*!
1181  * brief Set the target count for the fast clock.
1182  *
1183  * param targetCount The desired target for the fast clock, should be the number of clock cycles of the fast_clk per
1184  * divided ref_clk.
1185  */
CLOCK_OSC_SetOscRc400MFastClkCount(uint16_t targetCount)1186 void CLOCK_OSC_SetOscRc400MFastClkCount(uint16_t targetCount)
1187 {
1188     uint32_t tmp32;
1189 
1190     tmp32 = ANATOP_AI_Read(kAI_Itf_400m, kAI_RCOSC400M_CTRL1);
1191     tmp32 = ((tmp32 & ~AI_RCOSC400M_CTRL1_TARGET_COUNT_MASK) | AI_RCOSC400M_CTRL1_TARGET_COUNT(targetCount));
1192     ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL1, tmp32);
1193 }
1194 
1195 /*!
1196  * brief Set the negative and positive hysteresis value for the tuned clock.
1197  *
1198  * note The hysteresis value should be set after the clock is tuned.
1199  *
1200  * param negHysteresis The negative hysteresis value for the turned clock, this value in number of clock cycles of the
1201  * fast clock
1202  * param posHysteresis The positive hysteresis value for the turned clock, this value in number of clock cycles of the
1203  * fast clock
1204  */
CLOCK_OSC_SetOscRc400MHysteresisValue(uint8_t negHysteresis,uint8_t posHysteresis)1205 void CLOCK_OSC_SetOscRc400MHysteresisValue(uint8_t negHysteresis, uint8_t posHysteresis)
1206 {
1207     uint32_t tmp32;
1208 
1209     tmp32 = ANATOP_AI_Read(kAI_Itf_400m, kAI_RCOSC400M_CTRL1);
1210     tmp32 = ((tmp32 & ~(AI_RCOSC400M_CTRL1_HYST_PLUS_MASK | AI_RCOSC400M_CTRL1_HYST_MINUS_MASK)) |
1211              (AI_RCOSC400M_CTRL1_HYST_PLUS(posHysteresis) | AI_RCOSC400M_CTRL1_HYST_MINUS(negHysteresis)));
1212     ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL1, tmp32);
1213 }
1214 
1215 /*!
1216  * brief Bypass/un-bypass the tune logic
1217  *
1218  * param enableBypass Used to control whether to bypass the turn logic.
1219  *        - \b true Bypass the tune logic and use the programmed oscillator frequency to run the oscillator.
1220  *                  Function CLOCK_OSC_SetOscRc400MTuneValue() can be used to set oscillator frequency.
1221  *        - \b false Use the output of tune logic to run the oscillator.
1222  */
CLOCK_OSC_BypassOscRc400MTuneLogic(bool enableBypass)1223 void CLOCK_OSC_BypassOscRc400MTuneLogic(bool enableBypass)
1224 {
1225     if (enableBypass)
1226     {
1227         ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL2_SET, AI_RCOSC400M_CTRL2_TUNE_BYP_MASK);
1228     }
1229     else
1230     {
1231         ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL2_CLR, AI_RCOSC400M_CTRL2_TUNE_BYP_MASK);
1232     }
1233 }
1234 
1235 /*!
1236  * brief Start/Stop the tune logic.
1237  *
1238  * param enable Used to start or stop the tune logic.
1239  *          - \b true Start tuning
1240  *          - \b false Stop tuning and reset the tuning logic.
1241  */
CLOCK_OSC_EnableOscRc400MTuneLogic(bool enable)1242 void CLOCK_OSC_EnableOscRc400MTuneLogic(bool enable)
1243 {
1244     if (enable)
1245     {
1246         ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL2_SET, AI_RCOSC400M_CTRL2_TUNE_START_MASK);
1247     }
1248     else
1249     {
1250         ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL2_CLR, AI_RCOSC400M_CTRL2_TUNE_START_MASK);
1251     }
1252 }
1253 
1254 /*!
1255  * brief Freeze/Unfreeze the tuning value.
1256  *
1257  * param enableFreeze Used to control whether to freeze the tune value.
1258  *          - \b true Freeze the tune at the current tuned value and the oscillator runs at tje frozen tune value.
1259  *          - \b false Unfreezes and continues the tune operation.
1260  */
CLOCK_OSC_FreezeOscRc400MTuneValue(bool enableFreeze)1261 void CLOCK_OSC_FreezeOscRc400MTuneValue(bool enableFreeze)
1262 {
1263     if (enableFreeze)
1264     {
1265         ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL2_SET, AI_RCOSC400M_CTRL2_TUNE_EN_MASK);
1266     }
1267     else
1268     {
1269         ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL2_CLR, AI_RCOSC400M_CTRL2_TUNE_EN_MASK);
1270     }
1271 }
1272 
1273 /*!
1274  * @brief Set the 400MHz RC oscillator tune value when the tune logic is disabled.
1275  *
1276  * @param tuneValue The tune value to determine the frequency of Oscillator.
1277  */
CLOCK_OSC_SetOscRc400MTuneValue(uint8_t tuneValue)1278 void CLOCK_OSC_SetOscRc400MTuneValue(uint8_t tuneValue)
1279 {
1280     uint32_t tmp32;
1281 
1282     tmp32 = ANATOP_AI_Read(kAI_Itf_400m, kAI_RCOSC400M_CTRL2);
1283     tmp32 &= ~AI_RCOSC400M_CTRL2_OSC_TUNE_VAL_MASK;
1284     tmp32 |= AI_RCOSC400M_CTRL2_OSC_TUNE_VAL(tuneValue);
1285     ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL2, tmp32);
1286 }
1287 
1288 /*!
1289  * brief Set the behavior of the 1MHz output clock, such as disable the 1MHz clock output,
1290  * enable the free-running 1MHz clock output, enable the locked 1MHz clock output.
1291  *
1292  * note The 1MHz clock is divided from 400M RC Oscillator.
1293  *
1294  * param behavior The behavior of 1MHz output clock, please refer to clock_1MHzOut_behavior_t for details.
1295  */
CLOCK_OSC_Set1MHzOutputBehavior(clock_1MHzOut_behavior_t behavior)1296 void CLOCK_OSC_Set1MHzOutputBehavior(clock_1MHzOut_behavior_t behavior)
1297 {
1298     uint32_t tmp32;
1299 
1300     tmp32 = ANATOP_AI_Read(kAI_Itf_400m, kAI_RCOSC400M_CTRL3);
1301     tmp32 &= ~(AI_RCOSC400M_CTRL3_EN_1M_CLK_MASK | AI_RCOSC400M_CTRL3_MUX_1M_CLK_MASK);
1302 
1303     if (behavior == kCLOCK_1MHzOutDisable)
1304     {
1305         tmp32 |= AI_RCOSC400M_CTRL3_EN_1M_CLK_MASK;
1306     }
1307     else
1308     {
1309         if (behavior == kCLOCK_1MHzOutEnableLocked1Mhz)
1310         {
1311             tmp32 |= AI_RCOSC400M_CTRL3_MUX_1M_CLK_MASK;
1312         }
1313     }
1314     ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL3, tmp32);
1315 }
1316 
1317 /*!
1318  * brief Set the count for the locked 1MHz clock out.
1319  *
1320  * param count Used to set the desired target for the locked 1MHz clock out, the value in number of clock cycles of the
1321  * osc_out_400M per divided ref_clk.
1322  */
CLOCK_OSC_SetLocked1MHzCount(uint16_t count)1323 void CLOCK_OSC_SetLocked1MHzCount(uint16_t count)
1324 {
1325     uint32_t tmp32;
1326     uint16_t targetCount;
1327     uint16_t hystMinus;
1328     uint16_t diffCount;
1329 
1330     tmp32       = ANATOP_AI_Read(kAI_Itf_400m, kAI_RCOSC400M_CTRL1);
1331     targetCount = (uint16_t)((tmp32 & AI_RCOSC400M_CTRL1_TARGET_COUNT_MASK) >> AI_RCOSC400M_CTRL1_TARGET_COUNT_SHIFT);
1332     hystMinus   = (uint16_t)((tmp32 & AI_RCOSC400M_CTRL1_HYST_MINUS_MASK) >> AI_RCOSC400M_CTRL1_HYST_MINUS_SHIFT);
1333     diffCount   = targetCount - hystMinus - count;
1334 
1335     /* The count for the locked 1MHz clock should be 4 to 8 counts less than CTRL[TARGET_COUNT] - CTRL1[HYST_MINUS]. */
1336     if ((diffCount >= 4U) && (diffCount <= 8U))
1337     {
1338         tmp32 = (tmp32 & ~AI_RCOSC400M_CTRL3_COUNT_1M_CLK_MASK) | AI_RCOSC400M_CTRL3_COUNT_1M_CLK(count);
1339         ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL3, tmp32);
1340     }
1341 }
1342 
1343 /*!
1344  * brief Check the error flag for locked 1MHz clock out.
1345  *
1346  * return The error flag for locked 1MHz clock out.
1347  *      - \b true The count value has been reached within one diviced ref clock period
1348  *      - \b false No effect.
1349  */
CLOCK_OSC_CheckLocked1MHzErrorFlag(void)1350 bool CLOCK_OSC_CheckLocked1MHzErrorFlag(void)
1351 {
1352     uint32_t tmp32;
1353 
1354     tmp32 = ANATOP_AI_Read(kAI_Itf_400m, kAI_RCOSC400M_STAT0);
1355 
1356     return ((tmp32 & AI_RCOSC400M_STAT0_CLK1M_ERR_MASK) == AI_RCOSC400M_STAT0_CLK1M_ERR_MASK);
1357 }
1358 
1359 /*!
1360  * brief Clear the error flag for locked 1MHz clock out.
1361  */
CLOCK_OSC_ClearLocked1MHzErrorFlag(void)1362 void CLOCK_OSC_ClearLocked1MHzErrorFlag(void)
1363 {
1364     ANATOP_AI_Write(kAI_Itf_400m, kAI_RCOSC400M_CTRL3_SET, AI_RCOSC400M_CTRL3_CLR_ERR_MASK);
1365 }
1366 
1367 /*!
1368  * brief Get current count for the fast clock during the tune process.
1369  *
1370  * return The current count for the fast clock.
1371  */
CLOCK_OSC_GetCurrentOscRc400MFastClockCount(void)1372 uint16_t CLOCK_OSC_GetCurrentOscRc400MFastClockCount(void)
1373 {
1374     uint32_t tmp32;
1375 
1376     tmp32 = ANATOP_AI_Read(kAI_Itf_400m, kAI_RCOSC400M_STAT1);
1377 
1378     return (uint16_t)((tmp32 & AI_RCOSC400M_STAT1_CURR_COUNT_VAL_MASK) >> AI_RCOSC400M_STAT1_CURR_COUNT_VAL_SHIFT);
1379 }
1380 
1381 /*!
1382  * brief Get current tune value used by oscillator during tune process.
1383  *
1384  * return The current tune value.
1385  */
CLOCK_OSC_GetCurrentOscRc400MTuneValue(void)1386 uint8_t CLOCK_OSC_GetCurrentOscRc400MTuneValue(void)
1387 {
1388     uint32_t tmp32;
1389 
1390     tmp32 = ANATOP_AI_Read(kAI_Itf_400m, kAI_RCOSC400M_STAT2);
1391 
1392     return (uint8_t)((tmp32 & AI_RCOSC400M_STAT2_CURR_OSC_TUNE_VAL_MASK) >> AI_RCOSC400M_STAT2_CURR_OSC_TUNE_VAL_SHIFT);
1393 }
1394 
1395 #ifndef GET_FREQ_FROM_OBS
CLOCK_GetAvPllFreq(clock_pll_t pll)1396 static uint32_t CLOCK_GetAvPllFreq(clock_pll_t pll)
1397 {
1398     uint32_t freq = 0;
1399     uint32_t div;
1400     uint32_t post_div;
1401     double tmpDouble;
1402     double denom;
1403     double numer;
1404 
1405     assert((pll == kCLOCK_PllAudio) || (pll == kCLOCK_PllVideo));
1406 
1407     div      = ANATOP_AI_Read(pll == kCLOCK_PllAudio ? kAI_Itf_Audio : kAI_Itf_Video, PLL_AI_CTRL0_REG);
1408     post_div = (div & (0xE000000UL)) >> 25UL;
1409     div &= 0x7fUL;
1410     denom = (double)ANATOP_AI_Read(pll == kCLOCK_PllAudio ? kAI_Itf_Audio : kAI_Itf_Video, PLL_AI_CTRL3_REG);
1411     numer = (double)ANATOP_AI_Read(pll == kCLOCK_PllAudio ? kAI_Itf_Audio : kAI_Itf_Video, PLL_AI_CTRL2_REG);
1412 
1413     tmpDouble = ((double)XTAL_FREQ * ((double)div + (numer / denom)) / (double)(uint32_t)(1UL << post_div));
1414     freq      = (uint32_t)tmpDouble;
1415 
1416     return freq;
1417 }
1418 #endif
1419 
CLOCK_GetPllFreq(clock_pll_t pll)1420 uint32_t CLOCK_GetPllFreq(clock_pll_t pll)
1421 {
1422     uint32_t freq = 0;
1423 #ifndef GET_FREQ_FROM_OBS
1424     uint32_t divSelect, postDiv;
1425 #endif
1426 
1427     switch (pll)
1428     {
1429         case kCLOCK_PllArm:
1430 #ifndef GET_FREQ_FROM_OBS
1431             divSelect = (ANADIG_PLL->ARM_PLL_CTRL & ANADIG_PLL_ARM_PLL_CTRL_DIV_SELECT_MASK) >>
1432                         ANADIG_PLL_ARM_PLL_CTRL_DIV_SELECT_SHIFT;
1433             postDiv = (ANADIG_PLL->ARM_PLL_CTRL & ANADIG_PLL_ARM_PLL_CTRL_POST_DIV_SEL_MASK) >>
1434                       ANADIG_PLL_ARM_PLL_CTRL_POST_DIV_SEL_SHIFT;
1435             if (postDiv == (uint32_t)kCLOCK_PllPostDiv1)
1436             {
1437                 postDiv = 1UL;
1438             }
1439             else
1440             {
1441                 postDiv = (1UL << (postDiv + 1UL));
1442             }
1443             freq = XTAL_FREQ / (2UL * postDiv);
1444             freq *= divSelect;
1445 #else
1446             freq = CLOCK_GetFreqFromObs(CCM_OBS_ARM_PLL_OUT);
1447 #endif
1448             break;
1449         case kCLOCK_PllSys1:
1450 #ifndef GET_FREQ_FROM_OBS
1451             freq = SYS_PLL1_FREQ;
1452 #else
1453             freq = CLOCK_GetFreqFromObs(CCM_OBS_SYS_PLL1_OUT);
1454 #endif
1455             break;
1456         case kCLOCK_PllSys2:
1457 #ifndef GET_FREQ_FROM_OBS
1458             freq = SYS_PLL2_FREQ;
1459 #else
1460             freq = CLOCK_GetFreqFromObs(CCM_OBS_SYS_PLL2_OUT);
1461 #endif
1462             break;
1463         case kCLOCK_PllSys3:
1464 #ifndef GET_FREQ_FROM_OBS
1465             freq = SYS_PLL3_FREQ;
1466 #else
1467             freq = CLOCK_GetFreqFromObs(CCM_OBS_SYS_PLL3_OUT);
1468 #endif
1469             break;
1470         case kCLOCK_PllAudio:
1471 #ifndef GET_FREQ_FROM_OBS
1472             freq = CLOCK_GetAvPllFreq(kCLOCK_PllAudio);
1473 #else
1474             freq = CLOCK_GetFreqFromObs(CCM_OBS_PLL_AUDIO_OUT);
1475 #endif
1476             break;
1477         case kCLOCK_PllVideo:
1478 #ifndef GET_FREQ_FROM_OBS
1479             freq = CLOCK_GetAvPllFreq(kCLOCK_PllVideo);
1480 #else
1481             freq = CLOCK_GetFreqFromObs(CCM_OBS_PLL_VIDEO_OUT);
1482 #endif
1483             break;
1484         default:
1485             /* Wrong input parameter pll. */
1486             assert(false);
1487             break;
1488     }
1489     assert(freq != 0UL);
1490     return freq;
1491 }
1492 
CLOCK_GetFreq(clock_name_t name)1493 uint32_t CLOCK_GetFreq(clock_name_t name)
1494 {
1495     uint32_t freq = 0;
1496     switch (name)
1497     {
1498         case kCLOCK_OscRc16M:
1499 #ifndef GET_FREQ_FROM_OBS
1500             freq = 16000000U;
1501 #else
1502             freq = CLOCK_GetFreqFromObs(CCM_OBS_OSC_RC_16M);
1503 #endif
1504             break;
1505         case kCLOCK_OscRc48M:
1506 #ifndef GET_FREQ_FROM_OBS
1507             freq = 48000000U;
1508 #else
1509             freq = CLOCK_GetFreqFromObs(CCM_OBS_OSC_RC_48M);
1510 #endif
1511             break;
1512         case kCLOCK_OscRc48MDiv2:
1513 #ifndef GET_FREQ_FROM_OBS
1514             freq = 24000000U;
1515 #else
1516             freq = CLOCK_GetFreqFromObs(CCM_OBS_OSC_RC_48M_DIV2);
1517 #endif
1518             break;
1519         case kCLOCK_OscRc400M:
1520 #ifndef GET_FREQ_FROM_OBS
1521             freq = 400000000U;
1522 #else
1523             freq = CLOCK_GetFreqFromObs(CCM_OBS_OSC_RC_400M);
1524 #endif
1525             break;
1526         case kCLOCK_Osc24MOut:
1527         case kCLOCK_Osc24M:
1528 #ifndef GET_FREQ_FROM_OBS
1529             freq = 24000000U;
1530 #else
1531             freq = CLOCK_GetFreqFromObs(CCM_OBS_OSC_24M_OUT);
1532 #endif
1533             break;
1534         case kCLOCK_ArmPllOut:
1535         case kCLOCK_ArmPll:
1536             freq = CLOCK_GetPllFreq(kCLOCK_PllArm);
1537             break;
1538         case kCLOCK_SysPll2:
1539         case kCLOCK_SysPll2Out:
1540             freq = CLOCK_GetPllFreq(kCLOCK_PllSys2);
1541             break;
1542         case kCLOCK_SysPll2Pfd0:
1543             freq = CLOCK_GetPfdFreq(kCLOCK_PllSys2, kCLOCK_Pfd0);
1544             break;
1545         case kCLOCK_SysPll2Pfd1:
1546             freq = CLOCK_GetPfdFreq(kCLOCK_PllSys2, kCLOCK_Pfd1);
1547             break;
1548         case kCLOCK_SysPll2Pfd2:
1549             freq = CLOCK_GetPfdFreq(kCLOCK_PllSys2, kCLOCK_Pfd2);
1550             break;
1551         case kCLOCK_SysPll2Pfd3:
1552             freq = CLOCK_GetPfdFreq(kCLOCK_PllSys2, kCLOCK_Pfd3);
1553             break;
1554         case kCLOCK_SysPll3Out:
1555         case kCLOCK_SysPll3:
1556             freq = CLOCK_GetPllFreq(kCLOCK_PllSys3);
1557             break;
1558         case kCLOCK_SysPll3Div2:
1559             freq = (CLOCK_GetPllFreq(kCLOCK_PllSys3) / 2UL);
1560             break;
1561         case kCLOCK_SysPll3Pfd0:
1562             freq = CLOCK_GetPfdFreq(kCLOCK_PllSys3, kCLOCK_Pfd0);
1563             break;
1564         case kCLOCK_SysPll3Pfd1:
1565             freq = CLOCK_GetPfdFreq(kCLOCK_PllSys3, kCLOCK_Pfd1);
1566             break;
1567         case kCLOCK_SysPll3Pfd2:
1568             freq = CLOCK_GetPfdFreq(kCLOCK_PllSys3, kCLOCK_Pfd2);
1569             break;
1570         case kCLOCK_SysPll3Pfd3:
1571             freq = CLOCK_GetPfdFreq(kCLOCK_PllSys3, kCLOCK_Pfd3);
1572             break;
1573         case kCLOCK_SysPll1:
1574         case kCLOCK_SysPll1Out:
1575             freq = CLOCK_GetPllFreq(kCLOCK_PllSys1);
1576             break;
1577         case kCLOCK_SysPll1Div2:
1578             freq = CLOCK_GetPllFreq(kCLOCK_PllSys1) / 2UL;
1579             break;
1580         case kCLOCK_SysPll1Div5:
1581             freq = CLOCK_GetPllFreq(kCLOCK_PllSys1) / 5UL;
1582             break;
1583         case kCLOCK_AudioPll:
1584         case kCLOCK_AudioPllOut:
1585             freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
1586             break;
1587         case kCLOCK_VideoPll:
1588         case kCLOCK_VideoPllOut:
1589             freq = CLOCK_GetPllFreq(kCLOCK_PllVideo);
1590             break;
1591         case kCLOCK_CpuClk:
1592         case kCLOCK_CoreSysClk:
1593             freq = CLOCK_GetCpuClkFreq();
1594             break;
1595         default:
1596             /* Wrong input parameter name. */
1597             assert(false);
1598             break;
1599     }
1600     assert(freq != 0UL);
1601     return freq;
1602 }
1603 
CLOCK_SetGroupConfig(clock_group_t group,const clock_group_config_t * config)1604 void CLOCK_SetGroupConfig(clock_group_t group, const clock_group_config_t *config)
1605 {
1606     assert(group < kCLOCK_Group_Last);
1607 
1608     CCM->CLOCK_GROUP[group].CONTROL = ((config->clockOff ? CCM_CLOCK_GROUP_CONTROL_OFF_MASK : 0UL) |
1609                                        ((uint32_t)config->resetDiv << CCM_CLOCK_GROUP_CONTROL_RSTDIV_SHIFT) |
1610                                        (config->div0 << CCM_CLOCK_GROUP_CONTROL_DIV0_SHIFT));
1611 }
1612 
CLOCK_OSC_TrimOscRc400M(bool enable,bool bypass,uint16_t trim)1613 void CLOCK_OSC_TrimOscRc400M(bool enable, bool bypass, uint16_t trim)
1614 {
1615     if (enable)
1616     {
1617         ANADIG_MISC->VDDLPSR_AI400M_CTRL  = 0x20UL;
1618         ANADIG_MISC->VDDLPSR_AI400M_WDATA = ((uint32_t)bypass << 10UL) | ((uint32_t)trim << 24UL);
1619         ANADIG_MISC->VDDLPSR_AI400M_CTRL |= 0x100UL;
1620         SDK_DelayAtLeastUs(1, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
1621         ANADIG_MISC->VDDLPSR_AI400M_CTRL &= ~0x100UL;
1622     }
1623 }
1624 
CLOCK_OSC_EnableOscRc400M(void)1625 void CLOCK_OSC_EnableOscRc400M(void)
1626 {
1627     ANADIG_OSC->OSC_400M_CTRL1 &= ~ANADIG_OSC_OSC_400M_CTRL1_PWD_MASK;
1628     ANADIG_OSC->OSC_400M_CTRL2 |= ANADIG_OSC_OSC_400M_CTRL2_ENABLE_CLK_MASK;
1629 }
1630 
CLOCK_GetFreqFromObs(uint32_t obsSigIndex,uint32_t obsIndex)1631 uint32_t CLOCK_GetFreqFromObs(uint32_t obsSigIndex, uint32_t obsIndex)
1632 {
1633     CCM_OBS->OBSERVE[obsIndex].CONTROL     = CCM_OBS_OBSERVE_CONTROL_OFF_MASK;   /* turn off detect */
1634     CCM_OBS->OBSERVE[obsIndex].CONTROL_SET = CCM_OBS_OBSERVE_CONTROL_RESET_MASK; /* reset slice */
1635     CCM_OBS->OBSERVE[obsIndex].CONTROL_CLR = CCM_OBS_OBSERVE_CONTROL_RAW_MASK;   /* select raw obsSigIndex */
1636     CCM_OBS->OBSERVE[obsIndex].CONTROL &= ~CCM_OBS_OBSERVE_CONTROL_SELECT_MASK;  /* Select observed obsSigIndex */
1637     CCM_OBS->OBSERVE[obsIndex].CONTROL |= CCM_OBS_OBSERVE_CONTROL_SELECT(obsSigIndex) |
1638                                           CCM_OBS_OBSERVE_CONTROL_DIVIDE(CCM_OBS_DIV); /* turn on detection */
1639     CCM_OBS->OBSERVE[obsIndex].CONTROL_CLR =
1640         CCM_OBS_OBSERVE_CONTROL_RESET_MASK | CCM_OBS_OBSERVE_CONTROL_OFF_MASK; /* unreset and turn on detect */
1641 
1642     while (CCM_OBS->OBSERVE[obsIndex].FREQUENCY_CURRENT == 0UL)
1643     {
1644     }
1645 
1646     return (CCM_OBS->OBSERVE[obsIndex].FREQUENCY_CURRENT * ((uint32_t)CCM_OBS_DIV + 1UL));
1647 }
1648 
1649 /*! brief Enable USB HS clock.
1650  *
1651  * This function only enables the access to USB HS prepheral, upper layer
1652  * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY
1653  * clock to use USB HS.
1654  *
1655  * param src  USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused.
1656  * param freq USB HS does not care about the clock source, so this parameter is ignored.
1657  * retval true The clock is set successfully.
1658  * retval false The clock source is invalid to get proper USB HS clock.
1659  */
CLOCK_EnableUsbhs0Clock(clock_usb_src_t src,uint32_t freq)1660 bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq)
1661 {
1662     return true;
1663 }
1664 /*! brief Enable USB HS PHY PLL clock.
1665  *
1666  * This function enables the internal 480MHz USB PHY PLL clock.
1667  *
1668  * param src  USB HS PHY PLL clock source.
1669  * param freq The frequency specified by src.
1670  * retval true The clock is set successfully.
1671  * retval false The clock source is invalid to get proper USB HS clock.
1672  */
CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src,uint32_t freq)1673 bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
1674 {
1675     uint32_t phyPllDiv  = 0U;
1676     uint16_t multiplier = 0U;
1677     bool err            = false;
1678     CLOCK_EnableClock(kCLOCK_Usb);
1679 
1680     USBPHY1->CTRL_CLR = USBPHY_CTRL_SFTRST_MASK;
1681 
1682     USBPHY1->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_POWER(1) | USBPHY_PLL_SIC_PLL_REG_ENABLE_MASK);
1683     if ((480000000UL % freq) != 0UL)
1684     {
1685         return false;
1686     }
1687     multiplier = (uint16_t)(480000000UL / freq);
1688 
1689     switch (multiplier)
1690     {
1691         case 13:
1692         {
1693             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);
1694             break;
1695         }
1696         case 15:
1697         {
1698             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);
1699             break;
1700         }
1701         case 16:
1702         {
1703             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);
1704             break;
1705         }
1706         case 20:
1707         {
1708             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(3U);
1709             break;
1710         }
1711         case 22:
1712         {
1713             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(4U);
1714             break;
1715         }
1716         case 25:
1717         {
1718             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(5U);
1719             break;
1720         }
1721         case 30:
1722         {
1723             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(6U);
1724             break;
1725         }
1726         case 240:
1727         {
1728             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(7U);
1729             break;
1730         }
1731         default:
1732         {
1733             err = true;
1734             break;
1735         }
1736     }
1737 
1738     if (err)
1739     {
1740         return false;
1741     }
1742 
1743     USBPHY1->PLL_SIC = (USBPHY1->PLL_SIC & ~(USBPHY_PLL_SIC_PLL_DIV_SEL_MASK)) | phyPllDiv;
1744 
1745     USBPHY1->PLL_SIC_CLR = USBPHY_PLL_SIC_PLL_BYPASS_MASK;
1746     USBPHY1->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK);
1747 
1748     USBPHY1->CTRL_CLR = USBPHY_CTRL_CLR_CLKGATE_MASK;
1749 
1750     while (0UL == (USBPHY1->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK))
1751     {
1752     }
1753     return true;
1754 }
1755 /*! brief Enable USB HS clock.
1756  *
1757  * This function only enables the access to USB HS prepheral, upper layer
1758  * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY
1759  * clock to use USB HS.
1760  *
1761  * param src  USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused.
1762  * param freq USB HS does not care about the clock source, so this parameter is ignored.
1763  * retval true The clock is set successfully.
1764  * retval false The clock source is invalid to get proper USB HS clock.
1765  */
1766 /*! brief Disable USB HS PHY PLL clock.
1767  *
1768  * This function disables USB HS PHY PLL clock.
1769  */
CLOCK_DisableUsbhs0PhyPllClock(void)1770 void CLOCK_DisableUsbhs0PhyPllClock(void)
1771 {
1772     USBPHY1->PLL_SIC_CLR = (USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK);
1773     USBPHY1->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
1774 }
CLOCK_EnableUsbhs1Clock(clock_usb_src_t src,uint32_t freq)1775 bool CLOCK_EnableUsbhs1Clock(clock_usb_src_t src, uint32_t freq)
1776 {
1777     return true;
1778 }
CLOCK_EnableUsbhs1PhyPllClock(clock_usb_phy_src_t src,uint32_t freq)1779 bool CLOCK_EnableUsbhs1PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
1780 {
1781     uint32_t phyPllDiv  = 0U;
1782     uint16_t multiplier = 0U;
1783     bool err            = false;
1784     CLOCK_EnableClock(kCLOCK_Usb);
1785 
1786     USBPHY2->CTRL_CLR = USBPHY_CTRL_SFTRST_MASK;
1787 
1788     USBPHY2->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_POWER(1) | USBPHY_PLL_SIC_PLL_REG_ENABLE_MASK);
1789     if ((480000000UL % freq) != 0UL)
1790     {
1791         return false;
1792     }
1793     multiplier = (uint16_t)(uint32_t)(480000000UL / freq);
1794 
1795     switch (multiplier)
1796     {
1797         case 13:
1798         {
1799             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(0U);
1800             break;
1801         }
1802         case 15:
1803         {
1804             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(1U);
1805             break;
1806         }
1807         case 16:
1808         {
1809             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(2U);
1810             break;
1811         }
1812         case 20:
1813         {
1814             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(3U);
1815             break;
1816         }
1817         case 22:
1818         {
1819             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(4U);
1820             break;
1821         }
1822         case 25:
1823         {
1824             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(5U);
1825             break;
1826         }
1827         case 30:
1828         {
1829             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(6U);
1830             break;
1831         }
1832         case 240:
1833         {
1834             phyPllDiv = USBPHY_PLL_SIC_PLL_DIV_SEL(7U);
1835             break;
1836         }
1837         default:
1838         {
1839             err = true;
1840             break;
1841         }
1842     }
1843 
1844     if (err)
1845     {
1846         return false;
1847     }
1848     USBPHY2->PLL_SIC = (USBPHY2->PLL_SIC & ~(USBPHY_PLL_SIC_PLL_DIV_SEL_MASK)) | phyPllDiv;
1849 
1850     USBPHY2->PLL_SIC_CLR = USBPHY_PLL_SIC_PLL_BYPASS_MASK;
1851     USBPHY2->PLL_SIC_SET = (USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK);
1852 
1853     USBPHY2->CTRL_CLR = USBPHY_CTRL_CLR_CLKGATE_MASK;
1854 
1855     while (0UL == (USBPHY2->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK))
1856     {
1857     }
1858     return true;
1859 }
1860 /*! brief Disable USB HS PHY PLL clock.
1861  *
1862  * This function disables USB HS PHY PLL clock.
1863  */
CLOCK_DisableUsbhs1PhyPllClock(void)1864 void CLOCK_DisableUsbhs1PhyPllClock(void)
1865 {
1866     USBPHY2->PLL_SIC_CLR = (USBPHY_PLL_SIC_PLL_EN_USB_CLKS_MASK);
1867     USBPHY2->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
1868 }
1869 
CLOCK_OSCPLL_ControlBySetPointMode(clock_name_t name,uint16_t spValue,uint16_t stbyValue)1870 void CLOCK_OSCPLL_ControlBySetPointMode(clock_name_t name, uint16_t spValue, uint16_t stbyValue)
1871 {
1872     /* Set control mode to unassigned mode. */
1873     CCM->OSCPLL[name].AUTHEN &=
1874         ~(CCM_OSCPLL_AUTHEN_CPULPM_MASK | CCM_OSCPLL_AUTHEN_DOMAIN_MODE_MASK | CCM_OSCPLL_AUTHEN_SETPOINT_MODE_MASK);
1875     /* Change SetPoint value in unassigned mode. */
1876     CCM->OSCPLL[name].SETPOINT = CCM_OSCPLL_SETPOINT_STANDBY(stbyValue) | CCM_OSCPLL_SETPOINT_SETPOINT(spValue);
1877     /* Set control mode to SetPoint mode. */
1878     CCM->OSCPLL[name].AUTHEN |= CCM_OSCPLL_AUTHEN_SETPOINT_MODE_MASK;
1879 }
1880 
CLOCK_OSCPLL_ControlByCpuLowPowerMode(clock_name_t name,uint8_t domainId,clock_level_t level0,clock_level_t level1)1881 void CLOCK_OSCPLL_ControlByCpuLowPowerMode(clock_name_t name,
1882                                            uint8_t domainId,
1883                                            clock_level_t level0,
1884                                            clock_level_t level1)
1885 {
1886     /* Set control mode to unassigned mode. */
1887     CCM->OSCPLL[name].AUTHEN &=
1888         ~(CCM_OSCPLL_AUTHEN_SETPOINT_MODE_MASK | CCM_OSCPLL_AUTHEN_DOMAIN_MODE_MASK | CCM_OSCPLL_AUTHEN_CPULPM_MASK);
1889     /* Change clock depend level for each domain in unassigned mode. */
1890     CCM->OSCPLL[name].DOMAINr =
1891         ((((uint32_t)domainId & (1UL << 1UL)) != 0UL) ? CCM_OSCPLL_DOMAIN_LEVEL1(level1) : 0UL) |
1892         (((domainId & (1UL << 0UL)) != 0UL) ? CCM_OSCPLL_DOMAIN_LEVEL0(level0) : 0UL);
1893     /* Set control mode to CPU low power mode and update whitelist. */
1894     CCM->OSCPLL[name].AUTHEN = (CCM->OSCPLL[name].AUTHEN & ~CCM_OSCPLL_AUTHEN_WHITE_LIST_MASK) |
1895                                CCM_OSCPLL_AUTHEN_CPULPM_MASK | CCM_OSCPLL_AUTHEN_WHITE_LIST(domainId);
1896 }
1897 
CLOCK_ROOT_ControlBySetPointMode(clock_root_t name,const clock_root_setpoint_config_t * spTable)1898 void CLOCK_ROOT_ControlBySetPointMode(clock_root_t name, const clock_root_setpoint_config_t *spTable)
1899 {
1900     uint8_t i;
1901 
1902     /* Set control mode to unassigned mode. */
1903     CLOCK_ROOT_ControlByUnassignedMode(name);
1904     /* Change SetPoint value in unassigned mode. */
1905     for (i = 0U; i < 16U; i++)
1906     {
1907         CLOCK_ROOT_ConfigSetPoint(name, i, &spTable[i]);
1908     }
1909     /* Set control mode to SetPoint mode. */
1910     CLOCK_ROOT_EnableSetPointControl(name);
1911 }
1912 
CLOCK_LPCG_ControlBySetPointMode(clock_lpcg_t name,uint16_t spValue,uint16_t stbyValue)1913 void CLOCK_LPCG_ControlBySetPointMode(clock_lpcg_t name, uint16_t spValue, uint16_t stbyValue)
1914 {
1915     /* Set control mode to unassigned mode. */
1916     CCM->LPCG[name].AUTHEN &=
1917         ~(CCM_LPCG_AUTHEN_CPULPM_MASK | CCM_LPCG_AUTHEN_DOMAIN_MODE_MASK | CCM_LPCG_AUTHEN_SETPOINT_MODE_MASK);
1918     /* Change SetPoint value in unassigned mode. */
1919     CCM->LPCG[name].SETPOINT = CCM_LPCG_SETPOINT_STANDBY(stbyValue) | CCM_LPCG_SETPOINT_SETPOINT(spValue);
1920     /* Set control mode to SetPoint mode. */
1921     CCM->LPCG[name].AUTHEN |= CCM_LPCG_AUTHEN_SETPOINT_MODE_MASK;
1922 }
1923 
CLOCK_LPCG_ControlByCpuLowPowerMode(clock_lpcg_t name,uint8_t domainId,clock_level_t level0,clock_level_t level1)1924 void CLOCK_LPCG_ControlByCpuLowPowerMode(clock_lpcg_t name,
1925                                          uint8_t domainId,
1926                                          clock_level_t level0,
1927                                          clock_level_t level1)
1928 {
1929     /* Set control mode to unassigned mode. */
1930     CCM->LPCG[name].AUTHEN &=
1931         ~(CCM_LPCG_AUTHEN_SETPOINT_MODE_MASK | CCM_LPCG_AUTHEN_DOMAIN_MODE_MASK | CCM_LPCG_AUTHEN_CPULPM_MASK);
1932     /* Change clock depend level for each domain in unassigned mode. */
1933     CCM->LPCG[name].DOMAINr = ((((uint32_t)domainId & (1UL << 1UL)) != 0UL) ? CCM_LPCG_DOMAIN_LEVEL1(level1) : 0UL) |
1934                               ((((uint32_t)domainId & (1UL << 0UL)) != 0UL) ? CCM_LPCG_DOMAIN_LEVEL0(level0) : 0UL);
1935     /* Set control mode to CPU low power mode and update whitelist. */
1936     CCM->LPCG[name].AUTHEN = (CCM->LPCG[name].AUTHEN & ~CCM_LPCG_AUTHEN_WHITE_LIST_MASK) | CCM_LPCG_AUTHEN_CPULPM_MASK |
1937                              CCM_LPCG_AUTHEN_WHITE_LIST(domainId);
1938 }
1939