aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 06:00:46 -0400
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 06:00:46 -0400
commit6dfc6d250d0b7ebaa6423c44dcd09fcfe68deabd (patch)
tree2be25b1e302eca5984a8ad5ed3e5bde77bafaabb
parent7aa65bfd6793a56cc3bbce8436abbfea3a7bdd1f (diff)
[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@linutronix.de>
-rw-r--r--drivers/mtd/nand/ams-delta.c2
-rw-r--r--drivers/mtd/nand/au1550nd.c2
-rw-r--r--drivers/mtd/nand/autcpu12.c2
-rw-r--r--drivers/mtd/nand/cs553x_nand.c12
-rw-r--r--drivers/mtd/nand/diskonchip.c10
-rw-r--r--drivers/mtd/nand/h1910.c2
-rw-r--r--drivers/mtd/nand/nand_base.c146
-rw-r--r--drivers/mtd/nand/nandsim.c2
-rw-r--r--drivers/mtd/nand/ndfc.c10
-rw-r--r--drivers/mtd/nand/ppchameleonevb.c4
-rw-r--r--drivers/mtd/nand/rtc_from4.c12
-rw-r--r--drivers/mtd/nand/s3c2410.c16
-rw-r--r--drivers/mtd/nand/sharpsl.c10
-rw-r--r--drivers/mtd/nand/toto.c2
-rw-r--r--drivers/mtd/nand/ts7250.c2
-rw-r--r--include/linux/mtd/nand.h63
16 files changed, 131 insertions, 166 deletions
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index 5a349eb316f5..aeaf2dece095 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)
192 } 192 }
193 /* 25 us command delay time */ 193 /* 25 us command delay time */
194 this->chip_delay = 30; 194 this->chip_delay = 30;
195 this->eccmode = NAND_ECC_SOFT; 195 this->ecc.mode = NAND_ECC_SOFT;
196 196
197 /* Set chip enabled, but */ 197 /* Set chip enabled, but */
198 ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE | 198 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 d9a0143e1d3a..d7f04abfe18e 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -578,7 +578,7 @@ static int __init au1xxx_nand_init(void)
578 578
579 /* 30 us command delay time */ 579 /* 30 us command delay time */
580 this->chip_delay = 30; 580 this->chip_delay = 30;
581 this->eccmode = NAND_ECC_SOFT; 581 this->ecc.mode = NAND_ECC_SOFT;
582 582
583 this->options = NAND_NO_AUTOINCR; 583 this->options = NAND_NO_AUTOINCR;
584 584
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index 43b296040d7f..dbb1b6267ade 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -163,7 +163,7 @@ static int __init autcpu12_init(void)
163 this->dev_ready = autcpu12_device_ready; 163 this->dev_ready = autcpu12_device_ready;
164 /* 20 us command delay time */ 164 /* 20 us command delay time */
165 this->chip_delay = 20; 165 this->chip_delay = 20;
166 this->eccmode = NAND_ECC_SOFT; 166 this->ecc.mode = NAND_ECC_SOFT;
167 167
168 /* Enable the following for a flash based bad block table */ 168 /* Enable the following for a flash based bad block table */
169 /* 169 /*
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index bf251253ea1f..064f3feadf53 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, int mmio, unsigned long adr)
242 242
243 this->chip_delay = 0; 243 this->chip_delay = 0;
244 244
245 this->eccmode = NAND_ECC_HW3_256; 245 this->ecc.mode = NAND_ECC_HW;
246 this->enable_hwecc = cs_enable_hwecc; 246 this->ecc.size = 256;
247 this->calculate_ecc = cs_calculate_ecc; 247 this->ecc.bytes = 3;
248 this->correct_data = nand_correct_data; 248 this->ecc.hwctl = cs_enable_hwecc;
249 249 this->ecc.calculate = cs_calculate_ecc;
250 this->ecc.correct = nand_correct_data;
251
250 /* Enable the following for a flash based bad block table */ 252 /* Enable the following for a flash based bad block table */
251 this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR; 253 this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
252 254
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index a2391c66a63f..128c937af32f 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1674,12 +1674,14 @@ static int __init doc_probe(unsigned long physadr)
1674 nand->dev_ready = doc200x_dev_ready; 1674 nand->dev_ready = doc200x_dev_ready;
1675 nand->waitfunc = doc200x_wait; 1675 nand->waitfunc = doc200x_wait;
1676 nand->block_bad = doc200x_block_bad; 1676 nand->block_bad = doc200x_block_bad;
1677 nand->enable_hwecc = doc200x_enable_hwecc; 1677 nand->ecc.hwctl = doc200x_enable_hwecc;
1678 nand->calculate_ecc = doc200x_calculate_ecc; 1678 nand->ecc.calculate = doc200x_calculate_ecc;
1679 nand->correct_data = doc200x_correct_data; 1679 nand->ecc.correct = doc200x_correct_data;
1680 1680
1681 nand->autooob = &doc200x_oobinfo; 1681 nand->autooob = &doc200x_oobinfo;
1682 nand->eccmode = NAND_ECC_HW6_512; 1682 nand->ecc.mode = NAND_ECC_HW_SYNDROME;
1683 nand->ecc.size = 512;
1684 nand->ecc.bytes = 6;
1683 nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; 1685 nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME;
1684 1686
1685 doc->physadr = physadr; 1687 doc->physadr = physadr;
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index 9848eb09b884..06e91fa11b34 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -149,7 +149,7 @@ static int __init h1910_init(void)
149 this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */ 149 this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */
150 /* 15 us command delay time */ 150 /* 15 us command delay time */
151 this->chip_delay = 50; 151 this->chip_delay = 50;
152 this->eccmode = NAND_ECC_SOFT; 152 this->ecc.mode = NAND_ECC_SOFT;
153 this->options = NAND_NO_AUTOINCR; 153 this->options = NAND_NO_AUTOINCR;
154 154
155 /* Scan to find existence of the device */ 155 /* Scan to find existence of the device */
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 37db98a58c34..98792ec4c2dc 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_info *mtd, struct nand_chip *this, int pag
879{ 879{
880 int i, status; 880 int i, status;
881 uint8_t ecc_code[32]; 881 uint8_t ecc_code[32];
882 int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; 882 int eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
883 int *oob_config = oobsel->eccpos; 883 int *oob_config = oobsel->eccpos;
884 int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; 884 int datidx = 0, eccidx = 0, eccsteps = this->ecc.steps;
885 int eccbytes = 0; 885 int eccbytes = 0;
886 886
887 /* FIXME: Enable cached programming */ 887 /* FIXME: Enable cached programming */
@@ -901,20 +901,20 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag
901 /* Software ecc 3/256, write all */ 901 /* Software ecc 3/256, write all */
902 case NAND_ECC_SOFT: 902 case NAND_ECC_SOFT:
903 for (; eccsteps; eccsteps--) { 903 for (; eccsteps; eccsteps--) {
904 this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); 904 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
905 for (i = 0; i < 3; i++, eccidx++) 905 for (i = 0; i < 3; i++, eccidx++)
906 oob_buf[oob_config[eccidx]] = ecc_code[i]; 906 oob_buf[oob_config[eccidx]] = ecc_code[i];
907 datidx += this->eccsize; 907 datidx += this->ecc.size;
908 } 908 }
909 this->write_buf(mtd, this->data_poi, mtd->oobblock); 909 this->write_buf(mtd, this->data_poi, mtd->oobblock);
910 break; 910 break;
911 default: 911 default:
912 eccbytes = this->eccbytes; 912 eccbytes = this->ecc.bytes;
913 for (; eccsteps; eccsteps--) { 913 for (; eccsteps; eccsteps--) {
914 /* enable hardware ecc logic for write */ 914 /* enable hardware ecc logic for write */
915 this->enable_hwecc(mtd, NAND_ECC_WRITE); 915 this->ecc.hwctl(mtd, NAND_ECC_WRITE);
916 this->write_buf(mtd, &this->data_poi[datidx], this->eccsize); 916 this->write_buf(mtd, &this->data_poi[datidx], this->ecc.size);
917 this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); 917 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
918 for (i = 0; i < eccbytes; i++, eccidx++) 918 for (i = 0; i < eccbytes; i++, eccidx++)
919 oob_buf[oob_config[eccidx]] = ecc_code[i]; 919 oob_buf[oob_config[eccidx]] = ecc_code[i];
920 /* If the hardware ecc provides syndromes then 920 /* If the hardware ecc provides syndromes then
@@ -922,7 +922,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag
922 * the data bytes (words) */ 922 * the data bytes (words) */
923 if (this->options & NAND_HWECC_SYNDROME) 923 if (this->options & NAND_HWECC_SYNDROME)
924 this->write_buf(mtd, ecc_code, eccbytes); 924 this->write_buf(mtd, ecc_code, eccbytes);
925 datidx += this->eccsize; 925 datidx += this->ecc.size;
926 } 926 }
927 break; 927 break;
928 } 928 }
@@ -1155,7 +1155,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
1155 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) 1155 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
1156 oobsel = this->autooob; 1156 oobsel = this->autooob;
1157 1157
1158 eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; 1158 eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
1159 oob_config = oobsel->eccpos; 1159 oob_config = oobsel->eccpos;
1160 1160
1161 /* Select the NAND device */ 1161 /* Select the NAND device */
@@ -1170,8 +1170,8 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
1170 col = from & (mtd->oobblock - 1); 1170 col = from & (mtd->oobblock - 1);
1171 1171
1172 end = mtd->oobblock; 1172 end = mtd->oobblock;
1173 ecc = this->eccsize; 1173 ecc = this->ecc.size;
1174 eccbytes = this->eccbytes; 1174 eccbytes = this->ecc.bytes;
1175 1175
1176 if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) 1176 if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
1177 compareecc = 0; 1177 compareecc = 0;
@@ -1216,7 +1216,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
1216 oobsel->useecc == MTD_NANDECC_AUTOPL_USR) 1216 oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
1217 oob_data = &this->data_buf[end]; 1217 oob_data = &this->data_buf[end];
1218 1218
1219 eccsteps = this->eccsteps; 1219 eccsteps = this->ecc.steps;
1220 1220
1221 switch (eccmode) { 1221 switch (eccmode) {
1222 case NAND_ECC_NONE:{ 1222 case NAND_ECC_NONE:{
@@ -1234,12 +1234,12 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
1234 case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ 1234 case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
1235 this->read_buf(mtd, data_poi, end); 1235 this->read_buf(mtd, data_poi, end);
1236 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc) 1236 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc)
1237 this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); 1237 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
1238 break; 1238 break;
1239 1239
1240 default: 1240 default:
1241 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) { 1241 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) {
1242 this->enable_hwecc(mtd, NAND_ECC_READ); 1242 this->ecc.hwctl(mtd, NAND_ECC_READ);
1243 this->read_buf(mtd, &data_poi[datidx], ecc); 1243 this->read_buf(mtd, &data_poi[datidx], ecc);
1244 1244
1245 /* HW ecc with syndrome calculation must read the 1245 /* HW ecc with syndrome calculation must read the
@@ -1247,19 +1247,19 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
1247 if (!compareecc) { 1247 if (!compareecc) {
1248 /* Some hw ecc generators need to know when the 1248 /* Some hw ecc generators need to know when the
1249 * syndrome is read from flash */ 1249 * syndrome is read from flash */
1250 this->enable_hwecc(mtd, NAND_ECC_READSYN); 1250 this->ecc.hwctl(mtd, NAND_ECC_READSYN);
1251 this->read_buf(mtd, &oob_data[i], eccbytes); 1251 this->read_buf(mtd, &oob_data[i], eccbytes);
1252 /* We calc error correction directly, it checks the hw 1252 /* We calc error correction directly, it checks the hw
1253 * generator for an error, reads back the syndrome and 1253 * generator for an error, reads back the syndrome and
1254 * does the error correction on the fly */ 1254 * does the error correction on the fly */
1255 ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]); 1255 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
1256 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { 1256 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
1257 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: " 1257 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: "
1258 "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); 1258 "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
1259 ecc_failed++; 1259 ecc_failed++;
1260 } 1260 }
1261 } else { 1261 } else {
1262 this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); 1262 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
1263 } 1263 }
1264 } 1264 }
1265 break; 1265 break;
@@ -1277,8 +1277,8 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
1277 ecc_code[j] = oob_data[oob_config[j]]; 1277 ecc_code[j] = oob_data[oob_config[j]];
1278 1278
1279 /* correct data, if necessary */ 1279 /* correct data, if necessary */
1280 for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) { 1280 for (i = 0, j = 0, datidx = 0; i < this->ecc.steps; i++, datidx += ecc) {
1281 ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); 1281 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
1282 1282
1283 /* Get next chunk of ecc bytes */ 1283 /* Get next chunk of ecc bytes */
1284 j += eccbytes; 1284 j += eccbytes;
@@ -1315,7 +1315,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
1315 break; 1315 break;
1316 case MTD_NANDECC_PLACE: 1316 case MTD_NANDECC_PLACE:
1317 /* YAFFS1 legacy mode */ 1317 /* YAFFS1 legacy mode */
1318 oob_data += this->eccsteps * sizeof(int); 1318 oob_data += this->ecc.steps * sizeof(int);
1319 default: 1319 default:
1320 oob_data += mtd->oobsize; 1320 oob_data += mtd->oobsize;
1321 } 1321 }
@@ -2648,99 +2648,49 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
2648 * check ECC mode, default to software if 3byte/512byte hardware ECC is 2648 * check ECC mode, default to software if 3byte/512byte hardware ECC is
2649 * selected and we have 256 byte pagesize fallback to software ECC 2649 * selected and we have 256 byte pagesize fallback to software ECC
2650 */ 2650 */
2651 this->eccsize = 256; 2651 switch (this->ecc.mode) {
2652 this->eccbytes = 3; 2652 case NAND_ECC_HW:
2653 2653 case NAND_ECC_HW_SYNDROME:
2654 switch (this->eccmode) { 2654 if (!this->ecc.calculate || !this->ecc.correct ||
2655 case NAND_ECC_HW12_2048: 2655 !this->ecc.hwctl) {
2656 if (mtd->oobblock < 2048) { 2656 printk(KERN_WARNING "No ECC functions supplied, "
2657 printk(KERN_WARNING "2048 byte HW ECC not possible on " 2657 "Hardware ECC not possible\n");
2658 "%d byte page size, fallback to SW ECC\n", 2658 BUG();
2659 mtd->oobblock); 2659 }
2660 this->eccmode = NAND_ECC_SOFT; 2660 if (mtd->oobblock >= this->ecc.size)
2661 this->calculate_ecc = nand_calculate_ecc; 2661 break;
2662 this->correct_data = nand_correct_data; 2662 printk(KERN_WARNING "%d byte HW ECC not possible on "
2663 } else 2663 "%d byte page size, fallback to SW ECC\n",
2664 this->eccsize = 2048; 2664 this->ecc.size, mtd->oobblock);
2665 break; 2665 this->ecc.mode = NAND_ECC_SOFT;
2666
2667 case NAND_ECC_HW3_512:
2668 case NAND_ECC_HW6_512:
2669 case NAND_ECC_HW8_512:
2670 if (mtd->oobblock == 256) {
2671 printk(KERN_WARNING "512 byte HW ECC not possible on "
2672 "256 Byte pagesize, fallback to SW ECC \n");
2673 this->eccmode = NAND_ECC_SOFT;
2674 this->calculate_ecc = nand_calculate_ecc;
2675 this->correct_data = nand_correct_data;
2676 } else
2677 this->eccsize = 512; /* set eccsize to 512 */
2678 break;
2679 2666
2680 case NAND_ECC_HW3_256: 2667 case NAND_ECC_SOFT:
2668 this->ecc.calculate = nand_calculate_ecc;
2669 this->ecc.correct = nand_correct_data;
2670 this->ecc.size = 256;
2671 this->ecc.bytes = 3;
2681 break; 2672 break;
2682 2673
2683 case NAND_ECC_NONE: 2674 case NAND_ECC_NONE:
2684 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " 2675 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2685 "This is not recommended !!\n"); 2676 "This is not recommended !!\n");
2686 this->eccmode = NAND_ECC_NONE; 2677 this->ecc.size = mtd->oobblock;
2678 this->ecc.bytes = 0;
2687 break; 2679 break;
2688
2689 case NAND_ECC_SOFT:
2690 this->calculate_ecc = nand_calculate_ecc;
2691 this->correct_data = nand_correct_data;
2692 break;
2693
2694 default: 2680 default:
2695 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", 2681 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
2696 this->eccmode); 2682 this->ecc.mode);
2697 BUG();
2698 }
2699
2700 /*
2701 * Check hardware ecc function availability and adjust number of ecc
2702 * bytes per calculation step
2703 */
2704 switch (this->eccmode) {
2705 case NAND_ECC_HW12_2048:
2706 this->eccbytes += 4;
2707 case NAND_ECC_HW8_512:
2708 this->eccbytes += 2;
2709 case NAND_ECC_HW6_512:
2710 this->eccbytes += 3;
2711 case NAND_ECC_HW3_512:
2712 case NAND_ECC_HW3_256:
2713 if (this->calculate_ecc && this->correct_data &&
2714 this->enable_hwecc)
2715 break;
2716 printk(KERN_WARNING "No ECC functions supplied, "
2717 "Hardware ECC not possible\n");
2718 BUG(); 2683 BUG();
2719 } 2684 }
2720 2685
2721 mtd->eccsize = this->eccsize;
2722
2723 /* 2686 /*
2724 * Set the number of read / write steps for one page depending on ECC 2687 * Set the number of read / write steps for one page depending on ECC
2725 * mode 2688 * mode
2726 */ 2689 */
2727 switch (this->eccmode) { 2690 this->ecc.steps = mtd->oobblock / this->ecc.size;
2728 case NAND_ECC_HW12_2048: 2691 if(this->ecc.steps * this->ecc.size != mtd->oobblock) {
2729 this->eccsteps = mtd->oobblock / 2048; 2692 printk(KERN_WARNING "Invalid ecc parameters\n");
2730 break; 2693 BUG();
2731 case NAND_ECC_HW3_512:
2732 case NAND_ECC_HW6_512:
2733 case NAND_ECC_HW8_512:
2734 this->eccsteps = mtd->oobblock / 512;
2735 break;
2736 case NAND_ECC_HW3_256:
2737 case NAND_ECC_SOFT:
2738 this->eccsteps = mtd->oobblock / 256;
2739 break;
2740
2741 case NAND_ECC_NONE:
2742 this->eccsteps = 1;
2743 break;
2744 } 2694 }
2745 2695
2746 /* Initialize state, waitqueue and spinlock */ 2696 /* Initialize state, waitqueue and spinlock */
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 6903f5b903c6..9008bc5493fb 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -1523,7 +1523,7 @@ static int __init ns_init_module(void)
1523 chip->verify_buf = ns_nand_verify_buf; 1523 chip->verify_buf = ns_nand_verify_buf;
1524 chip->write_word = ns_nand_write_word; 1524 chip->write_word = ns_nand_write_word;
1525 chip->read_word = ns_nand_read_word; 1525 chip->read_word = ns_nand_read_word;
1526 chip->eccmode = NAND_ECC_SOFT; 1526 chip->ecc.mode = NAND_ECC_SOFT;
1527 chip->options |= NAND_SKIP_BBTSCAN; 1527 chip->options |= NAND_SKIP_BBTSCAN;
1528 1528
1529 /* 1529 /*
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 22fd682b70ca..e2dc81de106a 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -168,10 +168,12 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
168 chip->read_buf = ndfc_read_buf; 168 chip->read_buf = ndfc_read_buf;
169 chip->write_buf = ndfc_write_buf; 169 chip->write_buf = ndfc_write_buf;
170 chip->verify_buf = ndfc_verify_buf; 170 chip->verify_buf = ndfc_verify_buf;
171 chip->correct_data = nand_correct_data; 171 chip->ecc.correct = nand_correct_data;
172 chip->enable_hwecc = ndfc_enable_hwecc; 172 chip->ecc.hwctl = ndfc_enable_hwecc;
173 chip->calculate_ecc = ndfc_calculate_ecc; 173 chip->ecc.calculate = ndfc_calculate_ecc;
174 chip->eccmode = NAND_ECC_HW3_256; 174 chip->ecc.mode = NAND_ECC_HW;
175 chip->ecc.size = 256;
176 chip->ecc.bytes = 3;
175 chip->autooob = mtd->pl_chip->autooob; 177 chip->autooob = mtd->pl_chip->autooob;
176 mtd->mtd.priv = chip; 178 mtd->mtd.priv = chip;
177 mtd->mtd.owner = THIS_MODULE; 179 mtd->mtd.owner = THIS_MODULE;
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index 5d4d16fb1df6..9fab0998524d 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -257,7 +257,7 @@ static int __init ppchameleonevb_init(void)
257#endif 257#endif
258 this->chip_delay = NAND_BIG_DELAY_US; 258 this->chip_delay = NAND_BIG_DELAY_US;
259 /* ECC mode */ 259 /* ECC mode */
260 this->eccmode = NAND_ECC_SOFT; 260 this->ecc.mode = NAND_ECC_SOFT;
261 261
262 /* Scan to find existence of the device (it could not be mounted) */ 262 /* Scan to find existence of the device (it could not be mounted) */
263 if (nand_scan(ppchameleon_mtd, 1)) { 263 if (nand_scan(ppchameleon_mtd, 1)) {
@@ -358,7 +358,7 @@ static int __init ppchameleonevb_init(void)
358 this->chip_delay = NAND_SMALL_DELAY_US; 358 this->chip_delay = NAND_SMALL_DELAY_US;
359 359
360 /* ECC mode */ 360 /* ECC mode */
361 this->eccmode = NAND_ECC_SOFT; 361 this->ecc.mode = NAND_ECC_SOFT;
362 362
363 /* Scan to find existence of the device */ 363 /* Scan to find existence of the device */
364 if (nand_scan(ppchameleonevb_mtd, 1)) { 364 if (nand_scan(ppchameleonevb_mtd, 1)) {
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index bc9d849fbd5d..a2122fe4101a 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)
570#ifdef RTC_FROM4_HWECC 570#ifdef RTC_FROM4_HWECC
571 printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n"); 571 printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n");
572 572
573 this->eccmode = NAND_ECC_HW8_512; 573 this->ecc.mode = NAND_ECC_HW_SYNDROME;
574 this->ecc.size = 512;
575 this->ecc.bytes = 8;
574 this->options |= NAND_HWECC_SYNDROME; 576 this->options |= NAND_HWECC_SYNDROME;
575 /* return the status of extra status and ECC checks */ 577 /* return the status of extra status and ECC checks */
576 this->errstat = rtc_from4_errstat; 578 this->errstat = rtc_from4_errstat;
577 /* set the nand_oobinfo to support FPGA H/W error detection */ 579 /* set the nand_oobinfo to support FPGA H/W error detection */
578 this->autooob = &rtc_from4_nand_oobinfo; 580 this->autooob = &rtc_from4_nand_oobinfo;
579 this->enable_hwecc = rtc_from4_enable_hwecc; 581 this->ecc.hwctl = rtc_from4_enable_hwecc;
580 this->calculate_ecc = rtc_from4_calculate_ecc; 582 this->ecc.calculate = rtc_from4_calculate_ecc;
581 this->correct_data = rtc_from4_correct_data; 583 this->ecc.correct = rtc_from4_correct_data;
582#else 584#else
583 printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n"); 585 printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
584 586
585 this->eccmode = NAND_ECC_SOFT; 587 this->ecc.mode = NAND_ECC_SOFT;
586#endif 588#endif
587 589
588 /* set the bad block tables to support debugging */ 590 /* set the bad block tables to support debugging */
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index f8002596de8b..608340a25278 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -520,18 +520,20 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
520 nmtd->set = set; 520 nmtd->set = set;
521 521
522 if (hardware_ecc) { 522 if (hardware_ecc) {
523 chip->correct_data = s3c2410_nand_correct_data; 523 chip->ecc.correct = s3c2410_nand_correct_data;
524 chip->enable_hwecc = s3c2410_nand_enable_hwecc; 524 chip->ecc.hwctl = s3c2410_nand_enable_hwecc;
525 chip->calculate_ecc = s3c2410_nand_calculate_ecc; 525 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
526 chip->eccmode = NAND_ECC_HW3_512; 526 chip->ecc.mode = NAND_ECC_HW;
527 chip->ecc.size = 512;
528 chip->ecc.bytes = 3;
527 chip->autooob = &nand_hw_eccoob; 529 chip->autooob = &nand_hw_eccoob;
528 530
529 if (info->is_s3c2440) { 531 if (info->is_s3c2440) {
530 chip->enable_hwecc = s3c2440_nand_enable_hwecc; 532 chip->ecc.hwctl = s3c2440_nand_enable_hwecc;
531 chip->calculate_ecc = s3c2440_nand_calculate_ecc; 533 chip->ecc.calculate = s3c2440_nand_calculate_ecc;
532 } 534 }
533 } else { 535 } else {
534 chip->eccmode = NAND_ECC_SOFT; 536 chip->ecc.mode = NAND_ECC_SOFT;
535 } 537 }
536} 538}
537 539
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 60e10c0d6980..5554d0b97c8c 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -201,15 +201,17 @@ static int __init sharpsl_nand_init(void)
201 /* 15 us command delay time */ 201 /* 15 us command delay time */
202 this->chip_delay = 15; 202 this->chip_delay = 15;
203 /* set eccmode using hardware ECC */ 203 /* set eccmode using hardware ECC */
204 this->eccmode = NAND_ECC_HW3_256; 204 this->ecc.mode = NAND_ECC_HW;
205 this->ecc.size = 256;
206 this->ecc.bytes = 3;
205 this->badblock_pattern = &sharpsl_bbt; 207 this->badblock_pattern = &sharpsl_bbt;
206 if (machine_is_akita() || machine_is_borzoi()) { 208 if (machine_is_akita() || machine_is_borzoi()) {
207 this->badblock_pattern = &sharpsl_akita_bbt; 209 this->badblock_pattern = &sharpsl_akita_bbt;
208 this->autooob = &akita_oobinfo; 210 this->autooob = &akita_oobinfo;
209 } 211 }
210 this->enable_hwecc = sharpsl_nand_enable_hwecc; 212 this->ecc.hwctl = sharpsl_nand_enable_hwecc;
211 this->calculate_ecc = sharpsl_nand_calculate_ecc; 213 this->ecc.calculate = sharpsl_nand_calculate_ecc;
212 this->correct_data = nand_correct_data; 214 this->ecc.correct = nand_correct_data;
213 215
214 /* Scan to find existence of the device */ 216 /* Scan to find existence of the device */
215 err = nand_scan(sharpsl_mtd, 1); 217 err = nand_scan(sharpsl_mtd, 1);
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c
index c51c89559514..50aa6a46911f 100644
--- a/drivers/mtd/nand/toto.c
+++ b/drivers/mtd/nand/toto.c
@@ -146,7 +146,7 @@ static int __init toto_init(void)
146 this->dev_ready = NULL; 146 this->dev_ready = NULL;
147 /* 25 us command delay time */ 147 /* 25 us command delay time */
148 this->chip_delay = 30; 148 this->chip_delay = 30;
149 this->eccmode = NAND_ECC_SOFT; 149 this->ecc.mode = NAND_ECC_SOFT;
150 150
151 /* Scan to find existance of the device */ 151 /* Scan to find existance of the device */
152 if (nand_scan(toto_mtd, 1)) { 152 if (nand_scan(toto_mtd, 1)) {
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c
index 622db3127f7c..70bce1b0326c 100644
--- a/drivers/mtd/nand/ts7250.c
+++ b/drivers/mtd/nand/ts7250.c
@@ -155,7 +155,7 @@ static int __init ts7250_init(void)
155 this->hwcontrol = ts7250_hwcontrol; 155 this->hwcontrol = ts7250_hwcontrol;
156 this->dev_ready = ts7250_device_ready; 156 this->dev_ready = ts7250_device_ready;
157 this->chip_delay = 15; 157 this->chip_delay = 15;
158 this->eccmode = NAND_ECC_SOFT; 158 this->ecc.mode = NAND_ECC_SOFT;
159 159
160 printk("Searching for NAND flash...\n"); 160 printk("Searching for NAND flash...\n");
161 /* Scan to find existence of the device */ 161 /* Scan to find existence of the device */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 601c5c703a05..460525841a27 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -113,21 +113,12 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from,
113/* 113/*
114 * Constants for ECC_MODES 114 * Constants for ECC_MODES
115 */ 115 */
116 116typedef enum {
117/* No ECC. Usage is not recommended ! */ 117 NAND_ECC_NONE,
118#define NAND_ECC_NONE 0 118 NAND_ECC_SOFT,
119/* Software ECC 3 byte ECC per 256 Byte data */ 119 NAND_ECC_HW,
120#define NAND_ECC_SOFT 1 120 NAND_ECC_HW_SYNDROME,
121/* Hardware ECC 3 byte ECC per 256 Byte data */ 121} nand_ecc_modes_t;
122#define NAND_ECC_HW3_256 2
123/* Hardware ECC 3 byte ECC per 512 Byte data */
124#define NAND_ECC_HW3_512 3
125/* Hardware ECC 3 byte ECC per 512 Byte data */
126#define NAND_ECC_HW6_512 4
127/* Hardware ECC 8 byte ECC per 512 Byte data */
128#define NAND_ECC_HW8_512 6
129/* Hardware ECC 12 byte ECC per 2048 Byte data */
130#define NAND_ECC_HW12_2048 7
131 122
132/* 123/*
133 * Constants for Hardware ECC 124 * Constants for Hardware ECC
@@ -231,6 +222,31 @@ struct nand_hw_control {
231}; 222};
232 223
233/** 224/**
225 * struct nand_ecc_ctrl - Control structure for ecc
226 * @mode: ecc mode
227 * @steps: number of ecc steps per page
228 * @size: data bytes per ecc step
229 * @bytes: ecc bytes per step
230 * @hwctl: function to control hardware ecc generator. Must only
231 * be provided if an hardware ECC is available
232 * @calculate: function for ecc calculation or readback from ecc hardware
233 * @correct: function for ecc correction, matching to ecc generator (sw/hw)
234 */
235struct nand_ecc_ctrl {
236 nand_ecc_modes_t mode;
237 int steps;
238 int size;
239 int bytes;
240 int (*hwctl)(struct mtd_info *mtd, int mode);
241 int (*calculate)(struct mtd_info *mtd,
242 const uint8_t *dat,
243 uint8_t *ecc_code);
244 int (*correct)(struct mtd_info *mtd, uint8_t *dat,
245 uint8_t *read_ecc,
246 uint8_t *calc_ecc);
247};
248
249/**
234 * struct nand_chip - NAND Private Flash Chip Data 250 * struct nand_chip - NAND Private Flash Chip Data
235 * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device 251 * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
236 * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device 252 * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
@@ -250,16 +266,9 @@ struct nand_hw_control {
250 * is read from the chip status register 266 * is read from the chip status register
251 * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip 267 * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip
252 * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready 268 * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready
253 * @calculate_ecc: [REPLACEABLE] function for ecc calculation or readback from ecc hardware 269 * @ecc: [BOARDSPECIFIC] ecc control ctructure
254 * @correct_data: [REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
255 * @enable_hwecc: [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
256 * be provided if a hardware ECC is available
257 * @erase_cmd: [INTERN] erase command write function, selectable due to AND support 270 * @erase_cmd: [INTERN] erase command write function, selectable due to AND support
258 * @scan_bbt: [REPLACEABLE] function to scan bad block table 271 * @scan_bbt: [REPLACEABLE] function to scan bad block table
259 * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines
260 * @eccsize: [INTERN] databytes used per ecc-calculation
261 * @eccbytes: [INTERN] number of ecc bytes per ecc-calculation step
262 * @eccsteps: [INTERN] number of ecc calculation steps per page
263 * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR) 272 * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
264 * @wq: [INTERN] wait queue to sleep on if a NAND operation is in progress 273 * @wq: [INTERN] wait queue to sleep on if a NAND operation is in progress
265 * @state: [INTERN] the current state of the NAND device 274 * @state: [INTERN] the current state of the NAND device
@@ -309,15 +318,9 @@ struct nand_chip {
309 int (*dev_ready)(struct mtd_info *mtd); 318 int (*dev_ready)(struct mtd_info *mtd);
310 void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); 319 void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
311 int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state); 320 int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
312 int (*calculate_ecc)(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code);
313 int (*correct_data)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc);
314 void (*enable_hwecc)(struct mtd_info *mtd, int mode);
315 void (*erase_cmd)(struct mtd_info *mtd, int page); 321 void (*erase_cmd)(struct mtd_info *mtd, int page);
316 int (*scan_bbt)(struct mtd_info *mtd); 322 int (*scan_bbt)(struct mtd_info *mtd);
317 int eccmode; 323 struct nand_ecc_ctrl ecc;
318 int eccsize;
319 int eccbytes;
320 int eccsteps;
321 int chip_delay; 324 int chip_delay;
322 wait_queue_head_t wq; 325 wait_queue_head_t wq;
323 nand_state_t state; 326 nand_state_t state;