mtd: nand: add Broadcom NAND controller support
Subsystems (6)
v3 cover mtd: nand: add Broadcom NAND controller support
Hi,
This is version 3 of support for the Broadcom BCM7xxx Set-Top Box NAND controller. This controller has been used in a variety of Broadcom SoCs.
This series now adds support for a few new chips: BCM63138, and the iProc chip family. These add an additional 6 new patches to the original 4. If the only comments end up on the latter 6 patches, the first 4 might be worth merging independently.
Summary changelog:
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
v2 -> v3:
* rebase to v4.1-rc1
* add SoC-specific infrastructure, to help support other SoCs:
- add BCM63138 support
- add iProc/Cygnus support
* disable prefetch on v6.1
Brian Norris (8):
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
Documentation: devicetree: brcmstb_nand: add 'brcm,nand-soc' bindings
mtd: brcmstb_nand: add SoC-specific support
mtd: brcsmtb_nand_soc: add support for BCM63138
ARM: bcm63138: add NAND DT support
Ray Jui (2):
mtd: brcsmtb_nand_soc: add iProc support
ARM: dts: cygnus: Enable NAND support for Cygnus
.../devicetree/bindings/mtd/brcm,brcmstb-nand.txt | 147 ++ arch/arm/boot/dts/bcm-cygnus.dtsi | 20 + arch/arm/boot/dts/bcm63138.dtsi | 17 + arch/arm/boot/dts/bcm7445-bcm97445svmb.dts | 23 + arch/arm/boot/dts/bcm7445.dtsi | 22 + arch/arm/boot/dts/bcm958300k.dts | 16 + arch/arm/boot/dts/bcm963138dvt.dts | 12 + drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 2 + drivers/mtd/nand/brcmnand.h | 56 + drivers/mtd/nand/brcmstb_nand.c | 2263 ++++++++++++++++++++ drivers/mtd/nand/brcmstb_nand_soc.c | 244 +++ drivers/mtd/nand/nand_base.c | 41 + include/linux/mtd/nand.h | 5 + 14 files changed, 2876 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/brcm,brcmstb-nand.txt create mode 100644 drivers/mtd/nand/brcmnand.h create mode 100644 drivers/mtd/nand/brcmstb_nand.c create mode 100644 drivers/mtd/nand/brcmstb_nand_soc.c
Signature · 1 line
1.9.1
PATCH v3 1/10 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
@@ -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 = {
@@ -3798,6 +3799,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
@@ -3815,6 +3849,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
@@ -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 · 6 lines
1.9.1 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/
Re: [PATCH v3 01/10] mtd: nand: add common DT init code
Quoted 9 lines · Brian Norris
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()andnand_scan_tail().Signed-off-by Brian Norris <[email protected]>
Pushed just this patch to l2-mtd.git, since it's relatively uncontroversial and hasn't changed across the first three revisions. It should be of benefit to a few other driver writers out there that I've reviewed.
Brian
Quoted 104 lines
--- 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@@ -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 = {@@ -3798,6 +3799,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 @@ -3815,6 +3849,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@@ -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
PATCH v3 2/10 Documentation: devicetree: add binding doc for Broadcom NAND controller
In reply to Brian Norris--- .../devicetree/bindings/mtd/brcm,brcmstb-nand.txt | 110 +++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/brcm,brcmstb-nand.txt
Documentation/devicetree/bindings/mtd/brcm,brcmstb-nand.txt new file +110 -0
@@ -0,0 +1,110 @@ +* 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-v6.1 + 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 · 1 line
1.9.1
PATCH v3 3/10 mtd: nand: add NAND driver for Broadcom STB NAND controller
In reply to Brian NorrisThis 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 | 2198 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 2207 insertions(+) create mode 100644 drivers/mtd/nand/brcmstb_nand.c
drivers/mtd/nand/Kconfig +8 -0
@@ -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
@@ -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 +2198 -0
2,198 lines not on this page · raw message
Signature · 6 lines
1.9.1 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/
Re: [PATCH v3 03/10] mtd: nand: add NAND driver for Broadcom STB NAND controller
drivers/mtd/nand/brcmstb_nand.c line 363
Quoted 13 lines · On Wednesday 06 May 2015 10:59:47 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c new file +12
-0+ +static inline u32 nand_readreg (struct brcmnand_controller *ctrl,u32 offs) +{ +return __raw_readl (ctrl->nand_base + offs); +} + +static inline void nand_writereg (struct brcmnand_controller *ctrl,u32 offs, +u32 val) +{ +__raw_writel (val, ctrl->nand_base + offs); +} +
You had mentioned previously that there might be an endianess issue in this driver. I think this won't work on big-endian architectures other than MIPS, so it would be good to either list in the DT the endianess of the device and use appropriate accessors here, or hardcode it based on the architecture (using ioread32_be in big-endian mips, but readl elsewhere).
Using __raw_writel has another problem regarding the DMA capability of this driver, as it will not flush any write buffers or synchronize caches before sending data off to the device, so you risk data corruption. Also, the compiler can choose to split up the 32-bit word access into byte accesses, which on most hardware does not do what you want.
Arnd
Re: [PATCH v3 03/10] mtd: nand: add NAND driver for Broadcom STB NAND controller
Quoted 17 lines · Arnd Bergmann
drivers/mtd/nand/brcmstb_nand.c line 363
Quoted 13 lines · On Wednesday 06 May 2015 10:59:47 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c new file +12
-0+ +static inline u32 nand_readreg (struct brcmnand_controller *ctrl,u32 offs) +{ +return __raw_readl (ctrl->nand_base + offs); +} + +static inline void nand_writereg (struct brcmnand_controller *ctrl,u32 offs, +u32 val) +{ +__raw_writel (val, ctrl->nand_base + offs); +} +You had mentioned previously that there might be an endianess issue in this driver.
Might. I have a patch already, but I failed to boot a BE kernel, so I kept it out for now. If you don't mind, I'd prefer patching something like this once it's testable on ARM BE. This *is*, however, extensively tested on MIPS (LE and BE) and ARM (LE).
Quoted 4 lines
I think this won't work on big-endian architectures other than MIPS, so it would be good to either list in the DT the endianess of the device and use appropriate accessors here, or hardcode it based on the architecture (using
ioread32_bein big-endian mips, but readl elsewhere).
I suspect we wouldn't need a DT property but could just special-case MIPS BE, as you note.
Quoted 3 lines
Using
__raw_writelhas another problem regarding the DMA capability of this driver, as it will not flush any write buffers or synchronize caches before sending data off to the device, so you risk data corruption.
We use mb() before kicking off DMA or other commands.
Quoted 3 lines
Also, the
compiler can choose to split up the 32-bit word access into byte accesses, which on most hardware does not do what you want.
Huh? Wouldn't that break just about every driver in existence? And how is writel() any different than __raw_writel() in that regard? From include/asm-generic/io.h:
static inline void writel(u32 value, volatile void __iomem *addr)
{
__raw_writel(__cpu_to_le32(value), addr);
}And BTW, splitting isn't possible on ARM. Fromarch/arm/include/asm/io.h:
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
asm volatile("str %1, %0"
: "+Qo" (*(volatile u32 __force *)addr)
: "r" (val));
}Brian
Ray Jui
maintainerRe: [PATCH v3 03/10] mtd: nand: add NAND driver for Broadcom STB NAND controller
Quoted 19 lines · Brian Norris
Quoted 17 lines · Arnd Bergmann
drivers/mtd/nand/brcmstb_nand.c line 363
Quoted 13 lines · On Wednesday 06 May 2015 10:59:47 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c new file +12
-0+ +static inline u32 nand_readreg (struct brcmnand_controller *ctrl,u32 offs) +{ +return __raw_readl (ctrl->nand_base + offs); +} + +static inline void nand_writereg (struct brcmnand_controller *ctrl,u32 offs, +u32 val) +{ +__raw_writel (val, ctrl->nand_base + offs); +} +You had mentioned previously that there might be an endianess issue in this driver.
Quoted 4 lines
Might. I have a patch already, but I failed to boot a BE kernel, so I kept it out for now. If you don't mind, I'd prefer patching something like this once it's testable on ARM BE. This *is*, however, extensively tested on MIPS (LE and BE) and ARM (LE).
Correct, extensive test and pass all MTD test cases. We should eventually be able to test this on a working ARM BE platform, within the next couple months.
Quoted 31 lines
Quoted 5 lines
I think this won't work on big-endian architectures other than MIPS, so it would be good to either list in the DT the endianess of the device and use appropriate accessors here, or hardcode it based on the architecture (using
ioread32_bein big-endian mips, but readl elsewhere).I suspect we wouldn't need a DT property but could just special-case MIPS BE, as you note.
Quoted 3 lines
Using
__raw_writelhas another problem regarding the DMA capability of this driver, as it will not flush any write buffers or synchronize caches before sending data off to the device, so you risk data corruption.We use
mb()before kicking off DMA or other commands.Quoted 3 lines
Also, the
compiler can choose to split up the 32-bit word access into byte accesses, which on most hardware does not do what you want.Huh? Wouldn't that break just about every driver in existence? And how is
writel()any different than__raw_writel()in that regard? Frominclude/asm-generic/io.h:static inline void
writel(u32 value, volatile void __iomem *addr){ __raw_writel(__cpu_to_le32(value), addr); }And BTW, splitting isn't possible on ARM. From
arch/arm/include/asm/io.h:
Quoted 9 lines
static inline void
__raw_writel(u32 val, volatile void __iomem *addr){ asm volatile("str %1, %0" : "+Qo" (*(volatile u32 __force *)addr) : "r" (val)); }Brian
--
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
Re: [PATCH v3 03/10] mtd: nand: add NAND driver for Broadcom STB NAND controller
Quoted 21 lines · On Wednesday 06 May 2015 14:18:47 Ray Jui wrote:
Quoted 19 lines · Brian Norris
Quoted 17 lines · Arnd Bergmann
drivers/mtd/nand/brcmstb_nand.c line 363
Quoted 13 lines · On Wednesday 06 May 2015 10:59:47 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c new file +12
-0+ +static inline u32 nand_readreg (struct brcmnand_controller *ctrl,u32 offs) +{ +return __raw_readl (ctrl->nand_base + offs); +} + +static inline void nand_writereg (struct brcmnand_controller *ctrl,u32 offs, +u32 val) +{ +__raw_writel (val, ctrl->nand_base + offs); +} +You had mentioned previously that there might be an endianess issue in this driver.
Quoted 8 lines
Quoted 4 lines
Might. I have a patch already, but I failed to boot a BE kernel, so I kept it out for now. If you don't mind, I'd prefer patching something like this once it's testable on ARM BE. This *is*, however, extensively tested on MIPS (LE and BE) and ARM (LE).
Correct, extensive test and pass all MTD test cases. We should eventually be able to test this on a working ARM BE platform, within the next couple months.
I'm fine with not testing it on ARM, as long as the code is written in a way that is plausible to be correct and not obviously broken.
Quoted 7 lines
Quoted 7 lines
Quoted 4 lines
I think this won't work on big-endian architectures other than MIPS, so it would be good to either list in the DT the endianess of the device and use appropriate accessors here, or hardcode it based on the architecture (using
ioread32_bein big-endian mips, but readl elsewhere).I suspect we wouldn't need a DT property but could just special-case MIPS BE, as you note.
Ok
There is one twist here that I forgot to mention:
This loop in brcmnand_read_by_pio() and the respective one in brcmnand_write_by_pio():
+ if (likely(buf))
+ for (j = 0; j < FC_WORDS; j++, buf++)
+ *buf = brcmnand_read_fc(ctrl, j);
should be converted to use ioread32_rep(). There are two reasons for this:
a) accessing the flash data is inherently different from accessing an mmio register, and you want the bytes to end up in memory in the same order that they are in flash. ioread32_rep() uses __raw_readl() internally for this purpose, except on architectures that have a byte flipping hardware on the bus interface.
b) The implementation is optimized on ARM and will likely give you higher throughput than a manual loop using readl().
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
Using
__raw_writelhas another problem regarding the DMA capability of this driver, as it will not flush any write buffers or synchronize caches before sending data off to the device, so you risk data corruption.We use
mb()before kicking off DMA or other commands.
Ok, that should work, but will be a stronger barrier than necessary on some architectures. On ARM, mb() is 'dsb(); outer_sync();', while readl only needs a 'dsb()' and writel() can use dsb(st) that is slightly weaker than a full dsb().
Quoted 16 lines
Quoted 16 lines
Quoted 3 lines
Also, the
compiler can choose to split up the 32-bit word access into byte accesses, which on most hardware does not do what you want.Huh? Wouldn't that break just about every driver in existence? And how is
writel()any different than__raw_writel()in that regard? Frominclude/asm-generic/io.h:static inline void
writel(u32 value, volatile void __iomem *addr){ __raw_writel(__cpu_to_le32(value), addr); }And BTW, splitting isn't possible on ARM. From
arch/arm/include/asm/io.h:
Quoted 7 lines
Quoted 7 lines
static inline void
__raw_writel(u32 val, volatile void __iomem *addr){ asm volatile("str %1, %0" : "+Qo" (*(volatile u32 __force *)addr) : "r" (val)); }
Ah right, we changed that one to simplify KVM support. It used to just do a volatile store for __raw_* but use an assembly for writel_relaxed().
Arnd
Re: [PATCH v3 03/10] mtd: nand: add NAND driver for Broadcom STB NAND controller
Quoted 5 lines · Arnd Bergmann
Quoted 4 lines · On Wednesday 06 May 2015 14:18:47 Ray Jui wrote:
Quoted 2 lines · Brian Norris
Quoted 1 line · Arnd Bergmann
On Wednesday 06 May 2015 10:59:47 Brian Norris wrote:
[...]
Quoted 10 lines
There is one twist here that I forgot to mention:
This loop in
brcmnand_read_by_pio()and the respective one inbrcmnand_write_by_pio():drivers/mtd/nand/brcmstb_nand.c new file +3
-0+if (likely (buf)) +for (j =0 ; j <FC_WORDS ; j++, buf++) + *buf =brcmnand_read_fc (ctrl, j);should be converted to use
ioread32_rep().
Huh? That's completely wrong. You're assuming I have a single-register FIFO, when in fact, I have a memory-mapped hardware buffer. Maybe you're looking for memcpy_{to,from}io()? I see this is not optimized at all, though.
Quoted 6 lines
There are two reasons for
this:a) accessing the flash data is inherently different from accessing an mmio register, and you want the bytes to end up in memory in the same order that they are in flash.
Right, which is why it's a separate helper function in my driver, and it will stay with __raw_{read,write}l().
Quoted 6 lines
ioread32_rep()uses__raw_readl()
internally for this purpose, except on architectures that have a byte flipping hardware on the bus interface.b) The implementation is optimized on ARM and will likely give you higher throughput than a manual loop using
readl().
You suggested the wrong helper, and the "right" helper is *not* optimized. It even has comments saying "this needs to be optimized".
Quoted 35 lines
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
Using
__raw_writelhas another problem regarding the DMA capability of this driver, as it will not flush any write buffers or synchronize caches before sending data off to the device, so you risk data corruption.We use
mb()before kicking off DMA or other commands.Ok, that should work, but will be a stronger barrier than necessary on some architectures. On ARM,
mb()is 'dsb();outer_sync();', while readl only needs a 'dsb()' andwritel()can use dsb(st) that is slightly weaker than a fulldsb().Quoted 16 lines
Quoted 16 lines
Quoted 3 lines
Also, the
compiler can choose to split up the 32-bit word access into byte accesses, which on most hardware does not do what you want.Huh? Wouldn't that break just about every driver in existence? And how is
writel()any different than__raw_writel()in that regard? Frominclude/asm-generic/io.h:static inline void
writel(u32 value, volatile void __iomem *addr){ __raw_writel(__cpu_to_le32(value), addr); }And BTW, splitting isn't possible on ARM. From
arch/arm/include/asm/io.h:Quoted 7 lines
Quoted 7 lines
static inline void
__raw_writel(u32 val, volatile void __iomem *addr){ asm volatile("str %1, %0" : "+Qo" (*(volatile u32 __force *)addr) : "r" (val)); }
Quoted 2 lines
Ah right, we changed that one to simplify KVM support. It used to just do a volatile store for __raw_* but use an assembly for
writel_relaxed().
While the ARM case is rock-solid in my favor, I would appreciate an answer to the asm-generic case too; do you really expect that any sane compiler would break up word-aligned volatile stores into smaller (e.g., 8-bit) stores? As I said, I think that means every driver written in C is broken, not just the ones using your pet enemies, __raw_{read,write}l().
Brian
Re: [PATCH v3 03/10] mtd: nand: add NAND driver for Broadcom STB NAND controller
Quoted 16 lines · On Thursday 07 May 2015 11:52:11 Brian Norris wrote:
Quoted 5 lines · Arnd Bergmann
Quoted 4 lines · On Wednesday 06 May 2015 14:18:47 Ray Jui wrote:
Quoted 2 lines · Brian Norris
Quoted 1 line · Arnd Bergmann
On Wednesday 06 May 2015 10:59:47 Brian Norris wrote:
[...]
Quoted 9 lines
There is one twist here that I forgot to mention:
This loop in
brcmnand_read_by_pio()and the respective one inbrcmnand_write_by_pio():drivers/mtd/nand/brcmstb_nand.c new file +3
-0+if (likely (buf)) +for (j =0 ; j <FC_WORDS ; j++, buf++) + *buf =brcmnand_read_fc (ctrl, j);
Quoted 6 lines
Quoted 1 line
should be converted to use
ioread32_rep().Huh? That's completely wrong. You're assuming I have a single-register FIFO, when in fact, I have a memory-mapped hardware buffer. Maybe you're looking for memcpy_{to,from}io()? I see this is not optimized at all, though.
Ah, my mistake. So the brcmnand_read_fc() has to just keep using __raw_readl here, unlike the other accessors that should (on non-MIPS) use readl_relaxed or readl.
Quoted 10 lines
Quoted 7 lines
There are two reasons for
this:a) accessing the flash data is inherently different from accessing an mmio register, and you want the bytes to end up in memory in the same order that they are in flash.
Right, which is why it's a separate helper function in my driver, and it will stay with __raw_{read,write}l().
Ok.
Quoted 9 lines
Quoted 6 lines
ioread32_rep()uses__raw_readl()
internally for this purpose, except on architectures that have a byte flipping hardware on the bus interface.b) The implementation is optimized on ARM and will likely give you higher throughput than a manual loop using
readl().You suggested the wrong helper, and the "right" helper is *not* optimized. It even has comments saying "this needs to be optimized".
Yes, I was misreading the code and missed the fact that you implement a memcpy, not read-from-fifo in that loop. For the fifo case, the optimized implementation is in arch/arm/lib/io-readsl.S, while you are right that the ARM implementation of memcpy_fromio is pessimal by doing byte sized accesses, so don't use that. Your loop is fine.
Quoted 28 lines
Quoted 25 lines
Quoted 17 lines
Quoted 17 lines
Quoted 4 lines
Also, the
compiler can choose to split up the 32-bit word access into byte accesses, which on most hardware does not do what you want.Huh? Wouldn't that break just about every driver in existence? And how is
writel()any different than__raw_writel()in that regard? Frominclude/asm-generic/io.h:static inline void
writel(u32 value, volatile void __iomem *addr){ __raw_writel(__cpu_to_le32(value), addr); }And BTW, splitting isn't possible on ARM. From
arch/arm/include/asm/io.h:Quoted 7 lines
Quoted 7 lines
static inline void
__raw_writel(u32 val, volatile void __iomem *addr){ asm volatile("str %1, %0" : "+Qo" (*(volatile u32 __force *)addr) : "r" (val)); }Quoted 2 lines
Ah right, we changed that one to simplify KVM support. It used to just do a volatile store for __raw_* but use an assembly for
writel_relaxed().
Quoted 6 lines
While the ARM case is rock-solid in my favor, I would appreciate an answer to the asm-generic case too; do you really expect that any sane compiler would break up word-aligned volatile stores into smaller (e.g., 8-bit) stores? As I said, I think that means every driver written in C is broken, not just the ones using your pet enemies, __raw_{read,write}l().
Yes, we've had actual bugs in the past where it broke from one gcc release to the next. The reason it broke there was that the pointer was assigned (in violation of the C standard) from a pointer of smaller alignment. If you have code that does:
char __iomem *p1 = ...; void __iomem *p2 = p1; int __iomem *p3 = p2; u32 data = __raw_readl(p3);
then gcc may decide that it is not safe to do 32-bit aligned accesses because it does not know the alignment of p1.
Arnd
Re: [PATCH v3 03/10] mtd: nand: add NAND driver for Broadcom STB NAND controller
In reply to Arnd BergmannQuoted 11 lines · Arnd Bergmann
Quoted 10 lines · On Wednesday 06 May 2015 14:18:47 Ray Jui wrote:
Quoted 8 lines · Brian Norris
Quoted 2 lines · Arnd Bergmann
You had mentioned previously that there might be an endianess issue in this driver.
Might. I have a patch already, but I failed to boot a BE kernel, so I kept it out for now. If you don't mind, I'd prefer patching something like this once it's testable on ARM BE. This *is*, however, extensively tested on MIPS (LE and BE) and ARM (LE).
Quoted 6 lines
Quoted 3 lines
Correct, extensive test and pass all MTD test cases. We should eventually be able to test this on a working ARM BE platform, within the next couple months.
I'm fine with not testing it on ARM, as long as the code is written in a way that is plausible to be correct and not obviously broken.
Would this satisfy you?
From: Brian Norris <[email protected]>
Date: Tue, 5 May 2015 17:46:42 -0700
Subject: [PATCH] mtd: brcmstb_nand: fixup endianness assumptions
All users of this controller (MIPS or ARM) have previously used native I/O (__raw{read,write}l()) to access registers. This is normal for the MIPS case, where BMIPS chips often have a boot-strap that configures not only the CPU, but also all the busing, to use a given endianness. However, newer ARM cores support switching to big endian mode at runtime, which would leave us with different bus and CPU endianness. For these cases, we should use the endian-switching accessors, so we continue to access the NAND core in little endian mode.
Suggested by Arnd.
--- drivers/mtd/nand/brcmnand.h | 25 +++++++++++++++++++++++++ drivers/mtd/nand/brcmstb_nand.c | 8 ++++---- drivers/mtd/nand/brcmstb_nand_soc.c | 20 ++++++++++---------- 3 files changed, 39 insertions(+), 14 deletions(-)
drivers/mtd/nand/brcmnand.h +25 -0
@@ -53,4 +53,29 @@ static inline void brcmnand_soc_data_bus_unprepare(struct brcmnand_soc *soc) soc->prepare_data_bus(soc, false); } +static inline u32 brcmnand_readl (void __iomem *addr) +{ +/* +* MIPS endianness is configured by boot strap, which also reverses all +* bus endianness (i.e., big-endian CPU + big endian bus ==> native +* endian I/O). +* +* Other architectures (e.g., ARM) either do not support big endian, or +* else leave I/O in little endian mode. +*/ +if (IS_ENABLED (CONFIG_MIPS ) &&IS_ENABLED (__BIG_ENDIAN)) +return __raw_readl (addr); +else +return readl_relaxed (addr); +} + +static inline void brcmnand_writel (u32 val,void __iomem *addr) +{ +/* See brcmnand_readl() comments */ +if (IS_ENABLED (CONFIG_MIPS ) &&IS_ENABLED (__BIG_ENDIAN)) +__raw_writel (val, addr); +else +writel_relaxed (val, addr); +} +#endif /* __BRCMNAND_H__ */
drivers/mtd/nand/brcmstb_nand.c +4 -4
@@ -357,13 +357,13 @@ enum {static inline u32 nand_readreg (struct brcmnand_controller *ctrl,u32 offs) { -return __raw_readl (ctrl->nand_base + offs); +return brcmnand_readl (ctrl->nand_base + offs); }static inline void nand_writereg (struct brcmnand_controller *ctrl,u32 offs,u32 val) { -__raw_writel (val, ctrl->nand_base + offs); +brcmnand_writel (val, ctrl->nand_base + offs); }static int brcmnand_revision_init (struct brcmnand_controller *ctrl)
@@ -698,12 +698,12 @@ static inline bool flash_dma_buf_ok(const void *buf)static inline void flash_dma_writel (struct brcmnand_controller *ctrl,u8 offs,u32 val) { -__raw_writel (val, ctrl->flash_dma_base + offs); +brcmnand_writel (val, ctrl->flash_dma_base + offs); }static inline u32 flash_dma_readl (struct brcmnand_controller *ctrl,u8 offs) { -return __raw_readl (ctrl->flash_dma_base + offs); +return brcmnand_readl (ctrl->flash_dma_base + offs); }/* Low-level operation types: command, address, write, or read */
drivers/mtd/nand/brcmstb_nand_soc.c +10 -10
@@ -43,10 +43,10 @@ static bool bcm63138_nand_intc_ack(struct brcmnand_soc *soc) {struct bcm63138_nand_soc_priv *priv = soc->priv;void __iomem *mmio = priv->base +BCM63138_NAND_INT_STATUS ; -u32 val =__raw_readl (mmio); +u32 val =brcmnand_readl (mmio);if (val &BCM63138_CTLRDY ) { -__raw_writel (val & ~BCM63138_CTLRDY , mmio); +brcmnand_writel (val & ~BCM63138_CTLRDY , mmio);return true; }
@@ -57,14 +57,14 @@ static void bcm63138_nand_intc_set(struct brcmnand_soc *soc, bool en) {struct bcm63138_nand_soc_priv *priv = soc->priv;void __iomem *mmio = priv->base +BCM63138_NAND_INT_EN ; -u32 val =__raw_readl (mmio); +u32 val =brcmnand_readl (mmio);if (en) val |=BCM63138_CTLRDY ;else val &= ~BCM63138_CTLRDY ; -__raw_writel (val, mmio); +brcmnand_writel (val, mmio); }static int bcm63138_nand_soc_init (struct brcmnand_soc *soc)
@@ -110,10 +110,10 @@ static bool iproc_nand_intc_ack(struct brcmnand_soc *soc) {struct iproc_nand_soc_priv *priv = soc->priv;void __iomem *mmio = priv->ext_base +IPROC_NAND_CTLR_READY_OFFSET ; -u32 val =__raw_readl (mmio); +u32 val =brcmnand_readl (mmio);if (val &IPROC_NAND_CTLR_READY ) { -__raw_writel (IPROC_NAND_CTLR_READY , mmio); +brcmnand_writel (IPROC_NAND_CTLR_READY , mmio);return true; }
@@ -129,14 +129,14 @@ static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en)spin_lock_irqsave (&priv->idm_lock, flags); - val =__raw_readl (mmio); + val =brcmnand_readl (mmio);if (en) val |=IPROC_NAND_INT_CTRL_READ_ENABLE ;else val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE ; -__raw_writel (val, mmio); +brcmnand_writel (val, mmio);spin_unlock_irqrestore (&priv->idm_lock, flags); }
@@ -180,14 +180,14 @@ static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare)spin_lock_irqsave (&priv->idm_lock, flags); - val =__raw_readl (mmio); + val =brcmnand_readl (mmio);if (prepare) val |=IPROC_NAND_APB_LE_MODE ;else val &= ~IPROC_NAND_APB_LE_MODE ; -__raw_writel (val, mmio); +brcmnand_writel (val, mmio);spin_unlock_irqrestore (&priv->idm_lock, flags); }
Signature · 1 line
1.9.1
Re: [PATCH v3 03/10] mtd: nand: add NAND driver for Broadcom STB NAND controller
Quoted 16 lines · On Thursday 07 May 2015 19:01:13 Brian Norris wrote:
Would this satisfy you?
From: Brian Norris <[email protected]>
Date: Tue, 5 May 2015 17:46:42 -0700
Subject: [PATCH] mtd:brcmstb_nand: fixup endianness assumptionsAll users of this controller (MIPS or ARM) have previously used native I/O (__raw{read,write}l()) to access registers. This is normal for the MIPS case, where BMIPS chips often have a boot-strap that configures not only the CPU, but also all the busing, to use a given endianness. However, newer ARM cores support switching to big endian mode at runtime, which would leave us with different bus and CPU endianness. For these cases, we should use the endian-switching accessors, so we continue to access the NAND core in little endian mode.
Quoted 5 lines
Suggested by Arnd.
Signed-off-by Brian Norris <[email protected]>---
Yes, looks good, thanks!
Arnd
--
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
PATCH v3 4/10 ARM: bcm7445: add NAND to DTS
In reply to Brian Norris--- 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
@@ -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
@@ -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 = <GIC_SPI 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 · 1 line
1.9.1
PATCH v3 5/10 Documentation: devicetree: brcmstb_nand: add 'brcm,nand-soc' bindings
In reply to Brian Norris--- .../devicetree/bindings/mtd/brcm,brcmstb-nand.txt | 39 +++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/mtd/brcm,brcmstb-nand.txt +38 -1
@@ -30,7 +30,10 @@ Required properties: "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-names : For hardware without a dedicated 'brcm,nand-soc' node, may + be "nand_ctlrdy" or "flash_dma_done" + For hardware with a dedicated 'brcm,nand-soc' node for + breaking out individual interrupt types, may be "nand" - interrupt-parent : See standard interrupt bindings - #address-cells : <1> - subnodes give the chip-select number - #size-cells : <0>
@@ -40,6 +43,10 @@ Optional properties: (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 +- brcm,nand-soc : Phandle to SoC control node. This is necessary + for SoCs where NAND interrupts and bus + infrastructure are integrated in non-standard + ways. * NAND chip-select
@@ -74,6 +81,36 @@ Optional properties: Each nandcs device node may optionally contain sub-nodes describing the flash partition mapping. See partition.txt for more detail. + +* NAND SoC control node: + +The NAND controller is integrated differently on the variety of SoCs on which it +is found. Part of this integration involves providing status and enable bits +with which to control the 8 exposed NAND interrupts, as well as hardware for +configuring the endianness of the data bus. On some SoCs, these features are +handled via standard, modular components (e.g., their interrupts look like a +normal IRQ chip), but on others, they are controlled in unique and interesting +ways, sometimes with registers that lump multiple NAND-related functions +together. The former case can be described simply by the standard interrupts +properties in the main controller node. But for the latter exceptional cases, +we can describe these extra SoC-specific integration hardware via the following +node, referenced from the brcm,brcmnand node above. + + - compatible: Can be one of several SoC-specific strings. Each SoC may have + different requirements for its additional properties, as described below each + bullet point below. + + * "brcm,nand-soc-bcm63138" + - reg: (required) the 'NAND_INT_BASE' register range, with separate status + and enable registers + + * "brcm,nand-soc-iproc" + - reg: (required) the "IDM" register range, for interrupt enable and APB + bus access endianness configuration, and the "EXT" register range, + for interrupt status/ack. + - reg-names: (required) a list of the names corresponding to the previous + register ranges. Should contain "idm" and "ext". + Example: nand@f0442800 {
Signature · 1 line
1.9.1
PATCH v3 6/10 mtd: brcmstb_nand: add SoC-specific support
In reply to Brian NorrisThe STB NAND controller is integrated into various non-STB SoCs, and those SoCs integrate things like interrupts and busing differently. Add support for masking/clearing interrupts via a custom hook, as well as preparing/unpreparing the data bus for data transfers.
Does not support any new SoCs yet; support will be added incrementally.
--- drivers/mtd/nand/Makefile | 3 +- drivers/mtd/nand/brcmnand.h | 56 +++++++++++++++++++++++++++ drivers/mtd/nand/brcmstb_nand.c | 75 ++++++++++++++++++++++++++++++++++--- drivers/mtd/nand/brcmstb_nand_soc.c | 65 ++++++++++++++++++++++++++++++++ 4 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 drivers/mtd/nand/brcmnand.h create mode 100644 drivers/mtd/nand/brcmstb_nand_soc.c
drivers/mtd/nand/Makefile +2 -1
@@ -52,6 +52,7 @@ 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 +obj-$(CONFIG_MTD_NAND_BRCMSTB) += brcmnand.o +brcmnand-objs := brcmstb_nand.o brcmstb_nand_soc.o nand-objs := nand_base.o nand_bbt.o nand_timings.o
drivers/mtd/nand/brcmnand.h new file +56 -0
56 lines not on this page · raw message
drivers/mtd/nand/brcmstb_nand.c +70 -5
136 lines not on this page · raw message
drivers/mtd/nand/brcmstb_nand_soc.c new file +65 -0
65 lines not on this page · raw message
Signature · 1 line
1.9.1
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 21 lines · On Wednesday 06 May 2015 10:59:50 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c +20
-0+/* +* Some SoCs integrate this controller (e.g., its interrupt bits) in +* interesting ways +*/ +if (of_property_read_bool (dn,"brcm,nand-soc" )) { +struct device_node *soc_dn; + + soc_dn =of_parse_phandle (dn,"brcm,nand-soc" ,0 ); +if (!soc_dn) +return -ENODEV ; + + ctrl->soc =devm_brcmnand_probe_soc (dev, soc_dn); +if (!ctrl->soc) { +dev_err (dev,"could not probe SoC data\n" ); +of_node_put (soc_dn); +return -ENODEV ; + } + + ret =devm_request_irq (dev, ctrl->irq, brcmnand_irq,0 , +DRV_NAME , ctrl);
drivers/mtd/nand/brcmstb_nand.c static int brcmnand_probe(struct platform_device *pdev) · line 2191
Quoted 10 lines
drivers/mtd/nand/brcmstb_nand.c +10
-0+ +/* Enable interrupt */ + ctrl->soc->ctlrdy_set_enabled (ctrl->soc, true); + +of_node_put (soc_dn); + }else { +/* Use standard interrupt infrastructure */ + ret =devm_request_irq (dev, ctrl->irq, brcmnand_ctlrdy_irq,0 , +DRV_NAME , ctrl); + }
It looks to me like this should be handled as a nested irqchip, so the node you look up gets used as the "interrupt-parent" instead, making the behavior of this SoC transparent to the nand driver.
We recently merged nested irqdomain support as well, which might help here, or might not be needed.
Arnd
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 28 lines · Arnd Bergmann
Quoted 27 lines · On Wednesday 06 May 2015 10:59:50 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c +27
-0+/* +* Some SoCs integrate this controller (e.g., its interrupt bits) in +* interesting ways +*/ +if (of_property_read_bool (dn,"brcm,nand-soc" )) { +struct device_node *soc_dn; + + soc_dn =of_parse_phandle (dn,"brcm,nand-soc" ,0 ); +if (!soc_dn) +return -ENODEV ; + + ctrl->soc =devm_brcmnand_probe_soc (dev, soc_dn); +if (!ctrl->soc) { +dev_err (dev,"could not probe SoC data\n" ); +of_node_put (soc_dn); +return -ENODEV ; + } + + ret =devm_request_irq (dev, ctrl->irq, brcmnand_irq,0 , +DRV_NAME , ctrl); + +/* Enable interrupt */ + ctrl->soc->ctlrdy_set_enabled (ctrl->soc, true); + +of_node_put (soc_dn); + }else { +/* Use standard interrupt infrastructure */
Quoted 8 lines
drivers/mtd/nand/brcmstb_nand.c static int brcmnand_probe(struct platform_device *pdev) · line 2191
Quoted 4 lines
drivers/mtd/nand/brcmstb_nand.c +3
-0+ ret =devm_request_irq (dev, ctrl->irq, brcmnand_ctlrdy_irq,0 , +DRV_NAME , ctrl); + }It looks to me like this should be handled as a nested irqchip, so the node you look up gets used as the "interrupt-parent" instead, making the behavior of this SoC transparent to the nand driver.
You snipped the rest of the patch, which involves more than just IRQ handling. The same registers touch both interrupts and data bus endian configuration, so it can't possibly be done transparently to the NAND driver.
Quoted 2 lines
We recently merged nested irqdomain support as well, which might help here, or might not be needed.
I'm not familiar with nested irqdomains. Do they address anything like the above problem?
Brian
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 46 lines · Brian Norris
Quoted 28 lines · Arnd Bergmann
Quoted 27 lines · On Wednesday 06 May 2015 10:59:50 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c +27
-0+/* +* Some SoCs integrate this controller (e.g., its interrupt bits) in +* interesting ways +*/ +if (of_property_read_bool (dn,"brcm,nand-soc" )) { +struct device_node *soc_dn; + + soc_dn =of_parse_phandle (dn,"brcm,nand-soc" ,0 ); +if (!soc_dn) +return -ENODEV ; + + ctrl->soc =devm_brcmnand_probe_soc (dev, soc_dn); +if (!ctrl->soc) { +dev_err (dev,"could not probe SoC data\n" ); +of_node_put (soc_dn); +return -ENODEV ; + } + + ret =devm_request_irq (dev, ctrl->irq, brcmnand_irq,0 , +DRV_NAME , ctrl); + +/* Enable interrupt */ + ctrl->soc->ctlrdy_set_enabled (ctrl->soc, true); + +of_node_put (soc_dn); + }else { +/* Use standard interrupt infrastructure */ Quoted 8 lines
drivers/mtd/nand/brcmstb_nand.c static int brcmnand_probe(struct platform_device *pdev) · line 2191
Quoted 4 lines
drivers/mtd/nand/brcmstb_nand.c +3
-0+ ret =devm_request_irq (dev, ctrl->irq, brcmnand_ctlrdy_irq,0 , +DRV_NAME , ctrl); + }It looks to me like this should be handled as a nested irqchip, so the node you look up gets used as the "interrupt-parent" instead, making the behavior of this SoC transparent to the nand driver.
You snipped the rest of the patch, which involves more than just IRQ handling. The same registers touch both interrupts and data bus endian configuration, so it can't possibly be done transparently to the NAND driver.
Quoted 2 lines
We recently merged nested irqdomain support as well, which might help here, or might not be needed.
Quoted 9 lines
I'm not familiar with nested irqdomains. Do they address anything like the above problem?
Brian
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
Brian,
I don't known about them myself :). However always check the Documentation folder of the kernel root for things like this. Further more I already checked there and it appears there is a file explaining the basics entitled, IRQ-domain.txt.
Hope this helps,
Nick
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
In reply to Brian NorrisQuoted 38 lines · On Wednesday 06 May 2015 13:49:10 Brian Norris wrote:
Quoted 28 lines · Arnd Bergmann
Quoted 27 lines · On Wednesday 06 May 2015 10:59:50 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c +27
-0+/* +* Some SoCs integrate this controller (e.g., its interrupt bits) in +* interesting ways +*/ +if (of_property_read_bool (dn,"brcm,nand-soc" )) { +struct device_node *soc_dn; + + soc_dn =of_parse_phandle (dn,"brcm,nand-soc" ,0 ); +if (!soc_dn) +return -ENODEV ; + + ctrl->soc =devm_brcmnand_probe_soc (dev, soc_dn); +if (!ctrl->soc) { +dev_err (dev,"could not probe SoC data\n" ); +of_node_put (soc_dn); +return -ENODEV ; + } + + ret =devm_request_irq (dev, ctrl->irq, brcmnand_irq,0 , +DRV_NAME , ctrl); + +/* Enable interrupt */ + ctrl->soc->ctlrdy_set_enabled (ctrl->soc, true); + +of_node_put (soc_dn); + }else { +/* Use standard interrupt infrastructure */ Quoted 8 lines
drivers/mtd/nand/brcmstb_nand.c static int brcmnand_probe(struct platform_device *pdev) · line 2191
Quoted 4 lines
drivers/mtd/nand/brcmstb_nand.c +3
-0+ ret =devm_request_irq (dev, ctrl->irq, brcmnand_ctlrdy_irq,0 , +DRV_NAME , ctrl); + }It looks to me like this should be handled as a nested irqchip, so the node you look up gets used as the "interrupt-parent" instead, making the behavior of this SoC transparent to the nand driver.
Quoted 4 lines
You snipped the rest of the patch, which involves more than just IRQ handling. The same registers touch both interrupts and data bus endian configuration, so it can't possibly be done transparently to the NAND driver.
Anything else in there? The bus configuration would just involve writing a constant value in some register, right? Doing that in the irqchip is also a bit ugly, but may still be better overall than doing it the way you have above.
Quoted 5 lines
Quoted 2 lines
We recently merged nested irqdomain support as well, which might help here, or might not be needed.
I'm not familiar with nested irqdomains. Do they address anything like the above problem?
The problem that nested irqdomains address is when an interrupt is handled by two irqchips, in particular when one irqchip handles a virtual interrupt number that was claimed by another irqchip already.
Arnd
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 39 lines · Arnd Bergmann
Quoted 38 lines · On Wednesday 06 May 2015 13:49:10 Brian Norris wrote:
Quoted 36 lines · Arnd Bergmann
Quoted 21 lines · On Wednesday 06 May 2015 10:59:50 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c +20
-0+/* +* Some SoCs integrate this controller (e.g., its interrupt bits) in +* interesting ways +*/ +if (of_property_read_bool (dn,"brcm,nand-soc" )) { +struct device_node *soc_dn; + + soc_dn =of_parse_phandle (dn,"brcm,nand-soc" ,0 ); +if (!soc_dn) +return -ENODEV ; + + ctrl->soc =devm_brcmnand_probe_soc (dev, soc_dn); +if (!ctrl->soc) { +dev_err (dev,"could not probe SoC data\n" ); +of_node_put (soc_dn); +return -ENODEV ; + } + + ret =devm_request_irq (dev, ctrl->irq, brcmnand_irq,0 , +DRV_NAME , ctrl);drivers/mtd/nand/brcmstb_nand.c static int brcmnand_probe(struct platform_device *pdev) · line 2191
Quoted 10 lines
drivers/mtd/nand/brcmstb_nand.c +10
-0+ +/* Enable interrupt */ + ctrl->soc->ctlrdy_set_enabled (ctrl->soc, true); + +of_node_put (soc_dn); + }else { +/* Use standard interrupt infrastructure */ + ret =devm_request_irq (dev, ctrl->irq, brcmnand_ctlrdy_irq,0 , +DRV_NAME , ctrl); + }It looks to me like this should be handled as a nested irqchip, so the node you look up gets used as the "interrupt-parent" instead, making the behavior of this SoC transparent to the nand driver.
Quoted 6 lines
Quoted 4 lines
You snipped the rest of the patch, which involves more than just IRQ handling. The same registers touch both interrupts and data bus endian configuration, so it can't possibly be done transparently to the NAND driver.
Anything else in there?
Looks like miscellaneous NAND-related control bits. AXI and APB endian configuration; several interrupt-enable bits (we only use one for now); a clock-enable; and some timing test mode bits.
Quoted 2 lines
The bus configuration would just involve writing
a constant value in some register, right?
I'm not an expert on the Cygnus/iProc chips, but I believe the answer is
no: we *must* reconfigure the bus before and after each data transaction, because it affects the rest of the core too. Others on the CC list can probably elaborate.
Quoted 3 lines
Doing that in the irqchip
is also a bit ugly, but may still be better overall than doing it the way you have above.
Well, the Cygnus/iProc case is more complicated as I mention. But I agree that other cases could be nicer, like bcm63138 (which only has separate interrupt status/enable registers). Do you expect a new irqchip driver for every arrangement of registers like this? There are a few similar chips that have status/enable registers in different orders, and some that combine them into a single word. Do we really need a new irqchip driver for each one? I might have done that for bcm63138 and bcm3384, except that I thought I'd have to fall back to this extra per-SoC support driver for Cygnus anyway.
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
We recently merged nested irqdomain support as well, which might help here, or might not be needed.
I'm not familiar with nested irqdomains. Do they address anything like the above problem?
The problem that nested irqdomains address is when an interrupt is handled by two irqchips, in particular when one irqchip handles a virtual interrupt number that was claimed by another irqchip already.
I'll do some reading on that, but it definitely doesn't address the main problem here.
Brian
Ray Jui
maintainerRe: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 51 lines · Brian Norris
Quoted 39 lines · Arnd Bergmann
Quoted 38 lines · On Wednesday 06 May 2015 13:49:10 Brian Norris wrote:
Quoted 36 lines · Arnd Bergmann
Quoted 21 lines · On Wednesday 06 May 2015 10:59:50 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c +20
-0+/* +* Some SoCs integrate this controller (e.g., its interrupt bits) in +* interesting ways +*/ +if (of_property_read_bool (dn,"brcm,nand-soc" )) { +struct device_node *soc_dn; + + soc_dn =of_parse_phandle (dn,"brcm,nand-soc" ,0 ); +if (!soc_dn) +return -ENODEV ; + + ctrl->soc =devm_brcmnand_probe_soc (dev, soc_dn); +if (!ctrl->soc) { +dev_err (dev,"could not probe SoC data\n" ); +of_node_put (soc_dn); +return -ENODEV ; + } + + ret =devm_request_irq (dev, ctrl->irq, brcmnand_irq,0 , +DRV_NAME , ctrl);drivers/mtd/nand/brcmstb_nand.c static int brcmnand_probe(struct platform_device *pdev) · line 2191
Quoted 10 lines
drivers/mtd/nand/brcmstb_nand.c +10
-0+ +/* Enable interrupt */ + ctrl->soc->ctlrdy_set_enabled (ctrl->soc, true); + +of_node_put (soc_dn); + }else { +/* Use standard interrupt infrastructure */ + ret =devm_request_irq (dev, ctrl->irq, brcmnand_ctlrdy_irq,0 , +DRV_NAME , ctrl); + }It looks to me like this should be handled as a nested irqchip, so the node you look up gets used as the "interrupt-parent" instead, making the behavior of this SoC transparent to the nand driver.
Quoted 6 lines
Quoted 4 lines
You snipped the rest of the patch, which involves more than just IRQ handling. The same registers touch both interrupts and data bus endian configuration, so it can't possibly be done transparently to the NAND driver.
Anything else in there?
Looks like miscellaneous NAND-related control bits. AXI and APB endian configuration; several interrupt-enable bits (we only use one for now); a clock-enable; and some timing test mode bits.
Quoted 8 lines
Quoted 2 lines
The bus configuration would just involve writing
a constant value in some register, right?I'm not an expert on the Cygnus/iProc chips, but I believe the answer is
no: we *must* reconfigure the bus before and after each data transaction, because it affects the rest of the core too. Others on the CC list can probably elaborate.
Yes, we must configure the bus before the after each data/cache registers access, because it changes the APB bus endianess.
Thanks,
Ray
--
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
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
In reply to Brian NorrisQuoted 12 lines · On Thursday 07 May 2015 11:42:46 Brian Norris wrote:
Quoted 11 lines · Arnd Bergmann
Quoted 9 lines · On Wednesday 06 May 2015 13:49:10 Brian Norris wrote:
Quoted 3 lines · Arnd Bergmann
It looks to me like this should be handled as a nested irqchip, so the node you look up gets used as the "interrupt-parent" instead, making the behavior of this SoC transparent to the nand driver.
You snipped the rest of the patch, which involves more than just IRQ handling. The same registers touch both interrupts and data bus endian configuration, so it can't possibly be done transparently to the NAND driver.
Quoted 5 lines
Quoted 1 line
Anything else in there?
Looks like miscellaneous NAND-related control bits. AXI and APB endian configuration; several interrupt-enable bits (we only use one for now); a clock-enable; and some timing test mode bits.
I see. Describing that as an irqchip would indeed be too much of a stretch.
Quoted 7 lines
Quoted 2 lines
The bus configuration would just involve writing
a constant value in some register, right?I'm not an expert on the Cygnus/iProc chips, but I believe the answer is
no: we *must* reconfigure the bus before and after each data transaction, because it affects the rest of the core too. Others on the CC list can probably elaborate.
That would not be a problem I think: the irqchip driver would always get initialized first, because the main driver would get an -EPROBE_DEFER when requesting the interrupt line otherwise.
Quoted 4 lines
Quoted 3 lines
Doing that in the irqchip
is also a bit ugly, but may still be better overall than doing it the way you have above.
Quoted 9 lines
Well, the Cygnus/iProc case is more complicated as I mention. But I agree that other cases could be nicer, like bcm63138 (which only has separate interrupt status/enable registers). Do you expect a new irqchip driver for every arrangement of registers like this? There are a few similar chips that have status/enable registers in different orders, and some that combine them into a single word. Do we really need a new irqchip driver for each one? I might have done that for bcm63138 and bcm3384, except that I thought I'd have to fall back to this extra per-SoC support driver for Cygnus anyway.
I assumed this one was the only odd one.
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
Quoted 2 lines
We recently merged nested irqdomain support as well, which might help here, or might not be needed.
I'm not familiar with nested irqdomains. Do they address anything like the above problem?
Quoted 6 lines
Quoted 3 lines
The problem that nested irqdomains address is when an interrupt is handled by two irqchips, in particular when one irqchip handles a virtual interrupt number that was claimed by another irqchip already.
I'll do some reading on that, but it definitely doesn't address the main problem here.
Ok, back to the drawing board then: How about turning the probe order around and splitting the SoC-specific part out into its own platform_driver:
Instead of bus_prepare/bus_unprepare for bcm63138, you'd get a bcm63138_nand_driver with its own probe() function that calls the common probe function. That would make the soc specific parts better contained and match how we normally do abstractions of similar drivers.
Arnd
--
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
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 5 lines · Arnd Bergmann
Quoted 4 lines · On Thursday 07 May 2015 11:42:46 Brian Norris wrote:
Quoted 2 lines · Arnd Bergmann
The bus configuration would just involve writing
a constant value in some register, right?
Quoted 8 lines
Quoted 4 lines
I'm not an expert on the Cygnus/iProc chips, but I believe the answer is
no: we *must* reconfigure the bus before and after each data transaction, because it affects the rest of the core too. Others on the CC list can probably elaborate.That would not be a problem I think: the irqchip driver would always get initialized first, because the main driver would get an -EPROBE_DEFER when requesting the interrupt line otherwise.
Huh? I wasn't worried about initialization order. I was worried about the fact that the "NAND" and "SoC" portions are very integrated when handling the data path. And I think you agreed that this means we can't do a straight-up irqchip.
FWIW, I agree that -EPROBE_DEFER can handle initialization ordering issues...
Quoted 14 lines
Quoted 4 lines
Quoted 3 lines
Doing that in the irqchip
is also a bit ugly, but may still be better overall than doing it the way you have above.Quoted 9 lines
Well, the Cygnus/iProc case is more complicated as I mention. But I agree that other cases could be nicer, like bcm63138 (which only has separate interrupt status/enable registers). Do you expect a new irqchip driver for every arrangement of registers like this? There are a few similar chips that have status/enable registers in different orders, and some that combine them into a single word. Do we really need a new irqchip driver for each one? I might have done that for bcm63138 and bcm3384, except that I thought I'd have to fall back to this extra per-SoC support driver for Cygnus anyway.
Quoted 1 line
I assumed this one was the only odd one.
Yes, the Cygnus/iProc are the oddest. The others (BCM33xx (not yet supported) and BCM63xxx) just have separate one-off interrupt register blocks.
To be clear, since I'm not sure if you're confused below:
* Cygnus is a family of chips using the IPROC architecture, coming from the Infrastructure/Networking Group; there are BCMxxxx numbers noted in arch/arm/mach-bcm/Kconfig for them, but I usually just refer to the Cygnus family or the IPROC architecture.
* BCM63xxx is a class of DSL chips from the Broadband/Connectivity Group.
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
We recently merged nested irqdomain support as well, which might help here, or might not be needed.
I'm not familiar with nested irqdomains. Do they address anything like the above problem?
The problem that nested irqdomains address is when an interrupt is handled by two irqchips, in particular when one irqchip handles a virtual interrupt number that was claimed by another irqchip already.
Quoted 7 lines
Quoted 2 lines
I'll do some reading on that, but it definitely doesn't address the main problem here.
Ok, back to the drawing board then: How about turning the probe order around and splitting the SoC-specific part out into its own
platform_driver:Instead of bus_prepare/bus_unprepare for bcm63138, you'd get a
bcm63138 does not need the bus_{,un}prepare. That's for IPROC/Cygnus.
Quoted 4 lines
bcm63138_nand_driverwith its ownprobe()function that calls the common probe function. That would make the soc specific parts better contained and match how we normally do abstractions of similar drivers.
OK, so I can imagine this might require changing the DT binding a bit [1] (is that your goal?). But what's the intended software difference? [2] I'll still be passing around the same sorts of callbacks from the 'iproc_nand' probe to the common probe function.
Brian
[1] e.g.:
nand: nand@18046000 {
compatible = "brcm,iproc-nand", "brcm,brcmnand-v6.1", "brcm,brcmnand";
reg = <0x18046000 0x600>, <0xf8105408 0x600>, <0x18046f00 0x20>;
reg-names = "nand", "iproc-idm", "iproc-ext";
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
brcm,nand-has-wp;
};This captures the extra "iproc-*" register ranges. Then we could have the iproc_nand driver bind against "brcm,iproc-nand", then call into the common probe, which would then accept/reject based on "brcm,brcmnand-vX.Y".
[2] The DT structure from [1] could actually accommodate either driver structure just fine. So maybe that means it's a better hardware description?
--
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
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 11 lines · On Friday 08 May 2015 12:38:50 Brian Norris wrote:
Quoted 10 lines · Arnd Bergmann
Quoted 8 lines · On Thursday 07 May 2015 11:42:46 Brian Norris wrote:
Quoted 2 lines · Arnd Bergmann
The bus configuration would just involve writing
a constant value in some register, right?I'm not an expert on the Cygnus/iProc chips, but I believe the answer is
no: we *must* reconfigure the bus before and after each data transaction, because it affects the rest of the core too. Others on the CC list can probably elaborate.
Quoted 8 lines
Quoted 3 lines
That would not be a problem I think: the irqchip driver would always get initialized first, because the main driver would get an -EPROBE_DEFER when requesting the interrupt line otherwise.
Huh? I wasn't worried about initialization order. I was worried about the fact that the "NAND" and "SoC" portions are very integrated when handling the data path. And I think you agreed that this means we can't do a straight-up irqchip.
Sorry, I missed the part about "each data transaction", got it now.
Quoted 22 lines
Quoted 14 lines
Quoted 4 lines
Quoted 3 lines
Doing that in the irqchip
is also a bit ugly, but may still be better overall than doing it the way you have above.Quoted 9 lines
Well, the Cygnus/iProc case is more complicated as I mention. But I agree that other cases could be nicer, like bcm63138 (which only has separate interrupt status/enable registers). Do you expect a new irqchip driver for every arrangement of registers like this? There are a few similar chips that have status/enable registers in different orders, and some that combine them into a single word. Do we really need a new irqchip driver for each one? I might have done that for bcm63138 and bcm3384, except that I thought I'd have to fall back to this extra per-SoC support driver for Cygnus anyway.
Quoted 1 line
I assumed this one was the only odd one.
Yes, the Cygnus/iProc are the oddest. The others (BCM33xx (not yet supported) and BCM63xxx) just have separate one-off interrupt register blocks.
To be clear, since I'm not sure if you're confused below:
Quoted 7 lines
* Cygnus is a family of chips using the IPROC architecture, coming from the Infrastructure/Networking Group; there are BCMxxxx numbers noted in
arch/arm/mach-bcm/Kconfigfor them, but I usually just refer to the Cygnus family or the IPROC architecture.* BCM63xxx is a class of DSL chips from the Broadband/Connectivity Group.
Thanks for the clarification, I think that is roughly what I thought it was, but I'm still not sure about brcmstb. Is that related to bcm63xxx or separate?
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
We recently merged nested irqdomain support as well, which might help here, or might not be needed.
I'm not familiar with nested irqdomains. Do they address anything like the above problem?
The problem that nested irqdomains address is when an interrupt is handled by two irqchips, in particular when one irqchip handles a virtual interrupt number that was claimed by another irqchip already.
I'll do some reading on that, but it definitely doesn't address the main problem here.
Quoted 6 lines
Quoted 4 lines
Ok, back to the drawing board then: How about turning the probe order around and splitting the SoC-specific part out into its own
platform_driver:Instead of bus_prepare/bus_unprepare for bcm63138, you'd get a
bcm63138 does not need the bus_{,un}prepare. That's for IPROC/Cygnus.
Ok.
Quoted 26 lines
Quoted 4 lines
bcm63138_nand_driverwith its ownprobe()function that calls the common probe function. That would make the soc specific parts better contained and match how we normally do abstractions of similar drivers.OK, so I can imagine this might require changing the DT binding a bit [1] (is that your goal?). But what's the intended software difference? [2] I'll still be passing around the same sorts of callbacks from the '
iproc_nand' probe to the common probe function.Brian
[1] e.g.:
nand: nand@18046000 { compatible = "brcm,iproc-nand", "brcm,brcmnand-v6.1", "brcm,brcmnand"; reg = <0x18046000 0x600>, <0xf8105408 0x600>, <0x18046f00 0x20>; reg-names = "nand", "iproc-idm", "iproc-ext"; interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; brcm,nand-has-wp; };
Quoted 8 lines
This captures the extra "iproc-*" register ranges. Then we could have the
iproc_nanddriver bind against "brcm,iproc-nand", then call into the common probe, which would then accept/reject based on "brcm,brcmnand-vX.Y".[2] The DT structure from [1] could actually accommodate either driver structure just fine. So maybe that means it's a better hardware description?
Yes, I think this makes sense overall. Regarding the specific example, can you clarify how the register areas in iproc are structured?
The 0xf8105408 and 0x18046f00 start addresses are not aligned to large powers of two, which often indicates that they are part of some other, larger, unit that might need to have a driver of its own, so before we specify a binding like the one you proposed above I'd like to make sure we're not getting ourselves into trouble later.
Arnd
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 2 lines · Arnd Bergmann
Quoted 1 line · On Friday 08 May 2015 12:38:50 Brian Norris wrote:
On Fri, May 08, 2015 at 03:41:10PM +0200, Arnd Bergmann wrote:
[...]
Quoted 7 lines
Quoted 7 lines
To be clear, since I'm not sure if you're confused below:
* Cygnus is a family of chips using the IPROC architecture, coming from the Infrastructure/Networking Group; there are BCMxxxx numbers noted in
arch/arm/mach-bcm/Kconfigfor them, but I usually just refer to the Cygnus family or the IPROC architecture.
Quoted 5 lines
Quoted 2 lines
* BCM63xxx is a class of DSL chips from the Broadband/Connectivity Group.
Thanks for the clarification, I think that is roughly what I thought it was, but I'm still not sure about brcmstb. Is that related to bcm63xxx or separate?
I think arch/arm/mach-bcm/Kconfig has the best summary. brcmstb is separate; BCM7xxx is generally (always?) Set-Top Box.
Another potentially confusing point: the main driver is named 'brcsmtb_nand' since the NAND core (and driver) originated from STB chips. But that core was applied to other non-STB chips, and so the driver has been extended.
Quoted 9 lines
Quoted 9 lines
Quoted 4 lines
bcm63138_nand_driverwith its ownprobe()function that calls the common probe function. That would make the soc specific parts better contained and match how we normally do abstractions of similar drivers.OK, so I can imagine this might require changing the DT binding a bit [1] (is that your goal?). But what's the intended software difference? [2] I'll still be passing around the same sorts of callbacks from the '
iproc_nand' probe to the common probe function.
^^ before getting bogged down on the DT details (which can be changed independently), I'd like to address this point.
Quoted 25 lines
Quoted 16 lines
Brian
[1] e.g.:
nand: nand@18046000 { compatible = "brcm,iproc-nand", "brcm,brcmnand-v6.1", "brcm,brcmnand"; reg = <0x18046000 0x600>, <0xf8105408 0x600>, <0x18046f00 0x20>; reg-names = "nand", "iproc-idm", "iproc-ext"; interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; brcm,nand-has-wp; };Quoted 8 lines
This captures the extra "iproc-*" register ranges. Then we could have the
iproc_nanddriver bind against "brcm,iproc-nand", then call into the common probe, which would then accept/reject based on "brcm,brcmnand-vX.Y".[2] The DT structure from [1] could actually accommodate either driver structure just fine. So maybe that means it's a better hardware description?
Quoted 8 lines
Yes, I think this makes sense overall. Regarding the specific example, can you clarify how the register areas in iproc are structured?
The
0xf8105408and0x18046f00start addresses are not aligned to large powers of two, which often indicates that they are part of some other, larger, unit that might need to have a driver of its own, so before we specify a binding like the one you proposed above I'd like to make sure we're not getting ourselves into trouble later.
I may want the Cygnus guys to speak up here, partly for technical expertise and partly to know how much they care to share...
<0xf8105408 0x600>: covers a series of NAND_IDM registers. NAND has a few bits we don't care about (for debugging, logging, and resetting), as well as its interrupt enable bits. The adjacent blocks cover similar IDM blocks for other cores (SPI, PNOR, DDR), and they are similarly unaligned. Not sure why, exactly; probably just a compact layout.
<0x18046f00 0x20>: a series of 8 NAND interrupt registers, each word containing a single bit representing status/clear. There is nothing between the "nand" range and this range, and the SPI core register range follows.
So I think these are pretty clearly-delineated register ranges for NAND, and the alignment is not really missing anything. Adjacent hardware (e.g., SPI) is independent, though pieces look similar. For one, it has similar:
* interrupt enable bits in the IDM range (0xf8106408 to 0xf8106a00); and
* interrupt status/clear following the SPI block (0x180473a0 to 0x180473b8)
Brian
--
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
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 18 lines · On Friday 08 May 2015 13:47:25 Brian Norris wrote:
Quoted 2 lines · Arnd Bergmann
Quoted 1 line · On Friday 08 May 2015 12:38:50 Brian Norris wrote:
On Fri, May 08, 2015 at 03:41:10PM +0200, Arnd Bergmann wrote:
[...]
Quoted 7 lines
Quoted 7 lines
To be clear, since I'm not sure if you're confused below:
* Cygnus is a family of chips using the IPROC architecture, coming from the Infrastructure/Networking Group; there are BCMxxxx numbers noted in
arch/arm/mach-bcm/Kconfigfor them, but I usually just refer to the Cygnus family or the IPROC architecture.Quoted 5 lines
Quoted 2 lines
* BCM63xxx is a class of DSL chips from the Broadband/Connectivity Group.
Thanks for the clarification, I think that is roughly what I thought it was, but I'm still not sure about brcmstb. Is that related to bcm63xxx or separate?
Quoted 7 lines
I think
arch/arm/mach-bcm/Kconfighas the best summary. brcmstb is separate; BCM7xxx is generally (always?) Set-Top Box.Another potentially confusing point: the main driver is named '
brcsmtb_nand' since the NAND core (and driver) originated from STB chips. But that core was applied to other non-STB chips, and so the driver has been extended.
Ok, I see.
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
bcm63138_nand_driverwith its ownprobe()function that calls the common probe function. That would make the soc specific parts better contained and match how we normally do abstractions of similar drivers.
Quoted 7 lines
Quoted 4 lines
Quoted 4 lines
OK, so I can imagine this might require changing the DT binding a bit [1] (is that your goal?). But what's the intended software difference? [2] I'll still be passing around the same sorts of callbacks from the '
iproc_nand' probe to the common probe function.^^ before getting bogged down on the DT details (which can be changed independently), I'd like to address this point.
The intended change is to make it work according to Documentation/driver-model/design-patterns.txt
basically, by having all the shared code be a "library" module that gets called by the actual hardware specific drivers, rather than having the shared code be the central driver that fans out into all possible subdrivers.
Quoted 29 lines
Quoted 9 lines
Yes, I think this makes sense overall. Regarding the specific example, can you clarify how the register areas in iproc are structured?
The
0xf8105408and0x18046f00start addresses are not aligned to large powers of two, which often indicates that they are part of some other, larger, unit that might need to have a driver of its own, so before we specify a binding like the one you proposed above I'd like to make sure we're not getting ourselves into trouble later.I may want the Cygnus guys to speak up here, partly for technical expertise and partly to know how much they care to share...
<
0xf81054080x600>: covers a series ofNAND_IDMregisters. NAND has a few bits we don't care about (for debugging, logging, and resetting), as well as its interrupt enable bits. The adjacent blocks cover similar IDM blocks for other cores (SPI, PNOR, DDR), and they are similarly unaligned. Not sure why, exactly; probably just a compact layout.<
0x18046f000x20>: a series of 8 NAND interrupt registers, each word containing a single bit representing status/clear. There is nothing between the "nand" range and this range, and the SPI core register range follows.So I think these are pretty clearly-delineated register ranges for NAND, and the alignment is not really missing anything. Adjacent hardware (e.g., SPI) is independent, though pieces look similar. For one, it has similar:
Quoted 4 lines
* interrupt enable bits in the IDM range (
0xf8106408to0xf8106a00); and
* interrupt status/clear following the SPI block (0x180473a0to0x180473b8)
This would in turn indicate that we should treat these ranges as an irqchip that handles all sorts of devices, but it really depends on the particular register layout.
Arnd
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
Quoted 14 lines · Arnd Bergmann
Quoted 13 lines · On Friday 08 May 2015 13:47:25 Brian Norris wrote:
Quoted 11 lines · Arnd Bergmann
Quoted 10 lines · On Friday 08 May 2015 12:38:50 Brian Norris wrote:
Quoted 4 lines · Arnd Bergmann
bcm63138_nand_driverwith its ownprobe()function that calls the common probe function. That would make the soc specific parts better contained and match how we normally do abstractions of similar drivers.OK, so I can imagine this might require changing the DT binding a bit [1] (is that your goal?). But what's the intended software difference? [2] I'll still be passing around the same sorts of callbacks from the '
iproc_nand' probe to the common probe function.
Quoted 5 lines
Quoted 2 lines
^^ before getting bogged down on the DT details (which can be changed independently), I'd like to address this point.
The intended change is to make it work according to
Documentation/driver-model/design-patterns.txt
Huh? There are two bullet points in that file, and neither are particularly enlightening for this case. Maybe you're referring to your mental design patterns documentation? :)
Quoted 3 lines
basically, by having all the shared code be a "library" module that gets called by the actual hardware specific drivers, rather than having the shared code be the central driver that fans out into all possible subdrivers.
OK, I'll see what I can do. It will be a fairly opaque "library" though, consisting largely of a single monolithic core driver. Might just move to a whole drivers/mtd/nand/brcmnand/ subdirectory at the same time...
Quoted 28 lines
Quoted 28 lines
Quoted 8 lines
Yes, I think this makes sense overall. Regarding the specific example, can you clarify how the register areas in iproc are structured?
The
0xf8105408and0x18046f00start addresses are not aligned to large powers of two, which often indicates that they are part of some other, larger, unit that might need to have a driver of its own, so before we specify a binding like the one you proposed above I'd like to make sure we're not getting ourselves into trouble later.I may want the Cygnus guys to speak up here, partly for technical expertise and partly to know how much they care to share...
<
0xf81054080x600>: covers a series ofNAND_IDMregisters. NAND has a few bits we don't care about (for debugging, logging, and resetting), as well as its interrupt enable bits. The adjacent blocks cover similar IDM blocks for other cores (SPI, PNOR, DDR), and they are similarly unaligned. Not sure why, exactly; probably just a compact layout.<
0x18046f000x20>: a series of 8 NAND interrupt registers, each word containing a single bit representing status/clear. There is nothing between the "nand" range and this range, and the SPI core register range follows.So I think these are pretty clearly-delineated register ranges for NAND, and the alignment is not really missing anything. Adjacent hardware (e.g., SPI) is independent, though pieces look similar. For one, it has similar:
Quoted 8 lines
Quoted 4 lines
* interrupt enable bits in the IDM range (
0xf8106408to0xf8106a00); and
* interrupt status/clear following the SPI block (0x180473a0to0x180473b8)This would in turn indicate that we should treat these ranges as an irqchip that handles all sorts of devices, but it really depends on the particular register layout.
OK, sure. But this has nothing to do with NAND (which we established cannot be an irqchip on Cygnus). I think SPI is coming through the pipeline soon, though, and that's a good point.
Brian
Ray Jui
maintainerRe: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
In reply to Brian NorrisQuoted 73 lines · Brian Norris
Quoted 2 lines · Arnd Bergmann
Quoted 1 line · On Friday 08 May 2015 12:38:50 Brian Norris wrote:
On Fri, May 08, 2015 at 03:41:10PM +0200, Arnd Bergmann wrote:
[...]
Quoted 7 lines
Quoted 7 lines
To be clear, since I'm not sure if you're confused below:
* Cygnus is a family of chips using the IPROC architecture, coming from the Infrastructure/Networking Group; there are BCMxxxx numbers noted in
arch/arm/mach-bcm/Kconfigfor them, but I usually just refer to the Cygnus family or the IPROC architecture.Quoted 5 lines
Quoted 2 lines
* BCM63xxx is a class of DSL chips from the Broadband/Connectivity Group.
Thanks for the clarification, I think that is roughly what I thought it was, but I'm still not sure about brcmstb. Is that related to bcm63xxx or separate?
I think
arch/arm/mach-bcm/Kconfighas the best summary. brcmstb is separate; BCM7xxx is generally (always?) Set-Top Box.Another potentially confusing point: the main driver is named '
brcsmtb_nand' since the NAND core (and driver) originated from STB chips. But that core was applied to other non-STB chips, and so the driver has been extended.Quoted 9 lines
Quoted 9 lines
Quoted 4 lines
bcm63138_nand_driverwith its ownprobe()function that calls the common probe function. That would make the soc specific parts better contained and match how we normally do abstractions of similar drivers.OK, so I can imagine this might require changing the DT binding a bit [1] (is that your goal?). But what's the intended software difference? [2] I'll still be passing around the same sorts of callbacks from the '
iproc_nand' probe to the common probe function.^^ before getting bogged down on the DT details (which can be changed independently), I'd like to address this point.
Quoted 25 lines
Quoted 16 lines
Brian
[1] e.g.:
nand: nand@18046000 { compatible = "brcm,iproc-nand", "brcm,brcmnand-v6.1", "brcm,brcmnand"; reg = <0x18046000 0x600>, <0xf8105408 0x600>, <0x18046f00 0x20>; reg-names = "nand", "iproc-idm", "iproc-ext"; interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; brcm,nand-has-wp; };Quoted 8 lines
This captures the extra "iproc-*" register ranges. Then we could have the
iproc_nanddriver bind against "brcm,iproc-nand", then call into the common probe, which would then accept/reject based on "brcm,brcmnand-vX.Y".[2] The DT structure from [1] could actually accommodate either driver structure just fine. So maybe that means it's a better hardware description?
Quoted 8 lines
Yes, I think this makes sense overall. Regarding the specific example, can you clarify how the register areas in iproc are structured?
The
0xf8105408and0x18046f00start addresses are not aligned to large powers of two, which often indicates that they are part of some other, larger, unit that might need to have a driver of its own, so before we specify a binding like the one you proposed above I'd like to make sure we're not getting ourselves into trouble later.
Quoted 8 lines
I may want the Cygnus guys to speak up here, partly for technical expertise and partly to know how much they care to share...
<
0xf81054080x600>: covers a series ofNAND_IDMregisters. NAND has a few bits we don't care about (for debugging, logging, and resetting), as well as its interrupt enable bits. The adjacent blocks cover similar IDM blocks for other cores (SPI, PNOR, DDR), and they are similarly unaligned. Not sure why, exactly; probably just a compact layout.
Yes, starting from 0xf8105408, within the range of 0x600, there are various NAND_IDM registers scattered, which is indeed a very weird register layout.
Like Brian said, most of those NAND_IDM registers are for debugging, logging, or status reporting. As of today, we only care about the first register, that contains a bunch of bits that allow you to configure the endianness of the AXI/APB bus, enabling NAND interrupts and clocks.
Quoted 5 lines
<
0x18046f000x20>: a series of 8 NAND interrupt registers, each word containing a single bit representing status/clear. There is nothing between the "nand" range and this range, and the SPI core register range follows.
Correct.
Quoted 13 lines
So I think these are pretty clearly-delineated register ranges for NAND, and the alignment is not really missing anything. Adjacent hardware (e.g., SPI) is independent, though pieces look similar. For one, it has similar:
* interrupt enable bits in the IDM range (
0xf8106408to0xf8106a00); and
* interrupt status/clear following the SPI block (0x180473a0to0x180473b8)Brian
Re: [PATCH v3 06/10] mtd: brcmstb_nand: add SoC-specific support
In reply to Arnd BergmannQuoted 44 lines · Arnd Bergmann
Quoted 38 lines · On Wednesday 06 May 2015 13:49:10 Brian Norris wrote:
Quoted 28 lines · Arnd Bergmann
Quoted 27 lines · On Wednesday 06 May 2015 10:59:50 Brian Norris wrote:
drivers/mtd/nand/brcmstb_nand.c +27
-0+/* +* Some SoCs integrate this controller (e.g., its interrupt bits) in +* interesting ways +*/ +if (of_property_read_bool (dn,"brcm,nand-soc" )) { +struct device_node *soc_dn; + + soc_dn =of_parse_phandle (dn,"brcm,nand-soc" ,0 ); +if (!soc_dn) +return -ENODEV ; + + ctrl->soc =devm_brcmnand_probe_soc (dev, soc_dn); +if (!ctrl->soc) { +dev_err (dev,"could not probe SoC data\n" ); +of_node_put (soc_dn); +return -ENODEV ; + } + + ret =devm_request_irq (dev, ctrl->irq, brcmnand_irq,0 , +DRV_NAME , ctrl); + +/* Enable interrupt */ + ctrl->soc->ctlrdy_set_enabled (ctrl->soc, true); + +of_node_put (soc_dn); + }else { +/* Use standard interrupt infrastructure */ Quoted 8 lines
drivers/mtd/nand/brcmstb_nand.c static int brcmnand_probe(struct platform_device *pdev) · line 2191
Quoted 4 lines
drivers/mtd/nand/brcmstb_nand.c +3
-0+ ret =devm_request_irq (dev, ctrl->irq, brcmnand_ctlrdy_irq,0 , +DRV_NAME , ctrl); + }It looks to me like this should be handled as a nested irqchip, so the node you look up gets used as the "interrupt-parent" instead, making the behavior of this SoC transparent to the nand driver.
Quoted 4 lines
You snipped the rest of the patch, which involves more than just IRQ handling. The same registers touch both interrupts and data bus endian configuration, so it can't possibly be done transparently to the NAND driver.
Quoted 4 lines
Anything else in there? The bus configuration would just involve writing a constant value in some register, right? Doing that in the irqchip is also a bit ugly, but may still be better overall than doing it the way you have above.
IMHO this is uglier, having a pseudo interrupt controller driver that also takes care of preparing bus transfers, as opposed to an ad-hoc piece of code that does not pretend to be an interrupt controller at all sounds like the former is lying about what it is, while the latter is pretty straight forward even though it may duplicate an existing subsystem.
I would definitively see some value in writing an irqchip driver if this was remotely useful outside of the NAND block, e.g: the interrupt bits would serve other peripherals than NAND, which is not the case for 63138 and 338x AFAICT, Cygnus is a special case.
I could very well imagine a near future where this controller gets added more features in the DMA/data-path that may require bus/chip-level glue code to be interfaced properly between Broadcom's different internal buses. In which case, the interrupt controller portion of the code could be much smaller than the bus/data-path logic, would it still make sense to pretend this to be an interrupt controller?
Signature · 5 lines
Florian -- 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
PATCH v3 7/10 mtd: brcsmtb_nand_soc: add support for BCM63138
In reply to Brian NorrisThis SoC just has its custom interrupt status bits.
--- drivers/mtd/nand/brcmstb_nand_soc.c | 69 +++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)
drivers/mtd/nand/brcmstb_nand_soc.c +69 -0
@@ -28,7 +28,76 @@ struct brcmnand_soc_ofdata {void (*prepare_data_bus)(struct brcmnand_soc *soc,bool prepare); }; +struct bcm63138_nand_soc_priv { +void __iomem *base; +}; + +#define BCM63138_NAND_INT_STATUS 0x00 +#define BCM63138_NAND_INT_EN 0x04 + +enum { +BCM63138_CTLRDY =BIT (4 ), +}; + +static bool bcm63138_nand_intc_ack (struct brcmnand_soc *soc) +{ +struct bcm63138_nand_soc_priv *priv = soc->priv; +void __iomem *mmio = priv->base +BCM63138_NAND_INT_STATUS ; +u32 val =__raw_readl (mmio); + +if (val &BCM63138_CTLRDY ) { +__raw_writel (val & ~BCM63138_CTLRDY , mmio); +return true; + } + +return false; +} + +static void bcm63138_nand_intc_set (struct brcmnand_soc *soc,bool en) +{ +struct bcm63138_nand_soc_priv *priv = soc->priv; +void __iomem *mmio = priv->base +BCM63138_NAND_INT_EN ; +u32 val =__raw_readl (mmio); + +if (en) + val |=BCM63138_CTLRDY ; +else + val &= ~BCM63138_CTLRDY ; + +__raw_writel (val, mmio); +} + +static int bcm63138_nand_soc_init (struct brcmnand_soc *soc) +{ +struct bcm63138_nand_soc_priv *priv; + + priv =devm_kzalloc (soc->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->base =of_io_request_and_map (soc->dn,0 ,DRV_NAME ); +if (IS_ERR (priv->base)) +return PTR_ERR (priv->base); + + soc->priv = priv; + +/* Clear the interrupt */ +bcm63138_nand_intc_ack (soc); + +return 0 ; +} + +static const struct brcmnand_soc_ofdata bcm63138_nand_soc = { + .init = bcm63138_nand_soc_init, + .ctlrdy_ack = bcm63138_nand_intc_ack, + .ctlrdy_set_enabled = bcm63138_nand_intc_set, +}; +static const struct of_device_id brcmnand_soc_ofmatch[] = { + { + .compatible ="brcm,nand-soc-bcm63138" , + .data = &bcm63138_nand_soc, + }, {}, };
Signature · 1 line
1.9.1
PATCH v3 8/10 mtd: brcsmtb_nand_soc: add iProc support
In reply to Brian NorrisFrom: Ray Jui <[email protected]>
--- drivers/mtd/nand/brcmstb_nand_soc.c | 110 ++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+)
drivers/mtd/nand/brcmstb_nand_soc.c +110 -0
@@ -93,11 +93,121 @@ static const struct brcmnand_soc_ofdata bcm63138_nand_soc = { .ctlrdy_set_enabled = bcm63138_nand_intc_set, }; +struct iproc_nand_soc_priv { +void __iomem *idm_base; +void __iomem *ext_base; +spinlock_t idm_lock; +}; + +#define IPROC_NAND_CTLR_READY_OFFSET 0x10 +#define IPROC_NAND_CTLR_READY BIT(0) + +#define IPROC_NAND_IO_CTRL_OFFSET 0x00 +#define IPROC_NAND_APB_LE_MODE BIT(24) +#define IPROC_NAND_INT_CTRL_READ_ENABLE BIT(6) + +static bool iproc_nand_intc_ack (struct brcmnand_soc *soc) +{ +struct iproc_nand_soc_priv *priv = soc->priv; +void __iomem *mmio = priv->ext_base +IPROC_NAND_CTLR_READY_OFFSET ; +u32 val =__raw_readl (mmio); + +if (val &IPROC_NAND_CTLR_READY ) { +__raw_writel (IPROC_NAND_CTLR_READY , mmio); +return true; + } + +return false; +} + +static void iproc_nand_intc_set (struct brcmnand_soc *soc,bool en) +{ +struct iproc_nand_soc_priv *priv = soc->priv; +void __iomem *mmio = priv->idm_base +IPROC_NAND_IO_CTRL_OFFSET ; +u32 val; +unsigned long flags; + +spin_lock_irqsave (&priv->idm_lock, flags); + + val =__raw_readl (mmio); + +if (en) + val |=IPROC_NAND_INT_CTRL_READ_ENABLE ; +else + val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE ; + +__raw_writel (val, mmio); + +spin_unlock_irqrestore (&priv->idm_lock, flags); +} + +static int iproc_nand_soc_init (struct brcmnand_soc *soc) +{ +struct iproc_nand_soc_priv *priv; + + priv =devm_kzalloc (soc->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + +spin_lock_init (&priv->idm_lock); + + priv->idm_base =of_io_request_and_map (soc->dn,0 ,DRV_NAME ); +if (IS_ERR (priv->idm_base)) +return PTR_ERR (priv->idm_base); + + priv->ext_base =of_io_request_and_map (soc->dn,1 ,DRV_NAME ); +if (IS_ERR (priv->ext_base)) { +struct resource res; + +of_address_to_resource (soc->dn,0 , &res); +release_mem_region (res.start,resource_size (&res)); +iounmap (priv->idm_base); +return PTR_ERR (priv->ext_base); + } + + soc->priv = priv; +iproc_nand_intc_ack (soc); + +return 0 ; +} + +static void iproc_nand_apb_access (struct brcmnand_soc *soc,bool prepare) +{ +struct iproc_nand_soc_priv *priv = soc->priv; +void __iomem *mmio = priv->idm_base +IPROC_NAND_IO_CTRL_OFFSET ; +u32 val; +unsigned long flags; + +spin_lock_irqsave (&priv->idm_lock, flags); + + val =__raw_readl (mmio); + +if (prepare) + val |=IPROC_NAND_APB_LE_MODE ; +else + val &= ~IPROC_NAND_APB_LE_MODE ; + +__raw_writel (val, mmio); + +spin_unlock_irqrestore (&priv->idm_lock, flags); +} + +static const struct brcmnand_soc_ofdata iproc_nand_soc = { + .init = iproc_nand_soc_init, + .ctlrdy_ack = iproc_nand_intc_ack, + .ctlrdy_set_enabled = iproc_nand_intc_set, + .prepare_data_bus = iproc_nand_apb_access, +}; +static const struct of_device_id brcmnand_soc_ofmatch[] = { { .compatible ="brcm,nand-soc-bcm63138" , .data = &bcm63138_nand_soc, }, + { + .compatible ="brcm,nand-soc-iproc" , + .data = &iproc_nand_soc, + }, {}, };
Signature · 1 line
1.9.1
PATCH v3 9/10 ARM: bcm63138: add NAND DT support
In reply to Brian Norris--- arch/arm/boot/dts/bcm63138.dtsi | 17 +++++++++++++++++ arch/arm/boot/dts/bcm963138dvt.dts | 12 ++++++++++++ 2 files changed, 29 insertions(+)
arch/arm/boot/dts/bcm63138.dtsi +17 -0
@@ -131,5 +131,22 @@ clock-names = "periph"; status = "disabled"; }; + + nand: nand@2000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "brcm,brcmnand-v7.0", "brcm,brcmnand"; + reg = <0x2000 0x600>; + reg-names = "nand"; + status = "disabled"; + interrupts = <GIC_SPI 38 0>; + interrupt-names = "nand"; + brcm,nand-soc = <&nand_int_base>; + }; + + nand_int_base: nand-soc@f0 { + compatible = "brcm,nand-soc-bcm63138"; + reg = <0xf0 0x10>; + }; }; };
arch/arm/boot/dts/bcm963138dvt.dts +12 -0
@@ -28,3 +28,15 @@ &serial1 { status = "okay"; }; + +&nand { + status = "okay"; + + nandcs@0 { + compatible = "brcm,nandcs"; + reg = <0>; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + brcm,nand-oob-sectors-size = <16>; + }; +};
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
PATCH v3 10/10 ARM: dts: cygnus: Enable NAND support for Cygnus
In reply to Brian NorrisFrom: Ray Jui <[email protected]>
Enable NAND support for Broadcom Cygnus SoC
--- arch/arm/boot/dts/bcm-cygnus.dtsi | 20 ++++++++++++++++++++ arch/arm/boot/dts/bcm958300k.dts | 16 ++++++++++++++++ 2 files changed, 36 insertions(+)
arch/arm/boot/dts/bcm-cygnus.dtsi +20 -0
@@ -212,6 +212,26 @@ status = "disabled"; }; + nand_soc: nand_soc@f8105408 { + compatible = "brcm,nand-soc-iproc"; + reg = <0xf8105408 0x600>, + <0x18046f00 0x20>; + reg-names = "idm", "ext"; + }; + + nand: nand@18046000 { + compatible = "brcm,brcmnand-v6.1", "brcm,brcmnand"; + reg = <0x18046000 0x600>; + reg-names = "nand"; + interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; + + #address-cells = <1>; + #size-cells = <0>; + + brcm,nand-has-wp; + brcm,nand-soc = <&nand_soc>; + }; + gic: interrupt-controller@19021000 { compatible = "arm,cortex-a9-gic"; #interrupt-cells = <3>;
arch/arm/boot/dts/bcm958300k.dts +16 -0
@@ -58,4 +58,20 @@ uart3: serial@18023000 { status = "okay"; }; + + nand: nand@18046000 { + nandcs@1 { + compatible = "brcm,nandcs"; + reg = <0>; + nand-on-flash-bbt; + + #address-cells = <1>; + #size-cells = <1>; + + nand-ecc-strength = <24>; + nand-ecc-step-size = <1024>; + + brcm,nand-oob-sector-size = <27>; + }; + }; };
Signature · 1 line
1.9.1
Quoted 9 lines · Brian Norris
Hi,
This is version 3 of support for the Broadcom BCM7xxx Set-Top Box NAND controller. This controller has been used in a variety of Broadcom SoCs.
This series now adds support for a few new chips: BCM63138, and the iProc chip family. These add an additional 6 new patches to the original 4. If the only comments end up on the latter 6 patches, the first 4 might be worth merging independently.
This looks great, thanks!
on 63138DVT:
[ 0.575390] nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xf1 [ 0.581885] nand: Micron MT29F1G08ABADAWP [ 0.585979] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64 [ 0.593864] brcmstb_nand fffea000.nand: detected 128MiB total, 128KiB blocks, 2KiB pages, 164 [ 0.593864] [ 0.605742] Scanning device for bad blocks
Quoted 56 lines
Summary changelog:
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 mergedv2 -> v3:
* rebase to v4.1-rc1
* add SoC-specific infrastructure, to help support other SoCs:
- add BCM63138 support
- add iProc/Cygnus support
* disable prefetch on v6.1Brian Norris (8):
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
Documentation: devicetree:brcmstb_nand: add 'brcm,nand-soc' bindings
mtd:brcmstb_nand: add SoC-specific support
mtd:brcsmtb_nand_soc: add support for BCM63138
ARM: bcm63138: add NAND DT supportRay Jui (2):
mtd:brcsmtb_nand_soc: add iProc support
ARM: dts: cygnus: Enable NAND support for Cygnus.../devicetree/bindings/mtd/brcm,brcmstb-nand.txt | 147 ++ arch/arm/boot/dts/bcm-cygnus.dtsi | 20 + arch/arm/boot/dts/bcm63138.dtsi | 17 + arch/arm/boot/dts/bcm7445-bcm97445svmb.dts | 23 + arch/arm/boot/dts/bcm7445.dtsi | 22 + arch/arm/boot/dts/bcm958300k.dts | 16 + arch/arm/boot/dts/bcm963138dvt.dts | 12 + drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 2 + drivers/mtd/nand/brcmnand.h | 56 + drivers/mtd/nand/brcmstb_nand.c | 2263 ++++++++++++++++++++ drivers/mtd/nand/brcmstb_nand_soc.c | 244 +++ drivers/mtd/nand/nand_base.c | 41 + include/linux/mtd/nand.h | 5 + 14 files changed, 2876 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/brcm,brcmstb-nand.txt create mode 100644 drivers/mtd/nand/brcmnand.h create mode 100644 drivers/mtd/nand/brcmstb_nand.c create mode 100644 drivers/mtd/nand/brcmstb_nand_soc.c
Signature · 1 line
Florian