linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Chen-Yu Tsai <wens@csie.org>
To: Maxime Ripard <maxime.ripard@free-electrons.com>,
	Ulf Hansson <ulf.hansson@linaro.org>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@codeaurora.org>,
	Rob Herring <robh+dt@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>
Cc: Chen-Yu Tsai <wens@csie.org>,
	linux-arm-kernel@lists.infradead.org, linux-mmc@vger.kernel.org,
	linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-sunxi@googlegroups.com
Subject: [PATCH v2 02/10] clk: sunxi-ng: Add MP_MMC clocks that support MMC timing modes switching
Date: Thu, 20 Jul 2017 11:44:44 +0800	[thread overview]
Message-ID: <20170720034452.15920-3-wens@csie.org> (raw)
In-Reply-To: <20170720034452.15920-1-wens@csie.org>

All of our MMC clocks are of the MP clock type. A few MMC clocks on some
SoCs, such as MMC2 on the A83T, support new/old timing mode switching.

>From a clock rate point of view, when the new timing mode is active. the
output clock rate is halved.

This patch adds a special wrapper class of clocks, MP_MMC, around the
generic MP type clocks. The rate related callbacks in ccu_mp_mmc_ops
for this class look at the timing mode bit and apply the /2 post-divider
when needed, before passing it through to the generic class ops,
ccu_mp_ops.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 drivers/clk/sunxi-ng/ccu_mp.c | 80 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_mp.h | 24 +++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index b917ad7a386c..688855e7dc8c 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -172,3 +172,83 @@ const struct clk_ops ccu_mp_ops = {
 	.recalc_rate	= ccu_mp_recalc_rate,
 	.set_rate	= ccu_mp_set_rate,
 };
+
+/*
+ * Support for MMC timing mode switching
+ *
+ * The MMC clocks on some SoCs support switching between old and
+ * new timing modes. A platform specific API is provided to query
+ * and set the timing mode on supported SoCs.
+ *
+ * In addition, a special class of ccu_mp_ops is provided, which
+ * takes in to account the timing mode switch. When the new timing
+ * mode is active, the clock output rate is halved. This new class
+ * is a wrapper around the generic ccu_mp_ops. When clock rates
+ * are passed through to ccu_mp_ops callbacks, they are doubled
+ * if the new timing mode bit is set, to account for the post
+ * divider. Conversely, when clock rates are passed back, they
+ * are halved if the mode bit is set.
+ */
+
+static unsigned long ccu_mp_mmc_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	unsigned long rate = ccu_mp_recalc_rate(hw, parent_rate);
+	struct ccu_common *cm = hw_to_ccu_common(hw);
+	u32 val = readl(cm->base + cm->reg);
+
+	if (val & CCU_MMC_NEW_TIMING_MODE)
+		return rate / 2;
+	return rate;
+}
+
+static int ccu_mp_mmc_determine_rate(struct clk_hw *hw,
+				     struct clk_rate_request *req)
+{
+	struct ccu_common *cm = hw_to_ccu_common(hw);
+	u32 val = readl(cm->base + cm->reg);
+	int ret;
+
+	/* adjust the requested clock rate */
+	if (val & CCU_MMC_NEW_TIMING_MODE) {
+		req->rate *= 2;
+		req->min_rate *= 2;
+		req->max_rate *= 2;
+	}
+
+	ret = ccu_mp_determine_rate(hw, req);
+
+	/* re-adjust the requested clock rate back */
+	if (val & CCU_MMC_NEW_TIMING_MODE) {
+		req->rate /= 2;
+		req->min_rate /= 2;
+		req->max_rate /= 2;
+	}
+
+	return ret;
+}
+
+static int ccu_mp_mmc_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct ccu_common *cm = hw_to_ccu_common(hw);
+	u32 val = readl(cm->base + cm->reg);
+
+	if (val & CCU_MMC_NEW_TIMING_MODE)
+		rate *= 2;
+
+	return ccu_mp_set_rate(hw, rate, parent_rate);
+}
+
+const struct clk_ops ccu_mp_mmc_ops = {
+	.disable	= ccu_mp_disable,
+	.enable		= ccu_mp_enable,
+	.is_enabled	= ccu_mp_is_enabled,
+
+	.get_parent	= ccu_mp_get_parent,
+	.set_parent	= ccu_mp_set_parent,
+
+	.determine_rate	= ccu_mp_mmc_determine_rate,
+	.recalc_rate	= ccu_mp_mmc_recalc_rate,
+	.set_rate	= ccu_mp_mmc_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
index 915625e97d98..e5e90cec648e 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.h
+++ b/drivers/clk/sunxi-ng/ccu_mp.h
@@ -74,4 +74,28 @@ static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
 
 extern const struct clk_ops ccu_mp_ops;
 
+/* Special class of M-P clock that supports MMC timing modes */
+
+#define SUNXI_CCU_MP_MMC_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
+				       _mshift, _mwidth,		\
+				       _pshift, _pwidth,		\
+				       _muxshift, _muxwidth,		\
+				       _gate, _flags)			\
+	struct ccu_mp _struct = {					\
+		.enable	= _gate,					\
+		.m	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
+		.p	= _SUNXI_CCU_DIV(_pshift, _pwidth),		\
+		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
+		.common	= {						\
+			.reg		= _reg,				\
+			.features	= CCU_FEATURE_MMC_TIMING_SWITCH, \
+			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
+							      _parents, \
+							      &ccu_mp_mmc_ops, \
+							      _flags),	\
+		}							\
+	}
+
+extern const struct clk_ops ccu_mp_mmc_ops;
+
 #endif /* _CCU_MP_H_ */
-- 
2.13.2

  parent reply	other threads:[~2017-07-20  3:45 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-20  3:44 [PATCH v2 00/10] ARM: sun8i: a83t: Add support for MMC controllers Chen-Yu Tsai
2017-07-20  3:44 ` [PATCH v2 01/10] clk: sunxi-ng: Add interface to query or configure MMC timing modes Chen-Yu Tsai
2017-07-21  7:18   ` Maxime Ripard
2017-07-21  7:23     ` Chen-Yu Tsai
2017-07-20  3:44 ` Chen-Yu Tsai [this message]
2017-07-21  7:19   ` [PATCH v2 02/10] clk: sunxi-ng: Add MP_MMC clocks that support MMC timing modes switching Maxime Ripard
2017-07-20  3:44 ` [PATCH v2 03/10] clk: sunxi-ng: a83t: Support new timing mode for mmc2 clock Chen-Yu Tsai
2017-07-20  3:44 ` [PATCH v2 04/10] mmc: sunxi: Support controllers that can use both old and new timings Chen-Yu Tsai
2017-07-21  7:20   ` Maxime Ripard
2017-07-20  3:44 ` [PATCH v2 05/10] mmc: sunxi: Support MMC DDR52 transfer mode with new timing mode Chen-Yu Tsai
2017-07-21  7:21   ` Maxime Ripard
2017-07-20  3:44 ` [PATCH v2 06/10] mmc: sunxi: Add support for A83T eMMC (MMC2) Chen-Yu Tsai
2017-07-21  7:21   ` Maxime Ripard
2017-07-20  3:44 ` [PATCH v2 07/10] ARM: dts: sun8i: a83t: Add MMC controller device nodes Chen-Yu Tsai
2017-07-23  0:36   ` kbuild test robot
2017-07-20  3:44 ` [PATCH v2 08/10] ARM: dts: sun8i: a83t: Add pingroup for 8-bit eMMC on mmc2 Chen-Yu Tsai
2017-07-20  3:44 ` [PATCH v2 09/10] ARM: dts: sun8i: a83t: cubietruck-plus: Enable micro-SD card and eMMC Chen-Yu Tsai
2017-07-20  3:44 ` [PATCH v2 10/10] ARM: dts: sun8i: a83t: h8homlet: Enable micro-SD card and onboard eMMC Chen-Yu Tsai

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=20170720034452.15920-3-wens@csie.org \
    --to=wens@csie.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=linux-sunxi@googlegroups.com \
    --cc=mark.rutland@arm.com \
    --cc=maxime.ripard@free-electrons.com \
    --cc=mturquette@baylibre.com \
    --cc=robh+dt@kernel.org \
    --cc=sboyd@codeaurora.org \
    --cc=ulf.hansson@linaro.org \
    /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).