[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