nand: omap2: Add support for flash-based bad block table
authorEzequiel García <ezequiel@vanguardiasur.com.ar>
Thu, 11 Sep 2014 15:02:08 +0000 (12:02 -0300)
committerBrian Norris <computersforpeace@gmail.com>
Wed, 17 Sep 2014 08:02:48 +0000 (01:02 -0700)
This commit adds a new platform-data boolean property that enables use
of a flash-based bad block table. This can also be enabled by setting
the 'nand-on-flash-bbt' devicetree property.

If the flash BBT is not enabled, the driver falls back to use OOB
bad block markers only, as before. If the flash BBT is enabled the
kernel will keep track of bad blocks using a BBT, in addition to
the OOB markers.

As explained by Brian Norris the reasons for using a BBT are:

""
The primary reason would be that NAND datasheets specify it these days.
A better argument is that nobody guarantees that you can write a
bad block marker to a worn out block; you may just get program failures.

This has been acknowledged by several developers over the last several
years.

Additionally, you get a boot-time performance improvement if you only
have to read a few pages, instead of a page or two from every block on
the flash.
""

Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Acked-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
arch/arm/mach-omap2/gpmc.c
drivers/mtd/nand/omap2.c
include/linux/platform_data/mtd-nand-omap2.h

index 2f97228f188aa3a835146d81bb7bffc2edcb039d..b55a225387cde934bd793c09eefcac6a602fd17f 100644 (file)
@@ -1440,6 +1440,8 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
                                break;
                        }
 
+       gpmc_nand_data->flash_bbt = of_get_nand_on_flash_bbt(child);
+
        val = of_get_nand_bus_width(child);
        if (val == 16)
                gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
index 5967b385141b7f49bc669beda18ac69fbd7e06d0..e1a9b310c1596d33ba89a580a6ee4956891e27a5 100644 (file)
@@ -1663,7 +1663,6 @@ static int omap_nand_probe(struct platform_device *pdev)
        mtd->owner              = THIS_MODULE;
        nand_chip               = &info->nand;
        nand_chip->ecc.priv     = NULL;
-       nand_chip->options      |= NAND_SKIP_BBTSCAN;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
@@ -1692,6 +1691,11 @@ static int omap_nand_probe(struct platform_device *pdev)
                nand_chip->chip_delay = 50;
        }
 
+       if (pdata->flash_bbt)
+               nand_chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
+       else
+               nand_chip->options |= NAND_SKIP_BBTSCAN;
+
        /* scan NAND device connected to chip controller */
        nand_chip->options |= pdata->devsize & NAND_BUSWIDTH_16;
        if (nand_scan_ident(mtd, 1, NULL)) {
index 16ec262dfcc804a567910dad83bb3edbe72bdc74..090bbab0130a3d31b226b8fce8b50f9f6b231be9 100644 (file)
@@ -71,6 +71,7 @@ struct omap_nand_platform_data {
        struct mtd_partition    *parts;
        int                     nr_parts;
        bool                    dev_ready;
+       bool                    flash_bbt;
        enum nand_io            xfer_type;
        int                     devsize;
        enum omap_ecc           ecc_opt;