diff options
author | Albert ARIBAUD | 2014-04-08 09:25:08 +0200 |
---|---|---|
committer | Albert ARIBAUD | 2014-04-08 09:25:08 +0200 |
commit | 519fdde9e6a6ebce7dc743b4f5621503d25b7a45 (patch) | |
tree | 29649f48b92b92342183f71565c34afeca0b1735 /drivers | |
parent | c71645ad2bd5179ad21e2501c26f574e9688f02a (diff) | |
parent | 04d2f0a9f33112bd70ce4d9c451fdca1682e3a59 (diff) |
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.c | 23 | ||||
-rw-r--r-- | drivers/crypto/ace_sha.c | 73 | ||||
-rw-r--r-- | drivers/crypto/ace_sha.h | 8 | ||||
-rw-r--r-- | drivers/dfu/dfu.c | 42 | ||||
-rw-r--r-- | drivers/dfu/dfu_mmc.c | 31 | ||||
-rw-r--r-- | drivers/i2c/adi_i2c.c | 387 | ||||
-rw-r--r-- | drivers/mmc/arm_pl180_mmci.c | 50 | ||||
-rw-r--r-- | drivers/mmc/arm_pl180_mmci.h | 4 | ||||
-rw-r--r-- | drivers/mmc/bfin_sdh.c | 38 | ||||
-rw-r--r-- | drivers/mmc/davinci_mmc.c | 41 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 58 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc.c | 143 | ||||
-rw-r--r-- | drivers/mmc/ftsdc010_mci.c | 63 | ||||
-rw-r--r-- | drivers/mmc/gen_atmel_mci.c | 53 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 111 | ||||
-rw-r--r-- | drivers/mmc/mmc_spi.c | 50 | ||||
-rw-r--r-- | drivers/mmc/mmc_write.c | 3 | ||||
-rw-r--r-- | drivers/mmc/mxcmmc.c | 45 | ||||
-rw-r--r-- | drivers/mmc/mxsmmc.c | 48 | ||||
-rw-r--r-- | drivers/mmc/omap_hsmmc.c | 142 | ||||
-rw-r--r-- | drivers/mmc/pxa_mmc_gen.c | 70 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 84 | ||||
-rw-r--r-- | drivers/mmc/sh_mmcif.c | 55 | ||||
-rw-r--r-- | drivers/mmc/tegra_mmc.c | 53 | ||||
-rw-r--r-- | drivers/net/designware.h | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/f_dfu.c | 48 |
26 files changed, 787 insertions, 938 deletions
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index a409f637704..c8f65739e97 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 acbafde97cd..ed4f5418238 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, ®->hash_seed[i]); + + /* Wait for seed setup done */ + while (1) { + status = readl(®->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, ®->hash_control); + + /* Wait for PRNG done */ + while (1) { + status = readl(®->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, ®->hash_status); + + /* Read a PRNG result */ + for (i = 0; i < ACE_HASH_PRNG_REG_NUM; i++) + ret += readl(®->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 a426d523724..f1097f72dc2 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 56e69fd2315..8a09aafbf24 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 0816f46bad8..651cfff5b3b 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 675f4171ced..00000000000 --- 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 5a55fe73b7f..5ef7ff7ff2b 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 72344498d65..f23bd391eed 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 bd9b641135a..bcd6a3e52fd 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 b3809611888..aae00e9dab3 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(®s->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 d45c15cfa4e..eb4e2be5143 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 7b146a36044..4c3b93d413d 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(®s->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(®s->irqstat); - /* Reset CMD and DATA portions on error */ - if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) { - esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) | - SYSCTL_RSTC); - while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) - ; - - if (data) { - esdhc_write32(®s->sysctl, - esdhc_read32(®s->sysctl) | - SYSCTL_RSTD); - while ((esdhc_read32(®s->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(®s->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(®s->sysctl, esdhc_read32(®s->sysctl) | + SYSCTL_RSTC); + while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) + ; + + if (data) { + esdhc_write32(®s->sysctl, + esdhc_read32(®s->sysctl) | + SYSCTL_RSTD); + while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD)) + ; + } + } + esdhc_write32(®s->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(®s->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 7600d5ce555..a620678e5f9 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(®s->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 c11dcd0f97c..acca0269e58 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 8ab0bc948f5..16051e52ff1 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 fe6a5a166de..5b5b33a4b23 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 aa2fdefa75e..3db9669c82e 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 4f99617b9a9..561b2045986 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 245f9d0c672..2fa4eeef441 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 d3a8b5303d5..17cbb0983db 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 29f3eaf30b1..1f297571e56 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 1e86b92beec..3125d13ba3c 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 011d4f3e638..ed83a14c2de 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 3d1ce1263c8..ed67eec2527 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 afeaccec19a..382b0c7f0a6 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 a045864d730..de75ff13390 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 */ |