Tegra2: mmc: Support DMA restarts at buffer boundaries

Currently if a DMA buffer straddles a buffer alignment boundary
(512KiB) then the DMA engine will pause and generate a DMA
interrupt.  Since the DMA interrupt is not enabled it will hang
the MMC driver.

This patch adds support for restarting the DMA transfer.  The
SYSTEM_ADDRESS register contains the next address that would have
been read/written when a boundary is hit.  So we can read that
and write it back.  The write triggers the resumption of the
transfer.

Signed-off-by: Anton Staaf <robotboy@chromium.org>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Tom Warren <twarren@nvidia.com>
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Albert Aribaud <albert.u.boot@aribaud.net>
This commit is contained in:
Anton staaf 2011-11-10 11:56:50 +00:00 committed by Andy Fleming
parent 8e42f0d62b
commit 5a762e2509

View file

@ -270,9 +270,16 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
__func__, mask);
return -1;
} else if (mask & TEGRA_MMC_NORINTSTS_DMA_INTERRUPT) {
/* DMA Interrupt */
/*
* DMA Interrupt, restart the transfer where
* it was interrupted.
*/
unsigned int address = readl(&host->reg->sysad);
debug("DMA end\n");
break;
writel(TEGRA_MMC_NORINTSTS_DMA_INTERRUPT,
&host->reg->norintsts);
writel(address, &host->reg->sysad);
} else if (mask & TEGRA_MMC_NORINTSTS_XFER_COMPLETE) {
/* Transfer Complete */
debug("r/w is done\n");
@ -419,6 +426,7 @@ static int mmc_core_init(struct mmc *mmc)
* NORMAL Interrupt Status Enable Register init
* [5] ENSTABUFRDRDY : Buffer Read Ready Status Enable
* [4] ENSTABUFWTRDY : Buffer write Ready Status Enable
* [3] ENSTADMAINT : DMA boundary interrupt
* [1] ENSTASTANSCMPLT : Transfre Complete Status Enable
* [0] ENSTACMDCMPLT : Command Complete Status Enable
*/
@ -426,6 +434,7 @@ static int mmc_core_init(struct mmc *mmc)
mask &= ~(0xffff);
mask |= (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE |
TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE |
TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT |
TEGRA_MMC_NORINTSTSEN_BUFFER_WRITE_READY |
TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY);
writel(mask, &host->reg->norintstsen);