mtd: flash drivers set ecc strength
authorMike Dunn <mikedunn@newsguy.com>
Sun, 11 Mar 2012 21:21:11 +0000 (14:21 -0700)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Mon, 26 Mar 2012 23:56:46 +0000 (00:56 +0100)
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>
31 files changed:
drivers/mtd/devices/doc2000.c
drivers/mtd/devices/doc2001.c
drivers/mtd/devices/doc2001plus.c
drivers/mtd/devices/docg3.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/alauda.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/bcm_umi_nand.c
drivers/mtd/nand/bf5xx_nand.c
drivers/mtd/nand/cafe_nand.c
drivers/mtd/nand/cs553x_nand.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/nand/denali.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/docg4.c
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsmc_nand.c
drivers/mtd/nand/jz4740_nand.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/ndfc.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/r852.c
drivers/mtd/nand/rtc_from4.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/nand/sharpsl.c
drivers/mtd/nand/tmio_nand.c
drivers/mtd/nand/txx9ndfmc.c
drivers/mtd/onenand/onenand_base.c

index 7ad7b054800cdc5a6676e0b67caf2058605b617c..a4eb8b5b85ecb9b7db0c253622fc97720022f4f1 100644 (file)
@@ -564,6 +564,7 @@ void DoC2k_init(struct mtd_info *mtd)
        mtd->flags = MTD_CAP_NANDFLASH;
        mtd->writebufsize = mtd->writesize = 512;
        mtd->oobsize = 16;
+       mtd->ecc_strength = 2;
        mtd->owner = THIS_MODULE;
        mtd->_erase = doc_erase;
        mtd->_read = doc_read;
index 7bff54e62cd563663671c46c21151c159f522a54..f6927955dab0d108385f853b5f6499a19961d333 100644 (file)
@@ -348,6 +348,7 @@ void DoCMil_init(struct mtd_info *mtd)
        mtd->erasesize = 0x2000;
        mtd->writebufsize = mtd->writesize = 512;
        mtd->oobsize = 16;
+       mtd->ecc_strength = 2;
        mtd->owner = THIS_MODULE;
        mtd->_erase = doc_erase;
        mtd->_read = doc_read;
index 4a03d869ad03b42ca8425d37e438e8fbfd858486..04eb2e4aa50f1bdfd0aaae18de0b8700aef00483 100644 (file)
@@ -469,6 +469,7 @@ void DoCMilPlus_init(struct mtd_info *mtd)
        mtd->flags = MTD_CAP_NANDFLASH;
        mtd->writebufsize = mtd->writesize = 512;
        mtd->oobsize = 16;
+       mtd->ecc_strength = 2;
        mtd->owner = THIS_MODULE;
        mtd->_erase = doc_erase;
        mtd->_read = doc_read;
index 2c1d0fca675770fcb3d560765b5c635f30f395d2..349bbfa74d0dcb366ac0bfe120a93379db34657e 100644 (file)
@@ -1832,6 +1832,7 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
        mtd->_write_oob = doc_write_oob;
        mtd->_block_isbad = doc_block_isbad;
        mtd->ecclayout = &docg3_oobinfo;
+       mtd->ecc_strength = DOC_ECC_BCH_T;
 }
 
 /**
index 226d28a618d8de69e4d6575f17e6925e6b9dceaa..9651c06de0a9298f4db58265524ecaebe2c2b9b4 100644 (file)
@@ -516,6 +516,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
        }
 
        slave->mtd.ecclayout = master->ecclayout;
+       slave->mtd.ecc_strength = master->ecc_strength;
        if (master->_block_isbad) {
                uint64_t offs = 0;
 
index ac38f73fde3b8d87caeb2fc1519e1febf150d324..4f20e1d8bef10b43546bd64d51933c0ed010093d 100644 (file)
@@ -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) {
index 7769519a54a7036ceeddff614f4db7d09f22ed8f..662abf08061af34e712261b8207e2e08d6fa35f5 100644 (file)
@@ -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 */
index ee81b6333f6a51b7a42e499131386b16b33eea59..fc600431f519416f5eb44b021b8ad055e0f3706e 100644 (file)
@@ -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. */
index dd899cb5d366e4de044ec16129000bb99c6fcc58..d7b86b925de5ead4b4c0653bf13080bea55a4156 100644 (file)
@@ -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();
                }
index c23c07c5b3910428782e64db57312dfe93ce80ee..2a96e1a12062314234f2cd74b86163029abc3e3d 100644 (file)
@@ -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;
index e2b7c9e4c5c2cb677b670cca433324919d79d8a3..821c34c6250021246dfdb7ef97a44e497a05726c 100644 (file)
@@ -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;
index b81afc748fff90acdfd919fbed8ec2c4d0b9d864..d94b03c207af904f05b966783725d194b4d8b412 100644 (file)
@@ -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;
index 3984d488f9abbf5a3d6ed77fd49e2c4b7dc79381..a9e57d686297096e0700935a90d6a5257aa789ff 100644 (file)
@@ -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 =
index df921e7a496cb57dd2f27be1225fdd62fe52dfe6..e2ca067631cf118704c107e2bffbe4ab515abda8 100644 (file)
@@ -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;
index 9b3a64904668f471e8c997de2cdf1f074b3d3f5e..b08202664543200553255f89c00669e203783d14 100644 (file)
@@ -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;
index 7195ee6efe12293df9e92302959dbe786b3f80bd..80b5264f0a32f031a10f5b50e50987a1184646e1 100644 (file)
@@ -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;
index 341086c22e90587384a5d76325bef6b2e4d1c1f6..588e3733c3a43883fe8bb4a8fcc3a623f2aabdff 100644 (file)
@@ -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;
        }
 
        /*
index cc50e35cdc3d664f6d6ff20b25eeac65399ff2e0..e4147e8acb7c560f2a8c3fdae68bf1027266fdba 100644 (file)
@@ -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;
index 3c4c0533191d5e59c7546f81f2465719e8b4ee99..cc0678a967c12c6b054d21ee3fe5b868ee997924 100644 (file)
@@ -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);
index 1e907dc8638ac0e497e45b07ce2aba0fde83a12f..8008853756c99a1a552dff2c7425c8cc24c1edec 100644 (file)
@@ -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)
index ec688548c880ef67d1cf568e6f568c678099232f..2b6f632cf27429ff691c7007a8a842689a8878d4 100644 (file)
@@ -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;
index d2e7a7da81f87e252697456644681d92c7315c14..c2b0bba9d8b39607626f091d398a3fccfa8687c4 100644 (file)
@@ -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;
index d3bdc909c9390dd7da8bab6cc7e6804b21de49e2..def50caa6f84b259fd5ed23e702efcd5977317cb 100644 (file)
@@ -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;
index 769a4e096b3c6b8fc3ef036148bf78a609f289a1..c2040187c813e0084e6dc7da8441c675bbe6cc3e 100644 (file)
@@ -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;
index f309addc2fa0505137f83a7a389bcb74b4fff9e6..e55b5cfbe1457d1300524602ec00c11aecb78e3b 100644 (file)
@@ -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 */
index 97623be04e0f323066673058905dd8f683730fdb..91121f33f743a304213512edfe96d364dd0c0404 100644 (file)
@@ -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:
index 2ee9a1b50a221b782a678edc3531e69737fdf470..e9b2b260de3ae081bbeb2e04bbff4d61902003b3 100644 (file)
@@ -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;
index 2d269a53f8bbb72385617fe8ee6704a656561ed1..3421e3762a5a1ceda275b76f56386b29929d7b44 100644 (file)
@@ -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;
index 060848a91db706d0804278f5c84978bf01b2a5d4..5aa518081c513454e0fedb70f907cdeffcbaecd2 100644 (file)
@@ -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;
index 8db0acbae6fa8507c82201c0599ec44c827d28ce..26398dcf21cfdccb606c923a7e0d96eefbd370de 100644 (file)
@@ -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;
 
index a1592cf755f379638b5143206065d76c988f1f64..3d781b87b35869c95c5f8d7af41140eae14d5547 100644 (file)
@@ -4080,6 +4080,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
        mtd->oobavail = this->ecclayout->oobavail;
 
        mtd->ecclayout = this->ecclayout;
+       mtd->ecc_strength = 1;
 
        /* Fill in remaining MTD driver data */
        mtd->type = ONENAND_IS_MLC(this) ? MTD_MLCNANDFLASH : MTD_NANDFLASH;