mmc: Split mmc struct, rework mmc initialization (v2)
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.
Changes since v1:
* Use calloc instead of manually calling memset.
* Mark mmc_register as deprecated.
Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index ac07bb9..eccdbc4 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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
* 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 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 @@
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 @@
* 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 @@
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);
@@ -1171,8 +1167,33 @@
return 0;
}
-int mmc_register(struct mmc *mmc)
+/* not used any more */
+int __deprecated mmc_register(struct mmc *mmc)
{
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
+ printf("%s is deprecated! use mmc_create() instead.\n", __func__);
+#endif
+ return -1;
+}
+
+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 = calloc(1, sizeof(*mmc));
+ if (mmc == NULL)
+ return NULL;
+
+ mmc->cfg = cfg;
+ mmc->priv = priv;
+
+ /* the following chunk was mmc_register() */
+
/* Setup dsr related values */
mmc->dsr_imp = 0;
mmc->dsr = 0xffffffff;
@@ -1183,14 +1204,21 @@
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;
- INIT_LIST_HEAD (&mmc->link);
+ /* setup initial part type */
+ mmc->block_dev.part_type = mmc->cfg->part_type;
- list_add_tail (&mmc->link, &mmc_devices);
+ INIT_LIST_HEAD(&mmc->link);
- return 0;
+ list_add_tail(&mmc->link, &mmc_devices);
+
+ return mmc;
+}
+
+void mmc_destroy(struct mmc *mmc)
+{
+ /* only freeing memory for now */
+ free(mmc);
}
#ifdef CONFIG_PARTITIONS
@@ -1209,7 +1237,7 @@
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 +1249,7 @@
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 +1351,7 @@
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);