linux/arch/arm/mach-davinci/clock.c
<<
>>
Prefs
   1/*
   2 * Clock and PLL control for DaVinci devices
   3 *
   4 * Copyright (C) 2006-2007 Texas Instruments.
   5 * Copyright (C) 2008-2009 Deep Root Systems, LLC
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/kernel.h>
  15#include <linux/init.h>
  16#include <linux/errno.h>
  17#include <linux/clk.h>
  18#include <linux/err.h>
  19#include <linux/mutex.h>
  20#include <linux/platform_device.h>
  21#include <linux/io.h>
  22
  23#include <mach/hardware.h>
  24
  25#include <mach/psc.h>
  26#include <mach/cputype.h>
  27#include "clock.h"
  28
  29static LIST_HEAD(clocks);
  30static DEFINE_MUTEX(clocks_mutex);
  31static DEFINE_SPINLOCK(clockfw_lock);
  32
  33static unsigned psc_domain(struct clk *clk)
  34{
  35        return (clk->flags & PSC_DSP)
  36                ? DAVINCI_GPSC_DSPDOMAIN
  37                : DAVINCI_GPSC_ARMDOMAIN;
  38}
  39
  40static void __clk_enable(struct clk *clk)
  41{
  42        if (clk->parent)
  43                __clk_enable(clk->parent);
  44        if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
  45                davinci_psc_config(psc_domain(clk), clk->psc_ctlr,
  46                                clk->lpsc, 1);
  47}
  48
  49static void __clk_disable(struct clk *clk)
  50{
  51        if (WARN_ON(clk->usecount == 0))
  52                return;
  53        if (--clk->usecount == 0 && !(clk->flags & CLK_PLL))
  54                davinci_psc_config(psc_domain(clk), clk->psc_ctlr,
  55                                clk->lpsc, 0);
  56        if (clk->parent)
  57                __clk_disable(clk->parent);
  58}
  59
  60int clk_enable(struct clk *clk)
  61{
  62        unsigned long flags;
  63
  64        if (clk == NULL || IS_ERR(clk))
  65                return -EINVAL;
  66
  67        spin_lock_irqsave(&clockfw_lock, flags);
  68        __clk_enable(clk);
  69        spin_unlock_irqrestore(&clockfw_lock, flags);
  70
  71        return 0;
  72}
  73EXPORT_SYMBOL(clk_enable);
  74
  75void clk_disable(struct clk *clk)
  76{
  77        unsigned long flags;
  78
  79        if (clk == NULL || IS_ERR(clk))
  80                return;
  81
  82        spin_lock_irqsave(&clockfw_lock, flags);
  83        __clk_disable(clk);
  84        spin_unlock_irqrestore(&clockfw_lock, flags);
  85}
  86EXPORT_SYMBOL(clk_disable);
  87
  88unsigned long clk_get_rate(struct clk *clk)
  89{
  90        if (clk == NULL || IS_ERR(clk))
  91                return -EINVAL;
  92
  93        return clk->rate;
  94}
  95EXPORT_SYMBOL(clk_get_rate);
  96
  97long clk_round_rate(struct clk *clk, unsigned long rate)
  98{
  99        if (clk == NULL || IS_ERR(clk))
 100                return -EINVAL;
 101
 102        return clk->rate;
 103}
 104EXPORT_SYMBOL(clk_round_rate);
 105
 106int clk_set_rate(struct clk *clk, unsigned long rate)
 107{
 108        if (clk == NULL || IS_ERR(clk))
 109                return -EINVAL;
 110
 111        /* changing the clk rate is not supported */
 112        return -EINVAL;
 113}
 114EXPORT_SYMBOL(clk_set_rate);
 115
 116int clk_register(struct clk *clk)
 117{
 118        if (clk == NULL || IS_ERR(clk))
 119                return -EINVAL;
 120
 121        if (WARN(clk->parent && !clk->parent->rate,
 122                        "CLK: %s parent %s has no rate!\n",
 123                        clk->name, clk->parent->name))
 124                return -EINVAL;
 125
 126        mutex_lock(&clocks_mutex);
 127        list_add_tail(&clk->node, &clocks);
 128        mutex_unlock(&clocks_mutex);
 129
 130        /* If rate is already set, use it */
 131        if (clk->rate)
 132                return 0;
 133
 134        /* Otherwise, default to parent rate */
 135        if (clk->parent)
 136                clk->rate = clk->parent->rate;
 137
 138        return 0;
 139}
 140EXPORT_SYMBOL(clk_register);
 141
 142void clk_unregister(struct clk *clk)
 143{
 144        if (clk == NULL || IS_ERR(clk))
 145                return;
 146
 147        mutex_lock(&clocks_mutex);
 148        list_del(&clk->node);
 149        mutex_unlock(&clocks_mutex);
 150}
 151EXPORT_SYMBOL(clk_unregister);
 152
 153#ifdef CONFIG_DAVINCI_RESET_CLOCKS
 154/*
 155 * Disable any unused clocks left on by the bootloader
 156 */
 157static int __init clk_disable_unused(void)
 158{
 159        struct clk *ck;
 160
 161        spin_lock_irq(&clockfw_lock);
 162        list_for_each_entry(ck, &clocks, node) {
 163                if (ck->usecount > 0)
 164                        continue;
 165                if (!(ck->flags & CLK_PSC))
 166                        continue;
 167
 168                /* ignore if in Disabled or SwRstDisable states */
 169                if (!davinci_psc_is_clk_active(ck->psc_ctlr, ck->lpsc))
 170                        continue;
 171
 172                pr_info("Clocks: disable unused %s\n", ck->name);
 173                davinci_psc_config(psc_domain(ck), ck->psc_ctlr, ck->lpsc, 0);
 174        }
 175        spin_unlock_irq(&clockfw_lock);
 176
 177        return 0;
 178}
 179late_initcall(clk_disable_unused);
 180#endif
 181
 182static void clk_sysclk_recalc(struct clk *clk)
 183{
 184        u32 v, plldiv;
 185        struct pll_data *pll;
 186
 187        /* If this is the PLL base clock, no more calculations needed */
 188        if (clk->pll_data)
 189                return;
 190
 191        if (WARN_ON(!clk->parent))
 192                return;
 193
 194        clk->rate = clk->parent->rate;
 195
 196        /* Otherwise, the parent must be a PLL */
 197        if (WARN_ON(!clk->parent->pll_data))
 198                return;
 199
 200        pll = clk->parent->pll_data;
 201
 202        /* If pre-PLL, source clock is before the multiplier and divider(s) */
 203        if (clk->flags & PRE_PLL)
 204                clk->rate = pll->input_rate;
 205
 206        if (!clk->div_reg)
 207                return;
 208
 209        v = __raw_readl(pll->base + clk->div_reg);
 210        if (v & PLLDIV_EN) {
 211                plldiv = (v & PLLDIV_RATIO_MASK) + 1;
 212                if (plldiv)
 213                        clk->rate /= plldiv;
 214        }
 215}
 216
 217static void __init clk_pll_init(struct clk *clk)
 218{
 219        u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
 220        u8 bypass;
 221        struct pll_data *pll = clk->pll_data;
 222
 223        pll->base = IO_ADDRESS(pll->phys_base);
 224        ctrl = __raw_readl(pll->base + PLLCTL);
 225        clk->rate = pll->input_rate = clk->parent->rate;
 226
 227        if (ctrl & PLLCTL_PLLEN) {
 228                bypass = 0;
 229                mult = __raw_readl(pll->base + PLLM);
 230                if (cpu_is_davinci_dm365())
 231                        mult = 2 * (mult & PLLM_PLLM_MASK);
 232                else
 233                        mult = (mult & PLLM_PLLM_MASK) + 1;
 234        } else
 235                bypass = 1;
 236
 237        if (pll->flags & PLL_HAS_PREDIV) {
 238                prediv = __raw_readl(pll->base + PREDIV);
 239                if (prediv & PLLDIV_EN)
 240                        prediv = (prediv & PLLDIV_RATIO_MASK) + 1;
 241                else
 242                        prediv = 1;
 243        }
 244
 245        /* pre-divider is fixed, but (some?) chips won't report that */
 246        if (cpu_is_davinci_dm355() && pll->num == 1)
 247                prediv = 8;
 248
 249        if (pll->flags & PLL_HAS_POSTDIV) {
 250                postdiv = __raw_readl(pll->base + POSTDIV);
 251                if (postdiv & PLLDIV_EN)
 252                        postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1;
 253                else
 254                        postdiv = 1;
 255        }
 256
 257        if (!bypass) {
 258                clk->rate /= prediv;
 259                clk->rate *= mult;
 260                clk->rate /= postdiv;
 261        }
 262
 263        pr_debug("PLL%d: input = %lu MHz [ ",
 264                 pll->num, clk->parent->rate / 1000000);
 265        if (bypass)
 266                pr_debug("bypass ");
 267        if (prediv > 1)
 268                pr_debug("/ %d ", prediv);
 269        if (mult > 1)
 270                pr_debug("* %d ", mult);
 271        if (postdiv > 1)
 272                pr_debug("/ %d ", postdiv);
 273        pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000);
 274}
 275
 276int __init davinci_clk_init(struct davinci_clk *clocks)
 277  {
 278        struct davinci_clk *c;
 279        struct clk *clk;
 280
 281        for (c = clocks; c->lk.clk; c++) {
 282                clk = c->lk.clk;
 283
 284                if (clk->pll_data)
 285                        clk_pll_init(clk);
 286
 287                /* Calculate rates for PLL-derived clocks */
 288                else if (clk->flags & CLK_PLL)
 289                        clk_sysclk_recalc(clk);
 290
 291                if (clk->lpsc)
 292                        clk->flags |= CLK_PSC;
 293
 294                clkdev_add(&c->lk);
 295                clk_register(clk);
 296
 297                /* Turn on clocks that Linux doesn't otherwise manage */
 298                if (clk->flags & ALWAYS_ENABLED)
 299                        clk_enable(clk);
 300        }
 301
 302        return 0;
 303}
 304
 305#ifdef CONFIG_PROC_FS
 306#include <linux/proc_fs.h>
 307#include <linux/seq_file.h>
 308
 309static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
 310{
 311        return *pos < 1 ? (void *)1 : NULL;
 312}
 313
 314static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
 315{
 316        ++*pos;
 317        return NULL;
 318}
 319
 320static void davinci_ck_stop(struct seq_file *m, void *v)
 321{
 322}
 323
 324#define CLKNAME_MAX     10              /* longest clock name */
 325#define NEST_DELTA      2
 326#define NEST_MAX        4
 327
 328static void
 329dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
 330{
 331        char            *state;
 332        char            buf[CLKNAME_MAX + NEST_DELTA * NEST_MAX];
 333        struct clk      *clk;
 334        unsigned        i;
 335
 336        if (parent->flags & CLK_PLL)
 337                state = "pll";
 338        else if (parent->flags & CLK_PSC)
 339                state = "psc";
 340        else
 341                state = "";
 342
 343        /* <nest spaces> name <pad to end> */
 344        memset(buf, ' ', sizeof(buf) - 1);
 345        buf[sizeof(buf) - 1] = 0;
 346        i = strlen(parent->name);
 347        memcpy(buf + nest, parent->name,
 348                        min(i, (unsigned)(sizeof(buf) - 1 - nest)));
 349
 350        seq_printf(s, "%s users=%2d %-3s %9ld Hz\n",
 351                   buf, parent->usecount, state, clk_get_rate(parent));
 352        /* REVISIT show device associations too */
 353
 354        /* cost is now small, but not linear... */
 355        list_for_each_entry(clk, &clocks, node) {
 356                if (clk->parent == parent)
 357                        dump_clock(s, nest + NEST_DELTA, clk);
 358        }
 359}
 360
 361static int davinci_ck_show(struct seq_file *m, void *v)
 362{
 363        /* Show clock tree; we know the main oscillator is first.
 364         * We trust nonzero usecounts equate to PSC enables...
 365         */
 366        mutex_lock(&clocks_mutex);
 367        if (!list_empty(&clocks))
 368                dump_clock(m, 0, list_first_entry(&clocks, struct clk, node));
 369        mutex_unlock(&clocks_mutex);
 370
 371        return 0;
 372}
 373
 374static const struct seq_operations davinci_ck_op = {
 375        .start  = davinci_ck_start,
 376        .next   = davinci_ck_next,
 377        .stop   = davinci_ck_stop,
 378        .show   = davinci_ck_show
 379};
 380
 381static int davinci_ck_open(struct inode *inode, struct file *file)
 382{
 383        return seq_open(file, &davinci_ck_op);
 384}
 385
 386static const struct file_operations proc_davinci_ck_operations = {
 387        .open           = davinci_ck_open,
 388        .read           = seq_read,
 389        .llseek         = seq_lseek,
 390        .release        = seq_release,
 391};
 392
 393static int __init davinci_ck_proc_init(void)
 394{
 395        proc_create("davinci_clocks", 0, NULL, &proc_davinci_ck_operations);
 396        return 0;
 397
 398}
 399__initcall(davinci_ck_proc_init);
 400#endif /* CONFIG_DEBUG_PROC_FS */
 401
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.