When enabling/disabling a clk, also need to enable/disable the clk's parent. Implement this in clk_enable/disable.
Signed-off-by: Peng Fan <peng....@nxp.com> --- drivers/clk/clk-uclass.c | 68 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index cee4d912b0..208c9b7906 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -449,13 +449,41 @@ int clk_set_parent(struct clk *clk, struct clk *parent) int clk_enable(struct clk *clk) { const struct clk_ops *ops = clk_dev_ops(clk->dev); + struct clk *clkp = NULL; + int ret; debug("%s(clk=%p)\n", __func__, clk); - if (!ops->enable) - return -ENOSYS; + if (CONFIG_IS_ENABLED(CLK_CCF)) { + /* Take id 0 as a non-valid clk, such as dummy */ + if (clk->id && !clk_get_by_id(clk->id, &clkp)) { + if (clkp->dev->parent && + device_get_uclass_id(clkp->dev) == UCLASS_CLK) { + ret = clk_enable(dev_get_clk_ptr(clkp->dev->parent)); + if (ret) { + printf("Enable %s failed\n", + clkp->dev->parent->name); + return ret; + } + } + } - return ops->enable(clk); + if (ops->enable) { + ret = ops->enable(clk); + if (ret) { + printf("Enable %s failed\n", clk->dev->name); + return ret; + } + } + if (clkp) + clkp->enable_cnt++; + } else { + if (!ops->enable) + return -ENOSYS; + return ops->enable(clk); + } + + return 0; } int clk_enable_bulk(struct clk_bulk *bulk) @@ -474,13 +502,41 @@ int clk_enable_bulk(struct clk_bulk *bulk) int clk_disable(struct clk *clk) { const struct clk_ops *ops = clk_dev_ops(clk->dev); + struct clk *clkp; + int ret; debug("%s(clk=%p)\n", __func__, clk); - if (!ops->disable) - return -ENOSYS; + if (CONFIG_IS_ENABLED(CLK_CCF)) { + if (ops->disable) { + ret = ops->disable(clk); + if (ret) + return ret; + } + + if (clk->id && !clk_get_by_id(clk->id, &clkp)) { + if (clkp->dev->parent && + device_get_uclass_id(clkp->dev) == UCLASS_CLK) { + ret = clk_disable(dev_get_clk_ptr(clkp->dev->parent)); + if (ret) { + printf("Disable %s failed\n", + clkp->dev->parent->name); + return ret; + } + } + } + + if (clkp) + clkp->enable_cnt--; + } else { - return ops->disable(clk); + if (!ops->disable) + return -ENOSYS; + + return ops->disable(clk); + } + + return 0; } int clk_disable_bulk(struct clk_bulk *bulk) -- 2.16.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot