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/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 @@
/* 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 @@
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 @@
/* 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 @@
/* 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 @@
*/
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;
}