mmc/dwmmc: use bounce buffer for data exchange between CPU and MMC controller
authorAlexey Brodkin <Alexey.Brodkin@synopsys.com>
Thu, 26 Dec 2013 11:29:07 +0000 (15:29 +0400)
committerPantelis Antoniou <panto@antoniou-consulting.com>
Thu, 9 Jan 2014 09:29:02 +0000 (11:29 +0200)
Bounce buffer implementation takes care of proper data buffer alignemt
and correct flush/invalidation of data cache at once so we no longer
depend on input data variety and make sure CPU and MMC controller deal
with expected data in case of enabled data cache.

Bounce buffer requires to add its definition (CONFIG_BOUNCE_BUFFER) in
board configuration, otherwise corresponding library won't be compiled
and linker will fail to build resulting executable.

Difference since v1 - fixed compile-time warning with type casting to
"void *":

Slight edit to remove UTF8 characters in the commit message.

Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
Tested-by: Jaehoon Chung <jh80.chung@samsung.com>
Acked-by: Pantelis Antoniou <panto@antoniou-consulting.com>
====
passing argument 2 of 'bounce_buffer_start' discards 'const' qualifier
from pointer target type
====

Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Mischa Jonker <mjonker@synopsys.com>
Cc: Alim Akhtar <alim.akhtar@samsung.com>
Cc: Rajeshwari Shinde <rajeshwari.s@samsung.com>
Cc: Jaehoon Chung <jh80.chung@samsung.com>
Cc: Amar <amarendra.xt@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Minkyu Kang <mk7.kang@samsung.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
Cc: Andy Fleming <afleming@gmail.com>
drivers/mmc/dw_mmc.c
include/configs/arndale.h
include/configs/exynos5250-dt.h

index 82abe19eabaa5e2b44a8f35e4a558dfe57e7f7e6..4cec5aaa604b0fdba8bedbfed149e2405a6e7ded 100755 (executable)
@@ -6,6 +6,7 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
+#include <bouncebuf.h>
 #include <common.h>
 #include <malloc.h>
 #include <mmc.h>
@@ -41,11 +42,13 @@ static void dwmci_set_idma_desc(struct dwmci_idmac *idmac,
 }
 
 static void dwmci_prepare_data(struct dwmci_host *host,
-               struct mmc_data *data, struct dwmci_idmac *cur_idmac)
+                              struct mmc_data *data,
+                              struct dwmci_idmac *cur_idmac,
+                              void *bounce_buffer)
 {
        unsigned long ctrl;
        unsigned int i = 0, flags, cnt, blk_cnt;
-       ulong data_start, data_end, start_addr;
+       ulong data_start, data_end;
 
 
        blk_cnt = data->blocks;
@@ -55,11 +58,6 @@ static void dwmci_prepare_data(struct dwmci_host *host,
        data_start = (ulong)cur_idmac;
        dwmci_writel(host, DWMCI_DBADDR, (unsigned int)cur_idmac);
 
-       if (data->flags == MMC_DATA_READ)
-               start_addr = (unsigned int)data->dest;
-       else
-               start_addr = (unsigned int)data->src;
-
        do {
                flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH ;
                flags |= (i == 0) ? DWMCI_IDMAC_FS : 0;
@@ -70,7 +68,7 @@ static void dwmci_prepare_data(struct dwmci_host *host,
                        cnt = data->blocksize * 8;
 
                dwmci_set_idma_desc(cur_idmac, flags, cnt,
-                               start_addr + (i * PAGE_SIZE));
+                                   (u32)bounce_buffer + (i * PAGE_SIZE));
 
                if (blk_cnt <= 8)
                        break;
@@ -117,6 +115,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        u32 retry = 10000;
        u32 mask, ctrl;
        ulong start = get_timer(0);
+       struct bounce_buffer bbstate;
 
        while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
                if (get_timer(start) > timeout) {
@@ -127,8 +126,19 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 
        dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
 
-       if (data)
-               dwmci_prepare_data(host, data, cur_idmac);
+       if (data) {
+               if (data->flags == MMC_DATA_READ) {
+                       bounce_buffer_start(&bbstate, (void*)data->dest,
+                                           data->blocksize *
+                                           data->blocks, GEN_BB_WRITE);
+               } else {
+                       bounce_buffer_start(&bbstate, (void*)data->src,
+                                           data->blocksize *
+                                           data->blocks, GEN_BB_READ);
+               }
+               dwmci_prepare_data(host, data, cur_idmac,
+                                  bbstate.bounce_buffer);
+       }
 
        dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
@@ -204,6 +214,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
                ctrl = dwmci_readl(host, DWMCI_CTRL);
                ctrl &= ~(DWMCI_DMA_EN);
                dwmci_writel(host, DWMCI_CTRL, ctrl);
+
+               bounce_buffer_stop(&bbstate);
        }
 
        udelay(100);
index a3cb56b8bf2de3690f45c265257344ab2b36146f..3d29caf4c5e31d72ebe9a72467efc19a7be59e1a 100644 (file)
@@ -85,6 +85,7 @@
 #define CONFIG_DWMMC
 #define CONFIG_EXYNOS_DWMMC
 #define CONFIG_SUPPORT_EMMC_BOOT
+#define CONFIG_BOUNCE_BUFFER
 
 
 #define CONFIG_BOARD_EARLY_INIT_F
index 8fb904cddf45f12e4f48ff40a2d9b740a8e18666..b39bafca3e089f779c03725158c1ba0c4368c162 100644 (file)
 #define CONFIG_DWMMC
 #define CONFIG_EXYNOS_DWMMC
 #define CONFIG_SUPPORT_EMMC_BOOT
+#define CONFIG_BOUNCE_BUFFER
 
 
 #define CONFIG_BOARD_EARLY_INIT_F