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