aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2010-08-06 09:53:09 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-08-06 11:37:58 -0400
commit94f77e50d658be1d3ff23fb65e4d075a6f4ebee3 (patch)
tree325e73dc7f558144f3fbd20900e531c14f69c1d4 /drivers/mtd
parent1bc991808da890313c7a23ebc07e68ad8e79f42e (diff)
mxc_nand: fix correct_data function
The v2 controller has a totally different mechanism to check whether the data we read had ecc errors or not. Implement this. The mechanism in the v2 controller happens to be identical to the v3 controller. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/mxc_nand.c42
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
345static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, 346static 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
368static 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
367static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, 402static 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;