Merge tag 'v4.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux...
authorBoris Brezillon <boris.brezillon@bootlin.com>
Wed, 4 Apr 2018 20:13:35 +0000 (22:13 +0200)
committerBoris Brezillon <boris.brezillon@bootlin.com>
Wed, 4 Apr 2018 20:13:35 +0000 (22:13 +0200)
Backmerge v4.16-rc2 into mtd/next to resolve a conflict between Linus'
master branch and nand/for-4.17.

284 files changed:
.mailmap
Documentation/arm/Samsung-S3C24XX/S3C2412.txt
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt
Documentation/devicetree/bindings/mtd/marvell-nand.txt
Documentation/devicetree/bindings/mtd/mtd-physmap.txt
Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt [deleted file]
Documentation/devicetree/bindings/mtd/sunxi-nand.txt
Documentation/driver-api/mtdnand.rst
Documentation/gpio/drivers-on-gpio.txt
MAINTAINERS
arch/arm/boot/dts/pxa3xx.dtsi
arch/arm/configs/cm_x300_defconfig
arch/arm/configs/pxa3xx_defconfig
arch/arm/configs/pxa_defconfig
arch/arm/configs/raumfeld_defconfig
arch/arm/mach-mmp/aspenite.c
arch/arm/mach-mmp/ttc_dkb.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-pxa3xx.c
arch/arm/mach-pxa/colibri.h
arch/arm/mach-pxa/littleton.c
arch/arm/mach-pxa/mxm8x10.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/zylonite.c
arch/cris/arch-v32/drivers/mach-a3/nandflash.c
arch/cris/arch-v32/drivers/mach-fs/nandflash.c
drivers/mtd/Kconfig
drivers/mtd/Makefile
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/chips/jedec_probe.c
drivers/mtd/chips/map_ram.c
drivers/mtd/devices/bcm47xxsflash.c
drivers/mtd/devices/block2mtd.c
drivers/mtd/devices/docg3.c
drivers/mtd/devices/lart.c
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/devices/mtdram.c
drivers/mtd/devices/phram.c
drivers/mtd/devices/pmc551.c
drivers/mtd/devices/powernv_flash.c
drivers/mtd/devices/slram.c
drivers/mtd/devices/spear_smi.c
drivers/mtd/devices/sst25l.c
drivers/mtd/devices/st_spi_fsm.c
drivers/mtd/ftl.c
drivers/mtd/inftlmount.c
drivers/mtd/lpddr/lpddr2_nvm.c
drivers/mtd/lpddr/lpddr_cmds.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/bfin-async-flash.c [deleted file]
drivers/mtd/maps/physmap_of_core.c
drivers/mtd/mtdblock.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdoops.c
drivers/mtd/mtdpart.c
drivers/mtd/mtdswap.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/ams-delta.c [deleted file]
drivers/mtd/nand/atmel/Makefile [deleted file]
drivers/mtd/nand/atmel/nand-controller.c [deleted file]
drivers/mtd/nand/atmel/pmecc.c [deleted file]
drivers/mtd/nand/atmel/pmecc.h [deleted file]
drivers/mtd/nand/au1550nd.c [deleted file]
drivers/mtd/nand/bbt.c [new file with mode: 0644]
drivers/mtd/nand/bcm47xxnflash/Makefile [deleted file]
drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h [deleted file]
drivers/mtd/nand/bcm47xxnflash/main.c [deleted file]
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c [deleted file]
drivers/mtd/nand/bf5xx_nand.c [deleted file]
drivers/mtd/nand/brcmnand/Makefile [deleted file]
drivers/mtd/nand/brcmnand/bcm63138_nand.c [deleted file]
drivers/mtd/nand/brcmnand/bcm6368_nand.c [deleted file]
drivers/mtd/nand/brcmnand/brcmnand.c [deleted file]
drivers/mtd/nand/brcmnand/brcmnand.h [deleted file]
drivers/mtd/nand/brcmnand/brcmstb_nand.c [deleted file]
drivers/mtd/nand/brcmnand/iproc_nand.c [deleted file]
drivers/mtd/nand/cafe_nand.c [deleted file]
drivers/mtd/nand/cmx270_nand.c [deleted file]
drivers/mtd/nand/core.c [new file with mode: 0644]
drivers/mtd/nand/cs553x_nand.c [deleted file]
drivers/mtd/nand/davinci_nand.c [deleted file]
drivers/mtd/nand/denali.c [deleted file]
drivers/mtd/nand/denali.h [deleted file]
drivers/mtd/nand/denali_dt.c [deleted file]
drivers/mtd/nand/denali_pci.c [deleted file]
drivers/mtd/nand/diskonchip.c [deleted file]
drivers/mtd/nand/docg4.c [deleted file]
drivers/mtd/nand/fsl_elbc_nand.c [deleted file]
drivers/mtd/nand/fsl_ifc_nand.c [deleted file]
drivers/mtd/nand/fsl_upm.c [deleted file]
drivers/mtd/nand/fsmc_nand.c [deleted file]
drivers/mtd/nand/gpio.c [deleted file]
drivers/mtd/nand/gpmi-nand/Makefile [deleted file]
drivers/mtd/nand/gpmi-nand/bch-regs.h [deleted file]
drivers/mtd/nand/gpmi-nand/gpmi-lib.c [deleted file]
drivers/mtd/nand/gpmi-nand/gpmi-nand.c [deleted file]
drivers/mtd/nand/gpmi-nand/gpmi-nand.h [deleted file]
drivers/mtd/nand/gpmi-nand/gpmi-regs.h [deleted file]
drivers/mtd/nand/hisi504_nand.c [deleted file]
drivers/mtd/nand/jz4740_nand.c [deleted file]
drivers/mtd/nand/jz4780_bch.c [deleted file]
drivers/mtd/nand/jz4780_bch.h [deleted file]
drivers/mtd/nand/jz4780_nand.c [deleted file]
drivers/mtd/nand/lpc32xx_mlc.c [deleted file]
drivers/mtd/nand/lpc32xx_slc.c [deleted file]
drivers/mtd/nand/marvell_nand.c [deleted file]
drivers/mtd/nand/mpc5121_nfc.c [deleted file]
drivers/mtd/nand/mtk_ecc.c [deleted file]
drivers/mtd/nand/mtk_ecc.h [deleted file]
drivers/mtd/nand/mtk_nand.c [deleted file]
drivers/mtd/nand/mxc_nand.c [deleted file]
drivers/mtd/nand/nand_amd.c [deleted file]
drivers/mtd/nand/nand_base.c [deleted file]
drivers/mtd/nand/nand_bbt.c [deleted file]
drivers/mtd/nand/nand_bch.c [deleted file]
drivers/mtd/nand/nand_ecc.c [deleted file]
drivers/mtd/nand/nand_hynix.c [deleted file]
drivers/mtd/nand/nand_ids.c [deleted file]
drivers/mtd/nand/nand_macronix.c [deleted file]
drivers/mtd/nand/nand_micron.c [deleted file]
drivers/mtd/nand/nand_samsung.c [deleted file]
drivers/mtd/nand/nand_timings.c [deleted file]
drivers/mtd/nand/nand_toshiba.c [deleted file]
drivers/mtd/nand/nandsim.c [deleted file]
drivers/mtd/nand/ndfc.c [deleted file]
drivers/mtd/nand/nuc900_nand.c [deleted file]
drivers/mtd/nand/omap2.c [deleted file]
drivers/mtd/nand/omap_elm.c [deleted file]
drivers/mtd/nand/onenand/Kconfig [new file with mode: 0644]
drivers/mtd/nand/onenand/Makefile [new file with mode: 0644]
drivers/mtd/nand/onenand/generic.c [new file with mode: 0644]
drivers/mtd/nand/onenand/omap2.c [new file with mode: 0644]
drivers/mtd/nand/onenand/onenand_base.c [new file with mode: 0644]
drivers/mtd/nand/onenand/onenand_bbt.c [new file with mode: 0644]
drivers/mtd/nand/onenand/samsung.c [new file with mode: 0644]
drivers/mtd/nand/onenand/samsung.h [new file with mode: 0644]
drivers/mtd/nand/orion_nand.c [deleted file]
drivers/mtd/nand/oxnas_nand.c [deleted file]
drivers/mtd/nand/pasemi_nand.c [deleted file]
drivers/mtd/nand/plat_nand.c [deleted file]
drivers/mtd/nand/pxa3xx_nand.c [deleted file]
drivers/mtd/nand/qcom_nandc.c [deleted file]
drivers/mtd/nand/r852.c [deleted file]
drivers/mtd/nand/r852.h [deleted file]
drivers/mtd/nand/raw/Kconfig [new file with mode: 0644]
drivers/mtd/nand/raw/Makefile [new file with mode: 0644]
drivers/mtd/nand/raw/ams-delta.c [new file with mode: 0644]
drivers/mtd/nand/raw/atmel/Makefile [new file with mode: 0644]
drivers/mtd/nand/raw/atmel/nand-controller.c [new file with mode: 0644]
drivers/mtd/nand/raw/atmel/pmecc.c [new file with mode: 0644]
drivers/mtd/nand/raw/atmel/pmecc.h [new file with mode: 0644]
drivers/mtd/nand/raw/au1550nd.c [new file with mode: 0644]
drivers/mtd/nand/raw/bcm47xxnflash/Makefile [new file with mode: 0644]
drivers/mtd/nand/raw/bcm47xxnflash/bcm47xxnflash.h [new file with mode: 0644]
drivers/mtd/nand/raw/bcm47xxnflash/main.c [new file with mode: 0644]
drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c [new file with mode: 0644]
drivers/mtd/nand/raw/brcmnand/Makefile [new file with mode: 0644]
drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/brcmnand/brcmnand.c [new file with mode: 0644]
drivers/mtd/nand/raw/brcmnand/brcmnand.h [new file with mode: 0644]
drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/brcmnand/iproc_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/cafe_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/cmx270_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/cs553x_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/davinci_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/denali.c [new file with mode: 0644]
drivers/mtd/nand/raw/denali.h [new file with mode: 0644]
drivers/mtd/nand/raw/denali_dt.c [new file with mode: 0644]
drivers/mtd/nand/raw/denali_pci.c [new file with mode: 0644]
drivers/mtd/nand/raw/diskonchip.c [new file with mode: 0644]
drivers/mtd/nand/raw/docg4.c [new file with mode: 0644]
drivers/mtd/nand/raw/fsl_elbc_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/fsl_ifc_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/fsl_upm.c [new file with mode: 0644]
drivers/mtd/nand/raw/fsmc_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/gpio.c [new file with mode: 0644]
drivers/mtd/nand/raw/gpmi-nand/Makefile [new file with mode: 0644]
drivers/mtd/nand/raw/gpmi-nand/bch-regs.h [new file with mode: 0644]
drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c [new file with mode: 0644]
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h [new file with mode: 0644]
drivers/mtd/nand/raw/gpmi-nand/gpmi-regs.h [new file with mode: 0644]
drivers/mtd/nand/raw/hisi504_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/jz4740_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/jz4780_bch.c [new file with mode: 0644]
drivers/mtd/nand/raw/jz4780_bch.h [new file with mode: 0644]
drivers/mtd/nand/raw/jz4780_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/lpc32xx_mlc.c [new file with mode: 0644]
drivers/mtd/nand/raw/lpc32xx_slc.c [new file with mode: 0644]
drivers/mtd/nand/raw/marvell_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/mpc5121_nfc.c [new file with mode: 0644]
drivers/mtd/nand/raw/mtk_ecc.c [new file with mode: 0644]
drivers/mtd/nand/raw/mtk_ecc.h [new file with mode: 0644]
drivers/mtd/nand/raw/mtk_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/mxc_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_amd.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_base.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_bbt.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_bch.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_ecc.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_hynix.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_ids.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_macronix.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_micron.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_samsung.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_timings.c [new file with mode: 0644]
drivers/mtd/nand/raw/nand_toshiba.c [new file with mode: 0644]
drivers/mtd/nand/raw/nandsim.c [new file with mode: 0644]
drivers/mtd/nand/raw/ndfc.c [new file with mode: 0644]
drivers/mtd/nand/raw/nuc900_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/omap2.c [new file with mode: 0644]
drivers/mtd/nand/raw/omap_elm.c [new file with mode: 0644]
drivers/mtd/nand/raw/orion_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/oxnas_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/pasemi_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/plat_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/qcom_nandc.c [new file with mode: 0644]
drivers/mtd/nand/raw/r852.c [new file with mode: 0644]
drivers/mtd/nand/raw/r852.h [new file with mode: 0644]
drivers/mtd/nand/raw/s3c2410.c [new file with mode: 0644]
drivers/mtd/nand/raw/sh_flctl.c [new file with mode: 0644]
drivers/mtd/nand/raw/sharpsl.c [new file with mode: 0644]
drivers/mtd/nand/raw/sm_common.c [new file with mode: 0644]
drivers/mtd/nand/raw/sm_common.h [new file with mode: 0644]
drivers/mtd/nand/raw/socrates_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/sunxi_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/tango_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/tmio_nand.c [new file with mode: 0644]
drivers/mtd/nand/raw/txx9ndfmc.c [new file with mode: 0644]
drivers/mtd/nand/raw/vf610_nfc.c [new file with mode: 0644]
drivers/mtd/nand/raw/xway_nand.c [new file with mode: 0644]
drivers/mtd/nand/s3c2410.c [deleted file]
drivers/mtd/nand/sh_flctl.c [deleted file]
drivers/mtd/nand/sharpsl.c [deleted file]
drivers/mtd/nand/sm_common.c [deleted file]
drivers/mtd/nand/sm_common.h [deleted file]
drivers/mtd/nand/socrates_nand.c [deleted file]
drivers/mtd/nand/sunxi_nand.c [deleted file]
drivers/mtd/nand/tango_nand.c [deleted file]
drivers/mtd/nand/tmio_nand.c [deleted file]
drivers/mtd/nand/txx9ndfmc.c [deleted file]
drivers/mtd/nand/vf610_nfc.c [deleted file]
drivers/mtd/nand/xway_nand.c [deleted file]
drivers/mtd/nftlmount.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/Kconfig [deleted file]
drivers/mtd/onenand/Makefile [deleted file]
drivers/mtd/onenand/generic.c [deleted file]
drivers/mtd/onenand/omap2.c [deleted file]
drivers/mtd/onenand/onenand_base.c [deleted file]
drivers/mtd/onenand/onenand_bbt.c [deleted file]
drivers/mtd/onenand/samsung.c [deleted file]
drivers/mtd/onenand/samsung.h [deleted file]
drivers/mtd/rfd_ftl.c
drivers/mtd/sm_ftl.c
drivers/mtd/sm_ftl.h
drivers/mtd/spi-nor/fsl-quadspi.c
drivers/mtd/spi-nor/spi-nor.c
drivers/mtd/tests/mtd_test.c
drivers/mtd/tests/pagetest.c
drivers/mtd/tests/speedtest.c
drivers/mtd/ubi/gluebi.c
drivers/mtd/ubi/io.c
drivers/net/ethernet/sfc/falcon/mtd.c
drivers/net/ethernet/sfc/mtd.c
drivers/staging/goldfish/goldfish_nand.c
drivers/staging/mt29f_spinand/mt29f_spinand.c
fs/jffs2/erase.c
include/linux/mtd/bbm.h
include/linux/mtd/mtd.h
include/linux/mtd/nand.h [new file with mode: 0644]
include/linux/mtd/nand_ecc.h
include/linux/mtd/ndfc.h
include/linux/mtd/partitions.h
include/linux/mtd/rawnand.h
include/linux/platform_data/mtd-nand-pxa3xx.h

index e18cab73e209a7b3057cfd672356dab6d9846483..85b28e8eb8ee7de6bdb7a99d2938cfc19a74273a 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -33,9 +33,9 @@ Axel Lin <axel.lin@gmail.com>
 Ben Gardner <bgardner@wabtec.com>
 Ben M Cahill <ben.m.cahill@intel.com>
 Björn Steinbrink <B.Steinbrink@gmx.de>
-Boris Brezillon <boris.brezillon@free-electrons.com>
-Boris Brezillon <boris.brezillon@free-electrons.com> <b.brezillon.dev@gmail.com>
-Boris Brezillon <boris.brezillon@free-electrons.com> <b.brezillon@overkiz.com>
+Boris Brezillon <boris.brezillon@bootlin.com> <boris.brezillon@free-electrons.com>
+Boris Brezillon <boris.brezillon@bootlin.com> <b.brezillon.dev@gmail.com>
+Boris Brezillon <boris.brezillon@bootlin.com> <b.brezillon@overkiz.com>
 Brian Avery <b.avery@hp.com>
 Brian King <brking@us.ibm.com>
 Christoph Hellwig <hch@lst.de>
@@ -126,6 +126,7 @@ Mayuresh Janorkar <mayur@ti.com>
 Michael Buesch <m@bues.ch>
 Michel Dänzer <michel@tungstengraphics.com>
 Miodrag Dinic <miodrag.dinic@mips.com> <miodrag.dinic@imgtec.com>
+Miquel Raynal <miquel.raynal@bootlin.com> <miquel.raynal@free-electrons.com>
 Mitesh shah <mshah@teja.com>
 Mohit Kumar <mohit.kumar@st.com> <mohit.kumar.dhaka@gmail.com>
 Morten Welinder <terra@gnome.org>
index f057876b920bea6448949c91bb6098e5fee61d93..dc1fd362d3c156e23cb4f48044ace615a70b5b9f 100644 (file)
@@ -46,7 +46,7 @@ NAND
 ----
 
   The NAND hardware is similar to the S3C2440, and is supported by the
-  s3c2410 driver in the drivers/mtd/nand directory.
+  s3c2410 driver in the drivers/mtd/nand/raw directory.
 
 
 USB Host
index 63d4d626fbd5117095ecf706f5e66548d5a957da..483e9cfac1b1b31d5856623813fdaa6e21d0093a 100644 (file)
@@ -39,3 +39,27 @@ qspi0: quadspi@40044000 {
                ....
        };
 };
+
+Example showing the usage of two SPI NOR devices:
+
+&qspi2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_qspi2>;
+       status = "okay";
+
+       flash0: n25q256a@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "micron,n25q256a", "jedec,spi-nor";
+               spi-max-frequency = <29000000>;
+               reg = <0>;
+       };
+
+       flash1: n25q256a@1 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "micron,n25q256a", "jedec,spi-nor";
+               spi-max-frequency = <29000000>;
+               reg = <1>;
+       };
+};
index c08fb477b3c6fd4a8cdd46d40be8a036da7870fd..e0c790706b9b10646363548f432c92bf51fe48b5 100644 (file)
@@ -14,7 +14,10 @@ Required properties:
 - #address-cells: shall be set to 1. Encode the NAND CS.
 - #size-cells: shall be set to 0.
 - interrupts: shall define the NAND controller interrupt.
-- clocks: shall reference the NAND controller clock.
+- clocks: shall reference the NAND controller clocks, the second one is
+  is only needed for the Armada 7K/8K SoCs
+- clock-names: mandatory if there is a second clock, in this case there
+  should be one clock named "core" and another one named "reg"
 - marvell,system-controller: Set to retrieve the syscon node that handles
   NAND controller related registers (only required with the
   "marvell,armada-8k-nand[-controller]" compatibles).
index 4a0a48bf4ecb831d0fc1e2b0263208d0b42cbb36..232fa12e90efa59082ad5cb3c66640fc148d9976 100644 (file)
@@ -41,6 +41,13 @@ additional (optional) property is defined:
 
  - erase-size : The chip's physical erase block size in bytes.
 
+ The device tree may optionally contain endianness property.
+ little-endian or big-endian : It Represents the endianness that should be used
+                               by the controller to  properly read/write data
+                              from/to the flash. If this property is missing,
+                              the endianness is chosen by the system
+                              (potentially based on extra configuration options).
+
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
 
diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
deleted file mode 100644 (file)
index d4ee4da..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-PXA3xx NAND DT bindings
-
-Required properties:
-
- - compatible:         Should be set to one of the following:
-                       marvell,pxa3xx-nand
-                       marvell,armada370-nand
-                       marvell,armada-8k-nand
- - reg:                The register base for the controller
- - interrupts:         The interrupt to map
- - #address-cells:     Set to <1> if the node includes partitions
- - marvell,system-controller: Set to retrieve the syscon node that handles
-                       NAND controller related registers (only required
-                       with marvell,armada-8k-nand compatible).
-
-Optional properties:
-
- - dmas:                       dma data channel, see dma.txt binding doc
- - marvell,nand-enable-arbiter:        Set to enable the bus arbiter
- - marvell,nand-keep-config:   Set to keep the NAND controller config as set
-                               by the bootloader
- - num-cs:                     Number of chipselect lines to use
- - nand-on-flash-bbt:          boolean to enable on flash bbt option if
-                               not present false
- - nand-ecc-strength:           number of bits to correct per ECC step
- - nand-ecc-step-size:          number of data bytes covered by a single ECC step
-
-The following ECC strength and step size are currently supported:
-
- - nand-ecc-strength = <1>, nand-ecc-step-size = <512>
- - nand-ecc-strength = <4>, nand-ecc-step-size = <512>
- - nand-ecc-strength = <8>, nand-ecc-step-size = <512>
-
-Example:
-
-       nand0: nand@43100000 {
-               compatible = "marvell,pxa3xx-nand";
-               reg = <0x43100000 90>;
-               interrupts = <45>;
-               dmas = <&pdma 97 0>;
-               dma-names = "data";
-               #address-cells = <1>;
-
-               marvell,nand-enable-arbiter;
-               marvell,nand-keep-config;
-               num-cs = <1>;
-
-               /* partitions (optional) */
-       };
-
index 5e13a5cdff03c40c81f43b121902ed62e334a2c7..0734f03bf3d311d051a88dde9102a210206690e4 100644 (file)
@@ -24,8 +24,8 @@ Optional properties:
 - allwinner,rb : shall contain the native Ready/Busy ids.
  or
 - rb-gpios : shall contain the gpios used as R/B pins.
-- nand-ecc-mode : one of the supported ECC modes ("hw", "hw_syndrome", "soft",
-  "soft_bch" or "none")
+- nand-ecc-mode : one of the supported ECC modes ("hw", "soft", "soft_bch" or
+                 "none")
 
 see Documentation/devicetree/bindings/mtd/nand.txt for generic bindings.
 
index 2a5191b6d4459fa76734bcdbad1f21e30278dcd9..dcd63599f70024b3aeabc492b7602b83bced8446 100644 (file)
@@ -967,10 +967,10 @@ API functions which are exported. Each function has a short description
 which is marked with an [XXX] identifier. See the chapter "Documentation
 hints" for an explanation.
 
-.. kernel-doc:: drivers/mtd/nand/nand_base.c
+.. kernel-doc:: drivers/mtd/nand/raw/nand_base.c
    :export:
 
-.. kernel-doc:: drivers/mtd/nand/nand_ecc.c
+.. kernel-doc:: drivers/mtd/nand/raw/nand_ecc.c
    :export:
 
 Internal Functions Provided
@@ -982,10 +982,10 @@ marked with an [XXX] identifier. See the chapter "Documentation hints"
 for an explanation. The functions marked with [DEFAULT] might be
 relevant for a board driver developer.
 
-.. kernel-doc:: drivers/mtd/nand/nand_base.c
+.. kernel-doc:: drivers/mtd/nand/raw/nand_base.c
    :internal:
 
-.. kernel-doc:: drivers/mtd/nand/nand_bbt.c
+.. kernel-doc:: drivers/mtd/nand/raw/nand_bbt.c
    :internal:
 
 Credits
index a2ccbab12eb7a6cc7b5107fc9142175a09dbffd7..a3e612f55bc71d6c929eabc90ef6ebf894827ba8 100644 (file)
@@ -74,8 +74,8 @@ hardware descriptions such as device tree or ACPI:
   it from 1-to-0-to-1. If that hardware does not receive its "ping"
   periodically, it will reset the system.
 
-- gpio-nand: drivers/mtd/nand/gpio.c is used to connect a NAND flash chip to
-  a set of simple GPIO lines: RDY, NCE, ALE, CLE, NWP. It interacts with the
+- gpio-nand: drivers/mtd/nand/raw/gpio.c is used to connect a NAND flash chip
+  to a set of simple GPIO lines: RDY, NCE, ALE, CLE, NWP. It interacts with the
   NAND flash MTD subsystem and provides chip access and partition parsing like
   any other NAND driving hardware.
 
index 9a7f76eadae9a51c5b49e5faadf8aa0aef19f15c..ce3519e1c18c76dfb0eee38b6890e40281d395ab 100644 (file)
@@ -1232,7 +1232,7 @@ F:        arch/arm/boot/dts/aspeed-*
 F:     drivers/*/*aspeed*
 
 ARM/ATMEL AT91 Clock Support
-M:     Boris Brezillon <boris.brezillon@free-electrons.com>
+M:     Boris Brezillon <boris.brezillon@bootlin.com>
 S:     Maintained
 F:     drivers/clk/at91
 
@@ -1710,7 +1710,7 @@ F:        drivers/input/keyboard/w90p910_keypad.c
 F:     drivers/input/touchscreen/w90p910_ts.c
 F:     drivers/watchdog/nuc900_wdt.c
 F:     drivers/net/ethernet/nuvoton/w90p910_ether.c
-F:     drivers/mtd/nand/nuc900_nand.c
+F:     drivers/mtd/nand/raw/nuc900_nand.c
 F:     drivers/rtc/rtc-nuc900.c
 F:     drivers/spi/spi-nuc900.c
 F:     drivers/usb/host/ehci-w90x900.c
@@ -3014,7 +3014,7 @@ M:        Kamal Dasu <kdasu.kdev@gmail.com>
 L:     linux-mtd@lists.infradead.org
 L:     bcm-kernel-feedback-list@broadcom.com
 S:     Maintained
-F:     drivers/mtd/nand/brcmnand/
+F:     drivers/mtd/nand/raw/brcmnand/
 
 BROADCOM STB DPFE DRIVER
 M:     Markus Mayer <mmayer@broadcom.com>
@@ -4116,7 +4116,7 @@ DENALI NAND DRIVER
 M:     Masahiro Yamada <yamada.masahiro@socionext.com>
 L:     linux-mtd@lists.infradead.org
 S:     Supported
-F:     drivers/mtd/nand/denali*
+F:     drivers/mtd/nand/raw/denali*
 
 DESIGNWARE USB2 DRD IP DRIVER
 M:     John Youn <johnyoun@synopsys.com>
@@ -4644,7 +4644,7 @@ F:        Documentation/gpu/meson.rst
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DRM DRIVERS FOR ATMEL HLCDC
-M:     Boris Brezillon <boris.brezillon@free-electrons.com>
+M:     Boris Brezillon <boris.brezillon@bootlin.com>
 L:     dri-devel@lists.freedesktop.org
 S:     Supported
 F:     drivers/gpu/drm/atmel-hlcdc/
@@ -5646,7 +5646,7 @@ FREESCALE GPMI NAND DRIVER
 M:     Han Xu <han.xu@nxp.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
-F:     drivers/mtd/nand/gpmi-nand/*
+F:     drivers/mtd/nand/raw/gpmi-nand/*
 
 FREESCALE I2C CPM DRIVER
 M:     Jochen Friedrich <jochen@scram.de>
@@ -6955,7 +6955,7 @@ INGENIC JZ4780 NAND DRIVER
 M:     Harvey Hunt <harveyhuntnexus@gmail.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
-F:     drivers/mtd/nand/jz4780_*
+F:     drivers/mtd/nand/raw/jz4780_*
 
 INOTIFY
 M:     Jan Kara <jack@suse.cz>
@@ -8412,7 +8412,7 @@ F:        include/uapi/drm/armada_drm.h
 F:     Documentation/devicetree/bindings/display/armada/
 
 MARVELL CRYPTO DRIVER
-M:     Boris Brezillon <boris.brezillon@free-electrons.com>
+M:     Boris Brezillon <boris.brezillon@bootlin.com>
 M:     Arnaud Ebalard <arno@natisbad.org>
 F:     drivers/crypto/marvell/
 S:     Maintained
@@ -8471,10 +8471,10 @@ S:      Odd Fixes
 F:     drivers/net/wireless/marvell/mwl8k.c
 
 MARVELL NAND CONTROLLER DRIVER
-M:     Miquel Raynal <miquel.raynal@free-electrons.com>
+M:     Miquel Raynal <miquel.raynal@bootlin.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
-F:     drivers/mtd/nand/marvell_nand.c
+F:     drivers/mtd/nand/raw/marvell_nand.c
 F:     Documentation/devicetree/bindings/mtd/marvell-nand.txt
 
 MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
@@ -9034,10 +9034,9 @@ F:       mm/
 MEMORY TECHNOLOGY DEVICES (MTD)
 M:     David Woodhouse <dwmw2@infradead.org>
 M:     Brian Norris <computersforpeace@gmail.com>
-M:     Boris Brezillon <boris.brezillon@free-electrons.com>
+M:     Boris Brezillon <boris.brezillon@bootlin.com>
 M:     Marek Vasut <marek.vasut@gmail.com>
 M:     Richard Weinberger <richard@nod.at>
-M:     Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
 Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
@@ -9136,7 +9135,7 @@ M:        Wenyou Yang <wenyou.yang@microchip.com>
 M:     Josh Wu <rainyfeeling@outlook.com>
 L:     linux-mtd@lists.infradead.org
 S:     Supported
-F:     drivers/mtd/nand/atmel/*
+F:     drivers/mtd/nand/raw/atmel/*
 F:     Documentation/devicetree/bindings/mtd/atmel-nand.txt
 
 MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER
@@ -9453,7 +9452,7 @@ S:        Supported
 F:     drivers/net/ethernet/myricom/myri10ge/
 
 NAND FLASH SUBSYSTEM
-M:     Boris Brezillon <boris.brezillon@free-electrons.com>
+M:     Boris Brezillon <boris.brezillon@bootlin.com>
 R:     Richard Weinberger <richard@nod.at>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
@@ -10208,7 +10207,7 @@ ONENAND FLASH DRIVER
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
-F:     drivers/mtd/onenand/
+F:     drivers/mtd/nand/onenand/
 F:     include/linux/mtd/onenand*.h
 
 ONSTREAM SCSI TAPE DRIVER
@@ -11329,12 +11328,6 @@ F:     include/sound/pxa2xx-lib.h
 F:     sound/arm/pxa*
 F:     sound/soc/pxa/
 
-PXA3xx NAND FLASH DRIVER
-M:     Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
-L:     linux-mtd@lists.infradead.org
-S:     Maintained
-F:     drivers/mtd/nand/pxa3xx_nand.c
-
 QAT DRIVER
 M:     Giovanni Cabiddu <giovanni.cabiddu@intel.com>
 L:     qat-linux@intel.com
@@ -11817,8 +11810,8 @@ F:      drivers/memstick/host/r592.*
 RICOH SMARTMEDIA/XD DRIVER
 M:     Maxim Levitsky <maximlevitsky@gmail.com>
 S:     Maintained
-F:     drivers/mtd/nand/r852.c
-F:     drivers/mtd/nand/r852.h
+F:     drivers/mtd/nand/raw/r852.c
+F:     drivers/mtd/nand/raw/r852.h
 
 RISC-V ARCHITECTURE
 M:     Palmer Dabbelt <palmer@sifive.com>
@@ -13008,7 +13001,6 @@ F:      arch/arm/boot/dts/spear*
 F:     arch/arm/mach-spear/
 
 SPI NOR SUBSYSTEM
-M:     Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
 M:     Marek Vasut <marek.vasut@gmail.com>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
@@ -14637,7 +14629,7 @@ VF610 NAND DRIVER
 M:     Stefan Agner <stefan@agner.ch>
 L:     linux-mtd@lists.infradead.org
 S:     Supported
-F:     drivers/mtd/nand/vf610_nfc.c
+F:     drivers/mtd/nand/raw/vf610_nfc.c
 
 VFAT/FAT/MSDOS FILESYSTEM
 M:     OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
index 55c75b67351cbfb8273da7027f45aa9f86e3353f..982d1a62661d4e8d265c66ccba8193635a571962 100644 (file)
                        status = "disabled";
                };
 
-               nand0: nand@43100000 {
-                       compatible = "marvell,pxa3xx-nand";
+               nand_controller: nand-controller@43100000 {
+                       compatible = "marvell,pxa3xx-nand-controller";
                        reg = <0x43100000 90>;
                        interrupts = <45>;
                        clocks = <&clks CLK_NAND>;
                        dmas = <&pdma 97 3>;
                        dma-names = "data";
                        #address-cells = <1>;
-                       #size-cells = <1>;      
+                       #size-cells = <0>;
                        status = "disabled";
                };
 
index c0418e03d18010d29d353644db0f446d7ff2bc49..5e349c625b71c8b06092929c066ba6065f376c0b 100644 (file)
@@ -49,7 +49,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_PXA3xx=y
+CONFIG_MTD_NAND_MARVELL=y
 CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
index bfea6874b0a1b4003fdd8903c30d3db2d9078d00..3e0de035ab7725fb742b9f47806c474ae7d87868 100644 (file)
@@ -32,8 +32,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_PXA3xx=y
-CONFIG_MTD_NAND_PXA3xx_BUILTIN=y
+CONFIG_MTD_NAND_MARVELL=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
 CONFIG_MTD_ONENAND_GENERIC=y
index 837d0c9c8b0eb7ef2d80e777489633b011c506ff..5655a1cee87d4828c7deb53cf3dc657e1f8343ef 100644 (file)
@@ -197,7 +197,7 @@ CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0x4000000
 CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH=y
 CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
 CONFIG_MTD_NAND_SHARPSL=m
-CONFIG_MTD_NAND_PXA3xx=m
+CONFIG_MTD_NAND_MARVELL=m
 CONFIG_MTD_NAND_CM_X270=m
 CONFIG_MTD_NAND_TMIO=m
 CONFIG_MTD_NAND_BRCMNAND=m
index 77a56c23c6ef977fdc2ea94659ad002983ee91f4..2dd56e9a484ef218ff56ed63a75dfb49d492c0cb 100644 (file)
@@ -33,7 +33,7 @@ CONFIG_NFTL=y
 CONFIG_NFTL_RW=y
 CONFIG_MTD_BLOCK2MTD=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_PXA3xx=y
+CONFIG_MTD_NAND_MARVELL=y
 CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_ISL29003=y
index d2283009a5ff1a0b09a9b200ecb2ed1d490ed1be..6c2ebf01893afeb9e5ab76a2e7a57026db684b4f 100644 (file)
@@ -172,10 +172,8 @@ static struct mtd_partition aspenite_nand_partitions[] = {
 };
 
 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
-       .enable_arbiter = 1,
-       .num_cs = 1,
-       .parts[0]       = aspenite_nand_partitions,
-       .nr_parts[0]    = ARRAY_SIZE(aspenite_nand_partitions),
+       .parts          = aspenite_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(aspenite_nand_partitions),
 };
 
 static struct i2c_board_info aspenite_i2c_info[] __initdata = {
index d90c74fa614d0f0951c196ce28ab13a19354bd64..c7897fb2b6dadd82c20536ccc5147cee20431597 100644 (file)
@@ -178,11 +178,8 @@ static struct mv_usb_platform_data ttc_usb_pdata = {
 #endif
 #endif
 
-#if IS_ENABLED(CONFIG_MTD_NAND_PXA3xx)
-static struct pxa3xx_nand_platform_data dkb_nand_info = {
-       .enable_arbiter = 1,
-       .num_cs = 1,
-};
+#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
+static struct pxa3xx_nand_platform_data dkb_nand_info = {};
 #endif
 
 #if IS_ENABLED(CONFIG_MMP_DISP)
@@ -275,7 +272,7 @@ static void __init ttc_dkb_init(void)
 
        /* on-chip devices */
        pxa910_add_uart(1);
-#if IS_ENABLED(CONFIG_MTD_NAND_PXA3xx)
+#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
        pxa910_add_nand(&dkb_nand_info);
 #endif
 
index c487401b6fdb5dbeffa0752ad90a8065921a6762..0e71799cab258a793393a92781b667aadefe1c6e 100644 (file)
@@ -391,7 +391,7 @@ static void __init cm_x300_init_ac97(void)
 static inline void cm_x300_init_ac97(void) {}
 #endif
 
-#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
 static struct mtd_partition cm_x300_nand_partitions[] = {
        [0] = {
                .name        = "OBM",
@@ -429,11 +429,9 @@ static struct mtd_partition cm_x300_nand_partitions[] = {
 };
 
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
-       .enable_arbiter = 1,
        .keep_config    = 1,
-       .num_cs         = 1,
-       .parts[0]       = cm_x300_nand_partitions,
-       .nr_parts[0]    = ARRAY_SIZE(cm_x300_nand_partitions),
+       .parts          = cm_x300_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(cm_x300_nand_partitions),
 };
 
 static void __init cm_x300_init_nand(void)
index b04431bb4ba74dfc4a43d99bdcf0a1416a8e2807..e31a591e949f3914bea2205fed5a7b9cde05539d 100644 (file)
@@ -110,7 +110,7 @@ void __init colibri_pxa3xx_init_lcd(int bl_pin)
 }
 #endif
 
-#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
 static struct mtd_partition colibri_nand_partitions[] = {
        {
                .name        = "bootloader",
@@ -138,11 +138,9 @@ static struct mtd_partition colibri_nand_partitions[] = {
 };
 
 static struct pxa3xx_nand_platform_data colibri_nand_info = {
-       .enable_arbiter = 1,
        .keep_config    = 1,
-       .num_cs         = 1,
-       .parts[0]       = colibri_nand_partitions,
-       .nr_parts[0]    = ARRAY_SIZE(colibri_nand_partitions),
+       .parts          = colibri_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(colibri_nand_partitions),
 };
 
 void __init colibri_pxa3xx_init_nand(void)
index 673a131da875b1189c6a1a117322014284c215e9..85525d49e321bc7983559435e8ea60a14ae4a47d 100644 (file)
@@ -46,7 +46,7 @@ static inline void colibri_pxa3xx_init_lcd(int bl_pin) {}
 extern void colibri_pxa3xx_init_eth(struct ax_plat_data *plat_data);
 #endif
 
-#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
 extern void colibri_pxa3xx_init_nand(void);
 #else
 static inline void colibri_pxa3xx_init_nand(void) {}
index 4105614cc38e40407b075273fb0d6f40e072ef36..9e132b3e48c68ef767ef7055b8d37cddc9d6453c 100644 (file)
@@ -291,7 +291,7 @@ static void __init littleton_init_mmc(void)
 static inline void littleton_init_mmc(void) {}
 #endif
 
-#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
 static struct mtd_partition littleton_nand_partitions[] = {
        [0] = {
                .name        = "Bootloader",
@@ -329,10 +329,8 @@ static struct mtd_partition littleton_nand_partitions[] = {
 };
 
 static struct pxa3xx_nand_platform_data littleton_nand_info = {
-       .enable_arbiter = 1,
-       .num_cs         = 1,
-       .parts[0]       = littleton_nand_partitions,
-       .nr_parts[0]    = ARRAY_SIZE(littleton_nand_partitions),
+       .parts          = littleton_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(littleton_nand_partitions),
 };
 
 static void __init littleton_init_nand(void)
@@ -341,7 +339,7 @@ static void __init littleton_init_nand(void)
 }
 #else
 static inline void littleton_init_nand(void) {}
-#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
+#endif /* IS_ENABLED(CONFIG_MTD_NAND_MARVELL) */
 
 #if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE)
 static struct led_info littleton_da9034_leds[] = {
index f9e3d41a4609a19aa9052af8db5ef0bd2d68b9f9..616b22397d7351a74e814f9e00f2d9853bc5839d 100644 (file)
@@ -359,7 +359,7 @@ void __init mxm_8x10_ac97_init(void)
 }
 
 /* NAND flash Support */
-#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
 #define NAND_BLOCK_SIZE SZ_128K
 #define NB(x)           (NAND_BLOCK_SIZE * (x))
 static struct mtd_partition mxm_8x10_nand_partitions[] = {
@@ -389,11 +389,9 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = {
 };
 
 static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
-       .enable_arbiter = 1,
        .keep_config    = 1,
-       .num_cs         = 1,
-       .parts[0]       = mxm_8x10_nand_partitions,
-       .nr_parts[0]    = ARRAY_SIZE(mxm_8x10_nand_partitions)
+       .parts          = mxm_8x10_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(mxm_8x10_nand_partitions)
 };
 
 static void __init mxm_8x10_nand_init(void)
@@ -402,7 +400,7 @@ static void __init mxm_8x10_nand_init(void)
 }
 #else
 static inline void mxm_8x10_nand_init(void) {}
-#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
+#endif /* IS_ENABLED(CONFIG_MTD_NAND_MARVELL) */
 
 /* Ethernet support: Davicom DM9000 */
 static struct resource dm9k_resources[] = {
index 4d5d05cf87d69b513b337632ed6c3127a5ead6cf..8c95ae58312abeaa68517cf5dd392a2d2fe5dfbf 100644 (file)
@@ -346,11 +346,9 @@ static struct mtd_partition raumfeld_nand_partitions[] = {
 };
 
 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
-       .enable_arbiter = 1,
        .keep_config    = 1,
-       .num_cs         = 1,
-       .parts[0]       = raumfeld_nand_partitions,
-       .nr_parts[0]    = ARRAY_SIZE(raumfeld_nand_partitions),
+       .parts          = raumfeld_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(raumfeld_nand_partitions),
 };
 
 /**
index 4268552d600d6cd9b0db37473f843f37e95e55b8..d69de312d8d91a432d5652428cdfc3808ff760e6 100644 (file)
@@ -338,7 +338,7 @@ static void __init zylonite_init_keypad(void)
 static inline void zylonite_init_keypad(void) {}
 #endif
 
-#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
 static struct mtd_partition zylonite_nand_partitions[] = {
        [0] = {
                .name        = "Bootloader",
@@ -376,10 +376,8 @@ static struct mtd_partition zylonite_nand_partitions[] = {
 };
 
 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
-       .enable_arbiter = 1,
-       .num_cs         = 1,
-       .parts[0]       = zylonite_nand_partitions,
-       .nr_parts[0]    = ARRAY_SIZE(zylonite_nand_partitions),
+       .parts          = zylonite_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(zylonite_nand_partitions),
 };
 
 static void __init zylonite_init_nand(void)
@@ -388,7 +386,7 @@ static void __init zylonite_init_nand(void)
 }
 #else
 static inline void zylonite_init_nand(void) {}
-#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
+#endif /* IS_ENABLED(CONFIG_MTD_NAND_MARVELL) */
 
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 static struct pxaohci_platform_data zylonite_ohci_info = {
index 925a98eb6d688eb12e7a18eac07130de202d3095..7ec29d2d366167df268665d9306e8599a11e92bd 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (c) 2007
  *
- *  Derived from drivers/mtd/nand/spia.c
+ *  Derived from drivers/mtd/nand/spia.c (removed in v3.8)
  *       Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
  *
  * This program is free software; you can redistribute it and/or modify
index 53b56a429dde8b859b06106472765ac74dc21312..7ce72906039ab416613b169b75e5a2299edd5d75 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (c) 2004
  *
- *  Derived from drivers/mtd/nand/spia.c
+ *  Derived from drivers/mtd/nand/spia.c (removed in v3.8)
  *       Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
  *
  * This program is free software; you can redistribute it and/or modify
index 2a8ac6829d42b187e20f6f2a7c80b400d19a423b..46ab7feec6b686b1f217899420ff160505f46396 100644 (file)
@@ -333,8 +333,6 @@ source "drivers/mtd/devices/Kconfig"
 
 source "drivers/mtd/nand/Kconfig"
 
-source "drivers/mtd/onenand/Kconfig"
-
 source "drivers/mtd/lpddr/Kconfig"
 
 source "drivers/mtd/spi-nor/Kconfig"
index d6f8f625e1ff2806ee9284da58c863598219ed7c..93473d215a38776b0237556fc321f1d436ef5841 100644 (file)
@@ -32,7 +32,7 @@ obj-$(CONFIG_MTD_SWAP)                += mtdswap.o
 nftl-objs              := nftlcore.o nftlmount.o
 inftl-objs             := inftlcore.o inftlmount.o
 
-obj-y          += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
+obj-y          += chips/ lpddr/ maps/ devices/ nand/ tests/
 
 obj-$(CONFIG_MTD_SPI_NOR)      += spi-nor/
 obj-$(CONFIG_MTD_UBI)          += ubi/
index 5e1b68cbcd0acf736a9d28978b6b7ef37055c5cd..d4c07b85f18e598ef8c0f85e8ce6fd70c9709396 100644 (file)
@@ -1993,20 +1993,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
 
 static int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
 {
-       unsigned long ofs, len;
-       int ret;
-
-       ofs = instr->addr;
-       len = instr->len;
-
-       ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
-       if (ret)
-               return ret;
-
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
-
-       return 0;
+       return cfi_varsize_frob(mtd, do_erase_oneblock, instr->addr,
+                               instr->len, NULL);
 }
 
 static void cfi_intelext_sync (struct mtd_info *mtd)
index 56aa6b75213d86d0442823e9b4163118231f9f30..668e2cbc155bbe008858ba9a11a5467fb5fc39ba 100644 (file)
@@ -2415,20 +2415,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
 
 static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
 {
-       unsigned long ofs, len;
-       int ret;
-
-       ofs = instr->addr;
-       len = instr->len;
-
-       ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
-       if (ret)
-               return ret;
-
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
-
-       return 0;
+       return cfi_varsize_frob(mtd, do_erase_oneblock, instr->addr,
+                               instr->len, NULL);
 }
 
 
@@ -2436,7 +2424,6 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
 {
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
-       int ret = 0;
 
        if (instr->addr != 0)
                return -EINVAL;
@@ -2444,14 +2431,7 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
        if (instr->len != mtd->size)
                return -EINVAL;
 
-       ret = do_erase_chip(map, &cfi->chips[0]);
-       if (ret)
-               return ret;
-
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
-
-       return 0;
+       return do_erase_chip(map, &cfi->chips[0]);
 }
 
 static int do_atmel_lock(struct map_info *map, struct flchip *chip,
index 7d342965f392232d89919a0182982e7764982b82..7b7658a05036d59c46ea7ca8e5db9322e59792aa 100644 (file)
@@ -965,9 +965,6 @@ static int cfi_staa_erase_varsize(struct mtd_info *mtd,
                }
        }
 
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
-
        return 0;
 }
 
index 7c0b27d132b1bca8aa546cedac726cf5e92c6613..9516439bb1a5146e5e464cb28f8a36c812ba6900 100644 (file)
@@ -53,6 +53,8 @@
 #define AT49BV32XT     0x00C9
 
 /* Eon */
+#define EN29LV400AT    0x22B9
+#define EN29LV400AB    0x22BA
 #define EN29SL800BB    0x226B
 #define EN29SL800BT    0x22EA
 
@@ -641,6 +643,36 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x10000,63),
                        ERASEINFO(0x02000,8)
                }
+       }, {
+               .mfr_id         = CFI_MFR_EON,
+               .dev_id         = EN29LV400AT,
+               .name           = "Eon EN29LV400AT",
+               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_0x0AAA_0x0555,
+               .dev_size       = SIZE_512KiB,
+               .cmd_set        = P_ID_AMD_STD,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x10000,7),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x04000,1),
+               }
+       }, {
+               .mfr_id         = CFI_MFR_EON,
+               .dev_id         = EN29LV400AB,
+               .name           = "Eon EN29LV400AB",
+               .devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
+               .uaddr          = MTD_UADDR_0x0AAA_0x0555,
+               .dev_size       = SIZE_512KiB,
+               .cmd_set        = P_ID_AMD_STD,
+               .nr_regions     = 4,
+               .regions        = {
+                       ERASEINFO(0x04000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x10000,7),
+               }
        }, {
                .mfr_id         = CFI_MFR_EON,
                .dev_id         = EN29SL800BT,
index 1cd0fff0e9402d9c1ee477674be5b90611dcb561..c37fce92686407bbad54c0c4a8b4d6d78ffd4079 100644 (file)
@@ -131,8 +131,6 @@ static int mapram_erase (struct mtd_info *mtd, struct erase_info *instr)
        allff = map_word_ff(map);
        for (i=0; i<instr->len; i += map_bankwidth(map))
                map_write(map, allff, instr->addr + i);
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
        return 0;
 }
 
index e2bd81817df44b89bc8ed2b04d074949496785dc..9baa81b8780cefff65e6fec2fe69d96f1361240f 100644 (file)
@@ -68,7 +68,6 @@ static int bcm47xxsflash_poll(struct bcm47xxsflash *b47s, int timeout)
 static int bcm47xxsflash_erase(struct mtd_info *mtd, struct erase_info *erase)
 {
        struct bcm47xxsflash *b47s = mtd->priv;
-       int err;
 
        switch (b47s->type) {
        case BCM47XXSFLASH_TYPE_ST:
@@ -89,16 +88,7 @@ static int bcm47xxsflash_erase(struct mtd_info *mtd, struct erase_info *erase)
                break;
        }
 
-       err = bcm47xxsflash_poll(b47s, HZ);
-       if (err)
-               erase->state = MTD_ERASE_FAILED;
-       else
-               erase->state = MTD_ERASE_DONE;
-
-       if (erase->callback)
-               erase->callback(erase);
-
-       return err;
+       return bcm47xxsflash_poll(b47s, HZ);
 }
 
 static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
index 62fd6905c648c6eb5ef167e019831729bb294a85..c9e424993e37e1c9708e709a476461878553fe06 100644 (file)
@@ -88,17 +88,12 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
        size_t len = instr->len;
        int err;
 
-       instr->state = MTD_ERASING;
        mutex_lock(&dev->write_mutex);
        err = _block2mtd_erase(dev, from, len);
        mutex_unlock(&dev->write_mutex);
-       if (err) {
+       if (err)
                pr_err("erase failed err = %d\n", err);
-               instr->state = MTD_ERASE_FAILED;
-       } else
-               instr->state = MTD_ERASE_DONE;
 
-       mtd_erase_callback(instr);
        return err;
 }
 
@@ -225,7 +220,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
        int i;
 #endif
        const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
-       struct block_device *bdev = ERR_PTR(-ENODEV);
+       struct block_device *bdev;
        struct block2mtd_dev *dev;
        char *name;
 
index a85af236b44d7ff690e874f5c7f8db5d88ce1ae7..c594fe5eac085c337e3facdeb3306b3e07fef4ba 100644 (file)
@@ -1191,39 +1191,27 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *info)
 {
        struct docg3 *docg3 = mtd->priv;
        uint64_t len;
-       int block0, block1, page, ret, ofs = 0;
+       int block0, block1, page, ret = 0, ofs = 0;
 
        doc_dbg("doc_erase(from=%lld, len=%lld\n", info->addr, info->len);
 
-       info->state = MTD_ERASE_PENDING;
        calc_block_sector(info->addr + info->len, &block0, &block1, &page,
                          &ofs, docg3->reliable);
-       ret = -EINVAL;
        if (info->addr + info->len > mtd->size || page || ofs)
-               goto reset_err;
+               return -EINVAL;
 
-       ret = 0;
        calc_block_sector(info->addr, &block0, &block1, &page, &ofs,
                          docg3->reliable);
        mutex_lock(&docg3->cascade->lock);
        doc_set_device_id(docg3, docg3->device_id);
        doc_set_reliable_mode(docg3);
        for (len = info->len; !ret && len > 0; len -= mtd->erasesize) {
-               info->state = MTD_ERASING;
                ret = doc_erase_block(docg3, block0, block1);
                block0 += 2;
                block1 += 2;
        }
        mutex_unlock(&docg3->cascade->lock);
 
-       if (ret)
-               goto reset_err;
-
-       info->state = MTD_ERASE_DONE;
-       return 0;
-
-reset_err:
-       info->state = MTD_ERASE_FAILED;
        return ret;
 }
 
index 555b94406e0bb31a83c92fd03a70250cce015842..f67b653c17d70bd8d3fc08745f03963d174ea0ff 100644 (file)
@@ -414,10 +414,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
    while (len)
         {
                if (!erase_block (addr))
-                 {
-                        instr->state = MTD_ERASE_FAILED;
                         return (-EIO);
-                 }
 
                addr += mtd->eraseregions[i].erasesize;
                len -= mtd->eraseregions[i].erasesize;
@@ -425,9 +422,6 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
                if (addr == mtd->eraseregions[i].offset + (mtd->eraseregions[i].erasesize * mtd->eraseregions[i].numblocks)) i++;
         }
 
-   instr->state = MTD_ERASE_DONE;
-   mtd_erase_callback(instr);
-
    return (0);
 }
 
index 5dc8bd042cc54b2d07407f123d0ee62bce738594..aaaeaae01e1dfea48f57115d7519b27dfcc64fd6 100644 (file)
@@ -220,10 +220,6 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
        }
        mutex_unlock(&priv->lock);
 
-       /* Inform MTD subsystem that erase is complete */
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
-
        return 0;
 }
 
index 0bf4aeaf0cb8cf14665ee8474c3faeb68479fd88..46238796145ffad93092197b7dc76fa0ae9c91ef 100644 (file)
@@ -60,8 +60,7 @@ static int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
        if (check_offs_len(mtd, instr->addr, instr->len))
                return -EINVAL;
        memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
+
        return 0;
 }
 
index 7287696a21f91df6a875dc32a112e6206c855de1..9ee04b5f931139cbb6d119c6901c39a4a39cda0f 100644 (file)
@@ -39,13 +39,6 @@ static int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
 
        memset(start + instr->addr, 0xff, instr->len);
 
-       /*
-        * This'll catch a few races. Free the thing before returning :)
-        * I don't feel at all ashamed. This kind of thing is possible anyway
-        * with flash, but unlikely.
-        */
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
        return 0;
 }
 
index cadea0620cd0547f2698fb1eaef880059dfec676..5d842cbca3de9768aa3211ecefef269d16065bae 100644 (file)
@@ -184,12 +184,10 @@ static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
        }
 
       out:
-       instr->state = MTD_ERASE_DONE;
 #ifdef CONFIG_MTD_PMC551_DEBUG
        printk(KERN_DEBUG "pmc551_erase() done\n");
 #endif
 
-       mtd_erase_callback(instr);
        return 0;
 }
 
index 26f9feaa5d17442a078468ad96af503744ac94c6..c1312b141ae0538cbaeed3b4ccde20109dd01a62 100644 (file)
@@ -175,19 +175,11 @@ static int powernv_flash_erase(struct mtd_info *mtd, struct erase_info *erase)
 {
        int rc;
 
-       erase->state = MTD_ERASING;
-
-       /* todo: register our own notifier to do a true async implementation */
        rc =  powernv_flash_async_op(mtd, FLASH_OP_ERASE, erase->addr,
                        erase->len, NULL, NULL);
-
-       if (rc) {
+       if (rc)
                erase->fail_addr = erase->addr;
-               erase->state = MTD_ERASE_FAILED;
-       } else {
-               erase->state = MTD_ERASE_DONE;
-       }
-       mtd_erase_callback(erase);
+
        return rc;
 }
 
index 0ec85f316d24c04e8503c8ca7625a3c16399a97b..10183ee4e12b283dc87729d9d3e6dd9326ed220a 100644 (file)
@@ -84,12 +84,7 @@ static int slram_erase(struct mtd_info *mtd, struct erase_info *instr)
        slram_priv_t *priv = mtd->priv;
 
        memset(priv->start + instr->addr, 0xff, instr->len);
-       /* This'll catch a few races. Free the thing before returning :)
-        * I don't feel at all ashamed. This kind of thing is possible anyway
-        * with flash, but unlikely.
-        */
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
+
        return(0);
 }
 
index ddf4789760136ca5770a291a4ef84116ebd0dff5..986f81d2f93e3d8cdceed38250dbdc8d48046663 100644 (file)
@@ -518,7 +518,6 @@ static int spear_mtd_erase(struct mtd_info *mtd, struct erase_info *e_info)
                /* preparing the command for flash */
                ret = spear_smi_erase_sector(dev, bank, command, 4);
                if (ret) {
-                       e_info->state = MTD_ERASE_FAILED;
                        mutex_unlock(&flash->lock);
                        return ret;
                }
@@ -527,8 +526,6 @@ static int spear_mtd_erase(struct mtd_info *mtd, struct erase_info *e_info)
        }
 
        mutex_unlock(&flash->lock);
-       e_info->state = MTD_ERASE_DONE;
-       mtd_erase_callback(e_info);
 
        return 0;
 }
index 5b84d71efb3642f179b5128ae2d4c6c76a4cdc31..1897f33fe3e71dea5c6d75e794f83a7bfe129082 100644 (file)
@@ -195,7 +195,6 @@ static int sst25l_erase(struct mtd_info *mtd, struct erase_info *instr)
                err = sst25l_erase_sector(flash, addr);
                if (err) {
                        mutex_unlock(&flash->lock);
-                       instr->state = MTD_ERASE_FAILED;
                        dev_err(&flash->spi->dev, "Erase failed\n");
                        return err;
                }
@@ -205,8 +204,6 @@ static int sst25l_erase(struct mtd_info *mtd, struct erase_info *instr)
 
        mutex_unlock(&flash->lock);
 
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
        return 0;
 }
 
index 7bc29d7252005506c2c81f03d39815d3567e342c..55d4a77f3b7f5732b1db91e2b5910d9488228ee1 100644 (file)
@@ -1825,13 +1825,9 @@ static int stfsm_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 
        mutex_unlock(&fsm->lock);
 
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
-
        return 0;
 
 out1:
-       instr->state = MTD_ERASE_FAILED;
        mutex_unlock(&fsm->lock);
 
        return ret;
@@ -1868,8 +1864,7 @@ static struct flash_info *stfsm_jedec_probe(struct stfsm *fsm)
         */
        ext_jedec = id[3] << 8  | id[4];
 
-       dev_dbg(fsm->dev, "JEDEC =  0x%08x [%02x %02x %02x %02x %02x]\n",
-               jedec, id[0], id[1], id[2], id[3], id[4]);
+       dev_dbg(fsm->dev, "JEDEC =  0x%08x [%5ph]\n", jedec, id);
 
        for (info = flash_types; info->name; info++) {
                if (info->jedec_id == jedec) {
index 664d206a4cbee2c51bf1edcfb8cbfb6c78d200fc..ef6ad2551d574c5037767b1ff9fdf37300f3490c 100644 (file)
@@ -140,12 +140,6 @@ typedef struct partition_t {
 #define XFER_PREPARED  0x03
 #define XFER_FAILED    0x04
 
-/*====================================================================*/
-
-
-static void ftl_erase_callback(struct erase_info *done);
-
-
 /*======================================================================
 
     Scan_header() checks to see if a memory region contains an FTL
@@ -348,18 +342,19 @@ static int erase_xfer(partition_t *part,
     if (!erase)
             return -ENOMEM;
 
-    erase->mtd = part->mbd.mtd;
-    erase->callback = ftl_erase_callback;
     erase->addr = xfer->Offset;
     erase->len = 1 << part->header.EraseUnitSize;
-    erase->priv = (u_long)part;
 
     ret = mtd_erase(part->mbd.mtd, erase);
+    if (!ret) {
+       xfer->state = XFER_ERASED;
+       xfer->EraseCount++;
+    } else {
+       xfer->state = XFER_FAILED;
+       pr_notice("ftl_cs: erase failed: err = %d\n", ret);
+    }
 
-    if (!ret)
-           xfer->EraseCount++;
-    else
-           kfree(erase);
+    kfree(erase);
 
     return ret;
 } /* erase_xfer */
@@ -371,37 +366,6 @@ static int erase_xfer(partition_t *part,
 
 ======================================================================*/
 
-static void ftl_erase_callback(struct erase_info *erase)
-{
-    partition_t *part;
-    struct xfer_info_t *xfer;
-    int i;
-
-    /* Look up the transfer unit */
-    part = (partition_t *)(erase->priv);
-
-    for (i = 0; i < part->header.NumTransferUnits; i++)
-       if (part->XferInfo[i].Offset == erase->addr) break;
-
-    if (i == part->header.NumTransferUnits) {
-       printk(KERN_NOTICE "ftl_cs: internal error: "
-              "erase lookup failed!\n");
-       return;
-    }
-
-    xfer = &part->XferInfo[i];
-    if (erase->state == MTD_ERASE_DONE)
-       xfer->state = XFER_ERASED;
-    else {
-       xfer->state = XFER_FAILED;
-       printk(KERN_NOTICE "ftl_cs: erase failed: state = %d\n",
-              erase->state);
-    }
-
-    kfree(erase);
-
-} /* ftl_erase_callback */
-
 static int prepare_xfer(partition_t *part, int i)
 {
     erase_unit_header_t header;
@@ -429,8 +393,8 @@ static int prepare_xfer(partition_t *part, int i)
     }
 
     /* Write the BAM stub */
-    nbam = (part->BlocksPerUnit * sizeof(uint32_t) +
-           le32_to_cpu(part->header.BAMOffset) + SECTOR_SIZE - 1) / SECTOR_SIZE;
+    nbam = DIV_ROUND_UP(part->BlocksPerUnit * sizeof(uint32_t) +
+                       le32_to_cpu(part->header.BAMOffset), SECTOR_SIZE);
 
     offset = xfer->Offset + le32_to_cpu(part->header.BAMOffset);
     ctl = cpu_to_le32(BLOCK_CONTROL);
index 8d6bb189ea8ed2948435049b829fda0787f5cd48..aab4f68bd36fc71882900274aaf3791cf38d3ab8 100644 (file)
@@ -208,8 +208,6 @@ static int find_boot_record(struct INFTLrecord *inftl)
                        if (ip->Reserved0 != ip->firstUnit) {
                                struct erase_info *instr = &inftl->instr;
 
-                               instr->mtd = inftl->mbd.mtd;
-
                                /*
                                 *      Most likely this is using the
                                 *      undocumented qiuck mount feature.
@@ -385,7 +383,6 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
           _first_? */
 
        /* Use async erase interface, test return code */
-       instr->mtd = inftl->mbd.mtd;
        instr->addr = block * inftl->EraseSize;
        instr->len = inftl->mbd.mtd->erasesize;
        /* Erase one physical eraseblock at a time, even though the NAND api
@@ -393,9 +390,10 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
           mark only the failed block in the bbt. */
        for (physblock = 0; physblock < inftl->EraseSize;
             physblock += instr->len, instr->addr += instr->len) {
-               mtd_erase(inftl->mbd.mtd, instr);
+               int ret;
 
-               if (instr->state == MTD_ERASE_FAILED) {
+               ret = mtd_erase(inftl->mbd.mtd, instr);
+               if (ret) {
                        printk(KERN_WARNING "INFTL: error while formatting block %d\n",
                                block);
                        goto fail;
index 2342277c9bcb063f3c1c4691ecfe467cac04dfa8..5d73db2a496de2693ade04d28bcfb25ce814d7db 100644 (file)
@@ -380,14 +380,8 @@ out:
  */
 static int lpddr2_nvm_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
-       int ret = lpddr2_nvm_do_block_op(mtd, instr->addr, instr->len,
-               LPDDR2_NVM_ERASE);
-       if (!ret) {
-               instr->state = MTD_ERASE_DONE;
-               mtd_erase_callback(instr);
-       }
-
-       return ret;
+       return lpddr2_nvm_do_block_op(mtd, instr->addr, instr->len,
+                                     LPDDR2_NVM_ERASE);
 }
 
 /*
index 018c75faadb3d30c2de119608536b1335d175fa4..5c5ba3c7c79d5ffa8a1d545e68fec32feae291dd 100644 (file)
@@ -693,8 +693,6 @@ static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr)
                ofs += size;
                len -= size;
        }
-       instr->state = MTD_ERASE_DONE;
-       mtd_erase_callback(instr);
 
        return 0;
 }
index 542fdf8e81faf7a7152b5cb8312ed4721645a86d..bdc1283f30fb86bbc146d2ff8154dd04ff6d98a2 100644 (file)
@@ -334,16 +334,6 @@ config MTD_PCMCIA_ANONYMOUS
 
          If unsure, say N.
 
-config MTD_BFIN_ASYNC
-       tristate "Blackfin BF533-STAMP Flash Chip Support"
-       depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS
-       default y
-       help
-         Map driver which allows for simultaneous utilization of
-         ethernet and CFI parallel flash.
-
-         If compiled as a module, it will be called bfin-async-flash.
-
 config MTD_GPIO_ADDR
        tristate "GPIO-assisted Flash Chip Support"
        depends on GPIOLIB || COMPILE_TEST
index b849aaf85c347fa0c6e9f89124a78c525422e303..51acf1fec19b54bce18f66893e901024f1574899 100644 (file)
@@ -42,7 +42,6 @@ obj-$(CONFIG_MTD_SCB2_FLASH)  += scb2_flash.o
 obj-$(CONFIG_MTD_IXP4XX)       += ixp4xx.o
 obj-$(CONFIG_MTD_PLATRAM)      += plat-ram.o
 obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o
-obj-$(CONFIG_MTD_BFIN_ASYNC)   += bfin-async-flash.o
 obj-$(CONFIG_MTD_RBTX4939)     += rbtx4939-flash.o
 obj-$(CONFIG_MTD_VMU)          += vmu-flash.o
 obj-$(CONFIG_MTD_GPIO_ADDR)    += gpio-addr-flash.o
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
deleted file mode 100644 (file)
index 41730fe..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * drivers/mtd/maps/bfin-async-flash.c
- *
- * Handle the case where flash memory and ethernet mac/phy are
- * mapped onto the same async bank.  The BF533-STAMP does this
- * for example.  All board-specific configuration goes in your
- * board resources file.
- *
- * Copyright 2000 Nicolas Pitre <nico@fluxnic.net>
- * Copyright 2005-2008 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-#include <asm/blackfin.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <asm/unaligned.h>
-
-#define pr_devinit(fmt, args...) \
-               ({ static const char __fmt[] = fmt; printk(__fmt, ## args); })
-
-#define DRIVER_NAME "bfin-async-flash"
-
-struct async_state {
-       struct mtd_info *mtd;
-       struct map_info map;
-       int enet_flash_pin;
-       uint32_t flash_ambctl0, flash_ambctl1;
-       uint32_t save_ambctl0, save_ambctl1;
-       unsigned long irq_flags;
-};
-
-static void switch_to_flash(struct async_state *state)
-{
-       local_irq_save(state->irq_flags);
-
-       gpio_set_value(state->enet_flash_pin, 0);
-
-       state->save_ambctl0 = bfin_read_EBIU_AMBCTL0();
-       state->save_ambctl1 = bfin_read_EBIU_AMBCTL1();
-       bfin_write_EBIU_AMBCTL0(state->flash_ambctl0);
-       bfin_write_EBIU_AMBCTL1(state->flash_ambctl1);
-       SSYNC();
-}
-
-static void switch_back(struct async_state *state)
-{
-       bfin_write_EBIU_AMBCTL0(state->save_ambctl0);
-       bfin_write_EBIU_AMBCTL1(state->save_ambctl1);
-       SSYNC();
-
-       gpio_set_value(state->enet_flash_pin, 1);
-
-       local_irq_restore(state->irq_flags);
-}
-
-static map_word bfin_flash_read(struct map_info *map, unsigned long ofs)
-{
-       struct async_state *state = (struct async_state *)map->map_priv_1;
-       uint16_t word;
-       map_word test;
-
-       switch_to_flash(state);
-
-       word = readw(map->virt + ofs);
-
-       switch_back(state);
-
-       test.x[0] = word;
-       return test;
-}
-
-static void bfin_flash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-{
-       struct async_state *state = (struct async_state *)map->map_priv_1;
-
-       switch_to_flash(state);
-
-       memcpy(to, map->virt + from, len);
-
-       switch_back(state);
-}
-
-static void bfin_flash_write(struct map_info *map, map_word d1, unsigned long ofs)
-{
-       struct async_state *state = (struct async_state *)map->map_priv_1;
-       uint16_t d;
-
-       d = d1.x[0];
-
-       switch_to_flash(state);
-
-       writew(d, map->virt + ofs);
-       SSYNC();
-
-       switch_back(state);
-}
-
-static void bfin_flash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-{
-       struct async_state *state = (struct async_state *)map->map_priv_1;
-
-       switch_to_flash(state);
-
-       memcpy(map->virt + to, from, len);
-       SSYNC();
-
-       switch_back(state);
-}
-
-static const char * const part_probe_types[] = {
-       "cmdlinepart", "RedBoot", NULL };
-
-static int bfin_flash_probe(struct platform_device *pdev)
-{
-       struct physmap_flash_data *pdata = dev_get_platdata(&pdev->dev);
-       struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       struct resource *flash_ambctl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       struct async_state *state;
-
-       state = kzalloc(sizeof(*state), GFP_KERNEL);
-       if (!state)
-               return -ENOMEM;
-
-       state->map.name       = DRIVER_NAME;
-       state->map.read       = bfin_flash_read;
-       state->map.copy_from  = bfin_flash_copy_from;
-       state->map.write      = bfin_flash_write;
-       state->map.copy_to    = bfin_flash_copy_to;
-       state->map.bankwidth  = pdata->width;
-       state->map.size       = resource_size(memory);
-       state->map.virt       = (void __iomem *)memory->start;
-       state->map.phys       = memory->start;
-       state->map.map_priv_1 = (unsigned long)state;
-       state->enet_flash_pin = platform_get_irq(pdev, 0);
-       state->flash_ambctl0  = flash_ambctl->start;
-       state->flash_ambctl1  = flash_ambctl->end;
-
-       if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) {
-               pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin);
-               kfree(state);
-               return -EBUSY;
-       }
-       gpio_direction_output(state->enet_flash_pin, 1);
-
-       pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
-       state->mtd = do_map_probe(memory->name, &state->map);
-       if (!state->mtd) {
-               gpio_free(state->enet_flash_pin);
-               kfree(state);
-               return -ENXIO;
-       }
-
-       mtd_device_parse_register(state->mtd, part_probe_types, NULL,
-                                 pdata->parts, pdata->nr_parts);
-
-       platform_set_drvdata(pdev, state);
-
-       return 0;
-}
-
-static int bfin_flash_remove(struct platform_device *pdev)
-{
-       struct async_state *state = platform_get_drvdata(pdev);
-       gpio_free(state->enet_flash_pin);
-       mtd_device_unregister(state->mtd);
-       map_destroy(state->mtd);
-       kfree(state);
-       return 0;
-}
-
-static struct platform_driver bfin_flash_driver = {
-       .probe          = bfin_flash_probe,
-       .remove         = bfin_flash_remove,
-       .driver         = {
-               .name   = DRIVER_NAME,
-       },
-};
-
-module_platform_driver(bfin_flash_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MTD map driver for Blackfins with flash/ethernet on same async bank");
index b1bd4faecfb25798eb0c32e9cb16a5a9d8113ec0..527b1682381f4ed68714f8a2f5694884f3332acc 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/concat.h>
+#include <linux/mtd/cfi_endian.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
@@ -233,6 +234,11 @@ static int of_flash_probe(struct platform_device *dev)
                info->list[i].map.bankwidth = be32_to_cpup(width);
                info->list[i].map.device_node = dp;
 
+               if (of_property_read_bool(dp, "big-endian"))
+                       info->list[i].map.swap = CFI_BIG_ENDIAN;
+               else if (of_property_read_bool(dp, "little-endian"))
+                       info->list[i].map.swap = CFI_LITTLE_ENDIAN;
+
                err = of_flash_probe_gemini(dev, dp, &info->list[i].map);
                if (err)
                        goto err_out;
index bb4c14f83c75acd0c070fca721e2516447fe633c..a5b1933c0490946d3c328f13074865af10718f19 100644 (file)
@@ -55,48 +55,27 @@ struct mtdblk_dev {
  * being written to until a different sector is required.
  */
 
-static void erase_callback(struct erase_info *done)
-{
-       wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
-       wake_up(wait_q);
-}
-
 static int erase_write (struct mtd_info *mtd, unsigned long pos,
                        int len, const char *buf)
 {
        struct erase_info erase;
-       DECLARE_WAITQUEUE(wait, current);
-       wait_queue_head_t wait_q;
        size_t retlen;
        int ret;
 
        /*
         * First, let's erase the flash block.
         */
-
-       init_waitqueue_head(&wait_q);
-       erase.mtd = mtd;
-       erase.callback = erase_callback;
        erase.addr = pos;
        erase.len = len;
-       erase.priv = (u_long)&wait_q;
-
-       set_current_state(TASK_INTERRUPTIBLE);
-       add_wait_queue(&wait_q, &wait);
 
        ret = mtd_erase(mtd, &erase);
        if (ret) {
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&wait_q, &wait);
                printk (KERN_WARNING "mtdblock: erase of region [0x%lx, 0x%x] "
                                     "on \"%s\" failed\n",
                        pos, len, mtd->name);
                return ret;
        }
 
-       schedule();  /* Wait for erase to finish. */
-       remove_wait_queue(&wait_q, &wait);
-
        /*
         * Next, write the data to flash.
         */
index de8c902059b8b38db5a20705c3e2480af510a1d9..c06b33f80e751dadbbb26535cb3f3b9539c4bc01 100644 (file)
@@ -324,10 +324,6 @@ static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t c
     IOCTL calls for getting device parameters.
 
 ======================================================================*/
-static void mtdchar_erase_callback (struct erase_info *instr)
-{
-       wake_up((wait_queue_head_t *)instr->priv);
-}
 
 static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
 {
@@ -709,11 +705,6 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
                if (!erase)
                        ret = -ENOMEM;
                else {
-                       wait_queue_head_t waitq;
-                       DECLARE_WAITQUEUE(wait, current);
-
-                       init_waitqueue_head(&waitq);
-
                        if (cmd == MEMERASE64) {
                                struct erase_info_user64 einfo64;
 
@@ -735,31 +726,8 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
                                erase->addr = einfo32.start;
                                erase->len = einfo32.length;
                        }
-                       erase->mtd = mtd;
-                       erase->callback = mtdchar_erase_callback;
-                       erase->priv = (unsigned long)&waitq;
-
-                       /*
-                         FIXME: Allow INTERRUPTIBLE. Which means
-                         not having the wait_queue head on the stack.
-
-                         If the wq_head is on the stack, and we
-                         leave because we got interrupted, then the
-                         wq_head is no longer there when the
-                         callback routine tries to wake us up.
-                       */
+
                        ret = mtd_erase(mtd, erase);
-                       if (!ret) {
-                               set_current_state(TASK_UNINTERRUPTIBLE);
-                               add_wait_queue(&waitq, &wait);
-                               if (erase->state != MTD_ERASE_DONE &&
-                                   erase->state != MTD_ERASE_FAILED)
-                                       schedule();
-                               remove_wait_queue(&waitq, &wait);
-                               set_current_state(TASK_RUNNING);
-
-                               ret = (erase->state == MTD_ERASE_FAILED)?-EIO:0;
-                       }
                        kfree(erase);
                }
                break;
index 60bf53df5454101a533a17b8bf46eb11164a3824..6b86d1a73cf2bb73084e4a8def0feb8ae79400e7 100644 (file)
@@ -333,45 +333,6 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
        return -EINVAL;
 }
 
-static void concat_erase_callback(struct erase_info *instr)
-{
-       wake_up((wait_queue_head_t *) instr->priv);
-}
-
-static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
-{
-       int err;
-       wait_queue_head_t waitq;
-       DECLARE_WAITQUEUE(wait, current);
-
-       /*
-        * This code was stol^H^H^H^Hinspired by mtdchar.c
-        */
-       init_waitqueue_head(&waitq);
-
-       erase->mtd = mtd;
-       erase->callback = concat_erase_callback;
-       erase->priv = (unsigned long) &waitq;
-
-       /*
-        * FIXME: Allow INTERRUPTIBLE. Which means
-        * not having the wait_queue head on the stack.
-        */
-       err = mtd_erase(mtd, erase);
-       if (!err) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               add_wait_queue(&waitq, &wait);
-               if (erase->state != MTD_ERASE_DONE
-                   && erase->state != MTD_ERASE_FAILED)
-                       schedule();
-               remove_wait_queue(&waitq, &wait);
-               set_current_state(TASK_RUNNING);
-
-               err = (erase->state == MTD_ERASE_FAILED) ? -EIO : 0;
-       }
-       return err;
-}
-
 static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
        struct mtd_concat *concat = CONCAT(mtd);
@@ -466,7 +427,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
                        erase->len = length;
 
                length -= erase->len;
-               if ((err = concat_dev_erase(subdev, erase))) {
+               if ((err = mtd_erase(subdev, erase))) {
                        /* sanity check: should never happen since
                         * block alignment has been checked above */
                        BUG_ON(err == -EINVAL);
@@ -485,14 +446,9 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
                erase->addr = 0;
                offset += subdev->size;
        }
-       instr->state = erase->state;
        kfree(erase);
-       if (err)
-               return err;
 
-       if (instr->callback)
-               instr->callback(instr);
-       return 0;
+       return err;
 }
 
 static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
index 28553c840d3217bd7dcbc38c4851cc82438e203a..807d17d863b3e9736c51c920f8e7456fe8e7ec17 100644 (file)
@@ -419,7 +419,7 @@ int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
 EXPORT_SYMBOL_GPL(mtd_wunit_to_pairing_info);
 
 /**
- * mtd_wunit_to_pairing_info - get wunit from pairing information
+ * mtd_pairing_info_to_wunit - get wunit from pairing information
  * @mtd: pointer to new MTD device info structure
  * @info: pairing information struct
  *
@@ -641,29 +641,6 @@ out_error:
        return ret;
 }
 
-static int mtd_add_device_partitions(struct mtd_info *mtd,
-                                    struct mtd_partitions *parts)
-{
-       const struct mtd_partition *real_parts = parts->parts;
-       int nbparts = parts->nr_parts;
-       int ret;
-
-       if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
-               ret = add_mtd_device(mtd);
-               if (ret)
-                       return ret;
-       }
-
-       if (nbparts > 0) {
-               ret = add_mtd_partitions(mtd, real_parts, nbparts);
-               if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
-                       del_mtd_device(mtd);
-               return ret;
-       }
-
-       return 0;
-}
-
 /*
  * Set a few defaults based on the parent devices, if not provided by the
  * driver
@@ -696,14 +673,13 @@ static void mtd_set_dev_defaults(struct mtd_info *mtd)
  * 'parse_mtd_partitions()') and MTD device and partitions registering. It
  * basically follows the most common pattern found in many MTD drivers:
  *
- * * It first tries to probe partitions on MTD device @mtd using parsers
+ * * If the MTD_PARTITIONED_MASTER option is set, then the device as a whole is
+ *   registered first.
+ * * Then It tries to probe partitions on MTD device @mtd using parsers
  *   specified in @types (if @types is %NULL, then the default list of parsers
  *   is used, see 'parse_mtd_partitions()' for more information). If none are
  *   found this functions tries to fallback to information specified in
  *   @parts/@nr_parts.
- * * If any partitioning info was found, this function registers the found
- *   partitions. If the MTD_PARTITIONED_MASTER option is set, then the device
- *   as a whole is registered first.
  * * If no partitions were found this function just registers the MTD device
  *   @mtd and exits.
  *
@@ -714,29 +690,31 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
                              const struct mtd_partition *parts,
                              int nr_parts)
 {
-       struct mtd_partitions parsed;
+       struct mtd_partitions parsed = { };
        int ret;
 
        mtd_set_dev_defaults(mtd);
 
-       memset(&parsed, 0, sizeof(parsed));
+       if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
+               ret = add_mtd_device(mtd);
+               if (ret)
+                       return ret;
+       }
 
+       /* Prefer parsed partitions over driver-provided fallback */
        ret = parse_mtd_partitions(mtd, types, &parsed, parser_data);
-       if ((ret < 0 || parsed.nr_parts == 0) && parts && nr_parts) {
-               /* Fall back to driver-provided partitions */
-               parsed = (struct mtd_partitions){
-                       .parts          = parts,
-                       .nr_parts       = nr_parts,
-               };
-       } else if (ret < 0) {
-               /* Didn't come up with parsed OR fallback partitions */
-               pr_info("mtd: failed to find partitions; one or more parsers reports errors (%d)\n",
-                       ret);
-               /* Don't abort on errors; we can still use unpartitioned MTD */
-               memset(&parsed, 0, sizeof(parsed));
+       if (!ret && parsed.nr_parts) {
+               parts = parsed.parts;
+               nr_parts = parsed.nr_parts;
        }
 
-       ret = mtd_add_device_partitions(mtd, &parsed);
+       if (nr_parts)
+               ret = add_mtd_partitions(mtd, parts, nr_parts);
+       else if (!device_is_registered(&mtd->dev))
+               ret = add_mtd_device(mtd);
+       else
+               ret = 0;
+
        if (ret)
                goto out;
 
@@ -758,6 +736,9 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
 out:
        /* Cleanup any parsed partitions */
        mtd_part_parser_cleanup(&parsed);
+       if (ret && device_is_registered(&mtd->dev))
+               del_mtd_device(mtd);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_device_parse_register);
@@ -963,24 +944,25 @@ void __put_mtd_device(struct mtd_info *mtd)
 EXPORT_SYMBOL_GPL(__put_mtd_device);
 
 /*
- * Erase is an asynchronous operation.  Device drivers are supposed
- * to call instr->callback() whenever the operation completes, even
- * if it completes with a failure.
- * Callers are supposed to pass a callback function and wait for it
- * to be called before writing to the block.
+ * Erase is an synchronous operation. Device drivers are epected to return a
+ * negative error code if the operation failed and update instr->fail_addr
+ * to point the portion that was not properly erased.
  */
 int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
+       instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+
+       if (!mtd->erasesize || !mtd->_erase)
+               return -ENOTSUPP;
+
        if (instr->addr >= mtd->size || instr->len > mtd->size - instr->addr)
                return -EINVAL;
        if (!(mtd->flags & MTD_WRITEABLE))
                return -EROFS;
-       instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
-       if (!instr->len) {
-               instr->state = MTD_ERASE_DONE;
-               mtd_erase_callback(instr);
+
+       if (!instr->len)
                return 0;
-       }
+
        ledtrig_mtd_activity();
        return mtd->_erase(mtd, instr);
 }
@@ -1525,9 +1507,9 @@ int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
 EXPORT_SYMBOL_GPL(mtd_ooblayout_get_databytes);
 
 /**
- * mtd_ooblayout_get_eccbytes - set data bytes into the oob buffer
+ * mtd_ooblayout_set_databytes - set data bytes into the oob buffer
  * @mtd: mtd info structure
- * @eccbuf: source buffer to get data bytes from
+ * @databuf: source buffer to get data bytes from
  * @oobbuf: OOB buffer
  * @start: first ECC byte to set
  * @nbytes: number of ECC bytes to set
@@ -1559,7 +1541,7 @@ int mtd_ooblayout_count_freebytes(struct mtd_info *mtd)
 EXPORT_SYMBOL_GPL(mtd_ooblayout_count_freebytes);
 
 /**
- * mtd_ooblayout_count_freebytes - count the number of ECC bytes in OOB
+ * mtd_ooblayout_count_eccbytes - count the number of ECC bytes in OOB
  * @mtd: mtd info structure
  *
  * Works like mtd_ooblayout_count_bytes(), except it count ECC bytes.
index 97bb8f6304d4feebe6f38e357ca39a6a37fc7f71..9f25111fd55934973be421aca4ca63e41dc74da3 100644 (file)
@@ -84,12 +84,6 @@ static int page_is_used(struct mtdoops_context *cxt, int page)
        return test_bit(page, cxt->oops_page_used);
 }
 
-static void mtdoops_erase_callback(struct erase_info *done)
-{
-       wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
-       wake_up(wait_q);
-}
-
 static int mtdoops_erase_block(struct mtdoops_context *cxt, int offset)
 {
        struct mtd_info *mtd = cxt->mtd;
@@ -97,34 +91,20 @@ static int mtdoops_erase_block(struct mtdoops_context *cxt, int offset)
        u32 start_page = start_page_offset / record_size;
        u32 erase_pages = mtd->erasesize / record_size;
        struct erase_info erase;
-       DECLARE_WAITQUEUE(wait, current);
-       wait_queue_head_t wait_q;
        int ret;
        int page;
 
-       init_waitqueue_head(&wait_q);
-       erase.mtd = mtd;
-       erase.callback = mtdoops_erase_callback;
        erase.addr = offset;
        erase.len = mtd->erasesize;
-       erase.priv = (u_long)&wait_q;
-
-       set_current_state(TASK_INTERRUPTIBLE);
-       add_wait_queue(&wait_q, &wait);
 
        ret = mtd_erase(mtd, &erase);
        if (ret) {
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&wait_q, &wait);
                printk(KERN_WARNING "mtdoops: erase of region [0x%llx, 0x%llx] on \"%s\" failed\n",
                       (unsigned long long)erase.addr,
                       (unsigned long long)erase.len, mtddev);
                return ret;
        }
 
-       schedule();  /* Wait for erase to finish. */
-       remove_wait_queue(&wait_q, &wait);
-
        /* Mark pages as unused */
        for (page = start_page; page < start_page + erase_pages; page++)
                mark_page_unused(cxt, page);
index 76cd21d1171b51bb22dd843519db716591649f93..023516a632766c42df88c26ec2e504605f669639 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/err.h>
+#include <linux/of.h>
 
 #include "mtdcore.h"
 
@@ -205,27 +206,12 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
 
        instr->addr += part->offset;
        ret = part->parent->_erase(part->parent, instr);
-       if (ret) {
-               if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
-                       instr->fail_addr -= part->offset;
-               instr->addr -= part->offset;
-       }
-       return ret;
-}
-
-void mtd_erase_callback(struct erase_info *instr)
-{
-       if (instr->mtd->_erase == part_erase) {
-               struct mtd_part *part = mtd_to_part(instr->mtd);
+       if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
+               instr->fail_addr -= part->offset;
+       instr->addr -= part->offset;
 
-               if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
-                       instr->fail_addr -= part->offset;
-               instr->addr -= part->offset;
-       }
-       if (instr->callback)
-               instr->callback(instr);
+       return ret;
 }
-EXPORT_SYMBOL_GPL(mtd_erase_callback);
 
 static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
@@ -860,6 +846,92 @@ static int mtd_part_do_parse(struct mtd_part_parser *parser,
        return ret;
 }
 
+/**
+ * mtd_part_get_compatible_parser - find MTD parser by a compatible string
+ *
+ * @compat: compatible string describing partitions in a device tree
+ *
+ * MTD parsers can specify supported partitions by providing a table of
+ * compatibility strings. This function finds a parser that advertises support
+ * for a passed value of "compatible".
+ */
+static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat)
+{
+       struct mtd_part_parser *p, *ret = NULL;
+
+       spin_lock(&part_parser_lock);
+
+       list_for_each_entry(p, &part_parsers, list) {
+               const struct of_device_id *matches;
+
+               matches = p->of_match_table;
+               if (!matches)
+                       continue;
+
+               for (; matches->compatible[0]; matches++) {
+                       if (!strcmp(matches->compatible, compat) &&
+                           try_module_get(p->owner)) {
+                               ret = p;
+                               break;
+                       }
+               }
+
+               if (ret)
+                       break;
+       }
+
+       spin_unlock(&part_parser_lock);
+
+       return ret;
+}
+
+static int mtd_part_of_parse(struct mtd_info *master,
+                            struct mtd_partitions *pparts)
+{
+       struct mtd_part_parser *parser;
+       struct device_node *np;
+       struct property *prop;
+       const char *compat;
+       const char *fixed = "fixed-partitions";
+       int ret, err = 0;
+
+       np = of_get_child_by_name(mtd_get_of_node(master), "partitions");
+       of_property_for_each_string(np, "compatible", prop, compat) {
+               parser = mtd_part_get_compatible_parser(compat);
+               if (!parser)
+                       continue;
+               ret = mtd_part_do_parse(parser, master, pparts, NULL);
+               if (ret > 0) {
+                       of_node_put(np);
+                       return ret;
+               }
+               mtd_part_parser_put(parser);
+               if (ret < 0 && !err)
+                       err = ret;
+       }
+       of_node_put(np);
+
+       /*
+        * For backward compatibility we have to try the "fixed-partitions"
+        * parser. It supports old DT format with partitions specified as a
+        * direct subnodes of a flash device DT node without any compatibility
+        * specified we could match.
+        */
+       parser = mtd_part_parser_get(fixed);
+       if (!parser && !request_module("%s", fixed))
+               parser = mtd_part_parser_get(fixed);
+       if (parser) {
+               ret = mtd_part_do_parse(parser, master, pparts, NULL);
+               if (ret > 0)
+                       return ret;
+               mtd_part_parser_put(parser);
+               if (ret < 0 && !err)
+                       err = ret;
+       }
+
+       return err;
+}
+
 /**
  * parse_mtd_partitions - parse MTD partitions
  * @master: the master partition (describes whole MTD device)
@@ -892,19 +964,30 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
                types = default_mtd_part_types;
 
        for ( ; *types; types++) {
-               pr_debug("%s: parsing partitions %s\n", master->name, *types);
-               parser = mtd_part_parser_get(*types);
-               if (!parser && !request_module("%s", *types))
+               /*
+                * ofpart is a special type that means OF partitioning info
+                * should be used. It requires a bit different logic so it is
+                * handled in a separated function.
+                */
+               if (!strcmp(*types, "ofpart")) {
+                       ret = mtd_part_of_parse(master, pparts);
+               } else {
+                       pr_debug("%s: parsing partitions %s\n", master->name,
+                                *types);
                        parser = mtd_part_parser_get(*types);
-               pr_debug("%s: got parser %s\n", master->name,
-                        parser ? parser->name : NULL);
-               if (!parser)
-                       continue;
-               ret = mtd_part_do_parse(parser, master, pparts, data);
+                       if (!parser && !request_module("%s", *types))
+                               parser = mtd_part_parser_get(*types);
+                       pr_debug("%s: got parser %s\n", master->name,
+                               parser ? parser->name : NULL);
+                       if (!parser)
+                               continue;
+                       ret = mtd_part_do_parse(parser, master, pparts, data);
+                       if (ret <= 0)
+                               mtd_part_parser_put(parser);
+               }
                /* Found partitions! */
                if (ret > 0)
                        return 0;
-               mtd_part_parser_put(parser);
                /*
                 * Stash the first error we see; only report it if no parser
                 * succeeds
index 7eb0e1f4f9803ad3f9f00b296eb21388447f341e..7161f8a17f6204b59412eb7a04604993990f58d4 100644 (file)
@@ -536,18 +536,10 @@ static void mtdswap_store_eb(struct mtdswap_dev *d, struct swap_eb *eb)
                mtdswap_rb_add(d, eb, MTDSWAP_HIFRAG);
 }
 
-
-static void mtdswap_erase_callback(struct erase_info *done)
-{
-       wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
-       wake_up(wait_q);
-}
-
 static int mtdswap_erase_block(struct mtdswap_dev *d, struct swap_eb *eb)
 {
        struct mtd_info *mtd = d->mtd;
        struct erase_info erase;
-       wait_queue_head_t wq;
        unsigned int retries = 0;
        int ret;
 
@@ -556,14 +548,9 @@ static int mtdswap_erase_block(struct mtdswap_dev *d, struct swap_eb *eb)
                d->max_erase_count = eb->erase_count;
 
 retry:
-       init_waitqueue_head(&wq);
        memset(&erase, 0, sizeof(struct erase_info));
-
-       erase.mtd       = mtd;
-       erase.callback  = mtdswap_erase_callback;
        erase.addr      = mtdswap_eb_offset(d, eb);
        erase.len       = mtd->erasesize;
-       erase.priv      = (u_long)&wq;
 
        ret = mtd_erase(mtd, &erase);
        if (ret) {
@@ -582,27 +569,6 @@ retry:
                return -EIO;
        }
 
-       ret = wait_event_interruptible(wq, erase.state == MTD_ERASE_DONE ||
-                                          erase.state == MTD_ERASE_FAILED);
-       if (ret) {
-               dev_err(d->dev, "Interrupted erase block %#llx erasure on %s\n",
-                       erase.addr, mtd->name);
-               return -EINTR;
-       }
-
-       if (erase.state == MTD_ERASE_FAILED) {
-               if (retries++ < MTDSWAP_ERASE_RETRIES) {
-                       dev_warn(d->dev,
-                               "erase of erase block %#llx on %s failed",
-                               erase.addr, mtd->name);
-                       yield();
-                       goto retry;
-               }
-
-               mtdswap_handle_badblock(d, eb);
-               return -EIO;
-       }
-
        return 0;
 }
 
index 736ac887303c88baa86ab4857653c322d1d2f60b..88c7d3b4ff8b3661c34f046f36eb651e07b43929 100644 (file)
@@ -1,580 +1,6 @@
-config MTD_NAND_ECC
+config MTD_NAND_CORE
        tristate
 
-config MTD_NAND_ECC_SMC
-       bool "NAND ECC Smart Media byte order"
-       depends on MTD_NAND_ECC
-       default n
-       help
-         Software ECC according to the Smart Media Specification.
-         The original Linux implementation had byte 0 and 1 swapped.
+source "drivers/mtd/nand/onenand/Kconfig"
 
-
-menuconfig MTD_NAND
-       tristate "NAND Device Support"
-       depends on MTD
-       select MTD_NAND_ECC
-       help
-         This enables support for accessing all type of NAND flash
-         devices. For further information see
-         <http://www.linux-mtd.infradead.org/doc/nand.html>.
-
-if MTD_NAND
-
-config MTD_NAND_BCH
-       tristate
-       select BCH
-       depends on MTD_NAND_ECC_BCH
-       default MTD_NAND
-
-config MTD_NAND_ECC_BCH
-       bool "Support software BCH ECC"
-       default n
-       help
-         This enables support for software BCH error correction. Binary BCH
-         codes are more powerful and cpu intensive than traditional Hamming
-         ECC codes. They are used with NAND devices requiring more than 1 bit
-         of error correction.
-
-config MTD_SM_COMMON
-       tristate
-       default n
-
-config MTD_NAND_DENALI
-       tristate
-
-config MTD_NAND_DENALI_PCI
-        tristate "Support Denali NAND controller on Intel Moorestown"
-       select MTD_NAND_DENALI
-       depends on HAS_DMA && PCI
-        help
-          Enable the driver for NAND flash on Intel Moorestown, using the
-          Denali NAND controller core.
-
-config MTD_NAND_DENALI_DT
-       tristate "Support Denali NAND controller as a DT device"
-       select MTD_NAND_DENALI
-       depends on HAS_DMA && HAVE_CLK && OF
-       help
-         Enable the driver for NAND flash on platforms using a Denali NAND
-         controller as a DT device.
-
-config MTD_NAND_GPIO
-       tristate "GPIO assisted NAND Flash driver"
-       depends on GPIOLIB || COMPILE_TEST
-       depends on HAS_IOMEM
-       help
-         This enables a NAND flash driver where control signals are
-         connected to GPIO pins, and commands and data are communicated
-         via a memory mapped interface.
-
-config MTD_NAND_AMS_DELTA
-       tristate "NAND Flash device on Amstrad E3"
-       depends on MACH_AMS_DELTA
-       default y
-       help
-         Support for NAND flash on Amstrad E3 (Delta).
-
-config MTD_NAND_OMAP2
-       tristate "NAND Flash device on OMAP2, OMAP3, OMAP4 and Keystone"
-       depends on (ARCH_OMAP2PLUS || ARCH_KEYSTONE)
-       help
-          Support for NAND flash on Texas Instruments OMAP2, OMAP3, OMAP4
-         and Keystone platforms.
-
-config MTD_NAND_OMAP_BCH
-       depends on MTD_NAND_OMAP2
-       bool "Support hardware based BCH error correction"
-       default n
-       select BCH
-       help
-         This config enables the ELM hardware engine, which can be used to
-         locate and correct errors when using BCH ECC scheme. This offloads
-         the cpu from doing ECC error searching and correction. However some
-         legacy OMAP families like OMAP2xxx, OMAP3xxx do not have ELM engine
-         so this is optional for them.
-
-config MTD_NAND_OMAP_BCH_BUILD
-       def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH
-
-config MTD_NAND_RICOH
-       tristate "Ricoh xD card reader"
-       default n
-       depends on PCI
-       select MTD_SM_COMMON
-       help
-         Enable support for Ricoh R5C852 xD card reader
-         You also need to enable ether
-         NAND SSFDC (SmartMedia) read only translation layer' or new
-         expermental, readwrite
-         'SmartMedia/xD new translation layer'
-
-config MTD_NAND_AU1550
-       tristate "Au1550/1200 NAND support"
-       depends on MIPS_ALCHEMY
-       help
-         This enables the driver for the NAND flash controller on the
-         AMD/Alchemy 1550 SOC.
-
-config MTD_NAND_BF5XX
-       tristate "Blackfin on-chip NAND Flash Controller driver"
-       depends on BF54x || BF52x
-       help
-         This enables the Blackfin on-chip NAND flash controller
-
-         No board specific support is done by this driver, each board
-         must advertise a platform_device for the driver to attach.
-
-         This driver can also be built as a module. If so, the module
-         will be called bf5xx-nand.
-
-config MTD_NAND_BF5XX_HWECC
-       bool "BF5XX NAND Hardware ECC"
-       default y
-       depends on MTD_NAND_BF5XX
-       help
-         Enable the use of the BF5XX's internal ECC generator when
-         using NAND.
-
-config MTD_NAND_BF5XX_BOOTROM_ECC
-       bool "Use Blackfin BootROM ECC Layout"
-       default n
-       depends on MTD_NAND_BF5XX_HWECC
-       help
-         If you wish to modify NAND pages and allow the Blackfin on-chip
-         BootROM to boot from them, say Y here.  This is only necessary
-         if you are booting U-Boot out of NAND and you wish to update
-         U-Boot from Linux' userspace.  Otherwise, you should say N here.
-
-         If unsure, say N.
-
-config MTD_NAND_S3C2410
-       tristate "NAND Flash support for Samsung S3C SoCs"
-       depends on ARCH_S3C24XX || ARCH_S3C64XX
-       help
-         This enables the NAND flash controller on the S3C24xx and S3C64xx
-         SoCs
-
-         No board specific support is done by this driver, each board
-         must advertise a platform_device for the driver to attach.
-
-config MTD_NAND_S3C2410_DEBUG
-       bool "Samsung S3C NAND driver debug"
-       depends on MTD_NAND_S3C2410
-       help
-         Enable debugging of the S3C NAND driver
-
-config MTD_NAND_NDFC
-       tristate "NDFC NanD Flash Controller"
-       depends on 4xx
-       select MTD_NAND_ECC_SMC
-       help
-        NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
-
-config MTD_NAND_S3C2410_CLKSTOP
-       bool "Samsung S3C NAND IDLE clock stop"
-       depends on MTD_NAND_S3C2410
-       default n
-       help
-         Stop the clock to the NAND controller when there is no chip
-         selected to save power. This will mean there is a small delay
-         when the is NAND chip selected or released, but will save
-         approximately 5mA of power when there is nothing happening.
-
-config MTD_NAND_TANGO
-       tristate "NAND Flash support for Tango chips"
-       depends on ARCH_TANGO || COMPILE_TEST
-       depends on HAS_DMA
-       help
-         Enables the NAND Flash controller on Tango chips.
-
-config MTD_NAND_DISKONCHIP
-       tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation)"
-       depends on HAS_IOMEM
-       select REED_SOLOMON
-       select REED_SOLOMON_DEC16
-       help
-         This is a reimplementation of M-Systems DiskOnChip 2000,
-         Millennium and Millennium Plus as a standard NAND device driver,
-         as opposed to the earlier self-contained MTD device drivers.
-         This should enable, among other things, proper JFFS2 operation on
-         these devices.
-
-config MTD_NAND_DISKONCHIP_PROBE_ADVANCED
-        bool "Advanced detection options for DiskOnChip"
-        depends on MTD_NAND_DISKONCHIP
-        help
-          This option allows you to specify nonstandard address at which to
-          probe for a DiskOnChip, or to change the detection options.  You
-          are unlikely to need any of this unless you are using LinuxBIOS.
-          Say 'N'.
-
-config MTD_NAND_DISKONCHIP_PROBE_ADDRESS
-        hex "Physical address of DiskOnChip" if MTD_NAND_DISKONCHIP_PROBE_ADVANCED
-        depends on MTD_NAND_DISKONCHIP
-        default "0"
-        ---help---
-        By default, the probe for DiskOnChip devices will look for a
-        DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
-        This option allows you to specify a single address at which to probe
-        for the device, which is useful if you have other devices in that
-        range which get upset when they are probed.
-
-        (Note that on PowerPC, the normal probe will only check at
-        0xE4000000.)
-
-        Normally, you should leave this set to zero, to allow the probe at
-        the normal addresses.
-
-config MTD_NAND_DISKONCHIP_PROBE_HIGH
-        bool "Probe high addresses"
-        depends on MTD_NAND_DISKONCHIP_PROBE_ADVANCED
-        help
-          By default, the probe for DiskOnChip devices will look for a
-          DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
-          This option changes to make it probe between 0xFFFC8000 and
-          0xFFFEE000.  Unless you are using LinuxBIOS, this is unlikely to be
-          useful to you.  Say 'N'.
-
-config MTD_NAND_DISKONCHIP_BBTWRITE
-       bool "Allow BBT writes on DiskOnChip Millennium and 2000TSOP"
-       depends on MTD_NAND_DISKONCHIP
-       help
-         On DiskOnChip devices shipped with the INFTL filesystem (Millennium
-         and 2000 TSOP/Alon), Linux reserves some space at the end of the
-         device for the Bad Block Table (BBT).  If you have existing INFTL
-         data on your device (created by non-Linux tools such as M-Systems'
-         DOS drivers), your data might overlap the area Linux wants to use for
-         the BBT.  If this is a concern for you, leave this option disabled and
-         Linux will not write BBT data into this area.
-         The downside of leaving this option disabled is that if bad blocks
-         are detected by Linux, they will not be recorded in the BBT, which
-         could cause future problems.
-         Once you enable this option, new filesystems (INFTL or others, created
-         in Linux or other operating systems) will not use the reserved area.
-         The only reason not to enable this option is to prevent damage to
-         preexisting filesystems.
-         Even if you leave this disabled, you can enable BBT writes at module
-         load time (assuming you build diskonchip as a module) with the module
-         parameter "inftl_bbt_write=1".
-
-config MTD_NAND_DOCG4
-       tristate "Support for DiskOnChip G4"
-       depends on HAS_IOMEM
-       select BCH
-       select BITREVERSE
-       help
-         Support for diskonchip G4 nand flash, found in various smartphones and
-         PDAs, among them the Palm Treo680, HTC Prophet and Wizard, Toshiba
-         Portege G900, Asus P526, and O2 XDA Zinc.
-
-         With this driver you will be able to use UBI and create a ubifs on the
-         device, so you may wish to consider enabling UBI and UBIFS as well.
-
-         These devices ship with the Mys/Sandisk SAFTL formatting, for which
-         there is currently no mtd parser, so you may want to use command line
-         partitioning to segregate write-protected blocks. On the Treo680, the
-         first five erase blocks (256KiB each) are write-protected, followed
-         by the block containing the saftl partition table.  This is probably
-         typical.
-
-config MTD_NAND_SHARPSL
-       tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
-       depends on ARCH_PXA
-
-config MTD_NAND_CAFE
-       tristate "NAND support for OLPC CAFÉ chip"
-       depends on PCI
-       select REED_SOLOMON
-       select REED_SOLOMON_DEC16
-       help
-         Use NAND flash attached to the CAFÉ chip designed for the OLPC
-         laptop.
-
-config MTD_NAND_CS553X
-       tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
-       depends on X86_32
-       depends on !UML && HAS_IOMEM
-       help
-         The CS553x companion chips for the AMD Geode processor
-         include NAND flash controllers with built-in hardware ECC
-         capabilities; enabling this option will allow you to use
-         these. The driver will check the MSRs to verify that the
-         controller is enabled for NAND, and currently requires that
-         the controller be in MMIO mode.
-
-         If you say "m", the module will be called cs553x_nand.
-
-config MTD_NAND_ATMEL
-       tristate "Support for NAND Flash / SmartMedia on AT91"
-       depends on ARCH_AT91
-       select MFD_ATMEL_SMC
-       help
-         Enables support for NAND Flash / Smart Media Card interface
-         on Atmel AT91 processors.
-
-config MTD_NAND_PXA3xx
-       tristate "NAND support on PXA3xx and Armada 370/XP"
-       depends on !MTD_NAND_MARVELL
-       depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU
-       help
-
-         This enables the driver for the NAND flash device found on
-         PXA3xx processors (NFCv1) and also on 32-bit Armada
-         platforms (XP, 370, 375, 38x, 39x) and 64-bit Armada
-         platforms (7K, 8K) (NFCv2).
-
-config MTD_NAND_MARVELL
-       tristate "NAND controller support on Marvell boards"
-       depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU || \
-                  COMPILE_TEST
-       depends on HAS_IOMEM && HAS_DMA
-       help
-         This enables the NAND flash controller driver for Marvell boards,
-         including:
-         - PXA3xx processors (NFCv1)
-         - 32-bit Armada platforms (XP, 37x, 38x, 39x) (NFCv2)
-         - 64-bit Aramda platforms (7k, 8k) (NFCv2)
-
-config MTD_NAND_SLC_LPC32XX
-       tristate "NXP LPC32xx SLC Controller"
-       depends on ARCH_LPC32XX
-       help
-         Enables support for NXP's LPC32XX SLC (i.e. for Single Level Cell
-         chips) NAND controller. This is the default for the PHYTEC 3250
-         reference board which contains a NAND256R3A2CZA6 chip.
-
-         Please check the actual NAND chip connected and its support
-         by the SLC NAND controller.
-
-config MTD_NAND_MLC_LPC32XX
-       tristate "NXP LPC32xx MLC Controller"
-       depends on ARCH_LPC32XX
-       help
-         Uses the LPC32XX MLC (i.e. for Multi Level Cell chips) NAND
-         controller. This is the default for the WORK92105 controller
-         board.
-
-         Please check the actual NAND chip connected and its support
-         by the MLC NAND controller.
-
-config MTD_NAND_CM_X270
-       tristate "Support for NAND Flash on CM-X270 modules"
-       depends on MACH_ARMCORE
-
-config MTD_NAND_PASEMI
-       tristate "NAND support for PA Semi PWRficient"
-       depends on PPC_PASEMI
-       help
-         Enables support for NAND Flash interface on PA Semi PWRficient
-         based boards
-
-config MTD_NAND_TMIO
-       tristate "NAND Flash device on Toshiba Mobile IO Controller"
-       depends on MFD_TMIO
-       help
-         Support for NAND flash connected to a Toshiba Mobile IO
-         Controller in some PDAs, including the Sharp SL6000x.
-
-config MTD_NAND_NANDSIM
-       tristate "Support for NAND Flash Simulator"
-       help
-         The simulator may simulate various NAND flash chips for the
-         MTD nand layer.
-
-config MTD_NAND_GPMI_NAND
-        tristate "GPMI NAND Flash Controller driver"
-        depends on MTD_NAND && MXS_DMA
-        help
-        Enables NAND Flash support for IMX23, IMX28 or IMX6.
-        The GPMI controller is very powerful, with the help of BCH
-        module, it can do the hardware ECC. The GPMI supports several
-        NAND flashs at the same time.
-
-config MTD_NAND_BRCMNAND
-       tristate "Broadcom STB NAND controller"
-       depends on ARM || ARM64 || 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
-       help
-         BCMA bus can have various flash memories attached, they are
-         registered by bcma as platform devices. This enables driver for
-         NAND flash memories. For now only BCM4706 is supported.
-
-config MTD_NAND_PLATFORM
-       tristate "Support for generic platform NAND driver"
-       depends on HAS_IOMEM
-       help
-         This implements a generic NAND driver for on-SOC platform
-         devices. You will need to provide platform-specific functions
-         via platform_data.
-
-config MTD_NAND_ORION
-       tristate "NAND Flash support for Marvell Orion SoC"
-       depends on PLAT_ORION
-       help
-         This enables the NAND flash controller on Orion machines.
-
-         No board specific support is done by this driver, each board
-         must advertise a platform_device for the driver to attach.
-
-config MTD_NAND_OXNAS
-       tristate "NAND Flash support for Oxford Semiconductor SoC"
-       depends on ARCH_OXNAS || COMPILE_TEST
-       depends on HAS_IOMEM
-       help
-         This enables the NAND flash controller on Oxford Semiconductor SoCs.
-
-config MTD_NAND_FSL_ELBC
-       tristate "NAND support for Freescale eLBC controllers"
-       depends on FSL_SOC
-       select FSL_LBC
-       help
-         Various Freescale chips, including the 8313, include a NAND Flash
-         Controller Module with built-in hardware ECC capabilities.
-         Enabling this option will enable you to use this to control
-         external NAND devices.
-
-config MTD_NAND_FSL_IFC
-       tristate "NAND support for Freescale IFC controller"
-       depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A
-       select FSL_IFC
-       select MEMORY
-       help
-         Various Freescale chips e.g P1010, include a NAND Flash machine
-         with built-in hardware ECC capabilities.
-         Enabling this option will enable you to use this to control
-         external NAND devices.
-
-config MTD_NAND_FSL_UPM
-       tristate "Support for NAND on Freescale UPM"
-       depends on PPC_83xx || PPC_85xx
-       select FSL_LBC
-       help
-         Enables support for NAND Flash chips wired onto Freescale PowerPC
-         processor localbus with User-Programmable Machine support.
-
-config MTD_NAND_MPC5121_NFC
-       tristate "MPC5121 built-in NAND Flash Controller support"
-       depends on PPC_MPC512x
-       help
-         This enables the driver for the NAND flash controller on the
-         MPC5121 SoC.
-
-config MTD_NAND_VF610_NFC
-       tristate "Support for Freescale NFC for VF610/MPC5125"
-       depends on (SOC_VF610 || COMPILE_TEST)
-       depends on HAS_IOMEM
-       help
-         Enables support for NAND Flash Controller on some Freescale
-         processors like the VF610, MPC5125, MCF54418 or Kinetis K70.
-         The driver supports a maximum 2k page size. With 2k pages and
-         64 bytes or more of OOB, hardware ECC with up to 32-bit error
-         correction is supported. Hardware ECC is only enabled through
-         device tree.
-
-config MTD_NAND_MXC
-       tristate "MXC NAND support"
-       depends on ARCH_MXC
-       help
-         This enables the driver for the NAND flash controller on the
-         MXC processors.
-
-config MTD_NAND_SH_FLCTL
-       tristate "Support for NAND on Renesas SuperH FLCTL"
-       depends on SUPERH || COMPILE_TEST
-       depends on HAS_IOMEM
-       depends on HAS_DMA
-       help
-         Several Renesas SuperH CPU has FLCTL. This option enables support
-         for NAND Flash using FLCTL.
-
-config MTD_NAND_DAVINCI
-        tristate "Support NAND on DaVinci/Keystone SoC"
-        depends on ARCH_DAVINCI || (ARCH_KEYSTONE && TI_AEMIF)
-        help
-         Enable the driver for NAND flash chips on Texas Instruments
-         DaVinci/Keystone processors.
-
-config MTD_NAND_TXX9NDFMC
-       tristate "NAND Flash support for TXx9 SoC"
-       depends on SOC_TX4938 || SOC_TX4939
-       help
-         This enables the NAND flash controller on the TXx9 SoCs.
-
-config MTD_NAND_SOCRATES
-       tristate "Support for NAND on Socrates board"
-       depends on SOCRATES
-       help
-         Enables support for NAND Flash chips wired onto Socrates board.
-
-config MTD_NAND_NUC900
-       tristate "Support for NAND on Nuvoton NUC9xx/w90p910 evaluation boards."
-       depends on ARCH_W90X900
-       help
-         This enables the driver for the NAND Flash on evaluation board based
-         on w90p910 / NUC9xx.
-
-config MTD_NAND_JZ4740
-       tristate "Support for JZ4740 SoC NAND controller"
-       depends on MACH_JZ4740
-       help
-               Enables support for NAND Flash on JZ4740 SoC based boards.
-
-config MTD_NAND_JZ4780
-       tristate "Support for NAND on JZ4780 SoC"
-       depends on MACH_JZ4780 && JZ4780_NEMC
-       help
-         Enables support for NAND Flash connected to the NEMC on JZ4780 SoC
-         based boards, using the BCH controller for hardware error correction.
-
-config MTD_NAND_FSMC
-       tristate "Support for NAND on ST Micros FSMC"
-       depends on OF
-       depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
-       help
-         Enables support for NAND Flash chips on the ST Microelectronics
-         Flexible Static Memory Controller (FSMC)
-
-config MTD_NAND_XWAY
-       bool "Support for NAND on Lantiq XWAY SoC"
-       depends on LANTIQ && SOC_TYPE_XWAY
-       help
-         Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
-         to the External Bus Unit (EBU).
-
-config MTD_NAND_SUNXI
-       tristate "Support for NAND on Allwinner SoCs"
-       depends on ARCH_SUNXI
-       help
-         Enables support for NAND Flash chips on Allwinner SoCs.
-
-config MTD_NAND_HISI504
-       tristate "Support for NAND controller on Hisilicon SoC Hip04"
-       depends on ARCH_HISI || COMPILE_TEST
-       depends on HAS_DMA
-       help
-         Enables support for NAND controller on Hisilicon SoC Hip04.
-
-config MTD_NAND_QCOM
-       tristate "Support for NAND on QCOM SoCs"
-       depends on ARCH_QCOM
-       help
-         Enables support for NAND flash chips on SoCs containing the EBI2 NAND
-         controller. This controller is found on IPQ806x SoC.
-
-config MTD_NAND_MTK
-       tristate "Support for NAND controller on MTK SoCs"
-       depends on ARCH_MEDIATEK || COMPILE_TEST
-       depends on HAS_DMA
-       help
-         Enables support for NAND controller on MTK SoCs.
-         This controller is found on mt27xx, mt81xx, mt65xx SoCs.
-
-endif # MTD_NAND
+source "drivers/mtd/nand/raw/Kconfig"
index 921634ba400cfa3af1317c4ec35825b74fe5e49a..3f0cb87f1a57f11692a16b5a882d68ba055b0094 100644 (file)
@@ -1,71 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
-#
-# linux/drivers/nand/Makefile
-#
 
-obj-$(CONFIG_MTD_NAND)                 += nand.o
-obj-$(CONFIG_MTD_NAND_ECC)             += nand_ecc.o
-obj-$(CONFIG_MTD_NAND_BCH)             += nand_bch.o
-obj-$(CONFIG_MTD_SM_COMMON)            += sm_common.o
+nandcore-objs := core.o bbt.o
+obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
 
-obj-$(CONFIG_MTD_NAND_CAFE)            += cafe_nand.o
-obj-$(CONFIG_MTD_NAND_AMS_DELTA)       += ams-delta.o
-obj-$(CONFIG_MTD_NAND_DENALI)          += denali.o
-obj-$(CONFIG_MTD_NAND_DENALI_PCI)      += denali_pci.o
-obj-$(CONFIG_MTD_NAND_DENALI_DT)       += denali_dt.o
-obj-$(CONFIG_MTD_NAND_AU1550)          += au1550nd.o
-obj-$(CONFIG_MTD_NAND_BF5XX)           += bf5xx_nand.o
-obj-$(CONFIG_MTD_NAND_S3C2410)         += s3c2410.o
-obj-$(CONFIG_MTD_NAND_TANGO)           += tango_nand.o
-obj-$(CONFIG_MTD_NAND_DAVINCI)         += davinci_nand.o
-obj-$(CONFIG_MTD_NAND_DISKONCHIP)      += diskonchip.o
-obj-$(CONFIG_MTD_NAND_DOCG4)           += docg4.o
-obj-$(CONFIG_MTD_NAND_FSMC)            += fsmc_nand.o
-obj-$(CONFIG_MTD_NAND_SHARPSL)         += sharpsl.o
-obj-$(CONFIG_MTD_NAND_NANDSIM)         += nandsim.o
-obj-$(CONFIG_MTD_NAND_CS553X)          += cs553x_nand.o
-obj-$(CONFIG_MTD_NAND_NDFC)            += ndfc.o
-obj-$(CONFIG_MTD_NAND_ATMEL)           += atmel/
-obj-$(CONFIG_MTD_NAND_GPIO)            += gpio.o
-omap2_nand-objs := omap2.o
-obj-$(CONFIG_MTD_NAND_OMAP2)           += omap2_nand.o
-obj-$(CONFIG_MTD_NAND_OMAP_BCH_BUILD)  += omap_elm.o
-obj-$(CONFIG_MTD_NAND_CM_X270)         += cmx270_nand.o
-obj-$(CONFIG_MTD_NAND_PXA3xx)          += pxa3xx_nand.o
-obj-$(CONFIG_MTD_NAND_MARVELL)         += marvell_nand.o
-obj-$(CONFIG_MTD_NAND_TMIO)            += tmio_nand.o
-obj-$(CONFIG_MTD_NAND_PLATFORM)                += plat_nand.o
-obj-$(CONFIG_MTD_NAND_PASEMI)          += pasemi_nand.o
-obj-$(CONFIG_MTD_NAND_ORION)           += orion_nand.o
-obj-$(CONFIG_MTD_NAND_OXNAS)           += oxnas_nand.o
-obj-$(CONFIG_MTD_NAND_FSL_ELBC)                += fsl_elbc_nand.o
-obj-$(CONFIG_MTD_NAND_FSL_IFC)         += fsl_ifc_nand.o
-obj-$(CONFIG_MTD_NAND_FSL_UPM)         += fsl_upm.o
-obj-$(CONFIG_MTD_NAND_SLC_LPC32XX)      += lpc32xx_slc.o
-obj-$(CONFIG_MTD_NAND_MLC_LPC32XX)      += lpc32xx_mlc.o
-obj-$(CONFIG_MTD_NAND_SH_FLCTL)                += sh_flctl.o
-obj-$(CONFIG_MTD_NAND_MXC)             += mxc_nand.o
-obj-$(CONFIG_MTD_NAND_SOCRATES)                += socrates_nand.o
-obj-$(CONFIG_MTD_NAND_TXX9NDFMC)       += txx9ndfmc.o
-obj-$(CONFIG_MTD_NAND_NUC900)          += nuc900_nand.o
-obj-$(CONFIG_MTD_NAND_MPC5121_NFC)     += mpc5121_nfc.o
-obj-$(CONFIG_MTD_NAND_VF610_NFC)       += vf610_nfc.o
-obj-$(CONFIG_MTD_NAND_RICOH)           += r852.o
-obj-$(CONFIG_MTD_NAND_JZ4740)          += jz4740_nand.o
-obj-$(CONFIG_MTD_NAND_JZ4780)          += jz4780_nand.o jz4780_bch.o
-obj-$(CONFIG_MTD_NAND_GPMI_NAND)       += gpmi-nand/
-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_BRCMNAND)                += brcmnand/
-obj-$(CONFIG_MTD_NAND_QCOM)            += qcom_nandc.o
-obj-$(CONFIG_MTD_NAND_MTK)             += mtk_ecc.o mtk_nand.o
-
-nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o
-nand-objs += nand_amd.o
-nand-objs += nand_hynix.o
-nand-objs += nand_macronix.o
-nand-objs += nand_micron.o
-nand-objs += nand_samsung.o
-nand-objs += nand_toshiba.o
+obj-y  += onenand/
+obj-y  += raw/
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
deleted file mode 100644 (file)
index d60ada4..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- *  drivers/mtd/nand/ams-delta.c
- *
- *  Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
- *
- *  Derived from drivers/mtd/toto.c
- *  Converted to platform driver by Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
- *  Partially stolen from drivers/mtd/nand/plat_nand.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   Amstrad E3 (Delta).
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/mtd/partitions.h>
-#include <linux/gpio.h>
-#include <linux/platform_data/gpio-omap.h>
-
-#include <asm/io.h>
-#include <asm/sizes.h>
-
-#include <mach/board-ams-delta.h>
-
-#include <mach/hardware.h>
-
-/*
- * MTD structure for E3 (Delta)
- */
-static struct mtd_info *ams_delta_mtd = NULL;
-
-/*
- * Define partitions for flash devices
- */
-
-static const struct mtd_partition partition_info[] = {
-       { .name         = "Kernel",
-         .offset       = 0,
-         .size         = 3 * SZ_1M + SZ_512K },
-       { .name         = "u-boot",
-         .offset       = 3 * SZ_1M + SZ_512K,
-         .size         = SZ_256K },
-       { .name         = "u-boot params",
-         .offset       = 3 * SZ_1M + SZ_512K + SZ_256K,
-         .size         = SZ_256K },
-       { .name         = "Amstrad LDR",
-         .offset       = 4 * SZ_1M,
-         .size         = SZ_256K },
-       { .name         = "File system",
-         .offset       = 4 * SZ_1M + 1 * SZ_256K,
-         .size         = 27 * SZ_1M },
-       { .name         = "PBL reserved",
-         .offset       = 32 * SZ_1M - 3 * SZ_256K,
-         .size         =  3 * SZ_256K },
-};
-
-static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
-{
-       struct nand_chip *this = mtd_to_nand(mtd);
-       void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
-
-       writew(0, io_base + OMAP_MPUIO_IO_CNTL);
-       writew(byte, this->IO_ADDR_W);
-       gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0);
-       ndelay(40);
-       gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1);
-}
-
-static u_char ams_delta_read_byte(struct mtd_info *mtd)
-{
-       u_char res;
-       struct nand_chip *this = mtd_to_nand(mtd);
-       void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
-
-       gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
-       ndelay(40);
-       writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
-       res = readw(this->IO_ADDR_R);
-       gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1);
-
-       return res;
-}
-
-static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
-                               int len)
-{
-       int i;
-
-       for (i=0; i<len; i++)
-               ams_delta_write_byte(mtd, buf[i]);
-}
-
-static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
-{
-       int i;
-
-       for (i=0; i<len; i++)
-               buf[i] = ams_delta_read_byte(mtd);
-}
-
-/*
- * Command control function
- *
- * ctrl:
- * NAND_NCE: bit 0 -> bit 2
- * NAND_CLE: bit 1 -> bit 7
- * NAND_ALE: bit 2 -> bit 6
- */
-static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
-                               unsigned int ctrl)
-{
-
-       if (ctrl & NAND_CTRL_CHANGE) {
-               gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE,
-                               (ctrl & NAND_NCE) == 0);
-               gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE,
-                               (ctrl & NAND_CLE) != 0);
-               gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE,
-                               (ctrl & NAND_ALE) != 0);
-       }
-
-       if (cmd != NAND_CMD_NONE)
-               ams_delta_write_byte(mtd, cmd);
-}
-
-static int ams_delta_nand_ready(struct mtd_info *mtd)
-{
-       return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
-}
-
-static const struct gpio _mandatory_gpio[] = {
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_NAND_NCE,
-               .flags  = GPIOF_OUT_INIT_HIGH,
-               .label  = "nand_nce",
-       },
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_NAND_NRE,
-               .flags  = GPIOF_OUT_INIT_HIGH,
-               .label  = "nand_nre",
-       },
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_NAND_NWP,
-               .flags  = GPIOF_OUT_INIT_HIGH,
-               .label  = "nand_nwp",
-       },
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_NAND_NWE,
-               .flags  = GPIOF_OUT_INIT_HIGH,
-               .label  = "nand_nwe",
-       },
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_NAND_ALE,
-               .flags  = GPIOF_OUT_INIT_LOW,
-               .label  = "nand_ale",
-       },
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_NAND_CLE,
-               .flags  = GPIOF_OUT_INIT_LOW,
-               .label  = "nand_cle",
-       },
-};
-
-/*
- * Main initialization routine
- */
-static int ams_delta_init(struct platform_device *pdev)
-{
-       struct nand_chip *this;
-       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       void __iomem *io_base;
-       int err = 0;
-
-       if (!res)
-               return -ENXIO;
-
-       /* Allocate memory for MTD device structure and private data */
-       this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
-       if (!this) {
-               printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
-               err = -ENOMEM;
-               goto out;
-       }
-
-       ams_delta_mtd = nand_to_mtd(this);
-       ams_delta_mtd->owner = THIS_MODULE;
-
-       /*
-        * Don't try to request the memory region from here,
-        * it should have been already requested from the
-        * gpio-omap driver and requesting it again would fail.
-        */
-
-       io_base = ioremap(res->start, resource_size(res));
-       if (io_base == NULL) {
-               dev_err(&pdev->dev, "ioremap failed\n");
-               err = -EIO;
-               goto out_free;
-       }
-
-       nand_set_controller_data(this, (void *)io_base);
-
-       /* Set address of NAND IO lines */
-       this->IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH;
-       this->IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT;
-       this->read_byte = ams_delta_read_byte;
-       this->write_buf = ams_delta_write_buf;
-       this->read_buf = ams_delta_read_buf;
-       this->cmd_ctrl = ams_delta_hwcontrol;
-       if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
-               this->dev_ready = ams_delta_nand_ready;
-       } else {
-               this->dev_ready = NULL;
-               printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n");
-       }
-       /* 25 us command delay time */
-       this->chip_delay = 30;
-       this->ecc.mode = NAND_ECC_SOFT;
-       this->ecc.algo = NAND_ECC_HAMMING;
-
-       platform_set_drvdata(pdev, io_base);
-
-       /* Set chip enabled, but  */
-       err = gpio_request_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
-       if (err)
-               goto out_gpio;
-
-       /* Scan to find existence of the device */
-       err = nand_scan(ams_delta_mtd, 1);
-       if (err)
-               goto out_mtd;
-
-       /* Register the partitions */
-       mtd_device_register(ams_delta_mtd, partition_info,
-                           ARRAY_SIZE(partition_info));
-
-       goto out;
-
- out_mtd:
-       gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
-out_gpio:
-       gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
-       iounmap(io_base);
-out_free:
-       kfree(this);
- out:
-       return err;
-}
-
-/*
- * Clean up routine
- */
-static int ams_delta_cleanup(struct platform_device *pdev)
-{
-       void __iomem *io_base = platform_get_drvdata(pdev);
-
-       /* Release resources, unregister device */
-       nand_release(ams_delta_mtd);
-
-       gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
-       gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
-       iounmap(io_base);
-
-       /* Free the MTD device structure */
-       kfree(mtd_to_nand(ams_delta_mtd));
-
-       return 0;
-}
-
-static struct platform_driver ams_delta_nand_driver = {
-       .probe          = ams_delta_init,
-       .remove         = ams_delta_cleanup,
-       .driver         = {
-               .name   = "ams-delta-nand",
-       },
-};
-
-module_platform_driver(ams_delta_nand_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
-MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)");
diff --git a/drivers/mtd/nand/atmel/Makefile b/drivers/mtd/nand/atmel/Makefile
deleted file mode 100644 (file)
index 288db4f..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_MTD_NAND_ATMEL)   += atmel-nand-controller.o atmel-pmecc.o
-
-atmel-nand-controller-objs     := nand-controller.o
-atmel-pmecc-objs               := pmecc.o
diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c
deleted file mode 100644 (file)
index b2f00b3..0000000
+++ /dev/null
@@ -1,2565 +0,0 @@
-/*
- * Copyright 2017 ATMEL
- * Copyright 2017 Free Electrons
- *
- * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
- *
- * Derived from the atmel_nand.c driver which contained the following
- * copyrights:
- *
- *   Copyright 2003 Rick Bronson
- *
- *   Derived from drivers/mtd/nand/autcpu12.c
- *     Copyright 2001 Thomas Gleixner (gleixner@autronix.de)
- *
- *   Derived from drivers/mtd/spia.c
- *     Copyright 2000 Steven J. Hill (sjhill@cotw.com)
- *
- *
- *   Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
- *     Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright 2007
- *
- *   Derived from Das U-Boot source code
- *     (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
- *     Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
- *
- *   Add Programmable Multibit ECC support for various AT91 SoC
- *     Copyright 2012 ATMEL, Hong Xu
- *
- *   Add Nand Flash Controller support for SAMA5 SoC
- *     Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * A few words about the naming convention in this file. This convention
- * applies to structure and function names.
- *
- * Prefixes:
- *
- * - atmel_nand_: all generic structures/functions
- * - atmel_smc_nand_: all structures/functions specific to the SMC interface
- *                   (at91sam9 and avr32 SoCs)
- * - atmel_hsmc_nand_: all structures/functions specific to the HSMC interface
- *                    (sama5 SoCs and later)
- * - atmel_nfc_: all structures/functions used to manipulate the NFC sub-block
- *              that is available in the HSMC block
- * - <soc>_nand_: all SoC specific structures/functions
- */
-
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmaengine.h>
-#include <linux/genalloc.h>
-#include <linux/gpio.h>
-#include <linux/gpio/consumer.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/atmel-matrix.h>
-#include <linux/mfd/syscon/atmel-smc.h>
-#include <linux/module.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/iopoll.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#include "pmecc.h"
-
-#define ATMEL_HSMC_NFC_CFG                     0x0
-#define ATMEL_HSMC_NFC_CFG_SPARESIZE(x)                (((x) / 4) << 24)
-#define ATMEL_HSMC_NFC_CFG_SPARESIZE_MASK      GENMASK(30, 24)
-#define ATMEL_HSMC_NFC_CFG_DTO(cyc, mul)       (((cyc) << 16) | ((mul) << 20))
-#define ATMEL_HSMC_NFC_CFG_DTO_MAX             GENMASK(22, 16)
-#define ATMEL_HSMC_NFC_CFG_RBEDGE              BIT(13)
-#define ATMEL_HSMC_NFC_CFG_FALLING_EDGE                BIT(12)
-#define ATMEL_HSMC_NFC_CFG_RSPARE              BIT(9)
-#define ATMEL_HSMC_NFC_CFG_WSPARE              BIT(8)
-#define ATMEL_HSMC_NFC_CFG_PAGESIZE_MASK       GENMASK(2, 0)
-#define ATMEL_HSMC_NFC_CFG_PAGESIZE(x)         (fls((x) / 512) - 1)
-
-#define ATMEL_HSMC_NFC_CTRL                    0x4
-#define ATMEL_HSMC_NFC_CTRL_EN                 BIT(0)
-#define ATMEL_HSMC_NFC_CTRL_DIS                        BIT(1)
-
-#define ATMEL_HSMC_NFC_SR                      0x8
-#define ATMEL_HSMC_NFC_IER                     0xc
-#define ATMEL_HSMC_NFC_IDR                     0x10
-#define ATMEL_HSMC_NFC_IMR                     0x14
-#define ATMEL_HSMC_NFC_SR_ENABLED              BIT(1)
-#define ATMEL_HSMC_NFC_SR_RB_RISE              BIT(4)
-#define ATMEL_HSMC_NFC_SR_RB_FALL              BIT(5)
-#define ATMEL_HSMC_NFC_SR_BUSY                 BIT(8)
-#define ATMEL_HSMC_NFC_SR_WR                   BIT(11)
-#define ATMEL_HSMC_NFC_SR_CSID                 GENMASK(14, 12)
-#define ATMEL_HSMC_NFC_SR_XFRDONE              BIT(16)
-#define ATMEL_HSMC_NFC_SR_CMDDONE              BIT(17)
-#define ATMEL_HSMC_NFC_SR_DTOE                 BIT(20)
-#define ATMEL_HSMC_NFC_SR_UNDEF                        BIT(21)
-#define ATMEL_HSMC_NFC_SR_AWB                  BIT(22)
-#define ATMEL_HSMC_NFC_SR_NFCASE               BIT(23)
-#define ATMEL_HSMC_NFC_SR_ERRORS               (ATMEL_HSMC_NFC_SR_DTOE | \
-                                                ATMEL_HSMC_NFC_SR_UNDEF | \
-                                                ATMEL_HSMC_NFC_SR_AWB | \
-                                                ATMEL_HSMC_NFC_SR_NFCASE)
-#define ATMEL_HSMC_NFC_SR_RBEDGE(x)            BIT((x) + 24)
-
-#define ATMEL_HSMC_NFC_ADDR                    0x18
-#define ATMEL_HSMC_NFC_BANK                    0x1c
-
-#define ATMEL_NFC_MAX_RB_ID                    7
-
-#define ATMEL_NFC_SRAM_SIZE                    0x2400
-
-#define ATMEL_NFC_CMD(pos, cmd)                        ((cmd) << (((pos) * 8) + 2))
-#define ATMEL_NFC_VCMD2                                BIT(18)
-#define ATMEL_NFC_ACYCLE(naddrs)               ((naddrs) << 19)
-#define ATMEL_NFC_CSID(cs)                     ((cs) << 22)
-#define ATMEL_NFC_DATAEN                       BIT(25)
-#define ATMEL_NFC_NFCWR                                BIT(26)
-
-#define ATMEL_NFC_MAX_ADDR_CYCLES              5
-
-#define ATMEL_NAND_ALE_OFFSET                  BIT(21)
-#define ATMEL_NAND_CLE_OFFSET                  BIT(22)
-
-#define DEFAULT_TIMEOUT_MS                     1000
-#define MIN_DMA_LEN                            128
-
-enum atmel_nand_rb_type {
-       ATMEL_NAND_NO_RB,
-       ATMEL_NAND_NATIVE_RB,
-       ATMEL_NAND_GPIO_RB,
-};
-
-struct atmel_nand_rb {
-       enum atmel_nand_rb_type type;
-       union {
-               struct gpio_desc *gpio;
-               int id;
-       };
-};
-
-struct atmel_nand_cs {
-       int id;
-       struct atmel_nand_rb rb;
-       struct gpio_desc *csgpio;
-       struct {
-               void __iomem *virt;
-               dma_addr_t dma;
-       } io;
-
-       struct atmel_smc_cs_conf smcconf;
-};
-
-struct atmel_nand {
-       struct list_head node;
-       struct device *dev;
-       struct nand_chip base;
-       struct atmel_nand_cs *activecs;
-       struct atmel_pmecc_user *pmecc;
-       struct gpio_desc *cdgpio;
-       int numcs;
-       struct atmel_nand_cs cs[];
-};
-
-static inline struct atmel_nand *to_atmel_nand(struct nand_chip *chip)
-{
-       return container_of(chip, struct atmel_nand, base);
-}
-
-enum atmel_nfc_data_xfer {
-       ATMEL_NFC_NO_DATA,
-       ATMEL_NFC_READ_DATA,
-       ATMEL_NFC_WRITE_DATA,
-};
-
-struct atmel_nfc_op {
-       u8 cs;
-       u8 ncmds;
-       u8 cmds[2];
-       u8 naddrs;
-       u8 addrs[5];
-       enum atmel_nfc_data_xfer data;
-       u32 wait;
-       u32 errors;
-};
-
-struct atmel_nand_controller;
-struct atmel_nand_controller_caps;
-
-struct atmel_nand_controller_ops {
-       int (*probe)(struct platform_device *pdev,
-                    const struct atmel_nand_controller_caps *caps);
-       int (*remove)(struct atmel_nand_controller *nc);
-       void (*nand_init)(struct atmel_nand_controller *nc,
-                         struct atmel_nand *nand);
-       int (*ecc_init)(struct atmel_nand *nand);
-       int (*setup_data_interface)(struct atmel_nand *nand, int csline,
-                                   const struct nand_data_interface *conf);
-};
-
-struct atmel_nand_controller_caps {
-       bool has_dma;
-       bool legacy_of_bindings;
-       u32 ale_offs;
-       u32 cle_offs;
-       const struct atmel_nand_controller_ops *ops;
-};
-
-struct atmel_nand_controller {
-       struct nand_hw_control base;
-       const struct atmel_nand_controller_caps *caps;
-       struct device *dev;
-       struct regmap *smc;
-       struct dma_chan *dmac;
-       struct atmel_pmecc *pmecc;
-       struct list_head chips;
-       struct clk *mck;
-};
-
-static inline struct atmel_nand_controller *
-to_nand_controller(struct nand_hw_control *ctl)
-{
-       return container_of(ctl, struct atmel_nand_controller, base);
-}
-
-struct atmel_smc_nand_controller {
-       struct atmel_nand_controller base;
-       struct regmap *matrix;
-       unsigned int ebi_csa_offs;
-};
-
-static inline struct atmel_smc_nand_controller *
-to_smc_nand_controller(struct nand_hw_control *ctl)
-{
-       return container_of(to_nand_controller(ctl),
-                           struct atmel_smc_nand_controller, base);
-}
-
-struct atmel_hsmc_nand_controller {
-       struct atmel_nand_controller base;
-       struct {
-               struct gen_pool *pool;
-               void __iomem *virt;
-               dma_addr_t dma;
-       } sram;
-       const struct atmel_hsmc_reg_layout *hsmc_layout;
-       struct regmap *io;
-       struct atmel_nfc_op op;
-       struct completion complete;
-       int irq;
-
-       /* Only used when instantiating from legacy DT bindings. */
-       struct clk *clk;
-};
-
-static inline struct atmel_hsmc_nand_controller *
-to_hsmc_nand_controller(struct nand_hw_control *ctl)
-{
-       return container_of(to_nand_controller(ctl),
-                           struct atmel_hsmc_nand_controller, base);
-}
-
-static bool atmel_nfc_op_done(struct atmel_nfc_op *op, u32 status)
-{
-       op->errors |= status & ATMEL_HSMC_NFC_SR_ERRORS;
-       op->wait ^= status & op->wait;
-
-       return !op->wait || op->errors;
-}
-
-static irqreturn_t atmel_nfc_interrupt(int irq, void *data)
-{
-       struct atmel_hsmc_nand_controller *nc = data;
-       u32 sr, rcvd;
-       bool done;
-
-       regmap_read(nc->base.smc, ATMEL_HSMC_NFC_SR, &sr);
-
-       rcvd = sr & (nc->op.wait | ATMEL_HSMC_NFC_SR_ERRORS);
-       done = atmel_nfc_op_done(&nc->op, sr);
-
-       if (rcvd)
-               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_IDR, rcvd);
-
-       if (done)
-               complete(&nc->complete);
-
-       return rcvd ? IRQ_HANDLED : IRQ_NONE;
-}
-
-static int atmel_nfc_wait(struct atmel_hsmc_nand_controller *nc, bool poll,
-                         unsigned int timeout_ms)
-{
-       int ret;
-
-       if (!timeout_ms)
-               timeout_ms = DEFAULT_TIMEOUT_MS;
-
-       if (poll) {
-               u32 status;
-
-               ret = regmap_read_poll_timeout(nc->base.smc,
-                                              ATMEL_HSMC_NFC_SR, status,
-                                              atmel_nfc_op_done(&nc->op,
-                                                                status),
-                                              0, timeout_ms * 1000);
-       } else {
-               init_completion(&nc->complete);
-               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_IER,
-                            nc->op.wait | ATMEL_HSMC_NFC_SR_ERRORS);
-               ret = wait_for_completion_timeout(&nc->complete,
-                                               msecs_to_jiffies(timeout_ms));
-               if (!ret)
-                       ret = -ETIMEDOUT;
-               else
-                       ret = 0;
-
-               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_IDR, 0xffffffff);
-       }
-
-       if (nc->op.errors & ATMEL_HSMC_NFC_SR_DTOE) {
-               dev_err(nc->base.dev, "Waiting NAND R/B Timeout\n");
-               ret = -ETIMEDOUT;
-       }
-
-       if (nc->op.errors & ATMEL_HSMC_NFC_SR_UNDEF) {
-               dev_err(nc->base.dev, "Access to an undefined area\n");
-               ret = -EIO;
-       }
-
-       if (nc->op.errors & ATMEL_HSMC_NFC_SR_AWB) {
-               dev_err(nc->base.dev, "Access while busy\n");
-               ret = -EIO;
-       }
-
-       if (nc->op.errors & ATMEL_HSMC_NFC_SR_NFCASE) {
-               dev_err(nc->base.dev, "Wrong access size\n");
-               ret = -EIO;
-       }
-
-       return ret;
-}
-
-static void atmel_nand_dma_transfer_finished(void *data)
-{
-       struct completion *finished = data;
-
-       complete(finished);
-}
-
-static int atmel_nand_dma_transfer(struct atmel_nand_controller *nc,
-                                  void *buf, dma_addr_t dev_dma, size_t len,
-                                  enum dma_data_direction dir)
-{
-       DECLARE_COMPLETION_ONSTACK(finished);
-       dma_addr_t src_dma, dst_dma, buf_dma;
-       struct dma_async_tx_descriptor *tx;
-       dma_cookie_t cookie;
-
-       buf_dma = dma_map_single(nc->dev, buf, len, dir);
-       if (dma_mapping_error(nc->dev, dev_dma)) {
-               dev_err(nc->dev,
-                       "Failed to prepare a buffer for DMA access\n");
-               goto err;
-       }
-
-       if (dir == DMA_FROM_DEVICE) {
-               src_dma = dev_dma;
-               dst_dma = buf_dma;
-       } else {
-               src_dma = buf_dma;
-               dst_dma = dev_dma;
-       }
-
-       tx = dmaengine_prep_dma_memcpy(nc->dmac, dst_dma, src_dma, len,
-                                      DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
-       if (!tx) {
-               dev_err(nc->dev, "Failed to prepare DMA memcpy\n");
-               goto err_unmap;
-       }
-
-       tx->callback = atmel_nand_dma_transfer_finished;
-       tx->callback_param = &finished;
-
-       cookie = dmaengine_submit(tx);
-       if (dma_submit_error(cookie)) {
-               dev_err(nc->dev, "Failed to do DMA tx_submit\n");
-               goto err_unmap;
-       }
-
-       dma_async_issue_pending(nc->dmac);
-       wait_for_completion(&finished);
-
-       return 0;
-
-err_unmap:
-       dma_unmap_single(nc->dev, buf_dma, len, dir);
-
-err:
-       dev_dbg(nc->dev, "Fall back to CPU I/O\n");
-
-       return -EIO;
-}
-
-static u8 atmel_nand_read_byte(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-
-       return ioread8(nand->activecs->io.virt);
-}
-
-static u16 atmel_nand_read_word(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-
-       return ioread16(nand->activecs->io.virt);
-}
-
-static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-
-       if (chip->options & NAND_BUSWIDTH_16)
-               iowrite16(byte | (byte << 8), nand->activecs->io.virt);
-       else
-               iowrite8(byte, nand->activecs->io.virt);
-}
-
-static void atmel_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_nand_controller *nc;
-
-       nc = to_nand_controller(chip->controller);
-
-       /*
-        * If the controller supports DMA, the buffer address is DMA-able and
-        * len is long enough to make DMA transfers profitable, let's trigger
-        * a DMA transfer. If it fails, fallback to PIO mode.
-        */
-       if (nc->dmac && virt_addr_valid(buf) &&
-           len >= MIN_DMA_LEN &&
-           !atmel_nand_dma_transfer(nc, buf, nand->activecs->io.dma, len,
-                                    DMA_FROM_DEVICE))
-               return;
-
-       if (chip->options & NAND_BUSWIDTH_16)
-               ioread16_rep(nand->activecs->io.virt, buf, len / 2);
-       else
-               ioread8_rep(nand->activecs->io.virt, buf, len);
-}
-
-static void atmel_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_nand_controller *nc;
-
-       nc = to_nand_controller(chip->controller);
-
-       /*
-        * If the controller supports DMA, the buffer address is DMA-able and
-        * len is long enough to make DMA transfers profitable, let's trigger
-        * a DMA transfer. If it fails, fallback to PIO mode.
-        */
-       if (nc->dmac && virt_addr_valid(buf) &&
-           len >= MIN_DMA_LEN &&
-           !atmel_nand_dma_transfer(nc, (void *)buf, nand->activecs->io.dma,
-                                    len, DMA_TO_DEVICE))
-               return;
-
-       if (chip->options & NAND_BUSWIDTH_16)
-               iowrite16_rep(nand->activecs->io.virt, buf, len / 2);
-       else
-               iowrite8_rep(nand->activecs->io.virt, buf, len);
-}
-
-static int atmel_nand_dev_ready(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-
-       return gpiod_get_value(nand->activecs->rb.gpio);
-}
-
-static void atmel_nand_select_chip(struct mtd_info *mtd, int cs)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-
-       if (cs < 0 || cs >= nand->numcs) {
-               nand->activecs = NULL;
-               chip->dev_ready = NULL;
-               return;
-       }
-
-       nand->activecs = &nand->cs[cs];
-
-       if (nand->activecs->rb.type == ATMEL_NAND_GPIO_RB)
-               chip->dev_ready = atmel_nand_dev_ready;
-}
-
-static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_hsmc_nand_controller *nc;
-       u32 status;
-
-       nc = to_hsmc_nand_controller(chip->controller);
-
-       regmap_read(nc->base.smc, ATMEL_HSMC_NFC_SR, &status);
-
-       return status & ATMEL_HSMC_NFC_SR_RBEDGE(nand->activecs->rb.id);
-}
-
-static void atmel_hsmc_nand_select_chip(struct mtd_info *mtd, int cs)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_hsmc_nand_controller *nc;
-
-       nc = to_hsmc_nand_controller(chip->controller);
-
-       atmel_nand_select_chip(mtd, cs);
-
-       if (!nand->activecs) {
-               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_CTRL,
-                            ATMEL_HSMC_NFC_CTRL_DIS);
-               return;
-       }
-
-       if (nand->activecs->rb.type == ATMEL_NAND_NATIVE_RB)
-               chip->dev_ready = atmel_hsmc_nand_dev_ready;
-
-       regmap_update_bits(nc->base.smc, ATMEL_HSMC_NFC_CFG,
-                          ATMEL_HSMC_NFC_CFG_PAGESIZE_MASK |
-                          ATMEL_HSMC_NFC_CFG_SPARESIZE_MASK |
-                          ATMEL_HSMC_NFC_CFG_RSPARE |
-                          ATMEL_HSMC_NFC_CFG_WSPARE,
-                          ATMEL_HSMC_NFC_CFG_PAGESIZE(mtd->writesize) |
-                          ATMEL_HSMC_NFC_CFG_SPARESIZE(mtd->oobsize) |
-                          ATMEL_HSMC_NFC_CFG_RSPARE);
-       regmap_write(nc->base.smc, ATMEL_HSMC_NFC_CTRL,
-                    ATMEL_HSMC_NFC_CTRL_EN);
-}
-
-static int atmel_nfc_exec_op(struct atmel_hsmc_nand_controller *nc, bool poll)
-{
-       u8 *addrs = nc->op.addrs;
-       unsigned int op = 0;
-       u32 addr, val;
-       int i, ret;
-
-       nc->op.wait = ATMEL_HSMC_NFC_SR_CMDDONE;
-
-       for (i = 0; i < nc->op.ncmds; i++)
-               op |= ATMEL_NFC_CMD(i, nc->op.cmds[i]);
-
-       if (nc->op.naddrs == ATMEL_NFC_MAX_ADDR_CYCLES)
-               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_ADDR, *addrs++);
-
-       op |= ATMEL_NFC_CSID(nc->op.cs) |
-             ATMEL_NFC_ACYCLE(nc->op.naddrs);
-
-       if (nc->op.ncmds > 1)
-               op |= ATMEL_NFC_VCMD2;
-
-       addr = addrs[0] | (addrs[1] << 8) | (addrs[2] << 16) |
-              (addrs[3] << 24);
-
-       if (nc->op.data != ATMEL_NFC_NO_DATA) {
-               op |= ATMEL_NFC_DATAEN;
-               nc->op.wait |= ATMEL_HSMC_NFC_SR_XFRDONE;
-
-               if (nc->op.data == ATMEL_NFC_WRITE_DATA)
-                       op |= ATMEL_NFC_NFCWR;
-       }
-
-       /* Clear all flags. */
-       regmap_read(nc->base.smc, ATMEL_HSMC_NFC_SR, &val);
-
-       /* Send the command. */
-       regmap_write(nc->io, op, addr);
-
-       ret = atmel_nfc_wait(nc, poll, 0);
-       if (ret)
-               dev_err(nc->base.dev,
-                       "Failed to send NAND command (err = %d)!",
-                       ret);
-
-       /* Reset the op state. */
-       memset(&nc->op, 0, sizeof(nc->op));
-
-       return ret;
-}
-
-static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat,
-                                    unsigned int ctrl)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_hsmc_nand_controller *nc;
-
-       nc = to_hsmc_nand_controller(chip->controller);
-
-       if (ctrl & NAND_ALE) {
-               if (nc->op.naddrs == ATMEL_NFC_MAX_ADDR_CYCLES)
-                       return;
-
-               nc->op.addrs[nc->op.naddrs++] = dat;
-       } else if (ctrl & NAND_CLE) {
-               if (nc->op.ncmds > 1)
-                       return;
-
-               nc->op.cmds[nc->op.ncmds++] = dat;
-       }
-
-       if (dat == NAND_CMD_NONE) {
-               nc->op.cs = nand->activecs->id;
-               atmel_nfc_exec_op(nc, true);
-       }
-}
-
-static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
-                               unsigned int ctrl)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_nand_controller *nc;
-
-       nc = to_nand_controller(chip->controller);
-
-       if ((ctrl & NAND_CTRL_CHANGE) && nand->activecs->csgpio) {
-               if (ctrl & NAND_NCE)
-                       gpiod_set_value(nand->activecs->csgpio, 0);
-               else
-                       gpiod_set_value(nand->activecs->csgpio, 1);
-       }
-
-       if (ctrl & NAND_ALE)
-               writeb(cmd, nand->activecs->io.virt + nc->caps->ale_offs);
-       else if (ctrl & NAND_CLE)
-               writeb(cmd, nand->activecs->io.virt + nc->caps->cle_offs);
-}
-
-static void atmel_nfc_copy_to_sram(struct nand_chip *chip, const u8 *buf,
-                                  bool oob_required)
-{
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_hsmc_nand_controller *nc;
-       int ret = -EIO;
-
-       nc = to_hsmc_nand_controller(chip->controller);
-
-       if (nc->base.dmac)
-               ret = atmel_nand_dma_transfer(&nc->base, (void *)buf,
-                                             nc->sram.dma, mtd->writesize,
-                                             DMA_TO_DEVICE);
-
-       /* Falling back to CPU copy. */
-       if (ret)
-               memcpy_toio(nc->sram.virt, buf, mtd->writesize);
-
-       if (oob_required)
-               memcpy_toio(nc->sram.virt + mtd->writesize, chip->oob_poi,
-                           mtd->oobsize);
-}
-
-static void atmel_nfc_copy_from_sram(struct nand_chip *chip, u8 *buf,
-                                    bool oob_required)
-{
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_hsmc_nand_controller *nc;
-       int ret = -EIO;
-
-       nc = to_hsmc_nand_controller(chip->controller);
-
-       if (nc->base.dmac)
-               ret = atmel_nand_dma_transfer(&nc->base, buf, nc->sram.dma,
-                                             mtd->writesize, DMA_FROM_DEVICE);
-
-       /* Falling back to CPU copy. */
-       if (ret)
-               memcpy_fromio(buf, nc->sram.virt, mtd->writesize);
-
-       if (oob_required)
-               memcpy_fromio(chip->oob_poi, nc->sram.virt + mtd->writesize,
-                             mtd->oobsize);
-}
-
-static void atmel_nfc_set_op_addr(struct nand_chip *chip, int page, int column)
-{
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_hsmc_nand_controller *nc;
-
-       nc = to_hsmc_nand_controller(chip->controller);
-
-       if (column >= 0) {
-               nc->op.addrs[nc->op.naddrs++] = column;
-
-               /*
-                * 2 address cycles for the column offset on large page NANDs.
-                */
-               if (mtd->writesize > 512)
-                       nc->op.addrs[nc->op.naddrs++] = column >> 8;
-       }
-
-       if (page >= 0) {
-               nc->op.addrs[nc->op.naddrs++] = page;
-               nc->op.addrs[nc->op.naddrs++] = page >> 8;
-
-               if (chip->options & NAND_ROW_ADDR_3)
-                       nc->op.addrs[nc->op.naddrs++] = page >> 16;
-       }
-}
-
-static int atmel_nand_pmecc_enable(struct nand_chip *chip, int op, bool raw)
-{
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_nand_controller *nc;
-       int ret;
-
-       nc = to_nand_controller(chip->controller);
-
-       if (raw)
-               return 0;
-
-       ret = atmel_pmecc_enable(nand->pmecc, op);
-       if (ret)
-               dev_err(nc->dev,
-                       "Failed to enable ECC engine (err = %d)\n", ret);
-
-       return ret;
-}
-
-static void atmel_nand_pmecc_disable(struct nand_chip *chip, bool raw)
-{
-       struct atmel_nand *nand = to_atmel_nand(chip);
-
-       if (!raw)
-               atmel_pmecc_disable(nand->pmecc);
-}
-
-static int atmel_nand_pmecc_generate_eccbytes(struct nand_chip *chip, bool raw)
-{
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_nand_controller *nc;
-       struct mtd_oob_region oobregion;
-       void *eccbuf;
-       int ret, i;
-
-       nc = to_nand_controller(chip->controller);
-
-       if (raw)
-               return 0;
-
-       ret = atmel_pmecc_wait_rdy(nand->pmecc);
-       if (ret) {
-               dev_err(nc->dev,
-                       "Failed to transfer NAND page data (err = %d)\n",
-                       ret);
-               return ret;
-       }
-
-       mtd_ooblayout_ecc(mtd, 0, &oobregion);
-       eccbuf = chip->oob_poi + oobregion.offset;
-
-       for (i = 0; i < chip->ecc.steps; i++) {
-               atmel_pmecc_get_generated_eccbytes(nand->pmecc, i,
-                                                  eccbuf);
-               eccbuf += chip->ecc.bytes;
-       }
-
-       return 0;
-}
-
-static int atmel_nand_pmecc_correct_data(struct nand_chip *chip, void *buf,
-                                        bool raw)
-{
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_nand_controller *nc;
-       struct mtd_oob_region oobregion;
-       int ret, i, max_bitflips = 0;
-       void *databuf, *eccbuf;
-
-       nc = to_nand_controller(chip->controller);
-
-       if (raw)
-               return 0;
-
-       ret = atmel_pmecc_wait_rdy(nand->pmecc);
-       if (ret) {
-               dev_err(nc->dev,
-                       "Failed to read NAND page data (err = %d)\n",
-                       ret);
-               return ret;
-       }
-
-       mtd_ooblayout_ecc(mtd, 0, &oobregion);
-       eccbuf = chip->oob_poi + oobregion.offset;
-       databuf = buf;
-
-       for (i = 0; i < chip->ecc.steps; i++) {
-               ret = atmel_pmecc_correct_sector(nand->pmecc, i, databuf,
-                                                eccbuf);
-               if (ret < 0 && !atmel_pmecc_correct_erased_chunks(nand->pmecc))
-                       ret = nand_check_erased_ecc_chunk(databuf,
-                                                         chip->ecc.size,
-                                                         eccbuf,
-                                                         chip->ecc.bytes,
-                                                         NULL, 0,
-                                                         chip->ecc.strength);
-
-               if (ret >= 0)
-                       max_bitflips = max(ret, max_bitflips);
-               else
-                       mtd->ecc_stats.failed++;
-
-               databuf += chip->ecc.size;
-               eccbuf += chip->ecc.bytes;
-       }
-
-       return max_bitflips;
-}
-
-static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,
-                                    bool oob_required, int page, bool raw)
-{
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       int ret;
-
-       nand_prog_page_begin_op(chip, page, 0, NULL, 0);
-
-       ret = atmel_nand_pmecc_enable(chip, NAND_ECC_WRITE, raw);
-       if (ret)
-               return ret;
-
-       atmel_nand_write_buf(mtd, buf, mtd->writesize);
-
-       ret = atmel_nand_pmecc_generate_eccbytes(chip, raw);
-       if (ret) {
-               atmel_pmecc_disable(nand->pmecc);
-               return ret;
-       }
-
-       atmel_nand_pmecc_disable(chip, raw);
-
-       atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-       return nand_prog_page_end_op(chip);
-}
-
-static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
-                                      struct nand_chip *chip, const u8 *buf,
-                                      int oob_required, int page)
-{
-       return atmel_nand_pmecc_write_pg(chip, buf, oob_required, page, false);
-}
-
-static int atmel_nand_pmecc_write_page_raw(struct mtd_info *mtd,
-                                          struct nand_chip *chip,
-                                          const u8 *buf, int oob_required,
-                                          int page)
-{
-       return atmel_nand_pmecc_write_pg(chip, buf, oob_required, page, true);
-}
-
-static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
-                                   bool oob_required, int page, bool raw)
-{
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       int ret;
-
-       nand_read_page_op(chip, page, 0, NULL, 0);
-
-       ret = atmel_nand_pmecc_enable(chip, NAND_ECC_READ, raw);
-       if (ret)
-               return ret;
-
-       atmel_nand_read_buf(mtd, buf, mtd->writesize);
-       atmel_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-       ret = atmel_nand_pmecc_correct_data(chip, buf, raw);
-
-       atmel_nand_pmecc_disable(chip, raw);
-
-       return ret;
-}
-
-static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
-                                     struct nand_chip *chip, u8 *buf,
-                                     int oob_required, int page)
-{
-       return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page, false);
-}
-
-static int atmel_nand_pmecc_read_page_raw(struct mtd_info *mtd,
-                                         struct nand_chip *chip, u8 *buf,
-                                         int oob_required, int page)
-{
-       return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page, true);
-}
-
-static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip,
-                                         const u8 *buf, bool oob_required,
-                                         int page, bool raw)
-{
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_hsmc_nand_controller *nc;
-       int ret, status;
-
-       nc = to_hsmc_nand_controller(chip->controller);
-
-       atmel_nfc_copy_to_sram(chip, buf, false);
-
-       nc->op.cmds[0] = NAND_CMD_SEQIN;
-       nc->op.ncmds = 1;
-       atmel_nfc_set_op_addr(chip, page, 0x0);
-       nc->op.cs = nand->activecs->id;
-       nc->op.data = ATMEL_NFC_WRITE_DATA;
-
-       ret = atmel_nand_pmecc_enable(chip, NAND_ECC_WRITE, raw);
-       if (ret)
-               return ret;
-
-       ret = atmel_nfc_exec_op(nc, false);
-       if (ret) {
-               atmel_nand_pmecc_disable(chip, raw);
-               dev_err(nc->base.dev,
-                       "Failed to transfer NAND page data (err = %d)\n",
-                       ret);
-               return ret;
-       }
-
-       ret = atmel_nand_pmecc_generate_eccbytes(chip, raw);
-
-       atmel_nand_pmecc_disable(chip, raw);
-
-       if (ret)
-               return ret;
-
-       atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-       nc->op.cmds[0] = NAND_CMD_PAGEPROG;
-       nc->op.ncmds = 1;
-       nc->op.cs = nand->activecs->id;
-       ret = atmel_nfc_exec_op(nc, false);
-       if (ret)
-               dev_err(nc->base.dev, "Failed to program NAND page (err = %d)\n",
-                       ret);
-
-       status = chip->waitfunc(mtd, chip);
-       if (status & NAND_STATUS_FAIL)
-               return -EIO;
-
-       return ret;
-}
-
-static int atmel_hsmc_nand_pmecc_write_page(struct mtd_info *mtd,
-                                           struct nand_chip *chip,
-                                           const u8 *buf, int oob_required,
-                                           int page)
-{
-       return atmel_hsmc_nand_pmecc_write_pg(chip, buf, oob_required, page,
-                                             false);
-}
-
-static int atmel_hsmc_nand_pmecc_write_page_raw(struct mtd_info *mtd,
-                                               struct nand_chip *chip,
-                                               const u8 *buf,
-                                               int oob_required, int page)
-{
-       return atmel_hsmc_nand_pmecc_write_pg(chip, buf, oob_required, page,
-                                             true);
-}
-
-static int atmel_hsmc_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
-                                        bool oob_required, int page,
-                                        bool raw)
-{
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_hsmc_nand_controller *nc;
-       int ret;
-
-       nc = to_hsmc_nand_controller(chip->controller);
-
-       /*
-        * Optimized read page accessors only work when the NAND R/B pin is
-        * connected to a native SoC R/B pin. If that's not the case, fallback
-        * to the non-optimized one.
-        */
-       if (nand->activecs->rb.type != ATMEL_NAND_NATIVE_RB) {
-               nand_read_page_op(chip, page, 0, NULL, 0);
-
-               return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page,
-                                               raw);
-       }
-
-       nc->op.cmds[nc->op.ncmds++] = NAND_CMD_READ0;
-
-       if (mtd->writesize > 512)
-               nc->op.cmds[nc->op.ncmds++] = NAND_CMD_READSTART;
-
-       atmel_nfc_set_op_addr(chip, page, 0x0);
-       nc->op.cs = nand->activecs->id;
-       nc->op.data = ATMEL_NFC_READ_DATA;
-
-       ret = atmel_nand_pmecc_enable(chip, NAND_ECC_READ, raw);
-       if (ret)
-               return ret;
-
-       ret = atmel_nfc_exec_op(nc, false);
-       if (ret) {
-               atmel_nand_pmecc_disable(chip, raw);
-               dev_err(nc->base.dev,
-                       "Failed to load NAND page data (err = %d)\n",
-                       ret);
-               return ret;
-       }
-
-       atmel_nfc_copy_from_sram(chip, buf, true);
-
-       ret = atmel_nand_pmecc_correct_data(chip, buf, raw);
-
-       atmel_nand_pmecc_disable(chip, raw);
-
-       return ret;
-}
-
-static int atmel_hsmc_nand_pmecc_read_page(struct mtd_info *mtd,
-                                          struct nand_chip *chip, u8 *buf,
-                                          int oob_required, int page)
-{
-       return atmel_hsmc_nand_pmecc_read_pg(chip, buf, oob_required, page,
-                                            false);
-}
-
-static int atmel_hsmc_nand_pmecc_read_page_raw(struct mtd_info *mtd,
-                                              struct nand_chip *chip,
-                                              u8 *buf, int oob_required,
-                                              int page)
-{
-       return atmel_hsmc_nand_pmecc_read_pg(chip, buf, oob_required, page,
-                                            true);
-}
-
-static int atmel_nand_pmecc_init(struct nand_chip *chip)
-{
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_nand_controller *nc;
-       struct atmel_pmecc_user_req req;
-
-       nc = to_nand_controller(chip->controller);
-
-       if (!nc->pmecc) {
-               dev_err(nc->dev, "HW ECC not supported\n");
-               return -ENOTSUPP;
-       }
-
-       if (nc->caps->legacy_of_bindings) {
-               u32 val;
-
-               if (!of_property_read_u32(nc->dev->of_node, "atmel,pmecc-cap",
-                                         &val))
-                       chip->ecc.strength = val;
-
-               if (!of_property_read_u32(nc->dev->of_node,
-                                         "atmel,pmecc-sector-size",
-                                         &val))
-                       chip->ecc.size = val;
-       }
-
-       if (chip->ecc.options & NAND_ECC_MAXIMIZE)
-               req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH;
-       else if (chip->ecc.strength)
-               req.ecc.strength = chip->ecc.strength;
-       else if (chip->ecc_strength_ds)
-               req.ecc.strength = chip->ecc_strength_ds;
-       else
-               req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH;
-
-       if (chip->ecc.size)
-               req.ecc.sectorsize = chip->ecc.size;
-       else if (chip->ecc_step_ds)
-               req.ecc.sectorsize = chip->ecc_step_ds;
-       else
-               req.ecc.sectorsize = ATMEL_PMECC_SECTOR_SIZE_AUTO;
-
-       req.pagesize = mtd->writesize;
-       req.oobsize = mtd->oobsize;
-
-       if (mtd->writesize <= 512) {
-               req.ecc.bytes = 4;
-               req.ecc.ooboffset = 0;
-       } else {
-               req.ecc.bytes = mtd->oobsize - 2;
-               req.ecc.ooboffset = ATMEL_PMECC_OOBOFFSET_AUTO;
-       }
-
-       nand->pmecc = atmel_pmecc_create_user(nc->pmecc, &req);
-       if (IS_ERR(nand->pmecc))
-               return PTR_ERR(nand->pmecc);
-
-       chip->ecc.algo = NAND_ECC_BCH;
-       chip->ecc.size = req.ecc.sectorsize;
-       chip->ecc.bytes = req.ecc.bytes / req.ecc.nsectors;
-       chip->ecc.strength = req.ecc.strength;
-
-       chip->options |= NAND_NO_SUBPAGE_WRITE;
-
-       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
-
-       return 0;
-}
-
-static int atmel_nand_ecc_init(struct atmel_nand *nand)
-{
-       struct nand_chip *chip = &nand->base;
-       struct atmel_nand_controller *nc;
-       int ret;
-
-       nc = to_nand_controller(chip->controller);
-
-       switch (chip->ecc.mode) {
-       case NAND_ECC_NONE:
-       case NAND_ECC_SOFT:
-               /*
-                * Nothing to do, the core will initialize everything for us.
-                */
-               break;
-
-       case NAND_ECC_HW:
-               ret = atmel_nand_pmecc_init(chip);
-               if (ret)
-                       return ret;
-
-               chip->ecc.read_page = atmel_nand_pmecc_read_page;
-               chip->ecc.write_page = atmel_nand_pmecc_write_page;
-               chip->ecc.read_page_raw = atmel_nand_pmecc_read_page_raw;
-               chip->ecc.write_page_raw = atmel_nand_pmecc_write_page_raw;
-               break;
-
-       default:
-               /* Other modes are not supported. */
-               dev_err(nc->dev, "Unsupported ECC mode: %d\n",
-                       chip->ecc.mode);
-               return -ENOTSUPP;
-       }
-
-       return 0;
-}
-
-static int atmel_hsmc_nand_ecc_init(struct atmel_nand *nand)
-{
-       struct nand_chip *chip = &nand->base;
-       int ret;
-
-       ret = atmel_nand_ecc_init(nand);
-       if (ret)
-               return ret;
-
-       if (chip->ecc.mode != NAND_ECC_HW)
-               return 0;
-
-       /* Adjust the ECC operations for the HSMC IP. */
-       chip->ecc.read_page = atmel_hsmc_nand_pmecc_read_page;
-       chip->ecc.write_page = atmel_hsmc_nand_pmecc_write_page;
-       chip->ecc.read_page_raw = atmel_hsmc_nand_pmecc_read_page_raw;
-       chip->ecc.write_page_raw = atmel_hsmc_nand_pmecc_write_page_raw;
-
-       return 0;
-}
-
-static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand,
-                                       const struct nand_data_interface *conf,
-                                       struct atmel_smc_cs_conf *smcconf)
-{
-       u32 ncycles, totalcycles, timeps, mckperiodps;
-       struct atmel_nand_controller *nc;
-       int ret;
-
-       nc = to_nand_controller(nand->base.controller);
-
-       /* DDR interface not supported. */
-       if (conf->type != NAND_SDR_IFACE)
-               return -ENOTSUPP;
-
-       /*
-        * tRC < 30ns implies EDO mode. This controller does not support this
-        * mode.
-        */
-       if (conf->timings.sdr.tRC_min < 30000)
-               return -ENOTSUPP;
-
-       atmel_smc_cs_conf_init(smcconf);
-
-       mckperiodps = NSEC_PER_SEC / clk_get_rate(nc->mck);
-       mckperiodps *= 1000;
-
-       /*
-        * Set write pulse timing. This one is easy to extract:
-        *
-        * NWE_PULSE = tWP
-        */
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tWP_min, mckperiodps);
-       totalcycles = ncycles;
-       ret = atmel_smc_cs_conf_set_pulse(smcconf, ATMEL_SMC_NWE_SHIFT,
-                                         ncycles);
-       if (ret)
-               return ret;
-
-       /*
-        * The write setup timing depends on the operation done on the NAND.
-        * All operations goes through the same data bus, but the operation
-        * type depends on the address we are writing to (ALE/CLE address
-        * lines).
-        * Since we have no way to differentiate the different operations at
-        * the SMC level, we must consider the worst case (the biggest setup
-        * time among all operation types):
-        *
-        * NWE_SETUP = max(tCLS, tCS, tALS, tDS) - NWE_PULSE
-        */
-       timeps = max3(conf->timings.sdr.tCLS_min, conf->timings.sdr.tCS_min,
-                     conf->timings.sdr.tALS_min);
-       timeps = max(timeps, conf->timings.sdr.tDS_min);
-       ncycles = DIV_ROUND_UP(timeps, mckperiodps);
-       ncycles = ncycles > totalcycles ? ncycles - totalcycles : 0;
-       totalcycles += ncycles;
-       ret = atmel_smc_cs_conf_set_setup(smcconf, ATMEL_SMC_NWE_SHIFT,
-                                         ncycles);
-       if (ret)
-               return ret;
-
-       /*
-        * As for the write setup timing, the write hold timing depends on the
-        * operation done on the NAND:
-        *
-        * NWE_HOLD = max(tCLH, tCH, tALH, tDH, tWH)
-        */
-       timeps = max3(conf->timings.sdr.tCLH_min, conf->timings.sdr.tCH_min,
-                     conf->timings.sdr.tALH_min);
-       timeps = max3(timeps, conf->timings.sdr.tDH_min,
-                     conf->timings.sdr.tWH_min);
-       ncycles = DIV_ROUND_UP(timeps, mckperiodps);
-       totalcycles += ncycles;
-
-       /*
-        * The write cycle timing is directly matching tWC, but is also
-        * dependent on the other timings on the setup and hold timings we
-        * calculated earlier, which gives:
-        *
-        * NWE_CYCLE = max(tWC, NWE_SETUP + NWE_PULSE + NWE_HOLD)
-        */
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tWC_min, mckperiodps);
-       ncycles = max(totalcycles, ncycles);
-       ret = atmel_smc_cs_conf_set_cycle(smcconf, ATMEL_SMC_NWE_SHIFT,
-                                         ncycles);
-       if (ret)
-               return ret;
-
-       /*
-        * We don't want the CS line to be toggled between each byte/word
-        * transfer to the NAND. The only way to guarantee that is to have the
-        * NCS_{WR,RD}_{SETUP,HOLD} timings set to 0, which in turn means:
-        *
-        * NCS_WR_PULSE = NWE_CYCLE
-        */
-       ret = atmel_smc_cs_conf_set_pulse(smcconf, ATMEL_SMC_NCS_WR_SHIFT,
-                                         ncycles);
-       if (ret)
-               return ret;
-
-       /*
-        * As for the write setup timing, the read hold timing depends on the
-        * operation done on the NAND:
-        *
-        * NRD_HOLD = max(tREH, tRHOH)
-        */
-       timeps = max(conf->timings.sdr.tREH_min, conf->timings.sdr.tRHOH_min);
-       ncycles = DIV_ROUND_UP(timeps, mckperiodps);
-       totalcycles = ncycles;
-
-       /*
-        * TDF = tRHZ - NRD_HOLD
-        */
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tRHZ_max, mckperiodps);
-       ncycles -= totalcycles;
-
-       /*
-        * In ONFI 4.0 specs, tRHZ has been increased to support EDO NANDs and
-        * we might end up with a config that does not fit in the TDF field.
-        * Just take the max value in this case and hope that the NAND is more
-        * tolerant than advertised.
-        */
-       if (ncycles > ATMEL_SMC_MODE_TDF_MAX)
-               ncycles = ATMEL_SMC_MODE_TDF_MAX;
-       else if (ncycles < ATMEL_SMC_MODE_TDF_MIN)
-               ncycles = ATMEL_SMC_MODE_TDF_MIN;
-
-       smcconf->mode |= ATMEL_SMC_MODE_TDF(ncycles) |
-                        ATMEL_SMC_MODE_TDFMODE_OPTIMIZED;
-
-       /*
-        * Read pulse timing directly matches tRP:
-        *
-        * NRD_PULSE = tRP
-        */
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tRP_min, mckperiodps);
-       totalcycles += ncycles;
-       ret = atmel_smc_cs_conf_set_pulse(smcconf, ATMEL_SMC_NRD_SHIFT,
-                                         ncycles);
-       if (ret)
-               return ret;
-
-       /*
-        * The write cycle timing is directly matching tWC, but is also
-        * dependent on the setup and hold timings we calculated earlier,
-        * which gives:
-        *
-        * NRD_CYCLE = max(tRC, NRD_PULSE + NRD_HOLD)
-        *
-        * NRD_SETUP is always 0.
-        */
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tRC_min, mckperiodps);
-       ncycles = max(totalcycles, ncycles);
-       ret = atmel_smc_cs_conf_set_cycle(smcconf, ATMEL_SMC_NRD_SHIFT,
-                                         ncycles);
-       if (ret)
-               return ret;
-
-       /*
-        * We don't want the CS line to be toggled between each byte/word
-        * transfer from the NAND. The only way to guarantee that is to have
-        * the NCS_{WR,RD}_{SETUP,HOLD} timings set to 0, which in turn means:
-        *
-        * NCS_RD_PULSE = NRD_CYCLE
-        */
-       ret = atmel_smc_cs_conf_set_pulse(smcconf, ATMEL_SMC_NCS_RD_SHIFT,
-                                         ncycles);
-       if (ret)
-               return ret;
-
-       /* Txxx timings are directly matching tXXX ones. */
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tCLR_min, mckperiodps);
-       ret = atmel_smc_cs_conf_set_timing(smcconf,
-                                          ATMEL_HSMC_TIMINGS_TCLR_SHIFT,
-                                          ncycles);
-       if (ret)
-               return ret;
-
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tADL_min, mckperiodps);
-       ret = atmel_smc_cs_conf_set_timing(smcconf,
-                                          ATMEL_HSMC_TIMINGS_TADL_SHIFT,
-                                          ncycles);
-       /*
-        * Version 4 of the ONFI spec mandates that tADL be at least 400
-        * nanoseconds, but, depending on the master clock rate, 400 ns may not
-        * fit in the tADL field of the SMC reg. We need to relax the check and
-        * accept the -ERANGE return code.
-        *
-        * Note that previous versions of the ONFI spec had a lower tADL_min
-        * (100 or 200 ns). It's not clear why this timing constraint got
-        * increased but it seems most NANDs are fine with values lower than
-        * 400ns, so we should be safe.
-        */
-       if (ret && ret != -ERANGE)
-               return ret;
-
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tAR_min, mckperiodps);
-       ret = atmel_smc_cs_conf_set_timing(smcconf,
-                                          ATMEL_HSMC_TIMINGS_TAR_SHIFT,
-                                          ncycles);
-       if (ret)
-               return ret;
-
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tRR_min, mckperiodps);
-       ret = atmel_smc_cs_conf_set_timing(smcconf,
-                                          ATMEL_HSMC_TIMINGS_TRR_SHIFT,
-                                          ncycles);
-       if (ret)
-               return ret;
-
-       ncycles = DIV_ROUND_UP(conf->timings.sdr.tWB_max, mckperiodps);
-       ret = atmel_smc_cs_conf_set_timing(smcconf,
-                                          ATMEL_HSMC_TIMINGS_TWB_SHIFT,
-                                          ncycles);
-       if (ret)
-               return ret;
-
-       /* Attach the CS line to the NFC logic. */
-       smcconf->timings |= ATMEL_HSMC_TIMINGS_NFSEL;
-
-       /* Set the appropriate data bus width. */
-       if (nand->base.options & NAND_BUSWIDTH_16)
-               smcconf->mode |= ATMEL_SMC_MODE_DBW_16;
-
-       /* Operate in NRD/NWE READ/WRITEMODE. */
-       smcconf->mode |= ATMEL_SMC_MODE_READMODE_NRD |
-                        ATMEL_SMC_MODE_WRITEMODE_NWE;
-
-       return 0;
-}
-
-static int atmel_smc_nand_setup_data_interface(struct atmel_nand *nand,
-                                       int csline,
-                                       const struct nand_data_interface *conf)
-{
-       struct atmel_nand_controller *nc;
-       struct atmel_smc_cs_conf smcconf;
-       struct atmel_nand_cs *cs;
-       int ret;
-
-       nc = to_nand_controller(nand->base.controller);
-
-       ret = atmel_smc_nand_prepare_smcconf(nand, conf, &smcconf);
-       if (ret)
-               return ret;
-
-       if (csline == NAND_DATA_IFACE_CHECK_ONLY)
-               return 0;
-
-       cs = &nand->cs[csline];
-       cs->smcconf = smcconf;
-       atmel_smc_cs_conf_apply(nc->smc, cs->id, &cs->smcconf);
-
-       return 0;
-}
-
-static int atmel_hsmc_nand_setup_data_interface(struct atmel_nand *nand,
-                                       int csline,
-                                       const struct nand_data_interface *conf)
-{
-       struct atmel_hsmc_nand_controller *nc;
-       struct atmel_smc_cs_conf smcconf;
-       struct atmel_nand_cs *cs;
-       int ret;
-
-       nc = to_hsmc_nand_controller(nand->base.controller);
-
-       ret = atmel_smc_nand_prepare_smcconf(nand, conf, &smcconf);
-       if (ret)
-               return ret;
-
-       if (csline == NAND_DATA_IFACE_CHECK_ONLY)
-               return 0;
-
-       cs = &nand->cs[csline];
-       cs->smcconf = smcconf;
-
-       if (cs->rb.type == ATMEL_NAND_NATIVE_RB)
-               cs->smcconf.timings |= ATMEL_HSMC_TIMINGS_RBNSEL(cs->rb.id);
-
-       atmel_hsmc_cs_conf_apply(nc->base.smc, nc->hsmc_layout, cs->id,
-                                &cs->smcconf);
-
-       return 0;
-}
-
-static int atmel_nand_setup_data_interface(struct mtd_info *mtd, int csline,
-                                       const struct nand_data_interface *conf)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand *nand = to_atmel_nand(chip);
-       struct atmel_nand_controller *nc;
-
-       nc = to_nand_controller(nand->base.controller);
-
-       if (csline >= nand->numcs ||
-           (csline < 0 && csline != NAND_DATA_IFACE_CHECK_ONLY))
-               return -EINVAL;
-
-       return nc->caps->ops->setup_data_interface(nand, csline, conf);
-}
-
-static void atmel_nand_init(struct atmel_nand_controller *nc,
-                           struct atmel_nand *nand)
-{
-       struct nand_chip *chip = &nand->base;
-       struct mtd_info *mtd = nand_to_mtd(chip);
-
-       mtd->dev.parent = nc->dev;
-       nand->base.controller = &nc->base;
-
-       chip->cmd_ctrl = atmel_nand_cmd_ctrl;
-       chip->read_byte = atmel_nand_read_byte;
-       chip->read_word = atmel_nand_read_word;
-       chip->write_byte = atmel_nand_write_byte;
-       chip->read_buf = atmel_nand_read_buf;
-       chip->write_buf = atmel_nand_write_buf;
-       chip->select_chip = atmel_nand_select_chip;
-
-       if (nc->mck && nc->caps->ops->setup_data_interface)
-               chip->setup_data_interface = atmel_nand_setup_data_interface;
-
-       /* Some NANDs require a longer delay than the default one (20us). */
-       chip->chip_delay = 40;
-
-       /*
-        * Use a bounce buffer when the buffer passed by the MTD user is not
-        * suitable for DMA.
-        */
-       if (nc->dmac)
-               chip->options |= NAND_USE_BOUNCE_BUFFER;
-
-       /* Default to HW ECC if pmecc is available. */
-       if (nc->pmecc)
-               chip->ecc.mode = NAND_ECC_HW;
-}
-
-static void atmel_smc_nand_init(struct atmel_nand_controller *nc,
-                               struct atmel_nand *nand)
-{
-       struct nand_chip *chip = &nand->base;
-       struct atmel_smc_nand_controller *smc_nc;
-       int i;
-
-       atmel_nand_init(nc, nand);
-
-       smc_nc = to_smc_nand_controller(chip->controller);
-       if (!smc_nc->matrix)
-               return;
-
-       /* Attach the CS to the NAND Flash logic. */
-       for (i = 0; i < nand->numcs; i++)
-               regmap_update_bits(smc_nc->matrix, smc_nc->ebi_csa_offs,
-                                  BIT(nand->cs[i].id), BIT(nand->cs[i].id));
-}
-
-static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc,
-                                struct atmel_nand *nand)
-{
-       struct nand_chip *chip = &nand->base;
-
-       atmel_nand_init(nc, nand);
-
-       /* Overload some methods for the HSMC controller. */
-       chip->cmd_ctrl = atmel_hsmc_nand_cmd_ctrl;
-       chip->select_chip = atmel_hsmc_nand_select_chip;
-}
-
-static int atmel_nand_detect(struct atmel_nand *nand)
-{
-       struct nand_chip *chip = &nand->base;
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_nand_controller *nc;
-       int ret;
-
-       nc = to_nand_controller(chip->controller);
-
-       ret = nand_scan_ident(mtd, nand->numcs, NULL);
-       if (ret)
-               dev_err(nc->dev, "nand_scan_ident() failed: %d\n", ret);
-
-       return ret;
-}
-
-static int atmel_nand_unregister(struct atmel_nand *nand)
-{
-       struct nand_chip *chip = &nand->base;
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       int ret;
-
-       ret = mtd_device_unregister(mtd);
-       if (ret)
-               return ret;
-
-       nand_cleanup(chip);
-       list_del(&nand->node);
-
-       return 0;
-}
-
-static int atmel_nand_register(struct atmel_nand *nand)
-{
-       struct nand_chip *chip = &nand->base;
-       struct mtd_info *mtd = nand_to_mtd(chip);
-       struct atmel_nand_controller *nc;
-       int ret;
-
-       nc = to_nand_controller(chip->controller);
-
-       if (nc->caps->legacy_of_bindings || !nc->dev->of_node) {
-               /*
-                * We keep the MTD name unchanged to avoid breaking platforms
-                * where the MTD cmdline parser is used and the bootloader
-                * has not been updated to use the new naming scheme.
-                */
-               mtd->name = "atmel_nand";
-       } else if (!mtd->name) {
-               /*
-                * If the new bindings are used and the bootloader has not been
-                * updated to pass a new mtdparts parameter on the cmdline, you
-                * should define the following property in your nand node:
-                *
-                *      label = "atmel_nand";
-                *
-                * This way, mtd->name will be set by the core when
-                * nand_set_flash_node() is called.
-                */
-               mtd->name = devm_kasprintf(nc->dev, GFP_KERNEL,
-                                          "%s:nand.%d", dev_name(nc->dev),
-                                          nand->cs[0].id);
-               if (!mtd->name) {
-                       dev_err(nc->dev, "Failed to allocate mtd->name\n");
-                       return -ENOMEM;
-               }
-       }
-
-       ret = nand_scan_tail(mtd);
-       if (ret) {
-               dev_err(nc->dev, "nand_scan_tail() failed: %d\n", ret);
-               return ret;
-       }
-
-       ret = mtd_device_register(mtd, NULL, 0);
-       if (ret) {
-               dev_err(nc->dev, "Failed to register mtd device: %d\n", ret);
-               nand_cleanup(chip);
-               return ret;
-       }
-
-       list_add_tail(&nand->node, &nc->chips);
-
-       return 0;
-}
-
-static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc,
-                                           struct device_node *np,
-                                           int reg_cells)
-{
-       struct atmel_nand *nand;
-       struct gpio_desc *gpio;
-       int numcs, ret, i;
-
-       numcs = of_property_count_elems_of_size(np, "reg",
-                                               reg_cells * sizeof(u32));
-       if (numcs < 1) {
-               dev_err(nc->dev, "Missing or invalid reg property\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       nand = devm_kzalloc(nc->dev,
-                           sizeof(*nand) + (numcs * sizeof(*nand->cs)),
-                           GFP_KERNEL);
-       if (!nand) {
-               dev_err(nc->dev, "Failed to allocate NAND object\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       nand->numcs = numcs;
-
-       gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "det", 0,
-                                                     &np->fwnode, GPIOD_IN,
-                                                     "nand-det");
-       if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) {
-               dev_err(nc->dev,
-                       "Failed to get detect gpio (err = %ld)\n",
-                       PTR_ERR(gpio));
-               return ERR_CAST(gpio);
-       }
-
-       if (!IS_ERR(gpio))
-               nand->cdgpio = gpio;
-
-       for (i = 0; i < numcs; i++) {
-               struct resource res;
-               u32 val;
-
-               ret = of_address_to_resource(np, 0, &res);
-               if (ret) {
-                       dev_err(nc->dev, "Invalid reg property (err = %d)\n",
-                               ret);
-                       return ERR_PTR(ret);
-               }
-
-               ret = of_property_read_u32_index(np, "reg", i * reg_cells,
-                                                &val);
-               if (ret) {
-                       dev_err(nc->dev, "Invalid reg property (err = %d)\n",
-                               ret);
-                       return ERR_PTR(ret);
-               }
-
-               nand->cs[i].id = val;
-
-               nand->cs[i].io.dma = res.start;
-               nand->cs[i].io.virt = devm_ioremap_resource(nc->dev, &res);
-               if (IS_ERR(nand->cs[i].io.virt))
-                       return ERR_CAST(nand->cs[i].io.virt);
-
-               if (!of_property_read_u32(np, "atmel,rb", &val)) {
-                       if (val > ATMEL_NFC_MAX_RB_ID)
-                               return ERR_PTR(-EINVAL);
-
-                       nand->cs[i].rb.type = ATMEL_NAND_NATIVE_RB;
-                       nand->cs[i].rb.id = val;
-               } else {
-                       gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev,
-                                                       "rb", i, &np->fwnode,
-                                                       GPIOD_IN, "nand-rb");
-                       if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) {
-                               dev_err(nc->dev,
-                                       "Failed to get R/B gpio (err = %ld)\n",
-                                       PTR_ERR(gpio));
-                               return ERR_CAST(gpio);
-                       }
-
-                       if (!IS_ERR(gpio)) {
-                               nand->cs[i].rb.type = ATMEL_NAND_GPIO_RB;
-                               nand->cs[i].rb.gpio = gpio;
-                       }
-               }
-
-               gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "cs",
-                                                             i, &np->fwnode,
-                                                             GPIOD_OUT_HIGH,
-                                                             "nand-cs");
-               if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) {
-                       dev_err(nc->dev,
-                               "Failed to get CS gpio (err = %ld)\n",
-                               PTR_ERR(gpio));
-                       return ERR_CAST(gpio);
-               }
-
-               if (!IS_ERR(gpio))
-                       nand->cs[i].csgpio = gpio;
-       }
-
-       nand_set_flash_node(&nand->base, np);
-
-       return nand;
-}
-
-static int
-atmel_nand_controller_add_nand(struct atmel_nand_controller *nc,
-                              struct atmel_nand *nand)
-{
-       int ret;
-
-       /* No card inserted, skip this NAND. */
-       if (nand->cdgpio && gpiod_get_value(nand->cdgpio)) {
-               dev_info(nc->dev, "No SmartMedia card inserted.\n");
-               return 0;
-       }
-
-       nc->caps->ops->nand_init(nc, nand);
-
-       ret = atmel_nand_detect(nand);
-       if (ret)
-               return ret;
-
-       ret = nc->caps->ops->ecc_init(nand);
-       if (ret)
-               return ret;
-
-       return atmel_nand_register(nand);
-}
-
-static int
-atmel_nand_controller_remove_nands(struct atmel_nand_controller *nc)
-{
-       struct atmel_nand *nand, *tmp;
-       int ret;
-
-       list_for_each_entry_safe(nand, tmp, &nc->chips, node) {
-               ret = atmel_nand_unregister(nand);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int
-atmel_nand_controller_legacy_add_nands(struct atmel_nand_controller *nc)
-{
-       struct device *dev = nc->dev;
-       struct platform_device *pdev = to_platform_device(dev);
-       struct atmel_nand *nand;
-       struct gpio_desc *gpio;
-       struct resource *res;
-
-       /*
-        * Legacy bindings only allow connecting a single NAND with a unique CS
-        * line to the controller.
-        */
-       nand = devm_kzalloc(nc->dev, sizeof(*nand) + sizeof(*nand->cs),
-                           GFP_KERNEL);
-       if (!nand)
-               return -ENOMEM;
-
-       nand->numcs = 1;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       nand->cs[0].io.virt = devm_ioremap_resource(dev, res);
-       if (IS_ERR(nand->cs[0].io.virt))
-               return PTR_ERR(nand->cs[0].io.virt);
-
-       nand->cs[0].io.dma = res->start;
-
-       /*
-        * The old driver was hardcoding the CS id to 3 for all sama5
-        * controllers. Since this id is only meaningful for the sama5
-        * controller we can safely assign this id to 3 no matter the
-        * controller.
-        * If one wants to connect a NAND to a different CS line, he will
-        * have to use the new bindings.
-        */
-       nand->cs[0].id = 3;
-
-       /* R/B GPIO. */
-       gpio = devm_gpiod_get_index_optional(dev, NULL, 0,  GPIOD_IN);
-       if (IS_ERR(gpio)) {
-               dev_err(dev, "Failed to get R/B gpio (err = %ld)\n",
-                       PTR_ERR(gpio));
-               return PTR_ERR(gpio);
-       }
-
-       if (gpio) {
-               nand->cs[0].rb.type = ATMEL_NAND_GPIO_RB;
-               nand->cs[0].rb.gpio = gpio;
-       }
-
-       /* CS GPIO. */
-       gpio = devm_gpiod_get_index_optional(dev, NULL, 1, GPIOD_OUT_HIGH);
-       if (IS_ERR(gpio)) {
-               dev_err(dev, "Failed to get CS gpio (err = %ld)\n",
-                       PTR_ERR(gpio));
-               return PTR_ERR(gpio);
-       }
-
-       nand->cs[0].csgpio = gpio;
-
-       /* Card detect GPIO. */
-       gpio = devm_gpiod_get_index_optional(nc->dev, NULL, 2, GPIOD_IN);
-       if (IS_ERR(gpio)) {
-               dev_err(dev,
-                       "Failed to get detect gpio (err = %ld)\n",
-                       PTR_ERR(gpio));
-               return PTR_ERR(gpio);
-       }
-
-       nand->cdgpio = gpio;
-
-       nand_set_flash_node(&nand->base, nc->dev->of_node);
-
-       return atmel_nand_controller_add_nand(nc, nand);
-}
-
-static int atmel_nand_controller_add_nands(struct atmel_nand_controller *nc)
-{
-       struct device_node *np, *nand_np;
-       struct device *dev = nc->dev;
-       int ret, reg_cells;
-       u32 val;
-
-       /* We do not retrieve the SMC syscon when parsing old DTs. */
-       if (nc->caps->legacy_of_bindings)
-               return atmel_nand_controller_legacy_add_nands(nc);
-
-       np = dev->of_node;
-
-       ret = of_property_read_u32(np, "#address-cells", &val);
-       if (ret) {
-               dev_err(dev, "missing #address-cells property\n");
-               return ret;
-       }
-
-       reg_cells = val;
-
-       ret = of_property_read_u32(np, "#size-cells", &val);
-       if (ret) {
-               dev_err(dev, "missing #address-cells property\n");
-               return ret;
-       }
-
-       reg_cells += val;
-
-       for_each_child_of_node(np, nand_np) {
-               struct atmel_nand *nand;
-
-               nand = atmel_nand_create(nc, nand_np, reg_cells);
-               if (IS_ERR(nand)) {
-                       ret = PTR_ERR(nand);
-                       goto err;
-               }
-
-               ret = atmel_nand_controller_add_nand(nc, nand);
-               if (ret)
-                       goto err;
-       }
-
-       return 0;
-
-err:
-       atmel_nand_controller_remove_nands(nc);
-
-       return ret;
-}
-
-static void atmel_nand_controller_cleanup(struct atmel_nand_controller *nc)
-{
-       if (nc->dmac)
-               dma_release_channel(nc->dmac);
-
-       clk_put(nc->mck);
-}
-
-static const struct of_device_id atmel_matrix_of_ids[] = {
-       {
-               .compatible = "atmel,at91sam9260-matrix",
-               .data = (void *)AT91SAM9260_MATRIX_EBICSA,
-       },
-       {
-               .compatible = "atmel,at91sam9261-matrix",
-               .data = (void *)AT91SAM9261_MATRIX_EBICSA,
-       },
-       {
-               .compatible = "atmel,at91sam9263-matrix",
-               .data = (void *)AT91SAM9263_MATRIX_EBI0CSA,
-       },
-       {
-               .compatible = "atmel,at91sam9rl-matrix",
-               .data = (void *)AT91SAM9RL_MATRIX_EBICSA,
-       },
-       {
-               .compatible = "atmel,at91sam9g45-matrix",
-               .data = (void *)AT91SAM9G45_MATRIX_EBICSA,
-       },
-       {
-               .compatible = "atmel,at91sam9n12-matrix",
-               .data = (void *)AT91SAM9N12_MATRIX_EBICSA,
-       },
-       {
-               .compatible = "atmel,at91sam9x5-matrix",
-               .data = (void *)AT91SAM9X5_MATRIX_EBICSA,
-       },
-       { /* sentinel */ },
-};
-
-static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
-                               struct platform_device *pdev,
-                               const struct atmel_nand_controller_caps *caps)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       int ret;
-
-       nand_hw_control_init(&nc->base);
-       INIT_LIST_HEAD(&nc->chips);
-       nc->dev = dev;
-       nc->caps = caps;
-
-       platform_set_drvdata(pdev, nc);
-
-       nc->pmecc = devm_atmel_pmecc_get(dev);
-       if (IS_ERR(nc->pmecc)) {
-               ret = PTR_ERR(nc->pmecc);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "Could not get PMECC object (err = %d)\n",
-                               ret);
-               return ret;
-       }
-
-       if (nc->caps->has_dma) {
-               dma_cap_mask_t mask;
-
-               dma_cap_zero(mask);
-               dma_cap_set(DMA_MEMCPY, mask);
-
-               nc->dmac = dma_request_channel(mask, NULL, NULL);
-               if (!nc->dmac)
-                       dev_err(nc->dev, "Failed to request DMA channel\n");
-       }
-
-       /* We do not retrieve the SMC syscon when parsing old DTs. */
-       if (nc->caps->legacy_of_bindings)
-               return 0;
-
-       nc->mck = of_clk_get(dev->parent->of_node, 0);
-       if (IS_ERR(nc->mck)) {
-               dev_err(dev, "Failed to retrieve MCK clk\n");
-               return PTR_ERR(nc->mck);
-       }
-
-       np = of_parse_phandle(dev->parent->of_node, "atmel,smc", 0);
-       if (!np) {
-               dev_err(dev, "Missing or invalid atmel,smc property\n");
-               return -EINVAL;
-       }
-
-       nc->smc = syscon_node_to_regmap(np);
-       of_node_put(np);
-       if (IS_ERR(nc->smc)) {
-               ret = PTR_ERR(nc->smc);
-               dev_err(dev, "Could not get SMC regmap (err = %d)\n", ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int
-atmel_smc_nand_controller_init(struct atmel_smc_nand_controller *nc)
-{
-       struct device *dev = nc->base.dev;
-       const struct of_device_id *match;
-       struct device_node *np;
-       int ret;
-
-       /* We do not retrieve the matrix syscon when parsing old DTs. */
-       if (nc->base.caps->legacy_of_bindings)
-               return 0;
-
-       np = of_parse_phandle(dev->parent->of_node, "atmel,matrix", 0);
-       if (!np)
-               return 0;
-
-       match = of_match_node(atmel_matrix_of_ids, np);
-       if (!match) {
-               of_node_put(np);
-               return 0;
-       }
-
-       nc->matrix = syscon_node_to_regmap(np);
-       of_node_put(np);
-       if (IS_ERR(nc->matrix)) {
-               ret = PTR_ERR(nc->matrix);
-               dev_err(dev, "Could not get Matrix regmap (err = %d)\n", ret);
-               return ret;
-       }
-
-       nc->ebi_csa_offs = (unsigned int)match->data;
-
-       /*
-        * The at91sam9263 has 2 EBIs, if the NAND controller is under EBI1
-        * add 4 to ->ebi_csa_offs.
-        */
-       if (of_device_is_compatible(dev->parent->of_node,
-                                   "atmel,at91sam9263-ebi1"))
-               nc->ebi_csa_offs += 4;
-
-       return 0;
-}
-
-static int
-atmel_hsmc_nand_controller_legacy_init(struct atmel_hsmc_nand_controller *nc)
-{
-       struct regmap_config regmap_conf = {
-               .reg_bits = 32,
-               .val_bits = 32,
-               .reg_stride = 4,
-       };
-
-       struct device *dev = nc->base.dev;
-       struct device_node *nand_np, *nfc_np;
-       void __iomem *iomem;
-       struct resource res;
-       int ret;
-
-       nand_np = dev->of_node;
-       nfc_np = of_find_compatible_node(dev->of_node, NULL,
-                                        "atmel,sama5d3-nfc");
-
-       nc->clk = of_clk_get(nfc_np, 0);
-       if (IS_ERR(nc->clk)) {
-               ret = PTR_ERR(nc->clk);
-               dev_err(dev, "Failed to retrieve HSMC clock (err = %d)\n",
-                       ret);
-               goto out;
-       }
-
-       ret = clk_prepare_enable(nc->clk);
-       if (ret) {
-               dev_err(dev, "Failed to enable the HSMC clock (err = %d)\n",
-                       ret);
-               goto out;
-       }
-
-       nc->irq = of_irq_get(nand_np, 0);
-       if (nc->irq <= 0) {
-               ret = nc->irq ?: -ENXIO;
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "Failed to get IRQ number (err = %d)\n",
-                               ret);
-               goto out;
-       }
-
-       ret = of_address_to_resource(nfc_np, 0, &res);
-       if (ret) {
-               dev_err(dev, "Invalid or missing NFC IO resource (err = %d)\n",
-                       ret);
-               goto out;
-       }
-
-       iomem = devm_ioremap_resource(dev, &res);
-       if (IS_ERR(iomem)) {
-               ret = PTR_ERR(iomem);
-               goto out;
-       }
-
-       regmap_conf.name = "nfc-io";
-       regmap_conf.max_register = resource_size(&res) - 4;
-       nc->io = devm_regmap_init_mmio(dev, iomem, &regmap_conf);
-       if (IS_ERR(nc->io)) {
-               ret = PTR_ERR(nc->io);
-               dev_err(dev, "Could not create NFC IO regmap (err = %d)\n",
-                       ret);
-               goto out;
-       }
-
-       ret = of_address_to_resource(nfc_np, 1, &res);
-       if (ret) {
-               dev_err(dev, "Invalid or missing HSMC resource (err = %d)\n",
-                       ret);
-               goto out;
-       }
-
-       iomem = devm_ioremap_resource(dev, &res);
-       if (IS_ERR(iomem)) {
-               ret = PTR_ERR(iomem);
-               goto out;
-       }
-
-       regmap_conf.name = "smc";
-       regmap_conf.max_register = resource_size(&res) - 4;
-       nc->base.smc = devm_regmap_init_mmio(dev, iomem, &regmap_conf);
-       if (IS_ERR(nc->base.smc)) {
-               ret = PTR_ERR(nc->base.smc);
-               dev_err(dev, "Could not create NFC IO regmap (err = %d)\n",
-                       ret);
-               goto out;
-       }
-
-       ret = of_address_to_resource(nfc_np, 2, &res);
-       if (ret) {
-               dev_err(dev, "Invalid or missing SRAM resource (err = %d)\n",
-                       ret);
-               goto out;
-       }
-
-       nc->sram.virt = devm_ioremap_resource(dev, &res);
-       if (IS_ERR(nc->sram.virt)) {
-               ret = PTR_ERR(nc->sram.virt);
-               goto out;
-       }
-
-       nc->sram.dma = res.start;
-
-out:
-       of_node_put(nfc_np);
-
-       return ret;
-}
-
-static int
-atmel_hsmc_nand_controller_init(struct atmel_hsmc_nand_controller *nc)
-{
-       struct device *dev = nc->base.dev;
-       struct device_node *np;
-       int ret;
-
-       np = of_parse_phandle(dev->parent->of_node, "atmel,smc", 0);
-       if (!np) {
-               dev_err(dev, "Missing or invalid atmel,smc property\n");
-               return -EINVAL;
-       }
-
-       nc->hsmc_layout = atmel_hsmc_get_reg_layout(np);
-
-       nc->irq = of_irq_get(np, 0);
-       of_node_put(np);
-       if (nc->irq <= 0) {
-               ret = nc->irq ?: -ENXIO;
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "Failed to get IRQ number (err = %d)\n",
-                               ret);
-               return ret;
-       }
-
-       np = of_parse_phandle(dev->of_node, "atmel,nfc-io", 0);
-       if (!np) {
-               dev_err(dev, "Missing or invalid atmel,nfc-io property\n");
-               return -EINVAL;
-       }
-
-       nc->io = syscon_node_to_regmap(np);
-       of_node_put(np);
-       if (IS_ERR(nc->io)) {
-               ret = PTR_ERR(nc->io);
-               dev_err(dev, "Could not get NFC IO regmap (err = %d)\n", ret);
-               return ret;
-       }
-
-       nc->sram.pool = of_gen_pool_get(nc->base.dev->of_node,
-                                        "atmel,nfc-sram", 0);
-       if (!nc->sram.pool) {
-               dev_err(nc->base.dev, "Missing SRAM\n");
-               return -ENOMEM;
-       }
-
-       nc->sram.virt = gen_pool_dma_alloc(nc->sram.pool,
-                                           ATMEL_NFC_SRAM_SIZE,
-                                           &nc->sram.dma);
-       if (!nc->sram.virt) {
-               dev_err(nc->base.dev,
-                       "Could not allocate memory from the NFC SRAM pool\n");
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static int
-atmel_hsmc_nand_controller_remove(struct atmel_nand_controller *nc)
-{
-       struct atmel_hsmc_nand_controller *hsmc_nc;
-       int ret;
-
-       ret = atmel_nand_controller_remove_nands(nc);
-       if (ret)
-               return ret;
-
-       hsmc_nc = container_of(nc, struct atmel_hsmc_nand_controller, base);
-       if (hsmc_nc->sram.pool)
-               gen_pool_free(hsmc_nc->sram.pool,
-                             (unsigned long)hsmc_nc->sram.virt,
-                             ATMEL_NFC_SRAM_SIZE);
-
-       if (hsmc_nc->clk) {
-               clk_disable_unprepare(hsmc_nc->clk);
-               clk_put(hsmc_nc->clk);
-       }
-
-       atmel_nand_controller_cleanup(nc);
-
-       return 0;
-}
-
-static int atmel_hsmc_nand_controller_probe(struct platform_device *pdev,
-                               const struct atmel_nand_controller_caps *caps)
-{
-       struct device *dev = &pdev->dev;
-       struct atmel_hsmc_nand_controller *nc;
-       int ret;
-
-       nc = devm_kzalloc(dev, sizeof(*nc), GFP_KERNEL);
-       if (!nc)
-               return -ENOMEM;
-
-       ret = atmel_nand_controller_init(&nc->base, pdev, caps);
-       if (ret)
-               return ret;
-
-       if (caps->legacy_of_bindings)
-               ret = atmel_hsmc_nand_controller_legacy_init(nc);
-       else
-               ret = atmel_hsmc_nand_controller_init(nc);
-
-       if (ret)
-               return ret;
-
-       /* Make sure all irqs are masked before registering our IRQ handler. */
-       regmap_write(nc->base.smc, ATMEL_HSMC_NFC_IDR, 0xffffffff);
-       ret = devm_request_irq(dev, nc->irq, atmel_nfc_interrupt,
-                              IRQF_SHARED, "nfc", nc);
-       if (ret) {
-               dev_err(dev,
-                       "Could not get register NFC interrupt handler (err = %d)\n",
-                       ret);
-               goto err;
-       }
-
-       /* Initial NFC configuration. */
-       regmap_write(nc->base.smc, ATMEL_HSMC_NFC_CFG,
-                    ATMEL_HSMC_NFC_CFG_DTO_MAX);
-
-       ret = atmel_nand_controller_add_nands(&nc->base);
-       if (ret)
-               goto err;
-
-       return 0;
-
-err:
-       atmel_hsmc_nand_controller_remove(&nc->base);
-
-       return ret;
-}
-
-static const struct atmel_nand_controller_ops atmel_hsmc_nc_ops = {
-       .probe = atmel_hsmc_nand_controller_probe,
-       .remove = atmel_hsmc_nand_controller_remove,
-       .ecc_init = atmel_hsmc_nand_ecc_init,
-       .nand_init = atmel_hsmc_nand_init,
-       .setup_data_interface = atmel_hsmc_nand_setup_data_interface,
-};
-
-static const struct atmel_nand_controller_caps atmel_sama5_nc_caps = {
-       .has_dma = true,
-       .ale_offs = BIT(21),
-       .cle_offs = BIT(22),
-       .ops = &atmel_hsmc_nc_ops,
-};
-
-/* Only used to parse old bindings. */
-static const struct atmel_nand_controller_caps atmel_sama5_nand_caps = {
-       .has_dma = true,
-       .ale_offs = BIT(21),
-       .cle_offs = BIT(22),
-       .ops = &atmel_hsmc_nc_ops,
-       .legacy_of_bindings = true,
-};
-
-static int atmel_smc_nand_controller_probe(struct platform_device *pdev,
-                               const struct atmel_nand_controller_caps *caps)
-{
-       struct device *dev = &pdev->dev;
-       struct atmel_smc_nand_controller *nc;
-       int ret;
-
-       nc = devm_kzalloc(dev, sizeof(*nc), GFP_KERNEL);
-       if (!nc)
-               return -ENOMEM;
-
-       ret = atmel_nand_controller_init(&nc->base, pdev, caps);
-       if (ret)
-               return ret;
-
-       ret = atmel_smc_nand_controller_init(nc);
-       if (ret)
-               return ret;
-
-       return atmel_nand_controller_add_nands(&nc->base);
-}
-
-static int
-atmel_smc_nand_controller_remove(struct atmel_nand_controller *nc)
-{
-       int ret;
-
-       ret = atmel_nand_controller_remove_nands(nc);
-       if (ret)
-               return ret;
-
-       atmel_nand_controller_cleanup(nc);
-
-       return 0;
-}
-
-/*
- * The SMC reg layout of at91rm9200 is completely different which prevents us
- * from re-using atmel_smc_nand_setup_data_interface() for the
- * ->setup_data_interface() hook.
- * At this point, there's no support for the at91rm9200 SMC IP, so we leave
- * ->setup_data_interface() unassigned.
- */
-static const struct atmel_nand_controller_ops at91rm9200_nc_ops = {
-       .probe = atmel_smc_nand_controller_probe,
-       .remove = atmel_smc_nand_controller_remove,
-       .ecc_init = atmel_nand_ecc_init,
-       .nand_init = atmel_smc_nand_init,
-};
-
-static const struct atmel_nand_controller_caps atmel_rm9200_nc_caps = {
-       .ale_offs = BIT(21),
-       .cle_offs = BIT(22),
-       .ops = &at91rm9200_nc_ops,
-};
-
-static const struct atmel_nand_controller_ops atmel_smc_nc_ops = {
-       .probe = atmel_smc_nand_controller_probe,
-       .remove = atmel_smc_nand_controller_remove,
-       .ecc_init = atmel_nand_ecc_init,
-       .nand_init = atmel_smc_nand_init,
-       .setup_data_interface = atmel_smc_nand_setup_data_interface,
-};
-
-static const struct atmel_nand_controller_caps atmel_sam9260_nc_caps = {
-       .ale_offs = BIT(21),
-       .cle_offs = BIT(22),
-       .ops = &atmel_smc_nc_ops,
-};
-
-static const struct atmel_nand_controller_caps atmel_sam9261_nc_caps = {
-       .ale_offs = BIT(22),
-       .cle_offs = BIT(21),
-       .ops = &atmel_smc_nc_ops,
-};
-
-static const struct atmel_nand_controller_caps atmel_sam9g45_nc_caps = {
-       .has_dma = true,
-       .ale_offs = BIT(21),
-       .cle_offs = BIT(22),
-       .ops = &atmel_smc_nc_ops,
-};
-
-/* Only used to parse old bindings. */
-static const struct atmel_nand_controller_caps atmel_rm9200_nand_caps = {
-       .ale_offs = BIT(21),
-       .cle_offs = BIT(22),
-       .ops = &atmel_smc_nc_ops,
-       .legacy_of_bindings = true,
-};
-
-static const struct atmel_nand_controller_caps atmel_sam9261_nand_caps = {
-       .ale_offs = BIT(22),
-       .cle_offs = BIT(21),
-       .ops = &atmel_smc_nc_ops,
-       .legacy_of_bindings = true,
-};
-
-static const struct atmel_nand_controller_caps atmel_sam9g45_nand_caps = {
-       .has_dma = true,
-       .ale_offs = BIT(21),
-       .cle_offs = BIT(22),
-       .ops = &atmel_smc_nc_ops,
-       .legacy_of_bindings = true,
-};
-
-static const struct of_device_id atmel_nand_controller_of_ids[] = {
-       {
-               .compatible = "atmel,at91rm9200-nand-controller",
-               .data = &atmel_rm9200_nc_caps,
-       },
-       {
-               .compatible = "atmel,at91sam9260-nand-controller",
-               .data = &atmel_sam9260_nc_caps,
-       },
-       {
-               .compatible = "atmel,at91sam9261-nand-controller",
-               .data = &atmel_sam9261_nc_caps,
-       },
-       {
-               .compatible = "atmel,at91sam9g45-nand-controller",
-               .data = &atmel_sam9g45_nc_caps,
-       },
-       {
-               .compatible = "atmel,sama5d3-nand-controller",
-               .data = &atmel_sama5_nc_caps,
-       },
-       /* Support for old/deprecated bindings: */
-       {
-               .compatible = "atmel,at91rm9200-nand",
-               .data = &atmel_rm9200_nand_caps,
-       },
-       {
-               .compatible = "atmel,sama5d4-nand",
-               .data = &atmel_rm9200_nand_caps,
-       },
-       {
-               .compatible = "atmel,sama5d2-nand",
-               .data = &atmel_rm9200_nand_caps,
-       },
-       { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, atmel_nand_controller_of_ids);
-
-static int atmel_nand_controller_probe(struct platform_device *pdev)
-{
-       const struct atmel_nand_controller_caps *caps;
-
-       if (pdev->id_entry)
-               caps = (void *)pdev->id_entry->driver_data;
-       else
-               caps = of_device_get_match_data(&pdev->dev);
-
-       if (!caps) {
-               dev_err(&pdev->dev, "Could not retrieve NFC caps\n");
-               return -EINVAL;
-       }
-
-       if (caps->legacy_of_bindings) {
-               u32 ale_offs = 21;
-
-               /*
-                * If we are parsing legacy DT props and the DT contains a
-                * valid NFC node, forward the request to the sama5 logic.
-                */
-               if (of_find_compatible_node(pdev->dev.of_node, NULL,
-                                           "atmel,sama5d3-nfc"))
-                       caps = &atmel_sama5_nand_caps;
-
-               /*
-                * Even if the compatible says we are dealing with an
-                * at91rm9200 controller, the atmel,nand-has-dma specify that
-                * this controller supports DMA, which means we are in fact
-                * dealing with an at91sam9g45+ controller.
-                */
-               if (!caps->has_dma &&
-                   of_property_read_bool(pdev->dev.of_node,
-                                         "atmel,nand-has-dma"))
-                       caps = &atmel_sam9g45_nand_caps;
-
-               /*
-                * All SoCs except the at91sam9261 are assigning ALE to A21 and
-                * CLE to A22. If atmel,nand-addr-offset != 21 this means we're
-                * actually dealing with an at91sam9261 controller.
-                */
-               of_property_read_u32(pdev->dev.of_node,
-                                    "atmel,nand-addr-offset", &ale_offs);
-               if (ale_offs != 21)
-                       caps = &atmel_sam9261_nand_caps;
-       }
-
-       return caps->ops->probe(pdev, caps);
-}
-
-static int atmel_nand_controller_remove(struct platform_device *pdev)
-{
-       struct atmel_nand_controller *nc = platform_get_drvdata(pdev);
-
-       return nc->caps->ops->remove(nc);
-}
-
-static __maybe_unused int atmel_nand_controller_resume(struct device *dev)
-{
-       struct atmel_nand_controller *nc = dev_get_drvdata(dev);
-       struct atmel_nand *nand;
-
-       if (nc->pmecc)
-               atmel_pmecc_reset(nc->pmecc);
-
-       list_for_each_entry(nand, &nc->chips, node) {
-               int i;
-
-               for (i = 0; i < nand->numcs; i++)
-                       nand_reset(&nand->base, i);
-       }
-
-       return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(atmel_nand_controller_pm_ops, NULL,
-                        atmel_nand_controller_resume);
-
-static struct platform_driver atmel_nand_controller_driver = {
-       .driver = {
-               .name = "atmel-nand-controller",
-               .of_match_table = of_match_ptr(atmel_nand_controller_of_ids),
-               .pm = &atmel_nand_controller_pm_ops,
-       },
-       .probe = atmel_nand_controller_probe,
-       .remove = atmel_nand_controller_remove,
-};
-module_platform_driver(atmel_nand_controller_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
-MODULE_DESCRIPTION("NAND Flash Controller driver for Atmel SoCs");
-MODULE_ALIAS("platform:atmel-nand-controller");
diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/atmel/pmecc.c
deleted file mode 100644 (file)
index fcbe4fd..0000000
+++ /dev/null
@@ -1,1012 +0,0 @@
-/*
- * Copyright 2017 ATMEL
- * Copyright 2017 Free Electrons
- *
- * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
- *
- * Derived from the atmel_nand.c driver which contained the following
- * copyrights:
- *
- *   Copyright 2003 Rick Bronson
- *
- *   Derived from drivers/mtd/nand/autcpu12.c
- *     Copyright 2001 Thomas Gleixner (gleixner@autronix.de)
- *
- *   Derived from drivers/mtd/spia.c
- *     Copyright 2000 Steven J. Hill (sjhill@cotw.com)
- *
- *   Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
- *     Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright 2007
- *
- *   Derived from Das U-Boot source code
- *     (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
- *      Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
- *
- *   Add Programmable Multibit ECC support for various AT91 SoC
- *     Copyright 2012 ATMEL, Hong Xu
- *
- *   Add Nand Flash Controller support for SAMA5 SoC
- *     Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * The PMECC is an hardware assisted BCH engine, which means part of the
- * ECC algorithm is left to the software. The hardware/software repartition
- * is explained in the "PMECC Controller Functional Description" chapter in
- * Atmel datasheets, and some of the functions in this file are directly
- * implementing the algorithms described in the "Software Implementation"
- * sub-section.
- *
- * TODO: it seems that the software BCH implementation in lib/bch.c is already
- * providing some of the logic we are implementing here. It would be smart
- * to expose the needed lib/bch.c helpers/functions and re-use them here.
- */
-
-#include <linux/genalloc.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include "pmecc.h"
-
-/* Galois field dimension */
-#define PMECC_GF_DIMENSION_13                  13
-#define PMECC_GF_DIMENSION_14                  14
-
-/* Primitive Polynomial used by PMECC */
-#define PMECC_GF_13_PRIMITIVE_POLY             0x201b
-#define PMECC_GF_14_PRIMITIVE_POLY             0x4443
-
-#define PMECC_LOOKUP_TABLE_SIZE_512            0x2000
-#define PMECC_LOOKUP_TABLE_SIZE_1024           0x4000
-
-/* Time out value for reading PMECC status register */
-#define PMECC_MAX_TIMEOUT_MS                   100
-
-/* PMECC Register Definitions */
-#define ATMEL_PMECC_CFG                                0x0
-#define PMECC_CFG_BCH_STRENGTH(x)              (x)
-#define PMECC_CFG_BCH_STRENGTH_MASK            GENMASK(2, 0)
-#define PMECC_CFG_SECTOR512                    (0 << 4)
-#define PMECC_CFG_SECTOR1024                   (1 << 4)
-#define PMECC_CFG_NSECTORS(x)                  ((fls(x) - 1) << 8)
-#define PMECC_CFG_READ_OP                      (0 << 12)
-#define PMECC_CFG_WRITE_OP                     (1 << 12)
-#define PMECC_CFG_SPARE_ENABLE                 BIT(16)
-#define PMECC_CFG_AUTO_ENABLE                  BIT(20)
-
-#define ATMEL_PMECC_SAREA                      0x4
-#define ATMEL_PMECC_SADDR                      0x8
-#define ATMEL_PMECC_EADDR                      0xc
-
-#define ATMEL_PMECC_CLK                                0x10
-#define PMECC_CLK_133MHZ                       (2 << 0)
-
-#define ATMEL_PMECC_CTRL                       0x14
-#define PMECC_CTRL_RST                         BIT(0)
-#define PMECC_CTRL_DATA                                BIT(1)
-#define PMECC_CTRL_USER                                BIT(2)
-#define PMECC_CTRL_ENABLE                      BIT(4)
-#define PMECC_CTRL_DISABLE                     BIT(5)
-
-#define ATMEL_PMECC_SR                         0x18
-#define PMECC_SR_BUSY                          BIT(0)
-#define PMECC_SR_ENABLE                                BIT(4)
-
-#define ATMEL_PMECC_IER                                0x1c
-#define ATMEL_PMECC_IDR                                0x20
-#define ATMEL_PMECC_IMR                                0x24
-#define ATMEL_PMECC_ISR                                0x28
-#define PMECC_ERROR_INT                                BIT(0)
-
-#define ATMEL_PMECC_ECC(sector, n)             \
-       ((((sector) + 1) * 0x40) + (n))
-
-#define ATMEL_PMECC_REM(sector, n)             \
-       ((((sector) + 1) * 0x40) + ((n) * 4) + 0x200)
-
-/* PMERRLOC Register Definitions */
-#define ATMEL_PMERRLOC_ELCFG                   0x0
-#define PMERRLOC_ELCFG_SECTOR_512              (0 << 0)
-#define PMERRLOC_ELCFG_SECTOR_1024             (1 << 0)
-#define PMERRLOC_ELCFG_NUM_ERRORS(n)           ((n) << 16)
-
-#define ATMEL_PMERRLOC_ELPRIM                  0x4
-#define ATMEL_PMERRLOC_ELEN                    0x8
-#define ATMEL_PMERRLOC_ELDIS                   0xc
-#define PMERRLOC_DISABLE                       BIT(0)
-
-#define ATMEL_PMERRLOC_ELSR                    0x10
-#define PMERRLOC_ELSR_BUSY                     BIT(0)
-
-#define ATMEL_PMERRLOC_ELIER                   0x14
-#define ATMEL_PMERRLOC_ELIDR                   0x18
-#define ATMEL_PMERRLOC_ELIMR                   0x1c
-#define ATMEL_PMERRLOC_ELISR                   0x20
-#define PMERRLOC_ERR_NUM_MASK                  GENMASK(12, 8)
-#define PMERRLOC_CALC_DONE                     BIT(0)
-
-#define ATMEL_PMERRLOC_SIGMA(x)                        (((x) * 0x4) + 0x28)
-
-#define ATMEL_PMERRLOC_EL(offs, x)             (((x) * 0x4) + (offs))
-
-struct atmel_pmecc_gf_tables {
-       u16 *alpha_to;
-       u16 *index_of;
-};
-
-struct atmel_pmecc_caps {
-       const int *strengths;
-       int nstrengths;
-       int el_offset;
-       bool correct_erased_chunks;
-};
-
-struct atmel_pmecc {
-       struct device *dev;
-       const struct atmel_pmecc_caps *caps;
-
-       struct {
-               void __iomem *base;
-               void __iomem *errloc;
-       } regs;
-
-       struct mutex lock;
-};
-
-struct atmel_pmecc_user_conf_cache {
-       u32 cfg;
-       u32 sarea;
-       u32 saddr;
-       u32 eaddr;
-};
-
-struct atmel_pmecc_user {
-       struct atmel_pmecc_user_conf_cache cache;
-       struct atmel_pmecc *pmecc;
-       const struct atmel_pmecc_gf_tables *gf_tables;
-       int eccbytes;
-       s16 *partial_syn;
-       s16 *si;
-       s16 *lmu;
-       s16 *smu;
-       s32 *mu;
-       s32 *dmu;
-       s32 *delta;
-       u32 isr;
-};
-
-static DEFINE_MUTEX(pmecc_gf_tables_lock);
-static const struct atmel_pmecc_gf_tables *pmecc_gf_tables_512;
-static const struct atmel_pmecc_gf_tables *pmecc_gf_tables_1024;
-
-static inline int deg(unsigned int poly)
-{
-       /* polynomial degree is the most-significant bit index */
-       return fls(poly) - 1;
-}
-
-static int atmel_pmecc_build_gf_tables(int mm, unsigned int poly,
-                                      struct atmel_pmecc_gf_tables *gf_tables)
-{
-       unsigned int i, x = 1;
-       const unsigned int k = BIT(deg(poly));
-       unsigned int nn = BIT(mm) - 1;
-
-       /* primitive polynomial must be of degree m */
-       if (k != (1u << mm))
-               return -EINVAL;
-
-       for (i = 0; i < nn; i++) {
-               gf_tables->alpha_to[i] = x;
-               gf_tables->index_of[x] = i;
-               if (i && (x == 1))
-                       /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
-                       return -EINVAL;
-               x <<= 1;
-               if (x & k)
-                       x ^= poly;
-       }
-       gf_tables->alpha_to[nn] = 1;
-       gf_tables->index_of[0] = 0;
-
-       return 0;
-}
-
-static const struct atmel_pmecc_gf_tables *
-atmel_pmecc_create_gf_tables(const struct atmel_pmecc_user_req *req)
-{
-       struct atmel_pmecc_gf_tables *gf_tables;
-       unsigned int poly, degree, table_size;
-       int ret;
-
-       if (req->ecc.sectorsize == 512) {
-               degree = PMECC_GF_DIMENSION_13;
-               poly = PMECC_GF_13_PRIMITIVE_POLY;
-               table_size = PMECC_LOOKUP_TABLE_SIZE_512;
-       } else {
-               degree = PMECC_GF_DIMENSION_14;
-               poly = PMECC_GF_14_PRIMITIVE_POLY;
-               table_size = PMECC_LOOKUP_TABLE_SIZE_1024;
-       }
-
-       gf_tables = kzalloc(sizeof(*gf_tables) +
-                           (2 * table_size * sizeof(u16)),
-                           GFP_KERNEL);
-       if (!gf_tables)
-               return ERR_PTR(-ENOMEM);
-
-       gf_tables->alpha_to = (void *)(gf_tables + 1);
-       gf_tables->index_of = gf_tables->alpha_to + table_size;
-
-       ret = atmel_pmecc_build_gf_tables(degree, poly, gf_tables);
-       if (ret) {
-               kfree(gf_tables);
-               return ERR_PTR(ret);
-       }
-
-       return gf_tables;
-}
-
-static const struct atmel_pmecc_gf_tables *
-atmel_pmecc_get_gf_tables(const struct atmel_pmecc_user_req *req)
-{
-       const struct atmel_pmecc_gf_tables **gf_tables, *ret;
-
-       mutex_lock(&pmecc_gf_tables_lock);
-       if (req->ecc.sectorsize == 512)
-               gf_tables = &pmecc_gf_tables_512;
-       else
-               gf_tables = &pmecc_gf_tables_1024;
-
-       ret = *gf_tables;
-
-       if (!ret) {
-               ret = atmel_pmecc_create_gf_tables(req);
-               if (!IS_ERR(ret))
-                       *gf_tables = ret;
-       }
-       mutex_unlock(&pmecc_gf_tables_lock);
-
-       return ret;
-}
-
-static int atmel_pmecc_prepare_user_req(struct atmel_pmecc *pmecc,
-                                       struct atmel_pmecc_user_req *req)
-{
-       int i, max_eccbytes, eccbytes = 0, eccstrength = 0;
-
-       if (req->pagesize <= 0 || req->oobsize <= 0 || req->ecc.bytes <= 0)
-               return -EINVAL;
-
-       if (req->ecc.ooboffset >= 0 &&
-           req->ecc.ooboffset + req->ecc.bytes > req->oobsize)
-               return -EINVAL;
-
-       if (req->ecc.sectorsize == ATMEL_PMECC_SECTOR_SIZE_AUTO) {
-               if (req->ecc.strength != ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH)
-                       return -EINVAL;
-
-               if (req->pagesize > 512)
-                       req->ecc.sectorsize = 1024;
-               else
-                       req->ecc.sectorsize = 512;
-       }
-
-       if (req->ecc.sectorsize != 512 && req->ecc.sectorsize != 1024)
-               return -EINVAL;
-
-       if (req->pagesize % req->ecc.sectorsize)
-               return -EINVAL;
-
-       req->ecc.nsectors = req->pagesize / req->ecc.sectorsize;
-
-       max_eccbytes = req->ecc.bytes;
-
-       for (i = 0; i < pmecc->caps->nstrengths; i++) {
-               int nbytes, strength = pmecc->caps->strengths[i];
-
-               if (req->ecc.strength != ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH &&
-                   strength < req->ecc.strength)
-                       continue;
-
-               nbytes = DIV_ROUND_UP(strength * fls(8 * req->ecc.sectorsize),
-                                     8);
-               nbytes *= req->ecc.nsectors;
-
-               if (nbytes > max_eccbytes)
-                       break;
-
-               eccstrength = strength;
-               eccbytes = nbytes;
-
-               if (req->ecc.strength != ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH)
-                       break;
-       }
-
-       if (!eccstrength)
-               return -EINVAL;
-
-       req->ecc.bytes = eccbytes;
-       req->ecc.strength = eccstrength;
-
-       if (req->ecc.ooboffset < 0)
-               req->ecc.ooboffset = req->oobsize - eccbytes;
-
-       return 0;
-}
-
-struct atmel_pmecc_user *
-atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
-                       struct atmel_pmecc_user_req *req)
-{
-       struct atmel_pmecc_user *user;
-       const struct atmel_pmecc_gf_tables *gf_tables;
-       int strength, size, ret;
-
-       ret = atmel_pmecc_prepare_user_req(pmecc, req);
-       if (ret)
-               return ERR_PTR(ret);
-
-       size = sizeof(*user);
-       size = ALIGN(size, sizeof(u16));
-       /* Reserve space for partial_syn, si and smu */
-       size += ((2 * req->ecc.strength) + 1) * sizeof(u16) *
-               (2 + req->ecc.strength + 2);
-       /* Reserve space for lmu. */
-       size += (req->ecc.strength + 1) * sizeof(u16);
-       /* Reserve space for mu, dmu and delta. */
-       size = ALIGN(size, sizeof(s32));
-       size += (req->ecc.strength + 1) * sizeof(s32) * 3;
-
-       user = kzalloc(size, GFP_KERNEL);
-       if (!user)
-               return ERR_PTR(-ENOMEM);
-
-       user->pmecc = pmecc;
-
-       user->partial_syn = (s16 *)PTR_ALIGN(user + 1, sizeof(u16));
-       user->si = user->partial_syn + ((2 * req->ecc.strength) + 1);
-       user->lmu = user->si + ((2 * req->ecc.strength) + 1);
-       user->smu = user->lmu + (req->ecc.strength + 1);
-       user->mu = (s32 *)PTR_ALIGN(user->smu +
-                                   (((2 * req->ecc.strength) + 1) *
-                                    (req->ecc.strength + 2)),
-                                   sizeof(s32));
-       user->dmu = user->mu + req->ecc.strength + 1;
-       user->delta = user->dmu + req->ecc.strength + 1;
-
-       gf_tables = atmel_pmecc_get_gf_tables(req);
-       if (IS_ERR(gf_tables)) {
-               kfree(user);
-               return ERR_CAST(gf_tables);
-       }
-
-       user->gf_tables = gf_tables;
-
-       user->eccbytes = req->ecc.bytes / req->ecc.nsectors;
-
-       for (strength = 0; strength < pmecc->caps->nstrengths; strength++) {
-               if (pmecc->caps->strengths[strength] == req->ecc.strength)
-                       break;
-       }
-
-       user->cache.cfg = PMECC_CFG_BCH_STRENGTH(strength) |
-                         PMECC_CFG_NSECTORS(req->ecc.nsectors);
-
-       if (req->ecc.sectorsize == 1024)
-               user->cache.cfg |= PMECC_CFG_SECTOR1024;
-
-       user->cache.sarea = req->oobsize - 1;
-       user->cache.saddr = req->ecc.ooboffset;
-       user->cache.eaddr = req->ecc.ooboffset + req->ecc.bytes - 1;
-
-       return user;
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_create_user);
-
-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user)
-{
-       kfree(user);
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_destroy_user);
-
-static int get_strength(struct atmel_pmecc_user *user)
-{
-       const int *strengths = user->pmecc->caps->strengths;
-
-       return strengths[user->cache.cfg & PMECC_CFG_BCH_STRENGTH_MASK];
-}
-
-static int get_sectorsize(struct atmel_pmecc_user *user)
-{
-       return user->cache.cfg & PMECC_LOOKUP_TABLE_SIZE_1024 ? 1024 : 512;
-}
-
-static void atmel_pmecc_gen_syndrome(struct atmel_pmecc_user *user, int sector)
-{
-       int strength = get_strength(user);
-       u32 value;
-       int i;
-
-       /* Fill odd syndromes */
-       for (i = 0; i < strength; i++) {
-               value = readl_relaxed(user->pmecc->regs.base +
-                                     ATMEL_PMECC_REM(sector, i / 2));
-               if (i & 1)
-                       value >>= 16;
-
-               user->partial_syn[(2 * i) + 1] = value;
-       }
-}
-
-static void atmel_pmecc_substitute(struct atmel_pmecc_user *user)
-{
-       int degree = get_sectorsize(user) == 512 ? 13 : 14;
-       int cw_len = BIT(degree) - 1;
-       int strength = get_strength(user);
-       s16 *alpha_to = user->gf_tables->alpha_to;
-       s16 *index_of = user->gf_tables->index_of;
-       s16 *partial_syn = user->partial_syn;
-       s16 *si;
-       int i, j;
-
-       /*
-        * si[] is a table that holds the current syndrome value,
-        * an element of that table belongs to the field
-        */
-       si = user->si;
-
-       memset(&si[1], 0, sizeof(s16) * ((2 * strength) - 1));
-
-       /* Computation 2t syndromes based on S(x) */
-       /* Odd syndromes */
-       for (i = 1; i < 2 * strength; i += 2) {
-               for (j = 0; j < degree; j++) {
-                       if (partial_syn[i] & BIT(j))
-                               si[i] = alpha_to[i * j] ^ si[i];
-               }
-       }
-       /* Even syndrome = (Odd syndrome) ** 2 */
-       for (i = 2, j = 1; j <= strength; i = ++j << 1) {
-               if (si[j] == 0) {
-                       si[i] = 0;
-               } else {
-                       s16 tmp;
-
-                       tmp = index_of[si[j]];
-                       tmp = (tmp * 2) % cw_len;
-                       si[i] = alpha_to[tmp];
-               }
-       }
-}
-
-static void atmel_pmecc_get_sigma(struct atmel_pmecc_user *user)
-{
-       s16 *lmu = user->lmu;
-       s16 *si = user->si;
-       s32 *mu = user->mu;
-       s32 *dmu = user->dmu;
-       s32 *delta = user->delta;
-       int degree = get_sectorsize(user) == 512 ? 13 : 14;
-       int cw_len = BIT(degree) - 1;
-       int strength = get_strength(user);
-       int num = 2 * strength + 1;
-       s16 *index_of = user->gf_tables->index_of;
-       s16 *alpha_to = user->gf_tables->alpha_to;
-       int i, j, k;
-       u32 dmu_0_count, tmp;
-       s16 *smu = user->smu;
-
-       /* index of largest delta */
-       int ro;
-       int largest;
-       int diff;
-
-       dmu_0_count = 0;
-
-       /* First Row */
-
-       /* Mu */
-       mu[0] = -1;
-
-       memset(smu, 0, sizeof(s16) * num);
-       smu[0] = 1;
-
-       /* discrepancy set to 1 */
-       dmu[0] = 1;
-       /* polynom order set to 0 */
-       lmu[0] = 0;
-       delta[0] = (mu[0] * 2 - lmu[0]) >> 1;
-
-       /* Second Row */
-
-       /* Mu */
-       mu[1] = 0;
-       /* Sigma(x) set to 1 */
-       memset(&smu[num], 0, sizeof(s16) * num);
-       smu[num] = 1;
-
-       /* discrepancy set to S1 */
-       dmu[1] = si[1];
-
-       /* polynom order set to 0 */
-       lmu[1] = 0;
-
-       delta[1] = (mu[1] * 2 - lmu[1]) >> 1;
-
-       /* Init the Sigma(x) last row */
-       memset(&smu[(strength + 1) * num], 0, sizeof(s16) * num);
-
-       for (i = 1; i <= strength; i++) {
-               mu[i + 1] = i << 1;
-               /* Begin Computing Sigma (Mu+1) and L(mu) */
-               /* check if discrepancy is set to 0 */
-               if (dmu[i] == 0) {
-                       dmu_0_count++;
-
-                       tmp = ((strength - (lmu[i] >> 1) - 1) / 2);
-                       if ((strength - (lmu[i] >> 1) - 1) & 0x1)
-                               tmp += 2;
-                       else
-                               tmp += 1;
-
-                       if (dmu_0_count == tmp) {
-                               for (j = 0; j <= (lmu[i] >> 1) + 1; j++)
-                                       smu[(strength + 1) * num + j] =
-                                                       smu[i * num + j];
-
-                               lmu[strength + 1] = lmu[i];
-                               return;
-                       }
-
-                       /* copy polynom */
-                       for (j = 0; j <= lmu[i] >> 1; j++)
-                               smu[(i + 1) * num + j] = smu[i * num + j];
-
-                       /* copy previous polynom order to the next */
-                       lmu[i + 1] = lmu[i];
-               } else {
-                       ro = 0;
-                       largest = -1;
-                       /* find largest delta with dmu != 0 */
-                       for (j = 0; j < i; j++) {
-                               if ((dmu[j]) && (delta[j] > largest)) {
-                                       largest = delta[j];
-                                       ro = j;
-                               }
-                       }
-
-                       /* compute difference */
-                       diff = (mu[i] - mu[ro]);
-
-                       /* Compute degree of the new smu polynomial */
-                       if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff))
-                               lmu[i + 1] = lmu[i];
-                       else
-                               lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2;
-
-                       /* Init smu[i+1] with 0 */
-                       for (k = 0; k < num; k++)
-                               smu[(i + 1) * num + k] = 0;
-
-                       /* Compute smu[i+1] */
-                       for (k = 0; k <= lmu[ro] >> 1; k++) {
-                               s16 a, b, c;
-
-                               if (!(smu[ro * num + k] && dmu[i]))
-                                       continue;
-
-                               a = index_of[dmu[i]];
-                               b = index_of[dmu[ro]];
-                               c = index_of[smu[ro * num + k]];
-                               tmp = a + (cw_len - b) + c;
-                               a = alpha_to[tmp % cw_len];
-                               smu[(i + 1) * num + (k + diff)] = a;
-                       }
-
-                       for (k = 0; k <= lmu[i] >> 1; k++)
-                               smu[(i + 1) * num + k] ^= smu[i * num + k];
-               }
-
-               /* End Computing Sigma (Mu+1) and L(mu) */
-               /* In either case compute delta */
-               delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1;
-
-               /* Do not compute discrepancy for the last iteration */
-               if (i >= strength)
-                       continue;
-
-               for (k = 0; k <= (lmu[i + 1] >> 1); k++) {
-                       tmp = 2 * (i - 1);
-                       if (k == 0) {
-                               dmu[i + 1] = si[tmp + 3];
-                       } else if (smu[(i + 1) * num + k] && si[tmp + 3 - k]) {
-                               s16 a, b, c;
-
-                               a = index_of[smu[(i + 1) * num + k]];
-                               b = si[2 * (i - 1) + 3 - k];
-                               c = index_of[b];
-                               tmp = a + c;
-                               tmp %= cw_len;
-                               dmu[i + 1] = alpha_to[tmp] ^ dmu[i + 1];
-                       }
-               }
-       }
-}
-
-static int atmel_pmecc_err_location(struct atmel_pmecc_user *user)
-{
-       int sector_size = get_sectorsize(user);
-       int degree = sector_size == 512 ? 13 : 14;
-       struct atmel_pmecc *pmecc = user->pmecc;
-       int strength = get_strength(user);
-       int ret, roots_nbr, i, err_nbr = 0;
-       int num = (2 * strength) + 1;
-       s16 *smu = user->smu;
-       u32 val;
-
-       writel(PMERRLOC_DISABLE, pmecc->regs.errloc + ATMEL_PMERRLOC_ELDIS);
-
-       for (i = 0; i <= user->lmu[strength + 1] >> 1; i++) {
-               writel_relaxed(smu[(strength + 1) * num + i],
-                              pmecc->regs.errloc + ATMEL_PMERRLOC_SIGMA(i));
-