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 19DECLARE_GLOBAL_DATA_PTR; 20 21struct 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 */ 29static 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 35static 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 */ 42static 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 58static 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 112static 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 137static 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 158static 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 188static 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 202static 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 */ 237static 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 346static 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 379static 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 385static 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 391static 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 398static 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 435static 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 447static 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 454static 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 465static 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 477static 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 488static 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 499static 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 507static 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 587static 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 618static int socfpga_clk_enable(struct clk *clk) 619{ 620 return 0; 621} 622 623static 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 632static 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 645static struct clk_ops socfpga_clk_ops = { 646 .enable = socfpga_clk_enable, 647 .get_rate = socfpga_clk_get_rate, 648}; 649 650static const struct udevice_id socfpga_clk_match[] = { 651 { .compatible = "intel,agilex-clkmgr" }, 652 {} 653}; 654 655U_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