linux/drivers/clk/pistachio/clk-pll.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2014 Google, Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 */
   8
   9#define pr_fmt(fmt) "%s: " fmt, __func__
  10
  11#include <linux/clk-provider.h>
  12#include <linux/io.h>
  13#include <linux/kernel.h>
  14#include <linux/printk.h>
  15#include <linux/slab.h>
  16
  17#include "clk.h"
  18
  19#define PLL_STATUS                      0x0
  20#define PLL_STATUS_LOCK                 BIT(0)
  21
  22#define PLL_CTRL1                       0x4
  23#define PLL_CTRL1_REFDIV_SHIFT          0
  24#define PLL_CTRL1_REFDIV_MASK           0x3f
  25#define PLL_CTRL1_FBDIV_SHIFT           6
  26#define PLL_CTRL1_FBDIV_MASK            0xfff
  27#define PLL_INT_CTRL1_POSTDIV1_SHIFT    18
  28#define PLL_INT_CTRL1_POSTDIV1_MASK     0x7
  29#define PLL_INT_CTRL1_POSTDIV2_SHIFT    21
  30#define PLL_INT_CTRL1_POSTDIV2_MASK     0x7
  31#define PLL_INT_CTRL1_PD                BIT(24)
  32#define PLL_INT_CTRL1_DSMPD             BIT(25)
  33#define PLL_INT_CTRL1_FOUTPOSTDIVPD     BIT(26)
  34#define PLL_INT_CTRL1_FOUTVCOPD         BIT(27)
  35
  36#define PLL_CTRL2                       0x8
  37#define PLL_FRAC_CTRL2_FRAC_SHIFT       0
  38#define PLL_FRAC_CTRL2_FRAC_MASK        0xffffff
  39#define PLL_FRAC_CTRL2_POSTDIV1_SHIFT   24
  40#define PLL_FRAC_CTRL2_POSTDIV1_MASK    0x7
  41#define PLL_FRAC_CTRL2_POSTDIV2_SHIFT   27
  42#define PLL_FRAC_CTRL2_POSTDIV2_MASK    0x7
  43#define PLL_INT_CTRL2_BYPASS            BIT(28)
  44
  45#define PLL_CTRL3                       0xc
  46#define PLL_FRAC_CTRL3_PD               BIT(0)
  47#define PLL_FRAC_CTRL3_DACPD            BIT(1)
  48#define PLL_FRAC_CTRL3_DSMPD            BIT(2)
  49#define PLL_FRAC_CTRL3_FOUTPOSTDIVPD    BIT(3)
  50#define PLL_FRAC_CTRL3_FOUT4PHASEPD     BIT(4)
  51#define PLL_FRAC_CTRL3_FOUTVCOPD        BIT(5)
  52
  53#define PLL_CTRL4                       0x10
  54#define PLL_FRAC_CTRL4_BYPASS           BIT(28)
  55
  56#define MIN_PFD                         9600000UL
  57#define MIN_VCO_LA                      400000000UL
  58#define MAX_VCO_LA                      1600000000UL
  59#define MIN_VCO_FRAC_INT                600000000UL
  60#define MAX_VCO_FRAC_INT                1600000000UL
  61#define MIN_VCO_FRAC_FRAC               600000000UL
  62#define MAX_VCO_FRAC_FRAC               2400000000UL
  63#define MIN_OUTPUT_LA                   8000000UL
  64#define MAX_OUTPUT_LA                   1600000000UL
  65#define MIN_OUTPUT_FRAC                 12000000UL
  66#define MAX_OUTPUT_FRAC                 1600000000UL
  67
  68/* Fractional PLL operating modes */
  69enum pll_mode {
  70        PLL_MODE_FRAC,
  71        PLL_MODE_INT,
  72};
  73
  74struct pistachio_clk_pll {
  75        struct clk_hw hw;
  76        void __iomem *base;
  77        struct pistachio_pll_rate_table *rates;
  78        unsigned int nr_rates;
  79};
  80
  81static inline u32 pll_readl(struct pistachio_clk_pll *pll, u32 reg)
  82{
  83        return readl(pll->base + reg);
  84}
  85
  86static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg)
  87{
  88        writel(val, pll->base + reg);
  89}
  90
  91static inline void pll_lock(struct pistachio_clk_pll *pll)
  92{
  93        while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
  94                cpu_relax();
  95}
  96
  97static inline u64 do_div_round_closest(u64 dividend, u64 divisor)
  98{
  99        dividend += divisor / 2;
 100        return div64_u64(dividend, divisor);
 101}
 102
 103static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw)
 104{
 105        return container_of(hw, struct pistachio_clk_pll, hw);
 106}
 107
 108static inline enum pll_mode pll_frac_get_mode(struct clk_hw *hw)
 109{
 110        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 111        u32 val;
 112
 113        val = pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_DSMPD;
 114        return val ? PLL_MODE_INT : PLL_MODE_FRAC;
 115}
 116
 117static inline void pll_frac_set_mode(struct clk_hw *hw, enum pll_mode mode)
 118{
 119        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 120        u32 val;
 121
 122        val = pll_readl(pll, PLL_CTRL3);
 123        if (mode == PLL_MODE_INT)
 124                val |= PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD;
 125        else
 126                val &= ~(PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD);
 127
 128        pll_writel(pll, val, PLL_CTRL3);
 129}
 130
 131static struct pistachio_pll_rate_table *
 132pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref,
 133               unsigned long fout)
 134{
 135        unsigned int i;
 136
 137        for (i = 0; i < pll->nr_rates; i++) {
 138                if (pll->rates[i].fref == fref && pll->rates[i].fout == fout)
 139                        return &pll->rates[i];
 140        }
 141
 142        return NULL;
 143}
 144
 145static long pll_round_rate(struct clk_hw *hw, unsigned long rate,
 146                           unsigned long *parent_rate)
 147{
 148        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 149        unsigned int i;
 150
 151        for (i = 0; i < pll->nr_rates; i++) {
 152                if (i > 0 && pll->rates[i].fref == *parent_rate &&
 153                    pll->rates[i].fout <= rate)
 154                        return pll->rates[i - 1].fout;
 155        }
 156
 157        return pll->rates[0].fout;
 158}
 159
 160static int pll_gf40lp_frac_enable(struct clk_hw *hw)
 161{
 162        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 163        u32 val;
 164
 165        val = pll_readl(pll, PLL_CTRL3);
 166        val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD |
 167                 PLL_FRAC_CTRL3_FOUT4PHASEPD | PLL_FRAC_CTRL3_FOUTVCOPD);
 168        pll_writel(pll, val, PLL_CTRL3);
 169
 170        val = pll_readl(pll, PLL_CTRL4);
 171        val &= ~PLL_FRAC_CTRL4_BYPASS;
 172        pll_writel(pll, val, PLL_CTRL4);
 173
 174        pll_lock(pll);
 175
 176        return 0;
 177}
 178
 179static void pll_gf40lp_frac_disable(struct clk_hw *hw)
 180{
 181        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 182        u32 val;
 183
 184        val = pll_readl(pll, PLL_CTRL3);
 185        val |= PLL_FRAC_CTRL3_PD;
 186        pll_writel(pll, val, PLL_CTRL3);
 187}
 188
 189static int pll_gf40lp_frac_is_enabled(struct clk_hw *hw)
 190{
 191        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 192
 193        return !(pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_PD);
 194}
 195
 196static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
 197                                    unsigned long parent_rate)
 198{
 199        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 200        struct pistachio_pll_rate_table *params;
 201        int enabled = pll_gf40lp_frac_is_enabled(hw);
 202        u64 val, vco, old_postdiv1, old_postdiv2;
 203        const char *name = clk_hw_get_name(hw);
 204
 205        if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC)
 206                return -EINVAL;
 207
 208        params = pll_get_params(pll, parent_rate, rate);
 209        if (!params || !params->refdiv)
 210                return -EINVAL;
 211
 212        /* calculate vco */
 213        vco = params->fref;
 214        vco *= (params->fbdiv << 24) + params->frac;
 215        vco = div64_u64(vco, params->refdiv << 24);
 216
 217        if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC)
 218                pr_warn("%s: VCO %llu is out of range %lu..%lu\n", name, vco,
 219                        MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC);
 220
 221        val = div64_u64(params->fref, params->refdiv);
 222        if (val < MIN_PFD)
 223                pr_warn("%s: PFD %llu is too low (min %lu)\n",
 224                        name, val, MIN_PFD);
 225        if (val > vco / 16)
 226                pr_warn("%s: PFD %llu is too high (max %llu)\n",
 227                        name, val, vco / 16);
 228
 229        val = pll_readl(pll, PLL_CTRL1);
 230        val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
 231                 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT));
 232        val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) |
 233                (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT);
 234        pll_writel(pll, val, PLL_CTRL1);
 235
 236        val = pll_readl(pll, PLL_CTRL2);
 237
 238        old_postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
 239                       PLL_FRAC_CTRL2_POSTDIV1_MASK;
 240        old_postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
 241                       PLL_FRAC_CTRL2_POSTDIV2_MASK;
 242        if (enabled &&
 243            (params->postdiv1 != old_postdiv1 ||
 244             params->postdiv2 != old_postdiv2))
 245                pr_warn("%s: changing postdiv while PLL is enabled\n", name);
 246
 247        if (params->postdiv2 > params->postdiv1)
 248                pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
 249
 250        val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) |
 251                 (PLL_FRAC_CTRL2_POSTDIV1_MASK <<
 252                  PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
 253                 (PLL_FRAC_CTRL2_POSTDIV2_MASK <<
 254                  PLL_FRAC_CTRL2_POSTDIV2_SHIFT));
 255        val |= (params->frac << PLL_FRAC_CTRL2_FRAC_SHIFT) |
 256                (params->postdiv1 << PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
 257                (params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
 258        pll_writel(pll, val, PLL_CTRL2);
 259
 260        /* set operating mode */
 261        if (params->frac)
 262                pll_frac_set_mode(hw, PLL_MODE_FRAC);
 263        else
 264                pll_frac_set_mode(hw, PLL_MODE_INT);
 265
 266        if (enabled)
 267                pll_lock(pll);
 268
 269        return 0;
 270}
 271
 272static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw,
 273                                                 unsigned long parent_rate)
 274{
 275        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 276        u64 val, prediv, fbdiv, frac, postdiv1, postdiv2, rate;
 277
 278        val = pll_readl(pll, PLL_CTRL1);
 279        prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK;
 280        fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK;
 281
 282        val = pll_readl(pll, PLL_CTRL2);
 283        postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
 284                PLL_FRAC_CTRL2_POSTDIV1_MASK;
 285        postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
 286                PLL_FRAC_CTRL2_POSTDIV2_MASK;
 287        frac = (val >> PLL_FRAC_CTRL2_FRAC_SHIFT) & PLL_FRAC_CTRL2_FRAC_MASK;
 288
 289        /* get operating mode (int/frac) and calculate rate accordingly */
 290        rate = parent_rate;
 291        if (pll_frac_get_mode(hw) == PLL_MODE_FRAC)
 292                rate *= (fbdiv << 24) + frac;
 293        else
 294                rate *= (fbdiv << 24);
 295
 296        rate = do_div_round_closest(rate, (prediv * postdiv1 * postdiv2) << 24);
 297
 298        return rate;
 299}
 300
 301static struct clk_ops pll_gf40lp_frac_ops = {
 302        .enable = pll_gf40lp_frac_enable,
 303        .disable = pll_gf40lp_frac_disable,
 304        .is_enabled = pll_gf40lp_frac_is_enabled,
 305        .recalc_rate = pll_gf40lp_frac_recalc_rate,
 306        .round_rate = pll_round_rate,
 307        .set_rate = pll_gf40lp_frac_set_rate,
 308};
 309
 310static struct clk_ops pll_gf40lp_frac_fixed_ops = {
 311        .enable = pll_gf40lp_frac_enable,
 312        .disable = pll_gf40lp_frac_disable,
 313        .is_enabled = pll_gf40lp_frac_is_enabled,
 314        .recalc_rate = pll_gf40lp_frac_recalc_rate,
 315};
 316
 317static int pll_gf40lp_laint_enable(struct clk_hw *hw)
 318{
 319        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 320        u32 val;
 321
 322        val = pll_readl(pll, PLL_CTRL1);
 323        val &= ~(PLL_INT_CTRL1_PD |
 324                 PLL_INT_CTRL1_FOUTPOSTDIVPD | PLL_INT_CTRL1_FOUTVCOPD);
 325        pll_writel(pll, val, PLL_CTRL1);
 326
 327        val = pll_readl(pll, PLL_CTRL2);
 328        val &= ~PLL_INT_CTRL2_BYPASS;
 329        pll_writel(pll, val, PLL_CTRL2);
 330
 331        pll_lock(pll);
 332
 333        return 0;
 334}
 335
 336static void pll_gf40lp_laint_disable(struct clk_hw *hw)
 337{
 338        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 339        u32 val;
 340
 341        val = pll_readl(pll, PLL_CTRL1);
 342        val |= PLL_INT_CTRL1_PD;
 343        pll_writel(pll, val, PLL_CTRL1);
 344}
 345
 346static int pll_gf40lp_laint_is_enabled(struct clk_hw *hw)
 347{
 348        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 349
 350        return !(pll_readl(pll, PLL_CTRL1) & PLL_INT_CTRL1_PD);
 351}
 352
 353static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
 354                                     unsigned long parent_rate)
 355{
 356        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 357        struct pistachio_pll_rate_table *params;
 358        int enabled = pll_gf40lp_laint_is_enabled(hw);
 359        u32 val, vco, old_postdiv1, old_postdiv2;
 360        const char *name = clk_hw_get_name(hw);
 361
 362        if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA)
 363                return -EINVAL;
 364
 365        params = pll_get_params(pll, parent_rate, rate);
 366        if (!params || !params->refdiv)
 367                return -EINVAL;
 368
 369        vco = div_u64(params->fref * params->fbdiv, params->refdiv);
 370        if (vco < MIN_VCO_LA || vco > MAX_VCO_LA)
 371                pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
 372                        MIN_VCO_LA, MAX_VCO_LA);
 373
 374        val = div_u64(params->fref, params->refdiv);
 375        if (val < MIN_PFD)
 376                pr_warn("%s: PFD %u is too low (min %lu)\n",
 377                        name, val, MIN_PFD);
 378        if (val > vco / 16)
 379                pr_warn("%s: PFD %u is too high (max %u)\n",
 380                        name, val, vco / 16);
 381
 382        val = pll_readl(pll, PLL_CTRL1);
 383
 384        old_postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
 385                       PLL_INT_CTRL1_POSTDIV1_MASK;
 386        old_postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
 387                       PLL_INT_CTRL1_POSTDIV2_MASK;
 388        if (enabled &&
 389            (params->postdiv1 != old_postdiv1 ||
 390             params->postdiv2 != old_postdiv2))
 391                pr_warn("%s: changing postdiv while PLL is enabled\n", name);
 392
 393        if (params->postdiv2 > params->postdiv1)
 394                pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
 395
 396        val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
 397                 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) |
 398                 (PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) |
 399                 (PLL_INT_CTRL1_POSTDIV2_MASK << PLL_INT_CTRL1_POSTDIV2_SHIFT));
 400        val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) |
 401                (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT) |
 402                (params->postdiv1 << PLL_INT_CTRL1_POSTDIV1_SHIFT) |
 403                (params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT);
 404        pll_writel(pll, val, PLL_CTRL1);
 405
 406        if (enabled)
 407                pll_lock(pll);
 408
 409        return 0;
 410}
 411
 412static unsigned long pll_gf40lp_laint_recalc_rate(struct clk_hw *hw,
 413                                                  unsigned long parent_rate)
 414{
 415        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 416        u32 val, prediv, fbdiv, postdiv1, postdiv2;
 417        u64 rate = parent_rate;
 418
 419        val = pll_readl(pll, PLL_CTRL1);
 420        prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK;
 421        fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK;
 422        postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
 423                PLL_INT_CTRL1_POSTDIV1_MASK;
 424        postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
 425                PLL_INT_CTRL1_POSTDIV2_MASK;
 426
 427        rate *= fbdiv;
 428        rate = do_div_round_closest(rate, prediv * postdiv1 * postdiv2);
 429
 430        return rate;
 431}
 432
 433static struct clk_ops pll_gf40lp_laint_ops = {
 434        .enable = pll_gf40lp_laint_enable,
 435        .disable = pll_gf40lp_laint_disable,
 436        .is_enabled = pll_gf40lp_laint_is_enabled,
 437        .recalc_rate = pll_gf40lp_laint_recalc_rate,
 438        .round_rate = pll_round_rate,
 439        .set_rate = pll_gf40lp_laint_set_rate,
 440};
 441
 442static struct clk_ops pll_gf40lp_laint_fixed_ops = {
 443        .enable = pll_gf40lp_laint_enable,
 444        .disable = pll_gf40lp_laint_disable,
 445        .is_enabled = pll_gf40lp_laint_is_enabled,
 446        .recalc_rate = pll_gf40lp_laint_recalc_rate,
 447};
 448
 449static struct clk *pll_register(const char *name, const char *parent_name,
 450                                unsigned long flags, void __iomem *base,
 451                                enum pistachio_pll_type type,
 452                                struct pistachio_pll_rate_table *rates,
 453                                unsigned int nr_rates)
 454{
 455        struct pistachio_clk_pll *pll;
 456        struct clk_init_data init;
 457        struct clk *clk;
 458
 459        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 460        if (!pll)
 461                return ERR_PTR(-ENOMEM);
 462
 463        init.name = name;
 464        init.flags = flags | CLK_GET_RATE_NOCACHE;
 465        init.parent_names = &parent_name;
 466        init.num_parents = 1;
 467
 468        switch (type) {
 469        case PLL_GF40LP_FRAC:
 470                if (rates)
 471                        init.ops = &pll_gf40lp_frac_ops;
 472                else
 473                        init.ops = &pll_gf40lp_frac_fixed_ops;
 474                break;
 475        case PLL_GF40LP_LAINT:
 476                if (rates)
 477                        init.ops = &pll_gf40lp_laint_ops;
 478                else
 479                        init.ops = &pll_gf40lp_laint_fixed_ops;
 480                break;
 481        default:
 482                pr_err("Unrecognized PLL type %u\n", type);
 483                kfree(pll);
 484                return ERR_PTR(-EINVAL);
 485        }
 486
 487        pll->hw.init = &init;
 488        pll->base = base;
 489        pll->rates = rates;
 490        pll->nr_rates = nr_rates;
 491
 492        clk = clk_register(NULL, &pll->hw);
 493        if (IS_ERR(clk))
 494                kfree(pll);
 495
 496        return clk;
 497}
 498
 499void pistachio_clk_register_pll(struct pistachio_clk_provider *p,
 500                                struct pistachio_pll *pll,
 501                                unsigned int num)
 502{
 503        struct clk *clk;
 504        unsigned int i;
 505
 506        for (i = 0; i < num; i++) {
 507                clk = pll_register(pll[i].name, pll[i].parent,
 508                                   0, p->base + pll[i].reg_base,
 509                                   pll[i].type, pll[i].rates,
 510                                   pll[i].nr_rates);
 511                p->clk_data.clks[pll[i].id] = clk;
 512        }
 513}
 514