mmc: renesas_sdhi: do hard reset if possible
authorWolfram Sang <wsa+renesas@sang-engineering.com>
Wed, 17 Mar 2021 09:16:22 +0000 (10:16 +0100)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 30 Mar 2021 09:42:05 +0000 (11:42 +0200)
All recent SDHI instances can be reset via the reset controller. If one
is found, use it instead of the open coded reset. This is to get a
future-proof sane reset state.

Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Link: https://lore.kernel.org/r/20210317091622.31890-4-wsa+renesas@sang-engineering.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/Kconfig
drivers/mmc/host/renesas_sdhi.h
drivers/mmc/host/renesas_sdhi_core.c

index e911eb5..a4d4c75 100644 (file)
@@ -708,6 +708,7 @@ config MMC_SDHI
        tristate "Renesas SDHI SD/SDIO controller support"
        depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
        select MMC_TMIO_CORE
+       select RESET_CONTROLLER if ARCH_RENESAS
        help
          This provides support for the SDHI SD/SDIO controller found in
          Renesas SuperH, ARM and ARM64 based SoCs
index cb962c7..53eded8 100644 (file)
@@ -70,6 +70,8 @@ struct renesas_sdhi {
        DECLARE_BITMAP(smpcmp, BITS_PER_LONG);
        unsigned int tap_num;
        unsigned int tap_set;
+
+       struct reset_control *rstc;
 };
 
 #define host_to_priv(host) \
index db75382..d36181b 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
@@ -32,6 +33,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/regulator/consumer.h>
+#include <linux/reset.h>
 #include <linux/sh_dma.h>
 #include <linux/slab.h>
 #include <linux/sys_soc.h>
@@ -572,10 +574,19 @@ static void renesas_sdhi_scc_reset(struct tmio_mmc_host *host, struct renesas_sd
 static void renesas_sdhi_reset(struct tmio_mmc_host *host)
 {
        struct renesas_sdhi *priv = host_to_priv(host);
+       int ret;
        u16 val;
 
-       if (priv->scc_ctl)
+       if (priv->rstc) {
+               reset_control_reset(priv->rstc);
+               /* Unknown why but without polling reset status, it will hang */
+               read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100,
+                                 false, priv->rstc);
+               priv->needs_adjust_hs400 = false;
+               renesas_sdhi_set_clock(host, host->clk_cache);
+       } else if (priv->scc_ctl) {
                renesas_sdhi_scc_reset(host, priv);
+       }
 
        sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, TMIO_MASK_ALL_RCAR2);
 
@@ -1081,6 +1092,10 @@ int renesas_sdhi_probe(struct platform_device *pdev,
        if (ret)
                goto efree;
 
+       priv->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+       if (IS_ERR(priv->rstc))
+               return PTR_ERR(priv->rstc);
+
        ver = sd_ctrl_read16(host, CTL_VERSION);
        /* GEN2_SDR104 is first known SDHI to use 32bit block count */
        if (ver < SDHI_VER_GEN2_SDR104 && mmc_data->max_blk_count > U16_MAX)