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