Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-mmc

* 'devel' of master.kernel.org:/home/rmk/linux-2.6-mmc:
  [MMC] Don't check READY_FOR_DATA when reading
  [MMC] MMC_CAP_BYTEBLOCK flag for non-log2 block sizes capable hosts
  [MMC] Add multi block-write capability
  [MMC] Remove data->blksz_bits member
  [MMC] Convert mmci to use data->blksz rather than data->blksz_bits
This commit is contained in:
Linus Torvalds 2006-09-28 14:23:55 -07:00
commit fecf3404f4
10 changed files with 58 additions and 37 deletions

View File

@ -822,6 +822,7 @@ static int at91_mci_probe(struct platform_device *pdev)
mmc->f_min = 375000; mmc->f_min = 375000;
mmc->f_max = 25000000; mmc->f_max = 25000000;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->caps = MMC_CAP_BYTEBLOCK;
host = mmc_priv(mmc); host = mmc_priv(mmc);
host->mmc = mmc; host->mmc = mmc;

View File

@ -956,7 +956,7 @@ static int imxmci_probe(struct platform_device *pdev)
mmc->f_min = 150000; mmc->f_min = 150000;
mmc->f_max = CLK_RATE/2; mmc->f_max = CLK_RATE/2;
mmc->ocr_avail = MMC_VDD_32_33; mmc->ocr_avail = MMC_VDD_32_33;
mmc->caps |= MMC_CAP_4_BIT_DATA; mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_BYTEBLOCK;
/* MMC core transfer sizes tunable parameters */ /* MMC core transfer sizes tunable parameters */
mmc->max_hw_segs = 64; mmc->max_hw_segs = 64;

View File

@ -996,7 +996,6 @@ static void mmc_read_scrs(struct mmc_host *host)
mmc_set_data_timeout(&data, card, 0); mmc_set_data_timeout(&data, card, 0);
data.blksz_bits = 3;
data.blksz = 1 << 3; data.blksz = 1 << 3;
data.blocks = 1; data.blocks = 1;
data.flags = MMC_DATA_READ; data.flags = MMC_DATA_READ;

View File

@ -32,6 +32,7 @@
#include <linux/mmc/card.h> #include <linux/mmc/card.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/protocol.h> #include <linux/mmc/protocol.h>
#include <linux/mmc/host.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
@ -165,6 +166,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
do { do {
struct mmc_blk_request brq; struct mmc_blk_request brq;
struct mmc_command cmd; struct mmc_command cmd;
u32 readcmd, writecmd;
memset(&brq, 0, sizeof(struct mmc_blk_request)); memset(&brq, 0, sizeof(struct mmc_blk_request));
brq.mrq.cmd = &brq.cmd; brq.mrq.cmd = &brq.cmd;
@ -172,7 +174,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.cmd.arg = req->sector << 9; brq.cmd.arg = req->sector << 9;
brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
brq.data.blksz_bits = md->block_bits;
brq.data.blksz = 1 << md->block_bits; brq.data.blksz = 1 << md->block_bits;
brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
brq.stop.opcode = MMC_STOP_TRANSMISSION; brq.stop.opcode = MMC_STOP_TRANSMISSION;
@ -181,20 +182,31 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ); mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
if (rq_data_dir(req) == READ) { /*
brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; * If the host doesn't support multiple block writes, force
brq.data.flags |= MMC_DATA_READ; * block writes to single block.
} else { */
brq.cmd.opcode = MMC_WRITE_BLOCK; if (rq_data_dir(req) != READ &&
brq.data.flags |= MMC_DATA_WRITE; !(card->host->caps & MMC_CAP_MULTIWRITE))
brq.data.blocks = 1; brq.data.blocks = 1;
}
if (brq.data.blocks > 1) { if (brq.data.blocks > 1) {
brq.data.flags |= MMC_DATA_MULTI; brq.data.flags |= MMC_DATA_MULTI;
brq.mrq.stop = &brq.stop; brq.mrq.stop = &brq.stop;
readcmd = MMC_READ_MULTIPLE_BLOCK;
writecmd = MMC_WRITE_MULTIPLE_BLOCK;
} else { } else {
brq.mrq.stop = NULL; brq.mrq.stop = NULL;
readcmd = MMC_READ_SINGLE_BLOCK;
writecmd = MMC_WRITE_BLOCK;
}
if (rq_data_dir(req) == READ) {
brq.cmd.opcode = readcmd;
brq.data.flags |= MMC_DATA_READ;
} else {
brq.cmd.opcode = writecmd;
brq.data.flags |= MMC_DATA_WRITE;
} }
brq.data.sg = mq->sg; brq.data.sg = mq->sg;
@ -219,27 +231,29 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
goto cmd_err; goto cmd_err;
} }
do { if (rq_data_dir(req) != READ) {
int err; do {
int err;
cmd.opcode = MMC_SEND_STATUS; cmd.opcode = MMC_SEND_STATUS;
cmd.arg = card->rca << 16; cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(card->host, &cmd, 5); err = mmc_wait_for_cmd(card->host, &cmd, 5);
if (err) { if (err) {
printk(KERN_ERR "%s: error %d requesting status\n", printk(KERN_ERR "%s: error %d requesting status\n",
req->rq_disk->disk_name, err); req->rq_disk->disk_name, err);
goto cmd_err; goto cmd_err;
} }
} while (!(cmd.resp[0] & R1_READY_FOR_DATA)); } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
#if 0 #if 0
if (cmd.resp[0] & ~0x00000900) if (cmd.resp[0] & ~0x00000900)
printk(KERN_ERR "%s: status = %08x\n", printk(KERN_ERR "%s: status = %08x\n",
req->rq_disk->disk_name, cmd.resp[0]); req->rq_disk->disk_name, cmd.resp[0]);
if (mmc_decode_status(cmd.resp)) if (mmc_decode_status(cmd.resp))
goto cmd_err; goto cmd_err;
#endif #endif
}
/* /*
* A block was successfully transferred. * A block was successfully transferred.

View File

@ -69,12 +69,13 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
unsigned int datactrl, timeout, irqmask; unsigned int datactrl, timeout, irqmask;
unsigned long long clks; unsigned long long clks;
void __iomem *base; void __iomem *base;
int blksz_bits;
DBG(host, "blksz %04x blks %04x flags %08x\n", DBG(host, "blksz %04x blks %04x flags %08x\n",
1 << data->blksz_bits, data->blocks, data->flags); data->blksz, data->blocks, data->flags);
host->data = data; host->data = data;
host->size = data->blocks << data->blksz_bits; host->size = data->blksz;
host->data_xfered = 0; host->data_xfered = 0;
mmci_init_sg(host, data); mmci_init_sg(host, data);
@ -88,7 +89,10 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
writel(timeout, base + MMCIDATATIMER); writel(timeout, base + MMCIDATATIMER);
writel(host->size, base + MMCIDATALENGTH); writel(host->size, base + MMCIDATALENGTH);
datactrl = MCI_DPSM_ENABLE | data->blksz_bits << 4; blksz_bits = ffs(data->blksz) - 1;
BUG_ON(1 << blksz_bits != data->blksz);
datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
if (data->flags & MMC_DATA_READ) { if (data->flags & MMC_DATA_READ) {
datactrl |= MCI_DPSM_DIRECTION; datactrl |= MCI_DPSM_DIRECTION;
irqmask = MCI_RXFIFOHALFFULLMASK; irqmask = MCI_RXFIFOHALFFULLMASK;
@ -145,7 +149,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
unsigned int status) unsigned int status)
{ {
if (status & MCI_DATABLOCKEND) { if (status & MCI_DATABLOCKEND) {
host->data_xfered += 1 << data->blksz_bits; host->data_xfered += data->blksz;
} }
if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
if (status & MCI_DATACRCFAIL) if (status & MCI_DATACRCFAIL)
@ -505,6 +509,7 @@ static int mmci_probe(struct amba_device *dev, void *id)
mmc->f_min = (host->mclk + 511) / 512; mmc->f_min = (host->mclk + 511) / 512;
mmc->f_max = min(host->mclk, fmax); mmc->f_max = min(host->mclk, fmax);
mmc->ocr_avail = plat->ocr_mask; mmc->ocr_avail = plat->ocr_mask;
mmc->caps = MMC_CAP_MULTIWRITE;
/* /*
* We can do SGIO * We can do SGIO

View File

@ -1034,13 +1034,14 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
host->irq = pdev->resource[1].start; host->irq = pdev->resource[1].start;
host->base = (void __iomem*)IO_ADDRESS(r->start); host->base = (void __iomem*)IO_ADDRESS(r->start);
if (minfo->wire4)
mmc->caps |= MMC_CAP_4_BIT_DATA;
mmc->ops = &mmc_omap_ops; mmc->ops = &mmc_omap_ops;
mmc->f_min = 400000; mmc->f_min = 400000;
mmc->f_max = 24000000; mmc->f_max = 24000000;
mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
mmc->caps = MMC_CAP_BYTEBLOCK;
if (minfo->wire4)
mmc->caps |= MMC_CAP_4_BIT_DATA;
/* Use scatterlist DMA to reduce per-transfer costs. /* Use scatterlist DMA to reduce per-transfer costs.
* NOTE max_seg_size assumption that small blocks aren't * NOTE max_seg_size assumption that small blocks aren't

View File

@ -1262,7 +1262,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
mmc->ops = &sdhci_ops; mmc->ops = &sdhci_ops;
mmc->f_min = host->max_clk / 256; mmc->f_min = host->max_clk / 256;
mmc->f_max = host->max_clk; mmc->f_max = host->max_clk;
mmc->caps = MMC_CAP_4_BIT_DATA; mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
mmc->ocr_avail = 0; mmc->ocr_avail = 0;
if (caps & SDHCI_CAN_VDD_330) if (caps & SDHCI_CAN_VDD_330)

View File

@ -1323,7 +1323,7 @@ static int __devinit wbsd_alloc_mmc(struct device *dev)
mmc->f_min = 375000; mmc->f_min = 375000;
mmc->f_max = 24000000; mmc->f_max = 24000000;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->caps = MMC_CAP_4_BIT_DATA; mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
spin_lock_init(&host->lock); spin_lock_init(&host->lock);

View File

@ -85,6 +85,8 @@ struct mmc_host {
unsigned long caps; /* Host capabilities */ unsigned long caps; /* Host capabilities */
#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */ #define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */
#define MMC_CAP_MULTIWRITE (1 << 1) /* Can accurately report bytes sent to card on error */
#define MMC_CAP_BYTEBLOCK (1 << 2) /* Can do non-log2 block sizes */
/* host specific block data */ /* host specific block data */
unsigned int max_seg_size; /* see blk_queue_max_segment_size */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */

View File

@ -68,7 +68,6 @@ struct mmc_command {
struct mmc_data { struct mmc_data {
unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */ unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */
unsigned int timeout_clks; /* data timeout (in clocks) */ unsigned int timeout_clks; /* data timeout (in clocks) */
unsigned int blksz_bits; /* data block size */
unsigned int blksz; /* data block size */ unsigned int blksz; /* data block size */
unsigned int blocks; /* number of blocks */ unsigned int blocks; /* number of blocks */
unsigned int error; /* data error */ unsigned int error; /* data error */