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