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));
}
/**
{
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);
{
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);
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);
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);
}
/* 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);
#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;
#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) */
* 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;