fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / sh / kernel / cpu / clock.c
index 97fa37f..abb586b 100644 (file)
@@ -1,13 +1,15 @@
 /*
  * arch/sh/kernel/cpu/clock.c - SuperH clock framework
  *
- *  Copyright (C) 2005  Paul Mundt
+ *  Copyright (C) 2005, 2006  Paul Mundt
  *
  * This clock framework is derived from the OMAP version by:
  *
- *     Copyright (C) 2004 Nokia Corporation
+ *     Copyright (C) 2004 - 2005 Nokia Corporation
  *     Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
  *
+ *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
+ *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/kref.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
+#include <linux/platform_device.h>
 #include <asm/clock.h>
 #include <asm/timer.h>
 
 static LIST_HEAD(clock_list);
 static DEFINE_SPINLOCK(clock_lock);
-static DECLARE_MUTEX(clock_list_sem);
+static DEFINE_MUTEX(clock_list_sem);
 
 /*
  * Each subtype is expected to define the init routines for these clocks,
@@ -140,21 +144,21 @@ void clk_disable(struct clk *clk)
 
 int clk_register(struct clk *clk)
 {
-       down(&clock_list_sem);
+       mutex_lock(&clock_list_sem);
 
        list_add(&clk->node, &clock_list);
        kref_init(&clk->kref);
 
-       up(&clock_list_sem);
+       mutex_unlock(&clock_list_sem);
 
        return 0;
 }
 
 void clk_unregister(struct clk *clk)
 {
-       down(&clock_list_sem);
+       mutex_lock(&clock_list_sem);
        list_del(&clk->node);
-       up(&clock_list_sem);
+       mutex_unlock(&clock_list_sem);
 }
 
 inline unsigned long clk_get_rate(struct clk *clk)
@@ -194,18 +198,38 @@ void clk_recalc_rate(struct clk *clk)
                propagate_rate(clk);
 }
 
-struct clk *clk_get(const char *id)
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
+struct clk *clk_get(struct device *dev, const char *id)
 {
        struct clk *p, *clk = ERR_PTR(-ENOENT);
+       int idno;
+
+       if (dev == NULL || dev->bus != &platform_bus_type)
+               idno = -1;
+       else
+               idno = to_platform_device(dev)->id;
+
+       mutex_lock(&clock_list_sem);
+       list_for_each_entry(p, &clock_list, node) {
+               if (p->id == idno &&
+                   strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+                       clk = p;
+                       goto found;
+               }
+       }
 
-       down(&clock_list_sem);
        list_for_each_entry(p, &clock_list, node) {
                if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
                        clk = p;
                        break;
                }
        }
-       up(&clock_list_sem);
+
+found:
+       mutex_unlock(&clock_list_sem);
 
        return clk;
 }
@@ -225,7 +249,7 @@ int __init clk_init(void)
 {
        int i, ret = 0;
 
-       BUG_ON(unlikely(!master_clk.rate));
+       BUG_ON(!master_clk.rate);
 
        for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
                struct clk *clk = onchip_clocks[i];