sunxi: add support for 4.1
[openwrt/staging/florian.git] / target / linux / sunxi / patches-4.1 / 111-mtd-add-support-for-nand-partitions.patch
1 From a95cc309cf74eed3fc457dec3dcc44d9bf79e0e6 Mon Sep 17 00:00:00 2001
2 From: Boris BREZILLON <boris.brezillon@free-electrons.com>
3 Date: Mon, 28 Jul 2014 15:01:15 +0200
4 Subject: [PATCH] mtd: nand: Add support for NAND partitions
5
6 Add support for NAND partitions, and indirectly for per partition ECC
7 config, and also per partiton random seed support for the upcoming
8 randomizer support.
9
10 This is necessary to be able to use different ECC / randomizer settings for
11 the parts of the NAND which are read directly by a bootrom (which has a
12 fixed ECC / random seed setting) and the generic data part of the NAND for
13 which we often want a stronger ECC and / or random seed.
14
15 Provide helper functions to add/delete/allocate nand partitions.
16 NAND core code now make use of the partition specific nand_ecc_ctrl struct
17 (if available) when doing read/write operations.
18
19 Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
20 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
21 ---
22 drivers/mtd/nand/Kconfig | 4 +
23 drivers/mtd/nand/Makefile | 2 +
24 drivers/mtd/nand/nand_base.c | 712 +++++++++++++++++++++++++++++++++++--------
25 drivers/mtd/nand/nand_bch.c | 16 +-
26 drivers/mtd/nand/nand_ecc.c | 4 +-
27 include/linux/mtd/nand.h | 38 +++
28 6 files changed, 635 insertions(+), 141 deletions(-)
29
30 diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
31 index 5897d8d..8242470 100644
32 --- a/drivers/mtd/nand/Kconfig
33 +++ b/drivers/mtd/nand/Kconfig
34 @@ -22,6 +22,10 @@ menuconfig MTD_NAND
35
36 if MTD_NAND
37
38 +config MTD_OF_NAND_PARTS
39 + tristate
40 + default n
41 +
42 config MTD_NAND_BCH
43 tristate
44 select BCH
45 diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
46 index 582bbd05..fcbe032 100644
47 --- a/drivers/mtd/nand/Makefile
48 +++ b/drivers/mtd/nand/Makefile
49 @@ -53,4 +53,6 @@ obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/
50 obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o
51 obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o
52
53 +obj-$(CONFIG_MTD_OF_NAND_PARTS) += ofnandpart.o
54 +
55 nand-objs := nand_base.o nand_bbt.o nand_timings.o
56 diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
57 index f580ed1..a30b67f 100644
58 --- a/drivers/mtd/nand/nand_base.c
59 +++ b/drivers/mtd/nand/nand_base.c
60 @@ -1134,26 +1134,26 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
61 struct nand_chip *chip, uint8_t *buf,
62 int oob_required, int page)
63 {
64 - int eccsize = chip->ecc.size;
65 - int eccbytes = chip->ecc.bytes;
66 + int eccsize = chip->cur_ecc->size;
67 + int eccbytes = chip->cur_ecc->bytes;
68 uint8_t *oob = chip->oob_poi;
69 int steps, size;
70
71 - for (steps = chip->ecc.steps; steps > 0; steps--) {
72 + for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
73 chip->read_buf(mtd, buf, eccsize);
74 buf += eccsize;
75
76 - if (chip->ecc.prepad) {
77 - chip->read_buf(mtd, oob, chip->ecc.prepad);
78 - oob += chip->ecc.prepad;
79 + if (chip->cur_ecc->prepad) {
80 + chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
81 + oob += chip->cur_ecc->prepad;
82 }
83
84 chip->read_buf(mtd, oob, eccbytes);
85 oob += eccbytes;
86
87 - if (chip->ecc.postpad) {
88 - chip->read_buf(mtd, oob, chip->ecc.postpad);
89 - oob += chip->ecc.postpad;
90 + if (chip->cur_ecc->postpad) {
91 + chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
92 + oob += chip->cur_ecc->postpad;
93 }
94 }
95
96 @@ -1175,30 +1175,31 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
97 static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
98 uint8_t *buf, int oob_required, int page)
99 {
100 - int i, eccsize = chip->ecc.size;
101 - int eccbytes = chip->ecc.bytes;
102 - int eccsteps = chip->ecc.steps;
103 + int i, eccsize = chip->cur_ecc->size;
104 + int eccbytes = chip->cur_ecc->bytes;
105 + int eccsteps = chip->cur_ecc->steps;
106 uint8_t *p = buf;
107 uint8_t *ecc_calc = chip->buffers->ecccalc;
108 uint8_t *ecc_code = chip->buffers->ecccode;
109 - uint32_t *eccpos = chip->ecc.layout->eccpos;
110 + uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
111 unsigned int max_bitflips = 0;
112
113 - chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
114 + chip->cur_ecc->read_page_raw(mtd, chip, buf, 1, page);
115
116 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
117 - chip->ecc.calculate(mtd, p, &ecc_calc[i]);
118 + chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
119
120 - for (i = 0; i < chip->ecc.total; i++)
121 + for (i = 0; i < chip->cur_ecc->total; i++)
122 ecc_code[i] = chip->oob_poi[eccpos[i]];
123
124 - eccsteps = chip->ecc.steps;
125 + eccsteps = chip->cur_ecc->steps;
126 p = buf;
127
128 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
129 int stat;
130
131 - stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
132 + stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i],
133 + &ecc_calc[i]);
134 if (stat < 0) {
135 mtd->ecc_stats.failed++;
136 } else {
137 @@ -1223,7 +1224,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
138 int page)
139 {
140 int start_step, end_step, num_steps;
141 - uint32_t *eccpos = chip->ecc.layout->eccpos;
142 + uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
143 uint8_t *p;
144 int data_col_addr, i, gaps = 0;
145 int datafrag_len, eccfrag_len, aligned_len, aligned_pos;
146 @@ -1232,16 +1233,16 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
147 unsigned int max_bitflips = 0;
148
149 /* Column address within the page aligned to ECC size (256bytes) */
150 - start_step = data_offs / chip->ecc.size;
151 - end_step = (data_offs + readlen - 1) / chip->ecc.size;
152 + start_step = data_offs / chip->cur_ecc->size;
153 + end_step = (data_offs + readlen - 1) / chip->cur_ecc->size;
154 num_steps = end_step - start_step + 1;
155 - index = start_step * chip->ecc.bytes;
156 + index = start_step * chip->cur_ecc->bytes;
157
158 /* Data size aligned to ECC ecc.size */
159 - datafrag_len = num_steps * chip->ecc.size;
160 - eccfrag_len = num_steps * chip->ecc.bytes;
161 + datafrag_len = num_steps * chip->cur_ecc->size;
162 + eccfrag_len = num_steps * chip->cur_ecc->bytes;
163
164 - data_col_addr = start_step * chip->ecc.size;
165 + data_col_addr = start_step * chip->cur_ecc->size;
166 /* If we read not a page aligned data */
167 if (data_col_addr != 0)
168 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
169 @@ -1250,8 +1251,9 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
170 chip->read_buf(mtd, p, datafrag_len);
171
172 /* Calculate ECC */
173 - for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
174 - chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
175 + for (i = 0; i < eccfrag_len;
176 + i += chip->cur_ecc->bytes, p += chip->cur_ecc->size)
177 + chip->cur_ecc->calculate(mtd, p, &chip->buffers->ecccalc[i]);
178
179 /*
180 * The performance is faster if we position offsets according to
181 @@ -1275,7 +1277,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
182 aligned_len = eccfrag_len;
183 if (eccpos[index] & (busw - 1))
184 aligned_len++;
185 - if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1))
186 + if (eccpos[index + (num_steps * chip->cur_ecc->bytes)] &
187 + (busw - 1))
188 aligned_len++;
189
190 chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
191 @@ -1287,11 +1290,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
192 chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]];
193
194 p = bufpoi + data_col_addr;
195 - for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) {
196 + for (i = 0; i < eccfrag_len;
197 + i += chip->cur_ecc->bytes, p += chip->cur_ecc->size) {
198 int stat;
199
200 - stat = chip->ecc.correct(mtd, p,
201 - &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
202 + stat = chip->cur_ecc->correct(mtd, p,
203 + &chip->buffers->ecccode[i],
204 + &chip->buffers->ecccalc[i]);
205 if (stat < 0) {
206 mtd->ecc_stats.failed++;
207 } else {
208 @@ -1315,32 +1320,33 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
209 static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
210 uint8_t *buf, int oob_required, int page)
211 {
212 - int i, eccsize = chip->ecc.size;
213 - int eccbytes = chip->ecc.bytes;
214 - int eccsteps = chip->ecc.steps;
215 + int i, eccsize = chip->cur_ecc->size;
216 + int eccbytes = chip->cur_ecc->bytes;
217 + int eccsteps = chip->cur_ecc->steps;
218 uint8_t *p = buf;
219 uint8_t *ecc_calc = chip->buffers->ecccalc;
220 uint8_t *ecc_code = chip->buffers->ecccode;
221 - uint32_t *eccpos = chip->ecc.layout->eccpos;
222 + uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
223 unsigned int max_bitflips = 0;
224
225 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
226 - chip->ecc.hwctl(mtd, NAND_ECC_READ);
227 + chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
228 chip->read_buf(mtd, p, eccsize);
229 - chip->ecc.calculate(mtd, p, &ecc_calc[i]);
230 + chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
231 }
232 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
233
234 - for (i = 0; i < chip->ecc.total; i++)
235 + for (i = 0; i < chip->cur_ecc->total; i++)
236 ecc_code[i] = chip->oob_poi[eccpos[i]];
237
238 - eccsteps = chip->ecc.steps;
239 + eccsteps = chip->cur_ecc->steps;
240 p = buf;
241
242 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
243 int stat;
244
245 - stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
246 + stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i],
247 + &ecc_calc[i]);
248 if (stat < 0) {
249 mtd->ecc_stats.failed++;
250 } else {
251 @@ -1368,12 +1374,12 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
252 static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
253 struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
254 {
255 - int i, eccsize = chip->ecc.size;
256 - int eccbytes = chip->ecc.bytes;
257 - int eccsteps = chip->ecc.steps;
258 + int i, eccsize = chip->cur_ecc->size;
259 + int eccbytes = chip->cur_ecc->bytes;
260 + int eccsteps = chip->cur_ecc->steps;
261 uint8_t *p = buf;
262 uint8_t *ecc_code = chip->buffers->ecccode;
263 - uint32_t *eccpos = chip->ecc.layout->eccpos;
264 + uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
265 uint8_t *ecc_calc = chip->buffers->ecccalc;
266 unsigned int max_bitflips = 0;
267
268 @@ -1382,17 +1388,17 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
269 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
270 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
271
272 - for (i = 0; i < chip->ecc.total; i++)
273 + for (i = 0; i < chip->cur_ecc->total; i++)
274 ecc_code[i] = chip->oob_poi[eccpos[i]];
275
276 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
277 int stat;
278
279 - chip->ecc.hwctl(mtd, NAND_ECC_READ);
280 + chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
281 chip->read_buf(mtd, p, eccsize);
282 - chip->ecc.calculate(mtd, p, &ecc_calc[i]);
283 + chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
284
285 - stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
286 + stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i], NULL);
287 if (stat < 0) {
288 mtd->ecc_stats.failed++;
289 } else {
290 @@ -1417,9 +1423,9 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
291 static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
292 uint8_t *buf, int oob_required, int page)
293 {
294 - int i, eccsize = chip->ecc.size;
295 - int eccbytes = chip->ecc.bytes;
296 - int eccsteps = chip->ecc.steps;
297 + int i, eccsize = chip->cur_ecc->size;
298 + int eccbytes = chip->cur_ecc->bytes;
299 + int eccsteps = chip->cur_ecc->steps;
300 uint8_t *p = buf;
301 uint8_t *oob = chip->oob_poi;
302 unsigned int max_bitflips = 0;
303 @@ -1427,17 +1433,17 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
304 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
305 int stat;
306
307 - chip->ecc.hwctl(mtd, NAND_ECC_READ);
308 + chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
309 chip->read_buf(mtd, p, eccsize);
310
311 - if (chip->ecc.prepad) {
312 - chip->read_buf(mtd, oob, chip->ecc.prepad);
313 - oob += chip->ecc.prepad;
314 + if (chip->cur_ecc->prepad) {
315 + chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
316 + oob += chip->cur_ecc->prepad;
317 }
318
319 - chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
320 + chip->cur_ecc->hwctl(mtd, NAND_ECC_READSYN);
321 chip->read_buf(mtd, oob, eccbytes);
322 - stat = chip->ecc.correct(mtd, p, oob, NULL);
323 + stat = chip->cur_ecc->correct(mtd, p, oob, NULL);
324
325 if (stat < 0) {
326 mtd->ecc_stats.failed++;
327 @@ -1448,9 +1454,9 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
328
329 oob += eccbytes;
330
331 - if (chip->ecc.postpad) {
332 - chip->read_buf(mtd, oob, chip->ecc.postpad);
333 - oob += chip->ecc.postpad;
334 + if (chip->cur_ecc->postpad) {
335 + chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
336 + oob += chip->cur_ecc->postpad;
337 }
338 }
339
340 @@ -1480,7 +1486,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
341 return oob + len;
342
343 case MTD_OPS_AUTO_OOB: {
344 - struct nand_oobfree *free = chip->ecc.layout->oobfree;
345 + struct nand_oobfree *free = chip->cur_ecc->layout->oobfree;
346 uint32_t boffs = 0, roffs = ops->ooboffs;
347 size_t bytes = 0;
348
349 @@ -1600,17 +1606,21 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
350 * the read methods return max bitflips per ecc step.
351 */
352 if (unlikely(ops->mode == MTD_OPS_RAW))
353 - ret = chip->ecc.read_page_raw(mtd, chip, bufpoi,
354 - oob_required,
355 - page);
356 + ret = chip->cur_ecc->read_page_raw(mtd, chip,
357 + bufpoi,
358 + oob_required,
359 + page);
360 else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) &&
361 !oob)
362 - ret = chip->ecc.read_subpage(mtd, chip,
363 - col, bytes, bufpoi,
364 - page);
365 + ret = chip->cur_ecc->read_subpage(mtd, chip,
366 + col, bytes,
367 + bufpoi,
368 + page);
369 else
370 - ret = chip->ecc.read_page(mtd, chip, bufpoi,
371 - oob_required, page);
372 + ret = chip->cur_ecc->read_page(mtd, chip,
373 + bufpoi,
374 + oob_required,
375 + page);
376 if (ret < 0) {
377 if (use_bufpoi)
378 /* Invalidate page cache */
379 @@ -1746,6 +1756,39 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
380 }
381
382 /**
383 + * nand_part_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc
384 + * @mtd: MTD device structure
385 + * @from: offset to read from
386 + * @len: number of bytes to read
387 + * @retlen: pointer to variable to store the number of read bytes
388 + * @buf: the databuffer to put data
389 + *
390 + * Get hold of the chip and call nand_do_read.
391 + */
392 +static int nand_part_read(struct mtd_info *mtd, loff_t from, size_t len,
393 + size_t *retlen, uint8_t *buf)
394 +{
395 + struct nand_chip *chip = mtd->priv;
396 + struct nand_part *part = to_nand_part(mtd);
397 + struct mtd_oob_ops ops;
398 + int ret;
399 +
400 + from += part->offset;
401 + nand_get_device(part->master, FL_READING);
402 + if (part->ecc)
403 + chip->cur_ecc = part->ecc;
404 + ops.len = len;
405 + ops.datbuf = buf;
406 + ops.oobbuf = NULL;
407 + ops.mode = MTD_OPS_PLACE_OOB;
408 + ret = nand_do_read_ops(part->master, from, &ops);
409 + *retlen = ops.retlen;
410 + chip->cur_ecc = &chip->ecc;
411 + nand_release_device(part->master);
412 + return ret;
413 +}
414 +
415 +/**
416 * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function
417 * @mtd: mtd info structure
418 * @chip: nand chip info structure
419 @@ -1770,13 +1813,14 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
420 int page)
421 {
422 int length = mtd->oobsize;
423 - int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
424 - int eccsize = chip->ecc.size;
425 + int chunk = chip->cur_ecc->bytes + chip->cur_ecc->prepad +
426 + chip->cur_ecc->postpad;
427 + int eccsize = chip->cur_ecc->size;
428 uint8_t *bufpoi = chip->oob_poi;
429 int i, toread, sndrnd = 0, pos;
430
431 - chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page);
432 - for (i = 0; i < chip->ecc.steps; i++) {
433 + chip->cmdfunc(mtd, NAND_CMD_READ0, chip->cur_ecc->size, page);
434 + for (i = 0; i < chip->cur_ecc->steps; i++) {
435 if (sndrnd) {
436 pos = eccsize + i * (eccsize + chunk);
437 if (mtd->writesize > 512)
438 @@ -1829,9 +1873,10 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
439 static int nand_write_oob_syndrome(struct mtd_info *mtd,
440 struct nand_chip *chip, int page)
441 {
442 - int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
443 - int eccsize = chip->ecc.size, length = mtd->oobsize;
444 - int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps;
445 + int chunk = chip->cur_ecc->bytes + chip->cur_ecc->prepad +
446 + chip->cur_ecc->postpad;
447 + int eccsize = chip->cur_ecc->size, length = mtd->oobsize;
448 + int i, len, pos, status = 0, sndcmd = 0, steps = chip->cur_ecc->steps;
449 const uint8_t *bufpoi = chip->oob_poi;
450
451 /*
452 @@ -1839,7 +1884,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,
453 * or
454 * data-pad-ecc-pad-data-pad .... ecc-pad-oob
455 */
456 - if (!chip->ecc.prepad && !chip->ecc.postpad) {
457 + if (!chip->cur_ecc->prepad && !chip->cur_ecc->postpad) {
458 pos = steps * (eccsize + chunk);
459 steps = 0;
460 } else
461 @@ -1903,7 +1948,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
462 stats = mtd->ecc_stats;
463
464 if (ops->mode == MTD_OPS_AUTO_OOB)
465 - len = chip->ecc.layout->oobavail;
466 + len = chip->cur_ecc->layout->oobavail;
467 else
468 len = mtd->oobsize;
469
470 @@ -1931,9 +1976,9 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
471
472 while (1) {
473 if (ops->mode == MTD_OPS_RAW)
474 - ret = chip->ecc.read_oob_raw(mtd, chip, page);
475 + ret = chip->cur_ecc->read_oob_raw(mtd, chip, page);
476 else
477 - ret = chip->ecc.read_oob(mtd, chip, page);
478 + ret = chip->cur_ecc->read_oob(mtd, chip, page);
479
480 if (ret < 0)
481 break;
482 @@ -2021,6 +2066,56 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
483 return ret;
484 }
485
486 +/**
487 + * nand_part_read_oob - [MTD Interface] NAND read data and/or out-of-band
488 + * @mtd: MTD device structure
489 + * @from: offset to read from
490 + * @ops: oob operation description structure
491 + *
492 + * NAND read data and/or out-of-band data.
493 + */
494 +static int nand_part_read_oob(struct mtd_info *mtd, loff_t from,
495 + struct mtd_oob_ops *ops)
496 +{
497 + struct nand_chip *chip = mtd->priv;
498 + struct nand_part *part = to_nand_part(mtd);
499 + int ret = -ENOTSUPP;
500 +
501 + ops->retlen = 0;
502 +
503 + /* Do not allow reads past end of device */
504 + if (ops->datbuf && (from + ops->len) > mtd->size) {
505 + pr_debug("%s: attempt to read beyond end of device\n",
506 + __func__);
507 + return -EINVAL;
508 + }
509 +
510 + from += part->offset;
511 + nand_get_device(part->master, FL_READING);
512 + if (part->ecc)
513 + chip->cur_ecc = part->ecc;
514 +
515 + switch (ops->mode) {
516 + case MTD_OPS_PLACE_OOB:
517 + case MTD_OPS_AUTO_OOB:
518 + case MTD_OPS_RAW:
519 + break;
520 +
521 + default:
522 + goto out;
523 + }
524 +
525 + if (!ops->datbuf)
526 + ret = nand_do_read_oob(part->master, from, ops);
527 + else
528 + ret = nand_do_read_ops(part->master, from, ops);
529 +
530 +out:
531 + chip->cur_ecc = &chip->ecc;
532 + nand_release_device(part->master);
533 + return ret;
534 +}
535 +
536
537 /**
538 * nand_write_page_raw - [INTERN] raw page write function
539 @@ -2054,26 +2149,26 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
540 struct nand_chip *chip,
541 const uint8_t *buf, int oob_required)
542 {
543 - int eccsize = chip->ecc.size;
544 - int eccbytes = chip->ecc.bytes;
545 + int eccsize = chip->cur_ecc->size;
546 + int eccbytes = chip->cur_ecc->bytes;
547 uint8_t *oob = chip->oob_poi;
548 int steps, size;
549
550 - for (steps = chip->ecc.steps; steps > 0; steps--) {
551 + for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
552 chip->write_buf(mtd, buf, eccsize);
553 buf += eccsize;
554
555 - if (chip->ecc.prepad) {
556 - chip->write_buf(mtd, oob, chip->ecc.prepad);
557 - oob += chip->ecc.prepad;
558 + if (chip->cur_ecc->prepad) {
559 + chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
560 + oob += chip->cur_ecc->prepad;
561 }
562
563 chip->write_buf(mtd, oob, eccbytes);
564 oob += eccbytes;
565
566 - if (chip->ecc.postpad) {
567 - chip->write_buf(mtd, oob, chip->ecc.postpad);
568 - oob += chip->ecc.postpad;
569 + if (chip->cur_ecc->postpad) {
570 + chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
571 + oob += chip->cur_ecc->postpad;
572 }
573 }
574
575 @@ -2093,21 +2188,21 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
576 static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
577 const uint8_t *buf, int oob_required)
578 {
579 - int i, eccsize = chip->ecc.size;
580 - int eccbytes = chip->ecc.bytes;
581 - int eccsteps = chip->ecc.steps;
582 + int i, eccsize = chip->cur_ecc->size;
583 + int eccbytes = chip->cur_ecc->bytes;
584 + int eccsteps = chip->cur_ecc->steps;
585 uint8_t *ecc_calc = chip->buffers->ecccalc;
586 const uint8_t *p = buf;
587 - uint32_t *eccpos = chip->ecc.layout->eccpos;
588 + uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
589
590 /* Software ECC calculation */
591 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
592 - chip->ecc.calculate(mtd, p, &ecc_calc[i]);
593 + chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
594
595 - for (i = 0; i < chip->ecc.total; i++)
596 + for (i = 0; i < chip->cur_ecc->total; i++)
597 chip->oob_poi[eccpos[i]] = ecc_calc[i];
598
599 - return chip->ecc.write_page_raw(mtd, chip, buf, 1);
600 + return chip->cur_ecc->write_page_raw(mtd, chip, buf, 1);
601 }
602
603 /**
604 @@ -2120,20 +2215,20 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
605 static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
606 const uint8_t *buf, int oob_required)
607 {
608 - int i, eccsize = chip->ecc.size;
609 - int eccbytes = chip->ecc.bytes;
610 - int eccsteps = chip->ecc.steps;
611 + int i, eccsize = chip->cur_ecc->size;
612 + int eccbytes = chip->cur_ecc->bytes;
613 + int eccsteps = chip->cur_ecc->steps;
614 uint8_t *ecc_calc = chip->buffers->ecccalc;
615 const uint8_t *p = buf;
616 - uint32_t *eccpos = chip->ecc.layout->eccpos;
617 + uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
618
619 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
620 - chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
621 + chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
622 chip->write_buf(mtd, p, eccsize);
623 - chip->ecc.calculate(mtd, p, &ecc_calc[i]);
624 + chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
625 }
626
627 - for (i = 0; i < chip->ecc.total; i++)
628 + for (i = 0; i < chip->cur_ecc->total; i++)
629 chip->oob_poi[eccpos[i]] = ecc_calc[i];
630
631 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
632 @@ -2158,10 +2253,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
633 {
634 uint8_t *oob_buf = chip->oob_poi;
635 uint8_t *ecc_calc = chip->buffers->ecccalc;
636 - int ecc_size = chip->ecc.size;
637 - int ecc_bytes = chip->ecc.bytes;
638 - int ecc_steps = chip->ecc.steps;
639 - uint32_t *eccpos = chip->ecc.layout->eccpos;
640 + int ecc_size = chip->cur_ecc->size;
641 + int ecc_bytes = chip->cur_ecc->bytes;
642 + int ecc_steps = chip->cur_ecc->steps;
643 + uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
644 uint32_t start_step = offset / ecc_size;
645 uint32_t end_step = (offset + data_len - 1) / ecc_size;
646 int oob_bytes = mtd->oobsize / ecc_steps;
647 @@ -2169,7 +2264,7 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
648
649 for (step = 0; step < ecc_steps; step++) {
650 /* configure controller for WRITE access */
651 - chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
652 + chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
653
654 /* write data (untouched subpages already masked by 0xFF) */
655 chip->write_buf(mtd, buf, ecc_size);
656 @@ -2178,7 +2273,7 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
657 if ((step < start_step) || (step > end_step))
658 memset(ecc_calc, 0xff, ecc_bytes);
659 else
660 - chip->ecc.calculate(mtd, buf, ecc_calc);
661 + chip->cur_ecc->calculate(mtd, buf, ecc_calc);
662
663 /* mask OOB of un-touched subpages by padding 0xFF */
664 /* if oob_required, preserve OOB metadata of written subpage */
665 @@ -2193,7 +2288,7 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
666 /* copy calculated ECC for whole page to chip->buffer->oob */
667 /* this include masked-value(0xFF) for unwritten subpages */
668 ecc_calc = chip->buffers->ecccalc;
669 - for (i = 0; i < chip->ecc.total; i++)
670 + for (i = 0; i < chip->cur_ecc->total; i++)
671 chip->oob_poi[eccpos[i]] = ecc_calc[i];
672
673 /* write OOB buffer to NAND device */
674 @@ -2217,29 +2312,29 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
675 struct nand_chip *chip,
676 const uint8_t *buf, int oob_required)
677 {
678 - int i, eccsize = chip->ecc.size;
679 - int eccbytes = chip->ecc.bytes;
680 - int eccsteps = chip->ecc.steps;
681 + int i, eccsize = chip->cur_ecc->size;
682 + int eccbytes = chip->cur_ecc->bytes;
683 + int eccsteps = chip->cur_ecc->steps;
684 const uint8_t *p = buf;
685 uint8_t *oob = chip->oob_poi;
686
687 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
688
689 - chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
690 + chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
691 chip->write_buf(mtd, p, eccsize);
692
693 - if (chip->ecc.prepad) {
694 - chip->write_buf(mtd, oob, chip->ecc.prepad);
695 - oob += chip->ecc.prepad;
696 + if (chip->cur_ecc->prepad) {
697 + chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
698 + oob += chip->cur_ecc->prepad;
699 }
700
701 - chip->ecc.calculate(mtd, p, oob);
702 + chip->cur_ecc->calculate(mtd, p, oob);
703 chip->write_buf(mtd, oob, eccbytes);
704 oob += eccbytes;
705
706 - if (chip->ecc.postpad) {
707 - chip->write_buf(mtd, oob, chip->ecc.postpad);
708 - oob += chip->ecc.postpad;
709 + if (chip->cur_ecc->postpad) {
710 + chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
711 + oob += chip->cur_ecc->postpad;
712 }
713 }
714
715 @@ -2270,7 +2365,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
716 int status, subpage;
717
718 if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
719 - chip->ecc.write_subpage)
720 + chip->cur_ecc->write_subpage)
721 subpage = offset || (data_len < mtd->writesize);
722 else
723 subpage = 0;
724 @@ -2278,13 +2373,15 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
725 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
726
727 if (unlikely(raw))
728 - status = chip->ecc.write_page_raw(mtd, chip, buf,
729 - oob_required);
730 + status = chip->cur_ecc->write_page_raw(mtd, chip, buf,
731 + oob_required);
732 else if (subpage)
733 - status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
734 - buf, oob_required);
735 + status = chip->cur_ecc->write_subpage(mtd, chip, offset,
736 + data_len, buf,
737 + oob_required);
738 else
739 - status = chip->ecc.write_page(mtd, chip, buf, oob_required);
740 + status = chip->cur_ecc->write_page(mtd, chip, buf,
741 + oob_required);
742
743 if (status < 0)
744 return status;
745 @@ -2343,7 +2440,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
746 return oob + len;
747
748 case MTD_OPS_AUTO_OOB: {
749 - struct nand_oobfree *free = chip->ecc.layout->oobfree;
750 + struct nand_oobfree *free = chip->cur_ecc->layout->oobfree;
751 uint32_t boffs = 0, woffs = ops->ooboffs;
752 size_t bytes = 0;
753
754 @@ -2539,6 +2636,46 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
755 }
756
757 /**
758 + * panic_nand_part_write - [MTD Interface] NAND write with ECC
759 + * @mtd: MTD device structure
760 + * @to: offset to write to
761 + * @len: number of bytes to write
762 + * @retlen: pointer to variable to store the number of written bytes
763 + * @buf: the data to write
764 + *
765 + * NAND write with ECC. Used when performing writes in interrupt context, this
766 + * may for example be called by mtdoops when writing an oops while in panic.
767 + */
768 +static int panic_nand_part_write(struct mtd_info *mtd, loff_t to, size_t len,
769 + size_t *retlen, const uint8_t *buf)
770 +{
771 + struct nand_chip *chip = mtd->priv;
772 + struct nand_part *part = to_nand_part(mtd);
773 + struct mtd_oob_ops ops;
774 + int ret;
775 +
776 + to += part->offset;
777 + /* Wait for the device to get ready */
778 + panic_nand_wait(part->master, chip, 400);
779 +
780 + /* Grab the device */
781 + panic_nand_get_device(chip, part->master, FL_WRITING);
782 + if (part->ecc)
783 + chip->cur_ecc = part->ecc;
784 +
785 + ops.len = len;
786 + ops.datbuf = (uint8_t *)buf;
787 + ops.oobbuf = NULL;
788 + ops.mode = MTD_OPS_PLACE_OOB;
789 +
790 + ret = nand_do_write_ops(part->master, to, &ops);
791 +
792 + chip->cur_ecc = &chip->ecc;
793 + *retlen = ops.retlen;
794 + return ret;
795 +}
796 +
797 +/**
798 * nand_write - [MTD Interface] NAND write with ECC
799 * @mtd: MTD device structure
800 * @to: offset to write to
801 @@ -2566,6 +2703,39 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
802 }
803
804 /**
805 + * nand_part_write - [MTD Interface] NAND write with ECC
806 + * @mtd: MTD device structure
807 + * @to: offset to write to
808 + * @len: number of bytes to write
809 + * @retlen: pointer to variable to store the number of written bytes
810 + * @buf: the data to write
811 + *
812 + * NAND write with ECC.
813 + */
814 +static int nand_part_write(struct mtd_info *mtd, loff_t to, size_t len,
815 + size_t *retlen, const uint8_t *buf)
816 +{
817 + struct nand_chip *chip = mtd->priv;
818 + struct nand_part *part = to_nand_part(mtd);
819 + struct mtd_oob_ops ops;
820 + int ret;
821 +
822 + to += part->offset;
823 + nand_get_device(part->master, FL_WRITING);
824 + if (part->ecc)
825 + chip->cur_ecc = part->ecc;
826 + ops.len = len;
827 + ops.datbuf = (uint8_t *)buf;
828 + ops.oobbuf = NULL;
829 + ops.mode = MTD_OPS_PLACE_OOB;
830 + ret = nand_do_write_ops(part->master, to, &ops);
831 + *retlen = ops.retlen;
832 + chip->cur_ecc = &chip->ecc;
833 + nand_release_device(part->master);
834 + return ret;
835 +}
836 +
837 +/**
838 * nand_do_write_oob - [MTD Interface] NAND write out-of-band
839 * @mtd: MTD device structure
840 * @to: offset to write to
841 @@ -2583,7 +2753,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
842 __func__, (unsigned int)to, (int)ops->ooblen);
843
844 if (ops->mode == MTD_OPS_AUTO_OOB)
845 - len = chip->ecc.layout->oobavail;
846 + len = chip->cur_ecc->layout->oobavail;
847 else
848 len = mtd->oobsize;
849
850 @@ -2637,9 +2807,11 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
851 nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops);
852
853 if (ops->mode == MTD_OPS_RAW)
854 - status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask);
855 + status = chip->cur_ecc->write_oob_raw(mtd, chip,
856 + page & chip->pagemask);
857 else
858 - status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
859 + status = chip->cur_ecc->write_oob(mtd, chip,
860 + page & chip->pagemask);
861
862 chip->select_chip(mtd, -1);
863
864 @@ -2694,6 +2866,54 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
865 }
866
867 /**
868 + * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
869 + * @mtd: MTD device structure
870 + * @to: offset to write to
871 + * @ops: oob operation description structure
872 + */
873 +static int nand_part_write_oob(struct mtd_info *mtd, loff_t to,
874 + struct mtd_oob_ops *ops)
875 +{
876 + struct nand_chip *chip = mtd->priv;
877 + struct nand_part *part = to_nand_part(mtd);
878 + int ret = -ENOTSUPP;
879 +
880 + ops->retlen = 0;
881 +
882 + /* Do not allow writes past end of device */
883 + if (ops->datbuf && (to + ops->len) > mtd->size) {
884 + pr_debug("%s: attempt to write beyond end of device\n",
885 + __func__);
886 + return -EINVAL;
887 + }
888 +
889 + to += part->offset;
890 + nand_get_device(part->master, FL_WRITING);
891 + if (part->ecc)
892 + chip->cur_ecc = part->ecc;
893 +
894 + switch (ops->mode) {
895 + case MTD_OPS_PLACE_OOB:
896 + case MTD_OPS_AUTO_OOB:
897 + case MTD_OPS_RAW:
898 + break;
899 +
900 + default:
901 + goto out;
902 + }
903 +
904 + if (!ops->datbuf)
905 + ret = nand_do_write_oob(part->master, to, ops);
906 + else
907 + ret = nand_do_write_ops(part->master, to, ops);
908 +
909 +out:
910 + chip->cur_ecc = &chip->ecc;
911 + nand_release_device(part->master);
912 + return ret;
913 +}
914 +
915 +/**
916 * single_erase - [GENERIC] NAND standard block erase command function
917 * @mtd: MTD device structure
918 * @page: the page address of the block which will be erased
919 @@ -2723,6 +2943,29 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
920 }
921
922 /**
923 + * nand_part_erase - [MTD Interface] erase partition block(s)
924 + * @mtd: MTD device structure
925 + * @instr: erase instruction
926 + *
927 + * Erase one ore more blocks.
928 + */
929 +static int nand_part_erase(struct mtd_info *mtd, struct erase_info *instr)
930 +{
931 + struct nand_part *part = to_nand_part(mtd);
932 + int ret;
933 +
934 + instr->addr += part->offset;
935 + ret = nand_erase_nand(part->master, instr, 0);
936 + if (ret) {
937 + if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
938 + instr->fail_addr -= part->offset;
939 + instr->addr -= part->offset;
940 + }
941 +
942 + return ret;
943 +}
944 +
945 +/**
946 * nand_erase_nand - [INTERN] erase block(s)
947 * @mtd: MTD device structure
948 * @instr: erase instruction
949 @@ -2864,6 +3107,18 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
950 }
951
952 /**
953 + * nand_part_block_isbad - [MTD Interface] Check if block at offset is bad
954 + * @mtd: MTD device structure
955 + * @offs: offset relative to mtd start
956 + */
957 +static int nand_part_block_isbad(struct mtd_info *mtd, loff_t offs)
958 +{
959 + struct nand_part *part = to_nand_part(mtd);
960 +
961 + return nand_block_checkbad(part->master, part->offset + offs, 1, 0);
962 +}
963 +
964 +/**
965 * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
966 * @mtd: MTD device structure
967 * @ofs: offset relative to mtd start
968 @@ -2884,6 +3139,33 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
969 }
970
971 /**
972 + * nand_part_block_markbad - [MTD Interface] Mark block at the given offset as
973 + * bad
974 + * @mtd: MTD device structure
975 + * @ofs: offset relative to mtd start
976 + */
977 +static int nand_part_block_markbad(struct mtd_info *mtd, loff_t ofs)
978 +{
979 + struct nand_part *part = to_nand_part(mtd);
980 + int ret;
981 +
982 + ofs += part->offset;
983 + ret = nand_block_isbad(part->master, ofs);
984 + if (ret) {
985 + /* If it was bad already, return success and do nothing */
986 + if (ret > 0)
987 + return 0;
988 + return ret;
989 + }
990 +
991 + ret = nand_block_markbad_lowlevel(part->master, ofs);
992 + if (!ret)
993 + mtd->ecc_stats.badblocks++;
994 +
995 + return ret;
996 +}
997 +
998 +/**
999 * nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand
1000 * @mtd: MTD device structure
1001 * @chip: nand chip info structure
1002 @@ -4099,6 +4381,169 @@ static int nand_ecc_ctrl_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc)
1003 }
1004
1005 /**
1006 + * nand_add_partition - [NAND Interface] Add a NAND partition to a NAND device
1007 + * @master: MTD device structure representing the NAND device
1008 + * @part: NAND partition to add to the NAND device
1009 + *
1010 + * Adds a NAND partition to a NAND device.
1011 + * The NAND partition cannot overlap with another existing partition.
1012 + *
1013 + * Returns zero in case of success and a negative error code in case of failure.
1014 + */
1015 +int nand_add_partition(struct mtd_info *master, struct nand_part *part)
1016 +{
1017 + struct nand_chip *chip = master->priv;
1018 + struct mtd_info *mtd = &part->mtd;
1019 + struct nand_ecc_ctrl *ecc = part->ecc;
1020 + struct nand_part *pos;
1021 + bool inserted = false;
1022 + int ret;
1023 +
1024 + /* set up the MTD object for this partition */
1025 + mtd->type = master->type;
1026 + mtd->flags = master->flags & ~mtd->flags;
1027 + mtd->writesize = master->writesize;
1028 + mtd->writebufsize = master->writebufsize;
1029 + mtd->oobsize = master->oobsize;
1030 + mtd->oobavail = master->oobavail;
1031 + mtd->subpage_sft = master->subpage_sft;
1032 + mtd->erasesize = master->erasesize;
1033 +
1034 + mtd->priv = chip;
1035 + mtd->owner = master->owner;
1036 + mtd->backing_dev_info = master->backing_dev_info;
1037 +
1038 + mtd->dev.parent = master->dev.parent;
1039 +
1040 + if (ecc) {
1041 + ret = nand_ecc_ctrl_init(mtd, ecc);
1042 + if (ret)
1043 + return ret;
1044 + } else {
1045 + ecc = &chip->ecc;
1046 + }
1047 +
1048 + mtd->_erase = nand_part_erase;
1049 + mtd->_point = NULL;
1050 + mtd->_unpoint = NULL;
1051 + mtd->_read = nand_part_read;
1052 + mtd->_write = nand_part_write;
1053 + mtd->_panic_write = panic_nand_part_write;
1054 + mtd->_read_oob = nand_part_read_oob;
1055 + mtd->_write_oob = nand_part_write_oob;
1056 + mtd->_sync = nand_sync;
1057 + mtd->_lock = NULL;
1058 + mtd->_unlock = NULL;
1059 + mtd->_suspend = nand_suspend;
1060 + mtd->_resume = nand_resume;
1061 + mtd->_block_isbad = nand_part_block_isbad;
1062 + mtd->_block_markbad = nand_part_block_markbad;
1063 +
1064 + /* propagate ecc info to mtd_info */
1065 + mtd->ecclayout = ecc->layout;
1066 + mtd->ecc_strength = ecc->strength;
1067 + mtd->ecc_step_size = ecc->size;
1068 + /*
1069 + * Initialize bitflip_threshold to its default prior scan_bbt() call.
1070 + * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be
1071 + * properly set.
1072 + */
1073 + if (!mtd->bitflip_threshold)
1074 + mtd->bitflip_threshold = mtd->ecc_strength;
1075 +
1076 + part->master = master;
1077 +
1078 + mutex_lock(&chip->part_lock);
1079 + list_for_each_entry(pos, &chip->partitions, node) {
1080 + if (part->offset >= pos->offset + pos->mtd.size) {
1081 + continue;
1082 + } else if (part->offset + mtd->size > pos->offset) {
1083 + ret = -EINVAL;
1084 + goto out;
1085 + }
1086 +
1087 + list_add(&part->node, pos->node.prev);
1088 + inserted = true;
1089 + break;
1090 + }
1091 +
1092 + if (!inserted)
1093 + list_add_tail(&part->node, &chip->partitions);
1094 +
1095 + ret = mtd_device_register(mtd, NULL, 0);
1096 + if (ret) {
1097 + list_del(&part->node);
1098 + goto out;
1099 + }
1100 +
1101 + if (master->_block_isbad) {
1102 + uint64_t offs = 0;
1103 +
1104 + while (offs < mtd->size) {
1105 + if (mtd_block_isreserved(master, offs + part->offset))
1106 + mtd->ecc_stats.bbtblocks++;
1107 + else if (mtd_block_isbad(master, offs + part->offset))
1108 + mtd->ecc_stats.badblocks++;
1109 + offs += mtd->erasesize;
1110 + }
1111 + }
1112 +
1113 +out:
1114 + mutex_unlock(&chip->part_lock);
1115 + return ret;
1116 +}
1117 +EXPORT_SYMBOL(nand_add_partition);
1118 +
1119 +/**
1120 + * nand_del_partition - [NAND Interface] Delete a NAND part from a NAND dev
1121 + * @part: NAND partition to delete
1122 + *
1123 + * Deletes a NAND partition from a NAND device.
1124 + */
1125 +void nand_del_partition(struct nand_part *part)
1126 +{
1127 + struct nand_chip *chip = part->mtd.priv;
1128 +
1129 + mutex_lock(&chip->part_lock);
1130 + mtd_device_unregister(&part->mtd);
1131 + list_del(&part->node);
1132 + mutex_unlock(&chip->part_lock);
1133 +
1134 + if (part->ecc && part->ecc->mode == NAND_ECC_SOFT_BCH)
1135 + nand_bch_free((struct nand_bch_control *)part->ecc->priv);
1136 +
1137 + if (part->release)
1138 + part->release(part);
1139 +}
1140 +EXPORT_SYMBOL(nand_del_partition);
1141 +
1142 +/*
1143 + * NAND part release function. Used by nandpart_alloc as its release function.
1144 + */
1145 +static void nandpart_release(struct nand_part *part)
1146 +{
1147 + kfree(part);
1148 +}
1149 +
1150 +/**
1151 + * nandpart_alloc - [NAND Interface] Allocate a NAND part struct
1152 + *
1153 + * Allocate a NAND partition and assign the nandpart release function.
1154 + * This nand_part struct must be filled before passing it to the
1155 + * nand_add_partition function.
1156 + */
1157 +struct nand_part *nandpart_alloc(void)
1158 +{
1159 + struct nand_part *part = kzalloc(sizeof(*part), GFP_KERNEL);
1160 + if (!part)
1161 + return ERR_PTR(-ENOMEM);
1162 + part->release = nandpart_release;
1163 +
1164 + return part;
1165 +}
1166 +EXPORT_SYMBOL(nandpart_alloc);
1167 +
1168 +/**
1169 * nand_scan_tail - [NAND Interface] Scan for the NAND device
1170 * @mtd: MTD device structure
1171 *
1172 @@ -4146,6 +4591,11 @@ int nand_scan_tail(struct mtd_info *mtd)
1173 return ret;
1174 }
1175
1176 + INIT_LIST_HEAD(&chip->partitions);
1177 + mutex_init(&chip->part_lock);
1178 +
1179 + chip->cur_ecc = &chip->ecc;
1180 +
1181 /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
1182 if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
1183 switch (ecc->steps) {
1184 diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c
1185 index 3803e0b..b82b976 100644
1186 --- a/drivers/mtd/nand/nand_bch.c
1187 +++ b/drivers/mtd/nand/nand_bch.c
1188 @@ -53,14 +53,14 @@ int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
1189 unsigned char *code)
1190 {
1191 const struct nand_chip *chip = mtd->priv;
1192 - struct nand_bch_control *nbc = chip->ecc.priv;
1193 + struct nand_bch_control *nbc = chip->cur_ecc->priv;
1194 unsigned int i;
1195
1196 - memset(code, 0, chip->ecc.bytes);
1197 - encode_bch(nbc->bch, buf, chip->ecc.size, code);
1198 + memset(code, 0, chip->cur_ecc->bytes);
1199 + encode_bch(nbc->bch, buf, chip->cur_ecc->size, code);
1200
1201 /* apply mask so that an erased page is a valid codeword */
1202 - for (i = 0; i < chip->ecc.bytes; i++)
1203 + for (i = 0; i < chip->cur_ecc->bytes; i++)
1204 code[i] ^= nbc->eccmask[i];
1205
1206 return 0;
1207 @@ -80,15 +80,15 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
1208 unsigned char *read_ecc, unsigned char *calc_ecc)
1209 {
1210 const struct nand_chip *chip = mtd->priv;
1211 - struct nand_bch_control *nbc = chip->ecc.priv;
1212 + struct nand_bch_control *nbc = chip->cur_ecc->priv;
1213 unsigned int *errloc = nbc->errloc;
1214 int i, count;
1215
1216 - count = decode_bch(nbc->bch, NULL, chip->ecc.size, read_ecc, calc_ecc,
1217 - NULL, errloc);
1218 + count = decode_bch(nbc->bch, NULL, chip->cur_ecc->size, read_ecc,
1219 + calc_ecc, NULL, errloc);
1220 if (count > 0) {
1221 for (i = 0; i < count; i++) {
1222 - if (errloc[i] < (chip->ecc.size*8))
1223 + if (errloc[i] < (chip->cur_ecc->size*8))
1224 /* error is located in data, correct it */
1225 buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7));
1226 /* else error in ecc, no action needed */
1227 diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
1228 index 97c4c02..f35c418 100644
1229 --- a/drivers/mtd/nand/nand_ecc.c
1230 +++ b/drivers/mtd/nand/nand_ecc.c
1231 @@ -424,7 +424,7 @@ int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
1232 unsigned char *code)
1233 {
1234 __nand_calculate_ecc(buf,
1235 - ((struct nand_chip *)mtd->priv)->ecc.size, code);
1236 + ((struct nand_chip *)mtd->priv)->cur_ecc->size, code);
1237
1238 return 0;
1239 }
1240 @@ -524,7 +524,7 @@ int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
1241 unsigned char *read_ecc, unsigned char *calc_ecc)
1242 {
1243 return __nand_correct_data(buf, read_ecc, calc_ecc,
1244 - ((struct nand_chip *)mtd->priv)->ecc.size);
1245 + ((struct nand_chip *)mtd->priv)->cur_ecc->size);
1246 }
1247 EXPORT_SYMBOL(nand_correct_data);
1248
1249 diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
1250 index 3d4ea7e..510e09b 100644
1251 --- a/include/linux/mtd/nand.h
1252 +++ b/include/linux/mtd/nand.h
1253 @@ -708,6 +708,7 @@ struct nand_chip {
1254 struct nand_hw_control *controller;
1255
1256 struct nand_ecc_ctrl ecc;
1257 + struct nand_ecc_ctrl *cur_ecc;
1258 struct nand_buffers *buffers;
1259 struct nand_hw_control hwcontrol;
1260
1261 @@ -717,9 +718,46 @@ struct nand_chip {
1262
1263 struct nand_bbt_descr *badblock_pattern;
1264
1265 + struct list_head partitions;
1266 + struct mutex part_lock;
1267 +
1268 void *priv;
1269 };
1270
1271 +/**
1272 + * struct nand_part - NAND partition structure
1273 + * @node: list node used to attach the partition to its NAND dev
1274 + * @mtd: MTD partiton info
1275 + * @master: MTD device representing the NAND chip
1276 + * @offset: partition offset
1277 + * @ecc: partition specific ECC struct
1278 + * @release: function used to release this nand_part struct
1279 + *
1280 + * NAND partitions work as standard MTD partitions except it can override
1281 + * NAND chip ECC handling.
1282 + * This is particularly useful for SoCs that need specific ECC configs to boot
1283 + * from NAND while these ECC configs do not fit the NAND chip ECC requirements.
1284 + */
1285 +struct nand_part {
1286 + struct list_head node;
1287 + struct mtd_info mtd;
1288 + struct mtd_info *master;
1289 + uint64_t offset;
1290 + struct nand_ecc_ctrl *ecc;
1291 + void (*release)(struct nand_part *part);
1292 +};
1293 +
1294 +static inline struct nand_part *to_nand_part(struct mtd_info *mtd)
1295 +{
1296 + return container_of(mtd, struct nand_part, mtd);
1297 +}
1298 +
1299 +int nand_add_partition(struct mtd_info *master, struct nand_part *part);
1300 +
1301 +void nand_del_partition(struct nand_part *part);
1302 +
1303 +struct nand_part *nandpart_alloc(void);
1304 +
1305 /*
1306 * NAND Flash Manufacturer ID Codes
1307 */