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