sh: clkfwk: Wire up clk_get_sys() support.
authorPaul Mundt <lethal@linux-sh.org>
Mon, 11 May 2009 21:18:09 +0000 (06:18 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 11 May 2009 21:18:09 +0000 (06:18 +0900)
This stubs in clk_get_sys() from the ARM clkdev implementation.
Tentatively conver the clk_get() lookup code to use this, and once the
rest of the in-tree users are happy with this, it can replace the
fallback lookups.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/include/asm/clock.h
arch/sh/kernel/cpu/clock.c

index 6a2f463..e2f5bf1 100644 (file)
@@ -37,6 +37,13 @@ struct clk {
        unsigned long           arch_flags;
 };
 
+struct clk_lookup {
+       struct list_head        node;
+       const char              *dev_id;
+       const char              *con_id;
+       struct clk              *clk;
+};
+
 #define CLK_ENABLE_ON_INIT     (1 << 0)
 
 /* Should be defined by processor-specific code */
index 7a356de..34707b8 100644 (file)
  *
  *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
  *
+ *  With clkdev bits:
+ *
+ *     Copyright (C) 2008 Russell King.
+ *
  * 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.
@@ -335,14 +339,69 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 EXPORT_SYMBOL_GPL(clk_round_rate);
 
 /*
+ * Find the correct struct clk for the device and connection ID.
+ * We do slightly fuzzy matching here:
+ *  An entry with a NULL ID is assumed to be a wildcard.
+ *  If an entry has a device ID, it must match
+ *  If an entry has a connection ID, it must match
+ * Then we take the most specific entry - with the following
+ * order of precidence: dev+con > dev only > con only.
+ */
+static struct clk *clk_find(const char *dev_id, const char *con_id)
+{
+       struct clk_lookup *p;
+       struct clk *clk = NULL;
+       int match, best = 0;
+
+       list_for_each_entry(p, &clock_list, node) {
+               match = 0;
+               if (p->dev_id) {
+                       if (!dev_id || strcmp(p->dev_id, dev_id))
+                               continue;
+                       match += 2;
+               }
+               if (p->con_id) {
+                       if (!con_id || strcmp(p->con_id, con_id))
+                               continue;
+                       match += 1;
+               }
+               if (match == 0)
+                       continue;
+
+               if (match > best) {
+                       clk = p->clk;
+                       best = match;
+               }
+       }
+       return clk;
+}
+
+struct clk *clk_get_sys(const char *dev_id, const char *con_id)
+{
+       struct clk *clk;
+
+       mutex_lock(&clock_list_sem);
+       clk = clk_find(dev_id, con_id);
+       mutex_unlock(&clock_list_sem);
+
+       return clk ? clk : ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL_GPL(clk_get_sys);
+
+/*
  * 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)
 {
+       const char *dev_id = dev ? dev_name(dev) : NULL;
        struct clk *p, *clk = ERR_PTR(-ENOENT);
        int idno;
 
+       clk = clk_get_sys(dev_id, id);
+       if (clk)
+               return clk;
+
        if (dev == NULL || dev->bus != &platform_bus_type)
                idno = -1;
        else