All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Lad Prabhakar" <prabhakar.mahadev-lad.rj@bp.renesas.com>
To: cip-dev@lists.cip-project.org,
	Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>,
	Pavel Machek <pavel@denx.de>
Cc: Biju Das <biju.das.jz@bp.renesas.com>
Subject: [RESEND PATCH 5.10.y-cip 27/40] clk: renesas: rzg2l: Add SDHI clk mux support
Date: Fri,  1 Apr 2022 20:42:21 +0100	[thread overview]
Message-ID: <20220401194234.14057-28-prabhakar.mahadev-lad.rj@bp.renesas.com> (raw)
In-Reply-To: <20220401194234.14057-1-prabhakar.mahadev-lad.rj@bp.renesas.com>

From: Biju Das <biju.das.jz@bp.renesas.com>

commit eaff33646f4cb6a541d01013b0a222f03f6dfac3 upstream.

Add SDHI clk mux support to select SDHI clock from different clock
sources.

As per HW manual, direct clock switching from 533MHz to 400MHz and
vice versa is not recommended. So added support for handling this
in mux.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20211007111434.8665-2-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 drivers/clk/renesas/rzg2l-cpg.c | 118 ++++++++++++++++++++++++++++++++
 drivers/clk/renesas/rzg2l-cpg.h |  12 ++++
 2 files changed, 130 insertions(+)

diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 1501547a11a3..4021f6cabda4 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/iopoll.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
@@ -55,6 +56,14 @@
 #define GET_REG_SAMPLL_CLK1(val)	((val >> 22) & 0xfff)
 #define GET_REG_SAMPLL_CLK2(val)	((val >> 12) & 0xfff)
 
+struct sd_hw_data {
+	struct clk_hw hw;
+	u32 conf;
+	struct rzg2l_cpg_priv *priv;
+};
+
+#define to_sd_hw_data(_hw)	container_of(_hw, struct sd_hw_data, hw)
+
 /**
  * struct rzg2l_cpg_priv - Clock Pulse Generator Private Data
  *
@@ -150,6 +159,112 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
 	return clk_hw->clk;
 }
 
+static int rzg2l_cpg_sd_clk_mux_determine_rate(struct clk_hw *hw,
+					       struct clk_rate_request *req)
+{
+	return clk_mux_determine_rate_flags(hw, req, 0);
+}
+
+static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct sd_hw_data *hwdata = to_sd_hw_data(hw);
+	struct rzg2l_cpg_priv *priv = hwdata->priv;
+	u32 off = GET_REG_OFFSET(hwdata->conf);
+	u32 shift = GET_SHIFT(hwdata->conf);
+	const u32 clk_src_266 = 2;
+	u32 bitmask;
+
+	/*
+	 * As per the HW manual, we should not directly switch from 533 MHz to
+	 * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
+	 * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
+	 * and then switch to the target setting (2’b01 (533 MHz) or 2’b10
+	 * (400 MHz)).
+	 * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
+	 * switching register is prohibited.
+	 * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
+	 * the index to value mapping is done by adding 1 to the index.
+	 */
+	bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16;
+	if (index != clk_src_266) {
+		u32 msk, val;
+		int ret;
+
+		writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off);
+
+		msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS;
+
+		ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val,
+					 !(val & msk), 100,
+					 CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
+		if (ret) {
+			dev_err(priv->dev, "failed to switch clk source\n");
+			return ret;
+		}
+	}
+
+	writel(bitmask | ((index + 1) << shift), priv->base + off);
+
+	return 0;
+}
+
+static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw)
+{
+	struct sd_hw_data *hwdata = to_sd_hw_data(hw);
+	struct rzg2l_cpg_priv *priv = hwdata->priv;
+	u32 val = readl(priv->base + GET_REG_OFFSET(hwdata->conf));
+
+	val >>= GET_SHIFT(hwdata->conf);
+	val &= GENMASK(GET_WIDTH(hwdata->conf) - 1, 0);
+	if (val) {
+		val--;
+	} else {
+		/* Prohibited clk source, change it to 533 MHz(reset value) */
+		rzg2l_cpg_sd_clk_mux_set_parent(hw, 0);
+	}
+
+	return val;
+}
+
+static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = {
+	.determine_rate = rzg2l_cpg_sd_clk_mux_determine_rate,
+	.set_parent	= rzg2l_cpg_sd_clk_mux_set_parent,
+	.get_parent	= rzg2l_cpg_sd_clk_mux_get_parent,
+};
+
+static struct clk * __init
+rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
+			      void __iomem *base,
+			      struct rzg2l_cpg_priv *priv)
+{
+	struct sd_hw_data *clk_hw_data;
+	struct clk_init_data init;
+	struct clk_hw *clk_hw;
+	int ret;
+
+	clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
+	if (!clk_hw_data)
+		return ERR_PTR(-ENOMEM);
+
+	clk_hw_data->priv = priv;
+	clk_hw_data->conf = core->conf;
+
+	init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0";
+	init.ops = &rzg2l_cpg_sd_clk_mux_ops;
+	init.flags = 0;
+	init.num_parents = core->num_parents;
+	init.parent_names = core->parent_names;
+
+	clk_hw = &clk_hw_data->hw;
+	clk_hw->init = &init;
+
+	ret = devm_clk_hw_register(priv->dev, clk_hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return clk_hw->clk;
+}
+
 struct pll_clk {
 	struct clk_hw hw;
 	unsigned int conf;
@@ -311,6 +426,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
 	case CLK_TYPE_MUX:
 		clk = rzg2l_cpg_mux_clk_register(core, priv->base, priv);
 		break;
+	case CLK_TYPE_SD_MUX:
+		clk = rzg2l_cpg_sd_mux_clk_register(core, priv->base, priv);
+		break;
 	default:
 		goto fail;
 	}
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
index dc5b65a4029e..952fca98ba71 100644
--- a/drivers/clk/renesas/rzg2l-cpg.h
+++ b/drivers/clk/renesas/rzg2l-cpg.h
@@ -11,9 +11,15 @@
 
 #define CPG_PL2_DDIV		(0x204)
 #define CPG_PL3A_DDIV		(0x208)
+#define CPG_CLKSTATUS		(0x280)
 #define CPG_PL3_SSEL		(0x408)
 #define CPG_PL6_ETH_SSEL	(0x418)
 
+#define CPG_CLKSTATUS_SELSDHI0_STS	BIT(28)
+#define CPG_CLKSTATUS_SELSDHI1_STS	BIT(29)
+
+#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US	20000
+
 /* n = 0/1/2 for PLL1/4/6 */
 #define CPG_SAMPLL_CLK1(n)	(0x04 + (16 * n))
 #define CPG_SAMPLL_CLK2(n)	(0x08 + (16 * n))
@@ -67,6 +73,9 @@ enum clk_types {
 
 	/* Clock with clock source selector */
 	CLK_TYPE_MUX,
+
+	/* Clock with SD clock source selector */
+	CLK_TYPE_SD_MUX,
 };
 
 #define DEF_TYPE(_name, _id, _type...) \
@@ -87,6 +96,9 @@ enum clk_types {
 	DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \
 		 .parent_names = _parent_names, .num_parents = _num_parents, \
 		 .flag = _flag, .mux_flags = _mux_flags)
+#define DEF_SD_MUX(_name, _id, _conf, _parent_names, _num_parents) \
+	DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \
+		 .parent_names = _parent_names, .num_parents = _num_parents)
 
 /**
  * struct rzg2l_mod_clk - Module Clocks definitions
-- 
2.17.1



  parent reply	other threads:[~2022-04-01 19:43 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-01 19:41 [RESEND PATCH 5.10.y-cip 00/40] Add SD/eMMC support for Renesas RZ/G2L SoC Lad Prabhakar
2022-04-01 19:41 ` [RESEND PATCH 5.10.y-cip 01/40] mmc: renesas_sdhi: only reset SCC when its pointer is populated Lad Prabhakar
2022-04-01 19:41 ` [RESEND PATCH 5.10.y-cip 02/40] mmc: renesas_sdhi: probe into TMIO after SCC parameters have been setup Lad Prabhakar
2022-04-01 19:41 ` [RESEND PATCH 5.10.y-cip 03/40] mmc: renesas_sdhi: populate SCC pointer at the proper place Lad Prabhakar
2022-04-01 19:41 ` [RESEND PATCH 5.10.y-cip 04/40] mmc: renesas_sdhi: simplify reset routine a little Lad Prabhakar
2022-04-01 19:41 ` [RESEND PATCH 5.10.y-cip 05/40] mmc: renesas_sdhi: clear TAPEN when resetting, too Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 06/40] mmc: renesas_sdhi: merge the SCC reset functions Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 07/40] mmc: renesas_sdhi: remove superfluous SCLKEN Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 08/40] mmc: renesas_sdhi: improve HOST_MODE usage Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 09/40] mmc: renesas_sdhi: don't hardcode SDIF values Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 10/40] mmc: renesas_sdhi: sort includes Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 11/40] mmc: tmio: set max_busy_timeout Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 12/40] mmc: tmio: add hook for custom busy_wait calculation Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 13/40] mmc: renesas_sdhi: populate hook for longer busy_wait Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 14/40] mmc: renesas_internal_dmac: add pre_req and post_req support Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 15/40] mmc: tmio: Add data timeout error detection Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 16/40] mmc: renesas_sdhi: Add a condition of cmd/data timeout for retune Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 17/40] mmc: tmio: support custom irq masks Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 18/40] mmc: renesas_sdhi: use custom mask for TMIO_MASK_ALL Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 19/40] mmc: tmio: abort DMA before reset Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 20/40] mmc: tmio: restore bus width when resetting Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 21/40] mmc: renesas_sdhi: break SCC reset into own function Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 22/40] mmc: renesas_sdhi: do hard reset if possible Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 23/40] mmc: tmio: always flag retune when resetting and a card is present Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 24/40] mmc: tmio: always restore irq register Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 25/40] mmc: tmio: reenable card irqs after the reset callback Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 26/40] mmc: tmio: reinit card irqs in reset routine Lad Prabhakar
2022-04-01 19:42 ` Lad Prabhakar [this message]
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 28/40] clk: renesas: rzg2l: Add missing kerneldoc for resets Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 29/40] clk: renesas: rzg2l: Check return value of pm_genpd_init() Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 30/40] clk: renesas: rzg2l: propagate return value of_genpd_add_provider_simple() Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 31/40] clk: renesas: r9a07g044: Add SDHI clock and reset entries Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 32/40] dt-bindings: Fix errors in 'if' schemas Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 33/40] dt-bindings: Drop redundant minItems/maxItems Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 34/40] dt-bindings: mmc: renesas,sdhi: Fix dtbs-check warning Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 35/40] dt-bindings: mmc: renesas,sdhi: Document RZ/G2L bindings Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 36/40] dt-bindings: mmc: renesas,sdhi: Add optional SDnH clock Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 37/40] dt-bindings: mmc: renesas,sdhi: Rename RZ/G2L clocks Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 38/40] arm64: dts: renesas: r9a07g044: Add SDHI nodes Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 39/40] arm64: dts: renesas: rzg2l-smarc-som: Enable eMMC on SMARC platform Lad Prabhakar
2022-04-01 19:42 ` [RESEND PATCH 5.10.y-cip 40/40] arm64: dts: renesas: rzg2l-smarc: Enable microSD " Lad Prabhakar
2022-04-01 21:33 ` [RESEND PATCH 5.10.y-cip 00/40] Add SD/eMMC support for Renesas RZ/G2L SoC Pavel Machek

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=20220401194234.14057-28-prabhakar.mahadev-lad.rj@bp.renesas.com \
    --to=prabhakar.mahadev-lad.rj@bp.renesas.com \
    --cc=biju.das.jz@bp.renesas.com \
    --cc=cip-dev@lists.cip-project.org \
    --cc=nobuhiro1.iwamatsu@toshiba.co.jp \
    --cc=pavel@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.