1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2019 Intel Corporation <www.intel.com>
4  */
5 
6 #include <common.h>
7 #include <log.h>
8 #include <asm/global_data.h>
9 #include <asm/io.h>
10 #include <clk-uclass.h>
11 #include <dm.h>
12 #include <dm/lists.h>
13 #include <dm/util.h>
14 #include <dt-bindings/clock/agilex-clock.h>
15 #include <linux/bitops.h>
16 
17 #include <asm/arch/clock_manager.h>
18 
19 DECLARE_GLOBAL_DATA_PTR;
20 
21 struct socfpga_clk_plat {
22 	void __iomem *regs;
23 };
24 
25 /*
26  * function to write the bypass register which requires a poll of the
27  * busy bit
28  */
clk_write_bypass_mainpll(struct socfpga_clk_plat * plat,u32 val)29 static void clk_write_bypass_mainpll(struct socfpga_clk_plat *plat, u32 val)
30 {
31 	CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_BYPASS);
32 	cm_wait_for_fsm();
33 }
34 
clk_write_bypass_perpll(struct socfpga_clk_plat * plat,u32 val)35 static void clk_write_bypass_perpll(struct socfpga_clk_plat *plat, u32 val)
36 {
37 	CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_BYPASS);
38 	cm_wait_for_fsm();
39 }
40 
41 /* function to write the ctrl register which requires a poll of the busy bit */
clk_write_ctrl(struct socfpga_clk_plat * plat,u32 val)42 static void clk_write_ctrl(struct socfpga_clk_plat *plat, u32 val)
43 {
44 	CM_REG_WRITEL(plat, val, CLKMGR_CTRL);
45 	cm_wait_for_fsm();
46 }
47 
48 #define MEMBUS_MAINPLL				0
49 #define MEMBUS_PERPLL				1
50 #define MEMBUS_TIMEOUT				1000
51 
52 #define MEMBUS_CLKSLICE_REG				0x27
53 #define MEMBUS_SYNTHCALFOSC_INIT_CENTERFREQ_REG		0xb3
54 #define MEMBUS_SYNTHPPM_WATCHDOGTMR_VF01_REG		0xe6
55 #define MEMBUS_CALCLKSLICE0_DUTY_LOCOVR_REG		0x03
56 #define MEMBUS_CALCLKSLICE1_DUTY_LOCOVR_REG		0x07
57 
58 static const struct {
59 	u32 reg;
60 	u32 val;
61 	u32 mask;
62 } membus_pll[] = {
63 	{
64 		MEMBUS_CLKSLICE_REG,
65 		/*
66 		 * BIT[7:7]
67 		 * Enable source synchronous mode
68 		 */
69 		BIT(7),
70 		BIT(7)
71 	},
72 	{
73 		MEMBUS_SYNTHCALFOSC_INIT_CENTERFREQ_REG,
74 		/*
75 		 * BIT[0:0]
76 		 * Sets synthcalfosc_init_centerfreq=1 to limit overshoot
77 		 * frequency during lock
78 		 */
79 		BIT(0),
80 		BIT(0)
81 	},
82 	{
83 		MEMBUS_SYNTHPPM_WATCHDOGTMR_VF01_REG,
84 		/*
85 		 * BIT[0:0]
86 		 * Sets synthppm_watchdogtmr_vf0=1 to give the pll more time
87 		 * to settle before lock is asserted.
88 		 */
89 		BIT(0),
90 		BIT(0)
91 	},
92 	{
93 		MEMBUS_CALCLKSLICE0_DUTY_LOCOVR_REG,
94 		/*
95 		 * BIT[6:0]
96 		 * Centering duty cycle for clkslice0 output
97 		 */
98 		0x4a,
99 		GENMASK(6, 0)
100 	},
101 	{
102 		MEMBUS_CALCLKSLICE1_DUTY_LOCOVR_REG,
103 		/*
104 		 * BIT[6:0]
105 		 * Centering duty cycle for clkslice1 output
106 		 */
107 		0x4a,
108 		GENMASK(6, 0)
109 	},
110 };
111 
membus_wait_for_req(struct socfpga_clk_plat * plat,u32 pll,int timeout)112 static int membus_wait_for_req(struct socfpga_clk_plat *plat, u32 pll,
113 			       int timeout)
114 {
115 	int cnt = 0;
116 	u32 req_status;
117 
118 	if (pll == MEMBUS_MAINPLL)
119 		req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM);
120 	else
121 		req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM);
122 
123 	while ((cnt < timeout) && (req_status & CLKMGR_MEM_REQ_SET_MSK)) {
124 		if (pll == MEMBUS_MAINPLL)
125 			req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM);
126 		else
127 			req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM);
128 		cnt++;
129 	}
130 
131 	if (cnt >= timeout)
132 		return -ETIMEDOUT;
133 
134 	return 0;
135 }
136 
membus_write_pll(struct socfpga_clk_plat * plat,u32 pll,u32 addr_offset,u32 wdat,int timeout)137 static int membus_write_pll(struct socfpga_clk_plat *plat, u32 pll,
138 			    u32 addr_offset, u32 wdat, int timeout)
139 {
140 	u32 addr;
141 	u32 val;
142 
143 	addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
144 
145 	val = (CLKMGR_MEM_REQ_SET_MSK | CLKMGR_MEM_WR_SET_MSK |
146 	       (wdat << CLKMGR_MEM_WDAT_LSB_OFFSET) | addr);
147 
148 	if (pll == MEMBUS_MAINPLL)
149 		CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM);
150 	else
151 		CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM);
152 
153 	debug("MEMBUS: Write 0x%08x to addr = 0x%08x\n", wdat, addr);
154 
155 	return membus_wait_for_req(plat, pll, timeout);
156 }
157 
membus_read_pll(struct socfpga_clk_plat * plat,u32 pll,u32 addr_offset,u32 * rdata,int timeout)158 static int membus_read_pll(struct socfpga_clk_plat *plat, u32 pll,
159 			   u32 addr_offset, u32 *rdata, int timeout)
160 {
161 	u32 addr;
162 	u32 val;
163 
164 	addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
165 
166 	val = ((CLKMGR_MEM_REQ_SET_MSK & ~CLKMGR_MEM_WR_SET_MSK) | addr);
167 
168 	if (pll == MEMBUS_MAINPLL)
169 		CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM);
170 	else
171 		CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM);
172 
173 	*rdata = 0;
174 
175 	if (membus_wait_for_req(plat, pll, timeout))
176 		return -ETIMEDOUT;
177 
178 	if (pll == MEMBUS_MAINPLL)
179 		*rdata = CM_REG_READL(plat, CLKMGR_MAINPLL_MEMSTAT);
180 	else
181 		*rdata = CM_REG_READL(plat, CLKMGR_PERPLL_MEMSTAT);
182 
183 	debug("MEMBUS: Read 0x%08x from addr = 0x%08x\n", *rdata, addr);
184 
185 	return 0;
186 }
187 
membus_pll_configs(struct socfpga_clk_plat * plat,u32 pll)188 static void membus_pll_configs(struct socfpga_clk_plat *plat, u32 pll)
189 {
190 	int i;
191 	u32 rdata;
192 
193 	for (i = 0; i < ARRAY_SIZE(membus_pll); i++) {
194 		membus_read_pll(plat, pll, membus_pll[i].reg,
195 				&rdata, MEMBUS_TIMEOUT);
196 		membus_write_pll(plat, pll, membus_pll[i].reg,
197 			 ((rdata & ~membus_pll[i].mask) | membus_pll[i].val),
198 			 MEMBUS_TIMEOUT);
199 	}
200 }
201 
calc_vocalib_pll(u32 pllm,u32 pllglob)202 static u32 calc_vocalib_pll(u32 pllm, u32 pllglob)
203 {
204 	u32 mdiv, refclkdiv, arefclkdiv, drefclkdiv, mscnt, hscnt, vcocalib;
205 
206 	mdiv = pllm & CLKMGR_PLLM_MDIV_MASK;
207 	arefclkdiv = (pllglob & CLKMGR_PLLGLOB_AREFCLKDIV_MASK) >>
208 		      CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET;
209 	drefclkdiv = (pllglob & CLKMGR_PLLGLOB_DREFCLKDIV_MASK) >>
210 		      CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET;
211 	refclkdiv = (pllglob & CLKMGR_PLLGLOB_REFCLKDIV_MASK) >>
212 		     CLKMGR_PLLGLOB_REFCLKDIV_OFFSET;
213 	mscnt = CLKMGR_VCOCALIB_MSCNT_CONST / (mdiv * BIT(drefclkdiv));
214 	if (!mscnt)
215 		mscnt = 1;
216 	hscnt = (mdiv * mscnt * BIT(drefclkdiv) / refclkdiv) -
217 		CLKMGR_VCOCALIB_HSCNT_CONST;
218 	vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
219 		   ((mscnt << CLKMGR_VCOCALIB_MSCNT_OFFSET) &
220 		     CLKMGR_VCOCALIB_MSCNT_MASK);
221 
222 	/* Dump all the pll calibration settings for debug purposes */
223 	debug("mdiv          : %d\n", mdiv);
224 	debug("arefclkdiv    : %d\n", arefclkdiv);
225 	debug("drefclkdiv    : %d\n", drefclkdiv);
226 	debug("refclkdiv     : %d\n", refclkdiv);
227 	debug("mscnt         : %d\n", mscnt);
228 	debug("hscnt         : %d\n", hscnt);
229 	debug("vcocalib      : 0x%08x\n", vcocalib);
230 
231 	return vcocalib;
232 }
233 
234 /*
235  * Setup clocks while making no assumptions about previous state of the clocks.
236  */
clk_basic_init(struct udevice * dev,const struct cm_config * const cfg)237 static void clk_basic_init(struct udevice *dev,
238 			   const struct cm_config * const cfg)
239 {
240 	struct socfpga_clk_plat *plat = dev_get_plat(dev);
241 	u32 vcocalib;
242 
243 	if (!cfg)
244 		return;
245 
246 #ifdef CONFIG_SPL_BUILD
247 	/* Always force clock manager into boot mode before any configuration */
248 	clk_write_ctrl(plat,
249 		       CM_REG_READL(plat, CLKMGR_CTRL) | CLKMGR_CTRL_BOOTMODE);
250 #else
251 	/* Skip clock configuration in SSBL if it's not in boot mode */
252 	if (!(CM_REG_READL(plat, CLKMGR_CTRL) & CLKMGR_CTRL_BOOTMODE))
253 		return;
254 #endif
255 
256 	/* Put both PLLs in bypass */
257 	clk_write_bypass_mainpll(plat, CLKMGR_BYPASS_MAINPLL_ALL);
258 	clk_write_bypass_perpll(plat, CLKMGR_BYPASS_PERPLL_ALL);
259 
260 	/* Put both PLLs in Reset and Power Down */
261 	CM_REG_CLRBITS(plat, CLKMGR_MAINPLL_PLLGLOB,
262 		       CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
263 	CM_REG_CLRBITS(plat, CLKMGR_PERPLL_PLLGLOB,
264 		       CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
265 
266 	/* setup main PLL dividers where calculate the vcocalib value */
267 	vcocalib = calc_vocalib_pll(cfg->main_pll_pllm, cfg->main_pll_pllglob);
268 	CM_REG_WRITEL(plat, cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK,
269 		      CLKMGR_MAINPLL_PLLGLOB);
270 	CM_REG_WRITEL(plat, cfg->main_pll_fdbck, CLKMGR_MAINPLL_FDBCK);
271 	CM_REG_WRITEL(plat, vcocalib, CLKMGR_MAINPLL_VCOCALIB);
272 	CM_REG_WRITEL(plat, cfg->main_pll_pllc0, CLKMGR_MAINPLL_PLLC0);
273 	CM_REG_WRITEL(plat, cfg->main_pll_pllc1, CLKMGR_MAINPLL_PLLC1);
274 	CM_REG_WRITEL(plat, cfg->main_pll_pllc2, CLKMGR_MAINPLL_PLLC2);
275 	CM_REG_WRITEL(plat, cfg->main_pll_pllc3, CLKMGR_MAINPLL_PLLC3);
276 	CM_REG_WRITEL(plat, cfg->main_pll_pllm, CLKMGR_MAINPLL_PLLM);
277 	CM_REG_WRITEL(plat, cfg->main_pll_mpuclk, CLKMGR_MAINPLL_MPUCLK);
278 	CM_REG_WRITEL(plat, cfg->main_pll_nocclk, CLKMGR_MAINPLL_NOCCLK);
279 	CM_REG_WRITEL(plat, cfg->main_pll_nocdiv, CLKMGR_MAINPLL_NOCDIV);
280 
281 	/* setup peripheral PLL dividers where calculate the vcocalib value */
282 	vcocalib = calc_vocalib_pll(cfg->per_pll_pllm, cfg->per_pll_pllglob);
283 	CM_REG_WRITEL(plat, cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK,
284 		      CLKMGR_PERPLL_PLLGLOB);
285 	CM_REG_WRITEL(plat, cfg->per_pll_fdbck, CLKMGR_PERPLL_FDBCK);
286 	CM_REG_WRITEL(plat, vcocalib, CLKMGR_PERPLL_VCOCALIB);
287 	CM_REG_WRITEL(plat, cfg->per_pll_pllc0, CLKMGR_PERPLL_PLLC0);
288 	CM_REG_WRITEL(plat, cfg->per_pll_pllc1, CLKMGR_PERPLL_PLLC1);
289 	CM_REG_WRITEL(plat, cfg->per_pll_pllc2, CLKMGR_PERPLL_PLLC2);
290 	CM_REG_WRITEL(plat, cfg->per_pll_pllc3, CLKMGR_PERPLL_PLLC3);
291 	CM_REG_WRITEL(plat, cfg->per_pll_pllm, CLKMGR_PERPLL_PLLM);
292 	CM_REG_WRITEL(plat, cfg->per_pll_emacctl, CLKMGR_PERPLL_EMACCTL);
293 	CM_REG_WRITEL(plat, cfg->per_pll_gpiodiv, CLKMGR_PERPLL_GPIODIV);
294 
295 	/* Take both PLL out of reset and power up */
296 	CM_REG_SETBITS(plat, CLKMGR_MAINPLL_PLLGLOB,
297 		       CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
298 	CM_REG_SETBITS(plat, CLKMGR_PERPLL_PLLGLOB,
299 		       CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
300 
301 	/* Membus programming for mainpll */
302 	membus_pll_configs(plat, MEMBUS_MAINPLL);
303 	/* Membus programming for peripll */
304 	membus_pll_configs(plat, MEMBUS_PERPLL);
305 
306 	cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK);
307 
308 	/* Configure ping pong counters in altera group */
309 	CM_REG_WRITEL(plat, cfg->alt_emacactr, CLKMGR_ALTR_EMACACTR);
310 	CM_REG_WRITEL(plat, cfg->alt_emacbctr, CLKMGR_ALTR_EMACBCTR);
311 	CM_REG_WRITEL(plat, cfg->alt_emacptpctr, CLKMGR_ALTR_EMACPTPCTR);
312 	CM_REG_WRITEL(plat, cfg->alt_gpiodbctr, CLKMGR_ALTR_GPIODBCTR);
313 	CM_REG_WRITEL(plat, cfg->alt_sdmmcctr, CLKMGR_ALTR_SDMMCCTR);
314 	CM_REG_WRITEL(plat, cfg->alt_s2fuser0ctr, CLKMGR_ALTR_S2FUSER0CTR);
315 	CM_REG_WRITEL(plat, cfg->alt_s2fuser1ctr, CLKMGR_ALTR_S2FUSER1CTR);
316 	CM_REG_WRITEL(plat, cfg->alt_psirefctr, CLKMGR_ALTR_PSIREFCTR);
317 
318 	CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_MAINPLL_LOSTLOCK);
319 	CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_PERPLL_LOSTLOCK);
320 
321 	CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLGLOB) |
322 			CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
323 			CLKMGR_MAINPLL_PLLGLOB);
324 	CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLGLOB) |
325 			CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
326 			CLKMGR_PERPLL_PLLGLOB);
327 
328 	/* Take all PLLs out of bypass */
329 	clk_write_bypass_mainpll(plat, 0);
330 	clk_write_bypass_perpll(plat, 0);
331 
332 	/* Clear the loss of lock bits (write 1 to clear) */
333 	CM_REG_CLRBITS(plat, CLKMGR_INTRCLR,
334 		       CLKMGR_INTER_PERPLLLOST_MASK |
335 		       CLKMGR_INTER_MAINPLLLOST_MASK);
336 
337 	/* Take all ping pong counters out of reset */
338 	CM_REG_CLRBITS(plat, CLKMGR_ALTR_EXTCNTRST,
339 		       CLKMGR_ALT_EXTCNTRST_ALLCNTRST);
340 
341 	/* Out of boot mode */
342 	clk_write_ctrl(plat,
343 		       CM_REG_READL(plat, CLKMGR_CTRL) & ~CLKMGR_CTRL_BOOTMODE);
344 }
345 
clk_get_vco_clk_hz(struct socfpga_clk_plat * plat,u32 pllglob_reg,u32 pllm_reg)346 static u64 clk_get_vco_clk_hz(struct socfpga_clk_plat *plat,
347 			      u32 pllglob_reg, u32 pllm_reg)
348 {
349 	 u64 fref, arefdiv, mdiv, reg, vco;
350 
351 	reg = CM_REG_READL(plat, pllglob_reg);
352 
353 	fref = (reg & CLKMGR_PLLGLOB_VCO_PSRC_MASK) >>
354 		CLKMGR_PLLGLOB_VCO_PSRC_OFFSET;
355 
356 	switch (fref) {
357 	case CLKMGR_VCO_PSRC_EOSC1:
358 		fref = cm_get_osc_clk_hz();
359 		break;
360 	case CLKMGR_VCO_PSRC_INTOSC:
361 		fref = cm_get_intosc_clk_hz();
362 		break;
363 	case CLKMGR_VCO_PSRC_F2S:
364 		fref = cm_get_fpga_clk_hz();
365 		break;
366 	}
367 
368 	arefdiv = (reg & CLKMGR_PLLGLOB_AREFCLKDIV_MASK) >>
369 		   CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET;
370 
371 	mdiv = CM_REG_READL(plat, pllm_reg) & CLKMGR_PLLM_MDIV_MASK;
372 
373 	vco = fref / arefdiv;
374 	vco = vco * mdiv;
375 
376 	return vco;
377 }
378 
clk_get_main_vco_clk_hz(struct socfpga_clk_plat * plat)379 static u64 clk_get_main_vco_clk_hz(struct socfpga_clk_plat *plat)
380 {
381 	return clk_get_vco_clk_hz(plat, CLKMGR_MAINPLL_PLLGLOB,
382 				 CLKMGR_MAINPLL_PLLM);
383 }
384 
clk_get_per_vco_clk_hz(struct socfpga_clk_plat * plat)385 static u64 clk_get_per_vco_clk_hz(struct socfpga_clk_plat *plat)
386 {
387 	return clk_get_vco_clk_hz(plat, CLKMGR_PERPLL_PLLGLOB,
388 				 CLKMGR_PERPLL_PLLM);
389 }
390 
clk_get_5_1_clk_src(struct socfpga_clk_plat * plat,u64 reg)391 static u32 clk_get_5_1_clk_src(struct socfpga_clk_plat *plat, u64 reg)
392 {
393 	u32 clksrc = CM_REG_READL(plat, reg);
394 
395 	return (clksrc & CLKMGR_CLKSRC_MASK) >> CLKMGR_CLKSRC_OFFSET;
396 }
397 
clk_get_clksrc_hz(struct socfpga_clk_plat * plat,u32 clksrc_reg,u32 main_reg,u32 per_reg)398 static u64 clk_get_clksrc_hz(struct socfpga_clk_plat *plat, u32 clksrc_reg,
399 			     u32 main_reg, u32 per_reg)
400 {
401 	u64 clock;
402 	u32 clklsrc = clk_get_5_1_clk_src(plat, clksrc_reg);
403 
404 	switch (clklsrc) {
405 	case CLKMGR_CLKSRC_MAIN:
406 		clock = clk_get_main_vco_clk_hz(plat);
407 		clock /= (CM_REG_READL(plat, main_reg) &
408 			  CLKMGR_CLKCNT_MSK);
409 		break;
410 
411 	case CLKMGR_CLKSRC_PER:
412 		clock = clk_get_per_vco_clk_hz(plat);
413 		clock /= (CM_REG_READL(plat, per_reg) &
414 			  CLKMGR_CLKCNT_MSK);
415 		break;
416 
417 	case CLKMGR_CLKSRC_OSC1:
418 		clock = cm_get_osc_clk_hz();
419 		break;
420 
421 	case CLKMGR_CLKSRC_INTOSC:
422 		clock = cm_get_intosc_clk_hz();
423 		break;
424 
425 	case CLKMGR_CLKSRC_FPGA:
426 		clock = cm_get_fpga_clk_hz();
427 		break;
428 	default:
429 		return 0;
430 	}
431 
432 	return clock;
433 }
434 
clk_get_mpu_clk_hz(struct socfpga_clk_plat * plat)435 static u64 clk_get_mpu_clk_hz(struct socfpga_clk_plat *plat)
436 {
437 	u64 clock = clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_MPUCLK,
438 				      CLKMGR_MAINPLL_PLLC0,
439 				      CLKMGR_PERPLL_PLLC0);
440 
441 	clock /= 1 + (CM_REG_READL(plat, CLKMGR_MAINPLL_MPUCLK) &
442 		 CLKMGR_CLKCNT_MSK);
443 
444 	return clock;
445 }
446 
clk_get_l3_main_clk_hz(struct socfpga_clk_plat * plat)447 static u32 clk_get_l3_main_clk_hz(struct socfpga_clk_plat *plat)
448 {
449 	return clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_NOCCLK,
450 				      CLKMGR_MAINPLL_PLLC1,
451 				      CLKMGR_PERPLL_PLLC1);
452 }
453 
clk_get_l4_main_clk_hz(struct socfpga_clk_plat * plat)454 static u32 clk_get_l4_main_clk_hz(struct socfpga_clk_plat *plat)
455 {
456 	u64 clock = clk_get_l3_main_clk_hz(plat);
457 
458 	clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
459 	      CLKMGR_NOCDIV_L4MAIN_OFFSET) &
460 	      CLKMGR_NOCDIV_DIVIDER_MASK);
461 
462 	return clock;
463 }
464 
clk_get_sdmmc_clk_hz(struct socfpga_clk_plat * plat)465 static u32 clk_get_sdmmc_clk_hz(struct socfpga_clk_plat *plat)
466 {
467 	u64 clock = clk_get_clksrc_hz(plat, CLKMGR_ALTR_SDMMCCTR,
468 				      CLKMGR_MAINPLL_PLLC3,
469 				      CLKMGR_PERPLL_PLLC3);
470 
471 	clock /= 1 + (CM_REG_READL(plat, CLKMGR_ALTR_SDMMCCTR) &
472 		 CLKMGR_CLKCNT_MSK);
473 
474 	return clock / 4;
475 }
476 
clk_get_l4_sp_clk_hz(struct socfpga_clk_plat * plat)477 static u32 clk_get_l4_sp_clk_hz(struct socfpga_clk_plat *plat)
478 {
479 	u64 clock = clk_get_l3_main_clk_hz(plat);
480 
481 	clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
482 		      CLKMGR_NOCDIV_L4SPCLK_OFFSET) &
483 		      CLKMGR_NOCDIV_DIVIDER_MASK);
484 
485 	return clock;
486 }
487 
clk_get_l4_mp_clk_hz(struct socfpga_clk_plat * plat)488 static u32 clk_get_l4_mp_clk_hz(struct socfpga_clk_plat *plat)
489 {
490 	u64 clock = clk_get_l3_main_clk_hz(plat);
491 
492 	clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
493 		      CLKMGR_NOCDIV_L4MPCLK_OFFSET) &
494 		      CLKMGR_NOCDIV_DIVIDER_MASK);
495 
496 	return clock;
497 }
498 
clk_get_l4_sys_free_clk_hz(struct socfpga_clk_plat * plat)499 static u32 clk_get_l4_sys_free_clk_hz(struct socfpga_clk_plat *plat)
500 {
501 	if (CM_REG_READL(plat, CLKMGR_STAT) & CLKMGR_STAT_BOOTMODE)
502 		return clk_get_l3_main_clk_hz(plat) / 2;
503 
504 	return clk_get_l3_main_clk_hz(plat) / 4;
505 }
506 
clk_get_emac_clk_hz(struct socfpga_clk_plat * plat,u32 emac_id)507 static u32 clk_get_emac_clk_hz(struct socfpga_clk_plat *plat, u32 emac_id)
508 {
509 	bool emacsel_a;
510 	u32 ctl;
511 	u32 ctr_reg;
512 	u32 clock;
513 	u32 div;
514 	u32 reg;
515 
516 	/* Get EMAC clock source */
517 	ctl = CM_REG_READL(plat, CLKMGR_PERPLL_EMACCTL);
518 	if (emac_id == AGILEX_EMAC0_CLK)
519 		ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET) &
520 		       CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK;
521 	else if (emac_id == AGILEX_EMAC1_CLK)
522 		ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET) &
523 		       CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK;
524 	else if (emac_id == AGILEX_EMAC2_CLK)
525 		ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET) &
526 		       CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK;
527 	else
528 		return 0;
529 
530 	if (ctl) {
531 		/* EMAC B source */
532 		emacsel_a = false;
533 		ctr_reg = CLKMGR_ALTR_EMACBCTR;
534 	} else {
535 		/* EMAC A source */
536 		emacsel_a = true;
537 		ctr_reg = CLKMGR_ALTR_EMACACTR;
538 	}
539 
540 	reg = CM_REG_READL(plat, ctr_reg);
541 	clock = (reg & CLKMGR_ALT_EMACCTR_SRC_MASK)
542 		 >> CLKMGR_ALT_EMACCTR_SRC_OFFSET;
543 	div = (reg & CLKMGR_ALT_EMACCTR_CNT_MASK)
544 		>> CLKMGR_ALT_EMACCTR_CNT_OFFSET;
545 
546 	switch (clock) {
547 	case CLKMGR_CLKSRC_MAIN:
548 		clock = clk_get_main_vco_clk_hz(plat);
549 		if (emacsel_a) {
550 			clock /= (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC2) &
551 				  CLKMGR_CLKCNT_MSK);
552 		} else {
553 			clock /= (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC3) &
554 				  CLKMGR_CLKCNT_MSK);
555 		}
556 		break;
557 
558 	case CLKMGR_CLKSRC_PER:
559 		clock = clk_get_per_vco_clk_hz(plat);
560 		if (emacsel_a) {
561 			clock /= (CM_REG_READL(plat, CLKMGR_PERPLL_PLLC2) &
562 				  CLKMGR_CLKCNT_MSK);
563 		} else {
564 			clock /= (CM_REG_READL(plat, CLKMGR_PERPLL_PLLC3) &
565 				  CLKMGR_CLKCNT_MSK);
566 		}
567 		break;
568 
569 	case CLKMGR_CLKSRC_OSC1:
570 		clock = cm_get_osc_clk_hz();
571 		break;
572 
573 	case CLKMGR_CLKSRC_INTOSC:
574 		clock = cm_get_intosc_clk_hz();
575 		break;
576 
577 	case CLKMGR_CLKSRC_FPGA:
578 		clock = cm_get_fpga_clk_hz();
579 		break;
580 	}
581 
582 	clock /= 1 + div;
583 
584 	return clock;
585 }
586 
socfpga_clk_get_rate(struct clk * clk)587 static ulong socfpga_clk_get_rate(struct clk *clk)
588 {
589 	struct socfpga_clk_plat *plat = dev_get_plat(clk->dev);
590 
591 	switch (clk->id) {
592 	case AGILEX_MPU_CLK:
593 		return clk_get_mpu_clk_hz(plat);
594 	case AGILEX_L4_MAIN_CLK:
595 		return clk_get_l4_main_clk_hz(plat);
596 	case AGILEX_L4_SYS_FREE_CLK:
597 		return clk_get_l4_sys_free_clk_hz(plat);
598 	case AGILEX_L4_MP_CLK:
599 		return clk_get_l4_mp_clk_hz(plat);
600 	case AGILEX_L4_SP_CLK:
601 		return clk_get_l4_sp_clk_hz(plat);
602 	case AGILEX_SDMMC_CLK:
603 		return clk_get_sdmmc_clk_hz(plat);
604 	case AGILEX_EMAC0_CLK:
605 	case AGILEX_EMAC1_CLK:
606 	case AGILEX_EMAC2_CLK:
607 		return clk_get_emac_clk_hz(plat, clk->id);
608 	case AGILEX_USB_CLK:
609 	case AGILEX_NAND_X_CLK:
610 		return clk_get_l4_mp_clk_hz(plat);
611 	case AGILEX_NAND_CLK:
612 		return clk_get_l4_mp_clk_hz(plat) / 4;
613 	default:
614 		return -ENXIO;
615 	}
616 }
617 
socfpga_clk_enable(struct clk * clk)618 static int socfpga_clk_enable(struct clk *clk)
619 {
620 	return 0;
621 }
622 
socfpga_clk_probe(struct udevice * dev)623 static int socfpga_clk_probe(struct udevice *dev)
624 {
625 	const struct cm_config *cm_default_cfg = cm_get_default_config();
626 
627 	clk_basic_init(dev, cm_default_cfg);
628 
629 	return 0;
630 }
631 
socfpga_clk_of_to_plat(struct udevice * dev)632 static int socfpga_clk_of_to_plat(struct udevice *dev)
633 {
634 	struct socfpga_clk_plat *plat = dev_get_plat(dev);
635 	fdt_addr_t addr;
636 
637 	addr = dev_read_addr(dev);
638 	if (addr == FDT_ADDR_T_NONE)
639 		return -EINVAL;
640 	plat->regs = (void __iomem *)addr;
641 
642 	return 0;
643 }
644 
645 static struct clk_ops socfpga_clk_ops = {
646 	.enable		= socfpga_clk_enable,
647 	.get_rate	= socfpga_clk_get_rate,
648 };
649 
650 static const struct udevice_id socfpga_clk_match[] = {
651 	{ .compatible = "intel,agilex-clkmgr" },
652 	{}
653 };
654 
655 U_BOOT_DRIVER(socfpga_agilex_clk) = {
656 	.name		= "clk-agilex",
657 	.id		= UCLASS_CLK,
658 	.of_match	= socfpga_clk_match,
659 	.ops		= &socfpga_clk_ops,
660 	.probe		= socfpga_clk_probe,
661 	.of_to_plat = socfpga_clk_of_to_plat,
662 	.plat_auto	= sizeof(struct socfpga_clk_plat),
663 };
664