linux/arch/arm/plat-samsung/clock.c
<<
>>
Prefs
   1/* linux/arch/arm/plat-s3c24xx/clock.c
   2 *
   3 * Copyright 2004-2005 Simtec Electronics
   4 *      Ben Dooks <ben@simtec.co.uk>
   5 *
   6 * S3C24XX Core clock control support
   7 *
   8 * Based on, and code from linux/arch/arm/mach-versatile/clock.c
   9 **
  10 **  Copyright (C) 2004 ARM Limited.
  11 **  Written by Deep Blue Solutions Limited.
  12 *
  13 *
  14 * This program is free software; you can redistribute it and/or modify
  15 * it under the terms of the GNU General Public License as published by
  16 * the Free Software Foundation; either version 2 of the License, or
  17 * (at your option) any later version.
  18 *
  19 * This program is distributed in the hope that it will be useful,
  20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22 * GNU General Public License for more details.
  23 *
  24 * You should have received a copy of the GNU General Public License
  25 * along with this program; if not, write to the Free Software
  26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  27*/
  28
  29#include <linux/init.h>
  30#include <linux/module.h>
  31#include <linux/kernel.h>
  32#include <linux/list.h>
  33#include <linux/errno.h>
  34#include <linux/err.h>
  35#include <linux/platform_device.h>
  36#include <linux/sysdev.h>
  37#include <linux/interrupt.h>
  38#include <linux/ioport.h>
  39#include <linux/clk.h>
  40#include <linux/spinlock.h>
  41#include <linux/io.h>
  42#if defined(CONFIG_DEBUG_FS)
  43#include <linux/debugfs.h>
  44#endif
  45
  46#include <mach/hardware.h>
  47#include <asm/irq.h>
  48
  49#include <plat/cpu-freq.h>
  50
  51#include <plat/clock.h>
  52#include <plat/cpu.h>
  53
  54#include <linux/serial_core.h>
  55#include <plat/regs-serial.h> /* for s3c24xx_uart_devs */
  56
  57/* clock information */
  58
  59static LIST_HEAD(clocks);
  60
  61/* We originally used an mutex here, but some contexts (see resume)
  62 * are calling functions such as clk_set_parent() with IRQs disabled
  63 * causing an BUG to be triggered.
  64 */
  65DEFINE_SPINLOCK(clocks_lock);
  66
  67/* enable and disable calls for use with the clk struct */
  68
  69static int clk_null_enable(struct clk *clk, int enable)
  70{
  71        return 0;
  72}
  73
  74static int dev_is_s3c_uart(struct device *dev)
  75{
  76        struct platform_device **pdev = s3c24xx_uart_devs;
  77        int i;
  78        for (i = 0; i < ARRAY_SIZE(s3c24xx_uart_devs); i++, pdev++)
  79                if (*pdev && dev == &(*pdev)->dev)
  80                        return 1;
  81        return 0;
  82}
  83
  84/*
  85 * Serial drivers call get_clock() very early, before platform bus
  86 * has been set up, this requires a special check to let them get
  87 * a proper clock
  88 */
  89
  90static int dev_is_platform_device(struct device *dev)
  91{
  92        return dev->bus == &platform_bus_type ||
  93               (dev->bus == NULL && dev_is_s3c_uart(dev));
  94}
  95
  96/* Clock API calls */
  97
  98struct clk *clk_get(struct device *dev, const char *id)
  99{
 100        struct clk *p;
 101        struct clk *clk = ERR_PTR(-ENOENT);
 102        int idno;
 103
 104        if (dev == NULL || !dev_is_platform_device(dev))
 105                idno = -1;
 106        else
 107                idno = to_platform_device(dev)->id;
 108
 109        spin_lock(&clocks_lock);
 110
 111        list_for_each_entry(p, &clocks, list) {
 112                if (p->id == idno &&
 113                    strcmp(id, p->name) == 0 &&
 114                    try_module_get(p->owner)) {
 115                        clk = p;
 116                        break;
 117                }
 118        }
 119
 120        /* check for the case where a device was supplied, but the
 121         * clock that was being searched for is not device specific */
 122
 123        if (IS_ERR(clk)) {
 124                list_for_each_entry(p, &clocks, list) {
 125                        if (p->id == -1 && strcmp(id, p->name) == 0 &&
 126                            try_module_get(p->owner)) {
 127                                clk = p;
 128                                break;
 129                        }
 130                }
 131        }
 132
 133        spin_unlock(&clocks_lock);
 134        return clk;
 135}
 136
 137void clk_put(struct clk *clk)
 138{
 139        module_put(clk->owner);
 140}
 141
 142int clk_enable(struct clk *clk)
 143{
 144        if (IS_ERR(clk) || clk == NULL)
 145                return -EINVAL;
 146
 147        clk_enable(clk->parent);
 148
 149        spin_lock(&clocks_lock);
 150
 151        if ((clk->usage++) == 0)
 152                (clk->enable)(clk, 1);
 153
 154        spin_unlock(&clocks_lock);
 155        return 0;
 156}
 157
 158void clk_disable(struct clk *clk)
 159{
 160        if (IS_ERR(clk) || clk == NULL)
 161                return;
 162
 163        spin_lock(&clocks_lock);
 164
 165        if ((--clk->usage) == 0)
 166                (clk->enable)(clk, 0);
 167
 168        spin_unlock(&clocks_lock);
 169        clk_disable(clk->parent);
 170}
 171
 172
 173unsigned long clk_get_rate(struct clk *clk)
 174{
 175        if (IS_ERR(clk))
 176                return 0;
 177
 178        if (clk->rate != 0)
 179                return clk->rate;
 180
 181        if (clk->ops != NULL && clk->ops->get_rate != NULL)
 182                return (clk->ops->get_rate)(clk);
 183
 184        if (clk->parent != NULL)
 185                return clk_get_rate(clk->parent);
 186
 187        return clk->rate;
 188}
 189
 190long clk_round_rate(struct clk *clk, unsigned long rate)
 191{
 192        if (!IS_ERR(clk) && clk->ops && clk->ops->round_rate)
 193                return (clk->ops->round_rate)(clk, rate);
 194
 195        return rate;
 196}
 197
 198int clk_set_rate(struct clk *clk, unsigned long rate)
 199{
 200        int ret;
 201
 202        if (IS_ERR(clk))
 203                return -EINVAL;
 204
 205        /* We do not default just do a clk->rate = rate as
 206         * the clock may have been made this way by choice.
 207         */
 208
 209        WARN_ON(clk->ops == NULL);
 210        WARN_ON(clk->ops && clk->ops->set_rate == NULL);
 211
 212        if (clk->ops == NULL || clk->ops->set_rate == NULL)
 213                return -EINVAL;
 214
 215        spin_lock(&clocks_lock);
 216        ret = (clk->ops->set_rate)(clk, rate);
 217        spin_unlock(&clocks_lock);
 218
 219        return ret;
 220}
 221
 222struct clk *clk_get_parent(struct clk *clk)
 223{
 224        return clk->parent;
 225}
 226
 227int clk_set_parent(struct clk *clk, struct clk *parent)
 228{
 229        int ret = 0;
 230
 231        if (IS_ERR(clk))
 232                return -EINVAL;
 233
 234        spin_lock(&clocks_lock);
 235
 236        if (clk->ops && clk->ops->set_parent)
 237                ret = (clk->ops->set_parent)(clk, parent);
 238
 239        spin_unlock(&clocks_lock);
 240
 241        return ret;
 242}
 243
 244EXPORT_SYMBOL(clk_get);
 245EXPORT_SYMBOL(clk_put);
 246EXPORT_SYMBOL(clk_enable);
 247EXPORT_SYMBOL(clk_disable);
 248EXPORT_SYMBOL(clk_get_rate);
 249EXPORT_SYMBOL(clk_round_rate);
 250EXPORT_SYMBOL(clk_set_rate);
 251EXPORT_SYMBOL(clk_get_parent);
 252EXPORT_SYMBOL(clk_set_parent);
 253
 254/* base clocks */
 255
 256int clk_default_setrate(struct clk *clk, unsigned long rate)
 257{
 258        clk->rate = rate;
 259        return 0;
 260}
 261
 262struct clk_ops clk_ops_def_setrate = {
 263        .set_rate       = clk_default_setrate,
 264};
 265
 266struct clk clk_xtal = {
 267        .name           = "xtal",
 268        .id             = -1,
 269        .rate           = 0,
 270        .parent         = NULL,
 271        .ctrlbit        = 0,
 272};
 273
 274struct clk clk_ext = {
 275        .name           = "ext",
 276        .id             = -1,
 277};
 278
 279struct clk clk_epll = {
 280        .name           = "epll",
 281        .id             = -1,
 282};
 283
 284struct clk clk_mpll = {
 285        .name           = "mpll",
 286        .id             = -1,
 287        .ops            = &clk_ops_def_setrate,
 288};
 289
 290struct clk clk_upll = {
 291        .name           = "upll",
 292        .id             = -1,
 293        .parent         = NULL,
 294        .ctrlbit        = 0,
 295};
 296
 297struct clk clk_f = {
 298        .name           = "fclk",
 299        .id             = -1,
 300        .rate           = 0,
 301        .parent         = &clk_mpll,
 302        .ctrlbit        = 0,
 303};
 304
 305struct clk clk_h = {
 306        .name           = "hclk",
 307        .id             = -1,
 308        .rate           = 0,
 309        .parent         = NULL,
 310        .ctrlbit        = 0,
 311        .ops            = &clk_ops_def_setrate,
 312};
 313
 314struct clk clk_p = {
 315        .name           = "pclk",
 316        .id             = -1,
 317        .rate           = 0,
 318        .parent         = NULL,
 319        .ctrlbit        = 0,
 320        .ops            = &clk_ops_def_setrate,
 321};
 322
 323struct clk clk_usb_bus = {
 324        .name           = "usb-bus",
 325        .id             = -1,
 326        .rate           = 0,
 327        .parent         = &clk_upll,
 328};
 329
 330
 331struct clk s3c24xx_uclk = {
 332        .name           = "uclk",
 333        .id             = -1,
 334};
 335
 336/* initialise the clock system */
 337
 338/**
 339 * s3c24xx_register_clock() - register a clock
 340 * @clk: The clock to register
 341 *
 342 * Add the specified clock to the list of clocks known by the system.
 343 */
 344int s3c24xx_register_clock(struct clk *clk)
 345{
 346        if (clk->enable == NULL)
 347                clk->enable = clk_null_enable;
 348
 349        /* add to the list of available clocks */
 350
 351        /* Quick check to see if this clock has already been registered. */
 352        BUG_ON(clk->list.prev != clk->list.next);
 353
 354        spin_lock(&clocks_lock);
 355        list_add(&clk->list, &clocks);
 356        spin_unlock(&clocks_lock);
 357
 358        return 0;
 359}
 360
 361/**
 362 * s3c24xx_register_clocks() - register an array of clock pointers
 363 * @clks: Pointer to an array of struct clk pointers
 364 * @nr_clks: The number of clocks in the @clks array.
 365 *
 366 * Call s3c24xx_register_clock() for all the clock pointers contained
 367 * in the @clks list. Returns the number of failures.
 368 */
 369int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
 370{
 371        int fails = 0;
 372
 373        for (; nr_clks > 0; nr_clks--, clks++) {
 374                if (s3c24xx_register_clock(*clks) < 0) {
 375                        struct clk *clk = *clks;
 376                        printk(KERN_ERR "%s: failed to register %p: %s\n",
 377                               __func__, clk, clk->name);
 378                        fails++;
 379                }
 380        }
 381
 382        return fails;
 383}
 384
 385/**
 386 * s3c_register_clocks() - register an array of clocks
 387 * @clkp: Pointer to the first clock in the array.
 388 * @nr_clks: Number of clocks to register.
 389 *
 390 * Call s3c24xx_register_clock() on the @clkp array given, printing an
 391 * error if it fails to register the clock (unlikely).
 392 */
 393void __init s3c_register_clocks(struct clk *clkp, int nr_clks)
 394{
 395        int ret;
 396
 397        for (; nr_clks > 0; nr_clks--, clkp++) {
 398                ret = s3c24xx_register_clock(clkp);
 399
 400                if (ret < 0) {
 401                        printk(KERN_ERR "Failed to register clock %s (%d)\n",
 402                               clkp->name, ret);
 403                }
 404        }
 405}
 406
 407/**
 408 * s3c_disable_clocks() - disable an array of clocks
 409 * @clkp: Pointer to the first clock in the array.
 410 * @nr_clks: Number of clocks to register.
 411 *
 412 * for internal use only at initialisation time. disable the clocks in the
 413 * @clkp array.
 414 */
 415
 416void __init s3c_disable_clocks(struct clk *clkp, int nr_clks)
 417{
 418        for (; nr_clks > 0; nr_clks--, clkp++)
 419                (clkp->enable)(clkp, 0);
 420}
 421
 422/* initialise all the clocks */
 423
 424int __init s3c24xx_register_baseclocks(unsigned long xtal)
 425{
 426        printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");
 427
 428        clk_xtal.rate = xtal;
 429
 430        /* register our clocks */
 431
 432        if (s3c24xx_register_clock(&clk_xtal) < 0)
 433                printk(KERN_ERR "failed to register master xtal\n");
 434
 435        if (s3c24xx_register_clock(&clk_mpll) < 0)
 436                printk(KERN_ERR "failed to register mpll clock\n");
 437
 438        if (s3c24xx_register_clock(&clk_upll) < 0)
 439                printk(KERN_ERR "failed to register upll clock\n");
 440
 441        if (s3c24xx_register_clock(&clk_f) < 0)
 442                printk(KERN_ERR "failed to register cpu fclk\n");
 443
 444        if (s3c24xx_register_clock(&clk_h) < 0)
 445                printk(KERN_ERR "failed to register cpu hclk\n");
 446
 447        if (s3c24xx_register_clock(&clk_p) < 0)
 448                printk(KERN_ERR "failed to register cpu pclk\n");
 449
 450        return 0;
 451}
 452
 453#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
 454/* debugfs support to trace clock tree hierarchy and attributes */
 455
 456static struct dentry *clk_debugfs_root;
 457
 458static int clk_debugfs_register_one(struct clk *c)
 459{
 460        int err;
 461        struct dentry *d, *child, *child_tmp;
 462        struct clk *pa = c->parent;
 463        char s[255];
 464        char *p = s;
 465
 466        p += sprintf(p, "%s", c->name);
 467
 468        if (c->id >= 0)
 469                sprintf(p, ":%d", c->id);
 470
 471        d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
 472        if (!d)
 473                return -ENOMEM;
 474
 475        c->dent = d;
 476
 477        d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usage);
 478        if (!d) {
 479                err = -ENOMEM;
 480                goto err_out;
 481        }
 482
 483        d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
 484        if (!d) {
 485                err = -ENOMEM;
 486                goto err_out;
 487        }
 488        return 0;
 489
 490err_out:
 491        d = c->dent;
 492        list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
 493                debugfs_remove(child);
 494        debugfs_remove(c->dent);
 495        return err;
 496}
 497
 498static int clk_debugfs_register(struct clk *c)
 499{
 500        int err;
 501        struct clk *pa = c->parent;
 502
 503        if (pa && !pa->dent) {
 504                err = clk_debugfs_register(pa);
 505                if (err)
 506                        return err;
 507        }
 508
 509        if (!c->dent) {
 510                err = clk_debugfs_register_one(c);
 511                if (err)
 512                        return err;
 513        }
 514        return 0;
 515}
 516
 517static int __init clk_debugfs_init(void)
 518{
 519        struct clk *c;
 520        struct dentry *d;
 521        int err;
 522
 523        d = debugfs_create_dir("clock", NULL);
 524        if (!d)
 525                return -ENOMEM;
 526        clk_debugfs_root = d;
 527
 528        list_for_each_entry(c, &clocks, list) {
 529                err = clk_debugfs_register(c);
 530                if (err)
 531                        goto err_out;
 532        }
 533        return 0;
 534
 535err_out:
 536        debugfs_remove_recursive(clk_debugfs_root);
 537        return err;
 538}
 539late_initcall(clk_debugfs_init);
 540
 541#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
 542