mmc: S5P: Support DMA restarts at buffer boundaries
authorAnton Staaf <robotboy@chromium.org>
Thu, 30 Jun 2011 09:55:08 +0000 (09:55 +0000)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Sat, 3 Sep 2011 20:40:47 +0000 (22:40 +0200)
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>
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
Tested-by : Jaehoon Chung <jh80.chung@samsung.com>
Cc: Albert ARIBAUD <albert.u.boot@aribaud.net>
drivers/mmc/s5p_mmc.c

index f136813..7786ecf 100644 (file)
@@ -232,9 +232,15 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
                                                __func__, mask);
                                return -1;
                        } else if (mask & (1 << 3)) {
-                               /* DMA Interrupt */
+                               /*
+                                * DMA Interrupt, restart the transfer where
+                                * it was interrupted.
+                                */
+                               unsigned int address = readl(&host->reg->sysad);
+
                                debug("DMA end\n");
-                               break;
+                               writel((1 << 3), &host->reg->norintsts);
+                               writel(address, &host->reg->sysad);
                        } else if (mask & (1 << 1)) {
                                /* Transfer Complete */
                                debug("r/w is done\n");
@@ -425,12 +431,13 @@ 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 Interrupt Status Enable
         * [1] ENSTASTANSCMPLT : Transfre Complete Status Enable
         * [0] ENSTACMDCMPLT : Command Complete Status Enable
-       */
+        */
        mask = readl(&host->reg->norintstsen);
        mask &= ~(0xffff);
-       mask |= (1 << 5) | (1 << 4) | (1 << 1) | (1 << 0);
+       mask |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1) | (1 << 0);
        writel(mask, &host->reg->norintstsen);
 
        /*