linux/drivers/clk/samsung/clk-pll.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
   3 * Copyright (c) 2013 Linaro Ltd.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 *
   9 * This file contains the utility functions to register the pll clocks.
  10*/
  11
  12#include <linux/errno.h>
  13#include <linux/hrtimer.h>
  14#include <linux/delay.h>
  15#include <linux/slab.h>
  16#include <linux/clkdev.h>
  17#include "clk.h"
  18#include "clk-pll.h"
  19
  20#define PLL_TIMEOUT_MS          10
  21
  22struct samsung_clk_pll {
  23        struct clk_hw           hw;
  24        void __iomem            *lock_reg;
  25        void __iomem            *con_reg;
  26        enum samsung_pll_type   type;
  27        unsigned int            rate_count;
  28        const struct samsung_pll_rate_table *rate_table;
  29};
  30
  31#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
  32
  33static const struct samsung_pll_rate_table *samsung_get_pll_settings(
  34                                struct samsung_clk_pll *pll, unsigned long rate)
  35{
  36        const struct samsung_pll_rate_table  *rate_table = pll->rate_table;
  37        int i;
  38
  39        for (i = 0; i < pll->rate_count; i++) {
  40                if (rate == rate_table[i].rate)
  41                        return &rate_table[i];
  42        }
  43
  44        return NULL;
  45}
  46
  47static long samsung_pll_round_rate(struct clk_hw *hw,
  48                        unsigned long drate, unsigned long *prate)
  49{
  50        struct samsung_clk_pll *pll = to_clk_pll(hw);
  51        const struct samsung_pll_rate_table *rate_table = pll->rate_table;
  52        int i;
  53
  54        /* Assumming rate_table is in descending order */
  55        for (i = 0; i < pll->rate_count; i++) {
  56                if (drate >= rate_table[i].rate)
  57                        return rate_table[i].rate;
  58        }
  59
  60        /* return minimum supported value */
  61        return rate_table[i - 1].rate;
  62}
  63
  64/*
  65 * PLL2126 Clock Type
  66 */
  67
  68#define PLL2126_MDIV_MASK       (0xff)
  69#define PLL2126_PDIV_MASK       (0x3f)
  70#define PLL2126_SDIV_MASK       (0x3)
  71#define PLL2126_MDIV_SHIFT      (16)
  72#define PLL2126_PDIV_SHIFT      (8)
  73#define PLL2126_SDIV_SHIFT      (0)
  74
  75static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
  76                                unsigned long parent_rate)
  77{
  78        struct samsung_clk_pll *pll = to_clk_pll(hw);
  79        u32 pll_con, mdiv, pdiv, sdiv;
  80        u64 fvco = parent_rate;
  81
  82        pll_con = __raw_readl(pll->con_reg);
  83        mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK;
  84        pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK;
  85        sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK;
  86
  87        fvco *= (mdiv + 8);
  88        do_div(fvco, (pdiv + 2) << sdiv);
  89
  90        return (unsigned long)fvco;
  91}
  92
  93static const struct clk_ops samsung_pll2126_clk_ops = {
  94        .recalc_rate = samsung_pll2126_recalc_rate,
  95};
  96
  97/*
  98 * PLL3000 Clock Type
  99 */
 100
 101#define PLL3000_MDIV_MASK       (0xff)
 102#define PLL3000_PDIV_MASK       (0x3)
 103#define PLL3000_SDIV_MASK       (0x3)
 104#define PLL3000_MDIV_SHIFT      (16)
 105#define PLL3000_PDIV_SHIFT      (8)
 106#define PLL3000_SDIV_SHIFT      (0)
 107
 108static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
 109                                unsigned long parent_rate)
 110{
 111        struct samsung_clk_pll *pll = to_clk_pll(hw);
 112        u32 pll_con, mdiv, pdiv, sdiv;
 113        u64 fvco = parent_rate;
 114
 115        pll_con = __raw_readl(pll->con_reg);
 116        mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK;
 117        pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK;
 118        sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK;
 119
 120        fvco *= (2 * (mdiv + 8));
 121        do_div(fvco, pdiv << sdiv);
 122
 123        return (unsigned long)fvco;
 124}
 125
 126static const struct clk_ops samsung_pll3000_clk_ops = {
 127        .recalc_rate = samsung_pll3000_recalc_rate,
 128};
 129
 130/*
 131 * PLL35xx Clock Type
 132 */
 133/* Maximum lock time can be 270 * PDIV cycles */
 134#define PLL35XX_LOCK_FACTOR     (270)
 135
 136#define PLL35XX_MDIV_MASK       (0x3FF)
 137#define PLL35XX_PDIV_MASK       (0x3F)
 138#define PLL35XX_SDIV_MASK       (0x7)
 139#define PLL35XX_LOCK_STAT_MASK  (0x1)
 140#define PLL35XX_MDIV_SHIFT      (16)
 141#define PLL35XX_PDIV_SHIFT      (8)
 142#define PLL35XX_SDIV_SHIFT      (0)
 143#define PLL35XX_LOCK_STAT_SHIFT (29)
 144
 145static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
 146                                unsigned long parent_rate)
 147{
 148        struct samsung_clk_pll *pll = to_clk_pll(hw);
 149        u32 mdiv, pdiv, sdiv, pll_con;
 150        u64 fvco = parent_rate;
 151
 152        pll_con = __raw_readl(pll->con_reg);
 153        mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
 154        pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
 155        sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
 156
 157        fvco *= mdiv;
 158        do_div(fvco, (pdiv << sdiv));
 159
 160        return (unsigned long)fvco;
 161}
 162
 163static inline bool samsung_pll35xx_mp_change(
 164                const struct samsung_pll_rate_table *rate, u32 pll_con)
 165{
 166        u32 old_mdiv, old_pdiv;
 167
 168        old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
 169        old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
 170
 171        return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
 172}
 173
 174static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
 175                                        unsigned long prate)
 176{
 177        struct samsung_clk_pll *pll = to_clk_pll(hw);
 178        const struct samsung_pll_rate_table *rate;
 179        u32 tmp;
 180
 181        /* Get required rate settings from table */
 182        rate = samsung_get_pll_settings(pll, drate);
 183        if (!rate) {
 184                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
 185                        drate, clk_hw_get_name(hw));
 186                return -EINVAL;
 187        }
 188
 189        tmp = __raw_readl(pll->con_reg);
 190
 191        if (!(samsung_pll35xx_mp_change(rate, tmp))) {
 192                /* If only s change, change just s value only*/
 193                tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
 194                tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
 195                __raw_writel(tmp, pll->con_reg);
 196
 197                return 0;
 198        }
 199
 200        /* Set PLL lock time. */
 201        __raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR,
 202                        pll->lock_reg);
 203
 204        /* Change PLL PMS values */
 205        tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
 206                        (PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
 207                        (PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
 208        tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
 209                        (rate->pdiv << PLL35XX_PDIV_SHIFT) |
 210                        (rate->sdiv << PLL35XX_SDIV_SHIFT);
 211        __raw_writel(tmp, pll->con_reg);
 212
 213        /* wait_lock_time */
 214        do {
 215                cpu_relax();
 216                tmp = __raw_readl(pll->con_reg);
 217        } while (!(tmp & (PLL35XX_LOCK_STAT_MASK
 218                                << PLL35XX_LOCK_STAT_SHIFT)));
 219        return 0;
 220}
 221
 222static const struct clk_ops samsung_pll35xx_clk_ops = {
 223        .recalc_rate = samsung_pll35xx_recalc_rate,
 224        .round_rate = samsung_pll_round_rate,
 225        .set_rate = samsung_pll35xx_set_rate,
 226};
 227
 228static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 229        .recalc_rate = samsung_pll35xx_recalc_rate,
 230};
 231
 232/*
 233 * PLL36xx Clock Type
 234 */
 235/* Maximum lock time can be 3000 * PDIV cycles */
 236#define PLL36XX_LOCK_FACTOR    (3000)
 237
 238#define PLL36XX_KDIV_MASK       (0xFFFF)
 239#define PLL36XX_MDIV_MASK       (0x1FF)
 240#define PLL36XX_PDIV_MASK       (0x3F)
 241#define PLL36XX_SDIV_MASK       (0x7)
 242#define PLL36XX_MDIV_SHIFT      (16)
 243#define PLL36XX_PDIV_SHIFT      (8)
 244#define PLL36XX_SDIV_SHIFT      (0)
 245#define PLL36XX_KDIV_SHIFT      (0)
 246#define PLL36XX_LOCK_STAT_SHIFT (29)
 247
 248static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
 249                                unsigned long parent_rate)
 250{
 251        struct samsung_clk_pll *pll = to_clk_pll(hw);
 252        u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
 253        s16 kdiv;
 254        u64 fvco = parent_rate;
 255
 256        pll_con0 = __raw_readl(pll->con_reg);
 257        pll_con1 = __raw_readl(pll->con_reg + 4);
 258        mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
 259        pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
 260        sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
 261        kdiv = (s16)(pll_con1 & PLL36XX_KDIV_MASK);
 262
 263        fvco *= (mdiv << 16) + kdiv;
 264        do_div(fvco, (pdiv << sdiv));
 265        fvco >>= 16;
 266
 267        return (unsigned long)fvco;
 268}
 269
 270static inline bool samsung_pll36xx_mpk_change(
 271        const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
 272{
 273        u32 old_mdiv, old_pdiv, old_kdiv;
 274
 275        old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
 276        old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
 277        old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
 278
 279        return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
 280                rate->kdiv != old_kdiv);
 281}
 282
 283static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
 284                                        unsigned long parent_rate)
 285{
 286        struct samsung_clk_pll *pll = to_clk_pll(hw);
 287        u32 tmp, pll_con0, pll_con1;
 288        const struct samsung_pll_rate_table *rate;
 289
 290        rate = samsung_get_pll_settings(pll, drate);
 291        if (!rate) {
 292                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
 293                        drate, clk_hw_get_name(hw));
 294                return -EINVAL;
 295        }
 296
 297        pll_con0 = __raw_readl(pll->con_reg);
 298        pll_con1 = __raw_readl(pll->con_reg + 4);
 299
 300        if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
 301                /* If only s change, change just s value only*/
 302                pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
 303                pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
 304                __raw_writel(pll_con0, pll->con_reg);
 305
 306                return 0;
 307        }
 308
 309        /* Set PLL lock time. */
 310        __raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
 311
 312         /* Change PLL PMS values */
 313        pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
 314                        (PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
 315                        (PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
 316        pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
 317                        (rate->pdiv << PLL36XX_PDIV_SHIFT) |
 318                        (rate->sdiv << PLL36XX_SDIV_SHIFT);
 319        __raw_writel(pll_con0, pll->con_reg);
 320
 321        pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
 322        pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
 323        __raw_writel(pll_con1, pll->con_reg + 4);
 324
 325        /* wait_lock_time */
 326        do {
 327                cpu_relax();
 328                tmp = __raw_readl(pll->con_reg);
 329        } while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
 330
 331        return 0;
 332}
 333
 334static const struct clk_ops samsung_pll36xx_clk_ops = {
 335        .recalc_rate = samsung_pll36xx_recalc_rate,
 336        .set_rate = samsung_pll36xx_set_rate,
 337        .round_rate = samsung_pll_round_rate,
 338};
 339
 340static const struct clk_ops samsung_pll36xx_clk_min_ops = {
 341        .recalc_rate = samsung_pll36xx_recalc_rate,
 342};
 343
 344/*
 345 * PLL45xx Clock Type
 346 */
 347#define PLL4502_LOCK_FACTOR     400
 348#define PLL4508_LOCK_FACTOR     240
 349
 350#define PLL45XX_MDIV_MASK       (0x3FF)
 351#define PLL45XX_PDIV_MASK       (0x3F)
 352#define PLL45XX_SDIV_MASK       (0x7)
 353#define PLL45XX_AFC_MASK        (0x1F)
 354#define PLL45XX_MDIV_SHIFT      (16)
 355#define PLL45XX_PDIV_SHIFT      (8)
 356#define PLL45XX_SDIV_SHIFT      (0)
 357#define PLL45XX_AFC_SHIFT       (0)
 358
 359#define PLL45XX_ENABLE          BIT(31)
 360#define PLL45XX_LOCKED          BIT(29)
 361
 362static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
 363                                unsigned long parent_rate)
 364{
 365        struct samsung_clk_pll *pll = to_clk_pll(hw);
 366        u32 mdiv, pdiv, sdiv, pll_con;
 367        u64 fvco = parent_rate;
 368
 369        pll_con = __raw_readl(pll->con_reg);
 370        mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
 371        pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
 372        sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
 373
 374        if (pll->type == pll_4508)
 375                sdiv = sdiv - 1;
 376
 377        fvco *= mdiv;
 378        do_div(fvco, (pdiv << sdiv));
 379
 380        return (unsigned long)fvco;
 381}
 382
 383static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1,
 384                                const struct samsung_pll_rate_table *rate)
 385{
 386        u32 old_mdiv, old_pdiv, old_afc;
 387
 388        old_mdiv = (pll_con0 >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
 389        old_pdiv = (pll_con0 >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
 390        old_afc = (pll_con1 >> PLL45XX_AFC_SHIFT) & PLL45XX_AFC_MASK;
 391
 392        return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
 393                || old_afc != rate->afc);
 394}
 395
 396static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
 397                                        unsigned long prate)
 398{
 399        struct samsung_clk_pll *pll = to_clk_pll(hw);
 400        const struct samsung_pll_rate_table *rate;
 401        u32 con0, con1;
 402        ktime_t start;
 403
 404        /* Get required rate settings from table */
 405        rate = samsung_get_pll_settings(pll, drate);
 406        if (!rate) {
 407                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
 408                        drate, clk_hw_get_name(hw));
 409                return -EINVAL;
 410        }
 411
 412        con0 = __raw_readl(pll->con_reg);
 413        con1 = __raw_readl(pll->con_reg + 0x4);
 414
 415        if (!(samsung_pll45xx_mp_change(con0, con1, rate))) {
 416                /* If only s change, change just s value only*/
 417                con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT);
 418                con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT;
 419                __raw_writel(con0, pll->con_reg);
 420
 421                return 0;
 422        }
 423
 424        /* Set PLL PMS values. */
 425        con0 &= ~((PLL45XX_MDIV_MASK << PLL45XX_MDIV_SHIFT) |
 426                        (PLL45XX_PDIV_MASK << PLL45XX_PDIV_SHIFT) |
 427                        (PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT));
 428        con0 |= (rate->mdiv << PLL45XX_MDIV_SHIFT) |
 429                        (rate->pdiv << PLL45XX_PDIV_SHIFT) |
 430                        (rate->sdiv << PLL45XX_SDIV_SHIFT);
 431
 432        /* Set PLL AFC value. */
 433        con1 = __raw_readl(pll->con_reg + 0x4);
 434        con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT);
 435        con1 |= (rate->afc << PLL45XX_AFC_SHIFT);
 436
 437        /* Set PLL lock time. */
 438        switch (pll->type) {
 439        case pll_4502:
 440                __raw_writel(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
 441                break;
 442        case pll_4508:
 443                __raw_writel(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
 444                break;
 445        default:
 446                break;
 447        }
 448
 449        /* Set new configuration. */
 450        __raw_writel(con1, pll->con_reg + 0x4);
 451        __raw_writel(con0, pll->con_reg);
 452
 453        /* Wait for locking. */
 454        start = ktime_get();
 455        while (!(__raw_readl(pll->con_reg) & PLL45XX_LOCKED)) {
 456                ktime_t delta = ktime_sub(ktime_get(), start);
 457
 458                if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
 459                        pr_err("%s: could not lock PLL %s\n",
 460                                        __func__, clk_hw_get_name(hw));
 461                        return -EFAULT;
 462                }
 463
 464                cpu_relax();
 465        }
 466
 467        return 0;
 468}
 469
 470static const struct clk_ops samsung_pll45xx_clk_ops = {
 471        .recalc_rate = samsung_pll45xx_recalc_rate,
 472        .round_rate = samsung_pll_round_rate,
 473        .set_rate = samsung_pll45xx_set_rate,
 474};
 475
 476static const struct clk_ops samsung_pll45xx_clk_min_ops = {
 477        .recalc_rate = samsung_pll45xx_recalc_rate,
 478};
 479
 480/*
 481 * PLL46xx Clock Type
 482 */
 483#define PLL46XX_LOCK_FACTOR     3000
 484
 485#define PLL46XX_VSEL_MASK       (1)
 486#define PLL46XX_MDIV_MASK       (0x1FF)
 487#define PLL1460X_MDIV_MASK      (0x3FF)
 488
 489#define PLL46XX_PDIV_MASK       (0x3F)
 490#define PLL46XX_SDIV_MASK       (0x7)
 491#define PLL46XX_VSEL_SHIFT      (27)
 492#define PLL46XX_MDIV_SHIFT      (16)
 493#define PLL46XX_PDIV_SHIFT      (8)
 494#define PLL46XX_SDIV_SHIFT      (0)
 495
 496#define PLL46XX_KDIV_MASK       (0xFFFF)
 497#define PLL4650C_KDIV_MASK      (0xFFF)
 498#define PLL46XX_KDIV_SHIFT      (0)
 499#define PLL46XX_MFR_MASK        (0x3F)
 500#define PLL46XX_MRR_MASK        (0x1F)
 501#define PLL46XX_KDIV_SHIFT      (0)
 502#define PLL46XX_MFR_SHIFT       (16)
 503#define PLL46XX_MRR_SHIFT       (24)
 504
 505#define PLL46XX_ENABLE          BIT(31)
 506#define PLL46XX_LOCKED          BIT(29)
 507#define PLL46XX_VSEL            BIT(27)
 508
 509static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
 510                                unsigned long parent_rate)
 511{
 512        struct samsung_clk_pll *pll = to_clk_pll(hw);
 513        u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
 514        u64 fvco = parent_rate;
 515
 516        pll_con0 = __raw_readl(pll->con_reg);
 517        pll_con1 = __raw_readl(pll->con_reg + 4);
 518        mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & ((pll->type == pll_1460x) ?
 519                                PLL1460X_MDIV_MASK : PLL46XX_MDIV_MASK);
 520        pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
 521        sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
 522        kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK :
 523                                        pll_con1 & PLL46XX_KDIV_MASK;
 524
 525        shift = ((pll->type == pll_4600) || (pll->type == pll_1460x)) ? 16 : 10;
 526
 527        fvco *= (mdiv << shift) + kdiv;
 528        do_div(fvco, (pdiv << sdiv));
 529        fvco >>= shift;
 530
 531        return (unsigned long)fvco;
 532}
 533
 534static bool samsung_pll46xx_mpk_change(u32 pll_con0, u32 pll_con1,
 535                                const struct samsung_pll_rate_table *rate)
 536{
 537        u32 old_mdiv, old_pdiv, old_kdiv;
 538
 539        old_mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
 540        old_pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
 541        old_kdiv = (pll_con1 >> PLL46XX_KDIV_SHIFT) & PLL46XX_KDIV_MASK;
 542
 543        return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
 544                || old_kdiv != rate->kdiv);
 545}
 546
 547static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
 548                                        unsigned long prate)
 549{
 550        struct samsung_clk_pll *pll = to_clk_pll(hw);
 551        const struct samsung_pll_rate_table *rate;
 552        u32 con0, con1, lock;
 553        ktime_t start;
 554
 555        /* Get required rate settings from table */
 556        rate = samsung_get_pll_settings(pll, drate);
 557        if (!rate) {
 558                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
 559                        drate, clk_hw_get_name(hw));
 560                return -EINVAL;
 561        }
 562
 563        con0 = __raw_readl(pll->con_reg);
 564        con1 = __raw_readl(pll->con_reg + 0x4);
 565
 566        if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) {
 567                /* If only s change, change just s value only*/
 568                con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
 569                con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT;
 570                __raw_writel(con0, pll->con_reg);
 571
 572                return 0;
 573        }
 574
 575        /* Set PLL lock time. */
 576        lock = rate->pdiv * PLL46XX_LOCK_FACTOR;
 577        if (lock > 0xffff)
 578                /* Maximum lock time bitfield is 16-bit. */
 579                lock = 0xffff;
 580
 581        /* Set PLL PMS and VSEL values. */
 582        if (pll->type == pll_1460x) {
 583                con0 &= ~((PLL1460X_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
 584                        (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
 585                        (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT));
 586        } else {
 587                con0 &= ~((PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
 588                        (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
 589                        (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) |
 590                        (PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT));
 591                con0 |= rate->vsel << PLL46XX_VSEL_SHIFT;
 592        }
 593
 594        con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) |
 595                        (rate->pdiv << PLL46XX_PDIV_SHIFT) |
 596                        (rate->sdiv << PLL46XX_SDIV_SHIFT);
 597
 598        /* Set PLL K, MFR and MRR values. */
 599        con1 = __raw_readl(pll->con_reg + 0x4);
 600        con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) |
 601                        (PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) |
 602                        (PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT));
 603        con1 |= (rate->kdiv << PLL46XX_KDIV_SHIFT) |
 604                        (rate->mfr << PLL46XX_MFR_SHIFT) |
 605                        (rate->mrr << PLL46XX_MRR_SHIFT);
 606
 607        /* Write configuration to PLL */
 608        __raw_writel(lock, pll->lock_reg);
 609        __raw_writel(con0, pll->con_reg);
 610        __raw_writel(con1, pll->con_reg + 0x4);
 611
 612        /* Wait for locking. */
 613        start = ktime_get();
 614        while (!(__raw_readl(pll->con_reg) & PLL46XX_LOCKED)) {
 615                ktime_t delta = ktime_sub(ktime_get(), start);
 616
 617                if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
 618                        pr_err("%s: could not lock PLL %s\n",
 619                                        __func__, clk_hw_get_name(hw));
 620                        return -EFAULT;
 621                }
 622
 623                cpu_relax();
 624        }
 625
 626        return 0;
 627}
 628
 629static const struct clk_ops samsung_pll46xx_clk_ops = {
 630        .recalc_rate = samsung_pll46xx_recalc_rate,
 631        .round_rate = samsung_pll_round_rate,
 632        .set_rate = samsung_pll46xx_set_rate,
 633};
 634
 635static const struct clk_ops samsung_pll46xx_clk_min_ops = {
 636        .recalc_rate = samsung_pll46xx_recalc_rate,
 637};
 638
 639/*
 640 * PLL6552 Clock Type
 641 */
 642
 643#define PLL6552_MDIV_MASK       0x3ff
 644#define PLL6552_PDIV_MASK       0x3f
 645#define PLL6552_SDIV_MASK       0x7
 646#define PLL6552_MDIV_SHIFT      16
 647#define PLL6552_MDIV_SHIFT_2416 14
 648#define PLL6552_PDIV_SHIFT      8
 649#define PLL6552_PDIV_SHIFT_2416 5
 650#define PLL6552_SDIV_SHIFT      0
 651
 652static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
 653                                                unsigned long parent_rate)
 654{
 655        struct samsung_clk_pll *pll = to_clk_pll(hw);
 656        u32 mdiv, pdiv, sdiv, pll_con;
 657        u64 fvco = parent_rate;
 658
 659        pll_con = __raw_readl(pll->con_reg);
 660        if (pll->type == pll_6552_s3c2416) {
 661                mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK;
 662                pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK;
 663        } else {
 664                mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK;
 665                pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK;
 666        }
 667        sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK;
 668
 669        fvco *= mdiv;
 670        do_div(fvco, (pdiv << sdiv));
 671
 672        return (unsigned long)fvco;
 673}
 674
 675static const struct clk_ops samsung_pll6552_clk_ops = {
 676        .recalc_rate = samsung_pll6552_recalc_rate,
 677};
 678
 679/*
 680 * PLL6553 Clock Type
 681 */
 682
 683#define PLL6553_MDIV_MASK       0xff
 684#define PLL6553_PDIV_MASK       0x3f
 685#define PLL6553_SDIV_MASK       0x7
 686#define PLL6553_KDIV_MASK       0xffff
 687#define PLL6553_MDIV_SHIFT      16
 688#define PLL6553_PDIV_SHIFT      8
 689#define PLL6553_SDIV_SHIFT      0
 690#define PLL6553_KDIV_SHIFT      0
 691
 692static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
 693                                                unsigned long parent_rate)
 694{
 695        struct samsung_clk_pll *pll = to_clk_pll(hw);
 696        u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
 697        u64 fvco = parent_rate;
 698
 699        pll_con0 = __raw_readl(pll->con_reg);
 700        pll_con1 = __raw_readl(pll->con_reg + 0x4);
 701        mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK;
 702        pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK;
 703        sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK;
 704        kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK;
 705
 706        fvco *= (mdiv << 16) + kdiv;
 707        do_div(fvco, (pdiv << sdiv));
 708        fvco >>= 16;
 709
 710        return (unsigned long)fvco;
 711}
 712
 713static const struct clk_ops samsung_pll6553_clk_ops = {
 714        .recalc_rate = samsung_pll6553_recalc_rate,
 715};
 716
 717/*
 718 * PLL Clock Type of S3C24XX before S3C2443
 719 */
 720
 721#define PLLS3C2410_MDIV_MASK            (0xff)
 722#define PLLS3C2410_PDIV_MASK            (0x1f)
 723#define PLLS3C2410_SDIV_MASK            (0x3)
 724#define PLLS3C2410_MDIV_SHIFT           (12)
 725#define PLLS3C2410_PDIV_SHIFT           (4)
 726#define PLLS3C2410_SDIV_SHIFT           (0)
 727
 728#define PLLS3C2410_ENABLE_REG_OFFSET    0x10
 729
 730static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
 731                                        unsigned long parent_rate)
 732{
 733        struct samsung_clk_pll *pll = to_clk_pll(hw);
 734        u32 pll_con, mdiv, pdiv, sdiv;
 735        u64 fvco = parent_rate;
 736
 737        pll_con = __raw_readl(pll->con_reg);
 738        mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
 739        pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
 740        sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
 741
 742        fvco *= (mdiv + 8);
 743        do_div(fvco, (pdiv + 2) << sdiv);
 744
 745        return (unsigned int)fvco;
 746}
 747
 748static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
 749                                        unsigned long parent_rate)
 750{
 751        struct samsung_clk_pll *pll = to_clk_pll(hw);
 752        u32 pll_con, mdiv, pdiv, sdiv;
 753        u64 fvco = parent_rate;
 754
 755        pll_con = __raw_readl(pll->con_reg);
 756        mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
 757        pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
 758        sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
 759
 760        fvco *= (2 * (mdiv + 8));
 761        do_div(fvco, (pdiv + 2) << sdiv);
 762
 763        return (unsigned int)fvco;
 764}
 765
 766static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
 767                                        unsigned long prate)
 768{
 769        struct samsung_clk_pll *pll = to_clk_pll(hw);
 770        const struct samsung_pll_rate_table *rate;
 771        u32 tmp;
 772
 773        /* Get required rate settings from table */
 774        rate = samsung_get_pll_settings(pll, drate);
 775        if (!rate) {
 776                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
 777                        drate, clk_hw_get_name(hw));
 778                return -EINVAL;
 779        }
 780
 781        tmp = __raw_readl(pll->con_reg);
 782
 783        /* Change PLL PMS values */
 784        tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) |
 785                        (PLLS3C2410_PDIV_MASK << PLLS3C2410_PDIV_SHIFT) |
 786                        (PLLS3C2410_SDIV_MASK << PLLS3C2410_SDIV_SHIFT));
 787        tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) |
 788                        (rate->pdiv << PLLS3C2410_PDIV_SHIFT) |
 789                        (rate->sdiv << PLLS3C2410_SDIV_SHIFT);
 790        __raw_writel(tmp, pll->con_reg);
 791
 792        /* Time to settle according to the manual */
 793        udelay(300);
 794
 795        return 0;
 796}
 797
 798static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
 799{
 800        struct samsung_clk_pll *pll = to_clk_pll(hw);
 801        u32 pll_en = __raw_readl(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
 802        u32 pll_en_orig = pll_en;
 803
 804        if (enable)
 805                pll_en &= ~BIT(bit);
 806        else
 807                pll_en |= BIT(bit);
 808
 809        __raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
 810
 811        /* if we started the UPLL, then allow to settle */
 812        if (enable && (pll_en_orig & BIT(bit)))
 813                udelay(300);
 814
 815        return 0;
 816}
 817
 818static int samsung_s3c2410_mpll_enable(struct clk_hw *hw)
 819{
 820        return samsung_s3c2410_pll_enable(hw, 5, true);
 821}
 822
 823static void samsung_s3c2410_mpll_disable(struct clk_hw *hw)
 824{
 825        samsung_s3c2410_pll_enable(hw, 5, false);
 826}
 827
 828static int samsung_s3c2410_upll_enable(struct clk_hw *hw)
 829{
 830        return samsung_s3c2410_pll_enable(hw, 7, true);
 831}
 832
 833static void samsung_s3c2410_upll_disable(struct clk_hw *hw)
 834{
 835        samsung_s3c2410_pll_enable(hw, 7, false);
 836}
 837
 838static const struct clk_ops samsung_s3c2410_mpll_clk_min_ops = {
 839        .recalc_rate = samsung_s3c2410_pll_recalc_rate,
 840        .enable = samsung_s3c2410_mpll_enable,
 841        .disable = samsung_s3c2410_mpll_disable,
 842};
 843
 844static const struct clk_ops samsung_s3c2410_upll_clk_min_ops = {
 845        .recalc_rate = samsung_s3c2410_pll_recalc_rate,
 846        .enable = samsung_s3c2410_upll_enable,
 847        .disable = samsung_s3c2410_upll_disable,
 848};
 849
 850static const struct clk_ops samsung_s3c2440_mpll_clk_min_ops = {
 851        .recalc_rate = samsung_s3c2440_mpll_recalc_rate,
 852        .enable = samsung_s3c2410_mpll_enable,
 853        .disable = samsung_s3c2410_mpll_disable,
 854};
 855
 856static const struct clk_ops samsung_s3c2410_mpll_clk_ops = {
 857        .recalc_rate = samsung_s3c2410_pll_recalc_rate,
 858        .enable = samsung_s3c2410_mpll_enable,
 859        .disable = samsung_s3c2410_mpll_disable,
 860        .round_rate = samsung_pll_round_rate,
 861        .set_rate = samsung_s3c2410_pll_set_rate,
 862};
 863
 864static const struct clk_ops samsung_s3c2410_upll_clk_ops = {
 865        .recalc_rate = samsung_s3c2410_pll_recalc_rate,
 866        .enable = samsung_s3c2410_upll_enable,
 867        .disable = samsung_s3c2410_upll_disable,
 868        .round_rate = samsung_pll_round_rate,
 869        .set_rate = samsung_s3c2410_pll_set_rate,
 870};
 871
 872static const struct clk_ops samsung_s3c2440_mpll_clk_ops = {
 873        .recalc_rate = samsung_s3c2440_mpll_recalc_rate,
 874        .enable = samsung_s3c2410_mpll_enable,
 875        .disable = samsung_s3c2410_mpll_disable,
 876        .round_rate = samsung_pll_round_rate,
 877        .set_rate = samsung_s3c2410_pll_set_rate,
 878};
 879
 880/*
 881 * PLL2550x Clock Type
 882 */
 883
 884#define PLL2550X_R_MASK       (0x1)
 885#define PLL2550X_P_MASK       (0x3F)
 886#define PLL2550X_M_MASK       (0x3FF)
 887#define PLL2550X_S_MASK       (0x7)
 888#define PLL2550X_R_SHIFT      (20)
 889#define PLL2550X_P_SHIFT      (14)
 890#define PLL2550X_M_SHIFT      (4)
 891#define PLL2550X_S_SHIFT      (0)
 892
 893struct samsung_clk_pll2550x {
 894        struct clk_hw           hw;
 895        const void __iomem      *reg_base;
 896        unsigned long           offset;
 897};
 898
 899#define to_clk_pll2550x(_hw) container_of(_hw, struct samsung_clk_pll2550x, hw)
 900
 901static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
 902                                unsigned long parent_rate)
 903{
 904        struct samsung_clk_pll2550x *pll = to_clk_pll2550x(hw);
 905        u32 r, p, m, s, pll_stat;
 906        u64 fvco = parent_rate;
 907
 908        pll_stat = __raw_readl(pll->reg_base + pll->offset * 3);
 909        r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
 910        if (!r)
 911                return 0;
 912        p = (pll_stat >> PLL2550X_P_SHIFT) & PLL2550X_P_MASK;
 913        m = (pll_stat >> PLL2550X_M_SHIFT) & PLL2550X_M_MASK;
 914        s = (pll_stat >> PLL2550X_S_SHIFT) & PLL2550X_S_MASK;
 915
 916        fvco *= m;
 917        do_div(fvco, (p << s));
 918
 919        return (unsigned long)fvco;
 920}
 921
 922static const struct clk_ops samsung_pll2550x_clk_ops = {
 923        .recalc_rate = samsung_pll2550x_recalc_rate,
 924};
 925
 926struct clk * __init samsung_clk_register_pll2550x(const char *name,
 927                        const char *pname, const void __iomem *reg_base,
 928                        const unsigned long offset)
 929{
 930        struct samsung_clk_pll2550x *pll;
 931        struct clk *clk;
 932        struct clk_init_data init;
 933
 934        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 935        if (!pll) {
 936                pr_err("%s: could not allocate pll clk %s\n", __func__, name);
 937                return NULL;
 938        }
 939
 940        init.name = name;
 941        init.ops = &samsung_pll2550x_clk_ops;
 942        init.flags = CLK_GET_RATE_NOCACHE;
 943        init.parent_names = &pname;
 944        init.num_parents = 1;
 945
 946        pll->hw.init = &init;
 947        pll->reg_base = reg_base;
 948        pll->offset = offset;
 949
 950        clk = clk_register(NULL, &pll->hw);
 951        if (IS_ERR(clk)) {
 952                pr_err("%s: failed to register pll clock %s\n", __func__,
 953                                name);
 954                kfree(pll);
 955        }
 956
 957        if (clk_register_clkdev(clk, name, NULL))
 958                pr_err("%s: failed to register lookup for %s", __func__, name);
 959
 960        return clk;
 961}
 962
 963/*
 964 * PLL2550xx Clock Type
 965 */
 966
 967/* Maximum lock time can be 270 * PDIV cycles */
 968#define PLL2550XX_LOCK_FACTOR 270
 969
 970#define PLL2550XX_M_MASK                0x3FF
 971#define PLL2550XX_P_MASK                0x3F
 972#define PLL2550XX_S_MASK                0x7
 973#define PLL2550XX_LOCK_STAT_MASK        0x1
 974#define PLL2550XX_M_SHIFT               9
 975#define PLL2550XX_P_SHIFT               3
 976#define PLL2550XX_S_SHIFT               0
 977#define PLL2550XX_LOCK_STAT_SHIFT       21
 978
 979static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw,
 980                                unsigned long parent_rate)
 981{
 982        struct samsung_clk_pll *pll = to_clk_pll(hw);
 983        u32 mdiv, pdiv, sdiv, pll_con;
 984        u64 fvco = parent_rate;
 985
 986        pll_con = __raw_readl(pll->con_reg);
 987        mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
 988        pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
 989        sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK;
 990
 991        fvco *= mdiv;
 992        do_div(fvco, (pdiv << sdiv));
 993
 994        return (unsigned long)fvco;
 995}
 996
 997static inline bool samsung_pll2550xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con)
 998{
 999        u32 old_mdiv, old_pdiv;
1000
1001        old_mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
1002        old_pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
1003
1004        return mdiv != old_mdiv || pdiv != old_pdiv;
1005}
1006
1007static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
1008                                        unsigned long prate)
1009{
1010        struct samsung_clk_pll *pll = to_clk_pll(hw);
1011        const struct samsung_pll_rate_table *rate;
1012        u32 tmp;
1013
1014        /* Get required rate settings from table */
1015        rate = samsung_get_pll_settings(pll, drate);
1016        if (!rate) {
1017                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
1018                        drate, clk_hw_get_name(hw));
1019                return -EINVAL;
1020        }
1021
1022        tmp = __raw_readl(pll->con_reg);
1023
1024        if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) {
1025                /* If only s change, change just s value only*/
1026                tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT);
1027                tmp |= rate->sdiv << PLL2550XX_S_SHIFT;
1028                __raw_writel(tmp, pll->con_reg);
1029
1030                return 0;
1031        }
1032
1033        /* Set PLL lock time. */
1034        __raw_writel(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
1035
1036        /* Change PLL PMS values */
1037        tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) |
1038                        (PLL2550XX_P_MASK << PLL2550XX_P_SHIFT) |
1039                        (PLL2550XX_S_MASK << PLL2550XX_S_SHIFT));
1040        tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) |
1041                        (rate->pdiv << PLL2550XX_P_SHIFT) |
1042                        (rate->sdiv << PLL2550XX_S_SHIFT);
1043        __raw_writel(tmp, pll->con_reg);
1044
1045        /* wait_lock_time */
1046        do {
1047                cpu_relax();
1048                tmp = __raw_readl(pll->con_reg);
1049        } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK
1050                        << PLL2550XX_LOCK_STAT_SHIFT)));
1051
1052        return 0;
1053}
1054
1055static const struct clk_ops samsung_pll2550xx_clk_ops = {
1056        .recalc_rate = samsung_pll2550xx_recalc_rate,
1057        .round_rate = samsung_pll_round_rate,
1058        .set_rate = samsung_pll2550xx_set_rate,
1059};
1060
1061static const struct clk_ops samsung_pll2550xx_clk_min_ops = {
1062        .recalc_rate = samsung_pll2550xx_recalc_rate,
1063};
1064
1065/*
1066 * PLL2650XX Clock Type
1067 */
1068
1069/* Maximum lock time can be 3000 * PDIV cycles */
1070#define PLL2650XX_LOCK_FACTOR 3000
1071
1072#define PLL2650XX_MDIV_SHIFT            9
1073#define PLL2650XX_PDIV_SHIFT            3
1074#define PLL2650XX_SDIV_SHIFT            0
1075#define PLL2650XX_KDIV_SHIFT            0
1076#define PLL2650XX_MDIV_MASK             0x1ff
1077#define PLL2650XX_PDIV_MASK             0x3f
1078#define PLL2650XX_SDIV_MASK             0x7
1079#define PLL2650XX_KDIV_MASK             0xffff
1080#define PLL2650XX_PLL_ENABLE_SHIFT      23
1081#define PLL2650XX_PLL_LOCKTIME_SHIFT    21
1082#define PLL2650XX_PLL_FOUTMASK_SHIFT    31
1083
1084static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw,
1085                                unsigned long parent_rate)
1086{
1087        struct samsung_clk_pll *pll = to_clk_pll(hw);
1088        u32 mdiv, pdiv, sdiv, pll_con0, pll_con2;
1089        s16 kdiv;
1090        u64 fvco = parent_rate;
1091
1092        pll_con0 = __raw_readl(pll->con_reg);
1093        pll_con2 = __raw_readl(pll->con_reg + 8);
1094        mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK;
1095        pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK;
1096        sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK;
1097        kdiv = (s16)(pll_con2 & PLL2650XX_KDIV_MASK);
1098
1099        fvco *= (mdiv << 16) + kdiv;
1100        do_div(fvco, (pdiv << sdiv));
1101        fvco >>= 16;
1102
1103        return (unsigned long)fvco;
1104}
1105
1106static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
1107                                        unsigned long parent_rate)
1108{
1109        struct samsung_clk_pll *pll = to_clk_pll(hw);
1110        u32 tmp, pll_con0, pll_con2;
1111        const struct samsung_pll_rate_table *rate;
1112
1113        rate = samsung_get_pll_settings(pll, drate);
1114        if (!rate) {
1115                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
1116                        drate, clk_hw_get_name(hw));
1117                return -EINVAL;
1118        }
1119
1120        pll_con0 = __raw_readl(pll->con_reg);
1121        pll_con2 = __raw_readl(pll->con_reg + 8);
1122
1123         /* Change PLL PMS values */
1124        pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT |
1125                        PLL2650XX_PDIV_MASK << PLL2650XX_PDIV_SHIFT |
1126                        PLL2650XX_SDIV_MASK << PLL2650XX_SDIV_SHIFT);
1127        pll_con0 |= rate->mdiv << PLL2650XX_MDIV_SHIFT;
1128        pll_con0 |= rate->pdiv << PLL2650XX_PDIV_SHIFT;
1129        pll_con0 |= rate->sdiv << PLL2650XX_SDIV_SHIFT;
1130        pll_con0 |= 1 << PLL2650XX_PLL_ENABLE_SHIFT;
1131        pll_con0 |= 1 << PLL2650XX_PLL_FOUTMASK_SHIFT;
1132
1133        pll_con2 &= ~(PLL2650XX_KDIV_MASK << PLL2650XX_KDIV_SHIFT);
1134        pll_con2 |= ((~(rate->kdiv) + 1) & PLL2650XX_KDIV_MASK)
1135                        << PLL2650XX_KDIV_SHIFT;
1136
1137        /* Set PLL lock time. */
1138        __raw_writel(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
1139
1140        __raw_writel(pll_con0, pll->con_reg);
1141        __raw_writel(pll_con2, pll->con_reg + 8);
1142
1143        do {
1144                tmp = __raw_readl(pll->con_reg);
1145        } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT)));
1146
1147        return 0;
1148}
1149
1150static const struct clk_ops samsung_pll2650xx_clk_ops = {
1151        .recalc_rate = samsung_pll2650xx_recalc_rate,
1152        .set_rate = samsung_pll2650xx_set_rate,
1153        .round_rate = samsung_pll_round_rate,
1154};
1155
1156static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
1157        .recalc_rate = samsung_pll2650xx_recalc_rate,
1158};
1159
1160static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
1161                                const struct samsung_pll_clock *pll_clk,
1162                                void __iomem *base)
1163{
1164        struct samsung_clk_pll *pll;
1165        struct clk *clk;
1166        struct clk_init_data init;
1167        int ret, len;
1168
1169        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
1170        if (!pll) {
1171                pr_err("%s: could not allocate pll clk %s\n",
1172                        __func__, pll_clk->name);
1173                return;
1174        }
1175
1176        init.name = pll_clk->name;
1177        init.flags = pll_clk->flags;
1178        init.parent_names = &pll_clk->parent_name;
1179        init.num_parents = 1;
1180
1181        if (pll_clk->rate_table) {
1182                /* find count of rates in rate_table */
1183                for (len = 0; pll_clk->rate_table[len].rate != 0; )
1184                        len++;
1185
1186                pll->rate_count = len;
1187                pll->rate_table = kmemdup(pll_clk->rate_table,
1188                                        pll->rate_count *
1189                                        sizeof(struct samsung_pll_rate_table),
1190                                        GFP_KERNEL);
1191                WARN(!pll->rate_table,
1192                        "%s: could not allocate rate table for %s\n",
1193                        __func__, pll_clk->name);
1194        }
1195
1196        switch (pll_clk->type) {
1197        case pll_2126:
1198                init.ops = &samsung_pll2126_clk_ops;
1199                break;
1200        case pll_3000:
1201                init.ops = &samsung_pll3000_clk_ops;
1202                break;
1203        /* clk_ops for 35xx and 2550 are similar */
1204        case pll_35xx:
1205        case pll_2550:
1206        case pll_1450x:
1207        case pll_1451x:
1208        case pll_1452x:
1209                if (!pll->rate_table)
1210                        init.ops = &samsung_pll35xx_clk_min_ops;
1211                else
1212                        init.ops = &samsung_pll35xx_clk_ops;
1213                break;
1214        case pll_4500:
1215                init.ops = &samsung_pll45xx_clk_min_ops;
1216                break;
1217        case pll_4502:
1218        case pll_4508:
1219                if (!pll->rate_table)
1220                        init.ops = &samsung_pll45xx_clk_min_ops;
1221                else
1222                        init.ops = &samsung_pll45xx_clk_ops;
1223                break;
1224        /* clk_ops for 36xx and 2650 are similar */
1225        case pll_36xx:
1226        case pll_2650:
1227                if (!pll->rate_table)
1228                        init.ops = &samsung_pll36xx_clk_min_ops;
1229                else
1230                        init.ops = &samsung_pll36xx_clk_ops;
1231                break;
1232        case pll_6552:
1233        case pll_6552_s3c2416:
1234                init.ops = &samsung_pll6552_clk_ops;
1235                break;
1236        case pll_6553:
1237                init.ops = &samsung_pll6553_clk_ops;
1238                break;
1239        case pll_4600:
1240        case pll_4650:
1241        case pll_4650c:
1242        case pll_1460x:
1243                if (!pll->rate_table)
1244                        init.ops = &samsung_pll46xx_clk_min_ops;
1245                else
1246                        init.ops = &samsung_pll46xx_clk_ops;
1247                break;
1248        case pll_s3c2410_mpll:
1249                if (!pll->rate_table)
1250                        init.ops = &samsung_s3c2410_mpll_clk_min_ops;
1251                else
1252                        init.ops = &samsung_s3c2410_mpll_clk_ops;
1253                break;
1254        case pll_s3c2410_upll:
1255                if (!pll->rate_table)
1256                        init.ops = &samsung_s3c2410_upll_clk_min_ops;
1257                else
1258                        init.ops = &samsung_s3c2410_upll_clk_ops;
1259                break;
1260        case pll_s3c2440_mpll:
1261                if (!pll->rate_table)
1262                        init.ops = &samsung_s3c2440_mpll_clk_min_ops;
1263                else
1264                        init.ops = &samsung_s3c2440_mpll_clk_ops;
1265                break;
1266        case pll_2550xx:
1267                if (!pll->rate_table)
1268                        init.ops = &samsung_pll2550xx_clk_min_ops;
1269                else
1270                        init.ops = &samsung_pll2550xx_clk_ops;
1271                break;
1272        case pll_2650xx:
1273                if (!pll->rate_table)
1274                        init.ops = &samsung_pll2650xx_clk_min_ops;
1275                else
1276                        init.ops = &samsung_pll2650xx_clk_ops;
1277                break;
1278        default:
1279                pr_warn("%s: Unknown pll type for pll clk %s\n",
1280                        __func__, pll_clk->name);
1281        }
1282
1283        pll->hw.init = &init;
1284        pll->type = pll_clk->type;
1285        pll->lock_reg = base + pll_clk->lock_offset;
1286        pll->con_reg = base + pll_clk->con_offset;
1287
1288        clk = clk_register(NULL, &pll->hw);
1289        if (IS_ERR(clk)) {
1290                pr_err("%s: failed to register pll clock %s : %ld\n",
1291                        __func__, pll_clk->name, PTR_ERR(clk));
1292                kfree(pll);
1293                return;
1294        }
1295
1296        samsung_clk_add_lookup(ctx, clk, pll_clk->id);
1297
1298        if (!pll_clk->alias)
1299                return;
1300
1301        ret = clk_register_clkdev(clk, pll_clk->alias, pll_clk->dev_name);
1302        if (ret)
1303                pr_err("%s: failed to register lookup for %s : %d",
1304                        __func__, pll_clk->name, ret);
1305}
1306
1307void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
1308                        const struct samsung_pll_clock *pll_list,
1309                        unsigned int nr_pll, void __iomem *base)
1310{
1311        int cnt;
1312
1313        for (cnt = 0; cnt < nr_pll; cnt++)
1314                _samsung_clk_register_pll(ctx, &pll_list[cnt], base);
1315}
1316