summaryrefslogtreecommitdiffstats
path: root/drivers/clk/clkdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/clkdev.c')
-rw-r--r--drivers/clk/clkdev.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 717fea5689..1ae822ffa6 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -62,6 +62,34 @@ static struct clk *clk_find(const char *dev_id, const char *con_id)
return clk;
}
+static struct clk *clk_find_physbase(struct device_d *dev, const char *con_id)
+{
+ struct clk_lookup *p;
+ unsigned long start;
+ struct clk *clk = ERR_PTR(-ENOSYS);
+
+ if (!dev || !dev->resource)
+ return ERR_PTR(-ENOSYS);
+
+ start = dev->resource[0].start;
+
+ list_for_each_entry(p, &clocks, node) {
+ if (p->physbase == ~0)
+ continue;
+ if (p->physbase != start)
+ continue;
+ if (p->con_id) {
+ if (!con_id || strcmp(p->con_id, con_id))
+ continue;
+ return p->clk;
+ }
+ clk = p->clk;
+ }
+
+ return clk;
+
+}
+
struct clk *clk_get_sys(const char *dev_id, const char *con_id)
{
struct clk *clk;
@@ -77,6 +105,11 @@ EXPORT_SYMBOL(clk_get_sys);
struct clk *clk_get(struct device_d *dev, const char *con_id)
{
const char *dev_id = dev ? dev_name(dev) : NULL;
+ struct clk *clk;
+
+ clk = clk_find_physbase(dev, con_id);
+ if (!IS_ERR(clk))
+ return clk;
return clk_get_sys(dev_id, con_id);
}
@@ -90,6 +123,9 @@ EXPORT_SYMBOL(clk_put);
void clkdev_add(struct clk_lookup *cl)
{
+ if (cl->dev_id)
+ cl->physbase = ~0;
+
list_add_tail(&cl->node, &clocks);
}
EXPORT_SYMBOL(clkdev_add);
@@ -97,6 +133,8 @@ EXPORT_SYMBOL(clkdev_add);
void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
{
while (num--) {
+ if (cl->dev_id)
+ cl->physbase = ~0;
list_add_tail(&cl->node, &clocks);
cl++;
}
@@ -120,6 +158,7 @@ struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
if (!cla)
return NULL;
+ cla->cl.physbase = ~0;
cla->cl.clk = clk;
if (con_id) {
strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
@@ -166,3 +205,19 @@ void clkdev_drop(struct clk_lookup *cl)
kfree(cl);
}
EXPORT_SYMBOL(clkdev_drop);
+
+int clkdev_add_physbase(struct clk *clk, unsigned long base, const char *id)
+{
+ struct clk_lookup *cl;
+
+ cl = xzalloc(sizeof(*cl));
+
+ cl->clk = clk;
+ cl->con_id = id;
+ cl->physbase = base;
+
+ clkdev_add(cl);
+
+ return 0;
+}
+EXPORT_SYMBOL(clkdev_add_physbase);