aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/imxmmc.c
diff options
context:
space:
mode:
authorPavel Pisa <ppisa@pikron.com>2006-09-07 10:53:29 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-09-07 10:53:29 -0400
commit148f93d59cc9bb5e0f9a04d36a6f91d435e1a3f7 (patch)
tree1a413a79d37661199786f6fe2db3fe8bd7b5556a /drivers/mmc/imxmmc.c
parent385e3227d4d83ab13d7767c4bb3593b0256bf246 (diff)
[ARM] 3751/1: i.MX/MX1 SD/MMC use 512 bytes request for SCR read
Patch from Pavel Pisa This is another approach to SDHC deficiency workaround. It seems, that previous solution based on 16 bytes (FIFO length size) read is still timing sensitive on genirq and fully preemptive kernels. The new solution is backuped by M9328 UM statement, that only 512 byte block are working properly and by 2.4.26 FreeScale's SDHC code. Jay Monkman reports significant improvement on code based on this driver after applying this change on MX21 as well. Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/mmc/imxmmc.c')
-rw-r--r--drivers/mmc/imxmmc.c69
1 files changed, 35 insertions, 34 deletions
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index 7ca9e95bdf89..fb6565b98f32 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -91,6 +91,8 @@ struct imxmci_host {
91 int dma_allocated; 91 int dma_allocated;
92 92
93 unsigned char actual_bus_width; 93 unsigned char actual_bus_width;
94
95 int prev_cmd_code;
94}; 96};
95 97
96#define IMXMCI_PEND_IRQ_b 0 98#define IMXMCI_PEND_IRQ_b 0
@@ -248,16 +250,14 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
248 * partial FIFO fills and reads. The length has to be rounded up to burst size multiple. 250 * partial FIFO fills and reads. The length has to be rounded up to burst size multiple.
249 * This is required for SCR read at least. 251 * This is required for SCR read at least.
250 */ 252 */
251 if (datasz < 64) { 253 if (datasz < 512) {
252 host->dma_size = datasz; 254 host->dma_size = datasz;
253 if (data->flags & MMC_DATA_READ) { 255 if (data->flags & MMC_DATA_READ) {
254 host->dma_dir = DMA_FROM_DEVICE; 256 host->dma_dir = DMA_FROM_DEVICE;
255 257
256 /* Hack to enable read SCR */ 258 /* Hack to enable read SCR */
257 if(datasz < 16) { 259 MMC_NOB = 1;
258 MMC_NOB = 1; 260 MMC_BLK_LEN = 512;
259 MMC_BLK_LEN = 16;
260 }
261 } else { 261 } else {
262 host->dma_dir = DMA_TO_DEVICE; 262 host->dma_dir = DMA_TO_DEVICE;
263 } 263 }
@@ -409,6 +409,9 @@ static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request *
409 409
410 spin_unlock_irqrestore(&host->lock, flags); 410 spin_unlock_irqrestore(&host->lock, flags);
411 411
412 if(req && req->cmd)
413 host->prev_cmd_code = req->cmd->opcode;
414
412 host->req = NULL; 415 host->req = NULL;
413 host->cmd = NULL; 416 host->cmd = NULL;
414 host->data = NULL; 417 host->data = NULL;
@@ -553,7 +556,6 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
553{ 556{
554 int i; 557 int i;
555 int burst_len; 558 int burst_len;
556 int flush_len;
557 int trans_done = 0; 559 int trans_done = 0;
558 unsigned int stat = *pstat; 560 unsigned int stat = *pstat;
559 561
@@ -566,44 +568,43 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
566 dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n", 568 dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n",
567 stat); 569 stat);
568 570
571 udelay(20); /* required for clocks < 8MHz*/
572
569 if(host->dma_dir == DMA_FROM_DEVICE) { 573 if(host->dma_dir == DMA_FROM_DEVICE) {
570 imxmci_busy_wait_for_status(host, &stat, 574 imxmci_busy_wait_for_status(host, &stat,
571 STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE, 575 STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE,
572 20, "imxmci_cpu_driven_data read"); 576 50, "imxmci_cpu_driven_data read");
573 577
574 while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) && 578 while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) &&
575 (host->data_cnt < host->dma_size)) { 579 (host->data_cnt < 512)) {
576 if(burst_len >= host->dma_size - host->data_cnt) { 580
577 flush_len = burst_len; 581 udelay(20); /* required for clocks < 8MHz*/
578 burst_len = host->dma_size - host->data_cnt;
579 flush_len -= burst_len;
580 host->data_cnt = host->dma_size;
581 trans_done = 1;
582 } else {
583 flush_len = 0;
584 host->data_cnt += burst_len;
585 }
586 582
587 for(i = burst_len; i>=2 ; i-=2) { 583 for(i = burst_len; i>=2 ; i-=2) {
588 *(host->data_ptr++) = MMC_BUFFER_ACCESS; 584 u16 data;
589 udelay(20); /* required for clocks < 8MHz*/ 585 data = MMC_BUFFER_ACCESS;
586 udelay(10); /* required for clocks < 8MHz*/
587 if(host->data_cnt+2 <= host->dma_size) {
588 *(host->data_ptr++) = data;
589 } else {
590 if(host->data_cnt < host->dma_size)
591 *(u8*)(host->data_ptr) = data;
592 }
593 host->data_cnt += 2;
590 } 594 }
591 595
592 if(i == 1)
593 *(u8*)(host->data_ptr) = MMC_BUFFER_ACCESS;
594
595 stat = MMC_STATUS; 596 stat = MMC_STATUS;
596 597
597 /* Flush extra bytes from FIFO */ 598 dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read %d burst %d STATUS = 0x%x\n",
598 while(flush_len && !(stat & STATUS_DATA_TRANS_DONE)){ 599 host->data_cnt, burst_len, stat);
599 i = MMC_BUFFER_ACCESS;
600 stat = MMC_STATUS;
601 stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */
602 }
603
604 dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read burst %d STATUS = 0x%x\n",
605 burst_len, stat);
606 } 600 }
601
602 if((stat & STATUS_DATA_TRANS_DONE) && (host->data_cnt >= 512))
603 trans_done = 1;
604
605 if(host->dma_size & 0x1ff)
606 stat &= ~STATUS_CRC_READ_ERR;
607
607 } else { 608 } else {
608 imxmci_busy_wait_for_status(host, &stat, 609 imxmci_busy_wait_for_status(host, &stat,
609 STATUS_APPL_BUFF_FE, 610 STATUS_APPL_BUFF_FE,
@@ -692,8 +693,8 @@ static void imxmci_tasklet_fnc(unsigned long data)
692 what, stat, MMC_INT_MASK); 693 what, stat, MMC_INT_MASK);
693 dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n", 694 dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n",
694 MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma)); 695 MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma));
695 dev_err(mmc_dev(host->mmc), "CMD%d, bus %d-bit, dma_size = 0x%x\n", 696 dev_err(mmc_dev(host->mmc), "CMD%d, prevCMD%d, bus %d-bit, dma_size = 0x%x\n",
696 host->cmd?host->cmd->opcode:0, 1<<host->actual_bus_width, host->dma_size); 697 host->cmd?host->cmd->opcode:0, host->prev_cmd_code, 1<<host->actual_bus_width, host->dma_size);
697 } 698 }
698 699
699 if(!host->present || timeout) 700 if(!host->present || timeout)