From 1db2aadd8415778f05616e5bc1f1a7500ef7a40a Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Sun, 21 Jul 2024 23:45:52 +0200 Subject: [PATCH 1/5] mtd: nand: raw: atmel: Use ONFI ECC params if available When ECC parameters are not specified in DT, first try ONFI ECC parameters before fallback to maximum strength. It's the Linux driver behavior since the driver rewriting in f88fc12. From then 2 nand system refactors have been done in 6a1b66d6 and 53576c7b, chip->ecc_strength_ds and chip->ecc_step_ds became nanddev_get_ecc_requirements(). U-Boot didn't follow the refactor and always use these 2 fields. v2: Fix formatting, add upstream commit hash. Signed-off-by: Zixun LI Reviewed-by: Michael Trimarchi Acked-by: Balamanikandan Gunasundar --- drivers/mtd/nand/raw/atmel/nand-controller.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index ee4ec6da587..817fab4ca36 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1029,11 +1029,15 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip) req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; else if (chip->ecc.strength) req.ecc.strength = chip->ecc.strength; + else if (chip->ecc_strength_ds) + req.ecc.strength = chip->ecc_strength_ds; else req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; if (chip->ecc.size) req.ecc.sectorsize = chip->ecc.size; + else if (chip->ecc_step_ds) + req.ecc.sectorsize = chip->ecc_step_ds; else req.ecc.sectorsize = ATMEL_PMECC_SECTOR_SIZE_AUTO; From a49519539abd5e47eb14d665385222b9ba6f87d4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 11 Oct 2024 16:49:54 +0200 Subject: [PATCH 2/5] mtd: rawnand: brcmnand: Add BCMBCA RAW NAND driver The Broadcom BCA platforms are broadband access SoCs. This is a port of the upstream Linux driver to U-Boot. It was based on drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c from Linux v6.11. Reviewed-by: Michael Trimarchi Signed-off-by: Linus Walleij --- 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(+) create mode 100644 drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 9f3f1267cbd..c345fc1f1fb 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 0c6325aaa61..24d0d568449 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 00000000000..2753783ae70 --- /dev/null +++ b/drivers/mtd/nand/raw/brcmnand/bcmbca_nand.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} From 8439ab9b3d11672728f46d508b7a86c9e070ea4b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 11 Oct 2024 16:49:55 +0200 Subject: [PATCH 3/5] drivers: nand: bcmbca: Enable on BCM6846 The BCM6846 has the BRCMBCA NAND controller so enable it. Reviewed-by: Michael Trimarchi Signed-off-by: Linus Walleij --- arch/arm/mach-bcmbca/bcm6846/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-bcmbca/bcm6846/Kconfig b/arch/arm/mach-bcmbca/bcm6846/Kconfig index 229ab88dbb0..5ef9535369e 100644 --- a/arch/arm/mach-bcmbca/bcm6846/Kconfig +++ b/arch/arm/mach-bcmbca/bcm6846/Kconfig @@ -8,6 +8,9 @@ if BCM6846 config TARGET_BCM96846 bool "Broadcom 6846 Reference Board" depends on ARCH_BCMBCA + imply MTD_RAW_NAND + imply NAND_BRCMNAND + imply NAND_BRCMNAND_BCMBCA config SYS_SOC default "bcm6846" From 4c6f2ab29a27c9efd349dbe9d86c9e3c3d6f65bb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 11 Oct 2024 16:49:56 +0200 Subject: [PATCH 4/5] board: bcm96846: Enable NAND options This adds reasonable NAND options to the BCM96846 reference design: - CMD_NAND, MTD_RAW_NAND - Disable SYS_NAND_ONFI_DETECTION as this just give error messages - MTD, MTDPARTS with DM and related config options - CMD_UBI and CMD_UBIFS as this is likely used with ubi/ubifs What I didn't add was something like the following: CONFIG_MTDPARTS_DEFAULT="nand0:256k(cfi),257024k(image)" Because I don't actually have a BCM96846 reference design. These are only available to Broadcom and their customers I think, but perhaps the people at Broadcom can provide the detail of the flash layout for BCM96846 so we can add this too so the bcm96846_config is usable out of the box. Signed-off-by: Linus Walleij --- configs/bcm96846_defconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/configs/bcm96846_defconfig b/configs/bcm96846_defconfig index ea643eddcc6..2f94bd29512 100644 --- a/configs/bcm96846_defconfig +++ b/configs/bcm96846_defconfig @@ -18,5 +18,17 @@ CONFIG_OF_STDOUT_VIA_ALIAS=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_HUSH_PARSER=y CONFIG_CMD_CACHE=y +CONFIG_CMD_NAND=y +CONFIG_CMD_UBI=y +CONFIG_CMD_UBIFS=y +CONFIG_CMD_BOOTZ=y +CONFIG_CMD_MTDPARTS=y CONFIG_OF_EMBED=y CONFIG_CLK=y +CONFIG_MTD=y +CONFIG_MTDIDS_DEFAULT="nand0=nand0" +CONFIG_DM_MTD=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_UBI_FASTMAP=y +CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT=1 +CONFIG_SYS_NAND_ONFI_DETECTION=n From 25e46f8281075d3b3a8d393264ff1cd33f8815b3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 11 Oct 2024 16:49:57 +0200 Subject: [PATCH 5/5] board: bcm96846: Switch to using OF_UPSTREAM This board clearly develops first in Linux which had more hardware listed, so let's start to use OF_UPSTREAM. This makes the NAND driver work. Suggested-by: Neil Armstrong Signed-off-by: Linus Walleij --- arch/arm/dts/bcm6846.dtsi | 103 --------------------------- arch/arm/dts/bcm96846.dts | 30 -------- arch/arm/mach-bcmbca/bcm6846/Kconfig | 1 + configs/bcm96846_defconfig | 3 +- 4 files changed, 3 insertions(+), 134 deletions(-) delete mode 100644 arch/arm/dts/bcm6846.dtsi delete mode 100644 arch/arm/dts/bcm96846.dts diff --git a/arch/arm/dts/bcm6846.dtsi b/arch/arm/dts/bcm6846.dtsi deleted file mode 100644 index 8aa47a2583b..00000000000 --- a/arch/arm/dts/bcm6846.dtsi +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright 2022 Broadcom Ltd. - */ - -#include -#include - -/ { - compatible = "brcm,bcm6846", "brcm,bcmbca"; - #address-cells = <1>; - #size-cells = <1>; - - interrupt-parent = <&gic>; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - CA7_0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a7"; - reg = <0x0>; - next-level-cache = <&L2_0>; - enable-method = "psci"; - }; - - CA7_1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a7"; - reg = <0x1>; - next-level-cache = <&L2_0>; - enable-method = "psci"; - }; - - L2_0: l2-cache0 { - compatible = "cache"; - }; - }; - - timer { - compatible = "arm,armv7-timer"; - interrupts = , - , - , - ; - arm,cpu-registers-not-fw-configured; - }; - - pmu: pmu { - compatible = "arm,cortex-a7-pmu"; - interrupts = , - ; - interrupt-affinity = <&CA7_0>, <&CA7_1>; - }; - - clocks: clocks { - periph_clk: periph-clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <200000000>; - }; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - axi@81000000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0x81000000 0x8000>; - - gic: interrupt-controller@1000 { - compatible = "arm,cortex-a7-gic"; - #interrupt-cells = <3>; - interrupt-controller; - interrupts = ; - reg = <0x1000 0x1000>, - <0x2000 0x2000>, - <0x4000 0x2000>, - <0x6000 0x2000>; - }; - }; - - bus@ff800000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0xff800000 0x800000>; - - uart0: serial@640 { - compatible = "brcm,bcm6345-uart"; - reg = <0x640 0x1b>; - interrupts = ; - clocks = <&periph_clk>; - clock-names = "refclk"; - status = "disabled"; - }; - }; -}; diff --git a/arch/arm/dts/bcm96846.dts b/arch/arm/dts/bcm96846.dts deleted file mode 100644 index c70ebccabc1..00000000000 --- a/arch/arm/dts/bcm96846.dts +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright 2022 Broadcom Ltd. - */ - -/dts-v1/; - -#include "bcm6846.dtsi" - -/ { - model = "Broadcom BCM96846 Reference Board"; - compatible = "brcm,bcm96846", "brcm,bcm6846", "brcm,bcmbca"; - - aliases { - serial0 = &uart0; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - memory@0 { - device_type = "memory"; - reg = <0x0 0x08000000>; - }; -}; - -&uart0 { - status = "okay"; -}; diff --git a/arch/arm/mach-bcmbca/bcm6846/Kconfig b/arch/arm/mach-bcmbca/bcm6846/Kconfig index 5ef9535369e..1f5639f46df 100644 --- a/arch/arm/mach-bcmbca/bcm6846/Kconfig +++ b/arch/arm/mach-bcmbca/bcm6846/Kconfig @@ -8,6 +8,7 @@ if BCM6846 config TARGET_BCM96846 bool "Broadcom 6846 Reference Board" depends on ARCH_BCMBCA + imply OF_UPSTREAM imply MTD_RAW_NAND imply NAND_BRCMNAND imply NAND_BRCMNAND_BCMBCA diff --git a/configs/bcm96846_defconfig b/configs/bcm96846_defconfig index 2f94bd29512..877a606a965 100644 --- a/configs/bcm96846_defconfig +++ b/configs/bcm96846_defconfig @@ -9,11 +9,12 @@ CONFIG_TARGET_BCM96846=y CONFIG_NR_DRAM_BANKS=1 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x2000000 -CONFIG_DEFAULT_DEVICE_TREE="bcm96846" +CONFIG_DEFAULT_DEVICE_TREE="broadcom/bcm96846" CONFIG_SYS_BOOTM_LEN=0x4000000 CONFIG_SYS_LOAD_ADDR=0x01000000 CONFIG_IDENT_STRING=" Broadcom BCM6846" CONFIG_ENV_VARS_UBOOT_CONFIG=y +CONFIG_OF_UPSTREAM=y CONFIG_OF_STDOUT_VIA_ALIAS=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_HUSH_PARSER=y