sdhci: let the controller wait for busy state to end

The sdhci controllers can interrupt us when the busy state from the
card has ended, saving CPU cycles and power.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
This commit is contained in:
Pierre Ossman 2008-07-25 01:09:08 +02:00
parent 3fa8749e58
commit e809517f6f

View file

@ -1266,9 +1266,31 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
SDHCI_INT_INDEX)) SDHCI_INT_INDEX))
host->cmd->error = -EILSEQ; host->cmd->error = -EILSEQ;
if (host->cmd->error) if (host->cmd->error) {
tasklet_schedule(&host->finish_tasklet); tasklet_schedule(&host->finish_tasklet);
else if (intmask & SDHCI_INT_RESPONSE) 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
return;
}
if (intmask & SDHCI_INT_RESPONSE)
sdhci_finish_command(host); sdhci_finish_command(host);
} }
@ -1278,11 +1300,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
if (!host->data) { if (!host->data) {
/* /*
* A data end interrupt is sent together with the response * The "data complete" interrupt is also used to
* for the stop command. * indicate that a busy state has ended. See comment
* above in sdhci_cmd_irq().
*/ */
if (intmask & SDHCI_INT_DATA_END) if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) {
return; if (intmask & SDHCI_INT_DATA_END) {
sdhci_finish_command(host);
return;
}
}
printk(KERN_ERR "%s: Got data interrupt 0x%08x even " printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
"though no data operation was in progress.\n", "though no data operation was in progress.\n",