diff options
| -rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 74 | ||||
| -rw-r--r-- | include/linux/mtd/onenand.h | 1 |
2 files changed, 43 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 | ||
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index fe3500d7d4bb..f775a7af3890 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h | |||
| @@ -143,6 +143,7 @@ struct onenand_chip { | |||
| 143 | #define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) | 143 | #define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) |
| 144 | #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) | 144 | #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) |
| 145 | #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) | 145 | #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) |
| 146 | #define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1) | ||
| 146 | 147 | ||
| 147 | #define ONENAND_GET_SYS_CFG1(this) \ | 148 | #define ONENAND_GET_SYS_CFG1(this) \ |
| 148 | (this->read_word(this->base + ONENAND_REG_SYS_CFG1)) | 149 | (this->read_word(this->base + ONENAND_REG_SYS_CFG1)) |
