]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mtd: rawnand: use wrappers to call onfi GET/SET_FEATURES
authorMiquel Raynal <miquel.raynal@bootlin.com>
Mon, 19 Mar 2018 13:47:20 +0000 (14:47 +0100)
committerBoris Brezillon <boris.brezillon@bootlin.com>
Tue, 20 Mar 2018 08:46:02 +0000 (09:46 +0100)
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>
drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/raw/nand_base.c
drivers/mtd/nand/raw/nand_micron.c
include/linux/mtd/rawnand.h

index f78d907ca61ea00874e91234b352d4d2b44cddd6..039f2795617f03f0a6441d5ee84d9c4eb88a5c3c 100644 (file)
@@ -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;
 
index 802cd9ed44a1af16bc8efb098a4323fa3744fd34..d344dcb1262023ecb5686daf013b6bd9195e1e5f 100644 (file)
@@ -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);
 }
 
index ab3e3a1a5212b3a292a148c4a7d71f2a436bcfc1..b825656f628453bbc1869f63c444372519e25e27 100644 (file)
@@ -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;
 
index fb2e288ef8b121e1db1d1dadcfb3ede981b4a4b6..3cc2a3435b2097ec59d547becdec022a3355f7b6 100644 (file)
@@ -1629,6 +1629,9 @@ int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page);
 int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
                           int page);
 
+/* Wrapper to use in order for controllers/vendors to GET/SET FEATURES */
+int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
+int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param);
 /* Stub used by drivers that do not support GET/SET FEATURES operations */
 int nand_get_set_features_notsupp(struct mtd_info *mtd, struct nand_chip *chip,
                                  int addr, u8 *subfeature_param);