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