aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-25 03:51:54 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-25 07:45:27 -0400
commit7314e9e7d57293c58b3e10a25a8a1d9328444187 (patch)
tree024eedaa981089699bec36db78b8b460546df575 /drivers/mtd/nand
parent7a30601b3ac7b02440ffa629fd3d2cca71c1bcd8 (diff)
[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@linutronix.de>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/nand_base.c156
1 files changed, 81 insertions, 75 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 61b2363f9324..49bca242610b 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 *mtd, loff_t from, size_t len,
1270 * 1270 *
1271 * NAND read out-of-band data from the spare area 1271 * NAND read out-of-band data from the spare area
1272 */ 1272 */
1273static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf) 1273static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
1274 size_t *retlen, uint8_t *buf)
1274{ 1275{
1275 int i, col, page, chipnr; 1276 int col, page, realpage, chipnr, sndcmd = 1;
1276 struct nand_chip *chip = mtd->priv; 1277 struct nand_chip *chip = mtd->priv;
1277 int blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; 1278 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1278 1279 int readlen = len;
1279 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int)from, (int)len);
1280
1281 /* Shift to get page */
1282 page = (int)(from >> chip->page_shift);
1283 chipnr = (int)(from >> chip->chip_shift);
1284 1280
1285 /* Mask to get column */ 1281 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n",
1286 col = from & (mtd->oobsize - 1); 1282 (unsigned int)from, (int)len);
1287 1283
1288 /* Initialize return length value */ 1284 /* Initialize return length value */
1289 *retlen = 0; 1285 *retlen = 0;
1290 1286
1291 /* Do not allow reads past end of device */ 1287 /* Do not allow reads past end of device */
1292 if ((from + len) > mtd->size) { 1288 if ((from + len) > mtd->size) {
1293 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n"); 1289 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1294 *retlen = 0; 1290 "Attempt read beyond end of device\n");
1295 return -EINVAL; 1291 return -EINVAL;
1296 } 1292 }
1297 1293
1298 /* Grab the lock and see if the device is available */
1299 nand_get_device(chip, mtd, FL_READING); 1294 nand_get_device(chip, mtd, FL_READING);
1300 1295
1301 /* Select the NAND device */ 1296 chipnr = (int)(from >> chip->chip_shift);
1302 chip->select_chip(mtd, chipnr); 1297 chip->select_chip(mtd, chipnr);
1303 1298
1304 /* Send the read command */ 1299 /* Shift to get page */
1305 chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page & chip->pagemask); 1300 realpage = (int)(from >> chip->page_shift);
1306 /* 1301 page = realpage & chip->pagemask;
1307 * Read the data, if we read more than one page
1308 * oob data, let the device transfer the data !
1309 */
1310 i = 0;
1311 while (i < len) {
1312 int thislen = mtd->oobsize - col;
1313 thislen = min_t(int, thislen, len);
1314 chip->read_buf(mtd, &buf[i], thislen);
1315 i += thislen;
1316
1317 /* Read more ? */
1318 if (i < len) {
1319 page++;
1320 col = 0;
1321 1302
1322 /* Check, if we cross a chip boundary */ 1303 /* Mask to get column */
1323 if (!(page & chip->pagemask)) { 1304 col = from & (mtd->oobsize - 1);
1324 chipnr++; 1305
1325 chip->select_chip(mtd, -1); 1306 while(1) {
1326 chip->select_chip(mtd, chipnr); 1307 int bytes = min((int)(mtd->oobsize - col), readlen);
1327 } 1308
1309 if (likely(sndcmd)) {
1310 chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page);
1311 sndcmd = 0;
1312 }
1313
1314 chip->read_buf(mtd, buf, bytes);
1328 1315
1329 /* Apply delay or wait for ready/busy pin 1316 readlen -= bytes;
1330 * Do this before the AUTOINCR check, so no problems 1317 if (!readlen)
1331 * arise if a chip which does auto increment 1318 break;
1332 * is marked as NOAUTOINCR by the board driver. 1319
1320 if (!(chip->options & NAND_NO_READRDY)) {
1321 /*
1322 * Apply delay or wait for ready/busy pin. Do this
1323 * before the AUTOINCR check, so no problems arise if a
1324 * chip which does auto increment is marked as
1325 * NOAUTOINCR by the board driver.
1333 */ 1326 */
1334 if (!chip->dev_ready) 1327 if (!chip->dev_ready)
1335 udelay(chip->chip_delay); 1328 udelay(chip->chip_delay);
1336 else 1329 else
1337 nand_wait_ready(mtd); 1330 nand_wait_ready(mtd);
1331 }
1338 1332
1339 /* Check, if the chip supports auto page increment 1333 buf += bytes;
1340 * or if we have hit a block boundary. 1334 bytes = mtd->oobsize;
1341 */ 1335 col = 0;
1342 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck)) { 1336
1343 /* For subsequent page reads set offset to 0 */ 1337 /* Increment page address */
1344 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & chip->pagemask); 1338 realpage++;
1345 } 1339
1340 page = realpage & chip->pagemask;
1341 /* Check, if we cross a chip boundary */
1342 if (!page) {
1343 chipnr++;
1344 chip->select_chip(mtd, -1);
1345 chip->select_chip(mtd, chipnr);
1346 } 1346 }
1347
1348 /* Check, if the chip supports auto page increment
1349 * or if we have hit a block boundary.
1350 */
1351 if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
1352 sndcmd = 1;
1347 } 1353 }
1348 1354
1349 /* Deselect and wake up anyone waiting on the device */ 1355 /* Deselect and wake up anyone waiting on the device */
1350 nand_release_device(mtd); 1356 nand_release_device(mtd);
1351 1357
1352 /* Return happy */
1353 *retlen = len; 1358 *retlen = len;
1354 return 0; 1359 return 0;
1355} 1360}
@@ -1676,6 +1681,7 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1676 return ret; 1681 return ret;
1677} 1682}
1678 1683
1684
1679/** 1685/**
1680 * nand_write_oob - [MTD Interface] NAND write out-of-band 1686 * nand_write_oob - [MTD Interface] NAND write out-of-band
1681 * @mtd: MTD device structure 1687 * @mtd: MTD device structure
@@ -1686,40 +1692,40 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1686 * 1692 *
1687 * NAND write out-of-band 1693 * NAND write out-of-band
1688 */ 1694 */
1689static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) 1695static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1696 size_t *retlen, const uint8_t *buf)
1690{ 1697{
1691 int column, page, status, ret = -EIO, chipnr; 1698 int column, page, status, ret = -EIO, chipnr;
1692 struct nand_chip *chip = mtd->priv; 1699 struct nand_chip *chip = mtd->priv;
1693 1700
1694 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len); 1701 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
1695 1702 (unsigned int)to, (int)len);
1696 /* Shift to get page */
1697 page = (int)(to >> chip->page_shift);
1698 chipnr = (int)(to >> chip->chip_shift);
1699
1700 /* Mask to get column */
1701 column = to & (mtd->oobsize - 1);
1702 1703
1703 /* Initialize return length value */ 1704 /* Initialize return length value */
1704 *retlen = 0; 1705 *retlen = 0;
1705 1706
1706 /* Do not allow write past end of page */ 1707 /* Do not allow write past end of page */
1708 column = to & (mtd->oobsize - 1);
1707 if ((column + len) > mtd->oobsize) { 1709 if ((column + len) > mtd->oobsize) {
1708 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n"); 1710 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1711 "Attempt to write past end of page\n");
1709 return -EINVAL; 1712 return -EINVAL;
1710 } 1713 }
1711 1714
1712 /* Grab the lock and see if the device is available */
1713 nand_get_device(chip, mtd, FL_WRITING); 1715 nand_get_device(chip, mtd, FL_WRITING);
1714 1716
1715 /* Select the NAND device */ 1717 chipnr = (int)(to >> chip->chip_shift);
1716 chip->select_chip(mtd, chipnr); 1718 chip->select_chip(mtd, chipnr);
1717 1719
1718 /* Reset the chip. Some chips (like the Toshiba TC5832DC found 1720 /* Shift to get page */
1719 in one of my DiskOnChip 2000 test units) will clear the whole 1721 page = (int)(to >> chip->page_shift);
1720 data page too if we don't do this. I have no clue why, but 1722
1721 I seem to have 'fixed' it in the doc2000 driver in 1723 /*
1722 August 1999. dwmw2. */ 1724 * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
1725 * of my DiskOnChip 2000 test units) will clear the whole data page too
1726 * if we don't do this. I have no clue why, but I seem to have 'fixed'
1727 * it in the doc2000 driver in August 1999. dwmw2.
1728 */
1723 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); 1729 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
1724 1730
1725 /* Check, if it is write protected */ 1731 /* Check, if it is write protected */
@@ -1731,8 +1737,8 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *r
1731 chip->pagebuf = -1; 1737 chip->pagebuf = -1;
1732 1738
1733 if (NAND_MUST_PAD(chip)) { 1739 if (NAND_MUST_PAD(chip)) {
1734 /* Write out desired data */ 1740 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize,
1735 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page & chip->pagemask); 1741 page & chip->pagemask);
1736 /* prepad 0xff for partial programming */ 1742 /* prepad 0xff for partial programming */
1737 chip->write_buf(mtd, ffchars, column); 1743 chip->write_buf(mtd, ffchars, column);
1738 /* write data */ 1744 /* write data */
@@ -1740,9 +1746,8 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *r
1740 /* postpad 0xff for partial programming */ 1746 /* postpad 0xff for partial programming */
1741 chip->write_buf(mtd, ffchars, mtd->oobsize - (len + column)); 1747 chip->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
1742 } else { 1748 } else {
1743 /* Write out desired data */ 1749 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column,
1744 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column, page & chip->pagemask); 1750 page & chip->pagemask);
1745 /* write data */
1746 chip->write_buf(mtd, buf, len); 1751 chip->write_buf(mtd, buf, len);
1747 } 1752 }
1748 /* Send command to program the OOB data */ 1753 /* Send command to program the OOB data */
@@ -1752,11 +1757,11 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *r
1752 1757
1753 /* See if device thinks it succeeded */ 1758 /* See if device thinks it succeeded */
1754 if (status & NAND_STATUS_FAIL) { 1759 if (status & NAND_STATUS_FAIL) {
1755 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page); 1760 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1761 "Failed write, page 0x%08x\n", page);
1756 ret = -EIO; 1762 ret = -EIO;
1757 goto out; 1763 goto out;
1758 } 1764 }
1759 /* Return happy */
1760 *retlen = len; 1765 *retlen = len;
1761 1766
1762#ifdef CONFIG_MTD_NAND_VERIFY_WRITE 1767#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
@@ -1764,7 +1769,8 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *r
1764 chip->cmdfunc(mtd, NAND_CMD_READOOB, column, page & chip->pagemask); 1769 chip->cmdfunc(mtd, NAND_CMD_READOOB, column, page & chip->pagemask);
1765 1770
1766 if (chip->verify_buf(mtd, buf, len)) { 1771 if (chip->verify_buf(mtd, buf, len)) {
1767 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page); 1772 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1773 "Failed write verify, page 0x%08x\n", page);
1768 ret = -EIO; 1774 ret = -EIO;
1769 goto out; 1775 goto out;
1770 } 1776 }