aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci.c
diff options
context:
space:
mode:
authorChanho Min <chanho.min@lge.com>2014-08-29 23:40:40 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2014-09-09 07:59:23 -0400
commite99783a45220a2c5f5a598e0e81213ecf2dbcf2f (patch)
tree5e75b56488d2ab0da687cb17d1b93554f2565549 /drivers/mmc/host/sdhci.c
parent0b10f478d2ad93b3808d018327465aaab77c8d2b (diff)
mmc: sdhci: handle busy-end interrupt during command
It is fully legal for a controller to start handling busy-end interrupt before it has signaled that the command has completed. So make sure we do things in the proper order, Or it results that command interrupt is ignored so it can cause unexpected operations. This is founded at some toshiba emmc with the bellow warning. "mmc0: Got command interrupt 0x00000001 even though no command operation was in progress." This issue has been also reported by Youssef TRIKI: It is not specific to Toshiba devices, and happens with eMMC devices as well as SD card which support Auto-CMD12 rather than CMD23. Also, similar patch is submitted by: Gwendal Grignou <gwendal@chromium.org> Changes since v1: Fixed conflict with the next of git.linaro.org/people/ulf.hansson/mmc.git and Tested if issue is fixed again. Signed-off-by: Hankyung Yu <hankyung.yu@lge.com> Signed-off-by: Chanho Min <chanho.min@lge.com> Tested-by: Youssef TRIKI <youssef.triki@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r--drivers/mmc/host/sdhci.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index b5e22b8c4885..335cdf3b5224 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1016,6 +1016,7 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
1016 mod_timer(&host->timer, timeout); 1016 mod_timer(&host->timer, timeout);
1017 1017
1018 host->cmd = cmd; 1018 host->cmd = cmd;
1019 host->busy_handle = 0;
1019 1020
1020 sdhci_prepare_data(host, cmd); 1021 sdhci_prepare_data(host, cmd);
1021 1022
@@ -2261,8 +2262,12 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
2261 if (host->cmd->data) 2262 if (host->cmd->data)
2262 DBG("Cannot wait for busy signal when also " 2263 DBG("Cannot wait for busy signal when also "
2263 "doing a data transfer"); 2264 "doing a data transfer");
2264 else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) 2265 else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)
2266 && !host->busy_handle) {
2267 /* Mark that command complete before busy is ended */
2268 host->busy_handle = 1;
2265 return; 2269 return;
2270 }
2266 2271
2267 /* The controller does not support the end-of-busy IRQ, 2272 /* The controller does not support the end-of-busy IRQ,
2268 * fall through and take the SDHCI_INT_RESPONSE */ 2273 * fall through and take the SDHCI_INT_RESPONSE */
@@ -2330,7 +2335,15 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
2330 return; 2335 return;
2331 } 2336 }
2332 if (intmask & SDHCI_INT_DATA_END) { 2337 if (intmask & SDHCI_INT_DATA_END) {
2333 sdhci_finish_command(host); 2338 /*
2339 * Some cards handle busy-end interrupt
2340 * before the command completed, so make
2341 * sure we do things in the proper order.
2342 */
2343 if (host->busy_handle)
2344 sdhci_finish_command(host);
2345 else
2346 host->busy_handle = 1;
2334 return; 2347 return;
2335 } 2348 }
2336 } 2349 }