devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Chao Xie <chao.xie@marvell.com>
To: haojian.zhuang@gmail.com, mturquette@linaro.org,
	chao.xie@marvell.com, xiechao_mail@163.com,
	linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 07/12] clk: mmp: add clock type composite for mix
Date: Tue, 10 Jun 2014 09:27:43 +0800	[thread overview]
Message-ID: <1402363668-25806-8-git-send-email-chao.xie@marvell.com> (raw)
In-Reply-To: <1402363668-25806-1-git-send-email-chao.xie@marvell.com>

From: Chao Xie <chao.xie@marvell.com>

The general composite clock supports div/mux/gate.
marvell SOCes have many clocks that need change
div and mux together. So it need the composite
clock that supports mix/gate.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 drivers/clk/mmp/Makefile            |   3 +-
 drivers/clk/mmp/clk-mix-composite.c | 195 ++++++++++++++++++++++++++++++++++++
 drivers/clk/mmp/clk.h               |  20 ++++
 3 files changed, 217 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-mix-composite.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 2855f7b..2cd7d94 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,8 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o	\
+	 clk-mix-composite.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-mix-composite.c b/drivers/clk/mmp/clk-mix-composite.c
new file mode 100644
index 0000000..79d5286
--- /dev/null
+++ b/drivers/clk/mmp/clk-mix-composite.c
@@ -0,0 +1,195 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie <chao.xie@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+#define to_clk_composite(_hw) container_of(_hw, struct mmp_clk_composite, hw)
+
+static u8 mmp_clk_composite_get_parent(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->get_parent(mix_hw);
+}
+
+static int mmp_clk_composite_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->set_parent(mix_hw, index);
+}
+
+static int mmp_clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->set_rate(mix_hw, rate, parent_rate);
+}
+
+static unsigned long mmp_clk_composite_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->recalc_rate(mix_hw, parent_rate);
+}
+
+static long mmp_clk_composite_determine_rate(struct clk_hw *hw,
+					unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_p)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->determine_rate(mix_hw, rate, best_parent_rate,
+					best_parent_p);
+}
+
+static int mmp_clk_composite_set_rate_and_parent(struct clk_hw *hw,
+					unsigned long rate,
+					unsigned long parent_rate, u8 index)
+
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+
+	return mix_ops->set_rate_and_parent(mix_hw, rate, parent_rate, index);
+}
+
+static int mmp_clk_composite_is_enabled(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+
+	gate_hw->clk = hw->clk;
+
+	return gate_ops->is_enabled(gate_hw);
+}
+
+static int mmp_clk_composite_enable(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+
+	gate_hw->clk = hw->clk;
+
+	return gate_ops->enable(gate_hw);
+}
+
+static void mmp_clk_composite_disable(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+
+	gate_hw->clk = hw->clk;
+
+	gate_ops->disable(gate_hw);
+}
+
+static void mmp_clk_composite_init(struct clk_hw *hw)
+{
+	struct mmp_clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *gate_ops = composite->gate_ops;
+	struct clk_hw *gate_hw = composite->gate_hw;
+	const struct clk_ops *mix_ops = composite->mix_ops;
+	struct clk_hw *mix_hw = composite->mix_hw;
+
+	mix_hw->clk = hw->clk;
+	gate_hw->clk = hw->clk;
+
+	if (mix_ops->init)
+		mix_ops->init(mix_hw);
+	if (gate_ops->init)
+		gate_ops->init(gate_hw);
+}
+
+static struct clk_ops mmp_clk_composite_ops = {
+	.enable = mmp_clk_composite_enable,
+	.disable = mmp_clk_composite_disable,
+	.is_enabled = mmp_clk_composite_is_enabled,
+	.determine_rate = mmp_clk_composite_determine_rate,
+	.set_rate_and_parent = mmp_clk_composite_set_rate_and_parent,
+	.set_rate = mmp_clk_composite_set_rate,
+	.recalc_rate = mmp_clk_composite_recalc_rate,
+	.get_parent = mmp_clk_composite_get_parent,
+	.set_parent = mmp_clk_composite_set_parent,
+	.init = mmp_clk_composite_init,
+};
+
+struct clk *mmp_clk_register_composite(struct device *dev, const char *name,
+			const char **parent_names, int num_parents,
+			struct clk_hw *mix_hw, const struct clk_ops *mix_ops,
+			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+			unsigned long flags)
+{
+	struct clk *clk;
+	struct clk_init_data init;
+	struct mmp_clk_composite *composite;
+
+	if (!mix_hw || !gate_hw)
+		return ERR_PTR(-EINVAL);
+
+	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
+	if (!composite) {
+		pr_err("%s: could not allocate mmp composite clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.flags = flags;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+	init.ops = &mmp_clk_composite_ops;
+
+	composite->mix_hw = mix_hw;
+	composite->mix_ops = mix_ops;
+	composite->gate_hw = gate_hw;
+	composite->gate_ops = gate_ops;
+	composite->hw.init = &init;
+
+	clk = clk_register(dev, &composite->hw);
+	if (IS_ERR(clk))
+		kfree(composite);
+
+	return clk;
+}
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 9096f0a..9827a4f 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -120,6 +120,26 @@ extern struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
 			spinlock_t *lock);
 
 
+/* Clock type "composite" for mix clock */
+struct mmp_clk_composite {
+	struct clk_hw hw;
+	struct clk_ops ops;
+
+	struct clk_hw *mix_hw;
+	struct clk_hw *gate_hw;
+
+	const struct clk_ops *mix_ops;
+	const struct clk_ops *gate_ops;
+};
+
+extern struct clk *mmp_clk_register_composite(struct device *dev,
+			const char *name,
+			const char **parent_names, int num_parents,
+			struct clk_hw *mix_hw, const struct clk_ops *mix_ops,
+			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+			unsigned long flags);
+
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
 		const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
-- 
1.8.3.2

  parent reply	other threads:[~2014-06-10  1:27 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-10  1:27 [PATCH 00/12] clk: mmp: clock device tree support Chao Xie
2014-06-10  1:27 ` [PATCH 01/12] clk: mmp: add prefix "mmp" for structures defined for clk-frac Chao Xie
2014-06-10  1:27 ` [PATCH 02/12] clk: mmp: add spin lock " Chao Xie
     [not found] ` <1402363668-25806-1-git-send-email-chao.xie-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
2014-06-10  1:27   ` [PATCH 03/12] clk: mmp: add init callback " Chao Xie
2014-06-10  1:27 ` [PATCH 04/12] clk: mmp: move definiton of mmp_clk_frac to clk.h Chao Xie
2014-06-10  1:27 ` [PATCH 05/12] clk: mmp: add clock type mix Chao Xie
2014-06-10  1:27 ` [PATCH 06/12] clk: mmp: add mmp private gate clock Chao Xie
2014-06-10  1:27 ` Chao Xie [this message]
2014-06-10  1:27 ` [PATCH 08/12] clk: mmp: add clock type master Chao Xie
2014-06-10  1:27 ` [PATCH 09/12] clk: mmp: add spin lock automatic detection from device tree Chao Xie
2014-06-10  1:27 ` [PATCH 10/12] clk: mmp: add device tree support for composite type clock Chao Xie
2014-06-10  1:27 ` [PATCH 11/12] clk: mmp: add device tree support for clocks Chao Xie
2014-06-10  1:27 ` [PATCH 12/12] arm: mmp: support clock device tree for mmp platforms Chao Xie

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=1402363668-25806-8-git-send-email-chao.xie@marvell.com \
    --to=chao.xie@marvell.com \
    --cc=devicetree@vger.kernel.org \
    --cc=haojian.zhuang@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@linaro.org \
    --cc=xiechao_mail@163.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).