aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorArmando Visconti <armando.visconti@st.com>2012-03-07 06:30:54 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-03-26 19:48:06 -0400
commit753e0139e5569946056a8d5960111665a7f8f6f1 (patch)
tree53d2f38c02513638e4b83171c4f835e8e3302c82 /drivers/mtd/nand
parenta612c2ae483ee7e4d40c31d5374edf8a8b025f2a (diff)
mtd: fsmc: Improve the fsmc_correct_data() routine
This patch improves the error correction routine for bch8 - Loop only up to number of errors detected - Improve the error index calculation procedure Additionally, it also renames the "correct" routine to indicate that it is bch8 specific Signed-off-by: Armando Visconti <armando.visconti@st.com> Signed-off-by: Vipin Kumar <vipin.kumar@st.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/fsmc_nand.c38
1 files changed, 17 insertions, 21 deletions
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index cfe15a6f29d..5b217f2a31b 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -587,7 +587,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
587} 587}
588 588
589/* 589/*
590 * fsmc_correct_data 590 * fsmc_bch8_correct_data
591 * @mtd: mtd info structure 591 * @mtd: mtd info structure
592 * @dat: buffer of read data 592 * @dat: buffer of read data
593 * @read_ecc: ecc read from device spare area 593 * @read_ecc: ecc read from device spare area
@@ -596,7 +596,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
596 * calc_ecc is a 104 bit information containing maximum of 8 error 596 * calc_ecc is a 104 bit information containing maximum of 8 error
597 * offset informations of 13 bits each in 512 bytes of read data. 597 * offset informations of 13 bits each in 512 bytes of read data.
598 */ 598 */
599static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat, 599static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
600 uint8_t *read_ecc, uint8_t *calc_ecc) 600 uint8_t *read_ecc, uint8_t *calc_ecc)
601{ 601{
602 struct fsmc_nand_data *host = container_of(mtd, 602 struct fsmc_nand_data *host = container_of(mtd,
@@ -605,8 +605,8 @@ static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat,
605 struct fsmc_regs *regs = host->regs_va; 605 struct fsmc_regs *regs = host->regs_va;
606 unsigned int bank = host->bank; 606 unsigned int bank = host->bank;
607 uint32_t err_idx[8]; 607 uint32_t err_idx[8];
608 uint64_t ecc_data[2];
609 uint32_t num_err, i; 608 uint32_t num_err, i;
609 uint32_t ecc1, ecc2, ecc3, ecc4;
610 610
611 num_err = (readl(&regs->bank_regs[bank].sts) >> 10) & 0xF; 611 num_err = (readl(&regs->bank_regs[bank].sts) >> 10) & 0xF;
612 612
@@ -642,9 +642,6 @@ static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat,
642 return -EBADMSG; 642 return -EBADMSG;
643 } 643 }
644 644
645 /* The calculated ecc is actually the correction index in data */
646 memcpy(ecc_data, calc_ecc, chip->ecc.bytes);
647
648 /* 645 /*
649 * ------------------- calc_ecc[] bit wise -----------|--13 bits--| 646 * ------------------- calc_ecc[] bit wise -----------|--13 bits--|
650 * |---idx[7]--|--.....-----|---idx[2]--||---idx[1]--||---idx[0]--| 647 * |---idx[7]--|--.....-----|---idx[2]--||---idx[1]--||---idx[0]--|
@@ -654,20 +651,19 @@ static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat,
654 * uint64_t array and error offset indexes are populated in err_idx 651 * uint64_t array and error offset indexes are populated in err_idx
655 * array 652 * array
656 */ 653 */
657 for (i = 0; i < 8; i++) { 654 ecc1 = readl(&regs->bank_regs[bank].ecc1);
658 if (i == 4) { 655 ecc2 = readl(&regs->bank_regs[bank].ecc2);
659 err_idx[4] = ((ecc_data[1] & 0x1) << 12) | ecc_data[0]; 656 ecc3 = readl(&regs->bank_regs[bank].ecc3);
660 ecc_data[1] >>= 1; 657 ecc4 = readl(&regs->bank_regs[bank].sts);
661 continue; 658
662 } 659 err_idx[0] = (ecc1 >> 0) & 0x1FFF;
663 err_idx[i] = (ecc_data[i/4] & 0x1FFF); 660 err_idx[1] = (ecc1 >> 13) & 0x1FFF;
664 ecc_data[i/4] >>= 13; 661 err_idx[2] = (((ecc2 >> 0) & 0x7F) << 6) | ((ecc1 >> 26) & 0x3F);
665 } 662 err_idx[3] = (ecc2 >> 7) & 0x1FFF;
666 663 err_idx[4] = (((ecc3 >> 0) & 0x1) << 12) | ((ecc2 >> 20) & 0xFFF);
667 num_err = (readl(&regs->bank_regs[bank].sts) >> 10) & 0xF; 664 err_idx[5] = (ecc3 >> 1) & 0x1FFF;
668 665 err_idx[6] = (ecc3 >> 14) & 0x1FFF;
669 if (num_err == 0xF) 666 err_idx[7] = (((ecc4 >> 16) & 0xFF) << 5) | ((ecc3 >> 27) & 0x1F);
670 return -EBADMSG;
671 667
672 i = 0; 668 i = 0;
673 while (num_err--) { 669 while (num_err--) {
@@ -829,7 +825,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
829 if (AMBA_REV_BITS(host->pid) >= 8) { 825 if (AMBA_REV_BITS(host->pid) >= 8) {
830 nand->ecc.read_page = fsmc_read_page_hwecc; 826 nand->ecc.read_page = fsmc_read_page_hwecc;
831 nand->ecc.calculate = fsmc_read_hwecc_ecc4; 827 nand->ecc.calculate = fsmc_read_hwecc_ecc4;
832 nand->ecc.correct = fsmc_correct_data; 828 nand->ecc.correct = fsmc_bch8_correct_data;
833 nand->ecc.bytes = 13; 829 nand->ecc.bytes = 13;
834 } else { 830 } else {
835 nand->ecc.calculate = fsmc_read_hwecc_ecc1; 831 nand->ecc.calculate = fsmc_read_hwecc_ecc1;