diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index 6a2f46333376e2dbe105e1d5add3571a72744bb7..e2f5bf1b4a9c6c5805d316f6824545be3b0ac9c5 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 7a356de99d7d07ab0d625d0ef8f3f6d3959e1f0a..34707b867760832fe791e0436bc501c1902d4a18 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 * + * 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. @@ -334,15 +338,70 @@ 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