aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c57
1 files changed, 35 insertions, 22 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index ce3449c50e12..f00ce27f61d0 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -85,6 +85,9 @@
85#define NDCR_INT_MASK (0xFFF) 85#define NDCR_INT_MASK (0xFFF)
86 86
87#define NDSR_MASK (0xfff) 87#define NDSR_MASK (0xfff)
88#define NDSR_ERR_CNT_OFF (16)
89#define NDSR_ERR_CNT_MASK (0x1f)
90#define NDSR_ERR_CNT(sr) ((sr >> NDSR_ERR_CNT_OFF) & NDSR_ERR_CNT_MASK)
88#define NDSR_RDY (0x1 << 12) 91#define NDSR_RDY (0x1 << 12)
89#define NDSR_FLASH_RDY (0x1 << 11) 92#define NDSR_FLASH_RDY (0x1 << 11)
90#define NDSR_CS0_PAGED (0x1 << 10) 93#define NDSR_CS0_PAGED (0x1 << 10)
@@ -93,8 +96,8 @@
93#define NDSR_CS1_CMDD (0x1 << 7) 96#define NDSR_CS1_CMDD (0x1 << 7)
94#define NDSR_CS0_BBD (0x1 << 6) 97#define NDSR_CS0_BBD (0x1 << 6)
95#define NDSR_CS1_BBD (0x1 << 5) 98#define NDSR_CS1_BBD (0x1 << 5)
96#define NDSR_DBERR (0x1 << 4) 99#define NDSR_UNCORERR (0x1 << 4)
97#define NDSR_SBERR (0x1 << 3) 100#define NDSR_CORERR (0x1 << 3)
98#define NDSR_WRDREQ (0x1 << 2) 101#define NDSR_WRDREQ (0x1 << 2)
99#define NDSR_RDDREQ (0x1 << 1) 102#define NDSR_RDDREQ (0x1 << 1)
100#define NDSR_WRCMDREQ (0x1) 103#define NDSR_WRCMDREQ (0x1)
@@ -135,9 +138,9 @@ enum {
135 ERR_NONE = 0, 138 ERR_NONE = 0,
136 ERR_DMABUSERR = -1, 139 ERR_DMABUSERR = -1,
137 ERR_SENDCMD = -2, 140 ERR_SENDCMD = -2,
138 ERR_DBERR = -3, 141 ERR_UNCORERR = -3,
139 ERR_BBERR = -4, 142 ERR_BBERR = -4,
140 ERR_SBERR = -5, 143 ERR_CORERR = -5,
141}; 144};
142 145
143enum { 146enum {
@@ -221,6 +224,8 @@ struct pxa3xx_nand_info {
221 unsigned int oob_size; 224 unsigned int oob_size;
222 unsigned int spare_size; 225 unsigned int spare_size;
223 unsigned int ecc_size; 226 unsigned int ecc_size;
227 unsigned int ecc_err_cnt;
228 unsigned int max_bitflips;
224 int retcode; 229 int retcode;
225 230
226 /* cached register value */ 231 /* cached register value */
@@ -567,10 +572,25 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
567 572
568 status = nand_readl(info, NDSR); 573 status = nand_readl(info, NDSR);
569 574
570 if (status & NDSR_DBERR) 575 if (status & NDSR_UNCORERR)
571 info->retcode = ERR_DBERR; 576 info->retcode = ERR_UNCORERR;
572 if (status & NDSR_SBERR) 577 if (status & NDSR_CORERR) {
573 info->retcode = ERR_SBERR; 578 info->retcode = ERR_CORERR;
579 if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 &&
580 info->ecc_bch)
581 info->ecc_err_cnt = NDSR_ERR_CNT(status);
582 else
583 info->ecc_err_cnt = 1;
584
585 /*
586 * Each chunk composing a page is corrected independently,
587 * and we need to store maximum number of corrected bitflips
588 * to return it to the MTD layer in ecc.read_page().
589 */
590 info->max_bitflips = max_t(unsigned int,
591 info->max_bitflips,
592 info->ecc_err_cnt);
593 }
574 if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { 594 if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
575 /* whether use dma to transfer data */ 595 /* whether use dma to transfer data */
576 if (info->use_dma) { 596 if (info->use_dma) {
@@ -668,6 +688,7 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
668 info->use_ecc = 0; 688 info->use_ecc = 0;
669 info->use_spare = 1; 689 info->use_spare = 1;
670 info->retcode = ERR_NONE; 690 info->retcode = ERR_NONE;
691 info->ecc_err_cnt = 0;
671 info->ndcb3 = 0; 692 info->ndcb3 = 0;
672 693
673 switch (command) { 694 switch (command) {
@@ -1049,26 +1070,18 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
1049{ 1070{
1050 struct pxa3xx_nand_host *host = mtd->priv; 1071 struct pxa3xx_nand_host *host = mtd->priv;
1051 struct pxa3xx_nand_info *info = host->info_data; 1072 struct pxa3xx_nand_info *info = host->info_data;
1052 int max_bitflips = 0;
1053 1073
1054 chip->read_buf(mtd, buf, mtd->writesize); 1074 chip->read_buf(mtd, buf, mtd->writesize);
1055 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); 1075 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
1056 1076
1057 if (info->retcode == ERR_SBERR) { 1077 if (info->retcode == ERR_CORERR && info->use_ecc) {
1058 switch (info->use_ecc) { 1078 mtd->ecc_stats.corrected += info->ecc_err_cnt;
1059 case 1: 1079
1060 max_bitflips = 1; 1080 } else if (info->retcode == ERR_UNCORERR) {
1061 mtd->ecc_stats.corrected++;
1062 break;
1063 case 0:
1064 default:
1065 break;
1066 }
1067 } else if (info->retcode == ERR_DBERR) {
1068 /* 1081 /*
1069 * for blank page (all 0xff), HW will calculate its ECC as 1082 * for blank page (all 0xff), HW will calculate its ECC as
1070 * 0, which is different from the ECC information within 1083 * 0, which is different from the ECC information within
1071 * OOB, ignore such double bit errors 1084 * OOB, ignore such uncorrectable errors
1072 */ 1085 */
1073 if (is_buf_blank(buf, mtd->writesize)) 1086 if (is_buf_blank(buf, mtd->writesize))
1074 info->retcode = ERR_NONE; 1087 info->retcode = ERR_NONE;
@@ -1076,7 +1089,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
1076 mtd->ecc_stats.failed++; 1089 mtd->ecc_stats.failed++;
1077 } 1090 }
1078 1091
1079 return max_bitflips; 1092 return info->max_bitflips;
1080} 1093}
1081 1094
1082static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) 1095static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)