diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-03-01 08:11:52 -0500 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@free-electrons.com> | 2016-04-19 16:04:50 -0400 |
commit | ff6ee101584c17c4f30ca48d75e2910c49d0b0ff (patch) | |
tree | 0c6471fc6c8e6e4d890a1d4679888867b284fb21 | |
parent | 8ae6bcd1dcea249591b4165bd7f795c4868bc531 (diff) |
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>
-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, | |||
863 | uint8_t *buf_pos; | 863 | uint8_t *buf_pos; |
864 | int max_bitflips = 0; | 864 | int max_bitflips = 0; |
865 | 865 | ||
866 | /* If can correct bitfilps from erased page, do the normal check */ | ||
867 | if (host->caps->pmecc_correct_erase_page) | ||
868 | goto normal_check; | ||
869 | |||
870 | for (i = 0; i < nand_chip->ecc.total; i++) | ||
871 | if (ecc[i] != 0xff) | ||
872 | goto normal_check; | ||
873 | /* Erased page, return OK */ | ||
874 | return 0; | ||
875 | |||
876 | normal_check: | ||
877 | for (i = 0; i < nand_chip->ecc.steps; i++) { | 866 | for (i = 0; i < nand_chip->ecc.steps; i++) { |
878 | err_nbr = 0; | 867 | err_nbr = 0; |
879 | if (pmecc_stat & 0x1) { | 868 | if (pmecc_stat & 0x1) { |
@@ -884,16 +873,30 @@ normal_check: | |||
884 | pmecc_get_sigma(mtd); | 873 | pmecc_get_sigma(mtd); |
885 | 874 | ||
886 | err_nbr = pmecc_err_location(mtd); | 875 | err_nbr = pmecc_err_location(mtd); |
887 | if (err_nbr == -1) { | 876 | if (err_nbr >= 0) { |
877 | pmecc_correct_data(mtd, buf_pos, ecc, i, | ||
878 | nand_chip->ecc.bytes, | ||
879 | err_nbr); | ||
880 | } else if (!host->caps->pmecc_correct_erase_page) { | ||
881 | u8 *ecc_pos = ecc + (i * nand_chip->ecc.bytes); | ||
882 | |||
883 | /* Try to detect erased pages */ | ||
884 | err_nbr = nand_check_erased_ecc_chunk(buf_pos, | ||
885 | host->pmecc_sector_size, | ||
886 | ecc_pos, | ||
887 | nand_chip->ecc.bytes, | ||
888 | NULL, 0, | ||
889 | nand_chip->ecc.strength); | ||
890 | } | ||
891 | |||
892 | if (err_nbr < 0) { | ||
888 | dev_err(host->dev, "PMECC: Too many errors\n"); | 893 | dev_err(host->dev, "PMECC: Too many errors\n"); |
889 | mtd->ecc_stats.failed++; | 894 | mtd->ecc_stats.failed++; |
890 | return -EIO; | 895 | return -EIO; |
891 | } else { | ||
892 | pmecc_correct_data(mtd, buf_pos, ecc, i, | ||
893 | nand_chip->ecc.bytes, err_nbr); | ||
894 | mtd->ecc_stats.corrected += err_nbr; | ||
895 | max_bitflips = max_t(int, max_bitflips, err_nbr); | ||
896 | } | 896 | } |
897 | |||
898 | mtd->ecc_stats.corrected += err_nbr; | ||
899 | max_bitflips = max_t(int, max_bitflips, err_nbr); | ||
897 | } | 900 | } |
898 | pmecc_stat >>= 1; | 901 | pmecc_stat >>= 1; |
899 | } | 902 | } |