• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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