summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorUlf Hansson <(address hidden)>2011-11-08 10:53:22 +0100
committerPhilippe Langlais <philippe.langlais@linaro.org>2012-03-19 08:56:44 +0100
commitba4596790b03097bfbd2d74bdca1b62173e504ca (patch)
treec85a90393e3ea454e98d5fd8a7365687c0f5490d /drivers/mmc
parent97845db7f5cc05ee76de7ac44295732a577f81f7 (diff)
mmci: Fix incorrect handling of HW flow control for SDIO
For data writes smaller <= 8 bytes (only SDIO case), HW flow control was disabled but never re-enabled again. This meant that a following large read request would randomly give buffer overrun errors. Moreover HW flow control is not needed for transfers that fits in the FIFO of PL18x. Thus it is disabled for write operations <= the FIFO size. Signed-off-by: Ulf Hansson <(address hidden)> Signed-off-by: Stefan Nilsson XK <(address hidden)>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/mmci.c42
1 files changed, 24 insertions, 18 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 4bc4a115a52..ffc32b8b45d 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -611,9 +611,32 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
/* The ST Micro variants has a special bit to enable SDIO */
if (variant->sdio && host->mmc->card)
- if (mmc_card_sdio(host->mmc->card))
+ if (mmc_card_sdio(host->mmc->card)) {
+ /*
+ * The ST Micro variants has a special bit
+ * to enable SDIO.
+ */
datactrl |= MCI_ST_DPSM_SDIOEN;
+ /*
+ * The ST Micro variant for SDIO transfer sizes
+ * less then or equal to 8 bytes needs to have clock
+ * H/W flow control disabled. Since flow control is
+ * not really needed for anything that fits in the
+ * FIFO, we can disable it for any write smaller
+ * than the FIFO size.
+ */
+ if ((host->size <= variant->fifosize) &&
+ (data->flags & MMC_DATA_WRITE))
+ writel(readl(host->base + MMCICLOCK) &
+ ~variant->clkreg_enable,
+ host->base + MMCICLOCK);
+ else
+ writel(readl(host->base + MMCICLOCK) |
+ variant->clkreg_enable,
+ host->base + MMCICLOCK);
+ }
+
/*
* Attempt to use DMA operation mode, if this
* should fail, fall back to PIO mode
@@ -817,23 +840,6 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem
count = min(remain, maxcnt);
/*
- * The ST Micro variant for SDIO transfer sizes
- * less then 8 bytes should have clock H/W flow
- * control disabled.
- */
- if (variant->sdio &&
- mmc_card_sdio(host->mmc->card)) {
- if (count < 8)
- writel(readl(host->base + MMCICLOCK) &
- ~variant->clkreg_enable,
- host->base + MMCICLOCK);
- else
- writel(readl(host->base + MMCICLOCK) |
- variant->clkreg_enable,
- host->base + MMCICLOCK);
- }
-
- /*
* SDIO especially may want to send something that is
* not divisible by 4 (as opposed to card sectors
* etc), and the FIFO only accept full 32-bit writes.