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