linux/arch/arm/plat-omap/clock.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/plat-omap/clock.c
   3 *
   4 *  Copyright (C) 2004 - 2008 Nokia corporation
   5 *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
   6 *
   7 *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 */
  13#include <linux/kernel.h>
  14#include <linux/init.h>
  15#include <linux/list.h>
  16#include <linux/errno.h>
  17#include <linux/export.h>
  18#include <linux/err.h>
  19#include <linux/string.h>
  20#include <linux/clk.h>
  21#include <linux/mutex.h>
  22#include <linux/cpufreq.h>
  23#include <linux/debugfs.h>
  24#include <linux/io.h>
  25
  26#include <plat/clock.h>
  27
  28static LIST_HEAD(clocks);
  29static DEFINE_MUTEX(clocks_mutex);
  30static DEFINE_SPINLOCK(clockfw_lock);
  31
  32static struct clk_functions *arch_clock;
  33
  34/*
  35 * Standard clock functions defined in include/linux/clk.h
  36 */
  37
  38int clk_enable(struct clk *clk)
  39{
  40        unsigned long flags;
  41        int ret;
  42
  43        if (clk == NULL || IS_ERR(clk))
  44                return -EINVAL;
  45
  46        if (!arch_clock || !arch_clock->clk_enable)
  47                return -EINVAL;
  48
  49        spin_lock_irqsave(&clockfw_lock, flags);
  50        ret = arch_clock->clk_enable(clk);
  51        spin_unlock_irqrestore(&clockfw_lock, flags);
  52
  53        return ret;
  54}
  55EXPORT_SYMBOL(clk_enable);
  56
  57void clk_disable(struct clk *clk)
  58{
  59        unsigned long flags;
  60
  61        if (clk == NULL || IS_ERR(clk))
  62                return;
  63
  64        if (!arch_clock || !arch_clock->clk_disable)
  65                return;
  66
  67        spin_lock_irqsave(&clockfw_lock, flags);
  68        if (clk->usecount == 0) {
  69                pr_err("Trying disable clock %s with 0 usecount\n",
  70                       clk->name);
  71                WARN_ON(1);
  72                goto out;
  73        }
  74
  75        arch_clock->clk_disable(clk);
  76
  77out:
  78        spin_unlock_irqrestore(&clockfw_lock, flags);
  79}
  80EXPORT_SYMBOL(clk_disable);
  81
  82unsigned long clk_get_rate(struct clk *clk)
  83{
  84        unsigned long flags;
  85        unsigned long ret;
  86
  87        if (clk == NULL || IS_ERR(clk))
  88                return 0;
  89
  90        spin_lock_irqsave(&clockfw_lock, flags);
  91        ret = clk->rate;
  92        spin_unlock_irqrestore(&clockfw_lock, flags);
  93
  94        return ret;
  95}
  96EXPORT_SYMBOL(clk_get_rate);
  97
  98/*
  99 * Optional clock functions defined in include/linux/clk.h
 100 */
 101
 102long clk_round_rate(struct clk *clk, unsigned long rate)
 103{
 104        unsigned long flags;
 105        long ret;
 106
 107        if (clk == NULL || IS_ERR(clk))
 108                return 0;
 109
 110        if (!arch_clock || !arch_clock->clk_round_rate)
 111                return 0;
 112
 113        spin_lock_irqsave(&clockfw_lock, flags);
 114        ret = arch_clock->clk_round_rate(clk, rate);
 115        spin_unlock_irqrestore(&clockfw_lock, flags);
 116
 117        return ret;
 118}
 119EXPORT_SYMBOL(clk_round_rate);
 120
 121int clk_set_rate(struct clk *clk, unsigned long rate)
 122{
 123        unsigned long flags;
 124        int ret = -EINVAL;
 125
 126        if (clk == NULL || IS_ERR(clk))
 127                return ret;
 128
 129        if (!arch_clock || !arch_clock->clk_set_rate)
 130                return ret;
 131
 132        spin_lock_irqsave(&clockfw_lock, flags);
 133        ret = arch_clock->clk_set_rate(clk, rate);
 134        if (ret == 0)
 135                propagate_rate(clk);
 136        spin_unlock_irqrestore(&clockfw_lock, flags);
 137
 138        return ret;
 139}
 140EXPORT_SYMBOL(clk_set_rate);
 141
 142int clk_set_parent(struct clk *clk, struct clk *parent)
 143{
 144        unsigned long flags;
 145        int ret = -EINVAL;
 146
 147        if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
 148                return ret;
 149
 150        if (!arch_clock || !arch_clock->clk_set_parent)
 151                return ret;
 152
 153        spin_lock_irqsave(&clockfw_lock, flags);
 154        if (clk->usecount == 0) {
 155                ret = arch_clock->clk_set_parent(clk, parent);
 156                if (ret == 0)
 157                        propagate_rate(clk);
 158        } else
 159                ret = -EBUSY;
 160        spin_unlock_irqrestore(&clockfw_lock, flags);
 161
 162        return ret;
 163}
 164EXPORT_SYMBOL(clk_set_parent);
 165
 166struct clk *clk_get_parent(struct clk *clk)
 167{
 168        return clk->parent;
 169}
 170EXPORT_SYMBOL(clk_get_parent);
 171
 172/*
 173 * OMAP specific clock functions shared between omap1 and omap2
 174 */
 175
 176int __initdata mpurate;
 177
 178/*
 179 * By default we use the rate set by the bootloader.
 180 * You can override this with mpurate= cmdline option.
 181 */
 182static int __init omap_clk_setup(char *str)
 183{
 184        get_option(&str, &mpurate);
 185
 186        if (!mpurate)
 187                return 1;
 188
 189        if (mpurate < 1000)
 190                mpurate *= 1000000;
 191
 192        return 1;
 193}
 194__setup("mpurate=", omap_clk_setup);
 195
 196/* Used for clocks that always have same value as the parent clock */
 197unsigned long followparent_recalc(struct clk *clk)
 198{
 199        return clk->parent->rate;
 200}
 201
 202/*
 203 * Used for clocks that have the same value as the parent clock,
 204 * divided by some factor
 205 */
 206unsigned long omap_fixed_divisor_recalc(struct clk *clk)
 207{
 208        WARN_ON(!clk->fixed_div);
 209
 210        return clk->parent->rate / clk->fixed_div;
 211}
 212
 213void clk_reparent(struct clk *child, struct clk *parent)
 214{
 215        list_del_init(&child->sibling);
 216        if (parent)
 217                list_add(&child->sibling, &parent->children);
 218        child->parent = parent;
 219
 220        /* now do the debugfs renaming to reattach the child
 221           to the proper parent */
 222}
 223
 224/* Propagate rate to children */
 225void propagate_rate(struct clk *tclk)
 226{
 227        struct clk *clkp;
 228
 229        list_for_each_entry(clkp, &tclk->children, sibling) {
 230                if (clkp->recalc)
 231                        clkp->rate = clkp->recalc(clkp);
 232                propagate_rate(clkp);
 233        }
 234}
 235
 236static LIST_HEAD(root_clks);
 237
 238/**
 239 * recalculate_root_clocks - recalculate and propagate all root clocks
 240 *
 241 * Recalculates all root clocks (clocks with no parent), which if the
 242 * clock's .recalc is set correctly, should also propagate their rates.
 243 * Called at init.
 244 */
 245void recalculate_root_clocks(void)
 246{
 247        struct clk *clkp;
 248
 249        list_for_each_entry(clkp, &root_clks, sibling) {
 250                if (clkp->recalc)
 251                        clkp->rate = clkp->recalc(clkp);
 252                propagate_rate(clkp);
 253        }
 254}
 255
 256/**
 257 * clk_preinit - initialize any fields in the struct clk before clk init
 258 * @clk: struct clk * to initialize
 259 *
 260 * Initialize any struct clk fields needed before normal clk initialization
 261 * can run.  No return value.
 262 */
 263void clk_preinit(struct clk *clk)
 264{
 265        INIT_LIST_HEAD(&clk->children);
 266}
 267
 268int clk_register(struct clk *clk)
 269{
 270        if (clk == NULL || IS_ERR(clk))
 271                return -EINVAL;
 272
 273        /*
 274         * trap out already registered clocks
 275         */
 276        if (clk->node.next || clk->node.prev)
 277                return 0;
 278
 279        mutex_lock(&clocks_mutex);
 280        if (clk->parent)
 281                list_add(&clk->sibling, &clk->parent->children);
 282        else
 283                list_add(&clk->sibling, &root_clks);
 284
 285        list_add(&clk->node, &clocks);
 286        if (clk->init)
 287                clk->init(clk);
 288        mutex_unlock(&clocks_mutex);
 289
 290        return 0;
 291}
 292EXPORT_SYMBOL(clk_register);
 293
 294void clk_unregister(struct clk *clk)
 295{
 296        if (clk == NULL || IS_ERR(clk))
 297                return;
 298
 299        mutex_lock(&clocks_mutex);
 300        list_del(&clk->sibling);
 301        list_del(&clk->node);
 302        mutex_unlock(&clocks_mutex);
 303}
 304EXPORT_SYMBOL(clk_unregister);
 305
 306void clk_enable_init_clocks(void)
 307{
 308        struct clk *clkp;
 309
 310        list_for_each_entry(clkp, &clocks, node) {
 311                if (clkp->flags & ENABLE_ON_INIT)
 312                        clk_enable(clkp);
 313        }
 314}
 315
 316/**
 317 * omap_clk_get_by_name - locate OMAP struct clk by its name
 318 * @name: name of the struct clk to locate
 319 *
 320 * Locate an OMAP struct clk by its name.  Assumes that struct clk
 321 * names are unique.  Returns NULL if not found or a pointer to the
 322 * struct clk if found.
 323 */
 324struct clk *omap_clk_get_by_name(const char *name)
 325{
 326        struct clk *c;
 327        struct clk *ret = NULL;
 328
 329        mutex_lock(&clocks_mutex);
 330
 331        list_for_each_entry(c, &clocks, node) {
 332                if (!strcmp(c->name, name)) {
 333                        ret = c;
 334                        break;
 335                }
 336        }
 337
 338        mutex_unlock(&clocks_mutex);
 339
 340        return ret;
 341}
 342
 343int omap_clk_enable_autoidle_all(void)
 344{
 345        struct clk *c;
 346        unsigned long flags;
 347
 348        spin_lock_irqsave(&clockfw_lock, flags);
 349
 350        list_for_each_entry(c, &clocks, node)
 351                if (c->ops->allow_idle)
 352                        c->ops->allow_idle(c);
 353
 354        spin_unlock_irqrestore(&clockfw_lock, flags);
 355
 356        return 0;
 357}
 358
 359int omap_clk_disable_autoidle_all(void)
 360{
 361        struct clk *c;
 362        unsigned long flags;
 363
 364        spin_lock_irqsave(&clockfw_lock, flags);
 365
 366        list_for_each_entry(c, &clocks, node)
 367                if (c->ops->deny_idle)
 368                        c->ops->deny_idle(c);
 369
 370        spin_unlock_irqrestore(&clockfw_lock, flags);
 371
 372        return 0;
 373}
 374
 375/*
 376 * Low level helpers
 377 */
 378static int clkll_enable_null(struct clk *clk)
 379{
 380        return 0;
 381}
 382
 383static void clkll_disable_null(struct clk *clk)
 384{
 385}
 386
 387const struct clkops clkops_null = {
 388        .enable         = clkll_enable_null,
 389        .disable        = clkll_disable_null,
 390};
 391
 392/*
 393 * Dummy clock
 394 *
 395 * Used for clock aliases that are needed on some OMAPs, but not others
 396 */
 397struct clk dummy_ck = {
 398        .name   = "dummy",
 399        .ops    = &clkops_null,
 400};
 401
 402#ifdef CONFIG_CPU_FREQ
 403void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
 404{
 405        unsigned long flags;
 406
 407        if (!arch_clock || !arch_clock->clk_init_cpufreq_table)
 408                return;
 409
 410        spin_lock_irqsave(&clockfw_lock, flags);
 411        arch_clock->clk_init_cpufreq_table(table);
 412        spin_unlock_irqrestore(&clockfw_lock, flags);
 413}
 414
 415void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
 416{
 417        unsigned long flags;
 418
 419        if (!arch_clock || !arch_clock->clk_exit_cpufreq_table)
 420                return;
 421
 422        spin_lock_irqsave(&clockfw_lock, flags);
 423        arch_clock->clk_exit_cpufreq_table(table);
 424        spin_unlock_irqrestore(&clockfw_lock, flags);
 425}
 426#endif
 427
 428/*
 429 *
 430 */
 431
 432#ifdef CONFIG_OMAP_RESET_CLOCKS
 433/*
 434 * Disable any unused clocks left on by the bootloader
 435 */
 436static int __init clk_disable_unused(void)
 437{
 438        struct clk *ck;
 439        unsigned long flags;
 440
 441        if (!arch_clock || !arch_clock->clk_disable_unused)
 442                return 0;
 443
 444        pr_info("clock: disabling unused clocks to save power\n");
 445        list_for_each_entry(ck, &clocks, node) {
 446                if (ck->ops == &clkops_null)
 447                        continue;
 448
 449                if (ck->usecount > 0 || !ck->enable_reg)
 450                        continue;
 451
 452                spin_lock_irqsave(&clockfw_lock, flags);
 453                arch_clock->clk_disable_unused(ck);
 454                spin_unlock_irqrestore(&clockfw_lock, flags);
 455        }
 456
 457        return 0;
 458}
 459late_initcall(clk_disable_unused);
 460late_initcall(omap_clk_enable_autoidle_all);
 461#endif
 462
 463int __init clk_init(struct clk_functions * custom_clocks)
 464{
 465        if (!custom_clocks) {
 466                pr_err("No custom clock functions registered\n");
 467                BUG();
 468        }
 469
 470        arch_clock = custom_clocks;
 471
 472        return 0;
 473}
 474
 475#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
 476/*
 477 *      debugfs support to trace clock tree hierarchy and attributes
 478 */
 479
 480#include <linux/debugfs.h>
 481#include <linux/seq_file.h>
 482
 483static struct dentry *clk_debugfs_root;
 484
 485static int clk_dbg_show_summary(struct seq_file *s, void *unused)
 486{
 487        struct clk *c;
 488        struct clk *pa;
 489
 490        seq_printf(s, "%-30s %-30s %-10s %s\n",
 491                "clock-name", "parent-name", "rate", "use-count");
 492
 493        list_for_each_entry(c, &clocks, node) {
 494                pa = c->parent;
 495                seq_printf(s, "%-30s %-30s %-10lu %d\n",
 496                        c->name, pa ? pa->name : "none", c->rate, c->usecount);
 497        }
 498
 499        return 0;
 500}
 501
 502static int clk_dbg_open(struct inode *inode, struct file *file)
 503{
 504        return single_open(file, clk_dbg_show_summary, inode->i_private);
 505}
 506
 507static const struct file_operations debug_clock_fops = {
 508        .open           = clk_dbg_open,
 509        .read           = seq_read,
 510        .llseek         = seq_lseek,
 511        .release        = single_release,
 512};
 513
 514static int clk_debugfs_register_one(struct clk *c)
 515{
 516        int err;
 517        struct dentry *d;
 518        struct clk *pa = c->parent;
 519
 520        d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
 521        if (!d)
 522                return -ENOMEM;
 523        c->dent = d;
 524
 525        d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
 526        if (!d) {
 527                err = -ENOMEM;
 528                goto err_out;
 529        }
 530        d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
 531        if (!d) {
 532                err = -ENOMEM;
 533                goto err_out;
 534        }
 535        d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
 536        if (!d) {
 537                err = -ENOMEM;
 538                goto err_out;
 539        }
 540        return 0;
 541
 542err_out:
 543        debugfs_remove_recursive(c->dent);
 544        return err;
 545}
 546
 547static int clk_debugfs_register(struct clk *c)
 548{
 549        int err;
 550        struct clk *pa = c->parent;
 551
 552        if (pa && !pa->dent) {
 553                err = clk_debugfs_register(pa);
 554                if (err)
 555                        return err;
 556        }
 557
 558        if (!c->dent) {
 559                err = clk_debugfs_register_one(c);
 560                if (err)
 561                        return err;
 562        }
 563        return 0;
 564}
 565
 566static int __init clk_debugfs_init(void)
 567{
 568        struct clk *c;
 569        struct dentry *d;
 570        int err;
 571
 572        d = debugfs_create_dir("clock", NULL);
 573        if (!d)
 574                return -ENOMEM;
 575        clk_debugfs_root = d;
 576
 577        list_for_each_entry(c, &clocks, node) {
 578                err = clk_debugfs_register(c);
 579                if (err)
 580                        goto err_out;
 581        }
 582
 583        d = debugfs_create_file("summary", S_IRUGO,
 584                d, NULL, &debug_clock_fops);
 585        if (!d)
 586                return -ENOMEM;
 587
 588        return 0;
 589err_out:
 590        debugfs_remove_recursive(clk_debugfs_root);
 591        return err;
 592}
 593late_initcall(clk_debugfs_init);
 594
 595#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
 596