diff options
Diffstat (limited to 'drivers/mtd/onenand')
-rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 74 |
1 files changed, 42 insertions, 32 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index e80857b3bb83..abbe160b4309 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -727,40 +727,47 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
727 | /* TODO handling oob */ | 727 | /* TODO handling oob */ |
728 | 728 | ||
729 | stats = mtd->ecc_stats; | 729 | stats = mtd->ecc_stats; |
730 | while (read < len) { | ||
731 | cond_resched(); | ||
732 | |||
733 | thislen = min_t(int, mtd->writesize, len - read); | ||
734 | |||
735 | column = from & (mtd->writesize - 1); | ||
736 | if (column + thislen > mtd->writesize) | ||
737 | thislen = mtd->writesize - column; | ||
738 | |||
739 | if (!onenand_check_bufferram(mtd, from)) { | ||
740 | this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize); | ||
741 | |||
742 | ret = this->wait(mtd, FL_READING); | ||
743 | /* First copy data and check return value for ECC handling */ | ||
744 | onenand_update_bufferram(mtd, from, !ret); | ||
745 | } | ||
746 | |||
747 | this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); | ||
748 | 730 | ||
749 | if (ret) { | 731 | /* Read-while-load method */ |
750 | DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret); | 732 | |
751 | goto out; | 733 | /* Do first load to bufferRAM */ |
752 | } | 734 | if (read < len) { |
735 | if (!onenand_check_bufferram(mtd, from)) { | ||
736 | this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize); | ||
737 | ret = this->wait(mtd, FL_READING); | ||
738 | onenand_update_bufferram(mtd, from, !ret); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | thislen = min_t(int, mtd->writesize, len - read); | ||
743 | column = from & (mtd->writesize - 1); | ||
744 | if (column + thislen > mtd->writesize) | ||
745 | thislen = mtd->writesize - column; | ||
746 | |||
747 | while (!ret) { | ||
748 | /* If there is more to load then start next load */ | ||
749 | from += thislen; | ||
750 | if (read + thislen < len) { | ||
751 | this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize); | ||
752 | ONENAND_SET_PREV_BUFFERRAM(this); | ||
753 | } | ||
754 | /* While load is going, read from last bufferRAM */ | ||
755 | this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); | ||
756 | /* See if we are done */ | ||
757 | read += thislen; | ||
758 | if (read == len) | ||
759 | break; | ||
760 | /* Set up for next read from bufferRAM */ | ||
761 | ONENAND_SET_NEXT_BUFFERRAM(this); | ||
762 | buf += thislen; | ||
763 | thislen = min_t(int, mtd->writesize, len - read); | ||
764 | column = 0; | ||
765 | cond_resched(); | ||
766 | /* Now wait for load */ | ||
767 | ret = this->wait(mtd, FL_READING); | ||
768 | onenand_update_bufferram(mtd, from, !ret); | ||
769 | } | ||
753 | 770 | ||
754 | read += thislen; | ||
755 | |||
756 | if (read == len) | ||
757 | break; | ||
758 | |||
759 | from += thislen; | ||
760 | buf += thislen; | ||
761 | } | ||
762 | |||
763 | out: | ||
764 | /* Deselect and wake up anyone waiting on the device */ | 771 | /* Deselect and wake up anyone waiting on the device */ |
765 | onenand_release_device(mtd); | 772 | onenand_release_device(mtd); |
766 | 773 | ||
@@ -774,6 +781,9 @@ out: | |||
774 | if (mtd->ecc_stats.failed - stats.failed) | 781 | if (mtd->ecc_stats.failed - stats.failed) |
775 | return -EBADMSG; | 782 | return -EBADMSG; |
776 | 783 | ||
784 | if (ret) | ||
785 | return ret; | ||
786 | |||
777 | return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; | 787 | return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; |
778 | } | 788 | } |
779 | 789 | ||