123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- From: Florian Fainelli <[email protected]>
- 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 <[email protected]>
- ---
- 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
- @@ -208,6 +208,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
- @@ -627,7 +627,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)
|