davinci-mmc: speed up fifo access, fix initial fifo write, allow odd byte count
Signed-off-by: Troy Kisky <[EMAIL PROTECTED]> Note: this goes on top of previous patch diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 7fb8023..7459649 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -70,7 +70,7 @@ extern void davinci_clean_channel(int ch_no); struct device mmc_dev; struct clk *mmc_clkp = NULL; 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, @@ -281,7 +281,7 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, && (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(&mmc_lock, flags); @@ -314,9 +314,63 @@ static void mmc_davinci_dma_cb(int lch, u16 ch_status, void *data) } } -static void davinci_fifo_data_trans(struct mmc_davinci_host *host) + +#define ReadFifo(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"(offsetof(mmcsd_regs_base,mmc_drr)),"r"(cnt) : "r0","r1","r2","r3" ); + +#define WriteFifo(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"(offsetof(mmcsd_regs_base,mmc_dxr)),"r"(cnt) : "r0","r1","r2","r3" ); + + +static void davinci_fifo_data_trans(struct mmc_davinci_host *host, int n) { - int n, i; + unsigned int * p; if (host->buffer_bytes_left == 0) { host->sg_idx++; @@ -324,23 +378,18 @@ static void davinci_fifo_data_trans(struct mmc_davinci_host *host) 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++) { - mmcsd_regs->mmc_dxr = *host->buffer; - host->buffer++; - } + WriteFifo(p,mmcsd_regs,n); } else { - for (i = 0; i < (n / 4); i++) { - *host->buffer = mmcsd_regs->mmc_drr; - host->buffer++; - } + ReadFifo(p,mmcsd_regs,n); } + host->buffer = p; } static void davinci_reinit_chan(void) @@ -936,7 +985,7 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) 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); } } @@ -944,7 +993,7 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) 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); } } @@ -957,7 +1006,7 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) /* if datasize<32 no RX ints are generated */ if (host->bytes_left > 0) { davinci_fifo_data_trans - (host); + (host,mmcsd_cfg.rw_threshold); } end_transfer = 1; } diff --git a/drivers/mmc/host/davinci_mmc.h b/drivers/mmc/host/davinci_mmc.h index 5840ccf..446191e 100644 --- a/drivers/mmc/host/davinci_mmc.h +++ b/drivers/mmc/host/davinci_mmc.h @@ -177,7 +177,7 @@ typedef enum { static void init_mmcsd_host(void); -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 Davinci-linux-open-source@linux.davincidsp.com http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source