diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2017-02-13 09:26:04 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2017-02-13 09:26:04 +0100 |
commit | 30139163b75970fcd58df6b6b987883e36571046 (patch) | |
tree | 00bd354cefa617f8474cc73994b1a72c11e770a0 /drivers/clk/clk.c | |
parent | bb1a6a2fd3cc41be6db1a1362f311456019317b1 (diff) | |
parent | 19df384cec181be4407f82377ffbb3059b1ed748 (diff) | |
download | barebox-30139163b75970fcd58df6b6b987883e36571046.tar.gz barebox-30139163b75970fcd58df6b6b987883e36571046.tar.xz |
Merge branch 'for-next/imx'
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r-- | drivers/clk/clk.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 1566beabda..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) @@ -173,14 +186,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 +206,32 @@ 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); + + 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); + + return ret; } struct clk *clk_get_parent(struct clk *clk) |