aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm47xx/patches-5.15/108-v5.18-mtd-rawnand-brcmnand-Add-BCMA-shim.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm47xx/patches-5.15/108-v5.18-mtd-rawnand-brcmnand-Add-BCMA-shim.patch')
-rw-r--r--target/linux/bcm47xx/patches-5.15/108-v5.18-mtd-rawnand-brcmnand-Add-BCMA-shim.patch201
1 files changed, 201 insertions, 0 deletions
diff --git a/target/linux/bcm47xx/patches-5.15/108-v5.18-mtd-rawnand-brcmnand-Add-BCMA-shim.patch b/target/linux/bcm47xx/patches-5.15/108-v5.18-mtd-rawnand-brcmnand-Add-BCMA-shim.patch
new file mode 100644
index 0000000000..eabb4c2475
--- /dev/null
+++ b/target/linux/bcm47xx/patches-5.15/108-v5.18-mtd-rawnand-brcmnand-Add-BCMA-shim.patch
@@ -0,0 +1,201 @@
+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)