The Renesas RZ/N1 SoC contains a MMC controller using the Arasan IP.
It is supported by the exisitng driver, with the following changes:

1) Multiple clocks need to be enabled. This is handled using
   clk_get_bulk() and clock_enable_bulk().

2) It is necessary to defer the sdhci_probe(), similar to what is
   done in drivers/mmc/am654_sdhci.c

Signed-off-by: Ralph Siemsen <[email protected]>
---
 drivers/mmc/Kconfig      |  2 +-
 drivers/mmc/zynq_sdhci.c | 39 ++++++++++++++++++++++++++++++++-------
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index f9f7aa5cf97..7649fc8f53f 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -778,7 +778,7 @@ config TEGRA124_MMC_DISABLE_EXT_LOOPBACK
 config MMC_SDHCI_ZYNQ
        bool "Arasan SDHCI controller support"
        depends on OF_CONTROL
-       depends on ARCH_VERSAL || ARCH_VERSAL_NET || ARCH_VERSAL2 || ARCH_ZYNQ 
|| ARCH_ZYNQMP
+       depends on ARCH_RENESAS || ARCH_VERSAL || ARCH_VERSAL_NET || 
ARCH_VERSAL2 || ARCH_ZYNQ || ARCH_ZYNQMP
        depends on MMC_SDHCI
        help
          Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs 
platform
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index eda95b72f49..351e7d56569 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -1012,6 +1012,31 @@ static const struct sdhci_ops arasan_ops = {
        .config_dll = &arasan_sdhci_config_dll,
 #endif
 };
+
+#elif defined(CONFIG_ARCH_RENESAS)
+/*
+ * It is unknown whether the IP in RZ/N1 supports these clock phase
+ * adjustments. The devicetree does not include these properties.
+ * So this is a no-op for now.
+ */
+static void arasan_dt_parse_clk_phases(struct udevice *dev)
+{
+}
+
+/*
+ * Renesas RZ/N1 needs deferred sdhci_probe(), otherwise the
+ * first CMD_00 fails with "Timeout for status update"
+ */
+static int arasan_sdhci_deferred_probe(struct sdhci_host *host)
+{
+       struct udevice *dev = host->mmc->dev;
+
+       return sdhci_probe(dev);
+}
+
+static const struct sdhci_ops arasan_ops = {
+       .deferred_probe = arasan_sdhci_deferred_probe,
+};
 #endif
 
 #if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE)
@@ -1110,7 +1135,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
        struct arasan_sdhci_priv *priv = dev_get_priv(dev);
        struct sdhci_host *host;
-       struct clk clk;
+       struct clk_bulk clks;
        unsigned long clock;
        int ret;
 
@@ -1152,13 +1177,13 @@ static int arasan_sdhci_probe(struct udevice *dev)
                }
        }
 
-       ret = clk_get_by_index(dev, 0, &clk);
+       ret = clk_get_bulk(dev, &clks);
        if (ret < 0) {
-               dev_err(dev, "failed to get clock\n");
+               dev_err(dev, "failed to get clock(s)\n");
                return ret;
        }
 
-       clock = clk_get_rate(&clk);
+       clock = clk_get_rate(&clks.clks[0]);
        if (IS_ERR_VALUE(clock)) {
                dev_err(dev, "failed to get rate\n");
                return clock;
@@ -1166,9 +1191,9 @@ static int arasan_sdhci_probe(struct udevice *dev)
 
        dev_dbg(dev, "%s: CLK %ld\n", __func__, clock);
 
-       ret = clk_enable(&clk);
+       ret = clk_enable_bulk(&clks);
        if (ret) {
-               dev_err(dev, "failed to enable clock\n");
+               dev_err(dev, "failed to enable clock(s)\n");
                return ret;
        }
 
@@ -1239,7 +1264,7 @@ static int arasan_sdhci_of_to_plat(struct udevice *dev)
        priv->host->name = dev->name;
 
 #if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || 
defined(CONFIG_ARCH_VERSAL_NET) || \
-    defined(CONFIG_ARCH_VERSAL2)
+    defined(CONFIG_ARCH_VERSAL2) || defined(CONFIG_ARCH_RENESAS)
        priv->host->ops = &arasan_ops;
        arasan_dt_parse_clk_phases(dev);
 #endif

-- 
2.55.0

Reply via email to