Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8de85d5 authored by Adrian Hunter's avatar Adrian Hunter Committed by Artem Bityutskiy
Browse files

[MTD] OneNAND: Implement read-while-load



Read-while-load enables higher performance read operations.

Signed-off-by: default avatarAdrian Hunter <ext-adrian.hunter@nokia.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
parent 2fd32d4a
Loading
Loading
Loading
Loading
+42 −32
Original line number Original line Diff line number Diff line
@@ -727,40 +727,47 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
	/* TODO handling oob */
	/* TODO handling oob */


	stats = mtd->ecc_stats;
	stats = mtd->ecc_stats;
	while (read < len) {
		cond_resched();


		thislen = min_t(int, mtd->writesize, len - read);
 	/* Read-while-load method */

		column = from & (mtd->writesize - 1);
		if (column + thislen > mtd->writesize)
			thislen = mtd->writesize - column;


 	/* Do first load to bufferRAM */
 	if (read < len) {
 		if (!onenand_check_bufferram(mtd, from)) {
 		if (!onenand_check_bufferram(mtd, from)) {
 			this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
 			this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);

 			ret = this->wait(mtd, FL_READING);
 			ret = this->wait(mtd, FL_READING);
			/* First copy data and check return value for ECC handling */
 			onenand_update_bufferram(mtd, from, !ret);
 			onenand_update_bufferram(mtd, from, !ret);
 		}
 		}
 	}


		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
 	thislen = min_t(int, mtd->writesize, len - read);
 	column = from & (mtd->writesize - 1);
 	if (column + thislen > mtd->writesize)
 		thislen = mtd->writesize - column;


		if (ret) {
 	while (!ret) {
			DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret);
 		/* If there is more to load then start next load */
			goto out;
 		from += thislen;
 		if (read + thislen < len) {
 			this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
 			ONENAND_SET_PREV_BUFFERRAM(this);
 		}
 		}

 		/* While load is going, read from last bufferRAM */
 		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
 		/* See if we are done */
 		read += thislen;
 		read += thislen;

 		if (read == len)
 		if (read == len)
 			break;
 			break;

 		/* Set up for next read from bufferRAM */
		from += thislen;
 		ONENAND_SET_NEXT_BUFFERRAM(this);
 		buf += thislen;
 		buf += thislen;
 		thislen = min_t(int, mtd->writesize, len - read);
 		column = 0;
 		cond_resched();
 		/* Now wait for load */
 		ret = this->wait(mtd, FL_READING);
 		onenand_update_bufferram(mtd, from, !ret);
 	}
 	}


out:
	/* Deselect and wake up anyone waiting on the device */
	/* Deselect and wake up anyone waiting on the device */
	onenand_release_device(mtd);
	onenand_release_device(mtd);


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


	if (ret)
		return ret;

	return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
	return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
}
}


+1 −0
Original line number Original line Diff line number Diff line
@@ -143,6 +143,7 @@ struct onenand_chip {
#define ONENAND_CURRENT_BUFFERRAM(this)		(this->bufferram_index)
#define ONENAND_CURRENT_BUFFERRAM(this)		(this->bufferram_index)
#define ONENAND_NEXT_BUFFERRAM(this)		(this->bufferram_index ^ 1)
#define ONENAND_NEXT_BUFFERRAM(this)		(this->bufferram_index ^ 1)
#define ONENAND_SET_NEXT_BUFFERRAM(this)	(this->bufferram_index ^= 1)
#define ONENAND_SET_NEXT_BUFFERRAM(this)	(this->bufferram_index ^= 1)
#define ONENAND_SET_PREV_BUFFERRAM(this)	(this->bufferram_index ^= 1)


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