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
