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