diff options
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.patch | 847 |
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 |