aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/nand/raw/nand_base.c26
-rw-r--r--drivers/mtd/nand/raw/nand_micron.c4
-rw-r--r--include/linux/mtd/rawnand.h8
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;