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