summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-05-03 14:23:01 -0400
committerTom Rini <trini@konsulko.com>2019-05-03 14:23:01 -0400
commit4862830b696a6d0750e19d32a82553cdb41a85f8 (patch)
treef81a33bfd965bc92b5437e4a9744c72bd09f0e20 /drivers/mmc
parentc767b6ac98c8cee866954f5260734e8291d5c4ee (diff)
parent7110259f550ce2c300f6f2c1760576c180705f4e (diff)
Merge git://git.denx.de/u-boot-socfpga
- Misc MMC, FPGA bridge, general SoCFPGA fixes
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/dw_mmc.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 93a836eac3..1992d61182 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -74,15 +74,15 @@ static void dwmci_prepare_data(struct dwmci_host *host,
dwmci_set_idma_desc(cur_idmac, flags, cnt,
(ulong)bounce_buffer + (i * PAGE_SIZE));
+ cur_idmac++;
if (blk_cnt <= 8)
break;
blk_cnt -= 8;
- cur_idmac++;
i++;
} while(1);
data_end = (ulong)cur_idmac;
- flush_dcache_range(data_start, data_end + ARCH_DMA_MINALIGN);
+ flush_dcache_range(data_start, roundup(data_end, ARCH_DMA_MINALIGN));
ctrl = dwmci_readl(host, DWMCI_CTRL);
ctrl |= DWMCI_IDMAC_EN | DWMCI_DMA_EN;
@@ -114,22 +114,40 @@ static int dwmci_fifo_ready(struct dwmci_host *host, u32 bit, u32 *len)
return 0;
}
+static unsigned int dwmci_get_timeout(struct mmc *mmc, const unsigned int size)
+{
+ unsigned int timeout;
+
+ timeout = size * 8 * 1000; /* counting in bits and msec */
+ timeout *= 2; /* wait twice as long */
+ timeout /= mmc->clock;
+ timeout /= mmc->bus_width;
+ timeout /= mmc->ddr_mode ? 2 : 1;
+ timeout = (timeout < 1000) ? 1000 : timeout;
+
+ return timeout;
+}
+
static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
{
+ struct mmc *mmc = host->mmc;
int ret = 0;
- u32 timeout = 240000;
- u32 mask, size, i, len = 0;
+ u32 timeout, mask, size, i, len = 0;
u32 *buf = NULL;
ulong start = get_timer(0);
u32 fifo_depth = (((host->fifoth_val & RX_WMARK_MASK) >>
RX_WMARK_SHIFT) + 1) * 2;
- size = data->blocksize * data->blocks / 4;
+ size = data->blocksize * data->blocks;
if (data->flags == MMC_DATA_READ)
buf = (unsigned int *)data->dest;
else
buf = (unsigned int *)data->src;
+ timeout = dwmci_get_timeout(mmc, size);
+
+ size /= 4;
+
for (;;) {
mask = dwmci_readl(host, DWMCI_RINTSTS);
/* Error during data transfer. */
@@ -252,14 +270,20 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET);
} else {
if (data->flags == MMC_DATA_READ) {
- bounce_buffer_start(&bbstate, (void*)data->dest,
+ ret = bounce_buffer_start(&bbstate,
+ (void*)data->dest,
data->blocksize *
data->blocks, GEN_BB_WRITE);
} else {
- bounce_buffer_start(&bbstate, (void*)data->src,
+ ret = bounce_buffer_start(&bbstate,
+ (void*)data->src,
data->blocksize *
data->blocks, GEN_BB_READ);
}
+
+ if (ret)
+ return ret;
+
dwmci_prepare_data(host, data, cur_idmac,
bbstate.bounce_buffer);
}