diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index e3a8133560a2..30f64b1f2354 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -177,7 +177,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) | |||
177 | { | 177 | { |
178 | unsigned long flags; | 178 | unsigned long flags; |
179 | size_t blksize, len, chunk; | 179 | size_t blksize, len, chunk; |
180 | u32 scratch; | 180 | u32 uninitialized_var(scratch); |
181 | u8 *buf; | 181 | u8 *buf; |
182 | 182 | ||
183 | DBG("PIO reading\n"); | 183 | DBG("PIO reading\n"); |
@@ -1154,7 +1154,7 @@ static void sdhci_tasklet_card(unsigned long param) | |||
1154 | 1154 | ||
1155 | spin_unlock_irqrestore(&host->lock, flags); | 1155 | spin_unlock_irqrestore(&host->lock, flags); |
1156 | 1156 | ||
1157 | mmc_detect_change(host->mmc, msecs_to_jiffies(500)); | 1157 | mmc_detect_change(host->mmc, msecs_to_jiffies(200)); |
1158 | } | 1158 | } |
1159 | 1159 | ||
1160 | static void sdhci_tasklet_finish(unsigned long param) | 1160 | static void sdhci_tasklet_finish(unsigned long param) |
@@ -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", |
@@ -1604,7 +1631,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1604 | mmc->f_max = host->max_clk; | 1631 | mmc->f_max = host->max_clk; |
1605 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | 1632 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; |
1606 | 1633 | ||
1607 | if (caps & SDHCI_CAN_DO_HISPD) | 1634 | if ((caps & SDHCI_CAN_DO_HISPD) || |
1635 | (host->quirks & SDHCI_QUIRK_FORCE_HIGHSPEED)) | ||
1608 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; | 1636 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; |
1609 | 1637 | ||
1610 | mmc->ocr_avail = 0; | 1638 | mmc->ocr_avail = 0; |