Commit 93bfd616 authored by Pantelis Antoniou's avatar Pantelis Antoniou

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: default avatarPantelis Antoniou <panto@antoniou-consulting.com>
parent 22cb7d33
......@@ -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 {
......
......@@ -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);
......
......@@ -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,
......
......@@ -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;
......
......@@ -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;
}
......@@ -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 *);
......
......@@ -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;
}
......@@ -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;
}
......@@ -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;
}
......@@ -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;
}
......
......@@ -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;
}
......@@ -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;
}
......@@ -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