kernel: update 4.1 to 4.1.5
[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 --- 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);
41  
42  /**
43 + * nand_rnd_is_activ - check wether a region of a NAND page requires NAND
44 + *                    randomizer to be disabled
45 + * @mtd:       mtd info
46 + * @page:      NAND page
47 + * @column:    offset within the page
48 + * @len:       len of the region
49 + *
50 + * Returns 1 if the randomizer should be enabled, 0 if not, or -ERR in case of
51 + * error.
52 + *
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
56 + *    region
57 + */
58 +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len)
59 +{
60 +       struct nand_chip *chip = mtd->priv;
61 +       struct nand_rnd_layout *layout = chip->cur_rnd->layout;
62 +       struct nand_rndfree *range;
63 +       int ret = 1;
64 +       int tmp;
65 +       int i;
66 +
67 +       if (!len || *len < 0 || column < 0 ||
68 +           column + *len > mtd->writesize + mtd->oobsize)
69 +               return -EINVAL;
70 +
71 +       if (layout) {
72 +               for (i = 0; i < layout->nranges; i++) {
73 +                       range = &layout->ranges[i];
74 +                       if (column + *len <= range->offset) {
75 +                               break;
76 +                       } else if (column >= range->offset + range->length) {
77 +                               continue;
78 +                       } else if (column < range->offset) {
79 +                               tmp = range->offset - column;
80 +                               if (*len > tmp)
81 +                                       *len = tmp;
82 +                               break;
83 +                       } else {
84 +                               tmp = range->offset + range->length - column;
85 +                               if (*len > tmp)
86 +                                       *len = tmp;
87 +                               ret = 0;
88 +                               break;
89 +                       }
90 +
91 +               }
92 +       }
93 +
94 +       return ret;
95 +}
96 +EXPORT_SYMBOL(nand_rnd_is_activ);
97 +
98 +/**
99   * nand_page_is_empty - check wether a NAND page contains only FFs
100   * @mtd:       mtd info
101   * @data:      data buffer
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)
105  {
106 -       chip->read_buf(mtd, buf, mtd->writesize);
107 -       if (oob_required)
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);
114 +       }
115 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
116 +
117         return 0;
118  }
119  
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;
123         int steps, size;
124 +       int column = 0;
125  
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);
130                 buf += eccsize;
131 +               column += eccsize;
132  
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;
139                 }
140  
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);
144                 oob += eccbytes;
145 +               column += eccbytes;
146  
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;
153                 }
154         }
155  
156         size = mtd->oobsize - (oob - chip->oob_poi);
157 -       if (size)
158 -               chip->read_buf(mtd, oob, size);
159 +       if (size) {
160 +               nand_rnd_config(mtd, page, column, NAND_RND_READ);
161 +               nand_rnd_read_buf(mtd, oob, size);
162 +       }
163 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
164  
165         return 0;
166  }
167 @@ -1380,7 +1453,8 @@ static int nand_read_subpage(struct mtd_
168                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
169  
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);
174  
175         /* Calculate ECC */
176         for (i = 0; i < eccfrag_len;
177 @@ -1399,7 +1473,8 @@ static int nand_read_subpage(struct mtd_
178         }
179         if (gaps) {
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);
184         } else {
185                 /*
186                  * Send the command to read the particular ECC bytes take care
187 @@ -1415,7 +1490,8 @@ static int nand_read_subpage(struct mtd_
188  
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);
194         }
195  
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);
199                 }
200         }
201 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
202         return max_bitflips;
203  }
204  
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;
209 +       int column = 0;
210  
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]);
217 +               column += eccsize;
218         }
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);
222  
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);
227                 }
228         }
229 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
230         return max_bitflips;
231  }
232  
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;
237 +       int column = 0;
238  
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);
245 +       column = 0;
246  
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
250                 int stat;
251  
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]);
257  
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);
261                 }
262         }
263 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
264         return max_bitflips;
265  }
266  
267 @@ -1561,20 +1648,27 @@ static int nand_read_page_syndrome(struc
268         uint8_t *p = buf;
269         uint8_t *oob = chip->oob_poi;
270         unsigned int max_bitflips = 0;
271 +       int column = 0;
272  
273         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
274                 int stat;
275  
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);
280 +               column += eccsize;
281  
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;
287                 }
288  
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;
294 +
295                 stat = chip->cur_ecc->correct(mtd, p, oob, NULL);
296  
297                 if (stat < 0) {
298 @@ -1587,29 +1681,36 @@ static int nand_read_page_syndrome(struc
299                 oob += eccbytes;
300  
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;
307                 }
308         }
309  
310         /* Calculate remaining oob bytes */
311         i = mtd->oobsize - (oob - chip->oob_poi);
312 -       if (i)
313 -               chip->read_buf(mtd, oob, i);
314 +       if (i) {
315 +               nand_rnd_config(mtd, page, column, NAND_RND_READ);
316 +               nand_rnd_read_buf(mtd, oob, i);
317 +       }
318 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
319  
320         return max_bitflips;
321  }
322  
323  /**
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
330   */
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)
334  {
335 +       struct nand_chip *chip = mtd->priv;
336 +
337         switch (ops->mode) {
338  
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.
343                          */
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,
347                                                                 bufpoi,
348 @@ -1753,6 +1855,8 @@ read_retry:
349                                                                bufpoi,
350                                                                oob_required,
351                                                                page);
352 +                       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
353 +
354                         if (ret < 0) {
355                                 if (use_bufpoi)
356                                         /* Invalidate page cache */
357 @@ -1780,8 +1884,8 @@ read_retry:
358                                 int toread = min(oobreadlen, max_oobsize);
359  
360                                 if (toread) {
361 -                                       oob = nand_transfer_oob(chip,
362 -                                               oob, ops, toread);
363 +                                       oob = nand_transfer_oob(mtd, oob, ops,
364 +                                                               toread);
365                                         oobreadlen -= toread;
366                                 }
367                         }
368 @@ -1909,12 +2013,15 @@ static int nand_part_read(struct mtd_inf
369         nand_get_device(part->master, FL_READING);
370         if (part->ecc)
371                 chip->cur_ecc = part->ecc;
372 +       if (part->rnd)
373 +               chip->cur_rnd = part->rnd;
374         ops.len = len;
375         ops.datbuf = buf;
376         ops.oobbuf = NULL;
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);
383         return ret;
384 @@ -1930,7 +2037,9 @@ static int nand_read_oob_std(struct mtd_
385                              int page)
386  {
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);
392         return 0;
393  }
394  
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;
401  
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
405                 } else
406                         sndrnd = 1;
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);
411                 bufpoi += toread;
412                 length -= toread;
413         }
414 -       if (length > 0)
415 -               chip->read_buf(mtd, bufpoi, length);
416 +       if (length > 0) {
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);
420 +       }
421 +       nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
422  
423         return 0;
424  }
425 @@ -1986,7 +2100,9 @@ static int nand_write_oob_std(struct mtd
426         int length = mtd->oobsize;
427  
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);
435  
436 @@ -2042,12 +2158,18 @@ static int nand_write_oob_syndrome(struc
437                 } else
438                         sndcmd = 1;
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);
443                 bufpoi += len;
444                 length -= len;
445         }
446 -       if (length > 0)
447 -               chip->write_buf(mtd, bufpoi, length);
448 +       if (length > 0) {
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);
452 +       }
453 +
454 +       nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
455  
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
459                         break;
460  
461                 len = min(len, readlen);
462 -               buf = nand_transfer_oob(chip, buf, ops, len);
463 +               buf = nand_transfer_oob(mtd, buf, ops, len);
464  
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);
469         if (part->ecc)
470                 chip->cur_ecc = part->ecc;
471 +       if (part->rnd)
472 +               chip->cur_rnd = part->rnd;
473  
474         switch (ops->mode) {
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);
478  
479  out:
480 +       chip->cur_rnd = &chip->rnd;
481         chip->cur_ecc = &chip->ecc;
482         nand_release_device(part->master);
483         return ret;
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)
487  {
488 -       chip->write_buf(mtd, buf, mtd->writesize);
489 -       if (oob_required)
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);
495 +       }
496  
497         return 0;
498  }
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;
502         int steps, size;
503 +       int column = 0;
504  
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);
509                 buf += eccsize;
510 +               column += eccsize;
511  
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;
518                 }
519  
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);
523                 oob += eccbytes;
524 +               column += eccbytes;
525  
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;
532                 }
533         }
534  
535         size = mtd->oobsize - (oob - chip->oob_poi);
536 -       if (size)
537 -               chip->write_buf(mtd, oob, size);
538 +       if (size) {
539 +               nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
540 +               nand_rnd_write_buf(mtd, oob, size);
541 +       }
542  
543         return 0;
544  }
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;
549 +       int column = 0;
550  
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]);
557 +               column += eccsize;
558         }
559  
560         for (i = 0; i < chip->cur_ecc->total; i++)
561                 chip->oob_poi[eccpos[i]] = ecc_calc[i];
562  
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);
566  
567         return 0;
568  }
569 @@ -2399,7 +2541,9 @@ static int nand_write_subpage_hwecc(stru
570                 chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
571  
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;
577  
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];
582  
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);
587  
588         return 0;
589  }
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;
594 +       int column = 0;
595  
596         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
597  
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);
602 +               column += eccsize;
603  
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;
610                 }
611  
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);
616                 oob += eccbytes;
617 +               column += eccbytes;
618  
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;
625                 }
626         }
627  
628         /* Calculate remaining oob bytes */
629         i = mtd->oobsize - (oob - chip->oob_poi);
630 -       if (i)
631 -               chip->write_buf(mtd, oob, i);
632 +       if (i) {
633 +               nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
634 +               nand_rnd_write_buf(mtd, oob, i);
635 +       }
636  
637         return 0;
638  }
639 @@ -2504,6 +2660,7 @@ static int nand_write_page(struct mtd_in
640  
641         chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
642  
643 +       nand_rnd_config(mtd, page, 0, NAND_RND_WRITE);
644         if (unlikely(raw))
645                 status = chip->cur_ecc->write_page_raw(mtd, chip, buf,
646                                                        oob_required);
647 @@ -2514,6 +2671,7 @@ static int nand_write_page(struct mtd_in
648         else
649                 status = chip->cur_ecc->write_page(mtd, chip, buf,
650                                                    oob_required);
651 +       nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
652  
653         if (status < 0)
654                 return status;
655 @@ -2803,6 +2961,8 @@ static int panic_nand_part_write(struct
656         panic_nand_get_device(chip, part->master, FL_WRITING);
657         if (part->ecc)
658                 chip->cur_ecc = part->ecc;
659 +       if (part->rnd)
660 +               chip->cur_rnd = part->rnd;
661  
662         ops.len = len;
663         ops.datbuf = (uint8_t *)buf;
664 @@ -2811,6 +2971,7 @@ static int panic_nand_part_write(struct
665  
666         ret = nand_do_write_ops(part->master, to, &ops);
667  
668 +       chip->cur_rnd = &chip->rnd;
669         chip->cur_ecc = &chip->ecc;
670         *retlen = ops.retlen;
671         return ret;
672 @@ -2865,12 +3026,15 @@ static int nand_part_write(struct mtd_in
673         nand_get_device(part->master, FL_WRITING);
674         if (part->ecc)
675                 chip->cur_ecc = part->ecc;
676 +       if (part->rnd)
677 +               chip->cur_rnd = part->rnd;
678         ops.len = len;
679         ops.datbuf = (uint8_t *)buf;
680         ops.oobbuf = NULL;
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);
687         return ret;
688 @@ -3032,6 +3196,8 @@ static int nand_part_write_oob(struct mt
689         nand_get_device(part->master, FL_WRITING);
690         if (part->ecc)
691                 chip->cur_ecc = part->ecc;
692 +       if (part->rnd)
693 +               chip->cur_rnd = part->rnd;
694  
695         switch (ops->mode) {
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);
699  
700  out:
701 +       chip->cur_rnd = &chip->rnd;
702         chip->cur_ecc = &chip->ecc;
703         nand_release_device(part->master);
704         return ret;
705 @@ -4749,6 +4916,7 @@ int nand_scan_tail(struct mtd_info *mtd)
706         mutex_init(&chip->part_lock);
707  
708         chip->cur_ecc = &chip->ecc;
709 +       chip->cur_rnd = &chip->rnd;
710  
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
716  
717  int nand_pst_create(struct mtd_info *mtd);
718  
719 +/*
720 + * Constants for randomizer modes
721 + */
722 +typedef enum {
723 +       NAND_RND_NONE,
724 +       NAND_RND_SOFT,
725 +       NAND_RND_HW,
726 +} nand_rnd_modes_t;
727 +
728 +/*
729 + * Constants for randomizer actions
730 + */
731 +enum nand_rnd_action {
732 +       NAND_RND_NO_ACTION,
733 +       NAND_RND_READ,
734 +       NAND_RND_WRITE,
735 +};
736 +
737 +/**
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
742 + */
743 +struct nand_rndfree {
744 +       u32 offset;
745 +       u32 length;
746 +};
747 +
748 +/**
749 + * struct nand_rnd_layout - Structure defining rndfree regions
750 + * @nranges:   number of ranges
751 + * @ranges:    array defining the rndfree regions
752 + */
753 +struct nand_rnd_layout {
754 +       int nranges;
755 +       struct nand_rndfree ranges[0];
756 +};
757 +
758 +/**
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
764 + *             data.
765 + * @write_buf: function that scramble data before writing it to the NAND.
766 + */
767 +struct nand_rnd_ctrl {
768 +       nand_rnd_modes_t mode;
769 +       struct nand_rnd_layout *layout;
770 +       void *priv;
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);
775 +};
776 +
777  /**
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;
783  
784 +       struct nand_rnd_ctrl rnd;
785 +       struct nand_rnd_ctrl *cur_rnd;
786 +
787         uint8_t *bbt;
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
796   *
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;
800         uint64_t offset;
801         struct nand_ecc_ctrl *ecc;
802 +       struct nand_rnd_ctrl *rnd;
803         void (*release)(struct nand_part *part);
804  };
805  
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);
809  
810 +static inline int nand_rnd_config(struct mtd_info *mtd, int page, int column,
811 +                                 enum nand_rnd_action action)
812 +{
813 +       struct nand_chip *chip = mtd->priv;
814 +
815 +       if (chip->cur_rnd && chip->cur_rnd->config)
816 +               return chip->cur_rnd->config(mtd, page, column, action);
817 +
818 +       return 0;
819 +}
820 +
821 +static inline void nand_rnd_write_buf(struct mtd_info *mtd, const uint8_t *buf,
822 +                                    int len)
823 +{
824 +       struct nand_chip *chip = mtd->priv;
825 +
826 +       if (chip->cur_rnd && chip->cur_rnd->read_buf)
827 +               chip->cur_rnd->write_buf(mtd, buf, len);
828 +       else
829 +               chip->write_buf(mtd, buf, len);
830 +}
831 +
832 +static inline void nand_rnd_read_buf(struct mtd_info *mtd, uint8_t *buf,
833 +                                   int len)
834 +{
835 +       struct nand_chip *chip = mtd->priv;
836 +
837 +       if (chip->cur_rnd && chip->cur_rnd->read_buf)
838 +               chip->cur_rnd->read_buf(mtd, buf, len);
839 +       else
840 +               chip->read_buf(mtd, buf, len);
841 +}
842 +
843 +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len);
844 +
845  /**
846   * struct platform_nand_chip - chip level device structure
847   * @nr_chips:          max. number of chips to scan for