All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peng Fan <peng.fan@nxp.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH V3 12/16] clk: add composite clk support
Date: Wed, 31 Jul 2019 07:01:54 +0000	[thread overview]
Message-ID: <20190731071654.9970-12-peng.fan@nxp.com> (raw)
In-Reply-To: <20190731071654.9970-1-peng.fan@nxp.com>

Import clk composite clk support from Linux Kernel 5.1-rc5

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

V3:
 None
V2:
 Rebase

 drivers/clk/Kconfig          |  14 ++++
 drivers/clk/Makefile         |   1 +
 drivers/clk/clk-composite.c  | 160 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |  22 ++++++
 4 files changed, 197 insertions(+)
 create mode 100644 drivers/clk/clk-composite.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 5e92446c18..a3f0171b45 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -53,6 +53,13 @@ config SPL_CLK_CCF
 	  Enable this option if you want to (re-)use the Linux kernel's Common
 	  Clock Framework [CCF] code in U-Boot's SPL.
 
+config SPL_CLK_COMPOSITE_CCF
+	bool "SPL Common Clock Framework [CCF] composite clk support "
+	depends on SPL_CLK_CCF
+	help
+	  Enable this option if you want to (re-)use the Linux kernel's Common
+	  Clock Framework [CCF] composite code in U-Boot's SPL.
+
 config CLK_CCF
 	bool "Common Clock Framework [CCF] support "
 	depends on CLK_IMX6Q || SANDBOX_CLK_CCF
@@ -60,6 +67,13 @@ config CLK_CCF
 	  Enable this option if you want to (re-)use the Linux kernel's Common
 	  Clock Framework [CCF] code in U-Boot's clock driver.
 
+config CLK_COMPOSITE_CCF
+	bool "Common Clock Framework [CCF] composite clk support "
+	depends on CLK_CCF
+	help
+	  Enable this option if you want to (re-)use the Linux kernel's Common
+	  Clock Framework [CCF] composite code in U-Boot's clock driver.
+
 config CLK_STM32F
 	bool "Enable clock driver support for STM32F family"
 	depends on CLK && (STM32F7 || STM32F4)
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 39154eca59..68aabe1ca9 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_rate.o
 obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_factor.o
 obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o
 obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk-fixed-factor.o
+obj-$(CONFIG_$(SPL_TPL_)CLK_COMPOSITE_CCF) += clk-composite.o
 
 obj-y += analogbits/
 obj-y += imx/
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
new file mode 100644
index 0000000000..a5626c33d1
--- /dev/null
+++ b/drivers/clk/clk-composite.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2013 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/clk-provider.h>
+#include <clk.h>
+
+#include "clk.h"
+
+#define UBOOT_DM_CLK_COMPOSITE "clk_composite"
+
+static u8 clk_composite_get_parent(struct clk *clk)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	struct clk *mux = composite->mux;
+
+	return clk_mux_get_parent(mux);
+}
+
+static int clk_composite_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *mux_ops = composite->mux_ops;
+	struct clk *mux = composite->mux;
+
+	return mux_ops->set_parent(mux, parent);
+}
+
+static unsigned long clk_composite_recalc_rate(struct clk *clk)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *rate_ops = composite->rate_ops;
+	struct clk *rate = composite->rate;
+
+	return rate_ops->get_rate(rate);
+}
+
+static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *rate_ops = composite->rate_ops;
+	struct clk *clk_rate = composite->rate;
+
+	return rate_ops->set_rate(clk_rate, rate);
+}
+
+static int clk_composite_enable(struct clk *clk)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk *gate = composite->gate;
+
+	return gate_ops->enable(gate);
+}
+
+static int clk_composite_disable(struct clk *clk)
+{
+	struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
+		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk *gate = composite->gate;
+
+	gate_ops->disable(gate);
+
+	return 0;
+}
+
+struct clk_ops clk_composite_ops = {
+	/* This will be set according to clk_register_composite */
+};
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+				   const char * const *parent_names,
+				   int num_parents, struct clk *mux,
+				   const struct clk_ops *mux_ops,
+				   struct clk *rate,
+				   const struct clk_ops *rate_ops,
+				   struct clk *gate,
+				   const struct clk_ops *gate_ops,
+				   unsigned long flags)
+{
+	struct clk *clk;
+	struct clk_composite *composite;
+	int ret;
+	struct clk_ops *composite_ops = &clk_composite_ops;
+
+	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
+	if (!composite)
+		return ERR_PTR(-ENOMEM);
+
+	if (mux && mux_ops) {
+		composite->mux = mux;
+		composite->mux_ops = mux_ops;
+		if (mux_ops->set_parent)
+			composite_ops->set_parent = clk_composite_set_parent;
+		mux->data = (ulong)composite;
+	}
+
+	if (rate && rate_ops) {
+		if (!rate_ops->get_rate) {
+			clk = ERR_PTR(-EINVAL);
+			goto err;
+		}
+		composite_ops->get_rate = clk_composite_recalc_rate;
+
+		/* .set_rate requires either .round_rate or .determine_rate */
+		if (rate_ops->set_rate)
+			composite_ops->set_rate = clk_composite_set_rate;
+
+		composite->rate = rate;
+		composite->rate_ops = rate_ops;
+		rate->data = (ulong)composite;
+	}
+
+	if (gate && gate_ops) {
+		if (!gate_ops->enable || !gate_ops->disable) {
+			clk = ERR_PTR(-EINVAL);
+			goto err;
+		}
+
+		composite->gate = gate;
+		composite->gate_ops = gate_ops;
+		composite_ops->enable = clk_composite_enable;
+		composite_ops->disable = clk_composite_disable;
+		gate->data = (ulong)composite;
+	}
+
+	clk = &composite->clk;
+	ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name,
+			   parent_names[clk_composite_get_parent(clk)]);
+	if (ret) {
+		clk = ERR_PTR(ret);
+		goto err;
+	}
+
+	return clk;
+
+err:
+	kfree(composite);
+	return clk;
+}
+
+U_BOOT_DRIVER(clk_composite) = {
+	.name	= UBOOT_DM_CLK_COMPOSITE,
+	.id	= UCLASS_CLK,
+	.ops	= &clk_composite_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 522e73e851..b9547736ee 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -137,6 +137,28 @@ struct clk_fixed_rate {
 
 #define to_clk_fixed_rate(dev)	((struct clk_fixed_rate *)dev_get_platdata(dev))
 
+struct clk_composite {
+	struct clk	clk;
+	struct clk_ops	ops;
+
+	struct clk	*mux;
+	struct clk	*rate;
+	struct clk	*gate;
+
+	const struct clk_ops	*mux_ops;
+	const struct clk_ops	*rate_ops;
+	const struct clk_ops	*gate_ops;
+};
+
+#define to_clk_composite(_clk) container_of(_clk, struct clk_composite, clk)
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+		const char * const *parent_names, int num_parents,
+		struct clk *mux_clk, const struct clk_ops *mux_ops,
+		struct clk *rate_clk, const struct clk_ops *rate_ops,
+		struct clk *gate_clk, const struct clk_ops *gate_ops,
+		unsigned long flags);
+
 int clk_register(struct clk *clk, const char *drv_name, const char *name,
 		 const char *parent_name);
 
-- 
2.16.4

  parent reply	other threads:[~2019-07-31  7:01 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-31  7:01 [U-Boot] [PATCH V3 01/16] clk: introduce clk_dev_binded Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 02/16] clk: use clk_dev_binded Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 03/16] clk: mux: add set parent support Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 04/16] clk: export mux/divider ops Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 05/16] clk: add clk-gate support Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 06/16] clk: divider set rate supporrt Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 07/16] clk: fixed_rate: export clk_fixed_rate Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 08/16] clk: imx: import clk heplers Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 09/16] clk: imx: gate2 add set rate Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 10/16] dm: clk: ignore default settings when node not valid Peng Fan
2019-07-31  7:01 ` [U-Boot] [PATCH V3 11/16] clk-provider: include clk-uclass.h Peng Fan
2019-07-31  7:01 ` Peng Fan [this message]
2019-07-31  7:01 ` [U-Boot] [PATCH V3 13/16] clk: gate: support sandbox Peng Fan
2019-07-31  7:02 ` [U-Boot] [PATCH V3 14/16] configs: sandbox: Enable composite clk Peng Fan
2019-07-31  7:02 ` [U-Boot] [PATCH V3 15/16] clk: sandbox: add " Peng Fan
2019-07-31  7:02 ` [U-Boot] [PATCH V3 16/16] test: dm: clk_ccf: test " Peng Fan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190731071654.9970-12-peng.fan@nxp.com \
    --to=peng.fan@nxp.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.