All of the mtd patches are upstreamed to 5.18. Add tags indicating this.
Signed-off-by: Nick Hainke <vincent@systemli.org>
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: [PATCH v3 1/9] mtd: rawnand: brcmnand: Assign soc as early as possible
-Date: Fri, 07 Jan 2022 10:46:06 -0800
-Content-Type: text/plain; charset="utf-8"
-
-In order to key off the brcmnand_probe() code in subsequent changes
-depending upon ctrl->soc, assign that variable as early as possible,
-instead of much later when we have checked that it is non-NULL.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-@@ -2949,6 +2949,7 @@ int brcmnand_probe(struct platform_devic
-
- dev_set_drvdata(dev, ctrl);
- ctrl->dev = dev;
-+ ctrl->soc = soc;
-
- init_completion(&ctrl->done);
- init_completion(&ctrl->dma_done);
-@@ -3089,8 +3090,6 @@ int brcmnand_probe(struct platform_devic
- * interesting ways
- */
- if (soc) {
-- ctrl->soc = soc;
--
- ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0,
- DRV_NAME, ctrl);
-
--- /dev/null
+From: Florian Fainelli <f.fainelli@gmail.com>
+Subject: [PATCH v3 1/9] mtd: rawnand: brcmnand: Assign soc as early as possible
+Date: Fri, 07 Jan 2022 10:46:06 -0800
+Content-Type: text/plain; charset="utf-8"
+
+In order to key off the brcmnand_probe() code in subsequent changes
+depending upon ctrl->soc, assign that variable as early as possible,
+instead of much later when we have checked that it is non-NULL.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -2949,6 +2949,7 @@ int brcmnand_probe(struct platform_devic
+
+ dev_set_drvdata(dev, ctrl);
+ ctrl->dev = dev;
++ ctrl->soc = soc;
+
+ init_completion(&ctrl->done);
+ init_completion(&ctrl->dma_done);
+@@ -3089,8 +3090,6 @@ int brcmnand_probe(struct platform_devic
+ * interesting ways
+ */
+ if (soc) {
+- ctrl->soc = soc;
+-
+ ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0,
+ DRV_NAME, ctrl);
+
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: [PATCH v3 2/9] mtd: rawnand: brcmnand: Allow SoC to provide I/O operations
-Date: Fri, 07 Jan 2022 10:46:07 -0800
-Content-Type: text/plain; charset="utf-8"
-
-Allow a brcmnand_soc instance to provide a custom set of I/O operations
-which we will require when using this driver on a BCMA bus which is not
-directly memory mapped I/O. Update the nand_{read,write}_reg accordingly
-to use the SoC operations if provided.
-
-To minimize the penalty on other SoCs which do support standard MMIO
-accesses, we use a static key which is disabled by default and gets
-enabled if a soc implementation does provide I/O operations.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 28 +++++++++++++++++++++--
- drivers/mtd/nand/raw/brcmnand/brcmnand.h | 29 ++++++++++++++++++++++++
- 2 files changed, 55 insertions(+), 2 deletions(-)
-
---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-@@ -25,6 +25,7 @@
- #include <linux/of.h>
- #include <linux/of_platform.h>
- #include <linux/slab.h>
-+#include <linux/static_key.h>
- #include <linux/list.h>
- #include <linux/log2.h>
-
-@@ -207,6 +208,8 @@ enum {
-
- struct brcmnand_host;
-
-+static DEFINE_STATIC_KEY_FALSE(brcmnand_soc_has_ops_key);
-+
- struct brcmnand_controller {
- struct device *dev;
- struct nand_controller controller;
-@@ -589,15 +592,25 @@ enum {
- INTFC_CTLR_READY = BIT(31),
- };
-
-+static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
-+{
-+ return static_branch_unlikely(&brcmnand_soc_has_ops_key);
-+}
-+
- static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs)
- {
-+ if (brcmnand_non_mmio_ops(ctrl))
-+ return brcmnand_soc_read(ctrl->soc, offs);
- return brcmnand_readl(ctrl->nand_base + offs);
- }
-
- static inline void nand_writereg(struct brcmnand_controller *ctrl, u32 offs,
- u32 val)
- {
-- brcmnand_writel(val, ctrl->nand_base + offs);
-+ if (brcmnand_non_mmio_ops(ctrl))
-+ brcmnand_soc_write(ctrl->soc, val, offs);
-+ else
-+ brcmnand_writel(val, ctrl->nand_base + offs);
- }
-
- static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
-@@ -763,13 +776,18 @@ static inline void brcmnand_rmw_reg(stru
-
- static inline u32 brcmnand_read_fc(struct brcmnand_controller *ctrl, int word)
- {
-+ if (brcmnand_non_mmio_ops(ctrl))
-+ return brcmnand_soc_read(ctrl->soc, BRCMNAND_NON_MMIO_FC_ADDR);
- return __raw_readl(ctrl->nand_fc + word * 4);
- }
-
- static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl,
- int word, u32 val)
- {
-- __raw_writel(val, ctrl->nand_fc + word * 4);
-+ if (brcmnand_non_mmio_ops(ctrl))
-+ brcmnand_soc_write(ctrl->soc, val, BRCMNAND_NON_MMIO_FC_ADDR);
-+ else
-+ __raw_writel(val, ctrl->nand_fc + word * 4);
- }
-
- static inline void edu_writel(struct brcmnand_controller *ctrl,
-@@ -2951,6 +2969,12 @@ int brcmnand_probe(struct platform_devic
- ctrl->dev = dev;
- ctrl->soc = soc;
-
-+ /* Enable the static key if the soc provides I/O operations indicating
-+ * that a non-memory mapped IO access path must be used
-+ */
-+ if (brcmnand_soc_has_ops(ctrl->soc))
-+ static_branch_enable(&brcmnand_soc_has_ops_key);
-+
- init_completion(&ctrl->done);
- init_completion(&ctrl->dma_done);
- init_completion(&ctrl->edu_done);
---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.h
-+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
-@@ -11,12 +11,25 @@
-
- struct platform_device;
- struct dev_pm_ops;
-+struct brcmnand_io_ops;
-+
-+/* Special register offset constant to intercept a non-MMIO access
-+ * to the flash cache register space. This is intentionally large
-+ * not to overlap with an existing offset.
-+ */
-+#define BRCMNAND_NON_MMIO_FC_ADDR 0xffffffff
-
- struct brcmnand_soc {
- bool (*ctlrdy_ack)(struct brcmnand_soc *soc);
- void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en);
- void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare,
- bool is_param);
-+ const struct brcmnand_io_ops *ops;
-+};
-+
-+struct brcmnand_io_ops {
-+ u32 (*read_reg)(struct brcmnand_soc *soc, u32 offset);
-+ void (*write_reg)(struct brcmnand_soc *soc, u32 val, u32 offset);
- };
-
- static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc,
-@@ -58,6 +71,22 @@ static inline void brcmnand_writel(u32 v
- writel_relaxed(val, addr);
- }
-
-+static inline bool brcmnand_soc_has_ops(struct brcmnand_soc *soc)
-+{
-+ return soc && soc->ops && soc->ops->read_reg && soc->ops->write_reg;
-+}
-+
-+static inline u32 brcmnand_soc_read(struct brcmnand_soc *soc, u32 offset)
-+{
-+ return soc->ops->read_reg(soc, offset);
-+}
-+
-+static inline void brcmnand_soc_write(struct brcmnand_soc *soc, u32 val,
-+ u32 offset)
-+{
-+ soc->ops->write_reg(soc, val, offset);
-+}
-+
- int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc);
- int brcmnand_remove(struct platform_device *pdev);
-
--- /dev/null
+From: Florian Fainelli <f.fainelli@gmail.com>
+Subject: [PATCH v3 2/9] mtd: rawnand: brcmnand: Allow SoC to provide I/O operations
+Date: Fri, 07 Jan 2022 10:46:07 -0800
+Content-Type: text/plain; charset="utf-8"
+
+Allow a brcmnand_soc instance to provide a custom set of I/O operations
+which we will require when using this driver on a BCMA bus which is not
+directly memory mapped I/O. Update the nand_{read,write}_reg accordingly
+to use the SoC operations if provided.
+
+To minimize the penalty on other SoCs which do support standard MMIO
+accesses, we use a static key which is disabled by default and gets
+enabled if a soc implementation does provide I/O operations.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 28 +++++++++++++++++++++--
+ drivers/mtd/nand/raw/brcmnand/brcmnand.h | 29 ++++++++++++++++++++++++
+ 2 files changed, 55 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -25,6 +25,7 @@
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+ #include <linux/slab.h>
++#include <linux/static_key.h>
+ #include <linux/list.h>
+ #include <linux/log2.h>
+
+@@ -207,6 +208,8 @@ enum {
+
+ struct brcmnand_host;
+
++static DEFINE_STATIC_KEY_FALSE(brcmnand_soc_has_ops_key);
++
+ struct brcmnand_controller {
+ struct device *dev;
+ struct nand_controller controller;
+@@ -589,15 +592,25 @@ enum {
+ INTFC_CTLR_READY = BIT(31),
+ };
+
++static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
++{
++ return static_branch_unlikely(&brcmnand_soc_has_ops_key);
++}
++
+ static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs)
+ {
++ if (brcmnand_non_mmio_ops(ctrl))
++ return brcmnand_soc_read(ctrl->soc, offs);
+ return brcmnand_readl(ctrl->nand_base + offs);
+ }
+
+ static inline void nand_writereg(struct brcmnand_controller *ctrl, u32 offs,
+ u32 val)
+ {
+- brcmnand_writel(val, ctrl->nand_base + offs);
++ if (brcmnand_non_mmio_ops(ctrl))
++ brcmnand_soc_write(ctrl->soc, val, offs);
++ else
++ brcmnand_writel(val, ctrl->nand_base + offs);
+ }
+
+ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
+@@ -763,13 +776,18 @@ static inline void brcmnand_rmw_reg(stru
+
+ static inline u32 brcmnand_read_fc(struct brcmnand_controller *ctrl, int word)
+ {
++ if (brcmnand_non_mmio_ops(ctrl))
++ return brcmnand_soc_read(ctrl->soc, BRCMNAND_NON_MMIO_FC_ADDR);
+ return __raw_readl(ctrl->nand_fc + word * 4);
+ }
+
+ static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl,
+ int word, u32 val)
+ {
+- __raw_writel(val, ctrl->nand_fc + word * 4);
++ if (brcmnand_non_mmio_ops(ctrl))
++ brcmnand_soc_write(ctrl->soc, val, BRCMNAND_NON_MMIO_FC_ADDR);
++ else
++ __raw_writel(val, ctrl->nand_fc + word * 4);
+ }
+
+ static inline void edu_writel(struct brcmnand_controller *ctrl,
+@@ -2951,6 +2969,12 @@ int brcmnand_probe(struct platform_devic
+ ctrl->dev = dev;
+ ctrl->soc = soc;
+
++ /* Enable the static key if the soc provides I/O operations indicating
++ * that a non-memory mapped IO access path must be used
++ */
++ if (brcmnand_soc_has_ops(ctrl->soc))
++ static_branch_enable(&brcmnand_soc_has_ops_key);
++
+ init_completion(&ctrl->done);
+ init_completion(&ctrl->dma_done);
+ init_completion(&ctrl->edu_done);
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.h
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
+@@ -11,12 +11,25 @@
+
+ struct platform_device;
+ struct dev_pm_ops;
++struct brcmnand_io_ops;
++
++/* Special register offset constant to intercept a non-MMIO access
++ * to the flash cache register space. This is intentionally large
++ * not to overlap with an existing offset.
++ */
++#define BRCMNAND_NON_MMIO_FC_ADDR 0xffffffff
+
+ struct brcmnand_soc {
+ bool (*ctlrdy_ack)(struct brcmnand_soc *soc);
+ void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en);
+ void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare,
+ bool is_param);
++ const struct brcmnand_io_ops *ops;
++};
++
++struct brcmnand_io_ops {
++ u32 (*read_reg)(struct brcmnand_soc *soc, u32 offset);
++ void (*write_reg)(struct brcmnand_soc *soc, u32 val, u32 offset);
+ };
+
+ static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc,
+@@ -58,6 +71,22 @@ static inline void brcmnand_writel(u32 v
+ writel_relaxed(val, addr);
+ }
+
++static inline bool brcmnand_soc_has_ops(struct brcmnand_soc *soc)
++{
++ return soc && soc->ops && soc->ops->read_reg && soc->ops->write_reg;
++}
++
++static inline u32 brcmnand_soc_read(struct brcmnand_soc *soc, u32 offset)
++{
++ return soc->ops->read_reg(soc, offset);
++}
++
++static inline void brcmnand_soc_write(struct brcmnand_soc *soc, u32 val,
++ u32 offset)
++{
++ soc->ops->write_reg(soc, val, offset);
++}
++
+ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc);
+ int brcmnand_remove(struct platform_device *pdev);
+
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: [PATCH v3 3/9] mtd: rawnand: brcmnand: Avoid pdev in brcmnand_init_cs()
-Date: Fri, 07 Jan 2022 10:46:08 -0800
-Content-Type: text/plain; charset="utf-8"
-
-In preparation for encapsulating more of what the loop calling
-brcmnand_init_cs() does, avoid using platform_device when it is the
-device behind platform_device that we are using for printing errors.
-
-No functional changes introduced.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-@@ -2722,7 +2722,7 @@ static const struct nand_controller_ops
- static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
- {
- struct brcmnand_controller *ctrl = host->ctrl;
-- struct platform_device *pdev = host->pdev;
-+ struct device *dev = ctrl->dev;
- struct mtd_info *mtd;
- struct nand_chip *chip;
- int ret;
-@@ -2730,7 +2730,7 @@ static int brcmnand_init_cs(struct brcmn
-
- ret = of_property_read_u32(dn, "reg", &host->cs);
- if (ret) {
-- dev_err(&pdev->dev, "can't get chip-select\n");
-+ dev_err(dev, "can't get chip-select\n");
- return -ENXIO;
- }
-
-@@ -2739,13 +2739,13 @@ static int brcmnand_init_cs(struct brcmn
-
- nand_set_flash_node(chip, dn);
- nand_set_controller_data(chip, host);
-- mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d",
-+ mtd->name = devm_kasprintf(dev, GFP_KERNEL, "brcmnand.%d",
- host->cs);
- if (!mtd->name)
- return -ENOMEM;
-
- mtd->owner = THIS_MODULE;
-- mtd->dev.parent = &pdev->dev;
-+ mtd->dev.parent = dev;
-
- chip->legacy.cmd_ctrl = brcmnand_cmd_ctrl;
- chip->legacy.cmdfunc = brcmnand_cmdfunc;
--- /dev/null
+From: Florian Fainelli <f.fainelli@gmail.com>
+Subject: [PATCH v3 3/9] mtd: rawnand: brcmnand: Avoid pdev in brcmnand_init_cs()
+Date: Fri, 07 Jan 2022 10:46:08 -0800
+Content-Type: text/plain; charset="utf-8"
+
+In preparation for encapsulating more of what the loop calling
+brcmnand_init_cs() does, avoid using platform_device when it is the
+device behind platform_device that we are using for printing errors.
+
+No functional changes introduced.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -2722,7 +2722,7 @@ static const struct nand_controller_ops
+ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
+ {
+ struct brcmnand_controller *ctrl = host->ctrl;
+- struct platform_device *pdev = host->pdev;
++ struct device *dev = ctrl->dev;
+ struct mtd_info *mtd;
+ struct nand_chip *chip;
+ int ret;
+@@ -2730,7 +2730,7 @@ static int brcmnand_init_cs(struct brcmn
+
+ ret = of_property_read_u32(dn, "reg", &host->cs);
+ if (ret) {
+- dev_err(&pdev->dev, "can't get chip-select\n");
++ dev_err(dev, "can't get chip-select\n");
+ return -ENXIO;
+ }
+
+@@ -2739,13 +2739,13 @@ static int brcmnand_init_cs(struct brcmn
+
+ nand_set_flash_node(chip, dn);
+ nand_set_controller_data(chip, host);
+- mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d",
++ mtd->name = devm_kasprintf(dev, GFP_KERNEL, "brcmnand.%d",
+ host->cs);
+ if (!mtd->name)
+ return -ENOMEM;
+
+ mtd->owner = THIS_MODULE;
+- mtd->dev.parent = &pdev->dev;
++ mtd->dev.parent = dev;
+
+ chip->legacy.cmd_ctrl = brcmnand_cmd_ctrl;
+ chip->legacy.cmdfunc = brcmnand_cmdfunc;
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: [PATCH v3 4/9] mtd: rawnand: brcmnand: Move OF operations out of brcmnand_init_cs()
-Date: Fri, 07 Jan 2022 10:46:09 -0800
-Content-Type: text/plain; charset="utf-8"
-
-In order to initialize a given chip select object for use by the
-brcmnand driver, move all of the Device Tree specific routines outside
-of brcmnand_init_cs() in order to make it usable in a platform data
-configuration which will be necessary for supporting BCMA chips.
-
-No functional changes introduced.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 20 +++++++++++---------
- 1 file changed, 11 insertions(+), 9 deletions(-)
-
---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-@@ -2719,7 +2719,7 @@ static const struct nand_controller_ops
- .attach_chip = brcmnand_attach_chip,
- };
-
--static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
-+static int brcmnand_init_cs(struct brcmnand_host *host)
- {
- struct brcmnand_controller *ctrl = host->ctrl;
- struct device *dev = ctrl->dev;
-@@ -2728,16 +2728,9 @@ static int brcmnand_init_cs(struct brcmn
- int ret;
- u16 cfg_offs;
-
-- ret = of_property_read_u32(dn, "reg", &host->cs);
-- if (ret) {
-- dev_err(dev, "can't get chip-select\n");
-- return -ENXIO;
-- }
--
- mtd = nand_to_mtd(&host->chip);
- chip = &host->chip;
-
-- nand_set_flash_node(chip, dn);
- nand_set_controller_data(chip, host);
- mtd->name = devm_kasprintf(dev, GFP_KERNEL, "brcmnand.%d",
- host->cs);
-@@ -3144,7 +3137,16 @@ int brcmnand_probe(struct platform_devic
- host->pdev = pdev;
- host->ctrl = ctrl;
-
-- ret = brcmnand_init_cs(host, child);
-+ ret = of_property_read_u32(child, "reg", &host->cs);
-+ if (ret) {
-+ dev_err(dev, "can't get chip-select\n");
-+ devm_kfree(dev, host);
-+ continue;
-+ }
-+
-+ nand_set_flash_node(&host->chip, child);
-+
-+ ret = brcmnand_init_cs(host);
- if (ret) {
- devm_kfree(dev, host);
- continue; /* Try all chip-selects */
--- /dev/null
+From: Florian Fainelli <f.fainelli@gmail.com>
+Subject: [PATCH v3 4/9] mtd: rawnand: brcmnand: Move OF operations out of brcmnand_init_cs()
+Date: Fri, 07 Jan 2022 10:46:09 -0800
+Content-Type: text/plain; charset="utf-8"
+
+In order to initialize a given chip select object for use by the
+brcmnand driver, move all of the Device Tree specific routines outside
+of brcmnand_init_cs() in order to make it usable in a platform data
+configuration which will be necessary for supporting BCMA chips.
+
+No functional changes introduced.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -2719,7 +2719,7 @@ static const struct nand_controller_ops
+ .attach_chip = brcmnand_attach_chip,
+ };
+
+-static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
++static int brcmnand_init_cs(struct brcmnand_host *host)
+ {
+ struct brcmnand_controller *ctrl = host->ctrl;
+ struct device *dev = ctrl->dev;
+@@ -2728,16 +2728,9 @@ static int brcmnand_init_cs(struct brcmn
+ int ret;
+ u16 cfg_offs;
+
+- ret = of_property_read_u32(dn, "reg", &host->cs);
+- if (ret) {
+- dev_err(dev, "can't get chip-select\n");
+- return -ENXIO;
+- }
+-
+ mtd = nand_to_mtd(&host->chip);
+ chip = &host->chip;
+
+- nand_set_flash_node(chip, dn);
+ nand_set_controller_data(chip, host);
+ mtd->name = devm_kasprintf(dev, GFP_KERNEL, "brcmnand.%d",
+ host->cs);
+@@ -3144,7 +3137,16 @@ int brcmnand_probe(struct platform_devic
+ host->pdev = pdev;
+ host->ctrl = ctrl;
+
+- ret = brcmnand_init_cs(host, child);
++ ret = of_property_read_u32(child, "reg", &host->cs);
++ if (ret) {
++ dev_err(dev, "can't get chip-select\n");
++ devm_kfree(dev, host);
++ continue;
++ }
++
++ nand_set_flash_node(&host->chip, child);
++
++ ret = brcmnand_init_cs(host);
+ if (ret) {
+ devm_kfree(dev, host);
+ continue; /* Try all chip-selects */
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: [PATCH v3 5/9] mtd: rawnand: brcmnand: Allow working without interrupts
-Date: Fri, 07 Jan 2022 10:46:10 -0800
-Content-Type: text/plain; charset="utf-8"
-
-The BCMA devices include the brcmnand controller but they do not wire up
-any interrupt line, allow the main interrupt to be optional and update
-the completion path to also check for the lack of an interrupt line.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 52 +++++++++++-------------
- 1 file changed, 24 insertions(+), 28 deletions(-)
-
---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-@@ -216,7 +216,7 @@ struct brcmnand_controller {
- void __iomem *nand_base;
- void __iomem *nand_fc; /* flash cache */
- void __iomem *flash_dma_base;
-- unsigned int irq;
-+ int irq;
- unsigned int dma_irq;
- int nand_version;
-
-@@ -1590,7 +1590,7 @@ static bool brcmstb_nand_wait_for_comple
- bool err = false;
- int sts;
-
-- if (mtd->oops_panic_write) {
-+ if (mtd->oops_panic_write || ctrl->irq < 0) {
- /* switch to interrupt polling and PIO mode */
- disable_ctrl_irqs(ctrl);
- sts = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY,
-@@ -3095,33 +3095,29 @@ int brcmnand_probe(struct platform_devic
- }
-
- /* IRQ */
-- ctrl->irq = platform_get_irq(pdev, 0);
-- if ((int)ctrl->irq < 0) {
-- dev_err(dev, "no IRQ defined\n");
-- ret = -ENODEV;
-- goto err;
-- }
--
-- /*
-- * Some SoCs integrate this controller (e.g., its interrupt bits) in
-- * interesting ways
-- */
-- if (soc) {
-- ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0,
-- DRV_NAME, ctrl);
--
-- /* Enable interrupt */
-- ctrl->soc->ctlrdy_ack(ctrl->soc);
-- ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true);
-- } else {
-- /* Use standard interrupt infrastructure */
-- ret = devm_request_irq(dev, ctrl->irq, brcmnand_ctlrdy_irq, 0,
-- DRV_NAME, ctrl);
-- }
-- if (ret < 0) {
-- dev_err(dev, "can't allocate IRQ %d: error %d\n",
-- ctrl->irq, ret);
-- goto err;
-+ ctrl->irq = platform_get_irq_optional(pdev, 0);
-+ if (ctrl->irq > 0) {
-+ /*
-+ * Some SoCs integrate this controller (e.g., its interrupt bits) in
-+ * interesting ways
-+ */
-+ if (soc) {
-+ ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0,
-+ DRV_NAME, ctrl);
-+
-+ /* Enable interrupt */
-+ ctrl->soc->ctlrdy_ack(ctrl->soc);
-+ ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true);
-+ } else {
-+ /* Use standard interrupt infrastructure */
-+ ret = devm_request_irq(dev, ctrl->irq, brcmnand_ctlrdy_irq, 0,
-+ DRV_NAME, ctrl);
-+ }
-+ if (ret < 0) {
-+ dev_err(dev, "can't allocate IRQ %d: error %d\n",
-+ ctrl->irq, ret);
-+ goto err;
-+ }
- }
-
- for_each_available_child_of_node(dn, child) {
--- /dev/null
+From: Florian Fainelli <f.fainelli@gmail.com>
+Subject: [PATCH v3 5/9] mtd: rawnand: brcmnand: Allow working without interrupts
+Date: Fri, 07 Jan 2022 10:46:10 -0800
+Content-Type: text/plain; charset="utf-8"
+
+The BCMA devices include the brcmnand controller but they do not wire up
+any interrupt line, allow the main interrupt to be optional and update
+the completion path to also check for the lack of an interrupt line.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 52 +++++++++++-------------
+ 1 file changed, 24 insertions(+), 28 deletions(-)
+
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -216,7 +216,7 @@ struct brcmnand_controller {
+ void __iomem *nand_base;
+ void __iomem *nand_fc; /* flash cache */
+ void __iomem *flash_dma_base;
+- unsigned int irq;
++ int irq;
+ unsigned int dma_irq;
+ int nand_version;
+
+@@ -1590,7 +1590,7 @@ static bool brcmstb_nand_wait_for_comple
+ bool err = false;
+ int sts;
+
+- if (mtd->oops_panic_write) {
++ if (mtd->oops_panic_write || ctrl->irq < 0) {
+ /* switch to interrupt polling and PIO mode */
+ disable_ctrl_irqs(ctrl);
+ sts = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY,
+@@ -3095,33 +3095,29 @@ int brcmnand_probe(struct platform_devic
+ }
+
+ /* IRQ */
+- ctrl->irq = platform_get_irq(pdev, 0);
+- if ((int)ctrl->irq < 0) {
+- dev_err(dev, "no IRQ defined\n");
+- ret = -ENODEV;
+- goto err;
+- }
+-
+- /*
+- * Some SoCs integrate this controller (e.g., its interrupt bits) in
+- * interesting ways
+- */
+- if (soc) {
+- ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0,
+- DRV_NAME, ctrl);
+-
+- /* Enable interrupt */
+- ctrl->soc->ctlrdy_ack(ctrl->soc);
+- ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true);
+- } else {
+- /* Use standard interrupt infrastructure */
+- ret = devm_request_irq(dev, ctrl->irq, brcmnand_ctlrdy_irq, 0,
+- DRV_NAME, ctrl);
+- }
+- if (ret < 0) {
+- dev_err(dev, "can't allocate IRQ %d: error %d\n",
+- ctrl->irq, ret);
+- goto err;
++ ctrl->irq = platform_get_irq_optional(pdev, 0);
++ if (ctrl->irq > 0) {
++ /*
++ * Some SoCs integrate this controller (e.g., its interrupt bits) in
++ * interesting ways
++ */
++ if (soc) {
++ ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0,
++ DRV_NAME, ctrl);
++
++ /* Enable interrupt */
++ ctrl->soc->ctlrdy_ack(ctrl->soc);
++ ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true);
++ } else {
++ /* Use standard interrupt infrastructure */
++ ret = devm_request_irq(dev, ctrl->irq, brcmnand_ctlrdy_irq, 0,
++ DRV_NAME, ctrl);
++ }
++ if (ret < 0) {
++ dev_err(dev, "can't allocate IRQ %d: error %d\n",
++ ctrl->irq, ret);
++ goto err;
++ }
+ }
+
+ for_each_available_child_of_node(dn, child) {
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: [PATCH v3 6/9] mtd: rawnand: brcmnand: Add platform data structure for BCMA
-Date: Fri, 07 Jan 2022 10:46:11 -0800
-Content-Type: text/plain; charset="utf-8"
-
-Update the BCMA's chipcommon nand flash driver to detect which
-chip-select is used and pass that information via platform data to the
-brcmnand driver. Make sure that the brcmnand platform data structure is
-always at the beginning of the platform data of the "nflash" device
-created by BCMA to allow brcmnand to safely de-reference it.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- MAINTAINERS | 1 +
- drivers/bcma/driver_chipcommon_nflash.c | 20 +++++++++++++++++++-
- include/linux/bcma/bcma_driver_chipcommon.h | 5 +++++
- include/linux/platform_data/brcmnand.h | 12 ++++++++++++
- 4 files changed, 37 insertions(+), 1 deletion(-)
- create mode 100644 include/linux/platform_data/brcmnand.h
-
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -3712,6 +3712,7 @@ L: linux-mtd@lists.infradead.org
- L: bcm-kernel-feedback-list@broadcom.com
- S: Maintained
- F: drivers/mtd/nand/raw/brcmnand/
-+F: include/linux/platform_data/brcmnand.h
-
- BROADCOM SYSTEMPORT ETHERNET DRIVER
- M: Florian Fainelli <f.fainelli@gmail.com>
---- a/drivers/bcma/driver_chipcommon_nflash.c
-+++ b/drivers/bcma/driver_chipcommon_nflash.c
-@@ -7,18 +7,28 @@
-
- #include "bcma_private.h"
-
-+#include <linux/bitops.h>
- #include <linux/platform_device.h>
-+#include <linux/platform_data/brcmnand.h>
- #include <linux/bcma/bcma.h>
-
-+/* Alternate NAND controller driver name in order to allow both bcm47xxnflash
-+ * and bcma_brcmnand to be built into the same kernel image.
-+ */
-+static const char *bcma_nflash_alt_name = "bcma_brcmnand";
-+
- struct platform_device bcma_nflash_dev = {
- .name = "bcma_nflash",
- .num_resources = 0,
- };
-
-+static const char *probes[] = { "bcm47xxpart", NULL };
-+
- /* Initialize NAND flash access */
- int bcma_nflash_init(struct bcma_drv_cc *cc)
- {
- struct bcma_bus *bus = cc->core->bus;
-+ u32 reg;
-
- if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 &&
- cc->core->id.rev != 38) {
-@@ -33,8 +43,16 @@ int bcma_nflash_init(struct bcma_drv_cc
-
- cc->nflash.present = true;
- if (cc->core->id.rev == 38 &&
-- (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT))
-+ (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)) {
- cc->nflash.boot = true;
-+ /* Determine the chip select that is being used */
-+ reg = bcma_cc_read32(cc, BCMA_CC_NAND_CS_NAND_SELECT) & 0xff;
-+ cc->nflash.brcmnand_info.chip_select = ffs(reg) - 1;
-+ cc->nflash.brcmnand_info.part_probe_types = probes;
-+ cc->nflash.brcmnand_info.ecc_stepsize = 512;
-+ cc->nflash.brcmnand_info.ecc_strength = 1;
-+ bcma_nflash_dev.name = bcma_nflash_alt_name;
-+ }
-
- /* Prepare platform device, but don't register it yet. It's too early,
- * malloc (required by device_private_init) is not available yet. */
---- a/include/linux/bcma/bcma_driver_chipcommon.h
-+++ b/include/linux/bcma/bcma_driver_chipcommon.h
-@@ -3,6 +3,7 @@
- #define LINUX_BCMA_DRIVER_CC_H_
-
- #include <linux/platform_device.h>
-+#include <linux/platform_data/brcmnand.h>
- #include <linux/gpio.h>
-
- /** ChipCommon core registers. **/
-@@ -599,6 +600,10 @@ struct bcma_sflash {
-
- #ifdef CONFIG_BCMA_NFLASH
- struct bcma_nflash {
-+ /* Must be the fist member for the brcmnand driver to
-+ * de-reference that structure.
-+ */
-+ struct brcmnand_platform_data brcmnand_info;
- bool present;
- bool boot; /* This is the flash the SoC boots from */
- };
---- /dev/null
-+++ b/include/linux/platform_data/brcmnand.h
-@@ -0,0 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0-only */
-+#ifndef BRCMNAND_PLAT_DATA_H
-+#define BRCMNAND_PLAT_DATA_H
-+
-+struct brcmnand_platform_data {
-+ int chip_select;
-+ const char * const *part_probe_types;
-+ unsigned int ecc_stepsize;
-+ unsigned int ecc_strength;
-+};
-+
-+#endif /* BRCMNAND_PLAT_DATA_H */
--- /dev/null
+From: Florian Fainelli <f.fainelli@gmail.com>
+Subject: [PATCH v3 6/9] mtd: rawnand: brcmnand: Add platform data structure for BCMA
+Date: Fri, 07 Jan 2022 10:46:11 -0800
+Content-Type: text/plain; charset="utf-8"
+
+Update the BCMA's chipcommon nand flash driver to detect which
+chip-select is used and pass that information via platform data to the
+brcmnand driver. Make sure that the brcmnand platform data structure is
+always at the beginning of the platform data of the "nflash" device
+created by BCMA to allow brcmnand to safely de-reference it.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ MAINTAINERS | 1 +
+ drivers/bcma/driver_chipcommon_nflash.c | 20 +++++++++++++++++++-
+ include/linux/bcma/bcma_driver_chipcommon.h | 5 +++++
+ include/linux/platform_data/brcmnand.h | 12 ++++++++++++
+ 4 files changed, 37 insertions(+), 1 deletion(-)
+ create mode 100644 include/linux/platform_data/brcmnand.h
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3712,6 +3712,7 @@ L: linux-mtd@lists.infradead.org
+ L: bcm-kernel-feedback-list@broadcom.com
+ S: Maintained
+ F: drivers/mtd/nand/raw/brcmnand/
++F: include/linux/platform_data/brcmnand.h
+
+ BROADCOM SYSTEMPORT ETHERNET DRIVER
+ M: Florian Fainelli <f.fainelli@gmail.com>
+--- a/drivers/bcma/driver_chipcommon_nflash.c
++++ b/drivers/bcma/driver_chipcommon_nflash.c
+@@ -7,18 +7,28 @@
+
+ #include "bcma_private.h"
+
++#include <linux/bitops.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/brcmnand.h>
+ #include <linux/bcma/bcma.h>
+
++/* Alternate NAND controller driver name in order to allow both bcm47xxnflash
++ * and bcma_brcmnand to be built into the same kernel image.
++ */
++static const char *bcma_nflash_alt_name = "bcma_brcmnand";
++
+ struct platform_device bcma_nflash_dev = {
+ .name = "bcma_nflash",
+ .num_resources = 0,
+ };
+
++static const char *probes[] = { "bcm47xxpart", NULL };
++
+ /* Initialize NAND flash access */
+ int bcma_nflash_init(struct bcma_drv_cc *cc)
+ {
+ struct bcma_bus *bus = cc->core->bus;
++ u32 reg;
+
+ if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 &&
+ cc->core->id.rev != 38) {
+@@ -33,8 +43,16 @@ int bcma_nflash_init(struct bcma_drv_cc
+
+ cc->nflash.present = true;
+ if (cc->core->id.rev == 38 &&
+- (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT))
++ (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)) {
+ cc->nflash.boot = true;
++ /* Determine the chip select that is being used */
++ reg = bcma_cc_read32(cc, BCMA_CC_NAND_CS_NAND_SELECT) & 0xff;
++ cc->nflash.brcmnand_info.chip_select = ffs(reg) - 1;
++ cc->nflash.brcmnand_info.part_probe_types = probes;
++ cc->nflash.brcmnand_info.ecc_stepsize = 512;
++ cc->nflash.brcmnand_info.ecc_strength = 1;
++ bcma_nflash_dev.name = bcma_nflash_alt_name;
++ }
+
+ /* Prepare platform device, but don't register it yet. It's too early,
+ * malloc (required by device_private_init) is not available yet. */
+--- a/include/linux/bcma/bcma_driver_chipcommon.h
++++ b/include/linux/bcma/bcma_driver_chipcommon.h
+@@ -3,6 +3,7 @@
+ #define LINUX_BCMA_DRIVER_CC_H_
+
+ #include <linux/platform_device.h>
++#include <linux/platform_data/brcmnand.h>
+ #include <linux/gpio.h>
+
+ /** ChipCommon core registers. **/
+@@ -599,6 +600,10 @@ struct bcma_sflash {
+
+ #ifdef CONFIG_BCMA_NFLASH
+ struct bcma_nflash {
++ /* Must be the fist member for the brcmnand driver to
++ * de-reference that structure.
++ */
++ struct brcmnand_platform_data brcmnand_info;
+ bool present;
+ bool boot; /* This is the flash the SoC boots from */
+ };
+--- /dev/null
++++ b/include/linux/platform_data/brcmnand.h
+@@ -0,0 +1,12 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++#ifndef BRCMNAND_PLAT_DATA_H
++#define BRCMNAND_PLAT_DATA_H
++
++struct brcmnand_platform_data {
++ int chip_select;
++ const char * const *part_probe_types;
++ unsigned int ecc_stepsize;
++ unsigned int ecc_strength;
++};
++
++#endif /* BRCMNAND_PLAT_DATA_H */
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: [PATCH v3 7/9] mtd: rawnand: brcmnand: Allow platform data instantation
-Date: Fri, 07 Jan 2022 10:46:12 -0800
-Content-Type: text/plain; charset="utf-8"
-
-Make use of the recently refactored code in brcmnand_init_cs() and
-derive the chip-select from the platform data that is supplied. Update
-the various code paths to avoid relying on possibly non-existent
-resources, too.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 45 ++++++++++++++++++------
- 1 file changed, 35 insertions(+), 10 deletions(-)
-
---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-@@ -9,6 +9,7 @@
- #include <linux/delay.h>
- #include <linux/device.h>
- #include <linux/platform_device.h>
-+#include <linux/platform_data/brcmnand.h>
- #include <linux/err.h>
- #include <linux/completion.h>
- #include <linux/interrupt.h>
-@@ -2719,7 +2720,8 @@ static const struct nand_controller_ops
- .attach_chip = brcmnand_attach_chip,
- };
-
--static int brcmnand_init_cs(struct brcmnand_host *host)
-+static int brcmnand_init_cs(struct brcmnand_host *host,
-+ const char * const *part_probe_types)
- {
- struct brcmnand_controller *ctrl = host->ctrl;
- struct device *dev = ctrl->dev;
-@@ -2772,7 +2774,7 @@ static int brcmnand_init_cs(struct brcmn
- if (ret)
- return ret;
-
-- ret = mtd_device_register(mtd, NULL, 0);
-+ ret = mtd_device_parse_register(mtd, part_probe_types, NULL, NULL, 0);
- if (ret)
- nand_cleanup(chip);
-
-@@ -2941,17 +2943,15 @@ static int brcmnand_edu_setup(struct pla
-
- int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
- {
-+ struct brcmnand_platform_data *pd = dev_get_platdata(&pdev->dev);
- struct device *dev = &pdev->dev;
- struct device_node *dn = dev->of_node, *child;
- struct brcmnand_controller *ctrl;
-+ struct brcmnand_host *host;
- struct resource *res;
- int ret;
-
-- /* We only support device-tree instantiation */
-- if (!dn)
-- return -ENODEV;
--
-- if (!of_match_node(brcmnand_of_match, dn))
-+ if (dn && !of_match_node(brcmnand_of_match, dn))
- return -ENODEV;
-
- ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
-@@ -2978,7 +2978,7 @@ int brcmnand_probe(struct platform_devic
- /* NAND register range */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ctrl->nand_base = devm_ioremap_resource(dev, res);
-- if (IS_ERR(ctrl->nand_base))
-+ if (IS_ERR(ctrl->nand_base) && !brcmnand_soc_has_ops(soc))
- return PTR_ERR(ctrl->nand_base);
-
- /* Enable clock before using NAND registers */
-@@ -3122,7 +3122,6 @@ int brcmnand_probe(struct platform_devic
-
- for_each_available_child_of_node(dn, child) {
- if (of_device_is_compatible(child, "brcm,nandcs")) {
-- struct brcmnand_host *host;
-
- host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
- if (!host) {
-@@ -3142,7 +3141,7 @@ int brcmnand_probe(struct platform_devic
-
- nand_set_flash_node(&host->chip, child);
-
-- ret = brcmnand_init_cs(host);
-+ ret = brcmnand_init_cs(host, NULL);
- if (ret) {
- devm_kfree(dev, host);
- continue; /* Try all chip-selects */
-@@ -3152,6 +3151,32 @@ int brcmnand_probe(struct platform_devic
- }
- }
-
-+ if (!list_empty(&ctrl->host_list))
-+ return 0;
-+
-+ if (!pd) {
-+ ret = -ENODEV;
-+ goto err;
-+ }
-+
-+ /* If we got there we must have been probing via platform data */
-+ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
-+ if (!host) {
-+ ret = -ENOMEM;
-+ goto err;
-+ }
-+ host->pdev = pdev;
-+ host->ctrl = ctrl;
-+ host->cs = pd->chip_select;
-+ host->chip.ecc.size = pd->ecc_stepsize;
-+ host->chip.ecc.strength = pd->ecc_strength;
-+
-+ ret = brcmnand_init_cs(host, pd->part_probe_types);
-+ if (ret)
-+ goto err;
-+
-+ list_add_tail(&host->node, &ctrl->host_list);
-+
- /* No chip-selects could initialize properly */
- if (list_empty(&ctrl->host_list)) {
- ret = -ENODEV;
--- /dev/null
+From: Florian Fainelli <f.fainelli@gmail.com>
+Subject: [PATCH v3 7/9] mtd: rawnand: brcmnand: Allow platform data instantation
+Date: Fri, 07 Jan 2022 10:46:12 -0800
+Content-Type: text/plain; charset="utf-8"
+
+Make use of the recently refactored code in brcmnand_init_cs() and
+derive the chip-select from the platform data that is supplied. Update
+the various code paths to avoid relying on possibly non-existent
+resources, too.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 45 ++++++++++++++++++------
+ 1 file changed, 35 insertions(+), 10 deletions(-)
+
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -9,6 +9,7 @@
+ #include <linux/delay.h>
+ #include <linux/device.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/brcmnand.h>
+ #include <linux/err.h>
+ #include <linux/completion.h>
+ #include <linux/interrupt.h>
+@@ -2719,7 +2720,8 @@ static const struct nand_controller_ops
+ .attach_chip = brcmnand_attach_chip,
+ };
+
+-static int brcmnand_init_cs(struct brcmnand_host *host)
++static int brcmnand_init_cs(struct brcmnand_host *host,
++ const char * const *part_probe_types)
+ {
+ struct brcmnand_controller *ctrl = host->ctrl;
+ struct device *dev = ctrl->dev;
+@@ -2772,7 +2774,7 @@ static int brcmnand_init_cs(struct brcmn
+ if (ret)
+ return ret;
+
+- ret = mtd_device_register(mtd, NULL, 0);
++ ret = mtd_device_parse_register(mtd, part_probe_types, NULL, NULL, 0);
+ if (ret)
+ nand_cleanup(chip);
+
+@@ -2941,17 +2943,15 @@ static int brcmnand_edu_setup(struct pla
+
+ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
+ {
++ struct brcmnand_platform_data *pd = dev_get_platdata(&pdev->dev);
+ struct device *dev = &pdev->dev;
+ struct device_node *dn = dev->of_node, *child;
+ struct brcmnand_controller *ctrl;
++ struct brcmnand_host *host;
+ struct resource *res;
+ int ret;
+
+- /* We only support device-tree instantiation */
+- if (!dn)
+- return -ENODEV;
+-
+- if (!of_match_node(brcmnand_of_match, dn))
++ if (dn && !of_match_node(brcmnand_of_match, dn))
+ return -ENODEV;
+
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+@@ -2978,7 +2978,7 @@ int brcmnand_probe(struct platform_devic
+ /* NAND register range */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ctrl->nand_base = devm_ioremap_resource(dev, res);
+- if (IS_ERR(ctrl->nand_base))
++ if (IS_ERR(ctrl->nand_base) && !brcmnand_soc_has_ops(soc))
+ return PTR_ERR(ctrl->nand_base);
+
+ /* Enable clock before using NAND registers */
+@@ -3122,7 +3122,6 @@ int brcmnand_probe(struct platform_devic
+
+ for_each_available_child_of_node(dn, child) {
+ if (of_device_is_compatible(child, "brcm,nandcs")) {
+- struct brcmnand_host *host;
+
+ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
+ if (!host) {
+@@ -3142,7 +3141,7 @@ int brcmnand_probe(struct platform_devic
+
+ nand_set_flash_node(&host->chip, child);
+
+- ret = brcmnand_init_cs(host);
++ ret = brcmnand_init_cs(host, NULL);
+ if (ret) {
+ devm_kfree(dev, host);
+ continue; /* Try all chip-selects */
+@@ -3152,6 +3151,32 @@ int brcmnand_probe(struct platform_devic
+ }
+ }
+
++ if (!list_empty(&ctrl->host_list))
++ return 0;
++
++ if (!pd) {
++ ret = -ENODEV;
++ goto err;
++ }
++
++ /* If we got there we must have been probing via platform data */
++ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
++ if (!host) {
++ ret = -ENOMEM;
++ goto err;
++ }
++ host->pdev = pdev;
++ host->ctrl = ctrl;
++ host->cs = pd->chip_select;
++ host->chip.ecc.size = pd->ecc_stepsize;
++ host->chip.ecc.strength = pd->ecc_strength;
++
++ ret = brcmnand_init_cs(host, pd->part_probe_types);
++ if (ret)
++ goto err;
++
++ list_add_tail(&host->node, &ctrl->host_list);
++
+ /* No chip-selects could initialize properly */
+ if (list_empty(&ctrl->host_list)) {
+ ret = -ENODEV;
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: [PATCH v3 8/9] mtd: rawnand: brcmnand: BCMA controller uses command shift of 0
-Date: Fri, 07 Jan 2022 10:46:13 -0800
-Content-Type: text/plain; charset="utf-8"
-
-For some odd and unexplained reason the BCMA NAND controller, albeit
-revision 3.4 uses a command shift of 0 instead of 24 as it should be,
-quirk that.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-@@ -913,6 +913,12 @@ static void brcmnand_wr_corr_thresh(stru
-
- static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl)
- {
-+ /* Kludge for the BCMA-based NAND controller which does not actually
-+ * shift the command
-+ */
-+ if (ctrl->nand_version == 0x0304 && brcmnand_non_mmio_ops(ctrl))
-+ return 0;
-+
- if (ctrl->nand_version < 0x0602)
- return 24;
- return 0;
--- /dev/null
+From: Florian Fainelli <f.fainelli@gmail.com>
+Subject: [PATCH v3 8/9] mtd: rawnand: brcmnand: BCMA controller uses command shift of 0
+Date: Fri, 07 Jan 2022 10:46:13 -0800
+Content-Type: text/plain; charset="utf-8"
+
+For some odd and unexplained reason the BCMA NAND controller, albeit
+revision 3.4 uses a command shift of 0 instead of 24 as it should be,
+quirk that.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -913,6 +913,12 @@ static void brcmnand_wr_corr_thresh(stru
+
+ static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl)
+ {
++ /* Kludge for the BCMA-based NAND controller which does not actually
++ * shift the command
++ */
++ if (ctrl->nand_version == 0x0304 && brcmnand_non_mmio_ops(ctrl))
++ return 0;
++
+ if (ctrl->nand_version < 0x0602)
+ return 24;
+ return 0;
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: [PATCH v3 9/9] mtd: rawnand: brcmnand: Add BCMA shim
-Date: Fri, 07 Jan 2022 10:46:14 -0800
-Content-Type: text/plain; charset="utf-8"
-
-Add a BCMA shim to allow us to register the brcmnand driver using the
-BCMA bus which provides indirect memory mapped access to SoC registers.
-
-There are a number of registers that need to be byte swapped because
-they are natively big endian, coming directly from the NAND chip, and
-there is no bus interface unlike the iProc or STB platforms that
-performs the byte swapping for us.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/mtd/nand/raw/Kconfig | 13 +++
- drivers/mtd/nand/raw/brcmnand/Makefile | 2 +
- drivers/mtd/nand/raw/brcmnand/bcma_nand.c | 132 ++++++++++++++++++++++
- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 +
- 4 files changed, 151 insertions(+)
- create mode 100644 drivers/mtd/nand/raw/brcmnand/bcma_nand.c
-
---- a/drivers/mtd/nand/raw/Kconfig
-+++ b/drivers/mtd/nand/raw/Kconfig
-@@ -236,6 +236,19 @@ config MTD_NAND_BRCMNAND
- originally designed for Set-Top Box but is used on various BCM7xxx,
- BCM3xxx, BCM63xxx, iProc/Cygnus and more.
-
-+if MTD_NAND_BRCMNAND
-+
-+config MTD_NAND_BRCMNAND_BCMA
-+ tristate "Broadcom BCMA NAND controller"
-+ depends on BCMA_NFLASH
-+ depends on BCMA
-+ help
-+ Enables the BRCMNAND controller over BCMA on BCM47186/BCM5358 SoCs.
-+ The glue driver will take care of performing the low-level I/O
-+ operations to interface the BRCMNAND controller over the BCMA bus.
-+
-+endif # MTD_NAND_BRCMNAND
-+
- config MTD_NAND_BCM47XXNFLASH
- tristate "BCM4706 BCMA NAND controller"
- depends on BCMA_NFLASH
---- a/drivers/mtd/nand/raw/brcmnand/Makefile
-+++ b/drivers/mtd/nand/raw/brcmnand/Makefile
-@@ -6,3 +6,5 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6
- obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6368_nand.o
- obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
- obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
-+
-+obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMA) += bcma_nand.o
---- /dev/null
-+++ b/drivers/mtd/nand/raw/brcmnand/bcma_nand.c
-@@ -0,0 +1,132 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copyright © 2021 Broadcom
-+ */
-+#include <linux/bcma/bcma.h>
-+#include <linux/bcma/bcma_driver_chipcommon.h>
-+#include <linux/device.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+
-+#include "brcmnand.h"
-+
-+struct brcmnand_bcma_soc {
-+ struct brcmnand_soc soc;
-+ struct bcma_drv_cc *cc;
-+};
-+
-+static inline bool brcmnand_bcma_needs_swapping(u32 offset)
-+{
-+ switch (offset) {
-+ case BCMA_CC_NAND_SPARE_RD0:
-+ case BCMA_CC_NAND_SPARE_RD4:
-+ case BCMA_CC_NAND_SPARE_RD8:
-+ case BCMA_CC_NAND_SPARE_RD12:
-+ case BCMA_CC_NAND_SPARE_WR0:
-+ case BCMA_CC_NAND_SPARE_WR4:
-+ case BCMA_CC_NAND_SPARE_WR8:
-+ case BCMA_CC_NAND_SPARE_WR12:
-+ case BCMA_CC_NAND_DEVID:
-+ case BCMA_CC_NAND_DEVID_X:
-+ case BCMA_CC_NAND_SPARE_RD16:
-+ case BCMA_CC_NAND_SPARE_RD20:
-+ case BCMA_CC_NAND_SPARE_RD24:
-+ case BCMA_CC_NAND_SPARE_RD28:
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+static inline struct brcmnand_bcma_soc *to_bcma_soc(struct brcmnand_soc *soc)
-+{
-+ return container_of(soc, struct brcmnand_bcma_soc, soc);
-+}
-+
-+static u32 brcmnand_bcma_read_reg(struct brcmnand_soc *soc, u32 offset)
-+{
-+ struct brcmnand_bcma_soc *sc = to_bcma_soc(soc);
-+ u32 val;
-+
-+ /* Offset into the NAND block and deal with the flash cache separately */
-+ if (offset == BRCMNAND_NON_MMIO_FC_ADDR)
-+ offset = BCMA_CC_NAND_CACHE_DATA;
-+ else
-+ offset += BCMA_CC_NAND_REVISION;
-+
-+ val = bcma_cc_read32(sc->cc, offset);
-+
-+ /* Swap if necessary */
-+ if (brcmnand_bcma_needs_swapping(offset))
-+ val = be32_to_cpu(val);
-+ return val;
-+}
-+
-+static void brcmnand_bcma_write_reg(struct brcmnand_soc *soc, u32 val,
-+ u32 offset)
-+{
-+ struct brcmnand_bcma_soc *sc = to_bcma_soc(soc);
-+
-+ /* Offset into the NAND block */
-+ if (offset == BRCMNAND_NON_MMIO_FC_ADDR)
-+ offset = BCMA_CC_NAND_CACHE_DATA;
-+ else
-+ offset += BCMA_CC_NAND_REVISION;
-+
-+ /* Swap if necessary */
-+ if (brcmnand_bcma_needs_swapping(offset))
-+ val = cpu_to_be32(val);
-+
-+ bcma_cc_write32(sc->cc, offset, val);
-+}
-+
-+static struct brcmnand_io_ops brcmnand_bcma_io_ops = {
-+ .read_reg = brcmnand_bcma_read_reg,
-+ .write_reg = brcmnand_bcma_write_reg,
-+};
-+
-+static void brcmnand_bcma_prepare_data_bus(struct brcmnand_soc *soc, bool prepare,
-+ bool is_param)
-+{
-+ struct brcmnand_bcma_soc *sc = to_bcma_soc(soc);
-+
-+ /* Reset the cache address to ensure we are already accessing the
-+ * beginning of a sub-page.
-+ */
-+ bcma_cc_write32(sc->cc, BCMA_CC_NAND_CACHE_ADDR, 0);
-+}
-+
-+static int brcmnand_bcma_nand_probe(struct platform_device *pdev)
-+{
-+ struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
-+ struct brcmnand_bcma_soc *soc;
-+
-+ soc = devm_kzalloc(&pdev->dev, sizeof(*soc), GFP_KERNEL);
-+ if (!soc)
-+ return -ENOMEM;
-+
-+ soc->cc = container_of(nflash, struct bcma_drv_cc, nflash);
-+ soc->soc.prepare_data_bus = brcmnand_bcma_prepare_data_bus;
-+ soc->soc.ops = &brcmnand_bcma_io_ops;
-+
-+ if (soc->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
-+ dev_err(&pdev->dev, "Use bcm47xxnflash for 4706!\n");
-+ return -ENODEV;
-+ }
-+
-+ return brcmnand_probe(pdev, &soc->soc);
-+}
-+
-+static struct platform_driver brcmnand_bcma_nand_driver = {
-+ .probe = brcmnand_bcma_nand_probe,
-+ .remove = brcmnand_remove,
-+ .driver = {
-+ .name = "bcma_brcmnand",
-+ .pm = &brcmnand_pm_ops,
-+ }
-+};
-+module_platform_driver(brcmnand_bcma_nand_driver);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_AUTHOR("Broadcom");
-+MODULE_DESCRIPTION("NAND controller driver glue for BCMA chips");
---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
-@@ -595,7 +595,11 @@ enum {
-
- static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
- {
-+#if IS_ENABLED(CONFIG_MTD_NAND_BRCMNAND_BCMA)
- return static_branch_unlikely(&brcmnand_soc_has_ops_key);
-+#else
-+ return false;
-+#endif
- }
-
- static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs)
--- /dev/null
+From: Florian Fainelli <f.fainelli@gmail.com>
+Subject: [PATCH v3 9/9] mtd: rawnand: brcmnand: Add BCMA shim
+Date: Fri, 07 Jan 2022 10:46:14 -0800
+Content-Type: text/plain; charset="utf-8"
+
+Add a BCMA shim to allow us to register the brcmnand driver using the
+BCMA bus which provides indirect memory mapped access to SoC registers.
+
+There are a number of registers that need to be byte swapped because
+they are natively big endian, coming directly from the NAND chip, and
+there is no bus interface unlike the iProc or STB platforms that
+performs the byte swapping for us.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/mtd/nand/raw/Kconfig | 13 +++
+ drivers/mtd/nand/raw/brcmnand/Makefile | 2 +
+ drivers/mtd/nand/raw/brcmnand/bcma_nand.c | 132 ++++++++++++++++++++++
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 +
+ 4 files changed, 151 insertions(+)
+ create mode 100644 drivers/mtd/nand/raw/brcmnand/bcma_nand.c
+
+--- a/drivers/mtd/nand/raw/Kconfig
++++ b/drivers/mtd/nand/raw/Kconfig
+@@ -236,6 +236,19 @@ config MTD_NAND_BRCMNAND
+ originally designed for Set-Top Box but is used on various BCM7xxx,
+ BCM3xxx, BCM63xxx, iProc/Cygnus and more.
+
++if MTD_NAND_BRCMNAND
++
++config MTD_NAND_BRCMNAND_BCMA
++ tristate "Broadcom BCMA NAND controller"
++ depends on BCMA_NFLASH
++ depends on BCMA
++ help
++ Enables the BRCMNAND controller over BCMA on BCM47186/BCM5358 SoCs.
++ The glue driver will take care of performing the low-level I/O
++ operations to interface the BRCMNAND controller over the BCMA bus.
++
++endif # MTD_NAND_BRCMNAND
++
+ config MTD_NAND_BCM47XXNFLASH
+ tristate "BCM4706 BCMA NAND controller"
+ depends on BCMA_NFLASH
+--- a/drivers/mtd/nand/raw/brcmnand/Makefile
++++ b/drivers/mtd/nand/raw/brcmnand/Makefile
+@@ -6,3 +6,5 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6
+ obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6368_nand.o
+ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
+ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
++
++obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMA) += bcma_nand.o
+--- /dev/null
++++ b/drivers/mtd/nand/raw/brcmnand/bcma_nand.c
+@@ -0,0 +1,132 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright © 2021 Broadcom
++ */
++#include <linux/bcma/bcma.h>
++#include <linux/bcma/bcma_driver_chipcommon.h>
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include "brcmnand.h"
++
++struct brcmnand_bcma_soc {
++ struct brcmnand_soc soc;
++ struct bcma_drv_cc *cc;
++};
++
++static inline bool brcmnand_bcma_needs_swapping(u32 offset)
++{
++ switch (offset) {
++ case BCMA_CC_NAND_SPARE_RD0:
++ case BCMA_CC_NAND_SPARE_RD4:
++ case BCMA_CC_NAND_SPARE_RD8:
++ case BCMA_CC_NAND_SPARE_RD12:
++ case BCMA_CC_NAND_SPARE_WR0:
++ case BCMA_CC_NAND_SPARE_WR4:
++ case BCMA_CC_NAND_SPARE_WR8:
++ case BCMA_CC_NAND_SPARE_WR12:
++ case BCMA_CC_NAND_DEVID:
++ case BCMA_CC_NAND_DEVID_X:
++ case BCMA_CC_NAND_SPARE_RD16:
++ case BCMA_CC_NAND_SPARE_RD20:
++ case BCMA_CC_NAND_SPARE_RD24:
++ case BCMA_CC_NAND_SPARE_RD28:
++ return true;
++ }
++
++ return false;
++}
++
++static inline struct brcmnand_bcma_soc *to_bcma_soc(struct brcmnand_soc *soc)
++{
++ return container_of(soc, struct brcmnand_bcma_soc, soc);
++}
++
++static u32 brcmnand_bcma_read_reg(struct brcmnand_soc *soc, u32 offset)
++{
++ struct brcmnand_bcma_soc *sc = to_bcma_soc(soc);
++ u32 val;
++
++ /* Offset into the NAND block and deal with the flash cache separately */
++ if (offset == BRCMNAND_NON_MMIO_FC_ADDR)
++ offset = BCMA_CC_NAND_CACHE_DATA;
++ else
++ offset += BCMA_CC_NAND_REVISION;
++
++ val = bcma_cc_read32(sc->cc, offset);
++
++ /* Swap if necessary */
++ if (brcmnand_bcma_needs_swapping(offset))
++ val = be32_to_cpu(val);
++ return val;
++}
++
++static void brcmnand_bcma_write_reg(struct brcmnand_soc *soc, u32 val,
++ u32 offset)
++{
++ struct brcmnand_bcma_soc *sc = to_bcma_soc(soc);
++
++ /* Offset into the NAND block */
++ if (offset == BRCMNAND_NON_MMIO_FC_ADDR)
++ offset = BCMA_CC_NAND_CACHE_DATA;
++ else
++ offset += BCMA_CC_NAND_REVISION;
++
++ /* Swap if necessary */
++ if (brcmnand_bcma_needs_swapping(offset))
++ val = cpu_to_be32(val);
++
++ bcma_cc_write32(sc->cc, offset, val);
++}
++
++static struct brcmnand_io_ops brcmnand_bcma_io_ops = {
++ .read_reg = brcmnand_bcma_read_reg,
++ .write_reg = brcmnand_bcma_write_reg,
++};
++
++static void brcmnand_bcma_prepare_data_bus(struct brcmnand_soc *soc, bool prepare,
++ bool is_param)
++{
++ struct brcmnand_bcma_soc *sc = to_bcma_soc(soc);
++
++ /* Reset the cache address to ensure we are already accessing the
++ * beginning of a sub-page.
++ */
++ bcma_cc_write32(sc->cc, BCMA_CC_NAND_CACHE_ADDR, 0);
++}
++
++static int brcmnand_bcma_nand_probe(struct platform_device *pdev)
++{
++ struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
++ struct brcmnand_bcma_soc *soc;
++
++ soc = devm_kzalloc(&pdev->dev, sizeof(*soc), GFP_KERNEL);
++ if (!soc)
++ return -ENOMEM;
++
++ soc->cc = container_of(nflash, struct bcma_drv_cc, nflash);
++ soc->soc.prepare_data_bus = brcmnand_bcma_prepare_data_bus;
++ soc->soc.ops = &brcmnand_bcma_io_ops;
++
++ if (soc->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
++ dev_err(&pdev->dev, "Use bcm47xxnflash for 4706!\n");
++ return -ENODEV;
++ }
++
++ return brcmnand_probe(pdev, &soc->soc);
++}
++
++static struct platform_driver brcmnand_bcma_nand_driver = {
++ .probe = brcmnand_bcma_nand_probe,
++ .remove = brcmnand_remove,
++ .driver = {
++ .name = "bcma_brcmnand",
++ .pm = &brcmnand_pm_ops,
++ }
++};
++module_platform_driver(brcmnand_bcma_nand_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Broadcom");
++MODULE_DESCRIPTION("NAND controller driver glue for BCMA chips");
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -595,7 +595,11 @@ enum {
+
+ static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
+ {
++#if IS_ENABLED(CONFIG_MTD_NAND_BRCMNAND_BCMA)
+ return static_branch_unlikely(&brcmnand_soc_has_ops_key);
++#else
++ return false;
++#endif
+ }
+
+ static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs)