mtd/drivers/mtd/nand nand.c,1.47,1.48

David Woodhouse dwmw2 at infradead.org
Tue Jul 1 20:06:23 EDT 2003


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

Modified Files:
	nand.c 
Log Message:
First part of read_buf/write_buf conversion for DMA, DiskOnChip, etc.


Index: nand.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/nand.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -r1.47 -r1.48
--- nand.c	1 Jul 2003 23:31:15 -0000	1.47
+++ nand.c	2 Jul 2003 00:06:20 -0000	1.48
@@ -160,6 +160,10 @@
 /*
  * NAND low-level MTD interface functions
  */
+static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
+static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
+static int nand_verify_buf(struct mtd_info *mtd, u_char *buf, int len);
+
 static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
 static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
 			  size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
@@ -176,6 +180,35 @@
 static void nand_sync (struct mtd_info *mtd);
 static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,  struct nand_oobinfo *oobsel);
 
+static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+	int i;
+	struct nand_chip *this = mtd->priv;
+
+	for (i=0; i<len; i++)
+		writeb(buf[i], this->IO_ADDR_W);
+}
+
+static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	int i;
+	struct nand_chip *this = mtd->priv;
+
+	for (i=0; i<len; i++)
+		buf[i] = readb(this->IO_ADDR_R);
+}
+
+static int nand_verify_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	int i;
+	struct nand_chip *this = mtd->priv;
+
+	for (i=0; i<len; i++)
+		if (buf[i] != readb(this->IO_ADDR_R))
+			return i;
+
+	return 0;
+}
 
 /*
  * Send command to NAND device
@@ -383,8 +416,7 @@
 	/* No ecc and software ecc 3/256, write all */
 	case NAND_ECC_NONE:
 		printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
-		for (i = 0; i < mtd->oobblock; i++) 
-			writeb ( this->data_poi[i] , this->IO_ADDR_W);
+		this->write_buf(mtd, this->data_poi, mtd->oobblock);
 		break;
 	case NAND_ECC_SOFT:
 		this->calculate_ecc(mtd, &this->data_poi[0], &(ecc_code[0]));
@@ -396,15 +428,13 @@
 			for (i = 3; i < 6; i++)
 				oob_data[oob_config[i]] = ecc_code[i];
 		} 
-		for (i = 0; i < mtd->oobblock; i++) 
-			writeb ( this->data_poi[i] , this->IO_ADDR_W);
+		this->write_buf(mtd, this->data_poi, mtd->oobblock);
 		break;
 		
 	/* Hardware ecc 3 byte / 256 data, write first half, get ecc, then second, if 512 byte pagesize */	
 	case NAND_ECC_HW3_256:		
 		this->enable_hwecc(mtd, NAND_ECC_WRITE);	/* enable hardware ecc logic for write */
-		for (i = 0; i < mtd->eccsize; i++) 
-			writeb ( this->data_poi[i] , this->IO_ADDR_W);
+		this->write_buf(mtd, this->data_poi, mtd->eccsize);
 		
 		this->calculate_ecc(mtd, NULL, &(ecc_code[0]));
 		for (i = 0; i < 3; i++)
@@ -412,8 +442,7 @@
 			
 		if (mtd->oobblock == 512) {
 			this->enable_hwecc(mtd, NAND_ECC_WRITE);	/* enable hardware ecc logic for write*/
-			for (i = mtd->eccsize; i < mtd->oobblock; i++) 
-				writeb ( this->data_poi[i] , this->IO_ADDR_W);
+			this->write_buf(mtd, &this->data_poi[mtd->eccsize], mtd->oobblock - mtd->eccsize);
 			this->calculate_ecc(mtd, NULL, &(ecc_code[3]));
 			for (i = 3; i < 6; i++)
 				oob_data[oob_config[i]] = ecc_code[i];
@@ -423,8 +452,7 @@
 	/* Hardware ecc 3 byte / 512 byte data, write full page */	
 	case NAND_ECC_HW3_512:	
 		this->enable_hwecc(mtd, NAND_ECC_WRITE);	/* enable hardware ecc logic */
-		for (i = 0; i < mtd->oobblock; i++) 
-			writeb ( this->data_poi[i] , this->IO_ADDR_W);
+		this->write_buf(mtd, this->data_poi, mtd->oobblock);
 		this->calculate_ecc(mtd, NULL, &(ecc_code[0]));
 		for (i = 0; i < 3; i++)
 			oob_data[oob_config[i]] = ecc_code[i];
@@ -433,8 +461,7 @@
 	/* Hardware ecc 6 byte / 512 byte data, write full page */	
 	case NAND_ECC_HW6_512:	
 		this->enable_hwecc(mtd, NAND_ECC_WRITE);	/* enable hardware ecc logic */
-		for (i = 0; i < mtd->oobblock; i++) 
-			writeb ( this->data_poi[i] , this->IO_ADDR_W);
+		this->write_buf(mtd, this->data_poi, mtd->oobblock);
 		this->calculate_ecc(mtd, NULL, &(ecc_code[0]));
 		for (i = 0; i < 6; i++)
 			oob_data[oob_config[i]] = ecc_code[i];
@@ -446,8 +473,7 @@
 	}	
 	
 	/* Write out OOB data */
-	for (i = 0; i <  mtd->oobsize; i++)
-		writeb ( oob_data[i] , this->IO_ADDR_W);
+	this->write_buf(mtd, oob_data, mtd->oobsize);
 
 	/* Send command to actually program the data */
 	this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1);
@@ -478,20 +504,16 @@
 	/* Send command to read back the page */
 	this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);
 	/* Loop through and verify the data */
-	for (i = 0; i < mtd->oobblock; i++) {
-		if (this->data_poi[i] != readb (this->IO_ADDR_R)) {
-			DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-			return -EIO;
-		}
+	if (this->verify_buf(mtd, this->data_poi, mtd->oobblock)) {
+		DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
+		return -EIO;
 	}
 
 	/* check, if we have a fs-supplied oob-buffer */
 	if (oob_buf) {
-		for (i = 0; i < mtd->oobsize; i++) {
-			if (oob_data[i] != readb (this->IO_ADDR_R)) {
-				DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-				return -EIO;
-			}
+		if (this->verify_buf(mtd, oob_data, mtd->oobsize)) {
+			DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
+			return -EIO;
 		}
 	} else {
 		if (eccmode != NAND_ECC_NONE) {
@@ -504,8 +526,7 @@
 			case NAND_ECC_HW6_512: ecc_bytes = 6; break;
 			}
 
-			for (i = 0; i < mtd->oobsize; i++)
-				oob_data[i] = readb (this->IO_ADDR_R);
+			this->read_buf(mtd, oob_data, mtd->oobsize);
 
 			for (i = 0; i < ecc_bytes; i++) {
 				if (oob_data[oob_config[i]] != ecc_code[i]) {
@@ -617,13 +638,11 @@
 		switch (eccmode) {
 		case NAND_ECC_NONE:	/* No ECC, Read in a page */		
 			printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n");
-			while (j < end)
-				data_poi[j++] = readb (this->IO_ADDR_R);
+			this->read_buf(mtd, data_poi, end);
 			break;
 			
 		case NAND_ECC_SOFT:	/* Software ECC 3/256: Read in a page + oob data */
-			while (j < end)
-				data_poi[j++] = readb (this->IO_ADDR_R);
+			this->read_buf(mtd, data_poi, end);
 			this->calculate_ecc(mtd, &data_poi[0], &ecc_calc[0]);
 			if (mtd->oobblock == 512)
 				this->calculate_ecc(mtd, &data_poi[256], &ecc_calc[3]);
@@ -631,14 +650,12 @@
 			
 		case NAND_ECC_HW3_256: /* Hardware ECC 3 byte /256 byte data: Read in first 256 byte, get ecc, */
 			this->enable_hwecc(mtd, NAND_ECC_READ);	
-			while (j < ecc)
-				data_poi[j++] = readb (this->IO_ADDR_R);
+			this->read_buf(mtd, data_poi, ecc);
 			this->calculate_ecc(mtd, &data_poi[0], &ecc_calc[0]);	/* read from hardware */
 			
 			if (mtd->oobblock == 512) { /* read second, if pagesize = 512 */
 				this->enable_hwecc(mtd, NAND_ECC_READ);	
-				while (j < end)
-					data_poi[j++] = readb (this->IO_ADDR_R);
+				this->read_buf(mtd, &data_poi[ecc], end-ecc);
 				this->calculate_ecc(mtd, &data_poi[256], &ecc_calc[3]); /* read from hardware */
 			}					
 			break;						
@@ -646,8 +663,7 @@
 		case NAND_ECC_HW3_512:	
 		case NAND_ECC_HW6_512: /* Hardware ECC 3/6 byte / 512 byte data : Read in a page  */
 			this->enable_hwecc(mtd, NAND_ECC_READ);	
-			while (j < end)
-				data_poi[j++] = readb (this->IO_ADDR_R);
+			this->read_buf(mtd, data_poi, end);
 			this->calculate_ecc(mtd, &data_poi[0], &ecc_calc[0]);	/* read from hardware */
 			break;
 
@@ -761,10 +777,15 @@
 	 * Read the data, if we read more than one page
 	 * oob data, let the device transfer the data !
 	 */
-	for (i = 0; i < len; i++) {
-		buf[i] = readb (this->IO_ADDR_R);
-		if ((col++ & (mtd->oobsize - 1)) == (mtd->oobsize - 1))
-			udelay (this->chip_delay);
+	i = 0;
+	while (i < len) {
+		int thislen = (mtd->oobsize - col) & (mtd->oobsize - 1);
+
+		this->read_buf(mtd, &buf[i], thislen);
+		i += thislen;
+		col += thislen;
+		/* Delay between pages */
+		udelay (this->chip_delay);
 	}
 	/* De-select the NAND device */
 	nand_deselect ();
@@ -867,12 +888,17 @@
 	return ret;
 }
 
+static u_char ffchars[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
 /*
  * NAND write out-of-band
  */
 static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
 {
-	int i, column, page, status, ret = 0;
+	int column, page, status, ret = 0;
 	struct nand_chip *this = mtd->priv;
 
 	DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
@@ -909,14 +935,11 @@
 	/* Write out desired data */
 	this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page);
 	/* prepad 0xff for partial programming */
-	for (i = 0; i < column; i++)
-		writeb (0xff, this->IO_ADDR_W);
+	this->write_buf(mtd, ffchars, column);
 	/* write data */
-	for (i = 0; i < len; i++)
-		writeb (buf[i], this->IO_ADDR_W);	
+	this->write_buf(mtd, buf, len);
 	/* postpad 0xff for partial programming */
-	for (i = len + column; i < mtd->oobsize; i++)
-		writeb (0xff, this->IO_ADDR_W);
+	this->write_buf(mtd, ffchars, mtd->oobsize - (len+column));
 
 	/* Send command to program the OOB data */
 	this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1);
@@ -1270,6 +1293,13 @@
 	/* check, if a user supplied wait function given */
 	if (this->waitfunc == NULL)
 		this->waitfunc = nand_wait;
+
+	if (this->write_buf == NULL)
+		this->write_buf = nand_write_buf;
+	if (this->read_buf == NULL)
+		this->read_buf = nand_read_buf;
+	if (this->verify_buf == NULL)
+		this->verify_buf = nand_verify_buf;
 
 	/* Select the device */
 	nand_select ();




More information about the linux-mtd-cvs mailing list