aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci.c
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2008-10-13 12:13:56 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2008-10-13 12:13:56 -0400
commite758936e02700ff88a0b08b722a3847b95283ef2 (patch)
tree50c919bef1b459a778b85159d5929de95b6c4a01 /drivers/mmc/host/sdhci.c
parent239cfbde1f5843c4a24199f117d5f67f637d72d5 (diff)
parent4480f15b3306f43bbb0310d461142b4e897ca45b (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: include/asm-x86/statfs.h
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r--drivers/mmc/host/sdhci.c46
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
1160static void sdhci_tasklet_finish(unsigned long param) 1160static 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;