diff options
-rw-r--r-- | drivers/mtd/nand/raw/nand_base.c | 26 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/nand_micron.c | 4 | ||||
-rw-r--r-- | include/linux/mtd/rawnand.h | 8 |
3 files changed, 30 insertions, 8 deletions
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 789c11e0925e..0bd9f22973e9 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1160,9 +1160,16 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) return status; } -static bool nand_supports_set_get_features(struct nand_chip *chip) +static bool nand_supports_get_features(struct nand_chip *chip, int addr) { - return chip->parameters.supports_set_get_features; + return (chip->parameters.supports_set_get_features && + test_bit(addr, chip->parameters.get_feature_list)); +} + +static bool nand_supports_set_features(struct nand_chip *chip, int addr) +{ + return (chip->parameters.supports_set_get_features && + test_bit(addr, chip->parameters.set_feature_list)); } /** @@ -1179,7 +1186,7 @@ int nand_get_features(struct nand_chip *chip, int addr, { struct mtd_info *mtd = nand_to_mtd(chip); - if (!nand_supports_set_get_features(chip)) + if (!nand_supports_get_features(chip, addr)) return -ENOTSUPP; return chip->get_features(mtd, chip, addr, subfeature_param); @@ -1200,7 +1207,7 @@ int nand_set_features(struct nand_chip *chip, int addr, { struct mtd_info *mtd = nand_to_mtd(chip); - if (!nand_supports_set_get_features(chip)) + if (!nand_supports_set_features(chip, addr)) return -ENOTSUPP; return chip->set_features(mtd, chip, addr, subfeature_param); @@ -1271,7 +1278,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) return 0; /* Change the mode on the chip side (if supported by the NAND chip) */ - if (nand_supports_set_get_features(chip)) { + if (nand_supports_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE)) { chip->select_chip(mtd, chipnr); ret = nand_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE, tmode_param); @@ -1286,7 +1293,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) return ret; /* Check the mode has been accepted by the chip, if supported */ - if (!nand_supports_set_get_features(chip)) + if (!nand_supports_get_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE)) return 0; memset(tmode_param, 0, ONFI_SUBFEATURE_PARAM_LEN); @@ -5192,8 +5199,13 @@ static int nand_flash_detect_onfi(struct nand_chip *chip) } /* Save some parameters from the parameter page for future use */ - if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES) + if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES) { chip->parameters.supports_set_get_features = true; + bitmap_set(chip->parameters.get_feature_list, + ONFI_FEATURE_ADDR_TIMING_MODE, 1); + bitmap_set(chip->parameters.set_feature_list, + ONFI_FEATURE_ADDR_TIMING_MODE, 1); + } chip->parameters.onfi.tPROG = le16_to_cpu(p->t_prog); chip->parameters.onfi.tBERS = le16_to_cpu(p->t_bers); chip->parameters.onfi.tR = le16_to_cpu(p->t_r); diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c index c5974d8313e7..0af45b134c0c 100644 --- a/drivers/mtd/nand/raw/nand_micron.c +++ b/drivers/mtd/nand/raw/nand_micron.c @@ -64,6 +64,10 @@ static int micron_nand_onfi_init(struct nand_chip *chip) chip->setup_read_retry = micron_nand_setup_read_retry; } + if (p->supports_set_get_features) { + set_bit(ONFI_FEATURE_ADDR_READ_RETRY, p->set_feature_list); + set_bit(ONFI_FEATURE_ADDR_READ_RETRY, p->get_feature_list); + } return 0; } diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 7b5afa6ef5a9..d9f417719d36 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -21,6 +21,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/flashchip.h> #include <linux/mtd/bbm.h> +#include <linux/types.h> struct mtd_info; struct nand_flash_dev; @@ -235,7 +236,8 @@ struct nand_chip; #define ONFI_TIMING_MODE_5 (1 << 5) #define ONFI_TIMING_MODE_UNKNOWN (1 << 6) -/* ONFI feature address */ +/* ONFI feature number/address */ +#define ONFI_FEATURE_NUMBER 256 #define ONFI_FEATURE_ADDR_TIMING_MODE 0x1 /* Vendor-specific feature address (Micron) */ @@ -455,12 +457,16 @@ struct onfi_params { * struct nand_parameters - NAND generic parameters from the parameter page * @model: Model name * @supports_set_get_features: The NAND chip supports setting/getting features + * @set_feature_list: Bitmap of features that can be set + * @get_feature_list: Bitmap of features that can be get * @onfi: ONFI specific parameters */ struct nand_parameters { /* Generic parameters */ char model[100]; bool supports_set_get_features; + DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER); + DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER); /* ONFI parameters */ struct onfi_params onfi; |