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

Reply via email to