sunxi: add support for 4.1
[openwrt.git] / target / linux / sunxi / patches-4.1 / 114-mtd-randomizer-into-nand-framework.patch
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
5
6 This patch introduce a new layer in the NAND framework to support both HW
7 and SW randomizers.
8
9 This randomization is required on some MLC/TLC NAND chips which do not
10 support large islands of same patterns.
11
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.
15
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
20
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.
26
27 The randomizer layer provides helper functions that choose wether the
28 randomizer or the chip read/write_buf should be used.
29
30 Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
31 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
32 ---
33  drivers/mtd/nand/nand_base.c | 278 ++++++++++++++++++++++++++++++++++---------
34  include/linux/mtd/nand.h     |  98 +++++++++++++++
35  2 files changed, 321 insertions(+), 55 deletions(-)
36
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);
43  
44  /**
45 + * nand_rnd_is_activ - check wether a region of a NAND page requires NAND
46 + *                    randomizer to be disabled
47 + * @mtd:       mtd info
48 + * @page:      NAND page
49 + * @column:    offset within the page
50 + * @len:       len of the region
51 + *
52 + * Returns 1 if the randomizer should be enabled, 0 if not, or -ERR in case of
53 + * error.
54 + *
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
58 + *    region
59 + */
60 +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len)
61 +{
62 +       struct nand_chip *chip = mtd->priv;
63 +       struct nand_rnd_layout *layout = chip->cur_rnd->layout;
64 +       struct nand_rndfree *range;
65 +       int ret = 1;
66 +       int tmp;
67 +       int i;
68 +
69 +       if (!len || *len < 0 || column < 0 ||
70 +           column + *len > mtd->writesize + mtd->oobsize)
71 +               return -EINVAL;
72 +
73 +       if (layout) {
74 +               for (i = 0; i < layout->nranges; i++) {
75 +                       range = &layout->ranges[i];
76 +                       if (column + *len <= range->offset) {
77 +                               break;
78 +                       } else if (column >= range->offset + range->length) {
79 +                               continue;
80 +                       } else if (column < range->offset) {
81 +                               tmp = range->offset - column;
82 +                               if (*len > tmp)
83 +                                       *len = tmp;
84 +                               break;
85 +                       } else {
86 +                               tmp = range->offset + range->length - column;
87 +                               if (*len > tmp)
88 +                                       *len = tmp;
89 +                               ret = 0;
90 +                               break;
91 +                       }
92 +
93 +               }
94 +       }
95 +
96 +       return ret;
97 +}
98 +EXPORT_SYMBOL(nand_rnd_is_activ);
99 +
100 +/**
101   * nand_page_is_empty - check wether a NAND page contains only FFs
102   * @mtd:       mtd info
103   * @data:      data buffer
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)
107  {
108 -       chip->read_buf(mtd, buf, mtd->writesize);
109 -       if (oob_required)
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);
116 +       }
117 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
118 +
119         return 0;
120  }
121  
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;
125         int steps, size;
126 +       int column = 0;
127  
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);
132                 buf += eccsize;
133 +               column += eccsize;
134  
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;
141                 }
142  
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);
146                 oob += eccbytes;
147 +               column += eccbytes;
148  
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;
155                 }
156         }
157  
158         size = mtd->oobsize - (oob - chip->oob_poi);
159 -       if (size)
160 -               chip->read_buf(mtd, oob, size);
161 +       if (size) {
162 +               nand_rnd_config(mtd, page, column, NAND_RND_READ);
163 +               nand_rnd_read_buf(mtd, oob, size);
164 +       }
165 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
166  
167         return 0;
168  }
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);
171  
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);
176  
177         /* Calculate ECC */
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,
180         }
181         if (gaps) {
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);
186         } else {
187                 /*
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,
190  
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);
196         }
197  
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);
201                 }
202         }
203 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
204         return max_bitflips;
205  }
206  
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;
211 +       int column = 0;
212  
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]);
219 +               column += eccsize;
220         }
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);
224  
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);
229                 }
230         }
231 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
232         return max_bitflips;
233  }
234  
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;
239 +       int column = 0;
240  
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);
247 +       column = 0;
248  
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,
252                 int stat;
253  
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]);
259  
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);
263                 }
264         }
265 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
266         return max_bitflips;
267  }
268  
269 @@ -1561,20 +1648,27 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
270         uint8_t *p = buf;
271         uint8_t *oob = chip->oob_poi;
272         unsigned int max_bitflips = 0;
273 +       int column = 0;
274  
275         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
276                 int stat;
277  
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);
282 +               column += eccsize;
283  
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;
289                 }
290  
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;
296 +
297                 stat = chip->cur_ecc->correct(mtd, p, oob, NULL);
298  
299                 if (stat < 0) {
300 @@ -1587,29 +1681,36 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
301                 oob += eccbytes;
302  
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;
309                 }
310         }
311  
312         /* Calculate remaining oob bytes */
313         i = mtd->oobsize - (oob - chip->oob_poi);
314 -       if (i)
315 -               chip->read_buf(mtd, oob, i);
316 +       if (i) {
317 +               nand_rnd_config(mtd, page, column, NAND_RND_READ);
318 +               nand_rnd_read_buf(mtd, oob, i);
319 +       }
320 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
321  
322         return max_bitflips;
323  }
324  
325  /**
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
332   */
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)
336  {
337 +       struct nand_chip *chip = mtd->priv;
338 +
339         switch (ops->mode) {
340  
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.
345                          */
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,
349                                                                 bufpoi,
350 @@ -1753,6 +1855,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
351                                                                bufpoi,
352                                                                oob_required,
353                                                                page);
354 +                       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
355 +
356                         if (ret < 0) {
357                                 if (use_bufpoi)
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);
361  
362                                 if (toread) {
363 -                                       oob = nand_transfer_oob(chip,
364 -                                               oob, ops, toread);
365 +                                       oob = nand_transfer_oob(mtd, oob, ops,
366 +                                                               toread);
367                                         oobreadlen -= toread;
368                                 }
369                         }
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);
372         if (part->ecc)
373                 chip->cur_ecc = part->ecc;
374 +       if (part->rnd)
375 +               chip->cur_rnd = part->rnd;
376         ops.len = len;
377         ops.datbuf = buf;
378         ops.oobbuf = NULL;
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);
385         return ret;
386 @@ -1930,7 +2037,9 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
387                              int page)
388  {
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);
394         return 0;
395  }
396  
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;
403  
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,
407                 } else
408                         sndrnd = 1;
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);
413                 bufpoi += toread;
414                 length -= toread;
415         }
416 -       if (length > 0)
417 -               chip->read_buf(mtd, bufpoi, length);
418 +       if (length > 0) {
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);
422 +       }
423 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
424  
425         return 0;
426  }
427 @@ -1986,7 +2100,9 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
428         int length = mtd->oobsize;
429  
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);
437  
438 @@ -2042,12 +2158,18 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,
439                 } else
440                         sndcmd = 1;
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);
445                 bufpoi += len;
446                 length -= len;
447         }
448 -       if (length > 0)
449 -               chip->write_buf(mtd, bufpoi, length);
450 +       if (length > 0) {
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);
454 +       }
455 +
456 +       nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
457  
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,
461                         break;
462  
463                 len = min(len, readlen);
464 -               buf = nand_transfer_oob(chip, buf, ops, len);
465 +               buf = nand_transfer_oob(mtd, buf, ops, len);
466  
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);
471         if (part->ecc)
472                 chip->cur_ecc = part->ecc;
473 +       if (part->rnd)
474 +               chip->cur_rnd = part->rnd;
475  
476         switch (ops->mode) {
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);
480  
481  out:
482 +       chip->cur_rnd = &chip->rnd;
483         chip->cur_ecc = &chip->ecc;
484         nand_release_device(part->master);
485         return ret;
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)
489  {
490 -       chip->write_buf(mtd, buf, mtd->writesize);
491 -       if (oob_required)
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);
497 +       }
498  
499         return 0;
500  }
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;
504         int steps, size;
505 +       int column = 0;
506  
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);
511                 buf += eccsize;
512 +               column += eccsize;
513  
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;
520                 }
521  
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);
525                 oob += eccbytes;
526 +               column += eccbytes;
527  
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;
534                 }
535         }
536  
537         size = mtd->oobsize - (oob - chip->oob_poi);
538 -       if (size)
539 -               chip->write_buf(mtd, oob, size);
540 +       if (size) {
541 +               nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
542 +               nand_rnd_write_buf(mtd, oob, size);
543 +       }
544  
545         return 0;
546  }
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;
551 +       int column = 0;
552  
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]);
559 +               column += eccsize;
560         }
561  
562         for (i = 0; i < chip->cur_ecc->total; i++)
563                 chip->oob_poi[eccpos[i]] = ecc_calc[i];
564  
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);
568  
569         return 0;
570  }
571 @@ -2399,7 +2541,9 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
572                 chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
573  
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;
579  
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];
584  
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);
589  
590         return 0;
591  }
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;
596 +       int column = 0;
597  
598         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
599  
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);
604 +               column += eccsize;
605  
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;
612                 }
613  
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);
618                 oob += eccbytes;
619 +               column += eccbytes;
620  
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;
627                 }
628         }
629  
630         /* Calculate remaining oob bytes */
631         i = mtd->oobsize - (oob - chip->oob_poi);
632 -       if (i)
633 -               chip->write_buf(mtd, oob, i);
634 +       if (i) {
635 +               nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
636 +               nand_rnd_write_buf(mtd, oob, i);
637 +       }
638  
639         return 0;
640  }
641 @@ -2504,6 +2660,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
642  
643         chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
644  
645 +       nand_rnd_config(mtd, page, 0, NAND_RND_WRITE);
646         if (unlikely(raw))
647                 status = chip->cur_ecc->write_page_raw(mtd, chip, buf,
648                                                        oob_required);
649 @@ -2514,6 +2671,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
650         else
651                 status = chip->cur_ecc->write_page(mtd, chip, buf,
652                                                    oob_required);
653 +       nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
654  
655         if (status < 0)
656                 return status;
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);
659         if (part->ecc)
660                 chip->cur_ecc = part->ecc;
661 +       if (part->rnd)
662 +               chip->cur_rnd = part->rnd;
663  
664         ops.len = len;
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,
667  
668         ret = nand_do_write_ops(part->master, to, &ops);
669  
670 +       chip->cur_rnd = &chip->rnd;
671         chip->cur_ecc = &chip->ecc;
672         *retlen = ops.retlen;
673         return ret;
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);
676         if (part->ecc)
677                 chip->cur_ecc = part->ecc;
678 +       if (part->rnd)
679 +               chip->cur_rnd = part->rnd;
680         ops.len = len;
681         ops.datbuf = (uint8_t *)buf;
682         ops.oobbuf = NULL;
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);
689         return ret;
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);
692         if (part->ecc)
693                 chip->cur_ecc = part->ecc;
694 +       if (part->rnd)
695 +               chip->cur_rnd = part->rnd;
696  
697         switch (ops->mode) {
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);
701  
702  out:
703 +       chip->cur_rnd = &chip->rnd;
704         chip->cur_ecc = &chip->ecc;
705         nand_release_device(part->master);
706         return ret;
707 @@ -4749,6 +4916,7 @@ int nand_scan_tail(struct mtd_info *mtd)
708         mutex_init(&chip->part_lock);
709  
710         chip->cur_ecc = &chip->ecc;
711 +       chip->cur_rnd = &chip->rnd;
712  
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,
720  
721  int nand_pst_create(struct mtd_info *mtd);
722  
723 +/*
724 + * Constants for randomizer modes
725 + */
726 +typedef enum {
727 +       NAND_RND_NONE,
728 +       NAND_RND_SOFT,
729 +       NAND_RND_HW,
730 +} nand_rnd_modes_t;
731 +
732 +/*
733 + * Constants for randomizer actions
734 + */
735 +enum nand_rnd_action {
736 +       NAND_RND_NO_ACTION,
737 +       NAND_RND_READ,
738 +       NAND_RND_WRITE,
739 +};
740 +
741 +/**
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
746 + */
747 +struct nand_rndfree {
748 +       u32 offset;
749 +       u32 length;
750 +};
751 +
752 +/**
753 + * struct nand_rnd_layout - Structure defining rndfree regions
754 + * @nranges:   number of ranges
755 + * @ranges:    array defining the rndfree regions
756 + */
757 +struct nand_rnd_layout {
758 +       int nranges;
759 +       struct nand_rndfree ranges[0];
760 +};
761 +
762 +/**
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
768 + *             data.
769 + * @write_buf: function that scramble data before writing it to the NAND.
770 + */
771 +struct nand_rnd_ctrl {
772 +       nand_rnd_modes_t mode;
773 +       struct nand_rnd_layout *layout;
774 +       void *priv;
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);
779 +};
780 +
781  /**
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;
787  
788 +       struct nand_rnd_ctrl rnd;
789 +       struct nand_rnd_ctrl *cur_rnd;
790 +
791         uint8_t *bbt;
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
800   *
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;
804         uint64_t offset;
805         struct nand_ecc_ctrl *ecc;
806 +       struct nand_rnd_ctrl *rnd;
807         void (*release)(struct nand_part *part);
808  };
809  
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);
813  
814 +static inline int nand_rnd_config(struct mtd_info *mtd, int page, int column,
815 +                                 enum nand_rnd_action action)
816 +{
817 +       struct nand_chip *chip = mtd->priv;
818 +
819 +       if (chip->cur_rnd && chip->cur_rnd->config)
820 +               return chip->cur_rnd->config(mtd, page, column, action);
821 +
822 +       return 0;
823 +}
824 +
825 +static inline void nand_rnd_write_buf(struct mtd_info *mtd, const uint8_t *buf,
826 +                                    int len)
827 +{
828 +       struct nand_chip *chip = mtd->priv;
829 +
830 +       if (chip->cur_rnd && chip->cur_rnd->read_buf)
831 +               chip->cur_rnd->write_buf(mtd, buf, len);
832 +       else
833 +               chip->write_buf(mtd, buf, len);
834 +}
835 +
836 +static inline void nand_rnd_read_buf(struct mtd_info *mtd, uint8_t *buf,
837 +                                   int len)
838 +{
839 +       struct nand_chip *chip = mtd->priv;
840 +
841 +       if (chip->cur_rnd && chip->cur_rnd->read_buf)
842 +               chip->cur_rnd->read_buf(mtd, buf, len);
843 +       else
844 +               chip->read_buf(mtd, buf, len);
845 +}
846 +
847 +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len);
848 +
849  /**
850   * struct platform_nand_chip - chip level device structure
851   * @nr_chips:          max. number of chips to scan for