diff options
Diffstat (limited to 'drivers/mmc/imxmmc.c')
-rw-r--r-- | drivers/mmc/imxmmc.c | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index ffb7f55d3467..a4eb1d0e7a71 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c | |||
@@ -102,6 +102,7 @@ struct imxmci_host { | |||
102 | #define IMXMCI_PEND_CPU_DATA_b 5 | 102 | #define IMXMCI_PEND_CPU_DATA_b 5 |
103 | #define IMXMCI_PEND_CARD_XCHG_b 6 | 103 | #define IMXMCI_PEND_CARD_XCHG_b 6 |
104 | #define IMXMCI_PEND_SET_INIT_b 7 | 104 | #define IMXMCI_PEND_SET_INIT_b 7 |
105 | #define IMXMCI_PEND_STARTED_b 8 | ||
105 | 106 | ||
106 | #define IMXMCI_PEND_IRQ_m (1 << IMXMCI_PEND_IRQ_b) | 107 | #define IMXMCI_PEND_IRQ_m (1 << IMXMCI_PEND_IRQ_b) |
107 | #define IMXMCI_PEND_DMA_END_m (1 << IMXMCI_PEND_DMA_END_b) | 108 | #define IMXMCI_PEND_DMA_END_m (1 << IMXMCI_PEND_DMA_END_b) |
@@ -111,6 +112,7 @@ struct imxmci_host { | |||
111 | #define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b) | 112 | #define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b) |
112 | #define IMXMCI_PEND_CARD_XCHG_m (1 << IMXMCI_PEND_CARD_XCHG_b) | 113 | #define IMXMCI_PEND_CARD_XCHG_m (1 << IMXMCI_PEND_CARD_XCHG_b) |
113 | #define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b) | 114 | #define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b) |
115 | #define IMXMCI_PEND_STARTED_m (1 << IMXMCI_PEND_STARTED_b) | ||
114 | 116 | ||
115 | static void imxmci_stop_clock(struct imxmci_host *host) | 117 | static void imxmci_stop_clock(struct imxmci_host *host) |
116 | { | 118 | { |
@@ -131,23 +133,52 @@ static void imxmci_stop_clock(struct imxmci_host *host) | |||
131 | dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n"); | 133 | dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n"); |
132 | } | 134 | } |
133 | 135 | ||
134 | static void imxmci_start_clock(struct imxmci_host *host) | 136 | static int imxmci_start_clock(struct imxmci_host *host) |
135 | { | 137 | { |
136 | int i = 0; | 138 | unsigned int trials = 0; |
139 | unsigned int delay_limit = 128; | ||
140 | unsigned long flags; | ||
141 | |||
137 | MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK; | 142 | MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK; |
138 | while(i < 0x1000) { | ||
139 | if(!(i & 0x7f)) | ||
140 | MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK; | ||
141 | 143 | ||
142 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) { | 144 | clear_bit(IMXMCI_PEND_STARTED_b, &host->pending_events); |
143 | /* Check twice before cut */ | 145 | |
146 | /* | ||
147 | * Command start of the clock, this usually succeeds in less | ||
148 | * then 6 delay loops, but during card detection (low clockrate) | ||
149 | * it takes up to 5000 delay loops and sometimes fails for the first time | ||
150 | */ | ||
151 | MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK; | ||
152 | |||
153 | do { | ||
154 | unsigned int delay = delay_limit; | ||
155 | |||
156 | while(delay--){ | ||
144 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) | 157 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) |
145 | return; | 158 | /* Check twice before cut */ |
159 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) | ||
160 | return 0; | ||
161 | |||
162 | if(test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events)) | ||
163 | return 0; | ||
146 | } | 164 | } |
147 | 165 | ||
148 | i++; | 166 | local_irq_save(flags); |
149 | } | 167 | /* |
150 | dev_dbg(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n"); | 168 | * Ensure, that request is not doubled under all possible circumstances. |
169 | * It is possible, that cock running state is missed, because some other | ||
170 | * IRQ or schedule delays this function execution and the clocks has | ||
171 | * been already stopped by other means (response processing, SDHC HW) | ||
172 | */ | ||
173 | if(!test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events)) | ||
174 | MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK; | ||
175 | local_irq_restore(flags); | ||
176 | |||
177 | } while(++trials<256); | ||
178 | |||
179 | dev_err(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n"); | ||
180 | |||
181 | return -1; | ||
151 | } | 182 | } |
152 | 183 | ||
153 | static void imxmci_softreset(void) | 184 | static void imxmci_softreset(void) |
@@ -187,8 +218,10 @@ static int imxmci_busy_wait_for_status(struct imxmci_host *host, | |||
187 | if(!loops) | 218 | if(!loops) |
188 | return 0; | 219 | return 0; |
189 | 220 | ||
190 | dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n", | 221 | /* The busy-wait is expected there for clock <8MHz due to SDHC hardware flaws */ |
191 | loops, where, *pstat, stat_mask); | 222 | if(!(stat_mask & STATUS_END_CMD_RESP) || (host->mmc->ios.clock>=8000000)) |
223 | dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n", | ||
224 | loops, where, *pstat, stat_mask); | ||
192 | return loops; | 225 | return loops; |
193 | } | 226 | } |
194 | 227 | ||
@@ -302,6 +335,9 @@ static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, | |||
302 | WARN_ON(host->cmd != NULL); | 335 | WARN_ON(host->cmd != NULL); |
303 | host->cmd = cmd; | 336 | host->cmd = cmd; |
304 | 337 | ||
338 | /* Ensure, that clock are stopped else command programming and start fails */ | ||
339 | imxmci_stop_clock(host); | ||
340 | |||
305 | if (cmd->flags & MMC_RSP_BUSY) | 341 | if (cmd->flags & MMC_RSP_BUSY) |
306 | cmdat |= CMD_DAT_CONT_BUSY; | 342 | cmdat |= CMD_DAT_CONT_BUSY; |
307 | 343 | ||
@@ -498,7 +534,7 @@ static int imxmci_data_done(struct imxmci_host *host, unsigned int stat) | |||
498 | 534 | ||
499 | data_error = imxmci_finish_data(host, stat); | 535 | data_error = imxmci_finish_data(host, stat); |
500 | 536 | ||
501 | if (host->req->stop && (data_error == MMC_ERR_NONE)) { | 537 | if (host->req->stop) { |
502 | imxmci_stop_clock(host); | 538 | imxmci_stop_clock(host); |
503 | imxmci_start_cmd(host, host->req->stop, 0); | 539 | imxmci_start_cmd(host, host->req->stop, 0); |
504 | } else { | 540 | } else { |
@@ -522,7 +558,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) | |||
522 | int trans_done = 0; | 558 | int trans_done = 0; |
523 | unsigned int stat = *pstat; | 559 | unsigned int stat = *pstat; |
524 | 560 | ||
525 | if(host->actual_bus_width == MMC_BUS_WIDTH_4) | 561 | if(host->actual_bus_width != MMC_BUS_WIDTH_4) |
526 | burst_len = 16; | 562 | burst_len = 16; |
527 | else | 563 | else |
528 | burst_len = 64; | 564 | burst_len = 64; |
@@ -560,8 +596,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) | |||
560 | stat = MMC_STATUS; | 596 | stat = MMC_STATUS; |
561 | 597 | ||
562 | /* Flush extra bytes from FIFO */ | 598 | /* Flush extra bytes from FIFO */ |
563 | while(flush_len >= 2){ | 599 | while(flush_len && !(stat & STATUS_DATA_TRANS_DONE)){ |
564 | flush_len -= 2; | ||
565 | i = MMC_BUFFER_ACCESS; | 600 | i = MMC_BUFFER_ACCESS; |
566 | stat = MMC_STATUS; | 601 | stat = MMC_STATUS; |
567 | stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */ | 602 | stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */ |
@@ -622,6 +657,7 @@ static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs) | |||
622 | atomic_set(&host->stuck_timeout, 0); | 657 | atomic_set(&host->stuck_timeout, 0); |
623 | host->status_reg = stat; | 658 | host->status_reg = stat; |
624 | set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events); | 659 | set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events); |
660 | set_bit(IMXMCI_PEND_STARTED_b, &host->pending_events); | ||
625 | tasklet_schedule(&host->tasklet); | 661 | tasklet_schedule(&host->tasklet); |
626 | 662 | ||
627 | return IRQ_RETVAL(handled);; | 663 | return IRQ_RETVAL(handled);; |
@@ -714,10 +750,6 @@ static void imxmci_tasklet_fnc(unsigned long data) | |||
714 | data_dir_mask = STATUS_DATA_TRANS_DONE; | 750 | data_dir_mask = STATUS_DATA_TRANS_DONE; |
715 | } | 751 | } |
716 | 752 | ||
717 | imxmci_busy_wait_for_status(host, &stat, | ||
718 | data_dir_mask, | ||
719 | 50, "imxmci_tasklet_fnc data"); | ||
720 | |||
721 | if(stat & data_dir_mask) { | 753 | if(stat & data_dir_mask) { |
722 | clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events); | 754 | clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events); |
723 | imxmci_data_done(host, stat); | 755 | imxmci_data_done(host, stat); |
@@ -775,10 +807,6 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
775 | struct imxmci_host *host = mmc_priv(mmc); | 807 | struct imxmci_host *host = mmc_priv(mmc); |
776 | int prescaler; | 808 | int prescaler; |
777 | 809 | ||
778 | dev_dbg(mmc_dev(host->mmc), "clock %u power %u vdd %u width %u\n", | ||
779 | ios->clock, ios->power_mode, ios->vdd, | ||
780 | (ios->bus_width==MMC_BUS_WIDTH_4)?4:1); | ||
781 | |||
782 | if( ios->bus_width==MMC_BUS_WIDTH_4 ) { | 810 | if( ios->bus_width==MMC_BUS_WIDTH_4 ) { |
783 | host->actual_bus_width = MMC_BUS_WIDTH_4; | 811 | host->actual_bus_width = MMC_BUS_WIDTH_4; |
784 | imx_gpio_mode(PB11_PF_SD_DAT3); | 812 | imx_gpio_mode(PB11_PF_SD_DAT3); |
@@ -837,7 +865,11 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
837 | 865 | ||
838 | imxmci_stop_clock(host); | 866 | imxmci_stop_clock(host); |
839 | MMC_CLK_RATE = (prescaler<<3) | clk; | 867 | MMC_CLK_RATE = (prescaler<<3) | clk; |
840 | imxmci_start_clock(host); | 868 | /* |
869 | * Under my understanding, clock should not be started there, because it would | ||
870 | * initiate SDHC sequencer and send last or random command into card | ||
871 | */ | ||
872 | /*imxmci_start_clock(host);*/ | ||
841 | 873 | ||
842 | dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE); | 874 | dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE); |
843 | } else { | 875 | } else { |