From 3c0dbed232bd17a7bed773f545420460a3ac183a Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 23 Oct 2017 10:57:31 +0200 Subject: mmc: arm_pl180_mmci: adapt driver to DM usage 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 Signed-off-by: Patrice Chotard --- 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 940508364a5..62ce0af7d3c 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 7898b0dd70f..b3c1f0ddcb9 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -12,12 +12,27 @@ /* #define DEBUG */ -#include #include "common.h" #include +#include #include + #include "arm_pl180_mmci.h" -#include + +#include + +#ifdef CONFIG_DM_MMC +#include +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 6e232f7df26..b9352887045 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*/ -- cgit v1.2.3