summaryrefslogtreecommitdiff
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2009-01-31 10:05:51 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-02-08 17:50:42 +0000
commit3f0a820c4c0b4670fb5f164baa5582e23c2ef118 (patch)
tree6af02e1456c0316791ab95e7da9c09496f29c232 /arch/arm/plat-omap
parentb5088c0d90b898802318c62caf2320a53df6ce57 (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.c51
-rw-r--r--arch/arm/plat-omap/include/mach/clock.h7
2 files changed, 37 insertions, 21 deletions
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 54da27af0bd5..6a1737a74477 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 8705902de1d6..af6ae4fa46d6 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)