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>
This commit is contained in:
parent
8ae6bcd1dc
commit
ff6ee10158
@ -863,17 +863,6 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
|
|||||||
uint8_t *buf_pos;
|
uint8_t *buf_pos;
|
||||||
int max_bitflips = 0;
|
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++) {
|
for (i = 0; i < nand_chip->ecc.steps; i++) {
|
||||||
err_nbr = 0;
|
err_nbr = 0;
|
||||||
if (pmecc_stat & 0x1) {
|
if (pmecc_stat & 0x1) {
|
||||||
@ -884,16 +873,30 @@ normal_check:
|
|||||||
pmecc_get_sigma(mtd);
|
pmecc_get_sigma(mtd);
|
||||||
|
|
||||||
err_nbr = pmecc_err_location(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");
|
dev_err(host->dev, "PMECC: Too many errors\n");
|
||||||
mtd->ecc_stats.failed++;
|
mtd->ecc_stats.failed++;
|
||||||
return -EIO;
|
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;
|
pmecc_stat >>= 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user