diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/imxmmc.c | 69 |
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) |