diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-02-03 19:06:15 +0100 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-04-19 22:05:56 +0200 |
commit | 41b207a70d3a86b9e2eede155e87838234c7cbd5 (patch) | |
tree | bb4d67d4d372ed58187c446df6c0e755a61b1326 /drivers/mtd | |
parent | 1bd0b24737710697e0a850fb1983dcdce1d01196 (diff) | |
download | linux-41b207a70d3a86b9e2eede155e87838234c7cbd5.tar.bz2 |
mtd: nand: implement the default mtd_ooblayout_ops
Replace the default nand_ecclayout definitions for large and small page
devices with the equivalent mtd_ooblayout_ops.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 142 |
1 files changed, 93 insertions, 49 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index feb1448e9dd6..e8332ea45739 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -47,54 +47,96 @@ #include <linux/mtd/partitions.h> #include <linux/of_mtd.h> +static int nand_get_device(struct mtd_info *mtd, int new_state); + +static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops); + /* Define default oob placement schemes for large and small page devices */ -static struct nand_ecclayout nand_oob_8 = { - .eccbytes = 3, - .eccpos = {0, 1, 2}, - .oobfree = { - {.offset = 3, - .length = 2}, - {.offset = 6, - .length = 2} } -}; +static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; -static struct nand_ecclayout nand_oob_16 = { - .eccbytes = 6, - .eccpos = {0, 1, 2, 3, 6, 7}, - .oobfree = { - {.offset = 8, - . length = 8} } -}; + if (section > 1) + return -ERANGE; -static struct nand_ecclayout nand_oob_64 = { - .eccbytes = 24, - .eccpos = { - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63}, - .oobfree = { - {.offset = 2, - .length = 38} } -}; + if (!section) { + oobregion->offset = 0; + oobregion->length = 4; + } else { + oobregion->offset = 6; + oobregion->length = ecc->total - 4; + } -static struct nand_ecclayout nand_oob_128 = { - .eccbytes = 48, - .eccpos = { - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127}, - .oobfree = { - {.offset = 2, - .length = 78} } + return 0; +} + +static int nand_ooblayout_free_sp(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + if (section > 1) + return -ERANGE; + + if (mtd->oobsize == 16) { + if (section) + return -ERANGE; + + oobregion->length = 8; + oobregion->offset = 8; + } else { + oobregion->length = 2; + if (!section) + oobregion->offset = 3; + else + oobregion->offset = 6; + } + + return 0; +} + +const struct mtd_ooblayout_ops nand_ooblayout_sp_ops = { + .ecc = nand_ooblayout_ecc_sp, + .free = nand_ooblayout_free_sp, }; +EXPORT_SYMBOL_GPL(nand_ooblayout_sp_ops); -static int nand_get_device(struct mtd_info *mtd, int new_state); +static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; -static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops); + if (section) + return -ERANGE; + + oobregion->length = ecc->total; + oobregion->offset = mtd->oobsize - oobregion->length; + + return 0; +} + +static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; + + if (section) + return -ERANGE; + + oobregion->length = mtd->oobsize - ecc->total - 2; + oobregion->offset = 2; + + return 0; +} + +const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = { + .ecc = nand_ooblayout_ecc_lp, + .free = nand_ooblayout_free_lp, +}; +EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops); static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len) @@ -4110,21 +4152,24 @@ int nand_scan_tail(struct mtd_info *mtd) chip->oob_poi = chip->buffers->databuf + mtd->writesize; /* + * Set the provided ECC layout. If ecc->layout is NULL, the MTD core + * will just leave mtd->ooblayout to NULL, if it's not NULL, it will + * set ->ooblayout to the default ecclayout wrapper. + */ + mtd_set_ecclayout(mtd, ecc->layout); + + /* * If no default placement scheme is given, select an appropriate one. */ - if (!ecc->layout && (ecc->mode != NAND_ECC_SOFT_BCH)) { + if (!mtd->ooblayout && (ecc->mode != NAND_ECC_SOFT_BCH)) { switch (mtd->oobsize) { case 8: - ecc->layout = &nand_oob_8; - break; case 16: - ecc->layout = &nand_oob_16; + mtd_set_ooblayout(mtd, &nand_ooblayout_sp_ops); break; case 64: - ecc->layout = &nand_oob_64; - break; case 128: - ecc->layout = &nand_oob_128; + mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); break; default: WARN(1, "No oob scheme defined for oobsize %d\n", @@ -4285,7 +4330,6 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->write_oob_raw = ecc->write_oob; /* propagate ecc info to mtd_info */ - mtd_set_ecclayout(mtd, ecc->layout); mtd->ecc_strength = ecc->strength; mtd->ecc_step_size = ecc->size; |