[MTD] NAND modularize ECC

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Tue May 23 06:59:04 EDT 2006


Commit:     6dfc6d250d0b7ebaa6423c44dcd09fcfe68deabd
Parent:     7aa65bfd6793a56cc3bbce8436abbfea3a7bdd1f
Author:     Thomas Gleixner <tglx at cruncher.tec.linutronix.de>
AuthorDate: Tue May 23 12:00:46 2006 +0200
Commit:     Thomas Gleixner <tglx at cruncher.tec.linutronix.de>
CommitDate: Tue May 23 12:00:46 2006 +0200

    [MTD] NAND modularize ECC
    
    First step of modularizing ECC support.
    - Move ECC related functionality into a seperate embedded data structure
    - Get rid of the hardware dependend constants to simplify new ECC models
    
    Signed-off-by: Thomas Gleixner <tglx at linutronix.de>

 drivers/mtd/nand/ams-delta.c      |    2 -
 drivers/mtd/nand/au1550nd.c       |    2 -
 drivers/mtd/nand/autcpu12.c       |    2 -
 drivers/mtd/nand/cs553x_nand.c    |   12 ++-
 drivers/mtd/nand/diskonchip.c     |   10 ++-
 drivers/mtd/nand/h1910.c          |    2 -
 drivers/mtd/nand/nand_base.c      |  146 ++++++++++++-------------------------
 drivers/mtd/nand/nandsim.c        |    2 -
 drivers/mtd/nand/ndfc.c           |   10 ++-
 drivers/mtd/nand/ppchameleonevb.c |    4 +
 drivers/mtd/nand/rtc_from4.c      |   12 ++-
 drivers/mtd/nand/s3c2410.c        |   16 ++--
 drivers/mtd/nand/sharpsl.c        |   10 ++-
 drivers/mtd/nand/toto.c           |    2 -
 drivers/mtd/nand/ts7250.c         |    2 -
 include/linux/mtd/nand.h          |   63 ++++++++--------
 16 files changed, 131 insertions(+), 166 deletions(-)

diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index 5a349eb..aeaf2de 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -192,7 +192,7 @@ static int __init ams_delta_init(void)
 	}
 	/* 25 us command delay time */
 	this->chip_delay = 30;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Set chip enabled, but  */
 	ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index d9a0143..d7f04ab 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -578,7 +578,7 @@ #endif
 
 	/* 30 us command delay time */
 	this->chip_delay = 30;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	this->options = NAND_NO_AUTOINCR;
 
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index 43b2960..dbb1b62 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -163,7 +163,7 @@ static int __init autcpu12_init(void)
 	this->dev_ready = autcpu12_device_ready;
 	/* 20 us command delay time */
 	this->chip_delay = 20;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Enable the following for a flash based bad block table */
 	/*
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index bf25125..064f3fe 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -242,11 +242,13 @@ static int __init cs553x_init_one(int cs
 
 	this->chip_delay = 0;
 
-	this->eccmode = NAND_ECC_HW3_256;
-	this->enable_hwecc  = cs_enable_hwecc;
-	this->calculate_ecc = cs_calculate_ecc;
-	this->correct_data  = nand_correct_data;
-	
+	this->ecc.mode = NAND_ECC_HW;
+	this->ecc.size = 256;
+	this->ecc.bytes = 3;
+	this->ecc.hwctl  = cs_enable_hwecc;
+	this->ecc.calculate = cs_calculate_ecc;
+	this->ecc.correct  = nand_correct_data;
+
 	/* Enable the following for a flash based bad block table */
 	this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
 
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index a2391c6..128c937 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1674,12 +1674,14 @@ static int __init doc_probe(unsigned lon
 	nand->dev_ready		= doc200x_dev_ready;
 	nand->waitfunc		= doc200x_wait;
 	nand->block_bad		= doc200x_block_bad;
-	nand->enable_hwecc	= doc200x_enable_hwecc;
-	nand->calculate_ecc	= doc200x_calculate_ecc;
-	nand->correct_data	= doc200x_correct_data;
+	nand->ecc.hwctl		= doc200x_enable_hwecc;
+	nand->ecc.calculate	= doc200x_calculate_ecc;
+	nand->ecc.correct	= doc200x_correct_data;
 
 	nand->autooob		= &doc200x_oobinfo;
-	nand->eccmode		= NAND_ECC_HW6_512;
+	nand->ecc.mode		= NAND_ECC_HW_SYNDROME;
+	nand->ecc.size		= 512;
+	nand->ecc.bytes		= 6;
 	nand->options		= NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME;
 
 	doc->physadr		= physadr;
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index 9848eb0..06e91fa 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -149,7 +149,7 @@ static int __init h1910_init(void)
 	this->dev_ready = NULL;	/* unknown whether that was correct or not so we will just do it like this */
 	/* 15 us command delay time */
 	this->chip_delay = 50;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 	this->options = NAND_NO_AUTOINCR;
 
 	/* Scan to find existence of the device */
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 37db98a..98792ec 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -879,9 +879,9 @@ static int nand_write_page(struct mtd_in
 {
 	int i, status;
 	uint8_t ecc_code[32];
-	int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
+	int eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
 	int *oob_config = oobsel->eccpos;
-	int datidx = 0, eccidx = 0, eccsteps = this->eccsteps;
+	int datidx = 0, eccidx = 0, eccsteps = this->ecc.steps;
 	int eccbytes = 0;
 
 	/* FIXME: Enable cached programming */
@@ -901,20 +901,20 @@ static int nand_write_page(struct mtd_in
 		/* Software ecc 3/256, write all */
 	case NAND_ECC_SOFT:
 		for (; eccsteps; eccsteps--) {
-			this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
+			this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
 			for (i = 0; i < 3; i++, eccidx++)
 				oob_buf[oob_config[eccidx]] = ecc_code[i];
-			datidx += this->eccsize;
+			datidx += this->ecc.size;
 		}
 		this->write_buf(mtd, this->data_poi, mtd->oobblock);
 		break;
 	default:
-		eccbytes = this->eccbytes;
+		eccbytes = this->ecc.bytes;
 		for (; eccsteps; eccsteps--) {
 			/* enable hardware ecc logic for write */
-			this->enable_hwecc(mtd, NAND_ECC_WRITE);
-			this->write_buf(mtd, &this->data_poi[datidx], this->eccsize);
-			this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
+			this->ecc.hwctl(mtd, NAND_ECC_WRITE);
+			this->write_buf(mtd, &this->data_poi[datidx], this->ecc.size);
+			this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
 			for (i = 0; i < eccbytes; i++, eccidx++)
 				oob_buf[oob_config[eccidx]] = ecc_code[i];
 			/* If the hardware ecc provides syndromes then
@@ -922,7 +922,7 @@ static int nand_write_page(struct mtd_in
 			 * the data bytes (words) */
 			if (this->options & NAND_HWECC_SYNDROME)
 				this->write_buf(mtd, ecc_code, eccbytes);
-			datidx += this->eccsize;
+			datidx += this->ecc.size;
 		}
 		break;
 	}
@@ -1155,7 +1155,7 @@ int nand_do_read_ecc(struct mtd_info *mt
 	if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
 		oobsel = this->autooob;
 
-	eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
+	eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
 	oob_config = oobsel->eccpos;
 
 	/* Select the NAND device */
@@ -1170,8 +1170,8 @@ int nand_do_read_ecc(struct mtd_info *mt
 	col = from & (mtd->oobblock - 1);
 
 	end = mtd->oobblock;
-	ecc = this->eccsize;
-	eccbytes = this->eccbytes;
+	ecc = this->ecc.size;
+	eccbytes = this->ecc.bytes;
 
 	if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
 		compareecc = 0;
@@ -1216,7 +1216,7 @@ int nand_do_read_ecc(struct mtd_info *mt
 			oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
 			oob_data = &this->data_buf[end];
 
-		eccsteps = this->eccsteps;
+		eccsteps = this->ecc.steps;
 
 		switch (eccmode) {
 		case NAND_ECC_NONE:{
@@ -1234,12 +1234,12 @@ int nand_do_read_ecc(struct mtd_info *mt
 		case NAND_ECC_SOFT:	/* Software ECC 3/256: Read in a page + oob data */
 			this->read_buf(mtd, data_poi, end);
 			for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc)
-				this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
+				this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
 			break;
 
 		default:
 			for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) {
-				this->enable_hwecc(mtd, NAND_ECC_READ);
+				this->ecc.hwctl(mtd, NAND_ECC_READ);
 				this->read_buf(mtd, &data_poi[datidx], ecc);
 
 				/* HW ecc with syndrome calculation must read the
@@ -1247,19 +1247,19 @@ int nand_do_read_ecc(struct mtd_info *mt
 				if (!compareecc) {
 					/* Some hw ecc generators need to know when the
 					 * syndrome is read from flash */
-					this->enable_hwecc(mtd, NAND_ECC_READSYN);
+					this->ecc.hwctl(mtd, NAND_ECC_READSYN);
 					this->read_buf(mtd, &oob_data[i], eccbytes);
 					/* We calc error correction directly, it checks the hw
 					 * generator for an error, reads back the syndrome and
 					 * does the error correction on the fly */
-					ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
+					ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
 					if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
 						DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: "
 						      "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
 						ecc_failed++;
 					}
 				} else {
-					this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
+					this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
 				}
 			}
 			break;
@@ -1277,8 +1277,8 @@ int nand_do_read_ecc(struct mtd_info *mt
 			ecc_code[j] = oob_data[oob_config[j]];
 
 		/* correct data, if necessary */
-		for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) {
-			ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
+		for (i = 0, j = 0, datidx = 0; i < this->ecc.steps; i++, datidx += ecc) {
+			ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
 
 			/* Get next chunk of ecc bytes */
 			j += eccbytes;
@@ -1315,7 +1315,7 @@ int nand_do_read_ecc(struct mtd_info *mt
 				break;
 			case MTD_NANDECC_PLACE:
 				/* YAFFS1 legacy mode */
-				oob_data += this->eccsteps * sizeof(int);
+				oob_data += this->ecc.steps * sizeof(int);
 			default:
 				oob_data += mtd->oobsize;
 			}
@@ -2648,99 +2648,49 @@ int nand_scan(struct mtd_info *mtd, int 
 	 * check ECC mode, default to software if 3byte/512byte hardware ECC is
 	 * selected and we have 256 byte pagesize fallback to software ECC
 	 */
-	this->eccsize = 256;
-	this->eccbytes = 3;
-
-	switch (this->eccmode) {
-	case NAND_ECC_HW12_2048:
-		if (mtd->oobblock < 2048) {
-			printk(KERN_WARNING "2048 byte HW ECC not possible on "
-			       "%d byte page size, fallback to SW ECC\n",
-			       mtd->oobblock);
-			this->eccmode = NAND_ECC_SOFT;
-			this->calculate_ecc = nand_calculate_ecc;
-			this->correct_data = nand_correct_data;
-		} else
-			this->eccsize = 2048;
-		break;
-
-	case NAND_ECC_HW3_512:
-	case NAND_ECC_HW6_512:
-	case NAND_ECC_HW8_512:
-		if (mtd->oobblock == 256) {
-			printk(KERN_WARNING "512 byte HW ECC not possible on "
-			       "256 Byte pagesize, fallback to SW ECC \n");
-			this->eccmode = NAND_ECC_SOFT;
-			this->calculate_ecc = nand_calculate_ecc;
-			this->correct_data = nand_correct_data;
-		} else
-			this->eccsize = 512;	/* set eccsize to 512 */
-		break;
+	switch (this->ecc.mode) {
+	case NAND_ECC_HW:
+	case NAND_ECC_HW_SYNDROME:
+		if (!this->ecc.calculate || !this->ecc.correct ||
+		    !this->ecc.hwctl) {
+			printk(KERN_WARNING "No ECC functions supplied, "
+			       "Hardware ECC not possible\n");
+			BUG();
+		}
+		if (mtd->oobblock >= this->ecc.size)
+			break;
+		printk(KERN_WARNING "%d byte HW ECC not possible on "
+		       "%d byte page size, fallback to SW ECC\n",
+		       this->ecc.size, mtd->oobblock);
+		this->ecc.mode = NAND_ECC_SOFT;
 
-	case NAND_ECC_HW3_256:
+	case NAND_ECC_SOFT:
+		this->ecc.calculate = nand_calculate_ecc;
+		this->ecc.correct = nand_correct_data;
+		this->ecc.size = 256;
+		this->ecc.bytes = 3;
 		break;
 
 	case NAND_ECC_NONE:
 		printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
 		       "This is not recommended !!\n");
-		this->eccmode = NAND_ECC_NONE;
+		this->ecc.size = mtd->oobblock;
+		this->ecc.bytes = 0;
 		break;
-
-	case NAND_ECC_SOFT:
-		this->calculate_ecc = nand_calculate_ecc;
-		this->correct_data = nand_correct_data;
-		break;
-
 	default:
 		printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
-		       this->eccmode);
-		BUG();
-	}
-
-	/*
-	 * Check hardware ecc function availability and adjust number of ecc
-	 * bytes per calculation step
-	 */
-	switch (this->eccmode) {
-	case NAND_ECC_HW12_2048:
-		this->eccbytes += 4;
-	case NAND_ECC_HW8_512:
-		this->eccbytes += 2;
-	case NAND_ECC_HW6_512:
-		this->eccbytes += 3;
-	case NAND_ECC_HW3_512:
-	case NAND_ECC_HW3_256:
-		if (this->calculate_ecc && this->correct_data &&
-		    this->enable_hwecc)
-			break;
-		printk(KERN_WARNING "No ECC functions supplied, "
-		       "Hardware ECC not possible\n");
+		       this->ecc.mode);
 		BUG();
 	}
 
-	mtd->eccsize = this->eccsize;
-
 	/*
 	 * Set the number of read / write steps for one page depending on ECC
 	 * mode
 	 */
-	switch (this->eccmode) {
-	case NAND_ECC_HW12_2048:
-		this->eccsteps = mtd->oobblock / 2048;
-		break;
-	case NAND_ECC_HW3_512:
-	case NAND_ECC_HW6_512:
-	case NAND_ECC_HW8_512:
-		this->eccsteps = mtd->oobblock / 512;
-		break;
-	case NAND_ECC_HW3_256:
-	case NAND_ECC_SOFT:
-		this->eccsteps = mtd->oobblock / 256;
-		break;
-
-	case NAND_ECC_NONE:
-		this->eccsteps = 1;
-		break;
+	this->ecc.steps = mtd->oobblock / this->ecc.size;
+	if(this->ecc.steps * this->ecc.size != mtd->oobblock) {
+		printk(KERN_WARNING "Invalid ecc parameters\n");
+		BUG();
 	}
 
 	/* Initialize state, waitqueue and spinlock */
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 6903f5b..9008bc5 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -1523,7 +1523,7 @@ static int __init ns_init_module(void)
 	chip->verify_buf = ns_nand_verify_buf;
 	chip->write_word = ns_nand_write_word;
 	chip->read_word  = ns_nand_read_word;
-	chip->eccmode    = NAND_ECC_SOFT;
+	chip->ecc.mode   = NAND_ECC_SOFT;
 	chip->options   |= NAND_SKIP_BBTSCAN;
 
 	/*
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 22fd682..e2dc81d 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -168,10 +168,12 @@ static void ndfc_chip_init(struct ndfc_n
 	chip->read_buf = ndfc_read_buf;
 	chip->write_buf = ndfc_write_buf;
 	chip->verify_buf = ndfc_verify_buf;
-	chip->correct_data  = nand_correct_data;
-	chip->enable_hwecc  = ndfc_enable_hwecc;
-	chip->calculate_ecc = ndfc_calculate_ecc;
-	chip->eccmode = NAND_ECC_HW3_256;
+	chip->ecc.correct = nand_correct_data;
+	chip->ecc.hwctl = ndfc_enable_hwecc;
+	chip->ecc.calculate = ndfc_calculate_ecc;
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = 256;
+	chip->ecc.bytes = 3;
 	chip->autooob = mtd->pl_chip->autooob;
 	mtd->mtd.priv = chip;
 	mtd->mtd.owner = THIS_MODULE;
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index 5d4d16f..9fab099 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -257,7 +257,7 @@ #ifdef USE_READY_BUSY_PIN
 #endif
 	this->chip_delay = NAND_BIG_DELAY_US;
 	/* ECC mode */
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Scan to find existence of the device (it could not be mounted) */
 	if (nand_scan(ppchameleon_mtd, 1)) {
@@ -358,7 +358,7 @@ #endif
 	this->chip_delay = NAND_SMALL_DELAY_US;
 
 	/* ECC mode */
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Scan to find existence of the device */
 	if (nand_scan(ppchameleonevb_mtd, 1)) {
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index bc9d849..a2122fe 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -570,19 +570,21 @@ static int __init rtc_from4_init(void)
 #ifdef RTC_FROM4_HWECC
 	printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n");
 
-	this->eccmode = NAND_ECC_HW8_512;
+	this->ecc.mode = NAND_ECC_HW_SYNDROME;
+	this->ecc.size = 512;
+	this->ecc.bytes = 8;
 	this->options |= NAND_HWECC_SYNDROME;
 	/* return the status of extra status and ECC checks */
 	this->errstat = rtc_from4_errstat;
 	/* set the nand_oobinfo to support FPGA H/W error detection */
 	this->autooob = &rtc_from4_nand_oobinfo;
-	this->enable_hwecc = rtc_from4_enable_hwecc;
-	this->calculate_ecc = rtc_from4_calculate_ecc;
-	this->correct_data = rtc_from4_correct_data;
+	this->ecc.hwctl = rtc_from4_enable_hwecc;
+	this->ecc.calculate = rtc_from4_calculate_ecc;
+	this->ecc.correct = rtc_from4_correct_data;
 #else
 	printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
 
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 #endif
 
 	/* set the bad block tables to support debugging */
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index f800259..608340a 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -520,18 +520,20 @@ static void s3c2410_nand_init_chip(struc
 	nmtd->set	   = set;
 
 	if (hardware_ecc) {
-		chip->correct_data  = s3c2410_nand_correct_data;
-		chip->enable_hwecc  = s3c2410_nand_enable_hwecc;
-		chip->calculate_ecc = s3c2410_nand_calculate_ecc;
-		chip->eccmode	    = NAND_ECC_HW3_512;
+		chip->ecc.correct   = s3c2410_nand_correct_data;
+		chip->ecc.hwctl	    = s3c2410_nand_enable_hwecc;
+		chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+		chip->ecc.mode	    = NAND_ECC_HW;
+		chip->ecc.size	    = 512;
+		chip->ecc.bytes	    = 3;
 		chip->autooob       = &nand_hw_eccoob;
 
 		if (info->is_s3c2440) {
-			chip->enable_hwecc  = s3c2440_nand_enable_hwecc;
-			chip->calculate_ecc = s3c2440_nand_calculate_ecc;
+			chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
+			chip->ecc.calculate = s3c2440_nand_calculate_ecc;
 		}
 	} else {
-		chip->eccmode	    = NAND_ECC_SOFT;
+		chip->ecc.mode	    = NAND_ECC_SOFT;
 	}
 }
 
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 60e10c0..5554d0b 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -201,15 +201,17 @@ static int __init sharpsl_nand_init(void
 	/* 15 us command delay time */
 	this->chip_delay = 15;
 	/* set eccmode using hardware ECC */
-	this->eccmode = NAND_ECC_HW3_256;
+	this->ecc.mode = NAND_ECC_HW;
+	this->ecc.size = 256;
+	this->ecc.bytes = 3;
 	this->badblock_pattern = &sharpsl_bbt;
 	if (machine_is_akita() || machine_is_borzoi()) {
 		this->badblock_pattern = &sharpsl_akita_bbt;
 		this->autooob = &akita_oobinfo;
 	}
-	this->enable_hwecc = sharpsl_nand_enable_hwecc;
-	this->calculate_ecc = sharpsl_nand_calculate_ecc;
-	this->correct_data = nand_correct_data;
+	this->ecc.hwctl = sharpsl_nand_enable_hwecc;
+	this->ecc.calculate = sharpsl_nand_calculate_ecc;
+	this->ecc.correct = nand_correct_data;
 
 	/* Scan to find existence of the device */
 	err = nand_scan(sharpsl_mtd, 1);
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c
index c51c895..50aa6a4 100644
--- a/drivers/mtd/nand/toto.c
+++ b/drivers/mtd/nand/toto.c
@@ -146,7 +146,7 @@ static int __init toto_init(void)
 	this->dev_ready = NULL;
 	/* 25 us command delay time */
 	this->chip_delay = 30;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Scan to find existance of the device */
 	if (nand_scan(toto_mtd, 1)) {
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c
index 622db31..70bce1b 100644
--- a/drivers/mtd/nand/ts7250.c
+++ b/drivers/mtd/nand/ts7250.c
@@ -155,7 +155,7 @@ static int __init ts7250_init(void)
 	this->hwcontrol = ts7250_hwcontrol;
 	this->dev_ready = ts7250_device_ready;
 	this->chip_delay = 15;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	printk("Searching for NAND flash...\n");
 	/* Scan to find existence of the device */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 601c5c7..4605258 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -113,21 +113,12 @@ #define NAND_STATUS_WP		0x80
 /*
  * Constants for ECC_MODES
  */
-
-/* No ECC. Usage is not recommended ! */
-#define NAND_ECC_NONE		0
-/* Software ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_SOFT		1
-/* Hardware ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_HW3_256	2
-/* Hardware ECC 3 byte ECC per 512 Byte data */
-#define NAND_ECC_HW3_512	3
-/* Hardware ECC 3 byte ECC per 512 Byte data */
-#define NAND_ECC_HW6_512	4
-/* Hardware ECC 8 byte ECC per 512 Byte data */
-#define NAND_ECC_HW8_512	6
-/* Hardware ECC 12 byte ECC per 2048 Byte data */
-#define NAND_ECC_HW12_2048	7
+typedef enum {
+	NAND_ECC_NONE,
+	NAND_ECC_SOFT,
+	NAND_ECC_HW,
+	NAND_ECC_HW_SYNDROME,
+} nand_ecc_modes_t;
 
 /*
  * Constants for Hardware ECC
@@ -231,6 +222,31 @@ struct nand_hw_control {
 };
 
 /**
+ * struct nand_ecc_ctrl - Control structure for ecc
+ * @mode:	ecc mode
+ * @steps:	number of ecc steps per page
+ * @size:	data bytes per ecc step
+ * @bytes:	ecc bytes per step
+ * @hwctl:	function to control hardware ecc generator. Must only
+ *		be provided if an hardware ECC is available
+ * @calculate:	function for ecc calculation or readback from ecc hardware
+ * @correct:	function for ecc correction, matching to ecc generator (sw/hw)
+ */
+struct nand_ecc_ctrl {
+	nand_ecc_modes_t	mode;
+	int			steps;
+	int			size;
+	int			bytes;
+	int			(*hwctl)(struct mtd_info *mtd, int mode);
+	int			(*calculate)(struct mtd_info *mtd,
+					     const uint8_t *dat,
+					     uint8_t *ecc_code);
+	int			(*correct)(struct mtd_info *mtd, uint8_t *dat,
+					   uint8_t *read_ecc,
+					   uint8_t *calc_ecc);
+};
+
+/**
  * struct nand_chip - NAND Private Flash Chip Data
  * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
  * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
@@ -250,16 +266,9 @@ struct nand_hw_control {
  *			is read from the chip status register
  * @cmdfunc:		[REPLACEABLE] hardwarespecific function for writing commands to the chip
  * @waitfunc:		[REPLACEABLE] hardwarespecific function for wait on ready
- * @calculate_ecc:	[REPLACEABLE] function for ecc calculation or readback from ecc hardware
- * @correct_data:	[REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
- * @enable_hwecc:	[BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
- *			be provided if a hardware ECC is available
+ * @ecc:		[BOARDSPECIFIC] ecc control ctructure
  * @erase_cmd:		[INTERN] erase command write function, selectable due to AND support
  * @scan_bbt:		[REPLACEABLE] function to scan bad block table
- * @eccmode:		[BOARDSPECIFIC] mode of ecc, see defines
- * @eccsize:		[INTERN] databytes used per ecc-calculation
- * @eccbytes:		[INTERN] number of ecc bytes per ecc-calculation step
- * @eccsteps:		[INTERN] number of ecc calculation steps per page
  * @chip_delay:		[BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
  * @wq:			[INTERN] wait queue to sleep on if a NAND operation is in progress
  * @state:		[INTERN] the current state of the NAND device
@@ -309,15 +318,9 @@ struct nand_chip {
 	int		(*dev_ready)(struct mtd_info *mtd);
 	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
 	int		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
-	int		(*calculate_ecc)(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code);
-	int		(*correct_data)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc);
-	void		(*enable_hwecc)(struct mtd_info *mtd, int mode);
 	void		(*erase_cmd)(struct mtd_info *mtd, int page);
 	int		(*scan_bbt)(struct mtd_info *mtd);
-	int		eccmode;
-	int		eccsize;
-	int		eccbytes;
-	int		eccsteps;
+	struct nand_ecc_ctrl ecc;
 	int		chip_delay;
 	wait_queue_head_t wq;
 	nand_state_t	state;



More information about the linux-mtd-cvs mailing list