sunxi: delete old kernel versions
[openwrt/staging/chunkeey.git] / target / linux / sunxi / patches-4.1 / 114-mtd-randomizer-into-nand-framework.patch
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 (file)
index 173bd1e..0000000
+++ /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