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 diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
38 index 8a5d12e..577cb9e 100644
39 --- a/drivers/mtd/nand/nand_base.c
40 +++ b/drivers/mtd/nand/nand_base.c
41 @@ -1102,6 +1102,62 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
42 EXPORT_SYMBOL(nand_lock);
45 + * nand_rnd_is_activ - check wether a region of a NAND page requires NAND
46 + * randomizer to be disabled
49 + * @column: offset within the page
50 + * @len: len of the region
52 + * Returns 1 if the randomizer should be enabled, 0 if not, or -ERR in case of
55 + * In case of success len will contain the size of the region:
56 + * - if the requested region fits in a NAND random region len will not change
57 + * - else len will be replaced by the available length within the NAND random
60 +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len)
62 + struct nand_chip *chip = mtd->priv;
63 + struct nand_rnd_layout *layout = chip->cur_rnd->layout;
64 + struct nand_rndfree *range;
69 + if (!len || *len < 0 || column < 0 ||
70 + column + *len > mtd->writesize + mtd->oobsize)
74 + for (i = 0; i < layout->nranges; i++) {
75 + range = &layout->ranges[i];
76 + if (column + *len <= range->offset) {
78 + } else if (column >= range->offset + range->length) {
80 + } else if (column < range->offset) {
81 + tmp = range->offset - column;
86 + tmp = range->offset + range->length - column;
98 +EXPORT_SYMBOL(nand_rnd_is_activ);
101 * nand_page_is_empty - check wether a NAND page contains only FFs
104 @@ -1246,9 +1302,14 @@ EXPORT_SYMBOL(nand_pst_create);
105 static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
106 uint8_t *buf, int oob_required, int page)
108 - chip->read_buf(mtd, buf, mtd->writesize);
110 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
111 + nand_rnd_config(mtd, page, 0, NAND_RND_READ);
112 + nand_rnd_read_buf(mtd, buf, mtd->writesize);
113 + if (oob_required) {
114 + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
115 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
117 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
122 @@ -1270,28 +1331,40 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
123 int eccbytes = chip->cur_ecc->bytes;
124 uint8_t *oob = chip->oob_poi;
128 for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
129 - chip->read_buf(mtd, buf, eccsize);
130 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
131 + nand_rnd_read_buf(mtd, buf, eccsize);
135 if (chip->cur_ecc->prepad) {
136 - chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
137 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
138 + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->prepad);
139 oob += chip->cur_ecc->prepad;
140 + column += chip->cur_ecc->prepad;
143 - chip->read_buf(mtd, oob, eccbytes);
144 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
145 + nand_rnd_read_buf(mtd, oob, eccbytes);
147 + column += eccbytes;
149 if (chip->cur_ecc->postpad) {
150 - chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
151 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
152 + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->postpad);
153 oob += chip->cur_ecc->postpad;
154 + column += chip->cur_ecc->postpad;
158 size = mtd->oobsize - (oob - chip->oob_poi);
160 - chip->read_buf(mtd, oob, size);
162 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
163 + nand_rnd_read_buf(mtd, oob, size);
165 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
169 @@ -1380,7 +1453,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
170 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
172 p = bufpoi + data_col_addr;
173 - chip->read_buf(mtd, p, datafrag_len);
174 + nand_rnd_config(mtd, -1, data_col_addr, NAND_RND_READ);
175 + nand_rnd_read_buf(mtd, p, datafrag_len);
178 for (i = 0; i < eccfrag_len;
179 @@ -1399,7 +1473,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
182 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
183 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
184 + nand_rnd_config(mtd, -1, mtd->writesize, NAND_RND_READ);
185 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
188 * Send the command to read the particular ECC bytes take care
189 @@ -1415,7 +1490,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
191 chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
192 mtd->writesize + aligned_pos, -1);
193 - chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
194 + nand_rnd_config(mtd, -1, mtd->writesize + aligned_pos, NAND_RND_READ);
195 + nand_rnd_read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
198 for (i = 0; i < eccfrag_len; i++)
199 @@ -1436,6 +1512,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
200 max_bitflips = max_t(unsigned int, max_bitflips, stat);
203 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
207 @@ -1460,13 +1537,17 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
208 uint8_t *ecc_code = chip->buffers->ecccode;
209 uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
210 unsigned int max_bitflips = 0;
213 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
214 chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
215 - chip->read_buf(mtd, p, eccsize);
216 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
217 + nand_rnd_read_buf(mtd, p, eccsize);
218 chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
221 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
222 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
223 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
225 for (i = 0; i < chip->cur_ecc->total; i++)
226 ecc_code[i] = chip->oob_poi[eccpos[i]];
227 @@ -1486,6 +1567,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
228 max_bitflips = max_t(unsigned int, max_bitflips, stat);
231 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
235 @@ -1514,11 +1596,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
236 uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
237 uint8_t *ecc_calc = chip->buffers->ecccalc;
238 unsigned int max_bitflips = 0;
241 /* Read the OOB area first */
242 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
243 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
244 + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
245 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
246 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
249 for (i = 0; i < chip->cur_ecc->total; i++)
250 ecc_code[i] = chip->oob_poi[eccpos[i]];
251 @@ -1527,7 +1612,8 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
254 chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
255 - chip->read_buf(mtd, p, eccsize);
256 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
257 + nand_rnd_read_buf(mtd, p, eccsize);
258 chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
260 stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i], NULL);
261 @@ -1538,6 +1624,7 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
262 max_bitflips = max_t(unsigned int, max_bitflips, stat);
265 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
269 @@ -1561,20 +1648,27 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
271 uint8_t *oob = chip->oob_poi;
272 unsigned int max_bitflips = 0;
275 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
278 chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
279 - chip->read_buf(mtd, p, eccsize);
280 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
281 + nand_rnd_read_buf(mtd, p, eccsize);
284 if (chip->cur_ecc->prepad) {
285 - chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
286 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
287 + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->prepad);
288 oob += chip->cur_ecc->prepad;
291 chip->cur_ecc->hwctl(mtd, NAND_ECC_READSYN);
292 - chip->read_buf(mtd, oob, eccbytes);
293 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
294 + nand_rnd_read_buf(mtd, oob, eccbytes);
295 + column += eccbytes;
297 stat = chip->cur_ecc->correct(mtd, p, oob, NULL);
300 @@ -1587,29 +1681,36 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
303 if (chip->cur_ecc->postpad) {
304 - chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
305 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
306 + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->postpad);
307 + column += chip->cur_ecc->postpad;
308 oob += chip->cur_ecc->postpad;
312 /* Calculate remaining oob bytes */
313 i = mtd->oobsize - (oob - chip->oob_poi);
315 - chip->read_buf(mtd, oob, i);
317 + nand_rnd_config(mtd, page, column, NAND_RND_READ);
318 + nand_rnd_read_buf(mtd, oob, i);
320 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
326 * nand_transfer_oob - [INTERN] Transfer oob to client buffer
327 - * @chip: nand chip structure
328 + * @mtd: mtd structure
329 * @oob: oob destination address
330 * @ops: oob ops structure
331 * @len: size of oob to transfer
333 -static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
334 +static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob,
335 struct mtd_oob_ops *ops, size_t len)
337 + struct nand_chip *chip = mtd->priv;
341 case MTD_OPS_PLACE_OOB:
342 @@ -1737,6 +1838,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
343 * Now read the page into the buffer. Absent an error,
344 * the read methods return max bitflips per ecc step.
346 + nand_rnd_config(mtd, page, -1, NAND_RND_READ);
347 if (unlikely(ops->mode == MTD_OPS_RAW))
348 ret = chip->cur_ecc->read_page_raw(mtd, chip,
350 @@ -1753,6 +1855,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
354 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
358 /* Invalidate page cache */
359 @@ -1780,8 +1884,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
360 int toread = min(oobreadlen, max_oobsize);
363 - oob = nand_transfer_oob(chip,
365 + oob = nand_transfer_oob(mtd, oob, ops,
367 oobreadlen -= toread;
370 @@ -1909,12 +2013,15 @@ static int nand_part_read(struct mtd_info *mtd, loff_t from, size_t len,
371 nand_get_device(part->master, FL_READING);
373 chip->cur_ecc = part->ecc;
375 + chip->cur_rnd = part->rnd;
379 ops.mode = MTD_OPS_PLACE_OOB;
380 ret = nand_do_read_ops(part->master, from, &ops);
381 *retlen = ops.retlen;
382 + chip->cur_rnd = &chip->rnd;
383 chip->cur_ecc = &chip->ecc;
384 nand_release_device(part->master);
386 @@ -1930,7 +2037,9 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
389 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
390 - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
391 + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
392 + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
393 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
397 @@ -1949,7 +2058,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
398 chip->cur_ecc->postpad;
399 int eccsize = chip->cur_ecc->size;
400 uint8_t *bufpoi = chip->oob_poi;
401 - int i, toread, sndrnd = 0, pos;
402 + int i, toread, sndrnd = 0, pos = eccsize;
404 chip->cmdfunc(mtd, NAND_CMD_READ0, chip->cur_ecc->size, page);
405 for (i = 0; i < chip->cur_ecc->steps; i++) {
406 @@ -1962,12 +2071,17 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
409 toread = min_t(int, length, chunk);
410 - chip->read_buf(mtd, bufpoi, toread);
411 + nand_rnd_config(mtd, page, pos, NAND_RND_READ);
412 + nand_rnd_read_buf(mtd, bufpoi, toread);
417 - chip->read_buf(mtd, bufpoi, length);
419 + pos = mtd->writesize + mtd->oobsize - length;
420 + nand_rnd_config(mtd, page, pos, NAND_RND_READ);
421 + nand_rnd_read_buf(mtd, bufpoi, length);
423 + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
427 @@ -1986,7 +2100,9 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
428 int length = mtd->oobsize;
430 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
431 - chip->write_buf(mtd, buf, length);
432 + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_WRITE);
433 + nand_rnd_write_buf(mtd, buf, length);
434 + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
435 /* Send command to program the OOB data */
436 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
438 @@ -2042,12 +2158,18 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,
441 len = min_t(int, length, chunk);
442 - chip->write_buf(mtd, bufpoi, len);
443 + nand_rnd_config(mtd, page, pos, NAND_RND_WRITE);
444 + nand_rnd_write_buf(mtd, bufpoi, len);
449 - chip->write_buf(mtd, bufpoi, length);
451 + pos = mtd->writesize + mtd->oobsize - length;
452 + nand_rnd_config(mtd, page, pos, NAND_RND_WRITE);
453 + nand_rnd_write_buf(mtd, bufpoi, length);
456 + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
458 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
459 status = chip->waitfunc(mtd, chip);
460 @@ -2116,7 +2238,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
463 len = min(len, readlen);
464 - buf = nand_transfer_oob(chip, buf, ops, len);
465 + buf = nand_transfer_oob(mtd, buf, ops, len);
467 if (chip->options & NAND_NEED_READRDY) {
468 /* Apply delay or wait for ready/busy pin */
469 @@ -2226,6 +2348,8 @@ static int nand_part_read_oob(struct mtd_info *mtd, loff_t from,
470 nand_get_device(part->master, FL_READING);
472 chip->cur_ecc = part->ecc;
474 + chip->cur_rnd = part->rnd;
477 case MTD_OPS_PLACE_OOB:
478 @@ -2243,6 +2367,7 @@ static int nand_part_read_oob(struct mtd_info *mtd, loff_t from,
479 ret = nand_do_read_ops(part->master, from, ops);
482 + chip->cur_rnd = &chip->rnd;
483 chip->cur_ecc = &chip->ecc;
484 nand_release_device(part->master);
486 @@ -2261,9 +2386,11 @@ static int nand_part_read_oob(struct mtd_info *mtd, loff_t from,
487 static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
488 const uint8_t *buf, int oob_required)
490 - chip->write_buf(mtd, buf, mtd->writesize);
492 - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
493 + nand_rnd_write_buf(mtd, buf, mtd->writesize);
494 + if (oob_required) {
495 + nand_rnd_config(mtd, -1, mtd->writesize, NAND_RND_WRITE);
496 + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
501 @@ -2285,28 +2412,39 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
502 int eccbytes = chip->cur_ecc->bytes;
503 uint8_t *oob = chip->oob_poi;
507 for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
508 - chip->write_buf(mtd, buf, eccsize);
509 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
510 + nand_rnd_write_buf(mtd, buf, eccsize);
514 if (chip->cur_ecc->prepad) {
515 - chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
516 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
517 + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->prepad);
518 oob += chip->cur_ecc->prepad;
519 + column += chip->cur_ecc->prepad;
522 - chip->write_buf(mtd, oob, eccbytes);
523 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
524 + nand_rnd_write_buf(mtd, oob, eccbytes);
526 + column += eccbytes;
528 if (chip->cur_ecc->postpad) {
529 - chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
530 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
531 + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->postpad);
532 oob += chip->cur_ecc->postpad;
533 + column += chip->cur_ecc->postpad;
537 size = mtd->oobsize - (oob - chip->oob_poi);
539 - chip->write_buf(mtd, oob, size);
541 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
542 + nand_rnd_write_buf(mtd, oob, size);
547 @@ -2353,17 +2491,21 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
548 uint8_t *ecc_calc = chip->buffers->ecccalc;
549 const uint8_t *p = buf;
550 uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
553 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
554 chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
555 - chip->write_buf(mtd, p, eccsize);
556 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
557 + nand_rnd_write_buf(mtd, p, eccsize);
558 chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
562 for (i = 0; i < chip->cur_ecc->total; i++)
563 chip->oob_poi[eccpos[i]] = ecc_calc[i];
565 - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
566 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
567 + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
571 @@ -2399,7 +2541,9 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
572 chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
574 /* write data (untouched subpages already masked by 0xFF) */
575 - chip->write_buf(mtd, buf, ecc_size);
576 + nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE);
577 + nand_rnd_write_buf(mtd, buf, ecc_size);
578 + offset += ecc_size;
580 /* mask ECC of un-touched subpages by padding 0xFF */
581 if ((step < start_step) || (step > end_step))
582 @@ -2424,7 +2568,8 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
583 chip->oob_poi[eccpos[i]] = ecc_calc[i];
585 /* write OOB buffer to NAND device */
586 - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
587 + nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE);
588 + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
592 @@ -2449,31 +2594,42 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
593 int eccsteps = chip->cur_ecc->steps;
594 const uint8_t *p = buf;
595 uint8_t *oob = chip->oob_poi;
598 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
600 chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
601 - chip->write_buf(mtd, p, eccsize);
602 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
603 + nand_rnd_write_buf(mtd, p, eccsize);
606 if (chip->cur_ecc->prepad) {
607 - chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
608 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
609 + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->prepad);
610 oob += chip->cur_ecc->prepad;
611 + column += chip->cur_ecc->prepad;
614 chip->cur_ecc->calculate(mtd, p, oob);
615 - chip->write_buf(mtd, oob, eccbytes);
616 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
617 + nand_rnd_write_buf(mtd, oob, eccbytes);
619 + column += eccbytes;
621 if (chip->cur_ecc->postpad) {
622 - chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
623 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
624 + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->postpad);
625 oob += chip->cur_ecc->postpad;
626 + column += chip->cur_ecc->postpad;
630 /* Calculate remaining oob bytes */
631 i = mtd->oobsize - (oob - chip->oob_poi);
633 - chip->write_buf(mtd, oob, i);
635 + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
636 + nand_rnd_write_buf(mtd, oob, i);
641 @@ -2504,6 +2660,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
643 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
645 + nand_rnd_config(mtd, page, 0, NAND_RND_WRITE);
647 status = chip->cur_ecc->write_page_raw(mtd, chip, buf,
649 @@ -2514,6 +2671,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
651 status = chip->cur_ecc->write_page(mtd, chip, buf,
653 + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
657 @@ -2803,6 +2961,8 @@ static int panic_nand_part_write(struct mtd_info *mtd, loff_t to, size_t len,
658 panic_nand_get_device(chip, part->master, FL_WRITING);
660 chip->cur_ecc = part->ecc;
662 + chip->cur_rnd = part->rnd;
665 ops.datbuf = (uint8_t *)buf;
666 @@ -2811,6 +2971,7 @@ static int panic_nand_part_write(struct mtd_info *mtd, loff_t to, size_t len,
668 ret = nand_do_write_ops(part->master, to, &ops);
670 + chip->cur_rnd = &chip->rnd;
671 chip->cur_ecc = &chip->ecc;
672 *retlen = ops.retlen;
674 @@ -2865,12 +3026,15 @@ static int nand_part_write(struct mtd_info *mtd, loff_t to, size_t len,
675 nand_get_device(part->master, FL_WRITING);
677 chip->cur_ecc = part->ecc;
679 + chip->cur_rnd = part->rnd;
681 ops.datbuf = (uint8_t *)buf;
683 ops.mode = MTD_OPS_PLACE_OOB;
684 ret = nand_do_write_ops(part->master, to, &ops);
685 *retlen = ops.retlen;
686 + chip->cur_rnd = &chip->rnd;
687 chip->cur_ecc = &chip->ecc;
688 nand_release_device(part->master);
690 @@ -3032,6 +3196,8 @@ static int nand_part_write_oob(struct mtd_info *mtd, loff_t to,
691 nand_get_device(part->master, FL_WRITING);
693 chip->cur_ecc = part->ecc;
695 + chip->cur_rnd = part->rnd;
698 case MTD_OPS_PLACE_OOB:
699 @@ -3049,6 +3215,7 @@ static int nand_part_write_oob(struct mtd_info *mtd, loff_t to,
700 ret = nand_do_write_ops(part->master, to, ops);
703 + chip->cur_rnd = &chip->rnd;
704 chip->cur_ecc = &chip->ecc;
705 nand_release_device(part->master);
707 @@ -4749,6 +4916,7 @@ int nand_scan_tail(struct mtd_info *mtd)
708 mutex_init(&chip->part_lock);
710 chip->cur_ecc = &chip->ecc;
711 + chip->cur_rnd = &chip->rnd;
713 /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
714 if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
715 diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
716 index 4f7ca8d..6cbd06a3 100644
717 --- a/include/linux/mtd/nand.h
718 +++ b/include/linux/mtd/nand.h
719 @@ -539,6 +539,64 @@ void nand_page_set_status(struct mtd_info *mtd, int page,
721 int nand_pst_create(struct mtd_info *mtd);
724 + * Constants for randomizer modes
733 + * Constants for randomizer actions
735 +enum nand_rnd_action {
736 + NAND_RND_NO_ACTION,
742 + * struct nand_rndfree - Structure defining a NAND page region where the
743 + * randomizer should be disabled
744 + * @offset: range offset
745 + * @length: range length
747 +struct nand_rndfree {
753 + * struct nand_rnd_layout - Structure defining rndfree regions
754 + * @nranges: number of ranges
755 + * @ranges: array defining the rndfree regions
757 +struct nand_rnd_layout {
759 + struct nand_rndfree ranges[0];
763 + * struct nand_rnd_ctrl - Randomizer Control structure
764 + * @mode: Randomizer mode
765 + * @config: function to prepare the randomizer (i.e.: set the appropriate
766 + * seed/init value).
767 + * @read_buf: function that read from the NAND and descramble the retrieved
769 + * @write_buf: function that scramble data before writing it to the NAND.
771 +struct nand_rnd_ctrl {
772 + nand_rnd_modes_t mode;
773 + struct nand_rnd_layout *layout;
775 + int (*config)(struct mtd_info *mtd, int page, int column,
776 + enum nand_rnd_action action);
777 + void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
778 + void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
782 * struct nand_buffers - buffer structure for read/write
783 * @ecccalc: buffer pointer for calculated ECC, size is oobsize.
784 @@ -731,6 +789,9 @@ struct nand_chip {
785 struct nand_buffers *buffers;
786 struct nand_hw_control hwcontrol;
788 + struct nand_rnd_ctrl rnd;
789 + struct nand_rnd_ctrl *cur_rnd;
792 struct nand_bbt_descr *bbt_td;
793 struct nand_bbt_descr *bbt_md;
794 @@ -752,6 +813,7 @@ struct nand_chip {
795 * @master: MTD device representing the NAND chip
796 * @offset: partition offset
797 * @ecc: partition specific ECC struct
798 + * @rnd: partition specific randomizer struct
799 * @release: function used to release this nand_part struct
801 * NAND partitions work as standard MTD partitions except it can override
802 @@ -765,6 +827,7 @@ struct nand_part {
803 struct mtd_info *master;
805 struct nand_ecc_ctrl *ecc;
806 + struct nand_rnd_ctrl *rnd;
807 void (*release)(struct nand_part *part);
810 @@ -902,6 +965,41 @@ extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
811 extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
812 size_t *retlen, uint8_t *buf);
814 +static inline int nand_rnd_config(struct mtd_info *mtd, int page, int column,
815 + enum nand_rnd_action action)
817 + struct nand_chip *chip = mtd->priv;
819 + if (chip->cur_rnd && chip->cur_rnd->config)
820 + return chip->cur_rnd->config(mtd, page, column, action);
825 +static inline void nand_rnd_write_buf(struct mtd_info *mtd, const uint8_t *buf,
828 + struct nand_chip *chip = mtd->priv;
830 + if (chip->cur_rnd && chip->cur_rnd->read_buf)
831 + chip->cur_rnd->write_buf(mtd, buf, len);
833 + chip->write_buf(mtd, buf, len);
836 +static inline void nand_rnd_read_buf(struct mtd_info *mtd, uint8_t *buf,
839 + struct nand_chip *chip = mtd->priv;
841 + if (chip->cur_rnd && chip->cur_rnd->read_buf)
842 + chip->cur_rnd->read_buf(mtd, buf, len);
844 + chip->read_buf(mtd, buf, len);
847 +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len);
850 * struct platform_nand_chip - chip level device structure
851 * @nr_chips: max. number of chips to scan for