diff options
Diffstat (limited to 'target/linux/bcm47xx/patches-5.10/101-v5.18-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch')
-rw-r--r-- | target/linux/bcm47xx/patches-5.10/101-v5.18-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/target/linux/bcm47xx/patches-5.10/101-v5.18-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch b/target/linux/bcm47xx/patches-5.10/101-v5.18-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-v5.18-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); + |