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