From 7aedafd6b374b9c052474dc248fa7173c5c048a2 Mon Sep 17 00:00:00 2001
From: Jaehoon Chung <jh80.chung@samsung.com>
Date: Fri, 9 Sep 2016 18:23:23 +0900
Subject: [PATCH 1/5] mmc: s5p_sdhci: support the Driver model for Exynos

This patch support the driver model for s5p_sdhci controller.
To support the legacy model, maintained the existing code.

Note: If use the Driver Model, it needs to modify the device-tree.
In future, will update the Device-tree and enable the configuratioin.
(CONFIG_BLK, CONFIG_DM_MMC and CONFING_DM_MMC_OPS)

Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Minkyu Kang <mk7.kang@samsung.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/s5p_sdhci.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index 3bace21..0d65783 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <sdhci.h>
 #include <fdtdec.h>
@@ -16,6 +17,15 @@
 #include <errno.h>
 #include <asm/arch/pinmux.h>
 
+#ifdef CONFIG_DM_MMC
+struct s5p_sdhci_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
 static char *S5P_NAME = "SAMSUNG SDHCI";
 static void s5p_sdhci_set_control_reg(struct sdhci_host *host)
 {
@@ -79,7 +89,11 @@ static int s5p_sdhci_core_init(struct sdhci_host *host)
 	if (host->bus_width == 8)
 		host->host_caps |= MMC_MODE_8BIT;
 
+#ifndef CONFIG_BLK
 	return add_sdhci(host, 52000000, 400000);
+#else
+	return 0;
+#endif
 }
 
 int s5p_sdhci_init(u32 regbase, int index, int bus_width)
@@ -215,3 +229,60 @@ int exynos_mmc_init(const void *blob)
 	return process_nodes(blob, node_list, count);
 }
 #endif
+
+#ifdef CONFIG_DM_MMC
+static int s5p_sdhci_probe(struct udevice *dev)
+{
+	struct s5p_sdhci_plat *plat = dev_get_platdata(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct sdhci_host *host = dev_get_priv(dev);
+	int ret;
+
+	ret = sdhci_get_config(gd->fdt_blob, dev->of_offset, host);
+	if (ret)
+		return ret;
+
+	ret = do_sdhci_init(host);
+	if (ret)
+		return ret;
+
+	ret = sdhci_setup_cfg(&plat->cfg, host, 52000000, 400000);
+	if (ret)
+		return ret;
+
+	host->mmc = &plat->mmc;
+	host->mmc->priv = host;
+	host->mmc->dev = dev;
+	upriv->mmc = host->mmc;
+
+	return sdhci_probe(dev);
+}
+
+static int s5p_sdhci_bind(struct udevice *dev)
+{
+	struct s5p_sdhci_plat *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id s5p_sdhci_ids[] = {
+	{ .compatible = "samsung,exynos4412-sdhci"},
+	{ }
+};
+
+U_BOOT_DRIVER(s5p_sdhci_drv) = {
+	.name		= "s5p_sdhci",
+	.id		= UCLASS_MMC,
+	.of_match	= s5p_sdhci_ids,
+	.bind		= s5p_sdhci_bind,
+	.ops		= &sdhci_ops,
+	.probe		= s5p_sdhci_probe,
+	.priv_auto_alloc_size = sizeof(struct sdhci_host),
+	.platdata_auto_alloc_size = sizeof(struct s5p_sdhci_plat),
+};
+#endif /* CONFIG_DM_MMC */

From e5113c333b318328619f8cf2d9984f05fc5c3b59 Mon Sep 17 00:00:00 2001
From: Jaehoon Chung <jh80.chung@samsung.com>
Date: Fri, 23 Sep 2016 19:13:16 +0900
Subject: [PATCH 2/5] mmc: dw_mmc: remove the unnecessary arguments for
 dwmci_setup_cfg

Some arguments don't need to pass to dwmci_setup_cfg.
They are already included in dwmci_host structure.

Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/dw_mmc.c          | 13 ++++++-------
 drivers/mmc/exynos_dw_mmc.c   |  3 +--
 drivers/mmc/rockchip_dw_mmc.c |  3 +--
 drivers/mmc/socfpga_dw_mmc.c  |  3 +--
 include/dwmmc.h               |  8 +++-----
 5 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 074f86c..d6ac46c 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -488,10 +488,10 @@ static const struct mmc_ops dwmci_ops = {
 };
 #endif
 
-void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
-		     uint caps, u32 max_clk, u32 min_clk)
+void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host,
+		u32 max_clk, u32 min_clk)
 {
-	cfg->name = name;
+	cfg->name = host->name;
 #ifndef CONFIG_DM_MMC_OPS
 	cfg->ops = &dwmci_ops;
 #endif
@@ -500,9 +500,9 @@ void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
 
 	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 
-	cfg->host_caps = caps;
+	cfg->host_caps = host->caps;
 
-	if (buswidth == 8) {
+	if (host->buswidth == 8) {
 		cfg->host_caps |= MMC_MODE_8BIT;
 		cfg->host_caps &= ~MMC_MODE_4BIT;
 	} else {
@@ -522,8 +522,7 @@ int dwmci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
 #else
 int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
 {
-	dwmci_setup_cfg(&host->cfg, host->name, host->buswidth, host->caps,
-			max_clk, min_clk);
+	dwmci_setup_cfg(&host->cfg, host, max_clk, min_clk);
 
 	host->mmc = mmc_create(&host->cfg, host);
 	if (host->mmc == NULL)
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index 568fed7..c440399 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -271,8 +271,7 @@ static int exynos_dwmmc_probe(struct udevice *dev)
 	if (err)
 		return err;
 
-	dwmci_setup_cfg(&plat->cfg, host->name, host->buswidth, host->caps,
-			DWMMC_MAX_FREQ, DWMMC_MIN_FREQ);
+	dwmci_setup_cfg(&plat->cfg, host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ);
 	host->mmc = &plat->mmc;
 	host->mmc->priv = &priv->host;
 	host->priv = dev;
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index 859760b..47db678 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -129,8 +129,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
 			return ret;
 	}
 #endif
-	dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps,
-			priv->minmax[1], priv->minmax[0]);
+	dwmci_setup_cfg(&plat->cfg, host, priv->minmax[1], priv->minmax[0]);
 	host->mmc = &plat->mmc;
 	host->mmc->priv = &priv->host;
 	host->mmc->dev = dev;
diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c
index 8a96302..5a3a4ff 100644
--- a/drivers/mmc/socfpga_dw_mmc.c
+++ b/drivers/mmc/socfpga_dw_mmc.c
@@ -111,8 +111,7 @@ static int socfpga_dwmmc_probe(struct udevice *dev)
 	struct dwmci_host *host = &priv->host;
 
 #ifdef CONFIG_BLK
-	dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps,
-			host->bus_hz, 400000);
+	dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000);
 	host->mmc = &plat->mmc;
 #else
 	int ret;
diff --git a/include/dwmmc.h b/include/dwmmc.h
index 5b9602c..4dda009 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -253,14 +253,12 @@ static inline u8 dwmci_readb(struct dwmci_host *host, int reg)
  * See rockchip_dw_mmc.c for an example.
  *
  * @cfg:	Configuration structure to fill in (generally &plat->mmc)
- * @name:	Device name (normally dev->name)
- * @buswidth:	Bus width (in bits, such as 4 or 8)
- * @caps:	Host capabilities (MMC_MODE_...)
+ * @host:	DWMMC host
  * @max_clk:	Maximum supported clock speed in HZ (e.g. 150000000)
  * @min_clk:	Minimum supported clock speed in HZ (e.g. 400000)
  */
-void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
-		     uint caps, u32 max_clk, u32 min_clk);
+void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host,
+		u32 max_clk, u32 min_clk);
 
 /**
  * dwmci_bind() - Set up a new MMC block device

From 895549a2d994ecf1ca1636792e55019e56be2d7d Mon Sep 17 00:00:00 2001
From: Jaehoon Chung <jh80.chung@samsung.com>
Date: Mon, 26 Sep 2016 08:10:01 +0900
Subject: [PATCH 3/5] mmc: sdhci: use the host version value in sdhci_setup_cfg

"host->version" isn't a SoC specific value.
It doesn't need to get in each SoC drivers.

Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Reviewed-by: Minkyu Kang <mk7.kang@samsung.com>
---
 drivers/mmc/atmel_sdhci.c   | 1 -
 drivers/mmc/bcm2835_sdhci.c | 1 -
 drivers/mmc/kona_sdhci.c    | 5 -----
 drivers/mmc/msm_sdhci.c     | 3 ---
 drivers/mmc/mv_sdhci.c      | 4 ----
 drivers/mmc/s5p_sdhci.c     | 1 -
 drivers/mmc/sdhci.c         | 6 +++++-
 drivers/mmc/spear_sdhci.c   | 5 -----
 drivers/mmc/zynq_sdhci.c    | 2 --
 9 files changed, 5 insertions(+), 23 deletions(-)

diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c
index d8f8087..20bba1a 100644
--- a/drivers/mmc/atmel_sdhci.c
+++ b/drivers/mmc/atmel_sdhci.c
@@ -29,7 +29,6 @@ int atmel_sdhci_init(void *regbase, u32 id)
 	host->name = "atmel_sdhci";
 	host->ioaddr = regbase;
 	host->quirks = 0;
-	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 	max_clk = at91_get_periph_generated_clk(id);
 	if (!max_clk) {
 		printf("%s: Failed to get the proper clock\n", __func__);
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c
index 680b754..c1d8700 100644
--- a/drivers/mmc/bcm2835_sdhci.c
+++ b/drivers/mmc/bcm2835_sdhci.c
@@ -184,7 +184,6 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq)
 	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	host->ops = &bcm2835_ops;
 
-	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 	add_sdhci(host, emmc_freq, MIN_FREQ);
 
 	return 0;
diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c
index e730caa..c67a262 100644
--- a/drivers/mmc/kona_sdhci.c
+++ b/drivers/mmc/kona_sdhci.c
@@ -127,11 +127,6 @@ int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks)
 		return -EINVAL;
 	}
 
-	if (quirks & SDHCI_QUIRK_REG32_RW)
-		host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
-	else
-		host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
-
 	add_sdhci(host, max_clk, min_clk);
 	return ret;
 }
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 1b82991..f33714b 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -140,9 +140,6 @@ static int msm_sdc_probe(struct udevice *dev)
 		writel(caps, host->ioaddr + SDHCI_VENDOR_SPEC_CAPABILITIES0);
 	}
 
-	/* Set host controller version */
-	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
-
 	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
 	host->mmc = &plat->mmc;
 	if (ret)
diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c
index 82c695f..ca5f872 100644
--- a/drivers/mmc/mv_sdhci.c
+++ b/drivers/mmc/mv_sdhci.c
@@ -88,9 +88,5 @@ int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks)
 		sdhci_mvebu_mbus_config((void __iomem *)regbase);
 	}
 
-	if (quirks & SDHCI_QUIRK_REG32_RW)
-		host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
-	else
-		host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 	return add_sdhci(host, max_clk, min_clk);
 }
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index 0d65783..d7cfa3e 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -81,7 +81,6 @@ static int s5p_sdhci_core_init(struct sdhci_host *host)
 		SDHCI_QUIRK_32BIT_DMA_ADDR |
 		SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8;
 	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
-	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
 	host->set_control_reg = &s5p_sdhci_set_control_reg;
 	host->set_clock = set_mmc_clk;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index b2bf5a0..7337722 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -546,7 +546,11 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 		return -EINVAL;
 	}
 #endif
-	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+	if (host->quirks & SDHCI_QUIRK_REG32_RW)
+		host->version =
+			sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
+	else
+		host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
 	cfg->name = host->name;
 #ifndef CONFIG_DM_MMC_OPS
diff --git a/drivers/mmc/spear_sdhci.c b/drivers/mmc/spear_sdhci.c
index 6ca96a2..06179cd 100644
--- a/drivers/mmc/spear_sdhci.c
+++ b/drivers/mmc/spear_sdhci.c
@@ -22,11 +22,6 @@ int spear_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks)
 	host->ioaddr = (void *)regbase;
 	host->quirks = quirks;
 
-	if (quirks & SDHCI_QUIRK_REG32_RW)
-		host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
-	else
-		host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
-
 	add_sdhci(host, max_clk, min_clk);
 	return 0;
 }
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index b991102..3da1385 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -36,8 +36,6 @@ static int arasan_sdhci_probe(struct udevice *dev)
 	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
 #endif
 
-	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
-
 	ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ,
 			      CONFIG_ZYNQ_SDHCI_MIN_FREQ);
 	host->mmc = &plat->mmc;

From 2cb5d67c1aceb758033954cc06382367ac89e6ac Mon Sep 17 00:00:00 2001
From: Jaehoon Chung <jh80.chung@samsung.com>
Date: Mon, 26 Sep 2016 08:10:02 +0900
Subject: [PATCH 4/5] mmc: sdhci: use the generic error number

Use the generic error number instead of meaningless value.

Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/bcm2835_sdhci.c  |  2 +-
 drivers/mmc/ftsdc021_sdhci.c |  2 +-
 drivers/mmc/kona_sdhci.c     |  6 +++---
 drivers/mmc/mv_sdhci.c       |  2 +-
 drivers/mmc/s5p_sdhci.c      |  8 ++++----
 drivers/mmc/sdhci.c          | 12 ++++++------
 6 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c
index c1d8700..cb2bd40 100644
--- a/drivers/mmc/bcm2835_sdhci.c
+++ b/drivers/mmc/bcm2835_sdhci.c
@@ -157,7 +157,7 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq)
 	bcm_host = calloc(1, sizeof(*bcm_host));
 	if (!bcm_host) {
 		printf("sdhci_host calloc fail!\n");
-		return 1;
+		return -ENOMEM;
 	}
 
 	/*
diff --git a/drivers/mmc/ftsdc021_sdhci.c b/drivers/mmc/ftsdc021_sdhci.c
index 1f6cdba..6e9fefa 100644
--- a/drivers/mmc/ftsdc021_sdhci.c
+++ b/drivers/mmc/ftsdc021_sdhci.c
@@ -21,7 +21,7 @@ int ftsdc021_sdhci_init(u32 regbase)
 	host = calloc(1, sizeof(struct sdhci_host));
 	if (!host) {
 		puts("sdh_host malloc fail!\n");
-		return 1;
+		return -ENOMEM;
 	}
 
 	host->name = "FTSDC021";
diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c
index c67a262..549f6bc 100644
--- a/drivers/mmc/kona_sdhci.c
+++ b/drivers/mmc/kona_sdhci.c
@@ -27,7 +27,7 @@ static int init_kona_mmc_core(struct sdhci_host *host)
 
 	if (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) {
 		printf("%s: sd host controller reset error\n", __func__);
-		return 1;
+		return -EBUSY;
 	}
 
 	/* For kona a hardware reset before anything else. */
@@ -39,7 +39,7 @@ static int init_kona_mmc_core(struct sdhci_host *host)
 	do {
 		if (timeout == 0) {
 			printf("%s: reset timeout error\n", __func__);
-			return 1;
+			return -ETIMEDOUT;
 		}
 		timeout--;
 		udelay(100);
@@ -67,7 +67,7 @@ static int init_kona_mmc_core(struct sdhci_host *host)
 	while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
 		if (timeout == 0) {
 			printf("%s: CARD DETECT timeout error\n", __func__);
-			return 1;
+			return -ETIMEDOUT;
 		}
 		timeout--;
 		udelay(100);
diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c
index ca5f872..e388ad1 100644
--- a/drivers/mmc/mv_sdhci.c
+++ b/drivers/mmc/mv_sdhci.c
@@ -71,7 +71,7 @@ int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks)
 	host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
 	if (!host) {
 		printf("sdh_host malloc fail!\n");
-		return 1;
+		return -ENOMEM;
 	}
 
 	host->name = MVSDH_NAME;
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index d7cfa3e..b329bef 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -100,7 +100,7 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
 	struct sdhci_host *host = calloc(1, sizeof(struct sdhci_host));
 	if (!host) {
 		printf("sdhci__host allocation fail!\n");
-		return 1;
+		return -ENOMEM;
 	}
 	host->ioaddr = (void *)regbase;
 	host->index = index;
@@ -154,7 +154,7 @@ static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host)
 	dev_id = pinmux_decode_periph_id(blob, node);
 	if (dev_id < PERIPH_ID_SDMMC0 && dev_id > PERIPH_ID_SDMMC3) {
 		debug("MMC: Can't get device id\n");
-		return -1;
+		return -EINVAL;
 	}
 	host->index = dev_id - PERIPH_ID_SDMMC0;
 
@@ -162,7 +162,7 @@ static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host)
 	bus_width = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
 	if (bus_width <= 0) {
 		debug("MMC: Can't get bus-width\n");
-		return -1;
+		return -EINVAL;
 	}
 	host->bus_width = bus_width;
 
@@ -170,7 +170,7 @@ static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host)
 	base = fdtdec_get_addr(blob, node, "reg");
 	if (!base) {
 		debug("MMC: Can't get base address\n");
-		return -1;
+		return -EINVAL;
 	}
 	host->ioaddr = (void *)base;
 
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 7337722..837c538 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -87,7 +87,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
 		if (stat & SDHCI_INT_ERROR) {
 			printf("%s: Error detected in status(0x%X)!\n",
 			       __func__, stat);
-			return -1;
+			return -EIO;
 		}
 		if (stat & rdy) {
 			if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask))
@@ -110,7 +110,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
 			udelay(10);
 		else {
 			printf("%s: Transfer data timeout\n", __func__);
-			return -1;
+			return -ETIMEDOUT;
 		}
 	} while (!(stat & SDHCI_INT_DATA_END));
 	return 0;
@@ -303,7 +303,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 		if (timeout == 0) {
 			printf("%s: Timeout to wait cmd & data inhibit\n",
 			       __func__);
-			return -1;
+			return -EBUSY;
 		}
 
 		timeout--;
@@ -374,7 +374,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 		if (timeout == 0) {
 			printf("%s: Internal clock never stabilised.\n",
 			       __func__);
-			return -1;
+			return -EBUSY;
 		}
 		timeout--;
 		udelay(1000);
@@ -477,7 +477,7 @@ static int sdhci_init(struct mmc *mmc)
 		if (!aligned_buffer) {
 			printf("%s: Aligned buffer alloc failed!!!\n",
 			       __func__);
-			return -1;
+			return -ENOMEM;
 		}
 	}
 
@@ -631,7 +631,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
 	host->mmc = mmc_create(&host->cfg, host);
 	if (host->mmc == NULL) {
 		printf("%s: mmc create fail!\n", __func__);
-		return -1;
+		return -ENOMEM;
 	}
 
 	return 0;

From 57718f017b10871cd9dc03dca56c3bd690fc2614 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Sun, 25 Sep 2016 21:33:10 -0600
Subject: [PATCH 5/5] mmc: Fix cast for 64-bit compilation

Fix a cast that causes warnings on 64-bit machines.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---
 drivers/mmc/pci_mmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
index 340eef6..3d587cc 100644
--- a/drivers/mmc/pci_mmc.c
+++ b/drivers/mmc/pci_mmc.c
@@ -30,7 +30,7 @@ int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported)
 
 		mmc_host->name = name;
 		dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase);
-		mmc_host->ioaddr = (void *)iobase;
+		mmc_host->ioaddr = (void *)(ulong)iobase;
 		mmc_host->quirks = 0;
 		ret = add_sdhci(mmc_host, 0, 0);
 		if (ret)