aboutsummaryrefslogtreecommitdiff
path: root/arch/sh
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/include/asm/clock.h7
-rw-r--r--arch/sh/kernel/cpu/clock.c59
2 files changed, 66 insertions, 0 deletions
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h
index 6a2f4633337..e2f5bf1b4a9 100644
--- a/arch/sh/include/asm/clock.h
+++ b/arch/sh/include/asm/clock.h
@@ -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 */
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 7a356de99d7..34707b86776 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -10,6 +10,10 @@
*
* 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