summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAlbert ARIBAUD <albert.u.boot@aribaud.net>2014-04-08 09:25:08 +0200
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2014-04-08 09:25:08 +0200
commit519fdde9e6a6ebce7dc743b4f5621503d25b7a45 (patch)
tree29649f48b92b92342183f71565c34afeca0b1735 /drivers
parentc71645ad2bd5179ad21e2501c26f574e9688f02a (diff)
parent04d2f0a9f33112bd70ce4d9c451fdca1682e3a59 (diff)
downloadu-boot-imx-519fdde9e6a6ebce7dc743b4f5621503d25b7a45.zip
u-boot-imx-519fdde9e6a6ebce7dc743b4f5621503d25b7a45.tar.gz
u-boot-imx-519fdde9e6a6ebce7dc743b4f5621503d25b7a45.tar.bz2
Merge branch 'u-boot/master' into 'u-boot-arm/master'
Conflicts: arch/arm/cpu/arm926ejs/mxs/Makefile include/configs/trats.h include/configs/trats2.h include/mmc.h
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/ahci.c23
-rw-r--r--drivers/crypto/ace_sha.c73
-rw-r--r--drivers/crypto/ace_sha.h8
-rw-r--r--drivers/dfu/dfu.c42
-rw-r--r--drivers/dfu/dfu_mmc.c31
-rw-r--r--drivers/i2c/adi_i2c.c387
-rw-r--r--drivers/mmc/arm_pl180_mmci.c50
-rw-r--r--drivers/mmc/arm_pl180_mmci.h4
-rw-r--r--drivers/mmc/bfin_sdh.c38
-rw-r--r--drivers/mmc/davinci_mmc.c41
-rw-r--r--drivers/mmc/dw_mmc.c58
-rw-r--r--drivers/mmc/fsl_esdhc.c143
-rw-r--r--drivers/mmc/ftsdc010_mci.c63
-rw-r--r--drivers/mmc/gen_atmel_mci.c53
-rw-r--r--drivers/mmc/mmc.c111
-rw-r--r--drivers/mmc/mmc_spi.c50
-rw-r--r--drivers/mmc/mmc_write.c3
-rw-r--r--drivers/mmc/mxcmmc.c45
-rw-r--r--drivers/mmc/mxsmmc.c48
-rw-r--r--drivers/mmc/omap_hsmmc.c142
-rw-r--r--drivers/mmc/pxa_mmc_gen.c70
-rw-r--r--drivers/mmc/sdhci.c84
-rw-r--r--drivers/mmc/sh_mmcif.c55
-rw-r--r--drivers/mmc/tegra_mmc.c53
-rw-r--r--drivers/net/designware.h2
-rw-r--r--drivers/usb/gadget/f_dfu.c48
26 files changed, 787 insertions, 938 deletions
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c
index a409f63..c8f6573 100644
--- a/drivers/block/ahci.c
+++ b/drivers/block/ahci.c
@@ -623,6 +623,7 @@ static int ata_scsiop_inquiry(ccb *pccb)
95 - 4,
};
u8 fis[20];
+ u16 *idbuf;
ALLOC_CACHE_ALIGN_BUFFER(u16, tmpid, ATA_ID_WORDS);
u8 port;
@@ -649,17 +650,25 @@ static int ata_scsiop_inquiry(ccb *pccb)
return -EIO;
}
- if (ataid[port])
- free(ataid[port]);
- ataid[port] = tmpid;
- ata_swap_buf_le16(tmpid, ATA_ID_WORDS);
+ if (!ataid[port]) {
+ ataid[port] = malloc(ATA_ID_WORDS * 2);
+ if (!ataid[port]) {
+ printf("%s: No memory for ataid[port]\n", __func__);
+ return -ENOMEM;
+ }
+ }
+
+ idbuf = ataid[port];
+
+ memcpy(idbuf, tmpid, ATA_ID_WORDS * 2);
+ ata_swap_buf_le16(idbuf, ATA_ID_WORDS);
memcpy(&pccb->pdata[8], "ATA ", 8);
- ata_id_strcpy((u16 *) &pccb->pdata[16], &tmpid[ATA_ID_PROD], 16);
- ata_id_strcpy((u16 *) &pccb->pdata[32], &tmpid[ATA_ID_FW_REV], 4);
+ ata_id_strcpy((u16 *)&pccb->pdata[16], &idbuf[ATA_ID_PROD], 16);
+ ata_id_strcpy((u16 *)&pccb->pdata[32], &idbuf[ATA_ID_FW_REV], 4);
#ifdef DEBUG
- ata_dump_id(tmpid);
+ ata_dump_id(idbuf);
#endif
return 0;
}
diff --git a/drivers/crypto/ace_sha.c b/drivers/crypto/ace_sha.c
index acbafde..ed4f541 100644
--- a/drivers/crypto/ace_sha.c
+++ b/drivers/crypto/ace_sha.c
@@ -5,10 +5,12 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
+#include "ace_sha.h"
+
+#ifdef CONFIG_SHA_HW_ACCEL
#include <sha256.h>
#include <sha1.h>
#include <asm/errno.h>
-#include "ace_sha.h"
/* SHA1 value for the message of zero length */
static const unsigned char sha1_digest_emptymsg[SHA1_SUM_LEN] = {
@@ -111,3 +113,72 @@ void hw_sha1(const unsigned char *pbuf, unsigned int buf_len,
if (ace_sha_hash_digest(pbuf, buf_len, pout, ACE_SHA_TYPE_SHA1))
debug("ACE was not setup properly or it is faulty\n");
}
+#endif /* CONFIG_SHA_HW_ACCEL */
+
+#ifdef CONFIG_LIB_HW_RAND
+static unsigned int seed_done;
+
+void srand(unsigned int seed)
+{
+ struct exynos_ace_sfr *reg =
+ (struct exynos_ace_sfr *)samsung_get_base_ace_sfr();
+ int i, status;
+
+ /* Seed data */
+ for (i = 0; i < ACE_HASH_PRNG_REG_NUM; i++)
+ writel(seed << i, &reg->hash_seed[i]);
+
+ /* Wait for seed setup done */
+ while (1) {
+ status = readl(&reg->hash_status);
+ if ((status & ACE_HASH_SEEDSETTING_MASK) ||
+ (status & ACE_HASH_PRNGERROR_MASK))
+ break;
+ }
+
+ seed_done = 1;
+}
+
+unsigned int rand(void)
+{
+ struct exynos_ace_sfr *reg =
+ (struct exynos_ace_sfr *)samsung_get_base_ace_sfr();
+ int i, status;
+ unsigned int seed = (unsigned int)&status;
+ unsigned int ret = 0;
+
+ if (!seed_done)
+ srand(seed);
+
+ /* Start PRNG */
+ writel(ACE_HASH_ENGSEL_PRNG | ACE_HASH_STARTBIT_ON, &reg->hash_control);
+
+ /* Wait for PRNG done */
+ while (1) {
+ status = readl(&reg->hash_status);
+ if (status & ACE_HASH_PRNGDONE_MASK)
+ break;
+ if (status & ACE_HASH_PRNGERROR_MASK) {
+ seed_done = 0;
+ return 0;
+ }
+ }
+
+ /* Clear Done IRQ */
+ writel(ACE_HASH_PRNGDONE_MASK, &reg->hash_status);
+
+ /* Read a PRNG result */
+ for (i = 0; i < ACE_HASH_PRNG_REG_NUM; i++)
+ ret += readl(&reg->hash_prng[i]);
+
+ seed_done = 0;
+ return ret;
+}
+
+unsigned int rand_r(unsigned int *seedp)
+{
+ srand(*seedp);
+
+ return rand();
+}
+#endif /* CONFIG_LIB_HW_RAND */
diff --git a/drivers/crypto/ace_sha.h b/drivers/crypto/ace_sha.h
index a426d52..f1097f7 100644
--- a/drivers/crypto/ace_sha.h
+++ b/drivers/crypto/ace_sha.h
@@ -72,9 +72,10 @@ struct exynos_ace_sfr {
unsigned char res12[0x30];
unsigned int hash_result[8];
unsigned char res13[0x20];
- unsigned int hash_seed[8];
- unsigned int hash_prng[8];
- unsigned char res14[0x180];
+ unsigned int hash_seed[5];
+ unsigned char res14[12];
+ unsigned int hash_prng[5];
+ unsigned char res15[0x18c];
unsigned int pka_sfr[5]; /* base + 0x700 */
};
@@ -291,6 +292,7 @@ struct exynos_ace_sfr {
#define ACE_HASH_PRNGERROR_MASK (1 << 7)
#define ACE_HASH_PRNGERROR_OFF (0 << 7)
#define ACE_HASH_PRNGERROR_ON (1 << 7)
+#define ACE_HASH_PRNG_REG_NUM 5
#define ACE_SHA_TYPE_SHA1 1
#define ACE_SHA_TYPE_SHA256 2
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 56e69fd..8a09aaf 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -127,6 +127,28 @@ static int dfu_write_buffer_drain(struct dfu_entity *dfu)
return ret;
}
+int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+ int ret = 0;
+
+ if (dfu->flush_medium)
+ ret = dfu->flush_medium(dfu);
+
+ printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc);
+
+ /* clear everything */
+ dfu_free_buf();
+ dfu->crc = 0;
+ dfu->offset = 0;
+ dfu->i_blk_seq_num = 0;
+ dfu->i_buf_start = dfu_buf;
+ dfu->i_buf_end = dfu_buf;
+ dfu->i_buf = dfu->i_buf_start;
+ dfu->inited = 0;
+
+ return ret;
+}
+
int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
{
int ret = 0;
@@ -197,26 +219,6 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
ret = tret;
}
- /* end? */
- if (size == 0) {
- /* Now try and flush to the medium if needed. */
- if (dfu->flush_medium)
- ret = dfu->flush_medium(dfu);
- printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc);
-
- /* clear everything */
- dfu_free_buf();
- dfu->crc = 0;
- dfu->offset = 0;
- dfu->i_blk_seq_num = 0;
- dfu->i_buf_start = dfu_buf;
- dfu->i_buf_end = dfu_buf;
- dfu->i_buf = dfu->i_buf_start;
-
- dfu->inited = 0;
-
- }
-
return ret = 0 ? size : ret;
}
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 0816f46..651cfff 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -12,6 +12,7 @@
#include <errno.h>
#include <div64.h>
#include <dfu.h>
+#include <mmc.h>
static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE];
@@ -20,8 +21,8 @@ static long dfu_file_buf_len;
static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
u64 offset, void *buf, long *len)
{
- char cmd_buf[DFU_CMD_BUF_SIZE];
- u32 blk_start, blk_count;
+ struct mmc *mmc = find_mmc_device(dfu->dev_num);
+ u32 blk_start, blk_count, n = 0;
/*
* We must ensure that we work in lba_blk_size chunks, so ALIGN
@@ -38,12 +39,28 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
return -EINVAL;
}
- sprintf(cmd_buf, "mmc %s %p %x %x",
- op == DFU_OP_READ ? "read" : "write",
- buf, blk_start, blk_count);
+ debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__,
+ op == DFU_OP_READ ? "MMC READ" : "MMC WRITE", dfu->dev_num,
+ blk_start, blk_count, buf);
+ switch (op) {
+ case DFU_OP_READ:
+ n = mmc->block_dev.block_read(dfu->dev_num, blk_start,
+ blk_count, buf);
+ break;
+ case DFU_OP_WRITE:
+ n = mmc->block_dev.block_write(dfu->dev_num, blk_start,
+ blk_count, buf);
+ break;
+ default:
+ error("Operation not supported\n");
+ }
- debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
- return run_command(cmd_buf, 0);
+ if (n != blk_count) {
+ error("MMC operation failed");
+ return -EIO;
+ }
+
+ return 0;
}
static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len)
diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c
deleted file mode 100644
index 675f417..0000000
--- a/drivers/i2c/adi_i2c.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * i2c.c - driver for ADI TWI/I2C
- *
- * Copyright (c) 2006-2013 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <i2c.h>
-
-#include <asm/clock.h>
-#include <asm/twi.h>
-#include <asm/io.h>
-
-/* Every register is 32bit aligned, but only 16bits in size */
-#define ureg(name) u16 name; u16 __pad_##name;
-struct twi_regs {
- ureg(clkdiv);
- ureg(control);
- ureg(slave_ctl);
- ureg(slave_stat);
- ureg(slave_addr);
- ureg(master_ctl);
- ureg(master_stat);
- ureg(master_addr);
- ureg(int_stat);
- ureg(int_mask);
- ureg(fifo_ctl);
- ureg(fifo_stat);
- char __pad[0x50];
- ureg(xmt_data8);
- ureg(xmt_data16);
- ureg(rcv_data8);
- ureg(rcv_data16);
-};
-#undef ureg
-
-/* U-Boot I2C framework allows only one active device at a time. */
-#ifdef TWI_CLKDIV
-#define TWI0_CLKDIV TWI_CLKDIV
-#endif
-static struct twi_regs *twi = (void *)TWI0_CLKDIV;
-
-#ifdef DEBUG
-# define dmemset(s, c, n) memset(s, c, n)
-#else
-# define dmemset(s, c, n)
-#endif
-#define debugi(fmt, args...) \
- debug( \
- "MSTAT:0x%03x FSTAT:0x%x ISTAT:0x%02x\t%-20s:%-3i: " fmt "\n", \
- twi->master_stat, twi->fifo_stat, twi->int_stat, \
- __func__, __LINE__, ## args)
-
-#ifdef CONFIG_TWICLK_KHZ
-# error do not define CONFIG_TWICLK_KHZ ... use CONFIG_SYS_I2C_SPEED
-#endif
-
-/*
- * The way speed is changed into duty often results in integer truncation
- * with 50% duty, so we'll force rounding up to the next duty by adding 1
- * to the max. In practice this will get us a speed of something like
- * 385 KHz. The other limit is easy to handle as it is only 8 bits.
- */
-#define I2C_SPEED_MAX 400000
-#define I2C_SPEED_TO_DUTY(speed) (5000000 / (speed))
-#define I2C_DUTY_MAX (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1)
-#define I2C_DUTY_MIN 0xff /* 8 bit limited */
-#define SYS_I2C_DUTY I2C_SPEED_TO_DUTY(CONFIG_SYS_I2C_SPEED)
-/* Note: duty is inverse of speed, so the comparisons below are correct */
-#if SYS_I2C_DUTY < I2C_DUTY_MAX || SYS_I2C_DUTY > I2C_DUTY_MIN
-# error "The Blackfin I2C hardware can only operate 20KHz - 400KHz"
-#endif
-
-/* All transfers are described by this data structure */
-struct i2c_msg {
- u8 flags;
-#define I2C_M_COMBO 0x4
-#define I2C_M_STOP 0x2
-#define I2C_M_READ 0x1
- int len; /* msg length */
- u8 *buf; /* pointer to msg data */
- int alen; /* addr length */
- u8 *abuf; /* addr buffer */
-};
-
-/* Allow msec timeout per ~byte transfer */
-#define I2C_TIMEOUT 10
-
-/**
- * wait_for_completion - manage the actual i2c transfer
- * @msg: the i2c msg
- */
-static int wait_for_completion(struct i2c_msg *msg)
-{
- u16 int_stat, ctl;
- ulong timebase = get_timer(0);
-
- do {
- int_stat = readw(&twi->int_stat);
-
- if (int_stat & XMTSERV) {
- debugi("processing XMTSERV");
- writew(XMTSERV, &twi->int_stat);
- if (msg->alen) {
- writew(*(msg->abuf++), &twi->xmt_data8);
- --msg->alen;
- } else if (!(msg->flags & I2C_M_COMBO) && msg->len) {
- writew(*(msg->buf++), &twi->xmt_data8);
- --msg->len;
- } else {
- ctl = readw(&twi->master_ctl);
- if (msg->flags & I2C_M_COMBO)
- writew(ctl | RSTART | MDIR,
- &twi->master_ctl);
- else
- writew(ctl | STOP, &twi->master_ctl);
- }
- }
- if (int_stat & RCVSERV) {
- debugi("processing RCVSERV");
- writew(RCVSERV, &twi->int_stat);
- if (msg->len) {
- *(msg->buf++) = readw(&twi->rcv_data8);
- --msg->len;
- } else if (msg->flags & I2C_M_STOP) {
- ctl = readw(&twi->master_ctl);
- writew(ctl | STOP, &twi->master_ctl);
- }
- }
- if (int_stat & MERR) {
- debugi("processing MERR");
- writew(MERR, &twi->int_stat);
- return msg->len;
- }
- if (int_stat & MCOMP) {
- debugi("processing MCOMP");
- writew(MCOMP, &twi->int_stat);
- if (msg->flags & I2C_M_COMBO && msg->len) {
- ctl = readw(&twi->master_ctl);
- ctl = (ctl & ~RSTART) |
- (min(msg->len, 0xff) << 6) | MEN | MDIR;
- writew(ctl, &twi->master_ctl);
- } else
- break;
- }
-
- /* If we were able to do something, reset timeout */
- if (int_stat)
- timebase = get_timer(0);
-
- } while (get_timer(timebase) < I2C_TIMEOUT);
-
- return msg->len;
-}
-
-/**
- * i2c_transfer - setup an i2c transfer
- * @return: 0 if things worked, non-0 if things failed
- *
- * Here we just get the i2c stuff all prepped and ready, and then tail off
- * into wait_for_completion() for all the bits to go.
- */
-static int i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer,
- int len, u8 flags)
-{
- int ret;
- u16 ctl;
- uchar addr_buffer[] = {
- (addr >> 0),
- (addr >> 8),
- (addr >> 16),
- };
- struct i2c_msg msg = {
- .flags = flags | (len >= 0xff ? I2C_M_STOP : 0),
- .buf = buffer,
- .len = len,
- .abuf = addr_buffer,
- .alen = alen,
- };
-
- dmemset(buffer, 0xff, len);
- debugi("chip=0x%x addr=0x%02x alen=%i buf[0]=0x%02x len=%i ",
- chip, addr, alen, buffer[0], len);
- debugi("flags=0x%02x[%s] ", flags,
- (flags & I2C_M_READ ? "rd" : "wr"));
-
- /* wait for things to settle */
- while (readw(&twi->master_stat) & BUSBUSY)
- if (ctrlc())
- return 1;
-
- /* Set Transmit device address */
- writew(chip, &twi->master_addr);
-
- /* Clear the FIFO before starting things */
- writew(XMTFLUSH | RCVFLUSH, &twi->fifo_ctl);
- writew(0, &twi->fifo_ctl);
-
- /* prime the pump */
- if (msg.alen) {
- len = (msg.flags & I2C_M_COMBO) ? msg.alen : msg.alen + len;
- debugi("first byte=0x%02x", *msg.abuf);
- writew(*(msg.abuf++), &twi->xmt_data8);
- --msg.alen;
- } else if (!(msg.flags & I2C_M_READ) && msg.len) {
- debugi("first byte=0x%02x", *msg.buf);
- writew(*(msg.buf++), &twi->xmt_data8);
- --msg.len;
- }
-
- /* clear int stat */
- writew(-1, &twi->master_stat);
- writew(-1, &twi->int_stat);
- writew(0, &twi->int_mask);
-
- /* Master enable */
- ctl = readw(&twi->master_ctl);
- ctl = (ctl & FAST) | (min(len, 0xff) << 6) | MEN |
- ((msg.flags & I2C_M_READ) ? MDIR : 0);
- writew(ctl, &twi->master_ctl);
-
- /* process the rest */
- ret = wait_for_completion(&msg);
- debugi("ret=%d", ret);
-
- if (ret) {
- ctl = readw(&twi->master_ctl) & ~MEN;
- writew(ctl, &twi->master_ctl);
- ctl = readw(&twi->control) & ~TWI_ENA;
- writew(ctl, &twi->control);
- ctl = readw(&twi->control) | TWI_ENA;
- writew(ctl, &twi->control);
- }
-
- return ret;
-}
-
-/**
- * i2c_set_bus_speed - set i2c bus speed
- * @speed: bus speed (in HZ)
- */
-int i2c_set_bus_speed(unsigned int speed)
-{
- u16 clkdiv = I2C_SPEED_TO_DUTY(speed);
-
- /* Set TWI interface clock */
- if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN)
- return -1;
- clkdiv = (clkdiv << 8) | (clkdiv & 0xff);
- writew(clkdiv, &twi->clkdiv);
-
- /* Don't turn it on */
- writew(speed > 100000 ? FAST : 0, &twi->master_ctl);
-
- return 0;
-}
-
-/**
- * i2c_get_bus_speed - get i2c bus speed
- * @speed: bus speed (in HZ)
- */
-unsigned int i2c_get_bus_speed(void)
-{
- u16 clkdiv = readw(&twi->clkdiv) & 0xff;
- /* 10 MHz / (2 * CLKDIV) -> 5 MHz / CLKDIV */
- return 5000000 / clkdiv;
-}
-
-/**
- * i2c_init - initialize the i2c bus
- * @speed: bus speed (in HZ)
- * @slaveaddr: address of device in slave mode (0 - not slave)
- *
- * Slave mode isn't actually implemented. It'll stay that way until
- * we get a real request for it.
- */
-void i2c_init(int speed, int slaveaddr)
-{
- u16 prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F;
-
- /* Set TWI internal clock as 10MHz */
- writew(prescale, &twi->control);
-
- /* Set TWI interface clock as specified */
- i2c_set_bus_speed(speed);
-
- /* Enable it */
- writew(TWI_ENA | prescale, &twi->control);
-
- debugi("CONTROL:0x%04x CLKDIV:0x%04x", readw(&twi->control),
- readw(&twi->clkdiv));
-
-#if CONFIG_SYS_I2C_SLAVE
-# error I2C slave support not tested/supported
-#endif
-}
-
-/**
- * i2c_probe - test if a chip exists at a given i2c address
- * @chip: i2c chip addr to search for
- * @return: 0 if found, non-0 if not found
- */
-int i2c_probe(uchar chip)
-{
- u8 byte;
- return i2c_read(chip, 0, 0, &byte, 1);
-}
-
-/**
- * i2c_read - read data from an i2c device
- * @chip: i2c chip addr
- * @addr: memory (register) address in the chip
- * @alen: byte size of address
- * @buffer: buffer to store data read from chip
- * @len: how many bytes to read
- * @return: 0 on success, non-0 on failure
- */
-int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
-{
- return i2c_transfer(chip, addr, alen, buffer,
- len, (alen ? I2C_M_COMBO : I2C_M_READ));
-}
-
-/**
- * i2c_write - write data to an i2c device
- * @chip: i2c chip addr
- * @addr: memory (register) address in the chip
- * @alen: byte size of address
- * @buffer: buffer holding data to write to chip
- * @len: how many bytes to write
- * @return: 0 on success, non-0 on failure
- */
-int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
-{
- return i2c_transfer(chip, addr, alen, buffer, len, 0);
-}
-
-/**
- * i2c_set_bus_num - change active I2C bus
- * @bus: bus index, zero based
- * @returns: 0 on success, non-0 on failure
- */
-int i2c_set_bus_num(unsigned int bus)
-{
- switch (bus) {
-#if CONFIG_SYS_MAX_I2C_BUS > 0
- case 0:
- twi = (void *)TWI0_CLKDIV;
- return 0;
-#endif
-#if CONFIG_SYS_MAX_I2C_BUS > 1
- case 1:
- twi = (void *)TWI1_CLKDIV;
- return 0;
-#endif
-#if CONFIG_SYS_MAX_I2C_BUS > 2
- case 2:
- twi = (void *)TWI2_CLKDIV;
- return 0;
-#endif
- default: return -1;
- }
-}
-
-/**
- * i2c_get_bus_num - returns index of active I2C bus
- */
-unsigned int i2c_get_bus_num(void)
-{
- switch ((unsigned long)twi) {
-#if CONFIG_SYS_MAX_I2C_BUS > 0
- case TWI0_CLKDIV:
- return 0;
-#endif
-#if CONFIG_SYS_MAX_I2C_BUS > 1
- case TWI1_CLKDIV:
- return 1;
-#endif
-#if CONFIG_SYS_MAX_I2C_BUS > 2
- case TWI2_CLKDIV:
- return 2;
-#endif
- default: return -1;
- }
-}
diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index 5a55fe7..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;
}
@@ -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.
@@ -342,16 +348,9 @@ static void host_set_ios(struct mmc *dev)
*/
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);
@@ -359,19 +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);
- 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->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 bd9b641..bcd6a3e 100644
--- a/drivers/mmc/bfin_sdh.c
+++ b/drivers/mmc/bfin_sdh.c
@@ -274,30 +274,30 @@ 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,
+};
+
+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;
+ struct mmc *mmc;
- mmc = malloc(sizeof(struct mmc));
+ bfin_mmc_cfg.f_max = get_sclk();
+ bfin_mmc_cfg.f_min = bfin_mmc_cfg.f_max >> 9;
- 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->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;
-
- mmc->b_max = 0;
-
- 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 b380961..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;
@@ -363,32 +363,27 @@ 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
*/
int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
{
- struct mmc *mmc;
-
- mmc = malloc(sizeof(struct mmc));
- memset(mmc, 0, sizeof(struct mmc));
-
- 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->f_min = 200000;
- mmc->f_max = 25000000;
- mmc->voltages = host->voltages;
- mmc->host_caps = host->host_caps;
+ 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->b_max = DAVINCI_MAX_BLOCKS;
+ host->cfg.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 d45c15c..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);
@@ -343,41 +343,37 @@ 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;
- int err = 0;
-
- mmc = calloc(sizeof(struct mmc), 1);
- if (!mmc) {
- printf("mmc calloc fail!\n");
- return -1;
- }
-
- mmc->priv = host;
- host->mmc = mmc;
+ host->cfg.name = host->name;
+ host->cfg.ops = &dwmci_ops;
+ host->cfg.f_min = min_clk;
+ host->cfg.f_max = max_clk;
- sprintf(mmc->name, "%s", host->name);
- mmc->send_cmd = dwmci_send_cmd;
- mmc->set_ios = dwmci_set_ios;
- mmc->init = dwmci_init;
- 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 7b146a3..4c3b93d 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;
@@ -221,16 +221,16 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
* 2)Timeout period should be minimum 0.250sec as per SD Card spec
* So, Number of SD Clock cycles for 0.25sec should be minimum
* (SD Clock/sec * 0.25 sec) SD Clock cycles
- * = (mmc->tran_speed * 1/4) SD Clock cycles
+ * = (mmc->clock * 1/4) SD Clock cycles
* As 1) >= 2)
- * => (2^(timeout+13)) >= mmc->tran_speed * 1/4
+ * => (2^(timeout+13)) >= mmc->clock * 1/4
* Taking log2 both the sides
- * => timeout + 13 >= log2(mmc->tran_speed/4)
+ * => timeout + 13 >= log2(mmc->clock/4)
* Rounding up to next power of 2
- * => timeout + 13 = log2(mmc->tran_speed/4) + 1
- * => timeout + 13 = fls(mmc->tran_speed/4)
+ * => timeout + 13 = log2(mmc->clock/4) + 1
+ * => timeout + 13 = fls(mmc->clock/4)
*/
- timeout = fls(mmc->tran_speed/4);
+ timeout = fls(mmc->clock/4);
timeout -= 13;
if (timeout > 14)
@@ -244,6 +244,9 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
timeout++;
#endif
+#ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
+ timeout = 0xE;
+#endif
esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
return 0;
@@ -265,9 +268,10 @@ static void check_and_invalidate_dcache_range
static int
esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
+ int err = 0;
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
@@ -296,8 +300,6 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
/* Set up for a data transfer if we have one */
if (data) {
- int err;
-
err = esdhc_setup_data(mmc, data);
if(err)
return err;
@@ -325,27 +327,15 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
irqstat = esdhc_read32(&regs->irqstat);
- /* Reset CMD and DATA portions on error */
- if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) {
- esdhc_write32(&regs->sysctl, esdhc_read32(&regs->sysctl) |
- SYSCTL_RSTC);
- while (esdhc_read32(&regs->sysctl) & SYSCTL_RSTC)
- ;
-
- if (data) {
- esdhc_write32(&regs->sysctl,
- esdhc_read32(&regs->sysctl) |
- SYSCTL_RSTD);
- while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTD))
- ;
- }
+ if (irqstat & CMD_ERR) {
+ err = COMM_ERR;
+ goto out;
}
- if (irqstat & CMD_ERR)
- return COMM_ERR;
-
- if (irqstat & IRQSTAT_CTOE)
- return TIMEOUT;
+ if (irqstat & IRQSTAT_CTOE) {
+ err = TIMEOUT;
+ goto out;
+ }
/* Workaround for ESDHC errata ENGcm03648 */
if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
@@ -360,7 +350,8 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
if (timeout <= 0) {
printf("Timeout waiting for DAT0 to go high!\n");
- return TIMEOUT;
+ err = TIMEOUT;
+ goto out;
}
}
@@ -387,32 +378,53 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
do {
irqstat = esdhc_read32(&regs->irqstat);
- if (irqstat & IRQSTAT_DTOE)
- return TIMEOUT;
+ if (irqstat & IRQSTAT_DTOE) {
+ err = TIMEOUT;
+ goto out;
+ }
- if (irqstat & DATA_ERR)
- return COMM_ERR;
+ if (irqstat & DATA_ERR) {
+ err = COMM_ERR;
+ goto out;
+ }
} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
#endif
if (data->flags & MMC_DATA_READ)
check_and_invalidate_dcache_range(cmd, data);
}
+out:
+ /* Reset CMD and DATA portions on error */
+ if (err) {
+ esdhc_write32(&regs->sysctl, esdhc_read32(&regs->sysctl) |
+ SYSCTL_RSTC);
+ while (esdhc_read32(&regs->sysctl) & SYSCTL_RSTC)
+ ;
+
+ if (data) {
+ esdhc_write32(&regs->sysctl,
+ esdhc_read32(&regs->sysctl) |
+ SYSCTL_RSTD);
+ while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTD))
+ ;
+ }
+ }
+
esdhc_write32(&regs->irqstat, -1);
- return 0;
+ return err;
}
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 +455,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 +473,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 +508,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;
@@ -524,6 +536,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;
@@ -533,12 +552,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));
- sprintf(mmc->name, "FSL_SDHC");
regs = (struct fsl_esdhc *)cfg->esdhc_base;
/* First reset the eSDHC controller */
@@ -547,12 +560,7 @@ 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->send_cmd = esdhc_send_cmd;
- mmc->set_ios = esdhc_set_ios;
- mmc->init = esdhc_init;
- mmc->getcd = esdhc_getcd;
- mmc->getwp = NULL;
+ memset(&cfg->cfg, 0, sizeof(cfg->cfg));
voltage_caps = 0;
caps = regs->hostcapblt;
@@ -574,38 +582,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 7600d5c..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;
@@ -316,6 +309,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;
@@ -331,50 +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;
-
- sprintf(mmc->name, "ftsdc010");
- mmc->send_cmd = ftsdc010_request;
- mmc->set_ios = ftsdc010_set_ios;
- mmc->init = ftsdc010_init;
+#ifdef CONFIG_SYS_CLK_FREQ
+ chip->sclk = CONFIG_SYS_CLK_FREQ;
+#else
+ chip->sclk = clk_get_rate("SDC");
+#endif
- 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 c11dcd0..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 */
@@ -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
*
@@ -351,40 +357,45 @@ static int mci_init(struct mmc *mmc)
*/
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));
+
+ mci = (struct atmel_mci *)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;
+ 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 8ab0bc9..16051e5 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->getwp)
- wp = mmc->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->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->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->getcd)
- cd = mmc->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,16 +747,17 @@ static const int multipliers[] = {
static void mmc_set_ios(struct mmc *mmc)
{
- mmc->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;
@@ -1026,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) {
@@ -1081,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,
@@ -1154,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);
@@ -1170,8 +1167,33 @@ static int mmc_send_if_cond(struct mmc *mmc)
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;
@@ -1182,14 +1204,21 @@ 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;
- 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
@@ -1207,7 +1236,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->cfg->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 +1248,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->cfg->ops->init(mmc);
if (err)
return err;
@@ -1320,7 +1351,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);
@@ -1482,4 +1513,16 @@ int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
return err;
return 0;
}
+
+/*
+ * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value
+ * for enable. Note that this is a write-once field for non-zero values.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
+{
+ return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION,
+ enable);
+}
#endif
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index fe6a5a1..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 */
@@ -255,33 +255,37 @@ 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,
+};
+
+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;
- }
- 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->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 4f99617..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)
@@ -485,35 +487,30 @@ static int mxcmci_init(struct mmc *mmc)
return 0;
}
-static int mxcmci_initialize(bd_t *bis)
-{
- struct mmc *mmc = NULL;
-
- mmc = malloc(sizeof(struct mmc));
-
- if (!mmc)
- return -ENOMEM;
+static const struct mmc_ops mxcmci_ops = {
+ .send_cmd = mxcmci_request,
+ .set_ios = mxcmci_set_ios,
+ .init = mxcmci_init,
+};
- 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->host_caps = MMC_MODE_4BIT;
+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)
+{
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 245f9d0..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 */
@@ -363,6 +364,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;
@@ -373,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;
}
@@ -399,17 +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);
- 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->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;
@@ -419,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 d3a8b53..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>
@@ -35,14 +36,25 @@
#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;
+ struct mmc_config cfg;
+#ifdef OMAP_HSMMC_USE_GPIO
int cd_gpio;
int wp_gpio;
+#endif
};
/* If we fail after 1 second wait, something is really bad */
@@ -51,11 +63,8 @@ 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];
-#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)
@@ -158,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);
@@ -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,19 +595,58 @@ 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)
{
- 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;
- sprintf(mmc->name, "OMAP SD/MMC");
- mmc->send_cmd = mmc_send_cmd;
- mmc->set_ios = mmc_set_ios;
- mmc->init = mmc_init_setup;
- mmc->priv = priv_data;
+ priv_data = malloc(sizeof(*priv_data));
+ if (priv_data == NULL)
+ return -1;
+
+ host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
+ MMC_MODE_HC;
switch (dev_index) {
case 0:
@@ -647,42 +675,46 @@ 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
+
+ cfg = &priv_data->cfg;
- mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
- mmc->host_caps = host_caps_val & ~host_caps_mask;
+ cfg->name = "OMAP SD/MMC";
+ cfg->ops = &omap_hsmmc_ops;
- mmc->f_min = 400000;
+ 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 29f3eaf..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 */
@@ -366,6 +366,22 @@ 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,
+};
+
+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;
@@ -373,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:
@@ -389,26 +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;
-
- 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->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;
@@ -419,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 1e86b92..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;
@@ -430,26 +430,19 @@ 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;
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;
-
- 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;
+ host->cfg.name = host->name;
+ host->cfg.ops = &sdhci_ops;
caps = sdhci_readl(host, SDHCI_CAPABILITIES);
#ifdef CONFIG_MMC_SDMA
@@ -461,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 011d4f3..ed83a14 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,44 +562,48 @@ 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);
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,
+};
+
+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;
+ return -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;
- 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;
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 3d1ce12..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;
@@ -314,7 +313,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 +395,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;
@@ -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));
@@ -464,9 +463,9 @@ 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;
+ struct mmc_host *host = mmc->priv;
unsigned int mask;
debug(" mmc_core_init called\n");
@@ -511,7 +510,7 @@ static int 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");
@@ -521,6 +520,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;
@@ -554,23 +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));
- 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;
+ 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
@@ -578,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;
+
+ host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
- mmc_register(mmc);
+ mmc = mmc_create(&host->cfg, host);
+ if (mmc == NULL)
+ return -1;
return 0;
}
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index afeacce..382b0c7 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -110,7 +110,7 @@ struct dmamacdescr {
u32 dmamac_cntl;
void *dmamac_addr;
struct dmamacdescr *dmamac_next;
-} __aligned(16);
+} __aligned(ARCH_DMA_MINALIGN);
/*
* txrx_status definitions
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index a045864..de75ff1 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -164,9 +164,14 @@ static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
req->length, f_dfu->blk_seq_num);
+}
- if (req->length == 0)
- puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
+static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_dfu *f_dfu = req->context;
+
+ dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf,
+ req->length, f_dfu->blk_seq_num);
}
static void handle_getstatus(struct usb_request *req)
@@ -174,19 +179,22 @@ static void handle_getstatus(struct usb_request *req)
struct dfu_status *dstat = (struct dfu_status *)req->buf;
struct f_dfu *f_dfu = req->context;
+ dfu_set_poll_timeout(dstat, 0);
+
switch (f_dfu->dfu_state) {
case DFU_STATE_dfuDNLOAD_SYNC:
case DFU_STATE_dfuDNBUSY:
f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
break;
case DFU_STATE_dfuMANIFEST_SYNC:
+ f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
break;
+ case DFU_STATE_dfuMANIFEST:
+ dfu_set_poll_timeout(dstat, DFU_MANIFEST_POLL_TIMEOUT);
default:
break;
}
- dfu_set_poll_timeout(dstat, 0);
-
if (f_dfu->poll_timeout)
if (!(f_dfu->blk_seq_num %
(dfu_get_buf_size() / DFU_USB_BUFSIZ)))
@@ -446,10 +454,11 @@ static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
switch (ctrl->bRequest) {
case USB_REQ_DFU_GETSTATUS:
/* We're MainfestationTolerant */
- f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+ f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
handle_getstatus(req);
f_dfu->blk_seq_num = 0;
value = RET_STAT_LEN;
+ req->complete = dnload_request_flush;
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate(req);
@@ -463,6 +472,33 @@ static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
return value;
}
+static int state_dfu_manifest(struct f_dfu *f_dfu,
+ const struct usb_ctrlrequest *ctrl,
+ struct usb_gadget *gadget,
+ struct usb_request *req)
+{
+ int value = 0;
+
+ switch (ctrl->bRequest) {
+ case USB_REQ_DFU_GETSTATUS:
+ /* We're MainfestationTolerant */
+ f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+ handle_getstatus(req);
+ f_dfu->blk_seq_num = 0;
+ value = RET_STAT_LEN;
+ puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
+ break;
+ case USB_REQ_DFU_GETSTATE:
+ handle_getstate(req);
+ break;
+ default:
+ f_dfu->dfu_state = DFU_STATE_dfuERROR;
+ value = RET_STALL;
+ break;
+ }
+ return value;
+}
+
static int state_dfu_upload_idle(struct f_dfu *f_dfu,
const struct usb_ctrlrequest *ctrl,
struct usb_gadget *gadget,
@@ -539,7 +575,7 @@ static dfu_state_fn dfu_state[] = {
state_dfu_dnbusy, /* DFU_STATE_dfuDNBUSY */
state_dfu_dnload_idle, /* DFU_STATE_dfuDNLOAD_IDLE */
state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
- NULL, /* DFU_STATE_dfuMANIFEST */
+ state_dfu_manifest, /* DFU_STATE_dfuMANIFEST */
NULL, /* DFU_STATE_dfuMANIFEST_WAIT_RST */
state_dfu_upload_idle, /* DFU_STATE_dfuUPLOAD_IDLE */
state_dfu_error /* DFU_STATE_dfuERROR */