uboot/drivers/clk/rockchip/clk_rv1108.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * (C) Copyright 2016 Rockchip Electronics Co., Ltd
   4 * Author: Andy Yan <andy.yan@rock-chips.com>
   5 */
   6
   7#include <common.h>
   8#include <bitfield.h>
   9#include <clk-uclass.h>
  10#include <dm.h>
  11#include <errno.h>
  12#include <syscon.h>
  13#include <asm/io.h>
  14#include <asm/arch/clock.h>
  15#include <asm/arch/cru_rv1108.h>
  16#include <asm/arch/hardware.h>
  17#include <dm/lists.h>
  18#include <dt-bindings/clock/rv1108-cru.h>
  19
  20DECLARE_GLOBAL_DATA_PTR;
  21
  22enum {
  23        VCO_MAX_HZ      = 2400U * 1000000,
  24        VCO_MIN_HZ      = 600 * 1000000,
  25        OUTPUT_MAX_HZ   = 2400U * 1000000,
  26        OUTPUT_MIN_HZ   = 24 * 1000000,
  27};
  28
  29#define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
  30
  31#define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
  32        .refdiv = _refdiv,\
  33        .fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
  34        .postdiv1 = _postdiv1, .postdiv2 = _postdiv2};\
  35        _Static_assert(((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ) *\
  36                         OSC_HZ / (_refdiv * _postdiv1 * _postdiv2) == hz,\
  37                         #hz "Hz cannot be hit with PLL "\
  38                         "divisors on line " __stringify(__LINE__));
  39
  40static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
  41static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
  42
  43/* use integer mode */
  44static inline int rv1108_pll_id(enum rk_clk_id clk_id)
  45{
  46        int id = 0;
  47
  48        switch (clk_id) {
  49        case CLK_ARM:
  50        case CLK_DDR:
  51                id = clk_id - 1;
  52                break;
  53        case CLK_GENERAL:
  54                id = 2;
  55                break;
  56        default:
  57                printf("invalid pll id:%d\n", clk_id);
  58                id = -1;
  59                break;
  60        }
  61
  62        return id;
  63}
  64
  65static int rkclk_set_pll(struct rv1108_cru *cru, enum rk_clk_id clk_id,
  66                         const struct pll_div *div)
  67{
  68        int pll_id = rv1108_pll_id(clk_id);
  69        struct rv1108_pll *pll = &cru->pll[pll_id];
  70
  71        /* All PLLs have same VCO and output frequency range restrictions. */
  72        uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
  73        uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
  74
  75        debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
  76              pll, div->fbdiv, div->refdiv, div->postdiv1,
  77              div->postdiv2, vco_hz, output_hz);
  78        assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
  79               output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
  80
  81        /*
  82         * When power on or changing PLL setting,
  83         * we must force PLL into slow mode to ensure output stable clock.
  84         */
  85        rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
  86                     WORK_MODE_SLOW << WORK_MODE_SHIFT);
  87
  88        /* use integer mode */
  89        rk_setreg(&pll->con3, 1 << DSMPD_SHIFT);
  90        /* Power down */
  91        rk_setreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
  92
  93        rk_clrsetreg(&pll->con0, FBDIV_MASK, div->fbdiv << FBDIV_SHIFT);
  94        rk_clrsetreg(&pll->con1, POSTDIV1_MASK | POSTDIV2_MASK | REFDIV_MASK,
  95                     (div->postdiv1 << POSTDIV1_SHIFT |
  96                     div->postdiv2 << POSTDIV2_SHIFT |
  97                     div->refdiv << REFDIV_SHIFT));
  98        rk_clrsetreg(&pll->con2, FRACDIV_MASK,
  99                     (div->refdiv << REFDIV_SHIFT));
 100
 101        /* Power Up */
 102        rk_clrreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
 103
 104        /* waiting for pll lock */
 105        while (readl(&pll->con2) & (1 << LOCK_STA_SHIFT))
 106                udelay(1);
 107
 108        /*
 109         * set PLL into normal mode.
 110         */
 111        rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
 112                     WORK_MODE_NORMAL << WORK_MODE_SHIFT);
 113
 114        return 0;
 115}
 116
 117static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
 118                                   enum rk_clk_id clk_id)
 119{
 120        uint32_t refdiv, fbdiv, postdiv1, postdiv2;
 121        uint32_t con0, con1, con3;
 122        int pll_id = rv1108_pll_id(clk_id);
 123        struct rv1108_pll *pll = &cru->pll[pll_id];
 124        uint32_t freq;
 125
 126        con3 = readl(&pll->con3);
 127
 128        if (con3 & WORK_MODE_MASK) {
 129                con0 = readl(&pll->con0);
 130                con1 = readl(&pll->con1);
 131                fbdiv = (con0 >> FBDIV_SHIFT) & FBDIV_MASK;
 132                postdiv1 = (con1 & POSTDIV1_MASK) >> POSTDIV1_SHIFT;
 133                postdiv2 = (con1 & POSTDIV2_MASK) >> POSTDIV2_SHIFT;
 134                refdiv = (con1 >> REFDIV_SHIFT) & REFDIV_MASK;
 135                freq = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
 136        } else {
 137                freq = OSC_HZ;
 138        }
 139
 140        return freq;
 141}
 142
 143static int rv1108_mac_set_clk(struct rv1108_cru *cru, ulong rate)
 144{
 145        uint32_t con = readl(&cru->clksel_con[24]);
 146        ulong pll_rate;
 147        uint8_t div;
 148
 149        if ((con >> MAC_PLL_SEL_SHIFT) & MAC_PLL_SEL_GPLL)
 150                pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 151        else
 152                pll_rate = rkclk_pll_get_rate(cru, CLK_ARM);
 153
 154        /*default set 50MHZ for gmac*/
 155        if (!rate)
 156                rate = 50000000;
 157
 158        div = DIV_ROUND_UP(pll_rate, rate) - 1;
 159        if (div <= 0x1f)
 160                rk_clrsetreg(&cru->clksel_con[24], MAC_CLK_DIV_MASK,
 161                             div << MAC_CLK_DIV_SHIFT);
 162        else
 163                debug("Unsupported div for gmac:%d\n", div);
 164
 165        return DIV_TO_RATE(pll_rate, div);
 166}
 167
 168static int rv1108_sfc_set_clk(struct rv1108_cru *cru, uint rate)
 169{
 170        u32 con = readl(&cru->clksel_con[27]);
 171        u32 pll_rate;
 172        u32 div;
 173
 174        if ((con >> SFC_PLL_SEL_SHIFT) && SFC_PLL_SEL_GPLL)
 175                pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 176        else
 177                pll_rate = rkclk_pll_get_rate(cru, CLK_DDR);
 178
 179        div = DIV_ROUND_UP(pll_rate, rate) - 1;
 180        if (div <= 0x3f)
 181                rk_clrsetreg(&cru->clksel_con[27], SFC_CLK_DIV_MASK,
 182                             div << SFC_CLK_DIV_SHIFT);
 183        else
 184                debug("Unsupported sfc clk rate:%d\n", rate);
 185
 186        return DIV_TO_RATE(pll_rate, div);
 187}
 188
 189static ulong rv1108_saradc_get_clk(struct rv1108_cru *cru)
 190{
 191        u32 div, val;
 192
 193        val = readl(&cru->clksel_con[22]);
 194        div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
 195                               CLK_SARADC_DIV_CON_WIDTH);
 196
 197        return DIV_TO_RATE(OSC_HZ, div);
 198}
 199
 200static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
 201{
 202        int src_clk_div;
 203
 204        src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
 205        assert(src_clk_div < 128);
 206
 207        rk_clrsetreg(&cru->clksel_con[22],
 208                     CLK_SARADC_DIV_CON_MASK,
 209                     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
 210
 211        return rv1108_saradc_get_clk(cru);
 212}
 213
 214static ulong rv1108_aclk_vio1_get_clk(struct rv1108_cru *cru)
 215{
 216        u32 div, val;
 217
 218        val = readl(&cru->clksel_con[28]);
 219        div = bitfield_extract(val, ACLK_VIO1_CLK_DIV_SHIFT,
 220                               CLK_VIO_DIV_CON_WIDTH);
 221
 222        return DIV_TO_RATE(GPLL_HZ, div);
 223}
 224
 225static ulong rv1108_aclk_vio1_set_clk(struct rv1108_cru *cru, uint hz)
 226{
 227        int src_clk_div;
 228
 229        src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
 230        assert(src_clk_div < 32);
 231
 232        rk_clrsetreg(&cru->clksel_con[28],
 233                     ACLK_VIO1_CLK_DIV_MASK | ACLK_VIO1_PLL_SEL_MASK,
 234                     (src_clk_div << ACLK_VIO1_CLK_DIV_SHIFT) |
 235                     (VIO_PLL_SEL_GPLL << ACLK_VIO1_PLL_SEL_SHIFT));
 236
 237        return rv1108_aclk_vio1_get_clk(cru);
 238}
 239
 240static ulong rv1108_aclk_vio0_get_clk(struct rv1108_cru *cru)
 241{
 242        u32 div, val;
 243
 244        val = readl(&cru->clksel_con[28]);
 245        div = bitfield_extract(val, ACLK_VIO0_CLK_DIV_SHIFT,
 246                               CLK_VIO_DIV_CON_WIDTH);
 247
 248        return DIV_TO_RATE(GPLL_HZ, div);
 249}
 250
 251static ulong rv1108_aclk_vio0_set_clk(struct rv1108_cru *cru, uint hz)
 252{
 253        int src_clk_div;
 254
 255        src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
 256        assert(src_clk_div < 32);
 257
 258        rk_clrsetreg(&cru->clksel_con[28],
 259                     ACLK_VIO0_CLK_DIV_MASK | ACLK_VIO0_PLL_SEL_MASK,
 260                     (src_clk_div << ACLK_VIO0_CLK_DIV_SHIFT) |
 261                     (VIO_PLL_SEL_GPLL << ACLK_VIO0_PLL_SEL_SHIFT));
 262
 263        /*HCLK_VIO default div = 4*/
 264        rk_clrsetreg(&cru->clksel_con[29],
 265                     HCLK_VIO_CLK_DIV_MASK,
 266                     3 << HCLK_VIO_CLK_DIV_SHIFT);
 267        /*PCLK_VIO default div = 4*/
 268        rk_clrsetreg(&cru->clksel_con[29],
 269                     PCLK_VIO_CLK_DIV_MASK,
 270                     3 << PCLK_VIO_CLK_DIV_SHIFT);
 271
 272        return rv1108_aclk_vio0_get_clk(cru);
 273}
 274
 275static ulong rv1108_dclk_vop_get_clk(struct rv1108_cru *cru)
 276{
 277        u32 div, val;
 278
 279        val = readl(&cru->clksel_con[32]);
 280        div = bitfield_extract(val, DCLK_VOP_CLK_DIV_SHIFT,
 281                               DCLK_VOP_DIV_CON_WIDTH);
 282
 283        return DIV_TO_RATE(GPLL_HZ, div);
 284}
 285
 286static ulong rv1108_dclk_vop_set_clk(struct rv1108_cru *cru, uint hz)
 287{
 288        int src_clk_div;
 289
 290        src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
 291        assert(src_clk_div < 64);
 292
 293        rk_clrsetreg(&cru->clksel_con[32],
 294                     DCLK_VOP_CLK_DIV_MASK | DCLK_VOP_PLL_SEL_MASK |
 295                     DCLK_VOP_SEL_SHIFT,
 296                     (src_clk_div << DCLK_VOP_CLK_DIV_SHIFT) |
 297                     (DCLK_VOP_PLL_SEL_GPLL << DCLK_VOP_PLL_SEL_SHIFT) |
 298                     (DCLK_VOP_SEL_PLL << DCLK_VOP_SEL_SHIFT));
 299
 300        return rv1108_dclk_vop_get_clk(cru);
 301}
 302
 303static ulong rv1108_aclk_bus_get_clk(struct rv1108_cru *cru)
 304{
 305        u32 div, val;
 306        ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 307
 308        val = readl(&cru->clksel_con[2]);
 309        div = bitfield_extract(val, ACLK_BUS_DIV_CON_SHIFT,
 310                               ACLK_BUS_DIV_CON_WIDTH);
 311
 312        return DIV_TO_RATE(parent_rate, div);
 313}
 314
 315static ulong rv1108_aclk_bus_set_clk(struct rv1108_cru *cru, uint hz)
 316{
 317        int src_clk_div;
 318        ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 319
 320        src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
 321        assert(src_clk_div < 32);
 322
 323        rk_clrsetreg(&cru->clksel_con[2],
 324                     ACLK_BUS_DIV_CON_MASK | ACLK_BUS_PLL_SEL_MASK,
 325                     (src_clk_div << ACLK_BUS_DIV_CON_SHIFT) |
 326                     (ACLK_BUS_PLL_SEL_GPLL << ACLK_BUS_PLL_SEL_SHIFT));
 327
 328        return rv1108_aclk_bus_get_clk(cru);
 329}
 330
 331static ulong rv1108_aclk_peri_get_clk(struct rv1108_cru *cru)
 332{
 333        u32 div, val;
 334        ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 335
 336        val = readl(&cru->clksel_con[23]);
 337        div = bitfield_extract(val, ACLK_PERI_DIV_CON_SHIFT,
 338                               PERI_DIV_CON_WIDTH);
 339
 340        return DIV_TO_RATE(parent_rate, div);
 341}
 342
 343static ulong rv1108_hclk_peri_get_clk(struct rv1108_cru *cru)
 344{
 345        u32 div, val;
 346        ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 347
 348        val = readl(&cru->clksel_con[23]);
 349        div = bitfield_extract(val, HCLK_PERI_DIV_CON_SHIFT,
 350                               PERI_DIV_CON_WIDTH);
 351
 352        return DIV_TO_RATE(parent_rate, div);
 353}
 354
 355static ulong rv1108_pclk_peri_get_clk(struct rv1108_cru *cru)
 356{
 357        u32 div, val;
 358        ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 359
 360        val = readl(&cru->clksel_con[23]);
 361        div = bitfield_extract(val, PCLK_PERI_DIV_CON_SHIFT,
 362                               PERI_DIV_CON_WIDTH);
 363
 364        return DIV_TO_RATE(parent_rate, div);
 365}
 366
 367static ulong rv1108_aclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
 368{
 369        int src_clk_div;
 370        ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 371
 372        src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
 373        assert(src_clk_div < 32);
 374
 375        rk_clrsetreg(&cru->clksel_con[23],
 376                     ACLK_PERI_DIV_CON_MASK | ACLK_PERI_PLL_SEL_MASK,
 377                     (src_clk_div << ACLK_PERI_DIV_CON_SHIFT) |
 378                     (ACLK_PERI_PLL_SEL_GPLL << ACLK_PERI_PLL_SEL_SHIFT));
 379
 380        return rv1108_aclk_peri_get_clk(cru);
 381}
 382
 383static ulong rv1108_hclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
 384{
 385        int src_clk_div;
 386        ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 387
 388        src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
 389        assert(src_clk_div < 32);
 390
 391        rk_clrsetreg(&cru->clksel_con[23],
 392                     HCLK_PERI_DIV_CON_MASK,
 393                     (src_clk_div << HCLK_PERI_DIV_CON_SHIFT));
 394
 395        return rv1108_hclk_peri_get_clk(cru);
 396}
 397
 398static ulong rv1108_pclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
 399{
 400        int src_clk_div;
 401        ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 402
 403        src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
 404        assert(src_clk_div < 32);
 405
 406        rk_clrsetreg(&cru->clksel_con[23],
 407                     PCLK_PERI_DIV_CON_MASK,
 408                     (src_clk_div << PCLK_PERI_DIV_CON_SHIFT));
 409
 410        return rv1108_pclk_peri_get_clk(cru);
 411}
 412
 413static ulong rv1108_i2c_get_clk(struct rv1108_cru *cru, ulong clk_id)
 414{
 415        u32 div, con;
 416
 417        switch (clk_id) {
 418        case SCLK_I2C0_PMU:
 419                con = readl(&cru->clksel_con[19]);
 420                div = bitfield_extract(con, CLK_I2C0_DIV_CON_SHIFT,
 421                                       I2C_DIV_CON_WIDTH);
 422                break;
 423        case SCLK_I2C1:
 424                con = readl(&cru->clksel_con[19]);
 425                div = bitfield_extract(con, CLK_I2C1_DIV_CON_SHIFT,
 426                                       I2C_DIV_CON_WIDTH);
 427                break;
 428        case SCLK_I2C2:
 429                con = readl(&cru->clksel_con[20]);
 430                div = bitfield_extract(con, CLK_I2C2_DIV_CON_SHIFT,
 431                                       I2C_DIV_CON_WIDTH);
 432                break;
 433        case SCLK_I2C3:
 434                con = readl(&cru->clksel_con[20]);
 435                div = bitfield_extract(con, CLK_I2C3_DIV_CON_SHIFT,
 436                                       I2C_DIV_CON_WIDTH);
 437                break;
 438        default:
 439                printf("do not support this i2c bus\n");
 440                return -EINVAL;
 441        }
 442
 443        return DIV_TO_RATE(GPLL_HZ, div);
 444}
 445
 446static ulong rv1108_i2c_set_clk(struct rv1108_cru *cru, ulong clk_id, uint hz)
 447{
 448        int src_clk_div;
 449
 450        /* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
 451        src_clk_div = GPLL_HZ / hz;
 452        assert(src_clk_div - 1 <= 127);
 453
 454        switch (clk_id) {
 455        case SCLK_I2C0_PMU:
 456                rk_clrsetreg(&cru->clksel_con[19],
 457                             CLK_I2C0_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
 458                             (src_clk_div << CLK_I2C0_DIV_CON_SHIFT) |
 459                             (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
 460                break;
 461        case SCLK_I2C1:
 462                rk_clrsetreg(&cru->clksel_con[19],
 463                             CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
 464                             (src_clk_div << CLK_I2C1_DIV_CON_SHIFT) |
 465                             (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
 466                break;
 467        case SCLK_I2C2:
 468                rk_clrsetreg(&cru->clksel_con[20],
 469                             CLK_I2C2_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
 470                             (src_clk_div << CLK_I2C2_DIV_CON_SHIFT) |
 471                             (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
 472                break;
 473        case SCLK_I2C3:
 474                rk_clrsetreg(&cru->clksel_con[20],
 475                             CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
 476                             (src_clk_div << CLK_I2C3_DIV_CON_SHIFT) |
 477                             (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
 478                break;
 479        default:
 480                printf("do not support this i2c bus\n");
 481                return -EINVAL;
 482        }
 483
 484        return rv1108_i2c_get_clk(cru, clk_id);
 485}
 486
 487static ulong rv1108_mmc_get_clk(struct rv1108_cru *cru)
 488{
 489        u32 div, con;
 490        ulong mmc_clk;
 491
 492        con = readl(&cru->clksel_con[26]);
 493        div = bitfield_extract(con, EMMC_CLK_DIV_SHIFT, 8);
 494
 495        con = readl(&cru->clksel_con[25]);
 496
 497        if ((con & EMMC_PLL_SEL_MASK) >> EMMC_PLL_SEL_SHIFT == EMMC_PLL_SEL_OSC)
 498                mmc_clk = DIV_TO_RATE(OSC_HZ, div) / 2;
 499        else
 500                mmc_clk = DIV_TO_RATE(GPLL_HZ, div) / 2;
 501
 502        debug("%s div %d get_clk %ld\n", __func__, div, mmc_clk);
 503        return mmc_clk;
 504}
 505
 506static ulong rv1108_mmc_set_clk(struct rv1108_cru *cru, ulong rate)
 507{
 508        int div;
 509        u32 pll_rate;
 510
 511        div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, CLK_GENERAL), rate);
 512
 513        if (div < 127) {
 514                debug("%s source gpll\n", __func__);
 515                rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
 516                            (EMMC_PLL_SEL_GPLL << EMMC_PLL_SEL_SHIFT));
 517                pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
 518        } else {
 519                debug("%s source 24m\n", __func__);
 520                rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
 521                            (EMMC_PLL_SEL_OSC << EMMC_PLL_SEL_SHIFT));
 522                pll_rate = OSC_HZ;
 523        }
 524
 525        div = DIV_ROUND_UP(pll_rate / 2, rate);
 526        rk_clrsetreg(&cru->clksel_con[26], EMMC_CLK_DIV_MASK,
 527                    ((div - 1) << EMMC_CLK_DIV_SHIFT));
 528
 529        debug("%s set_rate %ld div %d\n", __func__,  rate, div);
 530
 531        return DIV_TO_RATE(pll_rate, div);
 532}
 533
 534static ulong rv1108_clk_get_rate(struct clk *clk)
 535{
 536        struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
 537
 538        switch (clk->id) {
 539        case 0 ... 63:
 540                return rkclk_pll_get_rate(priv->cru, clk->id);
 541        case SCLK_SARADC:
 542                return rv1108_saradc_get_clk(priv->cru);
 543        case ACLK_VIO0:
 544                return rv1108_aclk_vio0_get_clk(priv->cru);
 545        case ACLK_VIO1:
 546                return rv1108_aclk_vio1_get_clk(priv->cru);
 547        case DCLK_VOP:
 548                return rv1108_dclk_vop_get_clk(priv->cru);
 549        case ACLK_PRE:
 550                return rv1108_aclk_bus_get_clk(priv->cru);
 551        case ACLK_PERI:
 552                return rv1108_aclk_peri_get_clk(priv->cru);
 553        case HCLK_PERI:
 554                return rv1108_hclk_peri_get_clk(priv->cru);
 555        case PCLK_PERI:
 556                return rv1108_pclk_peri_get_clk(priv->cru);
 557        case SCLK_I2C0_PMU:
 558        case SCLK_I2C1:
 559        case SCLK_I2C2:
 560        case SCLK_I2C3:
 561                return rv1108_i2c_get_clk(priv->cru, clk->id);
 562        case HCLK_EMMC:
 563        case SCLK_EMMC:
 564        case SCLK_EMMC_SAMPLE:
 565                return rv1108_mmc_get_clk(priv->cru);
 566        default:
 567                return -ENOENT;
 568        }
 569}
 570
 571static ulong rv1108_clk_set_rate(struct clk *clk, ulong rate)
 572{
 573        struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
 574        ulong new_rate;
 575
 576        switch (clk->id) {
 577        case SCLK_MAC:
 578                new_rate = rv1108_mac_set_clk(priv->cru, rate);
 579                break;
 580        case SCLK_SFC:
 581                new_rate = rv1108_sfc_set_clk(priv->cru, rate);
 582                break;
 583        case SCLK_SARADC:
 584                new_rate = rv1108_saradc_set_clk(priv->cru, rate);
 585                break;
 586        case ACLK_VIO0:
 587                new_rate = rv1108_aclk_vio0_set_clk(priv->cru, rate);
 588                break;
 589        case ACLK_VIO1:
 590                new_rate = rv1108_aclk_vio1_set_clk(priv->cru, rate);
 591                break;
 592        case DCLK_VOP:
 593                new_rate = rv1108_dclk_vop_set_clk(priv->cru, rate);
 594                break;
 595        case ACLK_PRE:
 596                new_rate = rv1108_aclk_bus_set_clk(priv->cru, rate);
 597                break;
 598        case ACLK_PERI:
 599                new_rate = rv1108_aclk_peri_set_clk(priv->cru, rate);
 600                break;
 601        case HCLK_PERI:
 602                new_rate = rv1108_hclk_peri_set_clk(priv->cru, rate);
 603                break;
 604        case PCLK_PERI:
 605                new_rate = rv1108_pclk_peri_set_clk(priv->cru, rate);
 606                break;
 607        case SCLK_I2C0_PMU:
 608        case SCLK_I2C1:
 609        case SCLK_I2C2:
 610        case SCLK_I2C3:
 611                new_rate = rv1108_i2c_set_clk(priv->cru, clk->id, rate);
 612                break;
 613        case HCLK_EMMC:
 614        case SCLK_EMMC:
 615                new_rate = rv1108_mmc_set_clk(priv->cru, rate);
 616                break;
 617        default:
 618                return -ENOENT;
 619        }
 620
 621        return new_rate;
 622}
 623
 624static const struct clk_ops rv1108_clk_ops = {
 625        .get_rate       = rv1108_clk_get_rate,
 626        .set_rate       = rv1108_clk_set_rate,
 627};
 628
 629static void rkclk_init(struct rv1108_cru *cru)
 630{
 631        unsigned int apll, dpll, gpll;
 632        unsigned int aclk_bus, aclk_peri, hclk_peri, pclk_peri;
 633
 634        aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ / 2);
 635        aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ / 2);
 636        hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ / 2);
 637        pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ / 2);
 638        rv1108_aclk_vio0_set_clk(cru, 297000000);
 639        rv1108_aclk_vio1_set_clk(cru, 297000000);
 640
 641        /* configure apll */
 642        rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
 643        rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
 644        aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ);
 645        aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ);
 646        hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ);
 647        pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ);
 648
 649        apll = rkclk_pll_get_rate(cru, CLK_ARM);
 650        dpll = rkclk_pll_get_rate(cru, CLK_DDR);
 651        gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
 652
 653        rk_clrsetreg(&cru->clksel_con[0], CORE_CLK_DIV_MASK,
 654                     0 << MAC_CLK_DIV_SHIFT);
 655
 656        printf("APLL: %d DPLL:%d GPLL:%d\n", apll, dpll, gpll);
 657        printf("ACLK_BUS: %d ACLK_PERI:%d HCLK_PERI:%d PCLK_PERI:%d\n",
 658               aclk_bus, aclk_peri, hclk_peri, pclk_peri);
 659}
 660
 661static int rv1108_clk_ofdata_to_platdata(struct udevice *dev)
 662{
 663        struct rv1108_clk_priv *priv = dev_get_priv(dev);
 664
 665        priv->cru = dev_read_addr_ptr(dev);
 666
 667        return 0;
 668}
 669
 670static int rv1108_clk_probe(struct udevice *dev)
 671{
 672        struct rv1108_clk_priv *priv = dev_get_priv(dev);
 673
 674        rkclk_init(priv->cru);
 675
 676        return 0;
 677}
 678
 679static int rv1108_clk_bind(struct udevice *dev)
 680{
 681        int ret;
 682        struct udevice *sys_child, *sf_child;
 683        struct sysreset_reg *priv;
 684        struct softreset_reg *sf_priv;
 685
 686        /* The reset driver does not have a device node, so bind it here */
 687        ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
 688                                 &sys_child);
 689        if (ret) {
 690                debug("Warning: No sysreset driver: ret=%d\n", ret);
 691        } else {
 692                priv = malloc(sizeof(struct sysreset_reg));
 693                priv->glb_srst_fst_value = offsetof(struct rv1108_cru,
 694                                                    glb_srst_fst_val);
 695                priv->glb_srst_snd_value = offsetof(struct rv1108_cru,
 696                                                    glb_srst_snd_val);
 697                sys_child->priv = priv;
 698        }
 699
 700#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
 701        ret = offsetof(struct rk3368_cru, softrst_con[0]);
 702        ret = rockchip_reset_bind(dev, ret, 13);
 703        if (ret)
 704                debug("Warning: software reset driver bind faile\n");
 705#endif
 706        ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
 707                                         dev_ofnode(dev), &sf_child);
 708        if (ret) {
 709                debug("Warning: No rockchip reset driver: ret=%d\n", ret);
 710        } else {
 711                sf_priv = malloc(sizeof(struct softreset_reg));
 712                sf_priv->sf_reset_offset = offsetof(struct rv1108_cru,
 713                                                    softrst_con[0]);
 714                sf_priv->sf_reset_num = 13;
 715                sf_child->priv = sf_priv;
 716        }
 717
 718        return 0;
 719}
 720
 721static const struct udevice_id rv1108_clk_ids[] = {
 722        { .compatible = "rockchip,rv1108-cru" },
 723        { }
 724};
 725
 726U_BOOT_DRIVER(clk_rv1108) = {
 727        .name           = "clk_rv1108",
 728        .id             = UCLASS_CLK,
 729        .of_match       = rv1108_clk_ids,
 730        .priv_auto_alloc_size = sizeof(struct rv1108_clk_priv),
 731        .ops            = &rv1108_clk_ops,
 732        .bind           = rv1108_clk_bind,
 733        .ofdata_to_platdata     = rv1108_clk_ofdata_to_platdata,
 734        .probe          = rv1108_clk_probe,
 735};
 736