All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH V3 1/4] mmc: tmio: Switch to clock framework
@ 2018-11-05 21:45 Marek Vasut
  2018-11-05 21:45 ` [U-Boot] [PATCH V3 2/4] mmc: tmio: Do not set divider to 1 in DDR mode Marek Vasut
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Marek Vasut @ 2018-11-05 21:45 UTC (permalink / raw)
  To: u-boot

Switch the driver to using clk_get_rate()/clk_set_rate() instead of
caching the mclk frequency in it's private data. This is required on
the SDHI variant of the controller, where the upstream mclk need to
be adjusted when using UHS modes.

Platforms which do not support clock framework or do not support it
in eg. SPL default to 100 MHz clock.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
V2: - Fix build on certain platforms using SPL without clock framework
V3: - Turn clk_get_rate into a callback and fill it as needed on both
      renesas and socionext platforms
---
 drivers/mmc/renesas-sdhi.c | 21 +++++++++++++--------
 drivers/mmc/tmio-common.c  | 17 ++++++++++++++---
 drivers/mmc/tmio-common.h  |  5 ++++-
 drivers/mmc/uniphier-sd.c  | 30 ++++++++++++++++++++----------
 4 files changed, 51 insertions(+), 22 deletions(-)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index e7f96f8bf2..f4283d055f 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -358,15 +358,21 @@ static const struct udevice_id renesas_sdhi_match[] = {
 	{ /* sentinel */ }
 };
 
+static ulong renesas_sdhi_clk_get_rate(struct tmio_sd_priv *priv)
+{
+	return clk_get_rate(&priv->clk);
+}
+
 static int renesas_sdhi_probe(struct udevice *dev)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	u32 quirks = dev_get_driver_data(dev);
 	struct fdt_resource reg_res;
-	struct clk clk;
 	DECLARE_GLOBAL_DATA_PTR;
 	int ret;
 
+	priv->clk_get_rate = renesas_sdhi_clk_get_rate;
+
 	if (quirks == RENESAS_GEN2_QUIRKS) {
 		ret = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev),
 				       "reg", 0, &reg_res);
@@ -380,22 +386,21 @@ static int renesas_sdhi_probe(struct udevice *dev)
 			quirks |= TMIO_SD_CAP_16BIT;
 	}
 
-	ret = clk_get_by_index(dev, 0, &clk);
+	ret = clk_get_by_index(dev, 0, &priv->clk);
 	if (ret < 0) {
 		dev_err(dev, "failed to get host clock\n");
 		return ret;
 	}
 
 	/* set to max rate */
-	priv->mclk = clk_set_rate(&clk, ULONG_MAX);
-	if (IS_ERR_VALUE(priv->mclk)) {
+	ret = clk_set_rate(&priv->clk, 200000000);
+	if (ret < 0) {
 		dev_err(dev, "failed to set rate for host clock\n");
-		clk_free(&clk);
-		return priv->mclk;
+		clk_free(&priv->clk);
+		return ret;
 	}
 
-	ret = clk_enable(&clk);
-	clk_free(&clk);
+	ret = clk_enable(&priv->clk);
 	if (ret) {
 		dev_err(dev, "failed to enable host clock\n");
 		return ret;
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 0eca83a0f4..3ba2f07460 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -555,16 +555,24 @@ static void tmio_sd_set_ddr_mode(struct tmio_sd_priv *priv,
 	tmio_sd_writel(priv, tmp, TMIO_SD_IF_MODE);
 }
 
+static ulong tmio_sd_clk_get_rate(struct tmio_sd_priv *priv)
+{
+	return priv->clk_get_rate(priv);
+}
+
 static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
 				     struct mmc *mmc)
 {
 	unsigned int divisor;
 	u32 val, tmp;
+	ulong mclk;
 
 	if (!mmc->clock)
 		return;
 
-	divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
+	mclk = tmio_sd_clk_get_rate(priv);
+
+	divisor = DIV_ROUND_UP(mclk, mmc->clock);
 
 	if (divisor <= 1)
 		val = (priv->caps & TMIO_SD_CAP_RCAR) ?
@@ -708,6 +716,7 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 	fdt_addr_t base;
+	ulong mclk;
 	int ret;
 
 	base = devfdt_get_addr(dev);
@@ -750,10 +759,12 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
 
 	tmio_sd_host_init(priv);
 
+	mclk = tmio_sd_clk_get_rate(priv);
+
 	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
-	plat->cfg.f_min = priv->mclk /
+	plat->cfg.f_min = mclk /
 			(priv->caps & TMIO_SD_CAP_DIV1024 ? 1024 : 512);
-	plat->cfg.f_max = priv->mclk;
+	plat->cfg.f_max = mclk;
 	plat->cfg.b_max = U32_MAX; /* max value of TMIO_SD_SECCNT */
 
 	upriv->mmc = &plat->mmc;
diff --git a/drivers/mmc/tmio-common.h b/drivers/mmc/tmio-common.h
index 792b1ba5ae..6591c61c3c 100644
--- a/drivers/mmc/tmio-common.h
+++ b/drivers/mmc/tmio-common.h
@@ -117,7 +117,6 @@ struct tmio_sd_plat {
 
 struct tmio_sd_priv {
 	void __iomem			*regbase;
-	unsigned long			mclk;
 	unsigned int			version;
 	u32				caps;
 #define TMIO_SD_CAP_NONREMOVABLE	BIT(0)	/* Nonremovable e.g. eMMC */
@@ -133,6 +132,10 @@ struct tmio_sd_priv {
 #ifdef CONFIG_DM_REGULATOR
 	struct udevice *vqmmc_dev;
 #endif
+#if CONFIG_IS_ENABLED(CLK)
+	struct clk			clk;
+#endif
+	ulong (*clk_get_rate)(struct tmio_sd_priv *);
 };
 
 int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 813c28494c..6539880ab5 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -31,35 +31,45 @@ static const struct udevice_id uniphier_sd_match[] = {
 	{ /* sentinel */ }
 };
 
+static ulong uniphier_sd_clk_get_rate(struct tmio_sd_priv *priv)
+{
+#if CONFIG_IS_ENABLED(CLK)
+	return clk_get_rate(&priv->clk);
+#elif CONFIG_SPL_BUILD
+	return 100000000;
+#else
+	return 0;
+#endif
+}
+
 static int uniphier_sd_probe(struct udevice *dev)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+	priv->clk_get_rate = uniphier_sd_clk_get_rate;
+
 #ifndef CONFIG_SPL_BUILD
-	struct clk clk;
 	int ret;
 
-	ret = clk_get_by_index(dev, 0, &clk);
+	ret = clk_get_by_index(dev, 0, &priv->clk);
 	if (ret < 0) {
 		dev_err(dev, "failed to get host clock\n");
 		return ret;
 	}
 
 	/* set to max rate */
-	priv->mclk = clk_set_rate(&clk, ULONG_MAX);
-	if (IS_ERR_VALUE(priv->mclk)) {
+	ret = clk_set_rate(&priv->clk, ULONG_MAX);
+	if (ret < 0) {
 		dev_err(dev, "failed to set rate for host clock\n");
-		clk_free(&clk);
-		return priv->mclk;
+		clk_free(&priv->clk);
+		return ret;
 	}
 
-	ret = clk_enable(&clk);
-	clk_free(&clk);
+	ret = clk_enable(&priv->clk);
 	if (ret) {
 		dev_err(dev, "failed to enable host clock\n");
 		return ret;
 	}
-#else
-	priv->mclk = 100000000;
 #endif
 
 	return tmio_sd_probe(dev, 0);
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH V3 2/4] mmc: tmio: Do not set divider to 1 in DDR mode
  2018-11-05 21:45 [U-Boot] [PATCH V3 1/4] mmc: tmio: Switch to clock framework Marek Vasut
@ 2018-11-05 21:45 ` Marek Vasut
  2018-11-05 21:45 ` [U-Boot] [PATCH V3 3/4] mmc: tmio: Keep generating clock when clock are enabled Marek Vasut
  2018-11-05 21:45 ` [U-Boot] [PATCH V3 4/4] mmc: tmio: sdhi: Switch CPG settings in UHS modes Marek Vasut
  2 siblings, 0 replies; 4+ messages in thread
From: Marek Vasut @ 2018-11-05 21:45 UTC (permalink / raw)
  To: u-boot

The TMIO core has a quirk where divider == 1 must not be set in DDR modes.
Handle this by setting divider to 2, as suggested in the documentation.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
 drivers/mmc/tmio-common.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 3ba2f07460..424b60ce52 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -574,6 +574,10 @@ static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
 
 	divisor = DIV_ROUND_UP(mclk, mmc->clock);
 
+	/* Do not set divider to 0xff in DDR mode */
+	if (mmc->ddr_mode && (divisor == 1))
+		divisor = 2;
+
 	if (divisor <= 1)
 		val = (priv->caps & TMIO_SD_CAP_RCAR) ?
 		      TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH V3 3/4] mmc: tmio: Keep generating clock when clock are enabled
  2018-11-05 21:45 [U-Boot] [PATCH V3 1/4] mmc: tmio: Switch to clock framework Marek Vasut
  2018-11-05 21:45 ` [U-Boot] [PATCH V3 2/4] mmc: tmio: Do not set divider to 1 in DDR mode Marek Vasut
@ 2018-11-05 21:45 ` Marek Vasut
  2018-11-05 21:45 ` [U-Boot] [PATCH V3 4/4] mmc: tmio: sdhi: Switch CPG settings in UHS modes Marek Vasut
  2 siblings, 0 replies; 4+ messages in thread
From: Marek Vasut @ 2018-11-05 21:45 UTC (permalink / raw)
  To: u-boot

The TMIO core has a feature where it can automatically disable clock output
when the bus is not in use. While this is useful, it also interferes with
switching the bus to 1.8V and other background tasks of the SD/MMC cards,
which require clock to be enabled.

This patch respects the mmc->clk_disable and only disables the clock when
the MMC core requests it. Otherwise the clock are continuously generated
on the bus.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
 drivers/mmc/tmio-common.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 424b60ce52..fad2816ca5 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -612,10 +612,16 @@ static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
 	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
 	tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
-	tmp |= val | TMIO_SD_CLKCTL_OFFEN;
+	tmp |= val;
 	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
-	tmp |= TMIO_SD_CLKCTL_SCLKEN;
+	if (!mmc->clk_disable) {
+		tmp &= ~TMIO_SD_CLKCTL_OFFEN;
+		tmp |= TMIO_SD_CLKCTL_SCLKEN;
+	} else {
+		tmp |= TMIO_SD_CLKCTL_OFFEN;
+		tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+	}
 	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
 	udelay(1000);
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH V3 4/4] mmc: tmio: sdhi: Switch CPG settings in UHS modes
  2018-11-05 21:45 [U-Boot] [PATCH V3 1/4] mmc: tmio: Switch to clock framework Marek Vasut
  2018-11-05 21:45 ` [U-Boot] [PATCH V3 2/4] mmc: tmio: Do not set divider to 1 in DDR mode Marek Vasut
  2018-11-05 21:45 ` [U-Boot] [PATCH V3 3/4] mmc: tmio: Keep generating clock when clock are enabled Marek Vasut
@ 2018-11-05 21:45 ` Marek Vasut
  2 siblings, 0 replies; 4+ messages in thread
From: Marek Vasut @ 2018-11-05 21:45 UTC (permalink / raw)
  To: u-boot

Switch CPG settings when transitioning between HS200/HS400/SDR104
and regular modes. This is required for the SCC block to operate
correctly.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
---
 drivers/mmc/renesas-sdhi.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index f4283d055f..fd2a361a6d 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -289,9 +289,35 @@ out:
 }
 #endif
 
+static void renesas_sdhi_set_clk(struct udevice *dev)
+{
+	struct tmio_sd_priv *priv = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	u32 tmp;
+
+	if (!mmc->clock)
+		return;
+
+	/* Stop the clock before changing its rate to avoid a glitch signal */
+	tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
+	tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+
+	if ((mmc->selected_mode == UHS_SDR104) ||
+	    (mmc->selected_mode == MMC_HS_200)) {
+		clk_set_rate(&priv->clk, 400000000);
+	} else {
+		clk_set_rate(&priv->clk, 200000000);
+	}
+}
+
 static int renesas_sdhi_set_ios(struct udevice *dev)
 {
-	int ret = tmio_sd_set_ios(dev);
+	int ret;
+
+	renesas_sdhi_set_clk(dev);
+
+	ret = tmio_sd_set_ios(dev);
 
 	mdelay(10);
 
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-11-05 21:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-05 21:45 [U-Boot] [PATCH V3 1/4] mmc: tmio: Switch to clock framework Marek Vasut
2018-11-05 21:45 ` [U-Boot] [PATCH V3 2/4] mmc: tmio: Do not set divider to 1 in DDR mode Marek Vasut
2018-11-05 21:45 ` [U-Boot] [PATCH V3 3/4] mmc: tmio: Keep generating clock when clock are enabled Marek Vasut
2018-11-05 21:45 ` [U-Boot] [PATCH V3 4/4] mmc: tmio: sdhi: Switch CPG settings in UHS modes Marek Vasut

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.