rpcd: iwinfo plugin fixes
[openwrt/svn-archive/archive.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