summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-05-12 05:51:05 +0900
committerPaul Mundt <lethal@linux-sh.org>2009-05-12 05:51:05 +0900
commitaa87aa343f2cd236b5eccd643abd4df918ed5c4f (patch)
tree2a6dbd7be7f6ce9d00c0800e8a10a7cb7ed7c7d1 /arch
parentae891a4264c91246c0b4c22be68b9838747ae48d (diff)
downloadkernel-crypto-aa87aa343f2cd236b5eccd643abd4df918ed5c4f.tar.gz
kernel-crypto-aa87aa343f2cd236b5eccd643abd4df918ed5c4f.tar.xz
kernel-crypto-aa87aa343f2cd236b5eccd643abd4df918ed5c4f.zip
sh: clkfwk: Improve the generic clk_set_parent() implementation.
This causes the generic clk_set_parent() implementation to be a bit more intelligent. A clk_reparent() is added to move the clock over to the new parent's sibling list, which then allows the generic rate propagation code to succeed. This also becomes a nop if the new and old parents are unchanged. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/sh/include/asm/clock.h1
-rw-r--r--arch/sh/kernel/cpu/clock.c20
2 files changed, 21 insertions, 0 deletions
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h
index 5de72eef972..fdb915608db 100644
--- a/arch/sh/include/asm/clock.h
+++ b/arch/sh/include/asm/clock.h
@@ -48,6 +48,7 @@ int clk_init(void);
unsigned long followparent_recalc(struct clk *);
void recalculate_root_clocks(void);
void propagate_rate(struct clk *);
+int clk_reparent(struct clk *child, struct clk *parent);
void clk_recalc_rate(struct clk *);
int clk_register(struct clk *);
void clk_unregister(struct clk *);
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index e027fe5898d..e3d1de8a46f 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -81,6 +81,19 @@ unsigned long followparent_recalc(struct clk *clk)
return clk->parent->rate;
}
+int 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 */
+
+ return 0;
+}
+
/* Propagate rate to children */
void propagate_rate(struct clk *tclk)
{
@@ -288,12 +301,19 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
if (!parent || !clk)
return ret;
+ if (clk->parent == parent)
+ return 0;
spin_lock_irqsave(&clock_lock, flags);
if (clk->usecount == 0) {
if (clk->ops->set_parent)
ret = clk->ops->set_parent(clk, parent);
+ else
+ ret = clk_reparent(clk, parent);
+
if (ret == 0) {
+ pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
+ clk->name, clk->parent->name, clk->rate);
if (clk->ops->recalc)
clk->rate = clk->ops->recalc(clk);
propagate_rate(clk);