|
@@ -92,6 +92,24 @@ static void dwmci_prepare_data(struct dwmci_host *host,
|
|
dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks);
|
|
dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int dwmci_fifo_ready(struct dwmci_host *host, u32 bit, u32 *len)
|
|
|
|
+{
|
|
|
|
+ u32 timeout = 20000;
|
|
|
|
+
|
|
|
|
+ *len = dwmci_readl(host, DWMCI_STATUS);
|
|
|
|
+ while (--timeout && (*len & bit)) {
|
|
|
|
+ udelay(200);
|
|
|
|
+ *len = dwmci_readl(host, DWMCI_STATUS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!timeout) {
|
|
|
|
+ debug("%s: FIFO underflow timeout\n", __func__);
|
|
|
|
+ return -ETIMEDOUT;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
|
|
static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
|
|
{
|
|
{
|
|
int ret = 0;
|
|
int ret = 0;
|
|
@@ -122,7 +140,12 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
|
|
if (data->flags == MMC_DATA_READ &&
|
|
if (data->flags == MMC_DATA_READ &&
|
|
(mask & DWMCI_INTMSK_RXDR)) {
|
|
(mask & DWMCI_INTMSK_RXDR)) {
|
|
while (size) {
|
|
while (size) {
|
|
- len = dwmci_readl(host, DWMCI_STATUS);
|
|
|
|
|
|
+ ret = dwmci_fifo_ready(host,
|
|
|
|
+ DWMCI_FIFO_EMPTY,
|
|
|
|
+ &len);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ break;
|
|
|
|
+
|
|
len = (len >> DWMCI_FIFO_SHIFT) &
|
|
len = (len >> DWMCI_FIFO_SHIFT) &
|
|
DWMCI_FIFO_MASK;
|
|
DWMCI_FIFO_MASK;
|
|
len = min(size, len);
|
|
len = min(size, len);
|
|
@@ -136,7 +159,12 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
|
|
} else if (data->flags == MMC_DATA_WRITE &&
|
|
} else if (data->flags == MMC_DATA_WRITE &&
|
|
(mask & DWMCI_INTMSK_TXDR)) {
|
|
(mask & DWMCI_INTMSK_TXDR)) {
|
|
while (size) {
|
|
while (size) {
|
|
- len = dwmci_readl(host, DWMCI_STATUS);
|
|
|
|
|
|
+ ret = dwmci_fifo_ready(host,
|
|
|
|
+ DWMCI_FIFO_FULL,
|
|
|
|
+ &len);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ break;
|
|
|
|
+
|
|
len = fifo_depth - ((len >>
|
|
len = fifo_depth - ((len >>
|
|
DWMCI_FIFO_SHIFT) &
|
|
DWMCI_FIFO_SHIFT) &
|
|
DWMCI_FIFO_MASK);
|
|
DWMCI_FIFO_MASK);
|