diff options
-rw-r--r-- | drivers/mmc/host/mmc_spi.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 69e1442ff2e2..72f8bde4877a 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -612,6 +612,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, | |||
612 | struct spi_device *spi = host->spi; | 612 | struct spi_device *spi = host->spi; |
613 | int status, i; | 613 | int status, i; |
614 | struct scratch *scratch = host->data; | 614 | struct scratch *scratch = host->data; |
615 | u32 pattern; | ||
615 | 616 | ||
616 | if (host->mmc->use_spi_crc) | 617 | if (host->mmc->use_spi_crc) |
617 | scratch->crc_val = cpu_to_be16( | 618 | scratch->crc_val = cpu_to_be16( |
@@ -639,8 +640,27 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, | |||
639 | * doesn't necessarily tell whether the write operation succeeded; | 640 | * doesn't necessarily tell whether the write operation succeeded; |
640 | * it just says if the transmission was ok and whether *earlier* | 641 | * it just says if the transmission was ok and whether *earlier* |
641 | * writes succeeded; see the standard. | 642 | * writes succeeded; see the standard. |
643 | * | ||
644 | * In practice, there are (even modern SDHC-)cards which are late | ||
645 | * in sending the response, and miss the time frame by a few bits, | ||
646 | * so we have to cope with this situation and check the response | ||
647 | * bit-by-bit. Arggh!!! | ||
642 | */ | 648 | */ |
643 | switch (SPI_MMC_RESPONSE_CODE(scratch->status[0])) { | 649 | pattern = scratch->status[0] << 24; |
650 | pattern |= scratch->status[1] << 16; | ||
651 | pattern |= scratch->status[2] << 8; | ||
652 | pattern |= scratch->status[3]; | ||
653 | |||
654 | /* First 3 bit of pattern are undefined */ | ||
655 | pattern |= 0xE0000000; | ||
656 | |||
657 | /* left-adjust to leading 0 bit */ | ||
658 | while (pattern & 0x80000000) | ||
659 | pattern <<= 1; | ||
660 | /* right-adjust for pattern matching. Code is in bit 4..0 now. */ | ||
661 | pattern >>= 27; | ||
662 | |||
663 | switch (pattern) { | ||
644 | case SPI_RESPONSE_ACCEPTED: | 664 | case SPI_RESPONSE_ACCEPTED: |
645 | status = 0; | 665 | status = 0; |
646 | break; | 666 | break; |
@@ -671,8 +691,9 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, | |||
671 | /* Return when not busy. If we didn't collect that status yet, | 691 | /* Return when not busy. If we didn't collect that status yet, |
672 | * we'll need some more I/O. | 692 | * we'll need some more I/O. |
673 | */ | 693 | */ |
674 | for (i = 1; i < sizeof(scratch->status); i++) { | 694 | for (i = 4; i < sizeof(scratch->status); i++) { |
675 | if (scratch->status[i] != 0) | 695 | /* card is non-busy if the most recent bit is 1 */ |
696 | if (scratch->status[i] & 0x01) | ||
676 | return 0; | 697 | return 0; |
677 | } | 698 | } |
678 | return mmc_spi_wait_unbusy(host, timeout); | 699 | return mmc_spi_wait_unbusy(host, timeout); |