uboot/arch/arm/mach-exynos/clock.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2010 Samsung Electronics
   4 * Minkyu Kang <mk7.kang@samsung.com>
   5 */
   6
   7#include <common.h>
   8#include <asm/io.h>
   9#include <asm/arch/clock.h>
  10#include <asm/arch/clk.h>
  11#include <asm/arch/periph.h>
  12
  13#define PLL_DIV_1024    1024
  14#define PLL_DIV_65535   65535
  15#define PLL_DIV_65536   65536
  16/* *
  17 * This structure is to store the src bit, div bit and prediv bit
  18 * positions of the peripheral clocks of the src and div registers
  19 */
  20struct clk_bit_info {
  21        enum periph_id id;
  22        int32_t src_mask;
  23        int32_t div_mask;
  24        int32_t prediv_mask;
  25        int8_t src_bit;
  26        int8_t div_bit;
  27        int8_t prediv_bit;
  28};
  29
  30static struct clk_bit_info exynos5_bit_info[] = {
  31        /* periph id            s_mask  d_mask  p_mask  s_bit   d_bit   p_bit */
  32        {PERIPH_ID_UART0,       0xf,    0xf,    -1,     0,      0,      -1},
  33        {PERIPH_ID_UART1,       0xf,    0xf,    -1,     4,      4,      -1},
  34        {PERIPH_ID_UART2,       0xf,    0xf,    -1,     8,      8,      -1},
  35        {PERIPH_ID_UART3,       0xf,    0xf,    -1,     12,     12,     -1},
  36        {PERIPH_ID_I2C0,        -1,     0x7,    0x7,    -1,     24,     0},
  37        {PERIPH_ID_I2C1,        -1,     0x7,    0x7,    -1,     24,     0},
  38        {PERIPH_ID_I2C2,        -1,     0x7,    0x7,    -1,     24,     0},
  39        {PERIPH_ID_I2C3,        -1,     0x7,    0x7,    -1,     24,     0},
  40        {PERIPH_ID_I2C4,        -1,     0x7,    0x7,    -1,     24,     0},
  41        {PERIPH_ID_I2C5,        -1,     0x7,    0x7,    -1,     24,     0},
  42        {PERIPH_ID_I2C6,        -1,     0x7,    0x7,    -1,     24,     0},
  43        {PERIPH_ID_I2C7,        -1,     0x7,    0x7,    -1,     24,     0},
  44        {PERIPH_ID_SPI0,        0xf,    0xf,    0xff,   16,     0,      8},
  45        {PERIPH_ID_SPI1,        0xf,    0xf,    0xff,   20,     16,     24},
  46        {PERIPH_ID_SPI2,        0xf,    0xf,    0xff,   24,     0,      8},
  47        {PERIPH_ID_SDMMC0,      0xf,    0xf,    0xff,   0,      0,      8},
  48        {PERIPH_ID_SDMMC1,      0xf,    0xf,    0xff,   4,      16,     24},
  49        {PERIPH_ID_SDMMC2,      0xf,    0xf,    0xff,   8,      0,      8},
  50        {PERIPH_ID_SDMMC3,      0xf,    0xf,    0xff,   12,     16,     24},
  51        {PERIPH_ID_I2S0,        0xf,    0xf,    0xff,   0,      0,      4},
  52        {PERIPH_ID_I2S1,        0xf,    0xf,    0xff,   4,      12,     16},
  53        {PERIPH_ID_SPI3,        0xf,    0xf,    0xff,   0,      0,      4},
  54        {PERIPH_ID_SPI4,        0xf,    0xf,    0xff,   4,      12,     16},
  55        {PERIPH_ID_SDMMC4,      0xf,    0xf,    0xff,   16,     0,      8},
  56        {PERIPH_ID_PWM0,        0xf,    0xf,    -1,     24,     0,      -1},
  57        {PERIPH_ID_PWM1,        0xf,    0xf,    -1,     24,     0,      -1},
  58        {PERIPH_ID_PWM2,        0xf,    0xf,    -1,     24,     0,      -1},
  59        {PERIPH_ID_PWM3,        0xf,    0xf,    -1,     24,     0,      -1},
  60        {PERIPH_ID_PWM4,        0xf,    0xf,    -1,     24,     0,      -1},
  61
  62        {PERIPH_ID_NONE,        -1,     -1,     -1,     -1,     -1,     -1},
  63};
  64
  65static struct clk_bit_info exynos542x_bit_info[] = {
  66        /* periph id            s_mask  d_mask  p_mask  s_bit   d_bit   p_bit */
  67        {PERIPH_ID_UART0,       0xf,    0xf,    -1,     4,      8,      -1},
  68        {PERIPH_ID_UART1,       0xf,    0xf,    -1,     8,      12,     -1},
  69        {PERIPH_ID_UART2,       0xf,    0xf,    -1,     12,     16,     -1},
  70        {PERIPH_ID_UART3,       0xf,    0xf,    -1,     16,     20,     -1},
  71        {PERIPH_ID_I2C0,        -1,     0x3f,   -1,     -1,     8,      -1},
  72        {PERIPH_ID_I2C1,        -1,     0x3f,   -1,     -1,     8,      -1},
  73        {PERIPH_ID_I2C2,        -1,     0x3f,   -1,     -1,     8,      -1},
  74        {PERIPH_ID_I2C3,        -1,     0x3f,   -1,     -1,     8,      -1},
  75        {PERIPH_ID_I2C4,        -1,     0x3f,   -1,     -1,     8,      -1},
  76        {PERIPH_ID_I2C5,        -1,     0x3f,   -1,     -1,     8,      -1},
  77        {PERIPH_ID_I2C6,        -1,     0x3f,   -1,     -1,     8,      -1},
  78        {PERIPH_ID_I2C7,        -1,     0x3f,   -1,     -1,     8,      -1},
  79        {PERIPH_ID_SPI0,        0xf,    0xf,    0xff,   20,     20,     8},
  80        {PERIPH_ID_SPI1,        0xf,    0xf,    0xff,   24,     24,     16},
  81        {PERIPH_ID_SPI2,        0xf,    0xf,    0xff,   28,     28,     24},
  82        {PERIPH_ID_SDMMC0,      0x7,    0x3ff,  -1,     8,      0,      -1},
  83        {PERIPH_ID_SDMMC1,      0x7,    0x3ff,  -1,     12,     10,     -1},
  84        {PERIPH_ID_SDMMC2,      0x7,    0x3ff,  -1,     16,     20,     -1},
  85        {PERIPH_ID_I2C8,        -1,     0x3f,   -1,     -1,     8,      -1},
  86        {PERIPH_ID_I2C9,        -1,     0x3f,   -1,     -1,     8,      -1},
  87        {PERIPH_ID_I2S0,        0xf,    0xf,    0xff,   0,      0,      4},
  88        {PERIPH_ID_I2S1,        0xf,    0xf,    0xff,   4,      12,     16},
  89        {PERIPH_ID_SPI3,        0xf,    0xf,    0xff,   12,     16,     0},
  90        {PERIPH_ID_SPI4,        0xf,    0xf,    0xff,   16,     20,     8},
  91        {PERIPH_ID_PWM0,        0xf,    0xf,    -1,     24,     28,     -1},
  92        {PERIPH_ID_PWM1,        0xf,    0xf,    -1,     24,     28,     -1},
  93        {PERIPH_ID_PWM2,        0xf,    0xf,    -1,     24,     28,     -1},
  94        {PERIPH_ID_PWM3,        0xf,    0xf,    -1,     24,     28,     -1},
  95        {PERIPH_ID_PWM4,        0xf,    0xf,    -1,     24,     28,     -1},
  96        {PERIPH_ID_I2C10,       -1,     0x3f,   -1,     -1,     8,      -1},
  97
  98        {PERIPH_ID_NONE,        -1,     -1,     -1,     -1,     -1,     -1},
  99};
 100
 101/* Epll Clock division values to achive different frequency output */
 102static struct set_epll_con_val exynos5_epll_div[] = {
 103        { 192000000, 0, 48, 3, 1, 0 },
 104        { 180000000, 0, 45, 3, 1, 0 },
 105        {  73728000, 1, 73, 3, 3, 47710 },
 106        {  67737600, 1, 90, 4, 3, 20762 },
 107        {  49152000, 0, 49, 3, 3, 9961 },
 108        {  45158400, 0, 45, 3, 3, 10381 },
 109        { 180633600, 0, 45, 3, 1, 10381 }
 110};
 111
 112/* exynos: return pll clock frequency */
 113static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
 114{
 115        unsigned long m, p, s = 0, mask, fout;
 116        unsigned int div;
 117        unsigned int freq;
 118        /*
 119         * APLL_CON: MIDV [25:16]
 120         * MPLL_CON: MIDV [25:16]
 121         * EPLL_CON: MIDV [24:16]
 122         * VPLL_CON: MIDV [24:16]
 123         * BPLL_CON: MIDV [25:16]: Exynos5
 124         */
 125        if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL ||
 126            pllreg == SPLL)
 127                mask = 0x3ff;
 128        else
 129                mask = 0x1ff;
 130
 131        m = (r >> 16) & mask;
 132
 133        /* PDIV [13:8] */
 134        p = (r >> 8) & 0x3f;
 135        /* SDIV [2:0] */
 136        s = r & 0x7;
 137
 138        freq = CONFIG_SYS_CLK_FREQ;
 139
 140        if (pllreg == EPLL || pllreg == RPLL) {
 141                k = k & 0xffff;
 142                /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
 143                fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));
 144        } else if (pllreg == VPLL) {
 145                k = k & 0xfff;
 146
 147                /*
 148                 * Exynos4210
 149                 * FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV)
 150                 *
 151                 * Exynos4412
 152                 * FOUT = (MDIV + K / 65535) * FIN / (PDIV * 2^SDIV)
 153                 *
 154                 * Exynos5250
 155                 * FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV)
 156                 */
 157                if (proid_is_exynos4210())
 158                        div = PLL_DIV_1024;
 159                else if (proid_is_exynos4412())
 160                        div = PLL_DIV_65535;
 161                else if (proid_is_exynos5250() || proid_is_exynos5420() ||
 162                         proid_is_exynos5422())
 163                        div = PLL_DIV_65536;
 164                else
 165                        return 0;
 166
 167                fout = (m + k / div) * (freq / (p * (1 << s)));
 168        } else {
 169                /*
 170                 * Exynos4412 / Exynos5250
 171                 * FOUT = MDIV * FIN / (PDIV * 2^SDIV)
 172                 *
 173                 * Exynos4210
 174                 * FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1))
 175                 */
 176                if (proid_is_exynos4210())
 177                        fout = m * (freq / (p * (1 << (s - 1))));
 178                else
 179                        fout = m * (freq / (p * (1 << s)));
 180        }
 181        return fout;
 182}
 183
 184/* exynos4: return pll clock frequency */
 185static unsigned long exynos4_get_pll_clk(int pllreg)
 186{
 187        struct exynos4_clock *clk =
 188                (struct exynos4_clock *)samsung_get_base_clock();
 189        unsigned long r, k = 0;
 190
 191        switch (pllreg) {
 192        case APLL:
 193                r = readl(&clk->apll_con0);
 194                break;
 195        case MPLL:
 196                r = readl(&clk->mpll_con0);
 197                break;
 198        case EPLL:
 199                r = readl(&clk->epll_con0);
 200                k = readl(&clk->epll_con1);
 201                break;
 202        case VPLL:
 203                r = readl(&clk->vpll_con0);
 204                k = readl(&clk->vpll_con1);
 205                break;
 206        default:
 207                printf("Unsupported PLL (%d)\n", pllreg);
 208                return 0;
 209        }
 210
 211        return exynos_get_pll_clk(pllreg, r, k);
 212}
 213
 214/* exynos4x12: return pll clock frequency */
 215static unsigned long exynos4x12_get_pll_clk(int pllreg)
 216{
 217        struct exynos4x12_clock *clk =
 218                (struct exynos4x12_clock *)samsung_get_base_clock();
 219        unsigned long r, k = 0;
 220
 221        switch (pllreg) {
 222        case APLL:
 223                r = readl(&clk->apll_con0);
 224                break;
 225        case MPLL:
 226                r = readl(&clk->mpll_con0);
 227                break;
 228        case EPLL:
 229                r = readl(&clk->epll_con0);
 230                k = readl(&clk->epll_con1);
 231                break;
 232        case VPLL:
 233                r = readl(&clk->vpll_con0);
 234                k = readl(&clk->vpll_con1);
 235                break;
 236        default:
 237                printf("Unsupported PLL (%d)\n", pllreg);
 238                return 0;
 239        }
 240
 241        return exynos_get_pll_clk(pllreg, r, k);
 242}
 243
 244/* exynos5: return pll clock frequency */
 245static unsigned long exynos5_get_pll_clk(int pllreg)
 246{
 247        struct exynos5_clock *clk =
 248                (struct exynos5_clock *)samsung_get_base_clock();
 249        unsigned long r, k = 0, fout;
 250        unsigned int pll_div2_sel, fout_sel;
 251
 252        switch (pllreg) {
 253        case APLL:
 254                r = readl(&clk->apll_con0);
 255                break;
 256        case MPLL:
 257                r = readl(&clk->mpll_con0);
 258                break;
 259        case EPLL:
 260                r = readl(&clk->epll_con0);
 261                k = readl(&clk->epll_con1);
 262                break;
 263        case VPLL:
 264                r = readl(&clk->vpll_con0);
 265                k = readl(&clk->vpll_con1);
 266                break;
 267        case BPLL:
 268                r = readl(&clk->bpll_con0);
 269                break;
 270        default:
 271                printf("Unsupported PLL (%d)\n", pllreg);
 272                return 0;
 273        }
 274
 275        fout = exynos_get_pll_clk(pllreg, r, k);
 276
 277        /* According to the user manual, in EVT1 MPLL and BPLL always gives
 278         * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
 279        if (pllreg == MPLL || pllreg == BPLL) {
 280                pll_div2_sel = readl(&clk->pll_div2_sel);
 281
 282                switch (pllreg) {
 283                case MPLL:
 284                        fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT)
 285                                        & MPLL_FOUT_SEL_MASK;
 286                        break;
 287                case BPLL:
 288                        fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT)
 289                                        & BPLL_FOUT_SEL_MASK;
 290                        break;
 291                default:
 292                        fout_sel = -1;
 293                        break;
 294                }
 295
 296                if (fout_sel == 0)
 297                        fout /= 2;
 298        }
 299
 300        return fout;
 301}
 302
 303/* exynos542x: return pll clock frequency */
 304static unsigned long exynos542x_get_pll_clk(int pllreg)
 305{
 306        struct exynos5420_clock *clk =
 307                (struct exynos5420_clock *)samsung_get_base_clock();
 308        unsigned long r, k = 0;
 309
 310        switch (pllreg) {
 311        case APLL:
 312                r = readl(&clk->apll_con0);
 313                break;
 314        case MPLL:
 315                r = readl(&clk->mpll_con0);
 316                break;
 317        case EPLL:
 318                r = readl(&clk->epll_con0);
 319                k = readl(&clk->epll_con1);
 320                break;
 321        case VPLL:
 322                r = readl(&clk->vpll_con0);
 323                k = readl(&clk->vpll_con1);
 324                break;
 325        case BPLL:
 326                r = readl(&clk->bpll_con0);
 327                break;
 328        case RPLL:
 329                r = readl(&clk->rpll_con0);
 330                k = readl(&clk->rpll_con1);
 331                break;
 332        case SPLL:
 333                r = readl(&clk->spll_con0);
 334                break;
 335        default:
 336                printf("Unsupported PLL (%d)\n", pllreg);
 337                return 0;
 338        }
 339
 340        return exynos_get_pll_clk(pllreg, r, k);
 341}
 342
 343static struct clk_bit_info *get_clk_bit_info(int peripheral)
 344{
 345        int i;
 346        struct clk_bit_info *info;
 347
 348        if (proid_is_exynos542x())
 349                info = exynos542x_bit_info;
 350        else
 351                info = exynos5_bit_info;
 352
 353        for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
 354                if (info[i].id == peripheral)
 355                        break;
 356        }
 357
 358        if (info[i].id == PERIPH_ID_NONE)
 359                debug("ERROR: Peripheral ID %d not found\n", peripheral);
 360
 361        return &info[i];
 362}
 363
 364static unsigned long exynos5_get_periph_rate(int peripheral)
 365{
 366        struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
 367        unsigned long sclk = 0;
 368        unsigned int src = 0, div = 0, sub_div = 0;
 369        struct exynos5_clock *clk =
 370                        (struct exynos5_clock *)samsung_get_base_clock();
 371
 372        switch (peripheral) {
 373        case PERIPH_ID_UART0:
 374        case PERIPH_ID_UART1:
 375        case PERIPH_ID_UART2:
 376        case PERIPH_ID_UART3:
 377                src = readl(&clk->src_peric0);
 378                div = readl(&clk->div_peric0);
 379                break;
 380        case PERIPH_ID_PWM0:
 381        case PERIPH_ID_PWM1:
 382        case PERIPH_ID_PWM2:
 383        case PERIPH_ID_PWM3:
 384        case PERIPH_ID_PWM4:
 385                src = readl(&clk->src_peric0);
 386                div = readl(&clk->div_peric3);
 387                break;
 388        case PERIPH_ID_I2S0:
 389                src = readl(&clk->src_mau);
 390                div = sub_div = readl(&clk->div_mau);
 391        case PERIPH_ID_SPI0:
 392        case PERIPH_ID_SPI1:
 393                src = readl(&clk->src_peric1);
 394                div = sub_div = readl(&clk->div_peric1);
 395                break;
 396        case PERIPH_ID_SPI2:
 397                src = readl(&clk->src_peric1);
 398                div = sub_div = readl(&clk->div_peric2);
 399                break;
 400        case PERIPH_ID_SPI3:
 401        case PERIPH_ID_SPI4:
 402                src = readl(&clk->sclk_src_isp);
 403                div = sub_div = readl(&clk->sclk_div_isp);
 404                break;
 405        case PERIPH_ID_SDMMC0:
 406        case PERIPH_ID_SDMMC1:
 407                src = readl(&clk->src_fsys);
 408                div = sub_div = readl(&clk->div_fsys1);
 409                break;
 410        case PERIPH_ID_SDMMC2:
 411        case PERIPH_ID_SDMMC3:
 412                src = readl(&clk->src_fsys);
 413                div = sub_div = readl(&clk->div_fsys2);
 414                break;
 415        case PERIPH_ID_I2C0:
 416        case PERIPH_ID_I2C1:
 417        case PERIPH_ID_I2C2:
 418        case PERIPH_ID_I2C3:
 419        case PERIPH_ID_I2C4:
 420        case PERIPH_ID_I2C5:
 421        case PERIPH_ID_I2C6:
 422        case PERIPH_ID_I2C7:
 423                src = EXYNOS_SRC_MPLL;
 424                div = readl(&clk->div_top1);
 425                sub_div = readl(&clk->div_top0);
 426                break;
 427        default:
 428                debug("%s: invalid peripheral %d", __func__, peripheral);
 429                return -1;
 430        };
 431
 432        if (bit_info->src_bit >= 0)
 433                src = (src >> bit_info->src_bit) & bit_info->src_mask;
 434
 435        switch (src) {
 436        case EXYNOS_SRC_MPLL:
 437                sclk = exynos5_get_pll_clk(MPLL);
 438                break;
 439        case EXYNOS_SRC_EPLL:
 440                sclk = exynos5_get_pll_clk(EPLL);
 441                break;
 442        case EXYNOS_SRC_VPLL:
 443                sclk = exynos5_get_pll_clk(VPLL);
 444                break;
 445        default:
 446                debug("%s: EXYNOS_SRC %d not supported\n", __func__, src);
 447                return 0;
 448        }
 449
 450        /* Clock divider ratio for this peripheral */
 451        if (bit_info->div_bit >= 0)
 452                div = (div >> bit_info->div_bit) & bit_info->div_mask;
 453
 454        /* Clock pre-divider ratio for this peripheral */
 455        if (bit_info->prediv_bit >= 0)
 456                sub_div = (sub_div >> bit_info->prediv_bit)
 457                          & bit_info->prediv_mask;
 458
 459        /* Calculate and return required clock rate */
 460        return (sclk / (div + 1)) / (sub_div + 1);
 461}
 462
 463static unsigned long exynos542x_get_periph_rate(int peripheral)
 464{
 465        struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
 466        unsigned long sclk = 0;
 467        unsigned int src = 0, div = 0, sub_div = 0;
 468        struct exynos5420_clock *clk =
 469                        (struct exynos5420_clock *)samsung_get_base_clock();
 470
 471        switch (peripheral) {
 472        case PERIPH_ID_UART0:
 473        case PERIPH_ID_UART1:
 474        case PERIPH_ID_UART2:
 475        case PERIPH_ID_UART3:
 476        case PERIPH_ID_PWM0:
 477        case PERIPH_ID_PWM1:
 478        case PERIPH_ID_PWM2:
 479        case PERIPH_ID_PWM3:
 480        case PERIPH_ID_PWM4:
 481                src = readl(&clk->src_peric0);
 482                div = readl(&clk->div_peric0);
 483                break;
 484        case PERIPH_ID_SPI0:
 485        case PERIPH_ID_SPI1:
 486        case PERIPH_ID_SPI2:
 487                src = readl(&clk->src_peric1);
 488                div = readl(&clk->div_peric1);
 489                sub_div = readl(&clk->div_peric4);
 490                break;
 491        case PERIPH_ID_SPI3:
 492        case PERIPH_ID_SPI4:
 493                src = readl(&clk->src_isp);
 494                div = readl(&clk->div_isp1);
 495                sub_div = readl(&clk->div_isp1);
 496                break;
 497        case PERIPH_ID_SDMMC0:
 498        case PERIPH_ID_SDMMC1:
 499        case PERIPH_ID_SDMMC2:
 500        case PERIPH_ID_SDMMC3:
 501                src = readl(&clk->src_fsys);
 502                div = readl(&clk->div_fsys1);
 503                break;
 504        case PERIPH_ID_I2C0:
 505        case PERIPH_ID_I2C1:
 506        case PERIPH_ID_I2C2:
 507        case PERIPH_ID_I2C3:
 508        case PERIPH_ID_I2C4:
 509        case PERIPH_ID_I2C5:
 510        case PERIPH_ID_I2C6:
 511        case PERIPH_ID_I2C7:
 512        case PERIPH_ID_I2C8:
 513        case PERIPH_ID_I2C9:
 514        case PERIPH_ID_I2C10:
 515                src = EXYNOS542X_SRC_MPLL;
 516                div = readl(&clk->div_top1);
 517                break;
 518        default:
 519                debug("%s: invalid peripheral %d", __func__, peripheral);
 520                return -1;
 521        };
 522
 523        if (bit_info->src_bit >= 0)
 524                src = (src >> bit_info->src_bit) & bit_info->src_mask;
 525
 526        switch (src) {
 527        case EXYNOS542X_SRC_MPLL:
 528                sclk = exynos542x_get_pll_clk(MPLL);
 529                break;
 530        case EXYNOS542X_SRC_SPLL:
 531                sclk = exynos542x_get_pll_clk(SPLL);
 532                break;
 533        case EXYNOS542X_SRC_EPLL:
 534                sclk = exynos542x_get_pll_clk(EPLL);
 535                break;
 536        case EXYNOS542X_SRC_RPLL:
 537                sclk = exynos542x_get_pll_clk(RPLL);
 538                break;
 539        default:
 540                debug("%s: EXYNOS542X_SRC %d not supported", __func__, src);
 541                return 0;
 542        }
 543
 544        /* Clock divider ratio for this peripheral */
 545        if (bit_info->div_bit >= 0)
 546                div = (div >> bit_info->div_bit) & bit_info->div_mask;
 547
 548        /* Clock pre-divider ratio for this peripheral */
 549        if (bit_info->prediv_bit >= 0)
 550                sub_div = (sub_div >> bit_info->prediv_bit)
 551                          & bit_info->prediv_mask;
 552
 553        /* Calculate and return required clock rate */
 554        return (sclk / (div + 1)) / (sub_div + 1);
 555}
 556
 557unsigned long clock_get_periph_rate(int peripheral)
 558{
 559        if (cpu_is_exynos5()) {
 560                if (proid_is_exynos542x())
 561                        return exynos542x_get_periph_rate(peripheral);
 562                return exynos5_get_periph_rate(peripheral);
 563        } else {
 564                return 0;
 565        }
 566}
 567
 568/* exynos4: return ARM clock frequency */
 569static unsigned long exynos4_get_arm_clk(void)
 570{
 571        struct exynos4_clock *clk =
 572                (struct exynos4_clock *)samsung_get_base_clock();
 573        unsigned long div;
 574        unsigned long armclk;
 575        unsigned int core_ratio;
 576        unsigned int core2_ratio;
 577
 578        div = readl(&clk->div_cpu0);
 579
 580        /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
 581        core_ratio = (div >> 0) & 0x7;
 582        core2_ratio = (div >> 28) & 0x7;
 583
 584        armclk = get_pll_clk(APLL) / (core_ratio + 1);
 585        armclk /= (core2_ratio + 1);
 586
 587        return armclk;
 588}
 589
 590/* exynos4x12: return ARM clock frequency */
 591static unsigned long exynos4x12_get_arm_clk(void)
 592{
 593        struct exynos4x12_clock *clk =
 594                (struct exynos4x12_clock *)samsung_get_base_clock();
 595        unsigned long div;
 596        unsigned long armclk;
 597        unsigned int core_ratio;
 598        unsigned int core2_ratio;
 599
 600        div = readl(&clk->div_cpu0);
 601
 602        /* CORE_RATIO: [2:0], CORE2_RATIO: [30:28] */
 603        core_ratio = (div >> 0) & 0x7;
 604        core2_ratio = (div >> 28) & 0x7;
 605
 606        armclk = get_pll_clk(APLL) / (core_ratio + 1);
 607        armclk /= (core2_ratio + 1);
 608
 609        return armclk;
 610}
 611
 612/* exynos5: return ARM clock frequency */
 613static unsigned long exynos5_get_arm_clk(void)
 614{
 615        struct exynos5_clock *clk =
 616                (struct exynos5_clock *)samsung_get_base_clock();
 617        unsigned long div;
 618        unsigned long armclk;
 619        unsigned int arm_ratio;
 620        unsigned int arm2_ratio;
 621
 622        div = readl(&clk->div_cpu0);
 623
 624        /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
 625        arm_ratio = (div >> 0) & 0x7;
 626        arm2_ratio = (div >> 28) & 0x7;
 627
 628        armclk = get_pll_clk(APLL) / (arm_ratio + 1);
 629        armclk /= (arm2_ratio + 1);
 630
 631        return armclk;
 632}
 633
 634/* exynos4: return pwm clock frequency */
 635static unsigned long exynos4_get_pwm_clk(void)
 636{
 637        struct exynos4_clock *clk =
 638                (struct exynos4_clock *)samsung_get_base_clock();
 639        unsigned long pclk, sclk;
 640        unsigned int sel;
 641        unsigned int ratio;
 642
 643        if (s5p_get_cpu_rev() == 0) {
 644                /*
 645                 * CLK_SRC_PERIL0
 646                 * PWM_SEL [27:24]
 647                 */
 648                sel = readl(&clk->src_peril0);
 649                sel = (sel >> 24) & 0xf;
 650
 651                if (sel == 0x6)
 652                        sclk = get_pll_clk(MPLL);
 653                else if (sel == 0x7)
 654                        sclk = get_pll_clk(EPLL);
 655                else if (sel == 0x8)
 656                        sclk = get_pll_clk(VPLL);
 657                else
 658                        return 0;
 659
 660                /*
 661                 * CLK_DIV_PERIL3
 662                 * PWM_RATIO [3:0]
 663                 */
 664                ratio = readl(&clk->div_peril3);
 665                ratio = ratio & 0xf;
 666        } else if (s5p_get_cpu_rev() == 1) {
 667                sclk = get_pll_clk(MPLL);
 668                ratio = 8;
 669        } else
 670                return 0;
 671
 672        pclk = sclk / (ratio + 1);
 673
 674        return pclk;
 675}
 676
 677/* exynos4x12: return pwm clock frequency */
 678static unsigned long exynos4x12_get_pwm_clk(void)
 679{
 680        unsigned long pclk, sclk;
 681        unsigned int ratio;
 682
 683        sclk = get_pll_clk(MPLL);
 684        ratio = 8;
 685
 686        pclk = sclk / (ratio + 1);
 687
 688        return pclk;
 689}
 690
 691/* exynos4: return uart clock frequency */
 692static unsigned long exynos4_get_uart_clk(int dev_index)
 693{
 694        struct exynos4_clock *clk =
 695                (struct exynos4_clock *)samsung_get_base_clock();
 696        unsigned long uclk, sclk;
 697        unsigned int sel;
 698        unsigned int ratio;
 699
 700        /*
 701         * CLK_SRC_PERIL0
 702         * UART0_SEL [3:0]
 703         * UART1_SEL [7:4]
 704         * UART2_SEL [8:11]
 705         * UART3_SEL [12:15]
 706         * UART4_SEL [16:19]
 707         * UART5_SEL [23:20]
 708         */
 709        sel = readl(&clk->src_peril0);
 710        sel = (sel >> (dev_index << 2)) & 0xf;
 711
 712        if (sel == 0x6)
 713                sclk = get_pll_clk(MPLL);
 714        else if (sel == 0x7)
 715                sclk = get_pll_clk(EPLL);
 716        else if (sel == 0x8)
 717                sclk = get_pll_clk(VPLL);
 718        else
 719                return 0;
 720
 721        /*
 722         * CLK_DIV_PERIL0
 723         * UART0_RATIO [3:0]
 724         * UART1_RATIO [7:4]
 725         * UART2_RATIO [8:11]
 726         * UART3_RATIO [12:15]
 727         * UART4_RATIO [16:19]
 728         * UART5_RATIO [23:20]
 729         */
 730        ratio = readl(&clk->div_peril0);
 731        ratio = (ratio >> (dev_index << 2)) & 0xf;
 732
 733        uclk = sclk / (ratio + 1);
 734
 735        return uclk;
 736}
 737
 738/* exynos4x12: return uart clock frequency */
 739static unsigned long exynos4x12_get_uart_clk(int dev_index)
 740{
 741        struct exynos4x12_clock *clk =
 742                (struct exynos4x12_clock *)samsung_get_base_clock();
 743        unsigned long uclk, sclk;
 744        unsigned int sel;
 745        unsigned int ratio;
 746
 747        /*
 748         * CLK_SRC_PERIL0
 749         * UART0_SEL [3:0]
 750         * UART1_SEL [7:4]
 751         * UART2_SEL [8:11]
 752         * UART3_SEL [12:15]
 753         * UART4_SEL [16:19]
 754         */
 755        sel = readl(&clk->src_peril0);
 756        sel = (sel >> (dev_index << 2)) & 0xf;
 757
 758        if (sel == 0x6)
 759                sclk = get_pll_clk(MPLL);
 760        else if (sel == 0x7)
 761                sclk = get_pll_clk(EPLL);
 762        else if (sel == 0x8)
 763                sclk = get_pll_clk(VPLL);
 764        else
 765                return 0;
 766
 767        /*
 768         * CLK_DIV_PERIL0
 769         * UART0_RATIO [3:0]
 770         * UART1_RATIO [7:4]
 771         * UART2_RATIO [8:11]
 772         * UART3_RATIO [12:15]
 773         * UART4_RATIO [16:19]
 774         */
 775        ratio = readl(&clk->div_peril0);
 776        ratio = (ratio >> (dev_index << 2)) & 0xf;
 777
 778        uclk = sclk / (ratio + 1);
 779
 780        return uclk;
 781}
 782
 783static unsigned long exynos4_get_mmc_clk(int dev_index)
 784{
 785        struct exynos4_clock *clk =
 786                (struct exynos4_clock *)samsung_get_base_clock();
 787        unsigned long uclk, sclk;
 788        unsigned int sel, ratio, pre_ratio;
 789        int shift = 0;
 790
 791        sel = readl(&clk->src_fsys);
 792        sel = (sel >> (dev_index << 2)) & 0xf;
 793
 794        if (sel == 0x6)
 795                sclk = get_pll_clk(MPLL);
 796        else if (sel == 0x7)
 797                sclk = get_pll_clk(EPLL);
 798        else if (sel == 0x8)
 799                sclk = get_pll_clk(VPLL);
 800        else
 801                return 0;
 802
 803        switch (dev_index) {
 804        case 0:
 805        case 1:
 806                ratio = readl(&clk->div_fsys1);
 807                pre_ratio = readl(&clk->div_fsys1);
 808                break;
 809        case 2:
 810        case 3:
 811                ratio = readl(&clk->div_fsys2);
 812                pre_ratio = readl(&clk->div_fsys2);
 813                break;
 814        case 4:
 815                ratio = readl(&clk->div_fsys3);
 816                pre_ratio = readl(&clk->div_fsys3);
 817                break;
 818        default:
 819                return 0;
 820        }
 821
 822        if (dev_index == 1 || dev_index == 3)
 823                shift = 16;
 824
 825        ratio = (ratio >> shift) & 0xf;
 826        pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
 827        uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
 828
 829        return uclk;
 830}
 831
 832/* exynos4: set the mmc clock */
 833static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
 834{
 835        struct exynos4_clock *clk =
 836                (struct exynos4_clock *)samsung_get_base_clock();
 837        unsigned int addr, clear_bit, set_bit;
 838
 839        /*
 840         * CLK_DIV_FSYS1
 841         * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
 842         * CLK_DIV_FSYS2
 843         * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
 844         * CLK_DIV_FSYS3
 845         * MMC4_RATIO [3:0]
 846         */
 847        if (dev_index < 2) {
 848                addr = (unsigned int)&clk->div_fsys1;
 849                clear_bit = MASK_PRE_RATIO(dev_index);
 850                set_bit = SET_PRE_RATIO(dev_index, div);
 851        } else if (dev_index == 4) {
 852                addr = (unsigned int)&clk->div_fsys3;
 853                dev_index -= 4;
 854                /* MMC4 is controlled with the MMC4_RATIO value */
 855                clear_bit = MASK_RATIO(dev_index);
 856                set_bit = SET_RATIO(dev_index, div);
 857        } else {
 858                addr = (unsigned int)&clk->div_fsys2;
 859                dev_index -= 2;
 860                clear_bit = MASK_PRE_RATIO(dev_index);
 861                set_bit = SET_PRE_RATIO(dev_index, div);
 862        }
 863
 864        clrsetbits_le32(addr, clear_bit, set_bit);
 865}
 866
 867/* exynos5: set the mmc clock */
 868static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
 869{
 870        struct exynos5_clock *clk =
 871                (struct exynos5_clock *)samsung_get_base_clock();
 872        unsigned int addr;
 873
 874        /*
 875         * CLK_DIV_FSYS1
 876         * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
 877         * CLK_DIV_FSYS2
 878         * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
 879         */
 880        if (dev_index < 2) {
 881                addr = (unsigned int)&clk->div_fsys1;
 882        } else {
 883                addr = (unsigned int)&clk->div_fsys2;
 884                dev_index -= 2;
 885        }
 886
 887        clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8),
 888                        (div & 0xff) << ((dev_index << 4) + 8));
 889}
 890
 891/* exynos5: set the mmc clock */
 892static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
 893{
 894        struct exynos5420_clock *clk =
 895                (struct exynos5420_clock *)samsung_get_base_clock();
 896        unsigned int addr;
 897        unsigned int shift;
 898
 899        /*
 900         * CLK_DIV_FSYS1
 901         * MMC0_RATIO [9:0]
 902         * MMC1_RATIO [19:10]
 903         * MMC2_RATIO [29:20]
 904         */
 905        addr = (unsigned int)&clk->div_fsys1;
 906        shift = dev_index * 10;
 907
 908        clrsetbits_le32(addr, 0x3ff << shift, (div & 0x3ff) << shift);
 909}
 910
 911/* get_lcd_clk: return lcd clock frequency */
 912static unsigned long exynos4_get_lcd_clk(void)
 913{
 914        struct exynos4_clock *clk =
 915                (struct exynos4_clock *)samsung_get_base_clock();
 916        unsigned long pclk, sclk;
 917        unsigned int sel;
 918        unsigned int ratio;
 919
 920        /*
 921         * CLK_SRC_LCD0
 922         * FIMD0_SEL [3:0]
 923         */
 924        sel = readl(&clk->src_lcd0);
 925        sel = sel & 0xf;
 926
 927        /*
 928         * 0x6: SCLK_MPLL
 929         * 0x7: SCLK_EPLL
 930         * 0x8: SCLK_VPLL
 931         */
 932        if (sel == 0x6)
 933                sclk = get_pll_clk(MPLL);
 934        else if (sel == 0x7)
 935                sclk = get_pll_clk(EPLL);
 936        else if (sel == 0x8)
 937                sclk = get_pll_clk(VPLL);
 938        else
 939                return 0;
 940
 941        /*
 942         * CLK_DIV_LCD0
 943         * FIMD0_RATIO [3:0]
 944         */
 945        ratio = readl(&clk->div_lcd0);
 946        ratio = ratio & 0xf;
 947
 948        pclk = sclk / (ratio + 1);
 949
 950        return pclk;
 951}
 952
 953/* get_lcd_clk: return lcd clock frequency */
 954static unsigned long exynos5_get_lcd_clk(void)
 955{
 956        struct exynos5_clock *clk =
 957                (struct exynos5_clock *)samsung_get_base_clock();
 958        unsigned long pclk, sclk;
 959        unsigned int sel;
 960        unsigned int ratio;
 961
 962        /*
 963         * CLK_SRC_LCD0
 964         * FIMD0_SEL [3:0]
 965         */
 966        sel = readl(&clk->src_disp1_0);
 967        sel = sel & 0xf;
 968
 969        /*
 970         * 0x6: SCLK_MPLL
 971         * 0x7: SCLK_EPLL
 972         * 0x8: SCLK_VPLL
 973         */
 974        if (sel == 0x6)
 975                sclk = get_pll_clk(MPLL);
 976        else if (sel == 0x7)
 977                sclk = get_pll_clk(EPLL);
 978        else if (sel == 0x8)
 979                sclk = get_pll_clk(VPLL);
 980        else
 981                return 0;
 982
 983        /*
 984         * CLK_DIV_LCD0
 985         * FIMD0_RATIO [3:0]
 986         */
 987        ratio = readl(&clk->div_disp1_0);
 988        ratio = ratio & 0xf;
 989
 990        pclk = sclk / (ratio + 1);
 991
 992        return pclk;
 993}
 994
 995static unsigned long exynos5420_get_lcd_clk(void)
 996{
 997        struct exynos5420_clock *clk =
 998                (struct exynos5420_clock *)samsung_get_base_clock();
 999        unsigned long pclk, sclk;
1000        unsigned int sel;
1001        unsigned int ratio;
1002
1003        /*
1004         * CLK_SRC_DISP10
1005         * FIMD1_SEL [4]
1006         * 0: SCLK_RPLL
1007         * 1: SCLK_SPLL
1008         */
1009        sel = readl(&clk->src_disp10);
1010        sel &= (1 << 4);
1011
1012        if (sel)
1013                sclk = get_pll_clk(SPLL);
1014        else
1015                sclk = get_pll_clk(RPLL);
1016
1017        /*
1018         * CLK_DIV_DISP10
1019         * FIMD1_RATIO [3:0]
1020         */
1021        ratio = readl(&clk->div_disp10);
1022        ratio = ratio & 0xf;
1023
1024        pclk = sclk / (ratio + 1);
1025
1026        return pclk;
1027}
1028
1029static unsigned long exynos5800_get_lcd_clk(void)
1030{
1031        struct exynos5420_clock *clk =
1032                (struct exynos5420_clock *)samsung_get_base_clock();
1033        unsigned long sclk;
1034        unsigned int sel;
1035        unsigned int ratio;
1036
1037        /*
1038         * CLK_SRC_DISP10
1039         * CLKMUX_FIMD1 [6:4]
1040         */
1041        sel = (readl(&clk->src_disp10) >> 4) & 0x7;
1042
1043        if (sel) {
1044                /*
1045                 * Mapping of CLK_SRC_DISP10 CLKMUX_FIMD1 [6:4] values into
1046                 * PLLs. The first element is a placeholder to bypass the
1047                 * default settig.
1048                 */
1049                const int reg_map[] = {0, CPLL, DPLL, MPLL, SPLL, IPLL, EPLL,
1050                                                                        RPLL};
1051                sclk = get_pll_clk(reg_map[sel]);
1052        } else
1053                sclk = CONFIG_SYS_CLK_FREQ;
1054        /*
1055         * CLK_DIV_DISP10
1056         * FIMD1_RATIO [3:0]
1057         */
1058        ratio = readl(&clk->div_disp10) & 0xf;
1059
1060        return sclk / (ratio + 1);
1061}
1062
1063void exynos4_set_lcd_clk(void)
1064{
1065        struct exynos4_clock *clk =
1066            (struct exynos4_clock *)samsung_get_base_clock();
1067
1068        /*
1069         * CLK_GATE_BLOCK
1070         * CLK_CAM      [0]
1071         * CLK_TV       [1]
1072         * CLK_MFC      [2]
1073         * CLK_G3D      [3]
1074         * CLK_LCD0     [4]
1075         * CLK_LCD1     [5]
1076         * CLK_GPS      [7]
1077         */
1078        setbits_le32(&clk->gate_block, 1 << 4);
1079
1080        /*
1081         * CLK_SRC_LCD0
1082         * FIMD0_SEL            [3:0]
1083         * MDNIE0_SEL           [7:4]
1084         * MDNIE_PWM0_SEL       [8:11]
1085         * MIPI0_SEL            [12:15]
1086         * set lcd0 src clock 0x6: SCLK_MPLL
1087         */
1088        clrsetbits_le32(&clk->src_lcd0, 0xf, 0x6);
1089
1090        /*
1091         * CLK_GATE_IP_LCD0
1092         * CLK_FIMD0            [0]
1093         * CLK_MIE0             [1]
1094         * CLK_MDNIE0           [2]
1095         * CLK_DSIM0            [3]
1096         * CLK_SMMUFIMD0        [4]
1097         * CLK_PPMULCD0         [5]
1098         * Gating all clocks for FIMD0
1099         */
1100        setbits_le32(&clk->gate_ip_lcd0, 1 << 0);
1101
1102        /*
1103         * CLK_DIV_LCD0
1104         * FIMD0_RATIO          [3:0]
1105         * MDNIE0_RATIO         [7:4]
1106         * MDNIE_PWM0_RATIO     [11:8]
1107         * MDNIE_PWM_PRE_RATIO  [15:12]
1108         * MIPI0_RATIO          [19:16]
1109         * MIPI0_PRE_RATIO      [23:20]
1110         * set fimd ratio
1111         */
1112        clrsetbits_le32(&clk->div_lcd0, 0xf, 0x1);
1113}
1114
1115void exynos5_set_lcd_clk(void)
1116{
1117        struct exynos5_clock *clk =
1118            (struct exynos5_clock *)samsung_get_base_clock();
1119
1120        /*
1121         * CLK_GATE_BLOCK
1122         * CLK_CAM      [0]
1123         * CLK_TV       [1]
1124         * CLK_MFC      [2]
1125         * CLK_G3D      [3]
1126         * CLK_LCD0     [4]
1127         * CLK_LCD1     [5]
1128         * CLK_GPS      [7]
1129         */
1130        setbits_le32(&clk->gate_block, 1 << 4);
1131
1132        /*
1133         * CLK_SRC_LCD0
1134         * FIMD0_SEL            [3:0]
1135         * MDNIE0_SEL           [7:4]
1136         * MDNIE_PWM0_SEL       [8:11]
1137         * MIPI0_SEL            [12:15]
1138         * set lcd0 src clock 0x6: SCLK_MPLL
1139         */
1140        clrsetbits_le32(&clk->src_disp1_0, 0xf, 0x6);
1141
1142        /*
1143         * CLK_GATE_IP_LCD0
1144         * CLK_FIMD0            [0]
1145         * CLK_MIE0             [1]
1146         * CLK_MDNIE0           [2]
1147         * CLK_DSIM0            [3]
1148         * CLK_SMMUFIMD0        [4]
1149         * CLK_PPMULCD0         [5]
1150         * Gating all clocks for FIMD0
1151         */
1152        setbits_le32(&clk->gate_ip_disp1, 1 << 0);
1153
1154        /*
1155         * CLK_DIV_LCD0
1156         * FIMD0_RATIO          [3:0]
1157         * MDNIE0_RATIO         [7:4]
1158         * MDNIE_PWM0_RATIO     [11:8]
1159         * MDNIE_PWM_PRE_RATIO  [15:12]
1160         * MIPI0_RATIO          [19:16]
1161         * MIPI0_PRE_RATIO      [23:20]
1162         * set fimd ratio
1163         */
1164        clrsetbits_le32(&clk->div_disp1_0, 0xf, 0x0);
1165}
1166
1167void exynos5420_set_lcd_clk(void)
1168{
1169        struct exynos5420_clock *clk =
1170                (struct exynos5420_clock *)samsung_get_base_clock();
1171        unsigned int cfg;
1172
1173        /*
1174         * CLK_SRC_DISP10
1175         * FIMD1_SEL [4]
1176         * 0: SCLK_RPLL
1177         * 1: SCLK_SPLL
1178         */
1179        cfg = readl(&clk->src_disp10);
1180        cfg &= ~(0x1 << 4);
1181        cfg |= (0 << 4);
1182        writel(cfg, &clk->src_disp10);
1183
1184        /*
1185         * CLK_DIV_DISP10
1186         * FIMD1_RATIO          [3:0]
1187         */
1188        cfg = readl(&clk->div_disp10);
1189        cfg &= ~(0xf << 0);
1190        cfg |= (0 << 0);
1191        writel(cfg, &clk->div_disp10);
1192}
1193
1194void exynos5800_set_lcd_clk(void)
1195{
1196        struct exynos5420_clock *clk =
1197                (struct exynos5420_clock *)samsung_get_base_clock();
1198        unsigned int cfg;
1199
1200        /*
1201         * Use RPLL for pixel clock
1202         * CLK_SRC_DISP10 CLKMUX_FIMD1 [6:4]
1203         * ==================
1204         * 111: SCLK_RPLL
1205         */
1206        cfg = readl(&clk->src_disp10) | (0x7 << 4);
1207        writel(cfg, &clk->src_disp10);
1208
1209        /*
1210         * CLK_DIV_DISP10
1211         * FIMD1_RATIO          [3:0]
1212         */
1213        clrsetbits_le32(&clk->div_disp10, 0xf << 0, 0x0 << 0);
1214}
1215
1216void exynos4_set_mipi_clk(void)
1217{
1218        struct exynos4_clock *clk =
1219            (struct exynos4_clock *)samsung_get_base_clock();
1220
1221        /*
1222         * CLK_SRC_LCD0
1223         * FIMD0_SEL            [3:0]
1224         * MDNIE0_SEL           [7:4]
1225         * MDNIE_PWM0_SEL       [8:11]
1226         * MIPI0_SEL            [12:15]
1227         * set mipi0 src clock 0x6: SCLK_MPLL
1228         */
1229        clrsetbits_le32(&clk->src_lcd0, 0xf << 12, 0x6 << 12);
1230
1231        /*
1232         * CLK_SRC_MASK_LCD0
1233         * FIMD0_MASK           [0]
1234         * MDNIE0_MASK          [4]
1235         * MDNIE_PWM0_MASK      [8]
1236         * MIPI0_MASK           [12]
1237         * set src mask mipi0 0x1: Unmask
1238         */
1239        setbits_le32(&clk->src_mask_lcd0, 0x1 << 12);
1240
1241        /*
1242         * CLK_GATE_IP_LCD0
1243         * CLK_FIMD0            [0]
1244         * CLK_MIE0             [1]
1245         * CLK_MDNIE0           [2]
1246         * CLK_DSIM0            [3]
1247         * CLK_SMMUFIMD0        [4]
1248         * CLK_PPMULCD0         [5]
1249         * Gating all clocks for MIPI0
1250         */
1251        setbits_le32(&clk->gate_ip_lcd0, 1 << 3);
1252
1253        /*
1254         * CLK_DIV_LCD0
1255         * FIMD0_RATIO          [3:0]
1256         * MDNIE0_RATIO         [7:4]
1257         * MDNIE_PWM0_RATIO     [11:8]
1258         * MDNIE_PWM_PRE_RATIO  [15:12]
1259         * MIPI0_RATIO          [19:16]
1260         * MIPI0_PRE_RATIO      [23:20]
1261         * set mipi ratio
1262         */
1263        clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16);
1264}
1265
1266int exynos5_set_epll_clk(unsigned long rate)
1267{
1268        unsigned int epll_con, epll_con_k;
1269        unsigned int i;
1270        unsigned int lockcnt;
1271        unsigned int start;
1272        struct exynos5_clock *clk =
1273                (struct exynos5_clock *)samsung_get_base_clock();
1274
1275        epll_con = readl(&clk->epll_con0);
1276        epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
1277                        EPLL_CON0_LOCK_DET_EN_SHIFT) |
1278                EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
1279                EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
1280                EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
1281
1282        for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
1283                if (exynos5_epll_div[i].freq_out == rate)
1284                        break;
1285        }
1286
1287        if (i == ARRAY_SIZE(exynos5_epll_div))
1288                return -1;
1289
1290        epll_con_k = exynos5_epll_div[i].k_dsm << 0;
1291        epll_con |= exynos5_epll_div[i].en_lock_det <<
1292                                EPLL_CON0_LOCK_DET_EN_SHIFT;
1293        epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
1294        epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
1295        epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
1296
1297        /*
1298         * Required period ( in cycles) to genarate a stable clock output.
1299         * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
1300         * frequency input (as per spec)
1301         */
1302        lockcnt = 3000 * exynos5_epll_div[i].p_div;
1303
1304        writel(lockcnt, &clk->epll_lock);
1305        writel(epll_con, &clk->epll_con0);
1306        writel(epll_con_k, &clk->epll_con1);
1307
1308        start = get_timer(0);
1309
1310         while (!(readl(&clk->epll_con0) &
1311                        (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
1312                if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
1313                        debug("%s: Timeout waiting for EPLL lock\n", __func__);
1314                        return -1;
1315                }
1316        }
1317        return 0;
1318}
1319
1320static int exynos5420_set_i2s_clk_source(void)
1321{
1322        struct exynos5420_clock *clk =
1323                (struct exynos5420_clock *)samsung_get_base_clock();
1324
1325        setbits_le32(&clk->src_top6, EXYNOS5420_CLK_SRC_MOUT_EPLL);
1326        clrsetbits_le32(&clk->src_mau, EXYNOS5420_AUDIO0_SEL_MASK,
1327                        (EXYNOS5420_CLK_SRC_SCLK_EPLL));
1328        setbits_le32(EXYNOS5_AUDIOSS_BASE, 1 << 0);
1329
1330        return 0;
1331}
1332
1333int exynos5_set_i2s_clk_source(unsigned int i2s_id)
1334{
1335        struct exynos5_clock *clk =
1336                (struct exynos5_clock *)samsung_get_base_clock();
1337        unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
1338
1339        if (i2s_id == 0) {
1340                setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
1341                clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
1342                                (CLK_SRC_SCLK_EPLL));
1343                setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
1344        } else if (i2s_id == 1) {
1345                clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
1346                                (CLK_SRC_SCLK_EPLL));
1347        } else {
1348                return -1;
1349        }
1350        return 0;
1351}
1352
1353int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
1354                                  unsigned int dst_frq,
1355                                  unsigned int i2s_id)
1356{
1357        struct exynos5_clock *clk =
1358                (struct exynos5_clock *)samsung_get_base_clock();
1359        unsigned int div;
1360
1361        if ((dst_frq == 0) || (src_frq == 0)) {
1362                debug("%s: Invalid requency input for prescaler\n", __func__);
1363                debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1364                return -1;
1365        }
1366
1367        div = (src_frq / dst_frq);
1368        if (i2s_id == 0) {
1369                if (div > AUDIO_0_RATIO_MASK) {
1370                        debug("%s: Frequency ratio is out of range\n",
1371                              __func__);
1372                        debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1373                        return -1;
1374                }
1375                clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
1376                                (div & AUDIO_0_RATIO_MASK));
1377        } else if (i2s_id == 1) {
1378                if (div > AUDIO_1_RATIO_MASK) {
1379                        debug("%s: Frequency ratio is out of range\n",
1380                              __func__);
1381                        debug("src frq = %d des frq = %d ", src_frq, dst_frq);
1382                        return -1;
1383                }
1384                clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
1385                                (div & AUDIO_1_RATIO_MASK));
1386        } else {
1387                return -1;
1388        }
1389        return 0;
1390}
1391
1392/**
1393 * Linearly searches for the most accurate main and fine stage clock scalars
1394 * (divisors) for a specified target frequency and scalar bit sizes by checking
1395 * all multiples of main_scalar_bits values. Will always return scalars up to or
1396 * slower than target.
1397 *
1398 * @param main_scalar_bits      Number of main scalar bits, must be > 0 and < 32
1399 * @param fine_scalar_bits      Number of fine scalar bits, must be > 0 and < 32
1400 * @param input_freq            Clock frequency to be scaled in Hz
1401 * @param target_freq           Desired clock frequency in Hz
1402 * @param best_fine_scalar      Pointer to store the fine stage divisor
1403 *
1404 * @return best_main_scalar     Main scalar for desired frequency or -1 if none
1405 * found
1406 */
1407static int clock_calc_best_scalar(unsigned int main_scaler_bits,
1408        unsigned int fine_scalar_bits, unsigned int input_rate,
1409        unsigned int target_rate, unsigned int *best_fine_scalar)
1410{
1411        int i;
1412        int best_main_scalar = -1;
1413        unsigned int best_error = target_rate;
1414        const unsigned int cap = (1 << fine_scalar_bits) - 1;
1415        const unsigned int loops = 1 << main_scaler_bits;
1416
1417        debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
1418                        target_rate, cap);
1419
1420        assert(best_fine_scalar != NULL);
1421        assert(main_scaler_bits <= fine_scalar_bits);
1422
1423        *best_fine_scalar = 1;
1424
1425        if (input_rate == 0 || target_rate == 0)
1426                return -1;
1427
1428        if (target_rate >= input_rate)
1429                return 1;
1430
1431        for (i = 1; i <= loops; i++) {
1432                const unsigned int effective_div =
1433                        max(min(input_rate / i / target_rate, cap), 1U);
1434                const unsigned int effective_rate = input_rate / i /
1435                                                        effective_div;
1436                const int error = target_rate - effective_rate;
1437
1438                debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
1439                                effective_rate, error);
1440
1441                if (error >= 0 && error <= best_error) {
1442                        best_error = error;
1443                        best_main_scalar = i;
1444                        *best_fine_scalar = effective_div;
1445                }
1446        }
1447
1448        return best_main_scalar;
1449}
1450
1451static int exynos5_set_spi_clk(enum periph_id periph_id,
1452                                        unsigned int rate)
1453{
1454        struct exynos5_clock *clk =
1455                (struct exynos5_clock *)samsung_get_base_clock();
1456        int main;
1457        unsigned int fine;
1458        unsigned shift, pre_shift;
1459        unsigned mask = 0xff;
1460        u32 *reg;
1461
1462        main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1463        if (main < 0) {
1464                debug("%s: Cannot set clock rate for periph %d",
1465                                __func__, periph_id);
1466                return -1;
1467        }
1468        main = main - 1;
1469        fine = fine - 1;
1470
1471        switch (periph_id) {
1472        case PERIPH_ID_SPI0:
1473                reg = &clk->div_peric1;
1474                shift = 0;
1475                pre_shift = 8;
1476                break;
1477        case PERIPH_ID_SPI1:
1478                reg = &clk->div_peric1;
1479                shift = 16;
1480                pre_shift = 24;
1481                break;
1482        case PERIPH_ID_SPI2:
1483                reg = &clk->div_peric2;
1484                shift = 0;
1485                pre_shift = 8;
1486                break;
1487        case PERIPH_ID_SPI3:
1488                reg = &clk->sclk_div_isp;
1489                shift = 0;
1490                pre_shift = 4;
1491                break;
1492        case PERIPH_ID_SPI4:
1493                reg = &clk->sclk_div_isp;
1494                shift = 12;
1495                pre_shift = 16;
1496                break;
1497        default:
1498                debug("%s: Unsupported peripheral ID %d\n", __func__,
1499                      periph_id);
1500                return -1;
1501        }
1502        clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
1503        clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
1504
1505        return 0;
1506}
1507
1508static int exynos5420_set_spi_clk(enum periph_id periph_id,
1509                                        unsigned int rate)
1510{
1511        struct exynos5420_clock *clk =
1512                (struct exynos5420_clock *)samsung_get_base_clock();
1513        int main;
1514        unsigned int fine;
1515        unsigned shift, pre_shift;
1516        unsigned div_mask = 0xf, pre_div_mask = 0xff;
1517        u32 *reg;
1518        u32 *pre_reg;
1519
1520        main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
1521        if (main < 0) {
1522                debug("%s: Cannot set clock rate for periph %d",
1523                      __func__, periph_id);
1524                return -1;
1525        }
1526        main = main - 1;
1527        fine = fine - 1;
1528
1529        switch (periph_id) {
1530        case PERIPH_ID_SPI0:
1531                reg = &clk->div_peric1;
1532                shift = 20;
1533                pre_reg = &clk->div_peric4;
1534                pre_shift = 8;
1535                break;
1536        case PERIPH_ID_SPI1:
1537                reg = &clk->div_peric1;
1538                shift = 24;
1539                pre_reg = &clk->div_peric4;
1540                pre_shift = 16;
1541                break;
1542        case PERIPH_ID_SPI2:
1543                reg = &clk->div_peric1;
1544                shift = 28;
1545                pre_reg = &clk->div_peric4;
1546                pre_shift = 24;
1547                break;
1548        case PERIPH_ID_SPI3:
1549                reg = &clk->div_isp1;
1550                shift = 16;
1551                pre_reg = &clk->div_isp1;
1552                pre_shift = 0;
1553                break;
1554        case PERIPH_ID_SPI4:
1555                reg = &clk->div_isp1;
1556                shift = 20;
1557                pre_reg = &clk->div_isp1;
1558                pre_shift = 8;
1559                break;
1560        default:
1561                debug("%s: Unsupported peripheral ID %d\n", __func__,
1562                      periph_id);
1563                return -1;
1564        }
1565
1566        clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift);
1567        clrsetbits_le32(pre_reg, pre_div_mask << pre_shift,
1568                        (fine & pre_div_mask) << pre_shift);
1569
1570        return 0;
1571}
1572
1573static unsigned long exynos4_get_i2c_clk(void)
1574{
1575        struct exynos4_clock *clk =
1576                (struct exynos4_clock *)samsung_get_base_clock();
1577        unsigned long sclk, aclk_100;
1578        unsigned int ratio;
1579
1580        sclk = get_pll_clk(APLL);
1581
1582        ratio = (readl(&clk->div_top)) >> 4;
1583        ratio &= 0xf;
1584        aclk_100 = sclk / (ratio + 1);
1585        return aclk_100;
1586}
1587
1588unsigned long get_pll_clk(int pllreg)
1589{
1590        if (cpu_is_exynos5()) {
1591                if (proid_is_exynos542x())
1592                        return exynos542x_get_pll_clk(pllreg);
1593                return exynos5_get_pll_clk(pllreg);
1594        } else if (cpu_is_exynos4()) {
1595                if (proid_is_exynos4412())
1596                        return exynos4x12_get_pll_clk(pllreg);
1597                return exynos4_get_pll_clk(pllreg);
1598        }
1599
1600        return 0;
1601}
1602
1603unsigned long get_arm_clk(void)
1604{
1605        if (cpu_is_exynos5()) {
1606                return exynos5_get_arm_clk();
1607        } else if (cpu_is_exynos4()) {
1608                if (proid_is_exynos4412())
1609                        return exynos4x12_get_arm_clk();
1610                return exynos4_get_arm_clk();
1611        }
1612
1613        return 0;
1614}
1615
1616unsigned long get_i2c_clk(void)
1617{
1618        if (cpu_is_exynos5())
1619                return clock_get_periph_rate(PERIPH_ID_I2C0);
1620        else if (cpu_is_exynos4())
1621                return exynos4_get_i2c_clk();
1622
1623        return 0;
1624}
1625
1626unsigned long get_pwm_clk(void)
1627{
1628        if (cpu_is_exynos5()) {
1629                return clock_get_periph_rate(PERIPH_ID_PWM0);
1630        } else if (cpu_is_exynos4()) {
1631                if (proid_is_exynos4412())
1632                        return exynos4x12_get_pwm_clk();
1633                return exynos4_get_pwm_clk();
1634        }
1635
1636        return 0;
1637}
1638
1639unsigned long get_uart_clk(int dev_index)
1640{
1641        enum periph_id id;
1642
1643        switch (dev_index) {
1644        case 0:
1645                id = PERIPH_ID_UART0;
1646                break;
1647        case 1:
1648                id = PERIPH_ID_UART1;
1649                break;
1650        case 2:
1651                id = PERIPH_ID_UART2;
1652                break;
1653        case 3:
1654                id = PERIPH_ID_UART3;
1655                break;
1656        default:
1657                debug("%s: invalid UART index %d", __func__, dev_index);
1658                return -1;
1659        }
1660
1661        if (cpu_is_exynos5()) {
1662                return clock_get_periph_rate(id);
1663        } else if (cpu_is_exynos4()) {
1664                if (proid_is_exynos4412())
1665                        return exynos4x12_get_uart_clk(dev_index);
1666                return exynos4_get_uart_clk(dev_index);
1667        }
1668
1669        return 0;
1670}
1671
1672unsigned long get_mmc_clk(int dev_index)
1673{
1674        enum periph_id id;
1675
1676        if (cpu_is_exynos4())
1677                return exynos4_get_mmc_clk(dev_index);
1678
1679        switch (dev_index) {
1680        case 0:
1681                id = PERIPH_ID_SDMMC0;
1682                break;
1683        case 1:
1684                id = PERIPH_ID_SDMMC1;
1685                break;
1686        case 2:
1687                id = PERIPH_ID_SDMMC2;
1688                break;
1689        case 3:
1690                id = PERIPH_ID_SDMMC3;
1691                break;
1692        default:
1693                debug("%s: invalid MMC index %d", __func__, dev_index);
1694                return -1;
1695        }
1696
1697        return clock_get_periph_rate(id);
1698}
1699
1700void set_mmc_clk(int dev_index, unsigned int div)
1701{
1702        /* If want to set correct value, it needs to substract one from div.*/
1703        if (div > 0)
1704                div -= 1;
1705
1706        if (cpu_is_exynos5()) {
1707                if (proid_is_exynos542x())
1708                        exynos5420_set_mmc_clk(dev_index, div);
1709                else
1710                        exynos5_set_mmc_clk(dev_index, div);
1711        } else if (cpu_is_exynos4()) {
1712                exynos4_set_mmc_clk(dev_index, div);
1713        }
1714}
1715
1716unsigned long get_lcd_clk(void)
1717{
1718        if (cpu_is_exynos4()) {
1719                return exynos4_get_lcd_clk();
1720        } else if (cpu_is_exynos5()) {
1721                if (proid_is_exynos5420())
1722                        return exynos5420_get_lcd_clk();
1723                else if (proid_is_exynos5422())
1724                        return exynos5800_get_lcd_clk();
1725                else
1726                        return exynos5_get_lcd_clk();
1727        }
1728
1729        return 0;
1730}
1731
1732void set_lcd_clk(void)
1733{
1734        if (cpu_is_exynos4()) {
1735                exynos4_set_lcd_clk();
1736        } else if (cpu_is_exynos5()) {
1737                if (proid_is_exynos5250())
1738                        exynos5_set_lcd_clk();
1739                else if (proid_is_exynos5420())
1740                        exynos5420_set_lcd_clk();
1741                else
1742                        exynos5800_set_lcd_clk();
1743        }
1744}
1745
1746void set_mipi_clk(void)
1747{
1748        if (cpu_is_exynos4())
1749                exynos4_set_mipi_clk();
1750}
1751
1752int set_spi_clk(int periph_id, unsigned int rate)
1753{
1754        if (cpu_is_exynos5()) {
1755                if (proid_is_exynos542x())
1756                        return exynos5420_set_spi_clk(periph_id, rate);
1757                return exynos5_set_spi_clk(periph_id, rate);
1758        }
1759
1760        return 0;
1761}
1762
1763int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
1764                          unsigned int i2s_id)
1765{
1766        if (cpu_is_exynos5())
1767                return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
1768
1769        return 0;
1770}
1771
1772int set_i2s_clk_source(unsigned int i2s_id)
1773{
1774        if (cpu_is_exynos5()) {
1775                if (proid_is_exynos542x())
1776                        return exynos5420_set_i2s_clk_source();
1777                else
1778                        return exynos5_set_i2s_clk_source(i2s_id);
1779        }
1780
1781        return 0;
1782}
1783
1784int set_epll_clk(unsigned long rate)
1785{
1786        if (cpu_is_exynos5())
1787                return exynos5_set_epll_clk(rate);
1788
1789        return 0;
1790}
1791