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