[linux-yocto] [PATCH 57/87] lsi/nand:Use EP501G1_NAND_1BIT_ECC0_STATUS to check HW ECC

Paul Butler butler.paul at gmail.com
Mon May 27 09:56:28 PDT 2013


From: Jiang Lu <lu.jiang at windriver.com>

On ACP34xx, remounting a jffs2 partition will fail after writing file
with following error:
mount:/dev/mtdblock6 can't read superblock

This is caused by involving EP501G1_NAND_BCH_STATUS to check HW ECC
result. This patch reads EP501G1_NAND_1BIT_ECC0_STATUS to check HW
ECC result. When EP501G1_NAND_BCH_STATUS returns non-zero value,
EP501G1_NAND_1BIT_ECC0_STATUS reads zero, it indicate no HW ECC error.

Extract from vendor drop patch lsi-patch 3.8.1.12.

Signed-off-by: Jiang Lu <lu.jiang at windriver.com>
---
 drivers/mtd/nand/lsi_acp_nand.c | 104 +++++++---------------------------------
 1 file changed, 16 insertions(+), 88 deletions(-)

diff --git a/drivers/mtd/nand/lsi_acp_nand.c b/drivers/mtd/nand/lsi_acp_nand.c
index 94b8e3c..eb9943a 100644
--- a/drivers/mtd/nand/lsi_acp_nand.c
+++ b/drivers/mtd/nand/lsi_acp_nand.c
@@ -2820,100 +2820,28 @@ static int
 report_ecc_errors_ep501g1(struct mtd_info *mtd, struct nand_chip *chip,
 			  uint8_t *buffer, int page)
 {
-	unsigned long bch_status;
-	int rc = 0;
+	unsigned long ecc_status;
 	int i;
-	int is_blank = 1;
-	uint8_t *data = buffer;
-	int section;
-	int syndrome;
-	unsigned long syndromes[8][8];
-
-	/* If there are no errors, return. */
-	bch_status = READL(chip->IO_ADDR_R + EP501G1_NAND_BCH_STATUS);
 
-	if (0 == bch_status)
-		goto report_ecc_errors_ep501g1_end;
+	for (i = 0; i < (mtd->writesize / 1024); ++i) {
+		ecc_status = readl(chip->IO_ADDR_R +
+				   EP501G1_NAND_1BIT_ECC0_STATUS + (i * 4));
 
-	switch (mtd->writesize) {
-	case 512:
-		bch_status &= 0x1;
-		break;
-	case 2048:
-		bch_status &= 0xf;
-		break;
-	case 4096:
-		bch_status &= 0xff;
-		break;
-	default:
-		printk(KERN_ERR "Unexpected Page Size!\n");
-		rc = -1;
-		goto report_ecc_errors_ep501g1_end;
-		break;
-	}
-
-	/* Ignore fully erased blocks. */
-	if (NULL != data) {
-		for (i = 0; i < mtd->writesize; ++i) {
-			if (0xff != *data++) {
-				is_blank = 0;
-				break;
-			}
-		}
-	}
-
-	if (0 != is_blank)
-		goto report_ecc_errors_ep501g1_end;
-
-	/* Read the syndrome registers and split them into syndromes. */
-	for (section = 0; section < 8; ++section) {
-		unsigned long address;
-		unsigned long value;
-
-		address = EP501G1_NAND_SYN_R12_S0 + (section * 0x10);
-
-		for (syndrome = 0; syndrome < 8; syndrome += 2) {
-			value = READL(chip->IO_ADDR_R + address +
-				      (syndrome * 2));
-			syndromes[section][syndrome] =
-				(value & 0x1fff);
-			syndromes[section][syndrome + 1] =
-				((value & 0x1fff0000) >> 16);
-		}
-	}
-
-#ifdef NOT_USED
-	/* Debug output (BCH status register and syndromes). */
-	printk(KERN_INFO "BCH Status Register: 0x%02lx\n", bch_status);
-
-	for (section = 0; section < 8; ++section) {
-		printk(KERN_INFO "Syndromes, Section %d: ", section);
-
-		for (syndrome = 0; syndrome < 8; ++syndrome) {
-			printk(KERN_INFO "0x%04lx ",
-			       syndromes[section][syndrome]);
-		}
-
-		printk(KERN_INFO "\n");
-	}
-#endif
-
-	for (i = 0; i < 4; ++i) {
-		if ((1 << i) == (bch_status & (1 << i))) {
-			rc = fix_section(((page * mtd->writesize) + (512 * i)),
-					 (void *)(buffer + (512 * i)),
-					 (int *)&syndromes[i]);
-
-			if (-1 == rc)
-				printk(KERN_ERR
-				       "Uncorrectable ECC Error: Page %d\n",
-				       page);
+		switch (ecc_status & (3 << 12)) {
+		case 01:
+			printk(KERN_ERR
+			       "Correctable ECC Error: %d:0x%lx\n",
+			       i, ecc_status);
+			break;
+		case 02:
+			printk(KERN_ERR
+			       "Uncorrectable ECC Error: %d:0x%lx\n",
+			       i, ecc_status);
+			break;
 		}
 	}
 
- report_ecc_errors_ep501g1_end:
-
-	return rc;
+	return 0;
 }
 
 /*
-- 
1.8.3




More information about the linux-yocto mailing list