diff options
Diffstat (limited to 'target/linux/sunxi/patches-4.1/111-mtd-add-support-for-nand-partitions.patch')
-rw-r--r-- | target/linux/sunxi/patches-4.1/111-mtd-add-support-for-nand-partitions.patch | 1295 |
1 files changed, 0 insertions, 1295 deletions
diff --git a/target/linux/sunxi/patches-4.1/111-mtd-add-support-for-nand-partitions.patch b/target/linux/sunxi/patches-4.1/111-mtd-add-support-for-nand-partitions.patch deleted file mode 100644 index d4eaeec118..0000000000 --- a/target/linux/sunxi/patches-4.1/111-mtd-add-support-for-nand-partitions.patch +++ /dev/null @@ -1,1295 +0,0 @@ -From a95cc309cf74eed3fc457dec3dcc44d9bf79e0e6 Mon Sep 17 00:00:00 2001 -From: Boris BREZILLON <boris.brezillon@free-electrons.com> -Date: Mon, 28 Jul 2014 15:01:15 +0200 -Subject: [PATCH] mtd: nand: Add support for NAND partitions - -Add support for NAND partitions, and indirectly for per partition ECC -config, and also per partiton random seed support for the upcoming -randomizer support. - -This is necessary to be able to use different ECC / randomizer settings for -the parts of the NAND which are read directly by a bootrom (which has a -fixed ECC / random seed setting) and the generic data part of the NAND for -which we often want a stronger ECC and / or random seed. - -Provide helper functions to add/delete/allocate nand partitions. -NAND core code now make use of the partition specific nand_ecc_ctrl struct -(if available) when doing read/write operations. - -Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/mtd/nand/Kconfig | 4 + - drivers/mtd/nand/Makefile | 2 + - drivers/mtd/nand/nand_base.c | 712 +++++++++++++++++++++++++++++++++++-------- - drivers/mtd/nand/nand_bch.c | 16 +- - drivers/mtd/nand/nand_ecc.c | 4 +- - include/linux/mtd/nand.h | 38 +++ - 6 files changed, 635 insertions(+), 141 deletions(-) - ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -22,6 +22,10 @@ menuconfig MTD_NAND - - if MTD_NAND - -+config MTD_OF_NAND_PARTS -+ tristate -+ default n -+ - config MTD_NAND_BCH - tristate - select BCH ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -53,4 +53,6 @@ obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += - obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o - obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o - -+obj-$(CONFIG_MTD_OF_NAND_PARTS) += ofnandpart.o -+ - nand-objs := nand_base.o nand_bbt.o nand_timings.o ---- a/drivers/mtd/nand/nand_base.c -+++ b/drivers/mtd/nand/nand_base.c -@@ -1134,26 +1134,26 @@ static int nand_read_page_raw_syndrome(s - struct nand_chip *chip, uint8_t *buf, - int oob_required, int page) - { -- int eccsize = chip->ecc.size; -- int eccbytes = chip->ecc.bytes; -+ int eccsize = chip->cur_ecc->size; -+ int eccbytes = chip->cur_ecc->bytes; - uint8_t *oob = chip->oob_poi; - int steps, size; - -- for (steps = chip->ecc.steps; steps > 0; steps--) { -+ for (steps = chip->cur_ecc->steps; steps > 0; steps--) { - chip->read_buf(mtd, buf, eccsize); - buf += eccsize; - -- if (chip->ecc.prepad) { -- chip->read_buf(mtd, oob, chip->ecc.prepad); -- oob += chip->ecc.prepad; -+ if (chip->cur_ecc->prepad) { -+ chip->read_buf(mtd, oob, chip->cur_ecc->prepad); -+ oob += chip->cur_ecc->prepad; - } - - chip->read_buf(mtd, oob, eccbytes); - oob += eccbytes; - -- if (chip->ecc.postpad) { -- chip->read_buf(mtd, oob, chip->ecc.postpad); -- oob += chip->ecc.postpad; -+ if (chip->cur_ecc->postpad) { -+ chip->read_buf(mtd, oob, chip->cur_ecc->postpad); -+ oob += chip->cur_ecc->postpad; - } - } - -@@ -1175,30 +1175,31 @@ static int nand_read_page_raw_syndrome(s - static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) - { -- int i, eccsize = chip->ecc.size; -- int eccbytes = chip->ecc.bytes; -- int eccsteps = chip->ecc.steps; -+ int i, eccsize = chip->cur_ecc->size; -+ int eccbytes = chip->cur_ecc->bytes; -+ int eccsteps = chip->cur_ecc->steps; - uint8_t *p = buf; - uint8_t *ecc_calc = chip->buffers->ecccalc; - uint8_t *ecc_code = chip->buffers->ecccode; -- uint32_t *eccpos = chip->ecc.layout->eccpos; -+ uint32_t *eccpos = chip->cur_ecc->layout->eccpos; - unsigned int max_bitflips = 0; - -- chip->ecc.read_page_raw(mtd, chip, buf, 1, page); -+ chip->cur_ecc->read_page_raw(mtd, chip, buf, 1, page); - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) -- chip->ecc.calculate(mtd, p, &ecc_calc[i]); -+ chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]); - -- for (i = 0; i < chip->ecc.total; i++) -+ for (i = 0; i < chip->cur_ecc->total; i++) - ecc_code[i] = chip->oob_poi[eccpos[i]]; - -- eccsteps = chip->ecc.steps; -+ eccsteps = chip->cur_ecc->steps; - p = buf; - - for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - int stat; - -- stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); -+ stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i], -+ &ecc_calc[i]); - if (stat < 0) { - mtd->ecc_stats.failed++; - } else { -@@ -1223,7 +1224,7 @@ static int nand_read_subpage(struct mtd_ - int page) - { - int start_step, end_step, num_steps; -- uint32_t *eccpos = chip->ecc.layout->eccpos; -+ uint32_t *eccpos = chip->cur_ecc->layout->eccpos; - uint8_t *p; - int data_col_addr, i, gaps = 0; - int datafrag_len, eccfrag_len, aligned_len, aligned_pos; -@@ -1232,16 +1233,16 @@ static int nand_read_subpage(struct mtd_ - unsigned int max_bitflips = 0; - - /* Column address within the page aligned to ECC size (256bytes) */ -- start_step = data_offs / chip->ecc.size; -- end_step = (data_offs + readlen - 1) / chip->ecc.size; -+ start_step = data_offs / chip->cur_ecc->size; -+ end_step = (data_offs + readlen - 1) / chip->cur_ecc->size; - num_steps = end_step - start_step + 1; -- index = start_step * chip->ecc.bytes; -+ index = start_step * chip->cur_ecc->bytes; - - /* Data size aligned to ECC ecc.size */ -- datafrag_len = num_steps * chip->ecc.size; -- eccfrag_len = num_steps * chip->ecc.bytes; -+ datafrag_len = num_steps * chip->cur_ecc->size; -+ eccfrag_len = num_steps * chip->cur_ecc->bytes; - -- data_col_addr = start_step * chip->ecc.size; -+ data_col_addr = start_step * chip->cur_ecc->size; - /* If we read not a page aligned data */ - if (data_col_addr != 0) - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1); -@@ -1250,8 +1251,9 @@ static int nand_read_subpage(struct mtd_ - chip->read_buf(mtd, p, datafrag_len); - - /* Calculate ECC */ -- for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) -- chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]); -+ for (i = 0; i < eccfrag_len; -+ i += chip->cur_ecc->bytes, p += chip->cur_ecc->size) -+ chip->cur_ecc->calculate(mtd, p, &chip->buffers->ecccalc[i]); - - /* - * The performance is faster if we position offsets according to -@@ -1275,7 +1277,8 @@ static int nand_read_subpage(struct mtd_ - aligned_len = eccfrag_len; - if (eccpos[index] & (busw - 1)) - aligned_len++; -- if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1)) -+ if (eccpos[index + (num_steps * chip->cur_ecc->bytes)] & -+ (busw - 1)) - aligned_len++; - - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, -@@ -1287,11 +1290,13 @@ static int nand_read_subpage(struct mtd_ - chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]]; - - p = bufpoi + data_col_addr; -- for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { -+ for (i = 0; i < eccfrag_len; -+ i += chip->cur_ecc->bytes, p += chip->cur_ecc->size) { - int stat; - -- stat = chip->ecc.correct(mtd, p, -- &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); -+ stat = chip->cur_ecc->correct(mtd, p, -+ &chip->buffers->ecccode[i], -+ &chip->buffers->ecccalc[i]); - if (stat < 0) { - mtd->ecc_stats.failed++; - } else { -@@ -1315,32 +1320,33 @@ static int nand_read_subpage(struct mtd_ - static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) - { -- int i, eccsize = chip->ecc.size; -- int eccbytes = chip->ecc.bytes; -- int eccsteps = chip->ecc.steps; -+ int i, eccsize = chip->cur_ecc->size; -+ int eccbytes = chip->cur_ecc->bytes; -+ int eccsteps = chip->cur_ecc->steps; - uint8_t *p = buf; - uint8_t *ecc_calc = chip->buffers->ecccalc; - uint8_t *ecc_code = chip->buffers->ecccode; -- uint32_t *eccpos = chip->ecc.layout->eccpos; -+ uint32_t *eccpos = chip->cur_ecc->layout->eccpos; - unsigned int max_bitflips = 0; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -- chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->cur_ecc->hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); -- chip->ecc.calculate(mtd, p, &ecc_calc[i]); -+ chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]); - } - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - -- for (i = 0; i < chip->ecc.total; i++) -+ for (i = 0; i < chip->cur_ecc->total; i++) - ecc_code[i] = chip->oob_poi[eccpos[i]]; - -- eccsteps = chip->ecc.steps; -+ eccsteps = chip->cur_ecc->steps; - p = buf; - - for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - int stat; - -- stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); -+ stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i], -+ &ecc_calc[i]); - if (stat < 0) { - mtd->ecc_stats.failed++; - } else { -@@ -1368,12 +1374,12 @@ static int nand_read_page_hwecc(struct m - static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, int page) - { -- int i, eccsize = chip->ecc.size; -- int eccbytes = chip->ecc.bytes; -- int eccsteps = chip->ecc.steps; -+ int i, eccsize = chip->cur_ecc->size; -+ int eccbytes = chip->cur_ecc->bytes; -+ int eccsteps = chip->cur_ecc->steps; - uint8_t *p = buf; - uint8_t *ecc_code = chip->buffers->ecccode; -- uint32_t *eccpos = chip->ecc.layout->eccpos; -+ uint32_t *eccpos = chip->cur_ecc->layout->eccpos; - uint8_t *ecc_calc = chip->buffers->ecccalc; - unsigned int max_bitflips = 0; - -@@ -1382,17 +1388,17 @@ static int nand_read_page_hwecc_oob_firs - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); - -- for (i = 0; i < chip->ecc.total; i++) -+ for (i = 0; i < chip->cur_ecc->total; i++) - ecc_code[i] = chip->oob_poi[eccpos[i]]; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - int stat; - -- chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->cur_ecc->hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); -- chip->ecc.calculate(mtd, p, &ecc_calc[i]); -+ chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]); - -- stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); -+ stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i], NULL); - if (stat < 0) { - mtd->ecc_stats.failed++; - } else { -@@ -1417,9 +1423,9 @@ static int nand_read_page_hwecc_oob_firs - static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) - { -- int i, eccsize = chip->ecc.size; -- int eccbytes = chip->ecc.bytes; -- int eccsteps = chip->ecc.steps; -+ int i, eccsize = chip->cur_ecc->size; -+ int eccbytes = chip->cur_ecc->bytes; -+ int eccsteps = chip->cur_ecc->steps; - uint8_t *p = buf; - uint8_t *oob = chip->oob_poi; - unsigned int max_bitflips = 0; -@@ -1427,17 +1433,17 @@ static int nand_read_page_syndrome(struc - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - int stat; - -- chip->ecc.hwctl(mtd, NAND_ECC_READ); -+ chip->cur_ecc->hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); - -- if (chip->ecc.prepad) { -- chip->read_buf(mtd, oob, chip->ecc.prepad); -- oob += chip->ecc.prepad; -+ if (chip->cur_ecc->prepad) { -+ chip->read_buf(mtd, oob, chip->cur_ecc->prepad); -+ oob += chip->cur_ecc->prepad; - } - -- chip->ecc.hwctl(mtd, NAND_ECC_READSYN); -+ chip->cur_ecc->hwctl(mtd, NAND_ECC_READSYN); - chip->read_buf(mtd, oob, eccbytes); -- stat = chip->ecc.correct(mtd, p, oob, NULL); -+ stat = chip->cur_ecc->correct(mtd, p, oob, NULL); - - if (stat < 0) { - mtd->ecc_stats.failed++; -@@ -1448,9 +1454,9 @@ static int nand_read_page_syndrome(struc - - oob += eccbytes; - -- if (chip->ecc.postpad) { -- chip->read_buf(mtd, oob, chip->ecc.postpad); -- oob += chip->ecc.postpad; -+ if (chip->cur_ecc->postpad) { -+ chip->read_buf(mtd, oob, chip->cur_ecc->postpad); -+ oob += chip->cur_ecc->postpad; - } - } - -@@ -1480,7 +1486,7 @@ static uint8_t *nand_transfer_oob(struct - return oob + len; - - case MTD_OPS_AUTO_OOB: { -- struct nand_oobfree *free = chip->ecc.layout->oobfree; -+ struct nand_oobfree *free = chip->cur_ecc->layout->oobfree; - uint32_t boffs = 0, roffs = ops->ooboffs; - size_t bytes = 0; - -@@ -1600,17 +1606,21 @@ read_retry: - * the read methods return max bitflips per ecc step. - */ - if (unlikely(ops->mode == MTD_OPS_RAW)) -- ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, -- oob_required, -- page); -+ ret = chip->cur_ecc->read_page_raw(mtd, chip, -+ bufpoi, -+ oob_required, -+ page); - else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) && - !oob) -- ret = chip->ecc.read_subpage(mtd, chip, -- col, bytes, bufpoi, -- page); -+ ret = chip->cur_ecc->read_subpage(mtd, chip, -+ col, bytes, -+ bufpoi, -+ page); - else -- ret = chip->ecc.read_page(mtd, chip, bufpoi, -- oob_required, page); -+ ret = chip->cur_ecc->read_page(mtd, chip, -+ bufpoi, -+ oob_required, -+ page); - if (ret < 0) { - if (use_bufpoi) - /* Invalidate page cache */ -@@ -1746,6 +1756,39 @@ static int nand_read(struct mtd_info *mt - } - - /** -+ * nand_part_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc -+ * @mtd: MTD device structure -+ * @from: offset to read from -+ * @len: number of bytes to read -+ * @retlen: pointer to variable to store the number of read bytes -+ * @buf: the databuffer to put data -+ * -+ * Get hold of the chip and call nand_do_read. -+ */ -+static int nand_part_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, uint8_t *buf) -+{ -+ struct nand_chip *chip = mtd->priv; -+ struct nand_part *part = to_nand_part(mtd); -+ struct mtd_oob_ops ops; -+ int ret; -+ -+ from += part->offset; -+ nand_get_device(part->master, FL_READING); -+ if (part->ecc) -+ chip->cur_ecc = part->ecc; -+ ops.len = len; -+ ops.datbuf = buf; -+ ops.oobbuf = NULL; -+ ops.mode = MTD_OPS_PLACE_OOB; -+ ret = nand_do_read_ops(part->master, from, &ops); -+ *retlen = ops.retlen; -+ chip->cur_ecc = &chip->ecc; -+ nand_release_device(part->master); -+ return ret; -+} -+ -+/** - * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function - * @mtd: mtd info structure - * @chip: nand chip info structure -@@ -1770,13 +1813,14 @@ static int nand_read_oob_syndrome(struct - int page) - { - int length = mtd->oobsize; -- int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; -- int eccsize = chip->ecc.size; -+ int chunk = chip->cur_ecc->bytes + chip->cur_ecc->prepad + -+ chip->cur_ecc->postpad; -+ int eccsize = chip->cur_ecc->size; - uint8_t *bufpoi = chip->oob_poi; - int i, toread, sndrnd = 0, pos; - -- chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page); -- for (i = 0; i < chip->ecc.steps; i++) { -+ chip->cmdfunc(mtd, NAND_CMD_READ0, chip->cur_ecc->size, page); -+ for (i = 0; i < chip->cur_ecc->steps; i++) { - if (sndrnd) { - pos = eccsize + i * (eccsize + chunk); - if (mtd->writesize > 512) -@@ -1829,9 +1873,10 @@ static int nand_write_oob_std(struct mtd - static int nand_write_oob_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, int page) - { -- int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; -- int eccsize = chip->ecc.size, length = mtd->oobsize; -- int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps; -+ int chunk = chip->cur_ecc->bytes + chip->cur_ecc->prepad + -+ chip->cur_ecc->postpad; -+ int eccsize = chip->cur_ecc->size, length = mtd->oobsize; -+ int i, len, pos, status = 0, sndcmd = 0, steps = chip->cur_ecc->steps; - const uint8_t *bufpoi = chip->oob_poi; - - /* -@@ -1839,7 +1884,7 @@ static int nand_write_oob_syndrome(struc - * or - * data-pad-ecc-pad-data-pad .... ecc-pad-oob - */ -- if (!chip->ecc.prepad && !chip->ecc.postpad) { -+ if (!chip->cur_ecc->prepad && !chip->cur_ecc->postpad) { - pos = steps * (eccsize + chunk); - steps = 0; - } else -@@ -1903,7 +1948,7 @@ static int nand_do_read_oob(struct mtd_i - stats = mtd->ecc_stats; - - if (ops->mode == MTD_OPS_AUTO_OOB) -- len = chip->ecc.layout->oobavail; -+ len = chip->cur_ecc->layout->oobavail; - else - len = mtd->oobsize; - -@@ -1931,9 +1976,9 @@ static int nand_do_read_oob(struct mtd_i - - while (1) { - if (ops->mode == MTD_OPS_RAW) -- ret = chip->ecc.read_oob_raw(mtd, chip, page); -+ ret = chip->cur_ecc->read_oob_raw(mtd, chip, page); - else -- ret = chip->ecc.read_oob(mtd, chip, page); -+ ret = chip->cur_ecc->read_oob(mtd, chip, page); - - if (ret < 0) - break; -@@ -2021,6 +2066,56 @@ out: - return ret; - } - -+/** -+ * nand_part_read_oob - [MTD Interface] NAND read data and/or out-of-band -+ * @mtd: MTD device structure -+ * @from: offset to read from -+ * @ops: oob operation description structure -+ * -+ * NAND read data and/or out-of-band data. -+ */ -+static int nand_part_read_oob(struct mtd_info *mtd, loff_t from, -+ struct mtd_oob_ops *ops) -+{ -+ struct nand_chip *chip = mtd->priv; -+ struct nand_part *part = to_nand_part(mtd); -+ int ret = -ENOTSUPP; -+ -+ ops->retlen = 0; -+ -+ /* Do not allow reads past end of device */ -+ if (ops->datbuf && (from + ops->len) > mtd->size) { -+ pr_debug("%s: attempt to read beyond end of device\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ from += part->offset; -+ nand_get_device(part->master, FL_READING); -+ if (part->ecc) -+ chip->cur_ecc = part->ecc; -+ -+ switch (ops->mode) { -+ case MTD_OPS_PLACE_OOB: -+ case MTD_OPS_AUTO_OOB: -+ case MTD_OPS_RAW: -+ break; -+ -+ default: -+ goto out; -+ } -+ -+ if (!ops->datbuf) -+ ret = nand_do_read_oob(part->master, from, ops); -+ else -+ ret = nand_do_read_ops(part->master, from, ops); -+ -+out: -+ chip->cur_ecc = &chip->ecc; -+ nand_release_device(part->master); -+ return ret; -+} -+ - - /** - * nand_write_page_raw - [INTERN] raw page write function -@@ -2054,26 +2149,26 @@ static int nand_write_page_raw_syndrome( - struct nand_chip *chip, - const uint8_t *buf, int oob_required) - { -- int eccsize = chip->ecc.size; -- int eccbytes = chip->ecc.bytes; -+ int eccsize = chip->cur_ecc->size; -+ int eccbytes = chip->cur_ecc->bytes; - uint8_t *oob = chip->oob_poi; - int steps, size; - -- for (steps = chip->ecc.steps; steps > 0; steps--) { -+ for (steps = chip->cur_ecc->steps; steps > 0; steps--) { - chip->write_buf(mtd, buf, eccsize); - buf += eccsize; - -- if (chip->ecc.prepad) { -- chip->write_buf(mtd, oob, chip->ecc.prepad); -- oob += chip->ecc.prepad; -+ if (chip->cur_ecc->prepad) { -+ chip->write_buf(mtd, oob, chip->cur_ecc->prepad); -+ oob += chip->cur_ecc->prepad; - } - - chip->write_buf(mtd, oob, eccbytes); - oob += eccbytes; - -- if (chip->ecc.postpad) { -- chip->write_buf(mtd, oob, chip->ecc.postpad); -- oob += chip->ecc.postpad; -+ if (chip->cur_ecc->postpad) { -+ chip->write_buf(mtd, oob, chip->cur_ecc->postpad); -+ oob += chip->cur_ecc->postpad; - } - } - -@@ -2093,21 +2188,21 @@ static int nand_write_page_raw_syndrome( - static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) - { -- int i, eccsize = chip->ecc.size; -- int eccbytes = chip->ecc.bytes; -- int eccsteps = chip->ecc.steps; -+ int i, eccsize = chip->cur_ecc->size; -+ int eccbytes = chip->cur_ecc->bytes; -+ int eccsteps = chip->cur_ecc->steps; - uint8_t *ecc_calc = chip->buffers->ecccalc; - const uint8_t *p = buf; -- uint32_t *eccpos = chip->ecc.layout->eccpos; -+ uint32_t *eccpos = chip->cur_ecc->layout->eccpos; - - /* Software ECC calculation */ - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) -- chip->ecc.calculate(mtd, p, &ecc_calc[i]); -+ chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]); - -- for (i = 0; i < chip->ecc.total; i++) -+ for (i = 0; i < chip->cur_ecc->total; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; - -- return chip->ecc.write_page_raw(mtd, chip, buf, 1); -+ return chip->cur_ecc->write_page_raw(mtd, chip, buf, 1); - } - - /** -@@ -2120,20 +2215,20 @@ static int nand_write_page_swecc(struct - static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) - { -- int i, eccsize = chip->ecc.size; -- int eccbytes = chip->ecc.bytes; -- int eccsteps = chip->ecc.steps; -+ int i, eccsize = chip->cur_ecc->size; -+ int eccbytes = chip->cur_ecc->bytes; -+ int eccsteps = chip->cur_ecc->steps; - uint8_t *ecc_calc = chip->buffers->ecccalc; - const uint8_t *p = buf; -- uint32_t *eccpos = chip->ecc.layout->eccpos; -+ uint32_t *eccpos = chip->cur_ecc->layout->eccpos; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { -- chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -+ chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE); - chip->write_buf(mtd, p, eccsize); -- chip->ecc.calculate(mtd, p, &ecc_calc[i]); -+ chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]); - } - -- for (i = 0; i < chip->ecc.total; i++) -+ for (i = 0; i < chip->cur_ecc->total; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; - - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); -@@ -2158,10 +2253,10 @@ static int nand_write_subpage_hwecc(stru - { - uint8_t *oob_buf = chip->oob_poi; - uint8_t *ecc_calc = chip->buffers->ecccalc; -- int ecc_size = chip->ecc.size; -- int ecc_bytes = chip->ecc.bytes; -- int ecc_steps = chip->ecc.steps; -- uint32_t *eccpos = chip->ecc.layout->eccpos; -+ int ecc_size = chip->cur_ecc->size; -+ int ecc_bytes = chip->cur_ecc->bytes; -+ int ecc_steps = chip->cur_ecc->steps; -+ uint32_t *eccpos = chip->cur_ecc->layout->eccpos; - uint32_t start_step = offset / ecc_size; - uint32_t end_step = (offset + data_len - 1) / ecc_size; - int oob_bytes = mtd->oobsize / ecc_steps; -@@ -2169,7 +2264,7 @@ static int nand_write_subpage_hwecc(stru - - for (step = 0; step < ecc_steps; step++) { - /* configure controller for WRITE access */ -- chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -+ chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE); - - /* write data (untouched subpages already masked by 0xFF) */ - chip->write_buf(mtd, buf, ecc_size); -@@ -2178,7 +2273,7 @@ static int nand_write_subpage_hwecc(stru - if ((step < start_step) || (step > end_step)) - memset(ecc_calc, 0xff, ecc_bytes); - else -- chip->ecc.calculate(mtd, buf, ecc_calc); -+ chip->cur_ecc->calculate(mtd, buf, ecc_calc); - - /* mask OOB of un-touched subpages by padding 0xFF */ - /* if oob_required, preserve OOB metadata of written subpage */ -@@ -2193,7 +2288,7 @@ static int nand_write_subpage_hwecc(stru - /* copy calculated ECC for whole page to chip->buffer->oob */ - /* this include masked-value(0xFF) for unwritten subpages */ - ecc_calc = chip->buffers->ecccalc; -- for (i = 0; i < chip->ecc.total; i++) -+ for (i = 0; i < chip->cur_ecc->total; i++) - chip->oob_poi[eccpos[i]] = ecc_calc[i]; - - /* write OOB buffer to NAND device */ -@@ -2217,29 +2312,29 @@ static int nand_write_page_syndrome(stru - struct nand_chip *chip, - const uint8_t *buf, int oob_required) - { -- int i, eccsize = chip->ecc.size; -- int eccbytes = chip->ecc.bytes; -- int eccsteps = chip->ecc.steps; -+ int i, eccsize = chip->cur_ecc->size; -+ int eccbytes = chip->cur_ecc->bytes; -+ int eccsteps = chip->cur_ecc->steps; - const uint8_t *p = buf; - uint8_t *oob = chip->oob_poi; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - -- chip->ecc.hwctl(mtd, NAND_ECC_WRITE); -+ chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE); - chip->write_buf(mtd, p, eccsize); - -- if (chip->ecc.prepad) { -- chip->write_buf(mtd, oob, chip->ecc.prepad); -- oob += chip->ecc.prepad; -+ if (chip->cur_ecc->prepad) { -+ chip->write_buf(mtd, oob, chip->cur_ecc->prepad); -+ oob += chip->cur_ecc->prepad; - } - -- chip->ecc.calculate(mtd, p, oob); -+ chip->cur_ecc->calculate(mtd, p, oob); - chip->write_buf(mtd, oob, eccbytes); - oob += eccbytes; - -- if (chip->ecc.postpad) { -- chip->write_buf(mtd, oob, chip->ecc.postpad); -- oob += chip->ecc.postpad; -+ if (chip->cur_ecc->postpad) { -+ chip->write_buf(mtd, oob, chip->cur_ecc->postpad); -+ oob += chip->cur_ecc->postpad; - } - } - -@@ -2270,7 +2365,7 @@ static int nand_write_page(struct mtd_in - int status, subpage; - - if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && -- chip->ecc.write_subpage) -+ chip->cur_ecc->write_subpage) - subpage = offset || (data_len < mtd->writesize); - else - subpage = 0; -@@ -2278,13 +2373,15 @@ static int nand_write_page(struct mtd_in - chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); - - if (unlikely(raw)) -- status = chip->ecc.write_page_raw(mtd, chip, buf, -- oob_required); -+ status = chip->cur_ecc->write_page_raw(mtd, chip, buf, -+ oob_required); - else if (subpage) -- status = chip->ecc.write_subpage(mtd, chip, offset, data_len, -- buf, oob_required); -+ status = chip->cur_ecc->write_subpage(mtd, chip, offset, -+ data_len, buf, -+ oob_required); - else -- status = chip->ecc.write_page(mtd, chip, buf, oob_required); -+ status = chip->cur_ecc->write_page(mtd, chip, buf, -+ oob_required); - - if (status < 0) - return status; -@@ -2343,7 +2440,7 @@ static uint8_t *nand_fill_oob(struct mtd - return oob + len; - - case MTD_OPS_AUTO_OOB: { -- struct nand_oobfree *free = chip->ecc.layout->oobfree; -+ struct nand_oobfree *free = chip->cur_ecc->layout->oobfree; - uint32_t boffs = 0, woffs = ops->ooboffs; - size_t bytes = 0; - -@@ -2539,6 +2636,46 @@ static int panic_nand_write(struct mtd_i - } - - /** -+ * panic_nand_part_write - [MTD Interface] NAND write with ECC -+ * @mtd: MTD device structure -+ * @to: offset to write to -+ * @len: number of bytes to write -+ * @retlen: pointer to variable to store the number of written bytes -+ * @buf: the data to write -+ * -+ * NAND write with ECC. Used when performing writes in interrupt context, this -+ * may for example be called by mtdoops when writing an oops while in panic. -+ */ -+static int panic_nand_part_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const uint8_t *buf) -+{ -+ struct nand_chip *chip = mtd->priv; -+ struct nand_part *part = to_nand_part(mtd); -+ struct mtd_oob_ops ops; -+ int ret; -+ -+ to += part->offset; -+ /* Wait for the device to get ready */ -+ panic_nand_wait(part->master, chip, 400); -+ -+ /* Grab the device */ -+ panic_nand_get_device(chip, part->master, FL_WRITING); -+ if (part->ecc) -+ chip->cur_ecc = part->ecc; -+ -+ ops.len = len; -+ ops.datbuf = (uint8_t *)buf; -+ ops.oobbuf = NULL; -+ ops.mode = MTD_OPS_PLACE_OOB; -+ -+ ret = nand_do_write_ops(part->master, to, &ops); -+ -+ chip->cur_ecc = &chip->ecc; -+ *retlen = ops.retlen; -+ return ret; -+} -+ -+/** - * nand_write - [MTD Interface] NAND write with ECC - * @mtd: MTD device structure - * @to: offset to write to -@@ -2566,6 +2703,39 @@ static int nand_write(struct mtd_info *m - } - - /** -+ * nand_part_write - [MTD Interface] NAND write with ECC -+ * @mtd: MTD device structure -+ * @to: offset to write to -+ * @len: number of bytes to write -+ * @retlen: pointer to variable to store the number of written bytes -+ * @buf: the data to write -+ * -+ * NAND write with ECC. -+ */ -+static int nand_part_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const uint8_t *buf) -+{ -+ struct nand_chip *chip = mtd->priv; -+ struct nand_part *part = to_nand_part(mtd); -+ struct mtd_oob_ops ops; -+ int ret; -+ -+ to += part->offset; -+ nand_get_device(part->master, FL_WRITING); -+ if (part->ecc) -+ chip->cur_ecc = part->ecc; -+ ops.len = len; -+ ops.datbuf = (uint8_t *)buf; -+ ops.oobbuf = NULL; -+ ops.mode = MTD_OPS_PLACE_OOB; -+ ret = nand_do_write_ops(part->master, to, &ops); -+ *retlen = ops.retlen; -+ chip->cur_ecc = &chip->ecc; -+ nand_release_device(part->master); -+ return ret; -+} -+ -+/** - * nand_do_write_oob - [MTD Interface] NAND write out-of-band - * @mtd: MTD device structure - * @to: offset to write to -@@ -2583,7 +2753,7 @@ static int nand_do_write_oob(struct mtd_ - __func__, (unsigned int)to, (int)ops->ooblen); - - if (ops->mode == MTD_OPS_AUTO_OOB) -- len = chip->ecc.layout->oobavail; -+ len = chip->cur_ecc->layout->oobavail; - else - len = mtd->oobsize; - -@@ -2637,9 +2807,11 @@ static int nand_do_write_oob(struct mtd_ - nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops); - - if (ops->mode == MTD_OPS_RAW) -- status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask); -+ status = chip->cur_ecc->write_oob_raw(mtd, chip, -+ page & chip->pagemask); - else -- status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); -+ status = chip->cur_ecc->write_oob(mtd, chip, -+ page & chip->pagemask); - - chip->select_chip(mtd, -1); - -@@ -2694,6 +2866,54 @@ out: - } - - /** -+ * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band -+ * @mtd: MTD device structure -+ * @to: offset to write to -+ * @ops: oob operation description structure -+ */ -+static int nand_part_write_oob(struct mtd_info *mtd, loff_t to, -+ struct mtd_oob_ops *ops) -+{ -+ struct nand_chip *chip = mtd->priv; -+ struct nand_part *part = to_nand_part(mtd); -+ int ret = -ENOTSUPP; -+ -+ ops->retlen = 0; -+ -+ /* Do not allow writes past end of device */ -+ if (ops->datbuf && (to + ops->len) > mtd->size) { -+ pr_debug("%s: attempt to write beyond end of device\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ to += part->offset; -+ nand_get_device(part->master, FL_WRITING); -+ if (part->ecc) -+ chip->cur_ecc = part->ecc; -+ -+ switch (ops->mode) { -+ case MTD_OPS_PLACE_OOB: -+ case MTD_OPS_AUTO_OOB: -+ case MTD_OPS_RAW: -+ break; -+ -+ default: -+ goto out; -+ } -+ -+ if (!ops->datbuf) -+ ret = nand_do_write_oob(part->master, to, ops); -+ else -+ ret = nand_do_write_ops(part->master, to, ops); -+ -+out: -+ chip->cur_ecc = &chip->ecc; -+ nand_release_device(part->master); -+ return ret; -+} -+ -+/** - * single_erase - [GENERIC] NAND standard block erase command function - * @mtd: MTD device structure - * @page: the page address of the block which will be erased -@@ -2723,6 +2943,29 @@ static int nand_erase(struct mtd_info *m - } - - /** -+ * nand_part_erase - [MTD Interface] erase partition block(s) -+ * @mtd: MTD device structure -+ * @instr: erase instruction -+ * -+ * Erase one ore more blocks. -+ */ -+static int nand_part_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct nand_part *part = to_nand_part(mtd); -+ int ret; -+ -+ instr->addr += part->offset; -+ ret = nand_erase_nand(part->master, instr, 0); -+ if (ret) { -+ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) -+ instr->fail_addr -= part->offset; -+ instr->addr -= part->offset; -+ } -+ -+ return ret; -+} -+ -+/** - * nand_erase_nand - [INTERN] erase block(s) - * @mtd: MTD device structure - * @instr: erase instruction -@@ -2864,6 +3107,18 @@ static int nand_block_isbad(struct mtd_i - } - - /** -+ * nand_part_block_isbad - [MTD Interface] Check if block at offset is bad -+ * @mtd: MTD device structure -+ * @offs: offset relative to mtd start -+ */ -+static int nand_part_block_isbad(struct mtd_info *mtd, loff_t offs) -+{ -+ struct nand_part *part = to_nand_part(mtd); -+ -+ return nand_block_checkbad(part->master, part->offset + offs, 1, 0); -+} -+ -+/** - * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad - * @mtd: MTD device structure - * @ofs: offset relative to mtd start -@@ -2884,6 +3139,33 @@ static int nand_block_markbad(struct mtd - } - - /** -+ * nand_part_block_markbad - [MTD Interface] Mark block at the given offset as -+ * bad -+ * @mtd: MTD device structure -+ * @ofs: offset relative to mtd start -+ */ -+static int nand_part_block_markbad(struct mtd_info *mtd, loff_t ofs) -+{ -+ struct nand_part *part = to_nand_part(mtd); -+ int ret; -+ -+ ofs += part->offset; -+ ret = nand_block_isbad(part->master, ofs); -+ if (ret) { -+ /* If it was bad already, return success and do nothing */ -+ if (ret > 0) -+ return 0; -+ return ret; -+ } -+ -+ ret = nand_block_markbad_lowlevel(part->master, ofs); -+ if (!ret) -+ mtd->ecc_stats.badblocks++; -+ -+ return ret; -+} -+ -+/** - * nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand - * @mtd: MTD device structure - * @chip: nand chip info structure -@@ -4099,6 +4381,169 @@ static int nand_ecc_ctrl_init(struct mtd - } - - /** -+ * nand_add_partition - [NAND Interface] Add a NAND partition to a NAND device -+ * @master: MTD device structure representing the NAND device -+ * @part: NAND partition to add to the NAND device -+ * -+ * Adds a NAND partition to a NAND device. -+ * The NAND partition cannot overlap with another existing partition. -+ * -+ * Returns zero in case of success and a negative error code in case of failure. -+ */ -+int nand_add_partition(struct mtd_info *master, struct nand_part *part) -+{ -+ struct nand_chip *chip = master->priv; -+ struct mtd_info *mtd = &part->mtd; -+ struct nand_ecc_ctrl *ecc = part->ecc; -+ struct nand_part *pos; -+ bool inserted = false; -+ int ret; -+ -+ /* set up the MTD object for this partition */ -+ mtd->type = master->type; -+ mtd->flags = master->flags & ~mtd->flags; -+ mtd->writesize = master->writesize; -+ mtd->writebufsize = master->writebufsize; -+ mtd->oobsize = master->oobsize; -+ mtd->oobavail = master->oobavail; -+ mtd->subpage_sft = master->subpage_sft; -+ mtd->erasesize = master->erasesize; -+ -+ mtd->priv = chip; -+ mtd->owner = master->owner; -+ mtd->backing_dev_info = master->backing_dev_info; -+ -+ mtd->dev.parent = master->dev.parent; -+ -+ if (ecc) { -+ ret = nand_ecc_ctrl_init(mtd, ecc); -+ if (ret) -+ return ret; -+ } else { -+ ecc = &chip->ecc; -+ } -+ -+ mtd->_erase = nand_part_erase; -+ mtd->_point = NULL; -+ mtd->_unpoint = NULL; -+ mtd->_read = nand_part_read; -+ mtd->_write = nand_part_write; -+ mtd->_panic_write = panic_nand_part_write; -+ mtd->_read_oob = nand_part_read_oob; -+ mtd->_write_oob = nand_part_write_oob; -+ mtd->_sync = nand_sync; -+ mtd->_lock = NULL; -+ mtd->_unlock = NULL; -+ mtd->_suspend = nand_suspend; -+ mtd->_resume = nand_resume; -+ mtd->_block_isbad = nand_part_block_isbad; -+ mtd->_block_markbad = nand_part_block_markbad; -+ -+ /* propagate ecc info to mtd_info */ -+ mtd->ecclayout = ecc->layout; -+ mtd->ecc_strength = ecc->strength; -+ mtd->ecc_step_size = ecc->size; -+ /* -+ * Initialize bitflip_threshold to its default prior scan_bbt() call. -+ * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be -+ * properly set. -+ */ -+ if (!mtd->bitflip_threshold) -+ mtd->bitflip_threshold = mtd->ecc_strength; -+ -+ part->master = master; -+ -+ mutex_lock(&chip->part_lock); -+ list_for_each_entry(pos, &chip->partitions, node) { -+ if (part->offset >= pos->offset + pos->mtd.size) { -+ continue; -+ } else if (part->offset + mtd->size > pos->offset) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ list_add(&part->node, pos->node.prev); -+ inserted = true; -+ break; -+ } -+ -+ if (!inserted) -+ list_add_tail(&part->node, &chip->partitions); -+ -+ ret = mtd_device_register(mtd, NULL, 0); -+ if (ret) { -+ list_del(&part->node); -+ goto out; -+ } -+ -+ if (master->_block_isbad) { -+ uint64_t offs = 0; -+ -+ while (offs < mtd->size) { -+ if (mtd_block_isreserved(master, offs + part->offset)) -+ mtd->ecc_stats.bbtblocks++; -+ else if (mtd_block_isbad(master, offs + part->offset)) -+ mtd->ecc_stats.badblocks++; -+ offs += mtd->erasesize; -+ } -+ } -+ -+out: -+ mutex_unlock(&chip->part_lock); -+ return ret; -+} -+EXPORT_SYMBOL(nand_add_partition); -+ -+/** -+ * nand_del_partition - [NAND Interface] Delete a NAND part from a NAND dev -+ * @part: NAND partition to delete -+ * -+ * Deletes a NAND partition from a NAND device. -+ */ -+void nand_del_partition(struct nand_part *part) -+{ -+ struct nand_chip *chip = part->mtd.priv; -+ -+ mutex_lock(&chip->part_lock); -+ mtd_device_unregister(&part->mtd); -+ list_del(&part->node); -+ mutex_unlock(&chip->part_lock); -+ -+ if (part->ecc && part->ecc->mode == NAND_ECC_SOFT_BCH) -+ nand_bch_free((struct nand_bch_control *)part->ecc->priv); -+ -+ if (part->release) -+ part->release(part); -+} -+EXPORT_SYMBOL(nand_del_partition); -+ -+/* -+ * NAND part release function. Used by nandpart_alloc as its release function. -+ */ -+static void nandpart_release(struct nand_part *part) -+{ -+ kfree(part); -+} -+ -+/** -+ * nandpart_alloc - [NAND Interface] Allocate a NAND part struct -+ * -+ * Allocate a NAND partition and assign the nandpart release function. -+ * This nand_part struct must be filled before passing it to the -+ * nand_add_partition function. -+ */ -+struct nand_part *nandpart_alloc(void) -+{ -+ struct nand_part *part = kzalloc(sizeof(*part), GFP_KERNEL); -+ if (!part) -+ return ERR_PTR(-ENOMEM); -+ part->release = nandpart_release; -+ -+ return part; -+} -+EXPORT_SYMBOL(nandpart_alloc); -+ -+/** - * nand_scan_tail - [NAND Interface] Scan for the NAND device - * @mtd: MTD device structure - * -@@ -4146,6 +4591,11 @@ int nand_scan_tail(struct mtd_info *mtd) - return ret; - } - -+ INIT_LIST_HEAD(&chip->partitions); -+ mutex_init(&chip->part_lock); -+ -+ chip->cur_ecc = &chip->ecc; -+ - /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ - if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { - switch (ecc->steps) { ---- a/drivers/mtd/nand/nand_bch.c -+++ b/drivers/mtd/nand/nand_bch.c -@@ -53,14 +53,14 @@ int nand_bch_calculate_ecc(struct mtd_in - unsigned char *code) - { - const struct nand_chip *chip = mtd->priv; -- struct nand_bch_control *nbc = chip->ecc.priv; -+ struct nand_bch_control *nbc = chip->cur_ecc->priv; - unsigned int i; - -- memset(code, 0, chip->ecc.bytes); -- encode_bch(nbc->bch, buf, chip->ecc.size, code); -+ memset(code, 0, chip->cur_ecc->bytes); -+ encode_bch(nbc->bch, buf, chip->cur_ecc->size, code); - - /* apply mask so that an erased page is a valid codeword */ -- for (i = 0; i < chip->ecc.bytes; i++) -+ for (i = 0; i < chip->cur_ecc->bytes; i++) - code[i] ^= nbc->eccmask[i]; - - return 0; -@@ -80,15 +80,15 @@ int nand_bch_correct_data(struct mtd_inf - unsigned char *read_ecc, unsigned char *calc_ecc) - { - const struct nand_chip *chip = mtd->priv; -- struct nand_bch_control *nbc = chip->ecc.priv; -+ struct nand_bch_control *nbc = chip->cur_ecc->priv; - unsigned int *errloc = nbc->errloc; - int i, count; - -- count = decode_bch(nbc->bch, NULL, chip->ecc.size, read_ecc, calc_ecc, -- NULL, errloc); -+ count = decode_bch(nbc->bch, NULL, chip->cur_ecc->size, read_ecc, -+ calc_ecc, NULL, errloc); - if (count > 0) { - for (i = 0; i < count; i++) { -- if (errloc[i] < (chip->ecc.size*8)) -+ if (errloc[i] < (chip->cur_ecc->size*8)) - /* error is located in data, correct it */ - buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7)); - /* else error in ecc, no action needed */ ---- a/drivers/mtd/nand/nand_ecc.c -+++ b/drivers/mtd/nand/nand_ecc.c -@@ -424,7 +424,7 @@ int nand_calculate_ecc(struct mtd_info * - unsigned char *code) - { - __nand_calculate_ecc(buf, -- ((struct nand_chip *)mtd->priv)->ecc.size, code); -+ ((struct nand_chip *)mtd->priv)->cur_ecc->size, code); - - return 0; - } -@@ -524,7 +524,7 @@ int nand_correct_data(struct mtd_info *m - unsigned char *read_ecc, unsigned char *calc_ecc) - { - return __nand_correct_data(buf, read_ecc, calc_ecc, -- ((struct nand_chip *)mtd->priv)->ecc.size); -+ ((struct nand_chip *)mtd->priv)->cur_ecc->size); - } - EXPORT_SYMBOL(nand_correct_data); - ---- a/include/linux/mtd/nand.h -+++ b/include/linux/mtd/nand.h -@@ -708,6 +708,7 @@ struct nand_chip { - struct nand_hw_control *controller; - - struct nand_ecc_ctrl ecc; -+ struct nand_ecc_ctrl *cur_ecc; - struct nand_buffers *buffers; - struct nand_hw_control hwcontrol; - -@@ -717,9 +718,46 @@ struct nand_chip { - - struct nand_bbt_descr *badblock_pattern; - -+ struct list_head partitions; -+ struct mutex part_lock; -+ - void *priv; - }; - -+/** -+ * struct nand_part - NAND partition structure -+ * @node: list node used to attach the partition to its NAND dev -+ * @mtd: MTD partiton info -+ * @master: MTD device representing the NAND chip -+ * @offset: partition offset -+ * @ecc: partition specific ECC struct -+ * @release: function used to release this nand_part struct -+ * -+ * NAND partitions work as standard MTD partitions except it can override -+ * NAND chip ECC handling. -+ * This is particularly useful for SoCs that need specific ECC configs to boot -+ * from NAND while these ECC configs do not fit the NAND chip ECC requirements. -+ */ -+struct nand_part { -+ struct list_head node; -+ struct mtd_info mtd; -+ struct mtd_info *master; -+ uint64_t offset; -+ struct nand_ecc_ctrl *ecc; -+ void (*release)(struct nand_part *part); -+}; -+ -+static inline struct nand_part *to_nand_part(struct mtd_info *mtd) -+{ -+ return container_of(mtd, struct nand_part, mtd); -+} -+ -+int nand_add_partition(struct mtd_info *master, struct nand_part *part); -+ -+void nand_del_partition(struct nand_part *part); -+ -+struct nand_part *nandpart_alloc(void); -+ - /* - * NAND Flash Manufacturer ID Codes - */ |