]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
mtd: rawnand: Move ->setup_data_interface() to nand_controller_ops
authorBoris Brezillon <boris.brezillon@bootlin.com>
Sun, 11 Nov 2018 07:55:24 +0000 (08:55 +0100)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Fri, 7 Dec 2018 09:38:27 +0000 (10:38 +0100)
->setup_data_interface() is a controller specific method and should
thus be placed in nand_controller_ops.

In order to make that work with controllers that support keeping
pre-configured timings we need to add a new NAND_KEEP_TIMINGS flag to
inform the core it should skip the timings selection step.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Tested-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
15 files changed:
drivers/mtd/nand/raw/atmel/nand-controller.c
drivers/mtd/nand/raw/denali.c
drivers/mtd/nand/raw/fsmc_nand.c
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/raw/internals.h
drivers/mtd/nand/raw/marvell_nand.c
drivers/mtd/nand/raw/mtk_nand.c
drivers/mtd/nand/raw/mxc_nand.c
drivers/mtd/nand/raw/nand_base.c
drivers/mtd/nand/raw/nand_legacy.c
drivers/mtd/nand/raw/s3c2410.c
drivers/mtd/nand/raw/sunxi_nand.c
drivers/mtd/nand/raw/tango_nand.c
drivers/mtd/nand/raw/tegra_nand.c
include/linux/mtd/rawnand.h

index d5c58eb040d8ab263c2f41f19a8ad63c01f08002..dcd3bd73e5493469ecf3e97d7c64fc40995cf983 100644 (file)
@@ -1479,8 +1479,8 @@ static void atmel_nand_init(struct atmel_nand_controller *nc,
        chip->legacy.write_buf = atmel_nand_write_buf;
        chip->legacy.select_chip = atmel_nand_select_chip;
 
-       if (nc->mck && nc->caps->ops->setup_data_interface)
-               chip->setup_data_interface = atmel_nand_setup_data_interface;
+       if (!nc->mck || !nc->caps->ops->setup_data_interface)
+               chip->options |= NAND_KEEP_TIMINGS;
 
        /* Some NANDs require a longer delay than the default one (20us). */
        chip->legacy.chip_delay = 40;
@@ -1908,6 +1908,7 @@ static int atmel_nand_attach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops atmel_nand_controller_ops = {
        .attach_chip = atmel_nand_attach_chip,
+       .setup_data_interface = atmel_nand_setup_data_interface,
 };
 
 static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
index 64895ca68c8d056939746eaa7a228bf371c2b24e..bad3b8ad5e0a16f8331c5118bff9174873529716 100644 (file)
@@ -1316,6 +1316,7 @@ static void denali_detach_chip(struct nand_chip *chip)
 static const struct nand_controller_ops denali_controller_ops = {
        .attach_chip = denali_attach_chip,
        .detach_chip = denali_detach_chip,
+       .setup_data_interface = denali_setup_data_interface,
 };
 
 int denali_init(struct denali_nand_info *denali)
@@ -1372,7 +1373,7 @@ int denali_init(struct denali_nand_info *denali)
 
        /* clk rate info is needed for setup_data_interface */
        if (denali->clk_rate && denali->clk_x_rate)
-               chip->setup_data_interface = denali_setup_data_interface;
+               chip->options |= NAND_KEEP_TIMINGS;
 
        chip->dummy_controller.ops = &denali_controller_ops;
        ret = nand_scan(chip, denali->max_banks);
index 1eb5008e7453ef67e7b5ad4e7d069efea012b2f1..61927c4c26503bc61a35ebc26dbde95cb1088939 100644 (file)
@@ -996,6 +996,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
 static const struct nand_controller_ops fsmc_nand_controller_ops = {
        .attach_chip = fsmc_nand_attach_chip,
        .exec_op = fsmc_exec_op,
+       .setup_data_interface = fsmc_setup_data_interface,
 };
 
 /*
@@ -1108,10 +1109,10 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
                }
        }
 
-       if (host->dev_timings)
+       if (host->dev_timings) {
                fsmc_nand_setup(host, host->dev_timings);
-       else
-               nand->setup_data_interface = fsmc_setup_data_interface;
+               nand->options |= NAND_KEEP_TIMINGS;
+       }
 
        if (AMBA_REV_BITS(host->pid) >= 8) {
                nand->ecc.read_page = fsmc_read_page_hwecc;
index c461d5efabc00bb404ee771b21b5837d934f5466..25f9fe79796a931afa98fe18d46b7d97111e791e 100644 (file)
@@ -1889,6 +1889,7 @@ static int gpmi_nand_attach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops gpmi_nand_controller_ops = {
        .attach_chip = gpmi_nand_attach_chip,
+       .setup_data_interface = gpmi_setup_data_interface,
 };
 
 static int gpmi_nand_init(struct gpmi_nand_data *this)
@@ -1908,7 +1909,6 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
        nand_set_controller_data(chip, this);
        nand_set_flash_node(chip, this->pdev->dev.of_node);
        chip->legacy.select_chip        = gpmi_select_chip;
-       chip->setup_data_interface = gpmi_setup_data_interface;
        chip->legacy.cmd_ctrl   = gpmi_cmd_ctrl;
        chip->legacy.dev_ready  = gpmi_dev_ready;
        chip->legacy.read_byte  = gpmi_read_byte;
index ac66b458566fc0be87cdc82e2d80542da3f2d98f..fbf6ca015cd7e9c73cc07e9c9f771d17da569ce8 100644 (file)
@@ -116,6 +116,18 @@ static inline int nand_exec_op(struct nand_chip *chip,
        return chip->controller->ops->exec_op(chip, op, false);
 }
 
+static inline bool nand_has_setup_data_iface(struct nand_chip *chip)
+{
+       if (!chip->controller || !chip->controller->ops ||
+           !chip->controller->ops->setup_data_interface)
+               return false;
+
+       if (chip->options & NAND_KEEP_TIMINGS)
+               return false;
+
+       return true;
+}
+
 /* BBT functions */
 int nand_markbad_bbt(struct nand_chip *chip, loff_t offs);
 int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs);
index 2e8257fe7d003cb1c508706e8addc754c9ee3e37..b7b4d9b14da1e2c89643852aa0ab9538671dee82 100644 (file)
@@ -2506,6 +2506,7 @@ static int marvell_nand_attach_chip(struct nand_chip *chip)
 static const struct nand_controller_ops marvell_nand_controller_ops = {
        .attach_chip = marvell_nand_attach_chip,
        .exec_op = marvell_nfc_exec_op,
+       .setup_data_interface = marvell_nfc_setup_data_interface,
 };
 
 static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
@@ -2629,7 +2630,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
        nand_set_flash_node(chip, np);
 
        if (!of_property_read_bool(np, "marvell,nand-keep-config"))
-               chip->setup_data_interface = marvell_nfc_setup_data_interface;
+               chip->options |= NAND_KEEP_TIMINGS;
 
        mtd = nand_to_mtd(chip);
        mtd->dev.parent = dev;
index ce124f8c02cd105b0b46b99866f61782734e94e9..b6b4602f5132ebc7b9b3fe30daabd3094bd06ccf 100644 (file)
@@ -1288,6 +1288,7 @@ static int mtk_nfc_attach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops mtk_nfc_controller_ops = {
        .attach_chip = mtk_nfc_attach_chip,
+       .setup_data_interface = mtk_nfc_setup_data_interface,
 };
 
 static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
@@ -1339,7 +1340,6 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
        nand->legacy.read_byte = mtk_nfc_read_byte;
        nand->legacy.read_buf = mtk_nfc_read_buf;
        nand->legacy.cmd_ctrl = mtk_nfc_cmd_ctrl;
-       nand->setup_data_interface = mtk_nfc_setup_data_interface;
 
        /* set default mode in case dt entry is missing */
        nand->ecc.mode = NAND_ECC_HW;
index c00b1d408a0429c5cf04c97e3d9b0d42dc6ed247..9b75d894cb74c6dc0057ce08404a72b45529d5c0 100644 (file)
@@ -1738,8 +1738,17 @@ static int mxcnd_attach_chip(struct nand_chip *chip)
        return 0;
 }
 
+static int mxcnd_setup_data_interface(struct nand_chip *chip, int chipnr,
+                                     const struct nand_data_interface *conf)
+{
+       struct mxc_nand_host *host = nand_get_controller_data(chip);
+
+       return host->devtype_data->setup_data_interface(chip, chipnr, conf);
+}
+
 static const struct nand_controller_ops mxcnd_controller_ops = {
        .attach_chip = mxcnd_attach_chip,
+       .setup_data_interface = mxcnd_setup_data_interface,
 };
 
 static int mxcnd_probe(struct platform_device *pdev)
@@ -1800,7 +1809,8 @@ static int mxcnd_probe(struct platform_device *pdev)
        if (err < 0)
                return err;
 
-       this->setup_data_interface = host->devtype_data->setup_data_interface;
+       if (!host->devtype_data->setup_data_interface)
+               this->options |= NAND_KEEP_TIMINGS;
 
        if (host->devtype_data->needs_ip) {
                res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index eabef6a3857ead8eb19c952eeadd84a7ab187a6f..3fc5c00f8dba72a94ae6e387535084a568a5dd37 100644 (file)
@@ -807,7 +807,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
 {
        int ret;
 
-       if (!chip->setup_data_interface)
+       if (!nand_has_setup_data_iface(chip))
                return 0;
 
        /*
@@ -825,7 +825,8 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
         */
 
        onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
-       ret = chip->setup_data_interface(chip, chipnr, &chip->data_interface);
+       ret = chip->controller->ops->setup_data_interface(chip, chipnr,
+                                                       &chip->data_interface);
        if (ret)
                pr_err("Failed to configure data interface to SDR timing mode 0\n");
 
@@ -852,7 +853,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
        };
        int ret;
 
-       if (!chip->setup_data_interface)
+       if (!nand_has_setup_data_iface(chip))
                return 0;
 
        /* Change the mode on the chip side (if supported by the NAND chip) */
@@ -866,7 +867,8 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
        }
 
        /* Change the mode on the controller side */
-       ret = chip->setup_data_interface(chip, chipnr, &chip->data_interface);
+       ret = chip->controller->ops->setup_data_interface(chip, chipnr,
+                                                       &chip->data_interface);
        if (ret)
                return ret;
 
@@ -921,7 +923,7 @@ static int nand_init_data_interface(struct nand_chip *chip)
 {
        int modes, mode, ret;
 
-       if (!chip->setup_data_interface)
+       if (!nand_has_setup_data_iface(chip))
                return 0;
 
        /*
@@ -947,7 +949,7 @@ static int nand_init_data_interface(struct nand_chip *chip)
                 * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the
                 * controller supports the requested timings.
                 */
-               ret = chip->setup_data_interface(chip,
+               ret = chip->controller->ops->setup_data_interface(chip,
                                                 NAND_DATA_IFACE_CHECK_ONLY,
                                                 &chip->data_interface);
                if (!ret) {
index 47364237861e144e994e7905d7cf292eeb6cd8ab..43575943f13bde45a3ff5889af83e0506e82e758 100644 (file)
@@ -364,7 +364,7 @@ static void nand_ccs_delay(struct nand_chip *chip)
         * Wait tCCS_min if it is correctly defined, otherwise wait 500ns
         * (which should be safe for all NANDs).
         */
-       if (chip->setup_data_interface)
+       if (nand_has_setup_data_iface(chip))
                ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000);
        else
                ndelay(500);
index a8905463701a7489721e2b65535b245fdfded8bc..adc7a196e3836d8ee700624a5d83b1d1e83e8b8c 100644 (file)
@@ -876,8 +876,8 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
         * let's keep behavior unchanged for legacy boards booting via pdata and
         * auto-detect timings only when booting with a device tree.
         */
-       if (np)
-               chip->setup_data_interface = s3c2410_nand_setup_data_interface;
+       if (!np)
+               chip->options |= NAND_KEEP_TIMINGS;
 
        switch (info->cpu_type) {
        case TYPE_S3C2410:
@@ -1011,6 +1011,7 @@ static int s3c2410_nand_attach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops s3c24xx_nand_controller_ops = {
        .attach_chip = s3c2410_nand_attach_chip,
+       .setup_data_interface = s3c2410_nand_setup_data_interface,
 };
 
 static const struct of_device_id s3c24xx_nand_dt_ids[] = {
index e489a6ff57d7f966b62bfb5afc7811d3a54bdcf8..a5c83cbe489728826dc77abbca05a88724c07df1 100644 (file)
@@ -1847,6 +1847,7 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand)
 
 static const struct nand_controller_ops sunxi_nand_controller_ops = {
        .attach_chip = sunxi_nand_attach_chip,
+       .setup_data_interface = sunxi_nfc_setup_data_interface,
 };
 
 static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
@@ -1927,7 +1928,6 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
        nand->legacy.read_buf = sunxi_nfc_read_buf;
        nand->legacy.write_buf = sunxi_nfc_write_buf;
        nand->legacy.read_byte = sunxi_nfc_read_byte;
-       nand->setup_data_interface = sunxi_nfc_setup_data_interface;
 
        mtd = nand_to_mtd(nand);
        mtd->dev.parent = dev;
index ebca4579c033d4b238ed9461738ffbccc5d1a0b9..cb3beda88789a77844a15175d0cd4834572a5f96 100644 (file)
@@ -530,6 +530,7 @@ static int tango_attach_chip(struct nand_chip *chip)
 
 static const struct nand_controller_ops tango_controller_ops = {
        .attach_chip = tango_attach_chip,
+       .setup_data_interface = tango_set_timings,
 };
 
 static int chip_init(struct device *dev, struct device_node *np)
@@ -570,7 +571,6 @@ static int chip_init(struct device *dev, struct device_node *np)
        chip->legacy.select_chip = tango_select_chip;
        chip->legacy.cmd_ctrl = tango_cmd_ctrl;
        chip->legacy.dev_ready = tango_dev_ready;
-       chip->setup_data_interface = tango_set_timings;
        chip->options = NAND_USE_BOUNCE_BUFFER |
                        NAND_NO_SUBPAGE_WRITE |
                        NAND_WAIT_TCCS;
index 2fe6de09f4ff0d9a289d5530920b103865b793cb..13be32c381948f1e621368cbd26f1e2e2ee8aa9f 100644 (file)
@@ -1051,6 +1051,7 @@ static int tegra_nand_attach_chip(struct nand_chip *chip)
 static const struct nand_controller_ops tegra_nand_controller_ops = {
        .attach_chip = &tegra_nand_attach_chip,
        .exec_op = tegra_nand_exec_op,
+       .setup_data_interface = tegra_nand_setup_data_interface,
 };
 
 static int tegra_nand_chips_init(struct device *dev,
@@ -1113,7 +1114,6 @@ static int tegra_nand_chips_init(struct device *dev,
                mtd->name = "tegra_nand";
 
        chip->options = NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER;
-       chip->setup_data_interface = tegra_nand_setup_data_interface;
 
        ret = nand_scan(chip, 1);
        if (ret)
index 297b40c564030a516a3149a7a4f491f8c9274ce4..f50f40643895653e39cd4ee63490381e5658f1fc 100644 (file)
@@ -203,6 +203,13 @@ enum nand_ecc_algo {
  */
 #define NAND_IS_BOOT_MEDIUM    0x00400000
 
+/*
+ * Do not try to tweak the timings at runtime. This is needed when the
+ * controller initializes the timings on itself or when it relies on
+ * configuration done by the bootloader.
+ */
+#define NAND_KEEP_TIMINGS      0x00800000
+
 /* Cell info constants */
 #define NAND_CI_CHIPNR_MSK     0x03
 #define NAND_CI_CELLTYPE_MSK   0x0C
@@ -871,6 +878,11 @@ int nand_op_parser_exec_op(struct nand_chip *chip,
  *              This method replaces chip->legacy.cmdfunc(),
  *              chip->legacy.{read,write}_{buf,byte,word}(),
  *              chip->legacy.dev_ready() and chip->legacy.waifunc().
+ * @setup_data_interface: 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.
+ *                       This hook is optional.
  */
 struct nand_controller_ops {
        int (*attach_chip)(struct nand_chip *chip);
@@ -878,6 +890,8 @@ struct nand_controller_ops {
        int (*exec_op)(struct nand_chip *chip,
                       const struct nand_operation *op,
                       bool check_only);
+       int (*setup_data_interface)(struct nand_chip *chip, int chipnr,
+                                   const struct nand_data_interface *conf);
 };
 
 /**
@@ -1019,10 +1033,6 @@ struct nand_legacy {
  *                     cur_cs < numchips. NAND Controller drivers should not
  *                     modify this value, but they're allowed to read it.
  * @read_retries:      [INTERN] the number of read retry modes supported
- * @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.
@@ -1044,8 +1054,6 @@ struct nand_chip {
        struct nand_legacy legacy;
 
        int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
-       int (*setup_data_interface)(struct nand_chip *chip, int chipnr,
-                                   const struct nand_data_interface *conf);
 
        unsigned int options;
        unsigned int bbt_options;