summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorMike Dunn <mikedunn@newsguy.com>2012-03-12 01:21:11 +0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-03-27 03:56:46 +0400
commit6a918bade9dab40aaef80559bd1169c69e8d69cb (patch)
tree1be69789f9b6c6e064a36f4ef6e142a8ec0058b5 /drivers/mtd/nand
parent1d0b95b0834087ba3653f69c24483d63a26d51a7 (diff)
downloadlinux-6a918bade9dab40aaef80559bd1169c69e8d69cb.tar.xz
mtd: flash drivers set ecc strength
Flash device drivers initialize 'ecc_strength' in struct mtd_info, which is the maximum number of bit errors that can be corrected in one writesize region. Drivers using the nand interface intitialize 'strength' in struct nand_ecc_ctrl, which is the maximum number of bit errors that can be corrected in one ecc step. Nand infrastructure code translates this to 'ecc_strength'. Also for nand drivers, the nand infrastructure code sets ecc.strength for ecc modes NAND_ECC_SOFT, NAND_ECC_SOFT_BCH, and NAND_ECC_NONE. It is set in the driver for all other modes. Signed-off-by: Mike Dunn <mikedunn@newsguy.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/alauda.c1
-rw-r--r--drivers/mtd/nand/atmel_nand.c1
-rw-r--r--drivers/mtd/nand/bcm_umi_nand.c8
-rw-r--r--drivers/mtd/nand/bf5xx_nand.c2
-rw-r--r--drivers/mtd/nand/cafe_nand.c1
-rw-r--r--drivers/mtd/nand/cs553x_nand.c2
-rw-r--r--drivers/mtd/nand/davinci_nand.c1
-rw-r--r--drivers/mtd/nand/denali.c3
-rw-r--r--drivers/mtd/nand/diskonchip.c1
-rw-r--r--drivers/mtd/nand/docg4.c1
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c6
-rw-r--r--drivers/mtd/nand/fsmc_nand.c2
-rw-r--r--drivers/mtd/nand/jz4740_nand.c5
-rw-r--r--drivers/mtd/nand/mxc_nand.c7
-rw-r--r--drivers/mtd/nand/nand_base.c7
-rw-r--r--drivers/mtd/nand/ndfc.c1
-rw-r--r--drivers/mtd/nand/omap2.c1
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c1
-rw-r--r--drivers/mtd/nand/r852.c1
-rw-r--r--drivers/mtd/nand/rtc_from4.c1
-rw-r--r--drivers/mtd/nand/s3c2410.c1
-rw-r--r--drivers/mtd/nand/sh_flctl.c1
-rw-r--r--drivers/mtd/nand/sharpsl.c1
-rw-r--r--drivers/mtd/nand/tmio_nand.c1
-rw-r--r--drivers/mtd/nand/txx9ndfmc.c1
25 files changed, 57 insertions, 1 deletions
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c
index ac38f73fde3b..4f20e1d8bef1 100644
--- a/drivers/mtd/nand/alauda.c
+++ b/drivers/mtd/nand/alauda.c
@@ -591,6 +591,7 @@ static int alauda_init_media(struct alauda *al)
mtd->_block_isbad = alauda_isbad;
mtd->priv = al;
mtd->owner = THIS_MODULE;
+ mtd->ecc_strength = 1;
err = mtd_device_register(mtd, NULL, 0);
if (err) {
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 7769519a54a7..662abf08061a 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -554,6 +554,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
nand_chip->ecc.hwctl = atmel_nand_hwctl;
nand_chip->ecc.read_page = atmel_nand_read_page;
nand_chip->ecc.bytes = 4;
+ nand_chip->ecc.strength = 1;
}
nand_chip->chip_delay = 20; /* 20us command delay time */
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index ee81b6333f6a..fc600431f519 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -476,6 +476,14 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
largepage_bbt.options = NAND_BBT_SCAN2NDPAGE;
this->badblock_pattern = &largepage_bbt;
}
+
+ /*
+ * FIXME: ecc strength value of 6 bits per 512 bytes of data is a
+ * conservative guess, given 13 ecc bytes and using bch alg.
+ * (Assume Galois field order m=15 to allow a margin of error.)
+ */
+ this->ecc.strength = 6;
+
#endif
/* Now finish off the scan, now that ecc.layout has been initialized. */
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index dd899cb5d366..d7b86b925de5 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -702,9 +702,11 @@ static int bf5xx_nand_scan(struct mtd_info *mtd)
if (likely(mtd->writesize >= 512)) {
chip->ecc.size = 512;
chip->ecc.bytes = 6;
+ chip->ecc.strength = 2;
} else {
chip->ecc.size = 256;
chip->ecc.bytes = 3;
+ chip->ecc.strength = 1;
bfin_write_NFC_CTL(bfin_read_NFC_CTL() & ~(1 << NFC_PG_SIZE_OFFSET));
SSYNC();
}
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index c23c07c5b391..2a96e1a12062 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -783,6 +783,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
cafe->nand.ecc.size = mtd->writesize;
cafe->nand.ecc.bytes = 14;
+ cafe->nand.ecc.strength = 4;
cafe->nand.ecc.hwctl = (void *)cafe_nand_bug;
cafe->nand.ecc.calculate = (void *)cafe_nand_bug;
cafe->nand.ecc.correct = (void *)cafe_nand_bug;
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index e2b7c9e4c5c2..821c34c62500 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -248,6 +248,8 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
goto out_ior;
}
+ this->ecc.strength = 1;
+
new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs);
cs553x_mtd[cs] = new_mtd;
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index b81afc748fff..d94b03c207af 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -641,6 +641,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
info->chip.ecc.bytes = 3;
}
info->chip.ecc.size = 512;
+ info->chip.ecc.strength = pdata->ecc_bits;
break;
default:
ret = -EINVAL;
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 3984d488f9ab..a9e57d686297 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1590,6 +1590,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
ECC_15BITS * (denali->mtd.writesize /
ECC_SECTOR_SIZE)))) {
/* if MLC OOB size is large enough, use 15bit ECC*/
+ denali->nand.ecc.strength = 15;
denali->nand.ecc.layout = &nand_15bit_oob;
denali->nand.ecc.bytes = ECC_15BITS;
iowrite32(15, denali->flash_reg + ECC_CORRECTION);
@@ -1600,12 +1601,14 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
" contain 8bit ECC correction codes");
goto failed_req_irq;
} else {
+ denali->nand.ecc.strength = 8;
denali->nand.ecc.layout = &nand_8bit_oob;
denali->nand.ecc.bytes = ECC_8BITS;
iowrite32(8, denali->flash_reg + ECC_CORRECTION);
}
denali->nand.ecc.bytes *= denali->devnum;
+ denali->nand.ecc.strength *= denali->devnum;
denali->nand.ecc.layout->eccbytes *=
denali->mtd.writesize / ECC_SECTOR_SIZE;
denali->nand.ecc.layout->oobfree[0].offset =
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index df921e7a496c..e2ca067631cf 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1653,6 +1653,7 @@ static int __init doc_probe(unsigned long physadr)
nand->ecc.mode = NAND_ECC_HW_SYNDROME;
nand->ecc.size = 512;
nand->ecc.bytes = 6;
+ nand->ecc.strength = 2;
nand->bbt_options = NAND_BBT_USE_FLASH;
doc->physadr = physadr;
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index 9b3a64904668..b08202664543 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -1191,6 +1191,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
nand->ecc.size = DOCG4_PAGE_SIZE;
nand->ecc.prepad = 8;
nand->ecc.bytes = 8;
+ nand->ecc.strength = DOCG4_T;
nand->options =
NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE | NAND_NO_AUTOINCR;
nand->IO_ADDR_R = nand->IO_ADDR_W = doc->virtadr + DOC_IOSPACE_DATA;
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 7195ee6efe12..80b5264f0a32 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -813,6 +813,12 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
&fsl_elbc_oob_sp_eccm1 : &fsl_elbc_oob_sp_eccm0;
chip->ecc.size = 512;
chip->ecc.bytes = 3;
+ chip->ecc.strength = 1;
+ /*
+ * FIXME: can hardware ecc correct 4 bitflips if page size is
+ * 2k? Then does hardware report number of corrections for this
+ * case? If so, ecc_stats reporting needs to be fixed as well.
+ */
} else {
/* otherwise fall back to default software ECC */
chip->ecc.mode = NAND_ECC_SOFT;
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 341086c22e90..588e3733c3a4 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -863,10 +863,12 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand->ecc.calculate = fsmc_read_hwecc_ecc4;
nand->ecc.correct = fsmc_bch8_correct_data;
nand->ecc.bytes = 13;
+ nand->ecc.strength = 8;
} else {
nand->ecc.calculate = fsmc_read_hwecc_ecc1;
nand->ecc.correct = nand_correct_data;
nand->ecc.bytes = 3;
+ nand->ecc.strength = 1;
}
/*
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index cc50e35cdc3d..e4147e8acb7c 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -332,6 +332,11 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
chip->ecc.mode = NAND_ECC_HW_OOB_FIRST;
chip->ecc.size = 512;
chip->ecc.bytes = 9;
+ chip->ecc.strength = 2;
+ /*
+ * FIXME: ecc_strength value of 2 bits per 512 bytes of data is a
+ * conservative guess, given 9 ecc bytes and reed-solomon alg.
+ */
if (pdata)
chip->ecc.layout = pdata->ecc_layout;
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 3c4c0533191d..cc0678a967c1 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -1225,6 +1225,13 @@ static int __init mxcnd_probe(struct platform_device *pdev)
goto escan;
}
+ if (this->ecc.mode == NAND_ECC_HW) {
+ if (nfc_is_v1())
+ this->ecc.strength = 1;
+ else
+ this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
+ }
+
/* Register the partitions */
mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts,
pdata->nr_parts);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 1e907dc8638a..8008853756c9 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3350,6 +3350,7 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!chip->ecc.size)
chip->ecc.size = 256;
chip->ecc.bytes = 3;
+ chip->ecc.strength = 1;
break;
case NAND_ECC_SOFT_BCH:
@@ -3384,6 +3385,8 @@ int nand_scan_tail(struct mtd_info *mtd)
pr_warn("BCH ECC initialization failed!\n");
BUG();
}
+ chip->ecc.strength =
+ chip->ecc.bytes*8 / fls(8*chip->ecc.size);
break;
case NAND_ECC_NONE:
@@ -3397,6 +3400,7 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->ecc.write_oob = nand_write_oob_std;
chip->ecc.size = mtd->writesize;
chip->ecc.bytes = 0;
+ chip->ecc.strength = 0;
break;
default:
@@ -3478,8 +3482,9 @@ int nand_scan_tail(struct mtd_info *mtd)
mtd->_block_markbad = nand_block_markbad;
mtd->writebufsize = mtd->writesize;
- /* propagate ecc.layout to mtd_info */
+ /* propagate ecc info to mtd_info */
mtd->ecclayout = chip->ecc.layout;
+ mtd->ecc_strength = chip->ecc.strength * chip->ecc.steps;
/* Check, if we should skip the bad block table scan */
if (chip->options & NAND_SKIP_BBTSCAN)
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index ec688548c880..2b6f632cf274 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -179,6 +179,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = 256;
chip->ecc.bytes = 3;
+ chip->ecc.strength = 1;
chip->priv = ndfc;
ndfc->mtd.priv = chip;
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index d2e7a7da81f8..c2b0bba9d8b3 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1058,6 +1058,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
(pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) {
info->nand.ecc.bytes = 3;
info->nand.ecc.size = 512;
+ info->nand.ecc.strength = 1;
info->nand.ecc.calculate = omap_calculate_ecc;
info->nand.ecc.hwctl = omap_enable_hwecc;
info->nand.ecc.correct = omap_correct_data;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index d3bdc909c939..def50caa6f84 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1002,6 +1002,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
KEEP_CONFIG:
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = host->page_size;
+ chip->ecc.strength = 1;
chip->options = NAND_NO_AUTOINCR;
chip->options |= NAND_NO_READRDY;
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 769a4e096b3c..c2040187c813 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -891,6 +891,7 @@ int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
chip->ecc.mode = NAND_ECC_HW_SYNDROME;
chip->ecc.size = R852_DMA_LEN;
chip->ecc.bytes = SM_OOB_SIZE;
+ chip->ecc.strength = 2;
chip->ecc.hwctl = r852_ecc_hwctl;
chip->ecc.calculate = r852_ecc_calculate;
chip->ecc.correct = r852_ecc_correct;
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index f309addc2fa0..e55b5cfbe145 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -527,6 +527,7 @@ static int __init rtc_from4_init(void)
this->ecc.mode = NAND_ECC_HW_SYNDROME;
this->ecc.size = 512;
this->ecc.bytes = 8;
+ this->ecc.strength = 3;
/* 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 */
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 97623be04e0f..91121f33f743 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -823,6 +823,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
chip->ecc.calculate = s3c2410_nand_calculate_ecc;
chip->ecc.correct = s3c2410_nand_correct_data;
chip->ecc.mode = NAND_ECC_HW;
+ chip->ecc.strength = 1;
switch (info->cpu_type) {
case TYPE_S3C2410:
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 2ee9a1b50a22..e9b2b260de3a 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -825,6 +825,7 @@ static int flctl_chip_init_tail(struct mtd_info *mtd)
chip->ecc.size = 512;
chip->ecc.bytes = 10;
+ chip->ecc.strength = 4;
chip->ecc.read_page = flctl_read_page_hwecc;
chip->ecc.write_page = flctl_write_page_hwecc;
chip->ecc.mode = NAND_ECC_HW;
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 2d269a53f8bb..3421e3762a5a 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -167,6 +167,7 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
this->ecc.mode = NAND_ECC_HW;
this->ecc.size = 256;
this->ecc.bytes = 3;
+ this->ecc.strength = 1;
this->badblock_pattern = data->badblock_pattern;
this->ecc.layout = data->ecc_layout;
this->ecc.hwctl = sharpsl_nand_enable_hwecc;
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index 060848a91db7..5aa518081c51 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -430,6 +430,7 @@ static int tmio_probe(struct platform_device *dev)
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.size = 512;
nand_chip->ecc.bytes = 6;
+ nand_chip->ecc.strength = 2;
nand_chip->ecc.hwctl = tmio_nand_enable_hwecc;
nand_chip->ecc.calculate = tmio_nand_calculate_ecc;
nand_chip->ecc.correct = tmio_nand_correct_data;
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 8db0acbae6fa..26398dcf21cf 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -356,6 +356,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
/* txx9ndfmc_nand_scan will overwrite ecc.size and ecc.bytes */
chip->ecc.size = 256;
chip->ecc.bytes = 3;
+ chip->ecc.strength = 1;
chip->chip_delay = 100;
chip->controller = &drvdata->hw_control;