Merge branch 'u-boot-nand-20241012' of https://source.denx.de/u-boot/custodians/u-boot-nand-flash

This merge request add support for BCMBCA raw nand driver for bcm96846
board that switch using OF_UPSTREAM and allow use onfi ecc params when
they are available in the atmel nand controller

The patches pass the pipeline CI:
https://source.denx.de/u-boot/custodians/u-boot-nand-flash/-/pipelines/22638
diff --git a/arch/arm/dts/bcm6846.dtsi b/arch/arm/dts/bcm6846.dtsi
deleted file mode 100644
index 8aa47a2..0000000
--- 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 <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-
-/ {
-	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 = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
-			<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
-			<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
-			<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
-		arm,cpu-registers-not-fw-configured;
-	};
-
-	pmu: pmu {
-		compatible = "arm,cortex-a7-pmu";
-		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
-			<GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
-		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 = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
-			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 = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
-			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 c70ebcc..0000000
--- 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 229ab88..1f5639f 100644
--- a/arch/arm/mach-bcmbca/bcm6846/Kconfig
+++ b/arch/arm/mach-bcmbca/bcm6846/Kconfig
@@ -8,6 +8,10 @@
 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
 
 config SYS_SOC
 	default "bcm6846"
diff --git a/configs/bcm96846_defconfig b/configs/bcm96846_defconfig
index ea643ed..877a606 100644
--- a/configs/bcm96846_defconfig
+++ b/configs/bcm96846_defconfig
@@ -9,14 +9,27 @@
 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
 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
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 9f3f126..c345fc1 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -120,6 +120,13 @@
 	  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/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
index ee4ec6d..817fab4 100644
--- a/drivers/mtd/nand/raw/atmel/nand-controller.c
+++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
@@ -1029,11 +1029,15 @@
 		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;
 
diff --git a/drivers/mtd/nand/raw/brcmnand/Makefile b/drivers/mtd/nand/raw/brcmnand/Makefile
index 0c6325a..24d0d56 100644
--- a/drivers/mtd/nand/raw/brcmnand/Makefile
+++ b/drivers/mtd/nand/raw/brcmnand/Makefile
@@ -6,6 +6,7 @@
 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 0000000..2753783
--- /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);
+}