diff mbox

[U-Boot,1/3] mmc: sh_sdhi: Add DM and DT probing support

Message ID 20170721212256.25961-1-marek.vasut+renesas@gmail.com
State Accepted
Commit d1c18ca1103956087f303cf6a28fc84ba5b25922
Delegated to: Jaehoon Chung
Headers show

Commit Message

Marek Vasut July 21, 2017, 9:22 p.m. UTC
Add MMC DM and DT probing support into the SH SDHI driver.
This patch abstracts out the common bits of the send command
and set ios functions, so they can be used both by DM and non
DM setups and adds the DM probe support.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
Cc: Jaehoon Chung <jh80.chung@samsung.com>
---
 drivers/mmc/sh_sdhi.c | 165 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 145 insertions(+), 20 deletions(-)

Comments

Nobuhiro Iwamatsu Aug. 2, 2017, 11:17 p.m. UTC | #1
Hi,

2017-07-22 6:22 GMT+09:00 Marek Vasut <marek.vasut@gmail.com>:
> Add MMC DM and DT probing support into the SH SDHI driver.
> This patch abstracts out the common bits of the send command
> and set ios functions, so they can be used both by DM and non
> DM setups and adds the DM probe support.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> Cc: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
> Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
> Cc: Jaehoon Chung <jh80.chung@samsung.com>

Reviewed-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>

> ---
>  drivers/mmc/sh_sdhi.c | 165 ++++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 145 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
> index d181b63905..fd710399b6 100644
> --- a/drivers/mmc/sh_sdhi.c
> +++ b/drivers/mmc/sh_sdhi.c
> @@ -13,15 +13,18 @@
>  #include <common.h>
>  #include <malloc.h>
>  #include <mmc.h>
> +#include <dm.h>
>  #include <linux/errno.h>
> -#include <asm/io.h>
> +#include <linux/compat.h>
> +#include <linux/io.h>
> +#include <linux/sizes.h>
>  #include <asm/arch/rmobile.h>
>  #include <asm/arch/sh_sdhi.h>
>
>  #define DRIVER_NAME "sh-sdhi"
>
>  struct sh_sdhi_host {
> -       unsigned long addr;
> +       void __iomem *addr;
>         int ch;
>         int bus_shift;
>         unsigned long quirks;
> @@ -50,11 +53,6 @@ static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
>         return readw(host->addr + (reg << host->bus_shift));
>  }
>
> -static void *mmc_priv(struct mmc *mmc)
> -{
> -       return (void *)mmc->priv;
> -}
> -
>  static void sh_sdhi_detect(struct sh_sdhi_host *host)
>  {
>         sh_sdhi_writew(host, SDHI_OPTION,
> @@ -634,23 +632,17 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
>         return ret;
>  }
>
> -static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
> -                       struct mmc_data *data)
> +static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
> +                                  struct mmc_cmd *cmd, struct mmc_data *data)
>  {
> -       struct sh_sdhi_host *host = mmc_priv(mmc);
> -       int ret;
> -
>         host->sd_error = 0;
>
> -       ret = sh_sdhi_start_cmd(host, data, cmd);
> -
> -       return ret;
> +       return sh_sdhi_start_cmd(host, data, cmd);
>  }
>
> -static int sh_sdhi_set_ios(struct mmc *mmc)
> +static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc)
>  {
>         int ret;
> -       struct sh_sdhi_host *host = mmc_priv(mmc);
>
>         ret = sh_sdhi_clock_control(host, mmc->clock);
>         if (ret)
> @@ -674,9 +666,8 @@ static int sh_sdhi_set_ios(struct mmc *mmc)
>         return 0;
>  }
>
> -static int sh_sdhi_initialize(struct mmc *mmc)
> +static int sh_sdhi_initialize_common(struct sh_sdhi_host *host)
>  {
> -       struct sh_sdhi_host *host = mmc_priv(mmc);
>         int ret = sh_sdhi_sync_reset(host);
>
>         sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
> @@ -692,6 +683,34 @@ static int sh_sdhi_initialize(struct mmc *mmc)
>         return ret;
>  }
>
> +#ifndef CONFIG_DM_MMC
> +static void *mmc_priv(struct mmc *mmc)
> +{
> +       return (void *)mmc->priv;
> +}
> +
> +static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
> +                           struct mmc_data *data)
> +{
> +       struct sh_sdhi_host *host = mmc_priv(mmc);
> +
> +       return sh_sdhi_send_cmd_common(host, cmd, data);
> +}
> +
> +static int sh_sdhi_set_ios(struct mmc *mmc)
> +{
> +       struct sh_sdhi_host *host = mmc_priv(mmc);
> +
> +       return sh_sdhi_set_ios_common(host, mmc);
> +}
> +
> +static int sh_sdhi_initialize(struct mmc *mmc)
> +{
> +       struct sh_sdhi_host *host = mmc_priv(mmc);
> +
> +       return sh_sdhi_initialize_common(host);
> +}
> +
>  static const struct mmc_ops sh_sdhi_ops = {
>         .send_cmd       = sh_sdhi_send_cmd,
>         .set_ios        = sh_sdhi_set_ios,
> @@ -743,7 +762,7 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
>         }
>
>         host->ch = ch;
> -       host->addr = addr;
> +       host->addr = (void __iomem *)addr;
>         host->quirks = quirks;
>
>         if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
> @@ -757,3 +776,109 @@ error:
>                 free(host);
>         return ret;
>  }
> +
> +#else
> +
> +struct sh_sdhi_plat {
> +       struct mmc_config cfg;
> +       struct mmc mmc;
> +};
> +
> +int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
> +                       struct mmc_data *data)
> +{
> +       struct sh_sdhi_host *host = dev_get_priv(dev);
> +
> +       return sh_sdhi_send_cmd_common(host, cmd, data);
> +}
> +
> +int sh_sdhi_dm_set_ios(struct udevice *dev)
> +{
> +       struct sh_sdhi_host *host = dev_get_priv(dev);
> +       struct mmc *mmc = mmc_get_mmc_dev(dev);
> +
> +       return sh_sdhi_set_ios_common(host, mmc);
> +}
> +
> +static const struct dm_mmc_ops sh_sdhi_dm_ops = {
> +       .send_cmd       = sh_sdhi_dm_send_cmd,
> +       .set_ios        = sh_sdhi_dm_set_ios,
> +};
> +
> +static int sh_sdhi_dm_bind(struct udevice *dev)
> +{
> +       struct sh_sdhi_plat *plat = dev_get_platdata(dev);
> +
> +       return mmc_bind(dev, &plat->mmc, &plat->cfg);
> +}
> +
> +static int sh_sdhi_dm_probe(struct udevice *dev)
> +{
> +       struct sh_sdhi_plat *plat = dev_get_platdata(dev);
> +       struct sh_sdhi_host *host = dev_get_priv(dev);
> +       struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
> +       const u32 quirks = dev_get_driver_data(dev);
> +       fdt_addr_t base;
> +
> +       base = devfdt_get_addr(dev);
> +       if (base == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       host->addr = devm_ioremap(dev, base, SZ_2K);
> +       if (!host->addr)
> +               return -ENOMEM;
> +
> +       host->quirks = quirks;
> +
> +       if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
> +               host->bus_shift = 2;
> +       else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
> +               host->bus_shift = 1;
> +
> +       plat->cfg.name = dev->name;
> +       plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
> +
> +       switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
> +                              1)) {
> +       case 8:
> +               plat->cfg.host_caps |= MMC_MODE_8BIT;
> +               break;
> +       case 4:
> +               plat->cfg.host_caps |= MMC_MODE_4BIT;
> +               break;
> +       case 1:
> +               break;
> +       default:
> +               dev_err(dev, "Invalid \"bus-width\" value\n");
> +               return -EINVAL;
> +       }
> +
> +       sh_sdhi_initialize_common(host);
> +
> +       plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
> +       plat->cfg.f_min = CLKDEV_INIT;
> +       plat->cfg.f_max = CLKDEV_HS_DATA;
> +       plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
> +
> +       upriv->mmc = &plat->mmc;
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id sh_sdhi_sd_match[] = {
> +       { .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
> +       { .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
> +       { /* sentinel */ }
> +};
> +
> +U_BOOT_DRIVER(sh_sdhi_mmc) = {
> +       .name                   = "sh-sdhi-mmc",
> +       .id                     = UCLASS_MMC,
> +       .of_match               = sh_sdhi_sd_match,
> +       .bind                   = sh_sdhi_dm_bind,
> +       .probe                  = sh_sdhi_dm_probe,
> +       .priv_auto_alloc_size   = sizeof(struct sh_sdhi_host),
> +       .platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat),
> +       .ops                    = &sh_sdhi_dm_ops,
> +};
> +#endif
> --
> 2.11.0
>
Marek Vasut Aug. 5, 2017, 9:55 a.m. UTC | #2
On 08/03/2017 01:17 AM, Nobuhiro Iwamatsu wrote:
> Hi,
> 
> 2017-07-22 6:22 GMT+09:00 Marek Vasut <marek.vasut@gmail.com>:
>> Add MMC DM and DT probing support into the SH SDHI driver.
>> This patch abstracts out the common bits of the send command
>> and set ios functions, so they can be used both by DM and non
>> DM setups and adds the DM probe support.
>>
>> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
>> Cc: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
>> Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
>> Cc: Jaehoon Chung <jh80.chung@samsung.com>
> 
> Reviewed-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
> 

Thanks.

Jaehoon, can you pick those three patches, it's blocking some further
board-level cleanups I'd like to get into this release.
Jaehoon Chung Aug. 17, 2017, 5:38 a.m. UTC | #3
On 07/22/2017 06:22 AM, Marek Vasut wrote:
> Add MMC DM and DT probing support into the SH SDHI driver.
> This patch abstracts out the common bits of the send command
> and set ios functions, so they can be used both by DM and non
> DM setups and adds the DM probe support.
> 
> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> Cc: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
> Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
> Cc: Jaehoon Chung <jh80.chung@samsung.com>
> Reviewed-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>

Applied to u-boot-mmc. Sorry for late!

Best Regards,
Jaehoon Chung

> ---
>  drivers/mmc/sh_sdhi.c | 165 ++++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 145 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
> index d181b63905..fd710399b6 100644
> --- a/drivers/mmc/sh_sdhi.c
> +++ b/drivers/mmc/sh_sdhi.c
> @@ -13,15 +13,18 @@
>  #include <common.h>
>  #include <malloc.h>
>  #include <mmc.h>
> +#include <dm.h>
>  #include <linux/errno.h>
> -#include <asm/io.h>
> +#include <linux/compat.h>
> +#include <linux/io.h>
> +#include <linux/sizes.h>
>  #include <asm/arch/rmobile.h>
>  #include <asm/arch/sh_sdhi.h>
>  
>  #define DRIVER_NAME "sh-sdhi"
>  
>  struct sh_sdhi_host {
> -	unsigned long addr;
> +	void __iomem *addr;
>  	int ch;
>  	int bus_shift;
>  	unsigned long quirks;
> @@ -50,11 +53,6 @@ static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
>  	return readw(host->addr + (reg << host->bus_shift));
>  }
>  
> -static void *mmc_priv(struct mmc *mmc)
> -{
> -	return (void *)mmc->priv;
> -}
> -
>  static void sh_sdhi_detect(struct sh_sdhi_host *host)
>  {
>  	sh_sdhi_writew(host, SDHI_OPTION,
> @@ -634,23 +632,17 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
>  	return ret;
>  }
>  
> -static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
> -			struct mmc_data *data)
> +static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
> +				   struct mmc_cmd *cmd, struct mmc_data *data)
>  {
> -	struct sh_sdhi_host *host = mmc_priv(mmc);
> -	int ret;
> -
>  	host->sd_error = 0;
>  
> -	ret = sh_sdhi_start_cmd(host, data, cmd);
> -
> -	return ret;
> +	return sh_sdhi_start_cmd(host, data, cmd);
>  }
>  
> -static int sh_sdhi_set_ios(struct mmc *mmc)
> +static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc)
>  {
>  	int ret;
> -	struct sh_sdhi_host *host = mmc_priv(mmc);
>  
>  	ret = sh_sdhi_clock_control(host, mmc->clock);
>  	if (ret)
> @@ -674,9 +666,8 @@ static int sh_sdhi_set_ios(struct mmc *mmc)
>  	return 0;
>  }
>  
> -static int sh_sdhi_initialize(struct mmc *mmc)
> +static int sh_sdhi_initialize_common(struct sh_sdhi_host *host)
>  {
> -	struct sh_sdhi_host *host = mmc_priv(mmc);
>  	int ret = sh_sdhi_sync_reset(host);
>  
>  	sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
> @@ -692,6 +683,34 @@ static int sh_sdhi_initialize(struct mmc *mmc)
>  	return ret;
>  }
>  
> +#ifndef CONFIG_DM_MMC
> +static void *mmc_priv(struct mmc *mmc)
> +{
> +	return (void *)mmc->priv;
> +}
> +
> +static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
> +			    struct mmc_data *data)
> +{
> +	struct sh_sdhi_host *host = mmc_priv(mmc);
> +
> +	return sh_sdhi_send_cmd_common(host, cmd, data);
> +}
> +
> +static int sh_sdhi_set_ios(struct mmc *mmc)
> +{
> +	struct sh_sdhi_host *host = mmc_priv(mmc);
> +
> +	return sh_sdhi_set_ios_common(host, mmc);
> +}
> +
> +static int sh_sdhi_initialize(struct mmc *mmc)
> +{
> +	struct sh_sdhi_host *host = mmc_priv(mmc);
> +
> +	return sh_sdhi_initialize_common(host);
> +}
> +
>  static const struct mmc_ops sh_sdhi_ops = {
>  	.send_cmd       = sh_sdhi_send_cmd,
>  	.set_ios        = sh_sdhi_set_ios,
> @@ -743,7 +762,7 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
>  	}
>  
>  	host->ch = ch;
> -	host->addr = addr;
> +	host->addr = (void __iomem *)addr;
>  	host->quirks = quirks;
>  
>  	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
> @@ -757,3 +776,109 @@ error:
>  		free(host);
>  	return ret;
>  }
> +
> +#else
> +
> +struct sh_sdhi_plat {
> +	struct mmc_config cfg;
> +	struct mmc mmc;
> +};
> +
> +int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
> +			struct mmc_data *data)
> +{
> +	struct sh_sdhi_host *host = dev_get_priv(dev);
> +
> +	return sh_sdhi_send_cmd_common(host, cmd, data);
> +}
> +
> +int sh_sdhi_dm_set_ios(struct udevice *dev)
> +{
> +	struct sh_sdhi_host *host = dev_get_priv(dev);
> +	struct mmc *mmc = mmc_get_mmc_dev(dev);
> +
> +	return sh_sdhi_set_ios_common(host, mmc);
> +}
> +
> +static const struct dm_mmc_ops sh_sdhi_dm_ops = {
> +	.send_cmd	= sh_sdhi_dm_send_cmd,
> +	.set_ios	= sh_sdhi_dm_set_ios,
> +};
> +
> +static int sh_sdhi_dm_bind(struct udevice *dev)
> +{
> +	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
> +
> +	return mmc_bind(dev, &plat->mmc, &plat->cfg);
> +}
> +
> +static int sh_sdhi_dm_probe(struct udevice *dev)
> +{
> +	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
> +	struct sh_sdhi_host *host = dev_get_priv(dev);
> +	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
> +	const u32 quirks = dev_get_driver_data(dev);
> +	fdt_addr_t base;
> +
> +	base = devfdt_get_addr(dev);
> +	if (base == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	host->addr = devm_ioremap(dev, base, SZ_2K);
> +	if (!host->addr)
> +		return -ENOMEM;
> +
> +	host->quirks = quirks;
> +
> +	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
> +		host->bus_shift = 2;
> +	else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
> +		host->bus_shift = 1;
> +
> +	plat->cfg.name = dev->name;
> +	plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
> +
> +	switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
> +			       1)) {
> +	case 8:
> +		plat->cfg.host_caps |= MMC_MODE_8BIT;
> +		break;
> +	case 4:
> +		plat->cfg.host_caps |= MMC_MODE_4BIT;
> +		break;
> +	case 1:
> +		break;
> +	default:
> +		dev_err(dev, "Invalid \"bus-width\" value\n");
> +		return -EINVAL;
> +	}
> +
> +	sh_sdhi_initialize_common(host);
> +
> +	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
> +	plat->cfg.f_min = CLKDEV_INIT;
> +	plat->cfg.f_max = CLKDEV_HS_DATA;
> +	plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
> +
> +	upriv->mmc = &plat->mmc;
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id sh_sdhi_sd_match[] = {
> +	{ .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
> +	{ .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
> +	{ /* sentinel */ }
> +};
> +
> +U_BOOT_DRIVER(sh_sdhi_mmc) = {
> +	.name			= "sh-sdhi-mmc",
> +	.id			= UCLASS_MMC,
> +	.of_match		= sh_sdhi_sd_match,
> +	.bind			= sh_sdhi_dm_bind,
> +	.probe			= sh_sdhi_dm_probe,
> +	.priv_auto_alloc_size	= sizeof(struct sh_sdhi_host),
> +	.platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat),
> +	.ops			= &sh_sdhi_dm_ops,
> +};
> +#endif
>
diff mbox

Patch

diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
index d181b63905..fd710399b6 100644
--- a/drivers/mmc/sh_sdhi.c
+++ b/drivers/mmc/sh_sdhi.c
@@ -13,15 +13,18 @@ 
 #include <common.h>
 #include <malloc.h>
 #include <mmc.h>
+#include <dm.h>
 #include <linux/errno.h>
-#include <asm/io.h>
+#include <linux/compat.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
 #include <asm/arch/rmobile.h>
 #include <asm/arch/sh_sdhi.h>
 
 #define DRIVER_NAME "sh-sdhi"
 
 struct sh_sdhi_host {
-	unsigned long addr;
+	void __iomem *addr;
 	int ch;
 	int bus_shift;
 	unsigned long quirks;
@@ -50,11 +53,6 @@  static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
 	return readw(host->addr + (reg << host->bus_shift));
 }
 
-static void *mmc_priv(struct mmc *mmc)
-{
-	return (void *)mmc->priv;
-}
-
 static void sh_sdhi_detect(struct sh_sdhi_host *host)
 {
 	sh_sdhi_writew(host, SDHI_OPTION,
@@ -634,23 +632,17 @@  static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
 	return ret;
 }
 
-static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
-			struct mmc_data *data)
+static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
+				   struct mmc_cmd *cmd, struct mmc_data *data)
 {
-	struct sh_sdhi_host *host = mmc_priv(mmc);
-	int ret;
-
 	host->sd_error = 0;
 
-	ret = sh_sdhi_start_cmd(host, data, cmd);
-
-	return ret;
+	return sh_sdhi_start_cmd(host, data, cmd);
 }
 
-static int sh_sdhi_set_ios(struct mmc *mmc)
+static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc)
 {
 	int ret;
-	struct sh_sdhi_host *host = mmc_priv(mmc);
 
 	ret = sh_sdhi_clock_control(host, mmc->clock);
 	if (ret)
@@ -674,9 +666,8 @@  static int sh_sdhi_set_ios(struct mmc *mmc)
 	return 0;
 }
 
-static int sh_sdhi_initialize(struct mmc *mmc)
+static int sh_sdhi_initialize_common(struct sh_sdhi_host *host)
 {
-	struct sh_sdhi_host *host = mmc_priv(mmc);
 	int ret = sh_sdhi_sync_reset(host);
 
 	sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
@@ -692,6 +683,34 @@  static int sh_sdhi_initialize(struct mmc *mmc)
 	return ret;
 }
 
+#ifndef CONFIG_DM_MMC
+static void *mmc_priv(struct mmc *mmc)
+{
+	return (void *)mmc->priv;
+}
+
+static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+			    struct mmc_data *data)
+{
+	struct sh_sdhi_host *host = mmc_priv(mmc);
+
+	return sh_sdhi_send_cmd_common(host, cmd, data);
+}
+
+static int sh_sdhi_set_ios(struct mmc *mmc)
+{
+	struct sh_sdhi_host *host = mmc_priv(mmc);
+
+	return sh_sdhi_set_ios_common(host, mmc);
+}
+
+static int sh_sdhi_initialize(struct mmc *mmc)
+{
+	struct sh_sdhi_host *host = mmc_priv(mmc);
+
+	return sh_sdhi_initialize_common(host);
+}
+
 static const struct mmc_ops sh_sdhi_ops = {
 	.send_cmd       = sh_sdhi_send_cmd,
 	.set_ios        = sh_sdhi_set_ios,
@@ -743,7 +762,7 @@  int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
 	}
 
 	host->ch = ch;
-	host->addr = addr;
+	host->addr = (void __iomem *)addr;
 	host->quirks = quirks;
 
 	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
@@ -757,3 +776,109 @@  error:
 		free(host);
 	return ret;
 }
+
+#else
+
+struct sh_sdhi_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+			struct mmc_data *data)
+{
+	struct sh_sdhi_host *host = dev_get_priv(dev);
+
+	return sh_sdhi_send_cmd_common(host, cmd, data);
+}
+
+int sh_sdhi_dm_set_ios(struct udevice *dev)
+{
+	struct sh_sdhi_host *host = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+	return sh_sdhi_set_ios_common(host, mmc);
+}
+
+static const struct dm_mmc_ops sh_sdhi_dm_ops = {
+	.send_cmd	= sh_sdhi_dm_send_cmd,
+	.set_ios	= sh_sdhi_dm_set_ios,
+};
+
+static int sh_sdhi_dm_bind(struct udevice *dev)
+{
+	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
+
+	return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static int sh_sdhi_dm_probe(struct udevice *dev)
+{
+	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
+	struct sh_sdhi_host *host = dev_get_priv(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	const u32 quirks = dev_get_driver_data(dev);
+	fdt_addr_t base;
+
+	base = devfdt_get_addr(dev);
+	if (base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	host->addr = devm_ioremap(dev, base, SZ_2K);
+	if (!host->addr)
+		return -ENOMEM;
+
+	host->quirks = quirks;
+
+	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
+		host->bus_shift = 2;
+	else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
+		host->bus_shift = 1;
+
+	plat->cfg.name = dev->name;
+	plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+	switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
+			       1)) {
+	case 8:
+		plat->cfg.host_caps |= MMC_MODE_8BIT;
+		break;
+	case 4:
+		plat->cfg.host_caps |= MMC_MODE_4BIT;
+		break;
+	case 1:
+		break;
+	default:
+		dev_err(dev, "Invalid \"bus-width\" value\n");
+		return -EINVAL;
+	}
+
+	sh_sdhi_initialize_common(host);
+
+	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
+	plat->cfg.f_min = CLKDEV_INIT;
+	plat->cfg.f_max = CLKDEV_HS_DATA;
+	plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+	upriv->mmc = &plat->mmc;
+
+	return 0;
+}
+
+static const struct udevice_id sh_sdhi_sd_match[] = {
+	{ .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
+	{ .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sh_sdhi_mmc) = {
+	.name			= "sh-sdhi-mmc",
+	.id			= UCLASS_MMC,
+	.of_match		= sh_sdhi_sd_match,
+	.bind			= sh_sdhi_dm_bind,
+	.probe			= sh_sdhi_dm_probe,
+	.priv_auto_alloc_size	= sizeof(struct sh_sdhi_host),
+	.platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat),
+	.ops			= &sh_sdhi_dm_ops,
+};
+#endif