mtd/drivers/mtd/nand rtc_from4.c,1.8,1.9

dmarlin at infradead.org dmarlin at infradead.org
Mon Jan 24 15:40:15 EST 2005


Update of /home/cvs/mtd/drivers/mtd/nand
In directory phoenix.infradead.org:/tmp/cvs-serv25418/drivers/mtd/nand

Modified Files:
	rtc_from4.c 
Log Message:
Added routine to perform extra error status checks on erase and write 
  failures to determine if errors are correctable.
Added option to prevent JFFS2 from using virtual erase blocks.
Performed minor cleanup on whitespace and comments.


Index: rtc_from4.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/rtc_from4.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- rtc_from4.c	17 Jan 2005 19:44:36 -0000	1.8
+++ rtc_from4.c	24 Jan 2005 20:40:11 -0000	1.9
@@ -83,9 +83,14 @@
 #define RTC_FROM4_RS_ECC_CHK		(RTC_FROM4_NAND_ADDR_FPGA | 0x00000070)
 #define RTC_FROM4_RS_ECC_CHK_ERROR	(1 << 7)
 
+#define ERR_STAT_ECC_AVAILABLE		0x20
+
 /* Undefine for software ECC */
 #define RTC_FROM4_HWECC	1
 
+/* Define as 1 for no virtual erase blocks (in JFFS2) */
+#define RTC_FROM4_NO_VIRTBLOCKS	0
+
 /*
  * Module stuff
  */
@@ -267,7 +272,6 @@
 }
 
 
-
 /*
  * rtc_from4_nand_device_ready - hardware specific ready/busy check
  * @mtd:	MTD device structure
@@ -363,6 +367,7 @@
 
 }
 
+
 /*
  * rtc_from4_calculate_ecc - hardware specific code to read ECC code
  * @mtd:	MTD device structure
@@ -390,6 +395,7 @@
 	ecc_code[7] |= 0x0f;	/* set the last four bits (not used) */
 }
 
+
 /*
  * rtc_from4_correct_data - hardware specific code to correct data using ECC code
  * @mtd:	MTD device structure
@@ -399,10 +405,8 @@
  *
  * The FPGA tells us fast, if there's an error or not. If no, we go back happy
  * else we read the ecc results from the fpga and call the rs library to decode
- * and hopefully correct the error
+ * and hopefully correct the error.
  *
- * For now I use the code, which we read from the FLASH to use the RS lib,
- * as the syndrom conversion has a unresolved issue.
  */
 static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2)
 {
@@ -457,8 +461,79 @@
 	}
 	return res;
 }
+
+
+/**
+ * rtc_from4_errstat - perform additional error status checks
+ * @mtd:	MTD device structure
+ * @this:	NAND chip structure
+ * @state:	state or the operation
+ * @status:	status code returned from read status
+ * @page:	startpage inside the chip, must be called with (page & this->pagemask)
+ * 
+ * Perform additional error status checks on erase and write failures 
+ * to determine if errors are correctable.  For this device, correctable 
+ * 1-bit errors on erase and write are considered acceptable.
+ *
+ * note: see pages 34..37 of data sheet for details.
+ *
+ */
+static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page)
+{
+	int	er_stat=0;
+	int	rtn, retlen;
+	size_t	len;
+	uint8_t *buf;
+	int	i;
+
+	this->cmdfunc (mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
+
+        if (state == FL_ERASING) {
+		for (i=0; i<4; i++) {
+			if (status & 1<<(i+1)) {
+				this->cmdfunc (mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);
+				rtn = this->read_byte(mtd);
+				this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
+				if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
+					er_stat |= 1<<(i+1);	/* err_ecc_not_avail */
+				}
+			}
+		}
+	} else if (state == FL_WRITING) {
+		/* single bank write logic */
+		this->cmdfunc (mtd, NAND_CMD_STATUS_ERROR, -1, -1);
+		rtn = this->read_byte(mtd);
+		this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
+		if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
+			er_stat |= 1<<1;	/* err_ecc_not_avail */
+		} else {
+			len = mtd->oobblock;
+			buf = kmalloc (len, GFP_KERNEL);
+			if (!buf) {
+				printk (KERN_ERR "rtc_from4_errstat: Out of memory!\n");
+				er_stat = 1;			/* if we can't check, assume failed */
+			} else {
+				/* recovery read */
+				/* page read */
+				rtn = nand_do_read_ecc (mtd, page, len, &retlen, buf, NULL, this->autooob, 1);
+				if (rtn) {	/* if read failed or > 1-bit error corrected */
+					er_stat |= 1<<1;	/* ECC read failed */
+				}
+				kfree(buf);
+			}
+		}
+	}
+
+	rtn = status;
+	if (er_stat == 0) {				/* if ECC is available   */
+		rtn = (status & ~NAND_STATUS_FAIL);	/*   clear the error bit */
+	}
+
+	return rtn;
+}
 #endif
 
+
 /*
  * Main initialization routine
  */
@@ -518,6 +593,8 @@
 
         this->eccmode = NAND_ECC_HW8_512;
 	this->options |= NAND_HWECC_SYNDROME;
+	/* return the status of extra status and ECC checks */
+	this->errstat = rtc_from4_errstat;
 	/* set the nand_oobinfo to support FPGA H/W error detection */
 	this->autooob = &rtc_from4_nand_oobinfo;
 	this->enable_hwecc = rtc_from4_enable_hwecc;
@@ -544,6 +621,13 @@
 		deplete(rtc_from4_mtd, i);
 	}
 
+#if RTC_FROM4_NO_VIRTBLOCKS
+	/* use a smaller erase block to minimize wasted space when a block is bad */
+	/* note: this uses eight times as much RAM as using the default and makes */
+	/*       mounts take four times as long. */
+	rtc_from4_mtd->flags |= MTD_NO_VIRTBLOCKS;
+#endif
+
 	/* Register the partitions */
 	add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
 





More information about the linux-mtd-cvs mailing list