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 <robot...@chromium.org>
Cc: Andy Fleming <aflem...@gmail.com>
Cc: Tom Warren <twar...@nvidia.com>
Cc: Stephen Warren <swar...@nvidia.com>
Cc: Albert Aribaud <albert.u.b...@aribaud.net>
---
 drivers/mmc/tegra2_mmc.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra2_mmc.c
index 2e7746d..73f6405 100644
--- a/drivers/mmc/tegra2_mmc.c
+++ b/drivers/mmc/tegra2_mmc.c
@@ -240,9 +240,16 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd 
*cmd,
                                                __func__, mask);
                                return -1;
                        } else if (mask & TEGRA2_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(TEGRA2_MMC_NORINTSTS_DMA_INTERRUPT,
+                                      &host->reg->norintsts);
+                               writel(address, &host->reg->sysad);
                        } else if (mask & TEGRA2_MMC_NORINTSTS_XFER_COMPLETE) {
                                /* Transfer Complete */
                                debug("r/w is done\n");
@@ -380,6 +387,7 @@ static int mmc_core_init(struct mmc *mmc)
        mask |= (1 << 5) | (1 << 4) | (1 << 1) | (1 << 0);
        mask |= (TEGRA2_MMC_NORINTSTSEN_CMD_COMPLETE |
                 TEGRA2_MMC_NORINTSTSEN_XFER_COMPLETE |
+                TEGRA2_MMC_NORINTSTSEN_DMA_INTERRUPT |
                 TEGRA2_MMC_NORINTSTSEN_BUFFER_WRITE_READY |
                 TEGRA2_MMC_NORINTSTSEN_BUFFER_READ_READY);
        writel(mask, &host->reg->norintstsen);
-- 
1.7.3.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to