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
  68struct pistachio_clk_pll {
  69        struct clk_hw hw;
  70        void __iomem *base;
  71        struct pistachio_pll_rate_table *rates;
  72        unsigned int nr_rates;
  73};
  74
  75static inline u32 pll_readl(struct pistachio_clk_pll *pll, u32 reg)
  76{
  77        return readl(pll->base + reg);
  78}
  79
  80static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg)
  81{
  82        writel(val, pll->base + reg);
  83}
  84
  85static inline void pll_lock(struct pistachio_clk_pll *pll)
  86{
  87        while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
  88                cpu_relax();
  89}
  90
  91static inline u32 do_div_round_closest(u64 dividend, u32 divisor)
  92{
  93        dividend += divisor / 2;
  94        do_div(dividend, divisor);
  95
  96        return dividend;
  97}
  98
  99static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw)
 100{
 101        return container_of(hw, struct pistachio_clk_pll, hw);
 102}
 103
 104static struct pistachio_pll_rate_table *
 105pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref,
 106               unsigned long fout)
 107{
 108        unsigned int i;
 109
 110        for (i = 0; i < pll->nr_rates; i++) {
 111                if (pll->rates[i].fref == fref && pll->rates[i].fout == fout)
 112                        return &pll->rates[i];
 113        }
 114
 115        return NULL;
 116}
 117
 118static long pll_round_rate(struct clk_hw *hw, unsigned long rate,
 119                           unsigned long *parent_rate)
 120{
 121        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 122        unsigned int i;
 123
 124        for (i = 0; i < pll->nr_rates; i++) {
 125                if (i > 0 && pll->rates[i].fref == *parent_rate &&
 126                    pll->rates[i].fout <= rate)
 127                        return pll->rates[i - 1].fout;
 128        }
 129
 130        return pll->rates[0].fout;
 131}
 132
 133static int pll_gf40lp_frac_enable(struct clk_hw *hw)
 134{
 135        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 136        u32 val;
 137
 138        val = pll_readl(pll, PLL_CTRL3);
 139        val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_DACPD |
 140                 PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD |
 141                 PLL_FRAC_CTRL3_FOUT4PHASEPD | PLL_FRAC_CTRL3_FOUTVCOPD);
 142        pll_writel(pll, val, PLL_CTRL3);
 143
 144        val = pll_readl(pll, PLL_CTRL4);
 145        val &= ~PLL_FRAC_CTRL4_BYPASS;
 146        pll_writel(pll, val, PLL_CTRL4);
 147
 148        pll_lock(pll);
 149
 150        return 0;
 151}
 152
 153static void pll_gf40lp_frac_disable(struct clk_hw *hw)
 154{
 155        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 156        u32 val;
 157
 158        val = pll_readl(pll, PLL_CTRL3);
 159        val |= PLL_FRAC_CTRL3_PD;
 160        pll_writel(pll, val, PLL_CTRL3);
 161}
 162
 163static int pll_gf40lp_frac_is_enabled(struct clk_hw *hw)
 164{
 165        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 166
 167        return !(pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_PD);
 168}
 169
 170static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
 171                                    unsigned long parent_rate)
 172{
 173        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 174        struct pistachio_pll_rate_table *params;
 175        int enabled = pll_gf40lp_frac_is_enabled(hw);
 176        u32 val, vco, old_postdiv1, old_postdiv2;
 177        const char *name = __clk_get_name(hw->clk);
 178
 179        if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC)
 180                return -EINVAL;
 181
 182        params = pll_get_params(pll, parent_rate, rate);
 183        if (!params || !params->refdiv)
 184                return -EINVAL;
 185
 186        vco = params->fref * params->fbdiv / params->refdiv;
 187        if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC)
 188                pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
 189                        MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC);
 190
 191        val = params->fref / params->refdiv;
 192        if (val < MIN_PFD)
 193                pr_warn("%s: PFD %u is too low (min %lu)\n",
 194                        name, val, MIN_PFD);
 195        if (val > vco / 16)
 196                pr_warn("%s: PFD %u is too high (max %u)\n",
 197                        name, val, vco / 16);
 198
 199        val = pll_readl(pll, PLL_CTRL1);
 200        val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
 201                 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT));
 202        val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) |
 203                (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT);
 204        pll_writel(pll, val, PLL_CTRL1);
 205
 206        val = pll_readl(pll, PLL_CTRL2);
 207
 208        old_postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
 209                       PLL_FRAC_CTRL2_POSTDIV1_MASK;
 210        old_postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
 211                       PLL_FRAC_CTRL2_POSTDIV2_MASK;
 212        if (enabled &&
 213            (params->postdiv1 != old_postdiv1 ||
 214             params->postdiv2 != old_postdiv2))
 215                pr_warn("%s: changing postdiv while PLL is enabled\n", name);
 216
 217        if (params->postdiv2 > params->postdiv1)
 218                pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
 219
 220        val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) |
 221                 (PLL_FRAC_CTRL2_POSTDIV1_MASK <<
 222                  PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
 223                 (PLL_FRAC_CTRL2_POSTDIV2_MASK <<
 224                  PLL_FRAC_CTRL2_POSTDIV2_SHIFT));
 225        val |= (params->frac << PLL_FRAC_CTRL2_FRAC_SHIFT) |
 226                (params->postdiv1 << PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
 227                (params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
 228        pll_writel(pll, val, PLL_CTRL2);
 229
 230        if (enabled)
 231                pll_lock(pll);
 232
 233        return 0;
 234}
 235
 236static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw,
 237                                                 unsigned long parent_rate)
 238{
 239        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 240        u32 val, prediv, fbdiv, frac, postdiv1, postdiv2;
 241        u64 rate = parent_rate;
 242
 243        val = pll_readl(pll, PLL_CTRL1);
 244        prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK;
 245        fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK;
 246
 247        val = pll_readl(pll, PLL_CTRL2);
 248        postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
 249                PLL_FRAC_CTRL2_POSTDIV1_MASK;
 250        postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
 251                PLL_FRAC_CTRL2_POSTDIV2_MASK;
 252        frac = (val >> PLL_FRAC_CTRL2_FRAC_SHIFT) & PLL_FRAC_CTRL2_FRAC_MASK;
 253
 254        rate *= (fbdiv << 24) + frac;
 255        rate = do_div_round_closest(rate, (prediv * postdiv1 * postdiv2) << 24);
 256
 257        return rate;
 258}
 259
 260static struct clk_ops pll_gf40lp_frac_ops = {
 261        .enable = pll_gf40lp_frac_enable,
 262        .disable = pll_gf40lp_frac_disable,
 263        .is_enabled = pll_gf40lp_frac_is_enabled,
 264        .recalc_rate = pll_gf40lp_frac_recalc_rate,
 265        .round_rate = pll_round_rate,
 266        .set_rate = pll_gf40lp_frac_set_rate,
 267};
 268
 269static struct clk_ops pll_gf40lp_frac_fixed_ops = {
 270        .enable = pll_gf40lp_frac_enable,
 271        .disable = pll_gf40lp_frac_disable,
 272        .is_enabled = pll_gf40lp_frac_is_enabled,
 273        .recalc_rate = pll_gf40lp_frac_recalc_rate,
 274};
 275
 276static int pll_gf40lp_laint_enable(struct clk_hw *hw)
 277{
 278        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 279        u32 val;
 280
 281        val = pll_readl(pll, PLL_CTRL1);
 282        val &= ~(PLL_INT_CTRL1_PD | PLL_INT_CTRL1_DSMPD |
 283                 PLL_INT_CTRL1_FOUTPOSTDIVPD | PLL_INT_CTRL1_FOUTVCOPD);
 284        pll_writel(pll, val, PLL_CTRL1);
 285
 286        val = pll_readl(pll, PLL_CTRL2);
 287        val &= ~PLL_INT_CTRL2_BYPASS;
 288        pll_writel(pll, val, PLL_CTRL2);
 289
 290        pll_lock(pll);
 291
 292        return 0;
 293}
 294
 295static void pll_gf40lp_laint_disable(struct clk_hw *hw)
 296{
 297        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 298        u32 val;
 299
 300        val = pll_readl(pll, PLL_CTRL1);
 301        val |= PLL_INT_CTRL1_PD;
 302        pll_writel(pll, val, PLL_CTRL1);
 303}
 304
 305static int pll_gf40lp_laint_is_enabled(struct clk_hw *hw)
 306{
 307        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 308
 309        return !(pll_readl(pll, PLL_CTRL1) & PLL_INT_CTRL1_PD);
 310}
 311
 312static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
 313                                     unsigned long parent_rate)
 314{
 315        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 316        struct pistachio_pll_rate_table *params;
 317        int enabled = pll_gf40lp_laint_is_enabled(hw);
 318        u32 val, vco, old_postdiv1, old_postdiv2;
 319        const char *name = __clk_get_name(hw->clk);
 320
 321        if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA)
 322                return -EINVAL;
 323
 324        params = pll_get_params(pll, parent_rate, rate);
 325        if (!params || !params->refdiv)
 326                return -EINVAL;
 327
 328        vco = params->fref * params->fbdiv / params->refdiv;
 329        if (vco < MIN_VCO_LA || vco > MAX_VCO_LA)
 330                pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
 331                        MIN_VCO_LA, MAX_VCO_LA);
 332
 333        val = params->fref / params->refdiv;
 334        if (val < MIN_PFD)
 335                pr_warn("%s: PFD %u is too low (min %lu)\n",
 336                        name, val, MIN_PFD);
 337        if (val > vco / 16)
 338                pr_warn("%s: PFD %u is too high (max %u)\n",
 339                        name, val, vco / 16);
 340
 341        val = pll_readl(pll, PLL_CTRL1);
 342
 343        old_postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
 344                       PLL_INT_CTRL1_POSTDIV1_MASK;
 345        old_postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
 346                       PLL_INT_CTRL1_POSTDIV2_MASK;
 347        if (enabled &&
 348            (params->postdiv1 != old_postdiv1 ||
 349             params->postdiv2 != old_postdiv2))
 350                pr_warn("%s: changing postdiv while PLL is enabled\n", name);
 351
 352        if (params->postdiv2 > params->postdiv1)
 353                pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
 354
 355        val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
 356                 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) |
 357                 (PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) |
 358                 (PLL_INT_CTRL1_POSTDIV2_MASK << PLL_INT_CTRL1_POSTDIV2_SHIFT));
 359        val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) |
 360                (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT) |
 361                (params->postdiv1 << PLL_INT_CTRL1_POSTDIV1_SHIFT) |
 362                (params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT);
 363        pll_writel(pll, val, PLL_CTRL1);
 364
 365        if (enabled)
 366                pll_lock(pll);
 367
 368        return 0;
 369}
 370
 371static unsigned long pll_gf40lp_laint_recalc_rate(struct clk_hw *hw,
 372                                                  unsigned long parent_rate)
 373{
 374        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 375        u32 val, prediv, fbdiv, postdiv1, postdiv2;
 376        u64 rate = parent_rate;
 377
 378        val = pll_readl(pll, PLL_CTRL1);
 379        prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK;
 380        fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK;
 381        postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
 382                PLL_INT_CTRL1_POSTDIV1_MASK;
 383        postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
 384                PLL_INT_CTRL1_POSTDIV2_MASK;
 385
 386        rate *= fbdiv;
 387        rate = do_div_round_closest(rate, prediv * postdiv1 * postdiv2);
 388
 389        return rate;
 390}
 391
 392static struct clk_ops pll_gf40lp_laint_ops = {
 393        .enable = pll_gf40lp_laint_enable,
 394        .disable = pll_gf40lp_laint_disable,
 395        .is_enabled = pll_gf40lp_laint_is_enabled,
 396        .recalc_rate = pll_gf40lp_laint_recalc_rate,
 397        .round_rate = pll_round_rate,
 398        .set_rate = pll_gf40lp_laint_set_rate,
 399};
 400
 401static struct clk_ops pll_gf40lp_laint_fixed_ops = {
 402        .enable = pll_gf40lp_laint_enable,
 403        .disable = pll_gf40lp_laint_disable,
 404        .is_enabled = pll_gf40lp_laint_is_enabled,
 405        .recalc_rate = pll_gf40lp_laint_recalc_rate,
 406};
 407
 408static struct clk *pll_register(const char *name, const char *parent_name,
 409                                unsigned long flags, void __iomem *base,
 410                                enum pistachio_pll_type type,
 411                                struct pistachio_pll_rate_table *rates,
 412                                unsigned int nr_rates)
 413{
 414        struct pistachio_clk_pll *pll;
 415        struct clk_init_data init;
 416        struct clk *clk;
 417
 418        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 419        if (!pll)
 420                return ERR_PTR(-ENOMEM);
 421
 422        init.name = name;
 423        init.flags = flags | CLK_GET_RATE_NOCACHE;
 424        init.parent_names = &parent_name;
 425        init.num_parents = 1;
 426
 427        switch (type) {
 428        case PLL_GF40LP_FRAC:
 429                if (rates)
 430                        init.ops = &pll_gf40lp_frac_ops;
 431                else
 432                        init.ops = &pll_gf40lp_frac_fixed_ops;
 433                break;
 434        case PLL_GF40LP_LAINT:
 435                if (rates)
 436                        init.ops = &pll_gf40lp_laint_ops;
 437                else
 438                        init.ops = &pll_gf40lp_laint_fixed_ops;
 439                break;
 440        default:
 441                pr_err("Unrecognized PLL type %u\n", type);
 442                kfree(pll);
 443                return ERR_PTR(-EINVAL);
 444        }
 445
 446        pll->hw.init = &init;
 447        pll->base = base;
 448        pll->rates = rates;
 449        pll->nr_rates = nr_rates;
 450
 451        clk = clk_register(NULL, &pll->hw);
 452        if (IS_ERR(clk))
 453                kfree(pll);
 454
 455        return clk;
 456}
 457
 458void pistachio_clk_register_pll(struct pistachio_clk_provider *p,
 459                                struct pistachio_pll *pll,
 460                                unsigned int num)
 461{
 462        struct clk *clk;
 463        unsigned int i;
 464
 465        for (i = 0; i < num; i++) {
 466                clk = pll_register(pll[i].name, pll[i].parent,
 467                                   0, p->base + pll[i].reg_base,
 468                                   pll[i].type, pll[i].rates,
 469                                   pll[i].nr_rates);
 470                p->clk_data.clks[pll[i].id] = clk;
 471        }
 472}
 473