dm: mmc: rpi: Convert Raspberry Pi to driver model for MMC

Convert the bcm2835 SDHCI driver over to support CONFIG_DM_MMC and move
all boards over. There is no need to keep the old code since there are no
other users.

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 2893f09..1fb7ba0 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -466,19 +466,6 @@
 	return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD);
 }
 
-int board_mmc_init(bd_t *bis)
-{
-	int ret;
-
-	bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI);
-
-	ret = bcm2835_get_mmc_clock();
-	if (ret)
-		return ret;
-
-	return bcm2835_sdhci_init(BCM2835_SDHCI_BASE, ret);
-}
-
 int ft_board_setup(void *blob, bd_t *bd)
 {
 	/*
diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig
index f13a29e..221026a 100644
--- a/configs/rpi_2_defconfig
+++ b/configs/rpi_2_defconfig
@@ -14,6 +14,7 @@
 # CONFIG_CMD_FPGA is not set
 CONFIG_CMD_GPIO=y
 CONFIG_OF_EMBED=y
+CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_BCM2835=y
 CONFIG_DM_ETH=y
diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig
index 306d54f..ab58045 100644
--- a/configs/rpi_3_32b_defconfig
+++ b/configs/rpi_3_32b_defconfig
@@ -15,6 +15,7 @@
 # CONFIG_CMD_FPGA is not set
 CONFIG_CMD_GPIO=y
 CONFIG_OF_EMBED=y
+CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_BCM2835=y
 CONFIG_DM_ETH=y
diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig
index 7fd5ca7..36f3def 100644
--- a/configs/rpi_3_defconfig
+++ b/configs/rpi_3_defconfig
@@ -15,6 +15,7 @@
 # CONFIG_CMD_FPGA is not set
 CONFIG_CMD_GPIO=y
 CONFIG_OF_EMBED=y
+CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_BCM2835=y
 CONFIG_DM_ETH=y
diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig
index d650e2e..72f8af9 100644
--- a/configs/rpi_defconfig
+++ b/configs/rpi_defconfig
@@ -14,6 +14,7 @@
 # CONFIG_CMD_FPGA is not set
 CONFIG_CMD_GPIO=y
 CONFIG_OF_EMBED=y
+CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_BCM2835=y
 CONFIG_DM_ETH=y
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c
index 20079bc..b6e2fc6 100644
--- a/drivers/mmc/bcm2835_sdhci.c
+++ b/drivers/mmc/bcm2835_sdhci.c
@@ -37,15 +37,24 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
+#include <memalign.h>
 #include <sdhci.h>
-#include <mach/timer.h>
+#include <asm/arch/msg.h>
+#include <asm/arch/mbox.h>
 #include <mach/sdhci.h>
+#include <mach/timer.h>
 
 /* 400KHz is max freq for card ID etc. Use that as min */
 #define MIN_FREQ 400000
 #define SDHCI_BUFFER 0x20
 
+struct bcm2835_sdhci_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
 struct bcm2835_sdhci_host {
 	struct sdhci_host host;
 	uint twoticks_delay;
@@ -58,7 +67,7 @@
 }
 
 static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val,
-						int reg)
+					    int reg)
 {
 	struct bcm2835_sdhci_host *bcm_host = to_bcm(host);
 
@@ -153,16 +162,33 @@
 	.read_b = bcm2835_sdhci_readb,
 };
 
-int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq)
+static int bcm2835_sdhci_bind(struct udevice *dev)
 {
-	struct bcm2835_sdhci_host *bcm_host;
-	struct sdhci_host *host;
+	struct bcm2835_sdhci_plat *plat = dev_get_platdata(dev);
 
-	bcm_host = calloc(1, sizeof(*bcm_host));
-	if (!bcm_host) {
-		printf("sdhci_host calloc fail!\n");
-		return -ENOMEM;
+	return sdhci_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static int bcm2835_sdhci_probe(struct udevice *dev)
+{
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct bcm2835_sdhci_plat *plat = dev_get_platdata(dev);
+	struct bcm2835_sdhci_host *priv = dev_get_priv(dev);
+	struct sdhci_host *host = &priv->host;
+	fdt_addr_t base;
+	int emmc_freq;
+	int ret;
+
+	base = dev_get_addr(dev);
+	if (base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	ret = bcm2835_get_mmc_clock();
+	if (ret < 0) {
+		debug("%s: Failed to set MMC clock (err=%d)\n", __func__, ret);
+		return ret;
 	}
+	emmc_freq = ret;
 
 	/*
 	 * See the comments in bcm2835_sdhci_raw_writel().
@@ -177,19 +203,42 @@
 	 * Multiply by 1000000 to get uS per two ticks.
 	 * +1 for hack rounding.
 	 */
-	bcm_host->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1;
-	bcm_host->last_write = 0;
+	priv->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1;
+	priv->last_write = 0;
 
-	host = &bcm_host->host;
-	host->name = "bcm2835_sdhci";
-	host->ioaddr = (void *)(unsigned long)regbase;
+	host->name = dev->name;
+	host->ioaddr = (void *)base;
 	host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B |
 		SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT;
 	host->max_clk = emmc_freq;
 	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	host->ops = &bcm2835_ops;
 
+	ret = sdhci_setup_cfg(&plat->cfg, host, emmc_freq, MIN_FREQ);
+	if (ret) {
+		debug("%s: Failed to setup SDHCI (err=%d)\n", __func__, ret);
+		return ret;
+	}
+
-	add_sdhci(host, 0, MIN_FREQ);
+	upriv->mmc = &plat->mmc;
+	host->mmc = &plat->mmc;
+	host->mmc->priv = host;
 
-	return 0;
+	return sdhci_probe(dev);
 }
+
+static const struct udevice_id bcm2835_sdhci_match[] = {
+	{ .compatible = "brcm,bcm2835-sdhci" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sdhci_cdns) = {
+	.name = "sdhci-bcm2835",
+	.id = UCLASS_MMC,
+	.of_match = bcm2835_sdhci_match,
+	.bind = bcm2835_sdhci_bind,
+	.probe = bcm2835_sdhci_probe,
+	.priv_auto_alloc_size = sizeof(struct bcm2835_sdhci_host),
+	.platdata_auto_alloc_size = sizeof(struct bcm2835_sdhci_plat),
+	.ops = &sdhci_ops,
+};