linux/arch/c6x/platforms/pll.c
<<
>>
Prefs
   1/*
   2 * Clock and PLL control for C64x+ devices
   3 *
   4 * Copyright (C) 2010, 2011 Texas Instruments.
   5 * Contributed by: Mark Salter <msalter@redhat.com>
   6 *
   7 * Copied heavily from arm/mach-davinci/clock.c, so:
   8 *
   9 * Copyright (C) 2006-2007 Texas Instruments.
  10 * Copyright (C) 2008-2009 Deep Root Systems, LLC
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/clkdev.h>
  20#include <linux/clk.h>
  21#include <linux/io.h>
  22#include <linux/err.h>
  23
  24#include <asm/clock.h>
  25#include <asm/soc.h>
  26
  27static LIST_HEAD(clocks);
  28static DEFINE_MUTEX(clocks_mutex);
  29static DEFINE_SPINLOCK(clockfw_lock);
  30
  31static void __clk_enable(struct clk *clk)
  32{
  33        if (clk->parent)
  34                __clk_enable(clk->parent);
  35        clk->usecount++;
  36}
  37
  38static void __clk_disable(struct clk *clk)
  39{
  40        if (WARN_ON(clk->usecount == 0))
  41                return;
  42        --clk->usecount;
  43
  44        if (clk->parent)
  45                __clk_disable(clk->parent);
  46}
  47
  48int clk_enable(struct clk *clk)
  49{
  50        unsigned long flags;
  51
  52        if (clk == NULL || IS_ERR(clk))
  53                return -EINVAL;
  54
  55        spin_lock_irqsave(&clockfw_lock, flags);
  56        __clk_enable(clk);
  57        spin_unlock_irqrestore(&clockfw_lock, flags);
  58
  59        return 0;
  60}
  61EXPORT_SYMBOL(clk_enable);
  62
  63void clk_disable(struct clk *clk)
  64{
  65        unsigned long flags;
  66
  67        if (clk == NULL || IS_ERR(clk))
  68                return;
  69
  70        spin_lock_irqsave(&clockfw_lock, flags);
  71        __clk_disable(clk);
  72        spin_unlock_irqrestore(&clockfw_lock, flags);
  73}
  74EXPORT_SYMBOL(clk_disable);
  75
  76unsigned long clk_get_rate(struct clk *clk)
  77{
  78        if (clk == NULL || IS_ERR(clk))
  79                return -EINVAL;
  80
  81        return clk->rate;
  82}
  83EXPORT_SYMBOL(clk_get_rate);
  84
  85long clk_round_rate(struct clk *clk, unsigned long rate)
  86{
  87        if (clk == NULL || IS_ERR(clk))
  88                return -EINVAL;
  89
  90        if (clk->round_rate)
  91                return clk->round_rate(clk, rate);
  92
  93        return clk->rate;
  94}
  95EXPORT_SYMBOL(clk_round_rate);
  96
  97/* Propagate rate to children */
  98static void propagate_rate(struct clk *root)
  99{
 100        struct clk *clk;
 101
 102        list_for_each_entry(clk, &root->children, childnode) {
 103                if (clk->recalc)
 104                        clk->rate = clk->recalc(clk);
 105                propagate_rate(clk);
 106        }
 107}
 108
 109int clk_set_rate(struct clk *clk, unsigned long rate)
 110{
 111        unsigned long flags;
 112        int ret = -EINVAL;
 113
 114        if (clk == NULL || IS_ERR(clk))
 115                return ret;
 116
 117        if (clk->set_rate)
 118                ret = clk->set_rate(clk, rate);
 119
 120        spin_lock_irqsave(&clockfw_lock, flags);
 121        if (ret == 0) {
 122                if (clk->recalc)
 123                        clk->rate = clk->recalc(clk);
 124                propagate_rate(clk);
 125        }
 126        spin_unlock_irqrestore(&clockfw_lock, flags);
 127
 128        return ret;
 129}
 130EXPORT_SYMBOL(clk_set_rate);
 131
 132int clk_set_parent(struct clk *clk, struct clk *parent)
 133{
 134        unsigned long flags;
 135
 136        if (clk == NULL || IS_ERR(clk))
 137                return -EINVAL;
 138
 139        /* Cannot change parent on enabled clock */
 140        if (WARN_ON(clk->usecount))
 141                return -EINVAL;
 142
 143        mutex_lock(&clocks_mutex);
 144        clk->parent = parent;
 145        list_del_init(&clk->childnode);
 146        list_add(&clk->childnode, &clk->parent->children);
 147        mutex_unlock(&clocks_mutex);
 148
 149        spin_lock_irqsave(&clockfw_lock, flags);
 150        if (clk->recalc)
 151                clk->rate = clk->recalc(clk);
 152        propagate_rate(clk);
 153        spin_unlock_irqrestore(&clockfw_lock, flags);
 154
 155        return 0;
 156}
 157EXPORT_SYMBOL(clk_set_parent);
 158
 159int clk_register(struct clk *clk)
 160{
 161        if (clk == NULL || IS_ERR(clk))
 162                return -EINVAL;
 163
 164        if (WARN(clk->parent && !clk->parent->rate,
 165                 "CLK: %s parent %s has no rate!\n",
 166                 clk->name, clk->parent->name))
 167                return -EINVAL;
 168
 169        mutex_lock(&clocks_mutex);
 170        list_add_tail(&clk->node, &clocks);
 171        if (clk->parent)
 172                list_add_tail(&clk->childnode, &clk->parent->children);
 173        mutex_unlock(&clocks_mutex);
 174
 175        /* If rate is already set, use it */
 176        if (clk->rate)
 177                return 0;
 178
 179        /* Else, see if there is a way to calculate it */
 180        if (clk->recalc)
 181                clk->rate = clk->recalc(clk);
 182
 183        /* Otherwise, default to parent rate */
 184        else if (clk->parent)
 185                clk->rate = clk->parent->rate;
 186
 187        return 0;
 188}
 189EXPORT_SYMBOL(clk_register);
 190
 191void clk_unregister(struct clk *clk)
 192{
 193        if (clk == NULL || IS_ERR(clk))
 194                return;
 195
 196        mutex_lock(&clocks_mutex);
 197        list_del(&clk->node);
 198        list_del(&clk->childnode);
 199        mutex_unlock(&clocks_mutex);
 200}
 201EXPORT_SYMBOL(clk_unregister);
 202
 203
 204static u32 pll_read(struct pll_data *pll, int reg)
 205{
 206        return soc_readl(pll->base + reg);
 207}
 208
 209static unsigned long clk_sysclk_recalc(struct clk *clk)
 210{
 211        u32 v, plldiv = 0;
 212        struct pll_data *pll;
 213        unsigned long rate = clk->rate;
 214
 215        if (WARN_ON(!clk->parent))
 216                return rate;
 217
 218        rate = clk->parent->rate;
 219
 220        /* the parent must be a PLL */
 221        if (WARN_ON(!clk->parent->pll_data))
 222                return rate;
 223
 224        pll = clk->parent->pll_data;
 225
 226        /* If pre-PLL, source clock is before the multiplier and divider(s) */
 227        if (clk->flags & PRE_PLL)
 228                rate = pll->input_rate;
 229
 230        if (!clk->div) {
 231                pr_debug("%s: (no divider) rate = %lu KHz\n",
 232                         clk->name, rate / 1000);
 233                return rate;
 234        }
 235
 236        if (clk->flags & FIXED_DIV_PLL) {
 237                rate /= clk->div;
 238                pr_debug("%s: (fixed divide by %d) rate = %lu KHz\n",
 239                         clk->name, clk->div, rate / 1000);
 240                return rate;
 241        }
 242
 243        v = pll_read(pll, clk->div);
 244        if (v & PLLDIV_EN)
 245                plldiv = (v & PLLDIV_RATIO_MASK) + 1;
 246
 247        if (plldiv == 0)
 248                plldiv = 1;
 249
 250        rate /= plldiv;
 251
 252        pr_debug("%s: (divide by %d) rate = %lu KHz\n",
 253                 clk->name, plldiv, rate / 1000);
 254
 255        return rate;
 256}
 257
 258static unsigned long clk_leafclk_recalc(struct clk *clk)
 259{
 260        if (WARN_ON(!clk->parent))
 261                return clk->rate;
 262
 263        pr_debug("%s: (parent %s) rate = %lu KHz\n",
 264                 clk->name, clk->parent->name,  clk->parent->rate / 1000);
 265
 266        return clk->parent->rate;
 267}
 268
 269static unsigned long clk_pllclk_recalc(struct clk *clk)
 270{
 271        u32 ctrl, mult = 0, prediv = 0, postdiv = 0;
 272        u8 bypass;
 273        struct pll_data *pll = clk->pll_data;
 274        unsigned long rate = clk->rate;
 275
 276        if (clk->flags & FIXED_RATE_PLL)
 277                return rate;
 278
 279        ctrl = pll_read(pll, PLLCTL);
 280        rate = pll->input_rate = clk->parent->rate;
 281
 282        if (ctrl & PLLCTL_PLLEN)
 283                bypass = 0;
 284        else
 285                bypass = 1;
 286
 287        if (pll->flags & PLL_HAS_MUL) {
 288                mult = pll_read(pll, PLLM);
 289                mult = (mult & PLLM_PLLM_MASK) + 1;
 290        }
 291        if (pll->flags & PLL_HAS_PRE) {
 292                prediv = pll_read(pll, PLLPRE);
 293                if (prediv & PLLDIV_EN)
 294                        prediv = (prediv & PLLDIV_RATIO_MASK) + 1;
 295                else
 296                        prediv = 0;
 297        }
 298        if (pll->flags & PLL_HAS_POST) {
 299                postdiv = pll_read(pll, PLLPOST);
 300                if (postdiv & PLLDIV_EN)
 301                        postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1;
 302                else
 303                        postdiv = 1;
 304        }
 305
 306        if (!bypass) {
 307                if (prediv)
 308                        rate /= prediv;
 309                if (mult)
 310                        rate *= mult;
 311                if (postdiv)
 312                        rate /= postdiv;
 313
 314                pr_debug("PLL%d: input = %luMHz, pre[%d] mul[%d] post[%d] "
 315                         "--> %luMHz output.\n",
 316                         pll->num, clk->parent->rate / 1000000,
 317                         prediv, mult, postdiv, rate / 1000000);
 318        } else
 319                pr_debug("PLL%d: input = %luMHz, bypass mode.\n",
 320                         pll->num, clk->parent->rate / 1000000);
 321
 322        return rate;
 323}
 324
 325
 326static void __init __init_clk(struct clk *clk)
 327{
 328        INIT_LIST_HEAD(&clk->node);
 329        INIT_LIST_HEAD(&clk->children);
 330        INIT_LIST_HEAD(&clk->childnode);
 331
 332        if (!clk->recalc) {
 333
 334                /* Check if clock is a PLL */
 335                if (clk->pll_data)
 336                        clk->recalc = clk_pllclk_recalc;
 337
 338                /* Else, if it is a PLL-derived clock */
 339                else if (clk->flags & CLK_PLL)
 340                        clk->recalc = clk_sysclk_recalc;
 341
 342                /* Otherwise, it is a leaf clock (PSC clock) */
 343                else if (clk->parent)
 344                        clk->recalc = clk_leafclk_recalc;
 345        }
 346}
 347
 348void __init c6x_clks_init(struct clk_lookup *clocks)
 349{
 350        struct clk_lookup *c;
 351        struct clk *clk;
 352        size_t num_clocks = 0;
 353
 354        for (c = clocks; c->clk; c++) {
 355                clk = c->clk;
 356
 357                __init_clk(clk);
 358                clk_register(clk);
 359                num_clocks++;
 360
 361                /* Turn on clocks that Linux doesn't otherwise manage */
 362                if (clk->flags & ALWAYS_ENABLED)
 363                        clk_enable(clk);
 364        }
 365
 366        clkdev_add_table(clocks, num_clocks);
 367}
 368
 369#ifdef CONFIG_DEBUG_FS
 370
 371#include <linux/debugfs.h>
 372#include <linux/seq_file.h>
 373
 374#define CLKNAME_MAX     10              /* longest clock name */
 375#define NEST_DELTA      2
 376#define NEST_MAX        4
 377
 378static void
 379dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
 380{
 381        char            *state;
 382        char            buf[CLKNAME_MAX + NEST_DELTA * NEST_MAX];
 383        struct clk      *clk;
 384        unsigned        i;
 385
 386        if (parent->flags & CLK_PLL)
 387                state = "pll";
 388        else
 389                state = "";
 390
 391        /* <nest spaces> name <pad to end> */
 392        memset(buf, ' ', sizeof(buf) - 1);
 393        buf[sizeof(buf) - 1] = 0;
 394        i = strlen(parent->name);
 395        memcpy(buf + nest, parent->name,
 396               min(i, (unsigned)(sizeof(buf) - 1 - nest)));
 397
 398        seq_printf(s, "%s users=%2d %-3s %9ld Hz\n",
 399                   buf, parent->usecount, state, clk_get_rate(parent));
 400        /* REVISIT show device associations too */
 401
 402        /* cost is now small, but not linear... */
 403        list_for_each_entry(clk, &parent->children, childnode) {
 404                dump_clock(s, nest + NEST_DELTA, clk);
 405        }
 406}
 407
 408static int c6x_ck_show(struct seq_file *m, void *v)
 409{
 410        struct clk *clk;
 411
 412        /*
 413         * Show clock tree; We trust nonzero usecounts equate to PSC enables...
 414         */
 415        mutex_lock(&clocks_mutex);
 416        list_for_each_entry(clk, &clocks, node)
 417                if (!clk->parent)
 418                        dump_clock(m, 0, clk);
 419        mutex_unlock(&clocks_mutex);
 420
 421        return 0;
 422}
 423
 424static int c6x_ck_open(struct inode *inode, struct file *file)
 425{
 426        return single_open(file, c6x_ck_show, NULL);
 427}
 428
 429static const struct file_operations c6x_ck_operations = {
 430        .open           = c6x_ck_open,
 431        .read           = seq_read,
 432        .llseek         = seq_lseek,
 433        .release        = single_release,
 434};
 435
 436static int __init c6x_clk_debugfs_init(void)
 437{
 438        debugfs_create_file("c6x_clocks", S_IFREG | S_IRUGO, NULL, NULL,
 439                            &c6x_ck_operations);
 440
 441        return 0;
 442}
 443device_initcall(c6x_clk_debugfs_init);
 444#endif /* CONFIG_DEBUG_FS */
 445