1 /*
2 * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
3 * Copyright (c) 2024, Altera Corporation. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <assert.h>
9 #include <errno.h>
10
11 #include <common/debug.h>
12 #include <drivers/delay_timer.h>
13 #include <lib/mmio.h>
14
15 #include "agilex5_clock_manager.h"
16 #include "agilex5_system_manager.h"
17 #include "socfpga_system_manager.h"
18
19 /* Main and Peripheral PLL configurations in Power Down(PD) state. */
20 static const pll_cfg_t pll_cfg_set[] = {
21 {
22 /* Enable source synchronous mode */
23 CLKMGR_PLLCFG_SRC_SYNC_MODE,
24 BIT(7),
25 BIT(7)
26 },
27 {
28 /* Limit the PLL overshoot frequency during lock */
29 CLKMGR_PLLCFG_OVRSHOOT_FREQ_LOCK,
30 BIT(0),
31 BIT(0)
32 },
33 {
34 /* To give the PLL more time to settle before lock is asserted */
35 CLKMGR_PLLCFG_LOCK_SETTLE_TIME,
36 BIT(0),
37 BIT(0)
38 },
39 {
40 /* To set the PLL centering duty cycle for clock slice 0 */
41 CLKMGR_PLLCFG_DUTYCYCLE_CLKSLICE0,
42 0x4A,
43 GENMASK(6, 0)
44 },
45 {
46 /* To set the PLL centering duty cycle for clock slice 1 */
47 CLKMGR_PLLCFG_DUTYCYCLE_CLKSLICE1,
48 0x4A,
49 GENMASK(6, 0)
50 },
51 };
52
wait_pll_lock(uint32_t mask)53 static int wait_pll_lock(uint32_t mask)
54 {
55 uint32_t data;
56 uint32_t count = 0;
57 uint32_t retry = 0U;
58
59 do {
60 /* return time out */
61 if (count >= CLKMGR_MAX_RETRY_COUNT) {
62 ERROR("CLKMGR: Timed out to satisfy the PLL mask\n");
63 return -ETIMEDOUT;
64 }
65
66 data = mmio_read_32(CLKMGR(STAT)) & mask;
67 /* wait for stable lock, make sure it is stable for these counts */
68 if (data == mask) {
69 retry++;
70 } else {
71 retry = 0U;
72 }
73
74 /* we are good now, break */
75 if (retry >= 5U) {
76 break;
77 }
78
79 count++;
80 } while (1);
81
82 return 0;
83 }
84
wait_fsm(void)85 static int wait_fsm(void)
86 {
87 uint32_t data;
88 uint32_t count = 0;
89
90 do {
91 data = mmio_read_32(CLKMGR(STAT));
92 count++;
93 if (count >= CLKMGR_MAX_RETRY_COUNT) {
94 ERROR("CLKMGR: Timed out on fsm state\n");
95 return -ETIMEDOUT;
96 }
97 } while (CLKMGR_STAT_BUSY(data) == CLKMGR_STAT_BUSY_E_BUSY);
98
99 return 0;
100 }
101
calc_pll_vcocalibration(uint32_t pllm,uint32_t pllglob)102 static uint32_t calc_pll_vcocalibration(uint32_t pllm, uint32_t pllglob)
103 {
104 uint32_t mdiv, refclkdiv, drefclkdiv, mscnt, hscnt, vcocalib;
105
106 mdiv = pllm & CLKMGR_PLLM_MDIV_MASK;
107 drefclkdiv = ((pllglob & CLKMGR_PLLGLOB_DREFCLKDIV_MASK) >>
108 CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET);
109 refclkdiv = ((pllglob & CLKMGR_PLLGLOB_REFCLKDIV_MASK) >>
110 CLKMGR_PLLGLOB_REFCLKDIV_OFFSET);
111 mscnt = CLKMGR_VCOCALIB_MSCNT_CONST / (mdiv * BIT(drefclkdiv));
112 if (mscnt == 0) {
113 mscnt = 1;
114 }
115
116 hscnt = (mdiv * mscnt * BIT(drefclkdiv) / refclkdiv) -
117 CLKMGR_VCOCALIB_HSCNT_CONST;
118
119 vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
120 ((mscnt << CLKMGR_VCOCALIB_MSCNT_OFFSET) &
121 CLKMGR_VCOCALIB_MSCNT_MASK);
122
123 return vcocalib;
124 }
125
pll_source_sync_wait(uint32_t pll_type,int retry_count)126 static int pll_source_sync_wait(uint32_t pll_type, int retry_count)
127 {
128 int count = 0;
129 uint32_t req_status;
130
131 if ((pll_type == CLKMGR_MAINPLL_TYPE) != 0) {
132 req_status = mmio_read_32(CLKMGR_MAINPLL(MEM));
133 } else {
134 req_status = mmio_read_32(CLKMGR_PERPLL(MEM));
135 }
136
137 /* Check for error bit set */
138 if ((req_status & CLKMGR_MEM_ERR) != 0) {
139 INFO("CLKMGR: %s: Memory Error Status Signal Assert\n", __func__);
140 }
141
142 while ((count < retry_count) && (req_status & CLKMGR_MEM_REQ)) {
143 if (pll_type == CLKMGR_MAINPLL_TYPE)
144 req_status = mmio_read_32(CLKMGR_MAINPLL(MEM));
145 else
146 req_status = mmio_read_32(CLKMGR_PERPLL(MEM));
147 count++;
148 }
149
150 if (count >= retry_count) {
151 ERROR("CLKMGR: %s: timeout with pll_type %d\n", __func__, pll_type);
152 return -ETIMEDOUT;
153 }
154
155 return 0;
156 }
157
pll_source_sync_config(uint32_t pll_type,uint32_t addr_offset,uint32_t wdat,int retry_count)158 static int pll_source_sync_config(uint32_t pll_type, uint32_t addr_offset,
159 uint32_t wdat, int retry_count)
160 {
161 uint32_t addr;
162 uint32_t val;
163
164 addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
165 val = (CLKMGR_MEM_REQ | CLKMGR_MEM_WR |
166 (wdat << CLKMGR_MEM_WDAT_OFFSET) | addr);
167
168 if ((pll_type == CLKMGR_MAINPLL_TYPE) != 0) {
169 mmio_write_32(CLKMGR_MAINPLL(MEM), val);
170 } else {
171 mmio_write_32(CLKMGR_PERPLL(MEM), val);
172 }
173
174 return pll_source_sync_wait(pll_type, retry_count);
175 }
176
pll_source_sync_read(uint32_t pll_type,uint32_t addr_offset,uint32_t * rdata,int retry_count)177 static int pll_source_sync_read(uint32_t pll_type, uint32_t addr_offset,
178 uint32_t *rdata, int retry_count)
179 {
180 uint32_t addr;
181 uint32_t val;
182
183 addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
184 val = ((CLKMGR_MEM_REQ & ~CLKMGR_MEM_WR) | addr);
185
186 if ((pll_type == CLKMGR_MAINPLL_TYPE) != 0) {
187 mmio_write_32(CLKMGR_MAINPLL(MEM), val);
188 } else {
189 mmio_write_32(CLKMGR_PERPLL(MEM), val);
190 }
191
192 *rdata = 0;
193
194 if ((pll_source_sync_wait(pll_type, retry_count)) != 0) {
195 return -ETIMEDOUT;
196 }
197
198 if ((pll_type == CLKMGR_MAINPLL_TYPE) != 0) {
199 *rdata = mmio_read_32(CLKMGR_MAINPLL(MEMSTAT));
200 } else {
201 *rdata = mmio_read_32(CLKMGR_PERPLL(MEMSTAT));
202 }
203
204 return 0;
205 }
206
config_pll_pd_state(uint32_t pll_type)207 static void config_pll_pd_state(uint32_t pll_type)
208 {
209 uint32_t rdata;
210
211 for (uint32_t i = 0; i < ARRAY_SIZE(pll_cfg_set); i++) {
212 (void)pll_source_sync_read(pll_type, pll_cfg_set[i].addr, &rdata,
213 CLKMGR_MAX_RETRY_COUNT);
214
215 (void)pll_source_sync_config(pll_type, pll_cfg_set[i].addr,
216 ((rdata & ~pll_cfg_set[i].mask) | pll_cfg_set[i].data),
217 CLKMGR_MAX_RETRY_COUNT);
218 }
219 }
220
config_clkmgr_handoff(handoff * hoff_ptr)221 int config_clkmgr_handoff(handoff *hoff_ptr)
222 {
223 int ret = 0;
224 uint32_t mainpll_vcocalib;
225 uint32_t perpll_vcocalib;
226
227 /* Enter boot mode before any configuration */
228 mmio_setbits_32(CLKMGR(CTRL), CLKMGR_CTRL_BOOTMODE);
229
230 /* Bypass all mainpllgrp's clocks to input clock ref */
231 mmio_setbits_32(CLKMGR_MAINPLL(BYPASS), CLKMGR_MAINPLL_BYPASS_ALL);
232 ret = wait_fsm();
233 if (ret != 0)
234 return ret;
235
236 /* Bypass all perpllgrp's clocks to input clock ref */
237 mmio_setbits_32(CLKMGR_PERPLL(BYPASS), CLKMGR_PERPLL_BYPASS_ALL);
238 ret = wait_fsm();
239 if (ret != 0)
240 return ret;
241
242 /* Take both PLL out of reset and power down */
243 mmio_clrbits_32(CLKMGR_MAINPLL(PLLGLOB),
244 CLKMGR_MAINPLL_PLLGLOB_PD_N | CLKMGR_MAINPLL_PLLGLOB_RST_N);
245 mmio_clrbits_32(CLKMGR_PERPLL(PLLGLOB),
246 CLKMGR_PERPLL_PLLGLOB_PD_N | CLKMGR_PERPLL_PLLGLOB_RST_N);
247
248 /* Setup main PLL dividers */
249 mainpll_vcocalib = calc_pll_vcocalibration(hoff_ptr->main_pll_pllm,
250 hoff_ptr->main_pll_pllglob);
251 mmio_write_32(CLKMGR_MAINPLL(PLLGLOB),
252 hoff_ptr->main_pll_pllglob & ~CLKMGR_MAINPLL_PLLGLOB_RST_N);
253 mmio_write_32(CLKMGR_MAINPLL(FDBCK), hoff_ptr->main_pll_fdbck);
254 mmio_write_32(CLKMGR_MAINPLL(VCOCALIB), mainpll_vcocalib);
255 mmio_write_32(CLKMGR_MAINPLL(PLLC0), hoff_ptr->main_pll_pllc0);
256 mmio_write_32(CLKMGR_MAINPLL(PLLC1), hoff_ptr->main_pll_pllc1);
257 mmio_write_32(CLKMGR_MAINPLL(PLLC2), hoff_ptr->main_pll_pllc2);
258 mmio_write_32(CLKMGR_MAINPLL(PLLC3), hoff_ptr->main_pll_pllc3);
259 mmio_write_32(CLKMGR_MAINPLL(PLLM), hoff_ptr->main_pll_pllm);
260 mmio_write_32(CLKMGR_MAINPLL(NOCCLK), hoff_ptr->main_pll_nocclk);
261 mmio_write_32(CLKMGR_MAINPLL(NOCDIV), hoff_ptr->main_pll_nocdiv);
262
263 /* Setup peripheral PLL dividers */
264 perpll_vcocalib = calc_pll_vcocalibration(hoff_ptr->per_pll_pllm,
265 hoff_ptr->per_pll_pllglob);
266 mmio_write_32(CLKMGR_PERPLL(PLLGLOB),
267 hoff_ptr->per_pll_pllglob & ~CLKMGR_PERPLL_PLLGLOB_RST_N);
268 mmio_write_32(CLKMGR_PERPLL(FDBCK), hoff_ptr->per_pll_fdbck);
269 mmio_write_32(CLKMGR_PERPLL(VCOCALIB), perpll_vcocalib);
270 mmio_write_32(CLKMGR_PERPLL(PLLC0), hoff_ptr->per_pll_pllc0);
271 mmio_write_32(CLKMGR_PERPLL(PLLC1), hoff_ptr->per_pll_pllc1);
272 mmio_write_32(CLKMGR_PERPLL(PLLC2), hoff_ptr->per_pll_pllc2);
273 mmio_write_32(CLKMGR_PERPLL(PLLC3), hoff_ptr->per_pll_pllc3);
274 mmio_write_32(CLKMGR_PERPLL(PLLM), hoff_ptr->per_pll_pllm);
275 mmio_write_32(CLKMGR_PERPLL(EMACCTL), hoff_ptr->per_pll_emacctl);
276 mmio_write_32(CLKMGR_PERPLL(GPIODIV), hoff_ptr->per_pll_gpiodiv);
277
278 /* Configure ping pong counters */
279 mmio_write_32(CLKMGR_ALTERA(EMACACTR), hoff_ptr->alt_emacactr);
280 mmio_write_32(CLKMGR_ALTERA(EMACBCTR), hoff_ptr->alt_emacbctr);
281 mmio_write_32(CLKMGR_ALTERA(EMACPTPCTR), hoff_ptr->alt_emacptpctr);
282 mmio_write_32(CLKMGR_ALTERA(GPIODBCTR), hoff_ptr->alt_gpiodbctr);
283 mmio_write_32(CLKMGR_ALTERA(S2FUSER0CTR), hoff_ptr->alt_s2fuser0ctr);
284 mmio_write_32(CLKMGR_ALTERA(S2FUSER1CTR), hoff_ptr->alt_s2fuser1ctr);
285 mmio_write_32(CLKMGR_ALTERA(PSIREFCTR), hoff_ptr->alt_psirefctr);
286 mmio_write_32(CLKMGR_ALTERA(USB31CTR), hoff_ptr->alt_usb31ctr);
287 mmio_write_32(CLKMGR_ALTERA(DSUCTR), hoff_ptr->alt_dsuctr);
288 mmio_write_32(CLKMGR_ALTERA(CORE01CTR), hoff_ptr->alt_core01ctr);
289 mmio_write_32(CLKMGR_ALTERA(CORE23CTR), hoff_ptr->alt_core23ctr);
290 mmio_write_32(CLKMGR_ALTERA(CORE2CTR), hoff_ptr->alt_core2ctr);
291 mmio_write_32(CLKMGR_ALTERA(CORE3CTR), hoff_ptr->alt_core3ctr);
292
293 /* Take both PLL out of reset and power up */
294 mmio_setbits_32(CLKMGR_MAINPLL(PLLGLOB),
295 CLKMGR_MAINPLL_PLLGLOB_PD_N | CLKMGR_MAINPLL_PLLGLOB_RST_N);
296 mmio_setbits_32(CLKMGR_PERPLL(PLLGLOB),
297 CLKMGR_PERPLL_PLLGLOB_PD_N | CLKMGR_PERPLL_PLLGLOB_RST_N);
298
299 /* Main PLL configuration in Powed down state */
300 config_pll_pd_state(CLKMGR_MAINPLL_TYPE);
301
302 /* Peripheral PLL configuration in Powed down state */
303 config_pll_pd_state(CLKMGR_PERPLL_TYPE);
304
305 /* Enable main PLL clkslices */
306 mmio_setbits_32(CLKMGR_MAINPLL(PLLC0), CLKMGR_MAINPLL_PLLCX_EN);
307 mmio_setbits_32(CLKMGR_MAINPLL(PLLC1), CLKMGR_MAINPLL_PLLCX_EN);
308 mmio_setbits_32(CLKMGR_MAINPLL(PLLC2), CLKMGR_MAINPLL_PLLCX_EN);
309 mmio_setbits_32(CLKMGR_MAINPLL(PLLC3), CLKMGR_MAINPLL_PLLCX_EN);
310
311 /* Enable periheral PLL clkslices */
312 mmio_setbits_32(CLKMGR_PERPLL(PLLC0), CLKMGR_PERPLL_PLLCX_EN);
313 mmio_setbits_32(CLKMGR_PERPLL(PLLC1), CLKMGR_PERPLL_PLLCX_EN);
314 mmio_setbits_32(CLKMGR_PERPLL(PLLC2), CLKMGR_PERPLL_PLLCX_EN);
315 mmio_setbits_32(CLKMGR_PERPLL(PLLC3), CLKMGR_PERPLL_PLLCX_EN);
316
317 /* Wait for main and peri PLL lock state */
318 ret = wait_pll_lock(CLKMGR_STAT_ALLPLLLOCKED);
319 if (ret != 0) {
320 return ret;
321 }
322
323 /* Main PLL and per PLL lost lock */
324 mmio_setbits_32(CLKMGR_MAINPLL(LOSTLOCK), CLKMGR_XPLL_LOSTLOCK_BYPASSCLEAR);
325 mmio_setbits_32(CLKMGR_PERPLL(LOSTLOCK), CLKMGR_XPLL_LOSTLOCK_BYPASSCLEAR);
326
327 /* Main PLL and per PLL clear lostlock bypass */
328 mmio_setbits_32(CLKMGR_MAINPLL(PLLGLOB), CLKMGR_XPLLGLOB_CLR_LOSTLOCK_BYPASS);
329 mmio_setbits_32(CLKMGR_PERPLL(PLLGLOB), CLKMGR_XPLLGLOB_CLR_LOSTLOCK_BYPASS);
330
331 /* Pass clock source frequency into boot scratch register */
332 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1), hoff_ptr->hps_osc_clk_hz);
333 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2), hoff_ptr->fpga_clk_hz);
334
335 /* Take all PLLs out of bypass */
336 mmio_clrbits_32(CLKMGR_MAINPLL(BYPASS), CLKMGR_MAINPLL_BYPASS_ALL);
337 ret = wait_fsm();
338 if (ret != 0) {
339 return ret;
340 }
341
342 mmio_clrbits_32(CLKMGR_PERPLL(BYPASS), CLKMGR_PERPLL_BYPASS_ALL);
343 ret = wait_fsm();
344 if (ret != 0) {
345 return ret;
346 }
347
348 /* Clear the loss of lock bits (write 1 to clear) */
349 mmio_write_32(CLKMGR(INTRCLR),
350 CLKMGR_INTRCLR_MAINLOCKLOST | CLKMGR_INTRCLR_PERLOCKLOST);
351
352 /* Take all ping pong counters out of reset */
353 mmio_clrbits_32(CLKMGR_ALTERA(EXTCNTRST), CLKMGR_ALTERA_EXTCNTRST_ALLCNTRST);
354
355 /* Exit boot mode */
356 mmio_clrbits_32(CLKMGR(CTRL), CLKMGR_CTRL_BOOTMODE);
357
358 return 0;
359 }
360
361 /* Extract reference clock from platform clock source */
get_ref_clk(uint32_t pllglob_reg,uint32_t pllm_reg)362 uint32_t get_ref_clk(uint32_t pllglob_reg, uint32_t pllm_reg)
363 {
364 uint32_t arefclkdiv, ref_clk, mdiv;
365 uint32_t pllglob_val, pllm_val;
366
367 /* Read pllglob and pllm registers */
368 pllglob_val = mmio_read_32(pllglob_reg);
369 pllm_val = mmio_read_32(pllm_reg);
370
371 switch (CLKMGR_PLLGLOB_PSRC(pllglob_val)) {
372 case CLKMGR_PLLGLOB_PSRC_EOSC1:
373 ref_clk = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1));
374 break;
375
376 case CLKMGR_PLLGLOB_PSRC_INTOSC:
377 ref_clk = CLKMGR_INTOSC_HZ;
378 break;
379
380 case CLKMGR_PLLGLOB_PSRC_F2S:
381 ref_clk = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2));
382 break;
383
384 default:
385 ref_clk = 0;
386 assert(0);
387 break;
388 }
389
390 /* Get reference clock divider */
391 arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob_val);
392 ref_clk /= arefclkdiv;
393
394 /* Feedback clock divider */
395 mdiv = CLKMGR_PLLM_MDIV(pllm_val);
396 ref_clk *= mdiv;
397
398 VERBOSE("CLKMGR: %s: ref_clk %u\n", __func__, ref_clk);
399 return ref_clk;
400 }
401
402 /* Calculate clock frequency based on parameter */
get_clk_freq(uint32_t psrc_reg,uint32_t mainpllc_reg,uint32_t perpllc_reg)403 uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t mainpllc_reg,
404 uint32_t perpllc_reg)
405 {
406 uint32_t clock = 0;
407 uint32_t clk_psrc;
408
409 /*
410 * Select source for the active 5:1 clock selection when the PLL
411 * is not bypassed
412 */
413 clk_psrc = mmio_read_32(psrc_reg);
414 switch (GET_CLKMGR_CLKSRC(clk_psrc)) {
415 case CLKMGR_CLKSRC_MAIN:
416 clock = get_ref_clk(CLKMGR_MAINPLL(PLLGLOB), CLKMGR_MAINPLL(PLLM));
417 clock /= (mmio_read_32(mainpllc_reg) & CLKMGR_PLLCX_DIV_MSK);
418 break;
419
420 case CLKMGR_CLKSRC_PER:
421 clock = get_ref_clk(CLKMGR_PERPLL(PLLGLOB), CLKMGR_PERPLL(PLLM));
422 clock /= (mmio_read_32(perpllc_reg) & CLKMGR_PLLCX_DIV_MSK);
423 break;
424
425 case CLKMGR_CLKSRC_OSC1:
426 clock = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1));
427 break;
428
429 case CLKMGR_CLKSRC_INTOSC:
430 clock = CLKMGR_INTOSC_HZ;
431 break;
432
433 case CLKMGR_CLKSRC_FPGA:
434 clock = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2));
435 break;
436
437 default:
438 ERROR("CLKMGR: Invalid clock source select\n");
439 assert(0);
440 break;
441 }
442
443 VERBOSE("CLKMGR: %s: clock type %lu and its value %u\n",
444 __func__, GET_CLKMGR_CLKSRC(clk_psrc), clock);
445
446 return clock;
447 }
448
449 /* Get L3 free clock */
get_l3_main_free_clk(void)450 static uint32_t get_l3_main_free_clk(void)
451 {
452 return get_clk_freq(CLKMGR_MAINPLL(NOCCLK),
453 CLKMGR_MAINPLL(PLLC3),
454 CLKMGR_PERPLL(PLLC1));
455 }
456
457 /* Get L4 main clock */
get_l4_main_clk(void)458 static uint32_t get_l4_main_clk(void)
459 {
460 return get_l3_main_free_clk();
461 }
462
463 /* Get L4 mp clock */
get_l4_mp_clk(void)464 static uint32_t get_l4_mp_clk(void)
465 {
466 uint32_t l3_main_free_clk = get_l3_main_free_clk();
467 uint32_t mainpll_nocdiv_l4mp = BIT(GET_CLKMGR_MAINPLL_NOCDIV_L4MP(
468 mmio_read_32(CLKMGR_MAINPLL(NOCDIV))));
469
470 uint32_t l4_mp_clk = (l3_main_free_clk / mainpll_nocdiv_l4mp);
471
472 return l4_mp_clk;
473 }
474
475 /* Get L4 sp clock */
get_l4_sp_clk(void)476 static uint32_t get_l4_sp_clk(void)
477 {
478 uint32_t l3_main_free_clk = get_l3_main_free_clk();
479 uint32_t mainpll_nocdiv_l4sp = BIT(GET_CLKMGR_MAINPLL_NOCDIV_L4SP(
480 mmio_read_32(CLKMGR_MAINPLL(NOCDIV))));
481
482 uint32_t l4_sp_clk = (l3_main_free_clk / mainpll_nocdiv_l4sp);
483
484 return l4_sp_clk;
485 }
486
487 /* Calculate clock frequency to be used for SDMMC driver */
get_sdmmc_clk(void)488 uint32_t get_sdmmc_clk(void)
489 {
490 uint32_t l4_mp_clk = get_l4_mp_clk();
491 uint32_t mainpll_nocdiv = mmio_read_32(CLKMGR_MAINPLL(NOCDIV));
492 uint32_t sdmmc_clk = l4_mp_clk / BIT(GET_CLKMGR_MAINPLL_NOCDIV_SPHY(mainpll_nocdiv));
493
494 return sdmmc_clk;
495 }
496
497 /* Get clock for ethernet mac0 */
get_emaca_clk(void)498 static uint32_t get_emaca_clk(void)
499 {
500 uint32_t emaca_ctr = mmio_read_32(CLKMGR_ALTERA(EMACACTR));
501 uint32_t perpll_emacctl = mmio_read_32(CLKMGR_PERPLL(EMACCTL));
502 uint32_t perpll_emac_src = GET_CLKMGR_PERPLL_EMAC0_CLK_SRC(perpll_emacctl);
503 uint32_t emac_ctr_reg;
504 uint32_t emac_clock;
505
506 if (perpll_emac_src != 0) {
507 emac_ctr_reg = CLKMGR_ALTERA(EMACBCTR);
508 } else {
509 emac_ctr_reg = CLKMGR_ALTERA(EMACACTR);
510 }
511
512 /* Get EMACA clock source */
513 uint32_t emacactr_src = GET_CLKMGR_EMACACTR_CLK_SRC(emaca_ctr);
514
515 /* Read the desired EMAC register again */
516 emaca_ctr = mmio_read_32(emac_ctr_reg);
517
518 /* Get the divider now */
519 uint32_t emaca_ctr_div = emaca_ctr & GENMASK(10, 0);
520
521 switch (emacactr_src) {
522 case CLKMGR_CLKSRC_MAIN:
523 emac_clock = get_ref_clk(CLKMGR_MAINPLL(PLLGLOB), CLKMGR_MAINPLL(PLLM));
524 emac_clock /= (mmio_read_32(CLKMGR_MAINPLL(PLLC1)) & GENMASK(10, 0));
525 break;
526
527 case CLKMGR_CLKSRC_PER:
528 emac_clock = get_ref_clk(CLKMGR_PERPLL(PLLGLOB), CLKMGR_PERPLL(PLLM));
529 emac_clock /= (mmio_read_32(CLKMGR_PERPLL(PLLC3)) & GENMASK(10, 0));
530 break;
531
532 default:
533 ERROR("CLKMGR: %s invalid clock source\n", __func__);
534 emac_clock = 0;
535 return emac_clock;
536 }
537
538 emac_clock /= 1 + emaca_ctr_div;
539
540 return emac_clock;
541 }
542
543 /* Get MPU clock */
get_mpu_clk(void)544 static uint32_t get_mpu_clk(void)
545 {
546 uint32_t cpu_id = MPIDR_AFFLVL1_VAL(read_mpidr());
547 uint32_t ctr_reg = 0U;
548 uint32_t clock;
549
550 if (cpu_id > CLKMGR_ALTERA_CORE1) {
551 clock = get_clk_freq(CLKMGR_ALTERA(CORE23CTR),
552 CLKMGR_MAINPLL(PLLC0),
553 CLKMGR_PERPLL(PLLC0));
554 } else {
555 clock = get_clk_freq(CLKMGR_ALTERA(CORE01CTR),
556 CLKMGR_MAINPLL(PLLC1),
557 CLKMGR_PERPLL(PLLC0));
558 }
559
560 switch (cpu_id) {
561 case CLKMGR_ALTERA_CORE0:
562 case CLKMGR_ALTERA_CORE1:
563 ctr_reg = CLKMGR_ALTERA(CORE01CTR);
564 break;
565
566 case CLKMGR_ALTERA_CORE2:
567 ctr_reg = CLKMGR_ALTERA(CORE2CTR);
568 break;
569
570 case CLKMGR_ALTERA_CORE3:
571 ctr_reg = CLKMGR_ALTERA(CORE3CTR);
572 break;
573
574 default:
575 break;
576 }
577
578 /* Division setting for ping pong counter in clock slice */
579 clock /= 1 + (mmio_read_32(ctr_reg) & CLKMGR_PLLCX_DIV_MSK);
580
581 return clock;
582 }
583
584 /* Calculate clock frequency to be used for watchdog timer */
get_wdt_clk(void)585 static uint32_t get_wdt_clk(void)
586 {
587 uint32_t l3_main_free_clk = get_l3_main_free_clk();
588 uint32_t mainpll_nocdiv_l4sysfreeclk = BIT(GET_CLKMGR_MAINPLL_NOCDIV_L4SYSFREE(
589 mmio_read_32(CLKMGR_MAINPLL(NOCDIV))));
590 uint32_t l4_sys_free_clk = (l3_main_free_clk / mainpll_nocdiv_l4sysfreeclk);
591
592 return l4_sys_free_clk;
593 }
594
595 /*
596 * Calculate clock frequency to be used for UART driver.
597 * 'l4_sp_clk' (100MHz) will be used for slow peripherals like UART, I2C
598 * and Timers.
599 */
get_uart_clk(void)600 static uint32_t get_uart_clk(void)
601 {
602 return get_l4_sp_clk();
603 }
604
605 /* Return the clock value of a given system component */
clkmgr_get_rate(uint32_t clk_id)606 uint32_t clkmgr_get_rate(uint32_t clk_id)
607 {
608 uint32_t clk_rate;
609
610 switch (clk_id) {
611 case CLKMGR_MPU_CLK_ID:
612 clk_rate = get_mpu_clk();
613 break;
614
615 case CLKMGR_L4_MAIN_CLK_ID:
616 clk_rate = get_l4_main_clk();
617 break;
618
619 case CLKMGR_L4_MP_CLK_ID:
620 clk_rate = get_l4_mp_clk();
621 break;
622
623 case CLKMGR_L4_SP_CLK_ID:
624 clk_rate = get_l4_sp_clk();
625 break;
626
627 case CLKMGR_EMAC0_CLK_ID:
628 clk_rate = get_emaca_clk();
629 break;
630
631 case CLKMGR_SDMMC_CLK_ID:
632 clk_rate = get_sdmmc_clk();
633 break;
634
635 case CLKMGR_UART_CLK_ID:
636 clk_rate = get_uart_clk();
637 break;
638
639 case CLKMGR_WDT_CLK_ID:
640 clk_rate = get_wdt_clk();
641 break;
642
643 default:
644 ERROR("CLKMGR: %s: Invalid clock ID\n", __func__);
645 clk_rate = 0;
646 break;
647 }
648
649 return clk_rate;
650 }
651
652 /* Return mpu_periph_clk tick */
plat_get_syscnt_freq2(void)653 unsigned int plat_get_syscnt_freq2(void)
654 {
655 return PLAT_SYS_COUNTER_FREQ_IN_TICKS;
656 }
657