uboot/drivers/clk/rockchip/clk_rk3328.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * (C) Copyright 2017 Rockchip Electronics Co., Ltd
   4 */
   5
   6#include <common.h>
   7#include <bitfield.h>
   8#include <clk-uclass.h>
   9#include <dm.h>
  10#include <errno.h>
  11#include <log.h>
  12#include <malloc.h>
  13#include <syscon.h>
  14#include <asm/arch-rockchip/clock.h>
  15#include <asm/arch-rockchip/cru_rk3328.h>
  16#include <asm/arch-rockchip/hardware.h>
  17#include <asm/arch-rockchip/grf_rk3328.h>
  18#include <asm/io.h>
  19#include <dm/device-internal.h>
  20#include <dm/lists.h>
  21#include <dt-bindings/clock/rk3328-cru.h>
  22#include <linux/bitops.h>
  23#include <linux/delay.h>
  24
  25struct pll_div {
  26        u32 refdiv;
  27        u32 fbdiv;
  28        u32 postdiv1;
  29        u32 postdiv2;
  30        u32 frac;
  31};
  32
  33#define RATE_TO_DIV(input_rate, output_rate) \
  34        ((input_rate) / (output_rate) - 1);
  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
  42static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 4, 1);
  43static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 2, 2, 1);
  44
  45static const struct pll_div apll_816_cfg = PLL_DIVISORS(816 * MHz, 1, 2, 1);
  46static const struct pll_div apll_600_cfg = PLL_DIVISORS(600 * MHz, 1, 3, 1);
  47
  48static const struct pll_div *apll_cfgs[] = {
  49        [APLL_816_MHZ] = &apll_816_cfg,
  50        [APLL_600_MHZ] = &apll_600_cfg,
  51};
  52
  53enum {
  54        /* PLL_CON0 */
  55        PLL_POSTDIV1_SHIFT              = 12,
  56        PLL_POSTDIV1_MASK               = 0x7 << PLL_POSTDIV1_SHIFT,
  57        PLL_FBDIV_SHIFT                 = 0,
  58        PLL_FBDIV_MASK                  = 0xfff,
  59
  60        /* PLL_CON1 */
  61        PLL_DSMPD_SHIFT                 = 12,
  62        PLL_DSMPD_MASK                  = 1 << PLL_DSMPD_SHIFT,
  63        PLL_INTEGER_MODE                = 1,
  64        PLL_LOCK_STATUS_SHIFT           = 10,
  65        PLL_LOCK_STATUS_MASK            = 1 << PLL_LOCK_STATUS_SHIFT,
  66        PLL_POSTDIV2_SHIFT              = 6,
  67        PLL_POSTDIV2_MASK               = 0x7 << PLL_POSTDIV2_SHIFT,
  68        PLL_REFDIV_SHIFT                = 0,
  69        PLL_REFDIV_MASK                 = 0x3f,
  70
  71        /* PLL_CON2 */
  72        PLL_FRACDIV_SHIFT               = 0,
  73        PLL_FRACDIV_MASK                = 0xffffff,
  74
  75        /* MODE_CON */
  76        APLL_MODE_SHIFT                 = 0,
  77        NPLL_MODE_SHIFT                 = 1,
  78        DPLL_MODE_SHIFT                 = 4,
  79        CPLL_MODE_SHIFT                 = 8,
  80        GPLL_MODE_SHIFT                 = 12,
  81        PLL_MODE_SLOW                   = 0,
  82        PLL_MODE_NORM,
  83
  84        /* CLKSEL_CON0 */
  85        CLK_CORE_PLL_SEL_APLL           = 0,
  86        CLK_CORE_PLL_SEL_GPLL,
  87        CLK_CORE_PLL_SEL_DPLL,
  88        CLK_CORE_PLL_SEL_NPLL,
  89        CLK_CORE_PLL_SEL_SHIFT          = 6,
  90        CLK_CORE_PLL_SEL_MASK           = 3 << CLK_CORE_PLL_SEL_SHIFT,
  91        CLK_CORE_DIV_SHIFT              = 0,
  92        CLK_CORE_DIV_MASK               = 0x1f,
  93
  94        /* CLKSEL_CON1 */
  95        ACLKM_CORE_DIV_SHIFT            = 4,
  96        ACLKM_CORE_DIV_MASK             = 0x7 << ACLKM_CORE_DIV_SHIFT,
  97        PCLK_DBG_DIV_SHIFT              = 0,
  98        PCLK_DBG_DIV_MASK               = 0xF << PCLK_DBG_DIV_SHIFT,
  99
 100        /* CLKSEL_CON27 */
 101        GMAC2IO_PLL_SEL_SHIFT           = 7,
 102        GMAC2IO_PLL_SEL_MASK            = 1 << GMAC2IO_PLL_SEL_SHIFT,
 103        GMAC2IO_PLL_SEL_CPLL            = 0,
 104        GMAC2IO_PLL_SEL_GPLL            = 1,
 105        GMAC2IO_CLK_DIV_MASK            = 0x1f,
 106        GMAC2IO_CLK_DIV_SHIFT           = 0,
 107
 108        /* CLKSEL_CON28 */
 109        ACLK_PERIHP_PLL_SEL_CPLL        = 0,
 110        ACLK_PERIHP_PLL_SEL_GPLL,
 111        ACLK_PERIHP_PLL_SEL_HDMIPHY,
 112        ACLK_PERIHP_PLL_SEL_SHIFT       = 6,
 113        ACLK_PERIHP_PLL_SEL_MASK        = 3 << ACLK_PERIHP_PLL_SEL_SHIFT,
 114        ACLK_PERIHP_DIV_CON_SHIFT       = 0,
 115        ACLK_PERIHP_DIV_CON_MASK        = 0x1f,
 116
 117        /* CLKSEL_CON29 */
 118        PCLK_PERIHP_DIV_CON_SHIFT       = 4,
 119        PCLK_PERIHP_DIV_CON_MASK        = 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
 120        HCLK_PERIHP_DIV_CON_SHIFT       = 0,
 121        HCLK_PERIHP_DIV_CON_MASK        = 3 << HCLK_PERIHP_DIV_CON_SHIFT,
 122
 123        /* CLKSEL_CON22 */
 124        CLK_TSADC_DIV_CON_SHIFT         = 0,
 125        CLK_TSADC_DIV_CON_MASK          = 0x3ff,
 126
 127        /* CLKSEL_CON23 */
 128        CLK_SARADC_DIV_CON_SHIFT        = 0,
 129        CLK_SARADC_DIV_CON_MASK         = GENMASK(9, 0),
 130        CLK_SARADC_DIV_CON_WIDTH        = 10,
 131
 132        /* CLKSEL_CON24 */
 133        CLK_PWM_PLL_SEL_CPLL            = 0,
 134        CLK_PWM_PLL_SEL_GPLL,
 135        CLK_PWM_PLL_SEL_SHIFT           = 15,
 136        CLK_PWM_PLL_SEL_MASK            = 1 << CLK_PWM_PLL_SEL_SHIFT,
 137        CLK_PWM_DIV_CON_SHIFT           = 8,
 138        CLK_PWM_DIV_CON_MASK            = 0x7f << CLK_PWM_DIV_CON_SHIFT,
 139
 140        CLK_SPI_PLL_SEL_CPLL            = 0,
 141        CLK_SPI_PLL_SEL_GPLL,
 142        CLK_SPI_PLL_SEL_SHIFT           = 7,
 143        CLK_SPI_PLL_SEL_MASK            = 1 << CLK_SPI_PLL_SEL_SHIFT,
 144        CLK_SPI_DIV_CON_SHIFT           = 0,
 145        CLK_SPI_DIV_CON_MASK            = 0x7f << CLK_SPI_DIV_CON_SHIFT,
 146
 147        /* CLKSEL_CON30 */
 148        CLK_SDMMC_PLL_SEL_CPLL          = 0,
 149        CLK_SDMMC_PLL_SEL_GPLL,
 150        CLK_SDMMC_PLL_SEL_24M,
 151        CLK_SDMMC_PLL_SEL_USBPHY,
 152        CLK_SDMMC_PLL_SHIFT             = 8,
 153        CLK_SDMMC_PLL_MASK              = 0x3 << CLK_SDMMC_PLL_SHIFT,
 154        CLK_SDMMC_DIV_CON_SHIFT          = 0,
 155        CLK_SDMMC_DIV_CON_MASK           = 0xff << CLK_SDMMC_DIV_CON_SHIFT,
 156
 157        /* CLKSEL_CON32 */
 158        CLK_EMMC_PLL_SEL_CPLL           = 0,
 159        CLK_EMMC_PLL_SEL_GPLL,
 160        CLK_EMMC_PLL_SEL_24M,
 161        CLK_EMMC_PLL_SEL_USBPHY,
 162        CLK_EMMC_PLL_SHIFT              = 8,
 163        CLK_EMMC_PLL_MASK               = 0x3 << CLK_EMMC_PLL_SHIFT,
 164        CLK_EMMC_DIV_CON_SHIFT          = 0,
 165        CLK_EMMC_DIV_CON_MASK           = 0xff << CLK_EMMC_DIV_CON_SHIFT,
 166
 167        /* CLKSEL_CON34 */
 168        CLK_I2C_PLL_SEL_CPLL            = 0,
 169        CLK_I2C_PLL_SEL_GPLL,
 170        CLK_I2C_DIV_CON_MASK            = 0x7f,
 171        CLK_I2C_PLL_SEL_MASK            = 1,
 172        CLK_I2C1_PLL_SEL_SHIFT          = 15,
 173        CLK_I2C1_DIV_CON_SHIFT          = 8,
 174        CLK_I2C0_PLL_SEL_SHIFT          = 7,
 175        CLK_I2C0_DIV_CON_SHIFT          = 0,
 176
 177        /* CLKSEL_CON35 */
 178        CLK_I2C3_PLL_SEL_SHIFT          = 15,
 179        CLK_I2C3_DIV_CON_SHIFT          = 8,
 180        CLK_I2C2_PLL_SEL_SHIFT          = 7,
 181        CLK_I2C2_DIV_CON_SHIFT          = 0,
 182};
 183
 184#define VCO_MAX_KHZ     (3200 * (MHz / KHz))
 185#define VCO_MIN_KHZ     (800 * (MHz / KHz))
 186#define OUTPUT_MAX_KHZ  (3200 * (MHz / KHz))
 187#define OUTPUT_MIN_KHZ  (16 * (MHz / KHz))
 188
 189/*
 190 *  the div restructions of pll in integer mode, these are defined in
 191 *  * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
 192 */
 193#define PLL_DIV_MIN     16
 194#define PLL_DIV_MAX     3200
 195
 196/*
 197 * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
 198 * Formulas also embedded within the Fractional PLL Verilog model:
 199 * If DSMPD = 1 (DSM is disabled, "integer mode")
 200 * FOUTVCO = FREF / REFDIV * FBDIV
 201 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
 202 * Where:
 203 * FOUTVCO = Fractional PLL non-divided output frequency
 204 * FOUTPOSTDIV = Fractional PLL divided output frequency
 205 *               (output of second post divider)
 206 * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
 207 * REFDIV = Fractional PLL input reference clock divider
 208 * FBDIV = Integer value programmed into feedback divide
 209 *
 210 */
 211static void rkclk_set_pll(struct rk3328_cru *cru, enum rk_clk_id clk_id,
 212                        const struct pll_div *div)
 213{
 214        u32 *pll_con;
 215        u32 mode_shift, mode_mask;
 216
 217        pll_con = NULL;
 218        mode_shift = 0;
 219        switch (clk_id) {
 220        case CLK_ARM:
 221                pll_con = cru->apll_con;
 222                mode_shift = APLL_MODE_SHIFT;
 223                break;
 224        case CLK_DDR:
 225                pll_con = cru->dpll_con;
 226                mode_shift = DPLL_MODE_SHIFT;
 227                break;
 228        case CLK_CODEC:
 229                pll_con = cru->cpll_con;
 230                mode_shift = CPLL_MODE_SHIFT;
 231                break;
 232        case CLK_GENERAL:
 233                pll_con = cru->gpll_con;
 234                mode_shift = GPLL_MODE_SHIFT;
 235                break;
 236        case CLK_NEW:
 237                pll_con = cru->npll_con;
 238                mode_shift = NPLL_MODE_SHIFT;
 239                break;
 240        default:
 241                break;
 242        }
 243        mode_mask = 1 << mode_shift;
 244
 245        /* All 8 PLLs have same VCO and output frequency range restrictions. */
 246        u32 vco_khz = OSC_HZ / 1000 * div->fbdiv / div->refdiv;
 247        u32 output_khz = vco_khz / div->postdiv1 / div->postdiv2;
 248
 249        debug("PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, \
 250              postdiv2=%d, vco=%u khz, output=%u khz\n",
 251              pll_con, div->fbdiv, div->refdiv, div->postdiv1,
 252              div->postdiv2, vco_khz, output_khz);
 253        assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ &&
 254               output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ &&
 255               div->fbdiv >= PLL_DIV_MIN && div->fbdiv <= PLL_DIV_MAX);
 256
 257        /*
 258         * When power on or changing PLL setting,
 259         * we must force PLL into slow mode to ensure output stable clock.
 260         */
 261        rk_clrsetreg(&cru->mode_con, mode_mask, PLL_MODE_SLOW << mode_shift);
 262
 263        /* use integer mode */
 264        rk_clrsetreg(&pll_con[1], PLL_DSMPD_MASK,
 265                     PLL_INTEGER_MODE << PLL_DSMPD_SHIFT);
 266
 267        rk_clrsetreg(&pll_con[0],
 268                     PLL_FBDIV_MASK | PLL_POSTDIV1_MASK,
 269                     (div->fbdiv << PLL_FBDIV_SHIFT) |
 270                     (div->postdiv1 << PLL_POSTDIV1_SHIFT));
 271        rk_clrsetreg(&pll_con[1],
 272                     PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
 273                     (div->postdiv2 << PLL_POSTDIV2_SHIFT) |
 274                     (div->refdiv << PLL_REFDIV_SHIFT));
 275
 276        /* waiting for pll lock */
 277        while (!(readl(&pll_con[1]) & (1 << PLL_LOCK_STATUS_SHIFT)))
 278                udelay(1);
 279
 280        /* pll enter normal mode */
 281        rk_clrsetreg(&cru->mode_con, mode_mask, PLL_MODE_NORM << mode_shift);
 282}
 283
 284static void rkclk_init(struct rk3328_cru *cru)
 285{
 286        u32 aclk_div;
 287        u32 hclk_div;
 288        u32 pclk_div;
 289
 290        rk3328_configure_cpu(cru, APLL_600_MHZ);
 291
 292        /* configure gpll cpll */
 293        rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
 294        rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg);
 295
 296        /* configure perihp aclk, hclk, pclk */
 297        aclk_div = GPLL_HZ / PERIHP_ACLK_HZ - 1;
 298        hclk_div = PERIHP_ACLK_HZ / PERIHP_HCLK_HZ - 1;
 299        pclk_div = PERIHP_ACLK_HZ / PERIHP_PCLK_HZ - 1;
 300
 301        rk_clrsetreg(&cru->clksel_con[28],
 302                     ACLK_PERIHP_PLL_SEL_MASK | ACLK_PERIHP_DIV_CON_MASK,
 303                     ACLK_PERIHP_PLL_SEL_GPLL << ACLK_PERIHP_PLL_SEL_SHIFT |
 304                     aclk_div << ACLK_PERIHP_DIV_CON_SHIFT);
 305        rk_clrsetreg(&cru->clksel_con[29],
 306                     PCLK_PERIHP_DIV_CON_MASK | HCLK_PERIHP_DIV_CON_MASK,
 307                     pclk_div << PCLK_PERIHP_DIV_CON_SHIFT |
 308                     hclk_div << HCLK_PERIHP_DIV_CON_SHIFT);
 309}
 310
 311void rk3328_configure_cpu(struct rk3328_cru *cru,
 312                          enum apll_frequencies apll_freq)
 313{
 314        u32 clk_core_div;
 315        u32 aclkm_div;
 316        u32 pclk_dbg_div;
 317
 318        rkclk_set_pll(cru, CLK_ARM, apll_cfgs[apll_freq]);
 319
 320        clk_core_div = APLL_HZ / CLK_CORE_HZ - 1;
 321        aclkm_div = APLL_HZ / ACLKM_CORE_HZ / (clk_core_div + 1) - 1;
 322        pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ / (clk_core_div + 1) - 1;
 323
 324        rk_clrsetreg(&cru->clksel_con[0],
 325                     CLK_CORE_PLL_SEL_MASK | CLK_CORE_DIV_MASK,
 326                     CLK_CORE_PLL_SEL_APLL << CLK_CORE_PLL_SEL_SHIFT |
 327                     clk_core_div << CLK_CORE_DIV_SHIFT);
 328
 329        rk_clrsetreg(&cru->clksel_con[1],
 330                     PCLK_DBG_DIV_MASK | ACLKM_CORE_DIV_MASK,
 331                     pclk_dbg_div << PCLK_DBG_DIV_SHIFT |
 332                     aclkm_div << ACLKM_CORE_DIV_SHIFT);
 333}
 334
 335
 336static ulong rk3328_i2c_get_clk(struct rk3328_cru *cru, ulong clk_id)
 337{
 338        u32 div, con;
 339
 340        switch (clk_id) {
 341        case SCLK_I2C0:
 342                con = readl(&cru->clksel_con[34]);
 343                div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
 344                break;
 345        case SCLK_I2C1:
 346                con = readl(&cru->clksel_con[34]);
 347                div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
 348                break;
 349        case SCLK_I2C2:
 350                con = readl(&cru->clksel_con[35]);
 351                div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
 352                break;
 353        case SCLK_I2C3:
 354                con = readl(&cru->clksel_con[35]);
 355                div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
 356                break;
 357        default:
 358                printf("do not support this i2c bus\n");
 359                return -EINVAL;
 360        }
 361
 362        return DIV_TO_RATE(GPLL_HZ, div);
 363}
 364
 365static ulong rk3328_i2c_set_clk(struct rk3328_cru *cru, ulong clk_id, uint hz)
 366{
 367        int src_clk_div;
 368
 369        src_clk_div = GPLL_HZ / hz;
 370        assert(src_clk_div - 1 < 127);
 371
 372        switch (clk_id) {
 373        case SCLK_I2C0:
 374                rk_clrsetreg(&cru->clksel_con[34],
 375                             CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
 376                             CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
 377                             (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
 378                             CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
 379                break;
 380        case SCLK_I2C1:
 381                rk_clrsetreg(&cru->clksel_con[34],
 382                             CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
 383                             CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
 384                             (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
 385                             CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
 386                break;
 387        case SCLK_I2C2:
 388                rk_clrsetreg(&cru->clksel_con[35],
 389                             CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
 390                             CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
 391                             (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
 392                             CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
 393                break;
 394        case SCLK_I2C3:
 395                rk_clrsetreg(&cru->clksel_con[35],
 396                             CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
 397                             CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
 398                             (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
 399                             CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
 400                break;
 401        default:
 402                printf("do not support this i2c bus\n");
 403                return -EINVAL;
 404        }
 405
 406        return DIV_TO_RATE(GPLL_HZ, src_clk_div);
 407}
 408
 409static ulong rk3328_gmac2io_set_clk(struct rk3328_cru *cru, ulong rate)
 410{
 411        struct rk3328_grf_regs *grf;
 412        ulong ret;
 413
 414        grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
 415
 416        /*
 417         * The RGMII CLK can be derived either from an external "clkin"
 418         * or can be generated from internally by a divider from SCLK_MAC.
 419         */
 420        if (readl(&grf->mac_con[1]) & BIT(10) &&
 421            readl(&grf->soc_con[4]) & BIT(14)) {
 422                /* An external clock will always generate the right rate... */
 423                ret = rate;
 424        } else {
 425                u32 con = readl(&cru->clksel_con[27]);
 426                ulong pll_rate;
 427                u8 div;
 428
 429                if ((con >> GMAC2IO_PLL_SEL_SHIFT) & GMAC2IO_PLL_SEL_GPLL)
 430                        pll_rate = GPLL_HZ;
 431                else
 432                        pll_rate = CPLL_HZ;
 433
 434                div = DIV_ROUND_UP(pll_rate, rate) - 1;
 435                if (div <= 0x1f)
 436                        rk_clrsetreg(&cru->clksel_con[27], GMAC2IO_CLK_DIV_MASK,
 437                                     div << GMAC2IO_CLK_DIV_SHIFT);
 438                else
 439                        debug("Unsupported div for gmac:%d\n", div);
 440
 441                return DIV_TO_RATE(pll_rate, div);
 442        }
 443
 444        return ret;
 445}
 446
 447static ulong rk3328_mmc_get_clk(struct rk3328_cru *cru, uint clk_id)
 448{
 449        u32 div, con, con_id;
 450
 451        switch (clk_id) {
 452        case HCLK_SDMMC:
 453        case SCLK_SDMMC:
 454                con_id = 30;
 455                break;
 456        case HCLK_EMMC:
 457        case SCLK_EMMC:
 458                con_id = 32;
 459                break;
 460        default:
 461                return -EINVAL;
 462        }
 463        con = readl(&cru->clksel_con[con_id]);
 464        div = (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT;
 465
 466        if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT
 467            == CLK_EMMC_PLL_SEL_24M)
 468                return DIV_TO_RATE(OSC_HZ, div) / 2;
 469        else
 470                return DIV_TO_RATE(GPLL_HZ, div) / 2;
 471}
 472
 473static ulong rk3328_mmc_set_clk(struct rk3328_cru *cru,
 474                                ulong clk_id, ulong set_rate)
 475{
 476        int src_clk_div;
 477        u32 con_id;
 478
 479        switch (clk_id) {
 480        case HCLK_SDMMC:
 481        case SCLK_SDMMC:
 482                con_id = 30;
 483                break;
 484        case HCLK_EMMC:
 485        case SCLK_EMMC:
 486                con_id = 32;
 487                break;
 488        default:
 489                return -EINVAL;
 490        }
 491        /* Select clk_sdmmc/emmc source from GPLL by default */
 492        /* mmc clock defaulg div 2 internal, need provide double in cru */
 493        src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
 494
 495        if (src_clk_div > 127) {
 496                /* use 24MHz source for 400KHz clock */
 497                src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
 498                rk_clrsetreg(&cru->clksel_con[con_id],
 499                             CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
 500                             CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
 501                             (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
 502        } else {
 503                rk_clrsetreg(&cru->clksel_con[con_id],
 504                             CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
 505                             CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
 506                             (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
 507        }
 508
 509        return rk3328_mmc_get_clk(cru, clk_id);
 510}
 511
 512static ulong rk3328_pwm_get_clk(struct rk3328_cru *cru)
 513{
 514        u32 div, con;
 515
 516        con = readl(&cru->clksel_con[24]);
 517        div = (con & CLK_PWM_DIV_CON_MASK) >> CLK_PWM_DIV_CON_SHIFT;
 518
 519        return DIV_TO_RATE(GPLL_HZ, div);
 520}
 521
 522static ulong rk3328_pwm_set_clk(struct rk3328_cru *cru, uint hz)
 523{
 524        u32 div = GPLL_HZ / hz;
 525
 526        rk_clrsetreg(&cru->clksel_con[24],
 527                     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
 528                     CLK_PWM_PLL_SEL_GPLL << CLK_PWM_PLL_SEL_SHIFT |
 529                     (div - 1) << CLK_PWM_DIV_CON_SHIFT);
 530
 531        return DIV_TO_RATE(GPLL_HZ, div);
 532}
 533
 534static ulong rk3328_saradc_get_clk(struct rk3328_cru *cru)
 535{
 536        u32 div, val;
 537
 538        val = readl(&cru->clksel_con[23]);
 539        div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
 540                               CLK_SARADC_DIV_CON_WIDTH);
 541
 542        return DIV_TO_RATE(OSC_HZ, div);
 543}
 544
 545static ulong rk3328_saradc_set_clk(struct rk3328_cru *cru, uint hz)
 546{
 547        int src_clk_div;
 548
 549        src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
 550        assert(src_clk_div < 128);
 551
 552        rk_clrsetreg(&cru->clksel_con[23],
 553                     CLK_SARADC_DIV_CON_MASK,
 554                     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
 555
 556        return rk3328_saradc_get_clk(cru);
 557}
 558
 559static ulong rk3328_spi_get_clk(struct rk3328_cru *cru)
 560{
 561        u32 div, val;
 562
 563        val = readl(&cru->clksel_con[24]);
 564        div = (val & CLK_SPI_DIV_CON_MASK) >> CLK_SPI_DIV_CON_SHIFT;
 565
 566        return DIV_TO_RATE(OSC_HZ, div);
 567}
 568
 569static ulong rk3328_spi_set_clk(struct rk3328_cru *cru, uint hz)
 570{
 571        u32 src_clk_div;
 572
 573        src_clk_div = GPLL_HZ / hz;
 574        assert(src_clk_div < 128);
 575
 576        rk_clrsetreg(&cru->clksel_con[24],
 577                     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
 578                     CLK_PWM_PLL_SEL_GPLL << CLK_PWM_PLL_SEL_SHIFT |
 579                     (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT);
 580
 581        return rk3328_spi_get_clk(cru);
 582}
 583
 584static ulong rk3328_clk_get_rate(struct clk *clk)
 585{
 586        struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
 587        ulong rate = 0;
 588
 589        switch (clk->id) {
 590        case 0 ... 29:
 591                return 0;
 592        case HCLK_SDMMC:
 593        case HCLK_EMMC:
 594        case SCLK_SDMMC:
 595        case SCLK_EMMC:
 596                rate = rk3328_mmc_get_clk(priv->cru, clk->id);
 597                break;
 598        case SCLK_I2C0:
 599        case SCLK_I2C1:
 600        case SCLK_I2C2:
 601        case SCLK_I2C3:
 602                rate = rk3328_i2c_get_clk(priv->cru, clk->id);
 603                break;
 604        case SCLK_PWM:
 605                rate = rk3328_pwm_get_clk(priv->cru);
 606                break;
 607        case SCLK_SARADC:
 608                rate = rk3328_saradc_get_clk(priv->cru);
 609                break;
 610        case SCLK_SPI:
 611                rate = rk3328_spi_get_clk(priv->cru);
 612                break;
 613        default:
 614                return -ENOENT;
 615        }
 616
 617        return rate;
 618}
 619
 620static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
 621{
 622        struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
 623        ulong ret = 0;
 624
 625        switch (clk->id) {
 626        case 0 ... 29:
 627                return 0;
 628        case HCLK_SDMMC:
 629        case HCLK_EMMC:
 630        case SCLK_SDMMC:
 631        case SCLK_EMMC:
 632                ret = rk3328_mmc_set_clk(priv->cru, clk->id, rate);
 633                break;
 634        case SCLK_I2C0:
 635        case SCLK_I2C1:
 636        case SCLK_I2C2:
 637        case SCLK_I2C3:
 638                ret = rk3328_i2c_set_clk(priv->cru, clk->id, rate);
 639                break;
 640        case SCLK_MAC2IO:
 641                ret = rk3328_gmac2io_set_clk(priv->cru, rate);
 642                break;
 643        case SCLK_PWM:
 644                ret = rk3328_pwm_set_clk(priv->cru, rate);
 645                break;
 646        case SCLK_SARADC:
 647                ret = rk3328_saradc_set_clk(priv->cru, rate);
 648                break;
 649        case SCLK_SPI:
 650                ret = rk3328_spi_set_clk(priv->cru, rate);
 651                break;
 652        case DCLK_LCDC:
 653        case SCLK_PDM:
 654        case SCLK_RTC32K:
 655        case SCLK_UART0:
 656        case SCLK_UART1:
 657        case SCLK_UART2:
 658        case SCLK_SDIO:
 659        case SCLK_TSP:
 660        case SCLK_WIFI:
 661        case ACLK_BUS_PRE:
 662        case HCLK_BUS_PRE:
 663        case PCLK_BUS_PRE:
 664        case ACLK_PERI_PRE:
 665        case HCLK_PERI:
 666        case PCLK_PERI:
 667        case ACLK_VIO_PRE:
 668        case HCLK_VIO_PRE:
 669        case ACLK_RGA_PRE:
 670        case SCLK_RGA:
 671        case ACLK_VOP_PRE:
 672        case ACLK_RKVDEC_PRE:
 673        case ACLK_RKVENC:
 674        case ACLK_VPU_PRE:
 675        case SCLK_VDEC_CABAC:
 676        case SCLK_VDEC_CORE:
 677        case SCLK_VENC_CORE:
 678        case SCLK_VENC_DSP:
 679        case SCLK_EFUSE:
 680        case PCLK_DDR:
 681        case ACLK_GMAC:
 682        case PCLK_GMAC:
 683        case SCLK_USB3OTG_SUSPEND:
 684                return 0;
 685        default:
 686                return -ENOENT;
 687        }
 688
 689        return ret;
 690}
 691
 692static int rk3328_gmac2io_set_parent(struct clk *clk, struct clk *parent)
 693{
 694        struct rk3328_grf_regs *grf;
 695        const char *clock_output_name;
 696        int ret;
 697
 698        grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
 699
 700        /*
 701         * If the requested parent is in the same clock-controller and the id
 702         * is SCLK_MAC2IO_SRC ("clk_mac2io_src"), switch to the internal clock.
 703         */
 704        if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO_SRC)) {
 705                debug("%s: switching RGMII to SCLK_MAC2IO_SRC\n", __func__);
 706                rk_clrreg(&grf->mac_con[1], BIT(10));
 707                return 0;
 708        }
 709
 710        /*
 711         * Otherwise, we need to check the clock-output-names of the
 712         * requested parent to see if the requested id is "gmac_clkin".
 713         */
 714        ret = dev_read_string_index(parent->dev, "clock-output-names",
 715                                    parent->id, &clock_output_name);
 716        if (ret < 0)
 717                return -ENODATA;
 718
 719        /* If this is "gmac_clkin", switch to the external clock input */
 720        if (!strcmp(clock_output_name, "gmac_clkin")) {
 721                debug("%s: switching RGMII to CLKIN\n", __func__);
 722                rk_setreg(&grf->mac_con[1], BIT(10));
 723                return 0;
 724        }
 725
 726        return -EINVAL;
 727}
 728
 729static int rk3328_gmac2io_ext_set_parent(struct clk *clk, struct clk *parent)
 730{
 731        struct rk3328_grf_regs *grf;
 732        const char *clock_output_name;
 733        int ret;
 734
 735        grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
 736
 737        /*
 738         * If the requested parent is in the same clock-controller and the id
 739         * is SCLK_MAC2IO ("clk_mac2io"), switch to the internal clock.
 740         */
 741        if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO)) {
 742                debug("%s: switching RGMII to SCLK_MAC2IO\n", __func__);
 743                rk_clrreg(&grf->soc_con[4], BIT(14));
 744                return 0;
 745        }
 746
 747        /*
 748         * Otherwise, we need to check the clock-output-names of the
 749         * requested parent to see if the requested id is "gmac_clkin".
 750         */
 751        ret = dev_read_string_index(parent->dev, "clock-output-names",
 752                                    parent->id, &clock_output_name);
 753        if (ret < 0)
 754                return -ENODATA;
 755
 756        /* If this is "gmac_clkin", switch to the external clock input */
 757        if (!strcmp(clock_output_name, "gmac_clkin")) {
 758                debug("%s: switching RGMII to CLKIN\n", __func__);
 759                rk_setreg(&grf->soc_con[4], BIT(14));
 760                return 0;
 761        }
 762
 763        return -EINVAL;
 764}
 765
 766static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent)
 767{
 768        switch (clk->id) {
 769        case SCLK_MAC2IO:
 770                return rk3328_gmac2io_set_parent(clk, parent);
 771        case SCLK_MAC2IO_EXT:
 772                return rk3328_gmac2io_ext_set_parent(clk, parent);
 773        case DCLK_LCDC:
 774        case SCLK_PDM:
 775        case SCLK_RTC32K:
 776        case SCLK_UART0:
 777        case SCLK_UART1:
 778        case SCLK_UART2:
 779                return 0;
 780        }
 781
 782        debug("%s: unsupported clk %ld\n", __func__, clk->id);
 783        return -ENOENT;
 784}
 785
 786static struct clk_ops rk3328_clk_ops = {
 787        .get_rate = rk3328_clk_get_rate,
 788        .set_rate = rk3328_clk_set_rate,
 789        .set_parent = rk3328_clk_set_parent,
 790};
 791
 792static int rk3328_clk_probe(struct udevice *dev)
 793{
 794        struct rk3328_clk_priv *priv = dev_get_priv(dev);
 795
 796        rkclk_init(priv->cru);
 797
 798        return 0;
 799}
 800
 801static int rk3328_clk_of_to_plat(struct udevice *dev)
 802{
 803        struct rk3328_clk_priv *priv = dev_get_priv(dev);
 804
 805        priv->cru = dev_read_addr_ptr(dev);
 806
 807        return 0;
 808}
 809
 810static int rk3328_clk_bind(struct udevice *dev)
 811{
 812        int ret;
 813        struct udevice *sys_child;
 814        struct sysreset_reg *priv;
 815
 816        /* The reset driver does not have a device node, so bind it here */
 817        ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
 818                                 &sys_child);
 819        if (ret) {
 820                debug("Warning: No sysreset driver: ret=%d\n", ret);
 821        } else {
 822                priv = malloc(sizeof(struct sysreset_reg));
 823                priv->glb_srst_fst_value = offsetof(struct rk3328_cru,
 824                                                    glb_srst_fst_value);
 825                priv->glb_srst_snd_value = offsetof(struct rk3328_cru,
 826                                                    glb_srst_snd_value);
 827                dev_set_priv(sys_child, priv);
 828        }
 829
 830#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
 831        ret = offsetof(struct rk3328_cru, softrst_con[0]);
 832        ret = rockchip_reset_bind(dev, ret, 12);
 833        if (ret)
 834                debug("Warning: software reset driver bind faile\n");
 835#endif
 836
 837        return ret;
 838}
 839
 840static const struct udevice_id rk3328_clk_ids[] = {
 841        { .compatible = "rockchip,rk3328-cru" },
 842        { }
 843};
 844
 845U_BOOT_DRIVER(rockchip_rk3328_cru) = {
 846        .name           = "rockchip_rk3328_cru",
 847        .id             = UCLASS_CLK,
 848        .of_match       = rk3328_clk_ids,
 849        .priv_auto      = sizeof(struct rk3328_clk_priv),
 850        .of_to_plat = rk3328_clk_of_to_plat,
 851        .ops            = &rk3328_clk_ops,
 852        .bind           = rk3328_clk_bind,
 853        .probe          = rk3328_clk_probe,
 854};
 855