mtd: nand: Pass the CS line to ->setup_data_interface()
authorBoris Brezillon <boris.brezillon@free-electrons.com>
Thu, 16 Mar 2017 08:35:58 +0000 (09:35 +0100)
committerBoris Brezillon <boris.brezillon@free-electrons.com>
Thu, 1 Jun 2017 08:09:28 +0000 (10:09 +0200)
Some NAND controllers can assign different NAND timings to different
CS lines. Pass the CS line information to ->setup_data_interface() so
that the NAND controller driver knows which CS line is concerned by
the setup_data_interface() request.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
drivers/mtd/nand/fsmc_nand.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sunxi_nand.c
drivers/mtd/nand/tango_nand.c
include/linux/mtd/nand.h

index de57554b8c4f18e8d720b6eabfb332ffa7e774b8..9d8b051d318709d454bf5ad832cd13243eb735e7 100644 (file)
@@ -388,9 +388,8 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
        return 0;
 }
 
-static int fsmc_setup_data_interface(struct mtd_info *mtd,
-                                    const struct nand_data_interface *conf,
-                                    bool check_only)
+static int fsmc_setup_data_interface(struct mtd_info *mtd, int csline,
+                                    const struct nand_data_interface *conf)
 {
        struct nand_chip *nand = mtd_to_nand(mtd);
        struct fsmc_nand_data *host = nand_get_controller_data(nand);
@@ -406,7 +405,7 @@ static int fsmc_setup_data_interface(struct mtd_info *mtd,
        if (ret)
                return ret;
 
-       if (check_only)
+       if (csline == NAND_DATA_IFACE_CHECK_ONLY)
                return 0;
 
        fsmc_nand_setup(host, &tims);
index 61ca020c527295950241c0982b990af5967c9078..a764d5ca7536b33fdb60a7ced19cf9980cffdd71 100644 (file)
@@ -152,9 +152,8 @@ struct mxc_nand_devtype_data {
        void (*select_chip)(struct mtd_info *mtd, int chip);
        int (*correct_data)(struct mtd_info *mtd, u_char *dat,
                        u_char *read_ecc, u_char *calc_ecc);
-       int (*setup_data_interface)(struct mtd_info *mtd,
-                                   const struct nand_data_interface *conf,
-                                   bool check_only);
+       int (*setup_data_interface)(struct mtd_info *mtd, int csline,
+                                   const struct nand_data_interface *conf);
 
        /*
         * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
@@ -1015,9 +1014,8 @@ static void preset_v1(struct mtd_info *mtd)
        writew(0x4, NFC_V1_V2_WRPROT);
 }
 
-static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd,
-                                       const struct nand_data_interface *conf,
-                                       bool check_only)
+static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd, int csline,
+                                       const struct nand_data_interface *conf)
 {
        struct nand_chip *nand_chip = mtd_to_nand(mtd);
        struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
@@ -1075,7 +1073,7 @@ static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd,
                return -EINVAL;
        }
 
-       if (check_only)
+       if (csline == NAND_DATA_IFACE_CHECK_ONLY)
                return 0;
 
        ret = clk_set_rate(host->clk, rate);
index 79d98c9fa8a7528e8ac815e33dd480151462bd3e..3317acf0ce04d5575cbf755e01ffcf0c97d56052 100644 (file)
@@ -1042,12 +1042,13 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 /**
  * nand_reset_data_interface - Reset data interface and timings
  * @chip: The NAND chip
+ * @chipnr: Internal die id
  *
  * Reset the Data interface and timings to ONFI mode 0.
  *
  * Returns 0 for success or negative error code otherwise.
  */
-static int nand_reset_data_interface(struct nand_chip *chip)
+static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
 {
        struct mtd_info *mtd = nand_to_mtd(chip);
        const struct nand_data_interface *conf;
@@ -1071,7 +1072,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
         */
 
        conf = nand_get_default_data_interface();
-       ret = chip->setup_data_interface(mtd, conf, false);
+       ret = chip->setup_data_interface(mtd, chipnr, conf);
        if (ret)
                pr_err("Failed to configure data interface to SDR timing mode 0\n");
 
@@ -1081,6 +1082,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
 /**
  * nand_setup_data_interface - Setup the best data interface and timings
  * @chip: The NAND chip
+ * @chipnr: Internal die id
  *
  * Find and configure the best data interface and NAND timings supported by
  * the chip and the driver.
@@ -1090,7 +1092,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
  *
  * Returns 0 for success or negative error code otherwise.
  */
-static int nand_setup_data_interface(struct nand_chip *chip)
+static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
 {
        struct mtd_info *mtd = nand_to_mtd(chip);
        int ret;
@@ -1114,7 +1116,7 @@ static int nand_setup_data_interface(struct nand_chip *chip)
                        goto err;
        }
 
-       ret = chip->setup_data_interface(mtd, chip->data_interface, false);
+       ret = chip->setup_data_interface(mtd, chipnr, chip->data_interface);
 err:
        return ret;
 }
@@ -1165,8 +1167,10 @@ static int nand_init_data_interface(struct nand_chip *chip)
                if (ret)
                        continue;
 
-               ret = chip->setup_data_interface(mtd, chip->data_interface,
-                                                true);
+               /* Pass -1 to only */
+               ret = chip->setup_data_interface(mtd,
+                                                NAND_DATA_IFACE_CHECK_ONLY,
+                                                chip->data_interface);
                if (!ret) {
                        chip->onfi_timing_mode_default = mode;
                        break;
@@ -1193,7 +1197,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
        struct mtd_info *mtd = nand_to_mtd(chip);
        int ret;
 
-       ret = nand_reset_data_interface(chip);
+       ret = nand_reset_data_interface(chip, chipnr);
        if (ret)
                return ret;
 
@@ -1206,7 +1210,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
        chip->select_chip(mtd, -1);
 
        chip->select_chip(mtd, chipnr);
-       ret = nand_setup_data_interface(chip);
+       ret = nand_setup_data_interface(chip, chipnr);
        chip->select_chip(mtd, -1);
        if (ret)
                return ret;
@@ -4396,7 +4400,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
         * For the other dies, nand_reset() will automatically switch to the
         * best mode for us.
         */
-       ret = nand_setup_data_interface(chip);
+       ret = nand_setup_data_interface(chip, 0);
        if (ret)
                return ret;
 
index f0b030d44f71ff2add4383196fba0c9e02350277..9e0c849607b9ca8345828f0128ce9d796eee1f7f 100644 (file)
@@ -812,9 +812,8 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
        return -ENODEV;
 }
 
-static int s3c2410_nand_setup_data_interface(struct mtd_info *mtd,
-                                       const struct nand_data_interface *conf,
-                                       bool check_only)
+static int s3c2410_nand_setup_data_interface(struct mtd_info *mtd, int csline,
+                                       const struct nand_data_interface *conf)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
        struct s3c2410_platform_nand *pdata = info->platform;
index 118a26fff36856dd3f47fa523494ab05909924e4..9c2dbe352c439b710d199c1e3a32194f2820aeaa 100644 (file)
@@ -1592,9 +1592,8 @@ static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
 #define sunxi_nand_lookup_timing(l, p, c) \
                        _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
 
-static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd,
-                                       const struct nand_data_interface *conf,
-                                       bool check_only)
+static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd, int csline,
+                                       const struct nand_data_interface *conf)
 {
        struct nand_chip *nand = mtd_to_nand(mtd);
        struct sunxi_nand_chip *chip = to_sunxi_nand(nand);
@@ -1707,7 +1706,7 @@ static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd,
                return tRHW;
        }
 
-       if (check_only)
+       if (csline == NAND_DATA_IFACE_CHECK_ONLY)
                return 0;
 
        /*
index 05b6e106520331ddd48f619f798d21c4cfeb2059..85e0d97593e84fd34ba75df6ed46d98fa04f8321 100644 (file)
@@ -476,9 +476,8 @@ static u32 to_ticks(int kHz, int ps)
        return DIV_ROUND_UP_ULL((u64)kHz * ps, NSEC_PER_SEC);
 }
 
-static int tango_set_timings(struct mtd_info *mtd,
-                            const struct nand_data_interface *conf,
-                            bool check_only)
+static int tango_set_timings(struct mtd_info *mtd, int csline,
+                            const struct nand_data_interface *conf)
 {
        const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf);
        struct nand_chip *chip = mtd_to_nand(mtd);
@@ -490,7 +489,7 @@ static int tango_set_timings(struct mtd_info *mtd,
        if (IS_ERR(sdr))
                return PTR_ERR(sdr);
 
-       if (check_only)
+       if (csline == NAND_DATA_IFACE_CHECK_ONLY)
                return 0;
 
        Trdy = to_ticks(kHz, sdr->tCEA_max - sdr->tREA_max);
index 893d0ce08030dbe30457a808fba4262a3d0eba9b..9de3686e738c107db2d094f58b6e2775aa792042 100644 (file)
@@ -107,6 +107,8 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 #define NAND_STATUS_READY      0x40
 #define NAND_STATUS_WP         0x80
 
+#define NAND_DATA_IFACE_CHECK_ONLY     -1
+
 /*
  * Constants for ECC_MODES
  */
@@ -818,7 +820,10 @@ struct nand_manufacturer_ops {
  * @read_retries:      [INTERN] the number of read retry modes supported
  * @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
  * @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
- * @setup_data_interface: [OPTIONAL] setup the data interface and timing
+ * @setup_data_interface: [OPTIONAL] setup the data interface and timing. If
+ *                       chipnr is set to %NAND_DATA_IFACE_CHECK_ONLY this
+ *                       means the configuration should not be applied but
+ *                       only checked.
  * @bbt:               [INTERN] bad block table pointer
  * @bbt_td:            [REPLACEABLE] bad block table descriptor for flash
  *                     lookup.
@@ -862,9 +867,8 @@ struct nand_chip {
        int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
                        int feature_addr, uint8_t *subfeature_para);
        int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode);
-       int (*setup_data_interface)(struct mtd_info *mtd,
-                                   const struct nand_data_interface *conf,
-                                   bool check_only);
+       int (*setup_data_interface)(struct mtd_info *mtd, int chipnr,
+                                   const struct nand_data_interface *conf);
 
 
        int chip_delay;