aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAnton staaf <robotboy@chromium.org>2011-11-10 11:56:50 +0000
committerAndy Fleming <afleming@freescale.com>2011-11-12 15:39:29 -0600
commit5a762e2509a2d4b2e86168a2ffbc425087ecd75c (patch)
treeab7b84c2789f53550d7051c654f961513d67256b /drivers
parent8e42f0d62b9ee5ff5d3b2ddda16d98d5c792719c (diff)
downloadu-boot-5a762e2509a2d4b2e86168a2ffbc425087ecd75c.zip
u-boot-5a762e2509a2d4b2e86168a2ffbc425087ecd75c.tar.gz
u-boot-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')
-rw-r--r--drivers/mmc/tegra2_mmc.c13
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);