summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/sdhci.c54
1 files changed, 26 insertions, 28 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 44cdb6d035f2..9ca4253b0ab7 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -45,7 +45,6 @@ static unsigned int debug_quirks2;
static void sdhci_finish_data(struct sdhci_host *);
-static void sdhci_finish_command(struct sdhci_host *);
static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
static void sdhci_dumpregs(struct sdhci_host *host)
@@ -1079,6 +1078,28 @@ static void sdhci_finish_command(struct sdhci_host *host)
}
}
+ /*
+ * The host can send and interrupt when the busy state has
+ * ended, allowing us to wait without wasting CPU cycles.
+ * The busy signal uses DAT0 so this is similar to waiting
+ * for data to complete.
+ *
+ * Note: The 1.0 specification is a bit ambiguous about this
+ * feature so there might be some problems with older
+ * controllers.
+ */
+ if (host->cmd->flags & MMC_RSP_BUSY) {
+ if (host->cmd->data) {
+ DBG("Cannot wait for busy signal when also doing a data transfer");
+ } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
+ !host->busy_handle) {
+ /* Mark that command complete before busy is ended */
+ host->busy_handle = 1;
+ host->cmd = NULL;
+ return;
+ }
+ }
+
/* Finished CMD23, now send actual command. */
if (host->cmd == host->mrq->sbc) {
host->cmd = NULL;
@@ -2295,33 +2316,10 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
return;
}
- /*
- * The host can send and interrupt when the busy state has
- * ended, allowing us to wait without wasting CPU cycles.
- * Unfortunately this is overloaded on the "data complete"
- * interrupt, so we need to take some care when handling
- * it.
- *
- * Note: The 1.0 specification is a bit ambiguous about this
- * feature so there might be some problems with older
- * controllers.
- */
- if (host->cmd->flags & MMC_RSP_BUSY) {
- if (host->cmd->data)
- DBG("Cannot wait for busy signal when also doing a data transfer");
- else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)
- && !host->busy_handle) {
- /* Mark that command complete before busy is ended */
- host->busy_handle = 1;
- return;
- }
-
- /* The controller does not support the end-of-busy IRQ,
- * fall through and take the SDHCI_INT_RESPONSE */
- } else if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) &&
- host->cmd->opcode == MMC_STOP_TRANSMISSION && !host->data) {
+ if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) &&
+ !(host->cmd->flags & MMC_RSP_BUSY) && !host->data &&
+ host->cmd->opcode == MMC_STOP_TRANSMISSION)
*mask &= ~SDHCI_INT_DATA_END;
- }
if (intmask & SDHCI_INT_RESPONSE)
sdhci_finish_command(host);
@@ -2395,7 +2393,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
* sure we do things in the proper order.
*/
if (host->busy_handle)
- sdhci_finish_command(host);
+ tasklet_schedule(&host->finish_tasklet);
else
host->busy_handle = 1;
return;