aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/omap_hsmmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r--drivers/mmc/host/omap_hsmmc.c54
1 files changed, 30 insertions, 24 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 8d21a07f63de..a631c81dce12 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -376,6 +376,32 @@ static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
376} 376}
377#endif /* CONFIG_MMC_DEBUG */ 377#endif /* CONFIG_MMC_DEBUG */
378 378
379/*
380 * MMC controller internal state machines reset
381 *
382 * Used to reset command or data internal state machines, using respectively
383 * SRC or SRD bit of SYSCTL register
384 * Can be called from interrupt context
385 */
386static inline void mmc_omap_reset_controller_fsm(struct mmc_omap_host *host,
387 unsigned long bit)
388{
389 unsigned long i = 0;
390 unsigned long limit = (loops_per_jiffy *
391 msecs_to_jiffies(MMC_TIMEOUT_MS));
392
393 OMAP_HSMMC_WRITE(host->base, SYSCTL,
394 OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
395
396 while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) &&
397 (i++ < limit))
398 cpu_relax();
399
400 if (OMAP_HSMMC_READ(host->base, SYSCTL) & bit)
401 dev_err(mmc_dev(host->mmc),
402 "Timeout waiting on controller reset in %s\n",
403 __func__);
404}
379 405
380/* 406/*
381 * MMC controller IRQ handler 407 * MMC controller IRQ handler
@@ -404,13 +430,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
404 (status & CMD_CRC)) { 430 (status & CMD_CRC)) {
405 if (host->cmd) { 431 if (host->cmd) {
406 if (status & CMD_TIMEOUT) { 432 if (status & CMD_TIMEOUT) {
407 OMAP_HSMMC_WRITE(host->base, SYSCTL, 433 mmc_omap_reset_controller_fsm(host, SRC);
408 OMAP_HSMMC_READ(host->base,
409 SYSCTL) | SRC);
410 while (OMAP_HSMMC_READ(host->base,
411 SYSCTL) & SRC)
412 ;
413
414 host->cmd->error = -ETIMEDOUT; 434 host->cmd->error = -ETIMEDOUT;
415 } else { 435 } else {
416 host->cmd->error = -EILSEQ; 436 host->cmd->error = -EILSEQ;
@@ -419,12 +439,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
419 } 439 }
420 if (host->data) { 440 if (host->data) {
421 mmc_dma_cleanup(host); 441 mmc_dma_cleanup(host);
422 OMAP_HSMMC_WRITE(host->base, SYSCTL, 442 mmc_omap_reset_controller_fsm(host, SRD);
423 OMAP_HSMMC_READ(host->base,
424 SYSCTL) | SRD);
425 while (OMAP_HSMMC_READ(host->base,
426 SYSCTL) & SRD)
427 ;
428 } 443 }
429 } 444 }
430 if ((status & DATA_TIMEOUT) || 445 if ((status & DATA_TIMEOUT) ||
@@ -434,12 +449,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
434 mmc_dma_cleanup(host); 449 mmc_dma_cleanup(host);
435 else 450 else
436 host->data->error = -EILSEQ; 451 host->data->error = -EILSEQ;
437 OMAP_HSMMC_WRITE(host->base, SYSCTL, 452 mmc_omap_reset_controller_fsm(host, SRD);
438 OMAP_HSMMC_READ(host->base,
439 SYSCTL) | SRD);
440 while (OMAP_HSMMC_READ(host->base,
441 SYSCTL) & SRD)
442 ;
443 end_trans = 1; 453 end_trans = 1;
444 } 454 }
445 } 455 }
@@ -547,11 +557,7 @@ static void mmc_omap_detect(struct work_struct *work)
547 if (host->carddetect) { 557 if (host->carddetect) {
548 mmc_detect_change(host->mmc, (HZ * 200) / 1000); 558 mmc_detect_change(host->mmc, (HZ * 200) / 1000);
549 } else { 559 } else {
550 OMAP_HSMMC_WRITE(host->base, SYSCTL, 560 mmc_omap_reset_controller_fsm(host, SRD);
551 OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
552 while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
553 ;
554
555 mmc_detect_change(host->mmc, (HZ * 50) / 1000); 561 mmc_detect_change(host->mmc, (HZ * 50) / 1000);
556 } 562 }
557} 563}