[U-Boot] [PATCH 01/13] mmc: tmio: Simplify pinmux handling

The SD UHS SDR12, SDR25, SDR50, SDR104, DDR50 and MMC HS200, HS400 modes all use 1.8V signaling, while all the legacy modes use 3.3V signaling. While there are extra modes which use 1.2V signaling, the existing hardware does not support those.
Simplify the pinmux such that 3.3V signaling implies legacy mode pinmux and the rest implies UHS mode pinmux. This prevents the massive case statement from growing further. Moreover, it fixes an edge case where during SD 1.8V switch, the bus mode is still set to default while the signaling is already set to 1.8V, which results in an attempt to communicate with a 1.8V card using pins in 3.3V mode and thus communication failure.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/tmio-common.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 138de59470..5f927c6150 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -622,26 +622,10 @@ static void tmio_sd_set_pins(struct udevice *dev) #endif
#ifdef CONFIG_PINCTRL - switch (mmc->selected_mode) { - case MMC_LEGACY: - case SD_LEGACY: - case MMC_HS: - case SD_HS: - case MMC_HS_52: - case MMC_DDR_52: - pinctrl_select_state(dev, "default"); - break; - case UHS_SDR12: - case UHS_SDR25: - case UHS_SDR50: - case UHS_DDR50: - case UHS_SDR104: - case MMC_HS_200: + if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) pinctrl_select_state(dev, "state_uhs"); - break; - default: - break; - } + else + pinctrl_select_state(dev, "default"); #endif }

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.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/renesas-sdhi.c | 14 ++++++-------- drivers/mmc/tmio-common.c | 12 +++++++++--- drivers/mmc/tmio-common.h | 2 +- drivers/mmc/uniphier-sd.c | 13 +++++-------- 4 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index f8dc5f57ce..1590f496d7 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -333,7 +333,6 @@ 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;
@@ -350,22 +349,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 5f927c6150..9eb2984ed3 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -556,11 +556,14 @@ static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv, { unsigned int divisor; u32 val, tmp; + ulong mclk;
if (!mmc->clock) return;
- divisor = DIV_ROUND_UP(priv->mclk, mmc->clock); + mclk = clk_get_rate(&priv->clk); + + divisor = DIV_ROUND_UP(mclk, mmc->clock);
if (divisor <= 1) val = (priv->caps & TMIO_SD_CAP_RCAR) ? @@ -704,6 +707,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); @@ -744,10 +748,12 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
tmio_sd_host_init(priv);
+ mclk = clk_get_rate(&priv->clk); + 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..fcdee4df57 100644 --- a/drivers/mmc/tmio-common.h +++ b/drivers/mmc/tmio-common.h @@ -117,7 +117,7 @@ struct tmio_sd_plat {
struct tmio_sd_priv { void __iomem *regbase; - unsigned long mclk; + struct clk clk; unsigned int version; u32 caps; #define TMIO_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 813c28494c..870d1c9929 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -38,28 +38,25 @@ static int uniphier_sd_probe(struct udevice *dev) 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); if (ret) { dev_err(dev, "failed to enable host clock\n"); return ret; } -#else - priv->mclk = 100000000; #endif
return tmio_sd_probe(dev, 0);

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 --- drivers/mmc/renesas-sdhi.c | 14 ++++++-------- drivers/mmc/tmio-common.c | 21 ++++++++++++++++++--- drivers/mmc/tmio-common.h | 2 +- drivers/mmc/uniphier-sd.c | 13 +++++-------- 4 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index f8dc5f57ce..1590f496d7 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -333,7 +333,6 @@ 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;
@@ -350,22 +349,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 5f927c6150..611fc5fdbc 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -551,16 +551,28 @@ 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) +{ +#if CONFIG_IS_ENABLED(CLK) + return clk_get_rate(&priv->clk); +#else + return 100000000; +#endif +} + 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) ? @@ -704,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); @@ -744,10 +757,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..fcdee4df57 100644 --- a/drivers/mmc/tmio-common.h +++ b/drivers/mmc/tmio-common.h @@ -117,7 +117,7 @@ struct tmio_sd_plat {
struct tmio_sd_priv { void __iomem *regbase; - unsigned long mclk; + struct clk clk; unsigned int version; u32 caps; #define TMIO_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 813c28494c..870d1c9929 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -38,28 +38,25 @@ static int uniphier_sd_probe(struct udevice *dev) 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); if (ret) { dev_err(dev, "failed to enable host clock\n"); return ret; } -#else - priv->mclk = 100000000; #endif
return tmio_sd_probe(dev, 0);

On Thu, Nov 1, 2018 at 6:39 PM Marek Vasut marek.vasut@gmail.com wrote:
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.
No.
What you need to do is move tmio_sd_set_clk_rate() to a platform hook.
See Linux commit 0196c8db8363f7627df6f78615271ae0ba430500
Platforms which do not support clock framework or do not support it in eg. SPL default to 100 MHz clock.
This is bad. You never know whether the default clock is 100 MHz or not.
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
drivers/mmc/renesas-sdhi.c | 14 ++++++-------- drivers/mmc/tmio-common.c | 21 ++++++++++++++++++--- drivers/mmc/tmio-common.h | 2 +- drivers/mmc/uniphier-sd.c | 13 +++++-------- 4 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index f8dc5f57ce..1590f496d7 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -333,7 +333,6 @@ 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;
@@ -350,22 +349,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 5f927c6150..611fc5fdbc 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -551,16 +551,28 @@ 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) +{ +#if CONFIG_IS_ENABLED(CLK)
return clk_get_rate(&priv->clk);
+#else
return 100000000;
+#endif +} 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) ?
@@ -704,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);
@@ -744,10 +757,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..fcdee4df57 100644 --- a/drivers/mmc/tmio-common.h +++ b/drivers/mmc/tmio-common.h @@ -117,7 +117,7 @@ struct tmio_sd_plat {
struct tmio_sd_priv { void __iomem *regbase;
unsigned long mclk;
struct clk clk; unsigned int version; u32 caps;
#define TMIO_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 813c28494c..870d1c9929 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -38,28 +38,25 @@ static int uniphier_sd_probe(struct udevice *dev) 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); 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
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
-- Best Regards Masahiro Yamada

On Thu, Nov 1, 2018 at 8:38 PM Masahiro Yamada yamada.masahiro@socionext.com wrote:
On Thu, Nov 1, 2018 at 6:39 PM Marek Vasut marek.vasut@gmail.com wrote:
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.
No.
What you need to do is move tmio_sd_set_clk_rate() to a platform hook.
See Linux commit 0196c8db8363f7627df6f78615271ae0ba430500
Platforms which do not support clock framework or do not support it in eg. SPL default to 100 MHz clock.
This is bad. You never know whether the default clock is 100 MHz or not.
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
drivers/mmc/renesas-sdhi.c | 14 ++++++-------- drivers/mmc/tmio-common.c | 21 ++++++++++++++++++--- drivers/mmc/tmio-common.h | 2 +- drivers/mmc/uniphier-sd.c | 13 +++++-------- 4 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index f8dc5f57ce..1590f496d7 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -333,7 +333,6 @@ 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;
@@ -350,22 +349,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 5f927c6150..611fc5fdbc 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -551,16 +551,28 @@ 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) +{ +#if CONFIG_IS_ENABLED(CLK)
return clk_get_rate(&priv->clk);
+#else
return 100000000;
+#endif +} 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) ?
@@ -704,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);
@@ -744,10 +757,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..fcdee4df57 100644 --- a/drivers/mmc/tmio-common.h +++ b/drivers/mmc/tmio-common.h @@ -117,7 +117,7 @@ struct tmio_sd_plat {
struct tmio_sd_priv { void __iomem *regbase;
unsigned long mclk;
struct clk clk; unsigned int version; u32 caps;
#define TMIO_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 813c28494c..870d1c9929 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -38,28 +38,25 @@ static int uniphier_sd_probe(struct udevice *dev) 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); if (ret) { dev_err(dev, "failed to enable host clock\n"); return ret; }
-#else
priv->mclk = 100000000;
#endif
return tmio_sd_probe(dev, 0);
Finally, I figure out why this patch breaks my boards.
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 870d1c9..d8eca30 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -35,7 +35,6 @@ static int uniphier_sd_probe(struct udevice *dev) { struct tmio_sd_priv *priv = dev_get_priv(dev); #ifndef CONFIG_SPL_BUILD - struct clk clk; int ret;
ret = clk_get_by_index(dev, 0, &priv->clk); @@ -52,7 +51,7 @@ static int uniphier_sd_probe(struct udevice *dev) return ret; }
- ret = clk_enable(&clk); + ret = clk_enable(&priv->clk); if (ret) { dev_err(dev, "failed to enable host clock\n"); return ret;

On 11/02/2018 03:19 AM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 8:38 PM Masahiro Yamada yamada.masahiro@socionext.com wrote:
On Thu, Nov 1, 2018 at 6:39 PM Marek Vasut marek.vasut@gmail.com wrote:
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.
No.
What you need to do is move tmio_sd_set_clk_rate() to a platform hook.
See Linux commit 0196c8db8363f7627df6f78615271ae0ba430500
Platforms which do not support clock framework or do not support it in eg. SPL default to 100 MHz clock.
This is bad. You never know whether the default clock is 100 MHz or not.
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
drivers/mmc/renesas-sdhi.c | 14 ++++++-------- drivers/mmc/tmio-common.c | 21 ++++++++++++++++++--- drivers/mmc/tmio-common.h | 2 +- drivers/mmc/uniphier-sd.c | 13 +++++-------- 4 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index f8dc5f57ce..1590f496d7 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -333,7 +333,6 @@ 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;
@@ -350,22 +349,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 5f927c6150..611fc5fdbc 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -551,16 +551,28 @@ 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) +{ +#if CONFIG_IS_ENABLED(CLK)
return clk_get_rate(&priv->clk);
+#else
return 100000000;
+#endif +} 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) ?
@@ -704,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);
@@ -744,10 +757,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..fcdee4df57 100644 --- a/drivers/mmc/tmio-common.h +++ b/drivers/mmc/tmio-common.h @@ -117,7 +117,7 @@ struct tmio_sd_plat {
struct tmio_sd_priv { void __iomem *regbase;
unsigned long mclk;
struct clk clk; unsigned int version; u32 caps;
#define TMIO_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 813c28494c..870d1c9929 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -38,28 +38,25 @@ static int uniphier_sd_probe(struct udevice *dev) 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); if (ret) { dev_err(dev, "failed to enable host clock\n"); return ret; }
-#else
priv->mclk = 100000000;
#endif
return tmio_sd_probe(dev, 0);
Finally, I figure out why this patch breaks my boards.
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 870d1c9..d8eca30 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -35,7 +35,6 @@ static int uniphier_sd_probe(struct udevice *dev) { struct tmio_sd_priv *priv = dev_get_priv(dev); #ifndef CONFIG_SPL_BUILD
struct clk clk; int ret; ret = clk_get_by_index(dev, 0, &priv->clk);
@@ -52,7 +51,7 @@ static int uniphier_sd_probe(struct udevice *dev) return ret; }
ret = clk_enable(&clk);
ret = clk_enable(&priv->clk); if (ret) { dev_err(dev, "failed to enable host clock\n"); return ret;
Thanks, added.
I'll also turn the clk_get_rate() into a callback and implement it differently on socionext and renesas platforms to avoid polluting the core code.

On Thu, Nov 1, 2018 at 6:39 PM Marek Vasut marek.vasut@gmail.com wrote:
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
No. Not fixed.
uniphier_ld4_sld8_defconfig produces the following warning.
drivers/mmc/uniphier-sd.c: In function ‘uniphier_sd_probe’: drivers/mmc/uniphier-sd.c:36:23: warning: unused variable ‘priv’ [-Wunused-variable] struct tmio_sd_priv *priv = dev_get_priv(dev); ^~~~

On 11/02/2018 03:24 AM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 6:39 PM Marek Vasut marek.vasut@gmail.com wrote:
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
No. Not fixed.
uniphier_ld4_sld8_defconfig produces the following warning.
drivers/mmc/uniphier-sd.c: In function ‘uniphier_sd_probe’: drivers/mmc/uniphier-sd.c:36:23: warning: unused variable ‘priv’ [-Wunused-variable] struct tmio_sd_priv *priv = dev_get_priv(dev);
Fixed in V3

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 9eb2984ed3..072171d4b3 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -565,6 +565,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;

On Thu, Nov 1, 2018 at 2:22 AM Marek Vasut marek.vasut@gmail.com wrote:
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 9eb2984ed3..072171d4b3 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -565,6 +565,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;
With this patch applied, my board would not boot any more.
Please stop adding Renesas-specific quirks to tmio-common.
By moving tmio_sd_set_clk_rate to a platform hook, you can do anything you want to do in renesas-sdhi.c
if (divisor <= 1) val = (priv->caps & TMIO_SD_CAP_RCAR) ? TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
-- 2.18.0
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
-- Best Regards Masahiro Yamada

On 11/01/2018 12:39 PM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 2:22 AM Marek Vasut marek.vasut@gmail.com wrote:
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 9eb2984ed3..072171d4b3 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -565,6 +565,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;
With this patch applied, my board would not boot any more.
Please stop adding Renesas-specific quirks to tmio-common.
By moving tmio_sd_set_clk_rate to a platform hook, you can do anything you want to do in renesas-sdhi.c
Are you sure this is renesas-specific ? My understanding is this is common to SDHI. I am happy to pull this whole thing into renesas specific part of the driver, but then you won't get all the clock fixes and there'll be duplication of code.

Configure the clock settings before reconfiguring any other IO settings. This is required when the clock must be stopped before changing eg. the pin configuration or any of the other properties of the bus. Running the clock configuration first allows the MMC core to do just that.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/tmio-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 072171d4b3..ef06f0aa4b 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -645,11 +645,11 @@ int tmio_sd_set_ios(struct udevice *dev) dev_dbg(dev, "clock %uHz, DDRmode %d, width %u\n", mmc->clock, mmc->ddr_mode, mmc->bus_width);
+ tmio_sd_set_clk_rate(priv, mmc); ret = tmio_sd_set_bus_width(priv, mmc); if (ret) return ret; tmio_sd_set_ddr_mode(priv, mmc); - tmio_sd_set_clk_rate(priv, mmc); tmio_sd_set_pins(dev);
return 0;

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 ef06f0aa4b..42eb847edb 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -603,10 +603,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);

On Thu, Nov 1, 2018 at 2:21 AM Marek Vasut marek.vasut@gmail.com wrote:
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 ef06f0aa4b..42eb847edb 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -603,10 +603,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;
Sorry, _OFFEN is Socionext-specific extension.
I believe moving tmio_sd_set_clk_rate to a platform hook will make our life easier.
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
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

On 11/01/2018 12:46 PM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 2:21 AM Marek Vasut marek.vasut@gmail.com wrote:
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 ef06f0aa4b..42eb847edb 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -603,10 +603,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;
Sorry, _OFFEN is Socionext-specific extension.
It's documented in renesas docs too.
I believe moving tmio_sd_set_clk_rate to a platform hook will make our life easier.
Are you sure ?

Preinitialize the SD card signals regulator to 3.3V, which is the default post-reset setting, to be sure the regulator is set to a valid value.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/tmio-common.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 42eb847edb..c8caa0fb18 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -730,6 +730,8 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
#ifdef CONFIG_DM_REGULATOR device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc_dev); + if (priv->vqmmc_dev) + regulator_set_value(priv->vqmmc_dev, 3300000); #endif
ret = mmc_of_parse(dev, &plat->cfg);

Properly handle return values and abort operations when they are non-zero. This is a minor improvement, which fixes two remaining unchecked return values.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/tmio-common.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index c8caa0fb18..8e83584e57 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -498,6 +498,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, ret = tmio_sd_dma_xfer(dev, data); else ret = tmio_sd_pio_xfer(dev, data); + if (ret) + return ret;
ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1, TMIO_SD_INFO1_CMP); @@ -505,9 +507,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, return ret; }
- tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, TMIO_SD_INFO2_SCLKDIVEN); - - return ret; + return tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, + TMIO_SD_INFO2_SCLKDIVEN); }
static int tmio_sd_set_bus_width(struct tmio_sd_priv *priv,

On Thu, Nov 1, 2018 at 2:25 AM Marek Vasut marek.vasut@gmail.com wrote:
Properly handle return values and abort operations when they are non-zero. This is a minor improvement, which fixes two remaining unchecked return values.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
Good catch! Thanks.
drivers/mmc/tmio-common.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index c8caa0fb18..8e83584e57 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -498,6 +498,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, ret = tmio_sd_dma_xfer(dev, data); else ret = tmio_sd_pio_xfer(dev, data);
if (ret)
return ret; ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1, TMIO_SD_INFO1_CMP);
@@ -505,9 +507,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, return ret; }
tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, TMIO_SD_INFO2_SCLKDIVEN);
return ret;
return tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
TMIO_SD_INFO2_SCLKDIVEN);
}
static int tmio_sd_set_bus_width(struct tmio_sd_priv *priv,
2.18.0
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

In case the controller performs card tuning, that is, sends MMC command 19 or 21, silence possible CRC error warning prints. The warnings are bound to happen, since the tuning will fail for some settings while searching for the optimal configuration of the bus and that is perfectly OK.
This patch passes around the MMC command structure and adds check into tmio_sd_check_error() to avoid printing CRC error warning when the tuning happens.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/tmio-common.c | 45 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 8e83584e57..8e1bcd7ed5 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -95,7 +95,7 @@ static void __dma_unmap_single(dma_addr_t addr, size_t size, invalidate_dcache_range(addr, addr + size); }
-static int tmio_sd_check_error(struct udevice *dev) +static int tmio_sd_check_error(struct udevice *dev, struct mmc_cmd *cmd) { struct tmio_sd_priv *priv = dev_get_priv(dev); u32 info2 = tmio_sd_readl(priv, TMIO_SD_INFO2); @@ -116,7 +116,9 @@ static int tmio_sd_check_error(struct udevice *dev)
if (info2 & (TMIO_SD_INFO2_ERR_END | TMIO_SD_INFO2_ERR_CRC | TMIO_SD_INFO2_ERR_IDX)) { - dev_err(dev, "communication out of sync\n"); + if ((cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK) && + (cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK_HS200)) + dev_err(dev, "communication out of sync\n"); return -EILSEQ; }
@@ -129,8 +131,8 @@ static int tmio_sd_check_error(struct udevice *dev) return 0; }
-static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg, - u32 flag) +static int tmio_sd_wait_for_irq(struct udevice *dev, struct mmc_cmd *cmd, + unsigned int reg, u32 flag) { struct tmio_sd_priv *priv = dev_get_priv(dev); long wait = 1000000; @@ -142,7 +144,7 @@ static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg, return -ETIMEDOUT; }
- ret = tmio_sd_check_error(dev); + ret = tmio_sd_check_error(dev, cmd); if (ret) return ret;
@@ -178,15 +180,15 @@ tmio_pio_read_fifo(64, q) tmio_pio_read_fifo(32, l) tmio_pio_read_fifo(16, w)
-static int tmio_sd_pio_read_one_block(struct udevice *dev, char *pbuf, - uint blocksize) +static int tmio_sd_pio_read_one_block(struct udevice *dev, struct mmc_cmd *cmd, + char *pbuf, uint blocksize) { struct tmio_sd_priv *priv = dev_get_priv(dev); int ret;
/* wait until the buffer is filled with data */ - ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, - TMIO_SD_INFO2_BRE); + ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2, + TMIO_SD_INFO2_BRE); if (ret) return ret;
@@ -231,15 +233,15 @@ tmio_pio_write_fifo(64, q) tmio_pio_write_fifo(32, l) tmio_pio_write_fifo(16, w)
-static int tmio_sd_pio_write_one_block(struct udevice *dev, +static int tmio_sd_pio_write_one_block(struct udevice *dev, struct mmc_cmd *cmd, const char *pbuf, uint blocksize) { struct tmio_sd_priv *priv = dev_get_priv(dev); int ret;
/* wait until the buffer becomes empty */ - ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, - TMIO_SD_INFO2_BWE); + ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2, + TMIO_SD_INFO2_BWE); if (ret) return ret;
@@ -255,7 +257,8 @@ static int tmio_sd_pio_write_one_block(struct udevice *dev, return 0; }
-static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data) +static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) { const char *src = data->src; char *dest = data->dest; @@ -263,10 +266,10 @@ static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data)
for (i = 0; i < data->blocks; i++) { if (data->flags & MMC_DATA_READ) - ret = tmio_sd_pio_read_one_block(dev, dest, + ret = tmio_sd_pio_read_one_block(dev, cmd, dest, data->blocksize); else - ret = tmio_sd_pio_write_one_block(dev, src, + ret = tmio_sd_pio_write_one_block(dev, cmd, src, data->blocksize); if (ret) return ret; @@ -468,8 +471,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, cmd->cmdidx, tmp, cmd->cmdarg); tmio_sd_writel(priv, tmp, TMIO_SD_CMD);
- ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1, - TMIO_SD_INFO1_RSP); + ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1, + TMIO_SD_INFO1_RSP); if (ret) return ret;
@@ -497,17 +500,17 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, tmio_sd_addr_is_dmaable(data->src)) ret = tmio_sd_dma_xfer(dev, data); else - ret = tmio_sd_pio_xfer(dev, data); + ret = tmio_sd_pio_xfer(dev, cmd, data); if (ret) return ret;
- ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1, - TMIO_SD_INFO1_CMP); + ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1, + TMIO_SD_INFO1_CMP); if (ret) return ret; }
- return tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, + return tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2, TMIO_SD_INFO2_SCLKDIVEN); }

On Thu, Nov 1, 2018 at 2:22 AM Marek Vasut marek.vasut@gmail.com wrote:
In case the controller performs card tuning, that is, sends MMC command 19 or 21, silence possible CRC error warning prints. The warnings are bound to happen, since the tuning will fail for some settings while searching for the optimal configuration of the bus and that is perfectly OK.
This patch passes around the MMC command structure and adds check into tmio_sd_check_error() to avoid printing CRC error warning when the tuning happens.
Make sense, but another solution might be to delete the message entirely, or to turn it into a debug message.
FWIW,
commit 61f2e5ee12895a2bdaeac8dd13e8d7f50ca7e375 Author: Masahiro Yamada yamada.masahiro@socionext.com Date: Sat Dec 30 02:00:12 2017 +0900
mmc: sdhci: change data transfer failure into debug message
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
drivers/mmc/tmio-common.c | 45 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 8e83584e57..8e1bcd7ed5 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -95,7 +95,7 @@ static void __dma_unmap_single(dma_addr_t addr, size_t size, invalidate_dcache_range(addr, addr + size); }
-static int tmio_sd_check_error(struct udevice *dev) +static int tmio_sd_check_error(struct udevice *dev, struct mmc_cmd *cmd) { struct tmio_sd_priv *priv = dev_get_priv(dev); u32 info2 = tmio_sd_readl(priv, TMIO_SD_INFO2); @@ -116,7 +116,9 @@ static int tmio_sd_check_error(struct udevice *dev)
if (info2 & (TMIO_SD_INFO2_ERR_END | TMIO_SD_INFO2_ERR_CRC | TMIO_SD_INFO2_ERR_IDX)) {
dev_err(dev, "communication out of sync\n");
if ((cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK) &&
(cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK_HS200))
dev_err(dev, "communication out of sync\n"); return -EILSEQ; }
@@ -129,8 +131,8 @@ static int tmio_sd_check_error(struct udevice *dev) return 0; }
-static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg,
u32 flag)
+static int tmio_sd_wait_for_irq(struct udevice *dev, struct mmc_cmd *cmd,
unsigned int reg, u32 flag)
{ struct tmio_sd_priv *priv = dev_get_priv(dev); long wait = 1000000; @@ -142,7 +144,7 @@ static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg, return -ETIMEDOUT; }
ret = tmio_sd_check_error(dev);
ret = tmio_sd_check_error(dev, cmd); if (ret) return ret;
@@ -178,15 +180,15 @@ tmio_pio_read_fifo(64, q) tmio_pio_read_fifo(32, l) tmio_pio_read_fifo(16, w)
-static int tmio_sd_pio_read_one_block(struct udevice *dev, char *pbuf,
uint blocksize)
+static int tmio_sd_pio_read_one_block(struct udevice *dev, struct mmc_cmd *cmd,
char *pbuf, uint blocksize)
{ struct tmio_sd_priv *priv = dev_get_priv(dev); int ret;
/* wait until the buffer is filled with data */
ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
TMIO_SD_INFO2_BRE);
ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2,
TMIO_SD_INFO2_BRE); if (ret) return ret;
@@ -231,15 +233,15 @@ tmio_pio_write_fifo(64, q) tmio_pio_write_fifo(32, l) tmio_pio_write_fifo(16, w)
-static int tmio_sd_pio_write_one_block(struct udevice *dev, +static int tmio_sd_pio_write_one_block(struct udevice *dev, struct mmc_cmd *cmd, const char *pbuf, uint blocksize) { struct tmio_sd_priv *priv = dev_get_priv(dev); int ret;
/* wait until the buffer becomes empty */
ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
TMIO_SD_INFO2_BWE);
ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2,
TMIO_SD_INFO2_BWE); if (ret) return ret;
@@ -255,7 +257,8 @@ static int tmio_sd_pio_write_one_block(struct udevice *dev, return 0; }
-static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data) +static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{ const char *src = data->src; char *dest = data->dest; @@ -263,10 +266,10 @@ static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data)
for (i = 0; i < data->blocks; i++) { if (data->flags & MMC_DATA_READ)
ret = tmio_sd_pio_read_one_block(dev, dest,
ret = tmio_sd_pio_read_one_block(dev, cmd, dest, data->blocksize); else
ret = tmio_sd_pio_write_one_block(dev, src,
ret = tmio_sd_pio_write_one_block(dev, cmd, src, data->blocksize); if (ret) return ret;
@@ -468,8 +471,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, cmd->cmdidx, tmp, cmd->cmdarg); tmio_sd_writel(priv, tmp, TMIO_SD_CMD);
ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1,
TMIO_SD_INFO1_RSP);
ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1,
TMIO_SD_INFO1_RSP); if (ret) return ret;
@@ -497,17 +500,17 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, tmio_sd_addr_is_dmaable(data->src)) ret = tmio_sd_dma_xfer(dev, data); else
ret = tmio_sd_pio_xfer(dev, data);
ret = tmio_sd_pio_xfer(dev, cmd, data); if (ret) return ret;
ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1,
TMIO_SD_INFO1_CMP);
ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1,
TMIO_SD_INFO1_CMP); if (ret) return ret; }
return tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2,
return tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2, TMIO_SD_INFO2_SCLKDIVEN);
}
-- 2.18.0
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
-- Best Regards Masahiro Yamada

On 11/01/2018 12:42 PM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 2:22 AM Marek Vasut marek.vasut@gmail.com wrote:
In case the controller performs card tuning, that is, sends MMC command 19 or 21, silence possible CRC error warning prints. The warnings are bound to happen, since the tuning will fail for some settings while searching for the optimal configuration of the bus and that is perfectly OK.
This patch passes around the MMC command structure and adds check into tmio_sd_check_error() to avoid printing CRC error warning when the tuning happens.
Make sense, but another solution might be to delete the message entirely, or to turn it into a debug message.
I'd like to see errors when they happen though, so what do you think about this patch ?

On Thu, Nov 1, 2018 at 9:14 PM Marek Vasut marek.vasut@gmail.com wrote:
On 11/01/2018 12:42 PM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 2:22 AM Marek Vasut marek.vasut@gmail.com wrote:
In case the controller performs card tuning, that is, sends MMC command 19 or 21, silence possible CRC error warning prints. The warnings are bound to happen, since the tuning will fail for some settings while searching for the optimal configuration of the bus and that is perfectly OK.
This patch passes around the MMC command structure and adds check into tmio_sd_check_error() to avoid printing CRC error warning when the tuning happens.
Make sense, but another solution might be to delete the message entirely, or to turn it into a debug message.
I'd like to see errors when they happen though, so what do you think about this patch ?
I am fine if you want to go with this patch.

On 11/02/2018 04:59 AM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 9:14 PM Marek Vasut marek.vasut@gmail.com wrote:
On 11/01/2018 12:42 PM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 2:22 AM Marek Vasut marek.vasut@gmail.com wrote:
In case the controller performs card tuning, that is, sends MMC command 19 or 21, silence possible CRC error warning prints. The warnings are bound to happen, since the tuning will fail for some settings while searching for the optimal configuration of the bus and that is perfectly OK.
This patch passes around the MMC command structure and adds check into tmio_sd_check_error() to avoid printing CRC error warning when the tuning happens.
Make sense, but another solution might be to delete the message entirely, or to turn it into a debug message.
I'd like to see errors when they happen though, so what do you think about this patch ?
I am fine if you want to go with this patch.
OK, thanks !

Add check to avoid touching the SCC tuning registers in case the IP doesn't support them or if the support isn't in place yet.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/renesas-sdhi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 1590f496d7..6b5871a0ae 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -294,7 +294,8 @@ static int renesas_sdhi_set_ios(struct udevice *dev) #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) struct tmio_sd_priv *priv = dev_get_priv(dev);
- renesas_sdhi_reset_tuning(priv); + if (priv->caps & TMIO_SD_CAP_RCAR_UHS) + renesas_sdhi_reset_tuning(priv); #endif
return ret; @@ -371,7 +372,7 @@ static int renesas_sdhi_probe(struct udevice *dev)
ret = tmio_sd_probe(dev, quirks); #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) - if (!ret) + if (!ret && (priv->caps & TMIO_SD_CAP_RCAR_UHS)) renesas_sdhi_reset_tuning(priv); #endif return ret;

Make sure to clear HS400 configuration when reseting the SCC block.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/renesas-sdhi.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 6b5871a0ae..2949c517cb 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -34,6 +34,8 @@ #define RENESAS_SDHI_SCC_RVSREQ_RVSERR BIT(2) #define RENESAS_SDHI_SCC_SMPCMP 0x818 #define RENESAS_SDHI_SCC_TMPPORT2 0x81c +#define RENESAS_SDHI_SCC_TMPPORT2_HS400EN BIT(31) +#define RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL BIT(4)
#define RENESAS_SDHI_MAX_TAP 3
@@ -90,6 +92,11 @@ static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv) reg &= ~RENESAS_SDHI_SCC_CKSEL_DTSEL; tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL);
+ reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_TMPPORT2); + reg &= ~(RENESAS_SDHI_SCC_TMPPORT2_HS400EN | + RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL); + tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2); + reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL); reg |= TMIO_SD_CLKCTL_SCLKEN; tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);

When the bus switches to 1.8V mode of operation, it is necessary to verify that the card correctly initiated and completed the voltage switch. This is done by reading out the state of DATA0 line.
This patch implement support for reading out the state of the DATA0 line, so the MMC core code can correctly switch to 1.8V mode.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/renesas-sdhi.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 2949c517cb..e6e6fca061 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -308,13 +308,38 @@ static int renesas_sdhi_set_ios(struct udevice *dev) return ret; }
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) +static int renesas_sdhi_wait_dat0(struct udevice *dev, int state, int timeout) +{ + int ret = -ETIMEDOUT; + bool dat0_high; + bool target_dat0_high = !!state; + struct tmio_sd_priv *priv = dev_get_priv(dev); + + timeout = DIV_ROUND_UP(timeout, 10); /* check every 10 us. */ + while (timeout--) { + dat0_high = !!(tmio_sd_readl(priv, TMIO_SD_INFO2) & TMIO_SD_INFO2_DAT0); + if (dat0_high == target_dat0_high) { + ret = 0; + break; + } + udelay(10); + } + + return ret; +} +#endif + static const struct dm_mmc_ops renesas_sdhi_ops = { .send_cmd = tmio_sd_send_cmd, .set_ios = renesas_sdhi_set_ios, .get_cd = tmio_sd_get_cd, -#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) .execute_tuning = renesas_sdhi_execute_tuning, #endif +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + .wait_dat0 = renesas_sdhi_wait_dat0, +#endif };
#define RENESAS_GEN2_QUIRKS TMIO_SD_CAP_RCAR_GEN2

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 e6e6fca061..813cf8749b 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -292,9 +292,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);

It is perfectly fine to write th DTCNTL TAP count and enable the SCC sampling clock operation in the same write.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com --- drivers/mmc/renesas-sdhi.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 813cf8749b..05a100754a 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -51,12 +51,9 @@ static unsigned int renesas_sdhi_init_tuning(struct tmio_sd_priv *priv) tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
/* Set sampling clock selection range */ - tmio_sd_writel(priv, 0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT, - RENESAS_SDHI_SCC_DTCNTL); - - reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_DTCNTL); - reg |= RENESAS_SDHI_SCC_DTCNTL_TAPEN; - tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_DTCNTL); + tmio_sd_writel(priv, (0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) | + RENESAS_SDHI_SCC_DTCNTL_TAPEN, + RENESAS_SDHI_SCC_DTCNTL);
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL); reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL;

On Thu, Nov 1, 2018 at 2:21 AM Marek Vasut marek.vasut@gmail.com wrote:
The SD UHS SDR12, SDR25, SDR50, SDR104, DDR50 and MMC HS200, HS400 modes all use 1.8V signaling, while all the legacy modes use 3.3V signaling. While there are extra modes which use 1.2V signaling, the existing hardware does not support those.
Simplify the pinmux such that 3.3V signaling implies legacy mode pinmux and the rest implies UHS mode pinmux. This prevents the massive case statement from growing further. Moreover, it fixes an edge case where during SD 1.8V switch, the bus mode is still set to default while the signaling is already set to 1.8V, which results in an attempt to communicate with a 1.8V card using pins in 3.3V mode and thus communication failure.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
drivers/mmc/tmio-common.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 138de59470..5f927c6150 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -622,26 +622,10 @@ static void tmio_sd_set_pins(struct udevice *dev) #endif
#ifdef CONFIG_PINCTRL
switch (mmc->selected_mode) {
case MMC_LEGACY:
case SD_LEGACY:
case MMC_HS:
case SD_HS:
case MMC_HS_52:
case MMC_DDR_52:
pinctrl_select_state(dev, "default");
break;
case UHS_SDR12:
case UHS_SDR25:
case UHS_SDR50:
case UHS_DDR50:
case UHS_SDR104:
case MMC_HS_200:
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) pinctrl_select_state(dev, "state_uhs");
break;
default:
break;
}
else
pinctrl_select_state(dev, "default");
#endif }
Looks a nice clean-up although the current code is already screwed up, I guess.
"state_uhs" is Renesas-specific DT binding while it is sitting in the common code.
-- Best Regards Masahiro Yamada

On 11/01/2018 12:38 PM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 2:21 AM Marek Vasut marek.vasut@gmail.com wrote:
The SD UHS SDR12, SDR25, SDR50, SDR104, DDR50 and MMC HS200, HS400 modes all use 1.8V signaling, while all the legacy modes use 3.3V signaling. While there are extra modes which use 1.2V signaling, the existing hardware does not support those.
Simplify the pinmux such that 3.3V signaling implies legacy mode pinmux and the rest implies UHS mode pinmux. This prevents the massive case statement from growing further. Moreover, it fixes an edge case where during SD 1.8V switch, the bus mode is still set to default while the signaling is already set to 1.8V, which results in an attempt to communicate with a 1.8V card using pins in 3.3V mode and thus communication failure.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
drivers/mmc/tmio-common.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 138de59470..5f927c6150 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -622,26 +622,10 @@ static void tmio_sd_set_pins(struct udevice *dev) #endif
#ifdef CONFIG_PINCTRL
switch (mmc->selected_mode) {
case MMC_LEGACY:
case SD_LEGACY:
case MMC_HS:
case SD_HS:
case MMC_HS_52:
case MMC_DDR_52:
pinctrl_select_state(dev, "default");
break;
case UHS_SDR12:
case UHS_SDR25:
case UHS_SDR50:
case UHS_DDR50:
case UHS_SDR104:
case MMC_HS_200:
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) pinctrl_select_state(dev, "state_uhs");
break;
default:
break;
}
else
pinctrl_select_state(dev, "default");
#endif }
Looks a nice clean-up although the current code is already screwed up, I guess.
"state_uhs" is Renesas-specific DT binding while it is sitting in the common code.
Is there any socionext device which supports 1V8 signaling with this core ?

On Thu, Nov 1, 2018 at 9:14 PM Marek Vasut marek.vasut@gmail.com wrote:
On 11/01/2018 12:38 PM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 2:21 AM Marek Vasut marek.vasut@gmail.com wrote:
The SD UHS SDR12, SDR25, SDR50, SDR104, DDR50 and MMC HS200, HS400 modes all use 1.8V signaling, while all the legacy modes use 3.3V signaling. While there are extra modes which use 1.2V signaling, the existing hardware does not support those.
Simplify the pinmux such that 3.3V signaling implies legacy mode pinmux and the rest implies UHS mode pinmux. This prevents the massive case statement from growing further. Moreover, it fixes an edge case where during SD 1.8V switch, the bus mode is still set to default while the signaling is already set to 1.8V, which results in an attempt to communicate with a 1.8V card using pins in 3.3V mode and thus communication failure.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
drivers/mmc/tmio-common.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 138de59470..5f927c6150 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -622,26 +622,10 @@ static void tmio_sd_set_pins(struct udevice *dev) #endif
#ifdef CONFIG_PINCTRL
switch (mmc->selected_mode) {
case MMC_LEGACY:
case SD_LEGACY:
case MMC_HS:
case SD_HS:
case MMC_HS_52:
case MMC_DDR_52:
pinctrl_select_state(dev, "default");
break;
case UHS_SDR12:
case UHS_SDR25:
case UHS_SDR50:
case UHS_DDR50:
case UHS_SDR104:
case MMC_HS_200:
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) pinctrl_select_state(dev, "state_uhs");
break;
default:
break;
}
else
pinctrl_select_state(dev, "default");
#endif }
Looks a nice clean-up although the current code is already screwed up, I guess.
"state_uhs" is Renesas-specific DT binding while it is sitting in the common code.
Is there any socionext device which supports 1V8 signaling with this core ?
Yes.

On 11/02/2018 04:58 AM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 9:14 PM Marek Vasut marek.vasut@gmail.com wrote:
On 11/01/2018 12:38 PM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 2:21 AM Marek Vasut marek.vasut@gmail.com wrote:
The SD UHS SDR12, SDR25, SDR50, SDR104, DDR50 and MMC HS200, HS400 modes all use 1.8V signaling, while all the legacy modes use 3.3V signaling. While there are extra modes which use 1.2V signaling, the existing hardware does not support those.
Simplify the pinmux such that 3.3V signaling implies legacy mode pinmux and the rest implies UHS mode pinmux. This prevents the massive case statement from growing further. Moreover, it fixes an edge case where during SD 1.8V switch, the bus mode is still set to default while the signaling is already set to 1.8V, which results in an attempt to communicate with a 1.8V card using pins in 3.3V mode and thus communication failure.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
drivers/mmc/tmio-common.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 138de59470..5f927c6150 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -622,26 +622,10 @@ static void tmio_sd_set_pins(struct udevice *dev) #endif
#ifdef CONFIG_PINCTRL
switch (mmc->selected_mode) {
case MMC_LEGACY:
case SD_LEGACY:
case MMC_HS:
case SD_HS:
case MMC_HS_52:
case MMC_DDR_52:
pinctrl_select_state(dev, "default");
break;
case UHS_SDR12:
case UHS_SDR25:
case UHS_SDR50:
case UHS_DDR50:
case UHS_SDR104:
case MMC_HS_200:
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) pinctrl_select_state(dev, "state_uhs");
break;
default:
break;
}
else
pinctrl_select_state(dev, "default");
#endif }
Looks a nice clean-up although the current code is already screwed up, I guess.
"state_uhs" is Renesas-specific DT binding while it is sitting in the common code.
Is there any socionext device which supports 1V8 signaling with this core ?
Yes.
You think I can get one ? :)
btw are you OK if I queue up patch 1,7,8 already for this cycle, as they are fixes ? I'd also like to pick 4 and 6 if you don't mind?

On Fri, Nov 2, 2018 at 11:29 PM Marek Vasut marek.vasut@gmail.com wrote:
On 11/02/2018 04:58 AM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 9:14 PM Marek Vasut marek.vasut@gmail.com wrote:
On 11/01/2018 12:38 PM, Masahiro Yamada wrote:
On Thu, Nov 1, 2018 at 2:21 AM Marek Vasut marek.vasut@gmail.com wrote:
The SD UHS SDR12, SDR25, SDR50, SDR104, DDR50 and MMC HS200, HS400 modes all use 1.8V signaling, while all the legacy modes use 3.3V signaling. While there are extra modes which use 1.2V signaling, the existing hardware does not support those.
Simplify the pinmux such that 3.3V signaling implies legacy mode pinmux and the rest implies UHS mode pinmux. This prevents the massive case statement from growing further. Moreover, it fixes an edge case where during SD 1.8V switch, the bus mode is still set to default while the signaling is already set to 1.8V, which results in an attempt to communicate with a 1.8V card using pins in 3.3V mode and thus communication failure.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Masahiro Yamada yamada.masahiro@socionext.com
drivers/mmc/tmio-common.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 138de59470..5f927c6150 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -622,26 +622,10 @@ static void tmio_sd_set_pins(struct udevice *dev) #endif
#ifdef CONFIG_PINCTRL
switch (mmc->selected_mode) {
case MMC_LEGACY:
case SD_LEGACY:
case MMC_HS:
case SD_HS:
case MMC_HS_52:
case MMC_DDR_52:
pinctrl_select_state(dev, "default");
break;
case UHS_SDR12:
case UHS_SDR25:
case UHS_SDR50:
case UHS_DDR50:
case UHS_SDR104:
case MMC_HS_200:
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) pinctrl_select_state(dev, "state_uhs");
break;
default:
break;
}
else
pinctrl_select_state(dev, "default");
#endif }
Looks a nice clean-up although the current code is already screwed up, I guess.
"state_uhs" is Renesas-specific DT binding while it is sitting in the common code.
Is there any socionext device which supports 1V8 signaling with this core ?
Yes.
You think I can get one ? :)
btw are you OK if I queue up patch 1,7,8 already for this cycle, as they are fixes ? I'd also like to pick 4 and 6 if you don't mind?
OK, go ahead.
participants (2)
-
Marek Vasut
-
Masahiro Yamada