diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-01-31 10:05:51 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-02-08 17:50:42 +0000 |
commit | 3f0a820c4c0b4670fb5f164baa5582e23c2ef118 (patch) | |
tree | 6af02e1456c0316791ab95e7da9c09496f29c232 /arch/arm/plat-omap | |
parent | b5088c0d90b898802318c62caf2320a53df6ce57 (diff) |
[ARM] omap: create a proper tree of clocks
Traditionally, we've tracked the parent/child relationships between
clk structures by setting the child's parent member to point at the
upstream clock. As a result, when decending the tree, we have had
to scan all clocks to find the children.
Avoid this wasteful scanning by keeping a list of the clock's children.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/clock.c | 51 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/mach/clock.h | 7 |
2 files changed, 37 insertions, 21 deletions
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 54da27af0bd..6a1737a7447 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -143,8 +143,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (ret == 0) { if (clk->recalc) clk->recalc(clk); - if (clk->flags & RATE_PROPAGATES) - propagate_rate(clk); + propagate_rate(clk); } spin_unlock_irqrestore(&clockfw_lock, flags); @@ -166,8 +165,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) if (ret == 0) { if (clk->recalc) clk->recalc(clk); - if (clk->flags & RATE_PROPAGATES) - propagate_rate(clk); + propagate_rate(clk); } spin_unlock_irqrestore(&clockfw_lock, flags); @@ -214,24 +212,31 @@ void followparent_recalc(struct clk *clk) clk->rate = clk->parent->rate; } +void clk_reparent(struct clk *child, struct clk *parent) +{ + list_del_init(&child->sibling); + if (parent) + list_add(&child->sibling, &parent->children); + child->parent = parent; + + /* now do the debugfs renaming to reattach the child + to the proper parent */ +} + /* Propagate rate to children */ void propagate_rate(struct clk * tclk) { struct clk *clkp; - if (tclk == NULL || IS_ERR(tclk)) - return; - - list_for_each_entry(clkp, &clocks, node) { - if (likely(clkp->parent != tclk)) - continue; + list_for_each_entry(clkp, &tclk->children, sibling) { if (clkp->recalc) clkp->recalc(clkp); - if (clkp->flags & RATE_PROPAGATES) - propagate_rate(clkp); + propagate_rate(clkp); } } +static LIST_HEAD(root_clks); + /** * recalculate_root_clocks - recalculate and propagate all root clocks * @@ -243,16 +248,18 @@ void recalculate_root_clocks(void) { struct clk *clkp; - list_for_each_entry(clkp, &clocks, node) { - if (!clkp->parent) { - if (clkp->recalc) - clkp->recalc(clkp); - if (clkp->flags & RATE_PROPAGATES) - propagate_rate(clkp); - } + list_for_each_entry(clkp, &root_clks, sibling) { + if (clkp->recalc) + clkp->recalc(clkp); + propagate_rate(clkp); } } +void clk_init_one(struct clk *clk) +{ + INIT_LIST_HEAD(&clk->children); +} + int clk_register(struct clk *clk) { if (clk == NULL || IS_ERR(clk)) @@ -265,6 +272,11 @@ int clk_register(struct clk *clk) return 0; mutex_lock(&clocks_mutex); + if (clk->parent) + list_add(&clk->sibling, &clk->parent->children); + else + list_add(&clk->sibling, &root_clks); + list_add(&clk->node, &clocks); if (clk->init) clk->init(clk); @@ -280,6 +292,7 @@ void clk_unregister(struct clk *clk) return; mutex_lock(&clocks_mutex); + list_del(&clk->sibling); list_del(&clk->node); mutex_unlock(&clocks_mutex); } diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 8705902de1d..af6ae4fa46d 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -70,6 +70,8 @@ struct clk { const char *name; int id; struct clk *parent; + struct list_head children; + struct list_head sibling; /* node for children */ unsigned long rate; __u32 flags; void __iomem *enable_reg; @@ -115,7 +117,9 @@ struct clk_functions { extern unsigned int mpurate; extern int clk_init(struct clk_functions *custom_clocks); +extern void clk_init_one(struct clk *clk); extern int clk_register(struct clk *clk); +extern void clk_reparent(struct clk *child, struct clk *parent); extern void clk_unregister(struct clk *clk); extern void propagate_rate(struct clk *clk); extern void recalculate_root_clocks(void); @@ -131,8 +135,7 @@ extern const struct clkops clkops_null; /* Clock flags */ /* bit 0 is free */ #define RATE_FIXED (1 << 1) /* Fixed clock rate */ -#define RATE_PROPAGATES (1 << 2) /* Program children too */ -/* bits 3-4 are free */ +/* bits 2-4 are free */ #define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */ #define CLOCK_IDLE_CONTROL (1 << 7) #define CLOCK_NO_IDLE_PARENT (1 << 8) |