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