diff options
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index a9c6ce74576..85cfc061d41 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -42,6 +42,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> +#include <linux/mtd/nand_bch.h> #include <linux/interrupt.h> #include <linux/bitops.h> #include <linux/leds.h> @@ -2377,7 +2378,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, return -EINVAL; } - /* Do not allow reads past end of device */ + /* Do not allow write past end of device */ if (unlikely(to >= mtd->size || ops->ooboffs + ops->ooblen > ((mtd->size >> chip->page_shift) - @@ -3248,7 +3249,7 @@ int nand_scan_tail(struct mtd_info *mtd) /* * If no default placement scheme is given, select an appropriate one */ - if (!chip->ecc.layout) { + if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) { switch (mtd->oobsize) { case 8: chip->ecc.layout = &nand_oob_8; @@ -3351,6 +3352,40 @@ int nand_scan_tail(struct mtd_info *mtd) chip->ecc.bytes = 3; break; + case NAND_ECC_SOFT_BCH: + if (!mtd_nand_has_bch()) { + printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n"); + BUG(); + } + chip->ecc.calculate = nand_bch_calculate_ecc; + chip->ecc.correct = nand_bch_correct_data; + chip->ecc.read_page = nand_read_page_swecc; + chip->ecc.read_subpage = nand_read_subpage; + chip->ecc.write_page = nand_write_page_swecc; + chip->ecc.read_page_raw = nand_read_page_raw; + chip->ecc.write_page_raw = nand_write_page_raw; + chip->ecc.read_oob = nand_read_oob_std; + chip->ecc.write_oob = nand_write_oob_std; + /* + * Board driver should supply ecc.size and ecc.bytes values to + * select how many bits are correctable; see nand_bch_init() + * for details. + * Otherwise, default to 4 bits for large page devices + */ + if (!chip->ecc.size && (mtd->oobsize >= 64)) { + chip->ecc.size = 512; + chip->ecc.bytes = 7; + } + chip->ecc.priv = nand_bch_init(mtd, + chip->ecc.size, + chip->ecc.bytes, + &chip->ecc.layout); + if (!chip->ecc.priv) { + printk(KERN_WARNING "BCH ECC initialization failed!\n"); + BUG(); + } + break; + case NAND_ECC_NONE: printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " "This is not recommended !!\n"); @@ -3501,6 +3536,9 @@ void nand_release(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; + if (chip->ecc.mode == NAND_ECC_SOFT_BCH) + nand_bch_free((struct nand_bch_control *)chip->ecc.priv); + #ifdef CONFIG_MTD_PARTITIONS /* Deregister partitions */ del_mtd_partitions(mtd); |