Skip to content

Commit 6dfc6d2

Browse files
author
Thomas Gleixner
committed
[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 <[email protected]>
1 parent 7aa65bf commit 6dfc6d2

File tree

16 files changed

+131
-166
lines changed

16 files changed

+131
-166
lines changed

drivers/mtd/nand/ams-delta.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ static int __init ams_delta_init(void)
192192
}
193193
/* 25 us command delay time */
194194
this->chip_delay = 30;
195-
this->eccmode = NAND_ECC_SOFT;
195+
this->ecc.mode = NAND_ECC_SOFT;
196196

197197
/* Set chip enabled, but */
198198
ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |

drivers/mtd/nand/au1550nd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ static int __init au1xxx_nand_init(void)
578578

579579
/* 30 us command delay time */
580580
this->chip_delay = 30;
581-
this->eccmode = NAND_ECC_SOFT;
581+
this->ecc.mode = NAND_ECC_SOFT;
582582

583583
this->options = NAND_NO_AUTOINCR;
584584

drivers/mtd/nand/autcpu12.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static int __init autcpu12_init(void)
163163
this->dev_ready = autcpu12_device_ready;
164164
/* 20 us command delay time */
165165
this->chip_delay = 20;
166-
this->eccmode = NAND_ECC_SOFT;
166+
this->ecc.mode = NAND_ECC_SOFT;
167167

168168
/* Enable the following for a flash based bad block table */
169169
/*

drivers/mtd/nand/cs553x_nand.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,13 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
242242

243243
this->chip_delay = 0;
244244

245-
this->eccmode = NAND_ECC_HW3_256;
246-
this->enable_hwecc = cs_enable_hwecc;
247-
this->calculate_ecc = cs_calculate_ecc;
248-
this->correct_data = nand_correct_data;
249-
245+
this->ecc.mode = NAND_ECC_HW;
246+
this->ecc.size = 256;
247+
this->ecc.bytes = 3;
248+
this->ecc.hwctl = cs_enable_hwecc;
249+
this->ecc.calculate = cs_calculate_ecc;
250+
this->ecc.correct = nand_correct_data;
251+
250252
/* Enable the following for a flash based bad block table */
251253
this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
252254

drivers/mtd/nand/diskonchip.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,12 +1674,14 @@ static int __init doc_probe(unsigned long physadr)
16741674
nand->dev_ready = doc200x_dev_ready;
16751675
nand->waitfunc = doc200x_wait;
16761676
nand->block_bad = doc200x_block_bad;
1677-
nand->enable_hwecc = doc200x_enable_hwecc;
1678-
nand->calculate_ecc = doc200x_calculate_ecc;
1679-
nand->correct_data = doc200x_correct_data;
1677+
nand->ecc.hwctl = doc200x_enable_hwecc;
1678+
nand->ecc.calculate = doc200x_calculate_ecc;
1679+
nand->ecc.correct = doc200x_correct_data;
16801680

16811681
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;
16831685
nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME;
16841686

16851687
doc->physadr = physadr;

drivers/mtd/nand/h1910.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ static int __init h1910_init(void)
149149
this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */
150150
/* 15 us command delay time */
151151
this->chip_delay = 50;
152-
this->eccmode = NAND_ECC_SOFT;
152+
this->ecc.mode = NAND_ECC_SOFT;
153153
this->options = NAND_NO_AUTOINCR;
154154

155155
/* Scan to find existence of the device */

drivers/mtd/nand/nand_base.c

Lines changed: 48 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -879,9 +879,9 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag
879879
{
880880
int i, status;
881881
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;
883883
int *oob_config = oobsel->eccpos;
884-
int datidx = 0, eccidx = 0, eccsteps = this->eccsteps;
884+
int datidx = 0, eccidx = 0, eccsteps = this->ecc.steps;
885885
int eccbytes = 0;
886886

887887
/* FIXME: Enable cached programming */
@@ -901,28 +901,28 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag
901901
/* Software ecc 3/256, write all */
902902
case NAND_ECC_SOFT:
903903
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);
905905
for (i = 0; i < 3; i++, eccidx++)
906906
oob_buf[oob_config[eccidx]] = ecc_code[i];
907-
datidx += this->eccsize;
907+
datidx += this->ecc.size;
908908
}
909909
this->write_buf(mtd, this->data_poi, mtd->oobblock);
910910
break;
911911
default:
912-
eccbytes = this->eccbytes;
912+
eccbytes = this->ecc.bytes;
913913
for (; eccsteps; eccsteps--) {
914914
/* enable hardware ecc logic for write */
915-
this->enable_hwecc(mtd, NAND_ECC_WRITE);
916-
this->write_buf(mtd, &this->data_poi[datidx], this->eccsize);
917-
this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
915+
this->ecc.hwctl(mtd, NAND_ECC_WRITE);
916+
this->write_buf(mtd, &this->data_poi[datidx], this->ecc.size);
917+
this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
918918
for (i = 0; i < eccbytes; i++, eccidx++)
919919
oob_buf[oob_config[eccidx]] = ecc_code[i];
920920
/* If the hardware ecc provides syndromes then
921921
* the ecc code must be written immidiately after
922922
* the data bytes (words) */
923923
if (this->options & NAND_HWECC_SYNDROME)
924924
this->write_buf(mtd, ecc_code, eccbytes);
925-
datidx += this->eccsize;
925+
datidx += this->ecc.size;
926926
}
927927
break;
928928
}
@@ -1155,7 +1155,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
11551155
if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
11561156
oobsel = this->autooob;
11571157

1158-
eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
1158+
eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
11591159
oob_config = oobsel->eccpos;
11601160

11611161
/* Select the NAND device */
@@ -1170,8 +1170,8 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
11701170
col = from & (mtd->oobblock - 1);
11711171

11721172
end = mtd->oobblock;
1173-
ecc = this->eccsize;
1174-
eccbytes = this->eccbytes;
1173+
ecc = this->ecc.size;
1174+
eccbytes = this->ecc.bytes;
11751175

11761176
if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
11771177
compareecc = 0;
@@ -1216,7 +1216,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
12161216
oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
12171217
oob_data = &this->data_buf[end];
12181218

1219-
eccsteps = this->eccsteps;
1219+
eccsteps = this->ecc.steps;
12201220

12211221
switch (eccmode) {
12221222
case NAND_ECC_NONE:{
@@ -1234,32 +1234,32 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
12341234
case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
12351235
this->read_buf(mtd, data_poi, end);
12361236
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]);
12381238
break;
12391239

12401240
default:
12411241
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);
12431243
this->read_buf(mtd, &data_poi[datidx], ecc);
12441244

12451245
/* HW ecc with syndrome calculation must read the
12461246
* syndrome from flash immidiately after the data */
12471247
if (!compareecc) {
12481248
/* Some hw ecc generators need to know when the
12491249
* syndrome is read from flash */
1250-
this->enable_hwecc(mtd, NAND_ECC_READSYN);
1250+
this->ecc.hwctl(mtd, NAND_ECC_READSYN);
12511251
this->read_buf(mtd, &oob_data[i], eccbytes);
12521252
/* We calc error correction directly, it checks the hw
12531253
* generator for an error, reads back the syndrome and
12541254
* 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]);
12561256
if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
12571257
DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: "
12581258
"Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
12591259
ecc_failed++;
12601260
}
12611261
} else {
1262-
this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
1262+
this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
12631263
}
12641264
}
12651265
break;
@@ -1277,8 +1277,8 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
12771277
ecc_code[j] = oob_data[oob_config[j]];
12781278

12791279
/* correct data, if necessary */
1280-
for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) {
1281-
ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
1280+
for (i = 0, j = 0, datidx = 0; i < this->ecc.steps; i++, datidx += ecc) {
1281+
ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
12821282

12831283
/* Get next chunk of ecc bytes */
12841284
j += eccbytes;
@@ -1315,7 +1315,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
13151315
break;
13161316
case MTD_NANDECC_PLACE:
13171317
/* YAFFS1 legacy mode */
1318-
oob_data += this->eccsteps * sizeof(int);
1318+
oob_data += this->ecc.steps * sizeof(int);
13191319
default:
13201320
oob_data += mtd->oobsize;
13211321
}
@@ -2648,99 +2648,49 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
26482648
* check ECC mode, default to software if 3byte/512byte hardware ECC is
26492649
* selected and we have 256 byte pagesize fallback to software ECC
26502650
*/
2651-
this->eccsize = 256;
2652-
this->eccbytes = 3;
2653-
2654-
switch (this->eccmode) {
2655-
case NAND_ECC_HW12_2048:
2656-
if (mtd->oobblock < 2048) {
2657-
printk(KERN_WARNING "2048 byte HW ECC not possible on "
2658-
"%d byte page size, fallback to SW ECC\n",
2659-
mtd->oobblock);
2660-
this->eccmode = NAND_ECC_SOFT;
2661-
this->calculate_ecc = nand_calculate_ecc;
2662-
this->correct_data = nand_correct_data;
2663-
} else
2664-
this->eccsize = 2048;
2665-
break;
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;
2651+
switch (this->ecc.mode) {
2652+
case NAND_ECC_HW:
2653+
case NAND_ECC_HW_SYNDROME:
2654+
if (!this->ecc.calculate || !this->ecc.correct ||
2655+
!this->ecc.hwctl) {
2656+
printk(KERN_WARNING "No ECC functions supplied, "
2657+
"Hardware ECC not possible\n");
2658+
BUG();
2659+
}
2660+
if (mtd->oobblock >= this->ecc.size)
2661+
break;
2662+
printk(KERN_WARNING "%d byte HW ECC not possible on "
2663+
"%d byte page size, fallback to SW ECC\n",
2664+
this->ecc.size, mtd->oobblock);
2665+
this->ecc.mode = NAND_ECC_SOFT;
26792666

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;
26812672
break;
26822673

26832674
case NAND_ECC_NONE:
26842675
printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
26852676
"This is not recommended !!\n");
2686-
this->eccmode = NAND_ECC_NONE;
2677+
this->ecc.size = mtd->oobblock;
2678+
this->ecc.bytes = 0;
26872679
break;
2688-
2689-
case NAND_ECC_SOFT:
2690-
this->calculate_ecc = nand_calculate_ecc;
2691-
this->correct_data = nand_correct_data;
2692-
break;
2693-
26942680
default:
26952681
printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
2696-
this->eccmode);
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");
2682+
this->ecc.mode);
27182683
BUG();
27192684
}
27202685

2721-
mtd->eccsize = this->eccsize;
2722-
27232686
/*
27242687
* Set the number of read / write steps for one page depending on ECC
27252688
* mode
27262689
*/
2727-
switch (this->eccmode) {
2728-
case NAND_ECC_HW12_2048:
2729-
this->eccsteps = mtd->oobblock / 2048;
2730-
break;
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;
2690+
this->ecc.steps = mtd->oobblock / this->ecc.size;
2691+
if(this->ecc.steps * this->ecc.size != mtd->oobblock) {
2692+
printk(KERN_WARNING "Invalid ecc parameters\n");
2693+
BUG();
27442694
}
27452695

27462696
/* Initialize state, waitqueue and spinlock */

drivers/mtd/nand/nandsim.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1523,7 +1523,7 @@ static int __init ns_init_module(void)
15231523
chip->verify_buf = ns_nand_verify_buf;
15241524
chip->write_word = ns_nand_write_word;
15251525
chip->read_word = ns_nand_read_word;
1526-
chip->eccmode = NAND_ECC_SOFT;
1526+
chip->ecc.mode = NAND_ECC_SOFT;
15271527
chip->options |= NAND_SKIP_BBTSCAN;
15281528

15291529
/*

drivers/mtd/nand/ndfc.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,12 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
168168
chip->read_buf = ndfc_read_buf;
169169
chip->write_buf = ndfc_write_buf;
170170
chip->verify_buf = ndfc_verify_buf;
171-
chip->correct_data = nand_correct_data;
172-
chip->enable_hwecc = ndfc_enable_hwecc;
173-
chip->calculate_ecc = ndfc_calculate_ecc;
174-
chip->eccmode = NAND_ECC_HW3_256;
171+
chip->ecc.correct = nand_correct_data;
172+
chip->ecc.hwctl = ndfc_enable_hwecc;
173+
chip->ecc.calculate = ndfc_calculate_ecc;
174+
chip->ecc.mode = NAND_ECC_HW;
175+
chip->ecc.size = 256;
176+
chip->ecc.bytes = 3;
175177
chip->autooob = mtd->pl_chip->autooob;
176178
mtd->mtd.priv = chip;
177179
mtd->mtd.owner = THIS_MODULE;

drivers/mtd/nand/ppchameleonevb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ static int __init ppchameleonevb_init(void)
257257
#endif
258258
this->chip_delay = NAND_BIG_DELAY_US;
259259
/* ECC mode */
260-
this->eccmode = NAND_ECC_SOFT;
260+
this->ecc.mode = NAND_ECC_SOFT;
261261

262262
/* Scan to find existence of the device (it could not be mounted) */
263263
if (nand_scan(ppchameleon_mtd, 1)) {
@@ -358,7 +358,7 @@ static int __init ppchameleonevb_init(void)
358358
this->chip_delay = NAND_SMALL_DELAY_US;
359359

360360
/* ECC mode */
361-
this->eccmode = NAND_ECC_SOFT;
361+
this->ecc.mode = NAND_ECC_SOFT;
362362

363363
/* Scan to find existence of the device */
364364
if (nand_scan(ppchameleonevb_mtd, 1)) {

0 commit comments

Comments
 (0)