[PATCH RFC 26/40] clk/clk-uclass: adapt for CCF_FULL

Casey Connolly casey.connolly at linaro.org
Thu Mar 19 21:56:48 CET 2026


When building U-Boot with CCF_FULL support, most clk operations
are implemented in clk/ccf/clk.c, so we can remove the conflicting
definitions in clk-uclass.c.

Additionally, registering clock consumers works quite differently, so we
adapt clk_get_by_name() and similar functions to call into CCF. Notably
while in Linux the struct clk handle is allocated inside CCF (since
it's an opaque cookie), in U-Boot struct clk is public and typically
allocated by the consumer driver, so we need a small adjustment to allow
CCF to populate an already-allocated struct clk.

Signed-off-by: Casey Connolly <casey.connolly at linaro.org>
---
 drivers/clk/clk-uclass.c | 297 +++++++++++++++++++++++++++--------------------
 1 file changed, 172 insertions(+), 125 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 095329e25f15..d54d76745560 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -23,8 +23,11 @@
 #include <linux/bug.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 
+#include <linux/clk/clk-conf.h>
+#include "ccf/clk.h"
+
 static inline const struct clk_ops_uboot *clk_dev_ops(struct udevice *dev)
 {
 	return (const struct clk_ops_uboot *)dev->driver->ops;
 }
@@ -74,9 +77,9 @@ static int clk_of_xlate_default(struct clk *clk,
 
 	return 0;
 }
 
-static int clk_get_by_index_tail(int ret, ofnode node,
+static int __maybe_unused clk_get_by_index_tail(int ret, ofnode node,
 				 struct ofnode_phandle_args *args,
 				 const char *list_name, int index,
 				 struct clk *clk)
 {
@@ -115,47 +118,30 @@ err:
 
 	return log_msg_ret("prop", ret);
 }
 
-static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
-				   int index, struct clk *clk)
-{
-	int ret;
-	struct ofnode_phandle_args args;
-
-	debug("%s(dev=%s, index=%d, clk=%p)\n", __func__, dev_read_name(dev),
-	      index, clk);
-
-	assert(clk);
-	clk->dev = NULL;
-
-	ret = dev_read_phandle_with_args(dev, prop_name, "#clock-cells", 0,
-					 index, &args);
-	if (ret) {
-		debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
-		      __func__, ret);
-		return log_ret(ret);
-	}
-
-	return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
-				     index, clk);
-}
-
 int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
 {
 	return clk_get_by_index_nodev(dev_ofnode(dev), index, clk);
 }
 
 int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk)
 {
+#if CONFIG_IS_ENABLED(CLK_CCF_FULL)
+	struct clk_hw *hw;
+
+	hw = of_clk_get_hw(node, index, NULL);
+	return clk_hw_create_clk_uboot(clk, hw);
+#else
 	struct ofnode_phandle_args args;
 	int ret;
 
 	ret = ofnode_parse_phandle_with_args(node, "clocks", "#clock-cells", 0,
 					     index, &args);
 
 	return clk_get_by_index_tail(ret, node, &args, "clocks",
 				     index, clk);
+#endif
 }
 
 int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
 {
@@ -189,8 +175,86 @@ bulk_get_err:
 
 	return ret;
 }
 
+int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
+{
+#if CONFIG_IS_ENABLED(CLK_CCF_FULL)
+	struct clk_hw *hw;
+
+	hw = of_clk_get_hw(dev_ofnode(dev), 0, name);
+	return clk_hw_create_clk_uboot(clk, hw);
+#else
+	return clk_get_by_name_nodev(dev_ofnode(dev), name, clk);
+#endif
+}
+#endif /* OF_REAL */
+
+int clk_get_by_name_nodev(ofnode node, const char *name, struct clk *clk)
+{
+	int index = 0;
+
+	debug("%s(node=%s, name=%s, clk=%p)\n", __func__,
+		ofnode_get_name(node), name, clk);
+	clk->dev = NULL;
+
+	if (name) {
+		index = ofnode_stringlist_search(node, "clock-names", name);
+		if (index < 0) {
+			debug("fdt_stringlist_search() failed: %d\n", index);
+			return index;
+		}
+	}
+
+	return clk_get_by_index_nodev(node, index, clk);
+}
+
+int clk_release_all(struct clk *clk, unsigned int count)
+{
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		debug("%s(clk[%u]=%p)\n", __func__, i, &clk[i]);
+
+		/* check if clock has been previously requested */
+		if (!clk[i].dev)
+			continue;
+
+		ret = clk_disable(&clk[i]);
+		if (ret && ret != -ENOSYS)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* Full CCF has its own versions of these functions */
+#if !CONFIG_IS_ENABLED(CLK_CCF_FULL)
+static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
+				   int index, struct clk *clk)
+{
+	int ret;
+	struct ofnode_phandle_args args;
+
+	debug("%s(dev=%s, index=%d, clk=%p)\n", __func__, dev_read_name(dev),
+	      index, clk);
+
+	assert(clk);
+	clk->dev = NULL;
+
+	ret = dev_read_phandle_with_args(dev, prop_name, "#clock-cells", 0,
+					 index, &args);
+	if (ret) {
+		debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+		      __func__, ret);
+		return log_ret(ret);
+	}
+
+	return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
+				     index, clk);
+}
+
 static struct clk *clk_set_default_get_by_id(struct clk *clk)
 {
 	struct clk *c = clk;
 
@@ -371,62 +435,8 @@ fail:
 	free(rates);
 	return ret;
 }
 
-int clk_set_defaults(struct udevice *dev, enum clk_defaults_stage stage)
-{
-	int ret;
-
-	if (!dev_has_ofnode(dev))
-		return 0;
-
-	/*
-	 * To avoid setting defaults twice, don't set them before relocation.
-	 * However, still set them for SPL. And still set them if explicitly
-	 * asked.
-	 */
-	if (!(IS_ENABLED(CONFIG_XPL_BUILD) || (gd->flags & GD_FLG_RELOC)))
-		if (stage != CLK_DEFAULTS_POST_FORCE)
-			return 0;
-
-	debug("%s(%s)\n", __func__, dev_read_name(dev));
-
-	ret = clk_set_default_parents(dev, stage);
-	if (ret)
-		return ret;
-
-	ret = clk_set_default_rates(dev, stage);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
-{
-	return clk_get_by_name_nodev(dev_ofnode(dev), name, clk);
-}
-#endif /* OF_REAL */
-
-int clk_get_by_name_nodev(ofnode node, const char *name, struct clk *clk)
-{
-	int index = 0;
-
-	debug("%s(node=%s, name=%s, clk=%p)\n", __func__,
-		ofnode_get_name(node), name, clk);
-	clk->dev = NULL;
-
-	if (name) {
-		index = ofnode_stringlist_search(node, "clock-names", name);
-		if (index < 0) {
-			debug("fdt_stringlist_search() failed: %d\n", index);
-			return index;
-		}
-	}
-
-	return clk_get_by_index_nodev(node, index, clk);
-}
-
 const char *
 clk_resolve_parent_clk(struct udevice *dev, const char *name)
 {
 	struct udevice *parent;
@@ -443,28 +453,8 @@ clk_resolve_parent_clk(struct udevice *dev, const char *name)
 
 	return clk.dev->name;
 }
 
-int clk_release_all(struct clk *clk, unsigned int count)
-{
-	unsigned int i;
-	int ret;
-
-	for (i = 0; i < count; i++) {
-		debug("%s(clk[%u]=%p)\n", __func__, i, &clk[i]);
-
-		/* check if clock has been previously requested */
-		if (!clk[i].dev)
-			continue;
-
-		ret = clk_disable(&clk[i]);
-		if (ret && ret != -ENOSYS)
-			return ret;
-	}
-
-	return 0;
-}
-
 int clk_request(struct udevice *dev, struct clk *clk)
 {
 	const struct clk_ops_uboot *ops;
 
@@ -704,21 +694,8 @@ int clk_enable(struct clk *clk)
 
 	return 0;
 }
 
-int clk_enable_bulk(struct clk_bulk *bulk)
-{
-	int i, ret;
-
-	for (i = 0; i < bulk->count; i++) {
-		ret = clk_enable(&bulk->clks[i]);
-		if (ret < 0 && ret != -ENOSYS)
-			return ret;
-	}
-
-	return 0;
-}
-
 int clk_disable(struct clk *clk)
 {
 	const struct clk_ops_uboot *ops;
 	struct clk *clkp = NULL;
@@ -769,21 +746,8 @@ int clk_disable(struct clk *clk)
 
 	return 0;
 }
 
-int clk_disable_bulk(struct clk_bulk *bulk)
-{
-	int i, ret;
-
-	for (i = 0; i < bulk->count; i++) {
-		ret = clk_disable(&bulk->clks[i]);
-		if (ret < 0 && ret != -ENOSYS)
-			return ret;
-	}
-
-	return 0;
-}
-
 int clk_get_by_id(ulong id, struct clk **clkp)
 {
 	struct udevice *dev;
 	struct uclass *uc;
@@ -820,8 +784,65 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
 		return true;
 
 	return false;
 }
+#else
+long clk_get_parent_rate(struct clk *clk)
+{
+	struct clk *pclk;
+
+	if (!clk)
+		return -EINVAL;
+
+	pclk = clk_get_parent(clk);
+	return clk_get_rate(pclk);
+}
+
+static int clk_set_default_parents(struct udevice *dev,
+				   enum clk_defaults_stage stage)
+{
+	return -ENOSYS;
+}
+
+static int clk_set_default_rates(struct udevice *dev,
+				 enum clk_defaults_stage stage)
+{
+	return -ENOSYS;
+}
+#endif
+
+int clk_set_defaults(struct udevice *dev, enum clk_defaults_stage stage)
+{
+	int ret;
+
+	if (!dev_has_ofnode(dev))
+		return 0;
+
+	/*
+	 * To avoid setting defaults twice, don't set them before relocation.
+	 * However, still set them for SPL. And still set them if explicitly
+	 * asked.
+	 */
+	if (!(IS_ENABLED(CONFIG_XPL_BUILD) || (gd->flags & GD_FLG_RELOC)))
+		if (stage != CLK_DEFAULTS_POST_FORCE)
+			return 0;
+
+	debug("%s(%s)\n", __func__, dev_read_name(dev));
+
+	if (CONFIG_IS_ENABLED(CLK_CCF_FULL)) {
+		return of_clk_set_defaults(dev_ofnode(dev), false);
+	} else {
+		ret = clk_set_default_parents(dev, stage);
+		if (ret)
+			return ret;
+
+		ret = clk_set_default_rates(dev, stage);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
 
 struct clk *devm_clk_get(struct udevice *dev, const char *id)
 {
 	int rc;
@@ -837,8 +858,34 @@ struct clk *devm_clk_get(struct udevice *dev, const char *id)
 
 	return clk;
 }
 
+int clk_enable_bulk(struct clk_bulk *bulk)
+{
+	int i, ret;
+
+	for (i = 0; i < bulk->count; i++) {
+		ret = clk_enable(&bulk->clks[i]);
+		if (ret < 0 && ret != -ENOSYS)
+			return ret;
+	}
+
+	return 0;
+}
+
+int clk_disable_bulk(struct clk_bulk *bulk)
+{
+	int i, ret;
+
+	for (i = 0; i < bulk->count; i++) {
+		ret = clk_disable(&bulk->clks[i]);
+		if (ret < 0 && ret != -ENOSYS)
+			return ret;
+	}
+
+	return 0;
+}
+
 int clk_uclass_post_probe(struct udevice *dev)
 {
 	/*
 	 * when a clock provider is probed. Call clk_set_defaults()

-- 
2.51.0



More information about the U-Boot mailing list