From 3bc87f243f64c953717bea058f4b458a57fc1a29 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 27 Aug 2006 13:51:28 +0100 Subject: [MMC] Convert mmci to use data->blksz rather than data->blksz_bits Signed-off-by: Russell King --- drivers/mmc/mmci.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 1886562abdd..8419489e774 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -69,12 +69,13 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) unsigned int datactrl, timeout, irqmask; unsigned long long clks; void __iomem *base; + int blksz_bits; 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->size = data->blocks << data->blksz_bits; + host->size = data->blksz; host->data_xfered = 0; 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(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) { datactrl |= MCI_DPSM_DIRECTION; irqmask = MCI_RXFIFOHALFFULLMASK; @@ -145,7 +149,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, unsigned int status) { 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) -- cgit v1.2.3 From 132919ba80ad207755fe271277bfefff865a54fe Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 27 Aug 2006 13:56:52 +0100 Subject: [MMC] Remove data->blksz_bits member data->blksz_bits is unused now - remove it. Signed-off-by: Russell King --- drivers/mmc/mmc.c | 1 - drivers/mmc/mmc_block.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 74eaaee66de..5b9caa7978d 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -996,7 +996,6 @@ static void mmc_read_scrs(struct mmc_host *host) mmc_set_data_timeout(&data, card, 0); - data.blksz_bits = 3; data.blksz = 1 << 3; data.blocks = 1; data.flags = MMC_DATA_READ; diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index a0e0dad1b41..f3a99dd8df8 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -172,7 +172,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.cmd.arg = req->sector << 9; 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.blocks = req->nr_sectors >> (md->block_bits - 9); brq.stop.opcode = MMC_STOP_TRANSMISSION; -- cgit v1.2.3 From db53f28b3a6d9338cca1b7e917dc063ac99e1871 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 30 Aug 2006 15:14:56 +0100 Subject: [MMC] Add multi block-write capability Add a capability flag for drivers to set when they can perform multi- block transfers to cards _and_ correctly report the number of bytes transferred should an error occur. The last point is very important - if a driver reports more bytes than were actually accepted by the card and an error occurs, there is the possibility for data loss. Pierre Ossman provided the patch for wbsd and sdhci. Signed-off-by: Pierre Ossman Signed-off-by: Russell King --- drivers/mmc/mmc_block.c | 27 ++++++++++++++++++++------- drivers/mmc/mmci.c | 1 + drivers/mmc/sdhci.c | 2 +- drivers/mmc/wbsd.c | 2 +- 4 files changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index f3a99dd8df8..8d18b87bfd3 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -165,6 +166,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) do { struct mmc_blk_request brq; struct mmc_command cmd; + u32 readcmd, writecmd; memset(&brq, 0, sizeof(struct mmc_blk_request)); brq.mrq.cmd = &brq.cmd; @@ -180,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); - if (rq_data_dir(req) == READ) { - brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; - brq.data.flags |= MMC_DATA_READ; - } else { - brq.cmd.opcode = MMC_WRITE_BLOCK; - brq.data.flags |= MMC_DATA_WRITE; + /* + * If the host doesn't support multiple block writes, force + * block writes to single block. + */ + if (rq_data_dir(req) != READ && + !(card->host->caps & MMC_CAP_MULTIWRITE)) brq.data.blocks = 1; - } if (brq.data.blocks > 1) { brq.data.flags |= MMC_DATA_MULTI; brq.mrq.stop = &brq.stop; + readcmd = MMC_READ_MULTIPLE_BLOCK; + writecmd = MMC_WRITE_MULTIPLE_BLOCK; } else { 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; diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 8419489e774..2b5a0cc9ea5 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -509,6 +509,7 @@ static int mmci_probe(struct amba_device *dev, void *id) mmc->f_min = (host->mclk + 511) / 512; mmc->f_max = min(host->mclk, fmax); mmc->ocr_avail = plat->ocr_mask; + mmc->caps = MMC_CAP_MULTIWRITE; /* * We can do SGIO diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 4e21b3b9d33..dea4edd1c43 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -1262,7 +1262,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) mmc->ops = &sdhci_ops; mmc->f_min = host->max_clk / 256; mmc->f_max = host->max_clk; - mmc->caps = MMC_CAP_4_BIT_DATA; + mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; mmc->ocr_avail = 0; if (caps & SDHCI_CAN_VDD_330) diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index c351c6d1a18..4a6617d9a49 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -1323,7 +1323,7 @@ static int __devinit wbsd_alloc_mmc(struct device *dev) mmc->f_min = 375000; mmc->f_max = 24000000; 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; spin_lock_init(&host->lock); -- cgit v1.2.3 From 42431acbac43eb47c774c29d370f5c59136805bf Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 24 Sep 2006 10:44:09 +0100 Subject: [MMC] MMC_CAP_BYTEBLOCK flag for non-log2 block sizes capable hosts Some MMC hosts can only handle log2 block sizes. Unfortunately, the MMC password support needs to be able to send non-log2 block sizes. Provide a capability so that the MMC password support can decide whether it should use this support or not. The unfortunate side effect of this host limitation is that any MMC card protected by a password which is not a log2 block size can not be accessed on a host which only allows a log2 block size. This change just adds the flag. The MMC password support code needs updating to use it (if and when it is finally submitted.) Signed-off-by: Russell King --- drivers/mmc/at91_mci.c | 1 + drivers/mmc/imxmmc.c | 2 +- drivers/mmc/omap.c | 7 ++++--- drivers/mmc/sdhci.c | 2 +- drivers/mmc/wbsd.c | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index 6b7638b8429..d34b7d9d92e 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c @@ -822,6 +822,7 @@ static int at91_mci_probe(struct platform_device *pdev) mmc->f_min = 375000; mmc->f_max = 25000000; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + mmc->caps = MMC_CAP_BYTEBLOCK; host = mmc_priv(mmc); host->mmc = mmc; diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index fb6565b98f3..1b79dd271aa 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c @@ -956,7 +956,7 @@ static int imxmci_probe(struct platform_device *pdev) mmc->f_min = 150000; mmc->f_max = CLK_RATE/2; 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->max_hw_segs = 64; diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index ddf06b32c15..52c9e52e6b7 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -1034,13 +1034,14 @@ static int __init mmc_omap_probe(struct platform_device *pdev) host->irq = pdev->resource[1].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->f_min = 400000; mmc->f_max = 24000000; 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. * NOTE max_seg_size assumption that small blocks aren't diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index dea4edd1c43..fdfc3838dd7 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -1262,7 +1262,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) mmc->ops = &sdhci_ops; mmc->f_min = host->max_clk / 256; mmc->f_max = host->max_clk; - mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; + mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK; mmc->ocr_avail = 0; if (caps & SDHCI_CAN_VDD_330) diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 4a6617d9a49..6435a6822ad 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -1323,7 +1323,7 @@ static int __devinit wbsd_alloc_mmc(struct device *dev) mmc->f_min = 375000; mmc->f_max = 24000000; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; + mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK; spin_lock_init(&host->lock); -- cgit v1.2.3 From 2ed6d22cec37d9a3df4c5bacf1160dee7700106e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 24 Sep 2006 10:46:43 +0100 Subject: [MMC] Don't check READY_FOR_DATA when reading There's no point checking to see if the card is ready to accept data when we're reading from it - sending the command only wastes precious bus bandwidth. Signed-off-by: Russell King --- drivers/mmc/mmc_block.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 8d18b87bfd3..db0e8ad439a 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -231,27 +231,29 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) goto cmd_err; } - do { - int err; - - cmd.opcode = MMC_SEND_STATUS; - cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - err = mmc_wait_for_cmd(card->host, &cmd, 5); - if (err) { - printk(KERN_ERR "%s: error %d requesting status\n", - req->rq_disk->disk_name, err); - goto cmd_err; - } - } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); + if (rq_data_dir(req) != READ) { + do { + int err; + + cmd.opcode = MMC_SEND_STATUS; + cmd.arg = card->rca << 16; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + err = mmc_wait_for_cmd(card->host, &cmd, 5); + if (err) { + printk(KERN_ERR "%s: error %d requesting status\n", + req->rq_disk->disk_name, err); + goto cmd_err; + } + } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); #if 0 - if (cmd.resp[0] & ~0x00000900) - printk(KERN_ERR "%s: status = %08x\n", - req->rq_disk->disk_name, cmd.resp[0]); - if (mmc_decode_status(cmd.resp)) - goto cmd_err; + if (cmd.resp[0] & ~0x00000900) + printk(KERN_ERR "%s: status = %08x\n", + req->rq_disk->disk_name, cmd.resp[0]); + if (mmc_decode_status(cmd.resp)) + goto cmd_err; #endif + } /* * A block was successfully transferred. -- cgit v1.2.3