diff options
author | Lily Zhang <r58066@freescale.com> | 2010-10-11 18:19:58 +0800 |
---|---|---|
committer | Scott Sweeny <scott.sweeny@timesys.com> | 2011-01-19 11:49:57 -0500 |
commit | 29b2f7aa5a03cb37361c735621087e88026f3048 (patch) | |
tree | 22ae22bd39474e0856d2697622c5cb6e8ffae147 /drivers/mtd | |
parent | beed8afb54af80eb983349622c2c045a55d7c0c2 (diff) |
ENGR00132430-2 mxc nand: add "ignore bad block" support
Add ignore_badblock support for mxc nand flash driver.
The usage is like:
echo 1 > /sys/devices/platform/mxc_nandv2_flash.0/ignorebad
Then nand flash operations will not check bad block marker
and conduct nand flash operations for all blocks.
The default value is 0 which means bad block marker will be
checked for nand operations.
Signed-off-by: Lily Zhang <r58066@freescale.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/mxc_nd2.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/drivers/mtd/nand/mxc_nd2.c b/drivers/mtd/nand/mxc_nd2.c index 18213448abf8..8d5c2866d8f9 100644 --- a/drivers/mtd/nand/mxc_nd2.c +++ b/drivers/mtd/nand/mxc_nd2.c @@ -40,6 +40,9 @@ struct mxc_mtd_s { struct mtd_partition *parts; struct device *dev; int disable_bi_swap; /* disable bi swap */ + int ignore_bad_block; /* ignore bad block marker */ + void *saved_bbt; + int (*saved_block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); int clk_active; }; @@ -1076,6 +1079,30 @@ static void mxc_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, } +/*! + * mxc_nand_block_bad - Claims all blocks are good + * In principle, this function is *only* called when the NAND Flash MTD system + * isn't allowed to keep an in-memory bad block table, so it is forced to ask + * the driver for bad block information. + * + * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so + * this function is *only* called when we take it away. + * + * We take away the in-memory BBT when the user sets the "ignorebad" parameter, + * which indicates that all blocks should be reported good. + * + * Thus, this function is only called when we want *all* blocks to look good, + * so it *always* return success. + * + * @mtd: Ignored. + * @ofs: Ignored. + * @getchip: Ignored. + */ +static int mxc_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +{ + return 0; +} + /* Define some generic bad / good block scan pattern which are used * while scanning a device for factory marked good / bad blocks. */ static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; @@ -1364,8 +1391,85 @@ static ssize_t store_device_disable_bi_swap(struct device *dev, static DEVICE_ATTR(disable_bi_swap, 0644, show_device_disable_bi_swap, store_device_disable_bi_swap); + +/*! + * show_device_ignorebad() + * Shows the value of the 'ignore_bad_block' flag. + * + * @dev: The device of interest. + * @attr: The attribute of interest. + * @buf: A buffer that will receive a representation of the attribute. + */ +static ssize_t show_device_ignorebad(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", mxc_nand_data->ignore_bad_block); +} + +/*! + * store_device_ignorebad() + * Sets the value of the 'ignore_bad_block' flag. + * + * @dev: The device of interest. + * @attr: The attribute of interest. + * @buf: A buffer containing a new attribute value. + * @size: The size of the buffer. + */ +static ssize_t store_device_ignorebad(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + const char *p = buf; + unsigned long v; + + /* Try to make sense of what arrived from user space. */ + + if (strict_strtoul(p, 0, &v) < 0) + return size; + + if (v > 0) + v = 1; + + /* Only do something if the value is changing. */ + if (v != mxc_nand_data->ignore_bad_block) { + if (v) { + /* + * If control arrives here, we want to begin ignoring + * bad block marks. Reach into the NAND Flash MTD data + * structures and set the in-memory BBT pointer to NULL. + * This will cause the NAND Flash MTD code to believe + * that it never created a BBT and force it to call our + * block_bad function. + */ + mxc_nand_data->saved_bbt = mxc_nand_data->nand.bbt; + mxc_nand_data->nand.bbt = 0; + mxc_nand_data->saved_block_bad = + mxc_nand_data->nand.block_bad; + mxc_nand_data->nand.block_bad = + mxc_nand_block_bad; + } else { + /* + * If control arrives here, we want to stop ignoring + * bad block marks. Restore the NAND Flash MTD's pointer + * to its in-memory BBT. + */ + mxc_nand_data->nand.bbt = mxc_nand_data->saved_bbt; + mxc_nand_data->nand.block_bad = + mxc_nand_data->saved_block_bad; + } + mxc_nand_data->ignore_bad_block = v; + } + + return size; + +} + +static DEVICE_ATTR(ignorebad, 0644, + show_device_ignorebad, store_device_ignorebad); + + static struct device_attribute *device_attributes[] = { &dev_attr_disable_bi_swap, + &dev_attr_ignorebad, }; /*! * manage_sysfs_files() - Creates/removes sysfs files for this device. |