[U-Boot] [PATCH 2/3] clk: prograte clk enable/disable to parent

Peng Fan peng.fan at nxp.com
Fri Aug 16 08:10:12 UTC 2019


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.fan at 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



More information about the U-Boot mailing list