[MTD] NAND Cleanup oob functions

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Thu May 25 08:59:06 EDT 2006


Commit:     7314e9e7d57293c58b3e10a25a8a1d9328444187
Parent:     7a30601b3ac7b02440ffa629fd3d2cca71c1bcd8
Author:     Thomas Gleixner <tglx at cruncher.tec.linutronix.de>
AuthorDate: Thu May 25 09:51:54 2006 +0200
Commit:     David Woodhouse <dwmw2 at infradead.org>
CommitDate: Thu May 25 12:45:27 2006 +0100

    [MTD] NAND Cleanup oob functions
    
    Cleanup the code in the oob related functions and
    make use of the new NO_READRDY flag.
    
    Signed-off-by: Thomas Gleixner <tglx at linutronix.de>

 drivers/mtd/nand/nand_base.c |  156 ++++++++++++++++++++++--------------------
 1 files changed, 81 insertions(+), 75 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 61b2363..49bca24 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1270,86 +1270,91 @@ int nand_do_read_ecc(struct mtd_info *mt
  *
  * NAND read out-of-band data from the spare area
  */
-static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf)
+static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+			 size_t *retlen, uint8_t *buf)
 {
-	int i, col, page, chipnr;
+	int col, page, realpage, chipnr, sndcmd = 1;
 	struct nand_chip *chip = mtd->priv;
-	int blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
-
-	DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int)from, (int)len);
-
-	/* Shift to get page */
-	page = (int)(from >> chip->page_shift);
-	chipnr = (int)(from >> chip->chip_shift);
+	int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+	int readlen = len;
 
-	/* Mask to get column */
-	col = from & (mtd->oobsize - 1);
+	DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n",
+	      (unsigned int)from, (int)len);
 
 	/* Initialize return length value */
 	*retlen = 0;
 
 	/* Do not allow reads past end of device */
 	if ((from + len) > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n");
-		*retlen = 0;
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+		      "Attempt read beyond end of device\n");
 		return -EINVAL;
 	}
 
-	/* Grab the lock and see if the device is available */
 	nand_get_device(chip, mtd, FL_READING);
 
-	/* Select the NAND device */
+	chipnr = (int)(from >> chip->chip_shift);
 	chip->select_chip(mtd, chipnr);
 
-	/* Send the read command */
-	chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page & chip->pagemask);
-	/*
-	 * Read the data, if we read more than one page
-	 * oob data, let the device transfer the data !
-	 */
-	i = 0;
-	while (i < len) {
-		int thislen = mtd->oobsize - col;
-		thislen = min_t(int, thislen, len);
-		chip->read_buf(mtd, &buf[i], thislen);
-		i += thislen;
-
-		/* Read more ? */
-		if (i < len) {
-			page++;
-			col = 0;
+	/* Shift to get page */
+	realpage = (int)(from >> chip->page_shift);
+	page = realpage & chip->pagemask;
 
-			/* Check, if we cross a chip boundary */
-			if (!(page & chip->pagemask)) {
-				chipnr++;
-				chip->select_chip(mtd, -1);
-				chip->select_chip(mtd, chipnr);
-			}
+	/* Mask to get column */
+	col = from & (mtd->oobsize - 1);
+
+	while(1) {
+		int bytes = min((int)(mtd->oobsize - col), readlen);
+
+		if (likely(sndcmd)) {
+			chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page);
+			sndcmd = 0;
+		}
+
+		chip->read_buf(mtd, buf, bytes);
 
-			/* Apply delay or wait for ready/busy pin
-			 * Do this before the AUTOINCR check, so no problems
-			 * arise if a chip which does auto increment
-			 * is marked as NOAUTOINCR by the board driver.
+		readlen -= bytes;
+		if (!readlen)
+			break;
+
+		if (!(chip->options & NAND_NO_READRDY)) {
+			/*
+			 * Apply delay or wait for ready/busy pin. Do this
+			 * before the AUTOINCR check, so no problems arise if a
+			 * chip which does auto increment is marked as
+			 * NOAUTOINCR by the board driver.
 			 */
 			if (!chip->dev_ready)
 				udelay(chip->chip_delay);
 			else
 				nand_wait_ready(mtd);
+		}
 
-			/* Check, if the chip supports auto page increment
-			 * or if we have hit a block boundary.
-			 */
-			if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck)) {
-				/* For subsequent page reads set offset to 0 */
-				chip->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & chip->pagemask);
-			}
+		buf += bytes;
+		bytes = mtd->oobsize;
+		col = 0;
+
+		/* Increment page address */
+		realpage++;
+
+		page = realpage & chip->pagemask;
+		/* Check, if we cross a chip boundary */
+		if (!page) {
+			chipnr++;
+			chip->select_chip(mtd, -1);
+			chip->select_chip(mtd, chipnr);
 		}
+
+		/* Check, if the chip supports auto page increment
+		 * or if we have hit a block boundary.
+		 */
+		if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
+			sndcmd = 1;
 	}
 
 	/* Deselect and wake up anyone waiting on the device */
 	nand_release_device(mtd);
 
-	/* Return happy */
 	*retlen = len;
 	return 0;
 }
@@ -1676,6 +1681,7 @@ static int nand_write(struct mtd_info *m
 	return ret;
 }
 
+
 /**
  * nand_write_oob - [MTD Interface] NAND write out-of-band
  * @mtd:	MTD device structure
@@ -1686,40 +1692,40 @@ static int nand_write(struct mtd_info *m
  *
  * NAND write out-of-band
  */
-static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf)
+static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
+			  size_t *retlen, const uint8_t *buf)
 {
 	int column, page, status, ret = -EIO, chipnr;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
-
-	/* Shift to get page */
-	page = (int)(to >> chip->page_shift);
-	chipnr = (int)(to >> chip->chip_shift);
-
-	/* Mask to get column */
-	column = to & (mtd->oobsize - 1);
+	DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
+	      (unsigned int)to, (int)len);
 
 	/* Initialize return length value */
 	*retlen = 0;
 
 	/* Do not allow write past end of page */
+	column = to & (mtd->oobsize - 1);
 	if ((column + len) > mtd->oobsize) {
-		DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
+		      "Attempt to write past end of page\n");
 		return -EINVAL;
 	}
 
-	/* Grab the lock and see if the device is available */
 	nand_get_device(chip, mtd, FL_WRITING);
 
-	/* Select the NAND device */
+	chipnr = (int)(to >> chip->chip_shift);
 	chip->select_chip(mtd, chipnr);
 
-	/* Reset the chip. Some chips (like the Toshiba TC5832DC found
-	   in one of my DiskOnChip 2000 test units) will clear the whole
-	   data page too if we don't do this. I have no clue why, but
-	   I seem to have 'fixed' it in the doc2000 driver in
-	   August 1999.  dwmw2. */
+	/* Shift to get page */
+	page = (int)(to >> chip->page_shift);
+
+	/*
+	 * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
+	 * of my DiskOnChip 2000 test units) will clear the whole data page too
+	 * if we don't do this. I have no clue why, but I seem to have 'fixed'
+	 * it in the doc2000 driver in August 1999.  dwmw2.
+	 */
 	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 
 	/* Check, if it is write protected */
@@ -1731,8 +1737,8 @@ static int nand_write_oob(struct mtd_inf
 		chip->pagebuf = -1;
 
 	if (NAND_MUST_PAD(chip)) {
-		/* Write out desired data */
-		chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page & chip->pagemask);
+		chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize,
+			      page & chip->pagemask);
 		/* prepad 0xff for partial programming */
 		chip->write_buf(mtd, ffchars, column);
 		/* write data */
@@ -1740,9 +1746,8 @@ static int nand_write_oob(struct mtd_inf
 		/* postpad 0xff for partial programming */
 		chip->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
 	} else {
-		/* Write out desired data */
-		chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column, page & chip->pagemask);
-		/* write data */
+		chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column,
+			      page & chip->pagemask);
 		chip->write_buf(mtd, buf, len);
 	}
 	/* Send command to program the OOB data */
@@ -1752,11 +1757,11 @@ static int nand_write_oob(struct mtd_inf
 
 	/* See if device thinks it succeeded */
 	if (status & NAND_STATUS_FAIL) {
-		DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
+		      "Failed write, page 0x%08x\n", page);
 		ret = -EIO;
 		goto out;
 	}
-	/* Return happy */
 	*retlen = len;
 
 #ifdef CONFIG_MTD_NAND_VERIFY_WRITE
@@ -1764,7 +1769,8 @@ #ifdef CONFIG_MTD_NAND_VERIFY_WRITE
 	chip->cmdfunc(mtd, NAND_CMD_READOOB, column, page & chip->pagemask);
 
 	if (chip->verify_buf(mtd, buf, len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
+		      "Failed write verify, page 0x%08x\n", page);
 		ret = -EIO;
 		goto out;
 	}



More information about the linux-mtd-cvs mailing list