[Uboot-stm32] [PATCH 13/36] clk: split clk-uclass.c into clk-common.c

Casey Connolly casey.connolly at linaro.org
Mon Jul 20 16:40:40 UTC 2026


clk-uclass.c contains all of the UCLASS_CLK specific code but it also
contains common clk functionality which is generic between UCLASS_CLK
and CCF.

Split this functionality out so that we can reuse it with CCF and avoid
building clk-uclass.c entirely.

Signed-off-by: Casey Connolly <casey.connolly at linaro.org>
---
 drivers/clk/Makefile         |   8 +-
 drivers/clk/clk-common.c     | 220 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clk-common.h     |  45 +++++++++
 drivers/clk/clk-uclass.c     | 175 ++--------------------------------
 include/linux/clk-provider.h |   3 +
 5 files changed, 278 insertions(+), 173 deletions(-)

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index dd71d005aada..ee06bffaef72 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -4,19 +4,19 @@
 # Wolfgang Denk, DENX Software Engineering, wd at denx.de.
 #
 
 obj-$(CONFIG_$(PHASE_)CLK) += clk-uclass.o
+obj-$(CONFIG_$(PHASE_)CLK) += clk-common.o
 obj-$(CONFIG_$(PHASE_)CLK_GPIO) += clk-gpio.o
 obj-$(CONFIG_$(PHASE_)CLK_STUB) += clk-stub.o
 
 # Full Linux CCF support
-obj-$(CONFIG_$(PHASE_)CLK_CCF_FULL) += ccf/
-
+ifdef CONFIG_CLK_CCF_FULL
+obj-y += ccf/
+else
 # U-Boot basic fixed clocks, full CCF has a
 # different and incompatible implementation
-ifndef CONFIG_CLK_CCF_FULL
 obj-y += basic/
-
 # U-Boot/IMX "micro" CCF port
 obj-$(CONFIG_$(PHASE_)CLK_CCF) += uccf/
 endif
 
diff --git a/drivers/clk/clk-common.c b/drivers/clk/clk-common.c
new file mode 100644
index 000000000000..7f30ad496da2
--- /dev/null
+++ b/drivers/clk/clk-common.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg at chromium.org>
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ * Copyright (c) 2018, Theobroma Systems Design und Consulting GmbH
+ *
+ * Common clock support code shared between CCF_FULL and UCLASS_CLK
+ */
+
+#include <clk.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <dm/device_compat.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/read.h>
+#include <linux/bug.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+
+#include "clk-common.h"
+
+#if CONFIG_IS_ENABLED(OF_REAL)
+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)
+{
+	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);
+}
+
+int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
+{
+	int i, ret, err, count;
+
+	bulk->count = 0;
+
+	count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", 0);
+	if (count < 1)
+		return count;
+
+	bulk->clks = devm_kcalloc(dev, count, sizeof(struct clk), GFP_KERNEL);
+	if (!bulk->clks)
+		return -ENOMEM;
+
+	for (i = 0; i < count; i++) {
+		ret = clk_get_by_index(dev, i, &bulk->clks[i]);
+		if (ret < 0)
+			goto bulk_get_err;
+
+		++bulk->count;
+	}
+
+	return 0;
+
+bulk_get_err:
+	err = clk_release_all(bulk->clks, bulk->count);
+	if (err)
+		debug("%s: could not release all clocks for %s\n",
+		      __func__, dev_read_name(dev));
+
+	return ret;
+}
+
+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);
+}
+
+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_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;
+}
+
+struct clk *devm_clk_get(struct udevice *dev, const char *id)
+{
+	int rc;
+	struct clk *clk;
+
+	clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
+	if (unlikely(!clk))
+		return ERR_PTR(-ENOMEM);
+
+	rc = clk_get_by_name(dev, id, clk);
+	if (rc)
+		return ERR_PTR(rc);
+
+	return clk;
+}
+
+int clk_prepare_bulk(struct clk_bulk *bulk)
+{
+	int i, ret;
+
+	for (i = 0; i < bulk->count; i++) {
+		ret = clk_prepare(&bulk->clks[i]);
+		if (ret < 0 && ret != -ENOSYS)
+			return ret;
+	}
+
+	return 0;
+}
+
+int clk_unprepare_bulk(struct clk_bulk *bulk)
+{
+	int i, ret;
+
+	for (i = 0; i < bulk->count; i++) {
+		ret = clk_prepare(&bulk->clks[i]);
+		if (ret < 0 && ret != -ENOSYS)
+			return ret;
+	}
+
+	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_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;
+}
diff --git a/drivers/clk/clk-common.h b/drivers/clk/clk-common.h
new file mode 100644
index 000000000000..fbb1bd5b3ba0
--- /dev/null
+++ b/drivers/clk/clk-common.h
@@ -0,0 +1,45 @@
+
+#include <dm/ofnode.h>
+#include <clk.h>
+
+#ifndef __CLK_COMMON_H__
+#define __CLK_COMMON_H__
+
+/* These functions are unused with CCF_FULL */
+
+#if !CONFIG_IS_ENABLED(CLK_CCF_FULL)
+int clk_get_by_index_tail(int ret, ofnode node,
+				 struct ofnode_phandle_args *args,
+				 const char *list_name, int index,
+				 struct clk *clk);
+
+int clk_set_default_parents(struct udevice *dev,
+				   enum clk_defaults_stage stage);
+
+
+int clk_set_default_rates(struct udevice *dev,
+				 enum clk_defaults_stage stage);
+#else
+int clk_get_by_index_tail(int ret, ofnode node,
+				 struct ofnode_phandle_args *args,
+				 const char *list_name, int index,
+				 struct clk *clk)
+{
+	return -ENOSYS;
+}
+
+int clk_set_default_parents(struct udevice *dev,
+				   enum clk_defaults_stage stage)
+{
+	return -ENOSYS;
+}
+
+int clk_set_default_rates(struct udevice *dev,
+				 enum clk_defaults_stage stage)
+{
+	return -ENOSYS;
+}
+
+#endif /* CONFIG_CLK_CCF_FULL */
+
+#endif /* __CLK_COMMON_H__ */
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index e960d2ad2383..e6036d880cb7 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -23,8 +23,10 @@
 #include <linux/bug.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 
+#include "clk-common.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 +76,9 @@ static int clk_of_xlate_default(struct clk *clk,
 
 	return 0;
 }
 
-static int clk_get_by_index_tail(int ret, ofnode node,
+int clk_get_by_index_tail(int ret, ofnode node,
 				 struct ofnode_phandle_args *args,
 				 const char *list_name, int index,
 				 struct clk *clk)
 {
@@ -114,8 +116,9 @@ err:
 	      __func__, ofnode_get_name(node), list_name, index, ret);
 
 	return log_msg_ret("prop", ret);
 }
+#endif /* OF_REAL */
 
 static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
 				   int index, struct clk *clk)
 {
@@ -139,58 +142,8 @@ static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
 	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)
-{
-	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);
-}
-
-int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
-{
-	int i, ret, err, count;
-
-	bulk->count = 0;
-
-	count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", 0);
-	if (count < 1)
-		return count;
-
-	bulk->clks = devm_kcalloc(dev, count, sizeof(struct clk), GFP_KERNEL);
-	if (!bulk->clks)
-		return -ENOMEM;
-
-	for (i = 0; i < count; i++) {
-		ret = clk_get_by_index(dev, i, &bulk->clks[i]);
-		if (ret < 0)
-			goto bulk_get_err;
-
-		++bulk->count;
-	}
-
-	return 0;
-
-bulk_get_err:
-	err = clk_release_all(bulk->clks, bulk->count);
-	if (err)
-		debug("%s: could not release all clocks for %s\n",
-		      __func__, dev_read_name(dev));
-
-	return ret;
-}
-
 static struct clk *clk_set_default_get_by_id(struct clk *clk)
 {
 	struct clk *c = clk;
 
@@ -206,9 +159,9 @@ static struct clk *clk_set_default_get_by_id(struct clk *clk)
 
 	return c;
 }
 
-static int clk_set_default_parents(struct udevice *dev,
+int clk_set_default_parents(struct udevice *dev,
 				   enum clk_defaults_stage stage)
 {
 	struct clk clk, parent_clk, *c, *p;
 	int index;
@@ -289,9 +242,9 @@ static int clk_set_default_parents(struct udevice *dev,
 
 	return 0;
 }
 
-static int clk_set_default_rates(struct udevice *dev,
+int clk_set_default_rates(struct udevice *dev,
 				 enum clk_defaults_stage stage)
 {
 	struct clk clk, *c;
 	int index;
@@ -371,62 +324,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 +342,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 +583,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 +635,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;
@@ -821,24 +674,8 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
 
 	return false;
 }
 
-struct clk *devm_clk_get(struct udevice *dev, const char *id)
-{
-	int rc;
-	struct clk *clk;
-
-	clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
-	if (unlikely(!clk))
-		return ERR_PTR(-ENOMEM);
-
-	rc = clk_get_by_name(dev, id, clk);
-	if (rc)
-		return ERR_PTR(rc);
-
-	return clk;
-}
-
 int clk_prepare(struct clk *clk)
 {
 	return 0;
 }
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 4fcdb5a86799..17d6190134dd 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -39,8 +39,11 @@
  */
 #if CONFIG_IS_ENABLED(CLK_CCF_FULL)
 #include "clk-provider-ccf_full.h"
 #else
+/* Forward-declare clk_hw so we can compile code that references it even though it's unused*/
+struct clk_hw;
+
 #include "clk-provider-uccf.h"
 #endif
 
 #endif /* __LINUX_CLK_PROVIDER_H */

-- 
2.55.0



More information about the Uboot-stm32 mailing list