diff options
author | Thomas Gleixner <tglx@cruncher.tec.linutronix.de> | 2006-05-23 06:00:46 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@cruncher.tec.linutronix.de> | 2006-05-23 06:00:46 -0400 |
commit | 6dfc6d250d0b7ebaa6423c44dcd09fcfe68deabd (patch) | |
tree | 2be25b1e302eca5984a8ad5ed3e5bde77bafaabb | |
parent | 7aa65bfd6793a56cc3bbce8436abbfea3a7bdd1f (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.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/au1550nd.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/autcpu12.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/cs553x_nand.c | 12 | ||||
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 10 | ||||
-rw-r--r-- | drivers/mtd/nand/h1910.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 146 | ||||
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/ndfc.c | 10 | ||||
-rw-r--r-- | drivers/mtd/nand/ppchameleonevb.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/rtc_from4.c | 12 | ||||
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 16 | ||||
-rw-r--r-- | drivers/mtd/nand/sharpsl.c | 10 | ||||
-rw-r--r-- | drivers/mtd/nand/toto.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/ts7250.c | 2 | ||||
-rw-r--r-- | 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 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 | 116 | typedef 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 | */ | ||
235 | struct 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; |