#define INFO2_DTRANERR1                BIT(17)
 #define INFO2_DTRANERR0                BIT(16)
 
+enum renesas_sdhi_dma_cookie {
+       COOKIE_UNMAPPED,
+       COOKIE_PRE_MAPPED,
+       COOKIE_MAPPED,
+};
+
 /*
  * Specification of this driver:
  * - host->chan_{rx,tx} will be used as a flag of enabling/disabling the dma
        tasklet_schedule(&priv->dma_priv.dma_complete);
 }
 
+/*
+ * renesas_sdhi_internal_dmac_map() will be called with two difference
+ * sg pointers in two mmc_data by .pre_req(), but tmio host can have a single
+ * sg_ptr only. So, renesas_sdhi_internal_dmac_{un}map() should use a sg
+ * pointer in a mmc_data instead of host->sg_ptr.
+ */
+static void
+renesas_sdhi_internal_dmac_unmap(struct tmio_mmc_host *host,
+                                struct mmc_data *data,
+                                enum renesas_sdhi_dma_cookie cookie)
+{
+       bool unmap = cookie == COOKIE_UNMAPPED ? (data->host_cookie != cookie) :
+                                                (data->host_cookie == cookie);
+
+       if (unmap) {
+               dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
+                            mmc_get_dma_dir(data));
+               data->host_cookie = COOKIE_UNMAPPED;
+       }
+}
+
+static bool
+renesas_sdhi_internal_dmac_map(struct tmio_mmc_host *host,
+                              struct mmc_data *data,
+                              enum renesas_sdhi_dma_cookie cookie)
+{
+       if (data->host_cookie == COOKIE_PRE_MAPPED)
+               return true;
+
+       if (!dma_map_sg(&host->pdev->dev, data->sg, data->sg_len,
+                           mmc_get_dma_dir(data)))
+               return false;
+
+       data->host_cookie = cookie;
+
+       /* This DMAC cannot handle if buffer is not 128-bytes alignment */
+       if (!IS_ALIGNED(sg_dma_address(data->sg), 128)) {
+               renesas_sdhi_internal_dmac_unmap(host, data, cookie);
+               return false;
+       }
+
+       return true;
+}
+
 static void
 renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host,
                                     struct mmc_data *data)
        if (!test_bit(SDHI_INTERNAL_DMAC_ADDR_MODE_FIXED_ONLY, &global_flags))
                dtran_mode |= DTRAN_MODE_ADDR_MODE;
 
-       if (!dma_map_sg(&host->pdev->dev, sg, host->sg_len,
-                       mmc_get_dma_dir(data)))
+       if (!renesas_sdhi_internal_dmac_map(host, data, COOKIE_MAPPED))
                goto force_pio;
 
-       /* This DMAC cannot handle if buffer is not 128-bytes alignment */
-       if (!IS_ALIGNED(sg_dma_address(sg), 128))
-               goto force_pio_with_unmap;
-
        if (data->flags & MMC_DATA_READ) {
                dtran_mode |= DTRAN_MODE_CH_NUM_CH1;
                if (test_bit(SDHI_INTERNAL_DMAC_ONE_RX_ONLY, &global_flags) &&
        return;
 
 force_pio_with_unmap:
-       dma_unmap_sg(&host->pdev->dev, sg, host->sg_len, mmc_get_dma_dir(data));
+       renesas_sdhi_internal_dmac_unmap(host, data, COOKIE_UNMAPPED);
 
 force_pio:
        renesas_sdhi_internal_dmac_enable_dma(host, false);
                dir = DMA_TO_DEVICE;
 
        renesas_sdhi_internal_dmac_enable_dma(host, false);
-       dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->sg_len, dir);
+       renesas_sdhi_internal_dmac_unmap(host, host->data, COOKIE_MAPPED);
 
        if (dir == DMA_FROM_DEVICE)
                clear_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags);
                renesas_sdhi_internal_dmac_complete(host);
 }
 
+static void renesas_sdhi_internal_dmac_post_req(struct mmc_host *mmc,
+                                               struct mmc_request *mrq,
+                                               int err)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct mmc_data *data = mrq->data;
+
+       if (!data)
+               return;
+
+       renesas_sdhi_internal_dmac_unmap(host, data, COOKIE_UNMAPPED);
+}
+
+static void renesas_sdhi_internal_dmac_pre_req(struct mmc_host *mmc,
+                                              struct mmc_request *mrq)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct mmc_data *data = mrq->data;
+
+       if (!data)
+               return;
+
+       data->host_cookie = COOKIE_UNMAPPED;
+       renesas_sdhi_internal_dmac_map(host, data, COOKIE_PRE_MAPPED);
+}
+
 static void
 renesas_sdhi_internal_dmac_request_dma(struct tmio_mmc_host *host,
                                       struct tmio_mmc_data *pdata)
        tasklet_init(&host->dma_issue,
                     renesas_sdhi_internal_dmac_issue_tasklet_fn,
                     (unsigned long)host);
+
+       /* Add pre_req and post_req */
+       host->ops.pre_req = renesas_sdhi_internal_dmac_pre_req;
+       host->ops.post_req = renesas_sdhi_internal_dmac_post_req;
 }
 
 static void