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