aboutsummaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 17:21:03 +0200
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 17:21:03 +0200
commit9223a456da8ed357bf7e0b128c853e2c8bd54614 (patch)
tree50cb225c4ba9c610ae4cb67231b319e78e935ac4 /drivers/mtd/nand
parent2528e8cdf376d7da24647c442ec1e88c360d76ca (diff)
[MTD] Remove read/write _ecc variants
MTD clients are agnostic of FLASH which needs ECC suppport. Remove the functions and fixup the callers. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/nand_base.c122
-rw-r--r--drivers/mtd/nand/nand_bbt.c104
2 files changed, 122 insertions, 104 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index da2f4d16e50..d796eb508b4 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -139,16 +139,10 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, uint8_t *buf);
-static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, uint8_t *buf, uint8_t *eccbuf,
- struct nand_oobinfo *oobsel);
static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, uint8_t *buf);
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const uint8_t *buf);
-static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const uint8_t *buf, uint8_t *eccbuf,
- struct nand_oobinfo *oobsel);
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_erase(struct mtd_info *mtd, struct erase_info *instr);
@@ -1080,27 +1074,6 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retl
}
/**
- * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc
- * @mtd: MTD device structure
- * @from: offset to read from
- * @len: number of bytes to read
- * @retlen: pointer to variable to store the number of read bytes
- * @buf: the databuffer to put data
- * @oob_buf: filesystem supplied oob data buffer
- * @oobsel: oob selection structure
- *
- * This function simply calls nand_do_read_ecc with flags = 0xff
- */
-static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel)
-{
- /* use userspace supplied oobinfo, if zero */
- if (oobsel == NULL)
- oobsel = &mtd->oobinfo;
- return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff);
-}
-
-/**
* nand_do_read_ecc - [MTD Interface] Read data with ECC
* @mtd: MTD device structure
* @from: offset to read from
@@ -1524,6 +1497,55 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, s
}
/**
+ * nand_write_raw - [GENERIC] Write raw data including oob
+ * @mtd: MTD device structure
+ * @buf: source buffer
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @buf: source buffer
+ * @oob: oob buffer
+ *
+ * Write raw data including oob
+ */
+int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
+ uint8_t *buf, uint8_t *oob)
+{
+ struct nand_chip *this = mtd->priv;
+ int page = (int)(to >> this->page_shift);
+ int chip = (int)(to >> this->chip_shift);
+ int ret;
+
+ *retlen = 0;
+
+ /* Do not allow writes past end of device */
+ if ((to + len) > mtd->size) {
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
+ "beyond end of device\n");
+ return -EINVAL;
+ }
+
+ /* Grab the lock and see if the device is available */
+ nand_get_device(this, mtd, FL_WRITING);
+
+ this->select_chip(mtd, chip);
+ this->data_poi = buf;
+
+ while (len != *retlen) {
+ ret = nand_write_page(mtd, this, page, oob, &mtd->oobinfo, 0);
+ if (ret)
+ return ret;
+ page++;
+ *retlen += mtd->writesize;
+ this->data_poi += mtd->writesize;
+ oob += mtd->oobsize;
+ }
+
+ /* Deselect and wake up anyone waiting on the device */
+ nand_release_device(mtd);
+ return 0;
+}
+
+/**
* nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
* @mtd: MTD device structure
* @fsbuf: buffer given by fs driver
@@ -1585,57 +1607,39 @@ static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct
#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
/**
- * nand_write - [MTD Interface] compability function for nand_write_ecc
- * @mtd: MTD device structure
- * @to: offset to write to
- * @len: number of bytes to write
- * @retlen: pointer to variable to store the number of written bytes
- * @buf: the data to write
- *
- * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
- *
-*/
-static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf)
-{
- return (nand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL));
-}
-
-/**
- * nand_write_ecc - [MTD Interface] NAND write with ECC
+ * nand_write - [MTD Interface] NAND write with ECC
* @mtd: MTD device structure
* @to: offset to write to
* @len: number of bytes to write
* @retlen: pointer to variable to store the number of written bytes
* @buf: the data to write
- * @eccbuf: filesystem supplied oob data buffer
- * @oobsel: oob selection structure
*
* NAND write with ECC
*/
-static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const uint8_t *buf, uint8_t *eccbuf,
- struct nand_oobinfo *oobsel)
+static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const uint8_t *buf)
{
int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
int autoplace = 0, numpages, totalpages;
struct nand_chip *this = mtd->priv;
- uint8_t *oobbuf, *bufstart;
+ uint8_t *oobbuf, *bufstart, *eccbuf = NULL;
int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
+ struct nand_oobinfo *oobsel = &mtd->oobinfo;
- DEBUG(MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
+ DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
/* Initialize retlen, in case of early exit */
*retlen = 0;
/* Do not allow write past end of device */
if ((to + len) > mtd->size) {
- DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n");
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n");
return -EINVAL;
}
/* reject writes, which are not page aligned */
if (NOTALIGNED(to) || NOTALIGNED(len)) {
- printk(KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
+ printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n");
return -EINVAL;
}
@@ -1651,10 +1655,6 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
if (nand_check_wp(mtd))
goto out;
- /* if oobsel is NULL, use chip defaults */
- if (oobsel == NULL)
- oobsel = &mtd->oobinfo;
-
/* Autoplace of oob data ? Use the default placement scheme */
if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
oobsel = this->autooob;
@@ -1689,7 +1689,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
*/
ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
if (ret) {
- DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret);
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret);
goto out;
}
/* Next oob page */
@@ -1712,7 +1712,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
ret = nand_verify_pages(mtd, this, startpage, page - startpage,
oobbuf, oobsel, chipnr, (eccbuf != NULL));
if (ret) {
- DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
goto out;
}
*retlen = written;
@@ -1741,7 +1741,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
if (!ret)
*retlen = written;
else
- DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
out:
/* Deselect and wake up anyone waiting on the device */
@@ -2527,8 +2527,6 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
mtd->unpoint = NULL;
mtd->read = nand_read;
mtd->write = nand_write;
- mtd->read_ecc = nand_read_ecc;
- mtd->write_ecc = nand_write_ecc;
mtd->read_oob = nand_read_oob;
mtd->write_oob = nand_write_oob;
mtd->sync = nand_sync;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index fbccb2a2518..ecaaca18d1e 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -156,7 +156,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
while (totlen) {
len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
- res = mtd->read_ecc(mtd, from, len, &retlen, buf, NULL, this->autooob);
+ res = mtd->read(mtd, from, len, &retlen, buf);
if (res < 0) {
if (retlen != len) {
printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
@@ -471,17 +471,17 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
*
*/
static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
- struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
+ struct nand_bbt_descr *td, struct nand_bbt_descr *md,
+ int chipsel)
{
struct nand_chip *this = mtd->priv;
- struct nand_oobinfo oobinfo;
struct erase_info einfo;
int i, j, res, chip = 0;
int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
- int nrchips, bbtoffs, pageoffs;
+ int nrchips, bbtoffs, pageoffs, ooboffs;
uint8_t msk[4];
uint8_t rcode = td->reserved_block_code;
- size_t retlen, len = 0;
+ size_t retlen, len = 0, ooblen;
loff_t to;
if (!rcode)
@@ -526,12 +526,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
for (i = 0; i < td->maxblocks; i++) {
int block = startblock + dir * i;
/* Check, if the block is bad */
- switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) {
+ switch ((this->bbt[block >> 2] >>
+ (2 * (block & 0x03))) & 0x03) {
case 0x01:
case 0x03:
continue;
}
- page = block << (this->bbt_erase_shift - this->page_shift);
+ page = block <<
+ (this->bbt_erase_shift - this->page_shift);
/* Check, if the block is used by the mirror table */
if (!md || md->pages[chip] != page)
goto write;
@@ -542,11 +544,20 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
/* Set up shift count and masks for the flash table */
bits = td->options & NAND_BBT_NRBITS_MSK;
+ msk[2] = ~rcode;
switch (bits) {
- case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break;
- case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break;
- case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break;
- case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
+ case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
+ msk[3] = 0x01;
+ break;
+ case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
+ msk[3] = 0x03;
+ break;
+ case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
+ msk[3] = 0x0f;
+ break;
+ case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
+ msk[3] = 0xff;
+ break;
default: return -EINVAL;
}
@@ -554,49 +565,55 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
to = ((loff_t) page) << this->page_shift;
- memcpy(&oobinfo, this->autooob, sizeof(oobinfo));
- oobinfo.useecc = MTD_NANDECC_PLACEONLY;
-
/* Must we save the block contents ? */
if (td->options & NAND_BBT_SAVECONTENT) {
/* Make it block aligned */
to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
len = 1 << this->bbt_erase_shift;
- res = mtd->read_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
+ res = mtd->read(mtd, to, len, &retlen, buf);
if (res < 0) {
if (retlen != len) {
- printk(KERN_INFO
- "nand_bbt: Error reading block for writing the bad block table\n");
+ printk(KERN_INFO "nand_bbt: Error "
+ "reading block for writing "
+ "the bad block table\n");
return res;
}
- printk(KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n");
+ printk(KERN_WARNING "nand_bbt: ECC error "
+ "while reading block for writing "
+ "bad block table\n");
}
+ /* Read oob data */
+ ooblen = (len >> this->page_shift) * mtd->oobsize;
+ res = mtd->read_oob(mtd, to + mtd->writesize, ooblen,
+ &retlen, &buf[len]);
+ if (res < 0 || retlen != ooblen)
+ goto outerr;
+
/* Calc the byte offset in the buffer */
pageoffs = page - (int)(to >> this->page_shift);
offs = pageoffs << this->page_shift;
/* Preset the bbt area with 0xff */
memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
- /* Preset the bbt's oob area with 0xff */
- memset(&buf[len + pageoffs * mtd->oobsize], 0xff,
- ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
- if (td->options & NAND_BBT_VERSION) {
- buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
- }
+ ooboffs = len + (pageoffs * mtd->oobsize);
+
} else {
/* Calc length */
len = (size_t) (numblocks >> sft);
/* Make it page aligned ! */
- len = (len + (mtd->writesize - 1)) & ~(mtd->writesize - 1);
+ len = (len + (mtd->writesize - 1)) &
+ ~(mtd->writesize - 1);
/* Preset the buffer with 0xff */
- memset(buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
+ memset(buf, 0xff, len +
+ (len >> this->page_shift)* mtd->oobsize);
offs = 0;
+ ooboffs = len;
/* Pattern is located in oob area of first page */
- memcpy(&buf[len + td->offs], td->pattern, td->len);
- if (td->options & NAND_BBT_VERSION) {
- buf[len + td->veroffs] = td->version[chip];
- }
+ memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
}
+ if (td->options & NAND_BBT_VERSION)
+ buf[ooboffs + td->veroffs] = td->version[chip];
+
/* walk through the memory table */
for (i = 0; i < numblocks;) {
uint8_t dat;
@@ -604,7 +621,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
for (j = 0; j < 4; j++, i++) {
int sftcnt = (i << (3 - sft)) & sftmsk;
/* Do not store the reserved bbt blocks ! */
- buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
+ buf[offs + (i >> sft)] &=
+ ~(msk[dat & 0x03] << sftcnt);
dat >>= 2;
}
}
@@ -614,23 +632,25 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
einfo.addr = (unsigned long)to;
einfo.len = 1 << this->bbt_erase_shift;
res = nand_erase_nand(mtd, &einfo, 1);
- if (res < 0) {
- printk(KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
- return res;
- }
+ if (res < 0)
+ goto outerr;
- res = mtd->write_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
- if (res < 0) {
- printk(KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
- return res;
- }
- printk(KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
- (unsigned int)to, td->version[chip]);
+ res = nand_write_raw(mtd, to, len, &retlen, buf, &buf[len]);
+ if (res < 0)
+ goto outerr;
+
+ printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
+ "0x%02X\n", (unsigned int)to, td->version[chip]);
/* Mark it as used */
td->pages[chip] = page;
}
return 0;
+
+ outerr:
+ printk(KERN_WARNING
+ "nand_bbt: Error while writing bad block table %d\n", res);
+ return res;
}
/**