9
0
Fork 0

clk clkdev: Add clkdev matching based on physbase

Most clock/device associations can be done based on the physical
base address of the corresponding device. So instead of depending
on string matching add an optional possibility to associate a clock
lookups with physical addresses. This also has the advantage that
the lookups for devicetree based devices can be identical to the
platform based devices.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Sascha Hauer 2012-09-20 22:03:05 +02:00
parent 6f4dd1b204
commit 89b710e509
2 changed files with 58 additions and 0 deletions

View File

@ -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);

View File

@ -19,6 +19,7 @@ struct device_d;
struct clk_lookup {
struct list_head node;
unsigned long physbase;
const char *dev_id;
const char *con_id;
struct clk *clk;
@ -33,6 +34,8 @@ void clkdev_drop(struct clk_lookup *cl);
void clkdev_add_table(struct clk_lookup *, size_t);
int clk_add_alias(const char *, const char *, char *, struct device_d *);
int clkdev_add_physbase(struct clk *clk, unsigned long base, const char *id);
#define CLKDEV_DEV_ID(_id, _clk) \
{ \
.dev_id = _id, \