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