This patch improves performance for filling the FIFO by rewriting in
assembly, and as a side-effect fixes odd-byte transfers.

Signed-off-by: Troy Kisky <[EMAIL PROTECTED]>
Signed-off-by: Bernard Blackham <[EMAIL PROTECTED]>

-- 
 drivers/mmc/host/davinci_mmc.c |   86 ++++++++++++++++++++++++++++++++-------
 drivers/mmc/host/davinci_mmc.h |    2 +-
 2 files changed, 71 insertions(+), 17 deletions(-)

Index: linux-davinci-2.6.24.git/drivers/mmc/host/davinci_mmc.c
===================================================================
--- linux-davinci-2.6.24.git.orig/drivers/mmc/host/davinci_mmc.c        
2008-02-16 12:07:53.000000000 +0900
+++ linux-davinci-2.6.24.git/drivers/mmc/host/davinci_mmc.c     2008-02-16 
13:06:38.000000000 +0900
@@ -62,7 +62,7 @@
 #define MULTIPILER_TO_HZ 1
 
 static struct mmcsd_config_def mmcsd_cfg = {
-/* read write thresholds (in bytes) can be any power of 2 from 2 to 64 */
+/* read write thresholds (in bytes) can be 16/32 */
        32,
 /* To use the DMA or not-- 1- Use DMA, 0-Interrupt mode */
        1,
@@ -215,7 +215,7 @@
                        && (cmd_type == DAVINCI_MMC_CMDTYPE_ADTC)
                        && (host->do_dma != 1))
                /* Fill the FIFO for Tx */
-               davinci_fifo_data_trans(host);
+               davinci_fifo_data_trans(host, 32);
 
        if (cmd->opcode == 7) {
                spin_lock_irqsave(&host->lock, flags);
@@ -247,9 +247,64 @@
        }
 }
 
-static void davinci_fifo_data_trans(struct mmc_davinci_host *host)
+
+#define DAVINCI_MMCSD_READ_FIFO(pDst, pRegs, cnt) asm( \
+       "       cmp     %3,#16\n" \
+       "1:     ldrhs   r0,[%1,%2]\n" \
+       "       ldrhs   r1,[%1,%2]\n" \
+       "       ldrhs   r2,[%1,%2]\n" \
+       "       ldrhs   r3,[%1,%2]\n" \
+       "       stmhsia %0!,{r0,r1,r2,r3}\n" \
+       "       beq     3f\n" \
+       "       subhs   %3,%3,#16\n" \
+       "       cmp     %3,#16\n" \
+       "       bhs     1b\n" \
+       "       tst     %3,#0x0c\n" \
+       "2:     ldrne   r0,[%1,%2]\n" \
+       "       strne   r0,[%0],#4\n" \
+       "       subne   %3,%3,#4\n" \
+       "       tst     %3,#0x0c\n" \
+       "       bne     2b\n" \
+       "       tst     %3,#2\n" \
+       "       ldrneh  r0,[%1,%2]\n" \
+       "       strneh  r0,[%0],#2\n" \
+       "       tst     %3,#1\n" \
+       "       ldrneb  r0,[%1,%2]\n" \
+       "       strneb  r0,[%0],#1\n" \
+       "3:\n" \
+        : "+r"(pDst) : "r"(pRegs), "i"(DAVINCI_MMCDRR), \
+        "r"(cnt) : "r0", "r1", "r2", "r3");
+
+#define DAVINCI_MMCSD_WRITE_FIFO(pDst, pRegs, cnt) asm( \
+       "       cmp     %3,#16\n" \
+       "1:     ldmhsia %0!,{r0,r1,r2,r3}\n" \
+       "       strhs   r0,[%1,%2]\n" \
+       "       strhs   r1,[%1,%2]\n" \
+       "       strhs   r2,[%1,%2]\n" \
+       "       strhs   r3,[%1,%2]\n" \
+       "       beq     3f\n" \
+       "       subhs   %3,%3,#16\n" \
+       "       cmp     %3,#16\n" \
+       "       bhs     1b\n" \
+       "       tst     %3,#0x0c\n" \
+       "2:     ldrne   r0,[%0],#4\n" \
+       "       strne   r0,[%1,%2]\n" \
+       "       subne   %3,%3,#4\n" \
+       "       tst     %3,#0x0c\n" \
+       "       bne     2b\n" \
+       "       tst     %3,#2\n" \
+       "       ldrneh  r0,[%0],#2\n" \
+       "       strneh  r0,[%1,%2]\n" \
+       "       tst     %3,#1\n" \
+       "       ldrneb  r0,[%0],#1\n" \
+       "       strneb  r0,[%1,%2]\n" \
+       "3:\n" \
+        : "+r"(pDst) : "r"(pRegs), "i"(DAVINCI_MMCDXR), \
+        "r"(cnt) : "r0", "r1", "r2", "r3");
+
+static void davinci_fifo_data_trans(struct mmc_davinci_host *host, int n)
 {
-       int n, i;
+       u8 *p;
 
        if (host->buffer_bytes_left == 0) {
                host->sg_idx++;
@@ -257,23 +312,18 @@
                mmc_davinci_sg_to_buf(host);
        }
 
-       n = mmcsd_cfg.rw_threshold;
+       p = host->buffer;
        if (n > host->buffer_bytes_left)
                n = host->buffer_bytes_left;
        host->buffer_bytes_left -= n;
        host->bytes_left -= n;
 
        if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
-               for (i = 0; i < (n / 4); i++) {
-                       writel(*host->buffer, host->base + DAVINCI_MMCDXR);
-                       host->buffer++;
-               }
+               DAVINCI_MMCSD_WRITE_FIFO(p, host->base, n);
        } else {
-               for (i = 0; i < (n / 4); i++) {
-                       *host->buffer = readl(host->base + DAVINCI_MMCDRR);
-                       host->buffer++;
-               }
+               DAVINCI_MMCSD_READ_FIFO(p, host->base, n);
        }
+       host->buffer = p;
 }
 
 static void davinci_reinit_chan(void)
@@ -905,7 +955,8 @@
                                if (status & MMCSD_EVENT_WRITE) {
                                        /* Buffer almost empty */
                                        if (host->bytes_left > 0)
-                                               davinci_fifo_data_trans(host);
+                                               davinci_fifo_data_trans(host,
+                                                       mmcsd_cfg.rw_threshold);
                                }
                        }
 
@@ -913,7 +964,8 @@
                                if (status & MMCSD_EVENT_READ) {
                                        /* Buffer almost empty */
                                        if (host->bytes_left > 0)
-                                               davinci_fifo_data_trans(host);
+                                               davinci_fifo_data_trans(host,
+                                                       mmcsd_cfg.rw_threshold);
                                }
                        }
 
@@ -927,7 +979,9 @@
                                                 * are generated */
                                                if (host->bytes_left > 0)
                                                        davinci_fifo_data_trans(
-                                                               host);
+                                                         host,
+                                                         mmcsd_cfg.rw_threshold
+                                                         );
                                                end_transfer = 1;
                                        }
                                } else {
Index: linux-davinci-2.6.24.git/drivers/mmc/host/davinci_mmc.h
===================================================================
--- linux-davinci-2.6.24.git.orig/drivers/mmc/host/davinci_mmc.h        
2008-02-16 12:07:53.000000000 +0900
+++ linux-davinci-2.6.24.git/drivers/mmc/host/davinci_mmc.h     2008-02-16 
12:08:23.000000000 +0900
@@ -246,7 +246,7 @@
 
 static void init_mmcsd_host(struct mmc_davinci_host *host);
 
-static void davinci_fifo_data_trans(struct mmc_davinci_host *host);
+static void davinci_fifo_data_trans(struct mmc_davinci_host *host, int n);
 
 static void mmc_davinci_sg_to_buf(struct mmc_davinci_host *host);
 
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to