summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMiquel Raynal <miquel.raynal@bootlin.com>2018-03-19 14:47:20 +0100
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-03-20 09:46:02 +0100
commit97baea1e6b74c73973fa0922252f880ab15450ea (patch)
tree45bf059e4fcf9ba28672b9c175d0a9417de7230e /drivers
parentb958758e686aebe84672acc8871aca87d04f13a3 (diff)
downloadlinux-stable-97baea1e6b74c73973fa0922252f880ab15450ea.tar.gz
linux-stable-97baea1e6b74c73973fa0922252f880ab15450ea.tar.bz2
linux-stable-97baea1e6b74c73973fa0922252f880ab15450ea.zip
mtd: rawnand: use wrappers to call onfi GET/SET_FEATURES
Prepare the fact that some features managed by GET/SET_FEATURES could be overloaded by vendor code. To handle this logic, use new wrappers instead of directly call the ->get/set_features() hooks. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c6
-rw-r--r--drivers/mtd/nand/raw/nand_base.c89
-rw-r--r--drivers/mtd/nand/raw/nand_micron.c18
3 files changed, 71 insertions, 42 deletions
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
index f78d907ca61e..039f2795617f 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
@@ -934,15 +934,13 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
/* [1] send SET FEATURE command to NAND */
feature[0] = mode;
- ret = nand->set_features(mtd, nand,
- ONFI_FEATURE_ADDR_TIMING_MODE, feature);
+ ret = nand_set_features(nand, ONFI_FEATURE_ADDR_TIMING_MODE, feature);
if (ret)
goto err_out;
/* [2] send GET FEATURE command to double-check the timing mode */
memset(feature, 0, ONFI_SUBFEATURE_PARAM_LEN);
- ret = nand->get_features(mtd, nand,
- ONFI_FEATURE_ADDR_TIMING_MODE, feature);
+ ret = nand_get_features(nand, ONFI_FEATURE_ADDR_TIMING_MODE, feature);
if (ret || feature[0] != mode)
goto err_out;
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 802cd9ed44a1..d344dcb12620 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -1160,6 +1160,55 @@ 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)
+{
+ return (chip->onfi_version &&
+ (le16_to_cpu(chip->onfi_params.opt_cmd) &
+ ONFI_OPT_CMD_SET_GET_FEATURES));
+}
+
+/**
+ * nand_get_features - wrapper to perform a GET_FEATURE
+ * @chip: NAND chip info structure
+ * @addr: feature address
+ * @subfeature_param: the subfeature parameters, a four bytes array
+ *
+ * Returns 0 for success, a negative error otherwise. Returns -ENOTSUPP if the
+ * operation cannot be handled.
+ */
+int nand_get_features(struct nand_chip *chip, int addr,
+ u8 *subfeature_param)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+
+ if (!nand_supports_set_get_features(chip))
+ return -ENOTSUPP;
+
+ return chip->get_features(mtd, chip, addr, subfeature_param);
+}
+EXPORT_SYMBOL_GPL(nand_get_features);
+
+/**
+ * nand_set_features - wrapper to perform a SET_FEATURE
+ * @chip: NAND chip info structure
+ * @addr: feature address
+ * @subfeature_param: the subfeature parameters, a four bytes array
+ *
+ * Returns 0 for success, a negative error otherwise. Returns -ENOTSUPP if the
+ * operation cannot be handled.
+ */
+int nand_set_features(struct nand_chip *chip, int addr,
+ u8 *subfeature_param)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+
+ if (!nand_supports_set_get_features(chip))
+ return -ENOTSUPP;
+
+ return chip->set_features(mtd, chip, addr, subfeature_param);
+}
+EXPORT_SYMBOL_GPL(nand_set_features);
+
/**
* nand_reset_data_interface - Reset data interface and timings
* @chip: The NAND chip
@@ -1215,32 +1264,22 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
{
struct mtd_info *mtd = nand_to_mtd(chip);
+ u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
+ chip->onfi_timing_mode_default,
+ };
int ret;
if (!chip->setup_data_interface)
return 0;
- /*
- * Ensure the timing mode has been changed on the chip side
- * before changing timings on the controller side.
- */
- if (chip->onfi_version &&
- (le16_to_cpu(chip->onfi_params.opt_cmd) &
- ONFI_OPT_CMD_SET_GET_FEATURES)) {
- u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
- chip->onfi_timing_mode_default,
- };
-
- ret = chip->set_features(mtd, chip,
- ONFI_FEATURE_ADDR_TIMING_MODE,
- tmode_param);
- if (ret)
- goto err;
- }
+ /* Change the mode on the chip side */
+ ret = nand_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE,
+ tmode_param);
+ if (ret)
+ return ret;
- ret = chip->setup_data_interface(mtd, chipnr, &chip->data_interface);
-err:
- return ret;
+ /* Change the mode on the controller side */
+ return chip->setup_data_interface(mtd, chipnr, &chip->data_interface);
}
/**
@@ -4779,11 +4818,6 @@ static int nand_default_set_features(struct mtd_info *mtd,
struct nand_chip *chip, int addr,
uint8_t *subfeature_param)
{
- if (!chip->onfi_version ||
- !(le16_to_cpu(chip->onfi_params.opt_cmd)
- & ONFI_OPT_CMD_SET_GET_FEATURES))
- return -EINVAL;
-
return nand_set_features_op(chip, addr, subfeature_param);
}
@@ -4798,11 +4832,6 @@ static int nand_default_get_features(struct mtd_info *mtd,
struct nand_chip *chip, int addr,
uint8_t *subfeature_param)
{
- if (!chip->onfi_version ||
- !(le16_to_cpu(chip->onfi_params.opt_cmd)
- & ONFI_OPT_CMD_SET_GET_FEATURES))
- return -EINVAL;
-
return nand_get_features_op(chip, addr, subfeature_param);
}
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index ab3e3a1a5212..b825656f6284 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -48,8 +48,7 @@ static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
struct nand_chip *chip = mtd_to_nand(mtd);
u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
- return chip->set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
- feature);
+ return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
}
/*
@@ -108,8 +107,7 @@ static int micron_nand_on_die_ecc_setup(struct nand_chip *chip, bool enable)
if (enable)
feature[0] |= ONFI_FEATURE_ON_DIE_ECC_EN;
- return chip->set_features(nand_to_mtd(chip), chip,
- ONFI_FEATURE_ON_DIE_ECC, feature);
+ return nand_set_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
}
static int
@@ -219,8 +217,10 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
if (ret)
return MICRON_ON_DIE_UNSUPPORTED;
- chip->get_features(nand_to_mtd(chip), chip,
- ONFI_FEATURE_ON_DIE_ECC, feature);
+ ret = nand_get_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
+ if (ret < 0)
+ return ret;
+
if ((feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN) == 0)
return MICRON_ON_DIE_UNSUPPORTED;
@@ -228,8 +228,10 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
if (ret)
return MICRON_ON_DIE_UNSUPPORTED;
- chip->get_features(nand_to_mtd(chip), chip,
- ONFI_FEATURE_ON_DIE_ECC, feature);
+ ret = nand_get_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature);
+ if (ret < 0)
+ return ret;
+
if (feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN)
return MICRON_ON_DIE_MANDATORY;