aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/Kconfig9
-rw-r--r--drivers/mmc/davinci_mmc.c63
-rw-r--r--drivers/mmc/mmc.c2
-rw-r--r--drivers/mmc/omap_hsmmc.c3
-rw-r--r--drivers/mmc/pxa_mmc_gen.c160
-rw-r--r--drivers/mmc/zynq_sdhci.c2
6 files changed, 170 insertions, 69 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 8f56572c39a..ad86c232c43 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -66,7 +66,6 @@ config MMC_SPI_CRC_ON
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.
@@ -300,6 +299,14 @@ config MMC_PCI
If unsure, say N.
+config PXA_MMC_GENERIC
+ bool "Support for MMC controllers on PXA"
+ help
+ This selects MMC controllers on PXA.
+ If you are on a PXA architecture, say Y here.
+
+ If unsure, say N.
+
config MMC_OMAP_HS
bool "TI OMAP High Speed Multimedia Card Interface support"
select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR
diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c
index 2408a687d23..4ef9f7cc8bc 100644
--- a/drivers/mmc/davinci_mmc.c
+++ b/drivers/mmc/davinci_mmc.c
@@ -18,7 +18,6 @@
#include <asm-generic/gpio.h>
#include <linux/delay.h>
-#define DAVINCI_MAX_BLOCKS (32)
#define WATCHDOG_COUNT (100000)
#define get_val(addr) REG(addr)
@@ -34,12 +33,6 @@ struct davinci_mmc_priv {
struct gpio_desc cd_gpio; /* Card Detect GPIO */
struct gpio_desc wp_gpio; /* Write Protect GPIO */
};
-
-struct davinci_mmc_plat
-{
- struct mmc_config cfg;
- struct mmc mmc;
-};
#endif
/* Set davinci clock prescalar value based on the required clock in HZ */
@@ -487,43 +480,16 @@ static int davinci_mmc_probe(struct udevice *dev)
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct davinci_mmc_plat *plat = dev_get_platdata(dev);
struct davinci_mmc_priv *priv = dev_get_priv(dev);
- struct mmc_config *cfg = &plat->cfg;
-#ifdef CONFIG_SPL_BUILD
- int ret;
-#endif
-
- cfg->f_min = 200000;
- cfg->f_max = 25000000;
- cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
- cfg->host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */
- cfg->b_max = DAVINCI_MAX_BLOCKS;
- cfg->name = "da830-mmc";
- priv->reg_base = (struct davinci_mmc_regs *)dev_read_addr(dev);
+ priv->reg_base = plat->reg_base;
priv->input_clk = clk_get(DAVINCI_MMCSD_CLKID);
-
#if CONFIG_IS_ENABLED(DM_GPIO)
/* These GPIOs are optional */
gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN);
#endif
-
upriv->mmc = &plat->mmc;
-#ifdef CONFIG_SPL_BUILD
- /*
- * FIXME This is a temporary workaround to enable the driver model in
- * SPL on omapl138-lcdk. For some reason the bind() callback is not
- * being called in SPL for MMC which breaks the mmc boot - the hack
- * is to call mmc_bind() from probe(). We also don't have full DT
- * support in SPL, hence the hard-coded base register address.
- */
- priv->reg_base = (struct davinci_mmc_regs *)DAVINCI_MMC_SD0_BASE;
- ret = mmc_bind(dev, &plat->mmc, &plat->cfg);
- if (ret)
- return ret;
-#endif
-
return davinci_dm_mmc_init(dev);
}
@@ -534,21 +500,44 @@ static int davinci_mmc_bind(struct udevice *dev)
return mmc_bind(dev, &plat->mmc, &plat->cfg);
}
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int davinci_mmc_ofdata_to_platdata(struct udevice *dev)
+{
+ struct davinci_mmc_plat *plat = dev_get_platdata(dev);
+ struct mmc_config *cfg = &plat->cfg;
+
+ plat->reg_base = (struct davinci_mmc_regs *)dev_read_addr(dev);
+ cfg->f_min = 200000;
+ cfg->f_max = 25000000;
+ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
+ cfg->host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */
+ cfg->b_max = DAVINCI_MAX_BLOCKS;
+ cfg->name = "da830-mmc";
+
+ return 0;
+}
+
static const struct udevice_id davinci_mmc_ids[] = {
{ .compatible = "ti,da830-mmc" },
{},
};
-
+#endif
U_BOOT_DRIVER(davinci_mmc_drv) = {
.name = "davinci_mmc",
.id = UCLASS_MMC,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
.of_match = davinci_mmc_ids,
+ .platdata_auto_alloc_size = sizeof(struct davinci_mmc_plat),
+ .ofdata_to_platdata = davinci_mmc_ofdata_to_platdata,
+#endif
#if CONFIG_BLK
.bind = davinci_mmc_bind,
#endif
.probe = davinci_mmc_probe,
.ops = &davinci_mmc_ops,
- .platdata_auto_alloc_size = sizeof(struct davinci_mmc_plat),
.priv_auto_alloc_size = sizeof(struct davinci_mmc_priv),
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
};
#endif
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 725a36799d3..50f47d4ba26 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2831,7 +2831,7 @@ retry:
if (err)
return err;
- /* The internal partition reset to user partition(0) at every CMD0*/
+ /* The internal partition reset to user partition(0) at every CMD0 */
mmc_get_blk_desc(mmc)->hwpart = 0;
/* Test for SD version 2 */
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 8636cd713a3..0e05fe4cfcb 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -175,6 +175,8 @@ static inline struct omap_hsmmc_data *omap_hsmmc_get_data(struct mmc *mmc)
return (struct omap_hsmmc_data *)mmc->priv;
#endif
}
+
+#if defined(CONFIG_OMAP34XX) || defined(CONFIG_IODELAY_RECALIBRATION)
static inline struct mmc_config *omap_hsmmc_get_cfg(struct mmc *mmc)
{
#if CONFIG_IS_ENABLED(DM_MMC)
@@ -184,6 +186,7 @@ static inline struct mmc_config *omap_hsmmc_get_cfg(struct mmc *mmc)
return &((struct omap_hsmmc_data *)mmc->priv)->cfg;
#endif
}
+#endif
#if defined(OMAP_HSMMC_USE_GPIO) && !CONFIG_IS_ENABLED(DM_MMC)
static int omap_mmc_setup_gpio_in(int gpio, const char *label)
diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c
index cc6014703cc..2c081fdc69f 100644
--- a/drivers/mmc/pxa_mmc_gen.c
+++ b/drivers/mmc/pxa_mmc_gen.c
@@ -2,6 +2,9 @@
/*
* Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
*
+ * Modified to add driver model (DM) support
+ * Copyright (C) 2019 Marcel Ziswiler <marcel@ziswiler.com>
+ *
* Loosely based on the old code and Linux's PXA MMC driver
*/
@@ -11,6 +14,8 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <asm/io.h>
+#include <dm.h>
+#include <dm/platform_data/pxa_mmc_gen.h>
#include <malloc.h>
#include <mmc.h>
@@ -96,7 +101,7 @@ static int pxa_mmc_stop_clock(struct mmc *mmc)
}
static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
- uint32_t cmdat)
+ uint32_t cmdat)
{
struct pxa_mmc_priv *priv = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
@@ -143,7 +148,7 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
{
struct pxa_mmc_priv *priv = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
- uint32_t a, b, c;
+ u32 a, b, c;
int i;
int stat;
@@ -152,7 +157,7 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
/*
* Linux says:
- * Did I mention this is Sick. We always need to
+ * Did I mention this is Sick. We always need to
* discard the upper 8 bits of the first 16-bit word.
*/
a = readl(&regs->res) & 0xffff;
@@ -164,13 +169,13 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
}
/* The command response didn't arrive */
- if (stat & MMC_STAT_TIME_OUT_RESPONSE)
+ if (stat & MMC_STAT_TIME_OUT_RESPONSE) {
return -ETIMEDOUT;
- else if (stat & MMC_STAT_RES_CRC_ERROR
- && cmd->resp_type & MMC_RSP_CRC) {
-#ifdef PXAMMC_CRC_SKIP
- if (cmd->resp_type & MMC_RSP_136
- && cmd->response[0] & (1 << 31))
+ } else if (stat & MMC_STAT_RES_CRC_ERROR &&
+ cmd->resp_type & MMC_RSP_CRC) {
+#ifdef PXAMMC_CRC_SKIP
+ if (cmd->resp_type & MMC_RSP_136 &&
+ cmd->response[0] & (1 << 31))
printf("Ignoring CRC, this may be dangerous!\n");
else
#endif
@@ -185,8 +190,8 @@ static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data)
{
struct pxa_mmc_priv *priv = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
- uint32_t len;
- uint32_t *buf = (uint32_t *)data->dest;
+ u32 len;
+ u32 *buf = (uint32_t *)data->dest;
int size;
int ret;
@@ -202,7 +207,6 @@ static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data)
/* Read data into the buffer */
while (size--)
*buf++ = readl(&regs->rxfifo);
-
}
if (readl(&regs->stat) & MMC_STAT_ERRORS)
@@ -221,8 +225,8 @@ static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data)
{
struct pxa_mmc_priv *priv = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
- uint32_t len;
- uint32_t *buf = (uint32_t *)data->src;
+ u32 len;
+ u32 *buf = (uint32_t *)data->src;
int size;
int ret;
@@ -259,12 +263,11 @@ static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data)
return 0;
}
-static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
- struct mmc_data *data)
+static int pxa_mmc_send_cmd_common(struct pxa_mmc_priv *priv, struct mmc *mmc,
+ struct mmc_cmd *cmd, struct mmc_data *data)
{
- struct pxa_mmc_priv *priv = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
- uint32_t cmdat = 0;
+ u32 cmdat = 0;
int ret;
/* Stop the controller */
@@ -313,12 +316,11 @@ static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
return 0;
}
-static int pxa_mmc_set_ios(struct mmc *mmc)
+static int pxa_mmc_set_ios_common(struct pxa_mmc_priv *priv, struct mmc *mmc)
{
- struct pxa_mmc_priv *priv = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
- uint32_t tmp;
- uint32_t pxa_mmc_clock;
+ u32 tmp;
+ u32 pxa_mmc_clock;
if (!mmc->clock) {
pxa_mmc_stop_clock(mmc);
@@ -346,9 +348,8 @@ static int pxa_mmc_set_ios(struct mmc *mmc)
return 0;
}
-static int pxa_mmc_init(struct mmc *mmc)
+static int pxa_mmc_init_common(struct pxa_mmc_priv *priv, struct mmc *mmc)
{
- struct pxa_mmc_priv *priv = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
/* Make sure the clock are stopped */
@@ -362,10 +363,34 @@ static int pxa_mmc_init(struct mmc *mmc)
/* Mask all interrupts */
writel(~(MMC_I_MASK_TXFIFO_WR_REQ | MMC_I_MASK_RXFIFO_RD_REQ),
- &regs->i_mask);
+ &regs->i_mask);
+
return 0;
}
+#if !CONFIG_IS_ENABLED(DM_MMC)
+static int pxa_mmc_init(struct mmc *mmc)
+{
+ struct pxa_mmc_priv *priv = mmc->priv;
+
+ return pxa_mmc_init_common(priv, mmc);
+}
+
+static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct pxa_mmc_priv *priv = mmc->priv;
+
+ return pxa_mmc_send_cmd_common(priv, mmc, cmd, data);
+}
+
+static int pxa_mmc_set_ios(struct mmc *mmc)
+{
+ struct pxa_mmc_priv *priv = mmc->priv;
+
+ return pxa_mmc_set_ios_common(priv, mmc);
+}
+
static const struct mmc_ops pxa_mmc_ops = {
.send_cmd = pxa_mmc_request,
.set_ios = pxa_mmc_set_ios,
@@ -386,7 +411,7 @@ int pxa_mmc_register(int card_index)
{
struct mmc *mmc;
struct pxa_mmc_priv *priv;
- uint32_t reg;
+ u32 reg;
int ret = -ENOMEM;
priv = malloc(sizeof(struct pxa_mmc_priv));
@@ -405,7 +430,7 @@ int pxa_mmc_register(int card_index)
default:
ret = -EINVAL;
printf("PXA MMC: Invalid MMC controller ID (card_index = %d)\n",
- card_index);
+ card_index);
goto err1;
}
@@ -420,7 +445,7 @@ int pxa_mmc_register(int card_index)
#endif
mmc = mmc_create(&pxa_mmc_cfg, priv);
- if (mmc == NULL)
+ if (!mmc)
goto err1;
return 0;
@@ -430,3 +455,82 @@ err1:
err0:
return ret;
}
+#else /* !CONFIG_IS_ENABLED(DM_MMC) */
+static int pxa_mmc_probe(struct udevice *dev)
+{
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct pxa_mmc_plat *plat = dev_get_platdata(dev);
+ struct mmc_config *cfg = &plat->cfg;
+ struct mmc *mmc = &plat->mmc;
+ struct pxa_mmc_priv *priv = dev_get_priv(dev);
+ u32 reg;
+
+ upriv->mmc = mmc;
+
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+ cfg->f_max = PXAMMC_MAX_SPEED;
+ cfg->f_min = PXAMMC_MIN_SPEED;
+ cfg->host_caps = PXAMMC_HOST_CAPS;
+ cfg->name = dev->name;
+ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+ mmc->priv = priv;
+
+ priv->regs = plat->base;
+
+#ifndef CONFIG_CPU_MONAHANS /* PXA2xx */
+ reg = readl(CKEN);
+ reg |= CKEN12_MMC;
+ writel(reg, CKEN);
+#else /* PXA3xx */
+ reg = readl(CKENA);
+ reg |= CKENA_12_MMC0 | CKENA_13_MMC1;
+ writel(reg, CKENA);
+#endif
+
+ return pxa_mmc_init_common(priv, mmc);
+}
+
+static int pxa_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct pxa_mmc_plat *plat = dev_get_platdata(dev);
+ struct pxa_mmc_priv *priv = dev_get_priv(dev);
+
+ return pxa_mmc_send_cmd_common(priv, &plat->mmc, cmd, data);
+}
+
+static int pxa_mmc_set_ios(struct udevice *dev)
+{
+ struct pxa_mmc_plat *plat = dev_get_platdata(dev);
+ struct pxa_mmc_priv *priv = dev_get_priv(dev);
+
+ return pxa_mmc_set_ios_common(priv, &plat->mmc);
+}
+
+static const struct dm_mmc_ops pxa_mmc_ops = {
+ .get_cd = NULL,
+ .send_cmd = pxa_mmc_send_cmd,
+ .set_ios = pxa_mmc_set_ios,
+};
+
+#if CONFIG_IS_ENABLED(BLK)
+static int pxa_mmc_bind(struct udevice *dev)
+{
+ struct pxa_mmc_plat *plat = dev_get_platdata(dev);
+
+ return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+#endif
+
+U_BOOT_DRIVER(pxa_mmc) = {
+#if CONFIG_IS_ENABLED(BLK)
+ .bind = pxa_mmc_bind,
+#endif
+ .id = UCLASS_MMC,
+ .name = "pxa_mmc",
+ .ops = &pxa_mmc_ops,
+ .priv_auto_alloc_size = sizeof(struct pxa_mmc_priv),
+ .probe = pxa_mmc_probe,
+};
+#endif /* !CONFIG_IS_ENABLED(DM_MMC) */
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index de404aa9560..43b9f215229 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -19,8 +19,6 @@
#include <sdhci.h>
#include <zynqmp_tap_delay.h>
-DECLARE_GLOBAL_DATA_PTR;
-
struct arasan_sdhci_plat {
struct mmc_config cfg;
struct mmc mmc;