sunxi: add support for 4.1
[openwrt/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