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