linux/drivers/clk/at91/clk-pll.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2 of the License, or
   7 * (at your option) any later version.
   8 *
   9 */
  10
  11#include <linux/clk-provider.h>
  12#include <linux/clkdev.h>
  13#include <linux/clk/at91_pmc.h>
  14#include <linux/of.h>
  15#include <linux/mfd/syscon.h>
  16#include <linux/regmap.h>
  17
  18#include "pmc.h"
  19
  20#define PLL_STATUS_MASK(id)     (1 << (1 + (id)))
  21#define PLL_REG(id)             (AT91_CKGR_PLLAR + ((id) * 4))
  22#define PLL_DIV_MASK            0xff
  23#define PLL_DIV_MAX             PLL_DIV_MASK
  24#define PLL_DIV(reg)            ((reg) & PLL_DIV_MASK)
  25#define PLL_MUL(reg, layout)    (((reg) >> (layout)->mul_shift) & \
  26                                 (layout)->mul_mask)
  27#define PLL_MUL_MIN             2
  28#define PLL_MUL_MASK(layout)    ((layout)->mul_mask)
  29#define PLL_MUL_MAX(layout)     (PLL_MUL_MASK(layout) + 1)
  30#define PLL_ICPR_SHIFT(id)      ((id) * 16)
  31#define PLL_ICPR_MASK(id)       (0xffff << PLL_ICPR_SHIFT(id))
  32#define PLL_MAX_COUNT           0x3f
  33#define PLL_COUNT_SHIFT         8
  34#define PLL_OUT_SHIFT           14
  35#define PLL_MAX_ID              1
  36
  37struct clk_pll_characteristics {
  38        struct clk_range input;
  39        int num_output;
  40        struct clk_range *output;
  41        u16 *icpll;
  42        u8 *out;
  43};
  44
  45struct clk_pll_layout {
  46        u32 pllr_mask;
  47        u16 mul_mask;
  48        u8 mul_shift;
  49};
  50
  51#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw)
  52
  53struct clk_pll {
  54        struct clk_hw hw;
  55        struct regmap *regmap;
  56        u8 id;
  57        u8 div;
  58        u8 range;
  59        u16 mul;
  60        const struct clk_pll_layout *layout;
  61        const struct clk_pll_characteristics *characteristics;
  62};
  63
  64static inline bool clk_pll_ready(struct regmap *regmap, int id)
  65{
  66        unsigned int status;
  67
  68        regmap_read(regmap, AT91_PMC_SR, &status);
  69
  70        return status & PLL_STATUS_MASK(id) ? 1 : 0;
  71}
  72
  73static int clk_pll_prepare(struct clk_hw *hw)
  74{
  75        struct clk_pll *pll = to_clk_pll(hw);
  76        struct regmap *regmap = pll->regmap;
  77        const struct clk_pll_layout *layout = pll->layout;
  78        const struct clk_pll_characteristics *characteristics =
  79                                                        pll->characteristics;
  80        u8 id = pll->id;
  81        u32 mask = PLL_STATUS_MASK(id);
  82        int offset = PLL_REG(id);
  83        u8 out = 0;
  84        unsigned int pllr;
  85        unsigned int status;
  86        u8 div;
  87        u16 mul;
  88
  89        regmap_read(regmap, offset, &pllr);
  90        div = PLL_DIV(pllr);
  91        mul = PLL_MUL(pllr, layout);
  92
  93        regmap_read(regmap, AT91_PMC_SR, &status);
  94        if ((status & mask) &&
  95            (div == pll->div && mul == pll->mul))
  96                return 0;
  97
  98        if (characteristics->out)
  99                out = characteristics->out[pll->range];
 100
 101        if (characteristics->icpll)
 102                regmap_update_bits(regmap, AT91_PMC_PLLICPR, PLL_ICPR_MASK(id),
 103                        characteristics->icpll[pll->range] << PLL_ICPR_SHIFT(id));
 104
 105        regmap_update_bits(regmap, offset, layout->pllr_mask,
 106                        pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) |
 107                        (out << PLL_OUT_SHIFT) |
 108                        ((pll->mul & layout->mul_mask) << layout->mul_shift));
 109
 110        while (!clk_pll_ready(regmap, pll->id))
 111                cpu_relax();
 112
 113        return 0;
 114}
 115
 116static int clk_pll_is_prepared(struct clk_hw *hw)
 117{
 118        struct clk_pll *pll = to_clk_pll(hw);
 119
 120        return clk_pll_ready(pll->regmap, pll->id);
 121}
 122
 123static void clk_pll_unprepare(struct clk_hw *hw)
 124{
 125        struct clk_pll *pll = to_clk_pll(hw);
 126        unsigned int mask = pll->layout->pllr_mask;
 127
 128        regmap_update_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask);
 129}
 130
 131static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 132                                         unsigned long parent_rate)
 133{
 134        struct clk_pll *pll = to_clk_pll(hw);
 135
 136        return (parent_rate / pll->div) * (pll->mul + 1);
 137}
 138
 139static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate,
 140                                     unsigned long parent_rate,
 141                                     u32 *div, u32 *mul,
 142                                     u32 *index) {
 143        const struct clk_pll_layout *layout = pll->layout;
 144        const struct clk_pll_characteristics *characteristics =
 145                                                        pll->characteristics;
 146        unsigned long bestremainder = ULONG_MAX;
 147        unsigned long maxdiv, mindiv, tmpdiv;
 148        long bestrate = -ERANGE;
 149        unsigned long bestdiv;
 150        unsigned long bestmul;
 151        int i = 0;
 152
 153        /* Check if parent_rate is a valid input rate */
 154        if (parent_rate < characteristics->input.min)
 155                return -ERANGE;
 156
 157        /*
 158         * Calculate minimum divider based on the minimum multiplier, the
 159         * parent_rate and the requested rate.
 160         * Should always be 2 according to the input and output characteristics
 161         * of the PLL blocks.
 162         */
 163        mindiv = (parent_rate * PLL_MUL_MIN) / rate;
 164        if (!mindiv)
 165                mindiv = 1;
 166
 167        if (parent_rate > characteristics->input.max) {
 168                tmpdiv = DIV_ROUND_UP(parent_rate, characteristics->input.max);
 169                if (tmpdiv > PLL_DIV_MAX)
 170                        return -ERANGE;
 171
 172                if (tmpdiv > mindiv)
 173                        mindiv = tmpdiv;
 174        }
 175
 176        /*
 177         * Calculate the maximum divider which is limited by PLL register
 178         * layout (limited by the MUL or DIV field size).
 179         */
 180        maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX(layout), rate);
 181        if (maxdiv > PLL_DIV_MAX)
 182                maxdiv = PLL_DIV_MAX;
 183
 184        /*
 185         * Iterate over the acceptable divider values to find the best
 186         * divider/multiplier pair (the one that generates the closest
 187         * rate to the requested one).
 188         */
 189        for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) {
 190                unsigned long remainder;
 191                unsigned long tmprate;
 192                unsigned long tmpmul;
 193
 194                /*
 195                 * Calculate the multiplier associated with the current
 196                 * divider that provide the closest rate to the requested one.
 197                 */
 198                tmpmul = DIV_ROUND_CLOSEST(rate, parent_rate / tmpdiv);
 199                tmprate = (parent_rate / tmpdiv) * tmpmul;
 200                if (tmprate > rate)
 201                        remainder = tmprate - rate;
 202                else
 203                        remainder = rate - tmprate;
 204
 205                /*
 206                 * Compare the remainder with the best remainder found until
 207                 * now and elect a new best multiplier/divider pair if the
 208                 * current remainder is smaller than the best one.
 209                 */
 210                if (remainder < bestremainder) {
 211                        bestremainder = remainder;
 212                        bestdiv = tmpdiv;
 213                        bestmul = tmpmul;
 214                        bestrate = tmprate;
 215                }
 216
 217                /*
 218                 * We've found a perfect match!
 219                 * Stop searching now and use this multiplier/divider pair.
 220                 */
 221                if (!remainder)
 222                        break;
 223        }
 224
 225        /* We haven't found any multiplier/divider pair => return -ERANGE */
 226        if (bestrate < 0)
 227                return bestrate;
 228
 229        /* Check if bestrate is a valid output rate  */
 230        for (i = 0; i < characteristics->num_output; i++) {
 231                if (bestrate >= characteristics->output[i].min &&
 232                    bestrate <= characteristics->output[i].max)
 233                        break;
 234        }
 235
 236        if (i >= characteristics->num_output)
 237                return -ERANGE;
 238
 239        if (div)
 240                *div = bestdiv;
 241        if (mul)
 242                *mul = bestmul - 1;
 243        if (index)
 244                *index = i;
 245
 246        return bestrate;
 247}
 248
 249static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 250                                        unsigned long *parent_rate)
 251{
 252        struct clk_pll *pll = to_clk_pll(hw);
 253
 254        return clk_pll_get_best_div_mul(pll, rate, *parent_rate,
 255                                        NULL, NULL, NULL);
 256}
 257
 258static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 259                            unsigned long parent_rate)
 260{
 261        struct clk_pll *pll = to_clk_pll(hw);
 262        long ret;
 263        u32 div;
 264        u32 mul;
 265        u32 index;
 266
 267        ret = clk_pll_get_best_div_mul(pll, rate, parent_rate,
 268                                       &div, &mul, &index);
 269        if (ret < 0)
 270                return ret;
 271
 272        pll->range = index;
 273        pll->div = div;
 274        pll->mul = mul;
 275
 276        return 0;
 277}
 278
 279static const struct clk_ops pll_ops = {
 280        .prepare = clk_pll_prepare,
 281        .unprepare = clk_pll_unprepare,
 282        .is_prepared = clk_pll_is_prepared,
 283        .recalc_rate = clk_pll_recalc_rate,
 284        .round_rate = clk_pll_round_rate,
 285        .set_rate = clk_pll_set_rate,
 286};
 287
 288static struct clk_hw * __init
 289at91_clk_register_pll(struct regmap *regmap, const char *name,
 290                      const char *parent_name, u8 id,
 291                      const struct clk_pll_layout *layout,
 292                      const struct clk_pll_characteristics *characteristics)
 293{
 294        struct clk_pll *pll;
 295        struct clk_hw *hw;
 296        struct clk_init_data init;
 297        int offset = PLL_REG(id);
 298        unsigned int pllr;
 299        int ret;
 300
 301        if (id > PLL_MAX_ID)
 302                return ERR_PTR(-EINVAL);
 303
 304        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 305        if (!pll)
 306                return ERR_PTR(-ENOMEM);
 307
 308        init.name = name;
 309        init.ops = &pll_ops;
 310        init.parent_names = &parent_name;
 311        init.num_parents = 1;
 312        init.flags = CLK_SET_RATE_GATE;
 313
 314        pll->id = id;
 315        pll->hw.init = &init;
 316        pll->layout = layout;
 317        pll->characteristics = characteristics;
 318        pll->regmap = regmap;
 319        regmap_read(regmap, offset, &pllr);
 320        pll->div = PLL_DIV(pllr);
 321        pll->mul = PLL_MUL(pllr, layout);
 322
 323        hw = &pll->hw;
 324        ret = clk_hw_register(NULL, &pll->hw);
 325        if (ret) {
 326                kfree(pll);
 327                hw = ERR_PTR(ret);
 328        }
 329
 330        return hw;
 331}
 332
 333
 334static const struct clk_pll_layout at91rm9200_pll_layout = {
 335        .pllr_mask = 0x7FFFFFF,
 336        .mul_shift = 16,
 337        .mul_mask = 0x7FF,
 338};
 339
 340static const struct clk_pll_layout at91sam9g45_pll_layout = {
 341        .pllr_mask = 0xFFFFFF,
 342        .mul_shift = 16,
 343        .mul_mask = 0xFF,
 344};
 345
 346static const struct clk_pll_layout at91sam9g20_pllb_layout = {
 347        .pllr_mask = 0x3FFFFF,
 348        .mul_shift = 16,
 349        .mul_mask = 0x3F,
 350};
 351
 352static const struct clk_pll_layout sama5d3_pll_layout = {
 353        .pllr_mask = 0x1FFFFFF,
 354        .mul_shift = 18,
 355        .mul_mask = 0x7F,
 356};
 357
 358
 359static struct clk_pll_characteristics * __init
 360of_at91_clk_pll_get_characteristics(struct device_node *np)
 361{
 362        int i;
 363        int offset;
 364        u32 tmp;
 365        int num_output;
 366        u32 num_cells;
 367        struct clk_range input;
 368        struct clk_range *output;
 369        u8 *out = NULL;
 370        u16 *icpll = NULL;
 371        struct clk_pll_characteristics *characteristics;
 372
 373        if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
 374                return NULL;
 375
 376        if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
 377                                 &num_cells))
 378                return NULL;
 379
 380        if (num_cells < 2 || num_cells > 4)
 381                return NULL;
 382
 383        if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
 384                return NULL;
 385        num_output = tmp / (sizeof(u32) * num_cells);
 386
 387        characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
 388        if (!characteristics)
 389                return NULL;
 390
 391        output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
 392        if (!output)
 393                goto out_free_characteristics;
 394
 395        if (num_cells > 2) {
 396                out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
 397                if (!out)
 398                        goto out_free_output;
 399        }
 400
 401        if (num_cells > 3) {
 402                icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
 403                if (!icpll)
 404                        goto out_free_output;
 405        }
 406
 407        for (i = 0; i < num_output; i++) {
 408                offset = i * num_cells;
 409                if (of_property_read_u32_index(np,
 410                                               "atmel,pll-clk-output-ranges",
 411                                               offset, &tmp))
 412                        goto out_free_output;
 413                output[i].min = tmp;
 414                if (of_property_read_u32_index(np,
 415                                               "atmel,pll-clk-output-ranges",
 416                                               offset + 1, &tmp))
 417                        goto out_free_output;
 418                output[i].max = tmp;
 419
 420                if (num_cells == 2)
 421                        continue;
 422
 423                if (of_property_read_u32_index(np,
 424                                               "atmel,pll-clk-output-ranges",
 425                                               offset + 2, &tmp))
 426                        goto out_free_output;
 427                out[i] = tmp;
 428
 429                if (num_cells == 3)
 430                        continue;
 431
 432                if (of_property_read_u32_index(np,
 433                                               "atmel,pll-clk-output-ranges",
 434                                               offset + 3, &tmp))
 435                        goto out_free_output;
 436                icpll[i] = tmp;
 437        }
 438
 439        characteristics->input = input;
 440        characteristics->num_output = num_output;
 441        characteristics->output = output;
 442        characteristics->out = out;
 443        characteristics->icpll = icpll;
 444        return characteristics;
 445
 446out_free_output:
 447        kfree(icpll);
 448        kfree(out);
 449        kfree(output);
 450out_free_characteristics:
 451        kfree(characteristics);
 452        return NULL;
 453}
 454
 455static void __init
 456of_at91_clk_pll_setup(struct device_node *np,
 457                      const struct clk_pll_layout *layout)
 458{
 459        u32 id;
 460        struct clk_hw *hw;
 461        struct regmap *regmap;
 462        const char *parent_name;
 463        const char *name = np->name;
 464        struct clk_pll_characteristics *characteristics;
 465
 466        if (of_property_read_u32(np, "reg", &id))
 467                return;
 468
 469        parent_name = of_clk_get_parent_name(np, 0);
 470
 471        of_property_read_string(np, "clock-output-names", &name);
 472
 473        regmap = syscon_node_to_regmap(of_get_parent(np));
 474        if (IS_ERR(regmap))
 475                return;
 476
 477        characteristics = of_at91_clk_pll_get_characteristics(np);
 478        if (!characteristics)
 479                return;
 480
 481        hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
 482                                    characteristics);
 483        if (IS_ERR(hw))
 484                goto out_free_characteristics;
 485
 486        of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
 487        return;
 488
 489out_free_characteristics:
 490        kfree(characteristics);
 491}
 492
 493static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
 494{
 495        of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
 496}
 497CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
 498               of_at91rm9200_clk_pll_setup);
 499
 500static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
 501{
 502        of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
 503}
 504CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
 505               of_at91sam9g45_clk_pll_setup);
 506
 507static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
 508{
 509        of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
 510}
 511CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
 512               of_at91sam9g20_clk_pllb_setup);
 513
 514static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
 515{
 516        of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
 517}
 518CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
 519               of_sama5d3_clk_pll_setup);
 520