diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-03-01 14:11:52 +0100 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-04-19 22:04:50 +0200 |
commit | ff6ee101584c17c4f30ca48d75e2910c49d0b0ff (patch) | |
tree | 0c6471fc6c8e6e4d890a1d4679888867b284fb21 /drivers/mtd/nand/atmel_nand.c | |
parent | mtd: nand: nandsim: set ECC algorithm explicitly (diff) | |
download | linux-ff6ee101584c17c4f30ca48d75e2910c49d0b0ff.tar.xz linux-ff6ee101584c17c4f30ca48d75e2910c49d0b0ff.zip |
mtd: nand: atmel: correct bitflips in erased pages for pre-sama5d4 SoCs
New atmel SoCs are able to fix bitflips in erased pages, but old ones
are still impacted by this problem. Use nand_check_erased_ecc_chunk() to
handle this case.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Reported-by: Herve Codina <herve.CODINA@celad.com>
Reviewed-by: Herve Codina <herve.CODINA@celad.com>
Tested-by: Herve Codina <herve.CODINA@celad.com>
Diffstat (limited to 'drivers/mtd/nand/atmel_nand.c')
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 37 |
1 files changed, 20 insertions, 17 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 20cbaabb2959..0b5da7271440 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -863,17 +863,6 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, uint8_t *buf_pos; int max_bitflips = 0; - /* If can correct bitfilps from erased page, do the normal check */ - if (host->caps->pmecc_correct_erase_page) - goto normal_check; - - for (i = 0; i < nand_chip->ecc.total; i++) - if (ecc[i] != 0xff) - goto normal_check; - /* Erased page, return OK */ - return 0; - -normal_check: for (i = 0; i < nand_chip->ecc.steps; i++) { err_nbr = 0; if (pmecc_stat & 0x1) { @@ -884,16 +873,30 @@ normal_check: pmecc_get_sigma(mtd); err_nbr = pmecc_err_location(mtd); - if (err_nbr == -1) { + if (err_nbr >= 0) { + pmecc_correct_data(mtd, buf_pos, ecc, i, + nand_chip->ecc.bytes, + err_nbr); + } else if (!host->caps->pmecc_correct_erase_page) { + u8 *ecc_pos = ecc + (i * nand_chip->ecc.bytes); + + /* Try to detect erased pages */ + err_nbr = nand_check_erased_ecc_chunk(buf_pos, + host->pmecc_sector_size, + ecc_pos, + nand_chip->ecc.bytes, + NULL, 0, + nand_chip->ecc.strength); + } + + if (err_nbr < 0) { dev_err(host->dev, "PMECC: Too many errors\n"); mtd->ecc_stats.failed++; return -EIO; - } else { - pmecc_correct_data(mtd, buf_pos, ecc, i, - nand_chip->ecc.bytes, err_nbr); - mtd->ecc_stats.corrected += err_nbr; - max_bitflips = max_t(int, max_bitflips, err_nbr); } + + mtd->ecc_stats.corrected += err_nbr; + max_bitflips = max_t(int, max_bitflips, err_nbr); } pmecc_stat >>= 1; } |