summaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorKyoungil Kim2013-01-22 08:46:30 +0100
committerChris Ball2013-03-22 17:00:59 +0100
commit87a74d399a165510b053c406699992af9add0da9 (patch)
treeed1b7564f3a982aa262597a7bb37a5cfe168925f /drivers/mmc
parentmmc: dw_mmc: return the result of mmc_add_host() (diff)
downloadkernel-qcow2-linux-87a74d399a165510b053c406699992af9add0da9.tar.gz
kernel-qcow2-linux-87a74d399a165510b053c406699992af9add0da9.tar.xz
kernel-qcow2-linux-87a74d399a165510b053c406699992af9add0da9.zip
mmc: dw_mmc: empty FIFO after data transfer over interrupt in pio mode
In dwc manual, the below contents are described: "During end of packet, interrupt is not generated if threshold programming is larger than any remaining data. It is responsibility of host to read remaining bytes on seeing Data Transfer Done interrupt" We also have seen the data cannot be read fully when "sg_miter->length" is less than FIFO size. Signed-off-by: Kyoungil Kim <ki0351.kim@samsung.com> Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com> Acked-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/dw_mmc.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 6da19c15d73b..2f4a62ffb22d 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1438,7 +1438,7 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt)
host->pull_data(host, buf, cnt);
}
-static void dw_mci_read_data_pio(struct dw_mci *host)
+static void dw_mci_read_data_pio(struct dw_mci *host, bool dto)
{
struct sg_mapping_iter *sg_miter = &host->sg_miter;
void *buf;
@@ -1473,7 +1473,9 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
sg_miter->consumed = offset;
status = mci_readl(host, MINTSTS);
mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
- } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
+ /* if the RXDR is ready read again */
+ } while ((status & SDMMC_INT_RXDR) ||
+ (dto && SDMMC_GET_FCNT(mci_readl(host, STATUS))));
data->bytes_xfered += nbytes;
if (!remain) {
@@ -1605,7 +1607,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
smp_wmb();
if (host->dir_status == DW_MCI_RECV_STATUS) {
if (host->sg != NULL)
- dw_mci_read_data_pio(host);
+ dw_mci_read_data_pio(host, true);
}
set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
tasklet_schedule(&host->tasklet);
@@ -1614,7 +1616,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
if (pending & SDMMC_INT_RXDR) {
mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
if (host->dir_status == DW_MCI_RECV_STATUS && host->sg)
- dw_mci_read_data_pio(host);
+ dw_mci_read_data_pio(host, false);
}
if (pending & SDMMC_INT_TXDR) {