Commit fef775ca authored by Ezequiel García's avatar Ezequiel García Committed by Brian Norris

nand: omap2: Add support for flash-based bad block table

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: default avatarEzequiel Garcia <ezequiel@vanguardiasur.com.ar>
Acked-by: default avatarRoger Quadros <rogerq@ti.com>
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
parent 2d405ec5
...@@ -1440,6 +1440,8 @@ static int gpmc_probe_nand_child(struct platform_device *pdev, ...@@ -1440,6 +1440,8 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
break; break;
} }
gpmc_nand_data->flash_bbt = of_get_nand_on_flash_bbt(child);
val = of_get_nand_bus_width(child); val = of_get_nand_bus_width(child);
if (val == 16) if (val == 16)
gpmc_nand_data->devsize = NAND_BUSWIDTH_16; gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
......
...@@ -1663,7 +1663,6 @@ static int omap_nand_probe(struct platform_device *pdev) ...@@ -1663,7 +1663,6 @@ static int omap_nand_probe(struct platform_device *pdev)
mtd->owner = THIS_MODULE; mtd->owner = THIS_MODULE;
nand_chip = &info->nand; nand_chip = &info->nand;
nand_chip->ecc.priv = NULL; nand_chip->ecc.priv = NULL;
nand_chip->options |= NAND_SKIP_BBTSCAN;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
...@@ -1692,6 +1691,11 @@ static int omap_nand_probe(struct platform_device *pdev) ...@@ -1692,6 +1691,11 @@ static int omap_nand_probe(struct platform_device *pdev)
nand_chip->chip_delay = 50; 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 */ /* scan NAND device connected to chip controller */
nand_chip->options |= pdata->devsize & NAND_BUSWIDTH_16; nand_chip->options |= pdata->devsize & NAND_BUSWIDTH_16;
if (nand_scan_ident(mtd, 1, NULL)) { if (nand_scan_ident(mtd, 1, NULL)) {
......
...@@ -71,6 +71,7 @@ struct omap_nand_platform_data { ...@@ -71,6 +71,7 @@ struct omap_nand_platform_data {
struct mtd_partition *parts; struct mtd_partition *parts;
int nr_parts; int nr_parts;
bool dev_ready; bool dev_ready;
bool flash_bbt;
enum nand_io xfer_type; enum nand_io xfer_type;
int devsize; int devsize;
enum omap_ecc ecc_opt; enum omap_ecc ecc_opt;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment