mmc: arm_pl180_mmci: adapt driver to DM usage
authorPatrice Chotard <patrice.chotard@st.com>
Mon, 23 Oct 2017 08:57:31 +0000 (10:57 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 17 Nov 2017 12:44:13 +0000 (07:44 -0500)
Convert this driver to driver model.
This driver is also used by VEXPRESS platforms which doesn't
use driver model.

Tested on STM32F746 and STM32F769 platforms.

Signed-off-by: Christophe Priouzeau <christophe.priouzeau@st.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
drivers/mmc/Kconfig
drivers/mmc/arm_pl180_mmci.c
drivers/mmc/arm_pl180_mmci.h

index 940508364a51c1296504d5012f303aaf9b31fd87..62ce0af7d3c3bde24b6b89d2e663ce2b200efb4f 100644 (file)
@@ -33,6 +33,15 @@ config SPL_DM_MMC
 
 if MMC
 
+config ARM_PL180_MMCI
+       bool "ARM AMBA Multimedia Card Interface and compatible support"
+       depends on DM_MMC && OF_CONTROL
+       help
+         This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
+         Interface (PL180, PL181 and compatible) support.
+         If you have an ARM(R) platform with a Multimedia Card slot,
+         say Y or M here.
+
 config SPL_MMC_TINY
        bool "Tiny MMC framework in SPL"
        help
index 7898b0dd70f40d28d177075a7c6472a9aa632b8f..b3c1f0ddcb938351290c143c3d04e31bc0e185bb 100644 (file)
 
 /* #define DEBUG */
 
-#include <asm/io.h>
 #include "common.h"
 #include <errno.h>
+#include <malloc.h>
 #include <mmc.h>
+
 #include "arm_pl180_mmci.h"
-#include <malloc.h>
+
+#include <asm/io.h>
+
+#ifdef CONFIG_DM_MMC
+#include <dm.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MMC_CLOCK_MAX  48000000
+#define MMC_CLOCK_MIN  400000
+
+struct arm_pl180_mmc_plat {
+       struct mmc_config cfg;
+       struct mmc mmc;
+};
+#endif
 
 static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
 {
@@ -265,16 +280,6 @@ static int host_request(struct mmc *dev,
        return result;
 }
 
-/* MMC uses open drain drivers in the enumeration phase */
-static int mmc_host_reset(struct mmc *dev)
-{
-       struct pl180_mmc_host *host = dev->priv;
-
-       writel(host->pwr_init, &host->base->power);
-
-       return 0;
-}
-
 static int  host_set_ios(struct mmc *dev)
 {
        struct pl180_mmc_host *host = dev->priv;
@@ -337,11 +342,23 @@ static int  host_set_ios(struct mmc *dev)
        return 0;
 }
 
+#ifndef CONFIG_DM_MMC
+/* MMC uses open drain drivers in the enumeration phase */
+static int mmc_host_reset(struct mmc *dev)
+{
+       struct pl180_mmc_host *host = dev->priv;
+
+       writel(host->pwr_init, &host->base->power);
+
+       return 0;
+}
+
 static const struct mmc_ops arm_pl180_mmci_ops = {
        .send_cmd = host_request,
        .set_ios = host_set_ios,
        .init = mmc_host_reset,
 };
+#endif
 
 /*
  * mmc_host_init - initialize the mmc controller.
@@ -361,7 +378,9 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
        writel(sdi_u32, &host->base->mask0);
 
        host->cfg.name = host->name;
+#ifndef CONFIG_DM_MMC
        host->cfg.ops = &arm_pl180_mmci_ops;
+#endif
        /* TODO remove the duplicates */
        host->cfg.host_caps = host->caps;
        host->cfg.voltages = host->voltages;
@@ -381,3 +400,89 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
 
        return 0;
 }
+
+#ifdef CONFIG_DM_MMC
+static int arm_pl180_mmc_probe(struct udevice *dev)
+{
+       struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
+       struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+       struct mmc *mmc = &pdata->mmc;
+       struct pl180_mmc_host *host = mmc->priv;
+       int ret;
+
+       strcpy(host->name, "MMC");
+       host->pwr_init = INIT_PWR;
+       host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN |
+                           SDI_CLKCR_HWFC_EN;
+       host->voltages = VOLTAGE_WINDOW_SD;
+       host->caps = 0;
+       host->clock_in = MMC_CLOCK_MAX;
+       host->clock_min = MMC_CLOCK_MIN;
+       host->clock_max = dev_read_u32_default(dev, "max-frequency",
+                                              MMC_CLOCK_MAX);
+       host->version2 = dev_get_driver_data(dev);
+       ret = arm_pl180_mmci_init(host, &mmc);
+       if (ret) {
+               dev_err(dev, "arm_pl180_mmci init failed\n");
+               return ret;
+       }
+
+       mmc->dev = dev;
+       dev->priv = host;
+       upriv->mmc = mmc;
+
+       return 0;
+}
+
+static int dm_host_request(struct udevice *dev, struct mmc_cmd *cmd,
+                          struct mmc_data *data)
+{
+       struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+       return host_request(mmc, cmd, data);
+}
+
+static int dm_host_set_ios(struct udevice *dev)
+{
+       struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+       return host_set_ios(mmc);
+}
+
+static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = {
+       .send_cmd = dm_host_request,
+       .set_ios = dm_host_set_ios,
+};
+
+static int arm_pl180_mmc_ofdata_to_platdata(struct udevice *dev)
+{
+       struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
+       struct mmc *mmc = &pdata->mmc;
+       struct pl180_mmc_host *host = mmc->priv;
+       fdt_addr_t addr;
+
+       addr = devfdt_get_addr(dev);
+       if (addr == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       host->base = (void *)addr;
+
+       return 0;
+}
+
+static const struct udevice_id arm_pl180_mmc_match[] = {
+       { .compatible = "st,stm32f4xx-sdio", .data = VERSION1 },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(arm_pl180_mmc) = {
+       .name = "arm_pl180_mmc",
+       .id = UCLASS_MMC,
+       .of_match = arm_pl180_mmc_match,
+       .ops = &arm_pl180_dm_mmc_ops,
+       .probe = arm_pl180_mmc_probe,
+       .ofdata_to_platdata = arm_pl180_mmc_ofdata_to_platdata,
+       .priv_auto_alloc_size = sizeof(struct pl180_mmc_host),
+       .platdata_auto_alloc_size = sizeof(struct arm_pl180_mmc_plat),
+};
+#endif
index 6e232f7df26ccd1ec71054c24b4ed04a76b2dc47..b93528870458585eaa72a11714d03c34ec8093a7 100644 (file)
 
 #define SDI_FIFO_BURST_SIZE    8
 
+#define VERSION1       false
+#define VERSION2       true
+
 struct sdi_registers {
        u32 power;              /* 0x00*/
        u32 clock;              /* 0x04*/