1 From 293984c7f167a08285596ef2166d8ab9cb571778 Mon Sep 17 00:00:00 2001
2 From: Boris BREZILLON <boris.brezillon@free-electrons.com>
3 Date: Mon, 28 Jul 2014 14:46:26 +0200
4 Subject: [PATCH] mtd: nand: Introduce a randomizer layer in the NAND framework
6 This patch introduce a new layer in the NAND framework to support both HW
9 This randomization is required on some MLC/TLC NAND chips which do not
10 support large islands of same patterns.
12 The randomizer layer defines a nand_rnd_ctrl struct which is intended to
13 be used by NAND core functions or NAND drivers to randomize/derandomize
14 data stored on NAND chips.
16 The implementation can implement any of these functions:
17 - config: prepare a random transfer to/from the NAND chip
18 - write_buf: randomize and write data to the NAND chip
19 - read_buf: read and derandomize data from the NAND chip
21 read/write_buf functions are always called after a config call.
22 The config call specify the page, the column within the page and the action
23 that will take place after the config (either read or write).
24 If column is set to -1, the randomizer is disabled.
25 If page is set to -1, we keep working on the same page.
27 The randomizer layer provides helper functions that choose wether the
28 randomizer or the chip read/write_buf should be used.
30 Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
31 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
33 drivers/mtd/nand/nand_base.c | 278 ++++++++++++++++++++++++++++++++++---------
34 include/linux/mtd/nand.h | 98 +++++++++++++++
35 2 files changed, 321 insertions(+), 55 deletions(-)
37 --- a/drivers/mtd/nand/nand_base.c
38 +++ b/drivers/mtd/nand/nand_base.c
39 @@ -1102,6 +1102,62 @@ out:
40 EXPORT_SYMBOL(nand_lock);
43 + * nand_rnd_is_activ - check wether a region of a NAND page requires NAND
44 + * randomizer to be disabled
47 + * @column: offset within the page
48 + * @len: len of the region
50 + * Returns 1 if the randomizer should be enabled, 0 if not, or -ERR in case of
53 + * In case of success len will contain the size of the region:
54 + * - if the requested region fits in a NAND random region len will not change
55 + * - else len will be replaced by the available length within the NAND random
58 +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len)
60 + struct nand_chip *chip = mtd->priv;
61 + struct nand_rnd_layout *layout = chip->cur_rnd->layout;
62 + struct nand_rndfree *range;
67 + if (!len || *len < 0 || column < 0 ||
68 + column + *len > mtd->writesize + mtd->oobsize)
72 + for (i = 0; i < layout->nranges; i++) {
73 + range = &layout->ranges[i];
74 + if (column + *len <= range->offset) {
76 + } else if (column >= range->offset + range->length) {
78 + } else if (column < range->offset) {
79 + tmp = range->offset - column;
84 + tmp = range->offset + range->length - column;
96 +EXPORT_SYMBOL(nand_rnd_is_activ);
99 * nand_page_is_empty - check wether a NAND page contains only FFs
102 @@ -1246,9 +1302,14 @@ EXPORT_SYMBOL(nand_pst_create);
103 static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
104 uint8_t *buf, int oob_required, int page)
106 - chip->read_buf(mtd, buf, mtd->writesize);
108 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
109 + nand_rnd_config(mtd, page, 0, NAND_RND_READ);
110 + nand_rnd_read_buf(mtd, buf, mtd->writesize);
111 + if (oob_required) {
112 + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
113 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
115 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
120 @@ -1270,28 +1331,40 @@ static int nand_read_page_raw_syndrome(s
121 int eccbytes = chip->cur_ecc->bytes;
122 uint8_t *oob = chip->oob_poi;
126 for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
127 - chip->read_buf(mtd, buf, eccsize);
128 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
129 + nand_rnd_read_buf(mtd, buf, eccsize);
133 if (chip->cur_ecc->prepad) {
134 - chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
135 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
136 + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->prepad);
137 oob += chip->cur_ecc->prepad;
138 + column += chip->cur_ecc->prepad;
141 - chip->read_buf(mtd, oob, eccbytes);
142 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
143 + nand_rnd_read_buf(mtd, oob, eccbytes);
145 + column += eccbytes;
147 if (chip->cur_ecc->postpad) {
148 - chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
149 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
150 + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->postpad);
151 oob += chip->cur_ecc->postpad;
152 + column += chip->cur_ecc->postpad;
156 size = mtd->oobsize - (oob - chip->oob_poi);
158 - chip->read_buf(mtd, oob, size);
160 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
161 + nand_rnd_read_buf(mtd, oob, size);
163 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
167 @@ -1380,7 +1453,8 @@ static int nand_read_subpage(struct mtd_
168 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
170 p = bufpoi + data_col_addr;
171 - chip->read_buf(mtd, p, datafrag_len);
172 + nand_rnd_config(mtd, -1, data_col_addr, NAND_RND_READ);
173 + nand_rnd_read_buf(mtd, p, datafrag_len);
176 for (i = 0; i < eccfrag_len;
177 @@ -1399,7 +1473,8 @@ static int nand_read_subpage(struct mtd_
180 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
181 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
182 + nand_rnd_config(mtd, -1, mtd->writesize, NAND_RND_READ);
183 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
186 * Send the command to read the particular ECC bytes take care
187 @@ -1415,7 +1490,8 @@ static int nand_read_subpage(struct mtd_
189 chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
190 mtd->writesize + aligned_pos, -1);
191 - chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
192 + nand_rnd_config(mtd, -1, mtd->writesize + aligned_pos, NAND_RND_READ);
193 + nand_rnd_read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
196 for (i = 0; i < eccfrag_len; i++)
197 @@ -1436,6 +1512,7 @@ static int nand_read_subpage(struct mtd_
198 max_bitflips = max_t(unsigned int, max_bitflips, stat);
201 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
205 @@ -1460,13 +1537,17 @@ static int nand_read_page_hwecc(struct m
206 uint8_t *ecc_code = chip->buffers->ecccode;
207 uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
208 unsigned int max_bitflips = 0;
211 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
212 chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
213 - chip->read_buf(mtd, p, eccsize);
214 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
215 + nand_rnd_read_buf(mtd, p, eccsize);
216 chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
219 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
220 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
221 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
223 for (i = 0; i < chip->cur_ecc->total; i++)
224 ecc_code[i] = chip->oob_poi[eccpos[i]];
225 @@ -1486,6 +1567,7 @@ static int nand_read_page_hwecc(struct m
226 max_bitflips = max_t(unsigned int, max_bitflips, stat);
229 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
233 @@ -1514,11 +1596,14 @@ static int nand_read_page_hwecc_oob_firs
234 uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
235 uint8_t *ecc_calc = chip->buffers->ecccalc;
236 unsigned int max_bitflips = 0;
239 /* Read the OOB area first */
240 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
241 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
242 + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
243 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
244 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
247 for (i = 0; i < chip->cur_ecc->total; i++)
248 ecc_code[i] = chip->oob_poi[eccpos[i]];
249 @@ -1527,7 +1612,8 @@ static int nand_read_page_hwecc_oob_firs
252 chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
253 - chip->read_buf(mtd, p, eccsize);
254 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
255 + nand_rnd_read_buf(mtd, p, eccsize);
256 chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
258 stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i], NULL);
259 @@ -1538,6 +1624,7 @@ static int nand_read_page_hwecc_oob_firs
260 max_bitflips = max_t(unsigned int, max_bitflips, stat);
263 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
267 @@ -1561,20 +1648,27 @@ static int nand_read_page_syndrome(struc
269 uint8_t *oob = chip->oob_poi;
270 unsigned int max_bitflips = 0;
273 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
276 chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
277 - chip->read_buf(mtd, p, eccsize);
278 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
279 + nand_rnd_read_buf(mtd, p, eccsize);
282 if (chip->cur_ecc->prepad) {
283 - chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
284 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
285 + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->prepad);
286 oob += chip->cur_ecc->prepad;
289 chip->cur_ecc->hwctl(mtd, NAND_ECC_READSYN);
290 - chip->read_buf(mtd, oob, eccbytes);
291 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
292 + nand_rnd_read_buf(mtd, oob, eccbytes);
293 + column += eccbytes;
295 stat = chip->cur_ecc->correct(mtd, p, oob, NULL);
298 @@ -1587,29 +1681,36 @@ static int nand_read_page_syndrome(struc
301 if (chip->cur_ecc->postpad) {
302 - chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
303 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
304 + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->postpad);
305 + column += chip->cur_ecc->postpad;
306 oob += chip->cur_ecc->postpad;
310 /* Calculate remaining oob bytes */
311 i = mtd->oobsize - (oob - chip->oob_poi);
313 - chip->read_buf(mtd, oob, i);
315 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
316 + nand_rnd_read_buf(mtd, oob, i);
318 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
324 * nand_transfer_oob - [INTERN] Transfer oob to client buffer
325 - * @chip: nand chip structure
326 + * @mtd: mtd structure
327 * @oob: oob destination address
328 * @ops: oob ops structure
329 * @len: size of oob to transfer
331 -static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
332 +static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob,
333 struct mtd_oob_ops *ops, size_t len)
335 + struct nand_chip *chip = mtd->priv;
339 case MTD_OPS_PLACE_OOB:
340 @@ -1737,6 +1838,7 @@ read_retry:
341 * Now read the page into the buffer. Absent an error,
342 * the read methods return max bitflips per ecc step.
344 + nand_rnd_config(mtd, page, -1, NAND_RND_READ);
345 if (unlikely(ops->mode == MTD_OPS_RAW))
346 ret = chip->cur_ecc->read_page_raw(mtd, chip,
348 @@ -1753,6 +1855,8 @@ read_retry:
352 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
356 /* Invalidate page cache */
357 @@ -1780,8 +1884,8 @@ read_retry:
358 int toread = min(oobreadlen, max_oobsize);
361 - oob = nand_transfer_oob(chip,
363 + oob = nand_transfer_oob(mtd, oob, ops,
365 oobreadlen -= toread;
368 @@ -1909,12 +2013,15 @@ static int nand_part_read(struct mtd_inf
369 nand_get_device(part->master, FL_READING);
371 chip->cur_ecc = part->ecc;
373 + chip->cur_rnd = part->rnd;
377 ops.mode = MTD_OPS_PLACE_OOB;
378 ret = nand_do_read_ops(part->master, from, &ops);
379 *retlen = ops.retlen;
380 + chip->cur_rnd = &chip->rnd;
381 chip->cur_ecc = &chip->ecc;
382 nand_release_device(part->master);
384 @@ -1930,7 +2037,9 @@ static int nand_read_oob_std(struct mtd_
387 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
388 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
389 + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
390 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
391 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
395 @@ -1949,7 +2058,7 @@ static int nand_read_oob_syndrome(struct
396 chip->cur_ecc->postpad;
397 int eccsize = chip->cur_ecc->size;
398 uint8_t *bufpoi = chip->oob_poi;
399 - int i, toread, sndrnd = 0, pos;
400 + int i, toread, sndrnd = 0, pos = eccsize;
402 chip->cmdfunc(mtd, NAND_CMD_READ0, chip->cur_ecc->size, page);
403 for (i = 0; i < chip->cur_ecc->steps; i++) {
404 @@ -1962,12 +2071,17 @@ static int nand_read_oob_syndrome(struct
407 toread = min_t(int, length, chunk);
408 - chip->read_buf(mtd, bufpoi, toread);
409 + nand_rnd_config(mtd, page, pos, NAND_RND_READ);
410 + nand_rnd_read_buf(mtd, bufpoi, toread);
415 - chip->read_buf(mtd, bufpoi, length);
417 + pos = mtd->writesize + mtd->oobsize - length;
418 + nand_rnd_config(mtd, page, pos, NAND_RND_READ);
419 + nand_rnd_read_buf(mtd, bufpoi, length);
421 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
425 @@ -1986,7 +2100,9 @@ static int nand_write_oob_std(struct mtd
426 int length = mtd->oobsize;
428 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
429 - chip->write_buf(mtd, buf, length);
430 + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_WRITE);
431 + nand_rnd_write_buf(mtd, buf, length);
432 + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
433 /* Send command to program the OOB data */
434 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
436 @@ -2042,12 +2158,18 @@ static int nand_write_oob_syndrome(struc
439 len = min_t(int, length, chunk);
440 - chip->write_buf(mtd, bufpoi, len);
441 + nand_rnd_config(mtd, page, pos, NAND_RND_WRITE);
442 + nand_rnd_write_buf(mtd, bufpoi, len);
447 - chip->write_buf(mtd, bufpoi, length);
449 + pos = mtd->writesize + mtd->oobsize - length;
450 + nand_rnd_config(mtd, page, pos, NAND_RND_WRITE);
451 + nand_rnd_write_buf(mtd, bufpoi, length);
454 + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
456 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
457 status = chip->waitfunc(mtd, chip);
458 @@ -2116,7 +2238,7 @@ static int nand_do_read_oob(struct mtd_i
461 len = min(len, readlen);
462 - buf = nand_transfer_oob(chip, buf, ops, len);
463 + buf = nand_transfer_oob(mtd, buf, ops, len);
465 if (chip->options & NAND_NEED_READRDY) {
466 /* Apply delay or wait for ready/busy pin */
467 @@ -2226,6 +2348,8 @@ static int nand_part_read_oob(struct mtd
468 nand_get_device(part->master, FL_READING);
470 chip->cur_ecc = part->ecc;
472 + chip->cur_rnd = part->rnd;
475 case MTD_OPS_PLACE_OOB:
476 @@ -2243,6 +2367,7 @@ static int nand_part_read_oob(struct mtd
477 ret = nand_do_read_ops(part->master, from, ops);
480 + chip->cur_rnd = &chip->rnd;
481 chip->cur_ecc = &chip->ecc;
482 nand_release_device(part->master);
484 @@ -2261,9 +2386,11 @@ out:
485 static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
486 const uint8_t *buf, int oob_required)
488 - chip->write_buf(mtd, buf, mtd->writesize);
490 - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
491 + nand_rnd_write_buf(mtd, buf, mtd->writesize);
492 + if (oob_required) {
493 + nand_rnd_config(mtd, -1, mtd->writesize, NAND_RND_WRITE);
494 + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
499 @@ -2285,28 +2412,39 @@ static int nand_write_page_raw_syndrome(
500 int eccbytes = chip->cur_ecc->bytes;
501 uint8_t *oob = chip->oob_poi;
505 for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
506 - chip->write_buf(mtd, buf, eccsize);
507 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
508 + nand_rnd_write_buf(mtd, buf, eccsize);
512 if (chip->cur_ecc->prepad) {
513 - chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
514 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
515 + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->prepad);
516 oob += chip->cur_ecc->prepad;
517 + column += chip->cur_ecc->prepad;
520 - chip->write_buf(mtd, oob, eccbytes);
521 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
522 + nand_rnd_write_buf(mtd, oob, eccbytes);
524 + column += eccbytes;
526 if (chip->cur_ecc->postpad) {
527 - chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
528 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
529 + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->postpad);
530 oob += chip->cur_ecc->postpad;
531 + column += chip->cur_ecc->postpad;
535 size = mtd->oobsize - (oob - chip->oob_poi);
537 - chip->write_buf(mtd, oob, size);
539 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
540 + nand_rnd_write_buf(mtd, oob, size);
545 @@ -2353,17 +2491,21 @@ static int nand_write_page_hwecc(struct
546 uint8_t *ecc_calc = chip->buffers->ecccalc;
547 const uint8_t *p = buf;
548 uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
551 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
552 chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
553 - chip->write_buf(mtd, p, eccsize);
554 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
555 + nand_rnd_write_buf(mtd, p, eccsize);
556 chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
560 for (i = 0; i < chip->cur_ecc->total; i++)
561 chip->oob_poi[eccpos[i]] = ecc_calc[i];
563 - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
564 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
565 + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
569 @@ -2399,7 +2541,9 @@ static int nand_write_subpage_hwecc(stru
570 chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
572 /* write data (untouched subpages already masked by 0xFF) */
573 - chip->write_buf(mtd, buf, ecc_size);
574 + nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE);
575 + nand_rnd_write_buf(mtd, buf, ecc_size);
576 + offset += ecc_size;
578 /* mask ECC of un-touched subpages by padding 0xFF */
579 if ((step < start_step) || (step > end_step))
580 @@ -2424,7 +2568,8 @@ static int nand_write_subpage_hwecc(stru
581 chip->oob_poi[eccpos[i]] = ecc_calc[i];
583 /* write OOB buffer to NAND device */
584 - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
585 + nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE);
586 + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
590 @@ -2449,31 +2594,42 @@ static int nand_write_page_syndrome(stru
591 int eccsteps = chip->cur_ecc->steps;
592 const uint8_t *p = buf;
593 uint8_t *oob = chip->oob_poi;
596 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
598 chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
599 - chip->write_buf(mtd, p, eccsize);
600 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
601 + nand_rnd_write_buf(mtd, p, eccsize);
604 if (chip->cur_ecc->prepad) {
605 - chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
606 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
607 + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->prepad);
608 oob += chip->cur_ecc->prepad;
609 + column += chip->cur_ecc->prepad;
612 chip->cur_ecc->calculate(mtd, p, oob);
613 - chip->write_buf(mtd, oob, eccbytes);
614 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
615 + nand_rnd_write_buf(mtd, oob, eccbytes);
617 + column += eccbytes;
619 if (chip->cur_ecc->postpad) {
620 - chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
621 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
622 + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->postpad);
623 oob += chip->cur_ecc->postpad;
624 + column += chip->cur_ecc->postpad;
628 /* Calculate remaining oob bytes */
629 i = mtd->oobsize - (oob - chip->oob_poi);
631 - chip->write_buf(mtd, oob, i);
633 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
634 + nand_rnd_write_buf(mtd, oob, i);
639 @@ -2504,6 +2660,7 @@ static int nand_write_page(struct mtd_in
641 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
643 + nand_rnd_config(mtd, page, 0, NAND_RND_WRITE);
645 status = chip->cur_ecc->write_page_raw(mtd, chip, buf,
647 @@ -2514,6 +2671,7 @@ static int nand_write_page(struct mtd_in
649 status = chip->cur_ecc->write_page(mtd, chip, buf,
651 + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
655 @@ -2803,6 +2961,8 @@ static int panic_nand_part_write(struct
656 panic_nand_get_device(chip, part->master, FL_WRITING);
658 chip->cur_ecc = part->ecc;
660 + chip->cur_rnd = part->rnd;
663 ops.datbuf = (uint8_t *)buf;
664 @@ -2811,6 +2971,7 @@ static int panic_nand_part_write(struct
666 ret = nand_do_write_ops(part->master, to, &ops);
668 + chip->cur_rnd = &chip->rnd;
669 chip->cur_ecc = &chip->ecc;
670 *retlen = ops.retlen;
672 @@ -2865,12 +3026,15 @@ static int nand_part_write(struct mtd_in
673 nand_get_device(part->master, FL_WRITING);
675 chip->cur_ecc = part->ecc;
677 + chip->cur_rnd = part->rnd;
679 ops.datbuf = (uint8_t *)buf;
681 ops.mode = MTD_OPS_PLACE_OOB;
682 ret = nand_do_write_ops(part->master, to, &ops);
683 *retlen = ops.retlen;
684 + chip->cur_rnd = &chip->rnd;
685 chip->cur_ecc = &chip->ecc;
686 nand_release_device(part->master);
688 @@ -3032,6 +3196,8 @@ static int nand_part_write_oob(struct mt
689 nand_get_device(part->master, FL_WRITING);
691 chip->cur_ecc = part->ecc;
693 + chip->cur_rnd = part->rnd;
696 case MTD_OPS_PLACE_OOB:
697 @@ -3049,6 +3215,7 @@ static int nand_part_write_oob(struct mt
698 ret = nand_do_write_ops(part->master, to, ops);
701 + chip->cur_rnd = &chip->rnd;
702 chip->cur_ecc = &chip->ecc;
703 nand_release_device(part->master);
705 @@ -4749,6 +4916,7 @@ int nand_scan_tail(struct mtd_info *mtd)
706 mutex_init(&chip->part_lock);
708 chip->cur_ecc = &chip->ecc;
709 + chip->cur_rnd = &chip->rnd;
711 /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
712 if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
713 --- a/include/linux/mtd/nand.h
714 +++ b/include/linux/mtd/nand.h
715 @@ -539,6 +539,64 @@ void nand_page_set_status(struct mtd_inf
717 int nand_pst_create(struct mtd_info *mtd);
720 + * Constants for randomizer modes
729 + * Constants for randomizer actions
731 +enum nand_rnd_action {
732 + NAND_RND_NO_ACTION,
738 + * struct nand_rndfree - Structure defining a NAND page region where the
739 + * randomizer should be disabled
740 + * @offset: range offset
741 + * @length: range length
743 +struct nand_rndfree {
749 + * struct nand_rnd_layout - Structure defining rndfree regions
750 + * @nranges: number of ranges
751 + * @ranges: array defining the rndfree regions
753 +struct nand_rnd_layout {
755 + struct nand_rndfree ranges[0];
759 + * struct nand_rnd_ctrl - Randomizer Control structure
760 + * @mode: Randomizer mode
761 + * @config: function to prepare the randomizer (i.e.: set the appropriate
762 + * seed/init value).
763 + * @read_buf: function that read from the NAND and descramble the retrieved
765 + * @write_buf: function that scramble data before writing it to the NAND.
767 +struct nand_rnd_ctrl {
768 + nand_rnd_modes_t mode;
769 + struct nand_rnd_layout *layout;
771 + int (*config)(struct mtd_info *mtd, int page, int column,
772 + enum nand_rnd_action action);
773 + void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
774 + void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
778 * struct nand_buffers - buffer structure for read/write
779 * @ecccalc: buffer pointer for calculated ECC, size is oobsize.
780 @@ -731,6 +789,9 @@ struct nand_chip {
781 struct nand_buffers *buffers;
782 struct nand_hw_control hwcontrol;
784 + struct nand_rnd_ctrl rnd;
785 + struct nand_rnd_ctrl *cur_rnd;
788 struct nand_bbt_descr *bbt_td;
789 struct nand_bbt_descr *bbt_md;
790 @@ -752,6 +813,7 @@ struct nand_chip {
791 * @master: MTD device representing the NAND chip
792 * @offset: partition offset
793 * @ecc: partition specific ECC struct
794 + * @rnd: partition specific randomizer struct
795 * @release: function used to release this nand_part struct
797 * NAND partitions work as standard MTD partitions except it can override
798 @@ -765,6 +827,7 @@ struct nand_part {
799 struct mtd_info *master;
801 struct nand_ecc_ctrl *ecc;
802 + struct nand_rnd_ctrl *rnd;
803 void (*release)(struct nand_part *part);
806 @@ -902,6 +965,41 @@ extern int nand_erase_nand(struct mtd_in
807 extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
808 size_t *retlen, uint8_t *buf);
810 +static inline int nand_rnd_config(struct mtd_info *mtd, int page, int column,
811 + enum nand_rnd_action action)
813 + struct nand_chip *chip = mtd->priv;
815 + if (chip->cur_rnd && chip->cur_rnd->config)
816 + return chip->cur_rnd->config(mtd, page, column, action);
821 +static inline void nand_rnd_write_buf(struct mtd_info *mtd, const uint8_t *buf,
824 + struct nand_chip *chip = mtd->priv;
826 + if (chip->cur_rnd && chip->cur_rnd->read_buf)
827 + chip->cur_rnd->write_buf(mtd, buf, len);
829 + chip->write_buf(mtd, buf, len);
832 +static inline void nand_rnd_read_buf(struct mtd_info *mtd, uint8_t *buf,
835 + struct nand_chip *chip = mtd->priv;
837 + if (chip->cur_rnd && chip->cur_rnd->read_buf)
838 + chip->cur_rnd->read_buf(mtd, buf, len);
840 + chip->read_buf(mtd, buf, len);
843 +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len);
846 * struct platform_nand_chip - chip level device structure
847 * @nr_chips: max. number of chips to scan for