public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct
@ 2014-03-12 10:24 Pantelis Antoniou
  2014-03-12 10:24 ` [U-Boot] [PATCH 1/3] mmc: Remove ops from struct mmc and put in mmc_ops Pantelis Antoniou
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Pantelis Antoniou @ 2014-03-12 10:24 UTC (permalink / raw)
  To: u-boot

Struct mmc has picked up a lot of cruft over the years.

It is time for it to be split in 3 parts; the original mmc struct
containing the state, the mmc_config struct containing the board
setup configuration and the mmc_ops struct contains the method
pointers.

Using the new config structures the mmc device creation now gets
much more easier by using the new mmc_create() call

Pantelis Antoniou (3):
  mmc: Remove ops from struct mmc and put in mmc_ops
  mmc: Convert mmc struct's name array to a pointer
  mmc: Split mmc struct, rework mmc initialization

 arch/arm/include/asm/arch-davinci/sdmmc_defs.h |   1 +
 arch/arm/include/asm/arch-tegra/tegra_mmc.h    |   4 +
 common/cmd_mmc.c                               |   2 +-
 common/cmd_mmc_spi.c                           |   2 +-
 drivers/mmc/arm_pl180_mmci.c                   |  50 +++++----
 drivers/mmc/arm_pl180_mmci.h                   |   4 +
 drivers/mmc/bfin_sdh.c                         |  40 +++----
 drivers/mmc/davinci_mmc.c                      |  41 ++++---
 drivers/mmc/dw_mmc.c                           |  58 +++++-----
 drivers/mmc/fsl_esdhc.c                        |  65 +++++------
 drivers/mmc/ftsdc010_mci.c                     |  63 +++++------
 drivers/mmc/gen_atmel_mci.c                    |  53 +++++----
 drivers/mmc/mmc.c                              |  88 +++++++++------
 drivers/mmc/mmc_spi.c                          |  50 +++++----
 drivers/mmc/mmc_write.c                        |   3 +-
 drivers/mmc/mxcmmc.c                           |  45 ++++----
 drivers/mmc/mxsmmc.c                           |  48 ++++-----
 drivers/mmc/omap_hsmmc.c                       | 142 +++++++++++++++----------
 drivers/mmc/pxa_mmc_gen.c                      |  70 ++++++------
 drivers/mmc/sdhci.c                            |  84 ++++++++-------
 drivers/mmc/sh_mmcif.c                         |  52 ++++-----
 drivers/mmc/tegra_mmc.c                        |  53 ++++-----
 include/dwmmc.h                                |   2 +
 include/fsl_esdhc.h                            |   4 +
 include/mmc.h                                  |  48 ++++++---
 include/sdhci.h                                |   2 +
 26 files changed, 590 insertions(+), 484 deletions(-)

-- 
1.7.12

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/3] mmc: Remove ops from struct mmc and put in mmc_ops
  2014-03-12 10:24 [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct Pantelis Antoniou
@ 2014-03-12 10:24 ` Pantelis Antoniou
  2014-03-14 20:53   ` Simon Glass
  2014-03-12 10:24 ` [U-Boot] [PATCH 2/3] mmc: Convert mmc struct's name array to a pointer Pantelis Antoniou
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Pantelis Antoniou @ 2014-03-12 10:24 UTC (permalink / raw)
  To: u-boot

Remove the in-structure ops and put them in mmc_ops with
a constant pointer to it.

This makes the mmc structure smaller as well as conserving
code space (in theory).

All in-tree drivers are converted as well; this is done in a
single patch in order to not break git bisect.

Changes since V1:
Fix compilation b0rked issue on omap platforms where OMAP_GPIO was
not set.

Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
---
 drivers/mmc/arm_pl180_mmci.c | 12 +++---
 drivers/mmc/bfin_sdh.c       | 11 +++---
 drivers/mmc/davinci_mmc.c    | 13 ++++---
 drivers/mmc/dw_mmc.c         | 10 +++--
 drivers/mmc/fsl_esdhc.c      | 14 ++++---
 drivers/mmc/ftsdc010_mci.c   | 11 ++++--
 drivers/mmc/gen_atmel_mci.c  | 12 +++---
 drivers/mmc/mmc.c            | 21 ++++++-----
 drivers/mmc/mmc_spi.c        | 12 +++---
 drivers/mmc/mxcmmc.c         | 12 +++---
 drivers/mmc/mxsmmc.c         | 12 +++---
 drivers/mmc/omap_hsmmc.c     | 89 ++++++++++++++++++++++++++++----------------
 drivers/mmc/pxa_mmc_gen.c    | 11 ++++--
 drivers/mmc/sdhci.c          | 13 ++++---
 drivers/mmc/sh_mmcif.c       | 12 +++---
 drivers/mmc/tegra_mmc.c      | 19 ++++++----
 include/mmc.h                | 19 +++++++---
 17 files changed, 184 insertions(+), 119 deletions(-)

diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index 5a55fe7..4490e97 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -335,6 +335,12 @@ static void host_set_ios(struct mmc *dev)
 	udelay(CLK_CHANGE_DELAY);
 }
 
+static const struct mmc_ops arm_pl180_mmci_ops = {
+	.send_cmd = host_request,
+	.set_ios = host_set_ios,
+	.init = mmc_host_reset,
+};
+
 /*
  * mmc_host_init - initialize the mmc controller.
  * Set initial clock and power for mmc slot.
@@ -360,11 +366,7 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host)
 	sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
 	writel(sdi_u32, &host->base->mask0);
 	strncpy(dev->name, host->name, sizeof(dev->name));
-	dev->send_cmd = host_request;
-	dev->set_ios = host_set_ios;
-	dev->init = mmc_host_reset;
-	dev->getcd = NULL;
-	dev->getwp = NULL;
+	dev->ops = &arm_pl180_mmci_ops;
 	dev->host_caps = host->caps;
 	dev->voltages = host->voltages;
 	dev->f_min = host->clock_min;
diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c
index bd9b641..f0871ec 100644
--- a/drivers/mmc/bfin_sdh.c
+++ b/drivers/mmc/bfin_sdh.c
@@ -274,6 +274,11 @@ static int bfin_sdh_init(struct mmc *mmc)
 	return 0;
 }
 
+static const struct mmc_ops bfin_mmc_ops = {
+	.send_cmd	= bfin_sdh_request,
+	.set_ios	= bfin_sdh_set_ios,
+	.init		= bfin_sdh_init,
+};
 
 int bfin_mmc_init(bd_t *bis)
 {
@@ -284,11 +289,7 @@ int bfin_mmc_init(bd_t *bis)
 	if (!mmc)
 		return -ENOMEM;
 	sprintf(mmc->name, "Blackfin SDH");
-	mmc->send_cmd = bfin_sdh_request;
-	mmc->set_ios = bfin_sdh_set_ios;
-	mmc->init = bfin_sdh_init;
-	mmc->getcd = NULL;
-	mmc->getwp = NULL;
+	mmc->ops = &bfin_mmc_ops;
 	mmc->host_caps = MMC_MODE_4BIT;
 
 	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c
index b380961..29ca4a6 100644
--- a/drivers/mmc/davinci_mmc.c
+++ b/drivers/mmc/davinci_mmc.c
@@ -363,6 +363,12 @@ static void dmmc_set_ios(struct mmc *mmc)
 		dmmc_set_clock(mmc, mmc->clock);
 }
 
+static const struct mmc_ops dmmc_ops = {
+	.send_cmd	= dmmc_send_cmd,
+	.set_ios	= dmmc_set_ios,
+	.init		= dmmc_init,
+};
+
 /* Called from board_mmc_init during startup. Can be called multiple times
  * depending on the number of slots available on board and controller
  */
@@ -375,12 +381,7 @@ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
 
 	sprintf(mmc->name, "davinci");
 	mmc->priv = host;
-	mmc->send_cmd = dmmc_send_cmd;
-	mmc->set_ios = dmmc_set_ios;
-	mmc->init = dmmc_init;
-	mmc->getcd = NULL;
-	mmc->getwp = NULL;
-
+	mmc->ops = &dmmc_ops;
 	mmc->f_min = 200000;
 	mmc->f_max = 25000000;
 	mmc->voltages = host->voltages;
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index d45c15c..2e6576e 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -343,6 +343,12 @@ static int dwmci_init(struct mmc *mmc)
 	return 0;
 }
 
+static const struct mmc_ops dwmci_ops = {
+	.send_cmd	= dwmci_send_cmd,
+	.set_ios	= dwmci_set_ios,
+	.init		= dwmci_init,
+};
+
 int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
 {
 	struct mmc *mmc;
@@ -358,9 +364,7 @@ int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
 	host->mmc = mmc;
 
 	sprintf(mmc->name, "%s", host->name);
-	mmc->send_cmd = dwmci_send_cmd;
-	mmc->set_ios = dwmci_set_ios;
-	mmc->init = dwmci_init;
+	mmc->ops = &dwmci_ops;
 	mmc->f_min = min_clk;
 	mmc->f_max = max_clk;
 
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 7b146a3..861f536 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -524,6 +524,13 @@ static void esdhc_reset(struct fsl_esdhc *regs)
 		printf("MMC/SD: Reset never completed.\n");
 }
 
+static const struct mmc_ops esdhc_ops = {
+	.send_cmd	= esdhc_send_cmd,
+	.set_ios	= esdhc_set_ios,
+	.init		= esdhc_init,
+	.getcd		= esdhc_getcd,
+};
+
 int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 {
 	struct fsl_esdhc *regs;
@@ -548,12 +555,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 				| SYSCTL_IPGEN | SYSCTL_CKEN);
 
 	mmc->priv = cfg;
-	mmc->send_cmd = esdhc_send_cmd;
-	mmc->set_ios = esdhc_set_ios;
-	mmc->init = esdhc_init;
-	mmc->getcd = esdhc_getcd;
-	mmc->getwp = NULL;
-
+	mmc->ops = &esdhc_ops;
 	voltage_caps = 0;
 	caps = regs->hostcapblt;
 
diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c
index 7600d5c..ce43ae1 100644
--- a/drivers/mmc/ftsdc010_mci.c
+++ b/drivers/mmc/ftsdc010_mci.c
@@ -316,6 +316,12 @@ static int ftsdc010_init(struct mmc *mmc)
 	return 0;
 }
 
+static const struct mmc_ops ftsdc010_ops = {
+	.send_cmd	= ftsdc010_request,
+	.set_ios	= ftsdc010_set_ios,
+	.init		= ftsdc010_init,
+};
+
 int ftsdc010_mmc_init(int devid)
 {
 	struct mmc *mmc;
@@ -347,10 +353,7 @@ int ftsdc010_mmc_init(int devid)
 	mmc->priv  = chip;
 
 	sprintf(mmc->name, "ftsdc010");
-	mmc->send_cmd  = ftsdc010_request;
-	mmc->set_ios   = ftsdc010_set_ios;
-	mmc->init      = ftsdc010_init;
-
+	mmc->ops = &ftsdc010_ops;
 	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
 	switch (readl(&regs->bwr) & FTSDC010_BWR_CAPS_MASK) {
 	case FTSDC010_BWR_CAPS_4BIT:
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index c11dcd0..456f8bf 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -344,6 +344,12 @@ static int mci_init(struct mmc *mmc)
 	return 0;
 }
 
+static const struct mmc_ops atmel_mci_ops = {
+	.send_cmd	= mci_send_cmd,
+	.set_ios	= mci_set_ios,
+	.init		= mci_init,
+};
+
 /*
  * This is the only exported function
  *
@@ -360,11 +366,7 @@ int atmel_mci_init(void *regs)
 
 	strcpy(mmc->name, "mci");
 	mmc->priv = regs;
-	mmc->send_cmd = mci_send_cmd;
-	mmc->set_ios = mci_set_ios;
-	mmc->init = mci_init;
-	mmc->getcd = NULL;
-	mmc->getwp = NULL;
+	mmc->ops = &atmel_mci_ops;
 
 	/* need to be able to pass these in on a board by board basis */
 	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 8ab0bc9..ac07bb9 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -37,8 +37,8 @@ int mmc_getwp(struct mmc *mmc)
 	wp = board_mmc_getwp(mmc);
 
 	if (wp < 0) {
-		if (mmc->getwp)
-			wp = mmc->getwp(mmc);
+		if (mmc->ops->getwp)
+			wp = mmc->ops->getwp(mmc);
 		else
 			wp = 0;
 	}
@@ -63,7 +63,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 
 	printf("CMD_SEND:%d\n", cmd->cmdidx);
 	printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
-	ret = mmc->send_cmd(mmc, cmd, data);
+	ret = mmc->ops->send_cmd(mmc, cmd, data);
 	switch (cmd->resp_type) {
 		case MMC_RSP_NONE:
 			printf("\t\tMMC_RSP_NONE\n");
@@ -106,7 +106,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 			break;
 	}
 #else
-	ret = mmc->send_cmd(mmc, cmd, data);
+	ret = mmc->ops->send_cmd(mmc, cmd, data);
 #endif
 	return ret;
 }
@@ -578,8 +578,8 @@ int mmc_getcd(struct mmc *mmc)
 	cd = board_mmc_getcd(mmc);
 
 	if (cd < 0) {
-		if (mmc->getcd)
-			cd = mmc->getcd(mmc);
+		if (mmc->ops->getcd)
+			cd = mmc->ops->getcd(mmc);
 		else
 			cd = 1;
 	}
@@ -751,7 +751,8 @@ static const int multipliers[] = {
 
 static void mmc_set_ios(struct mmc *mmc)
 {
-	mmc->set_ios(mmc);
+	if (mmc->ops->set_ios)
+		mmc->ops->set_ios(mmc);
 }
 
 void mmc_set_clock(struct mmc *mmc, uint clock)
@@ -1207,7 +1208,8 @@ int mmc_start_init(struct mmc *mmc)
 {
 	int err;
 
-	if (mmc_getcd(mmc) == 0) {
+	/* we pretend there's no card when init is NULL */
+	if (mmc_getcd(mmc) == 0 || mmc->ops->init == NULL) {
 		mmc->has_init = 0;
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 		printf("MMC: no card present\n");
@@ -1218,7 +1220,8 @@ int mmc_start_init(struct mmc *mmc)
 	if (mmc->has_init)
 		return 0;
 
-	err = mmc->init(mmc);
+	/* made sure it's not NULL earlier */
+	err = mmc->ops->init(mmc);
 
 	if (err)
 		return err;
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index fe6a5a1..0a0f894 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -255,6 +255,12 @@ static int mmc_spi_init_p(struct mmc *mmc)
 	return 0;
 }
 
+static const struct mmc_ops mmc_spi_ops = {
+	.send_cmd	= mmc_spi_request,
+	.set_ios	= mmc_spi_set_ios,
+	.init		= mmc_spi_init_p,
+};
+
 struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
 {
 	struct mmc *mmc;
@@ -269,11 +275,7 @@ struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
 		return NULL;
 	}
 	sprintf(mmc->name, "MMC_SPI");
-	mmc->send_cmd = mmc_spi_request;
-	mmc->set_ios = mmc_spi_set_ios;
-	mmc->init = mmc_spi_init_p;
-	mmc->getcd = NULL;
-	mmc->getwp = NULL;
+	mmc->ops = &mmc_spi_ops;
 	mmc->host_caps = MMC_MODE_SPI;
 
 	mmc->voltages = MMC_SPI_VOLTAGE;
diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c
index 4f99617..f3e1eed 100644
--- a/drivers/mmc/mxcmmc.c
+++ b/drivers/mmc/mxcmmc.c
@@ -485,6 +485,12 @@ static int mxcmci_init(struct mmc *mmc)
 	return 0;
 }
 
+static const struct mmc_ops mxcmci_ops = {
+	.send_cmd	= mxcmci_request,
+	.set_ios	= mxcmci_set_ios,
+	.init		= mxcmci_init,
+};
+
 static int mxcmci_initialize(bd_t *bis)
 {
 	struct mmc *mmc = NULL;
@@ -495,11 +501,7 @@ static int mxcmci_initialize(bd_t *bis)
 		return -ENOMEM;
 
 	sprintf(mmc->name, "MXC MCI");
-	mmc->send_cmd = mxcmci_request;
-	mmc->set_ios = mxcmci_set_ios;
-	mmc->init = mxcmci_init;
-	mmc->getcd = NULL;
-	mmc->getwp = NULL;
+	mmc->ops = &mxcmci_ops;
 	mmc->host_caps = MMC_MODE_4BIT;
 
 	host->base = (struct mxcmci_regs *)CONFIG_MXC_MCI_REGS_BASE;
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index 245f9d0..97c9ee8 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -363,6 +363,12 @@ static int mxsmmc_init(struct mmc *mmc)
 	return 0;
 }
 
+static const struct mmc_ops mxsmmc_ops = {
+	.send_cmd	= mxsmmc_send_cmd,
+	.set_ios	= mxsmmc_set_ios,
+	.init		= mxsmmc_init,
+};
+
 int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
 {
 	struct mmc *mmc = NULL;
@@ -400,11 +406,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
 	priv->regs = mxs_ssp_regs_by_bus(id);
 
 	sprintf(mmc->name, "MXS MMC");
-	mmc->send_cmd = mxsmmc_send_cmd;
-	mmc->set_ios = mxsmmc_set_ios;
-	mmc->init = mxsmmc_init;
-	mmc->getcd = NULL;
-	mmc->getwp = NULL;
+	mmc->ops = &mxsmmc_ops;
 	mmc->priv = priv;
 
 	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index d3a8b53..6bf602f 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -35,14 +35,24 @@
 #include <asm/arch/mmc_host_def.h>
 #include <asm/arch/sys_proto.h>
 
+/* simplify defines to OMAP_HSMMC_USE_GPIO */
+#if (defined(CONFIG_OMAP_GPIO) && !defined(CONFIG_SPL_BUILD)) || \
+	(defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
+#define OMAP_HSMMC_USE_GPIO
+#else
+#undef OMAP_HSMMC_USE_GPIO
+#endif
+
 /* common definitions for all OMAPs */
 #define SYSCTL_SRC	(1 << 25)
 #define SYSCTL_SRD	(1 << 26)
 
 struct omap_hsmmc_data {
 	struct hsmmc *base_addr;
+#ifdef OMAP_HSMMC_USE_GPIO
 	int cd_gpio;
 	int wp_gpio;
+#endif
 };
 
 /* If we fail after 1 second wait, something is really bad */
@@ -54,8 +64,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
 static struct mmc hsmmc_dev[3];
 static struct omap_hsmmc_data hsmmc_dev_data[3];
 
-#if (defined(CONFIG_OMAP_GPIO) && !defined(CONFIG_SPL_BUILD)) || \
-	(defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
+#ifdef OMAP_HSMMC_USE_GPIO
 static int omap_mmc_setup_gpio_in(int gpio, const char *label)
 {
 	if (!gpio_is_valid(gpio))
@@ -69,26 +78,6 @@ static int omap_mmc_setup_gpio_in(int gpio, const char *label)
 
 	return gpio;
 }
-
-static int omap_mmc_getcd(struct mmc *mmc)
-{
-	int cd_gpio = ((struct omap_hsmmc_data *)mmc->priv)->cd_gpio;
-	return gpio_get_value(cd_gpio);
-}
-
-static int omap_mmc_getwp(struct mmc *mmc)
-{
-	int wp_gpio = ((struct omap_hsmmc_data *)mmc->priv)->wp_gpio;
-	return gpio_get_value(wp_gpio);
-}
-#else
-static inline int omap_mmc_setup_gpio_in(int gpio, const char *label)
-{
-	return -1;
-}
-
-#define omap_mmc_getcd NULL
-#define omap_mmc_getwp NULL
 #endif
 
 #if defined(CONFIG_OMAP44XX) && defined(CONFIG_TWL6030_POWER)
@@ -213,7 +202,7 @@ void mmc_init_stream(struct hsmmc *mmc_base)
 }
 
 
-static int mmc_init_setup(struct mmc *mmc)
+static int omap_hsmmc_init_setup(struct mmc *mmc)
 {
 	struct hsmmc *mmc_base;
 	unsigned int reg_val;
@@ -322,7 +311,7 @@ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit)
 	}
 }
 
-static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+static int omap_hsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 			struct mmc_data *data)
 {
 	struct hsmmc *mmc_base;
@@ -552,7 +541,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
 	return 0;
 }
 
-static void mmc_set_ios(struct mmc *mmc)
+static void omap_hsmmc_set_ios(struct mmc *mmc)
 {
 	struct hsmmc *mmc_base;
 	unsigned int dsor = 0;
@@ -606,6 +595,44 @@ static void mmc_set_ios(struct mmc *mmc)
 	writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
 }
 
+#ifdef OMAP_HSMMC_USE_GPIO
+static int omap_hsmmc_getcd(struct mmc *mmc)
+{
+	struct omap_hsmmc_data *priv_data = mmc->priv;
+	int cd_gpio;
+
+	/* if no CD return as 1 */
+	cd_gpio = priv_data->cd_gpio;
+	if (cd_gpio < 0)
+		return 1;
+
+	return gpio_get_value(cd_gpio);
+}
+
+static int omap_hsmmc_getwp(struct mmc *mmc)
+{
+	struct omap_hsmmc_data *priv_data = mmc->priv;
+	int wp_gpio;
+
+	/* if no WP return as 0 */
+	wp_gpio = priv_data->wp_gpio;
+	if (wp_gpio < 0)
+		return 0;
+
+	return gpio_get_value(wp_gpio);
+}
+#endif
+
+static const struct mmc_ops omap_hsmmc_ops = {
+	.send_cmd	= omap_hsmmc_send_cmd,
+	.set_ios	= omap_hsmmc_set_ios,
+	.init		= omap_hsmmc_init_setup,
+#ifdef OMAP_HSMMC_USE_GPIO
+	.getcd		= omap_hsmmc_getcd,
+	.getwp		= omap_hsmmc_getwp,
+#endif
+};
+
 int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 		int wp_gpio)
 {
@@ -615,9 +642,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 			     MMC_MODE_HC;
 
 	sprintf(mmc->name, "OMAP SD/MMC");
-	mmc->send_cmd = mmc_send_cmd;
-	mmc->set_ios = mmc_set_ios;
-	mmc->init = mmc_init_setup;
+	mmc->ops = &omap_hsmmc_ops;
 	mmc->priv = priv_data;
 
 	switch (dev_index) {
@@ -647,13 +672,11 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 		priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE;
 		return 1;
 	}
+#ifdef OMAP_HSMMC_USE_GPIO
+	/* on error gpio values are set to -1, which is what we want */
 	priv_data->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd");
-	if (priv_data->cd_gpio != -1)
-		mmc->getcd = omap_mmc_getcd;
-
 	priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");
-	if (priv_data->wp_gpio != -1)
-		mmc->getwp = omap_mmc_getwp;
+#endif
 
 	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	mmc->host_caps = host_caps_val & ~host_caps_mask;
diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c
index 29f3eaf..4694c8f 100644
--- a/drivers/mmc/pxa_mmc_gen.c
+++ b/drivers/mmc/pxa_mmc_gen.c
@@ -366,6 +366,12 @@ static int pxa_mmc_init(struct mmc *mmc)
 	return 0;
 }
 
+static const struct mmc_ops pxa_mmc_ops = {
+	.send_cmd	= pxa_mmc_request,
+	.set_ios	= pxa_mmc_set_ios,
+	.init		= pxa_mmc_init,
+};
+
 int pxa_mmc_register(int card_index)
 {
 	struct mmc *mmc;
@@ -397,10 +403,7 @@ int pxa_mmc_register(int card_index)
 	mmc->priv = priv;
 
 	sprintf(mmc->name, "PXA MMC");
-	mmc->send_cmd	= pxa_mmc_request;
-	mmc->set_ios	= pxa_mmc_set_ios;
-	mmc->init	= pxa_mmc_init;
-	mmc->getcd	= NULL;
+	mmc->ops = &pxa_mmc_ops;
 
 	mmc->voltages	= MMC_VDD_32_33 | MMC_VDD_33_34;
 	mmc->f_max	= PXAMMC_MAX_SPEED;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 1e86b92..c3425a6 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -430,6 +430,13 @@ int sdhci_init(struct mmc *mmc)
 	return 0;
 }
 
+
+static const struct mmc_ops sdhci_ops = {
+	.send_cmd	= sdhci_send_command,
+	.set_ios	= sdhci_set_ios,
+	.init		= sdhci_init,
+};
+
 int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
 {
 	struct mmc *mmc;
@@ -445,11 +452,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
 	host->mmc = mmc;
 
 	sprintf(mmc->name, "%s", host->name);
-	mmc->send_cmd = sdhci_send_command;
-	mmc->set_ios = sdhci_set_ios;
-	mmc->init = sdhci_init;
-	mmc->getcd = NULL;
-	mmc->getwp = NULL;
+	mmc->ops = &sdhci_ops;
 
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
 #ifdef CONFIG_MMC_SDMA
diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c
index 011d4f3..6a4860b 100644
--- a/drivers/mmc/sh_mmcif.c
+++ b/drivers/mmc/sh_mmcif.c
@@ -574,6 +574,12 @@ static int sh_mmcif_init(struct mmc *mmc)
 	return 0;
 }
 
+static const struct mmc_ops sh_mmcif_ops = {
+	.send_cmd	= sh_mmcif_request,
+	.set_ios	= sh_mmcif_set_ios,
+	.init		= sh_mmcif_init,
+};
+
 int mmcif_mmc_init(void)
 {
 	int ret = 0;
@@ -595,11 +601,7 @@ int mmcif_mmc_init(void)
 	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT |
 			 MMC_MODE_8BIT | MMC_MODE_HC;
 	memcpy(mmc->name, DRIVER_NAME, sizeof(DRIVER_NAME));
-	mmc->send_cmd = sh_mmcif_request;
-	mmc->set_ios = sh_mmcif_set_ios;
-	mmc->init = sh_mmcif_init;
-	mmc->getcd = NULL;
-	mmc->getwp = NULL;
+	mmc->ops = &sh_mmcif_ops;
 	host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR;
 	host->clk = CONFIG_SH_MMCIF_CLK;
 	mmc->priv = host;
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 3d1ce12..5f7b590 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -314,7 +314,7 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
 	return 0;
 }
 
-static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+static int tegra_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 			struct mmc_data *data)
 {
 	void *buf;
@@ -396,7 +396,7 @@ out:
 	host->clock = clock;
 }
 
-static void mmc_set_ios(struct mmc *mmc)
+static void tegra_mmc_set_ios(struct mmc *mmc)
 {
 	struct mmc_host *host = mmc->priv;
 	unsigned char ctrl;
@@ -464,7 +464,7 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc)
 	pad_init_mmc(host);
 }
 
-static int mmc_core_init(struct mmc *mmc)
+static int tegra_mmc_core_init(struct mmc *mmc)
 {
 	struct mmc_host *host = (struct mmc_host *)mmc->priv;
 	unsigned int mask;
@@ -521,6 +521,13 @@ int tegra_mmc_getcd(struct mmc *mmc)
 	return 1;
 }
 
+static const struct mmc_ops tegra_mmc_ops = {
+	.send_cmd	= tegra_mmc_send_cmd,
+	.set_ios	= tegra_mmc_set_ios,
+	.init		= tegra_mmc_core_init,
+	.getcd		= tegra_mmc_getcd,
+};
+
 static int do_mmc_init(int dev_index)
 {
 	struct mmc_host *host;
@@ -558,11 +565,7 @@ static int do_mmc_init(int dev_index)
 
 	sprintf(mmc->name, "Tegra SD/MMC");
 	mmc->priv = host;
-	mmc->send_cmd = mmc_send_cmd;
-	mmc->set_ios = mmc_set_ios;
-	mmc->init = mmc_core_init;
-	mmc->getcd = tegra_mmc_getcd;
-	mmc->getwp = NULL;
+	mmc->ops = &tegra_mmc_ops;
 
 	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	mmc->host_caps = 0;
diff --git a/include/mmc.h b/include/mmc.h
index e95a237..3d53ce1 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -250,6 +250,18 @@ struct mmc_data {
 	uint blocksize;
 };
 
+/* forward decl. */
+struct mmc;
+
+struct mmc_ops {
+	int (*send_cmd)(struct mmc *mmc,
+			struct mmc_cmd *cmd, struct mmc_data *data);
+	void (*set_ios)(struct mmc *mmc);
+	int (*init)(struct mmc *mmc);
+	int (*getcd)(struct mmc *mmc);
+	int (*getwp)(struct mmc *mmc);
+};
+
 struct mmc {
 	struct list_head link;
 	char name[32];
@@ -283,12 +295,7 @@ struct mmc {
 	u64 capacity_rpmb;
 	u64 capacity_gp[4];
 	block_dev_desc_t block_dev;
-	int (*send_cmd)(struct mmc *mmc,
-			struct mmc_cmd *cmd, struct mmc_data *data);
-	void (*set_ios)(struct mmc *mmc);
-	int (*init)(struct mmc *mmc);
-	int (*getcd)(struct mmc *mmc);
-	int (*getwp)(struct mmc *mmc);
+	const struct mmc_ops *ops;
 	uint b_max;
 	char op_cond_pending;	/* 1 if we are waiting on an op_cond command */
 	char init_in_progress;	/* 1 if we have done mmc_start_init() */
-- 
1.7.12

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 2/3] mmc: Convert mmc struct's name array to a pointer
  2014-03-12 10:24 [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct Pantelis Antoniou
  2014-03-12 10:24 ` [U-Boot] [PATCH 1/3] mmc: Remove ops from struct mmc and put in mmc_ops Pantelis Antoniou
@ 2014-03-12 10:24 ` Pantelis Antoniou
  2014-03-14 20:55   ` Simon Glass
  2014-03-12 10:24 ` [U-Boot] [PATCH 3/3] mmc: Split mmc struct, rework mmc initialization Pantelis Antoniou
  2014-03-12 11:32 ` [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct Marek Vasut
  3 siblings, 1 reply; 10+ messages in thread
From: Pantelis Antoniou @ 2014-03-12 10:24 UTC (permalink / raw)
  To: u-boot

Using an array is pointless; even more pointless (and scary) is using
sprintf to fill it without a format string.

Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
---
 drivers/mmc/arm_pl180_mmci.c | 2 +-
 drivers/mmc/bfin_sdh.c       | 2 +-
 drivers/mmc/davinci_mmc.c    | 2 +-
 drivers/mmc/dw_mmc.c         | 2 +-
 drivers/mmc/fsl_esdhc.c      | 2 +-
 drivers/mmc/ftsdc010_mci.c   | 2 +-
 drivers/mmc/gen_atmel_mci.c  | 2 +-
 drivers/mmc/mmc_spi.c        | 2 +-
 drivers/mmc/mxcmmc.c         | 2 +-
 drivers/mmc/mxsmmc.c         | 2 +-
 drivers/mmc/omap_hsmmc.c     | 2 +-
 drivers/mmc/pxa_mmc_gen.c    | 2 +-
 drivers/mmc/sdhci.c          | 2 +-
 drivers/mmc/sh_mmcif.c       | 2 +-
 drivers/mmc/tegra_mmc.c      | 2 +-
 include/mmc.h                | 2 +-
 16 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index 4490e97..5a30590 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -365,7 +365,7 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host)
 	/* Disable mmc interrupts */
 	sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
 	writel(sdi_u32, &host->base->mask0);
-	strncpy(dev->name, host->name, sizeof(dev->name));
+	dev->name = host->name;
 	dev->ops = &arm_pl180_mmci_ops;
 	dev->host_caps = host->caps;
 	dev->voltages = host->voltages;
diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c
index f0871ec..5f6145b 100644
--- a/drivers/mmc/bfin_sdh.c
+++ b/drivers/mmc/bfin_sdh.c
@@ -288,7 +288,7 @@ int bfin_mmc_init(bd_t *bis)
 
 	if (!mmc)
 		return -ENOMEM;
-	sprintf(mmc->name, "Blackfin SDH");
+	mmc->name = "Blackfin SDH";
 	mmc->ops = &bfin_mmc_ops;
 	mmc->host_caps = MMC_MODE_4BIT;
 
diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c
index 29ca4a6..cae972a 100644
--- a/drivers/mmc/davinci_mmc.c
+++ b/drivers/mmc/davinci_mmc.c
@@ -379,7 +379,7 @@ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
 	mmc = malloc(sizeof(struct mmc));
 	memset(mmc, 0, sizeof(struct mmc));
 
-	sprintf(mmc->name, "davinci");
+	mmc->name = "davinci";
 	mmc->priv = host;
 	mmc->ops = &dmmc_ops;
 	mmc->f_min = 200000;
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 2e6576e..011efb1 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -363,7 +363,7 @@ int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
 	mmc->priv = host;
 	host->mmc = mmc;
 
-	sprintf(mmc->name, "%s", host->name);
+	mmc->name = host->name;
 	mmc->ops = &dwmci_ops;
 	mmc->f_min = min_clk;
 	mmc->f_max = max_clk;
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 861f536..f66513e 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -545,7 +545,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 		return -ENOMEM;
 
 	memset(mmc, 0, sizeof(struct mmc));
-	sprintf(mmc->name, "FSL_SDHC");
+	mmc->name = "FSL_SDHC";
 	regs = (struct fsl_esdhc *)cfg->esdhc_base;
 
 	/* First reset the eSDHC controller */
diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c
index ce43ae1..b1673fc 100644
--- a/drivers/mmc/ftsdc010_mci.c
+++ b/drivers/mmc/ftsdc010_mci.c
@@ -352,7 +352,7 @@ int ftsdc010_mmc_init(int devid)
 	chip->regs = regs;
 	mmc->priv  = chip;
 
-	sprintf(mmc->name, "ftsdc010");
+	mmc->name = "ftsdc010";
 	mmc->ops = &ftsdc010_ops;
 	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
 	switch (readl(&regs->bwr) & FTSDC010_BWR_CAPS_MASK) {
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index 456f8bf..ce799f3 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -364,7 +364,7 @@ int atmel_mci_init(void *regs)
 	if (!mmc)
 		return -1;
 
-	strcpy(mmc->name, "mci");
+	mmc->name = "mci";
 	mmc->priv = regs;
 	mmc->ops = &atmel_mci_ops;
 
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index 0a0f894..e94de37 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -274,7 +274,7 @@ struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
 		free(mmc);
 		return NULL;
 	}
-	sprintf(mmc->name, "MMC_SPI");
+	mmc->name = "MMC_SPI";
 	mmc->ops = &mmc_spi_ops;
 	mmc->host_caps = MMC_MODE_SPI;
 
diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c
index f3e1eed..3357559 100644
--- a/drivers/mmc/mxcmmc.c
+++ b/drivers/mmc/mxcmmc.c
@@ -500,7 +500,7 @@ static int mxcmci_initialize(bd_t *bis)
 	if (!mmc)
 		return -ENOMEM;
 
-	sprintf(mmc->name, "MXC MCI");
+	mmc->name = "MXC MCI";
 	mmc->ops = &mxcmci_ops;
 	mmc->host_caps = MMC_MODE_4BIT;
 
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index 97c9ee8..3512a99 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -405,7 +405,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
 	priv->id = id;
 	priv->regs = mxs_ssp_regs_by_bus(id);
 
-	sprintf(mmc->name, "MXS MMC");
+	mmc->name = "MXS MMC";
 	mmc->ops = &mxsmmc_ops;
 	mmc->priv = priv;
 
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 6bf602f..fecac56 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -641,7 +641,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 	uint host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
 			     MMC_MODE_HC;
 
-	sprintf(mmc->name, "OMAP SD/MMC");
+	mmc->name = "OMAP SD/MMC";
 	mmc->ops = &omap_hsmmc_ops;
 	mmc->priv = priv_data;
 
diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c
index 4694c8f..188e1d4 100644
--- a/drivers/mmc/pxa_mmc_gen.c
+++ b/drivers/mmc/pxa_mmc_gen.c
@@ -402,7 +402,7 @@ int pxa_mmc_register(int card_index)
 
 	mmc->priv = priv;
 
-	sprintf(mmc->name, "PXA MMC");
+	mmc->name = "PXA MMC";
 	mmc->ops = &pxa_mmc_ops;
 
 	mmc->voltages	= MMC_VDD_32_33 | MMC_VDD_33_34;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index c3425a6..dc6f4e4 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -451,7 +451,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
 	mmc->priv = host;
 	host->mmc = mmc;
 
-	sprintf(mmc->name, "%s", host->name);
+	mmc->name = host->name;
 	mmc->ops = &sdhci_ops;
 
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c
index 6a4860b..008617d 100644
--- a/drivers/mmc/sh_mmcif.c
+++ b/drivers/mmc/sh_mmcif.c
@@ -600,7 +600,7 @@ int mmcif_mmc_init(void)
 	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT |
 			 MMC_MODE_8BIT | MMC_MODE_HC;
-	memcpy(mmc->name, DRIVER_NAME, sizeof(DRIVER_NAME));
+	mmc->name = DRIVER_NAME;
 	mmc->ops = &sh_mmcif_ops;
 	host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR;
 	host->clk = CONFIG_SH_MMCIF_CLK;
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 5f7b590..e8fbb63 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -563,7 +563,7 @@ static int do_mmc_init(int dev_index)
 
 	mmc = &mmc_dev[dev_index];
 
-	sprintf(mmc->name, "Tegra SD/MMC");
+	mmc->name = "Tegra SD/MMC";
 	mmc->priv = host;
 	mmc->ops = &tegra_mmc_ops;
 
diff --git a/include/mmc.h b/include/mmc.h
index 3d53ce1..6b08c62 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -264,7 +264,7 @@ struct mmc_ops {
 
 struct mmc {
 	struct list_head link;
-	char name[32];
+	const char *name;	/* no need for this to be an array */
 	void *priv;
 	uint voltages;
 	uint version;
-- 
1.7.12

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 3/3] mmc: Split mmc struct, rework mmc initialization
  2014-03-12 10:24 [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct Pantelis Antoniou
  2014-03-12 10:24 ` [U-Boot] [PATCH 1/3] mmc: Remove ops from struct mmc and put in mmc_ops Pantelis Antoniou
  2014-03-12 10:24 ` [U-Boot] [PATCH 2/3] mmc: Convert mmc struct's name array to a pointer Pantelis Antoniou
@ 2014-03-12 10:24 ` Pantelis Antoniou
  2014-03-14 20:56   ` Simon Glass
  2014-03-12 11:32 ` [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct Marek Vasut
  3 siblings, 1 reply; 10+ messages in thread
From: Pantelis Antoniou @ 2014-03-12 10:24 UTC (permalink / raw)
  To: u-boot

The way that struct mmc was implemented was a bit of a mess;
configuration and internal state all jumbled up in a single structure.

On top of that the way initialization is done with mmc_register leads
to a lot of duplicated code in drivers.

Typically the initialization got something like this in every driver.

	struct mmc *mmc = malloc(sizeof(struct mmc));
	memset(mmc, 0, sizeof(struct mmc);
	/* fill in fields of mmc struct */
	/* store private data pointer */
	mmc_register(mmc);

By using the new mmc_create call one just passes an mmc config struct
and an optional private data pointer like this:

	struct mmc = mmc_create(&cfg, priv);

All in tree drivers have been updated to the new form, and expect
mmc_register to go away before long.

Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
---
 arch/arm/include/asm/arch-davinci/sdmmc_defs.h |  1 +
 arch/arm/include/asm/arch-tegra/tegra_mmc.h    |  4 ++
 common/cmd_mmc.c                               |  2 +-
 common/cmd_mmc_spi.c                           |  2 +-
 drivers/mmc/arm_pl180_mmci.c                   | 40 ++++++------
 drivers/mmc/arm_pl180_mmci.h                   |  4 ++
 drivers/mmc/bfin_sdh.c                         | 31 +++++----
 drivers/mmc/davinci_mmc.c                      | 30 ++++-----
 drivers/mmc/dw_mmc.c                           | 50 +++++++--------
 drivers/mmc/fsl_esdhc.c                        | 55 ++++++++--------
 drivers/mmc/ftsdc010_mci.c                     | 54 +++++++---------
 drivers/mmc/gen_atmel_mci.c                    | 43 ++++++++-----
 drivers/mmc/mmc.c                              | 87 +++++++++++++++++---------
 drivers/mmc/mmc_spi.c                          | 40 ++++++------
 drivers/mmc/mmc_write.c                        |  3 +-
 drivers/mmc/mxcmmc.c                           | 35 +++++------
 drivers/mmc/mxsmmc.c                           | 38 ++++++-----
 drivers/mmc/omap_hsmmc.c                       | 55 +++++++++-------
 drivers/mmc/pxa_mmc_gen.c                      | 61 +++++++++---------
 drivers/mmc/sdhci.c                            | 73 +++++++++++----------
 drivers/mmc/sh_mmcif.c                         | 42 ++++++-------
 drivers/mmc/tegra_mmc.c                        | 36 ++++++-----
 include/dwmmc.h                                |  2 +
 include/fsl_esdhc.h                            |  4 ++
 include/mmc.h                                  | 31 ++++++---
 include/sdhci.h                                |  2 +
 26 files changed, 433 insertions(+), 392 deletions(-)

diff --git a/arch/arm/include/asm/arch-davinci/sdmmc_defs.h b/arch/arm/include/asm/arch-davinci/sdmmc_defs.h
index 3e9e606..9aa3f4a 100644
--- a/arch/arm/include/asm/arch-davinci/sdmmc_defs.h
+++ b/arch/arm/include/asm/arch-davinci/sdmmc_defs.h
@@ -151,6 +151,7 @@ struct davinci_mmc {
 	uint host_caps;		/* Host capabilities */
 	uint voltages;		/* Host supported voltages */
 	uint version;		/* MMC Controller version */
+	struct mmc_config cfg;
 };
 
 enum {
diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
index b6896af..310bbd7 100644
--- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
+++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
@@ -11,6 +11,9 @@
 
 #include <fdtdec.h>
 
+/* for mmc_config definition */
+#include <mmc.h>
+
 #define MAX_HOSTS		4	/* Max number of 'hosts'/controllers */
 
 #ifndef __ASSEMBLY__
@@ -138,6 +141,7 @@ struct mmc_host {
 	struct fdt_gpio_state wp_gpio;		/* Write Protect GPIO */
 	unsigned int version;	/* SDHCI spec. version */
 	unsigned int clock;	/* Current clock (MHz) */
+	struct mmc_config cfg;	/* mmc configuration */
 };
 
 void pad_init_mmc(struct mmc_host *host);
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 2d51927..bd1edc8 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -79,7 +79,7 @@ enum mmc_state {
 };
 static void print_mmcinfo(struct mmc *mmc)
 {
-	printf("Device: %s\n", mmc->name);
+	printf("Device: %s\n", mmc->cfg->name);
 	printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24);
 	printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff);
 	printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff,
diff --git a/common/cmd_mmc_spi.c b/common/cmd_mmc_spi.c
index 98cd788..a2138b8 100644
--- a/common/cmd_mmc_spi.c
+++ b/common/cmd_mmc_spi.c
@@ -72,7 +72,7 @@ static int do_mmc_spi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		printf("Failed to create MMC Device\n");
 		return 1;
 	}
-	printf("%s: %d at %u:%u hz %u mode %u\n", mmc->name, mmc->block_dev.dev,
+	printf("%s: %d at %u:%u hz %u mode %u\n", mmc->cfg->name, mmc->block_dev.dev,
 	       bus, cs, speed, mode);
 	mmc_init(mmc);
 	return 0;
diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index 5a30590..5ef7ff7 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -287,9 +287,9 @@ static void host_set_ios(struct mmc *dev)
 		u32 clkdiv = 0;
 		u32 tmp_clock;
 
-		if (dev->clock >= dev->f_max) {
+		if (dev->clock >= dev->cfg->f_max) {
 			clkdiv = 0;
-			dev->clock = dev->f_max;
+			dev->clock = dev->cfg->f_max;
 		} else {
 			clkdiv = (host->clock_in / dev->clock) - 2;
 		}
@@ -348,16 +348,9 @@ static const struct mmc_ops arm_pl180_mmci_ops = {
  */
 int arm_pl180_mmci_init(struct pl180_mmc_host *host)
 {
-	struct mmc *dev;
+	struct mmc *mmc;
 	u32 sdi_u32;
 
-	dev = malloc(sizeof(struct mmc));
-	if (!dev)
-		return -ENOMEM;
-
-	memset(dev, 0, sizeof(struct mmc));
-	dev->priv = host;
-
 	writel(host->pwr_init, &host->base->power);
 	writel(host->clkdiv_init, &host->base->clock);
 	udelay(CLK_CHANGE_DELAY);
@@ -365,15 +358,24 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host)
 	/* Disable mmc interrupts */
 	sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
 	writel(sdi_u32, &host->base->mask0);
-	dev->name = host->name;
-	dev->ops = &arm_pl180_mmci_ops;
-	dev->host_caps = host->caps;
-	dev->voltages = host->voltages;
-	dev->f_min = host->clock_min;
-	dev->f_max = host->clock_max;
-	dev->b_max = host->b_max;
-	mmc_register(dev);
-	debug("registered mmc interface number is:%d\n", dev->block_dev.dev);
+
+	host->cfg.name = host->name;
+	host->cfg.ops = &arm_pl180_mmci_ops;
+	/* TODO remove the duplicates */
+	host->cfg.host_caps = host->caps;
+	host->cfg.voltages = host->voltages;
+	host->cfg.f_min = host->clock_min;
+	host->cfg.f_max = host->clock_max;
+	if (host->b_max != 0)
+		host->cfg.b_max = host->b_max;
+	else
+		host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+	mmc = mmc_create(&host->cfg, host);
+	if (mmc == NULL)
+		return -1;
+
+	debug("registered mmc interface number is:%d\n", mmc->block_dev.dev);
 
 	return 0;
 }
diff --git a/drivers/mmc/arm_pl180_mmci.h b/drivers/mmc/arm_pl180_mmci.h
index 7234449..f23bd39 100644
--- a/drivers/mmc/arm_pl180_mmci.h
+++ b/drivers/mmc/arm_pl180_mmci.h
@@ -13,6 +13,9 @@
 #ifndef __ARM_PL180_MMCI_H__
 #define __ARM_PL180_MMCI_H__
 
+/* need definition of struct mmc_config */
+#include <mmc.h>
+
 #define COMMAND_REG_DELAY	300
 #define DATA_REG_DELAY		1000
 #define CLK_CHANGE_DELAY	2000
@@ -184,6 +187,7 @@ struct pl180_mmc_host {
 	unsigned int clkdiv_init;
 	unsigned int pwr_init;
 	int version2;
+	struct mmc_config cfg;
 };
 
 int arm_pl180_mmci_init(struct pl180_mmc_host *);
diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c
index 5f6145b..7b35d8e 100644
--- a/drivers/mmc/bfin_sdh.c
+++ b/drivers/mmc/bfin_sdh.c
@@ -238,7 +238,7 @@ static void bfin_sdh_set_ios(struct mmc *mmc)
 	u16 cfg = 0;
 	u16 clk_ctl = 0;
 
-	if (mmc->bus_width == 4) {
+	if (mmc_bus_width(mmc) == 4) {
 		cfg = bfin_read_SDH_CFG();
 #ifndef RSI_BLKSZ
 		cfg &= ~PD_SDDAT3;
@@ -280,25 +280,24 @@ static const struct mmc_ops bfin_mmc_ops = {
 	.init		= bfin_sdh_init,
 };
 
+static struct mmc_config bfin_mmc_cfg = {
+	.name		= "Blackfin SDH",
+	.ops		= &bfin_mmc_ops,
+	.host_caps	= MMC_MODE_4BIT,
+	.voltages	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.b_max		= CONFIG_SYS_MMC_MAX_BLK_COUNT,
+};
+
 int bfin_mmc_init(bd_t *bis)
 {
-	struct mmc *mmc = NULL;
-
-	mmc = malloc(sizeof(struct mmc));
-
-	if (!mmc)
-		return -ENOMEM;
-	mmc->name = "Blackfin SDH";
-	mmc->ops = &bfin_mmc_ops;
-	mmc->host_caps = MMC_MODE_4BIT;
-
-	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->f_max = get_sclk();
-	mmc->f_min = mmc->f_max >> 9;
+	struct mmc *mmc;
 
-	mmc->b_max = 0;
+	bfin_mmc_cfg.f_max = get_sclk();
+	bfin_mmc_cfg.f_min = bfin_mmc_cfg.f_max >> 9;
 
-	mmc_register(mmc);
+	mmc = mmc_create(&bfin_mmc_cfg, NULL);
+	if (mmc == NULL)
+		return -1;
 
 	return 0;
 }
diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c
index cae972a..aae00e9 100644
--- a/drivers/mmc/davinci_mmc.c
+++ b/drivers/mmc/davinci_mmc.c
@@ -30,10 +30,10 @@ static void dmmc_set_clock(struct mmc *mmc, uint clock)
 	struct davinci_mmc_regs *regs = host->reg_base;
 	uint clkrt, sysclk2, act_clock;
 
-	if (clock < mmc->f_min)
-		clock = mmc->f_min;
-	if (clock > mmc->f_max)
-		clock = mmc->f_max;
+	if (clock < mmc->cfg->f_min)
+		clock = mmc->cfg->f_min;
+	if (clock > mmc->cfg->f_max)
+		clock = mmc->cfg->f_max;
 
 	set_val(&regs->mmcclk, 0);
 	sysclk2 = host->input_clk;
@@ -374,22 +374,16 @@ static const struct mmc_ops dmmc_ops = {
  */
 int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
 {
-	struct mmc *mmc;
+	host->cfg.name = "davinci";
+	host->cfg.ops = &dmmc_ops;
+	host->cfg.f_min = 200000;
+	host->cfg.f_max = 25000000;
+	host->cfg.voltages = host->voltages;
+	host->cfg.host_caps = host->host_caps;
 
-	mmc = malloc(sizeof(struct mmc));
-	memset(mmc, 0, sizeof(struct mmc));
+	host->cfg.b_max = DAVINCI_MAX_BLOCKS;
 
-	mmc->name = "davinci";
-	mmc->priv = host;
-	mmc->ops = &dmmc_ops;
-	mmc->f_min = 200000;
-	mmc->f_max = 25000000;
-	mmc->voltages = host->voltages;
-	mmc->host_caps = host->host_caps;
-
-	mmc->b_max = DAVINCI_MAX_BLOCKS;
-
-	mmc_register(mmc);
+	mmc_create(&host->cfg, host);
 
 	return 0;
 }
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 011efb1..eb4e2be 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -107,7 +107,7 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host,
 static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 		struct mmc_data *data)
 {
-	struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
+	struct dwmci_host *host = mmc->priv;
 	ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
 				 data ? DIV_ROUND_UP(data->blocks, 8) : 0);
 	int flags = 0, i;
@@ -284,7 +284,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 
 static void dwmci_set_ios(struct mmc *mmc)
 {
-	struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
+	struct dwmci_host *host = mmc->priv;
 	u32 ctype;
 
 	debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock);
@@ -310,7 +310,7 @@ static void dwmci_set_ios(struct mmc *mmc)
 
 static int dwmci_init(struct mmc *mmc)
 {
-	struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
+	struct dwmci_host *host = mmc->priv;
 
 	if (host->board_init)
 		host->board_init(host);
@@ -323,7 +323,7 @@ static int dwmci_init(struct mmc *mmc)
 	}
 
 	/* Enumerate at 400KHz */
-	dwmci_setup_bus(host, mmc->f_min);
+	dwmci_setup_bus(host, mmc->cfg->f_min);
 
 	dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
 	dwmci_writel(host, DWMCI_INTMASK, 0);
@@ -351,37 +351,29 @@ static const struct mmc_ops dwmci_ops = {
 
 int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
 {
-	struct mmc *mmc;
-	int err = 0;
+	host->cfg.name = host->name;
+	host->cfg.ops = &dwmci_ops;
+	host->cfg.f_min = min_clk;
+	host->cfg.f_max = max_clk;
 
-	mmc = calloc(sizeof(struct mmc), 1);
-	if (!mmc) {
-		printf("mmc calloc fail!\n");
-		return -1;
-	}
-
-	mmc->priv = host;
-	host->mmc = mmc;
-
-	mmc->name = host->name;
-	mmc->ops = &dwmci_ops;
-	mmc->f_min = min_clk;
-	mmc->f_max = max_clk;
+	host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 
-	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
-
-	mmc->host_caps = host->caps;
+	host->cfg.host_caps = host->caps;
 
 	if (host->buswidth == 8) {
-		mmc->host_caps |= MMC_MODE_8BIT;
-		mmc->host_caps &= ~MMC_MODE_4BIT;
+		host->cfg.host_caps |= MMC_MODE_8BIT;
+		host->cfg.host_caps &= ~MMC_MODE_4BIT;
 	} else {
-		mmc->host_caps |= MMC_MODE_4BIT;
-		mmc->host_caps &= ~MMC_MODE_8BIT;
+		host->cfg.host_caps |= MMC_MODE_4BIT;
+		host->cfg.host_caps &= ~MMC_MODE_8BIT;
 	}
-	mmc->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC;
+	host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC;
+
+	host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
-	err = mmc_register(mmc);
+	host->mmc = mmc_create(&host->cfg, host);
+	if (host->mmc == NULL)
+		return -1;
 
-	return err;
+	return 0;
 }
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index f66513e..d649626 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -172,7 +172,7 @@ esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
 static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
 {
 	int timeout;
-	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	struct fsl_esdhc_cfg *cfg = mmc->priv;
 	struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
 	uint wml_value;
@@ -267,7 +267,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
 	uint	xfertyp;
 	uint	irqstat;
-	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	struct fsl_esdhc_cfg *cfg = mmc->priv;
 	volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
@@ -406,13 +406,13 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 static void set_sysctl(struct mmc *mmc, uint clock)
 {
 	int div, pre_div;
-	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	struct fsl_esdhc_cfg *cfg = mmc->priv;
 	volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 	int sdhc_clk = cfg->sdhc_clk;
 	uint clk;
 
-	if (clock < mmc->f_min)
-		clock = mmc->f_min;
+	if (clock < mmc->cfg->f_min)
+		clock = mmc->cfg->f_min;
 
 	if (sdhc_clk / 16 > clock) {
 		for (pre_div = 2; pre_div < 256; pre_div *= 2)
@@ -443,7 +443,7 @@ static void set_sysctl(struct mmc *mmc, uint clock)
 
 static void esdhc_set_ios(struct mmc *mmc)
 {
-	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	struct fsl_esdhc_cfg *cfg = mmc->priv;
 	struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 
 	/* Set the clock speed */
@@ -461,7 +461,7 @@ static void esdhc_set_ios(struct mmc *mmc)
 
 static int esdhc_init(struct mmc *mmc)
 {
-	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	struct fsl_esdhc_cfg *cfg = mmc->priv;
 	struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 	int timeout = 1000;
 
@@ -496,7 +496,7 @@ static int esdhc_init(struct mmc *mmc)
 
 static int esdhc_getcd(struct mmc *mmc)
 {
-	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	struct fsl_esdhc_cfg *cfg = mmc->priv;
 	struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 	int timeout = 1000;
 
@@ -540,12 +540,6 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 	if (!cfg)
 		return -1;
 
-	mmc = malloc(sizeof(struct mmc));
-	if (!mmc)
-		return -ENOMEM;
-
-	memset(mmc, 0, sizeof(struct mmc));
-	mmc->name = "FSL_SDHC";
 	regs = (struct fsl_esdhc *)cfg->esdhc_base;
 
 	/* First reset the eSDHC controller */
@@ -554,8 +548,8 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 	esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
 				| SYSCTL_IPGEN | SYSCTL_CKEN);
 
-	mmc->priv = cfg;
-	mmc->ops = &esdhc_ops;
+	memset(&cfg->cfg, 0, sizeof(cfg->cfg));
+
 	voltage_caps = 0;
 	caps = regs->hostcapblt;
 
@@ -576,38 +570,43 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 	if (caps & ESDHC_HOSTCAPBLT_VS33)
 		voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
 
+	cfg->cfg.name = "FSL_SDHC";
+	cfg->cfg.ops = &esdhc_ops;
 #ifdef CONFIG_SYS_SD_VOLTAGE
-	mmc->voltages = CONFIG_SYS_SD_VOLTAGE;
+	cfg->cfg.voltages = CONFIG_SYS_SD_VOLTAGE;
 #else
-	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+	cfg->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 #endif
-	if ((mmc->voltages & voltage_caps) == 0) {
+	if ((cfg->cfg.voltages & voltage_caps) == 0) {
 		printf("voltage not supported by controller\n");
 		return -1;
 	}
 
-	mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC;
+	cfg->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC;
 
 	if (cfg->max_bus_width > 0) {
 		if (cfg->max_bus_width < 8)
-			mmc->host_caps &= ~MMC_MODE_8BIT;
+			cfg->cfg.host_caps &= ~MMC_MODE_8BIT;
 		if (cfg->max_bus_width < 4)
-			mmc->host_caps &= ~MMC_MODE_4BIT;
+			cfg->cfg.host_caps &= ~MMC_MODE_4BIT;
 	}
 
 	if (caps & ESDHC_HOSTCAPBLT_HSS)
-		mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+		cfg->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
 
 #ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
 	if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
-		mmc->host_caps &= ~MMC_MODE_8BIT;
+		cfg->cfg.host_caps &= ~MMC_MODE_8BIT;
 #endif
 
-	mmc->f_min = 400000;
-	mmc->f_max = MIN(gd->arch.sdhc_clk, 52000000);
+	cfg->cfg.f_min = 400000;
+	cfg->cfg.f_max = MIN(gd->arch.sdhc_clk, 52000000);
 
-	mmc->b_max = 0;
-	mmc_register(mmc);
+	cfg->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+	mmc = mmc_create(&cfg->cfg, cfg);
+	if (mmc == NULL)
+		return -1;
 
 	return 0;
 }
diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c
index b1673fc..a620678 100644
--- a/drivers/mmc/ftsdc010_mci.c
+++ b/drivers/mmc/ftsdc010_mci.c
@@ -27,6 +27,7 @@ struct ftsdc010_chip {
 	uint32_t sclk;    /* FTSDC010 source clock in Hz */
 	uint32_t fifo;    /* fifo depth in bytes */
 	uint32_t acmd;
+	struct mmc_config cfg;	/* mmc configuration */
 };
 
 static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd)
@@ -123,14 +124,6 @@ static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate)
 	}
 }
 
-static inline int ftsdc010_is_ro(struct mmc *mmc)
-{
-	struct ftsdc010_chip *chip = mmc->priv;
-	const uint8_t *csd = (const uint8_t *)mmc->csd;
-
-	return chip->wprot || (csd[1] & 0x30);
-}
-
 static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask)
 {
 	int ret = TIMEOUT;
@@ -337,47 +330,44 @@ int ftsdc010_mmc_init(int devid)
 	regs = (void __iomem *)(CONFIG_FTSDC010_BASE + (devid << 20));
 #endif
 
-	mmc = malloc(sizeof(struct mmc));
-	if (!mmc)
-		return -ENOMEM;
-	memset(mmc, 0, sizeof(struct mmc));
-
 	chip = malloc(sizeof(struct ftsdc010_chip));
-	if (!chip) {
-		free(mmc);
+	if (!chip)
 		return -ENOMEM;
-	}
 	memset(chip, 0, sizeof(struct ftsdc010_chip));
 
 	chip->regs = regs;
-	mmc->priv  = chip;
+#ifdef CONFIG_SYS_CLK_FREQ
+	chip->sclk = CONFIG_SYS_CLK_FREQ;
+#else
+	chip->sclk = clk_get_rate("SDC");
+#endif
 
-	mmc->name = "ftsdc010";
-	mmc->ops = &ftsdc010_ops;
-	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
+	chip->cfg.name = "ftsdc010";
+	chip->cfg.ops = &ftsdc010_ops;
+	chip->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
 	switch (readl(&regs->bwr) & FTSDC010_BWR_CAPS_MASK) {
 	case FTSDC010_BWR_CAPS_4BIT:
-		mmc->host_caps |= MMC_MODE_4BIT;
+		chip->cfg.host_caps |= MMC_MODE_4BIT;
 		break;
 	case FTSDC010_BWR_CAPS_8BIT:
-		mmc->host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
+		chip->cfg.host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
 		break;
 	default:
 		break;
 	}
 
-#ifdef CONFIG_SYS_CLK_FREQ
-	chip->sclk = CONFIG_SYS_CLK_FREQ;
-#else
-	chip->sclk = clk_get_rate("SDC");
-#endif
+	chip->cfg.voltages  = MMC_VDD_32_33 | MMC_VDD_33_34;
+	chip->cfg.f_max     = chip->sclk / 2;
+	chip->cfg.f_min     = chip->sclk / 0x100;
 
-	mmc->voltages  = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->f_max     = chip->sclk / 2;
-	mmc->f_min     = chip->sclk / 0x100;
-	mmc->block_dev.part_type = PART_TYPE_DOS;
+	chip->cfg.part_type = PART_TYPE_DOS;
+	chip->cfg.b_max	    = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
-	mmc_register(mmc);
+	mmc = mmc_create(&chip->cfg, chip);
+	if (mmc == NULL) {
+		free(chip);
+		return -ENOMEM;
+	}
 
 	return 0;
 }
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index ce799f3..acca026 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -55,7 +55,7 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
 /* Setup for MCI Clock and Block Size */
 static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 {
-	atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
+	atmel_mci_t *mci = mmc->priv;
 	u32 bus_hz = get_mci_clk_rate();
 	u32 clkdiv = 255;
 
@@ -165,7 +165,7 @@ io_fail:
 static int
 mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
-	atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
+	atmel_mci_t *mci = mmc->priv;
 	u32 cmdr;
 	u32 error_flags = 0;
 	u32 status;
@@ -289,7 +289,7 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 /* Entered into mmc structure during driver init */
 static void mci_set_ios(struct mmc *mmc)
 {
-	atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
+	atmel_mci_t *mci = mmc->priv;
 	int bus_width = mmc->bus_width;
 	unsigned int version = atmel_mci_get_version(mci);
 	int busw;
@@ -325,7 +325,7 @@ static void mci_set_ios(struct mmc *mmc)
 /* Entered into mmc structure during driver init */
 static int mci_init(struct mmc *mmc)
 {
-	atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
+	atmel_mci_t *mci = mmc->priv;
 
 	/* Initialize controller */
 	writel(MMCI_BIT(SWRST), &mci->cr);	/* soft reset */
@@ -357,36 +357,45 @@ static const struct mmc_ops atmel_mci_ops = {
  */
 int atmel_mci_init(void *regs)
 {
-	struct mmc *mmc = malloc(sizeof(struct mmc));
+	struct mmc *mmc;
+	struct mmc_config *cfg;
 	struct atmel_mci *mci;
 	unsigned int version;
 
-	if (!mmc)
+	cfg = malloc(sizeof(*cfg));
+	if (cfg == NULL)
 		return -1;
+	memset(cfg, 0, sizeof(*cfg));
 
-	mmc->name = "mci";
-	mmc->priv = regs;
-	mmc->ops = &atmel_mci_ops;
+	mci = (struct atmel_mci *)regs;
+
+	cfg->name = "mci";
+	cfg->ops = &atmel_mci_ops;
 
 	/* need to be able to pass these in on a board by board basis */
-	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mci = (struct atmel_mci *)mmc->priv;
+	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 	version = atmel_mci_get_version(mci);
 	if ((version & 0xf00) >= 0x300)
-		mmc->host_caps = MMC_MODE_8BIT;
+		cfg->host_caps = MMC_MODE_8BIT;
 
-	mmc->host_caps |= MMC_MODE_4BIT;
+	cfg->host_caps |= MMC_MODE_4BIT;
 
 	/*
 	 * min and max frequencies determined by
 	 * max and min of clock divider
 	 */
-	mmc->f_min = get_mci_clk_rate() / (2*256);
-	mmc->f_max = get_mci_clk_rate() / (2*1);
+	cfg->f_min = get_mci_clk_rate() / (2*256);
+	cfg->f_max = get_mci_clk_rate() / (2*1);
+
+	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
-	mmc->b_max = 0;
+	mmc = mmc_create(cfg, regs);
 
-	mmc_register(mmc);
+	if (mmc == NULL) {
+		free(cfg);
+		return -1;
+	}
+	/* NOTE: possibly leaking the cfg structure */
 
 	return 0;
 }
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index ac07bb9..4adb886 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -17,11 +17,6 @@
 #include <div64.h>
 #include "mmc_private.h"
 
-/* Set block count limit because of 16 bit register limit on some hardware*/
-#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
-#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
-#endif
-
 static struct list_head mmc_devices;
 static int cur_dev_num = -1;
 
@@ -37,8 +32,8 @@ int mmc_getwp(struct mmc *mmc)
 	wp = board_mmc_getwp(mmc);
 
 	if (wp < 0) {
-		if (mmc->ops->getwp)
-			wp = mmc->ops->getwp(mmc);
+		if (mmc->cfg->ops->getwp)
+			wp = mmc->cfg->ops->getwp(mmc);
 		else
 			wp = 0;
 	}
@@ -63,7 +58,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 
 	printf("CMD_SEND:%d\n", cmd->cmdidx);
 	printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
-	ret = mmc->ops->send_cmd(mmc, cmd, data);
+	ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
 	switch (cmd->resp_type) {
 		case MMC_RSP_NONE:
 			printf("\t\tMMC_RSP_NONE\n");
@@ -106,7 +101,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 			break;
 	}
 #else
-	ret = mmc->ops->send_cmd(mmc, cmd, data);
+	ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
 #endif
 	return ret;
 }
@@ -253,7 +248,8 @@ static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
 		return 0;
 
 	do {
-		cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
+		cur = (blocks_todo > mmc->cfg->b_max) ?
+			mmc->cfg->b_max : blocks_todo;
 		if(mmc_read_blocks(mmc, dst, start, cur) != cur)
 			return 0;
 		blocks_todo -= cur;
@@ -312,7 +308,7 @@ static int sd_send_op_cond(struct mmc *mmc)
 		 * specified.
 		 */
 		cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
-			(mmc->voltages & 0xff8000);
+			(mmc->cfg->voltages & 0xff8000);
 
 		if (mmc->version == SD_VERSION_2)
 			cmd.cmdarg |= OCR_HCS;
@@ -361,11 +357,11 @@ static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd,
 	cmd->cmdarg = 0;
 	if (use_arg && !mmc_host_is_spi(mmc)) {
 		cmd->cmdarg =
-			(mmc->voltages &
+			(mmc->cfg->voltages &
 			(mmc->op_cond_response & OCR_VOLTAGE_MASK)) |
 			(mmc->op_cond_response & OCR_ACCESS_MODE);
 
-		if (mmc->host_caps & MMC_MODE_HC)
+		if (mmc->cfg->host_caps & MMC_MODE_HC)
 			cmd->cmdarg |= OCR_HCS;
 	}
 	err = mmc_send_cmd(mmc, cmd, NULL);
@@ -578,8 +574,8 @@ int mmc_getcd(struct mmc *mmc)
 	cd = board_mmc_getcd(mmc);
 
 	if (cd < 0) {
-		if (mmc->ops->getcd)
-			cd = mmc->ops->getcd(mmc);
+		if (mmc->cfg->ops->getcd)
+			cd = mmc->cfg->ops->getcd(mmc);
 		else
 			cd = 1;
 	}
@@ -703,8 +699,8 @@ retry_scr:
 	 * This can avoid furthur problem when the card runs in different
 	 * mode between the host.
 	 */
-	if (!((mmc->host_caps & MMC_MODE_HS_52MHz) &&
-		(mmc->host_caps & MMC_MODE_HS)))
+	if (!((mmc->cfg->host_caps & MMC_MODE_HS_52MHz) &&
+		(mmc->cfg->host_caps & MMC_MODE_HS)))
 		return 0;
 
 	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
@@ -751,17 +747,17 @@ static const int multipliers[] = {
 
 static void mmc_set_ios(struct mmc *mmc)
 {
-	if (mmc->ops->set_ios)
-		mmc->ops->set_ios(mmc);
+	if (mmc->cfg->ops->set_ios)
+		mmc->cfg->ops->set_ios(mmc);
 }
 
 void mmc_set_clock(struct mmc *mmc, uint clock)
 {
-	if (clock > mmc->f_max)
-		clock = mmc->f_max;
+	if (clock > mmc->cfg->f_max)
+		clock = mmc->cfg->f_max;
 
-	if (clock < mmc->f_min)
-		clock = mmc->f_min;
+	if (clock < mmc->cfg->f_min)
+		clock = mmc->cfg->f_min;
 
 	mmc->clock = clock;
 
@@ -1027,7 +1023,7 @@ static int mmc_startup(struct mmc *mmc)
 		return err;
 
 	/* Restrict card's capabilities by what the host can do */
-	mmc->card_caps &= mmc->host_caps;
+	mmc->card_caps &= mmc->cfg->host_caps;
 
 	if (IS_SD(mmc)) {
 		if (mmc->card_caps & MMC_MODE_4BIT) {
@@ -1082,7 +1078,7 @@ static int mmc_startup(struct mmc *mmc)
 			 * this bus width, if it's more than 1
 			 */
 			if (extw != EXT_CSD_BUS_WIDTH_1 &&
-					!(mmc->host_caps & ext_to_hostcaps[extw]))
+					!(mmc->cfg->host_caps & ext_to_hostcaps[extw]))
 				continue;
 
 			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
@@ -1155,7 +1151,7 @@ static int mmc_send_if_cond(struct mmc *mmc)
 
 	cmd.cmdidx = SD_CMD_SEND_IF_COND;
 	/* We set the bit if the host supports voltages between 2.7 and 3.6 V */
-	cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa;
+	cmd.cmdarg = ((mmc->cfg->voltages & 0xff8000) != 0) << 8 | 0xaa;
 	cmd.resp_type = MMC_RSP_R7;
 
 	err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -1183,8 +1179,9 @@ int mmc_register(struct mmc *mmc)
 	mmc->block_dev.block_read = mmc_bread;
 	mmc->block_dev.block_write = mmc_bwrite;
 	mmc->block_dev.block_erase = mmc_berase;
-	if (!mmc->b_max)
-		mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+	/* setup initial part type */
+	mmc->block_dev.part_type = mmc->cfg->part_type;
 
 	INIT_LIST_HEAD (&mmc->link);
 
@@ -1193,6 +1190,34 @@ int mmc_register(struct mmc *mmc)
 	return 0;
 }
 
+struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
+{
+	struct mmc *mmc;
+
+	/* quick validation */
+	if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL ||
+			cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0)
+		return NULL;
+
+	mmc = malloc(sizeof(*mmc));
+	if (mmc == NULL)
+		return NULL;
+	memset(mmc, 0, sizeof(*mmc));
+
+	mmc->cfg = cfg;
+	mmc->priv = priv;
+
+	mmc_register(mmc);
+
+	return mmc;
+}
+
+void mmc_destroy(struct mmc *mmc)
+{
+	/* only freeing memory for now */
+	free(mmc);
+}
+
 #ifdef CONFIG_PARTITIONS
 block_dev_desc_t *mmc_get_dev(int dev)
 {
@@ -1209,7 +1234,7 @@ int mmc_start_init(struct mmc *mmc)
 	int err;
 
 	/* we pretend there's no card when init is NULL */
-	if (mmc_getcd(mmc) == 0 || mmc->ops->init == NULL) {
+	if (mmc_getcd(mmc) == 0 || mmc->cfg->ops->init == NULL) {
 		mmc->has_init = 0;
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 		printf("MMC: no card present\n");
@@ -1221,7 +1246,7 @@ int mmc_start_init(struct mmc *mmc)
 		return 0;
 
 	/* made sure it's not NULL earlier */
-	err = mmc->ops->init(mmc);
+	err = mmc->cfg->ops->init(mmc);
 
 	if (err)
 		return err;
@@ -1323,7 +1348,7 @@ void print_mmc_devices(char separator)
 	list_for_each(entry, &mmc_devices) {
 		m = list_entry(entry, struct mmc, link);
 
-		printf("%s: %d", m->name, m->block_dev.dev);
+		printf("%s: %d", m->cfg->name, m->block_dev.dev);
 
 		if (entry->next != &mmc_devices)
 			printf("%c ", separator);
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index e94de37..5b5b33a 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -92,7 +92,7 @@ static uint mmc_spi_readdata(struct mmc *mmc, void *xbuf,
 			spi_xfer(spi, 2 * 8, NULL, &crc, 0);
 #ifdef CONFIG_MMC_SPI_CRC_ON
 			if (swab16(cyg_crc16(buf, bsize)) != crc) {
-				debug("%s: CRC error\n", mmc->name);
+				debug("%s: CRC error\n", mmc->cfg->name);
 				r1 = R1_SPI_COM_CRC;
 				break;
 			}
@@ -238,6 +238,7 @@ done:
 static void mmc_spi_set_ios(struct mmc *mmc)
 {
 	struct spi_slave *spi = mmc->priv;
+
 	debug("%s: clock %u\n", __func__, mmc->clock);
 	if (mmc->clock)
 		spi_set_speed(spi, mmc->clock);
@@ -246,7 +247,6 @@ static void mmc_spi_set_ios(struct mmc *mmc)
 static int mmc_spi_init_p(struct mmc *mmc)
 {
 	struct spi_slave *spi = mmc->priv;
-	mmc->clock = 0;
 	spi_set_speed(spi, MMC_SPI_MIN_CLOCK);
 	spi_claim_bus(spi);
 	/* cs deactivated for 100+ clock */
@@ -261,29 +261,31 @@ static const struct mmc_ops mmc_spi_ops = {
 	.init		= mmc_spi_init_p,
 };
 
+static struct mmc_config mmc_spi_cfg = {
+	.name		= "MMC_SPI",
+	.ops		= &mmc_spi_ops,
+	.host_caps	= MMC_MODE_SPI,
+	.voltages	= MMC_SPI_VOLTAGE,
+	.f_min		= MMC_SPI_MIN_CLOCK,
+	.part_type	= PART_TYPE_DOS,
+	.b_max		= CONFIG_SYS_MMC_MAX_BLK_COUNT,
+};
+
 struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
 {
 	struct mmc *mmc;
+	struct spi_slave *spi;
 
-	mmc = malloc(sizeof(*mmc));
-	if (!mmc)
-		return NULL;
-	memset(mmc, 0, sizeof(*mmc));
-	mmc->priv = spi_setup_slave(bus, cs, speed, mode);
-	if (!mmc->priv) {
-		free(mmc);
+	spi = spi_setup_slave(bus, cs, speed, mode);
+	if (spi == NULL)
 		return NULL;
-	}
-	mmc->name = "MMC_SPI";
-	mmc->ops = &mmc_spi_ops;
-	mmc->host_caps = MMC_MODE_SPI;
-
-	mmc->voltages = MMC_SPI_VOLTAGE;
-	mmc->f_max = speed;
-	mmc->f_min = MMC_SPI_MIN_CLOCK;
-	mmc->block_dev.part_type = PART_TYPE_DOS;
 
-	mmc_register(mmc);
+	mmc_spi_cfg.f_max = speed;
 
+	mmc = mmc_create(&mmc_spi_cfg, spi);
+	if (mmc == NULL) {
+		spi_free_slave(spi);
+		return NULL;
+	}
 	return mmc;
 }
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index aa2fdef..3db9669 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -167,7 +167,8 @@ ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src)
 		return 0;
 
 	do {
-		cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
+		cur = (blocks_todo > mmc->cfg->b_max) ?
+			mmc->cfg->b_max : blocks_todo;
 		if (mmc_write_blocks(mmc, start, cur, src) != cur)
 			return 0;
 		blocks_todo -= cur;
diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c
index 3357559..561b204 100644
--- a/drivers/mmc/mxcmmc.c
+++ b/drivers/mmc/mxcmmc.c
@@ -122,6 +122,8 @@ struct mxcmci_host {
 };
 
 static struct mxcmci_host mxcmci_host;
+
+/* maintainer note: do we really want to have a global host pointer? */
 static struct mxcmci_host *host = &mxcmci_host;
 
 static inline int mxcmci_use_dma(struct mxcmci_host *host)
@@ -491,31 +493,24 @@ static const struct mmc_ops mxcmci_ops = {
 	.init		= mxcmci_init,
 };
 
+static struct mmc_config mxcmci_cfg = {
+	.name		= "MXC MCI",
+	.ops		= &mxcmci_ops,
+	.host_caps	= MMC_MODE_4BIT,
+	.voltages	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.b_max		= CONFIG_SYS_MMC_MAX_BLK_COUNT,
+};
+
 static int mxcmci_initialize(bd_t *bis)
 {
-	struct mmc *mmc = NULL;
-
-	mmc = malloc(sizeof(struct mmc));
-
-	if (!mmc)
-		return -ENOMEM;
-
-	mmc->name = "MXC MCI";
-	mmc->ops = &mxcmci_ops;
-	mmc->host_caps = MMC_MODE_4BIT;
-
 	host->base = (struct mxcmci_regs *)CONFIG_MXC_MCI_REGS_BASE;
-	mmc->priv = host;
-	host->mmc = mmc;
-
-	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
-
-	mmc->f_min = mxc_get_clock(MXC_ESDHC_CLK) >> 7;
-	mmc->f_max = mxc_get_clock(MXC_ESDHC_CLK) >> 1;
 
-	mmc->b_max = 0;
+	mxcmci_cfg.f_min = mxc_get_clock(MXC_ESDHC_CLK) >> 7;
+	mxcmci_cfg.f_max = mxc_get_clock(MXC_ESDHC_CLK) >> 1;
 
-	mmc_register(mmc);
+	host->mmc = mmc_create(&mxcmci_cfg, host);
+	if (host->mmc == NULL)
+		return -1;
 
 	return 0;
 }
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index 3512a99..2fa4eee 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -35,6 +35,7 @@ struct mxsmmc_priv {
 	int			(*mmc_is_wp)(int);
 	int			(*mmc_cd)(int);
 	struct mxs_dma_desc	*desc;
+	struct mmc_config	cfg;	/* mmc configuration */
 };
 
 #define	MXSMMC_MAX_TIMEOUT	10000
@@ -134,7 +135,7 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
 static int
 mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
-	struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+	struct mxsmmc_priv *priv = mmc->priv;
 	struct mxs_ssp_regs *ssp_regs = priv->regs;
 	uint32_t reg;
 	int timeout;
@@ -305,7 +306,7 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 
 static void mxsmmc_set_ios(struct mmc *mmc)
 {
-	struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+	struct mxsmmc_priv *priv = mmc->priv;
 	struct mxs_ssp_regs *ssp_regs = priv->regs;
 
 	/* Set the clock speed */
@@ -334,7 +335,7 @@ static void mxsmmc_set_ios(struct mmc *mmc)
 
 static int mxsmmc_init(struct mmc *mmc)
 {
-	struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+	struct mxsmmc_priv *priv = mmc->priv;
 	struct mxs_ssp_regs *ssp_regs = priv->regs;
 
 	/* Reset SSP */
@@ -379,20 +380,13 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
 	if (!mxs_ssp_bus_id_valid(id))
 		return -ENODEV;
 
-	mmc = malloc(sizeof(struct mmc));
-	if (!mmc)
-		return -ENOMEM;
-
 	priv = malloc(sizeof(struct mxsmmc_priv));
-	if (!priv) {
-		free(mmc);
+	if (!priv)
 		return -ENOMEM;
-	}
 
 	priv->desc = mxs_dma_desc_alloc();
 	if (!priv->desc) {
 		free(priv);
-		free(mmc);
 		return -ENOMEM;
 	}
 
@@ -405,13 +399,12 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
 	priv->id = id;
 	priv->regs = mxs_ssp_regs_by_bus(id);
 
-	mmc->name = "MXS MMC";
-	mmc->ops = &mxsmmc_ops;
-	mmc->priv = priv;
+	priv->cfg.name = "MXS MMC";
+	priv->cfg.ops = &mxsmmc_ops;
 
-	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+	priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 
-	mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
+	priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
 			 MMC_MODE_HS_52MHz | MMC_MODE_HS |
 			 MMC_MODE_HC;
 
@@ -421,10 +414,15 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
 	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
 	 * CLOCK_RATE could be any integer from 0 to 255.
 	 */
-	mmc->f_min = 400000;
-	mmc->f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id) * 1000 / 2;
-	mmc->b_max = 0x20;
+	priv->cfg.f_min = 400000;
+	priv->cfg.f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id) * 1000 / 2;
+	priv->cfg.b_max = 0x20;
 
-	mmc_register(mmc);
+	mmc = mmc_create(&priv->cfg, priv);
+	if (mmc == NULL) {
+		mxs_dma_desc_free(priv->desc);
+		free(priv);
+		return -ENOMEM;
+	}
 	return 0;
 }
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index fecac56..17cbb09 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -24,6 +24,7 @@
 
 #include <config.h>
 #include <common.h>
+#include <malloc.h>
 #include <mmc.h>
 #include <part.h>
 #include <i2c.h>
@@ -49,6 +50,7 @@
 
 struct omap_hsmmc_data {
 	struct hsmmc *base_addr;
+	struct mmc_config cfg;
 #ifdef OMAP_HSMMC_USE_GPIO
 	int cd_gpio;
 	int wp_gpio;
@@ -61,8 +63,6 @@ struct omap_hsmmc_data {
 static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
 static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
 			unsigned int siz);
-static struct mmc hsmmc_dev[3];
-static struct omap_hsmmc_data hsmmc_dev_data[3];
 
 #ifdef OMAP_HSMMC_USE_GPIO
 static int omap_mmc_setup_gpio_in(int gpio, const char *label)
@@ -147,7 +147,7 @@ unsigned char mmc_board_init(struct mmc *mmc)
 		&t2_base->devconf1);
 
 	/* Change from default of 52MHz to 26MHz if necessary */
-	if (!(mmc->host_caps & MMC_MODE_HS_52MHz))
+	if (!(mmc->cfg->host_caps & MMC_MODE_HS_52MHz))
 		writel(readl(&t2_base->ctl_prog_io1) & ~CTLPROGIO1SPEEDCTRL,
 			&t2_base->ctl_prog_io1);
 
@@ -636,14 +636,17 @@ static const struct mmc_ops omap_hsmmc_ops = {
 int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 		int wp_gpio)
 {
-	struct mmc *mmc = &hsmmc_dev[dev_index];
-	struct omap_hsmmc_data *priv_data = &hsmmc_dev_data[dev_index];
-	uint host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
-			     MMC_MODE_HC;
+	struct mmc *mmc;
+	struct omap_hsmmc_data *priv_data;
+	struct mmc_config *cfg;
+	uint host_caps_val;
+
+	priv_data = malloc(sizeof(*priv_data));
+	if (priv_data == NULL)
+		return -1;
 
-	mmc->name = "OMAP SD/MMC";
-	mmc->ops = &omap_hsmmc_ops;
-	mmc->priv = priv_data;
+	host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
+			     MMC_MODE_HC;
 
 	switch (dev_index) {
 	case 0:
@@ -678,34 +681,40 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 	priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");
 #endif
 
-	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
-	mmc->host_caps = host_caps_val & ~host_caps_mask;
+	cfg = &priv_data->cfg;
 
-	mmc->f_min = 400000;
+	cfg->name = "OMAP SD/MMC";
+	cfg->ops = &omap_hsmmc_ops;
+
+	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+	cfg->host_caps = host_caps_val & ~host_caps_mask;
+
+	cfg->f_min = 400000;
 
 	if (f_max != 0)
-		mmc->f_max = f_max;
+		cfg->f_max = f_max;
 	else {
-		if (mmc->host_caps & MMC_MODE_HS) {
-			if (mmc->host_caps & MMC_MODE_HS_52MHz)
-				mmc->f_max = 52000000;
+		if (cfg->host_caps & MMC_MODE_HS) {
+			if (cfg->host_caps & MMC_MODE_HS_52MHz)
+				cfg->f_max = 52000000;
 			else
-				mmc->f_max = 26000000;
+				cfg->f_max = 26000000;
 		} else
-			mmc->f_max = 20000000;
+			cfg->f_max = 20000000;
 	}
 
-	mmc->b_max = 0;
+	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
 #if defined(CONFIG_OMAP34XX)
 	/*
 	 * Silicon revs 2.1 and older do not support multiblock transfers.
 	 */
 	if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21))
-		mmc->b_max = 1;
+		cfg->b_max = 1;
 #endif
-
-	mmc_register(mmc);
+	mmc = mmc_create(cfg, priv_data);
+	if (mmc == NULL)
+		return -1;
 
 	return 0;
 }
diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c
index 188e1d4..1f29757 100644
--- a/drivers/mmc/pxa_mmc_gen.c
+++ b/drivers/mmc/pxa_mmc_gen.c
@@ -52,7 +52,7 @@ struct pxa_mmc_priv {
 /* Wait for bit to be set */
 static int pxa_mmc_wait(struct mmc *mmc, uint32_t mask)
 {
-	struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
+	struct pxa_mmc_priv *priv = mmc->priv;
 	struct pxa_mmc_regs *regs = priv->regs;
 	unsigned int timeout = PXA_MMC_TIMEOUT;
 
@@ -71,7 +71,7 @@ static int pxa_mmc_wait(struct mmc *mmc, uint32_t mask)
 
 static int pxa_mmc_stop_clock(struct mmc *mmc)
 {
-	struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
+	struct pxa_mmc_priv *priv = mmc->priv;
 	struct pxa_mmc_regs *regs = priv->regs;
 	unsigned int timeout = PXA_MMC_TIMEOUT;
 
@@ -100,7 +100,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)
 {
-	struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
+	struct pxa_mmc_priv *priv = mmc->priv;
 	struct pxa_mmc_regs *regs = priv->regs;
 	int ret;
 
@@ -143,7 +143,7 @@ static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 
 static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
 {
-	struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
+	struct pxa_mmc_priv *priv = mmc->priv;
 	struct pxa_mmc_regs *regs = priv->regs;
 	uint32_t a, b, c;
 	int i;
@@ -185,7 +185,7 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
 
 static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data)
 {
-	struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
+	struct pxa_mmc_priv *priv = mmc->priv;
 	struct pxa_mmc_regs *regs = priv->regs;
 	uint32_t len;
 	uint32_t *buf = (uint32_t *)data->dest;
@@ -221,7 +221,7 @@ static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data)
 
 static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data)
 {
-	struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
+	struct pxa_mmc_priv *priv = mmc->priv;
 	struct pxa_mmc_regs *regs = priv->regs;
 	uint32_t len;
 	uint32_t *buf = (uint32_t *)data->src;
@@ -264,7 +264,7 @@ static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data)
 static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
 				struct mmc_data *data)
 {
-	struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
+	struct pxa_mmc_priv *priv = mmc->priv;
 	struct pxa_mmc_regs *regs = priv->regs;
 	uint32_t cmdat = 0;
 	int ret;
@@ -317,7 +317,7 @@ static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
 
 static void pxa_mmc_set_ios(struct mmc *mmc)
 {
-	struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
+	struct pxa_mmc_priv *priv = mmc->priv;
 	struct pxa_mmc_regs *regs = priv->regs;
 	uint32_t tmp;
 	uint32_t pxa_mmc_clock;
@@ -335,7 +335,7 @@ static void pxa_mmc_set_ios(struct mmc *mmc)
 
 	/* Set clock to the card the usual way. */
 	pxa_mmc_clock = 0;
-	tmp = mmc->f_max / mmc->clock;
+	tmp = mmc->cfg->f_max / mmc->clock;
 	tmp += tmp % 2;
 
 	while (tmp > 1) {
@@ -348,7 +348,7 @@ static void pxa_mmc_set_ios(struct mmc *mmc)
 
 static int pxa_mmc_init(struct mmc *mmc)
 {
-	struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
+	struct pxa_mmc_priv *priv = mmc->priv;
 	struct pxa_mmc_regs *regs = priv->regs;
 
 	/* Make sure the clock are stopped */
@@ -372,6 +372,16 @@ static const struct mmc_ops pxa_mmc_ops = {
 	.init		= pxa_mmc_init,
 };
 
+static struct mmc_config pxa_mmc_cfg = {
+	.name		= "PXA MMC",
+	.ops		= &pxa_mmc_ops,
+	.voltages	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.f_max		= PXAMMC_MAX_SPEED,
+	.f_min		= PXAMMC_MIN_SPEED,
+	.host_caps	= PXAMMC_HOST_CAPS,
+	.b_max		= CONFIG_SYS_MMC_MAX_BLK_COUNT,
+};
+
 int pxa_mmc_register(int card_index)
 {
 	struct mmc *mmc;
@@ -379,13 +389,11 @@ int pxa_mmc_register(int card_index)
 	uint32_t reg;
 	int ret = -ENOMEM;
 
-	mmc = malloc(sizeof(struct mmc));
-	if (!mmc)
-		goto err0;
-
 	priv = malloc(sizeof(struct pxa_mmc_priv));
 	if (!priv)
-		goto err1;
+		goto err0;
+
+	memset(priv, 0, sizeof(*priv));
 
 	switch (card_index) {
 	case 0:
@@ -395,23 +403,12 @@ int pxa_mmc_register(int card_index)
 		priv->regs = (struct pxa_mmc_regs *)MMC1_BASE;
 		break;
 	default:
+		ret = -EINVAL;
 		printf("PXA MMC: Invalid MMC controller ID (card_index = %d)\n",
 			card_index);
-		goto err2;
+		goto err1;
 	}
 
-	mmc->priv = priv;
-
-	mmc->name = "PXA MMC";
-	mmc->ops = &pxa_mmc_ops;
-
-	mmc->voltages	= MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->f_max	= PXAMMC_MAX_SPEED;
-	mmc->f_min	= PXAMMC_MIN_SPEED;
-	mmc->host_caps	= PXAMMC_HOST_CAPS;
-
-	mmc->b_max = 0;
-
 #ifndef	CONFIG_CPU_MONAHANS	/* PXA2xx */
 	reg = readl(CKEN);
 	reg |= CKEN12_MMC;
@@ -422,14 +419,14 @@ int pxa_mmc_register(int card_index)
 	writel(reg, CKENA);
 #endif
 
-	mmc_register(mmc);
+	mmc = mmc_create(&pxa_mmc_cfg, priv);
+	if (mmc == NULL)
+		goto err1;
 
 	return 0;
 
-err2:
-	free(priv);
 err1:
-	free(mmc);
+	free(priv);
 err0:
 	return ret;
 }
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index dc6f4e4..3125d13 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -127,7 +127,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
 int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 		       struct mmc_data *data)
 {
-	struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
+	struct sdhci_host *host = mmc->priv;
 	unsigned int stat = 0;
 	int ret = 0;
 	int trans_bytes = 0, is_aligned = 1;
@@ -268,7 +268,7 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 
 static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 {
-	struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
+	struct sdhci_host *host = mmc->priv;
 	unsigned int div, clk, timeout;
 
 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
@@ -278,18 +278,18 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
 		/* Version 3.00 divisors must be a multiple of 2. */
-		if (mmc->f_max <= clock)
+		if (mmc->cfg->f_max <= clock)
 			div = 1;
 		else {
 			for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
-				if ((mmc->f_max / div) <= clock)
+				if ((mmc->cfg->f_max / div) <= clock)
 					break;
 			}
 		}
 	} else {
 		/* Version 2.00 divisors must be a power of 2. */
 		for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
-			if ((mmc->f_max / div) <= clock)
+			if ((mmc->cfg->f_max / div) <= clock)
 				break;
 		}
 	}
@@ -358,7 +358,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 void sdhci_set_ios(struct mmc *mmc)
 {
 	u32 ctrl;
-	struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
+	struct sdhci_host *host = mmc->priv;
 
 	if (host->set_control_reg)
 		host->set_control_reg(host);
@@ -395,7 +395,7 @@ void sdhci_set_ios(struct mmc *mmc)
 
 int sdhci_init(struct mmc *mmc)
 {
-	struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
+	struct sdhci_host *host = mmc->priv;
 
 	if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) {
 		aligned_buffer = memalign(8, 512*1024);
@@ -406,7 +406,7 @@ int sdhci_init(struct mmc *mmc)
 		}
 	}
 
-	sdhci_set_power(host, fls(mmc->voltages) - 1);
+	sdhci_set_power(host, fls(mmc->cfg->voltages) - 1);
 
 	if (host->quirks & SDHCI_QUIRK_NO_CD) {
 		unsigned int status;
@@ -439,20 +439,10 @@ static const struct mmc_ops sdhci_ops = {
 
 int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
 {
-	struct mmc *mmc;
 	unsigned int caps;
 
-	mmc = malloc(sizeof(struct mmc));
-	if (!mmc) {
-		printf("%s: mmc malloc fail!\n", __func__);
-		return -1;
-	}
-
-	mmc->priv = host;
-	host->mmc = mmc;
-
-	mmc->name = host->name;
-	mmc->ops = &sdhci_ops;
+	host->cfg.name = host->name;
+	host->cfg.ops = &sdhci_ops;
 
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
 #ifdef CONFIG_MMC_SDMA
@@ -464,51 +454,60 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
 #endif
 
 	if (max_clk)
-		mmc->f_max = max_clk;
+		host->cfg.f_max = max_clk;
 	else {
 		if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
-			mmc->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
+			host->cfg.f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
 				>> SDHCI_CLOCK_BASE_SHIFT;
 		else
-			mmc->f_max = (caps & SDHCI_CLOCK_BASE_MASK)
+			host->cfg.f_max = (caps & SDHCI_CLOCK_BASE_MASK)
 				>> SDHCI_CLOCK_BASE_SHIFT;
-		mmc->f_max *= 1000000;
+		host->cfg.f_max *= 1000000;
 	}
-	if (mmc->f_max == 0) {
+	if (host->cfg.f_max == 0) {
 		printf("%s: Hardware doesn't specify base clock frequency\n",
 		       __func__);
 		return -1;
 	}
 	if (min_clk)
-		mmc->f_min = min_clk;
+		host->cfg.f_min = min_clk;
 	else {
 		if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
-			mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_300;
+			host->cfg.f_min = host->cfg.f_max /
+				SDHCI_MAX_DIV_SPEC_300;
 		else
-			mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_200;
+			host->cfg.f_min = host->cfg.f_max /
+				SDHCI_MAX_DIV_SPEC_200;
 	}
 
-	mmc->voltages = 0;
+	host->cfg.voltages = 0;
 	if (caps & SDHCI_CAN_VDD_330)
-		mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
+		host->cfg.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
 	if (caps & SDHCI_CAN_VDD_300)
-		mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
+		host->cfg.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
 	if (caps & SDHCI_CAN_VDD_180)
-		mmc->voltages |= MMC_VDD_165_195;
+		host->cfg.voltages |= MMC_VDD_165_195;
 
 	if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
-		mmc->voltages |= host->voltages;
+		host->cfg.voltages |= host->voltages;
 
-	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
+	host->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
 		if (caps & SDHCI_CAN_DO_8BIT)
-			mmc->host_caps |= MMC_MODE_8BIT;
+			host->cfg.host_caps |= MMC_MODE_8BIT;
 	}
 	if (host->host_caps)
-		mmc->host_caps |= host->host_caps;
+		host->cfg.host_caps |= host->host_caps;
+
+	host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
 	sdhci_reset(host, SDHCI_RESET_ALL);
-	mmc_register(mmc);
+
+	host->mmc = mmc_create(&host->cfg, host);
+	if (host->mmc == NULL) {
+		printf("%s: mmc create fail!\n", __func__);
+		return -1;
+	}
 
 	return 0;
 }
diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c
index 008617d..64b5b47 100644
--- a/drivers/mmc/sh_mmcif.c
+++ b/drivers/mmc/sh_mmcif.c
@@ -20,11 +20,6 @@
 
 #define DRIVER_NAME	"sh_mmcif"
 
-static void *mmc_priv(struct mmc *mmc)
-{
-	return (void *)mmc->priv;
-}
-
 static int sh_mmcif_intr(void *dev_id)
 {
 	struct sh_mmcif_host *host = dev_id;
@@ -522,7 +517,7 @@ static int sh_mmcif_start_cmd(struct sh_mmcif_host *host,
 static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd,
 			    struct mmc_data *data)
 {
-	struct sh_mmcif_host *host = mmc_priv(mmc);
+	struct sh_mmcif_host *host = mmc->priv;
 	int ret;
 
 	WATCHDOG_RESET();
@@ -550,7 +545,7 @@ static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd,
 
 static void sh_mmcif_set_ios(struct mmc *mmc)
 {
-	struct sh_mmcif_host *host = mmc_priv(mmc);
+	struct sh_mmcif_host *host = mmc->priv;
 
 	if (mmc->clock)
 		sh_mmcif_clock_control(host, mmc->clock);
@@ -567,7 +562,7 @@ static void sh_mmcif_set_ios(struct mmc *mmc)
 
 static int sh_mmcif_init(struct mmc *mmc)
 {
-	struct sh_mmcif_host *host = mmc_priv(mmc);
+	struct sh_mmcif_host *host = mmc->priv;
 
 	sh_mmcif_sync_reset(host);
 	sh_mmcif_write(MASK_ALL, &host->regs->ce_int_mask);
@@ -580,33 +575,36 @@ static const struct mmc_ops sh_mmcif_ops = {
 	.init		= sh_mmcif_init,
 };
 
+static struct mmc_config sh_mmcif_cfg = {
+	.name		= DRIVER_NAME,
+	.ops		= &sh_mmcif_ops,
+	.host_caps	= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT |
+			  MMC_MODE_8BIT | MMC_MODE_HC,
+	.voltages	= MMC_VDD_32_33 | MMC_VDD_33_34;
+	.f_min		= CLKDEV_MMC_INIT,
+	.f_max		= CLKDEV_EMMC_DATA,
+	.b_max		= CONFIG_SYS_MMC_MAX_BLK_COUNT,
+};
+
 int mmcif_mmc_init(void)
 {
 	int ret = 0;
 	struct mmc *mmc;
 	struct sh_mmcif_host *host = NULL;
 
-	mmc = malloc(sizeof(struct mmc));
-	if (!mmc)
-		ret = -ENOMEM;
-	memset(mmc, 0, sizeof(*mmc));
 	host = malloc(sizeof(struct sh_mmcif_host));
 	if (!host)
 		ret = -ENOMEM;
 	memset(host, 0, sizeof(*host));
 
-	mmc->f_min = CLKDEV_MMC_INIT;
-	mmc->f_max = CLKDEV_EMMC_DATA;
-	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT |
-			 MMC_MODE_8BIT | MMC_MODE_HC;
-	mmc->name = DRIVER_NAME;
-	mmc->ops = &sh_mmcif_ops;
 	host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR;
 	host->clk = CONFIG_SH_MMCIF_CLK;
-	mmc->priv = host;
 
-	mmc_register(mmc);
+	mmc = mmc_create(&sh_mmcif_cfg, host);
+	if (mmc == NULL) {
+		free(host);
+		return -ENOMEM;
+	}
 
-	return ret;
+	return 0;
 }
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index e8fbb63..ed67eec 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -18,7 +18,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-struct mmc mmc_dev[MAX_HOSTS];
 struct mmc_host mmc_host[MAX_HOSTS];
 
 #ifndef CONFIG_OF_CONTROL
@@ -145,7 +144,7 @@ static int mmc_wait_inhibit(struct mmc_host *host,
 static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
 			struct mmc_data *data, struct bounce_buffer *bbstate)
 {
-	struct mmc_host *host = (struct mmc_host *)mmc->priv;
+	struct mmc_host *host = mmc->priv;
 	int flags, i;
 	int result;
 	unsigned int mask = 0;
@@ -456,7 +455,7 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc)
 	}
 
 	/* Set SD bus voltage & enable bus power */
-	mmc_set_power(host, fls(mmc->voltages) - 1);
+	mmc_set_power(host, fls(mmc->cfg->voltages) - 1);
 	debug("%s: power control = %02X, host control = %02X\n", __func__,
 		readb(&host->reg->pwrcon), readb(&host->reg->hostctl));
 
@@ -466,7 +465,7 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc)
 
 static int tegra_mmc_core_init(struct mmc *mmc)
 {
-	struct mmc_host *host = (struct mmc_host *)mmc->priv;
+	struct mmc_host *host = mmc->priv;
 	unsigned int mask;
 	debug(" mmc_core_init called\n");
 
@@ -511,7 +510,7 @@ static int tegra_mmc_core_init(struct mmc *mmc)
 
 int tegra_mmc_getcd(struct mmc *mmc)
 {
-	struct mmc_host *host = (struct mmc_host *)mmc->priv;
+	struct mmc_host *host = mmc->priv;
 
 	debug("tegra_mmc_getcd called\n");
 
@@ -561,19 +560,18 @@ static int do_mmc_init(int dev_index)
 		debug(" CD GPIO name = %s\n", host->cd_gpio.name);
 	}
 
-	mmc = &mmc_dev[dev_index];
+	memset(&host->cfg, 0, sizeof(host->cfg));
 
-	mmc->name = "Tegra SD/MMC";
-	mmc->priv = host;
-	mmc->ops = &tegra_mmc_ops;
+	host->cfg.name = "Tegra SD/MMC";
+	host->cfg.ops = &tegra_mmc_ops;
 
-	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
-	mmc->host_caps = 0;
+	host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+	host->cfg.host_caps = 0;
 	if (host->width == 8)
-		mmc->host_caps |= MMC_MODE_8BIT;
+		host->cfg.host_caps |= MMC_MODE_8BIT;
 	if (host->width >= 4)
-		mmc->host_caps |= MMC_MODE_4BIT;
-	mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC;
+		host->cfg.host_caps |= MMC_MODE_4BIT;
+	host->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC;
 
 	/*
 	 * min freq is for card identification, and is the highest
@@ -581,10 +579,14 @@ static int do_mmc_init(int dev_index)
 	 * max freq is highest HS eMMC clock as per the SD/MMC spec
 	 *  (actually 52MHz)
 	 */
-	mmc->f_min = 375000;
-	mmc->f_max = 48000000;
+	host->cfg.f_min = 375000;
+	host->cfg.f_max = 48000000;
 
-	mmc_register(mmc);
+	host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+	mmc = mmc_create(&host->cfg, host);
+	if (mmc == NULL)
+		return -1;
 
 	return 0;
 }
diff --git a/include/dwmmc.h b/include/dwmmc.h
index b641558..c9bdf51 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -143,6 +143,8 @@ struct dwmci_host {
 	void (*clksel)(struct dwmci_host *host);
 	void (*board_init)(struct dwmci_host *host);
 	unsigned int (*get_mmc_clk)(struct dwmci_host *host);
+
+	struct mmc_config cfg;
 };
 
 struct dwmci_idmac {
diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h
index 89bcbd1..a6e3a5d 100644
--- a/include/fsl_esdhc.h
+++ b/include/fsl_esdhc.h
@@ -13,6 +13,9 @@
 #include <asm/errno.h>
 #include <asm/byteorder.h>
 
+/* needed for the mmc_cfg definition */
+#include <mmc.h>
+
 /* FSL eSDHC-specific constants */
 #define SYSCTL			0x0002e02c
 #define SYSCTL_INITA		0x08000000
@@ -155,6 +158,7 @@ struct fsl_esdhc_cfg {
 	u32	esdhc_base;
 	u32	sdhc_clk;
 	u8	max_bus_width;
+	struct mmc_config cfg;
 };
 
 /* Select the correct accessors depending on endianess */
diff --git a/include/mmc.h b/include/mmc.h
index 6b08c62..0172979 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -262,20 +262,28 @@ struct mmc_ops {
 	int (*getwp)(struct mmc *mmc);
 };
 
+struct mmc_config {
+	const char *name;
+	const struct mmc_ops *ops;
+	uint host_caps;
+	uint voltages;
+	uint f_min;
+	uint f_max;
+	uint b_max;
+	unsigned char part_type;
+};
+
+/* TODO struct mmc should be in mmc_private but it's hard to fix right now */
 struct mmc {
 	struct list_head link;
-	const char *name;	/* no need for this to be an array */
-	void *priv;
-	uint voltages;
+	const struct mmc_config *cfg;	/* provided configuration */
 	uint version;
+	void *priv;
 	uint has_init;
-	uint f_min;
-	uint f_max;
 	int high_capacity;
 	uint bus_width;
 	uint clock;
 	uint card_caps;
-	uint host_caps;
 	uint ocr;
 	uint dsr;
 	uint dsr_imp;
@@ -295,8 +303,6 @@ struct mmc {
 	u64 capacity_rpmb;
 	u64 capacity_gp[4];
 	block_dev_desc_t block_dev;
-	const struct mmc_ops *ops;
-	uint b_max;
 	char op_cond_pending;	/* 1 if we are waiting on an op_cond command */
 	char init_in_progress;	/* 1 if we have done mmc_start_init() */
 	char preinit;		/* start init as early as possible */
@@ -304,6 +310,8 @@ struct mmc {
 };
 
 int mmc_register(struct mmc *mmc);
+struct mmc *mmc_create(const struct mmc_config *cfg, void *priv);
+void mmc_destroy(struct mmc *mmc);
 int mmc_initialize(bd_t *bis);
 int mmc_init(struct mmc *mmc);
 int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
@@ -352,7 +360,7 @@ void mmc_set_preinit(struct mmc *mmc, int preinit);
 
 #ifdef CONFIG_GENERIC_MMC
 #ifdef CONFIG_MMC_SPI
-#define mmc_host_is_spi(mmc)	((mmc)->host_caps & MMC_MODE_SPI)
+#define mmc_host_is_spi(mmc)	((mmc)->cfg.host_caps & MMC_MODE_SPI)
 #else
 #define mmc_host_is_spi(mmc)	0
 #endif
@@ -361,4 +369,9 @@ struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
 int mmc_legacy_init(int verbose);
 #endif
 
+/* Set block count limit because of 16 bit register limit on some hardware*/
+#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
+#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
+#endif
+
 #endif /* _MMC_H_ */
diff --git a/include/sdhci.h b/include/sdhci.h
index 74d06ae..2c480d0 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -247,6 +247,8 @@ struct sdhci_host {
 	void (*set_control_reg)(struct sdhci_host *host);
 	void (*set_clock)(int dev_index, unsigned int div);
 	uint	voltages;
+
+	struct mmc_config cfg;
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
-- 
1.7.12

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct
  2014-03-12 10:24 [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct Pantelis Antoniou
                   ` (2 preceding siblings ...)
  2014-03-12 10:24 ` [U-Boot] [PATCH 3/3] mmc: Split mmc struct, rework mmc initialization Pantelis Antoniou
@ 2014-03-12 11:32 ` Marek Vasut
  3 siblings, 0 replies; 10+ messages in thread
From: Marek Vasut @ 2014-03-12 11:32 UTC (permalink / raw)
  To: u-boot

On Wednesday, March 12, 2014 at 11:24:24 AM, Pantelis Antoniou wrote:
> Struct mmc has picked up a lot of cruft over the years.
> 
> It is time for it to be split in 3 parts; the original mmc struct
> containing the state, the mmc_config struct containing the board
> setup configuration and the mmc_ops struct contains the method
> pointers.
> 
> Using the new config structures the mmc device creation now gets
> much more easier by using the new mmc_create() call

Is this a V2? I don't see a changelog or anything ...

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/3] mmc: Remove ops from struct mmc and put in mmc_ops
  2014-03-12 10:24 ` [U-Boot] [PATCH 1/3] mmc: Remove ops from struct mmc and put in mmc_ops Pantelis Antoniou
@ 2014-03-14 20:53   ` Simon Glass
  2014-03-14 23:10     ` Marek Vasut
  0 siblings, 1 reply; 10+ messages in thread
From: Simon Glass @ 2014-03-14 20:53 UTC (permalink / raw)
  To: u-boot

Hi,

On 12 March 2014 04:24, Pantelis Antoniou <panto@antoniou-consulting.com> wrote:
> Remove the in-structure ops and put them in mmc_ops with
> a constant pointer to it.
>
> This makes the mmc structure smaller as well as conserving
> code space (in theory).

You might be able to run buildman (and use -S) to check this.

These changes look good to me, and will make it easier to move to
driver model I suspect.

Regards,
Simon

>
> All in-tree drivers are converted as well; this is done in a
> single patch in order to not break git bisect.
>
> Changes since V1:
> Fix compilation b0rked issue on omap platforms where OMAP_GPIO was
> not set.
>
> Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 2/3] mmc: Convert mmc struct's name array to a pointer
  2014-03-12 10:24 ` [U-Boot] [PATCH 2/3] mmc: Convert mmc struct's name array to a pointer Pantelis Antoniou
@ 2014-03-14 20:55   ` Simon Glass
  2014-03-14 23:10     ` Marek Vasut
  0 siblings, 1 reply; 10+ messages in thread
From: Simon Glass @ 2014-03-14 20:55 UTC (permalink / raw)
  To: u-boot

Hi,

On 12 March 2014 04:24, Pantelis Antoniou <panto@antoniou-consulting.com> wrote:
> Using an array is pointless; even more pointless (and scary) is using
> sprintf to fill it without a format string.

This is certainly better, but how about an mmc structure init function
which sets this up?

Regards,
Simon

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 3/3] mmc: Split mmc struct, rework mmc initialization
  2014-03-12 10:24 ` [U-Boot] [PATCH 3/3] mmc: Split mmc struct, rework mmc initialization Pantelis Antoniou
@ 2014-03-14 20:56   ` Simon Glass
  0 siblings, 0 replies; 10+ messages in thread
From: Simon Glass @ 2014-03-14 20:56 UTC (permalink / raw)
  To: u-boot

On 12 March 2014 04:24, Pantelis Antoniou <panto@antoniou-consulting.com> wrote:
> The way that struct mmc was implemented was a bit of a mess;
> configuration and internal state all jumbled up in a single structure.
>
> On top of that the way initialization is done with mmc_register leads
> to a lot of duplicated code in drivers.
>
> Typically the initialization got something like this in every driver.
>
>         struct mmc *mmc = malloc(sizeof(struct mmc));
>         memset(mmc, 0, sizeof(struct mmc);
>         /* fill in fields of mmc struct */
>         /* store private data pointer */
>         mmc_register(mmc);
>
> By using the new mmc_create call one just passes an mmc config struct
> and an optional private data pointer like this:
>
>         struct mmc = mmc_create(&cfg, priv);
>
> All in tree drivers have been updated to the new form, and expect
> mmc_register to go away before long.

Looks like a big improvement!

>
> Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/3] mmc: Remove ops from struct mmc and put in mmc_ops
  2014-03-14 20:53   ` Simon Glass
@ 2014-03-14 23:10     ` Marek Vasut
  0 siblings, 0 replies; 10+ messages in thread
From: Marek Vasut @ 2014-03-14 23:10 UTC (permalink / raw)
  To: u-boot

On Friday, March 14, 2014 at 09:53:51 PM, Simon Glass wrote:
> Hi,
> 
> On 12 March 2014 04:24, Pantelis Antoniou <panto@antoniou-consulting.com> 
wrote:
> > Remove the in-structure ops and put them in mmc_ops with
> > a constant pointer to it.
> > 
> > This makes the mmc structure smaller as well as conserving
> > code space (in theory).
> 
> You might be able to run buildman (and use -S) to check this.
> 
> These changes look good to me, and will make it easier to move to
> driver model I suspect.

Full ack on the driver model part.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 2/3] mmc: Convert mmc struct's name array to a pointer
  2014-03-14 20:55   ` Simon Glass
@ 2014-03-14 23:10     ` Marek Vasut
  0 siblings, 0 replies; 10+ messages in thread
From: Marek Vasut @ 2014-03-14 23:10 UTC (permalink / raw)
  To: u-boot

On Friday, March 14, 2014 at 09:55:08 PM, Simon Glass wrote:
> Hi,
> 
> On 12 March 2014 04:24, Pantelis Antoniou <panto@antoniou-consulting.com> 
wrote:
> > Using an array is pointless; even more pointless (and scary) is using
> > sprintf to fill it without a format string.
> 
> This is certainly better, but how about an mmc structure init function
> which sets this up?

You mean DM's .probe() ? :-)

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-03-14 23:10 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-12 10:24 [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct Pantelis Antoniou
2014-03-12 10:24 ` [U-Boot] [PATCH 1/3] mmc: Remove ops from struct mmc and put in mmc_ops Pantelis Antoniou
2014-03-14 20:53   ` Simon Glass
2014-03-14 23:10     ` Marek Vasut
2014-03-12 10:24 ` [U-Boot] [PATCH 2/3] mmc: Convert mmc struct's name array to a pointer Pantelis Antoniou
2014-03-14 20:55   ` Simon Glass
2014-03-14 23:10     ` Marek Vasut
2014-03-12 10:24 ` [U-Boot] [PATCH 3/3] mmc: Split mmc struct, rework mmc initialization Pantelis Antoniou
2014-03-14 20:56   ` Simon Glass
2014-03-12 11:32 ` [U-Boot] [PATCH 0/3] mmc: Cleanup time for mmc_struct Marek Vasut

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox