Skip to content

Commit a8de85d

Browse files
Adrian Hunterdedekind
authored andcommitted
[MTD] OneNAND: Implement read-while-load
Read-while-load enables higher performance read operations. Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
1 parent 2fd32d4 commit a8de85d

2 files changed

Lines changed: 43 additions & 32 deletions

File tree

drivers/mtd/onenand/onenand_base.c

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -727,40 +727,47 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
727727
/* TODO handling oob */
728728

729729
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);
748730

749-
if (ret) {
750-
DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret);
751-
goto out;
752-
}
731+
/* Read-while-load method */
732+
733+
/* Do first load to bufferRAM */
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+
}
753770

754-
read += thislen;
755-
756-
if (read == len)
757-
break;
758-
759-
from += thislen;
760-
buf += thislen;
761-
}
762-
763-
out:
764771
/* Deselect and wake up anyone waiting on the device */
765772
onenand_release_device(mtd);
766773

@@ -774,6 +781,9 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
774781
if (mtd->ecc_stats.failed - stats.failed)
775782
return -EBADMSG;
776783

784+
if (ret)
785+
return ret;
786+
777787
return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
778788
}
779789

include/linux/mtd/onenand.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ struct onenand_chip {
143143
#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index)
144144
#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
145145
#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
146+
#define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)
146147

147148
#define ONENAND_GET_SYS_CFG1(this) \
148149
(this->read_word(this->base + ONENAND_REG_SYS_CFG1))

0 commit comments

Comments
 (0)