summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/nand/mxs_nand.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index 80d1808228..42fb1877e5 100644
--- a/drivers/mtd/nand/mxs_nand.c
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -645,6 +645,45 @@ static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
return buf;
}
+static bool mxs_nand_erased_page(struct mtd_info *mtd, struct nand_chip *nand,
+ uint8_t *buf, int chunk, int page)
+{
+ int gf_len = galois_field;
+ unsigned int flip_bits = 0, flip_bits_noecc = 0;
+ unsigned int threshold;
+ unsigned int ecc_chunkn_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+ unsigned int base = ecc_chunkn_size * chunk;
+ uint32_t *dma_buf = (uint32_t *)buf;
+ int i;
+
+ threshold = gf_len / 2;
+ if (threshold > ecc_strength)
+ threshold = ecc_strength;
+
+ for (i = 0; i < ecc_chunkn_size; i++) {
+ flip_bits += hweight8(~buf[base + i]);
+ if (flip_bits > threshold)
+ return false;
+ }
+
+ nand->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+ nand->read_buf(mtd, buf, mtd->writesize);
+
+ for (i = 0; i < mtd->writesize / 4; i++) {
+ flip_bits_noecc += hweight32(~dma_buf[i]);
+ if (flip_bits_noecc > threshold)
+ return false;
+ }
+
+ mtd->ecc_stats.corrected += flip_bits;
+
+ memset(buf, 0xff, mtd->writesize);
+
+ printf("The page(%d) is an erased page(%d,%d,%d,%d).\n", page, chunk, threshold, flip_bits, flip_bits_noecc);
+
+ return true;
+}
+
/*
* Read a page from NAND.
*/
@@ -747,6 +786,8 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
goto rtn;
}
+ mxs_nand_return_dma_descs(nand_info);
+
/* Invalidate caches */
mxs_nand_inval_data_buf(nand_info);
@@ -763,6 +804,9 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
continue;
if (status[i] == 0xfe) {
+ if (mxs_nand_erased_page(mtd, nand,
+ nand_info->data_buf, i, page))
+ break;
failed++;
continue;
}