diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2008-07-24 19:09:08 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2008-10-12 05:04:27 -0400 |
commit | e809517f6fa5803a5a1cd56026f0e2190fc13d5c (patch) | |
tree | c53f47a5e3704e7a4012e7dd26c6ce34333bc923 /drivers/mmc/host/sdhci.c | |
parent | 3fa8749e584b55f1180411ab1b51117190bac1e5 (diff) |
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>
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index e3a8133560a2..ef461274397b 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -1266,9 +1266,31 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
1266 | SDHCI_INT_INDEX)) | 1266 | SDHCI_INT_INDEX)) |
1267 | host->cmd->error = -EILSEQ; | 1267 | host->cmd->error = -EILSEQ; |
1268 | 1268 | ||
1269 | if (host->cmd->error) | 1269 | if (host->cmd->error) { |
1270 | tasklet_schedule(&host->finish_tasklet); | 1270 | tasklet_schedule(&host->finish_tasklet); |
1271 | else if (intmask & SDHCI_INT_RESPONSE) | 1271 | return; |
1272 | } | ||
1273 | |||
1274 | /* | ||
1275 | * The host can send and interrupt when the busy state has | ||
1276 | * ended, allowing us to wait without wasting CPU cycles. | ||
1277 | * Unfortunately this is overloaded on the "data complete" | ||
1278 | * interrupt, so we need to take some care when handling | ||
1279 | * it. | ||
1280 | * | ||
1281 | * Note: The 1.0 specification is a bit ambiguous about this | ||
1282 | * feature so there might be some problems with older | ||
1283 | * controllers. | ||
1284 | */ | ||
1285 | if (host->cmd->flags & MMC_RSP_BUSY) { | ||
1286 | if (host->cmd->data) | ||
1287 | DBG("Cannot wait for busy signal when also " | ||
1288 | "doing a data transfer"); | ||
1289 | else | ||
1290 | return; | ||
1291 | } | ||
1292 | |||
1293 | if (intmask & SDHCI_INT_RESPONSE) | ||
1272 | sdhci_finish_command(host); | 1294 | sdhci_finish_command(host); |
1273 | } | 1295 | } |
1274 | 1296 | ||
@@ -1278,11 +1300,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
1278 | 1300 | ||
1279 | if (!host->data) { | 1301 | if (!host->data) { |
1280 | /* | 1302 | /* |
1281 | * A data end interrupt is sent together with the response | 1303 | * The "data complete" interrupt is also used to |
1282 | * for the stop command. | 1304 | * indicate that a busy state has ended. See comment |
1305 | * above in sdhci_cmd_irq(). | ||
1283 | */ | 1306 | */ |
1284 | if (intmask & SDHCI_INT_DATA_END) | 1307 | if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { |
1285 | return; | 1308 | if (intmask & SDHCI_INT_DATA_END) { |
1309 | sdhci_finish_command(host); | ||
1310 | return; | ||
1311 | } | ||
1312 | } | ||
1286 | 1313 | ||
1287 | printk(KERN_ERR "%s: Got data interrupt 0x%08x even " | 1314 | printk(KERN_ERR "%s: Got data interrupt 0x%08x even " |
1288 | "though no data operation was in progress.\n", | 1315 | "though no data operation was in progress.\n", |