uboot/drivers/clk/altera/clk-agilex.c
<<
>>
Prefs
   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