From 2b42903397b4d6b68fe2af95565a8953b08ab96e Mon Sep 17 00:00:00 2001
From: Jacob Chen <jacob2.chen@rock-chips.com>
Date: Mon, 19 Sep 2016 10:16:50 +0800
Subject: [PATCH] mmc: dw_mmc: push/pop all FIFO data if any data request

When DTO interrupt occurred, there are any remaining data still in FIFO
due to RX FIFO threshold is larger than remaining data. It also
causes that dwmmc didn't trigger RXDR interrupt, so is TX.

It's responsibility of driver to read remaining bytes on seeing DTO
interrupt.

Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
Signed-off-by: Ziyuan Xu <xzy.xu@rock-chips.com>
---
 drivers/mmc/dw_mmc.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index afc674dd14..074f86c502 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -120,9 +120,9 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
 
 		if (host->fifo_mode && size) {
 			len = 0;
-			if (data->flags == MMC_DATA_READ) {
-				if ((dwmci_readl(host, DWMCI_RINTSTS) &
-				     DWMCI_INTMSK_RXDR)) {
+			if (data->flags == MMC_DATA_READ &&
+			    (mask & DWMCI_INTMSK_RXDR)) {
+				while (size) {
 					len = dwmci_readl(host, DWMCI_STATUS);
 					len = (len >> DWMCI_FIFO_SHIFT) &
 						    DWMCI_FIFO_MASK;
@@ -130,12 +130,13 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
 					for (i = 0; i < len; i++)
 						*buf++ =
 						dwmci_readl(host, DWMCI_DATA);
-					dwmci_writel(host, DWMCI_RINTSTS,
-						     DWMCI_INTMSK_RXDR);
+					size = size > len ? (size - len) : 0;
 				}
-			} else {
-				if ((dwmci_readl(host, DWMCI_RINTSTS) &
-				     DWMCI_INTMSK_TXDR)) {
+				dwmci_writel(host, DWMCI_RINTSTS,
+					     DWMCI_INTMSK_RXDR);
+			} else if (data->flags == MMC_DATA_WRITE &&
+				   (mask & DWMCI_INTMSK_TXDR)) {
+				while (size) {
 					len = dwmci_readl(host, DWMCI_STATUS);
 					len = fifo_depth - ((len >>
 						   DWMCI_FIFO_SHIFT) &
@@ -144,11 +145,11 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
 					for (i = 0; i < len; i++)
 						dwmci_writel(host, DWMCI_DATA,
 							     *buf++);
-					dwmci_writel(host, DWMCI_RINTSTS,
-						     DWMCI_INTMSK_TXDR);
+					size = size > len ? (size - len) : 0;
 				}
+				dwmci_writel(host, DWMCI_RINTSTS,
+					     DWMCI_INTMSK_TXDR);
 			}
-			size = size > len ? (size - len) : 0;
 		}
 
 		/* Data arrived correctly. */
-- 
2.39.5