summaryrefslogtreecommitdiffstats
path: root/target/linux/sunxi/patches-4.1/114-mtd-randomizer-into-nand-framework.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/sunxi/patches-4.1/114-mtd-randomizer-into-nand-framework.patch')
-rw-r--r--target/linux/sunxi/patches-4.1/114-mtd-randomizer-into-nand-framework.patch847
1 files changed, 0 insertions, 847 deletions
diff --git a/target/linux/sunxi/patches-4.1/114-mtd-randomizer-into-nand-framework.patch b/target/linux/sunxi/patches-4.1/114-mtd-randomizer-into-nand-framework.patch
deleted file mode 100644
index 173bd1eb49..0000000000
--- a/target/linux/sunxi/patches-4.1/114-mtd-randomizer-into-nand-framework.patch
+++ /dev/null
@@ -1,847 +0,0 @@
-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(-)
-
---- a/drivers/mtd/nand/nand_base.c
-+++ b/drivers/mtd/nand/nand_base.c
-@@ -1102,6 +1102,62 @@ out:
- 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(s
- 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_
- 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_
- }
- 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_
-
- 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_
- 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 m
- 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 m
- 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_firs
- 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_firs
- 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_firs
- 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(struc
- 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(struc
- 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 @@ read_retry:
- * 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 @@ read_retry:
- 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 @@ read_retry:
- 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_inf
- 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_
- 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
- 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
- } 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
- 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(struc
- } 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_i
- 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
- 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
- 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 @@ out:
- 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(
- 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
- 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(stru
- 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(stru
- 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(stru
- 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_in
-
- 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_in
- 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
- 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
-
- 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_in
- 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 mt
- 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 mt
- 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)) {
---- a/include/linux/mtd/nand.h
-+++ b/include/linux/mtd/nand.h
-@@ -539,6 +539,64 @@ void nand_page_set_status(struct mtd_inf
-
- 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_in
- 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