Merge tag 'nand/for-4.17' of git://git.infradead.org/linux-mtd into mtd/next
authorBoris Brezillon <boris.brezillon@bootlin.com>
Wed, 4 Apr 2018 20:11:36 +0000 (22:11 +0200)
committerBoris Brezillon <boris.brezillon@bootlin.com>
Wed, 4 Apr 2018 20:11:36 +0000 (22:11 +0200)
Core changes:
* Prepare arrival of the SPI NAND subsystem by implementing a generic
  (interface-agnostic) layer to ease manipulation of NAND devices
* Move onenand code base to the drivers/mtd/nand/ dir
* Rework timing mode selection
* Provide a generic way for NAND chip drivers to flag a specific
  GET/SET FEATURE operation as supported/unsupported
* Stop embedding ONFI/JEDEC param page in nand_chip

Driver changes:
* Rework/cleanup of the mxc driver
* Various cleanups in the vf610 driver
* Migrate the fsmc and vf610 to ->exec_op()
* Get rid of the pxa driver (replaced by marvell_nand)
* Support ->setup_data_interface() in the GPMI driver
* Fix probe error path in several drivers
* Remove support for unused hw_syndrome mode in sunxi_nand
* Various minor improvements

232 files changed:
.mailmap
Documentation/arm/Samsung-S3C24XX/S3C2412.txt
Documentation/devicetree/bindings/mtd/marvell-nand.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/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/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/sm_ftl.c
drivers/staging/mt29f_spinand/mt29f_spinand.c
include/linux/mtd/bbm.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/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 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).
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 7892db9a9494cb0d116714fd4c587d02c7d88fc3..fc3427d11d75a62a35101414932ca0fd6ce181c8 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,7 +9034,7 @@ 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>
 L:     linux-mtd@lists.infradead.org
@@ -9135,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
@@ -9451,7 +9451,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/
@@ -10205,7 +10205,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
@@ -11326,12 +11326,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
@@ -11814,8 +11808,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>
@@ -14633,7 +14627,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 e6b8c59f2c0da7c0f5f8be9fc609e8f96b8b2140..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
-       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));
-               err_nbr++;
-       }
-
-       val = (err_nbr - 1) << 16;
-       if (sector_size == 1024)
-               val |= 1;
-
-       writel(val, pmecc->regs.errloc + ATMEL_PMERRLOC_ELCFG);
-       writel((sector_size * 8) + (degree * strength),
-              pmecc->regs.errloc + ATMEL_PMERRLOC_ELEN);
-
-       ret = readl_relaxed_poll_timeout(pmecc->regs.errloc +
-                                        ATMEL_PMERRLOC_ELISR,
-                                        val, val & PMERRLOC_CALC_DONE, 0,
-                                        PMECC_MAX_TIMEOUT_MS * 1000);
-       if (ret) {
-               dev_err(pmecc->dev,
-                       "PMECC: Timeout to calculate error location.\n");
-               return ret;
-       }
-
-       roots_nbr = (val & PMERRLOC_ERR_NUM_MASK) >> 8;
-       /* Number of roots == degree of smu hence <= cap */
-       if (roots_nbr == user->lmu[strength + 1] >> 1)
-               return err_nbr - 1;
-
-       /*
-        * Number of roots does not match the degree of smu
-        * unable to correct error.
-        */
-       return -EBADMSG;
-}
-
-int atmel_pmecc_correct_sector(struct atmel_pmecc_user *user, int sector,
-                              void *data, void *ecc)
-{
-       struct atmel_pmecc *pmecc = user->pmecc;
-       int sectorsize = get_sectorsize(user);
-       int eccbytes = user->eccbytes;
-       int i, nerrors;
-
-       if (!(user->isr & BIT(sector)))
-               return 0;
-
-       atmel_pmecc_gen_syndrome(user, sector);
-       atmel_pmecc_substitute(user);
-       atmel_pmecc_get_sigma(user);
-
-       nerrors = atmel_pmecc_err_location(user);
-       if (nerrors < 0)
-               return nerrors;
-
-       for (i = 0; i < nerrors; i++) {
-               const char *area;
-               int byte, bit;
-               u32 errpos;
-               u8 *ptr;
-
-               errpos = readl_relaxed(pmecc->regs.errloc +
-                               ATMEL_PMERRLOC_EL(pmecc->caps->el_offset, i));
-               errpos--;
-
-               byte = errpos / 8;
-               bit = errpos % 8;
-
-               if (byte < sectorsize) {
-                       ptr = data + byte;
-                       area = "data";
-               } else if (byte < sectorsize + eccbytes) {
-                       ptr = ecc + byte - sectorsize;
-                       area = "ECC";
-               } else {
-                       dev_dbg(pmecc->dev,
-                               "Invalid errpos value (%d, max is %d)\n",
-                               errpos, (sectorsize + eccbytes) * 8);
-                       return -EINVAL;
-               }
-
-               dev_dbg(pmecc->dev,
-                       "Bit flip in %s area, byte %d: 0x%02x -> 0x%02x\n",
-                       area, byte, *ptr, (unsigned int)(*ptr ^ BIT(bit)));
-
-               *ptr ^= BIT(bit);
-       }
-
-       return nerrors;
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_correct_sector);
-
-bool atmel_pmecc_correct_erased_chunks(struct atmel_pmecc_user *user)
-{
-       return user->pmecc->caps->correct_erased_chunks;
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_correct_erased_chunks);
-
-void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user,
-                                       int sector, void *ecc)
-{
-       struct atmel_pmecc *pmecc = user->pmecc;
-       u8 *ptr = ecc;
-       int i;
-
-       for (i = 0; i < user->eccbytes; i++)
-               ptr[i] = readb_relaxed(pmecc->regs.base +
-                                      ATMEL_PMECC_ECC(sector, i));
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_get_generated_eccbytes);
-
-void atmel_pmecc_reset(struct atmel_pmecc *pmecc)
-{
-       writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
-       writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_reset);
-
-int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op)
-{
-       struct atmel_pmecc *pmecc = user->pmecc;
-       u32 cfg;
-
-       if (op != NAND_ECC_READ && op != NAND_ECC_WRITE) {
-               dev_err(pmecc->dev, "Bad ECC operation!");
-               return -EINVAL;
-       }
-
-       mutex_lock(&user->pmecc->lock);
-
-       cfg = user->cache.cfg;
-       if (op == NAND_ECC_WRITE)
-               cfg |= PMECC_CFG_WRITE_OP;
-       else
-               cfg |= PMECC_CFG_AUTO_ENABLE;
-
-       writel(cfg, pmecc->regs.base + ATMEL_PMECC_CFG);
-       writel(user->cache.sarea, pmecc->regs.base + ATMEL_PMECC_SAREA);
-       writel(user->cache.saddr, pmecc->regs.base + ATMEL_PMECC_SADDR);
-       writel(user->cache.eaddr, pmecc->regs.base + ATMEL_PMECC_EADDR);
-
-       writel(PMECC_CTRL_ENABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
-       writel(PMECC_CTRL_DATA, pmecc->regs.base + ATMEL_PMECC_CTRL);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_enable);
-
-void atmel_pmecc_disable(struct atmel_pmecc_user *user)
-{
-       atmel_pmecc_reset(user->pmecc);
-       mutex_unlock(&user->pmecc->lock);
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_disable);
-
-int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user)
-{
-       struct atmel_pmecc *pmecc = user->pmecc;
-       u32 status;
-       int ret;
-
-       ret = readl_relaxed_poll_timeout(pmecc->regs.base +
-                                        ATMEL_PMECC_SR,
-                                        status, !(status & PMECC_SR_BUSY), 0,
-                                        PMECC_MAX_TIMEOUT_MS * 1000);
-       if (ret) {
-               dev_err(pmecc->dev,
-                       "Timeout while waiting for PMECC ready.\n");
-               return ret;
-       }
-
-       user->isr = readl_relaxed(pmecc->regs.base + ATMEL_PMECC_ISR);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_wait_rdy);
-
-static struct atmel_pmecc *atmel_pmecc_create(struct platform_device *pdev,
-                                       const struct atmel_pmecc_caps *caps,
-                                       int pmecc_res_idx, int errloc_res_idx)
-{
-       struct device *dev = &pdev->dev;
-       struct atmel_pmecc *pmecc;
-       struct resource *res;
-
-       pmecc = devm_kzalloc(dev, sizeof(*pmecc), GFP_KERNEL);
-       if (!pmecc)
-               return ERR_PTR(-ENOMEM);
-
-       pmecc->caps = caps;
-       pmecc->dev = dev;
-       mutex_init(&pmecc->lock);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, pmecc_res_idx);
-       pmecc->regs.base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(pmecc->regs.base))
-               return ERR_CAST(pmecc->regs.base);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, errloc_res_idx);
-       pmecc->regs.errloc = devm_ioremap_resource(dev, res);
-       if (IS_ERR(pmecc->regs.errloc))
-               return ERR_CAST(pmecc->regs.errloc);
-
-       /* Disable all interrupts before registering the PMECC handler. */
-       writel(0xffffffff, pmecc->regs.base + ATMEL_PMECC_IDR);
-       atmel_pmecc_reset(pmecc);
-
-       return pmecc;
-}
-
-static void devm_atmel_pmecc_put(struct device *dev, void *res)
-{
-       struct atmel_pmecc **pmecc = res;
-
-       put_device((*pmecc)->dev);
-}
-
-static struct atmel_pmecc *atmel_pmecc_get_by_node(struct device *userdev,
-                                                  struct device_node *np)
-{
-       struct platform_device *pdev;
-       struct atmel_pmecc *pmecc, **ptr;
-
-       pdev = of_find_device_by_node(np);
-       if (!pdev || !platform_get_drvdata(pdev))
-               return ERR_PTR(-EPROBE_DEFER);
-
-       ptr = devres_alloc(devm_atmel_pmecc_put, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
-
-       get_device(&pdev->dev);
-       pmecc = platform_get_drvdata(pdev);
-
-       *ptr = pmecc;
-
-       devres_add(userdev, ptr);
-
-       return pmecc;
-}
-
-static const int atmel_pmecc_strengths[] = { 2, 4, 8, 12, 24, 32 };
-
-static struct atmel_pmecc_caps at91sam9g45_caps = {
-       .strengths = atmel_pmecc_strengths,
-       .nstrengths = 5,
-       .el_offset = 0x8c,
-};
-
-static struct atmel_pmecc_caps sama5d4_caps = {
-       .strengths = atmel_pmecc_strengths,
-       .nstrengths = 5,
-       .el_offset = 0x8c,
-       .correct_erased_chunks = true,
-};
-
-static struct atmel_pmecc_caps sama5d2_caps = {
-       .strengths = atmel_pmecc_strengths,
-       .nstrengths = 6,
-       .el_offset = 0xac,
-       .correct_erased_chunks = true,
-};
-
-static const struct of_device_id atmel_pmecc_legacy_match[] = {
-       { .compatible = "atmel,sama5d4-nand", &sama5d4_caps },
-       { .compatible = "atmel,sama5d2-nand", &sama5d2_caps },
-       { /* sentinel */ }
-};
-
-struct atmel_pmecc *devm_atmel_pmecc_get(struct device *userdev)
-{
-       struct atmel_pmecc *pmecc;
-       struct device_node *np;
-
-       if (!userdev)
-               return ERR_PTR(-EINVAL);
-
-       if (!userdev->of_node)
-               return NULL;
-
-       np = of_parse_phandle(userdev->of_node, "ecc-engine", 0);
-       if (np) {
-               pmecc = atmel_pmecc_get_by_node(userdev, np);
-               of_node_put(np);
-       } else {
-               /*
-                * Support old DT bindings: in this case the PMECC iomem
-                * resources are directly defined in the user pdev at position
-                * 1 and 2. Extract all relevant information from there.
-                */
-               struct platform_device *pdev = to_platform_device(userdev);
-               const struct atmel_pmecc_caps *caps;
-               const struct of_device_id *match;
-
-               /* No PMECC engine available. */
-               if (!of_property_read_bool(userdev->of_node,
-                                          "atmel,has-pmecc"))
-                       return NULL;
-
-               caps = &at91sam9g45_caps;
-
-               /* Find the caps associated to the NAND dev node. */
-               match = of_match_node(atmel_pmecc_legacy_match,
-                                     userdev->of_node);
-               if (match && match->data)
-                       caps = match->data;
-
-               pmecc = atmel_pmecc_create(pdev, caps, 1, 2);
-       }
-
-       return pmecc;
-}
-EXPORT_SYMBOL(devm_atmel_pmecc_get);
-
-static const struct of_device_id atmel_pmecc_match[] = {
-       { .compatible = "atmel,at91sam9g45-pmecc", &at91sam9g45_caps },
-       { .compatible = "atmel,sama5d4-pmecc", &sama5d4_caps },
-       { .compatible = "atmel,sama5d2-pmecc", &sama5d2_caps },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, atmel_pmecc_match);
-
-static int atmel_pmecc_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       const struct atmel_pmecc_caps *caps;
-       struct atmel_pmecc *pmecc;
-
-       caps = of_device_get_match_data(&pdev->dev);
-       if (!caps) {
-               dev_err(dev, "Invalid caps\n");
-               return -EINVAL;
-       }
-
-       pmecc = atmel_pmecc_create(pdev, caps, 0, 1);
-       if (IS_ERR(pmecc))
-               return PTR_ERR(pmecc);
-
-       platform_set_drvdata(pdev, pmecc);
-
-       return 0;
-}
-
-static struct platform_driver atmel_pmecc_driver = {
-       .driver = {
-               .name = "atmel-pmecc",
-               .of_match_table = of_match_ptr(atmel_pmecc_match),
-       },
-       .probe = atmel_pmecc_probe,
-};
-module_platform_driver(atmel_pmecc_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
-MODULE_DESCRIPTION("PMECC engine driver");
-MODULE_ALIAS("platform:atmel_pmecc");
diff --git a/drivers/mtd/nand/atmel/pmecc.h b/drivers/mtd/nand/atmel/pmecc.h
deleted file mode 100644 (file)
index 817e0dd..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Â© Copyright 2016 ATMEL
- * Â© Copyright 2016 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.
- *
- */
-
-#ifndef ATMEL_PMECC_H
-#define ATMEL_PMECC_H
-
-#define ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH      0
-#define ATMEL_PMECC_SECTOR_SIZE_AUTO           0
-#define ATMEL_PMECC_OOBOFFSET_AUTO             -1
-
-struct atmel_pmecc_user_req {
-       int pagesize;
-       int oobsize;
-       struct {
-               int strength;
-               int bytes;
-               int sectorsize;
-               int nsectors;
-               int ooboffset;
-       } ecc;
-};
-
-struct atmel_pmecc *devm_atmel_pmecc_get(struct device *dev);
-
-struct atmel_pmecc_user *
-atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
-                       struct atmel_pmecc_user_req *req);
-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user);
-
-void atmel_pmecc_reset(struct atmel_pmecc *pmecc);
-int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op);
-void atmel_pmecc_disable(struct atmel_pmecc_user *user);
-int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user);
-int atmel_pmecc_correct_sector(struct atmel_pmecc_user *user, int sector,
-                              void *data, void *ecc);
-bool atmel_pmecc_correct_erased_chunks(struct atmel_pmecc_user *user);
-void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user,
-                                       int sector, void *ecc);
-
-#endif /* ATMEL_PMECC_H */
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
deleted file mode 100644 (file)
index 8ab827e..0000000
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- *  drivers/mtd/nand/au1550nd.c
- *
- *  Copyright (C) 2004 Embedded Edge, LLC
- *
- * 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.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/mtd/partitions.h>
-#include <linux/platform_device.h>
-#include <asm/io.h>
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/au1550nd.h>
-
-
-struct au1550nd_ctx {
-       struct nand_chip chip;
-
-       int cs;
-       void __iomem *base;
-       void (*write_byte)(struct mtd_info *, u_char);
-};
-
-/**
- * au_read_byte -  read one byte from the chip
- * @mtd:       MTD device structure
- *
- * read function for 8bit buswidth
- */
-static u_char au_read_byte(struct mtd_info *mtd)
-{
-       struct nand_chip *this = mtd_to_nand(mtd);
-       u_char ret = readb(this->IO_ADDR_R);
-       wmb(); /* drain writebuffer */
-       return ret;
-}
-
-/**
- * au_write_byte -  write one byte to the chip
- * @mtd:       MTD device structure
- * @byte:      pointer to data byte to write
- *
- * write function for 8it buswidth
- */
-static void au_write_byte(struct mtd_info *mtd, u_char byte)
-{
-       struct nand_chip *this = mtd_to_nand(mtd);
-       writeb(byte, this->IO_ADDR_W);
-       wmb(); /* drain writebuffer */
-}
-
-/**
- * au_read_byte16 -  read one byte endianness aware from the chip
- * @mtd:       MTD device structure
- *
- * read function for 16bit buswidth with endianness conversion
- */
-static u_char au_read_byte16(struct mtd_info *mtd)
-{
-       struct nand_chip *this = mtd_to_nand(mtd);
-       u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
-       wmb(); /* drain writebuffer */
-       return ret;
-}
-
-/**
- * au_write_byte16 -  write one byte endianness aware to the chip
- * @mtd:       MTD device structure
- * @byte:      pointer to data byte to write
- *
- * write function for 16bit buswidth with endianness conversion
- */
-static void au_write_byte16(struct mtd_info *mtd, u_char byte)
-{
-       struct nand_chip *this = mtd_to_nand(mtd);
-       writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
-       wmb(); /* drain writebuffer */
-}
-
-/**
- * au_read_word -  read one word from the chip
- * @mtd:       MTD device structure
- *
- * read function for 16bit buswidth without endianness conversion
- */
-static u16 au_read_word(struct mtd_info *mtd)
-{
-       struct nand_chip *this = mtd_to_nand(mtd);
-       u16 ret = readw(this->IO_ADDR_R);
-       wmb(); /* drain writebuffer */
-       return ret;
-}
-
-/**
- * au_write_buf -  write buffer to chip
- * @mtd:       MTD device structure
- * @buf:       data buffer
- * @len:       number of bytes to write
- *
- * write function for 8bit buswidth
- */
-static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       int i;
-       struct nand_chip *this = mtd_to_nand(mtd);
-
-       for (i = 0; i < len; i++) {
-               writeb(buf[i], this->IO_ADDR_W);
-               wmb(); /* drain writebuffer */
-       }
-}
-
-/**
- * au_read_buf -  read chip data into buffer
- * @mtd:       MTD device structure
- * @buf:       buffer to store date
- * @len:       number of bytes to read
- *
- * read function for 8bit buswidth
- */
-static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
-{
-       int i;
-       struct nand_chip *this = mtd_to_nand(mtd);
-
-       for (i = 0; i < len; i++) {
-               buf[i] = readb(this->IO_ADDR_R);
-               wmb(); /* drain writebuffer */
-       }
-}
-
-/**
- * au_write_buf16 -  write buffer to chip
- * @mtd:       MTD device structure
- * @buf:       data buffer
- * @len:       number of bytes to write
- *
- * write function for 16bit buswidth
- */
-static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
-{
-       int i;
-       struct nand_chip *this = mtd_to_nand(mtd);
-       u16 *p = (u16 *) buf;
-       len >>= 1;
-
-       for (i = 0; i < len; i++) {
-               writew(p[i], this->IO_ADDR_W);
-               wmb(); /* drain writebuffer */
-       }
-
-}
-
-/**
- * au_read_buf16 -  read chip data into buffer
- * @mtd:       MTD device structure
- * @buf:       buffer to store date
- * @len:       number of bytes to read
- *
- * read function for 16bit buswidth
- */
-static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
-{
-       int i;
-       struct nand_chip *this = mtd_to_nand(mtd);
-       u16 *p = (u16 *) buf;
-       len >>= 1;
-
-       for (i = 0; i < len; i++) {
-               p[i] = readw(this->IO_ADDR_R);
-               wmb(); /* drain writebuffer */
-       }
-}
-
-/* Select the chip by setting nCE to low */
-#define NAND_CTL_SETNCE                1
-/* Deselect the chip by setting nCE to high */
-#define NAND_CTL_CLRNCE                2
-/* Select the command latch by setting CLE to high */
-#define NAND_CTL_SETCLE                3
-/* Deselect the command latch by setting CLE to low */
-#define NAND_CTL_CLRCLE                4
-/* Select the address latch by setting ALE to high */
-#define NAND_CTL_SETALE                5
-/* Deselect the address latch by setting ALE to low */
-#define NAND_CTL_CLRALE                6
-
-static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
-{
-       struct nand_chip *this = mtd_to_nand(mtd);
-       struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
-                                               chip);
-
-       switch (cmd) {
-
-       case NAND_CTL_SETCLE:
-               this->IO_ADDR_W = ctx->base + MEM_STNAND_CMD;
-               break;
-
-       case NAND_CTL_CLRCLE:
-               this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
-               break;
-
-       case NAND_CTL_SETALE:
-               this->IO_ADDR_W = ctx->base + MEM_STNAND_ADDR;
-               break;
-
-       case NAND_CTL_CLRALE:
-               this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
-               /* FIXME: Nobody knows why this is necessary,
-                * but it works only that way */
-               udelay(1);
-               break;
-
-       case NAND_CTL_SETNCE:
-               /* assert (force assert) chip enable */
-               alchemy_wrsmem((1 << (4 + ctx->cs)), AU1000_MEM_STNDCTL);
-               break;
-
-       case NAND_CTL_CLRNCE:
-               /* deassert chip enable */
-               alchemy_wrsmem(0, AU1000_MEM_STNDCTL);
-               break;
-       }
-
-       this->IO_ADDR_R = this->IO_ADDR_W;
-
-       wmb(); /* Drain the writebuffer */
-}
-
-int au1550_device_ready(struct mtd_info *mtd)
-{
-       return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0;
-}
-
-/**
- * au1550_select_chip - control -CE line
- *     Forbid driving -CE manually permitting the NAND controller to do this.
- *     Keeping -CE asserted during the whole sector reads interferes with the
- *     NOR flash and PCMCIA drivers as it causes contention on the static bus.
- *     We only have to hold -CE low for the NAND read commands since the flash
- *     chip needs it to be asserted during chip not ready time but the NAND
- *     controller keeps it released.
- *
- * @mtd:       MTD device structure
- * @chip:      chipnumber to select, -1 for deselect
- */
-static void au1550_select_chip(struct mtd_info *mtd, int chip)
-{
-}
-
-/**
- * au1550_command - Send command to NAND device
- * @mtd:       MTD device structure
- * @command:   the command to be sent
- * @column:    the column address for this command, -1 if none
- * @page_addr: the page address for this command, -1 if none
- */
-static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
-{
-       struct nand_chip *this = mtd_to_nand(mtd);
-       struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
-                                               chip);
-       int ce_override = 0, i;
-       unsigned long flags = 0;
-
-       /* Begin command latch cycle */
-       au1550_hwcontrol(mtd, NAND_CTL_SETCLE);
-       /*
-        * Write out the command to the device.
-        */
-       if (command == NAND_CMD_SEQIN) {
-               int readcmd;
-
-               if (column >= mtd->writesize) {
-                       /* OOB area */
-                       column -= mtd->writesize;
-                       readcmd = NAND_CMD_READOOB;
-               } else if (column < 256) {
-                       /* First 256 bytes --> READ0 */
-                       readcmd = NAND_CMD_READ0;
-               } else {
-                       column -= 256;
-                       readcmd = NAND_CMD_READ1;
-               }
-               ctx->write_byte(mtd, readcmd);
-       }
-       ctx->write_byte(mtd, command);
-
-       /* Set ALE and clear CLE to start address cycle */
-       au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
-
-       if (column != -1 || page_addr != -1) {
-               au1550_hwcontrol(mtd, NAND_CTL_SETALE);
-
-               /* Serially input address */
-               if (column != -1) {
-                       /* Adjust columns for 16 bit buswidth */
-                       if (this->options & NAND_BUSWIDTH_16 &&
-                                       !nand_opcode_8bits(command))
-                               column >>= 1;
-                       ctx->write_byte(mtd, column);
-               }
-               if (page_addr != -1) {
-                       ctx->write_byte(mtd, (u8)(page_addr & 0xff));
-
-                       if (command == NAND_CMD_READ0 ||
-                           command == NAND_CMD_READ1 ||
-                           command == NAND_CMD_READOOB) {
-                               /*
-                                * NAND controller will release -CE after
-                                * the last address byte is written, so we'll
-                                * have to forcibly assert it. No interrupts
-                                * are allowed while we do this as we don't
-                                * want the NOR flash or PCMCIA drivers to
-                                * steal our precious bytes of data...
-                                */
-                               ce_override = 1;
-                               local_irq_save(flags);
-                               au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
-                       }
-
-                       ctx->write_byte(mtd, (u8)(page_addr >> 8));
-
-                       if (this->options & NAND_ROW_ADDR_3)
-                               ctx->write_byte(mtd,
-                                               ((page_addr >> 16) & 0x0f));
-               }
-               /* Latch in address */
-               au1550_hwcontrol(mtd, NAND_CTL_CLRALE);
-       }
-
-       /*
-        * Program and erase have their own busy handlers.
-        * Status and sequential in need no delay.
-        */
-       switch (command) {
-
-       case NAND_CMD_PAGEPROG:
-       case NAND_CMD_ERASE1:
-       case NAND_CMD_ERASE2:
-       case NAND_CMD_SEQIN:
-       case NAND_CMD_STATUS:
-               return;
-
-       case NAND_CMD_RESET:
-               break;
-
-       case NAND_CMD_READ0:
-       case NAND_CMD_READ1:
-       case NAND_CMD_READOOB:
-               /* Check if we're really driving -CE low (just in case) */
-               if (unlikely(!ce_override))
-                       break;
-
-               /* Apply a short delay always to ensure that we do wait tWB. */
-               ndelay(100);
-               /* Wait for a chip to become ready... */
-               for (i = this->chip_delay; !this->dev_ready(mtd) && i > 0; --i)
-                       udelay(1);
-
-               /* Release -CE and re-enable interrupts. */
-               au1550_hwcontrol(mtd, NAND_CTL_CLRNCE);
-               local_irq_restore(flags);
-               return;
-       }
-       /* Apply this short delay always to ensure that we do wait tWB. */
-       ndelay(100);
-
-       while(!this->dev_ready(mtd));
-}
-
-static int find_nand_cs(unsigned long nand_base)
-{
-       void __iomem *base =
-                       (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
-       unsigned long addr, staddr, start, mask, end;
-       int i;
-
-       for (i = 0; i < 4; i++) {
-               addr = 0x1000 + (i * 0x10);                     /* CSx */
-               staddr = __raw_readl(base + addr + 0x08);       /* STADDRx */
-               /* figure out the decoded range of this CS */
-               start = (staddr << 4) & 0xfffc0000;
-               mask = (staddr << 18) & 0xfffc0000;
-               end = (start | (start - 1)) & ~(start ^ mask);
-               if ((nand_base >= start) && (nand_base < end))
-                       return i;
-       }
-
-       return -ENODEV;
-}
-
-static int au1550nd_probe(struct platform_device *pdev)
-{
-       struct au1550nd_platdata *pd;
-       struct au1550nd_ctx *ctx;
-       struct nand_chip *this;
-       struct mtd_info *mtd;
-       struct resource *r;
-       int ret, cs;
-
-       pd = dev_get_platdata(&pdev->dev);
-       if (!pd) {
-               dev_err(&pdev->dev, "missing platform data\n");
-               return -ENODEV;
-       }
-
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
-               return -ENOMEM;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(&pdev->dev, "no NAND memory resource\n");
-               ret = -ENODEV;
-               goto out1;
-       }
-       if (request_mem_region(r->start, resource_size(r), "au1550-nand")) {
-               dev_err(&pdev->dev, "cannot claim NAND memory area\n");
-               ret = -ENOMEM;
-               goto out1;
-       }
-
-       ctx->base = ioremap_nocache(r->start, 0x1000);
-       if (!ctx->base) {
-               dev_err(&pdev->dev, "cannot remap NAND memory area\n");
-               ret = -ENODEV;
-               goto out2;
-       }
-
-       this = &ctx->chip;
-       mtd = nand_to_mtd(this);
-       mtd->dev.parent = &pdev->dev;
-
-       /* figure out which CS# r->start belongs to */
-       cs = find_nand_cs(r->start);
-       if (cs < 0) {
-               dev_err(&pdev->dev, "cannot detect NAND chipselect\n");
-               ret = -ENODEV;
-               goto out3;
-       }
-       ctx->cs = cs;
-
-       this->dev_ready = au1550_device_ready;
-       this->select_chip = au1550_select_chip;
-       this->cmdfunc = au1550_command;
-
-       /* 30 us command delay time */
-       this->chip_delay = 30;
-       this->ecc.mode = NAND_ECC_SOFT;
-       this->ecc.algo = NAND_ECC_HAMMING;
-
-       if (pd->devwidth)
-               this->options |= NAND_BUSWIDTH_16;
-
-       this->read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte;
-       ctx->write_byte = (pd->devwidth) ? au_write_byte16 : au_write_byte;
-       this->read_word = au_read_word;
-       this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf;
-       this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf;
-
-       ret = nand_scan(mtd, 1);
-       if (ret) {
-               dev_err(&pdev->dev, "NAND scan failed with %d\n", ret);
-               goto out3;
-       }
-
-       mtd_device_register(mtd, pd->parts, pd->num_parts);
-
-       platform_set_drvdata(pdev, ctx);
-
-       return 0;
-
-out3:
-       iounmap(ctx->base);
-out2:
-       release_mem_region(r->start, resource_size(r));
-out1:
-       kfree(ctx);
-       return ret;
-}
-
-static int au1550nd_remove(struct platform_device *pdev)
-{
-       struct au1550nd_ctx *ctx = platform_get_drvdata(pdev);
-       struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       nand_release(nand_to_mtd(&ctx->chip));
-       iounmap(ctx->base);
-       release_mem_region(r->start, 0x1000);
-       kfree(ctx);
-       return 0;
-}
-
-static struct platform_driver au1550nd_driver = {
-       .driver = {
-               .name   = "au1550-nand",
-       },
-       .probe          = au1550nd_probe,
-       .remove         = au1550nd_remove,
-};
-
-module_platform_driver(au1550nd_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Embedded Edge, LLC");
-MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board");
diff --git a/drivers/mtd/nand/bbt.c b/drivers/mtd/nand/bbt.c
new file mode 100644 (file)
index 0000000..56cde38
--- /dev/null
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 Free Electrons
+ *
+ * Authors:
+ *     Boris Brezillon <boris.brezillon@free-electrons.com>
+ *     Peter Pan <peterpandong@micron.com>
+ */
+
+#define pr_fmt(fmt)    "nand-bbt: " fmt
+
+#include <linux/mtd/nand.h>
+#include <linux/slab.h>
+
+/**
+ * nanddev_bbt_init() - Initialize the BBT (Bad Block Table)
+ * @nand: NAND device
+ *
+ * Initialize the in-memory BBT.
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int nanddev_bbt_init(struct nand_device *nand)
+{
+       unsigned int bits_per_block = fls(NAND_BBT_BLOCK_NUM_STATUS);
+       unsigned int nblocks = nanddev_neraseblocks(nand);
+       unsigned int nwords = DIV_ROUND_UP(nblocks * bits_per_block,
+                                          BITS_PER_LONG);
+
+       nand->bbt.cache = kzalloc(nwords, GFP_KERNEL);
+       if (!nand->bbt.cache)
+               return -ENOMEM;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(nanddev_bbt_init);
+
+/**
+ * nanddev_bbt_cleanup() - Cleanup the BBT (Bad Block Table)
+ * @nand: NAND device
+ *
+ * Undoes what has been done in nanddev_bbt_init()
+ */
+void nanddev_bbt_cleanup(struct nand_device *nand)
+{
+       kfree(nand->bbt.cache);
+}
+EXPORT_SYMBOL_GPL(nanddev_bbt_cleanup);
+
+/**
+ * nanddev_bbt_update() - Update a BBT
+ * @nand: nand device
+ *
+ * Update the BBT. Currently a NOP function since on-flash bbt is not yet
+ * supported.
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int nanddev_bbt_update(struct nand_device *nand)
+{
+       return 0;
+}
+EXPORT_SYMBOL_GPL(nanddev_bbt_update);
+
+/**
+ * nanddev_bbt_get_block_status() - Return the status of an eraseblock
+ * @nand: nand device
+ * @entry: the BBT entry
+ *
+ * Return: a positive number nand_bbt_block_status status or -%ERANGE if @entry
+ *        is bigger than the BBT size.
+ */
+int nanddev_bbt_get_block_status(const struct nand_device *nand,
+                                unsigned int entry)
+{
+       unsigned int bits_per_block = fls(NAND_BBT_BLOCK_NUM_STATUS);
+       unsigned long *pos = nand->bbt.cache +
+                            ((entry * bits_per_block) / BITS_PER_LONG);
+       unsigned int offs = (entry * bits_per_block) % BITS_PER_LONG;
+       unsigned long status;
+
+       if (entry >= nanddev_neraseblocks(nand))
+               return -ERANGE;
+
+       status = pos[0] >> offs;
+       if (bits_per_block + offs > BITS_PER_LONG)
+               status |= pos[1] << (BITS_PER_LONG - offs);
+
+       return status & GENMASK(bits_per_block - 1, 0);
+}
+EXPORT_SYMBOL_GPL(nanddev_bbt_get_block_status);
+
+/**
+ * nanddev_bbt_set_block_status() - Update the status of an eraseblock in the
+ *                                 in-memory BBT
+ * @nand: nand device
+ * @entry: the BBT entry to update
+ * @status: the new status
+ *
+ * Update an entry of the in-memory BBT. If you want to push the updated BBT
+ * the NAND you should call nanddev_bbt_update().
+ *
+ * Return: 0 in case of success or -%ERANGE if @entry is bigger than the BBT
+ *        size.
+ */
+int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry,
+                                enum nand_bbt_block_status status)
+{
+       unsigned int bits_per_block = fls(NAND_BBT_BLOCK_NUM_STATUS);
+       unsigned long *pos = nand->bbt.cache +
+                            ((entry * bits_per_block) / BITS_PER_LONG);
+       unsigned int offs = (entry * bits_per_block) % BITS_PER_LONG;
+       unsigned long val = status & GENMASK(bits_per_block - 1, 0);
+
+       if (entry >= nanddev_neraseblocks(nand))
+               return -ERANGE;
+
+       pos[0] &= ~GENMASK(offs + bits_per_block - 1, offs);
+       pos[0] |= val << offs;
+
+       if (bits_per_block + offs > BITS_PER_LONG) {
+               unsigned int rbits = bits_per_block + offs - BITS_PER_LONG;
+
+               pos[1] &= ~GENMASK(rbits - 1, 0);
+               pos[1] |= val >> rbits;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(nanddev_bbt_set_block_status);
diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/bcm47xxnflash/Makefile
deleted file mode 100644 (file)
index f05b119..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-bcm47xxnflash-y                                += main.o
-bcm47xxnflash-y                                += ops_bcm4706.o
-
-obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)   += bcm47xxnflash.o
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
deleted file mode 100644 (file)
index 201b9ba..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __BCM47XXNFLASH_H
-#define __BCM47XXNFLASH_H
-
-#ifndef pr_fmt
-#define pr_fmt(fmt)            KBUILD_MODNAME ": " fmt
-#endif
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/rawnand.h>
-
-struct bcm47xxnflash {
-       struct bcma_drv_cc *cc;
-
-       struct nand_chip nand_chip;
-
-       unsigned curr_command;
-       int curr_page_addr;
-       int curr_column;
-
-       u8 id_data[8];
-};
-
-int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n);
-
-#endif /* BCM47XXNFLASH */
diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c
deleted file mode 100644 (file)
index fb31429..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * BCM47XX NAND flash driver
- *
- * Copyright (C) 2012 RafaÅ‚ MiÅ‚ecki <zajec5@gmail.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.
- *
- */
-
-#include "bcm47xxnflash.h"
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/bcma/bcma.h>
-
-MODULE_DESCRIPTION("NAND flash driver for BCMA bus");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("RafaÅ‚ MiÅ‚ecki");
-
-static const char *probes[] = { "bcm47xxpart", NULL };
-
-static int bcm47xxnflash_probe(struct platform_device *pdev)
-{
-       struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
-       struct bcm47xxnflash *b47n;
-       struct mtd_info *mtd;
-       int err = 0;
-
-       b47n = devm_kzalloc(&pdev->dev, sizeof(*b47n), GFP_KERNEL);
-       if (!b47n)
-               return -ENOMEM;
-
-       nand_set_controller_data(&b47n->nand_chip, b47n);
-       mtd = nand_to_mtd(&b47n->nand_chip);
-       mtd->dev.parent = &pdev->dev;
-       b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash);
-
-       if (b47n->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
-               err = bcm47xxnflash_ops_bcm4706_init(b47n);
-       } else {
-               pr_err("Device not supported\n");
-               err = -ENOTSUPP;
-       }
-       if (err) {
-               pr_err("Initialization failed: %d\n", err);
-               return err;
-       }
-
-       platform_set_drvdata(pdev, b47n);
-
-       err = mtd_device_parse_register(mtd, probes, NULL, NULL, 0);
-       if (err) {
-               pr_err("Failed to register MTD device: %d\n", err);
-               return err;
-       }
-
-       return 0;
-}
-
-static int bcm47xxnflash_remove(struct platform_device *pdev)
-{
-       struct bcm47xxnflash *nflash = platform_get_drvdata(pdev);
-
-       nand_release(nand_to_mtd(&nflash->nand_chip));
-
-       return 0;
-}
-
-static struct platform_driver bcm47xxnflash_driver = {
-       .probe  = bcm47xxnflash_probe,
-       .remove = bcm47xxnflash_remove,
-       .driver = {
-               .name = "bcma_nflash",
-       },
-};
-
-module_platform_driver(bcm47xxnflash_driver);
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
deleted file mode 100644 (file)
index 54bac5b..0000000
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * BCM47XX NAND flash driver
- *
- * Copyright (C) 2012 RafaÅ‚ MiÅ‚ecki <zajec5@gmail.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.
- *
- */
-
-#include "bcm47xxnflash.h"
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/bcma/bcma.h>
-
-/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
- * shown ~1000 retries as maxiumum. */
-#define NFLASH_READY_RETRIES           10000
-
-#define NFLASH_SECTOR_SIZE             512
-
-#define NCTL_CMD0                      0x00010000
-#define NCTL_COL                       0x00020000      /* Update column with value from BCMA_CC_NFLASH_COL_ADDR */
-#define NCTL_ROW                       0x00040000      /* Update row (page) with value from BCMA_CC_NFLASH_ROW_ADDR */
-#define NCTL_CMD1W                     0x00080000
-#define NCTL_READ                      0x00100000
-#define NCTL_WRITE                     0x00200000
-#define NCTL_SPECADDR                  0x01000000
-#define NCTL_READY                     0x04000000
-#define NCTL_ERR                       0x08000000
-#define NCTL_CSA                       0x40000000
-#define NCTL_START                     0x80000000
-
-/**************************************************
- * Various helpers
- **************************************************/
-
-static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
-{
-       return ((ns * 1000 * clock) / 1000000) + 1;
-}
-
-static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
-{
-       int i = 0;
-
-       bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, NCTL_START | code);
-       for (i = 0; i < NFLASH_READY_RETRIES; i++) {
-               if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) {
-                       i = 0;
-                       break;
-               }
-       }
-       if (i) {
-               pr_err("NFLASH control command not ready!\n");
-               return -EBUSY;
-       }
-       return 0;
-}
-
-static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
-{
-       int i;
-
-       for (i = 0; i < NFLASH_READY_RETRIES; i++) {
-               if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) {
-                       if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) &
-                           BCMA_CC_NFLASH_CTL_ERR) {
-                               pr_err("Error on polling\n");
-                               return -EBUSY;
-                       } else {
-                               return 0;
-                       }
-               }
-       }
-
-       pr_err("Polling timeout!\n");
-       return -EBUSY;
-}
-
-/**************************************************
- * R/W
- **************************************************/
-
-static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
-                                          int len)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
-
-       u32 ctlcode;
-       u32 *dest = (u32 *)buf;
-       int i;
-       int toread;
-
-       BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
-       /* Don't validate column using nand_chip->page_shift, it may be bigger
-        * when accessing OOB */
-
-       while (len) {
-               /* We can read maximum of 0x200 bytes at once */
-               toread = min(len, 0x200);
-
-               /* Set page and column */
-               bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR,
-                               b47n->curr_column);
-               bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR,
-                               b47n->curr_page_addr);
-
-               /* Prepare to read */
-               ctlcode = NCTL_CSA | NCTL_CMD1W | NCTL_ROW | NCTL_COL |
-                         NCTL_CMD0;
-               ctlcode |= NAND_CMD_READSTART << 8;
-               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
-                       return;
-               if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc))
-                       return;
-
-               /* Eventually read some data :) */
-               for (i = 0; i < toread; i += 4, dest++) {
-                       ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ;
-                       if (i == toread - 4) /* Last read goes without that */
-                               ctlcode &= ~NCTL_CSA;
-                       if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
-                                                             ctlcode))
-                               return;
-                       *dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA);
-               }
-
-               b47n->curr_column += toread;
-               len -= toread;
-       }
-}
-
-static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
-                                           const uint8_t *buf, int len)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
-       struct bcma_drv_cc *cc = b47n->cc;
-
-       u32 ctlcode;
-       const u32 *data = (u32 *)buf;
-       int i;
-
-       BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
-       /* Don't validate column using nand_chip->page_shift, it may be bigger
-        * when accessing OOB */
-
-       for (i = 0; i < len; i += 4, data++) {
-               bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data);
-
-               ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE;
-               if (i == len - 4) /* Last read goes without that */
-                       ctlcode &= ~NCTL_CSA;
-               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) {
-                       pr_err("%s ctl_cmd didn't work!\n", __func__);
-                       return;
-               }
-       }
-
-       b47n->curr_column += len;
-}
-
-/**************************************************
- * NAND chip ops
- **************************************************/
-
-static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd,
-                                              unsigned int ctrl)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
-       u32 code = 0;
-
-       if (cmd == NAND_CMD_NONE)
-               return;
-
-       if (cmd & NAND_CTRL_CLE)
-               code = cmd | NCTL_CMD0;
-
-       /* nCS is not needed for reset command */
-       if (cmd != NAND_CMD_RESET)
-               code |= NCTL_CSA;
-
-       bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, code);
-}
-
-/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
-static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
-                                                 int chip)
-{
-       return;
-}
-
-static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
-
-       return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);
-}
-
-/*
- * Default nand_command and nand_command_lp don't match BCM4706 hardware layout.
- * For example, reading chip id is performed in a non-standard way.
- * Setting column and page is also handled differently, we use a special
- * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
- * standard commands would be much more complicated.
- */
-static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
-                                             unsigned command, int column,
-                                             int page_addr)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
-       struct bcma_drv_cc *cc = b47n->cc;
-       u32 ctlcode;
-       int i;
-
-       if (column != -1)
-               b47n->curr_column = column;
-       if (page_addr != -1)
-               b47n->curr_page_addr = page_addr;
-
-       switch (command) {
-       case NAND_CMD_RESET:
-               nand_chip->cmd_ctrl(mtd, command, NAND_CTRL_CLE);
-
-               ndelay(100);
-               nand_wait_ready(mtd);
-               break;
-       case NAND_CMD_READID:
-               ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;
-               ctlcode |= NAND_CMD_READID;
-               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
-                       pr_err("READID error\n");
-                       break;
-               }
-
-               /*
-                * Reading is specific, last one has to go without NCTL_CSA
-                * bit. We don't know how many reads NAND subsystem is going
-                * to perform, so cache everything.
-                */
-               for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
-                       ctlcode = NCTL_CSA | NCTL_READ;
-                       if (i == ARRAY_SIZE(b47n->id_data) - 1)
-                               ctlcode &= ~NCTL_CSA;
-                       if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
-                                                             ctlcode)) {
-                               pr_err("READID error\n");
-                               break;
-                       }
-                       b47n->id_data[i] =
-                               bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA)
-                               & 0xFF;
-               }
-
-               break;
-       case NAND_CMD_STATUS:
-               ctlcode = NCTL_CSA | NCTL_CMD0 | NAND_CMD_STATUS;
-               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
-                       pr_err("STATUS command error\n");
-               break;
-       case NAND_CMD_READ0:
-               break;
-       case NAND_CMD_READOOB:
-               if (page_addr != -1)
-                       b47n->curr_column += mtd->writesize;
-               break;
-       case NAND_CMD_ERASE1:
-               bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
-                               b47n->curr_page_addr);
-               ctlcode = NCTL_ROW | NCTL_CMD1W | NCTL_CMD0 |
-                         NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
-               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
-                       pr_err("ERASE1 failed\n");
-               break;
-       case NAND_CMD_ERASE2:
-               break;
-       case NAND_CMD_SEQIN:
-               /* Set page and column */
-               bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR,
-                               b47n->curr_column);
-               bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
-                               b47n->curr_page_addr);
-
-               /* Prepare to write */
-               ctlcode = 0x40000000 | NCTL_ROW | NCTL_COL | NCTL_CMD0;
-               ctlcode |= NAND_CMD_SEQIN;
-               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
-                       pr_err("SEQIN failed\n");
-               break;
-       case NAND_CMD_PAGEPROG:
-               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_CMD0 |
-                                                         NAND_CMD_PAGEPROG))
-                       pr_err("PAGEPROG failed\n");
-               if (bcm47xxnflash_ops_bcm4706_poll(cc))
-                       pr_err("PAGEPROG not ready\n");
-               break;
-       default:
-               pr_err("Command 0x%X unsupported\n", command);
-               break;
-       }
-       b47n->curr_command = command;
-}
-
-static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
-       struct bcma_drv_cc *cc = b47n->cc;
-       u32 tmp = 0;
-
-       switch (b47n->curr_command) {
-       case NAND_CMD_READID:
-               if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
-                       pr_err("Requested invalid id_data: %d\n",
-                              b47n->curr_column);
-                       return 0;
-               }
-               return b47n->id_data[b47n->curr_column++];
-       case NAND_CMD_STATUS:
-               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ))
-                       return 0;
-               return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff;
-       case NAND_CMD_READOOB:
-               bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);
-               return tmp & 0xFF;
-       }
-
-       pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
-       return 0;
-}
-
-static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
-                                              uint8_t *buf, int len)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
-
-       switch (b47n->curr_command) {
-       case NAND_CMD_READ0:
-       case NAND_CMD_READOOB:
-               bcm47xxnflash_ops_bcm4706_read(mtd, buf, len);
-               return;
-       }
-
-       pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
-}
-
-static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
-                                               const uint8_t *buf, int len)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
-
-       switch (b47n->curr_command) {
-       case NAND_CMD_SEQIN:
-               bcm47xxnflash_ops_bcm4706_write(mtd, buf, len);
-               return;
-       }
-
-       pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);
-}
-
-/**************************************************
- * Init
- **************************************************/
-
-int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
-{
-       struct nand_chip *nand_chip = (struct nand_chip *)&b47n->nand_chip;
-       int err;
-       u32 freq;
-       u16 clock;
-       u8 w0, w1, w2, w3, w4;
-
-       unsigned long chipsize; /* MiB */
-       u8 tbits, col_bits, col_size, row_bits, row_bsize;
-       u32 val;
-
-       b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
-       nand_chip->cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl;
-       nand_chip->dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready;
-       b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
-       b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
-       b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
-       b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
-       b47n->nand_chip.onfi_set_features = nand_onfi_get_set_features_notsupp;
-       b47n->nand_chip.onfi_get_features = nand_onfi_get_set_features_notsupp;
-
-       nand_chip->chip_delay = 50;
-       b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
-       b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
-
-       /* Enable NAND flash access */
-       bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
-                     BCMA_CC_4706_FLASHSCFG_NF1);
-
-       /* Configure wait counters */
-       if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
-               /* 400 MHz */
-               freq = 400000000 / 4;
-       } else {
-               freq = bcma_chipco_pll_read(b47n->cc, 4);
-               freq = (freq & 0xFFF) >> 3;
-               /* Fixed reference clock 25 MHz and m = 2 */
-               freq = (freq * 25000000 / 2) / 4;
-       }
-       clock = freq / 1000000;
-       w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
-       w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
-       w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
-       w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
-       w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
-       bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
-                       (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
-
-       /* Scan NAND */
-       err = nand_scan(nand_to_mtd(&b47n->nand_chip), 1);
-       if (err) {
-               pr_err("Could not scan NAND flash: %d\n", err);
-               goto exit;
-       }
-
-       /* Configure FLASH */
-       chipsize = b47n->nand_chip.chipsize >> 20;
-       tbits = ffs(chipsize); /* find first bit set */
-       if (!tbits || tbits != fls(chipsize)) {
-               pr_err("Invalid flash size: 0x%lX\n", chipsize);
-               err = -ENOTSUPP;
-               goto exit;
-       }
-       tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
-
-       col_bits = b47n->nand_chip.page_shift + 1;
-       col_size = (col_bits + 7) / 8;
-
-       row_bits = tbits - col_bits + 1;
-       row_bsize = (row_bits + 7) / 8;
-
-       val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
-       bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
-
-exit:
-       if (err)
-               bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
-                              ~BCMA_CC_4706_FLASHSCFG_NF1);
-       return err;
-}
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
deleted file mode 100644 (file)
index 87bbd17..0000000
+++ /dev/null
@@ -1,862 +0,0 @@
-/* linux/drivers/mtd/nand/bf5xx_nand.c
- *
- * Copyright 2006-2008 Analog Devices Inc.
- *     http://blackfin.uclinux.org/
- *     Bryan Wu <bryan.wu@analog.com>
- *
- * Blackfin BF5xx on-chip NAND flash controller driver
- *
- * Derived from drivers/mtd/nand/s3c2410.c
- * Copyright (c) 2007 Ben Dooks <ben@simtec.co.uk>
- *
- * Derived from drivers/mtd/nand/cafe.c
- * Copyright Â© 2006 Red Hat, Inc.
- * Copyright Â© 2006 David Woodhouse <dwmw2@infradead.org>
- *
- * Changelog:
- *     12-Jun-2007  Bryan Wu:  Initial version
- *     18-Jul-2007  Bryan Wu:
- *             - ECC_HW and ECC_SW supported
- *             - DMA supported in ECC_HW
- *             - YAFFS tested as rootfs in both ECC_HW and ECC_SW
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/blackfin.h>
-#include <asm/dma.h>
-#include <asm/cacheflush.h>
-#include <asm/nand.h>
-#include <asm/portmux.h>
-
-#define DRV_NAME       "bf5xx-nand"
-#define DRV_VERSION    "1.2"
-#define DRV_AUTHOR     "Bryan Wu <bryan.wu@analog.com>"
-#define DRV_DESC       "BF5xx on-chip NAND FLash Controller Driver"
-
-/* NFC_STAT Masks */
-#define NBUSY       0x01  /* Not Busy */
-#define WB_FULL     0x02  /* Write Buffer Full */
-#define PG_WR_STAT  0x04  /* Page Write Pending */
-#define PG_RD_STAT  0x08  /* Page Read Pending */
-#define WB_EMPTY    0x10  /* Write Buffer Empty */
-
-/* NFC_IRQSTAT Masks */
-#define NBUSYIRQ    0x01  /* Not Busy IRQ */
-#define WB_OVF      0x02  /* Write Buffer Overflow */
-#define WB_EDGE     0x04  /* Write Buffer Edge Detect */
-#define RD_RDY      0x08  /* Read Data Ready */
-#define WR_DONE     0x10  /* Page Write Done */
-
-/* NFC_RST Masks */
-#define ECC_RST     0x01  /* ECC (and NFC counters) Reset */
-
-/* NFC_PGCTL Masks */
-#define PG_RD_START 0x01  /* Page Read Start */
-#define PG_WR_START 0x02  /* Page Write Start */
-
-#ifdef CONFIG_MTD_NAND_BF5XX_HWECC
-static int hardware_ecc = 1;
-#else
-static int hardware_ecc;
-#endif
-
-static const unsigned short bfin_nfc_pin_req[] =
-       {P_NAND_CE,
-        P_NAND_RB,
-        P_NAND_D0,
-        P_NAND_D1,
-        P_NAND_D2,
-        P_NAND_D3,
-        P_NAND_D4,
-        P_NAND_D5,
-        P_NAND_D6,
-        P_NAND_D7,
-        P_NAND_WE,
-        P_NAND_RE,
-        P_NAND_CLE,
-        P_NAND_ALE,
-        0};
-
-#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
-static int bootrom_ooblayout_ecc(struct mtd_info *mtd, int section,
-                                struct mtd_oob_region *oobregion)
-{
-       if (section > 7)
-               return -ERANGE;
-
-       oobregion->offset = section * 8;
-       oobregion->length = 3;
-
-       return 0;
-}
-
-static int bootrom_ooblayout_free(struct mtd_info *mtd, int section,
-                                 struct mtd_oob_region *oobregion)
-{
-       if (section > 7)
-               return -ERANGE;
-
-       oobregion->offset = (section * 8) + 3;
-       oobregion->length = 5;
-
-       return 0;
-}
-
-static const struct mtd_ooblayout_ops bootrom_ooblayout_ops = {
-       .ecc = bootrom_ooblayout_ecc,
-       .free = bootrom_ooblayout_free,
-};
-#endif
-
-/*
- * Data structures for bf5xx nand flash controller driver
- */
-
-/* bf5xx nand info */
-struct bf5xx_nand_info {
-       /* mtd info */
-       struct nand_hw_control          controller;
-       struct nand_chip                chip;
-
-       /* platform info */
-       struct bf5xx_nand_platform      *platform;
-
-       /* device info */
-       struct device                   *device;
-
-       /* DMA stuff */
-       struct completion               dma_completion;
-};
-
-/*
- * Conversion functions
- */
-static struct bf5xx_nand_info *mtd_to_nand_info(struct mtd_info *mtd)
-{
-       return container_of(mtd_to_nand(mtd), struct bf5xx_nand_info,
-                           chip);
-}
-
-static struct bf5xx_nand_info *to_nand_info(struct platform_device *pdev)
-{
-       return platform_get_drvdata(pdev);
-}
-
-static struct bf5xx_nand_platform *to_nand_plat(struct platform_device *pdev)
-{
-       return dev_get_platdata(&pdev->dev);
-}
-
-/*
- * struct nand_chip interface function pointers
- */
-
-/*
- * bf5xx_nand_hwcontrol
- *
- * Issue command and address cycles to the chip
- */
-static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd,
-                                  unsigned int ctrl)
-{
-       if (cmd == NAND_CMD_NONE)
-               return;
-
-       while (bfin_read_NFC_STAT() & WB_FULL)
-               cpu_relax();
-
-       if (ctrl & NAND_CLE)
-               bfin_write_NFC_CMD(cmd);
-       else if (ctrl & NAND_ALE)
-               bfin_write_NFC_ADDR(cmd);
-       SSYNC();
-}
-
-/*
- * bf5xx_nand_devready()
- *
- * returns 0 if the nand is busy, 1 if it is ready
- */
-static int bf5xx_nand_devready(struct mtd_info *mtd)
-{
-       unsigned short val = bfin_read_NFC_STAT();
-
-       if ((val & NBUSY) == NBUSY)
-               return 1;
-       else
-               return 0;
-}
-
-/*
- * ECC functions
- * These allow the bf5xx to use the controller's ECC
- * generator block to ECC the data as it passes through
- */
-
-/*
- * ECC error correction function
- */
-static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
-                                       u_char *read_ecc, u_char *calc_ecc)
-{
-       struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-       u32 syndrome[5];
-       u32 calced, stored;
-       int i;
-       unsigned short failing_bit, failing_byte;
-       u_char data;
-
-       calced = calc_ecc[0] | (calc_ecc[1] << 8) | (calc_ecc[2] << 16);
-       stored = read_ecc[0] | (read_ecc[1] << 8) | (read_ecc[2] << 16);
-
-       syndrome[0] = (calced ^ stored);
-
-       /*
-        * syndrome 0: all zero
-        * No error in data
-        * No action
-        */
-       if (!syndrome[0] || !calced || !stored)
-               return 0;
-
-       /*
-        * sysdrome 0: only one bit is one
-        * ECC data was incorrect
-        * No action
-        */
-       if (hweight32(syndrome[0]) == 1) {
-               dev_err(info->device, "ECC data was incorrect!\n");
-               return -EBADMSG;
-       }
-
-       syndrome[1] = (calced & 0x7FF) ^ (stored & 0x7FF);
-       syndrome[2] = (calced & 0x7FF) ^ ((calced >> 11) & 0x7FF);
-       syndrome[3] = (stored & 0x7FF) ^ ((stored >> 11) & 0x7FF);
-       syndrome[4] = syndrome[2] ^ syndrome[3];
-
-       for (i = 0; i < 5; i++)
-               dev_info(info->device, "syndrome[%d] 0x%08x\n", i, syndrome[i]);
-
-       dev_info(info->device,
-               "calced[0x%08x], stored[0x%08x]\n",
-               calced, stored);
-
-       /*
-        * sysdrome 0: exactly 11 bits are one, each parity
-        * and parity' pair is 1 & 0 or 0 & 1.
-        * 1-bit correctable error
-        * Correct the error
-        */
-       if (hweight32(syndrome[0]) == 11 && syndrome[4] == 0x7FF) {
-               dev_info(info->device,
-                       "1-bit correctable error, correct it.\n");
-               dev_info(info->device,
-                       "syndrome[1] 0x%08x\n", syndrome[1]);
-
-               failing_bit = syndrome[1] & 0x7;
-               failing_byte = syndrome[1] >> 0x3;
-               data = *(dat + failing_byte);
-               data = data ^ (0x1 << failing_bit);
-               *(dat + failing_byte) = data;
-
-               return 1;
-       }
-
-       /*
-        * sysdrome 0: random data
-        * More than 1-bit error, non-correctable error
-        * Discard data, mark bad block
-        */
-       dev_err(info->device,
-               "More than 1-bit error, non-correctable error.\n");
-       dev_err(info->device,
-               "Please discard data, mark bad block\n");
-
-       return -EBADMSG;
-}
-
-static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
-                                       u_char *read_ecc, u_char *calc_ecc)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       int ret, bitflips = 0;
-
-       ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
-       if (ret < 0)
-               return ret;
-
-       bitflips = ret;
-
-       /* If ecc size is 512, correct second 256 bytes */
-       if (chip->ecc.size == 512) {
-               dat += 256;
-               read_ecc += 3;
-               calc_ecc += 3;
-               ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
-               if (ret < 0)
-                       return ret;
-
-               bitflips += ret;
-       }
-
-       return bitflips;
-}
-
-static void bf5xx_nand_enable_hwecc(struct mtd_info *mtd, int mode)
-{
-       return;
-}
-
-static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
-               const u_char *dat, u_char *ecc_code)
-{
-       struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       u16 ecc0, ecc1;
-       u32 code[2];
-       u8 *p;
-
-       /* first 3 bytes ECC code for 256 page size */
-       ecc0 = bfin_read_NFC_ECC0();
-       ecc1 = bfin_read_NFC_ECC1();
-
-       code[0] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
-
-       dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
-
-       p = (u8 *) code;
-       memcpy(ecc_code, p, 3);
-
-       /* second 3 bytes ECC code for 512 ecc size */
-       if (chip->ecc.size == 512) {
-               ecc0 = bfin_read_NFC_ECC2();
-               ecc1 = bfin_read_NFC_ECC3();
-               code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
-
-               /* second 3 bytes in ecc_code for second 256
-                * bytes of 512 page size
-                */
-               p = (u8 *) (code + 1);
-               memcpy((ecc_code + 3), p, 3);
-               dev_dbg(info->device, "returning ecc 0x%08x\n", code[1]);
-       }
-
-       return 0;
-}
-
-/*
- * PIO mode for buffer writing and reading
- */
-static void bf5xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
-       int i;
-       unsigned short val;
-
-       /*
-        * Data reads are requested by first writing to NFC_DATA_RD
-        * and then reading back from NFC_READ.
-        */
-       for (i = 0; i < len; i++) {
-               while (bfin_read_NFC_STAT() & WB_FULL)
-                       cpu_relax();
-
-               /* Contents do not matter */
-               bfin_write_NFC_DATA_RD(0x0000);
-               SSYNC();
-
-               while ((bfin_read_NFC_IRQSTAT() & RD_RDY) != RD_RDY)
-                       cpu_relax();
-
-               buf[i] = bfin_read_NFC_READ();
-
-               val = bfin_read_NFC_IRQSTAT();
-               val |= RD_RDY;
-               bfin_write_NFC_IRQSTAT(val);
-               SSYNC();
-       }
-}
-
-static uint8_t bf5xx_nand_read_byte(struct mtd_info *mtd)
-{
-       uint8_t val;
-
-       bf5xx_nand_read_buf(mtd, &val, 1);
-
-       return val;
-}
-
-static void bf5xx_nand_write_buf(struct mtd_info *mtd,
-                               const uint8_t *buf, int len)
-{
-       int i;
-
-       for (i = 0; i < len; i++) {
-               while (bfin_read_NFC_STAT() & WB_FULL)
-                       cpu_relax();
-
-               bfin_write_NFC_DATA_WR(buf[i]);
-               SSYNC();
-       }
-}
-
-static void bf5xx_nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
-{
-       int i;
-       u16 *p = (u16 *) buf;
-       len >>= 1;
-
-       /*
-        * Data reads are requested by first writing to NFC_DATA_RD
-        * and then reading back from NFC_READ.
-        */
-       bfin_write_NFC_DATA_RD(0x5555);
-
-       SSYNC();
-
-       for (i = 0; i < len; i++)
-               p[i] = bfin_read_NFC_READ();
-}
-
-static void bf5xx_nand_write_buf16(struct mtd_info *mtd,
-                               const uint8_t *buf, int len)
-{
-       int i;
-       u16 *p = (u16 *) buf;
-       len >>= 1;
-
-       for (i = 0; i < len; i++)
-               bfin_write_NFC_DATA_WR(p[i]);
-
-       SSYNC();
-}
-
-/*
- * DMA functions for buffer writing and reading
- */
-static irqreturn_t bf5xx_nand_dma_irq(int irq, void *dev_id)
-{
-       struct bf5xx_nand_info *info = dev_id;
-
-       clear_dma_irqstat(CH_NFC);
-       disable_dma(CH_NFC);
-       complete(&info->dma_completion);
-
-       return IRQ_HANDLED;
-}
-
-static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
-                               uint8_t *buf, int is_read)
-{
-       struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       unsigned short val;
-
-       dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
-                       mtd, buf, is_read);
-
-       /*
-        * Before starting a dma transfer, be sure to invalidate/flush
-        * the cache over the address range of your DMA buffer to
-        * prevent cache coherency problems. Otherwise very subtle bugs
-        * can be introduced to your driver.
-        */
-       if (is_read)
-               invalidate_dcache_range((unsigned int)buf,
-                               (unsigned int)(buf + chip->ecc.size));
-       else
-               flush_dcache_range((unsigned int)buf,
-                               (unsigned int)(buf + chip->ecc.size));
-
-       /*
-        * This register must be written before each page is
-        * transferred to generate the correct ECC register
-        * values.
-        */
-       bfin_write_NFC_RST(ECC_RST);
-       SSYNC();
-       while (bfin_read_NFC_RST() & ECC_RST)
-               cpu_relax();
-
-       disable_dma(CH_NFC);
-       clear_dma_irqstat(CH_NFC);
-
-       /* setup DMA register with Blackfin DMA API */
-       set_dma_config(CH_NFC, 0x0);
-       set_dma_start_addr(CH_NFC, (unsigned long) buf);
-
-       /* The DMAs have different size on BF52x and BF54x */
-#ifdef CONFIG_BF52x
-       set_dma_x_count(CH_NFC, (chip->ecc.size >> 1));
-       set_dma_x_modify(CH_NFC, 2);
-       val = DI_EN | WDSIZE_16;
-#endif
-
-#ifdef CONFIG_BF54x
-       set_dma_x_count(CH_NFC, (chip->ecc.size >> 2));
-       set_dma_x_modify(CH_NFC, 4);
-       val = DI_EN | WDSIZE_32;
-#endif
-       /* setup write or read operation */
-       if (is_read)
-               val |= WNR;
-       set_dma_config(CH_NFC, val);
-       enable_dma(CH_NFC);
-
-       /* Start PAGE read/write operation */
-       if (is_read)
-               bfin_write_NFC_PGCTL(PG_RD_START);
-       else
-               bfin_write_NFC_PGCTL(PG_WR_START);
-       wait_for_completion(&info->dma_completion);
-}
-
-static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
-                                       uint8_t *buf, int len)
-{
-       struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-       struct nand_chip *chip = mtd_to_nand(mtd);
-
-       dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
-
-       if (len == chip->ecc.size)
-               bf5xx_nand_dma_rw(mtd, buf, 1);
-       else
-               bf5xx_nand_read_buf(mtd, buf, len);
-}
-
-static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
-                               const uint8_t *buf, int len)
-{
-       struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-       struct nand_chip *chip = mtd_to_nand(mtd);
-
-       dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
-
-       if (len == chip->ecc.size)
-               bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0);
-       else
-               bf5xx_nand_write_buf(mtd, buf, len);
-}
-
-static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
-               uint8_t *buf, int oob_required, int page)
-{
-       nand_read_page_op(chip, page, 0, NULL, 0);
-
-       bf5xx_nand_read_buf(mtd, buf, mtd->writesize);
-       bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-       return 0;
-}
-
-static int bf5xx_nand_write_page_raw(struct mtd_info *mtd,
-               struct nand_chip *chip, const uint8_t *buf, int oob_required,
-               int page)
-{
-       nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
-       bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-       return nand_prog_page_end_op(chip);
-}
-
-/*
- * System initialization functions
- */
-static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info)
-{
-       int ret;
-
-       /* Do not use dma */
-       if (!hardware_ecc)
-               return 0;
-
-       init_completion(&info->dma_completion);
-
-       /* Request NFC DMA channel */
-       ret = request_dma(CH_NFC, "BF5XX NFC driver");
-       if (ret < 0) {
-               dev_err(info->device, " unable to get DMA channel\n");
-               return ret;
-       }
-
-#ifdef CONFIG_BF54x
-       /* Setup DMAC1 channel mux for NFC which shared with SDH */
-       bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() & ~1);
-       SSYNC();
-#endif
-
-       set_dma_callback(CH_NFC, bf5xx_nand_dma_irq, info);
-
-       /* Turn off the DMA channel first */
-       disable_dma(CH_NFC);
-       return 0;
-}
-
-static void bf5xx_nand_dma_remove(struct bf5xx_nand_info *info)
-{
-       /* Free NFC DMA channel */
-       if (hardware_ecc)
-               free_dma(CH_NFC);
-}
-
-/*
- * BF5XX NFC hardware initialization
- *  - pin mux setup
- *  - clear interrupt status
- */
-static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
-{
-       int err = 0;
-       unsigned short val;
-       struct bf5xx_nand_platform *plat = info->platform;
-
-       /* setup NFC_CTL register */
-       dev_info(info->device,
-               "data_width=%d, wr_dly=%d, rd_dly=%d\n",
-               (plat->data_width ? 16 : 8),
-               plat->wr_dly, plat->rd_dly);
-
-       val = (1 << NFC_PG_SIZE_OFFSET) |
-               (plat->data_width << NFC_NWIDTH_OFFSET) |
-               (plat->rd_dly << NFC_RDDLY_OFFSET) |
-               (plat->wr_dly << NFC_WRDLY_OFFSET);
-       dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val);
-
-       bfin_write_NFC_CTL(val);
-       SSYNC();
-
-       /* clear interrupt status */
-       bfin_write_NFC_IRQMASK(0x0);
-       SSYNC();
-       val = bfin_read_NFC_IRQSTAT();
-       bfin_write_NFC_IRQSTAT(val);
-       SSYNC();
-
-       /* DMA initialization  */
-       if (bf5xx_nand_dma_init(info))
-               err = -ENXIO;
-
-       return err;
-}
-
-/*
- * Device management interface
- */
-static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
-{
-       struct mtd_info *mtd = nand_to_mtd(&info->chip);
-       struct mtd_partition *parts = info->platform->partitions;
-       int nr = info->platform->nr_partitions;
-
-       return mtd_device_register(mtd, parts, nr);
-}
-
-static int bf5xx_nand_remove(struct platform_device *pdev)
-{
-       struct bf5xx_nand_info *info = to_nand_info(pdev);
-
-       /* first thing we need to do is release all our mtds
-        * and their partitions, then go through freeing the
-        * resources used
-        */
-       nand_release(nand_to_mtd(&info->chip));
-
-       peripheral_free_list(bfin_nfc_pin_req);
-       bf5xx_nand_dma_remove(info);
-
-       return 0;
-}
-
-static int bf5xx_nand_scan(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       int ret;
-
-       ret = nand_scan_ident(mtd, 1, NULL);
-       if (ret)
-               return ret;
-
-       if (hardware_ecc) {
-               /*
-                * for nand with page size > 512B, think it as several sections with 512B
-                */
-               if (likely(mtd->writesize >= 512)) {
-                       chip->ecc.size = 512;
-                       chip->ecc.bytes = 6;
-                       chip->ecc.strength = 2;
-               } else {
-                       chip->ecc.size = 256;
-                       chip->ecc.bytes = 3;
-                       chip->ecc.strength = 1;
-                       bfin_write_NFC_CTL(bfin_read_NFC_CTL() & ~(1 << NFC_PG_SIZE_OFFSET));
-                       SSYNC();
-               }
-       }
-
-       return  nand_scan_tail(mtd);
-}
-
-/*
- * bf5xx_nand_probe
- *
- * called by device layer when it finds a device matching
- * one our driver can handled. This code checks to see if
- * it can allocate all necessary resources then calls the
- * nand layer to look for devices
- */
-static int bf5xx_nand_probe(struct platform_device *pdev)
-{
-       struct bf5xx_nand_platform *plat = to_nand_plat(pdev);
-       struct bf5xx_nand_info *info = NULL;
-       struct nand_chip *chip = NULL;
-       struct mtd_info *mtd = NULL;
-       int err = 0;
-
-       dev_dbg(&pdev->dev, "(%p)\n", pdev);
-
-       if (!plat) {
-               dev_err(&pdev->dev, "no platform specific information\n");
-               return -EINVAL;
-       }
-
-       if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
-               dev_err(&pdev->dev, "requesting Peripherals failed\n");
-               return -EFAULT;
-       }
-
-       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
-       if (info == NULL) {
-               err = -ENOMEM;
-               goto out_err;
-       }
-
-       platform_set_drvdata(pdev, info);
-
-       nand_hw_control_init(&info->controller);
-
-       info->device     = &pdev->dev;
-       info->platform   = plat;
-
-       /* initialise chip data struct */
-       chip = &info->chip;
-       mtd = nand_to_mtd(&info->chip);
-
-       if (plat->data_width)
-               chip->options |= NAND_BUSWIDTH_16;
-
-       chip->options |= NAND_CACHEPRG | NAND_SKIP_BBTSCAN;
-
- &n