summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2017-02-01 15:56:35 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2017-02-06 07:31:00 +0100
commitc21794d0eea0dad22cb659ca41b13464f0ee1212 (patch)
tree59a42d038fa69bfe88ab239322a34b0046ed2798
parent4cb70c729f2e3563a4a626616aa2ca0c82dd9fff (diff)
downloadbarebox-c21794d0eea0dad22cb659ca41b13464f0ee1212.tar.gz
clk: Keep enable count consistent over reparent
When reparenting a clock we have to make sure the new parent is enabled when the clock was enabled on the old parent. Also we have to decrease the old parents use counter when the clock was enabled. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/clk/clk.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 1566bea..6f30537 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -173,14 +173,15 @@ struct clk *clk_lookup(const char *name)
return ERR_PTR(-ENODEV);
}
-int clk_set_parent(struct clk *clk, struct clk *parent)
+int clk_set_parent(struct clk *clk, struct clk *newparent)
{
- int i;
+ int i, ret;
+ struct clk *curparent = clk_get_parent(clk);
if (IS_ERR(clk))
return PTR_ERR(clk);
- if (IS_ERR(parent))
- return PTR_ERR(parent);
+ if (IS_ERR(newparent))
+ return PTR_ERR(newparent);
if (!clk->num_parents)
return -EINVAL;
@@ -192,14 +193,22 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
clk->parents[i] = clk_lookup(clk->parent_names[i]);
if (!IS_ERR_OR_NULL(clk->parents[i]))
- if (clk->parents[i] == parent)
+ if (clk->parents[i] == newparent)
break;
}
if (i == clk->num_parents)
return -EINVAL;
- return clk->ops->set_parent(clk, i);
+ if (clk->enable_count)
+ clk_enable(newparent);
+
+ ret = clk->ops->set_parent(clk, i);
+
+ if (clk->enable_count)
+ clk_disable(curparent);
+
+ return ret;
}
struct clk *clk_get_parent(struct clk *clk)