diff options
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_bch.c | 27 | ||||
-rw-r--r-- | drivers/mtd/nand/omap2.c | 28 |
3 files changed, 31 insertions, 30 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index a36f15b314ba..191e4f75a513 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4279,10 +4279,8 @@ int nand_scan_tail(struct mtd_info *mtd) } /* See nand_bch_init() for details. */ - ecc->bytes = DIV_ROUND_UP( - ecc->strength * fls(8 * ecc->size), 8); - ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, - &ecc->layout); + ecc->bytes = 0; + ecc->priv = nand_bch_init(mtd); if (!ecc->priv) { pr_warn("BCH ECC initialization failed!\n"); BUG(); diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index a87c1b628dfc..b585bae37929 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c @@ -107,9 +107,6 @@ EXPORT_SYMBOL(nand_bch_correct_data); /** * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction * @mtd: MTD block structure - * @eccsize: ecc block size in bytes - * @eccbytes: ecc length in bytes - * @ecclayout: output default layout * * Returns: * a pointer to a new NAND BCH control structure, or NULL upon failure @@ -123,14 +120,21 @@ EXPORT_SYMBOL(nand_bch_correct_data); * @eccsize = 512 (thus, m=13 is the smallest integer such that 2^m-1 > 512*8) * @eccbytes = 7 (7 bytes are required to store m*t = 13*4 = 52 bits) */ -struct nand_bch_control * -nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, - struct nand_ecclayout **ecclayout) +struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) { + struct nand_chip *nand = mtd_to_nand(mtd); unsigned int m, t, eccsteps, i; - struct nand_ecclayout *layout; + struct nand_ecclayout *layout = nand->ecc.layout; struct nand_bch_control *nbc = NULL; unsigned char *erased_page; + unsigned int eccsize = nand->ecc.size; + unsigned int eccbytes = nand->ecc.bytes; + unsigned int eccstrength = nand->ecc.strength; + + if (!eccbytes && eccstrength) { + eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8); + nand->ecc.bytes = eccbytes; + } if (!eccsize || !eccbytes) { printk(KERN_WARNING "ecc parameters not supplied\n"); @@ -158,7 +162,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, eccsteps = mtd->writesize/eccsize; /* if no ecc placement scheme was provided, build one */ - if (!*ecclayout) { + if (!layout) { /* handle large page devices only */ if (mtd->oobsize < 64) { @@ -184,7 +188,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, layout->oobfree[0].offset = 2; layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; - *ecclayout = layout; + nand->ecc.layout = layout; } /* sanity checks */ @@ -192,7 +196,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, printk(KERN_WARNING "eccsize %u is too large\n", eccsize); goto fail; } - if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) { + if (layout->eccbytes != (eccsteps*eccbytes)) { printk(KERN_WARNING "invalid ecc layout\n"); goto fail; } @@ -216,6 +220,9 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, for (i = 0; i < eccbytes; i++) nbc->eccmask[i] ^= 0xff; + if (!eccstrength) + nand->ecc.strength = (eccbytes * 8) / fls(8 * eccsize); + return nbc; fail: nand_bch_free(nbc); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index c553f78ab83f..0749ca1a1456 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1807,13 +1807,19 @@ static int omap_nand_probe(struct platform_device *pdev) goto return_error; } + /* + * Bail out earlier to let NAND_ECC_SOFT code create its own + * ecclayout instead of using ours. + */ + if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) { + nand_chip->ecc.mode = NAND_ECC_SOFT; + goto scan_tail; + } + /* populate MTD interface based on ECC scheme */ ecclayout = &info->oobinfo; + nand_chip->ecc.layout = ecclayout; switch (info->ecc_opt) { - case OMAP_ECC_HAM1_CODE_SW: - nand_chip->ecc.mode = NAND_ECC_SOFT; - break; - case OMAP_ECC_HAM1_CODE_HW: pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n"); nand_chip->ecc.mode = NAND_ECC_HW; @@ -1861,10 +1867,7 @@ static int omap_nand_probe(struct platform_device *pdev) ecclayout->oobfree->offset = 1 + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; /* software bch library is used for locating errors */ - nand_chip->ecc.priv = nand_bch_init(mtd, - nand_chip->ecc.size, - nand_chip->ecc.bytes, - &ecclayout); + nand_chip->ecc.priv = nand_bch_init(mtd); if (!nand_chip->ecc.priv) { dev_err(&info->pdev->dev, "unable to use BCH library\n"); err = -EINVAL; @@ -1925,10 +1928,7 @@ static int omap_nand_probe(struct platform_device *pdev) ecclayout->oobfree->offset = 1 + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; /* software bch library is used for locating errors */ - nand_chip->ecc.priv = nand_bch_init(mtd, - nand_chip->ecc.size, - nand_chip->ecc.bytes, - &ecclayout); + nand_chip->ecc.priv = nand_bch_init(mtd); if (!nand_chip->ecc.priv) { dev_err(&info->pdev->dev, "unable to use BCH library\n"); err = -EINVAL; @@ -2002,9 +2002,6 @@ static int omap_nand_probe(struct platform_device *pdev) goto return_error; } - if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) - goto scan_tail; - /* all OOB bytes from oobfree->offset till end off OOB are free */ ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset; /* check if NAND device's OOB is enough to store ECC signatures */ @@ -2015,7 +2012,6 @@ static int omap_nand_probe(struct platform_device *pdev) err = -EINVAL; goto return_error; } - nand_chip->ecc.layout = ecclayout; scan_tail: /* second phase scan */ |