diff options
-rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 6d0fa4cd1ddf..f5fd25461a09 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -94,6 +94,7 @@ struct mxc_nand_host { | |||
94 | struct clk *clk; | 94 | struct clk *clk; |
95 | int clk_act; | 95 | int clk_act; |
96 | int irq; | 96 | int irq; |
97 | int eccsize; | ||
97 | 98 | ||
98 | wait_queue_head_t irq_waitq; | 99 | wait_queue_head_t irq_waitq; |
99 | 100 | ||
@@ -342,7 +343,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) | |||
342 | */ | 343 | */ |
343 | } | 344 | } |
344 | 345 | ||
345 | static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | 346 | static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, |
346 | u_char *read_ecc, u_char *calc_ecc) | 347 | u_char *read_ecc, u_char *calc_ecc) |
347 | { | 348 | { |
348 | struct nand_chip *nand_chip = mtd->priv; | 349 | struct nand_chip *nand_chip = mtd->priv; |
@@ -364,6 +365,40 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
364 | return 0; | 365 | return 0; |
365 | } | 366 | } |
366 | 367 | ||
368 | static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, | ||
369 | u_char *read_ecc, u_char *calc_ecc) | ||
370 | { | ||
371 | struct nand_chip *nand_chip = mtd->priv; | ||
372 | struct mxc_nand_host *host = nand_chip->priv; | ||
373 | u32 ecc_stat, err; | ||
374 | int no_subpages = 1; | ||
375 | int ret = 0; | ||
376 | u8 ecc_bit_mask, err_limit; | ||
377 | |||
378 | ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf; | ||
379 | err_limit = (host->eccsize == 4) ? 0x4 : 0x8; | ||
380 | |||
381 | no_subpages = mtd->writesize >> 9; | ||
382 | |||
383 | ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT); | ||
384 | |||
385 | do { | ||
386 | err = ecc_stat & ecc_bit_mask; | ||
387 | if (err > err_limit) { | ||
388 | printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); | ||
389 | return -1; | ||
390 | } else { | ||
391 | ret += err; | ||
392 | } | ||
393 | ecc_stat >>= 4; | ||
394 | } while (--no_subpages); | ||
395 | |||
396 | mtd->ecc_stats.corrected += ret; | ||
397 | pr_debug("%d Symbol Correctable RS-ECC Error\n", ret); | ||
398 | |||
399 | return ret; | ||
400 | } | ||
401 | |||
367 | static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | 402 | static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, |
368 | u_char *ecc_code) | 403 | u_char *ecc_code) |
369 | { | 404 | { |
@@ -790,7 +825,10 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
790 | if (pdata->hw_ecc) { | 825 | if (pdata->hw_ecc) { |
791 | this->ecc.calculate = mxc_nand_calculate_ecc; | 826 | this->ecc.calculate = mxc_nand_calculate_ecc; |
792 | this->ecc.hwctl = mxc_nand_enable_hwecc; | 827 | this->ecc.hwctl = mxc_nand_enable_hwecc; |
793 | this->ecc.correct = mxc_nand_correct_data; | 828 | if (nfc_is_v1()) |
829 | this->ecc.correct = mxc_nand_correct_data_v1; | ||
830 | else | ||
831 | this->ecc.correct = mxc_nand_correct_data_v2_v3; | ||
794 | this->ecc.mode = NAND_ECC_HW; | 832 | this->ecc.mode = NAND_ECC_HW; |
795 | } else { | 833 | } else { |
796 | this->ecc.mode = NAND_ECC_SOFT; | 834 | this->ecc.mode = NAND_ECC_SOFT; |