diff options
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
| -rw-r--r-- | drivers/mtd/nand/nand_base.c | 39 | 
1 files changed, 38 insertions, 1 deletions
| diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 27f6c776b..b03953f5b 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -43,6 +43,7 @@  #include <linux/mtd/mtd.h>  #include <linux/mtd/nand.h>  #include <linux/mtd/nand_ecc.h> +#include <linux/mtd/nand_bch.h>  #ifdef CONFIG_MTD_PARTITIONS  #include <linux/mtd/partitions.h> @@ -2763,7 +2764,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; @@ -2864,6 +2865,39 @@ 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"); +			return -EINVAL; +		} +		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"); + +		break; +  	case NAND_ECC_NONE:  		printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "  		       "This is not recommended !!\n"); @@ -2989,6 +3023,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); |