diff options
author | Armando Visconti <armando.visconti@st.com> | 2012-03-07 06:30:54 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-03-26 19:48:06 -0400 |
commit | 753e0139e5569946056a8d5960111665a7f8f6f1 (patch) | |
tree | 53d2f38c02513638e4b83171c4f835e8e3302c82 /drivers/mtd | |
parent | a612c2ae483ee7e4d40c31d5374edf8a8b025f2a (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')
-rw-r--r-- | drivers/mtd/nand/fsmc_nand.c | 38 |
1 files changed, 17 insertions, 21 deletions
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index cfe15a6f29d0..5b217f2a31b7 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 | */ |
599 | static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat, | 599 | static 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(®s->bank_regs[bank].sts) >> 10) & 0xF; | 611 | num_err = (readl(®s->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(®s->bank_regs[bank].ecc1); |
658 | if (i == 4) { | 655 | ecc2 = readl(®s->bank_regs[bank].ecc2); |
659 | err_idx[4] = ((ecc_data[1] & 0x1) << 12) | ecc_data[0]; | 656 | ecc3 = readl(®s->bank_regs[bank].ecc3); |
660 | ecc_data[1] >>= 1; | 657 | ecc4 = readl(®s->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(®s->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; |