• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2019, Intel Corporation. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <common/debug.h>
9 #include <drivers/delay_timer.h>
10 #include <errno.h>
11 #include <lib/mmio.h>
12 
13 #include "agilex_clock_manager.h"
14 #include "socfpga_handoff.h"
15 #include "socfpga_system_manager.h"
16 
17 
wait_pll_lock(void)18 uint32_t wait_pll_lock(void)
19 {
20 	uint32_t data;
21 	uint32_t count = 0;
22 
23 	do {
24 		data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
25 		count++;
26 		if (count >= 1000)
27 			return -ETIMEDOUT;
28 
29 	} while ((CLKMGR_STAT_MAINPLLLOCKED(data) == 0) ||
30 			(CLKMGR_STAT_PERPLLLOCKED(data) == 0));
31 	return 0;
32 }
33 
wait_fsm(void)34 uint32_t wait_fsm(void)
35 {
36 	uint32_t data;
37 	uint32_t count = 0;
38 
39 	do {
40 		data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
41 		count++;
42 		if (count >= 1000)
43 			return -ETIMEDOUT;
44 
45 	} while (CLKMGR_STAT_BUSY(data) == CLKMGR_STAT_BUSY_E_BUSY);
46 
47 	return 0;
48 }
49 
pll_source_sync_config(uint32_t pll_mem_offset,uint32_t data)50 uint32_t pll_source_sync_config(uint32_t pll_mem_offset, uint32_t data)
51 {
52 	uint32_t val = 0;
53 	uint32_t count = 0;
54 	uint32_t req_status = 0;
55 
56 	val = (CLKMGR_MEM_WR | CLKMGR_MEM_REQ |
57 		(data << CLKMGR_MEM_WDAT_OFFSET) | CLKMGR_MEM_ADDR);
58 	mmio_write_32(pll_mem_offset, val);
59 
60 	do {
61 		req_status = mmio_read_32(pll_mem_offset);
62 		count++;
63 	} while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
64 
65 	if (count >= 100)
66 		return -ETIMEDOUT;
67 
68 	return 0;
69 }
70 
pll_source_sync_read(uint32_t pll_mem_offset)71 uint32_t pll_source_sync_read(uint32_t pll_mem_offset)
72 {
73 	uint32_t val = 0;
74 	uint32_t rdata = 0;
75 	uint32_t count = 0;
76 	uint32_t req_status = 0;
77 
78 	val = (CLKMGR_MEM_REQ | CLKMGR_MEM_ADDR);
79 	mmio_write_32(pll_mem_offset, val);
80 
81 	do {
82 		req_status = mmio_read_32(pll_mem_offset);
83 		count++;
84 	} while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
85 
86 	if (count >= 100)
87 		return -ETIMEDOUT;
88 
89 	rdata = mmio_read_32(pll_mem_offset + 0x4);
90 	INFO("rdata (%x) = %x\n", pll_mem_offset + 0x4, rdata);
91 
92 	return rdata;
93 }
94 
config_clkmgr_handoff(handoff * hoff_ptr)95 void config_clkmgr_handoff(handoff *hoff_ptr)
96 {
97 	uint32_t mdiv, mscnt, hscnt;
98 	uint32_t drefclk_div, refclk_div, rdata;
99 
100 	/* Set clock maanger into boot mode before running configuration */
101 	mmio_setbits_32(CLKMGR_OFFSET + CLKMGR_CTRL,
102 		CLKMGR_CTRL_BOOTMODE_SET_MSK);
103 	/* Bypass all mainpllgrp's clocks */
104 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0x7);
105 	wait_fsm();
106 
107 	/* Bypass all perpllgrp's clocks */
108 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0x7f);
109 	wait_fsm();
110 
111 	/* Put both PLL in reset and power down */
112 	mmio_clrbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
113 			CLKMGR_PLLGLOB_PD_SET_MSK |
114 			CLKMGR_PLLGLOB_RST_SET_MSK);
115 	mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
116 			CLKMGR_PLLGLOB_PD_SET_MSK |
117 			CLKMGR_PLLGLOB_RST_SET_MSK);
118 
119 	/* Setup main PLL dividers */
120 	mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->main_pll_pllm);
121 
122 	drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
123 			hoff_ptr->main_pll_pllglob);
124 	refclk_div = CLKMGR_PLLGLOB_REFCLKDIV(
125 			hoff_ptr->main_pll_pllglob);
126 
127 	mscnt = 100 / (mdiv * BIT(drefclk_div));
128 	if (!mscnt)
129 		mscnt = 1;
130 	hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4;
131 
132 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
133 			hoff_ptr->main_pll_pllglob &
134 			~CLKMGR_PLLGLOB_RST_SET_MSK);
135 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_FDBCK,
136 			hoff_ptr->main_pll_fdbck);
137 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_VCOCALIB,
138 			CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
139 			CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
140 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC0,
141 			hoff_ptr->main_pll_pllc0);
142 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC1,
143 			hoff_ptr->main_pll_pllc1);
144 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC2,
145 			hoff_ptr->main_pll_pllc2);
146 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC3,
147 			hoff_ptr->main_pll_pllc3);
148 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM,
149 			hoff_ptr->main_pll_pllm);
150 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MPUCLK,
151 			hoff_ptr->main_pll_mpuclk);
152 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCCLK,
153 			hoff_ptr->main_pll_nocclk);
154 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV,
155 			hoff_ptr->main_pll_nocdiv);
156 
157 	/* Setup peripheral PLL dividers */
158 	mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->per_pll_pllm);
159 
160 	drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
161 			hoff_ptr->per_pll_pllglob);
162 	refclk_div = CLKMGR_PLLGLOB_REFCLKDIV(
163 			hoff_ptr->per_pll_pllglob);
164 
165 
166 	mscnt = 100 / (mdiv * BIT(drefclk_div));
167 	if (!mscnt)
168 		mscnt = 1;
169 	hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4;
170 
171 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
172 			hoff_ptr->per_pll_pllglob &
173 			~CLKMGR_PLLGLOB_RST_SET_MSK);
174 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_FDBCK,
175 			hoff_ptr->per_pll_fdbck);
176 
177 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_VCOCALIB,
178 			CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
179 			CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
180 
181 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC0,
182 			hoff_ptr->per_pll_pllc0);
183 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC1,
184 			hoff_ptr->per_pll_pllc1);
185 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC2,
186 			hoff_ptr->per_pll_pllc2);
187 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC3,
188 			hoff_ptr->per_pll_pllc3);
189 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM,
190 			hoff_ptr->per_pll_pllm);
191 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL,
192 			hoff_ptr->per_pll_emacctl);
193 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_GPIODIV,
194 			hoff_ptr->per_pll_gpiodiv);
195 
196 	/* Take both PLL out of reset and power up */
197 	mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
198 			CLKMGR_PLLGLOB_PD_SET_MSK |
199 			CLKMGR_PLLGLOB_RST_SET_MSK);
200 	mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
201 			CLKMGR_PLLGLOB_PD_SET_MSK |
202 			CLKMGR_PLLGLOB_RST_SET_MSK);
203 
204 	rdata = pll_source_sync_read(CLKMGR_MAINPLL +
205 		CLKMGR_MAINPLL_MEM);
206 	pll_source_sync_config(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM,
207 		rdata | 0x80);
208 
209 	rdata = pll_source_sync_read(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM);
210 	pll_source_sync_config(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM,
211 		rdata | 0x80);
212 
213 	wait_pll_lock();
214 
215 	/*Configure Ping Pong counters in altera group */
216 	mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACACTR,
217 			hoff_ptr->alt_emacactr);
218 	mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACBCTR,
219 			hoff_ptr->alt_emacbctr);
220 	mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACPTPCTR,
221 			hoff_ptr->alt_emacptpctr);
222 	mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_GPIODBCTR,
223 			hoff_ptr->alt_gpiodbctr);
224 	mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR,
225 			hoff_ptr->alt_sdmmcctr);
226 	mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER0CTR,
227 			hoff_ptr->alt_s2fuser0ctr);
228 	mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER1CTR,
229 			hoff_ptr->alt_s2fuser1ctr);
230 	mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_PSIREFCTR,
231 			hoff_ptr->alt_psirefctr);
232 
233 	/* Clear lost lock bypass mode */
234 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_LOSTLOCK, 0x1);
235 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_LOSTLOCK, 0x1);
236 
237 	mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
238 			CLKMGR_CLR_LOSTLOCK_BYPASS);
239 
240 	mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
241 			CLKMGR_CLR_LOSTLOCK_BYPASS);
242 
243 	/* Take all PLLs out of bypass */
244 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0);
245 	wait_fsm();
246 
247 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0);
248 	wait_fsm();
249 
250 	/* Clear loss lock  interrupt status register that */
251 	/* might be set during configuration */
252 	mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_INTRCLR,
253 			CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK |
254 			CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK);
255 
256 	/* Take all ping pong counters out of reset */
257 	mmio_clrbits_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EXTCNTRST,
258 			CLKMGR_ALTERA_EXTCNTRST_RESET);
259 
260 	/* Set safe mode / out of boot mode */
261 	mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_CTRL,
262 		CLKMGR_CTRL_BOOTMODE_SET_MSK);
263 	wait_fsm();
264 
265 	/* Enable mainpllgrp's software-managed clock */
266 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_EN,
267 			CLKMGR_MAINPLL_EN_RESET);
268 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
269 			CLKMGR_PERPLL_EN_RESET);
270 
271 	/* Pass clock source frequency into scratch register */
272 	mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1),
273 		hoff_ptr->hps_osc_clk_h);
274 	mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2),
275 		hoff_ptr->fpga_clk_hz);
276 }
277 
278 /* Extract reference clock from platform clock source */
get_ref_clk(uint32_t pllglob)279 uint32_t get_ref_clk(uint32_t pllglob)
280 {
281 	uint32_t arefclkdiv, ref_clk;
282 	uint32_t scr_reg;
283 
284 	switch (CLKMGR_PSRC(pllglob)) {
285 	case CLKMGR_PLLGLOB_PSRC_EOSC1:
286 		scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1);
287 		ref_clk = mmio_read_32(scr_reg);
288 		break;
289 	case CLKMGR_PLLGLOB_PSRC_INTOSC:
290 		ref_clk = CLKMGR_INTOSC_HZ;
291 		break;
292 	case CLKMGR_PLLGLOB_PSRC_F2S:
293 		scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2);
294 		ref_clk = mmio_read_32(scr_reg);
295 		break;
296 	default:
297 		ref_clk = 0;
298 		assert(0);
299 		break;
300 	}
301 
302 	arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob);
303 	ref_clk /= arefclkdiv;
304 
305 	return ref_clk;
306 }
307 
308 /* Calculate clock frequency based on parameter */
get_clk_freq(uint32_t psrc_reg,uint32_t main_pllc,uint32_t per_pllc)309 uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc)
310 {
311 	uint32_t clk_psrc, mdiv, ref_clk;
312 	uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg;
313 
314 	clk_psrc = mmio_read_32(CLKMGR_MAINPLL + psrc_reg);
315 
316 	switch (CLKMGR_PSRC(clk_psrc)) {
317 	case CLKMGR_PSRC_MAIN:
318 		pllm_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM;
319 		pllc_reg = CLKMGR_MAINPLL + main_pllc;
320 		pllglob_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB;
321 		break;
322 	case CLKMGR_PSRC_PER:
323 		pllm_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM;
324 		pllc_reg = CLKMGR_PERPLL + per_pllc;
325 		pllglob_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB;
326 		break;
327 	default:
328 		return 0;
329 	}
330 
331 	ref_clk = get_ref_clk(mmio_read_32(pllglob_reg));
332 	mdiv = CLKMGR_PLLM_MDIV(mmio_read_32(pllm_reg));
333 	ref_clk *= mdiv;
334 
335 	pllc_div = mmio_read_32(pllc_reg) & 0x7ff;
336 
337 	return ref_clk / pllc_div;
338 }
339 
340 /* Return L3 interconnect clock */
get_l3_clk(void)341 uint32_t get_l3_clk(void)
342 {
343 	uint32_t l3_clk;
344 
345 	l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1,
346 				CLKMGR_PERPLL_PLLC1);
347 	return l3_clk;
348 }
349 
350 /* Calculate clock frequency to be used for watchdog timer */
get_wdt_clk(void)351 uint32_t get_wdt_clk(void)
352 {
353 	uint32_t l3_clk, l4_sys_clk;
354 
355 	l3_clk = get_l3_clk();
356 	l4_sys_clk = l3_clk / 4;
357 
358 	return l4_sys_clk;
359 }
360 
361 /* Calculate clock frequency to be used for UART driver */
get_uart_clk(void)362 uint32_t get_uart_clk(void)
363 {
364 	uint32_t data32, l3_clk, l4_sp_clk;
365 
366 	l3_clk = get_l3_clk();
367 
368 	data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV);
369 	data32 = (data32 >> 16) & 0x3;
370 
371 	l4_sp_clk = l3_clk >> data32;
372 
373 	return l4_sp_clk;
374 }
375 
376 /* Calculate clock frequency to be used for SDMMC driver */
get_mmc_clk(void)377 uint32_t get_mmc_clk(void)
378 {
379 	uint32_t data32, mmc_clk;
380 
381 	mmc_clk = get_clk_freq(CLKMGR_ALTERA_SDMMCCTR,
382 		CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3);
383 
384 	data32 = mmio_read_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR);
385 	data32 = (data32 & 0x7ff) + 1;
386 	mmc_clk = (mmc_clk / data32) / 4;
387 
388 	return mmc_clk;
389 }
390