aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm47xx/patches-5.10/101-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm47xx/patches-5.10/101-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch')
-rw-r--r--target/linux/bcm47xx/patches-5.10/101-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch150
1 files changed, 150 insertions, 0 deletions
diff --git a/target/linux/bcm47xx/patches-5.10/101-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch b/target/linux/bcm47xx/patches-5.10/101-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch
new file mode 100644
index 0000000000..23f5df3015
--- /dev/null
+++ b/target/linux/bcm47xx/patches-5.10/101-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch
@@ -0,0 +1,150 @@
+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);
+