diff options
author | Anton staaf <robotboy@chromium.org> | 2011-11-10 11:56:50 +0000 |
---|---|---|
committer | Andy Fleming <afleming@freescale.com> | 2011-11-12 15:39:29 -0600 |
commit | 5a762e2509a2d4b2e86168a2ffbc425087ecd75c (patch) | |
tree | ab7b84c2789f53550d7051c654f961513d67256b /drivers/mmc/tegra2_mmc.c | |
parent | 8e42f0d62b9ee5ff5d3b2ddda16d98d5c792719c (diff) | |
download | u-boot-imx-5a762e2509a2d4b2e86168a2ffbc425087ecd75c.zip u-boot-imx-5a762e2509a2d4b2e86168a2ffbc425087ecd75c.tar.gz u-boot-imx-5a762e2509a2d4b2e86168a2ffbc425087ecd75c.tar.bz2 |
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>
Diffstat (limited to 'drivers/mmc/tegra2_mmc.c')
-rw-r--r-- | drivers/mmc/tegra2_mmc.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra2_mmc.c index 2bea07d..159cef1 100644 --- a/drivers/mmc/tegra2_mmc.c +++ b/drivers/mmc/tegra2_mmc.c @@ -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); |