diff options
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 54 |
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 | */ | ||
386 | static 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 | } |