diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2017-02-01 15:58:58 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2017-02-06 07:31:12 +0100 |
commit | bea07a688163c806a1001028f9eda715ca96976c (patch) | |
tree | bf4967686bfad2126a884dec54ec7683682afb17 /drivers/clk/clk.c | |
parent | c21794d0eea0dad22cb659ca41b13464f0ee1212 (diff) | |
download | barebox-bea07a688163c806a1001028f9eda715ca96976c.tar.gz barebox-bea07a688163c806a1001028f9eda715ca96976c.tar.xz |
clk: implement CLK_OPS_PARENT_ENABLE
Some clocks may only be modified when their parent clocks are enabled.
The kernel has the CLK_OPS_PARENT_ENABLE flag for this purpose.
Implement it for barebox aswell.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r-- | drivers/clk/clk.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 6f3053727c..93e000c6e9 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -141,6 +141,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) { struct clk *parent; unsigned long parent_rate = 0; + int ret; if (!clk) return 0; @@ -148,14 +149,26 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (IS_ERR(clk)) return PTR_ERR(clk); + if (!clk->ops->set_rate) + return -ENOSYS; + parent = clk_get_parent(clk); - if (parent) + if (parent) { parent_rate = clk_get_rate(parent); - if (clk->ops->set_rate) - return clk->ops->set_rate(clk, rate, parent_rate); + if (clk->flags & CLK_OPS_PARENT_ENABLE) { + ret = clk_enable(parent); + if (ret) + return ret; + } + } + + ret = clk->ops->set_rate(clk, rate, parent_rate); + + if (parent && clk->flags & CLK_OPS_PARENT_ENABLE) + clk_disable(parent); - return -ENOSYS; + return ret; } struct clk *clk_lookup(const char *name) @@ -203,8 +216,18 @@ int clk_set_parent(struct clk *clk, struct clk *newparent) if (clk->enable_count) clk_enable(newparent); + if (clk->flags & CLK_OPS_PARENT_ENABLE) { + clk_enable(curparent); + clk_enable(newparent); + } + ret = clk->ops->set_parent(clk, i); + if (clk->flags & CLK_OPS_PARENT_ENABLE) { + clk_disable(curparent); + clk_disable(newparent); + } + if (clk->enable_count) clk_disable(curparent); |