Skip to contentSkip to conversation

mtd: nand: add Broadcom NAND controller support

PATCH Superseded Brian Norris 2 participants 6 messages Mar 19, 2015

Subsystems (4)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v2 cover mtd: nand: add Broadcom NAND controller support

Hi,

This is version 2 of the (long in coming) support for the Broadcom BCM7xxx Set-Top Box NAND controller. This controller has been used in a variety of Broadcom SoCs.

There are a few more features I'd like add in the near future, mostly to support more SoCs, but this is the base set, which should only need relatively minor additions to support chips like BCM63138, BCM3384, and Cygnus/iProc. Particularly, we may need to straighten out some endianness issues for the data path on iProc, and interrupt enabling/acking on iProc, BCM63xxx, BCM3xxx, and others.

I think I've addressed everybody's comments, but the delta changelog is:

v1 -> v2:
* add NAND to DTS for BCM7445 / BCM97445SVMB
* rename DT binding file to have 'brcm,' prefix
* catch DMA mapping errors
* fixup timeout / error messages (hex, remove misleading info)
* MODULE_LICENSE("GPL v2")
* fix incorrect comments
* print why we fail, when checking for supported controller revisions
* disable prefetch when using Flash DMA (see FIXME); will re-enable once we get a good erased-page verification scheme merged

To be clear: this does NOT yet handle some of the per-SoC quirks required for BCM53xxx/BCM4708 and Cygnus/iProc. Those patches are still WIP, and I want to keep this patch series going while the Cygnus guys are straightening this out.

Happy reviewing!

Brian

Brian Norris (4):
mtd: nand: add common DT init code
Documentation: devicetree: add binding doc for Broadcom NAND
controller
mtd: nand: add NAND driver for Broadcom STB NAND controller
ARM: bcm7445: add NAND to DTS

 .../devicetree/bindings/mtd/brcm,brcmstb-nand.txt  |  109 +
 arch/arm/boot/dts/bcm7445-bcm97445svmb.dts         |   23 +
 arch/arm/boot/dts/bcm7445.dtsi                     |   22 +
 drivers/mtd/nand/Kconfig                           |    8 +
 drivers/mtd/nand/Makefile                          |    1 +
 drivers/mtd/nand/brcmstb_nand.c                    | 2196 ++++++++++++++++++++
 drivers/mtd/nand/nand_base.c                       |   41 +
 include/linux/mtd/nand.h                           |    5 +
 8 files changed, 2405 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/brcm,brcmstb-nand.txt
 create mode 100644 drivers/mtd/nand/brcmstb_nand.c
Signature · 1 line
1.9.1
#1 lore raw

PATCH v2 1/4 mtd: nand: add common DT init code

These are already-documented common bindings for NAND chips. Let's handle them in nand_base.

If NAND controller drivers need to act on this data before bringing up the NAND chip (e.g., fill out ECC callback functions, change HW modes, etc.), then they can do so between calling nand_scan_ident() and nand_scan_tail().

---
 drivers/mtd/nand/nand_base.c | 41 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/nand.h     |  5 +++++
 2 files changed, 46 insertions(+)
drivers/mtd/nand/nand_base.c +41 -0
index d4cec2f8a016..692142da62e7 100644
@@ -48,6 +48,7 @@
 #include <linux/leds.h>
 #include <linux/io.h>
 #include <linux/mtd/partitions.h>
+#include <linux/of_mtd.h>
 
 /* Define default oob placement schemes for large and small page devices */
 static struct nand_ecclayout nand_oob_8 = {
@@ -3779,6 +3780,39 @@ ident_done:
 	return type;
 }
 
+static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip,
+			struct device_node *dn)
+{
+	int ecc_mode, ecc_strength, ecc_step;
+
+	if (of_get_nand_bus_width(dn) == 16)
+		chip->options |= NAND_BUSWIDTH_16;
+
+	if (of_get_nand_on_flash_bbt(dn))
+		chip->bbt_options |= NAND_BBT_USE_FLASH;
+
+	ecc_mode = of_get_nand_ecc_mode(dn);
+	ecc_strength = of_get_nand_ecc_strength(dn);
+	ecc_step = of_get_nand_ecc_step_size(dn);
+
+	if ((ecc_step >= 0 && !(ecc_strength >= 0)) ||
+	    (!(ecc_step >= 0) && ecc_strength >= 0)) {
+		pr_err("must set both strength and step size in DT\n");
+		return -EINVAL;
+	}
+
+	if (ecc_mode >= 0)
+		chip->ecc.mode = ecc_mode;
+
+	if (ecc_strength >= 0)
+		chip->ecc.strength = ecc_strength;
+
+	if (ecc_step > 0)
+		chip->ecc.size = ecc_step;
+
+	return 0;
+}
+
 /**
  * nand_scan_ident - [NAND Interface] Scan for the NAND device
  * @mtd: MTD device structure
@@ -3796,6 +3830,13 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 	int i, nand_maf_id, nand_dev_id;
 	struct nand_chip *chip = mtd->priv;
 	struct nand_flash_dev *type;
+	int ret;
+
+	if (chip->dn) {
+		ret = nand_dt_init(mtd, chip, chip->dn);
+		if (ret)
+			return ret;
+	}
 
 	/* Set the default functions */
 	nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
include/linux/mtd/nand.h +5 -0
index 3d4ea7eb2b68..e0f40e12a2c8 100644
@@ -26,6 +26,8 @@
 
 struct mtd_info;
 struct nand_flash_dev;
+struct device_node;
+
 /* Scan and identify a NAND device */
 extern int nand_scan(struct mtd_info *mtd, int max_chips);
 /*
@@ -542,6 +544,7 @@ struct nand_buffers {
  *			flash device
  * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the
  *			flash device.
+ * @dn:			[BOARDSPECIFIC] device node describing this instance
  * @read_byte:		[REPLACEABLE] read one byte from the chip
  * @read_word:		[REPLACEABLE] read one word from the chip
  * @write_byte:		[REPLACEABLE] write a single byte to the chip on the
@@ -644,6 +647,8 @@ struct nand_chip {
 	void __iomem *IO_ADDR_R;
 	void __iomem *IO_ADDR_W;
 
+	struct device_node *dn;
+
 	uint8_t (*read_byte)(struct mtd_info *mtd);
 	u16 (*read_word)(struct mtd_info *mtd);
 	void (*write_byte)(struct mtd_info *mtd, uint8_t byte);
Signature · 1 line
1.9.1
#2 lore raw

PATCH v2 2/4 Documentation: devicetree: add binding doc for Broadcom NAND controller

In reply to Brian Norris
---
 .../devicetree/bindings/mtd/brcm,brcmstb-nand.txt  | 109 +++++++++++++++++++++
 1 file changed, 109 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/brcm,brcmstb-nand.txt
Documentation/devicetree/bindings/mtd/brcm,brcmstb-nand.txt new file +109 -0
new file mode 100644
index 000000000000..933d44943cbb
@@ -0,0 +1,109 @@
+* Broadcom STB NAND Controller
+
+The Broadcom Set-Top Box NAND controller supports low-level access to raw NAND
+flash chips. It has a memory-mapped register interface for both control
+registers and for its data input/output buffer. On some SoCs, this controller is
+paired with a custom DMA engine (inventively named "Flash DMA") which supports
+basic PROGRAM and READ functions, among other features.
+
+This controller was originally designed for STB SoCs (BCM7xxx) but is now
+available on a variety of Broadcom SoCs, including some BCM3xxx, BCM63xx, and
+iProc/Cygnus. Its history includes several similar (but not fully register
+compatible) versions.
+
+Required properties:
+- compatible       : should contain "brcm,brcmnand" and an appropriate version
+                      compatibility string, like "brcm,brcmnand-v7.0"
+                      Possible values:
+                         brcm,brcmnand-v4.0
+                         brcm,brcmnand-v5.0
+                         brcm,brcmnand-v6.0
+                         brcm,brcmnand-v7.0
+                         brcm,brcmnand-v7.1
+                         brcm,brcmnand
+- reg              : the register start and length for NAND register region.
+                     (optional) Flash DMA register range (if present)
+                     (optional) NAND flash cache range (if at non-standard offset)
+- reg-names        : a list of the names corresponding to the previous register
+                     ranges. Should contain "nand" and (optionally)
+                     "flash-dma" and/or "nand-cache".
+- interrupts       : The NAND CTLRDY interrupt and (if Flash DMA is available)
+                     FLASH_DMA_DONE
+- interrupt-names  : May be "nand_ctlrdy" or "flash_dma_done"
+- interrupt-parent : See standard interrupt bindings
+- #address-cells   : <1> - subnodes give the chip-select number
+- #size-cells      : <0>
+
+Optional properties:
+- brcm,nand-has-wp          : Some versions of this IP include a write-protect
+                              (WP) control bit. It is always available on >=
+                              v7.0. Use this property to describe the rare
+                              earlier versions of this core that include WP
+
+* NAND chip-select
+
+Each controller (compatible: "brcm,brcmnand") may contain one or more subnodes
+to represent enabled chip-selects which (may) contain NAND flash chips. Their
+properties are as follows.
+
+Required properties:
+- compatible                : should contain "brcm,nandcs"
+- reg                       : a single integer representing the chip-select
+                              number (e.g., 0, 1, 2, etc.)
+- #address-cells            : see partition.txt
+- #size-cells               : see partition.txt
+- nand-ecc-strength         : see nand.txt
+- nand-ecc-step-size        : must be 512 or 1024. See nand.txt
+
+Optional properties:
+- nand-on-flash-bbt         : boolean, to enable the on-flash BBT for this
+                              chip-select. See nand.txt
+- brcm,nand-oob-sector-size : integer, to denote the spare area sector size
+                              expected for the ECC layout in use. This size, in
+                              addition to the strength and step-size,
+                              determines how the hardware BCH engine will lay
+                              out the parity bytes it stores on the flash.
+                              This property can be automatically determined by
+                              the flash geometry (particularly the NAND page
+                              and OOB size) in many cases, but when booting
+                              from NAND, the boot controller has only a limited
+                              number of available options for its default ECC
+                              layout.
+
+Each nandcs device node may optionally contain sub-nodes describing the flash
+partition mapping. See partition.txt for more detail.
+
+Example:
+
+nand@f0442800 {
+	compatible = "brcm,brcmnand-v7.0", "brcm,brcmnand";
+	reg = <0xF0442800 0x600>,
+	      <0xF0443000 0x100>;
+	reg-names = "nand", "flash-dma";
+	interrupt-parent = <&hif_intr2_intc>;
+	interrupts = <24>, <4>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	nandcs@1 {
+		compatible = "brcm,nandcs";
+		reg = <1>; // Chip select 1
+		nand-on-flash-bbt;
+		nand-ecc-strength = <12>;
+		nand-ecc-step-size = <512>;
+
+		// Partitions
+		#address-cells = <1>;  // <2>, for 64-bit offset
+		#size-cells = <1>;     // <2>, for 64-bit length
+		flash0.rootfs@0 {
+			reg = <0 0x10000000>;
+		};
+		flash0@0 {
+			reg = <0 0>; // MTDPART_SIZ_FULL
+		};
+		flash0.kernel@10000000 {
+			reg = <0x10000000 0x400000>;
+		};
+	};
+};
Signature · 6 lines
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#3 lore raw

PATCH v2 3/4 mtd: nand: add NAND driver for Broadcom STB NAND controller

In reply to Brian Norris

This core originated in Set-Top Box chips (BCM7xxx) but is used in a variety of other Broadcom chips, including some BCM63xxx, BCM33xx, and iProc/Cygnus. It's been used only on ARM and MIPS SoCs, so restrict it to those architectures.

There are multiple revisions of this core throughout the years, and almost every version broke register compatibility in some small way, but with some effort, this driver is able to support v4.0, v5.0, v6.x, v7.0, and v7.1. It's been tested on v5.0, v6.0, v7.0, and v7.1 recently, so there hopefully are no more lurking inconsistencies.

---
 drivers/mtd/nand/Kconfig        |    8 +
 drivers/mtd/nand/Makefile       |    1 +
 drivers/mtd/nand/brcmstb_nand.c | 2196 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 2205 insertions(+)
 create mode 100644 drivers/mtd/nand/brcmstb_nand.c
drivers/mtd/nand/Kconfig +8 -0
index 5b76a173cd95..6445323a8cff 100644
@@ -394,6 +394,14 @@ config MTD_NAND_GPMI_NAND
 	 block, such as SD card. So pay attention to it when you enable
 	 the GPMI.
 
+config MTD_NAND_BRCMSTB
+	tristate "Broadcom STB NAND controller"
+	depends on ARM || MIPS
+	help
+	  Enables the Broadcom NAND controller driver. The controller was
+	  originally designed for Set-Top Box but is used on various BCM7xxx,
+	  BCM3xxx, BCM63xxx, iProc/Cygnus and more.
+
 config MTD_NAND_BCM47XXNFLASH
 	tristate "Support for NAND flash on BCM4706 BCMA bus"
 	depends on BCMA_NFLASH
drivers/mtd/nand/Makefile +1 -0
index 582bbd05aff7..3b1adddc83dd 100644
@@ -52,5 +52,6 @@ obj-$(CONFIG_MTD_NAND_XWAY)		+= xway_nand.o
 obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)	+= bcm47xxnflash/
 obj-$(CONFIG_MTD_NAND_SUNXI)		+= sunxi_nand.o
 obj-$(CONFIG_MTD_NAND_HISI504)	        += hisi504_nand.o
+obj-$(CONFIG_MTD_NAND_BRCMSTB)		+= brcmstb_nand.o
 
 nand-objs := nand_base.o nand_bbt.o nand_timings.o
drivers/mtd/nand/brcmstb_nand.c new file +2196 -0

2,196 lines not on this page · raw message

Signature · 1 line
1.9.1
Reviewed-by on v2 3/4
#4 lore raw

Re: [PATCH v2 3/4] mtd: nand: add NAND driver for Broadcom STB NAND controller

Quoted 5 lines · Brian Norris

This core originated in Set-Top Box chips (BCM7xxx) but is used in a variety of other Broadcom chips, including some BCM63xxx, BCM33xx, and iProc/Cygnus. It's been used only on ARM and MIPS SoCs, so restrict it to those architectures.

Quoted 7 lines

There are multiple revisions of this core throughout the years, and almost every version broke register compatibility in some small way, but with some effort, this driver is able to support v4.0, v5.0, v6.x, v7.0, and v7.1. It's been tested on v5.0, v6.0, v7.0, and v7.1 recently, so there hopefully are no more lurking inconsistencies.

Signature · 1 line
Florian
#5 lore raw

PATCH v2 4/4 ARM: bcm7445: add NAND to DTS

In reply to Brian Norris

---
Light dependency on:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/331921.html
for the surrounding text.

 arch/arm/boot/dts/bcm7445-bcm97445svmb.dts | 23 +++++++++++++++++++++++
 arch/arm/boot/dts/bcm7445.dtsi             | 22 ++++++++++++++++++++++
 2 files changed, 45 insertions(+)
arch/arm/boot/dts/bcm7445-bcm97445svmb.dts +23 -0
index 9eec2ac1112f..0bb8d17e4c2d 100644
@@ -12,3 +12,26 @@
 		      <0x00 0x80000000 0x00 0x40000000>;
 	};
 };
+
+&nand {
+	status = "okay";
+
+	nandcs@1 {
+		compatible = "brcm,nandcs";
+		reg = <1>;
+		nand-ecc-step-size = <512>;
+		nand-ecc-strength = <8>;
+		nand-on-flash-bbt;
+
+		#size-cells = <2>;
+		#address-cells = <2>;
+
+		flash1.rootfs0@0 {
+			reg = <0x0 0x0 0x0 0x80000000>;
+		};
+
+		flash1.rootfs1@80000000 {
+			reg = <0x0 0x80000000 0x0 0x80000000>;
+		};
+	};
+};
arch/arm/boot/dts/bcm7445.dtsi +22 -0
index 9eaeac8dce1b..c148dcf8c69b 100644
@@ -108,6 +108,28 @@
 			brcm,int-map-mask = <0x25c>, <0x7000000>;
 			brcm,int-fwd-mask = <0x70000>;
 		};
+
+		hif_intr2_intc: interrupt-controller@3e1000 {
+			compatible = "brcm,l2-intc";
+			reg = <0x3e1000 0x30>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupts = <0x0 0x20 0x0>;
+			interrupt-parent = <&gic>;
+			interrupt-names = "hif";
+		};
+
+		nand: nand@3e2800 {
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "brcm,brcmnand-v7.1", "brcm,brcmnand";
+			reg-names = "nand", "flash-dma";
+			reg = <0x3e2800 0x600>, <0x3e3000 0x2c>;
+			interrupt-parent = <&hif_intr2_intc>;
+			interrupts = <24>, <4>;
+			interrupt-names = "nand_ctlrdy", "flash_dma_done";
+		};
 	};
 
 	smpboot {
Signature · 6 lines
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html