uboot/drivers/clk/rockchip/clk_rk3399.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * (C) Copyright 2015 Google, Inc
   4 * (C) 2017 Theobroma Systems Design und Consulting GmbH
   5 */
   6
   7#include <common.h>
   8#include <clk-uclass.h>
   9#include <dm.h>
  10#include <dt-structs.h>
  11#include <errno.h>
  12#include <log.h>
  13#include <malloc.h>
  14#include <mapmem.h>
  15#include <syscon.h>
  16#include <bitfield.h>
  17#include <asm/io.h>
  18#include <asm/arch-rockchip/clock.h>
  19#include <asm/arch-rockchip/cru.h>
  20#include <asm/arch-rockchip/hardware.h>
  21#include <asm/global_data.h>
  22#include <dm/device-internal.h>
  23#include <dm/lists.h>
  24#include <dt-bindings/clock/rk3399-cru.h>
  25#include <linux/bitops.h>
  26#include <linux/delay.h>
  27
  28DECLARE_GLOBAL_DATA_PTR;
  29
  30#if CONFIG_IS_ENABLED(OF_PLATDATA)
  31struct rk3399_clk_plat {
  32        struct dtd_rockchip_rk3399_cru dtd;
  33};
  34
  35struct rk3399_pmuclk_plat {
  36        struct dtd_rockchip_rk3399_pmucru dtd;
  37};
  38#endif
  39
  40struct pll_div {
  41        u32 refdiv;
  42        u32 fbdiv;
  43        u32 postdiv1;
  44        u32 postdiv2;
  45        u32 frac;
  46};
  47
  48#define RATE_TO_DIV(input_rate, output_rate) \
  49        ((input_rate) / (output_rate) - 1)
  50#define DIV_TO_RATE(input_rate, div)            ((input_rate) / ((div) + 1))
  51
  52#define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
  53        .refdiv = _refdiv,\
  54        .fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
  55        .postdiv1 = _postdiv1, .postdiv2 = _postdiv2};
  56
  57static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
  58static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2, 2);
  59#if !defined(CONFIG_SPL_BUILD)
  60static const struct pll_div ppll_init_cfg = PLL_DIVISORS(PPLL_HZ, 2, 2, 1);
  61#endif
  62
  63static const struct pll_div apll_l_1600_cfg = PLL_DIVISORS(1600 * MHz, 3, 1, 1);
  64static const struct pll_div apll_l_600_cfg = PLL_DIVISORS(600 * MHz, 1, 2, 1);
  65
  66static const struct pll_div *apll_l_cfgs[] = {
  67        [APLL_L_1600_MHZ] = &apll_l_1600_cfg,
  68        [APLL_L_600_MHZ] = &apll_l_600_cfg,
  69};
  70
  71static const struct pll_div apll_b_600_cfg = PLL_DIVISORS(600 * MHz, 1, 2, 1);
  72static const struct pll_div *apll_b_cfgs[] = {
  73        [APLL_B_600_MHZ] = &apll_b_600_cfg,
  74};
  75
  76enum {
  77        /* PLL_CON0 */
  78        PLL_FBDIV_MASK                  = 0xfff,
  79        PLL_FBDIV_SHIFT                 = 0,
  80
  81        /* PLL_CON1 */
  82        PLL_POSTDIV2_SHIFT              = 12,
  83        PLL_POSTDIV2_MASK               = 0x7 << PLL_POSTDIV2_SHIFT,
  84        PLL_POSTDIV1_SHIFT              = 8,
  85        PLL_POSTDIV1_MASK               = 0x7 << PLL_POSTDIV1_SHIFT,
  86        PLL_REFDIV_MASK                 = 0x3f,
  87        PLL_REFDIV_SHIFT                = 0,
  88
  89        /* PLL_CON2 */
  90        PLL_LOCK_STATUS_SHIFT           = 31,
  91        PLL_LOCK_STATUS_MASK            = 1 << PLL_LOCK_STATUS_SHIFT,
  92        PLL_FRACDIV_MASK                = 0xffffff,
  93        PLL_FRACDIV_SHIFT               = 0,
  94
  95        /* PLL_CON3 */
  96        PLL_MODE_SHIFT                  = 8,
  97        PLL_MODE_MASK                   = 3 << PLL_MODE_SHIFT,
  98        PLL_MODE_SLOW                   = 0,
  99        PLL_MODE_NORM,
 100        PLL_MODE_DEEP,
 101        PLL_DSMPD_SHIFT                 = 3,
 102        PLL_DSMPD_MASK                  = 1 << PLL_DSMPD_SHIFT,
 103        PLL_INTEGER_MODE                = 1,
 104
 105        /* PMUCRU_CLKSEL_CON0 */
 106        PMU_PCLK_DIV_CON_MASK           = 0x1f,
 107        PMU_PCLK_DIV_CON_SHIFT          = 0,
 108
 109        /* PMUCRU_CLKSEL_CON1 */
 110        SPI3_PLL_SEL_SHIFT              = 7,
 111        SPI3_PLL_SEL_MASK               = 1 << SPI3_PLL_SEL_SHIFT,
 112        SPI3_PLL_SEL_24M                = 0,
 113        SPI3_PLL_SEL_PPLL               = 1,
 114        SPI3_DIV_CON_SHIFT              = 0x0,
 115        SPI3_DIV_CON_MASK               = 0x7f,
 116
 117        /* PMUCRU_CLKSEL_CON2 */
 118        I2C_DIV_CON_MASK                = 0x7f,
 119        CLK_I2C8_DIV_CON_SHIFT          = 8,
 120        CLK_I2C0_DIV_CON_SHIFT          = 0,
 121
 122        /* PMUCRU_CLKSEL_CON3 */
 123        CLK_I2C4_DIV_CON_SHIFT          = 0,
 124
 125        /* CLKSEL_CON0 */
 126        ACLKM_CORE_L_DIV_CON_SHIFT      = 8,
 127        ACLKM_CORE_L_DIV_CON_MASK       = 0x1f << ACLKM_CORE_L_DIV_CON_SHIFT,
 128        CLK_CORE_L_PLL_SEL_SHIFT        = 6,
 129        CLK_CORE_L_PLL_SEL_MASK         = 3 << CLK_CORE_L_PLL_SEL_SHIFT,
 130        CLK_CORE_L_PLL_SEL_ALPLL        = 0x0,
 131        CLK_CORE_L_PLL_SEL_ABPLL        = 0x1,
 132        CLK_CORE_L_PLL_SEL_DPLL         = 0x10,
 133        CLK_CORE_L_PLL_SEL_GPLL         = 0x11,
 134        CLK_CORE_L_DIV_MASK             = 0x1f,
 135        CLK_CORE_L_DIV_SHIFT            = 0,
 136
 137        /* CLKSEL_CON1 */
 138        PCLK_DBG_L_DIV_SHIFT            = 0x8,
 139        PCLK_DBG_L_DIV_MASK             = 0x1f << PCLK_DBG_L_DIV_SHIFT,
 140        ATCLK_CORE_L_DIV_SHIFT          = 0,
 141        ATCLK_CORE_L_DIV_MASK           = 0x1f << ATCLK_CORE_L_DIV_SHIFT,
 142
 143        /* CLKSEL_CON2 */
 144        ACLKM_CORE_B_DIV_CON_SHIFT      = 8,
 145        ACLKM_CORE_B_DIV_CON_MASK       = 0x1f << ACLKM_CORE_B_DIV_CON_SHIFT,
 146        CLK_CORE_B_PLL_SEL_SHIFT        = 6,
 147        CLK_CORE_B_PLL_SEL_MASK         = 3 << CLK_CORE_B_PLL_SEL_SHIFT,
 148        CLK_CORE_B_PLL_SEL_ALPLL        = 0x0,
 149        CLK_CORE_B_PLL_SEL_ABPLL        = 0x1,
 150        CLK_CORE_B_PLL_SEL_DPLL         = 0x10,
 151        CLK_CORE_B_PLL_SEL_GPLL         = 0x11,
 152        CLK_CORE_B_DIV_MASK             = 0x1f,
 153        CLK_CORE_B_DIV_SHIFT            = 0,
 154
 155        /* CLKSEL_CON3 */
 156        PCLK_DBG_B_DIV_SHIFT            = 0x8,
 157        PCLK_DBG_B_DIV_MASK             = 0x1f << PCLK_DBG_B_DIV_SHIFT,
 158        ATCLK_CORE_B_DIV_SHIFT          = 0,
 159        ATCLK_CORE_B_DIV_MASK           = 0x1f << ATCLK_CORE_B_DIV_SHIFT,
 160
 161        /* CLKSEL_CON14 */
 162        PCLK_PERIHP_DIV_CON_SHIFT       = 12,
 163        PCLK_PERIHP_DIV_CON_MASK        = 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
 164        HCLK_PERIHP_DIV_CON_SHIFT       = 8,
 165        HCLK_PERIHP_DIV_CON_MASK        = 3 << HCLK_PERIHP_DIV_CON_SHIFT,
 166        ACLK_PERIHP_PLL_SEL_SHIFT       = 7,
 167        ACLK_PERIHP_PLL_SEL_MASK        = 1 << ACLK_PERIHP_PLL_SEL_SHIFT,
 168        ACLK_PERIHP_PLL_SEL_CPLL        = 0,
 169        ACLK_PERIHP_PLL_SEL_GPLL        = 1,
 170        ACLK_PERIHP_DIV_CON_SHIFT       = 0,
 171        ACLK_PERIHP_DIV_CON_MASK        = 0x1f,
 172
 173        /* CLKSEL_CON21 */
 174        ACLK_EMMC_PLL_SEL_SHIFT         = 7,
 175        ACLK_EMMC_PLL_SEL_MASK          = 0x1 << ACLK_EMMC_PLL_SEL_SHIFT,
 176        ACLK_EMMC_PLL_SEL_GPLL          = 0x1,
 177        ACLK_EMMC_DIV_CON_SHIFT         = 0,
 178        ACLK_EMMC_DIV_CON_MASK          = 0x1f,
 179
 180        /* CLKSEL_CON22 */
 181        CLK_EMMC_PLL_SHIFT              = 8,
 182        CLK_EMMC_PLL_MASK               = 0x7 << CLK_EMMC_PLL_SHIFT,
 183        CLK_EMMC_PLL_SEL_GPLL           = 0x1,
 184        CLK_EMMC_PLL_SEL_24M            = 0x5,
 185        CLK_EMMC_DIV_CON_SHIFT          = 0,
 186        CLK_EMMC_DIV_CON_MASK           = 0x7f << CLK_EMMC_DIV_CON_SHIFT,
 187
 188        /* CLKSEL_CON23 */
 189        PCLK_PERILP0_DIV_CON_SHIFT      = 12,
 190        PCLK_PERILP0_DIV_CON_MASK       = 0x7 << PCLK_PERILP0_DIV_CON_SHIFT,
 191        HCLK_PERILP0_DIV_CON_SHIFT      = 8,
 192        HCLK_PERILP0_DIV_CON_MASK       = 3 << HCLK_PERILP0_DIV_CON_SHIFT,
 193        ACLK_PERILP0_PLL_SEL_SHIFT      = 7,
 194        ACLK_PERILP0_PLL_SEL_MASK       = 1 << ACLK_PERILP0_PLL_SEL_SHIFT,
 195        ACLK_PERILP0_PLL_SEL_CPLL       = 0,
 196        ACLK_PERILP0_PLL_SEL_GPLL       = 1,
 197        ACLK_PERILP0_DIV_CON_SHIFT      = 0,
 198        ACLK_PERILP0_DIV_CON_MASK       = 0x1f,
 199
 200        /* CLKSEL_CON25 */
 201        PCLK_PERILP1_DIV_CON_SHIFT      = 8,
 202        PCLK_PERILP1_DIV_CON_MASK       = 0x7 << PCLK_PERILP1_DIV_CON_SHIFT,
 203        HCLK_PERILP1_PLL_SEL_SHIFT      = 7,
 204        HCLK_PERILP1_PLL_SEL_MASK       = 1 << HCLK_PERILP1_PLL_SEL_SHIFT,
 205        HCLK_PERILP1_PLL_SEL_CPLL       = 0,
 206        HCLK_PERILP1_PLL_SEL_GPLL       = 1,
 207        HCLK_PERILP1_DIV_CON_SHIFT      = 0,
 208        HCLK_PERILP1_DIV_CON_MASK       = 0x1f,
 209
 210        /* CLKSEL_CON26 */
 211        CLK_SARADC_DIV_CON_SHIFT        = 8,
 212        CLK_SARADC_DIV_CON_MASK         = GENMASK(15, 8),
 213        CLK_SARADC_DIV_CON_WIDTH        = 8,
 214
 215        /* CLKSEL_CON27 */
 216        CLK_TSADC_SEL_X24M              = 0x0,
 217        CLK_TSADC_SEL_SHIFT             = 15,
 218        CLK_TSADC_SEL_MASK              = 1 << CLK_TSADC_SEL_SHIFT,
 219        CLK_TSADC_DIV_CON_SHIFT         = 0,
 220        CLK_TSADC_DIV_CON_MASK          = 0x3ff,
 221
 222        /* CLKSEL_CON47 & CLKSEL_CON48 */
 223        ACLK_VOP_PLL_SEL_SHIFT          = 6,
 224        ACLK_VOP_PLL_SEL_MASK           = 0x3 << ACLK_VOP_PLL_SEL_SHIFT,
 225        ACLK_VOP_PLL_SEL_CPLL           = 0x1,
 226        ACLK_VOP_DIV_CON_SHIFT          = 0,
 227        ACLK_VOP_DIV_CON_MASK           = 0x1f << ACLK_VOP_DIV_CON_SHIFT,
 228
 229        /* CLKSEL_CON49 & CLKSEL_CON50 */
 230        DCLK_VOP_DCLK_SEL_SHIFT         = 11,
 231        DCLK_VOP_DCLK_SEL_MASK          = 1 << DCLK_VOP_DCLK_SEL_SHIFT,
 232        DCLK_VOP_DCLK_SEL_DIVOUT        = 0,
 233        DCLK_VOP_PLL_SEL_SHIFT          = 8,
 234        DCLK_VOP_PLL_SEL_MASK           = 3 << DCLK_VOP_PLL_SEL_SHIFT,
 235        DCLK_VOP_PLL_SEL_VPLL           = 0,
 236        DCLK_VOP_DIV_CON_MASK           = 0xff,
 237        DCLK_VOP_DIV_CON_SHIFT          = 0,
 238
 239        /* CLKSEL_CON57 */
 240        PCLK_ALIVE_DIV_CON_SHIFT        = 0,
 241        PCLK_ALIVE_DIV_CON_MASK         = 0x1f << PCLK_ALIVE_DIV_CON_SHIFT,
 242
 243        /* CLKSEL_CON58 */
 244        CLK_SPI_PLL_SEL_WIDTH = 1,
 245        CLK_SPI_PLL_SEL_MASK = ((1 < CLK_SPI_PLL_SEL_WIDTH) - 1),
 246        CLK_SPI_PLL_SEL_CPLL = 0,
 247        CLK_SPI_PLL_SEL_GPLL = 1,
 248        CLK_SPI_PLL_DIV_CON_WIDTH = 7,
 249        CLK_SPI_PLL_DIV_CON_MASK = ((1 << CLK_SPI_PLL_DIV_CON_WIDTH) - 1),
 250
 251        CLK_SPI5_PLL_DIV_CON_SHIFT      = 8,
 252        CLK_SPI5_PLL_SEL_SHIFT          = 15,
 253
 254        /* CLKSEL_CON59 */
 255        CLK_SPI1_PLL_SEL_SHIFT          = 15,
 256        CLK_SPI1_PLL_DIV_CON_SHIFT      = 8,
 257        CLK_SPI0_PLL_SEL_SHIFT          = 7,
 258        CLK_SPI0_PLL_DIV_CON_SHIFT      = 0,
 259
 260        /* CLKSEL_CON60 */
 261        CLK_SPI4_PLL_SEL_SHIFT          = 15,
 262        CLK_SPI4_PLL_DIV_CON_SHIFT      = 8,
 263        CLK_SPI2_PLL_SEL_SHIFT          = 7,
 264        CLK_SPI2_PLL_DIV_CON_SHIFT      = 0,
 265
 266        /* CLKSEL_CON61 */
 267        CLK_I2C_PLL_SEL_MASK            = 1,
 268        CLK_I2C_PLL_SEL_CPLL            = 0,
 269        CLK_I2C_PLL_SEL_GPLL            = 1,
 270        CLK_I2C5_PLL_SEL_SHIFT          = 15,
 271        CLK_I2C5_DIV_CON_SHIFT          = 8,
 272        CLK_I2C1_PLL_SEL_SHIFT          = 7,
 273        CLK_I2C1_DIV_CON_SHIFT          = 0,
 274
 275        /* CLKSEL_CON62 */
 276        CLK_I2C6_PLL_SEL_SHIFT          = 15,
 277        CLK_I2C6_DIV_CON_SHIFT          = 8,
 278        CLK_I2C2_PLL_SEL_SHIFT          = 7,
 279        CLK_I2C2_DIV_CON_SHIFT          = 0,
 280
 281        /* CLKSEL_CON63 */
 282        CLK_I2C7_PLL_SEL_SHIFT          = 15,
 283        CLK_I2C7_DIV_CON_SHIFT          = 8,
 284        CLK_I2C3_PLL_SEL_SHIFT          = 7,
 285        CLK_I2C3_DIV_CON_SHIFT          = 0,
 286
 287        /* CRU_SOFTRST_CON4 */
 288        RESETN_DDR0_REQ_SHIFT           = 8,
 289        RESETN_DDR0_REQ_MASK            = 1 << RESETN_DDR0_REQ_SHIFT,
 290        RESETN_DDRPHY0_REQ_SHIFT        = 9,
 291        RESETN_DDRPHY0_REQ_MASK         = 1 << RESETN_DDRPHY0_REQ_SHIFT,
 292        RESETN_DDR1_REQ_SHIFT           = 12,
 293        RESETN_DDR1_REQ_MASK            = 1 << RESETN_DDR1_REQ_SHIFT,
 294        RESETN_DDRPHY1_REQ_SHIFT        = 13,
 295        RESETN_DDRPHY1_REQ_MASK         = 1 << RESETN_DDRPHY1_REQ_SHIFT,
 296};
 297
 298#define VCO_MAX_KHZ     (3200 * (MHz / KHz))
 299#define VCO_MIN_KHZ     (800 * (MHz / KHz))
 300#define OUTPUT_MAX_KHZ  (3200 * (MHz / KHz))
 301#define OUTPUT_MIN_KHZ  (16 * (MHz / KHz))
 302
 303/*
 304 *  the div restructions of pll in integer mode, these are defined in
 305 *  * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
 306 */
 307#define PLL_DIV_MIN     16
 308#define PLL_DIV_MAX     3200
 309
 310/*
 311 * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
 312 * Formulas also embedded within the Fractional PLL Verilog model:
 313 * If DSMPD = 1 (DSM is disabled, "integer mode")
 314 * FOUTVCO = FREF / REFDIV * FBDIV
 315 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
 316 * Where:
 317 * FOUTVCO = Fractional PLL non-divided output frequency
 318 * FOUTPOSTDIV = Fractional PLL divided output frequency
 319 *               (output of second post divider)
 320 * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
 321 * REFDIV = Fractional PLL input reference clock divider
 322 * FBDIV = Integer value programmed into feedback divide
 323 *
 324 */
 325static void rkclk_set_pll(u32 *pll_con, const struct pll_div *div)
 326{
 327        /* All 8 PLLs have same VCO and output frequency range restrictions. */
 328        u32 vco_khz = OSC_HZ / 1000 * div->fbdiv / div->refdiv;
 329        u32 output_khz = vco_khz / div->postdiv1 / div->postdiv2;
 330
 331        debug("PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, "
 332                           "postdiv2=%d, vco=%u khz, output=%u khz\n",
 333                           pll_con, div->fbdiv, div->refdiv, div->postdiv1,
 334                           div->postdiv2, vco_khz, output_khz);
 335        assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ &&
 336               output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ &&
 337               div->fbdiv >= PLL_DIV_MIN && div->fbdiv <= PLL_DIV_MAX);
 338
 339        /*
 340         * When power on or changing PLL setting,
 341         * we must force PLL into slow mode to ensure output stable clock.
 342         */
 343        rk_clrsetreg(&pll_con[3], PLL_MODE_MASK,
 344                     PLL_MODE_SLOW << PLL_MODE_SHIFT);
 345
 346        /* use integer mode */
 347        rk_clrsetreg(&pll_con[3], PLL_DSMPD_MASK,
 348                     PLL_INTEGER_MODE << PLL_DSMPD_SHIFT);
 349
 350        rk_clrsetreg(&pll_con[0], PLL_FBDIV_MASK,
 351                     div->fbdiv << PLL_FBDIV_SHIFT);
 352        rk_clrsetreg(&pll_con[1],
 353                     PLL_POSTDIV2_MASK | PLL_POSTDIV1_MASK |
 354                     PLL_REFDIV_MASK | PLL_REFDIV_SHIFT,
 355                     (div->postdiv2 << PLL_POSTDIV2_SHIFT) |
 356                     (div->postdiv1 << PLL_POSTDIV1_SHIFT) |
 357                     (div->refdiv << PLL_REFDIV_SHIFT));
 358
 359        /* waiting for pll lock */
 360        while (!(readl(&pll_con[2]) & (1 << PLL_LOCK_STATUS_SHIFT)))
 361                udelay(1);
 362
 363        /* pll enter normal mode */
 364        rk_clrsetreg(&pll_con[3], PLL_MODE_MASK,
 365                     PLL_MODE_NORM << PLL_MODE_SHIFT);
 366}
 367
 368static int pll_para_config(u32 freq_hz, struct pll_div *div)
 369{
 370        u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
 371        u32 postdiv1, postdiv2 = 1;
 372        u32 fref_khz;
 373        u32 diff_khz, best_diff_khz;
 374        const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
 375        const u32 max_postdiv1 = 7, max_postdiv2 = 7;
 376        u32 vco_khz;
 377        u32 freq_khz = freq_hz / KHz;
 378
 379        if (!freq_hz) {
 380                printf("%s: the frequency can't be 0 Hz\n", __func__);
 381                return -1;
 382        }
 383
 384        postdiv1 = DIV_ROUND_UP(VCO_MIN_KHZ, freq_khz);
 385        if (postdiv1 > max_postdiv1) {
 386                postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
 387                postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
 388        }
 389
 390        vco_khz = freq_khz * postdiv1 * postdiv2;
 391
 392        if (vco_khz < VCO_MIN_KHZ || vco_khz > VCO_MAX_KHZ ||
 393            postdiv2 > max_postdiv2) {
 394                printf("%s: Cannot find out a supported VCO"
 395                       " for Frequency (%uHz).\n", __func__, freq_hz);
 396                return -1;
 397        }
 398
 399        div->postdiv1 = postdiv1;
 400        div->postdiv2 = postdiv2;
 401
 402        best_diff_khz = vco_khz;
 403        for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
 404                fref_khz = ref_khz / refdiv;
 405
 406                fbdiv = vco_khz / fref_khz;
 407                if (fbdiv >= max_fbdiv || fbdiv <= min_fbdiv)
 408                        continue;
 409                diff_khz = vco_khz - fbdiv * fref_khz;
 410                if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
 411                        fbdiv++;
 412                        diff_khz = fref_khz - diff_khz;
 413                }
 414
 415                if (diff_khz >= best_diff_khz)
 416                        continue;
 417
 418                best_diff_khz = diff_khz;
 419                div->refdiv = refdiv;
 420                div->fbdiv = fbdiv;
 421        }
 422
 423        if (best_diff_khz > 4 * (MHz / KHz)) {
 424                printf("%s: Failed to match output frequency %u, "
 425                       "difference is %u Hz,exceed 4MHZ\n", __func__, freq_hz,
 426                       best_diff_khz * KHz);
 427                return -1;
 428        }
 429        return 0;
 430}
 431
 432void rk3399_configure_cpu_l(struct rockchip_cru *cru,
 433                            enum apll_l_frequencies apll_l_freq)
 434{
 435        u32 aclkm_div;
 436        u32 pclk_dbg_div;
 437        u32 atclk_div;
 438
 439        /* Setup cluster L */
 440        rkclk_set_pll(&cru->apll_l_con[0], apll_l_cfgs[apll_l_freq]);
 441
 442        aclkm_div = LPLL_HZ / ACLKM_CORE_L_HZ - 1;
 443        assert((aclkm_div + 1) * ACLKM_CORE_L_HZ == LPLL_HZ &&
 444               aclkm_div < 0x1f);
 445
 446        pclk_dbg_div = LPLL_HZ / PCLK_DBG_L_HZ - 1;
 447        assert((pclk_dbg_div + 1) * PCLK_DBG_L_HZ == LPLL_HZ &&
 448               pclk_dbg_div < 0x1f);
 449
 450        atclk_div = LPLL_HZ / ATCLK_CORE_L_HZ - 1;
 451        assert((atclk_div + 1) * ATCLK_CORE_L_HZ == LPLL_HZ &&
 452               atclk_div < 0x1f);
 453
 454        rk_clrsetreg(&cru->clksel_con[0],
 455                     ACLKM_CORE_L_DIV_CON_MASK | CLK_CORE_L_PLL_SEL_MASK |
 456                     CLK_CORE_L_DIV_MASK,
 457                     aclkm_div << ACLKM_CORE_L_DIV_CON_SHIFT |
 458                     CLK_CORE_L_PLL_SEL_ALPLL << CLK_CORE_L_PLL_SEL_SHIFT |
 459                     0 << CLK_CORE_L_DIV_SHIFT);
 460
 461        rk_clrsetreg(&cru->clksel_con[1],
 462                     PCLK_DBG_L_DIV_MASK | ATCLK_CORE_L_DIV_MASK,
 463                     pclk_dbg_div << PCLK_DBG_L_DIV_SHIFT |
 464                     atclk_div << ATCLK_CORE_L_DIV_SHIFT);
 465}
 466
 467void rk3399_configure_cpu_b(struct rockchip_cru *cru,
 468                            enum apll_b_frequencies apll_b_freq)
 469{
 470        u32 aclkm_div;
 471        u32 pclk_dbg_div;
 472        u32 atclk_div;
 473
 474        /* Setup cluster B */
 475        rkclk_set_pll(&cru->apll_b_con[0], apll_b_cfgs[apll_b_freq]);
 476
 477        aclkm_div = BPLL_HZ / ACLKM_CORE_B_HZ - 1;
 478        assert((aclkm_div + 1) * ACLKM_CORE_B_HZ == BPLL_HZ &&
 479               aclkm_div < 0x1f);
 480
 481        pclk_dbg_div = BPLL_HZ / PCLK_DBG_B_HZ - 1;
 482        assert((pclk_dbg_div + 1) * PCLK_DBG_B_HZ == BPLL_HZ &&
 483               pclk_dbg_div < 0x1f);
 484
 485        atclk_div = BPLL_HZ / ATCLK_CORE_B_HZ - 1;
 486        assert((atclk_div + 1) * ATCLK_CORE_B_HZ == BPLL_HZ &&
 487               atclk_div < 0x1f);
 488
 489        rk_clrsetreg(&cru->clksel_con[2],
 490                     ACLKM_CORE_B_DIV_CON_MASK | CLK_CORE_B_PLL_SEL_MASK |
 491                     CLK_CORE_B_DIV_MASK,
 492                     aclkm_div << ACLKM_CORE_B_DIV_CON_SHIFT |
 493                     CLK_CORE_B_PLL_SEL_ABPLL << CLK_CORE_B_PLL_SEL_SHIFT |
 494                     0 << CLK_CORE_B_DIV_SHIFT);
 495
 496        rk_clrsetreg(&cru->clksel_con[3],
 497                     PCLK_DBG_B_DIV_MASK | ATCLK_CORE_B_DIV_MASK,
 498                     pclk_dbg_div << PCLK_DBG_B_DIV_SHIFT |
 499                     atclk_div << ATCLK_CORE_B_DIV_SHIFT);
 500}
 501
 502#define I2C_CLK_REG_MASK(bus) \
 503        (I2C_DIV_CON_MASK << CLK_I2C ##bus## _DIV_CON_SHIFT | \
 504         CLK_I2C_PLL_SEL_MASK << CLK_I2C ##bus## _PLL_SEL_SHIFT)
 505
 506#define I2C_CLK_REG_VALUE(bus, clk_div) \
 507        ((clk_div - 1) << CLK_I2C ##bus## _DIV_CON_SHIFT | \
 508         CLK_I2C_PLL_SEL_GPLL << CLK_I2C ##bus## _PLL_SEL_SHIFT)
 509
 510#define I2C_CLK_DIV_VALUE(con, bus) \
 511        ((con >> CLK_I2C ##bus## _DIV_CON_SHIFT) & I2C_DIV_CON_MASK)
 512
 513#define I2C_PMUCLK_REG_MASK(bus) \
 514        (I2C_DIV_CON_MASK << CLK_I2C ##bus## _DIV_CON_SHIFT)
 515
 516#define I2C_PMUCLK_REG_VALUE(bus, clk_div) \
 517        ((clk_div - 1) << CLK_I2C ##bus## _DIV_CON_SHIFT)
 518
 519static ulong rk3399_i2c_get_clk(struct rockchip_cru *cru, ulong clk_id)
 520{
 521        u32 div, con;
 522
 523        switch (clk_id) {
 524        case SCLK_I2C1:
 525                con = readl(&cru->clksel_con[61]);
 526                div = I2C_CLK_DIV_VALUE(con, 1);
 527                break;
 528        case SCLK_I2C2:
 529                con = readl(&cru->clksel_con[62]);
 530                div = I2C_CLK_DIV_VALUE(con, 2);
 531                break;
 532        case SCLK_I2C3:
 533                con = readl(&cru->clksel_con[63]);
 534                div = I2C_CLK_DIV_VALUE(con, 3);
 535                break;
 536        case SCLK_I2C5:
 537                con = readl(&cru->clksel_con[61]);
 538                div = I2C_CLK_DIV_VALUE(con, 5);
 539                break;
 540        case SCLK_I2C6:
 541                con = readl(&cru->clksel_con[62]);
 542                div = I2C_CLK_DIV_VALUE(con, 6);
 543                break;
 544        case SCLK_I2C7:
 545                con = readl(&cru->clksel_con[63]);
 546                div = I2C_CLK_DIV_VALUE(con, 7);
 547                break;
 548        default:
 549                printf("do not support this i2c bus\n");
 550                return -EINVAL;
 551        }
 552
 553        return DIV_TO_RATE(GPLL_HZ, div);
 554}
 555
 556static ulong rk3399_i2c_set_clk(struct rockchip_cru *cru, ulong clk_id, uint hz)
 557{
 558        int src_clk_div;
 559
 560        /* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
 561        src_clk_div = GPLL_HZ / hz;
 562        assert(src_clk_div - 1 < 127);
 563
 564        switch (clk_id) {
 565        case SCLK_I2C1:
 566                rk_clrsetreg(&cru->clksel_con[61], I2C_CLK_REG_MASK(1),
 567                             I2C_CLK_REG_VALUE(1, src_clk_div));
 568                break;
 569        case SCLK_I2C2:
 570                rk_clrsetreg(&cru->clksel_con[62], I2C_CLK_REG_MASK(2),
 571                             I2C_CLK_REG_VALUE(2, src_clk_div));
 572                break;
 573        case SCLK_I2C3:
 574                rk_clrsetreg(&cru->clksel_con[63], I2C_CLK_REG_MASK(3),
 575                             I2C_CLK_REG_VALUE(3, src_clk_div));
 576                break;
 577        case SCLK_I2C5:
 578                rk_clrsetreg(&cru->clksel_con[61], I2C_CLK_REG_MASK(5),
 579                             I2C_CLK_REG_VALUE(5, src_clk_div));
 580                break;
 581        case SCLK_I2C6:
 582                rk_clrsetreg(&cru->clksel_con[62], I2C_CLK_REG_MASK(6),
 583                             I2C_CLK_REG_VALUE(6, src_clk_div));
 584                break;
 585        case SCLK_I2C7:
 586                rk_clrsetreg(&cru->clksel_con[63], I2C_CLK_REG_MASK(7),
 587                             I2C_CLK_REG_VALUE(7, src_clk_div));
 588                break;
 589        default:
 590                printf("do not support this i2c bus\n");
 591                return -EINVAL;
 592        }
 593
 594        return rk3399_i2c_get_clk(cru, clk_id);
 595}
 596
 597/*
 598 * RK3399 SPI clocks have a common divider-width (7 bits) and a single bit
 599 * to select either CPLL or GPLL as the clock-parent. The location within
 600 * the enclosing CLKSEL_CON (i.e. div_shift and sel_shift) are variable.
 601 */
 602
 603struct spi_clkreg {
 604        u8 reg;  /* CLKSEL_CON[reg] register in CRU */
 605        u8 div_shift;
 606        u8 sel_shift;
 607};
 608
 609/*
 610 * The entries are numbered relative to their offset from SCLK_SPI0.
 611 *
 612 * Note that SCLK_SPI3 (which is configured via PMUCRU and requires different
 613 * logic is not supported).
 614 */
 615static const struct spi_clkreg spi_clkregs[] = {
 616        [0] = { .reg = 59,
 617                .div_shift = CLK_SPI0_PLL_DIV_CON_SHIFT,
 618                .sel_shift = CLK_SPI0_PLL_SEL_SHIFT, },
 619        [1] = { .reg = 59,
 620                .div_shift = CLK_SPI1_PLL_DIV_CON_SHIFT,
 621                .sel_shift = CLK_SPI1_PLL_SEL_SHIFT, },
 622        [2] = { .reg = 60,
 623                .div_shift = CLK_SPI2_PLL_DIV_CON_SHIFT,
 624                .sel_shift = CLK_SPI2_PLL_SEL_SHIFT, },
 625        [3] = { .reg = 60,
 626                .div_shift = CLK_SPI4_PLL_DIV_CON_SHIFT,
 627                .sel_shift = CLK_SPI4_PLL_SEL_SHIFT, },
 628        [4] = { .reg = 58,
 629                .div_shift = CLK_SPI5_PLL_DIV_CON_SHIFT,
 630                .sel_shift = CLK_SPI5_PLL_SEL_SHIFT, },
 631};
 632
 633static ulong rk3399_spi_get_clk(struct rockchip_cru *cru, ulong clk_id)
 634{
 635        const struct spi_clkreg *spiclk = NULL;
 636        u32 div, val;
 637
 638        switch (clk_id) {
 639        case SCLK_SPI0 ... SCLK_SPI5:
 640                spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
 641                break;
 642
 643        default:
 644                pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
 645                return -EINVAL;
 646        }
 647
 648        val = readl(&cru->clksel_con[spiclk->reg]);
 649        div = bitfield_extract(val, spiclk->div_shift,
 650                               CLK_SPI_PLL_DIV_CON_WIDTH);
 651
 652        return DIV_TO_RATE(GPLL_HZ, div);
 653}
 654
 655static ulong rk3399_spi_set_clk(struct rockchip_cru *cru, ulong clk_id, uint hz)
 656{
 657        const struct spi_clkreg *spiclk = NULL;
 658        int src_clk_div;
 659
 660        src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
 661        assert(src_clk_div < 128);
 662
 663        switch (clk_id) {
 664        case SCLK_SPI1 ... SCLK_SPI5:
 665                spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
 666                break;
 667
 668        default:
 669                pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
 670                return -EINVAL;
 671        }
 672
 673        rk_clrsetreg(&cru->clksel_con[spiclk->reg],
 674                     ((CLK_SPI_PLL_DIV_CON_MASK << spiclk->div_shift) |
 675                       (CLK_SPI_PLL_SEL_GPLL << spiclk->sel_shift)),
 676                     ((src_clk_div << spiclk->div_shift) |
 677                      (CLK_SPI_PLL_SEL_GPLL << spiclk->sel_shift)));
 678
 679        return rk3399_spi_get_clk(cru, clk_id);
 680}
 681
 682static ulong rk3399_vop_set_clk(struct rockchip_cru *cru, ulong clk_id, u32 hz)
 683{
 684        struct pll_div vpll_config = {0};
 685        int aclk_vop = 198 * MHz;
 686        void *aclkreg_addr, *dclkreg_addr;
 687        u32 div;
 688
 689        switch (clk_id) {
 690        case DCLK_VOP0:
 691                aclkreg_addr = &cru->clksel_con[47];
 692                dclkreg_addr = &cru->clksel_con[49];
 693                break;
 694        case DCLK_VOP1:
 695                aclkreg_addr = &cru->clksel_con[48];
 696                dclkreg_addr = &cru->clksel_con[50];
 697                break;
 698        default:
 699                return -EINVAL;
 700        }
 701        /* vop aclk source clk: cpll */
 702        div = CPLL_HZ / aclk_vop;
 703        assert(div - 1 < 32);
 704
 705        rk_clrsetreg(aclkreg_addr,
 706                     ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
 707                     ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT |
 708                     (div - 1) << ACLK_VOP_DIV_CON_SHIFT);
 709
 710        /* vop dclk source from vpll, and equals to vpll(means div == 1) */
 711        if (pll_para_config(hz, &vpll_config))
 712                return -1;
 713
 714        rkclk_set_pll(&cru->vpll_con[0], &vpll_config);
 715
 716        rk_clrsetreg(dclkreg_addr,
 717                     DCLK_VOP_DCLK_SEL_MASK | DCLK_VOP_PLL_SEL_MASK |
 718                     DCLK_VOP_DIV_CON_MASK,
 719                     DCLK_VOP_DCLK_SEL_DIVOUT << DCLK_VOP_DCLK_SEL_SHIFT |
 720                     DCLK_VOP_PLL_SEL_VPLL << DCLK_VOP_PLL_SEL_SHIFT |
 721                     (1 - 1) << DCLK_VOP_DIV_CON_SHIFT);
 722
 723        return hz;
 724}
 725
 726static ulong rk3399_mmc_get_clk(struct rockchip_cru *cru, uint clk_id)
 727{
 728        u32 div, con;
 729
 730        switch (clk_id) {
 731        case HCLK_SDIO:
 732        case SCLK_SDIO:
 733                con = readl(&cru->clksel_con[15]);
 734                /* dwmmc controller have internal div 2 */
 735                div = 2;
 736                break;
 737        case HCLK_SDMMC:
 738        case SCLK_SDMMC:
 739                con = readl(&cru->clksel_con[16]);
 740                /* dwmmc controller have internal div 2 */
 741                div = 2;
 742                break;
 743        case SCLK_EMMC:
 744                con = readl(&cru->clksel_con[22]);
 745                div = 1;
 746                break;
 747        default:
 748                return -EINVAL;
 749        }
 750
 751        div *= (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT;
 752        if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT
 753                        == CLK_EMMC_PLL_SEL_24M)
 754                return DIV_TO_RATE(OSC_HZ, div);
 755        else
 756                return DIV_TO_RATE(GPLL_HZ, div);
 757}
 758
 759static void rk3399_dwmmc_set_clk(struct rockchip_cru *cru,
 760                                 unsigned int con, ulong set_rate)
 761{
 762        /* Select clk_sdmmc source from GPLL by default */
 763        /* mmc clock defaulg div 2 internal, provide double in cru */
 764        int src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
 765
 766        if (src_clk_div > 128) {
 767                /* use 24MHz source for 400KHz clock */
 768                src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
 769                assert(src_clk_div - 1 < 128);
 770                rk_clrsetreg(&cru->clksel_con[con],
 771                             CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
 772                             CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
 773                             (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
 774        } else {
 775                rk_clrsetreg(&cru->clksel_con[con],
 776                             CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
 777                             CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
 778                             (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
 779        }
 780}
 781
 782static ulong rk3399_mmc_set_clk(struct rockchip_cru *cru,
 783                                ulong clk_id, ulong set_rate)
 784{
 785        switch (clk_id) {
 786        case HCLK_SDIO:
 787        case SCLK_SDIO:
 788                rk3399_dwmmc_set_clk(cru, 15, set_rate);
 789                break;
 790        case HCLK_SDMMC:
 791        case SCLK_SDMMC:
 792                rk3399_dwmmc_set_clk(cru, 16, set_rate);
 793                break;
 794        case SCLK_EMMC: {
 795                int aclk_emmc = 198 * MHz;
 796                /* Select aclk_emmc source from GPLL */
 797                int src_clk_div = DIV_ROUND_UP(GPLL_HZ, aclk_emmc);
 798
 799                assert(src_clk_div - 1 < 32);
 800
 801                rk_clrsetreg(&cru->clksel_con[21],
 802                             ACLK_EMMC_PLL_SEL_MASK | ACLK_EMMC_DIV_CON_MASK,
 803                             ACLK_EMMC_PLL_SEL_GPLL << ACLK_EMMC_PLL_SEL_SHIFT |
 804                             (src_clk_div - 1) << ACLK_EMMC_DIV_CON_SHIFT);
 805
 806                /* Select clk_emmc source from GPLL too */
 807                src_clk_div = DIV_ROUND_UP(GPLL_HZ, set_rate);
 808                assert(src_clk_div - 1 < 128);
 809
 810                rk_clrsetreg(&cru->clksel_con[22],
 811                             CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
 812                             CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
 813                             (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
 814                break;
 815        }
 816        default:
 817                return -EINVAL;
 818        }
 819        return rk3399_mmc_get_clk(cru, clk_id);
 820}
 821
 822static ulong rk3399_gmac_set_clk(struct rockchip_cru *cru, ulong rate)
 823{
 824        ulong ret;
 825
 826        /*
 827         * The RGMII CLK can be derived either from an external "clkin"
 828         * or can be generated from internally by a divider from SCLK_MAC.
 829         */
 830        if (readl(&cru->clksel_con[19]) & BIT(4)) {
 831                /* An external clock will always generate the right rate... */
 832                ret = rate;
 833        } else {
 834                /*
 835                 * No platform uses an internal clock to date.
 836                 * Implement this once it becomes necessary and print an error
 837                 * if someone tries to use it (while it remains unimplemented).
 838                 */
 839                pr_err("%s: internal clock is UNIMPLEMENTED\n", __func__);
 840                ret = 0;
 841        }
 842
 843        return ret;
 844}
 845
 846#define PMUSGRF_DDR_RGN_CON16 0xff330040
 847static ulong rk3399_ddr_set_clk(struct rockchip_cru *cru,
 848                                ulong set_rate)
 849{
 850        struct pll_div dpll_cfg;
 851
 852        /*  IC ECO bug, need to set this register */
 853        writel(0xc000c000, PMUSGRF_DDR_RGN_CON16);
 854
 855        /*  clk_ddrc == DPLL = 24MHz / refdiv * fbdiv / postdiv1 / postdiv2 */
 856        switch (set_rate) {
 857        case 50 * MHz:
 858                dpll_cfg = (struct pll_div)
 859                {.refdiv = 2, .fbdiv = 75, .postdiv1 = 3, .postdiv2 = 6};
 860                break;
 861        case 200 * MHz:
 862                dpll_cfg = (struct pll_div)
 863                {.refdiv = 1, .fbdiv = 50, .postdiv1 = 6, .postdiv2 = 1};
 864                break;
 865        case 300 * MHz:
 866                dpll_cfg = (struct pll_div)
 867                {.refdiv = 2, .fbdiv = 100, .postdiv1 = 4, .postdiv2 = 1};
 868                break;
 869        case 400 * MHz:
 870                dpll_cfg = (struct pll_div)
 871                {.refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 1};
 872                break;
 873        case 666 * MHz:
 874                dpll_cfg = (struct pll_div)
 875                {.refdiv = 2, .fbdiv = 111, .postdiv1 = 2, .postdiv2 = 1};
 876                break;
 877        case 800 * MHz:
 878                dpll_cfg = (struct pll_div)
 879                {.refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1};
 880                break;
 881        case 933 * MHz:
 882                dpll_cfg = (struct pll_div)
 883                {.refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1};
 884                break;
 885        default:
 886                pr_err("Unsupported SDRAM frequency!,%ld\n", set_rate);
 887        }
 888        rkclk_set_pll(&cru->dpll_con[0], &dpll_cfg);
 889
 890        return set_rate;
 891}
 892
 893static ulong rk3399_alive_get_clk(struct rockchip_cru *cru)
 894{
 895        u32 div, val;
 896
 897        val = readl(&cru->clksel_con[57]);
 898        div = (val & PCLK_ALIVE_DIV_CON_MASK) >>
 899               PCLK_ALIVE_DIV_CON_SHIFT;
 900
 901        return DIV_TO_RATE(GPLL_HZ, div);
 902}
 903
 904static ulong rk3399_saradc_get_clk(struct rockchip_cru *cru)
 905{
 906        u32 div, val;
 907
 908        val = readl(&cru->clksel_con[26]);
 909        div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
 910                               CLK_SARADC_DIV_CON_WIDTH);
 911
 912        return DIV_TO_RATE(OSC_HZ, div);
 913}
 914
 915static ulong rk3399_saradc_set_clk(struct rockchip_cru *cru, uint hz)
 916{
 917        int src_clk_div;
 918
 919        src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
 920        assert(src_clk_div < 128);
 921
 922        rk_clrsetreg(&cru->clksel_con[26],
 923                     CLK_SARADC_DIV_CON_MASK,
 924                     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
 925
 926        return rk3399_saradc_get_clk(cru);
 927}
 928
 929static ulong rk3399_clk_get_rate(struct clk *clk)
 930{
 931        struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
 932        ulong rate = 0;
 933
 934        switch (clk->id) {
 935        case 0 ... 63:
 936                return 0;
 937        case HCLK_SDIO:
 938        case SCLK_SDIO:
 939        case HCLK_SDMMC:
 940        case SCLK_SDMMC:
 941        case SCLK_EMMC:
 942                rate = rk3399_mmc_get_clk(priv->cru, clk->id);
 943                break;
 944        case SCLK_I2C1:
 945        case SCLK_I2C2:
 946        case SCLK_I2C3:
 947        case SCLK_I2C5:
 948        case SCLK_I2C6:
 949        case SCLK_I2C7:
 950                rate = rk3399_i2c_get_clk(priv->cru, clk->id);
 951                break;
 952        case SCLK_SPI0...SCLK_SPI5:
 953                rate = rk3399_spi_get_clk(priv->cru, clk->id);
 954                break;
 955        case SCLK_UART0:
 956        case SCLK_UART1:
 957        case SCLK_UART2:
 958        case SCLK_UART3:
 959                return 24000000;
 960        case PCLK_HDMI_CTRL:
 961                break;
 962        case DCLK_VOP0:
 963        case DCLK_VOP1:
 964                break;
 965        case PCLK_EFUSE1024NS:
 966                break;
 967        case SCLK_SARADC:
 968                rate = rk3399_saradc_get_clk(priv->cru);
 969                break;
 970        case ACLK_VIO:
 971        case ACLK_HDCP:
 972        case ACLK_GIC_PRE:
 973        case PCLK_DDR:
 974                break;
 975        case PCLK_ALIVE:
 976        case PCLK_WDT:
 977                rate = rk3399_alive_get_clk(priv->cru);
 978                break;
 979        default:
 980                log_debug("Unknown clock %lu\n", clk->id);
 981                return -ENOENT;
 982        }
 983
 984        return rate;
 985}
 986
 987static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
 988{
 989        struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
 990        ulong ret = 0;
 991
 992        switch (clk->id) {
 993        case 0 ... 63:
 994                return 0;
 995
 996        case ACLK_PERIHP:
 997        case HCLK_PERIHP:
 998        case PCLK_PERIHP:
 999                return 0;
1000
1001        case ACLK_PERILP0:
1002        case HCLK_PERILP0:
1003        case PCLK_PERILP0:
1004                return 0;
1005
1006        case ACLK_CCI:
1007                return 0;
1008
1009        case HCLK_PERILP1:
1010        case PCLK_PERILP1:
1011                return 0;
1012
1013        case HCLK_SDIO:
1014        case SCLK_SDIO:
1015        case HCLK_SDMMC:
1016        case SCLK_SDMMC:
1017        case SCLK_EMMC:
1018                ret = rk3399_mmc_set_clk(priv->cru, clk->id, rate);
1019                break;
1020        case SCLK_MAC:
1021                ret = rk3399_gmac_set_clk(priv->cru, rate);
1022                break;
1023        case SCLK_I2C1:
1024        case SCLK_I2C2:
1025        case SCLK_I2C3:
1026        case SCLK_I2C5:
1027        case SCLK_I2C6:
1028        case SCLK_I2C7:
1029                ret = rk3399_i2c_set_clk(priv->cru, clk->id, rate);
1030                break;
1031        case SCLK_SPI0...SCLK_SPI5:
1032                ret = rk3399_spi_set_clk(priv->cru, clk->id, rate);
1033                break;
1034        case PCLK_HDMI_CTRL:
1035        case PCLK_VIO_GRF:
1036                /* the PCLK gates for video are enabled by default */
1037                break;
1038        case DCLK_VOP0:
1039        case DCLK_VOP1:
1040                ret = rk3399_vop_set_clk(priv->cru, clk->id, rate);
1041                break;
1042        case ACLK_VOP1:
1043        case HCLK_VOP1:
1044        case HCLK_SD:
1045        case SCLK_UPHY0_TCPDCORE:
1046        case SCLK_UPHY1_TCPDCORE:
1047                /**
1048                 * assigned-clocks handling won't require for vopl, so
1049                 * return 0 to satisfy clk_set_defaults during device probe.
1050                 */
1051                return 0;
1052        case SCLK_DDRCLK:
1053                ret = rk3399_ddr_set_clk(priv->cru, rate);
1054                break;
1055        case PCLK_EFUSE1024NS:
1056                break;
1057        case SCLK_SARADC:
1058                ret = rk3399_saradc_set_clk(priv->cru, rate);
1059                break;
1060        case ACLK_VIO:
1061        case ACLK_HDCP:
1062        case ACLK_GIC_PRE:
1063        case PCLK_DDR:
1064                return 0;
1065        default:
1066                log_debug("Unknown clock %lu\n", clk->id);
1067                return -ENOENT;
1068        }
1069
1070        return ret;
1071}
1072
1073static int __maybe_unused rk3399_gmac_set_parent(struct clk *clk,
1074                                                 struct clk *parent)
1075{
1076        struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
1077        const char *clock_output_name;
1078        int ret;
1079
1080        /*
1081         * If the requested parent is in the same clock-controller and
1082         * the id is SCLK_MAC ("clk_gmac"), switch to the internal clock.
1083         */
1084        if (parent->dev == clk->dev && parent->id == SCLK_MAC) {
1085                debug("%s: switching RGMII to SCLK_MAC\n", __func__);
1086                rk_clrreg(&priv->cru->clksel_con[19], BIT(4));
1087                return 0;
1088        }
1089
1090        /*
1091         * Otherwise, we need to check the clock-output-names of the
1092         * requested parent to see if the requested id is "clkin_gmac".
1093         */
1094        ret = dev_read_string_index(parent->dev, "clock-output-names",
1095                                    parent->id, &clock_output_name);
1096        if (ret < 0)
1097                return -ENODATA;
1098
1099        /* If this is "clkin_gmac", switch to the external clock input */
1100        if (!strcmp(clock_output_name, "clkin_gmac")) {
1101                debug("%s: switching RGMII to CLKIN\n", __func__);
1102                rk_setreg(&priv->cru->clksel_con[19], BIT(4));
1103                return 0;
1104        }
1105
1106        return -EINVAL;
1107}
1108
1109static int __maybe_unused rk3399_clk_set_parent(struct clk *clk,
1110                                                struct clk *parent)
1111{
1112        switch (clk->id) {
1113        case SCLK_RMII_SRC:
1114                return rk3399_gmac_set_parent(clk, parent);
1115        }
1116
1117        debug("%s: unsupported clk %ld\n", __func__, clk->id);
1118        return -ENOENT;
1119}
1120
1121static int rk3399_clk_enable(struct clk *clk)
1122{
1123        struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
1124
1125        switch (clk->id) {
1126        case SCLK_MAC:
1127                rk_clrreg(&priv->cru->clkgate_con[5], BIT(5));
1128                break;
1129        case SCLK_MAC_RX:
1130                rk_clrreg(&priv->cru->clkgate_con[5], BIT(8));
1131                break;
1132        case SCLK_MAC_TX:
1133                rk_clrreg(&priv->cru->clkgate_con[5], BIT(9));
1134                break;
1135        case SCLK_MACREF:
1136                rk_clrreg(&priv->cru->clkgate_con[5], BIT(7));
1137                break;
1138        case SCLK_MACREF_OUT:
1139                rk_clrreg(&priv->cru->clkgate_con[5], BIT(6));
1140                break;
1141        case SCLK_USB2PHY0_REF:
1142                rk_clrreg(&priv->cru->clkgate_con[6], BIT(5));
1143                break;
1144        case SCLK_USB2PHY1_REF:
1145                rk_clrreg(&priv->cru->clkgate_con[6], BIT(6));
1146                break;
1147        case ACLK_GMAC:
1148                rk_clrreg(&priv->cru->clkgate_con[32], BIT(0));
1149                break;
1150        case PCLK_GMAC:
1151                rk_clrreg(&priv->cru->clkgate_con[32], BIT(2));
1152                break;
1153        case SCLK_USB3OTG0_REF:
1154                rk_clrreg(&priv->cru->clkgate_con[12], BIT(1));
1155                break;
1156        case SCLK_USB3OTG1_REF:
1157                rk_clrreg(&priv->cru->clkgate_con[12], BIT(2));
1158                break;
1159        case SCLK_USB3OTG0_SUSPEND:
1160                rk_clrreg(&priv->cru->clkgate_con[12], BIT(3));
1161                break;
1162        case SCLK_USB3OTG1_SUSPEND:
1163                rk_clrreg(&priv->cru->clkgate_con[12], BIT(4));
1164                break;
1165        case ACLK_USB3OTG0:
1166                rk_clrreg(&priv->cru->clkgate_con[30], BIT(1));
1167                break;
1168        case ACLK_USB3OTG1:
1169                rk_clrreg(&priv->cru->clkgate_con[30], BIT(2));
1170                break;
1171        case ACLK_USB3_RKSOC_AXI_PERF:
1172                rk_clrreg(&priv->cru->clkgate_con[30], BIT(3));
1173                break;
1174        case ACLK_USB3:
1175                rk_clrreg(&priv->cru->clkgate_con[12], BIT(0));
1176                break;
1177        case ACLK_USB3_GRF:
1178                rk_clrreg(&priv->cru->clkgate_con[30], BIT(4));
1179                break;
1180        case HCLK_HOST0:
1181                rk_clrreg(&priv->cru->clksel_con[20], BIT(5));
1182                break;
1183        case HCLK_HOST0_ARB:
1184                rk_clrreg(&priv->cru->clksel_con[20], BIT(6));
1185                break;
1186        case HCLK_HOST1:
1187                rk_clrreg(&priv->cru->clksel_con[20], BIT(7));
1188                break;
1189        case HCLK_HOST1_ARB:
1190                rk_clrreg(&priv->cru->clksel_con[20], BIT(8));
1191                break;
1192        case SCLK_UPHY0_TCPDPHY_REF:
1193                rk_clrreg(&priv->cru->clkgate_con[13], BIT(4));
1194                break;
1195        case SCLK_UPHY0_TCPDCORE:
1196                rk_clrreg(&priv->cru->clkgate_con[13], BIT(5));
1197                break;
1198        case SCLK_UPHY1_TCPDPHY_REF:
1199                rk_clrreg(&priv->cru->clkgate_con[13], BIT(6));
1200                break;
1201        case SCLK_UPHY1_TCPDCORE:
1202                rk_clrreg(&priv->cru->clkgate_con[13], BIT(7));
1203                break;
1204        case SCLK_PCIEPHY_REF:
1205                rk_clrreg(&priv->cru->clksel_con[18], BIT(10));
1206                break;
1207        default:
1208                debug("%s: unsupported clk %ld\n", __func__, clk->id);
1209                return -ENOENT;
1210        }
1211
1212        return 0;
1213}
1214
1215static int rk3399_clk_disable(struct clk *clk)
1216{
1217        struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
1218
1219        switch (clk->id) {
1220        case SCLK_MAC:
1221                rk_setreg(&priv->cru->clkgate_con[5], BIT(5));
1222                break;
1223        case SCLK_MAC_RX:
1224                rk_setreg(&priv->cru->clkgate_con[5], BIT(8));
1225                break;
1226        case SCLK_MAC_TX:
1227                rk_setreg(&priv->cru->clkgate_con[5], BIT(9));
1228                break;
1229        case SCLK_MACREF:
1230                rk_setreg(&priv->cru->clkgate_con[5], BIT(7));
1231                break;
1232        case SCLK_MACREF_OUT:
1233                rk_setreg(&priv->cru->clkgate_con[5], BIT(6));
1234                break;
1235        case SCLK_USB2PHY0_REF:
1236                rk_setreg(&priv->cru->clkgate_con[6], BIT(5));
1237                break;
1238        case SCLK_USB2PHY1_REF:
1239                rk_setreg(&priv->cru->clkgate_con[6], BIT(6));
1240                break;
1241        case ACLK_GMAC:
1242                rk_setreg(&priv->cru->clkgate_con[32], BIT(0));
1243                break;
1244        case PCLK_GMAC:
1245                rk_setreg(&priv->cru->clkgate_con[32], BIT(2));
1246                break;
1247        case SCLK_USB3OTG0_REF:
1248                rk_setreg(&priv->cru->clkgate_con[12], BIT(1));
1249                break;
1250        case SCLK_USB3OTG1_REF:
1251                rk_setreg(&priv->cru->clkgate_con[12], BIT(2));
1252                break;
1253        case SCLK_USB3OTG0_SUSPEND:
1254                rk_setreg(&priv->cru->clkgate_con[12], BIT(3));
1255                break;
1256        case SCLK_USB3OTG1_SUSPEND:
1257                rk_setreg(&priv->cru->clkgate_con[12], BIT(4));
1258                break;
1259        case ACLK_USB3OTG0:
1260                rk_setreg(&priv->cru->clkgate_con[30], BIT(1));
1261                break;
1262        case ACLK_USB3OTG1:
1263                rk_setreg(&priv->cru->clkgate_con[30], BIT(2));
1264                break;
1265        case ACLK_USB3_RKSOC_AXI_PERF:
1266                rk_setreg(&priv->cru->clkgate_con[30], BIT(3));
1267                break;
1268        case ACLK_USB3:
1269                rk_setreg(&priv->cru->clkgate_con[12], BIT(0));
1270                break;
1271        case ACLK_USB3_GRF:
1272                rk_setreg(&priv->cru->clkgate_con[30], BIT(4));
1273                break;
1274        case HCLK_HOST0:
1275                rk_setreg(&priv->cru->clksel_con[20], BIT(5));
1276                break;
1277        case HCLK_HOST0_ARB:
1278                rk_setreg(&priv->cru->clksel_con[20], BIT(6));
1279                break;
1280        case HCLK_HOST1:
1281                rk_setreg(&priv->cru->clksel_con[20], BIT(7));
1282                break;
1283        case HCLK_HOST1_ARB:
1284                rk_setreg(&priv->cru->clksel_con[20], BIT(8));
1285                break;
1286        case SCLK_UPHY0_TCPDPHY_REF:
1287                rk_setreg(&priv->cru->clkgate_con[13], BIT(4));
1288                break;
1289        case SCLK_UPHY0_TCPDCORE:
1290                rk_setreg(&priv->cru->clkgate_con[13], BIT(5));
1291                break;
1292        case SCLK_UPHY1_TCPDPHY_REF:
1293                rk_setreg(&priv->cru->clkgate_con[13], BIT(6));
1294                break;
1295        case SCLK_UPHY1_TCPDCORE:
1296                rk_setreg(&priv->cru->clkgate_con[13], BIT(7));
1297                break;
1298        case SCLK_PCIEPHY_REF:
1299                rk_clrreg(&priv->cru->clksel_con[18], BIT(10));
1300                break;
1301        default:
1302                debug("%s: unsupported clk %ld\n", __func__, clk->id);
1303                return -ENOENT;
1304        }
1305
1306        return 0;
1307}
1308
1309static struct clk_ops rk3399_clk_ops = {
1310        .get_rate = rk3399_clk_get_rate,
1311        .set_rate = rk3399_clk_set_rate,
1312#if CONFIG_IS_ENABLED(OF_REAL)
1313        .set_parent = rk3399_clk_set_parent,
1314#endif
1315        .enable = rk3399_clk_enable,
1316        .disable = rk3399_clk_disable,
1317};
1318
1319static void rkclk_init(struct rockchip_cru *cru)
1320{
1321        u32 aclk_div;
1322        u32 hclk_div;
1323        u32 pclk_div;
1324
1325        rk3399_configure_cpu_l(cru, APLL_L_600_MHZ);
1326        rk3399_configure_cpu_b(cru, APLL_B_600_MHZ);
1327        /*
1328         * some cru registers changed by bootrom, we'd better reset them to
1329         * reset/default values described in TRM to avoid confusion in kernel.
1330         * Please consider these three lines as a fix of bootrom bug.
1331         */
1332        rk_clrsetreg(&cru->clksel_con[12], 0xffff, 0x4101);
1333        rk_clrsetreg(&cru->clksel_con[19], 0xffff, 0x033f);
1334        rk_clrsetreg(&cru->clksel_con[56], 0x0003, 0x0003);
1335
1336        /* configure gpll cpll */
1337        rkclk_set_pll(&cru->gpll_con[0], &gpll_init_cfg);
1338        rkclk_set_pll(&cru->cpll_con[0], &cpll_init_cfg);
1339
1340        /* configure perihp aclk, hclk, pclk */
1341        aclk_div = GPLL_HZ / PERIHP_ACLK_HZ - 1;
1342        assert((aclk_div + 1) * PERIHP_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
1343
1344        hclk_div = PERIHP_ACLK_HZ / PERIHP_HCLK_HZ - 1;
1345        assert((hclk_div + 1) * PERIHP_HCLK_HZ ==
1346               PERIHP_ACLK_HZ && (hclk_div < 0x4));
1347
1348        pclk_div = PERIHP_ACLK_HZ / PERIHP_PCLK_HZ - 1;
1349        assert((pclk_div + 1) * PERIHP_PCLK_HZ ==
1350               PERIHP_ACLK_HZ && (pclk_div < 0x7));
1351
1352        rk_clrsetreg(&cru->clksel_con[14],
1353                     PCLK_PERIHP_DIV_CON_MASK | HCLK_PERIHP_DIV_CON_MASK |
1354                     ACLK_PERIHP_PLL_SEL_MASK | ACLK_PERIHP_DIV_CON_MASK,
1355                     pclk_div << PCLK_PERIHP_DIV_CON_SHIFT |
1356                     hclk_div << HCLK_PERIHP_DIV_CON_SHIFT |
1357                     ACLK_PERIHP_PLL_SEL_GPLL << ACLK_PERIHP_PLL_SEL_SHIFT |
1358                     aclk_div << ACLK_PERIHP_DIV_CON_SHIFT);
1359
1360        /* configure perilp0 aclk, hclk, pclk */
1361        aclk_div = GPLL_HZ / PERILP0_ACLK_HZ - 1;
1362        assert((aclk_div + 1) * PERILP0_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
1363
1364        hclk_div = PERILP0_ACLK_HZ / PERILP0_HCLK_HZ - 1;
1365        assert((hclk_div + 1) * PERILP0_HCLK_HZ ==
1366               PERILP0_ACLK_HZ && (hclk_div < 0x4));
1367
1368        pclk_div = PERILP0_ACLK_HZ / PERILP0_PCLK_HZ - 1;
1369        assert((pclk_div + 1) * PERILP0_PCLK_HZ ==
1370               PERILP0_ACLK_HZ && (pclk_div < 0x7));
1371
1372        rk_clrsetreg(&cru->clksel_con[23],
1373                     PCLK_PERILP0_DIV_CON_MASK | HCLK_PERILP0_DIV_CON_MASK |
1374                     ACLK_PERILP0_PLL_SEL_MASK | ACLK_PERILP0_DIV_CON_MASK,
1375                     pclk_div << PCLK_PERILP0_DIV_CON_SHIFT |
1376                     hclk_div << HCLK_PERILP0_DIV_CON_SHIFT |
1377                     ACLK_PERILP0_PLL_SEL_GPLL << ACLK_PERILP0_PLL_SEL_SHIFT |
1378                     aclk_div << ACLK_PERILP0_DIV_CON_SHIFT);
1379
1380        /* perilp1 hclk select gpll as source */
1381        hclk_div = GPLL_HZ / PERILP1_HCLK_HZ - 1;
1382        assert((hclk_div + 1) * PERILP1_HCLK_HZ ==
1383               GPLL_HZ && (hclk_div < 0x1f));
1384
1385        pclk_div = PERILP1_HCLK_HZ / PERILP1_HCLK_HZ - 1;
1386        assert((pclk_div + 1) * PERILP1_HCLK_HZ ==
1387               PERILP1_HCLK_HZ && (hclk_div < 0x7));
1388
1389        rk_clrsetreg(&cru->clksel_con[25],
1390                     PCLK_PERILP1_DIV_CON_MASK | HCLK_PERILP1_DIV_CON_MASK |
1391                     HCLK_PERILP1_PLL_SEL_MASK,
1392                     pclk_div << PCLK_PERILP1_DIV_CON_SHIFT |
1393                     hclk_div << HCLK_PERILP1_DIV_CON_SHIFT |
1394                     HCLK_PERILP1_PLL_SEL_GPLL << HCLK_PERILP1_PLL_SEL_SHIFT);
1395}
1396
1397static int rk3399_clk_probe(struct udevice *dev)
1398{
1399        struct rk3399_clk_priv *priv = dev_get_priv(dev);
1400        bool init_clocks = false;
1401
1402#if CONFIG_IS_ENABLED(OF_PLATDATA)
1403        struct rk3399_clk_plat *plat = dev_get_plat(dev);
1404
1405        priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
1406#endif
1407
1408#if defined(CONFIG_SPL_BUILD)
1409        init_clocks = true;
1410#elif CONFIG_IS_ENABLED(HANDOFF)
1411        if (!(gd->flags & GD_FLG_RELOC)) {
1412                if (!(gd->spl_handoff))
1413                        init_clocks = true;
1414        }
1415#endif
1416
1417        if (init_clocks)
1418                rkclk_init(priv->cru);
1419
1420        return 0;
1421}
1422
1423static int rk3399_clk_of_to_plat(struct udevice *dev)
1424{
1425        if (CONFIG_IS_ENABLED(OF_REAL)) {
1426                struct rk3399_clk_priv *priv = dev_get_priv(dev);
1427
1428                priv->cru = dev_read_addr_ptr(dev);
1429        }
1430
1431        return 0;
1432}
1433
1434static int rk3399_clk_bind(struct udevice *dev)
1435{
1436        int ret;
1437        struct udevice *sys_child;
1438        struct sysreset_reg *priv;
1439
1440        /* The reset driver does not have a device node, so bind it here */
1441        ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1442                                 &sys_child);
1443        if (ret) {
1444                debug("Warning: No sysreset driver: ret=%d\n", ret);
1445        } else {
1446                priv = malloc(sizeof(struct sysreset_reg));
1447                priv->glb_srst_fst_value = offsetof(struct rockchip_cru,
1448                                                    glb_srst_fst_value);
1449                priv->glb_srst_snd_value = offsetof(struct rockchip_cru,
1450                                                    glb_srst_snd_value);
1451                dev_set_priv(sys_child, priv);
1452        }
1453
1454#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
1455        ret = offsetof(struct rockchip_cru, softrst_con[0]);
1456        ret = rockchip_reset_bind(dev, ret, 21);
1457        if (ret)
1458                debug("Warning: software reset driver bind faile\n");
1459#endif
1460
1461        return 0;
1462}
1463
1464static const struct udevice_id rk3399_clk_ids[] = {
1465        { .compatible = "rockchip,rk3399-cru" },
1466        { }
1467};
1468
1469U_BOOT_DRIVER(clk_rk3399) = {
1470        .name           = "rockchip_rk3399_cru",
1471        .id             = UCLASS_CLK,
1472        .of_match       = rk3399_clk_ids,
1473        .priv_auto      = sizeof(struct rk3399_clk_priv),
1474        .of_to_plat = rk3399_clk_of_to_plat,
1475        .ops            = &rk3399_clk_ops,
1476        .bind           = rk3399_clk_bind,
1477        .probe          = rk3399_clk_probe,
1478#if CONFIG_IS_ENABLED(OF_PLATDATA)
1479        .plat_auto      = sizeof(struct rk3399_clk_plat),
1480#endif
1481};
1482
1483static ulong rk3399_i2c_get_pmuclk(struct rk3399_pmucru *pmucru, ulong clk_id)
1484{
1485        u32 div, con;
1486
1487        switch (clk_id) {
1488        case SCLK_I2C0_PMU:
1489                con = readl(&pmucru->pmucru_clksel[2]);
1490                div = I2C_CLK_DIV_VALUE(con, 0);
1491                break;
1492        case SCLK_I2C4_PMU:
1493                con = readl(&pmucru->pmucru_clksel[3]);
1494                div = I2C_CLK_DIV_VALUE(con, 4);
1495                break;
1496        case SCLK_I2C8_PMU:
1497                con = readl(&pmucru->pmucru_clksel[2]);
1498                div = I2C_CLK_DIV_VALUE(con, 8);
1499                break;
1500        default:
1501                printf("do not support this i2c bus\n");
1502                return -EINVAL;
1503        }
1504
1505        return DIV_TO_RATE(PPLL_HZ, div);
1506}
1507
1508static ulong rk3399_i2c_set_pmuclk(struct rk3399_pmucru *pmucru, ulong clk_id,
1509                                   uint hz)
1510{
1511        int src_clk_div;
1512
1513        src_clk_div = PPLL_HZ / hz;
1514        assert(src_clk_div - 1 < 127);
1515
1516        switch (clk_id) {
1517        case SCLK_I2C0_PMU:
1518                rk_clrsetreg(&pmucru->pmucru_clksel[2], I2C_PMUCLK_REG_MASK(0),
1519                             I2C_PMUCLK_REG_VALUE(0, src_clk_div));
1520                break;
1521        case SCLK_I2C4_PMU:
1522                rk_clrsetreg(&pmucru->pmucru_clksel[3], I2C_PMUCLK_REG_MASK(4),
1523                             I2C_PMUCLK_REG_VALUE(4, src_clk_div));
1524                break;
1525        case SCLK_I2C8_PMU:
1526                rk_clrsetreg(&pmucru->pmucru_clksel[2], I2C_PMUCLK_REG_MASK(8),
1527                             I2C_PMUCLK_REG_VALUE(8, src_clk_div));
1528                break;
1529        default:
1530                printf("do not support this i2c bus\n");
1531                return -EINVAL;
1532        }
1533
1534        return DIV_TO_RATE(PPLL_HZ, src_clk_div);
1535}
1536
1537static ulong rk3399_pwm_get_clk(struct rk3399_pmucru *pmucru)
1538{
1539        u32 div, con;
1540
1541        /* PWM closk rate is same as pclk_pmu */
1542        con = readl(&pmucru->pmucru_clksel[0]);
1543        div = con & PMU_PCLK_DIV_CON_MASK;
1544
1545        return DIV_TO_RATE(PPLL_HZ, div);
1546}
1547
1548static ulong rk3399_pmuclk_get_rate(struct clk *clk)
1549{
1550        struct rk3399_pmuclk_priv *priv = dev_get_priv(clk->dev);
1551        ulong rate = 0;
1552
1553        switch (clk->id) {
1554        case PLL_PPLL:
1555                return PPLL_HZ;
1556        case PCLK_RKPWM_PMU:
1557        case PCLK_WDT_M0_PMU:
1558                rate = rk3399_pwm_get_clk(priv->pmucru);
1559                break;
1560        case SCLK_I2C0_PMU:
1561        case SCLK_I2C4_PMU:
1562        case SCLK_I2C8_PMU:
1563                rate = rk3399_i2c_get_pmuclk(priv->pmucru, clk->id);
1564                break;
1565        default:
1566                return -ENOENT;
1567        }
1568
1569        return rate;
1570}
1571
1572static ulong rk3399_pmuclk_set_rate(struct clk *clk, ulong rate)
1573{
1574        struct rk3399_pmuclk_priv *priv = dev_get_priv(clk->dev);
1575        ulong ret = 0;
1576
1577        switch (clk->id) {
1578        case PLL_PPLL:
1579                /*
1580                 * This has already been set up and we don't want/need
1581                 * to change it here.  Accept the request though, as the
1582                 * device-tree has this in an 'assigned-clocks' list.
1583                 */
1584                return PPLL_HZ;
1585        case SCLK_I2C0_PMU:
1586        case SCLK_I2C4_PMU:
1587        case SCLK_I2C8_PMU:
1588                ret = rk3399_i2c_set_pmuclk(priv->pmucru, clk->id, rate);
1589                break;
1590        default:
1591                return -ENOENT;
1592        }
1593
1594        return ret;
1595}
1596
1597static struct clk_ops rk3399_pmuclk_ops = {
1598        .get_rate = rk3399_pmuclk_get_rate,
1599        .set_rate = rk3399_pmuclk_set_rate,
1600};
1601
1602#ifndef CONFIG_SPL_BUILD
1603static void pmuclk_init(struct rk3399_pmucru *pmucru)
1604{
1605        u32 pclk_div;
1606
1607        /*  configure pmu pll(ppll) */
1608        rkclk_set_pll(&pmucru->ppll_con[0], &ppll_init_cfg);
1609
1610        /*  configure pmu pclk */
1611        pclk_div = PPLL_HZ / PMU_PCLK_HZ - 1;
1612        rk_clrsetreg(&pmucru->pmucru_clksel[0],
1613                     PMU_PCLK_DIV_CON_MASK,
1614                     pclk_div << PMU_PCLK_DIV_CON_SHIFT);
1615}
1616#endif
1617
1618static int rk3399_pmuclk_probe(struct udevice *dev)
1619{
1620#if CONFIG_IS_ENABLED(OF_PLATDATA) || !defined(CONFIG_SPL_BUILD)
1621        struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
1622#endif
1623
1624#if CONFIG_IS_ENABLED(OF_PLATDATA)
1625        struct rk3399_pmuclk_plat *plat = dev_get_plat(dev);
1626
1627        priv->pmucru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
1628#endif
1629
1630#ifndef CONFIG_SPL_BUILD
1631        pmuclk_init(priv->pmucru);
1632#endif
1633        return 0;
1634}
1635
1636static int rk3399_pmuclk_of_to_plat(struct udevice *dev)
1637{
1638        if (CONFIG_IS_ENABLED(OF_REAL)) {
1639                struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
1640
1641                priv->pmucru = dev_read_addr_ptr(dev);
1642        }
1643
1644        return 0;
1645}
1646
1647static int rk3399_pmuclk_bind(struct udevice *dev)
1648{
1649#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
1650        int ret;
1651
1652        ret = offsetof(struct rk3399_pmucru, pmucru_softrst_con[0]);
1653        ret = rockchip_reset_bind(dev, ret, 2);
1654        if (ret)
1655                debug("Warning: software reset driver bind faile\n");
1656#endif
1657        return 0;
1658}
1659
1660static const struct udevice_id rk3399_pmuclk_ids[] = {
1661        { .compatible = "rockchip,rk3399-pmucru" },
1662        { }
1663};
1664
1665U_BOOT_DRIVER(rockchip_rk3399_pmuclk) = {
1666        .name           = "rockchip_rk3399_pmucru",
1667        .id             = UCLASS_CLK,
1668        .of_match       = rk3399_pmuclk_ids,
1669        .priv_auto      = sizeof(struct rk3399_pmuclk_priv),
1670        .of_to_plat = rk3399_pmuclk_of_to_plat,
1671        .ops            = &rk3399_pmuclk_ops,
1672        .probe          = rk3399_pmuclk_probe,
1673        .bind           = rk3399_pmuclk_bind,
1674#if CONFIG_IS_ENABLED(OF_PLATDATA)
1675        .plat_auto      = sizeof(struct rk3399_pmuclk_plat),
1676#endif
1677};
1678