Message ID | 20240930-bcmbca-nand-support-v1-1-e637c65de947@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | mtd: rawnand: brcmnand: Add BCMBCA support | expand |
Hi Linus On Mon, Sep 30, 2024 at 3:24 PM Linus Walleij <linus.walleij@linaro.org> wrote: > > The Broadcom BCA platforms are broadband access SoCs. > This is a port of the upstream Linux driver to U-Boot. > > Signed-off-by: Linus Walleij <linus.walleij@linaro.org> > --- > drivers/mtd/nand/raw/Kconfig | 7 ++ > drivers/mtd/nand/raw/brcmnand/Makefile | 1 + > drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c | 152 ++++++++++++++++++++++++++++ > 3 files changed, 160 insertions(+) > > diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig > index 9f3f1267cbd1..c345fc1f1fba 100644 > --- a/drivers/mtd/nand/raw/Kconfig > +++ b/drivers/mtd/nand/raw/Kconfig > @@ -120,6 +120,13 @@ config NAND_BRCMNAND > Enable the driver for NAND flash on platforms using a Broadcom NAND > controller. > > +config NAND_BRCMNAND_BCMBCA > + bool "Support Broadcom NAND controller on BCMBCA platforms" > + depends on NAND_BRCMNAND && ARCH_BCMBCA > + help > + Enable support for broadcom nand driver on BCA (broadband > + access) platforms such as BCM6846. > + > config NAND_BRCMNAND_6368 > bool "Support Broadcom NAND controller on bcm6368" > depends on NAND_BRCMNAND && ARCH_BMIPS > diff --git a/drivers/mtd/nand/raw/brcmnand/Makefile b/drivers/mtd/nand/raw/brcmnand/Makefile > index 0c6325aaa618..24d0d5684490 100644 > --- a/drivers/mtd/nand/raw/brcmnand/Makefile > +++ b/drivers/mtd/nand/raw/brcmnand/Makefile > @@ -6,6 +6,7 @@ obj-$(CONFIG_NAND_BRCMNAND_6753) += bcm6753_nand.o > obj-$(CONFIG_NAND_BRCMNAND_68360) += bcm68360_nand.o > obj-$(CONFIG_NAND_BRCMNAND_6838) += bcm6838_nand.o > obj-$(CONFIG_NAND_BRCMNAND_6858) += bcm6858_nand.o > +obj-$(CONFIG_NAND_BRCMNAND_BCMBCA) += bcmbca_nand.o > obj-$(CONFIG_NAND_BRCMNAND_IPROC) += iproc_nand.o > obj-$(CONFIG_NAND_BRCMNAND) += brcmnand.o > obj-$(CONFIG_NAND_BRCMNAND) += brcmnand_compat.o > diff --git a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c > new file mode 100644 > index 000000000000..2753783ae70f > --- /dev/null > +++ b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c > @@ -0,0 +1,152 @@ > +// SPDX-License-Identifier: GPL-2.0+ > + > +#include <asm/io.h> > +#include <memalign.h> > +#include <nand.h> > +#include <linux/bitops.h> > +#include <linux/err.h> > +#include <linux/errno.h> > +#include <linux/io.h> > +#include <linux/ioport.h> > +#include <dm.h> > +#include <linux/printk.h> > + > +#include "brcmnand.h" > + > +struct bcmbca_nand_soc { > + struct brcmnand_soc soc; > + void __iomem *base; > +}; > + > +#define BCMBCA_NAND_INT 0x00 > +#define BCMBCA_NAND_STATUS_SHIFT 0 > +#define BCMBCA_NAND_STATUS_MASK (0xfff << BCMBCA_NAND_STATUS_SHIFT) > + > +#define BCMBCA_NAND_INT_EN 0x04 > +#define BCMBCA_NAND_ENABLE_SHIFT 0 > +#define BCMBCA_NAND_ENABLE_MASK (0xffff << BCMBCA_NAND_ENABLE_SHIFT) > + > +enum { > + BCMBCA_NP_READ = BIT(0), > + BCMBCA_BLOCK_ERASE = BIT(1), > + BCMBCA_COPY_BACK = BIT(2), > + BCMBCA_PAGE_PGM = BIT(3), > + BCMBCA_CTRL_READY = BIT(4), > + BCMBCA_DEV_RBPIN = BIT(5), > + BCMBCA_ECC_ERR_UNC = BIT(6), > + BCMBCA_ECC_ERR_CORR = BIT(7), > +}; > + > +#if defined(CONFIG_ARM64) > +#define ALIGN_REQ 8 > +#else > +#define ALIGN_REQ 4 > +#endif > + > +static inline bool bcmbca_nand_is_buf_aligned(void *flash_cache, void *buffer) > +{ > + return IS_ALIGNED((uintptr_t)buffer, ALIGN_REQ) && > + IS_ALIGNED((uintptr_t)flash_cache, ALIGN_REQ); > +} > + > +static bool bcmbca_nand_intc_ack(struct brcmnand_soc *soc) > +{ > + struct bcmbca_nand_soc *priv = > + container_of(soc, struct bcmbca_nand_soc, soc); > + void __iomem *mmio = priv->base + BCMBCA_NAND_INT; > + u32 val = brcmnand_readl(mmio); > + > + if (val & (BCMBCA_CTRL_READY << BCMBCA_NAND_STATUS_SHIFT)) { > + /* Ack interrupt */ > + val &= ~BCMBCA_NAND_STATUS_MASK; > + val |= BCMBCA_CTRL_READY << BCMBCA_NAND_STATUS_SHIFT; > + brcmnand_writel(val, mmio); > + return true; > + } > + > + return false; > +} > + > +static void bcmbca_nand_intc_set(struct brcmnand_soc *soc, bool en) > +{ > + struct bcmbca_nand_soc *priv = > + container_of(soc, struct bcmbca_nand_soc, soc); > + void __iomem *mmio = priv->base + BCMBCA_NAND_INT_EN; > + u32 val = brcmnand_readl(mmio); > + > + /* Don't ack any interrupts */ > + val &= ~BCMBCA_NAND_STATUS_MASK; > + > + if (en) > + val |= BCMBCA_CTRL_READY << BCMBCA_NAND_ENABLE_SHIFT; > + else > + val &= ~(BCMBCA_CTRL_READY << BCMBCA_NAND_ENABLE_SHIFT); > + > + brcmnand_writel(val, mmio); > +} > + > +static void bcmbca_read_data_bus(struct brcmnand_soc *soc, > + void __iomem *flash_cache, u32 *buffer, int fc_words) > +{ > + /* > + * memcpy can do unaligned aligned access depending on source > + * and dest address, which is incompatible with nand cache. Fallback > + * to the memcpy_fromio in such case > + */ > + if (bcmbca_nand_is_buf_aligned((void __force *)flash_cache, buffer)) > + memcpy((void *)buffer, (void __force *)flash_cache, fc_words * 4); > + else > + memcpy_fromio((void *)buffer, flash_cache, fc_words * 4); > +} > + > +static int bcmbca_nand_probe(struct udevice *dev) > +{ > + struct udevice *pdev = dev; > + struct bcmbca_nand_soc *priv = dev_get_priv(dev); > + struct brcmnand_soc *soc; > + struct resource res; > + > + soc = &priv->soc; > + > + dev_read_resource_byname(pdev, "nand-int-base", &res); > + priv->base = devm_ioremap(dev, res.start, resource_size(&res)); > + if (IS_ERR(priv->base)) > + return PTR_ERR(priv->base); > + > + soc->ctlrdy_ack = bcmbca_nand_intc_ack; > + soc->ctlrdy_set_enabled = bcmbca_nand_intc_set; > + soc->read_data_bus = bcmbca_read_data_bus; > + > + /* Disable and ack all interrupts */ > + brcmnand_writel(0, priv->base + BCMBCA_NAND_INT_EN); > + brcmnand_writel(0, priv->base + BCMBCA_NAND_INT); > + > + return brcmnand_probe(pdev, soc); > +} > + > +static const struct udevice_id bcmbca_nand_dt_ids[] = { > + { > + .compatible = "brcm,nand-bcm63138", > + }, > + { /* sentinel */ } > +}; > + > +U_BOOT_DRIVER(bcmbca_nand) = { > + .name = "bcmbca-nand", > + .id = UCLASS_MTD, > + .of_match = bcmbca_nand_dt_ids, > + .probe = bcmbca_nand_probe, > + .priv_auto = sizeof(struct bcmbca_nand_soc), > +}; > + > +void board_nand_init(void) > +{ > + struct udevice *dev; > + int ret; > + > + ret = uclass_get_device_by_driver(UCLASS_MTD, > + DM_DRIVER_GET(bcmbca_nand), &dev); > + if (ret && ret != -ENODEV) > + pr_err("Failed to initialize %s. (error %d)\n", dev->name, > + ret); > +} We are trying to use log_err or log primitive in uboot otherwise. As a note I think that you keep basically from linux maybe if you can point me from what revision Reviewed-by: Michael Trimarchi <michael@amarulasolutions.com> > > -- > 2.46.1 >
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 9f3f1267cbd1..c345fc1f1fba 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -120,6 +120,13 @@ config NAND_BRCMNAND Enable the driver for NAND flash on platforms using a Broadcom NAND controller. +config NAND_BRCMNAND_BCMBCA + bool "Support Broadcom NAND controller on BCMBCA platforms" + depends on NAND_BRCMNAND && ARCH_BCMBCA + help + Enable support for broadcom nand driver on BCA (broadband + access) platforms such as BCM6846. + config NAND_BRCMNAND_6368 bool "Support Broadcom NAND controller on bcm6368" depends on NAND_BRCMNAND && ARCH_BMIPS diff --git a/drivers/mtd/nand/raw/brcmnand/Makefile b/drivers/mtd/nand/raw/brcmnand/Makefile index 0c6325aaa618..24d0d5684490 100644 --- a/drivers/mtd/nand/raw/brcmnand/Makefile +++ b/drivers/mtd/nand/raw/brcmnand/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_NAND_BRCMNAND_6753) += bcm6753_nand.o obj-$(CONFIG_NAND_BRCMNAND_68360) += bcm68360_nand.o obj-$(CONFIG_NAND_BRCMNAND_6838) += bcm6838_nand.o obj-$(CONFIG_NAND_BRCMNAND_6858) += bcm6858_nand.o +obj-$(CONFIG_NAND_BRCMNAND_BCMBCA) += bcmbca_nand.o obj-$(CONFIG_NAND_BRCMNAND_IPROC) += iproc_nand.o obj-$(CONFIG_NAND_BRCMNAND) += brcmnand.o obj-$(CONFIG_NAND_BRCMNAND) += brcmnand_compat.o diff --git a/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c new file mode 100644 index 000000000000..2753783ae70f --- /dev/null +++ b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <asm/io.h> +#include <memalign.h> +#include <nand.h> +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <dm.h> +#include <linux/printk.h> + +#include "brcmnand.h" + +struct bcmbca_nand_soc { + struct brcmnand_soc soc; + void __iomem *base; +}; + +#define BCMBCA_NAND_INT 0x00 +#define BCMBCA_NAND_STATUS_SHIFT 0 +#define BCMBCA_NAND_STATUS_MASK (0xfff << BCMBCA_NAND_STATUS_SHIFT) + +#define BCMBCA_NAND_INT_EN 0x04 +#define BCMBCA_NAND_ENABLE_SHIFT 0 +#define BCMBCA_NAND_ENABLE_MASK (0xffff << BCMBCA_NAND_ENABLE_SHIFT) + +enum { + BCMBCA_NP_READ = BIT(0), + BCMBCA_BLOCK_ERASE = BIT(1), + BCMBCA_COPY_BACK = BIT(2), + BCMBCA_PAGE_PGM = BIT(3), + BCMBCA_CTRL_READY = BIT(4), + BCMBCA_DEV_RBPIN = BIT(5), + BCMBCA_ECC_ERR_UNC = BIT(6), + BCMBCA_ECC_ERR_CORR = BIT(7), +}; + +#if defined(CONFIG_ARM64) +#define ALIGN_REQ 8 +#else +#define ALIGN_REQ 4 +#endif + +static inline bool bcmbca_nand_is_buf_aligned(void *flash_cache, void *buffer) +{ + return IS_ALIGNED((uintptr_t)buffer, ALIGN_REQ) && + IS_ALIGNED((uintptr_t)flash_cache, ALIGN_REQ); +} + +static bool bcmbca_nand_intc_ack(struct brcmnand_soc *soc) +{ + struct bcmbca_nand_soc *priv = + container_of(soc, struct bcmbca_nand_soc, soc); + void __iomem *mmio = priv->base + BCMBCA_NAND_INT; + u32 val = brcmnand_readl(mmio); + + if (val & (BCMBCA_CTRL_READY << BCMBCA_NAND_STATUS_SHIFT)) { + /* Ack interrupt */ + val &= ~BCMBCA_NAND_STATUS_MASK; + val |= BCMBCA_CTRL_READY << BCMBCA_NAND_STATUS_SHIFT; + brcmnand_writel(val, mmio); + return true; + } + + return false; +} + +static void bcmbca_nand_intc_set(struct brcmnand_soc *soc, bool en) +{ + struct bcmbca_nand_soc *priv = + container_of(soc, struct bcmbca_nand_soc, soc); + void __iomem *mmio = priv->base + BCMBCA_NAND_INT_EN; + u32 val = brcmnand_readl(mmio); + + /* Don't ack any interrupts */ + val &= ~BCMBCA_NAND_STATUS_MASK; + + if (en) + val |= BCMBCA_CTRL_READY << BCMBCA_NAND_ENABLE_SHIFT; + else + val &= ~(BCMBCA_CTRL_READY << BCMBCA_NAND_ENABLE_SHIFT); + + brcmnand_writel(val, mmio); +} + +static void bcmbca_read_data_bus(struct brcmnand_soc *soc, + void __iomem *flash_cache, u32 *buffer, int fc_words) +{ + /* + * memcpy can do unaligned aligned access depending on source + * and dest address, which is incompatible with nand cache. Fallback + * to the memcpy_fromio in such case + */ + if (bcmbca_nand_is_buf_aligned((void __force *)flash_cache, buffer)) + memcpy((void *)buffer, (void __force *)flash_cache, fc_words * 4); + else + memcpy_fromio((void *)buffer, flash_cache, fc_words * 4); +} + +static int bcmbca_nand_probe(struct udevice *dev) +{ + struct udevice *pdev = dev; + struct bcmbca_nand_soc *priv = dev_get_priv(dev); + struct brcmnand_soc *soc; + struct resource res; + + soc = &priv->soc; + + dev_read_resource_byname(pdev, "nand-int-base", &res); + priv->base = devm_ioremap(dev, res.start, resource_size(&res)); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + soc->ctlrdy_ack = bcmbca_nand_intc_ack; + soc->ctlrdy_set_enabled = bcmbca_nand_intc_set; + soc->read_data_bus = bcmbca_read_data_bus; + + /* Disable and ack all interrupts */ + brcmnand_writel(0, priv->base + BCMBCA_NAND_INT_EN); + brcmnand_writel(0, priv->base + BCMBCA_NAND_INT); + + return brcmnand_probe(pdev, soc); +} + +static const struct udevice_id bcmbca_nand_dt_ids[] = { + { + .compatible = "brcm,nand-bcm63138", + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(bcmbca_nand) = { + .name = "bcmbca-nand", + .id = UCLASS_MTD, + .of_match = bcmbca_nand_dt_ids, + .probe = bcmbca_nand_probe, + .priv_auto = sizeof(struct bcmbca_nand_soc), +}; + +void board_nand_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_DRIVER_GET(bcmbca_nand), &dev); + if (ret && ret != -ENODEV) + pr_err("Failed to initialize %s. (error %d)\n", dev->name, + ret); +}
The Broadcom BCA platforms are broadband access SoCs. This is a port of the upstream Linux driver to U-Boot. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> --- drivers/mtd/nand/raw/Kconfig | 7 ++ drivers/mtd/nand/raw/brcmnand/Makefile | 1 + drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c | 152 ++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+)