diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-01-06 20:29:26 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-01-06 20:29:26 -0500 |
commit | 5e93c6b4ecd78b1bab49bad1dc2f6ed7ec0115ee (patch) | |
tree | 4f4e321a1ca0baf64d8af528080c71f93495a7d7 /drivers/mmc/host | |
parent | 98d27b8abf413a310df6676f7d2128ada1cccc08 (diff) | |
parent | 3c0cb7c31c206aaedb967e44b98442bbeb17a6c4 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6 into rmobile-latest
Conflicts:
arch/arm/mach-shmobile/Kconfig
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r-- | drivers/mmc/host/at91_mci.c | 13 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 18 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.c | 207 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.h | 9 | ||||
-rw-r--r-- | drivers/mmc/host/msm_sdcc.c | 139 | ||||
-rw-r--r-- | drivers/mmc/host/msm_sdcc.h | 8 |
6 files changed, 320 insertions, 74 deletions
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 591ab540b407..d3e6a962f423 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
@@ -69,6 +69,7 @@ | |||
69 | #include <linux/highmem.h> | 69 | #include <linux/highmem.h> |
70 | 70 | ||
71 | #include <linux/mmc/host.h> | 71 | #include <linux/mmc/host.h> |
72 | #include <linux/mmc/sdio.h> | ||
72 | 73 | ||
73 | #include <asm/io.h> | 74 | #include <asm/io.h> |
74 | #include <asm/irq.h> | 75 | #include <asm/irq.h> |
@@ -493,10 +494,14 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command | |||
493 | else if (data->flags & MMC_DATA_WRITE) | 494 | else if (data->flags & MMC_DATA_WRITE) |
494 | cmdr |= AT91_MCI_TRCMD_START; | 495 | cmdr |= AT91_MCI_TRCMD_START; |
495 | 496 | ||
496 | if (data->flags & MMC_DATA_STREAM) | 497 | if (cmd->opcode == SD_IO_RW_EXTENDED) { |
497 | cmdr |= AT91_MCI_TRTYP_STREAM; | 498 | cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK; |
498 | if (data->blocks > 1) | 499 | } else { |
499 | cmdr |= AT91_MCI_TRTYP_MULTIPLE; | 500 | if (data->flags & MMC_DATA_STREAM) |
501 | cmdr |= AT91_MCI_TRTYP_STREAM; | ||
502 | if (data->blocks > 1) | ||
503 | cmdr |= AT91_MCI_TRTYP_MULTIPLE; | ||
504 | } | ||
500 | } | 505 | } |
501 | else { | 506 | else { |
502 | block_length = 0; | 507 | block_length = 0; |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 301351a5d838..ad2a7a032cdf 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/stat.h> | 26 | #include <linux/stat.h> |
27 | 27 | ||
28 | #include <linux/mmc/host.h> | 28 | #include <linux/mmc/host.h> |
29 | #include <linux/mmc/sdio.h> | ||
29 | 30 | ||
30 | #include <mach/atmel-mci.h> | 31 | #include <mach/atmel-mci.h> |
31 | #include <linux/atmel-mci.h> | 32 | #include <linux/atmel-mci.h> |
@@ -532,12 +533,17 @@ static u32 atmci_prepare_command(struct mmc_host *mmc, | |||
532 | data = cmd->data; | 533 | data = cmd->data; |
533 | if (data) { | 534 | if (data) { |
534 | cmdr |= MCI_CMDR_START_XFER; | 535 | cmdr |= MCI_CMDR_START_XFER; |
535 | if (data->flags & MMC_DATA_STREAM) | 536 | |
536 | cmdr |= MCI_CMDR_STREAM; | 537 | if (cmd->opcode == SD_IO_RW_EXTENDED) { |
537 | else if (data->blocks > 1) | 538 | cmdr |= MCI_CMDR_SDIO_BLOCK; |
538 | cmdr |= MCI_CMDR_MULTI_BLOCK; | 539 | } else { |
539 | else | 540 | if (data->flags & MMC_DATA_STREAM) |
540 | cmdr |= MCI_CMDR_BLOCK; | 541 | cmdr |= MCI_CMDR_STREAM; |
542 | else if (data->blocks > 1) | ||
543 | cmdr |= MCI_CMDR_MULTI_BLOCK; | ||
544 | else | ||
545 | cmdr |= MCI_CMDR_BLOCK; | ||
546 | } | ||
541 | 547 | ||
542 | if (data->flags & MMC_DATA_READ) | 548 | if (data->flags & MMC_DATA_READ) |
543 | cmdr |= MCI_CMDR_TRDIR_READ; | 549 | cmdr |= MCI_CMDR_TRDIR_READ; |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 87b4fc6c98c2..563022825667 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/highmem.h> | 19 | #include <linux/highmem.h> |
20 | #include <linux/log2.h> | 20 | #include <linux/log2.h> |
21 | #include <linux/mmc/host.h> | 21 | #include <linux/mmc/host.h> |
22 | #include <linux/mmc/card.h> | ||
22 | #include <linux/amba/bus.h> | 23 | #include <linux/amba/bus.h> |
23 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
24 | #include <linux/scatterlist.h> | 25 | #include <linux/scatterlist.h> |
@@ -45,6 +46,12 @@ static unsigned int fmax = 515633; | |||
45 | * is asserted (likewise for RX) | 46 | * is asserted (likewise for RX) |
46 | * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY | 47 | * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY |
47 | * 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 | ||
54 | * @st_clkdiv: true if using a ST-specific clock divider algorithm | ||
48 | */ | 55 | */ |
49 | struct variant_data { | 56 | struct variant_data { |
50 | unsigned int clkreg; | 57 | unsigned int clkreg; |
@@ -52,6 +59,10 @@ struct variant_data { | |||
52 | unsigned int datalength_bits; | 59 | unsigned int datalength_bits; |
53 | unsigned int fifosize; | 60 | unsigned int fifosize; |
54 | unsigned int fifohalfsize; | 61 | unsigned int fifohalfsize; |
62 | bool broken_blockend; | ||
63 | bool broken_blockend_dma; | ||
64 | bool sdio; | ||
65 | bool st_clkdiv; | ||
55 | }; | 66 | }; |
56 | 67 | ||
57 | static struct variant_data variant_arm = { | 68 | static struct variant_data variant_arm = { |
@@ -65,6 +76,8 @@ static struct variant_data variant_u300 = { | |||
65 | .fifohalfsize = 8 * 4, | 76 | .fifohalfsize = 8 * 4, |
66 | .clkreg_enable = 1 << 13, /* HWFCEN */ | 77 | .clkreg_enable = 1 << 13, /* HWFCEN */ |
67 | .datalength_bits = 16, | 78 | .datalength_bits = 16, |
79 | .broken_blockend_dma = true, | ||
80 | .sdio = true, | ||
68 | }; | 81 | }; |
69 | 82 | ||
70 | static struct variant_data variant_ux500 = { | 83 | static struct variant_data variant_ux500 = { |
@@ -73,7 +86,11 @@ static struct variant_data variant_ux500 = { | |||
73 | .clkreg = MCI_CLK_ENABLE, | 86 | .clkreg = MCI_CLK_ENABLE, |
74 | .clkreg_enable = 1 << 14, /* HWFCEN */ | 87 | .clkreg_enable = 1 << 14, /* HWFCEN */ |
75 | .datalength_bits = 24, | 88 | .datalength_bits = 24, |
89 | .broken_blockend = true, | ||
90 | .sdio = true, | ||
91 | .st_clkdiv = true, | ||
76 | }; | 92 | }; |
93 | |||
77 | /* | 94 | /* |
78 | * This must be called with host->lock held | 95 | * This must be called with host->lock held |
79 | */ | 96 | */ |
@@ -86,7 +103,22 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) | |||
86 | if (desired >= host->mclk) { | 103 | if (desired >= host->mclk) { |
87 | clk = MCI_CLK_BYPASS; | 104 | clk = MCI_CLK_BYPASS; |
88 | host->cclk = host->mclk; | 105 | host->cclk = host->mclk; |
106 | } else if (variant->st_clkdiv) { | ||
107 | /* | ||
108 | * DB8500 TRM says f = mclk / (clkdiv + 2) | ||
109 | * => clkdiv = (mclk / f) - 2 | ||
110 | * Round the divider up so we don't exceed the max | ||
111 | * frequency | ||
112 | */ | ||
113 | clk = DIV_ROUND_UP(host->mclk, desired) - 2; | ||
114 | if (clk >= 256) | ||
115 | clk = 255; | ||
116 | host->cclk = host->mclk / (clk + 2); | ||
89 | } else { | 117 | } else { |
118 | /* | ||
119 | * PL180 TRM says f = mclk / (2 * (clkdiv + 1)) | ||
120 | * => clkdiv = mclk / (2 * f) - 1 | ||
121 | */ | ||
90 | clk = host->mclk / (2 * desired) - 1; | 122 | clk = host->mclk / (2 * desired) - 1; |
91 | if (clk >= 256) | 123 | if (clk >= 256) |
92 | clk = 255; | 124 | clk = 255; |
@@ -129,10 +161,26 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) | |||
129 | spin_lock(&host->lock); | 161 | spin_lock(&host->lock); |
130 | } | 162 | } |
131 | 163 | ||
164 | static void mmci_set_mask1(struct mmci_host *host, unsigned int mask) | ||
165 | { | ||
166 | void __iomem *base = host->base; | ||
167 | |||
168 | if (host->singleirq) { | ||
169 | unsigned int mask0 = readl(base + MMCIMASK0); | ||
170 | |||
171 | mask0 &= ~MCI_IRQ1MASK; | ||
172 | mask0 |= mask; | ||
173 | |||
174 | writel(mask0, base + MMCIMASK0); | ||
175 | } | ||
176 | |||
177 | writel(mask, base + MMCIMASK1); | ||
178 | } | ||
179 | |||
132 | static void mmci_stop_data(struct mmci_host *host) | 180 | static void mmci_stop_data(struct mmci_host *host) |
133 | { | 181 | { |
134 | writel(0, host->base + MMCIDATACTRL); | 182 | writel(0, host->base + MMCIDATACTRL); |
135 | writel(0, host->base + MMCIMASK1); | 183 | mmci_set_mask1(host, 0); |
136 | host->data = NULL; | 184 | host->data = NULL; |
137 | } | 185 | } |
138 | 186 | ||
@@ -162,6 +210,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
162 | host->data = data; | 210 | host->data = data; |
163 | host->size = data->blksz * data->blocks; | 211 | host->size = data->blksz * data->blocks; |
164 | host->data_xfered = 0; | 212 | host->data_xfered = 0; |
213 | host->blockend = false; | ||
214 | host->dataend = false; | ||
165 | 215 | ||
166 | mmci_init_sg(host, data); | 216 | mmci_init_sg(host, data); |
167 | 217 | ||
@@ -196,9 +246,14 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
196 | irqmask = MCI_TXFIFOHALFEMPTYMASK; | 246 | irqmask = MCI_TXFIFOHALFEMPTYMASK; |
197 | } | 247 | } |
198 | 248 | ||
249 | /* The ST Micro variants has a special bit to enable SDIO */ | ||
250 | if (variant->sdio && host->mmc->card) | ||
251 | if (mmc_card_sdio(host->mmc->card)) | ||
252 | datactrl |= MCI_ST_DPSM_SDIOEN; | ||
253 | |||
199 | writel(datactrl, base + MMCIDATACTRL); | 254 | writel(datactrl, base + MMCIDATACTRL); |
200 | writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); | 255 | writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); |
201 | writel(irqmask, base + MMCIMASK1); | 256 | mmci_set_mask1(host, irqmask); |
202 | } | 257 | } |
203 | 258 | ||
204 | static void | 259 | static void |
@@ -233,20 +288,9 @@ static void | |||
233 | mmci_data_irq(struct mmci_host *host, struct mmc_data *data, | 288 | mmci_data_irq(struct mmci_host *host, struct mmc_data *data, |
234 | unsigned int status) | 289 | unsigned int status) |
235 | { | 290 | { |
236 | if (status & MCI_DATABLOCKEND) { | 291 | struct variant_data *variant = host->variant; |
237 | host->data_xfered += data->blksz; | 292 | |
238 | #ifdef CONFIG_ARCH_U300 | 293 | /* First check for errors */ |
239 | /* | ||
240 | * On the U300 some signal or other is | ||
241 | * badly routed so that a data write does | ||
242 | * not properly terminate with a MCI_DATAEND | ||
243 | * status flag. This quirk will make writes | ||
244 | * work again. | ||
245 | */ | ||
246 | if (data->flags & MMC_DATA_WRITE) | ||
247 | status |= MCI_DATAEND; | ||
248 | #endif | ||
249 | } | ||
250 | if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { | 294 | if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { |
251 | dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); | 295 | dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); |
252 | if (status & MCI_DATACRCFAIL) | 296 | if (status & MCI_DATACRCFAIL) |
@@ -255,7 +299,10 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, | |||
255 | data->error = -ETIMEDOUT; | 299 | data->error = -ETIMEDOUT; |
256 | else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) | 300 | else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) |
257 | data->error = -EIO; | 301 | data->error = -EIO; |
258 | status |= MCI_DATAEND; | 302 | |
303 | /* Force-complete the transaction */ | ||
304 | host->blockend = true; | ||
305 | host->dataend = true; | ||
259 | 306 | ||
260 | /* | 307 | /* |
261 | * We hit an error condition. Ensure that any data | 308 | * We hit an error condition. Ensure that any data |
@@ -273,9 +320,64 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, | |||
273 | local_irq_restore(flags); | 320 | local_irq_restore(flags); |
274 | } | 321 | } |
275 | } | 322 | } |
276 | if (status & MCI_DATAEND) { | 323 | |
324 | /* | ||
325 | * On ARM variants in PIO mode, MCI_DATABLOCKEND | ||
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 | |||
362 | /* | ||
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)) { | ||
277 | mmci_stop_data(host); | 368 | mmci_stop_data(host); |
278 | 369 | ||
370 | /* Reset these flags */ | ||
371 | host->blockend = false; | ||
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; | ||
380 | |||
279 | if (!data->stop) { | 381 | if (!data->stop) { |
280 | mmci_request_end(host, data->mrq); | 382 | mmci_request_end(host, data->mrq); |
281 | } else { | 383 | } else { |
@@ -356,7 +458,32 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem | |||
356 | variant->fifosize : variant->fifohalfsize; | 458 | variant->fifosize : variant->fifohalfsize; |
357 | count = min(remain, maxcnt); | 459 | count = min(remain, maxcnt); |
358 | 460 | ||
359 | writesl(base + MMCIFIFO, ptr, count >> 2); | 461 | /* |
462 | * The ST Micro variant for SDIO transfer sizes | ||
463 | * less then 8 bytes should have clock H/W flow | ||
464 | * control disabled. | ||
465 | */ | ||
466 | if (variant->sdio && | ||
467 | mmc_card_sdio(host->mmc->card)) { | ||
468 | if (count < 8) | ||
469 | writel(readl(host->base + MMCICLOCK) & | ||
470 | ~variant->clkreg_enable, | ||
471 | host->base + MMCICLOCK); | ||
472 | else | ||
473 | writel(readl(host->base + MMCICLOCK) | | ||
474 | variant->clkreg_enable, | ||
475 | host->base + MMCICLOCK); | ||
476 | } | ||
477 | |||
478 | /* | ||
479 | * SDIO especially may want to send something that is | ||
480 | * not divisible by 4 (as opposed to card sectors | ||
481 | * etc), and the FIFO only accept full 32-bit writes. | ||
482 | * So compensate by adding +3 on the count, a single | ||
483 | * byte become a 32bit write, 7 bytes will be two | ||
484 | * 32bit writes etc. | ||
485 | */ | ||
486 | writesl(base + MMCIFIFO, ptr, (count + 3) >> 2); | ||
360 | 487 | ||
361 | ptr += count; | 488 | ptr += count; |
362 | remain -= count; | 489 | remain -= count; |
@@ -437,7 +564,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) | |||
437 | * "any data available" mode. | 564 | * "any data available" mode. |
438 | */ | 565 | */ |
439 | if (status & MCI_RXACTIVE && host->size < variant->fifosize) | 566 | if (status & MCI_RXACTIVE && host->size < variant->fifosize) |
440 | writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); | 567 | mmci_set_mask1(host, MCI_RXDATAAVLBLMASK); |
441 | 568 | ||
442 | /* | 569 | /* |
443 | * If we run out of data, disable the data IRQs; this | 570 | * If we run out of data, disable the data IRQs; this |
@@ -446,7 +573,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) | |||
446 | * stops us racing with our data end IRQ. | 573 | * stops us racing with our data end IRQ. |
447 | */ | 574 | */ |
448 | if (host->size == 0) { | 575 | if (host->size == 0) { |
449 | writel(0, base + MMCIMASK1); | 576 | mmci_set_mask1(host, 0); |
450 | writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0); | 577 | writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0); |
451 | } | 578 | } |
452 | 579 | ||
@@ -469,6 +596,14 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) | |||
469 | struct mmc_data *data; | 596 | struct mmc_data *data; |
470 | 597 | ||
471 | status = readl(host->base + MMCISTATUS); | 598 | status = readl(host->base + MMCISTATUS); |
599 | |||
600 | if (host->singleirq) { | ||
601 | if (status & readl(host->base + MMCIMASK1)) | ||
602 | mmci_pio_irq(irq, dev_id); | ||
603 | |||
604 | status &= ~MCI_IRQ1MASK; | ||
605 | } | ||
606 | |||
472 | status &= readl(host->base + MMCIMASK0); | 607 | status &= readl(host->base + MMCIMASK0); |
473 | writel(status, host->base + MMCICLEAR); | 608 | writel(status, host->base + MMCICLEAR); |
474 | 609 | ||
@@ -635,6 +770,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
635 | struct variant_data *variant = id->data; | 770 | struct variant_data *variant = id->data; |
636 | struct mmci_host *host; | 771 | struct mmci_host *host; |
637 | struct mmc_host *mmc; | 772 | struct mmc_host *mmc; |
773 | unsigned int mask; | ||
638 | int ret; | 774 | int ret; |
639 | 775 | ||
640 | /* must have platform data */ | 776 | /* must have platform data */ |
@@ -806,20 +942,30 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
806 | if (ret) | 942 | if (ret) |
807 | goto unmap; | 943 | goto unmap; |
808 | 944 | ||
809 | ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, DRIVER_NAME " (pio)", host); | 945 | if (dev->irq[1] == NO_IRQ) |
810 | if (ret) | 946 | host->singleirq = true; |
811 | goto irq0_free; | 947 | else { |
948 | ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, | ||
949 | DRIVER_NAME " (pio)", host); | ||
950 | if (ret) | ||
951 | goto irq0_free; | ||
952 | } | ||
812 | 953 | ||
813 | writel(MCI_IRQENABLE, host->base + MMCIMASK0); | 954 | mask = MCI_IRQENABLE; |
955 | /* Don't use the datablockend flag if it's broken */ | ||
956 | if (variant->broken_blockend) | ||
957 | mask &= ~MCI_DATABLOCKEND; | ||
814 | 958 | ||
815 | amba_set_drvdata(dev, mmc); | 959 | writel(mask, host->base + MMCIMASK0); |
816 | 960 | ||
817 | mmc_add_host(mmc); | 961 | amba_set_drvdata(dev, mmc); |
818 | 962 | ||
819 | dev_info(&dev->dev, "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n", | 963 | dev_info(&dev->dev, "%s: PL%03x rev%u at 0x%08llx irq %d,%d\n", |
820 | mmc_hostname(mmc), amba_rev(dev), amba_config(dev), | 964 | mmc_hostname(mmc), amba_part(dev), amba_rev(dev), |
821 | (unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]); | 965 | (unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]); |
822 | 966 | ||
967 | mmc_add_host(mmc); | ||
968 | |||
823 | return 0; | 969 | return 0; |
824 | 970 | ||
825 | irq0_free: | 971 | irq0_free: |
@@ -864,7 +1010,8 @@ static int __devexit mmci_remove(struct amba_device *dev) | |||
864 | writel(0, host->base + MMCIDATACTRL); | 1010 | writel(0, host->base + MMCIDATACTRL); |
865 | 1011 | ||
866 | free_irq(dev->irq[0], host); | 1012 | free_irq(dev->irq[0], host); |
867 | free_irq(dev->irq[1], host); | 1013 | if (!host->singleirq) |
1014 | free_irq(dev->irq[1], host); | ||
868 | 1015 | ||
869 | if (host->gpio_wp != -ENOSYS) | 1016 | if (host->gpio_wp != -ENOSYS) |
870 | gpio_free(host->gpio_wp); | 1017 | gpio_free(host->gpio_wp); |
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 4ae887fc0189..df06f01aac89 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h | |||
@@ -139,6 +139,11 @@ | |||
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|MCI_DATABLOCKENDMASK) |
141 | 141 | ||
142 | /* These interrupts are directed to IRQ1 when two IRQ lines are available */ | ||
143 | #define MCI_IRQ1MASK \ | ||
144 | (MCI_RXFIFOHALFFULLMASK | MCI_RXDATAAVLBLMASK | \ | ||
145 | MCI_TXFIFOHALFEMPTYMASK) | ||
146 | |||
142 | #define NR_SG 16 | 147 | #define NR_SG 16 |
143 | 148 | ||
144 | struct clk; | 149 | struct clk; |
@@ -154,6 +159,7 @@ struct mmci_host { | |||
154 | int gpio_cd; | 159 | int gpio_cd; |
155 | int gpio_wp; | 160 | int gpio_wp; |
156 | int gpio_cd_irq; | 161 | int gpio_cd_irq; |
162 | bool singleirq; | ||
157 | 163 | ||
158 | unsigned int data_xfered; | 164 | unsigned int data_xfered; |
159 | 165 | ||
@@ -171,6 +177,9 @@ struct mmci_host { | |||
171 | struct timer_list timer; | 177 | struct timer_list timer; |
172 | unsigned int oldstat; | 178 | unsigned int oldstat; |
173 | 179 | ||
180 | bool blockend; | ||
181 | bool dataend; | ||
182 | |||
174 | /* pio stuff */ | 183 | /* pio stuff */ |
175 | struct sg_mapping_iter sg_miter; | 184 | struct sg_mapping_iter sg_miter; |
176 | unsigned int size; | 185 | unsigned int size; |
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 1290d14c5839..5decfd0bd61d 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <mach/mmc.h> | 44 | #include <mach/mmc.h> |
45 | #include <mach/msm_iomap.h> | 45 | #include <mach/msm_iomap.h> |
46 | #include <mach/dma.h> | 46 | #include <mach/dma.h> |
47 | #include <mach/clk.h> | ||
47 | 48 | ||
48 | #include "msm_sdcc.h" | 49 | #include "msm_sdcc.h" |
49 | 50 | ||
@@ -126,6 +127,40 @@ static void | |||
126 | msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, | 127 | msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, |
127 | u32 c); | 128 | u32 c); |
128 | 129 | ||
130 | static void msmsdcc_reset_and_restore(struct msmsdcc_host *host) | ||
131 | { | ||
132 | u32 mci_clk = 0; | ||
133 | u32 mci_mask0 = 0; | ||
134 | int ret = 0; | ||
135 | |||
136 | /* Save the controller state */ | ||
137 | mci_clk = readl(host->base + MMCICLOCK); | ||
138 | mci_mask0 = readl(host->base + MMCIMASK0); | ||
139 | |||
140 | /* Reset the controller */ | ||
141 | ret = clk_reset(host->clk, CLK_RESET_ASSERT); | ||
142 | if (ret) | ||
143 | pr_err("%s: Clock assert failed at %u Hz with err %d\n", | ||
144 | mmc_hostname(host->mmc), host->clk_rate, ret); | ||
145 | |||
146 | ret = clk_reset(host->clk, CLK_RESET_DEASSERT); | ||
147 | if (ret) | ||
148 | pr_err("%s: Clock deassert failed at %u Hz with err %d\n", | ||
149 | mmc_hostname(host->mmc), host->clk_rate, ret); | ||
150 | |||
151 | pr_info("%s: Controller has been re-initialiazed\n", | ||
152 | mmc_hostname(host->mmc)); | ||
153 | |||
154 | /* Restore the contoller state */ | ||
155 | writel(host->pwr, host->base + MMCIPOWER); | ||
156 | writel(mci_clk, host->base + MMCICLOCK); | ||
157 | writel(mci_mask0, host->base + MMCIMASK0); | ||
158 | ret = clk_set_rate(host->clk, host->clk_rate); | ||
159 | if (ret) | ||
160 | pr_err("%s: Failed to set clk rate %u Hz (%d)\n", | ||
161 | mmc_hostname(host->mmc), host->clk_rate, ret); | ||
162 | } | ||
163 | |||
129 | static void | 164 | static void |
130 | msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq) | 165 | msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq) |
131 | { | 166 | { |
@@ -155,7 +190,7 @@ static void | |||
155 | msmsdcc_stop_data(struct msmsdcc_host *host) | 190 | msmsdcc_stop_data(struct msmsdcc_host *host) |
156 | { | 191 | { |
157 | host->curr.data = NULL; | 192 | host->curr.data = NULL; |
158 | host->curr.got_dataend = host->curr.got_datablkend = 0; | 193 | host->curr.got_dataend = 0; |
159 | } | 194 | } |
160 | 195 | ||
161 | uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host) | 196 | uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host) |
@@ -189,42 +224,42 @@ msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd) | |||
189 | } | 224 | } |
190 | 225 | ||
191 | static void | 226 | static void |
192 | msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd, | 227 | msmsdcc_dma_complete_tlet(unsigned long data) |
193 | unsigned int result, | ||
194 | struct msm_dmov_errdata *err) | ||
195 | { | 228 | { |
196 | struct msmsdcc_dma_data *dma_data = | 229 | struct msmsdcc_host *host = (struct msmsdcc_host *)data; |
197 | container_of(cmd, struct msmsdcc_dma_data, hdr); | ||
198 | struct msmsdcc_host *host = dma_data->host; | ||
199 | unsigned long flags; | 230 | unsigned long flags; |
200 | struct mmc_request *mrq; | 231 | struct mmc_request *mrq; |
232 | struct msm_dmov_errdata err; | ||
201 | 233 | ||
202 | spin_lock_irqsave(&host->lock, flags); | 234 | spin_lock_irqsave(&host->lock, flags); |
203 | host->dma.active = 0; | 235 | host->dma.active = 0; |
204 | 236 | ||
237 | err = host->dma.err; | ||
205 | mrq = host->curr.mrq; | 238 | mrq = host->curr.mrq; |
206 | BUG_ON(!mrq); | 239 | BUG_ON(!mrq); |
207 | WARN_ON(!mrq->data); | 240 | WARN_ON(!mrq->data); |
208 | 241 | ||
209 | if (!(result & DMOV_RSLT_VALID)) { | 242 | if (!(host->dma.result & DMOV_RSLT_VALID)) { |
210 | pr_err("msmsdcc: Invalid DataMover result\n"); | 243 | pr_err("msmsdcc: Invalid DataMover result\n"); |
211 | goto out; | 244 | goto out; |
212 | } | 245 | } |
213 | 246 | ||
214 | if (result & DMOV_RSLT_DONE) { | 247 | if (host->dma.result & DMOV_RSLT_DONE) { |
215 | host->curr.data_xfered = host->curr.xfer_size; | 248 | host->curr.data_xfered = host->curr.xfer_size; |
216 | } else { | 249 | } else { |
217 | /* Error or flush */ | 250 | /* Error or flush */ |
218 | if (result & DMOV_RSLT_ERROR) | 251 | if (host->dma.result & DMOV_RSLT_ERROR) |
219 | pr_err("%s: DMA error (0x%.8x)\n", | 252 | pr_err("%s: DMA error (0x%.8x)\n", |
220 | mmc_hostname(host->mmc), result); | 253 | mmc_hostname(host->mmc), host->dma.result); |
221 | if (result & DMOV_RSLT_FLUSH) | 254 | if (host->dma.result & DMOV_RSLT_FLUSH) |
222 | pr_err("%s: DMA channel flushed (0x%.8x)\n", | 255 | pr_err("%s: DMA channel flushed (0x%.8x)\n", |
223 | mmc_hostname(host->mmc), result); | 256 | mmc_hostname(host->mmc), host->dma.result); |
224 | if (err) | 257 | |
225 | pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n", | 258 | pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n", |
226 | err->flush[0], err->flush[1], err->flush[2], | 259 | err.flush[0], err.flush[1], err.flush[2], |
227 | err->flush[3], err->flush[4], err->flush[5]); | 260 | err.flush[3], err.flush[4], err.flush[5]); |
261 | |||
262 | msmsdcc_reset_and_restore(host); | ||
228 | if (!mrq->data->error) | 263 | if (!mrq->data->error) |
229 | mrq->data->error = -EIO; | 264 | mrq->data->error = -EIO; |
230 | } | 265 | } |
@@ -242,8 +277,7 @@ msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd, | |||
242 | host->dma.sg = NULL; | 277 | host->dma.sg = NULL; |
243 | host->dma.busy = 0; | 278 | host->dma.busy = 0; |
244 | 279 | ||
245 | if ((host->curr.got_dataend && host->curr.got_datablkend) | 280 | if (host->curr.got_dataend || mrq->data->error) { |
246 | || mrq->data->error) { | ||
247 | 281 | ||
248 | /* | 282 | /* |
249 | * If we've already gotten our DATAEND / DATABLKEND | 283 | * If we've already gotten our DATAEND / DATABLKEND |
@@ -273,6 +307,22 @@ out: | |||
273 | return; | 307 | return; |
274 | } | 308 | } |
275 | 309 | ||
310 | static void | ||
311 | msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd, | ||
312 | unsigned int result, | ||
313 | struct msm_dmov_errdata *err) | ||
314 | { | ||
315 | struct msmsdcc_dma_data *dma_data = | ||
316 | container_of(cmd, struct msmsdcc_dma_data, hdr); | ||
317 | struct msmsdcc_host *host = dma_data->host; | ||
318 | |||
319 | dma_data->result = result; | ||
320 | if (err) | ||
321 | memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata)); | ||
322 | |||
323 | tasklet_schedule(&host->dma_tlet); | ||
324 | } | ||
325 | |||
276 | static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data) | 326 | static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data) |
277 | { | 327 | { |
278 | if (host->dma.channel == -1) | 328 | if (host->dma.channel == -1) |
@@ -424,6 +474,11 @@ msmsdcc_start_command_deferred(struct msmsdcc_host *host, | |||
424 | (cmd->opcode == 53)) | 474 | (cmd->opcode == 53)) |
425 | *c |= MCI_CSPM_DATCMD; | 475 | *c |= MCI_CSPM_DATCMD; |
426 | 476 | ||
477 | if (host->prog_scan && (cmd->opcode == 12)) { | ||
478 | *c |= MCI_CPSM_PROGENA; | ||
479 | host->prog_enable = true; | ||
480 | } | ||
481 | |||
427 | if (cmd == cmd->mrq->stop) | 482 | if (cmd == cmd->mrq->stop) |
428 | *c |= MCI_CSPM_MCIABORT; | 483 | *c |= MCI_CSPM_MCIABORT; |
429 | 484 | ||
@@ -450,7 +505,6 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data, | |||
450 | host->curr.xfer_remain = host->curr.xfer_size; | 505 | host->curr.xfer_remain = host->curr.xfer_size; |
451 | host->curr.data_xfered = 0; | 506 | host->curr.data_xfered = 0; |
452 | host->curr.got_dataend = 0; | 507 | host->curr.got_dataend = 0; |
453 | host->curr.got_datablkend = 0; | ||
454 | 508 | ||
455 | memset(&host->pio, 0, sizeof(host->pio)); | 509 | memset(&host->pio, 0, sizeof(host->pio)); |
456 | 510 | ||
@@ -494,6 +548,8 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data, | |||
494 | host->cmd_c = c; | 548 | host->cmd_c = c; |
495 | } | 549 | } |
496 | msm_dmov_enqueue_cmd(host->dma.channel, &host->dma.hdr); | 550 | msm_dmov_enqueue_cmd(host->dma.channel, &host->dma.hdr); |
551 | if (data->flags & MMC_DATA_WRITE) | ||
552 | host->prog_scan = true; | ||
497 | } else { | 553 | } else { |
498 | msmsdcc_writel(host, timeout, MMCIDATATIMER); | 554 | msmsdcc_writel(host, timeout, MMCIDATATIMER); |
499 | 555 | ||
@@ -555,6 +611,9 @@ msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain) | |||
555 | uint32_t *ptr = (uint32_t *) buffer; | 611 | uint32_t *ptr = (uint32_t *) buffer; |
556 | int count = 0; | 612 | int count = 0; |
557 | 613 | ||
614 | if (remain % 4) | ||
615 | remain = ((remain >> 2) + 1) << 2; | ||
616 | |||
558 | while (msmsdcc_readl(host, MMCISTATUS) & MCI_RXDATAAVLBL) { | 617 | while (msmsdcc_readl(host, MMCISTATUS) & MCI_RXDATAAVLBL) { |
559 | *ptr = msmsdcc_readl(host, MMCIFIFO + (count % MCI_FIFOSIZE)); | 618 | *ptr = msmsdcc_readl(host, MMCIFIFO + (count % MCI_FIFOSIZE)); |
560 | ptr++; | 619 | ptr++; |
@@ -575,13 +634,14 @@ msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer, | |||
575 | char *ptr = buffer; | 634 | char *ptr = buffer; |
576 | 635 | ||
577 | do { | 636 | do { |
578 | unsigned int count, maxcnt; | 637 | unsigned int count, maxcnt, sz; |
579 | 638 | ||
580 | maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : | 639 | maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : |
581 | MCI_FIFOHALFSIZE; | 640 | MCI_FIFOHALFSIZE; |
582 | count = min(remain, maxcnt); | 641 | count = min(remain, maxcnt); |
583 | 642 | ||
584 | writesl(base + MMCIFIFO, ptr, count >> 2); | 643 | sz = count % 4 ? (count >> 2) + 1 : (count >> 2); |
644 | writesl(base + MMCIFIFO, ptr, sz); | ||
585 | ptr += count; | 645 | ptr += count; |
586 | remain -= count; | 646 | remain -= count; |
587 | 647 | ||
@@ -702,10 +762,26 @@ static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status) | |||
702 | msm_dmov_stop_cmd(host->dma.channel, | 762 | msm_dmov_stop_cmd(host->dma.channel, |
703 | &host->dma.hdr, 0); | 763 | &host->dma.hdr, 0); |
704 | else if (host->curr.data) { /* Non DMA */ | 764 | else if (host->curr.data) { /* Non DMA */ |
765 | msmsdcc_reset_and_restore(host); | ||
705 | msmsdcc_stop_data(host); | 766 | msmsdcc_stop_data(host); |
706 | msmsdcc_request_end(host, cmd->mrq); | 767 | msmsdcc_request_end(host, cmd->mrq); |
707 | } else /* host->data == NULL */ | 768 | } else { /* host->data == NULL */ |
708 | msmsdcc_request_end(host, cmd->mrq); | 769 | if (!cmd->error && host->prog_enable) { |
770 | if (status & MCI_PROGDONE) { | ||
771 | host->prog_scan = false; | ||
772 | host->prog_enable = false; | ||
773 | msmsdcc_request_end(host, cmd->mrq); | ||
774 | } else { | ||
775 | host->curr.cmd = cmd; | ||
776 | } | ||
777 | } else { | ||
778 | if (host->prog_enable) { | ||
779 | host->prog_scan = false; | ||
780 | host->prog_enable = false; | ||
781 | } | ||
782 | msmsdcc_request_end(host, cmd->mrq); | ||
783 | } | ||
784 | } | ||
709 | } else if (cmd->data) | 785 | } else if (cmd->data) |
710 | if (!(cmd->data->flags & MMC_DATA_READ)) | 786 | if (!(cmd->data->flags & MMC_DATA_READ)) |
711 | msmsdcc_start_data(host, cmd->data, | 787 | msmsdcc_start_data(host, cmd->data, |
@@ -719,7 +795,7 @@ msmsdcc_handle_irq_data(struct msmsdcc_host *host, u32 status, | |||
719 | struct mmc_data *data = host->curr.data; | 795 | struct mmc_data *data = host->curr.data; |
720 | 796 | ||
721 | if (status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL | | 797 | if (status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL | |
722 | MCI_CMDTIMEOUT) && host->curr.cmd) { | 798 | MCI_CMDTIMEOUT | MCI_PROGDONE) && host->curr.cmd) { |
723 | msmsdcc_do_cmdirq(host, status); | 799 | msmsdcc_do_cmdirq(host, status); |
724 | } | 800 | } |
725 | 801 | ||
@@ -735,6 +811,7 @@ msmsdcc_handle_irq_data(struct msmsdcc_host *host, u32 status, | |||
735 | msm_dmov_stop_cmd(host->dma.channel, | 811 | msm_dmov_stop_cmd(host->dma.channel, |
736 | &host->dma.hdr, 0); | 812 | &host->dma.hdr, 0); |
737 | else { | 813 | else { |
814 | msmsdcc_reset_and_restore(host); | ||
738 | if (host->curr.data) | 815 | if (host->curr.data) |
739 | msmsdcc_stop_data(host); | 816 | msmsdcc_stop_data(host); |
740 | if (!data->stop) | 817 | if (!data->stop) |
@@ -748,14 +825,10 @@ msmsdcc_handle_irq_data(struct msmsdcc_host *host, u32 status, | |||
748 | if (!host->curr.got_dataend && (status & MCI_DATAEND)) | 825 | if (!host->curr.got_dataend && (status & MCI_DATAEND)) |
749 | host->curr.got_dataend = 1; | 826 | host->curr.got_dataend = 1; |
750 | 827 | ||
751 | if (!host->curr.got_datablkend && (status & MCI_DATABLOCKEND)) | ||
752 | host->curr.got_datablkend = 1; | ||
753 | |||
754 | /* | 828 | /* |
755 | * If DMA is still in progress, we complete via the completion handler | 829 | * If DMA is still in progress, we complete via the completion handler |
756 | */ | 830 | */ |
757 | if (host->curr.got_dataend && host->curr.got_datablkend && | 831 | if (host->curr.got_dataend && !host->dma.busy) { |
758 | !host->dma.busy) { | ||
759 | /* | 832 | /* |
760 | * There appears to be an issue in the controller where | 833 | * There appears to be an issue in the controller where |
761 | * if you request a small block transfer (< fifo size), | 834 | * if you request a small block transfer (< fifo size), |
@@ -792,8 +865,7 @@ msmsdcc_irq(int irq, void *dev_id) | |||
792 | 865 | ||
793 | do { | 866 | do { |
794 | status = msmsdcc_readl(host, MMCISTATUS); | 867 | status = msmsdcc_readl(host, MMCISTATUS); |
795 | status &= (msmsdcc_readl(host, MMCIMASK0) | | 868 | status &= msmsdcc_readl(host, MMCIMASK0); |
796 | MCI_DATABLOCKENDMASK); | ||
797 | msmsdcc_writel(host, status, MMCICLEAR); | 869 | msmsdcc_writel(host, status, MMCICLEAR); |
798 | 870 | ||
799 | if (status & MCI_SDIOINTR) | 871 | if (status & MCI_SDIOINTR) |
@@ -1118,6 +1190,9 @@ msmsdcc_probe(struct platform_device *pdev) | |||
1118 | host->dmares = dmares; | 1190 | host->dmares = dmares; |
1119 | spin_lock_init(&host->lock); | 1191 | spin_lock_init(&host->lock); |
1120 | 1192 | ||
1193 | tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet, | ||
1194 | (unsigned long)host); | ||
1195 | |||
1121 | /* | 1196 | /* |
1122 | * Setup DMA | 1197 | * Setup DMA |
1123 | */ | 1198 | */ |
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h index ff2b0f74f6f4..939557af266d 100644 --- a/drivers/mmc/host/msm_sdcc.h +++ b/drivers/mmc/host/msm_sdcc.h | |||
@@ -138,7 +138,7 @@ | |||
138 | #define MCI_IRQENABLE \ | 138 | #define MCI_IRQENABLE \ |
139 | (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ | 139 | (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ |
140 | MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ | 140 | MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ |
141 | MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK) | 141 | MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK|MCI_PROGDONEMASK) |
142 | 142 | ||
143 | /* | 143 | /* |
144 | * The size of the FIFO in bytes. | 144 | * The size of the FIFO in bytes. |
@@ -172,6 +172,8 @@ struct msmsdcc_dma_data { | |||
172 | struct msmsdcc_host *host; | 172 | struct msmsdcc_host *host; |
173 | int busy; /* Set if DM is busy */ | 173 | int busy; /* Set if DM is busy */ |
174 | int active; | 174 | int active; |
175 | unsigned int result; | ||
176 | struct msm_dmov_errdata err; | ||
175 | }; | 177 | }; |
176 | 178 | ||
177 | struct msmsdcc_pio_data { | 179 | struct msmsdcc_pio_data { |
@@ -188,7 +190,6 @@ struct msmsdcc_curr_req { | |||
188 | unsigned int xfer_remain; /* Bytes remaining to send */ | 190 | unsigned int xfer_remain; /* Bytes remaining to send */ |
189 | unsigned int data_xfered; /* Bytes acked by BLKEND irq */ | 191 | unsigned int data_xfered; /* Bytes acked by BLKEND irq */ |
190 | int got_dataend; | 192 | int got_dataend; |
191 | int got_datablkend; | ||
192 | int user_pages; | 193 | int user_pages; |
193 | }; | 194 | }; |
194 | 195 | ||
@@ -235,6 +236,7 @@ struct msmsdcc_host { | |||
235 | int cmdpoll; | 236 | int cmdpoll; |
236 | struct msmsdcc_stats stats; | 237 | struct msmsdcc_stats stats; |
237 | 238 | ||
239 | struct tasklet_struct dma_tlet; | ||
238 | /* Command parameters */ | 240 | /* Command parameters */ |
239 | unsigned int cmd_timeout; | 241 | unsigned int cmd_timeout; |
240 | unsigned int cmd_pio_irqmask; | 242 | unsigned int cmd_pio_irqmask; |
@@ -242,6 +244,8 @@ struct msmsdcc_host { | |||
242 | struct mmc_command *cmd_cmd; | 244 | struct mmc_command *cmd_cmd; |
243 | u32 cmd_c; | 245 | u32 cmd_c; |
244 | 246 | ||
247 | bool prog_scan; | ||
248 | bool prog_enable; | ||
245 | }; | 249 | }; |
246 | 250 | ||
247 | #endif | 251 | #endif |