aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci.c
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2008-07-04 18:25:15 -0400
committerPierre Ossman <drzeus@drzeus.cx>2008-07-15 08:14:39 -0400
commitee53ab5d73998e502801c024a08de2c39a92c52a (patch)
treebbee55e0cfffa4837918b7ada2f031f7dab3fcbb /drivers/mmc/host/sdhci.c
parent22606405894a3ca5796eb4454a4b83af611fd201 (diff)
sdhci: make workaround for timeout bug more general
Give the quirk for broken timeout handling a better chance of handling more controllers by simply classifying the system as broken and setting a fixed value. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r--drivers/mmc/host/sdhci.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 8ce01d434ea8..95b081a9967b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -314,23 +314,19 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
314 DBG("PIO transfer complete.\n"); 314 DBG("PIO transfer complete.\n");
315} 315}
316 316
317static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) 317static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
318{ 318{
319 u8 count; 319 u8 count;
320 unsigned target_timeout, current_timeout; 320 unsigned target_timeout, current_timeout;
321 321
322 WARN_ON(host->data); 322 /*
323 323 * If the host controller provides us with an incorrect timeout
324 if (data == NULL) 324 * value, just skip the check and use 0xE. The hardware may take
325 return; 325 * longer to time out, but that's much better than having a too-short
326 326 * timeout value.
327 /* Sanity checks */ 327 */
328 BUG_ON(data->blksz * data->blocks > 524288); 328 if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL))
329 BUG_ON(data->blksz > host->mmc->max_blk_size); 329 return 0xE;
330 BUG_ON(data->blocks > 65535);
331
332 host->data = data;
333 host->data_early = 0;
334 330
335 /* timeout in us */ 331 /* timeout in us */
336 target_timeout = data->timeout_ns / 1000 + 332 target_timeout = data->timeout_ns / 1000 +
@@ -355,19 +351,33 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
355 break; 351 break;
356 } 352 }
357 353
358 /*
359 * Compensate for an off-by-one error in the CaFe hardware; otherwise,
360 * a too-small count gives us interrupt timeouts.
361 */
362 if ((host->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL))
363 count++;
364
365 if (count >= 0xF) { 354 if (count >= 0xF) {
366 printk(KERN_WARNING "%s: Too large timeout requested!\n", 355 printk(KERN_WARNING "%s: Too large timeout requested!\n",
367 mmc_hostname(host->mmc)); 356 mmc_hostname(host->mmc));
368 count = 0xE; 357 count = 0xE;
369 } 358 }
370 359
360 return count;
361}
362
363static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
364{
365 u8 count;
366
367 WARN_ON(host->data);
368
369 if (data == NULL)
370 return;
371
372 /* Sanity checks */
373 BUG_ON(data->blksz * data->blocks > 524288);
374 BUG_ON(data->blksz > host->mmc->max_blk_size);
375 BUG_ON(data->blocks > 65535);
376
377 host->data = data;
378 host->data_early = 0;
379
380 count = sdhci_calc_timeout(host, data);
371 writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL); 381 writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
372 382
373 if (host->flags & SDHCI_USE_DMA) 383 if (host->flags & SDHCI_USE_DMA)