[U-Boot] [PATCH v2 2/5] mmc: arm_pl180_mmci: adapt driver to DM usage

patrice.chotard at st.com patrice.chotard at st.com
Mon Oct 23 08:57:31 UTC 2017


From: Patrice Chotard <patrice.chotard at st.com>

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 at st.com>
Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
---

v2: _ add defines for clock min and max value


 drivers/mmc/Kconfig          |   9 +++
 drivers/mmc/arm_pl180_mmci.c | 129 +++++++++++++++++++++++++++++++++++++++----
 drivers/mmc/arm_pl180_mmci.h |   3 +
 3 files changed, 129 insertions(+), 12 deletions(-)

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 94050836..62ce0af 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -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
diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index 7898b0d..b3c1f0d 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -12,12 +12,27 @@
 
 /* #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
diff --git a/drivers/mmc/arm_pl180_mmci.h b/drivers/mmc/arm_pl180_mmci.h
index 6e232f7..b935288 100644
--- a/drivers/mmc/arm_pl180_mmci.h
+++ b/drivers/mmc/arm_pl180_mmci.h
@@ -142,6 +142,9 @@
 
 #define SDI_FIFO_BURST_SIZE	8
 
+#define VERSION1	false
+#define VERSION2	true
+
 struct sdi_registers {
 	u32 power;		/* 0x00*/
 	u32 clock;		/* 0x04*/
-- 
1.9.1



More information about the U-Boot mailing list