mtd: rawnand: stm32_fmc2: add MP25 support
[linux-2.6-microblaze.git] / drivers / mtd / nand / raw / stm32_fmc2_nand.c
index a7db7b6..2645569 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
@@ -37,7 +38,7 @@
 #define FMC2_MAX_SG                    16
 
 /* Max chip enable */
-#define FMC2_MAX_CE                    2
+#define FMC2_MAX_CE                    4
 
 /* Max ECC buffer length */
 #define FMC2_MAX_ECC_BUF_LEN           (FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
@@ -243,6 +244,13 @@ static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip)
        return container_of(chip, struct stm32_fmc2_nand, chip);
 }
 
+struct stm32_fmc2_nfc;
+
+struct stm32_fmc2_nfc_data {
+       int max_ncs;
+       int (*set_cdev)(struct stm32_fmc2_nfc *nfc);
+};
+
 struct stm32_fmc2_nfc {
        struct nand_controller base;
        struct stm32_fmc2_nand nand;
@@ -256,6 +264,7 @@ struct stm32_fmc2_nfc {
        phys_addr_t data_phys_addr[FMC2_MAX_CE];
        struct clk *clk;
        u8 irq_state;
+       const struct stm32_fmc2_nfc_data *data;
 
        struct dma_chan *dma_tx_ch;
        struct dma_chan *dma_rx_ch;
@@ -1809,7 +1818,7 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
                        return ret;
                }
 
-               if (cs >= FMC2_MAX_CE) {
+               if (cs >= nfc->data->max_ncs) {
                        dev_err(nfc->dev, "invalid reg value: %d\n", cs);
                        return -EINVAL;
                }
@@ -1915,9 +1924,17 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
        nand_controller_init(&nfc->base);
        nfc->base.ops = &stm32_fmc2_nfc_controller_ops;
 
-       ret = stm32_fmc2_nfc_set_cdev(nfc);
-       if (ret)
-               return ret;
+       nfc->data = of_device_get_match_data(dev);
+       if (!nfc->data)
+               return -EINVAL;
+
+       if (nfc->data->set_cdev) {
+               ret = nfc->data->set_cdev(nfc);
+               if (ret)
+                       return ret;
+       } else {
+               nfc->cdev = dev->parent;
+       }
 
        ret = stm32_fmc2_nfc_parse_dt(nfc);
        if (ret)
@@ -1936,7 +1953,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
        if (nfc->dev == nfc->cdev)
                start_region = 1;
 
-       for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
+       for (chip_cs = 0, mem_region = start_region; chip_cs < nfc->data->max_ncs;
             chip_cs++, mem_region += 3) {
                if (!(nfc->cs_assigned & BIT(chip_cs)))
                        continue;
@@ -2092,7 +2109,7 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev)
 
        stm32_fmc2_nfc_wp_disable(nand);
 
-       for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) {
+       for (chip_cs = 0; chip_cs < nfc->data->max_ncs; chip_cs++) {
                if (!(nfc->cs_assigned & BIT(chip_cs)))
                        continue;
 
@@ -2105,9 +2122,28 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(stm32_fmc2_nfc_pm_ops, stm32_fmc2_nfc_suspend,
                         stm32_fmc2_nfc_resume);
 
+static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp1_data = {
+       .max_ncs = 2,
+       .set_cdev = stm32_fmc2_nfc_set_cdev,
+};
+
+static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp25_data = {
+       .max_ncs = 4,
+};
+
 static const struct of_device_id stm32_fmc2_nfc_match[] = {
-       {.compatible = "st,stm32mp15-fmc2"},
-       {.compatible = "st,stm32mp1-fmc2-nfc"},
+       {
+               .compatible = "st,stm32mp15-fmc2",
+               .data = &stm32_fmc2_nfc_mp1_data,
+       },
+       {
+               .compatible = "st,stm32mp1-fmc2-nfc",
+               .data = &stm32_fmc2_nfc_mp1_data,
+       },
+       {
+               .compatible = "st,stm32mp25-fmc2-nfc",
+               .data = &stm32_fmc2_nfc_mp25_data,
+       },
        {}
 };
 MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match);