aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@stericsson.com>2011-01-24 09:22:13 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-01-24 10:23:00 -0500
commit8cb2815574278a1bf966f041cbfe5b7c91472dcd (patch)
tree540d5b544f8ffc401737c1938258d04e1c3eff57
parent1bae4ce27c9c90344f23c65ea6966c50ffeae2f5 (diff)
ARM: 6632/3: mmci: stop using the blockend interrupts
Implement a suggestion from Russell to drop the use of blockend interrupts altogether and instead rely on the data counter. Tested with error-free cards on U300, U8500 and RealView PB1176. Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/mmc/host/mmci.c98
-rw-r--r--drivers/mmc/host/mmci.h5
2 files changed, 21 insertions, 82 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 563022825667..2de12fe155da 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -46,10 +46,6 @@ static unsigned int fmax = 515633;
46 * is asserted (likewise for RX) 46 * is asserted (likewise for RX)
47 * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY 47 * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
48 * is asserted (likewise for RX) 48 * is asserted (likewise for RX)
49 * @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware
50 * and will not work at all.
51 * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when
52 * using DMA.
53 * @sdio: variant supports SDIO 49 * @sdio: variant supports SDIO
54 * @st_clkdiv: true if using a ST-specific clock divider algorithm 50 * @st_clkdiv: true if using a ST-specific clock divider algorithm
55 */ 51 */
@@ -59,8 +55,6 @@ struct variant_data {
59 unsigned int datalength_bits; 55 unsigned int datalength_bits;
60 unsigned int fifosize; 56 unsigned int fifosize;
61 unsigned int fifohalfsize; 57 unsigned int fifohalfsize;
62 bool broken_blockend;
63 bool broken_blockend_dma;
64 bool sdio; 58 bool sdio;
65 bool st_clkdiv; 59 bool st_clkdiv;
66}; 60};
@@ -76,7 +70,6 @@ static struct variant_data variant_u300 = {
76 .fifohalfsize = 8 * 4, 70 .fifohalfsize = 8 * 4,
77 .clkreg_enable = 1 << 13, /* HWFCEN */ 71 .clkreg_enable = 1 << 13, /* HWFCEN */
78 .datalength_bits = 16, 72 .datalength_bits = 16,
79 .broken_blockend_dma = true,
80 .sdio = true, 73 .sdio = true,
81}; 74};
82 75
@@ -86,7 +79,6 @@ static struct variant_data variant_ux500 = {
86 .clkreg = MCI_CLK_ENABLE, 79 .clkreg = MCI_CLK_ENABLE,
87 .clkreg_enable = 1 << 14, /* HWFCEN */ 80 .clkreg_enable = 1 << 14, /* HWFCEN */
88 .datalength_bits = 24, 81 .datalength_bits = 24,
89 .broken_blockend = true,
90 .sdio = true, 82 .sdio = true,
91 .st_clkdiv = true, 83 .st_clkdiv = true,
92}; 84};
@@ -210,8 +202,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
210 host->data = data; 202 host->data = data;
211 host->size = data->blksz * data->blocks; 203 host->size = data->blksz * data->blocks;
212 host->data_xfered = 0; 204 host->data_xfered = 0;
213 host->blockend = false;
214 host->dataend = false;
215 205
216 mmci_init_sg(host, data); 206 mmci_init_sg(host, data);
217 207
@@ -288,21 +278,26 @@ static void
288mmci_data_irq(struct mmci_host *host, struct mmc_data *data, 278mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
289 unsigned int status) 279 unsigned int status)
290{ 280{
291 struct variant_data *variant = host->variant;
292
293 /* First check for errors */ 281 /* First check for errors */
294 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { 282 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
283 u32 remain, success;
284
285 /* Calculate how far we are into the transfer */
286 remain = readl(host->base + MMCIDATACNT) << 2;
287 success = data->blksz * data->blocks - remain;
288
295 dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); 289 dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);
296 if (status & MCI_DATACRCFAIL) 290 if (status & MCI_DATACRCFAIL) {
291 /* Last block was not successful */
292 host->data_xfered = ((success / data->blksz) - 1 * data->blksz);
297 data->error = -EILSEQ; 293 data->error = -EILSEQ;
298 else if (status & MCI_DATATIMEOUT) 294 } else if (status & MCI_DATATIMEOUT) {
295 host->data_xfered = success;
299 data->error = -ETIMEDOUT; 296 data->error = -ETIMEDOUT;
300 else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) 297 } else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
298 host->data_xfered = success;
301 data->error = -EIO; 299 data->error = -EIO;
302 300 }
303 /* Force-complete the transaction */
304 host->blockend = true;
305 host->dataend = true;
306 301
307 /* 302 /*
308 * We hit an error condition. Ensure that any data 303 * We hit an error condition. Ensure that any data
@@ -321,61 +316,14 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
321 } 316 }
322 } 317 }
323 318
324 /* 319 if (status & MCI_DATABLOCKEND)
325 * On ARM variants in PIO mode, MCI_DATABLOCKEND 320 dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n");
326 * is always sent first, and we increase the
327 * transfered number of bytes for that IRQ. Then
328 * MCI_DATAEND follows and we conclude the transaction.
329 *
330 * On the Ux500 single-IRQ variant MCI_DATABLOCKEND
331 * doesn't seem to immediately clear from the status,
332 * so we can't use it keep count when only one irq is
333 * used because the irq will hit for other reasons, and
334 * then the flag is still up. So we use the MCI_DATAEND
335 * IRQ at the end of the entire transfer because
336 * MCI_DATABLOCKEND is broken.
337 *
338 * In the U300, the IRQs can arrive out-of-order,
339 * e.g. MCI_DATABLOCKEND sometimes arrives after MCI_DATAEND,
340 * so for this case we use the flags "blockend" and
341 * "dataend" to make sure both IRQs have arrived before
342 * concluding the transaction. (This does not apply
343 * to the Ux500 which doesn't fire MCI_DATABLOCKEND
344 * at all.) In DMA mode it suffers from the same problem
345 * as the Ux500.
346 */
347 if (status & MCI_DATABLOCKEND) {
348 /*
349 * Just being a little over-cautious, we do not
350 * use this progressive update if the hardware blockend
351 * flag is unreliable: since it can stay high between
352 * IRQs it will corrupt the transfer counter.
353 */
354 if (!variant->broken_blockend)
355 host->data_xfered += data->blksz;
356 host->blockend = true;
357 }
358
359 if (status & MCI_DATAEND)
360 host->dataend = true;
361 321
362 /* 322 if (status & MCI_DATAEND) {
363 * On variants with broken blockend we shall only wait for dataend,
364 * on others we must sync with the blockend signal since they can
365 * appear out-of-order.
366 */
367 if (host->dataend && (host->blockend || variant->broken_blockend)) {
368 mmci_stop_data(host); 323 mmci_stop_data(host);
369 324
370 /* Reset these flags */ 325 if (!data->error)
371 host->blockend = false; 326 /* The error clause is handled above, success! */
372 host->dataend = false;
373
374 /*
375 * Variants with broken blockend flags need to handle the
376 * end of the entire transfer here.
377 */
378 if (variant->broken_blockend && !data->error)
379 host->data_xfered += data->blksz * data->blocks; 327 host->data_xfered += data->blksz * data->blocks;
380 328
381 if (!data->stop) { 329 if (!data->stop) {
@@ -770,7 +718,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
770 struct variant_data *variant = id->data; 718 struct variant_data *variant = id->data;
771 struct mmci_host *host; 719 struct mmci_host *host;
772 struct mmc_host *mmc; 720 struct mmc_host *mmc;
773 unsigned int mask;
774 int ret; 721 int ret;
775 722
776 /* must have platform data */ 723 /* must have platform data */
@@ -951,12 +898,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
951 goto irq0_free; 898 goto irq0_free;
952 } 899 }
953 900
954 mask = MCI_IRQENABLE; 901 writel(MCI_IRQENABLE, host->base + MMCIMASK0);
955 /* Don't use the datablockend flag if it's broken */
956 if (variant->broken_blockend)
957 mask &= ~MCI_DATABLOCKEND;
958
959 writel(mask, host->base + MMCIMASK0);
960 902
961 amba_set_drvdata(dev, mmc); 903 amba_set_drvdata(dev, mmc);
962 904
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index df06f01aac89..c1df7b82d36c 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -137,7 +137,7 @@
137#define MCI_IRQENABLE \ 137#define MCI_IRQENABLE \
138 (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ 138 (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \
139 MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ 139 MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
140 MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK) 140 MCI_CMDRESPENDMASK|MCI_CMDSENTMASK)
141 141
142/* These interrupts are directed to IRQ1 when two IRQ lines are available */ 142/* These interrupts are directed to IRQ1 when two IRQ lines are available */
143#define MCI_IRQ1MASK \ 143#define MCI_IRQ1MASK \
@@ -177,9 +177,6 @@ struct mmci_host {
177 struct timer_list timer; 177 struct timer_list timer;
178 unsigned int oldstat; 178 unsigned int oldstat;
179 179
180 bool blockend;
181 bool dataend;
182
183 /* pio stuff */ 180 /* pio stuff */
184 struct sg_mapping_iter sg_miter; 181 struct sg_mapping_iter sg_miter;
185 unsigned int size; 182 unsigned int size;