sunxi: add support for 4.1
Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu> SVN-Revision: 46571
This commit is contained in:
		@@ -0,0 +1,851 @@
 | 
			
		||||
From 293984c7f167a08285596ef2166d8ab9cb571778 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Boris BREZILLON <boris.brezillon@free-electrons.com>
 | 
			
		||||
Date: Mon, 28 Jul 2014 14:46:26 +0200
 | 
			
		||||
Subject: [PATCH] mtd: nand: Introduce a randomizer layer in the NAND framework
 | 
			
		||||
 | 
			
		||||
This patch introduce a new layer in the NAND framework to support both HW
 | 
			
		||||
and SW randomizers.
 | 
			
		||||
 | 
			
		||||
This randomization is required on some MLC/TLC NAND chips which do not
 | 
			
		||||
support large islands of same patterns.
 | 
			
		||||
 | 
			
		||||
The randomizer layer defines a nand_rnd_ctrl struct which is intended to
 | 
			
		||||
be used by NAND core functions or NAND drivers to randomize/derandomize
 | 
			
		||||
data stored on NAND chips.
 | 
			
		||||
 | 
			
		||||
The implementation can implement any of these functions:
 | 
			
		||||
- config: prepare a random transfer to/from the NAND chip
 | 
			
		||||
- write_buf: randomize and write data to the NAND chip
 | 
			
		||||
- read_buf: read and derandomize data from the NAND chip
 | 
			
		||||
 | 
			
		||||
read/write_buf functions are always called after a config call.
 | 
			
		||||
The config call specify the page, the column within the page and the action
 | 
			
		||||
that will take place after the config (either read or write).
 | 
			
		||||
If column is set to -1, the randomizer is disabled.
 | 
			
		||||
If page is set to -1, we keep working on the same page.
 | 
			
		||||
 | 
			
		||||
The randomizer layer provides helper functions that choose wether the
 | 
			
		||||
randomizer or the chip read/write_buf should be used.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
 | 
			
		||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/mtd/nand/nand_base.c | 278 ++++++++++++++++++++++++++++++++++---------
 | 
			
		||||
 include/linux/mtd/nand.h     |  98 +++++++++++++++
 | 
			
		||||
 2 files changed, 321 insertions(+), 55 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
 | 
			
		||||
index 8a5d12e..577cb9e 100644
 | 
			
		||||
--- a/drivers/mtd/nand/nand_base.c
 | 
			
		||||
+++ b/drivers/mtd/nand/nand_base.c
 | 
			
		||||
@@ -1102,6 +1102,62 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 | 
			
		||||
 EXPORT_SYMBOL(nand_lock);
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
+ * nand_rnd_is_activ - check wether a region of a NAND page requires NAND
 | 
			
		||||
+ *		       randomizer to be disabled
 | 
			
		||||
+ * @mtd:	mtd info
 | 
			
		||||
+ * @page:	NAND page
 | 
			
		||||
+ * @column:	offset within the page
 | 
			
		||||
+ * @len:	len of the region
 | 
			
		||||
+ *
 | 
			
		||||
+ * Returns 1 if the randomizer should be enabled, 0 if not, or -ERR in case of
 | 
			
		||||
+ * error.
 | 
			
		||||
+ *
 | 
			
		||||
+ * In case of success len will contain the size of the region:
 | 
			
		||||
+ *  - if the requested region fits in a NAND random region len will not change
 | 
			
		||||
+ *  - else len will be replaced by the available length within the NAND random
 | 
			
		||||
+ *    region
 | 
			
		||||
+ */
 | 
			
		||||
+int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len)
 | 
			
		||||
+{
 | 
			
		||||
+	struct nand_chip *chip = mtd->priv;
 | 
			
		||||
+	struct nand_rnd_layout *layout = chip->cur_rnd->layout;
 | 
			
		||||
+	struct nand_rndfree *range;
 | 
			
		||||
+	int ret = 1;
 | 
			
		||||
+	int tmp;
 | 
			
		||||
+	int i;
 | 
			
		||||
+
 | 
			
		||||
+	if (!len || *len < 0 || column < 0 ||
 | 
			
		||||
+	    column + *len > mtd->writesize + mtd->oobsize)
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+
 | 
			
		||||
+	if (layout) {
 | 
			
		||||
+		for (i = 0; i < layout->nranges; i++) {
 | 
			
		||||
+			range = &layout->ranges[i];
 | 
			
		||||
+			if (column + *len <= range->offset) {
 | 
			
		||||
+				break;
 | 
			
		||||
+			} else if (column >= range->offset + range->length) {
 | 
			
		||||
+				continue;
 | 
			
		||||
+			} else if (column < range->offset) {
 | 
			
		||||
+				tmp = range->offset - column;
 | 
			
		||||
+				if (*len > tmp)
 | 
			
		||||
+					*len = tmp;
 | 
			
		||||
+				break;
 | 
			
		||||
+			} else {
 | 
			
		||||
+				tmp = range->offset + range->length - column;
 | 
			
		||||
+				if (*len > tmp)
 | 
			
		||||
+					*len = tmp;
 | 
			
		||||
+				ret = 0;
 | 
			
		||||
+				break;
 | 
			
		||||
+			}
 | 
			
		||||
+
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return ret;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL(nand_rnd_is_activ);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
  * nand_page_is_empty - check wether a NAND page contains only FFs
 | 
			
		||||
  * @mtd:	mtd info
 | 
			
		||||
  * @data:	data buffer
 | 
			
		||||
@@ -1246,9 +1302,14 @@ EXPORT_SYMBOL(nand_pst_create);
 | 
			
		||||
 static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 			      uint8_t *buf, int oob_required, int page)
 | 
			
		||||
 {
 | 
			
		||||
-	chip->read_buf(mtd, buf, mtd->writesize);
 | 
			
		||||
-	if (oob_required)
 | 
			
		||||
-		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	nand_rnd_config(mtd, page, 0, NAND_RND_READ);
 | 
			
		||||
+	nand_rnd_read_buf(mtd, buf, mtd->writesize);
 | 
			
		||||
+	if (oob_required) {
 | 
			
		||||
+		nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	}
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
 | 
			
		||||
+
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1270,28 +1331,40 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
 | 
			
		||||
 	int eccbytes = chip->cur_ecc->bytes;
 | 
			
		||||
 	uint8_t *oob = chip->oob_poi;
 | 
			
		||||
 	int steps, size;
 | 
			
		||||
+	int column = 0;
 | 
			
		||||
 
 | 
			
		||||
 	for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
 | 
			
		||||
-		chip->read_buf(mtd, buf, eccsize);
 | 
			
		||||
+		nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, buf, eccsize);
 | 
			
		||||
 		buf += eccsize;
 | 
			
		||||
+		column += eccsize;
 | 
			
		||||
 
 | 
			
		||||
 		if (chip->cur_ecc->prepad) {
 | 
			
		||||
-			chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
 | 
			
		||||
+			nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+			nand_rnd_read_buf(mtd, oob, chip->cur_ecc->prepad);
 | 
			
		||||
 			oob += chip->cur_ecc->prepad;
 | 
			
		||||
+			column += chip->cur_ecc->prepad;
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
-		chip->read_buf(mtd, oob, eccbytes);
 | 
			
		||||
+		nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, oob, eccbytes);
 | 
			
		||||
 		oob += eccbytes;
 | 
			
		||||
+		column += eccbytes;
 | 
			
		||||
 
 | 
			
		||||
 		if (chip->cur_ecc->postpad) {
 | 
			
		||||
-			chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
 | 
			
		||||
+			nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+			nand_rnd_read_buf(mtd, oob, chip->cur_ecc->postpad);
 | 
			
		||||
 			oob += chip->cur_ecc->postpad;
 | 
			
		||||
+			column += chip->cur_ecc->postpad;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	size = mtd->oobsize - (oob - chip->oob_poi);
 | 
			
		||||
-	if (size)
 | 
			
		||||
-		chip->read_buf(mtd, oob, size);
 | 
			
		||||
+	if (size) {
 | 
			
		||||
+		nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, oob, size);
 | 
			
		||||
+	}
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -1380,7 +1453,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
 | 
			
		||||
 
 | 
			
		||||
 	p = bufpoi + data_col_addr;
 | 
			
		||||
-	chip->read_buf(mtd, p, datafrag_len);
 | 
			
		||||
+	nand_rnd_config(mtd, -1, data_col_addr, NAND_RND_READ);
 | 
			
		||||
+	nand_rnd_read_buf(mtd, p, datafrag_len);
 | 
			
		||||
 
 | 
			
		||||
 	/* Calculate ECC */
 | 
			
		||||
 	for (i = 0; i < eccfrag_len;
 | 
			
		||||
@@ -1399,7 +1473,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 	}
 | 
			
		||||
 	if (gaps) {
 | 
			
		||||
 		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
 | 
			
		||||
-		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+		nand_rnd_config(mtd, -1, mtd->writesize, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
 	} else {
 | 
			
		||||
 		/*
 | 
			
		||||
 		 * Send the command to read the particular ECC bytes take care
 | 
			
		||||
@@ -1415,7 +1490,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 
 | 
			
		||||
 		chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
 | 
			
		||||
 					mtd->writesize + aligned_pos, -1);
 | 
			
		||||
-		chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
 | 
			
		||||
+		nand_rnd_config(mtd, -1, mtd->writesize + aligned_pos, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; i < eccfrag_len; i++)
 | 
			
		||||
@@ -1436,6 +1512,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 			max_bitflips = max_t(unsigned int, max_bitflips, stat);
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
 | 
			
		||||
 	return max_bitflips;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1460,13 +1537,17 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 	uint8_t *ecc_code = chip->buffers->ecccode;
 | 
			
		||||
 	uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
 | 
			
		||||
 	unsigned int max_bitflips = 0;
 | 
			
		||||
+	int column = 0;
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 | 
			
		||||
 		chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
 | 
			
		||||
-		chip->read_buf(mtd, p, eccsize);
 | 
			
		||||
+		nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, p, eccsize);
 | 
			
		||||
 		chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
 | 
			
		||||
+		column += eccsize;
 | 
			
		||||
 	}
 | 
			
		||||
-	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+	nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; i < chip->cur_ecc->total; i++)
 | 
			
		||||
 		ecc_code[i] = chip->oob_poi[eccpos[i]];
 | 
			
		||||
@@ -1486,6 +1567,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 			max_bitflips = max_t(unsigned int, max_bitflips, stat);
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
 | 
			
		||||
 	return max_bitflips;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1514,11 +1596,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
 | 
			
		||||
 	uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
 | 
			
		||||
 	uint8_t *ecc_calc = chip->buffers->ecccalc;
 | 
			
		||||
 	unsigned int max_bitflips = 0;
 | 
			
		||||
+	int column = 0;
 | 
			
		||||
 
 | 
			
		||||
 	/* Read the OOB area first */
 | 
			
		||||
 	chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
 | 
			
		||||
-	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
 | 
			
		||||
+	nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
 	chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
 | 
			
		||||
+	column = 0;
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; i < chip->cur_ecc->total; i++)
 | 
			
		||||
 		ecc_code[i] = chip->oob_poi[eccpos[i]];
 | 
			
		||||
@@ -1527,7 +1612,8 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
 | 
			
		||||
 		int stat;
 | 
			
		||||
 
 | 
			
		||||
 		chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
 | 
			
		||||
-		chip->read_buf(mtd, p, eccsize);
 | 
			
		||||
+		nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, p, eccsize);
 | 
			
		||||
 		chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
 | 
			
		||||
 
 | 
			
		||||
 		stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i], NULL);
 | 
			
		||||
@@ -1538,6 +1624,7 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
 | 
			
		||||
 			max_bitflips = max_t(unsigned int, max_bitflips, stat);
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
 | 
			
		||||
 	return max_bitflips;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1561,20 +1648,27 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 	uint8_t *p = buf;
 | 
			
		||||
 	uint8_t *oob = chip->oob_poi;
 | 
			
		||||
 	unsigned int max_bitflips = 0;
 | 
			
		||||
+	int column = 0;
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 | 
			
		||||
 		int stat;
 | 
			
		||||
 
 | 
			
		||||
 		chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
 | 
			
		||||
-		chip->read_buf(mtd, p, eccsize);
 | 
			
		||||
+		nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, p, eccsize);
 | 
			
		||||
+		column += eccsize;
 | 
			
		||||
 
 | 
			
		||||
 		if (chip->cur_ecc->prepad) {
 | 
			
		||||
-			chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
 | 
			
		||||
+			nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+			nand_rnd_read_buf(mtd, oob, chip->cur_ecc->prepad);
 | 
			
		||||
 			oob += chip->cur_ecc->prepad;
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
 		chip->cur_ecc->hwctl(mtd, NAND_ECC_READSYN);
 | 
			
		||||
-		chip->read_buf(mtd, oob, eccbytes);
 | 
			
		||||
+		nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, oob, eccbytes);
 | 
			
		||||
+		column += eccbytes;
 | 
			
		||||
+
 | 
			
		||||
 		stat = chip->cur_ecc->correct(mtd, p, oob, NULL);
 | 
			
		||||
 
 | 
			
		||||
 		if (stat < 0) {
 | 
			
		||||
@@ -1587,29 +1681,36 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 		oob += eccbytes;
 | 
			
		||||
 
 | 
			
		||||
 		if (chip->cur_ecc->postpad) {
 | 
			
		||||
-			chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
 | 
			
		||||
+			nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+			nand_rnd_read_buf(mtd, oob, chip->cur_ecc->postpad);
 | 
			
		||||
+			column += chip->cur_ecc->postpad;
 | 
			
		||||
 			oob += chip->cur_ecc->postpad;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	/* Calculate remaining oob bytes */
 | 
			
		||||
 	i = mtd->oobsize - (oob - chip->oob_poi);
 | 
			
		||||
-	if (i)
 | 
			
		||||
-		chip->read_buf(mtd, oob, i);
 | 
			
		||||
+	if (i) {
 | 
			
		||||
+		nand_rnd_config(mtd, page, column, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, oob, i);
 | 
			
		||||
+	}
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
 | 
			
		||||
 
 | 
			
		||||
 	return max_bitflips;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
  * nand_transfer_oob - [INTERN] Transfer oob to client buffer
 | 
			
		||||
- * @chip: nand chip structure
 | 
			
		||||
+ * @mtd: mtd structure
 | 
			
		||||
  * @oob: oob destination address
 | 
			
		||||
  * @ops: oob ops structure
 | 
			
		||||
  * @len: size of oob to transfer
 | 
			
		||||
  */
 | 
			
		||||
-static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
 | 
			
		||||
+static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob,
 | 
			
		||||
 				  struct mtd_oob_ops *ops, size_t len)
 | 
			
		||||
 {
 | 
			
		||||
+	struct nand_chip *chip = mtd->priv;
 | 
			
		||||
+
 | 
			
		||||
 	switch (ops->mode) {
 | 
			
		||||
 
 | 
			
		||||
 	case MTD_OPS_PLACE_OOB:
 | 
			
		||||
@@ -1737,6 +1838,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 | 
			
		||||
 			 * Now read the page into the buffer.  Absent an error,
 | 
			
		||||
 			 * the read methods return max bitflips per ecc step.
 | 
			
		||||
 			 */
 | 
			
		||||
+			nand_rnd_config(mtd, page, -1, NAND_RND_READ);
 | 
			
		||||
 			if (unlikely(ops->mode == MTD_OPS_RAW))
 | 
			
		||||
 				ret = chip->cur_ecc->read_page_raw(mtd, chip,
 | 
			
		||||
 								bufpoi,
 | 
			
		||||
@@ -1753,6 +1855,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 | 
			
		||||
 							       bufpoi,
 | 
			
		||||
 							       oob_required,
 | 
			
		||||
 							       page);
 | 
			
		||||
+			nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
 | 
			
		||||
+
 | 
			
		||||
 			if (ret < 0) {
 | 
			
		||||
 				if (use_bufpoi)
 | 
			
		||||
 					/* Invalidate page cache */
 | 
			
		||||
@@ -1780,8 +1884,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 | 
			
		||||
 				int toread = min(oobreadlen, max_oobsize);
 | 
			
		||||
 
 | 
			
		||||
 				if (toread) {
 | 
			
		||||
-					oob = nand_transfer_oob(chip,
 | 
			
		||||
-						oob, ops, toread);
 | 
			
		||||
+					oob = nand_transfer_oob(mtd, oob, ops,
 | 
			
		||||
+								toread);
 | 
			
		||||
 					oobreadlen -= toread;
 | 
			
		||||
 				}
 | 
			
		||||
 			}
 | 
			
		||||
@@ -1909,12 +2013,15 @@ static int nand_part_read(struct mtd_info *mtd, loff_t from, size_t len,
 | 
			
		||||
 	nand_get_device(part->master, FL_READING);
 | 
			
		||||
 	if (part->ecc)
 | 
			
		||||
 		chip->cur_ecc = part->ecc;
 | 
			
		||||
+	if (part->rnd)
 | 
			
		||||
+		chip->cur_rnd = part->rnd;
 | 
			
		||||
 	ops.len = len;
 | 
			
		||||
 	ops.datbuf = buf;
 | 
			
		||||
 	ops.oobbuf = NULL;
 | 
			
		||||
 	ops.mode = MTD_OPS_PLACE_OOB;
 | 
			
		||||
 	ret = nand_do_read_ops(part->master, from, &ops);
 | 
			
		||||
 	*retlen = ops.retlen;
 | 
			
		||||
+	chip->cur_rnd = &chip->rnd;
 | 
			
		||||
 	chip->cur_ecc = &chip->ecc;
 | 
			
		||||
 	nand_release_device(part->master);
 | 
			
		||||
 	return ret;
 | 
			
		||||
@@ -1930,7 +2037,9 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 			     int page)
 | 
			
		||||
 {
 | 
			
		||||
 	chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
 | 
			
		||||
-	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
 | 
			
		||||
+	nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1949,7 +2058,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 		    chip->cur_ecc->postpad;
 | 
			
		||||
 	int eccsize = chip->cur_ecc->size;
 | 
			
		||||
 	uint8_t *bufpoi = chip->oob_poi;
 | 
			
		||||
-	int i, toread, sndrnd = 0, pos;
 | 
			
		||||
+	int i, toread, sndrnd = 0, pos = eccsize;
 | 
			
		||||
 
 | 
			
		||||
 	chip->cmdfunc(mtd, NAND_CMD_READ0, chip->cur_ecc->size, page);
 | 
			
		||||
 	for (i = 0; i < chip->cur_ecc->steps; i++) {
 | 
			
		||||
@@ -1962,12 +2071,17 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 		} else
 | 
			
		||||
 			sndrnd = 1;
 | 
			
		||||
 		toread = min_t(int, length, chunk);
 | 
			
		||||
-		chip->read_buf(mtd, bufpoi, toread);
 | 
			
		||||
+		nand_rnd_config(mtd, page, pos, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, bufpoi, toread);
 | 
			
		||||
 		bufpoi += toread;
 | 
			
		||||
 		length -= toread;
 | 
			
		||||
 	}
 | 
			
		||||
-	if (length > 0)
 | 
			
		||||
-		chip->read_buf(mtd, bufpoi, length);
 | 
			
		||||
+	if (length > 0) {
 | 
			
		||||
+		pos = mtd->writesize + mtd->oobsize - length;
 | 
			
		||||
+		nand_rnd_config(mtd, page, pos, NAND_RND_READ);
 | 
			
		||||
+		nand_rnd_read_buf(mtd, bufpoi, length);
 | 
			
		||||
+	}
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -1986,7 +2100,9 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 	int length = mtd->oobsize;
 | 
			
		||||
 
 | 
			
		||||
 	chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
 | 
			
		||||
-	chip->write_buf(mtd, buf, length);
 | 
			
		||||
+	nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_WRITE);
 | 
			
		||||
+	nand_rnd_write_buf(mtd, buf, length);
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
 | 
			
		||||
 	/* Send command to program the OOB data */
 | 
			
		||||
 	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
 | 
			
		||||
 
 | 
			
		||||
@@ -2042,12 +2158,18 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,
 | 
			
		||||
 		} else
 | 
			
		||||
 			sndcmd = 1;
 | 
			
		||||
 		len = min_t(int, length, chunk);
 | 
			
		||||
-		chip->write_buf(mtd, bufpoi, len);
 | 
			
		||||
+		nand_rnd_config(mtd, page, pos, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, bufpoi, len);
 | 
			
		||||
 		bufpoi += len;
 | 
			
		||||
 		length -= len;
 | 
			
		||||
 	}
 | 
			
		||||
-	if (length > 0)
 | 
			
		||||
-		chip->write_buf(mtd, bufpoi, length);
 | 
			
		||||
+	if (length > 0) {
 | 
			
		||||
+		pos = mtd->writesize + mtd->oobsize - length;
 | 
			
		||||
+		nand_rnd_config(mtd, page, pos, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, bufpoi, length);
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
 | 
			
		||||
 
 | 
			
		||||
 	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
 | 
			
		||||
 	status = chip->waitfunc(mtd, chip);
 | 
			
		||||
@@ -2116,7 +2238,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
 		len = min(len, readlen);
 | 
			
		||||
-		buf = nand_transfer_oob(chip, buf, ops, len);
 | 
			
		||||
+		buf = nand_transfer_oob(mtd, buf, ops, len);
 | 
			
		||||
 
 | 
			
		||||
 		if (chip->options & NAND_NEED_READRDY) {
 | 
			
		||||
 			/* Apply delay or wait for ready/busy pin */
 | 
			
		||||
@@ -2226,6 +2348,8 @@ static int nand_part_read_oob(struct mtd_info *mtd, loff_t from,
 | 
			
		||||
 	nand_get_device(part->master, FL_READING);
 | 
			
		||||
 	if (part->ecc)
 | 
			
		||||
 		chip->cur_ecc = part->ecc;
 | 
			
		||||
+	if (part->rnd)
 | 
			
		||||
+		chip->cur_rnd = part->rnd;
 | 
			
		||||
 
 | 
			
		||||
 	switch (ops->mode) {
 | 
			
		||||
 	case MTD_OPS_PLACE_OOB:
 | 
			
		||||
@@ -2243,6 +2367,7 @@ static int nand_part_read_oob(struct mtd_info *mtd, loff_t from,
 | 
			
		||||
 		ret = nand_do_read_ops(part->master, from, ops);
 | 
			
		||||
 
 | 
			
		||||
 out:
 | 
			
		||||
+	chip->cur_rnd = &chip->rnd;
 | 
			
		||||
 	chip->cur_ecc = &chip->ecc;
 | 
			
		||||
 	nand_release_device(part->master);
 | 
			
		||||
 	return ret;
 | 
			
		||||
@@ -2261,9 +2386,11 @@ static int nand_part_read_oob(struct mtd_info *mtd, loff_t from,
 | 
			
		||||
 static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 				const uint8_t *buf, int oob_required)
 | 
			
		||||
 {
 | 
			
		||||
-	chip->write_buf(mtd, buf, mtd->writesize);
 | 
			
		||||
-	if (oob_required)
 | 
			
		||||
-		chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	nand_rnd_write_buf(mtd, buf, mtd->writesize);
 | 
			
		||||
+	if (oob_required) {
 | 
			
		||||
+		nand_rnd_config(mtd, -1, mtd->writesize, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -2285,28 +2412,39 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
 | 
			
		||||
 	int eccbytes = chip->cur_ecc->bytes;
 | 
			
		||||
 	uint8_t *oob = chip->oob_poi;
 | 
			
		||||
 	int steps, size;
 | 
			
		||||
+	int column = 0;
 | 
			
		||||
 
 | 
			
		||||
 	for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
 | 
			
		||||
-		chip->write_buf(mtd, buf, eccsize);
 | 
			
		||||
+		nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, buf, eccsize);
 | 
			
		||||
 		buf += eccsize;
 | 
			
		||||
+		column += eccsize;
 | 
			
		||||
 
 | 
			
		||||
 		if (chip->cur_ecc->prepad) {
 | 
			
		||||
-			chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
 | 
			
		||||
+			nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+			nand_rnd_write_buf(mtd, oob, chip->cur_ecc->prepad);
 | 
			
		||||
 			oob += chip->cur_ecc->prepad;
 | 
			
		||||
+			column += chip->cur_ecc->prepad;
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
-		chip->write_buf(mtd, oob, eccbytes);
 | 
			
		||||
+		nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, oob, eccbytes);
 | 
			
		||||
 		oob += eccbytes;
 | 
			
		||||
+		column += eccbytes;
 | 
			
		||||
 
 | 
			
		||||
 		if (chip->cur_ecc->postpad) {
 | 
			
		||||
-			chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
 | 
			
		||||
+			nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+			nand_rnd_write_buf(mtd, oob, chip->cur_ecc->postpad);
 | 
			
		||||
 			oob += chip->cur_ecc->postpad;
 | 
			
		||||
+			column += chip->cur_ecc->postpad;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	size = mtd->oobsize - (oob - chip->oob_poi);
 | 
			
		||||
-	if (size)
 | 
			
		||||
-		chip->write_buf(mtd, oob, size);
 | 
			
		||||
+	if (size) {
 | 
			
		||||
+		nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, oob, size);
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -2353,17 +2491,21 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 	uint8_t *ecc_calc = chip->buffers->ecccalc;
 | 
			
		||||
 	const uint8_t *p = buf;
 | 
			
		||||
 	uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
 | 
			
		||||
+	int column = 0;
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 | 
			
		||||
 		chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
 | 
			
		||||
-		chip->write_buf(mtd, p, eccsize);
 | 
			
		||||
+		nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, p, eccsize);
 | 
			
		||||
 		chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
 | 
			
		||||
+		column += eccsize;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; i < chip->cur_ecc->total; i++)
 | 
			
		||||
 		chip->oob_poi[eccpos[i]] = ecc_calc[i];
 | 
			
		||||
 
 | 
			
		||||
-	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+	nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -2399,7 +2541,9 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
 | 
			
		||||
 		chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
 | 
			
		||||
 
 | 
			
		||||
 		/* write data (untouched subpages already masked by 0xFF) */
 | 
			
		||||
-		chip->write_buf(mtd, buf, ecc_size);
 | 
			
		||||
+		nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, buf, ecc_size);
 | 
			
		||||
+		offset += ecc_size;
 | 
			
		||||
 
 | 
			
		||||
 		/* mask ECC of un-touched subpages by padding 0xFF */
 | 
			
		||||
 		if ((step < start_step) || (step > end_step))
 | 
			
		||||
@@ -2424,7 +2568,8 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
 | 
			
		||||
 		chip->oob_poi[eccpos[i]] = ecc_calc[i];
 | 
			
		||||
 
 | 
			
		||||
 	/* write OOB buffer to NAND device */
 | 
			
		||||
-	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
+	nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE);
 | 
			
		||||
+	nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -2449,31 +2594,42 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
 | 
			
		||||
 	int eccsteps = chip->cur_ecc->steps;
 | 
			
		||||
 	const uint8_t *p = buf;
 | 
			
		||||
 	uint8_t *oob = chip->oob_poi;
 | 
			
		||||
+	int column = 0;
 | 
			
		||||
 
 | 
			
		||||
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 | 
			
		||||
 
 | 
			
		||||
 		chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
 | 
			
		||||
-		chip->write_buf(mtd, p, eccsize);
 | 
			
		||||
+		nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, p, eccsize);
 | 
			
		||||
+		column += eccsize;
 | 
			
		||||
 
 | 
			
		||||
 		if (chip->cur_ecc->prepad) {
 | 
			
		||||
-			chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
 | 
			
		||||
+			nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+			nand_rnd_write_buf(mtd, oob, chip->cur_ecc->prepad);
 | 
			
		||||
 			oob += chip->cur_ecc->prepad;
 | 
			
		||||
+			column += chip->cur_ecc->prepad;
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
 		chip->cur_ecc->calculate(mtd, p, oob);
 | 
			
		||||
-		chip->write_buf(mtd, oob, eccbytes);
 | 
			
		||||
+		nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, oob, eccbytes);
 | 
			
		||||
 		oob += eccbytes;
 | 
			
		||||
+		column += eccbytes;
 | 
			
		||||
 
 | 
			
		||||
 		if (chip->cur_ecc->postpad) {
 | 
			
		||||
-			chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
 | 
			
		||||
+			nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+			nand_rnd_write_buf(mtd, oob, chip->cur_ecc->postpad);
 | 
			
		||||
 			oob += chip->cur_ecc->postpad;
 | 
			
		||||
+			column += chip->cur_ecc->postpad;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	/* Calculate remaining oob bytes */
 | 
			
		||||
 	i = mtd->oobsize - (oob - chip->oob_poi);
 | 
			
		||||
-	if (i)
 | 
			
		||||
-		chip->write_buf(mtd, oob, i);
 | 
			
		||||
+	if (i) {
 | 
			
		||||
+		nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
 | 
			
		||||
+		nand_rnd_write_buf(mtd, oob, i);
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -2504,6 +2660,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 
 | 
			
		||||
 	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
 | 
			
		||||
 
 | 
			
		||||
+	nand_rnd_config(mtd, page, 0, NAND_RND_WRITE);
 | 
			
		||||
 	if (unlikely(raw))
 | 
			
		||||
 		status = chip->cur_ecc->write_page_raw(mtd, chip, buf,
 | 
			
		||||
 						       oob_required);
 | 
			
		||||
@@ -2514,6 +2671,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 | 
			
		||||
 	else
 | 
			
		||||
 		status = chip->cur_ecc->write_page(mtd, chip, buf,
 | 
			
		||||
 						   oob_required);
 | 
			
		||||
+	nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
 | 
			
		||||
 
 | 
			
		||||
 	if (status < 0)
 | 
			
		||||
 		return status;
 | 
			
		||||
@@ -2803,6 +2961,8 @@ static int panic_nand_part_write(struct mtd_info *mtd, loff_t to, size_t len,
 | 
			
		||||
 	panic_nand_get_device(chip, part->master, FL_WRITING);
 | 
			
		||||
 	if (part->ecc)
 | 
			
		||||
 		chip->cur_ecc = part->ecc;
 | 
			
		||||
+	if (part->rnd)
 | 
			
		||||
+		chip->cur_rnd = part->rnd;
 | 
			
		||||
 
 | 
			
		||||
 	ops.len = len;
 | 
			
		||||
 	ops.datbuf = (uint8_t *)buf;
 | 
			
		||||
@@ -2811,6 +2971,7 @@ static int panic_nand_part_write(struct mtd_info *mtd, loff_t to, size_t len,
 | 
			
		||||
 
 | 
			
		||||
 	ret = nand_do_write_ops(part->master, to, &ops);
 | 
			
		||||
 
 | 
			
		||||
+	chip->cur_rnd = &chip->rnd;
 | 
			
		||||
 	chip->cur_ecc = &chip->ecc;
 | 
			
		||||
 	*retlen = ops.retlen;
 | 
			
		||||
 	return ret;
 | 
			
		||||
@@ -2865,12 +3026,15 @@ static int nand_part_write(struct mtd_info *mtd, loff_t to, size_t len,
 | 
			
		||||
 	nand_get_device(part->master, FL_WRITING);
 | 
			
		||||
 	if (part->ecc)
 | 
			
		||||
 		chip->cur_ecc = part->ecc;
 | 
			
		||||
+	if (part->rnd)
 | 
			
		||||
+		chip->cur_rnd = part->rnd;
 | 
			
		||||
 	ops.len = len;
 | 
			
		||||
 	ops.datbuf = (uint8_t *)buf;
 | 
			
		||||
 	ops.oobbuf = NULL;
 | 
			
		||||
 	ops.mode = MTD_OPS_PLACE_OOB;
 | 
			
		||||
 	ret = nand_do_write_ops(part->master, to, &ops);
 | 
			
		||||
 	*retlen = ops.retlen;
 | 
			
		||||
+	chip->cur_rnd = &chip->rnd;
 | 
			
		||||
 	chip->cur_ecc = &chip->ecc;
 | 
			
		||||
 	nand_release_device(part->master);
 | 
			
		||||
 	return ret;
 | 
			
		||||
@@ -3032,6 +3196,8 @@ static int nand_part_write_oob(struct mtd_info *mtd, loff_t to,
 | 
			
		||||
 	nand_get_device(part->master, FL_WRITING);
 | 
			
		||||
 	if (part->ecc)
 | 
			
		||||
 		chip->cur_ecc = part->ecc;
 | 
			
		||||
+	if (part->rnd)
 | 
			
		||||
+		chip->cur_rnd = part->rnd;
 | 
			
		||||
 
 | 
			
		||||
 	switch (ops->mode) {
 | 
			
		||||
 	case MTD_OPS_PLACE_OOB:
 | 
			
		||||
@@ -3049,6 +3215,7 @@ static int nand_part_write_oob(struct mtd_info *mtd, loff_t to,
 | 
			
		||||
 		ret = nand_do_write_ops(part->master, to, ops);
 | 
			
		||||
 
 | 
			
		||||
 out:
 | 
			
		||||
+	chip->cur_rnd = &chip->rnd;
 | 
			
		||||
 	chip->cur_ecc = &chip->ecc;
 | 
			
		||||
 	nand_release_device(part->master);
 | 
			
		||||
 	return ret;
 | 
			
		||||
@@ -4749,6 +4916,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 | 
			
		||||
 	mutex_init(&chip->part_lock);
 | 
			
		||||
 
 | 
			
		||||
 	chip->cur_ecc = &chip->ecc;
 | 
			
		||||
+	chip->cur_rnd = &chip->rnd;
 | 
			
		||||
 
 | 
			
		||||
 	/* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
 | 
			
		||||
 	if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
 | 
			
		||||
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
 | 
			
		||||
index 4f7ca8d..6cbd06a3 100644
 | 
			
		||||
--- a/include/linux/mtd/nand.h
 | 
			
		||||
+++ b/include/linux/mtd/nand.h
 | 
			
		||||
@@ -539,6 +539,64 @@ void nand_page_set_status(struct mtd_info *mtd, int page,
 | 
			
		||||
 
 | 
			
		||||
 int nand_pst_create(struct mtd_info *mtd);
 | 
			
		||||
 
 | 
			
		||||
+/*
 | 
			
		||||
+ * Constants for randomizer modes
 | 
			
		||||
+ */
 | 
			
		||||
+typedef enum {
 | 
			
		||||
+	NAND_RND_NONE,
 | 
			
		||||
+	NAND_RND_SOFT,
 | 
			
		||||
+	NAND_RND_HW,
 | 
			
		||||
+} nand_rnd_modes_t;
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Constants for randomizer actions
 | 
			
		||||
+ */
 | 
			
		||||
+enum nand_rnd_action {
 | 
			
		||||
+	NAND_RND_NO_ACTION,
 | 
			
		||||
+	NAND_RND_READ,
 | 
			
		||||
+	NAND_RND_WRITE,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * struct nand_rndfree - Structure defining a NAND page region where the
 | 
			
		||||
+ *			 randomizer should be disabled
 | 
			
		||||
+ * @offset:	range offset
 | 
			
		||||
+ * @length:	range length
 | 
			
		||||
+ */
 | 
			
		||||
+struct nand_rndfree {
 | 
			
		||||
+	u32 offset;
 | 
			
		||||
+	u32 length;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * struct nand_rnd_layout - Structure defining rndfree regions
 | 
			
		||||
+ * @nranges:	number of ranges
 | 
			
		||||
+ * @ranges:	array defining the rndfree regions
 | 
			
		||||
+ */
 | 
			
		||||
+struct nand_rnd_layout {
 | 
			
		||||
+	int nranges;
 | 
			
		||||
+	struct nand_rndfree ranges[0];
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * struct nand_rnd_ctrl - Randomizer Control structure
 | 
			
		||||
+ * @mode:	Randomizer mode
 | 
			
		||||
+ * @config:	function to prepare the randomizer (i.e.: set the appropriate
 | 
			
		||||
+ *		seed/init value).
 | 
			
		||||
+ * @read_buf:	function that read from the NAND and descramble the retrieved
 | 
			
		||||
+ *		data.
 | 
			
		||||
+ * @write_buf:	function that scramble data before writing it to the NAND.
 | 
			
		||||
+ */
 | 
			
		||||
+struct nand_rnd_ctrl {
 | 
			
		||||
+	nand_rnd_modes_t mode;
 | 
			
		||||
+	struct nand_rnd_layout *layout;
 | 
			
		||||
+	void *priv;
 | 
			
		||||
+	int (*config)(struct mtd_info *mtd, int page, int column,
 | 
			
		||||
+		      enum nand_rnd_action action);
 | 
			
		||||
+	void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
 | 
			
		||||
+	void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 /**
 | 
			
		||||
  * struct nand_buffers - buffer structure for read/write
 | 
			
		||||
  * @ecccalc:	buffer pointer for calculated ECC, size is oobsize.
 | 
			
		||||
@@ -731,6 +789,9 @@ struct nand_chip {
 | 
			
		||||
 	struct nand_buffers *buffers;
 | 
			
		||||
 	struct nand_hw_control hwcontrol;
 | 
			
		||||
 
 | 
			
		||||
+	struct nand_rnd_ctrl rnd;
 | 
			
		||||
+	struct nand_rnd_ctrl *cur_rnd;
 | 
			
		||||
+
 | 
			
		||||
 	uint8_t *bbt;
 | 
			
		||||
 	struct nand_bbt_descr *bbt_td;
 | 
			
		||||
 	struct nand_bbt_descr *bbt_md;
 | 
			
		||||
@@ -752,6 +813,7 @@ struct nand_chip {
 | 
			
		||||
  * @master:	MTD device representing the NAND chip
 | 
			
		||||
  * @offset:	partition offset
 | 
			
		||||
  * @ecc:	partition specific ECC struct
 | 
			
		||||
+ * @rnd:	partition specific randomizer struct
 | 
			
		||||
  * @release:	function used to release this nand_part struct
 | 
			
		||||
  *
 | 
			
		||||
  * NAND partitions work as standard MTD partitions except it can override
 | 
			
		||||
@@ -765,6 +827,7 @@ struct nand_part {
 | 
			
		||||
 	struct mtd_info *master;
 | 
			
		||||
 	uint64_t offset;
 | 
			
		||||
 	struct nand_ecc_ctrl *ecc;
 | 
			
		||||
+	struct nand_rnd_ctrl *rnd;
 | 
			
		||||
 	void (*release)(struct nand_part *part);
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -902,6 +965,41 @@ extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 | 
			
		||||
 extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
 | 
			
		||||
 			size_t *retlen, uint8_t *buf);
 | 
			
		||||
 
 | 
			
		||||
+static inline int nand_rnd_config(struct mtd_info *mtd, int page, int column,
 | 
			
		||||
+				  enum nand_rnd_action action)
 | 
			
		||||
+{
 | 
			
		||||
+	struct nand_chip *chip = mtd->priv;
 | 
			
		||||
+
 | 
			
		||||
+	if (chip->cur_rnd && chip->cur_rnd->config)
 | 
			
		||||
+		return chip->cur_rnd->config(mtd, page, column, action);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static inline void nand_rnd_write_buf(struct mtd_info *mtd, const uint8_t *buf,
 | 
			
		||||
+				     int len)
 | 
			
		||||
+{
 | 
			
		||||
+	struct nand_chip *chip = mtd->priv;
 | 
			
		||||
+
 | 
			
		||||
+	if (chip->cur_rnd && chip->cur_rnd->read_buf)
 | 
			
		||||
+		chip->cur_rnd->write_buf(mtd, buf, len);
 | 
			
		||||
+	else
 | 
			
		||||
+		chip->write_buf(mtd, buf, len);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static inline void nand_rnd_read_buf(struct mtd_info *mtd, uint8_t *buf,
 | 
			
		||||
+				    int len)
 | 
			
		||||
+{
 | 
			
		||||
+	struct nand_chip *chip = mtd->priv;
 | 
			
		||||
+
 | 
			
		||||
+	if (chip->cur_rnd && chip->cur_rnd->read_buf)
 | 
			
		||||
+		chip->cur_rnd->read_buf(mtd, buf, len);
 | 
			
		||||
+	else
 | 
			
		||||
+		chip->read_buf(mtd, buf, len);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len);
 | 
			
		||||
+
 | 
			
		||||
 /**
 | 
			
		||||
  * struct platform_nand_chip - chip level device structure
 | 
			
		||||
  * @nr_chips:		max. number of chips to scan for
 | 
			
		||||
		Reference in New Issue
	
	Block a user