aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap7
-rw-r--r--Documentation/arm/Samsung-S3C24XX/S3C2412.txt2
-rw-r--r--Documentation/driver-api/mtdnand.rst8
-rw-r--r--Documentation/gpio/drivers-on-gpio.txt4
-rw-r--r--MAINTAINERS32
-rw-r--r--arch/cris/arch-v32/drivers/mach-a3/nandflash.c2
-rw-r--r--arch/cris/arch-v32/drivers/mach-fs/nandflash.c2
-rw-r--r--drivers/mtd/nand/Kconfig569
-rw-r--r--drivers/mtd/nand/Makefile70
-rw-r--r--drivers/mtd/nand/bbt.c130
-rw-r--r--drivers/mtd/nand/core.c244
-rw-r--r--drivers/mtd/nand/raw/Kconfig569
-rw-r--r--drivers/mtd/nand/raw/Makefile67
-rw-r--r--drivers/mtd/nand/raw/ams-delta.c (renamed from drivers/mtd/nand/ams-delta.c)9
-rw-r--r--drivers/mtd/nand/raw/atmel/Makefile (renamed from drivers/mtd/nand/atmel/Makefile)0
-rw-r--r--drivers/mtd/nand/raw/atmel/nand-controller.c (renamed from drivers/mtd/nand/atmel/nand-controller.c)4
-rw-r--r--drivers/mtd/nand/raw/atmel/pmecc.c (renamed from drivers/mtd/nand/atmel/pmecc.c)4
-rw-r--r--drivers/mtd/nand/raw/atmel/pmecc.h (renamed from drivers/mtd/nand/atmel/pmecc.h)4
-rw-r--r--drivers/mtd/nand/raw/au1550nd.c (renamed from drivers/mtd/nand/au1550nd.c)2
-rw-r--r--drivers/mtd/nand/raw/bcm47xxnflash/Makefile (renamed from drivers/mtd/nand/bcm47xxnflash/Makefile)0
-rw-r--r--drivers/mtd/nand/raw/bcm47xxnflash/bcm47xxnflash.h (renamed from drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h)0
-rw-r--r--drivers/mtd/nand/raw/bcm47xxnflash/main.c (renamed from drivers/mtd/nand/bcm47xxnflash/main.c)0
-rw-r--r--drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c (renamed from drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c)0
-rw-r--r--drivers/mtd/nand/raw/bf5xx_nand.c (renamed from drivers/mtd/nand/bf5xx_nand.c)7
-rw-r--r--drivers/mtd/nand/raw/brcmnand/Makefile (renamed from drivers/mtd/nand/brcmnand/Makefile)0
-rw-r--r--drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c (renamed from drivers/mtd/nand/brcmnand/bcm63138_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c (renamed from drivers/mtd/nand/brcmnand/bcm6368_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/brcmnand/brcmnand.c (renamed from drivers/mtd/nand/brcmnand/brcmnand.c)0
-rw-r--r--drivers/mtd/nand/raw/brcmnand/brcmnand.h (renamed from drivers/mtd/nand/brcmnand/brcmnand.h)0
-rw-r--r--drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c (renamed from drivers/mtd/nand/brcmnand/brcmstb_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/brcmnand/iproc_nand.c (renamed from drivers/mtd/nand/brcmnand/iproc_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/cafe_nand.c (renamed from drivers/mtd/nand/cafe_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/cmx270_nand.c (renamed from drivers/mtd/nand/cmx270_nand.c)4
-rw-r--r--drivers/mtd/nand/raw/cs553x_nand.c (renamed from drivers/mtd/nand/cs553x_nand.c)2
-rw-r--r--drivers/mtd/nand/raw/davinci_nand.c (renamed from drivers/mtd/nand/davinci_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/denali.c (renamed from drivers/mtd/nand/denali.c)0
-rw-r--r--drivers/mtd/nand/raw/denali.h (renamed from drivers/mtd/nand/denali.h)0
-rw-r--r--drivers/mtd/nand/raw/denali_dt.c (renamed from drivers/mtd/nand/denali_dt.c)0
-rw-r--r--drivers/mtd/nand/raw/denali_pci.c (renamed from drivers/mtd/nand/denali_pci.c)0
-rw-r--r--drivers/mtd/nand/raw/diskonchip.c (renamed from drivers/mtd/nand/diskonchip.c)2
-rw-r--r--drivers/mtd/nand/raw/docg4.c (renamed from drivers/mtd/nand/docg4.c)0
-rw-r--r--drivers/mtd/nand/raw/fsl_elbc_nand.c (renamed from drivers/mtd/nand/fsl_elbc_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/fsl_ifc_nand.c (renamed from drivers/mtd/nand/fsl_ifc_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/fsl_upm.c (renamed from drivers/mtd/nand/fsl_upm.c)0
-rw-r--r--drivers/mtd/nand/raw/fsmc_nand.c (renamed from drivers/mtd/nand/fsmc_nand.c)252
-rw-r--r--drivers/mtd/nand/raw/gpio.c (renamed from drivers/mtd/nand/gpio.c)2
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/Makefile (renamed from drivers/mtd/nand/gpmi-nand/Makefile)0
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/bch-regs.h (renamed from drivers/mtd/nand/gpmi-nand/bch-regs.h)0
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c (renamed from drivers/mtd/nand/gpmi-nand/gpmi-lib.c)0
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c (renamed from drivers/mtd/nand/gpmi-nand/gpmi-nand.c)0
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h (renamed from drivers/mtd/nand/gpmi-nand/gpmi-nand.h)0
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-regs.h (renamed from drivers/mtd/nand/gpmi-nand/gpmi-regs.h)0
-rw-r--r--drivers/mtd/nand/raw/hisi504_nand.c (renamed from drivers/mtd/nand/hisi504_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/jz4740_nand.c (renamed from drivers/mtd/nand/jz4740_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/jz4780_bch.c (renamed from drivers/mtd/nand/jz4780_bch.c)0
-rw-r--r--drivers/mtd/nand/raw/jz4780_bch.h (renamed from drivers/mtd/nand/jz4780_bch.h)0
-rw-r--r--drivers/mtd/nand/raw/jz4780_nand.c (renamed from drivers/mtd/nand/jz4780_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_mlc.c (renamed from drivers/mtd/nand/lpc32xx_mlc.c)0
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_slc.c (renamed from drivers/mtd/nand/lpc32xx_slc.c)0
-rw-r--r--drivers/mtd/nand/raw/marvell_nand.c (renamed from drivers/mtd/nand/marvell_nand.c)39
-rw-r--r--drivers/mtd/nand/raw/mpc5121_nfc.c (renamed from drivers/mtd/nand/mpc5121_nfc.c)5
-rw-r--r--drivers/mtd/nand/raw/mtk_ecc.c (renamed from drivers/mtd/nand/mtk_ecc.c)0
-rw-r--r--drivers/mtd/nand/raw/mtk_ecc.h (renamed from drivers/mtd/nand/mtk_ecc.h)0
-rw-r--r--drivers/mtd/nand/raw/mtk_nand.c (renamed from drivers/mtd/nand/mtk_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/mxc_nand.c (renamed from drivers/mtd/nand/mxc_nand.c)509
-rw-r--r--drivers/mtd/nand/raw/nand_amd.c (renamed from drivers/mtd/nand/nand_amd.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_base.c (renamed from drivers/mtd/nand/nand_base.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_bbt.c (renamed from drivers/mtd/nand/nand_bbt.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_bch.c (renamed from drivers/mtd/nand/nand_bch.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_ecc.c (renamed from drivers/mtd/nand/nand_ecc.c)2
-rw-r--r--drivers/mtd/nand/raw/nand_hynix.c (renamed from drivers/mtd/nand/nand_hynix.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_ids.c (renamed from drivers/mtd/nand/nand_ids.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_macronix.c (renamed from drivers/mtd/nand/nand_macronix.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_micron.c (renamed from drivers/mtd/nand/nand_micron.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_samsung.c (renamed from drivers/mtd/nand/nand_samsung.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_timings.c (renamed from drivers/mtd/nand/nand_timings.c)0
-rw-r--r--drivers/mtd/nand/raw/nand_toshiba.c (renamed from drivers/mtd/nand/nand_toshiba.c)26
-rw-r--r--drivers/mtd/nand/raw/nandsim.c (renamed from drivers/mtd/nand/nandsim.c)0
-rw-r--r--drivers/mtd/nand/raw/ndfc.c (renamed from drivers/mtd/nand/ndfc.c)0
-rw-r--r--drivers/mtd/nand/raw/nuc900_nand.c (renamed from drivers/mtd/nand/nuc900_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/omap2.c (renamed from drivers/mtd/nand/omap2.c)0
-rw-r--r--drivers/mtd/nand/raw/omap_elm.c (renamed from drivers/mtd/nand/omap_elm.c)0
-rw-r--r--drivers/mtd/nand/raw/orion_nand.c (renamed from drivers/mtd/nand/orion_nand.c)2
-rw-r--r--drivers/mtd/nand/raw/oxnas_nand.c (renamed from drivers/mtd/nand/oxnas_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/pasemi_nand.c (renamed from drivers/mtd/nand/pasemi_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/plat_nand.c (renamed from drivers/mtd/nand/plat_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/qcom_nandc.c (renamed from drivers/mtd/nand/qcom_nandc.c)0
-rw-r--r--drivers/mtd/nand/raw/r852.c (renamed from drivers/mtd/nand/r852.c)0
-rw-r--r--drivers/mtd/nand/raw/r852.h (renamed from drivers/mtd/nand/r852.h)0
-rw-r--r--drivers/mtd/nand/raw/s3c2410.c (renamed from drivers/mtd/nand/s3c2410.c)3
-rw-r--r--drivers/mtd/nand/raw/sh_flctl.c (renamed from drivers/mtd/nand/sh_flctl.c)0
-rw-r--r--drivers/mtd/nand/raw/sharpsl.c (renamed from drivers/mtd/nand/sharpsl.c)2
-rw-r--r--drivers/mtd/nand/raw/sm_common.c (renamed from drivers/mtd/nand/sm_common.c)0
-rw-r--r--drivers/mtd/nand/raw/sm_common.h (renamed from drivers/mtd/nand/sm_common.h)0
-rw-r--r--drivers/mtd/nand/raw/socrates_nand.c (renamed from drivers/mtd/nand/socrates_nand.c)2
-rw-r--r--drivers/mtd/nand/raw/sunxi_nand.c (renamed from drivers/mtd/nand/sunxi_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/tango_nand.c (renamed from drivers/mtd/nand/tango_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/tmio_nand.c (renamed from drivers/mtd/nand/tmio_nand.c)0
-rw-r--r--drivers/mtd/nand/raw/txx9ndfmc.c (renamed from drivers/mtd/nand/txx9ndfmc.c)0
-rw-r--r--drivers/mtd/nand/raw/vf610_nfc.c (renamed from drivers/mtd/nand/vf610_nfc.c)44
-rw-r--r--drivers/mtd/nand/raw/xway_nand.c (renamed from drivers/mtd/nand/xway_nand.c)0
-rw-r--r--drivers/mtd/sm_ftl.c2
-rw-r--r--include/linux/mtd/bbm.h2
-rw-r--r--include/linux/mtd/nand.h731
-rw-r--r--include/linux/mtd/nand_ecc.h2
-rw-r--r--include/linux/mtd/ndfc.h2
106 files changed, 2318 insertions, 1053 deletions
diff --git a/.mailmap b/.mailmap
index e18cab73e209..85b28e8eb8ee 100644
--- a/.mailmap
+++ b/.mailmap
@@ -33,9 +33,9 @@ Axel Lin <[email protected]>
Ben Gardner <[email protected]>
Ben M Cahill <[email protected]>
Björn Steinbrink <[email protected]>
-Boris Brezillon <[email protected]>
Brian Avery <[email protected]>
Brian King <[email protected]>
Christoph Hellwig <[email protected]>
@@ -126,6 +126,7 @@ Mayuresh Janorkar <[email protected]>
Michael Buesch <[email protected]>
Michel Dänzer <[email protected]>
Mitesh shah <[email protected]>
Morten Welinder <[email protected]>
diff --git a/Documentation/arm/Samsung-S3C24XX/S3C2412.txt b/Documentation/arm/Samsung-S3C24XX/S3C2412.txt
index f057876b920b..dc1fd362d3c1 100644
--- a/Documentation/arm/Samsung-S3C24XX/S3C2412.txt
+++ b/Documentation/arm/Samsung-S3C24XX/S3C2412.txt
@@ -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
diff --git a/Documentation/driver-api/mtdnand.rst b/Documentation/driver-api/mtdnand.rst
index 2a5191b6d445..dcd63599f700 100644
--- a/Documentation/driver-api/mtdnand.rst
+++ b/Documentation/driver-api/mtdnand.rst
@@ -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
diff --git a/Documentation/gpio/drivers-on-gpio.txt b/Documentation/gpio/drivers-on-gpio.txt
index a2ccbab12eb7..a3e612f55bc7 100644
--- a/Documentation/gpio/drivers-on-gpio.txt
+++ b/Documentation/gpio/drivers-on-gpio.txt
@@ -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.
diff --git a/MAINTAINERS b/MAINTAINERS
index 0b32e3c2f511..d5ebb8a1a7c2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1232,7 +1232,7 @@ F: arch/arm/boot/dts/aspeed-*
F: drivers/*/*aspeed*
ARM/ATMEL AT91 Clock Support
-M: Boris Brezillon <[email protected]>
+M: Boris Brezillon <[email protected]>
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 <[email protected]>
S: Maintained
-F: drivers/mtd/nand/brcmnand/
+F: drivers/mtd/nand/raw/brcmnand/
BROADCOM STB DPFE DRIVER
M: Markus Mayer <[email protected]>
@@ -4116,7 +4116,7 @@ DENALI NAND DRIVER
M: Masahiro Yamada <[email protected]>
S: Supported
-F: drivers/mtd/nand/denali*
+F: drivers/mtd/nand/raw/denali*
DESIGNWARE USB2 DRD IP DRIVER
M: John Youn <[email protected]>
@@ -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 <[email protected]>
+M: Boris Brezillon <[email protected]>
S: Supported
F: drivers/gpu/drm/atmel-hlcdc/
@@ -5646,7 +5646,7 @@ FREESCALE GPMI NAND DRIVER
M: Han Xu <[email protected]>
S: Maintained
-F: drivers/mtd/nand/gpmi-nand/*
+F: drivers/mtd/nand/raw/gpmi-nand/*
FREESCALE I2C CPM DRIVER
M: Jochen Friedrich <[email protected]>
@@ -6955,7 +6955,7 @@ INGENIC JZ4780 NAND DRIVER
M: Harvey Hunt <[email protected]>
S: Maintained
-F: drivers/mtd/nand/jz4780_*
+F: drivers/mtd/nand/raw/jz4780_*
INOTIFY
M: Jan Kara <[email protected]>
@@ -8412,7 +8412,7 @@ F: include/uapi/drm/armada_drm.h
F: Documentation/devicetree/bindings/display/armada/
MARVELL CRYPTO DRIVER
-M: Boris Brezillon <[email protected]>
+M: Boris Brezillon <[email protected]>
M: Arnaud Ebalard <[email protected]>
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 <[email protected]>
+M: Miquel Raynal <[email protected]>
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 <[email protected]>
M: Brian Norris <[email protected]>
-M: Boris Brezillon <[email protected]>
+M: Boris Brezillon <[email protected]>
M: Marek Vasut <[email protected]>
M: Richard Weinberger <[email protected]>
M: Cyrille Pitchen <[email protected]>
@@ -9136,7 +9136,7 @@ M: Wenyou Yang <[email protected]>
M: Josh Wu <[email protected]>
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
@@ -9452,7 +9452,7 @@ S: Supported
F: drivers/net/ethernet/myricom/myri10ge/
NAND FLASH SUBSYSTEM
-M: Boris Brezillon <[email protected]>
+M: Boris Brezillon <[email protected]>
R: Richard Weinberger <[email protected]>
W: http://www.linux-mtd.infradead.org/
@@ -11809,8 +11809,8 @@ F: drivers/memstick/host/r592.*
RICOH SMARTMEDIA/XD DRIVER
M: Maxim Levitsky <[email protected]>
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 <[email protected]>
@@ -14629,7 +14629,7 @@ VF610 NAND DRIVER
M: Stefan Agner <[email protected]>
S: Supported
-F: drivers/mtd/nand/vf610_nfc.c
+F: drivers/mtd/nand/raw/vf610_nfc.c
VFAT/FAT/MSDOS FILESYSTEM
M: OGAWA Hirofumi <[email protected]>
diff --git a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
index 925a98eb6d68..7ec29d2d3661 100644
--- a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
+++ b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
@@ -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 ([email protected])
*
* This program is free software; you can redistribute it and/or modify
diff --git a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
index 53b56a429dde..7ce72906039a 100644
--- a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
+++ b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
@@ -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 ([email protected])
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 2c6ecb7ae753..1c1a1f487e20 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,569 +1,4 @@
-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.
-
-
-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_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"
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index c882d5ef192a..a72d3cb0f325 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1,70 +1,6 @@
# 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_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 += raw/
diff --git a/drivers/mtd/nand/bbt.c b/drivers/mtd/nand/bbt.c
new file mode 100644
index 000000000000..56cde38b92c0
--- /dev/null
+++ b/drivers/mtd/nand/bbt.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 Free Electrons
+ *
+ * Authors:
+ * Boris Brezillon <[email protected]>
+ * Peter Pan <[email protected]>
+ */
+
+#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/core.c b/drivers/mtd/nand/core.c
new file mode 100644
index 000000000000..f237a688f8e9
--- /dev/null
+++ b/drivers/mtd/nand/core.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 Free Electrons
+ *
+ * Authors:
+ * Boris Brezillon <[email protected]>
+ * Peter Pan <[email protected]>
+ */
+
+#define pr_fmt(fmt) "nand: " fmt
+
+#include <linux/module.h>
+#include <linux/mtd/nand.h>
+
+/**
+ * nanddev_isbad() - Check if a block is bad
+ * @nand: NAND device
+ * @pos: position pointing to the block we want to check
+ *
+ * Return: true if the block is bad, false otherwise.
+ */
+bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos)
+{
+ if (nanddev_bbt_is_initialized(nand)) {
+ unsigned int entry;
+ int status;
+
+ entry = nanddev_bbt_pos_to_entry(nand, pos);
+ status = nanddev_bbt_get_block_status(nand, entry);
+ /* Lazy block status retrieval */
+ if (status == NAND_BBT_BLOCK_STATUS_UNKNOWN) {
+ if (nand->ops->isbad(nand, pos))
+ status = NAND_BBT_BLOCK_FACTORY_BAD;
+ else
+ status = NAND_BBT_BLOCK_GOOD;
+
+ nanddev_bbt_set_block_status(nand, entry, status);
+ }
+
+ if (status == NAND_BBT_BLOCK_WORN ||
+ status == NAND_BBT_BLOCK_FACTORY_BAD)
+ return true;
+
+ return false;
+ }
+
+ return nand->ops->isbad(nand, pos);
+}
+EXPORT_SYMBOL_GPL(nanddev_isbad);
+
+/**
+ * nanddev_markbad() - Mark a block as bad
+ * @nand: NAND device
+ * @block: block to mark bad
+ *
+ * Mark a block bad. This function is updating the BBT if available and
+ * calls the low-level markbad hook (nand->ops->markbad()).
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos)
+{
+ struct mtd_info *mtd = nanddev_to_mtd(nand);
+ unsigned int entry;
+ int ret = 0;
+
+ if (nanddev_isbad(nand, pos))
+ return 0;
+
+ ret = nand->ops->markbad(nand, pos);
+ if (ret)
+ pr_warn("failed to write BBM to block @%llx (err = %d)\n",
+ nanddev_pos_to_offs(nand, pos), ret);
+
+ if (!nanddev_bbt_is_initialized(nand))
+ goto out;
+
+ entry = nanddev_bbt_pos_to_entry(nand, pos);
+ ret = nanddev_bbt_set_block_status(nand, entry, NAND_BBT_BLOCK_WORN);
+ if (ret)
+ goto out;
+
+ ret = nanddev_bbt_update(nand);
+
+out:
+ if (!ret)
+ mtd->ecc_stats.badblocks++;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nanddev_markbad);
+
+/**
+ * nanddev_isreserved() - Check whether an eraseblock is reserved or not
+ * @nand: NAND device
+ * @pos: NAND position to test
+ *
+ * Checks whether the eraseblock pointed by @pos is reserved or not.
+ *
+ * Return: true if the eraseblock is reserved, false otherwise.
+ */
+bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos)
+{
+ unsigned int entry;
+ int status;
+
+ if (!nanddev_bbt_is_initialized(nand))
+ return false;
+
+ /* Return info from the table */
+ entry = nanddev_bbt_pos_to_entry(nand, pos);
+ status = nanddev_bbt_get_block_status(nand, entry);
+ return status == NAND_BBT_BLOCK_RESERVED;
+}
+EXPORT_SYMBOL_GPL(nanddev_isreserved);
+
+/**
+ * nanddev_erase() - Erase a NAND portion
+ * @nand: NAND device
+ * @block: eraseblock to erase
+ *
+ * Erases @block if it's not bad.
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
+{
+ if (nanddev_isbad(nand, pos) || nanddev_isreserved(nand, pos)) {
+ pr_warn("attempt to erase a bad/reserved block @%llx\n",
+ nanddev_pos_to_offs(nand, pos));
+ return -EIO;
+ }
+
+ return nand->ops->erase(nand, pos);
+}
+EXPORT_SYMBOL_GPL(nanddev_erase);
+
+/**
+ * nanddev_mtd_erase() - Generic mtd->_erase() implementation for NAND devices
+ * @mtd: MTD device
+ * @einfo: erase request
+ *
+ * This is a simple mtd->_erase() implementation iterating over all blocks
+ * concerned by @einfo and calling nand->ops->erase() on each of them.
+ *
+ * Note that mtd->_erase should not be directly assigned to this helper,
+ * because there's no locking here. NAND specialized layers should instead
+ * implement there own wrapper around nanddev_mtd_erase() taking the
+ * appropriate lock before calling nanddev_mtd_erase().
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo)
+{
+ struct nand_device *nand = mtd_to_nanddev(mtd);
+ struct nand_pos pos, last;
+ int ret;
+
+ nanddev_offs_to_pos(nand, einfo->addr, &pos);
+ nanddev_offs_to_pos(nand, einfo->addr + einfo->len - 1, &last);
+ while (nanddev_pos_cmp(&pos, &last) <= 0) {
+ ret = nanddev_erase(nand, &pos);
+ if (ret) {
+ einfo->fail_addr = nanddev_pos_to_offs(nand, &pos);
+ einfo->state = MTD_ERASE_FAILED;
+
+ return ret;
+ }
+
+ nanddev_pos_next_eraseblock(nand, &pos);
+ }
+
+ einfo->state = MTD_ERASE_DONE;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nanddev_mtd_erase);
+
+/**
+ * nanddev_init() - Initialize a NAND device
+ * @nand: NAND device
+ * @memorg: NAND memory organization descriptor
+ * @ops: NAND device operations
+ *
+ * Initializes a NAND device object. Consistency checks are done on @memorg and
+ * @ops. Also takes care of initializing the BBT.
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int nanddev_init(struct nand_device *nand, const struct nand_ops *ops,
+ struct module *owner)
+{
+ struct mtd_info *mtd = nanddev_to_mtd(nand);
+ struct nand_memory_organization *memorg = nanddev_get_memorg(nand);
+
+ if (!nand || !ops)
+ return -EINVAL;
+
+ if (!ops->erase || !ops->markbad || !ops->isbad)
+ return -EINVAL;
+
+ if (!memorg->bits_per_cell || !memorg->pagesize ||
+ !memorg->pages_per_eraseblock || !memorg->eraseblocks_per_lun ||
+ !memorg->planes_per_lun || !memorg->luns_per_target ||
+ !memorg->ntargets)
+ return -EINVAL;
+
+ nand->rowconv.eraseblock_addr_shift =
+ fls(memorg->pages_per_eraseblock - 1);
+ nand->rowconv.lun_addr_shift = fls(memorg->eraseblocks_per_lun - 1) +
+ nand->rowconv.eraseblock_addr_shift;
+
+ nand->ops = ops;
+
+ mtd->type = memorg->bits_per_cell == 1 ?
+ MTD_NANDFLASH : MTD_MLCNANDFLASH;
+ mtd->flags = MTD_CAP_NANDFLASH;
+ mtd->erasesize = memorg->pagesize * memorg->pages_per_eraseblock;
+ mtd->writesize = memorg->pagesize;
+ mtd->writebufsize = memorg->pagesize;
+ mtd->oobsize = memorg->oobsize;
+ mtd->size = nanddev_size(nand);
+ mtd->owner = owner;
+
+ return nanddev_bbt_init(nand);
+}
+EXPORT_SYMBOL_GPL(nanddev_init);
+
+/**
+ * nanddev_cleanup() - Release resources allocated in nanddev_init()
+ * @nand: NAND device
+ *
+ * Basically undoes what has been done in nanddev_init().
+ */
+void nanddev_cleanup(struct nand_device *nand)
+{
+ if (nanddev_bbt_is_initialized(nand))
+ nanddev_bbt_cleanup(nand);
+}
+EXPORT_SYMBOL_GPL(nanddev_cleanup);
+
+MODULE_DESCRIPTION("Generic NAND framework");
+MODULE_AUTHOR("Boris Brezillon <[email protected]>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
new file mode 100644
index 000000000000..2c6ecb7ae753
--- /dev/null
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -0,0 +1,569 @@
+config MTD_NAND_ECC
+ 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.
+
+
+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_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
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
new file mode 100644
index 000000000000..f16f59a197a3
--- /dev/null
+++ b/drivers/mtd/nand/raw/Makefile
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0
+
+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
+
+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_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
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index d60ada45c549..35f80523e52e 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -1,11 +1,12 @@
/*
- * drivers/mtd/nand/ams-delta.c
- *
* Copyright (C) 2006 Jonathan McDowell <[email protected]>
*
- * Derived from drivers/mtd/toto.c
+ * Derived from drivers/mtd/nand/toto.c (removed in v2.6.28)
+ * Copyright (c) 2003 Texas Instruments
+ * Copyright (c) 2002 Thomas Gleixner <[email protected]>
+ *
* Converted to platform driver by Janusz Krzysztofik <[email protected]>
- * Partially stolen from drivers/mtd/nand/plat_nand.c
+ * Partially stolen from 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
diff --git a/drivers/mtd/nand/atmel/Makefile b/drivers/mtd/nand/raw/atmel/Makefile
index 288db4f38a8f..288db4f38a8f 100644
--- a/drivers/mtd/nand/atmel/Makefile
+++ b/drivers/mtd/nand/raw/atmel/Makefile
diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
index b2f00b398490..12f6753d47ae 100644
--- a/drivers/mtd/nand/atmel/nand-controller.c
+++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
@@ -9,10 +9,10 @@
*
* Copyright 2003 Rick Bronson
*
- * Derived from drivers/mtd/nand/autcpu12.c
+ * Derived from drivers/mtd/nand/autcpu12.c (removed in v3.8)
* Copyright 2001 Thomas Gleixner ([email protected])
*
- * Derived from drivers/mtd/spia.c
+ * Derived from drivers/mtd/spia.c (removed in v3.8)
* Copyright 2000 Steven J. Hill ([email protected])
*
*
diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c
index fcbe4fd6e684..9de29c9afb0c 100644
--- a/drivers/mtd/nand/atmel/pmecc.c
+++ b/drivers/mtd/nand/raw/atmel/pmecc.c
@@ -9,10 +9,10 @@
*
* Copyright 2003 Rick Bronson
*
- * Derived from drivers/mtd/nand/autcpu12.c
+ * Derived from drivers/mtd/nand/autcpu12.c (removed in v3.8)
* Copyright 2001 Thomas Gleixner ([email protected])
*
- * Derived from drivers/mtd/spia.c
+ * Derived from drivers/mtd/spia.c (removed in v3.8)
* Copyright 2000 Steven J. Hill ([email protected])
*
* Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
diff --git a/drivers/mtd/nand/atmel/pmecc.h b/drivers/mtd/nand/raw/atmel/pmecc.h
index 817e0dd9fd15..808f1be0d6ad 100644
--- a/drivers/mtd/nand/atmel/pmecc.h
+++ b/drivers/mtd/nand/raw/atmel/pmecc.h
@@ -9,10 +9,10 @@
*
* Copyright © 2003 Rick Bronson
*
- * Derived from drivers/mtd/nand/autcpu12.c
+ * Derived from drivers/mtd/nand/autcpu12.c (removed in v3.8)
* Copyright © 2001 Thomas Gleixner ([email protected])
*
- * Derived from drivers/mtd/spia.c
+ * Derived from drivers/mtd/spia.c (removed in v3.8)
* Copyright © 2000 Steven J. Hill ([email protected])
*
*
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c
index 8ab827edf94e..df0ef1f1e2f5 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/raw/au1550nd.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand/au1550nd.c
- *
* Copyright (C) 2004 Embedded Edge, LLC
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/raw/bcm47xxnflash/Makefile
index f05b119e134b..f05b119e134b 100644
--- a/drivers/mtd/nand/bcm47xxnflash/Makefile
+++ b/drivers/mtd/nand/raw/bcm47xxnflash/Makefile
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/raw/bcm47xxnflash/bcm47xxnflash.h
index 201b9baa52a0..201b9baa52a0 100644
--- a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
+++ b/drivers/mtd/nand/raw/bcm47xxnflash/bcm47xxnflash.h
diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/raw/bcm47xxnflash/main.c
index fb31429b70a9..fb31429b70a9 100644
--- a/drivers/mtd/nand/bcm47xxnflash/main.c
+++ b/drivers/mtd/nand/raw/bcm47xxnflash/main.c
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
index 54bac5b73f0a..54bac5b73f0a 100644
--- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
+++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/raw/bf5xx_nand.c
index 87bbd177b3e5..9a1d8d104570 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/raw/bf5xx_nand.c
@@ -1,15 +1,14 @@
-/* linux/drivers/mtd/nand/bf5xx_nand.c
- *
+/*
* Copyright 2006-2008 Analog Devices Inc.
* http://blackfin.uclinux.org/
* Bryan Wu <[email protected]>
*
* Blackfin BF5xx on-chip NAND flash controller driver
*
- * Derived from drivers/mtd/nand/s3c2410.c
+ * Derived from s3c2410.c
* Copyright (c) 2007 Ben Dooks <[email protected]>
*
- * Derived from drivers/mtd/nand/cafe.c
+ * Derived from cafe.c
* Copyright © 2006 Red Hat, Inc.
* Copyright © 2006 David Woodhouse <[email protected]>
*
diff --git a/drivers/mtd/nand/brcmnand/Makefile b/drivers/mtd/nand/raw/brcmnand/Makefile
index 195b845e48b8..195b845e48b8 100644
--- a/drivers/mtd/nand/brcmnand/Makefile
+++ b/drivers/mtd/nand/raw/brcmnand/Makefile
diff --git a/drivers/mtd/nand/brcmnand/bcm63138_nand.c b/drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c
index 59444b3a697d..59444b3a697d 100644
--- a/drivers/mtd/nand/brcmnand/bcm63138_nand.c
+++ b/drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c
diff --git a/drivers/mtd/nand/brcmnand/bcm6368_nand.c b/drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c
index 34c91b0e1e69..34c91b0e1e69 100644
--- a/drivers/mtd/nand/brcmnand/bcm6368_nand.c
+++ b/drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
index c28fd2bc1a84..c28fd2bc1a84 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
index 5c44cd4aba87..5c44cd4aba87 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.h
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
diff --git a/drivers/mtd/nand/brcmnand/brcmstb_nand.c b/drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c
index 5c271077ac87..5c271077ac87 100644
--- a/drivers/mtd/nand/brcmnand/brcmstb_nand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c
diff --git a/drivers/mtd/nand/brcmnand/iproc_nand.c b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c
index 4c6ae113664d..4c6ae113664d 100644
--- a/drivers/mtd/nand/brcmnand/iproc_nand.c
+++ b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 567ff972d5fc..567ff972d5fc 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c
index b01c9804590e..02d6751e9efe 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/raw/cmx270_nand.c
@@ -1,10 +1,8 @@
/*
- * linux/drivers/mtd/nand/cmx270-nand.c
- *
* Copyright (C) 2006 Compulab, Ltd.
* Mike Rapoport <[email protected]>
*
- * Derived from drivers/mtd/nand/h1910.c
+ * Derived from drivers/mtd/nand/h1910.c (removed in v3.10)
* Copyright (C) 2002 Marius Gröger ([email protected])
* Copyright (c) 2001 Thomas Gleixner ([email protected])
*
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c
index d48877540f14..be1f28fc7363 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/raw/cs553x_nand.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand/cs553x_nand.c
- *
* (C) 2005, 2006 Red Hat Inc.
*
* Author: David Woodhouse <[email protected]>
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index ccc8c43abcff..ccc8c43abcff 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/raw/denali.c
index 313c7f50621b..313c7f50621b 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/raw/denali.h
index 9ad33d237378..9ad33d237378 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/raw/denali.h
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c
index cfd33e6ca77f..cfd33e6ca77f 100644
--- a/drivers/mtd/nand/denali_dt.c
+++ b/drivers/mtd/nand/raw/denali_dt.c
diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/raw/denali_pci.c
index 49cb3e1f8bd0..49cb3e1f8bd0 100644
--- a/drivers/mtd/nand/denali_pci.c
+++ b/drivers/mtd/nand/raw/denali_pci.c
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
index 6bc93ea66f50..1af77f798fe5 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/raw/diskonchip.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand/diskonchip.c
- *
* (C) 2003 Red Hat, Inc.
* (C) 2004 Dan Brown <[email protected]>
* (C) 2004 Kalev Lember <[email protected]>
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/raw/docg4.c
index 72f1327c4430..72f1327c4430 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/raw/docg4.c
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c
index 8b6dcd739ecb..8b6dcd739ecb 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
index 4872a7ba6503..4872a7ba6503 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c
index a88e2cf66e0f..a88e2cf66e0f 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/raw/fsl_upm.c
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index f49ed46fa770..28c48dcc514e 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand/fsmc_nand.c
- *
* ST Microelectronics
* Flexible Static Memory Controller (FSMC)
* Driver for NAND portions
@@ -9,7 +7,9 @@
* Vipin Kumar <[email protected]>
* Ashish Priyadarshi
*
- * Based on drivers/mtd/nand/nomadik_nand.c
+ * Based on drivers/mtd/nand/nomadik_nand.c (removed in v3.8)
+ * Copyright © 2007 STMicroelectronics Pvt. Ltd.
+ * Copyright © 2009 Alessandro Rubini
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -103,10 +103,6 @@
#define ECC3 0x1C
#define FSMC_NAND_BANK_SZ 0x20
-#define FSMC_NAND_REG(base, bank, reg) (base + FSMC_NOR_REG_SIZE + \
- (FSMC_NAND_BANK_SZ * (bank)) + \
- reg)
-
#define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ)
struct fsmc_nand_timings {
@@ -143,7 +139,7 @@ enum access_mode {
* @data_va: NAND port for Data.
* @cmd_va: NAND port for Command.
* @addr_va: NAND port for Address.
- * @regs_va: FSMC regs base address.
+ * @regs_va: Registers base address for a given bank.
*/
struct fsmc_nand_data {
u32 pid;
@@ -258,45 +254,6 @@ static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd)
}
/*
- * fsmc_cmd_ctrl - For facilitaing Hardware access
- * This routine allows hardware specific access to control-lines(ALE,CLE)
- */
-static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd_to_nand(mtd);
- struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
- void __iomem *regs = host->regs_va;
- unsigned int bank = host->bank;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- u32 pc;
-
- if (ctrl & NAND_CLE) {
- this->IO_ADDR_R = host->cmd_va;
- this->IO_ADDR_W = host->cmd_va;
- } else if (ctrl & NAND_ALE) {
- this->IO_ADDR_R = host->addr_va;
- this->IO_ADDR_W = host->addr_va;
- } else {
- this->IO_ADDR_R = host->data_va;
- this->IO_ADDR_W = host->data_va;
- }
-
- pc = readl(FSMC_NAND_REG(regs, bank, PC));
- if (ctrl & NAND_NCE)
- pc |= FSMC_ENABLE;
- else
- pc &= ~FSMC_ENABLE;
- writel_relaxed(pc, FSMC_NAND_REG(regs, bank, PC));
- }
-
- mb();
-
- if (cmd != NAND_CMD_NONE)
- writeb_relaxed(cmd, this->IO_ADDR_W);
-}
-
-/*
* fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine
*
* This routine initializes timing parameters related to NAND memory access in
@@ -307,8 +264,6 @@ static void fsmc_nand_setup(struct fsmc_nand_data *host,
{
uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON;
uint32_t tclr, tar, thiz, thold, twait, tset;
- unsigned int bank = host->bank;
- void __iomem *regs = host->regs_va;
tclr = (tims->tclr & FSMC_TCLR_MASK) << FSMC_TCLR_SHIFT;
tar = (tims->tar & FSMC_TAR_MASK) << FSMC_TAR_SHIFT;
@@ -318,18 +273,14 @@ static void fsmc_nand_setup(struct fsmc_nand_data *host,
tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
if (host->nand.options & NAND_BUSWIDTH_16)
- writel_relaxed(value | FSMC_DEVWID_16,
- FSMC_NAND_REG(regs, bank, PC));
+ writel_relaxed(value | FSMC_DEVWID_16, host->regs_va + PC);
else
- writel_relaxed(value | FSMC_DEVWID_8,
- FSMC_NAND_REG(regs, bank, PC));
-
- writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
- FSMC_NAND_REG(regs, bank, PC));
- writel_relaxed(thiz | thold | twait | tset,
- FSMC_NAND_REG(regs, bank, COMM));
- writel_relaxed(thiz | thold | twait | tset,
- FSMC_NAND_REG(regs, bank, ATTRIB));
+ writel_relaxed(value | FSMC_DEVWID_8, host->regs_va + PC);
+
+ writel_relaxed(readl(host->regs_va + PC) | tclr | tar,
+ host->regs_va + PC);
+ writel_relaxed(thiz | thold | twait | tset, host->regs_va + COMM);
+ writel_relaxed(thiz | thold | twait | tset, host->regs_va + ATTRIB);
}
static int fsmc_calc_timings(struct fsmc_nand_data *host,
@@ -419,15 +370,13 @@ static int fsmc_setup_data_interface(struct mtd_info *mtd, int csline,
static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
{
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
- void __iomem *regs = host->regs_va;
- uint32_t bank = host->bank;
-
- writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
- FSMC_NAND_REG(regs, bank, PC));
- writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
- FSMC_NAND_REG(regs, bank, PC));
- writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
- FSMC_NAND_REG(regs, bank, PC));
+
+ writel_relaxed(readl(host->regs_va + PC) & ~FSMC_ECCPLEN_256,
+ host->regs_va + PC);
+ writel_relaxed(readl(host->regs_va + PC) & ~FSMC_ECCEN,
+ host->regs_va + PC);
+ writel_relaxed(readl(host->regs_va + PC) | FSMC_ECCEN,
+ host->regs_va + PC);
}
/*
@@ -439,13 +388,11 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
uint8_t *ecc)
{
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
- void __iomem *regs = host->regs_va;
- uint32_t bank = host->bank;
uint32_t ecc_tmp;
unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT;
do {
- if (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
+ if (readl_relaxed(host->regs_va + STS) & FSMC_CODE_RDY)
break;
else
cond_resched();
@@ -456,25 +403,25 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
return -ETIMEDOUT;
}
- ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
+ ecc_tmp = readl_relaxed(host->regs_va + ECC1);
ecc[0] = (uint8_t) (ecc_tmp >> 0);
ecc[1] = (uint8_t) (ecc_tmp >> 8);
ecc[2] = (uint8_t) (ecc_tmp >> 16);
ecc[3] = (uint8_t) (ecc_tmp >> 24);
- ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
+ ecc_tmp = readl_relaxed(host->regs_va + ECC2);
ecc[4] = (uint8_t) (ecc_tmp >> 0);
ecc[5] = (uint8_t) (ecc_tmp >> 8);
ecc[6] = (uint8_t) (ecc_tmp >> 16);
ecc[7] = (uint8_t) (ecc_tmp >> 24);
- ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
+ ecc_tmp = readl_relaxed(host->regs_va + ECC3);
ecc[8] = (uint8_t) (ecc_tmp >> 0);
ecc[9] = (uint8_t) (ecc_tmp >> 8);
ecc[10] = (uint8_t) (ecc_tmp >> 16);
ecc[11] = (uint8_t) (ecc_tmp >> 24);
- ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
+ ecc_tmp = readl_relaxed(host->regs_va + STS);
ecc[12] = (uint8_t) (ecc_tmp >> 16);
return 0;
@@ -489,11 +436,9 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
uint8_t *ecc)
{
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
- void __iomem *regs = host->regs_va;
- uint32_t bank = host->bank;
uint32_t ecc_tmp;
- ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
+ ecc_tmp = readl_relaxed(host->regs_va + ECC1);
ecc[0] = (uint8_t) (ecc_tmp >> 0);
ecc[1] = (uint8_t) (ecc_tmp >> 8);
ecc[2] = (uint8_t) (ecc_tmp >> 16);
@@ -598,18 +543,18 @@ unmap_dma:
*/
static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
{
+ struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
int i;
- struct nand_chip *chip = mtd_to_nand(mtd);
if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
IS_ALIGNED(len, sizeof(uint32_t))) {
uint32_t *p = (uint32_t *)buf;
len = len >> 2;
for (i = 0; i < len; i++)
- writel_relaxed(p[i], chip->IO_ADDR_W);
+ writel_relaxed(p[i], host->data_va);
} else {
for (i = 0; i < len; i++)
- writeb_relaxed(buf[i], chip->IO_ADDR_W);
+ writeb_relaxed(buf[i], host->data_va);
}
}
@@ -621,18 +566,18 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
*/
static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
+ struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
int i;
- struct nand_chip *chip = mtd_to_nand(mtd);
if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
IS_ALIGNED(len, sizeof(uint32_t))) {
uint32_t *p = (uint32_t *)buf;
len = len >> 2;
for (i = 0; i < len; i++)
- p[i] = readl_relaxed(chip->IO_ADDR_R);
+ p[i] = readl_relaxed(host->data_va);
} else {
for (i = 0; i < len; i++)
- buf[i] = readb_relaxed(chip->IO_ADDR_R);
+ buf[i] = readb_relaxed(host->data_va);
}
}
@@ -663,6 +608,102 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
}
+/* fsmc_select_chip - assert or deassert nCE */
+static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
+{
+ struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
+ u32 pc;
+
+ /* Support only one CS */
+ if (chipnr > 0)
+ return;
+
+ pc = readl(host->regs_va + PC);
+ if (chipnr < 0)
+ writel_relaxed(pc & ~FSMC_ENABLE, host->regs_va + PC);
+ else
+ writel_relaxed(pc | FSMC_ENABLE, host->regs_va + PC);
+
+ /* nCE line must be asserted before starting any operation */
+ mb();
+}
+
+/*
+ * fsmc_exec_op - hook called by the core to execute NAND operations
+ *
+ * This controller is simple enough and thus does not need to use the parser
+ * provided by the core, instead, handle every situation here.
+ */
+static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
+ bool check_only)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
+ const struct nand_op_instr *instr = NULL;
+ int ret = 0;
+ unsigned int op_id;
+ int i;
+
+ pr_debug("Executing operation [%d instructions]:\n", op->ninstrs);
+ for (op_id = 0; op_id < op->ninstrs; op_id++) {
+ instr = &op->instrs[op_id];
+
+ switch (instr->type) {
+ case NAND_OP_CMD_INSTR:
+ pr_debug(" ->CMD [0x%02x]\n",
+ instr->ctx.cmd.opcode);
+
+ writeb_relaxed(instr->ctx.cmd.opcode, host->cmd_va);
+ break;
+
+ case NAND_OP_ADDR_INSTR:
+ pr_debug(" ->ADDR [%d cyc]",
+ instr->ctx.addr.naddrs);
+
+ for (i = 0; i < instr->ctx.addr.naddrs; i++)
+ writeb_relaxed(instr->ctx.addr.addrs[i],
+ host->addr_va);
+ break;
+
+ case NAND_OP_DATA_IN_INSTR:
+ pr_debug(" ->DATA_IN [%d B%s]\n", instr->ctx.data.len,
+ instr->ctx.data.force_8bit ?
+ ", force 8-bit" : "");
+
+ if (host->mode == USE_DMA_ACCESS)
+ fsmc_read_buf_dma(mtd, instr->ctx.data.buf.in,
+ instr->ctx.data.len);
+ else
+ fsmc_read_buf(mtd, instr->ctx.data.buf.in,
+ instr->ctx.data.len);
+ break;
+
+ case NAND_OP_DATA_OUT_INSTR:
+ pr_debug(" ->DATA_OUT [%d B%s]\n", instr->ctx.data.len,
+ instr->ctx.data.force_8bit ?
+ ", force 8-bit" : "");
+
+ if (host->mode == USE_DMA_ACCESS)
+ fsmc_write_buf_dma(mtd, instr->ctx.data.buf.out,
+ instr->ctx.data.len);
+ else
+ fsmc_write_buf(mtd, instr->ctx.data.buf.out,
+ instr->ctx.data.len);
+ break;
+
+ case NAND_OP_WAITRDY_INSTR:
+ pr_debug(" ->WAITRDY [max %d ms]\n",
+ instr->ctx.waitrdy.timeout_ms);
+
+ ret = nand_soft_waitrdy(chip,
+ instr->ctx.waitrdy.timeout_ms);
+ break;
+ }
+ }
+
+ return ret;
+}
+
/*
* fsmc_read_page_hwecc
* @mtd: mtd info structure
@@ -754,13 +795,11 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
- void __iomem *regs = host->regs_va;
- unsigned int bank = host->bank;
uint32_t err_idx[8];
uint32_t num_err, i;
uint32_t ecc1, ecc2, ecc3, ecc4;
- num_err = (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
+ num_err = (readl_relaxed(host->regs_va + STS) >> 10) & 0xF;
/* no bit flipping */
if (likely(num_err == 0))
@@ -803,10 +842,10 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
* uint64_t array and error offset indexes are populated in err_idx
* array
*/
- ecc1 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
- ecc2 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
- ecc3 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
- ecc4 = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
+ ecc1 = readl_relaxed(host->regs_va + ECC1);
+ ecc2 = readl_relaxed(host->regs_va + ECC2);
+ ecc3 = readl_relaxed(host->regs_va + ECC3);
+ ecc4 = readl_relaxed(host->regs_va + STS);
err_idx[0] = (ecc1 >> 0) & 0x1FFF;
err_idx[1] = (ecc1 >> 13) & 0x1FFF;
@@ -889,6 +928,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
struct mtd_info *mtd;
struct nand_chip *nand;
struct resource *res;
+ void __iomem *base;
dma_cap_mask_t mask;
int ret = 0;
u32 pid;
@@ -923,9 +963,12 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
return PTR_ERR(host->cmd_va);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs");
- host->regs_va = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(host->regs_va))
- return PTR_ERR(host->regs_va);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ host->regs_va = base + FSMC_NOR_REG_SIZE +
+ (host->bank * FSMC_NAND_BANK_SZ);
host->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(host->clk)) {
@@ -942,7 +985,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
* AMBA PrimeCell bus. However it is not a PrimeCell.
*/
for (pid = 0, i = 0; i < 4; i++)
- pid |= (readl(host->regs_va + resource_size(res) - 0x20 + 4 * i) & 255) << (i * 8);
+ pid |= (readl(base + resource_size(res) - 0x20 + 4 * i) & 255) << (i * 8);
host->pid = pid;
dev_info(&pdev->dev, "FSMC device partno %03x, manufacturer %02x, "
"revision %02x, config %02x\n",
@@ -960,9 +1003,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand_set_flash_node(nand, pdev->dev.of_node);
mtd->dev.parent = &pdev->dev;
- nand->IO_ADDR_R = host->data_va;
- nand->IO_ADDR_W = host->data_va;
- nand->cmd_ctrl = fsmc_cmd_ctrl;
+ nand->exec_op = fsmc_exec_op;
+ nand->select_chip = fsmc_select_chip;
nand->chip_delay = 30;
/*
@@ -974,8 +1016,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand->ecc.size = 512;
nand->badblockbits = 7;
- switch (host->mode) {
- case USE_DMA_ACCESS:
+ if (host->mode == USE_DMA_ACCESS) {
dma_cap_zero(mask);
dma_cap_set(DMA_MEMCPY, mask);
host->read_dma_chan = dma_request_channel(mask, filter, NULL);
@@ -988,15 +1029,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Unable to get write dma channel\n");
goto err_req_write_chnl;
}
- nand->read_buf = fsmc_read_buf_dma;
- nand->write_buf = fsmc_write_buf_dma;
- break;
-
- default:
- case USE_WORD_ACCESS:
- nand->read_buf = fsmc_read_buf;
- nand->write_buf = fsmc_write_buf;
- break;
}
if (host->dev_timings)
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/raw/gpio.c
index a8bde6665c24..2780af26d9ab 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/raw/gpio.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand/gpio.c
- *
* Updated, and converted to generic GPIO based driver by Russell King.
*
* Written by Ben Dooks <[email protected]>
diff --git a/drivers/mtd/nand/gpmi-nand/Makefile b/drivers/mtd/nand/raw/gpmi-nand/Makefile
index 3a462487c35e..3a462487c35e 100644
--- a/drivers/mtd/nand/gpmi-nand/Makefile
+++ b/drivers/mtd/nand/raw/gpmi-nand/Makefile
diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/raw/gpmi-nand/bch-regs.h
index 05bb91f2f4c4..05bb91f2f4c4 100644
--- a/drivers/mtd/nand/gpmi-nand/bch-regs.h
+++ b/drivers/mtd/nand/raw/gpmi-nand/bch-regs.h
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
index 97787246af41..97787246af41 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 61fdd733492f..61fdd733492f 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
index 06c1f993912c..06c1f993912c 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-regs.h
index 82114cdc8330..82114cdc8330 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-regs.h
diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c
index cb862793ab6d..cb862793ab6d 100644
--- a/drivers/mtd/nand/hisi504_nand.c
+++ b/drivers/mtd/nand/raw/hisi504_nand.c
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c
index 613b00a9604b..613b00a9604b 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/raw/jz4740_nand.c
diff --git a/drivers/mtd/nand/jz4780_bch.c b/drivers/mtd/nand/raw/jz4780_bch.c
index 731c6051d91e..731c6051d91e 100644
--- a/drivers/mtd/nand/jz4780_bch.c
+++ b/drivers/mtd/nand/raw/jz4780_bch.c
diff --git a/drivers/mtd/nand/jz4780_bch.h b/drivers/mtd/nand/raw/jz4780_bch.h
index bf4718088a3a..bf4718088a3a 100644
--- a/drivers/mtd/nand/jz4780_bch.h
+++ b/drivers/mtd/nand/raw/jz4780_bch.h
diff --git a/drivers/mtd/nand/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c
index e69f6ae4c539..e69f6ae4c539 100644
--- a/drivers/mtd/nand/jz4780_nand.c
+++ b/drivers/mtd/nand/raw/jz4780_nand.c
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
index e357948a7505..e357948a7505 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
index 5f7cc6da0a7f..5f7cc6da0a7f 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
diff --git a/drivers/mtd/nand/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index 03805f9669da..528a8e0342bd 100644
--- a/drivers/mtd/nand/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -379,6 +379,8 @@ struct marvell_nfc_timings {
* return the number of clock periods.
*/
#define TO_CYCLES(ps, period_ns) (DIV_ROUND_UP(ps / 1000, period_ns))
+#define TO_CYCLES64(ps, period_ns) (DIV_ROUND_UP_ULL(div_u64(ps, 1000), \
+ period_ns))
/**
* NAND driver structure filled during the parsing of the ->exec_op() subop
@@ -2236,8 +2238,20 @@ static int marvell_nfc_setup_data_interface(struct mtd_info *mtd, int chipnr,
nfc_tmg.tRHW = TO_CYCLES(max_t(int, sdr->tRHW_min, sdr->tCCS_min),
period_ns);
- /* Use WAIT_MODE (wait for RB line) instead of only relying on delays */
- nfc_tmg.tR = TO_CYCLES(sdr->tWB_max, period_ns);
+ /*
+ * NFCv2: Use WAIT_MODE (wait for RB line), do not rely only on delays.
+ * NFCv1: No WAIT_MODE, tR must be maximal.
+ */
+ if (nfc->caps->is_nfcv2) {
+ nfc_tmg.tR = TO_CYCLES(sdr->tWB_max, period_ns);
+ } else {
+ nfc_tmg.tR = TO_CYCLES64(sdr->tWB_max + sdr->tR_max,
+ period_ns);
+ if (nfc_tmg.tR + 3 > nfc_tmg.tCH)
+ nfc_tmg.tR = nfc_tmg.tCH - 3;
+ else
+ nfc_tmg.tR = 0;
+ }
if (chipnr < 0)
return 0;
@@ -2249,18 +2263,24 @@ static int marvell_nfc_setup_data_interface(struct mtd_info *mtd, int chipnr,
NDTR0_TWP(nfc_tmg.tWP) |
NDTR0_TWH(nfc_tmg.tWH) |
NDTR0_TCS(nfc_tmg.tCS) |
- NDTR0_TCH(nfc_tmg.tCH) |
- NDTR0_RD_CNT_DEL(read_delay) |
- NDTR0_SELCNTR |
- NDTR0_TADL(nfc_tmg.tADL);
+ NDTR0_TCH(nfc_tmg.tCH);
marvell_nand->ndtr1 =
NDTR1_TAR(nfc_tmg.tAR) |
NDTR1_TWHR(nfc_tmg.tWHR) |
- NDTR1_TRHW(nfc_tmg.tRHW) |
- NDTR1_WAIT_MODE |
NDTR1_TR(nfc_tmg.tR);
+ if (nfc->caps->is_nfcv2) {
+ marvell_nand->ndtr0 |=
+ NDTR0_RD_CNT_DEL(read_delay) |
+ NDTR0_SELCNTR |
+ NDTR0_TADL(nfc_tmg.tADL);
+
+ marvell_nand->ndtr1 |=
+ NDTR1_TRHW(nfc_tmg.tRHW) |
+ NDTR1_WAIT_MODE;
+ }
+
return 0;
}
@@ -2395,8 +2415,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
chip->exec_op = marvell_nfc_exec_op;
chip->select_chip = marvell_nfc_select_chip;
- if (nfc->caps->is_nfcv2 &&
- !of_property_read_bool(np, "marvell,nand-keep-config"))
+ if (!of_property_read_bool(np, "marvell,nand-keep-config"))
chip->setup_data_interface = marvell_nfc_setup_data_interface;
mtd = nand_to_mtd(chip);
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c
index b6b97cc9fba6..913b9d1225c6 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/raw/mpc5121_nfc.c
@@ -6,9 +6,8 @@
* by OSADL membership fees in 2009; for details see www.osadl.org.
*
* Based on original driver from Freescale Semiconductor
- * written by John Rigby <[email protected]> on basis
- * of drivers/mtd/nand/mxc_nand.c. Reworked and extended
- * Piotr Ziecik <[email protected]>.
+ * written by John Rigby <[email protected]> on basis of mxc_nand.c.
+ * Reworked and extended by Piotr Ziecik <[email protected]>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c
index 40d86a861a70..40d86a861a70 100644
--- a/drivers/mtd/nand/mtk_ecc.c
+++ b/drivers/mtd/nand/raw/mtk_ecc.c
diff --git a/drivers/mtd/nand/mtk_ecc.h b/drivers/mtd/nand/raw/mtk_ecc.h
index a455df080952..a455df080952 100644
--- a/drivers/mtd/nand/mtk_ecc.h
+++ b/drivers/mtd/nand/raw/mtk_ecc.h
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index 6977da3a26aa..6977da3a26aa 100644
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
index f3be0b2a8869..87b5ee66e501 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/raw/mxc_nand.c
@@ -140,6 +140,8 @@ struct mxc_nand_host;
struct mxc_nand_devtype_data {
void (*preset)(struct mtd_info *);
+ int (*read_page)(struct nand_chip *chip, void *buf, void *oob, bool ecc,
+ int page);
void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
void (*send_page)(struct mtd_info *, unsigned int);
@@ -150,10 +152,9 @@ struct mxc_nand_devtype_data {
u32 (*get_ecc_status)(struct mxc_nand_host *);
const struct mtd_ooblayout_ops *ooblayout;
void (*select_chip)(struct mtd_info *mtd, int chip);
- int (*correct_data)(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc);
int (*setup_data_interface)(struct mtd_info *mtd, int csline,
const struct nand_data_interface *conf);
+ void (*enable_hwecc)(struct nand_chip *chip, bool enable);
/*
* On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
@@ -252,6 +253,109 @@ static void memcpy16_toio(void __iomem *trg, const void *src, int size)
__raw_writew(*s++, t++);
}
+/*
+ * The controller splits a page into data chunks of 512 bytes + partial oob.
+ * There are writesize / 512 such chunks, the size of the partial oob parts is
+ * oobsize / #chunks rounded down to a multiple of 2. The last oob chunk then
+ * contains additionally the byte lost by rounding (if any).
+ * This function handles the needed shuffling between host->data_buf (which
+ * holds a page in natural order, i.e. writesize bytes data + oobsize bytes
+ * spare) and the NFC buffer.
+ */
+static void copy_spare(struct mtd_info *mtd, bool bfrom, void *buf)
+{
+ struct nand_chip *this = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(this);
+ u16 i, oob_chunk_size;
+ u16 num_chunks = mtd->writesize / 512;
+
+ u8 *d = buf;
+ u8 __iomem *s = host->spare0;
+ u16 sparebuf_size = host->devtype_data->spare_len;
+
+ /* size of oob chunk for all but possibly the last one */
+ oob_chunk_size = (host->used_oobsize / num_chunks) & ~1;
+
+ if (bfrom) {
+ for (i = 0; i < num_chunks - 1; i++)
+ memcpy16_fromio(d + i * oob_chunk_size,
+ s + i * sparebuf_size,
+ oob_chunk_size);
+
+ /* the last chunk */
+ memcpy16_fromio(d + i * oob_chunk_size,
+ s + i * sparebuf_size,
+ host->used_oobsize - i * oob_chunk_size);
+ } else {
+ for (i = 0; i < num_chunks - 1; i++)
+ memcpy16_toio(&s[i * sparebuf_size],
+ &d[i * oob_chunk_size],
+ oob_chunk_size);
+
+ /* the last chunk */
+ memcpy16_toio(&s[i * sparebuf_size],
+ &d[i * oob_chunk_size],
+ host->used_oobsize - i * oob_chunk_size);
+ }
+}
+
+/*
+ * MXC NANDFC can only perform full page+spare or spare-only read/write. When
+ * the upper layers perform a read/write buf operation, the saved column address
+ * is used to index into the full page. So usually this function is called with
+ * column == 0 (unless no column cycle is needed indicated by column == -1)
+ */
+static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
+{
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
+
+ /* Write out column address, if necessary */
+ if (column != -1) {
+ host->devtype_data->send_addr(host, column & 0xff,
+ page_addr == -1);
+ if (mtd->writesize > 512)
+ /* another col addr cycle for 2k page */
+ host->devtype_data->send_addr(host,
+ (column >> 8) & 0xff,
+ false);
+ }
+
+ /* Write out page address, if necessary */
+ if (page_addr != -1) {
+ /* paddr_0 - p_addr_7 */
+ host->devtype_data->send_addr(host, (page_addr & 0xff), false);
+
+ if (mtd->writesize > 512) {
+ if (mtd->size >= 0x10000000) {
+ /* paddr_8 - paddr_15 */
+ host->devtype_data->send_addr(host,
+ (page_addr >> 8) & 0xff,
+ false);
+ host->devtype_data->send_addr(host,
+ (page_addr >> 16) & 0xff,
+ true);
+ } else
+ /* paddr_8 - paddr_15 */
+ host->devtype_data->send_addr(host,
+ (page_addr >> 8) & 0xff, true);
+ } else {
+ if (nand_chip->options & NAND_ROW_ADDR_3) {
+ /* paddr_8 - paddr_15 */
+ host->devtype_data->send_addr(host,
+ (page_addr >> 8) & 0xff,
+ false);
+ host->devtype_data->send_addr(host,
+ (page_addr >> 16) & 0xff,
+ true);
+ } else
+ /* paddr_8 - paddr_15 */
+ host->devtype_data->send_addr(host,
+ (page_addr >> 8) & 0xff, true);
+ }
+ }
+}
+
static int check_int_v3(struct mxc_nand_host *host)
{
uint32_t tmp;
@@ -575,6 +679,42 @@ static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
return ret;
}
+static void mxc_nand_enable_hwecc_v1_v2(struct nand_chip *chip, bool enable)
+{
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
+ uint16_t config1;
+
+ if (chip->ecc.mode != NAND_ECC_HW)
+ return;
+
+ config1 = readw(NFC_V1_V2_CONFIG1);
+
+ if (enable)
+ config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
+ else
+ config1 &= ~NFC_V1_V2_CONFIG1_ECC_EN;
+
+ writew(config1, NFC_V1_V2_CONFIG1);
+}
+
+static void mxc_nand_enable_hwecc_v3(struct nand_chip *chip, bool enable)
+{
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
+ uint32_t config2;
+
+ if (chip->ecc.mode != NAND_ECC_HW)
+ return;
+
+ config2 = readl(NFC_V3_CONFIG2);
+
+ if (enable)
+ config2 |= NFC_V3_CONFIG2_ECC_EN;
+ else
+ config2 &= ~NFC_V3_CONFIG2_ECC_EN;
+
+ writel(config2, NFC_V3_CONFIG2);
+}
+
/* This functions is used by upper layer to checks if device is ready */
static int mxc_nand_dev_ready(struct mtd_info *mtd)
{
@@ -585,45 +725,90 @@ static int mxc_nand_dev_ready(struct mtd_info *mtd)
return 1;
}
-static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+static int mxc_nand_read_page_v1(struct nand_chip *chip, void *buf, void *oob,
+ bool ecc, int page)
{
- /*
- * If HW ECC is enabled, we turn it on during init. There is
- * no need to enable again here.
- */
-}
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
+ unsigned int bitflips_corrected = 0;
+ int no_subpages;
+ int i;
-static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
- struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
+ host->devtype_data->enable_hwecc(chip, ecc);
- /*
- * 1-Bit errors are automatically corrected in HW. No need for
- * additional correction. 2-Bit errors cannot be corrected by
- * HW ECC, so we need to return failure
- */
- uint16_t ecc_status = get_ecc_status_v1(host);
+ host->devtype_data->send_cmd(host, NAND_CMD_READ0, false);
+ mxc_do_addr_cycle(mtd, 0, page);
+
+ if (mtd->writesize > 512)
+ host->devtype_data->send_cmd(host, NAND_CMD_READSTART, true);
+
+ no_subpages = mtd->writesize >> 9;
+
+ for (i = 0; i < no_subpages; i++) {
+ uint16_t ecc_stats;
+
+ /* NANDFC buffer 0 is used for page read/write */
+ writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
+
+ writew(NFC_OUTPUT, NFC_V1_V2_CONFIG2);
+
+ /* Wait for operation to complete */
+ wait_op_done(host, true);
- if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
- dev_dbg(host->dev, "HWECC uncorrectable 2-bit ECC error\n");
- return -EBADMSG;
+ ecc_stats = get_ecc_status_v1(host);
+
+ ecc_stats >>= 2;
+
+ if (buf && ecc) {
+ switch (ecc_stats & 0x3) {
+ case 0:
+ default:
+ break;
+ case 1:
+ mtd->ecc_stats.corrected++;
+ bitflips_corrected = 1;
+ break;
+ case 2:
+ mtd->ecc_stats.failed++;
+ break;
+ }
+ }
}
- return 0;
+ if (buf)
+ memcpy32_fromio(buf, host->main_area0, mtd->writesize);
+ if (oob)
+ copy_spare(mtd, true, oob);
+
+ return bitflips_corrected;
}
-static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
+static int mxc_nand_read_page_v2_v3(struct nand_chip *chip, void *buf,
+ void *oob, bool ecc, int page)
{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
- struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
+ unsigned int max_bitflips = 0;
u32 ecc_stat, err;
- int no_subpages = 1;
- int ret = 0;
+ int no_subpages;
u8 ecc_bit_mask, err_limit;
+ host->devtype_data->enable_hwecc(chip, ecc);
+
+ host->devtype_data->send_cmd(host, NAND_CMD_READ0, false);
+ mxc_do_addr_cycle(mtd, 0, page);
+
+ if (mtd->writesize > 512)
+ host->devtype_data->send_cmd(host,
+ NAND_CMD_READSTART, true);
+
+ host->devtype_data->send_page(mtd, NFC_OUTPUT);
+
+ if (buf)
+ memcpy32_fromio(buf, host->main_area0, mtd->writesize);
+ if (oob)
+ copy_spare(mtd, true, oob);
+
ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
@@ -634,25 +819,99 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
do {
err = ecc_stat & ecc_bit_mask;
if (err > err_limit) {
- dev_dbg(host->dev, "UnCorrectable RS-ECC Error\n");
- return -EBADMSG;
+ mtd->ecc_stats.failed++;
} else {
- ret += err;
+ mtd->ecc_stats.corrected += err;
+ max_bitflips = max_t(unsigned int, max_bitflips, err);
}
+
ecc_stat >>= 4;
} while (--no_subpages);
- dev_dbg(host->dev, "%d Symbol Correctable RS-ECC Error\n", ret);
+ return max_bitflips;
+}
- return ret;
+static int mxc_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
+{
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
+ void *oob_buf;
+
+ if (oob_required)
+ oob_buf = chip->oob_poi;
+ else
+ oob_buf = NULL;
+
+ return host->devtype_data->read_page(chip, buf, oob_buf, 1, page);
}
-static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
- u_char *ecc_code)
+static int mxc_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
{
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
+ void *oob_buf;
+
+ if (oob_required)
+ oob_buf = chip->oob_poi;
+ else
+ oob_buf = NULL;
+
+ return host->devtype_data->read_page(chip, buf, oob_buf, 0, page);
+}
+
+static int mxc_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+ int page)
+{
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
+
+ return host->devtype_data->read_page(chip, NULL, chip->oob_poi, 0,
+ page);
+}
+
+static int mxc_nand_write_page(struct nand_chip *chip, const uint8_t *buf,
+ bool ecc, int page)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
+
+ host->devtype_data->enable_hwecc(chip, ecc);
+
+ host->devtype_data->send_cmd(host, NAND_CMD_SEQIN, false);
+ mxc_do_addr_cycle(mtd, 0, page);
+
+ memcpy32_toio(host->main_area0, buf, mtd->writesize);
+ copy_spare(mtd, false, chip->oob_poi);
+
+ host->devtype_data->send_page(mtd, NFC_INPUT);
+ host->devtype_data->send_cmd(host, NAND_CMD_PAGEPROG, true);
+ mxc_do_addr_cycle(mtd, 0, page);
+
return 0;
}
+static int mxc_nand_write_page_ecc(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required,
+ int page)
+{
+ return mxc_nand_write_page(chip, buf, true, page);
+}
+
+static int mxc_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required, int page)
+{
+ return mxc_nand_write_page(chip, buf, false, page);
+}
+
+static int mxc_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+ int page)
+{
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
+
+ memset(host->data_buf, 0xff, mtd->writesize);
+
+ return mxc_nand_write_page(chip, host->data_buf, false, page);
+}
+
static u_char mxc_nand_read_byte(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
@@ -772,109 +1031,6 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
}
-/*
- * The controller splits a page into data chunks of 512 bytes + partial oob.
- * There are writesize / 512 such chunks, the size of the partial oob parts is
- * oobsize / #chunks rounded down to a multiple of 2. The last oob chunk then
- * contains additionally the byte lost by rounding (if any).
- * This function handles the needed shuffling between host->data_buf (which
- * holds a page in natural order, i.e. writesize bytes data + oobsize bytes
- * spare) and the NFC buffer.
- */
-static void copy_spare(struct mtd_info *mtd, bool bfrom)
-{
- struct nand_chip *this = mtd_to_nand(mtd);
- struct mxc_nand_host *host = nand_get_controller_data(this);
- u16 i, oob_chunk_size;
- u16 num_chunks = mtd->writesize / 512;
-
- u8 *d = host->data_buf + mtd->writesize;
- u8 __iomem *s = host->spare0;
- u16 sparebuf_size = host->devtype_data->spare_len;
-
- /* size of oob chunk for all but possibly the last one */
- oob_chunk_size = (host->used_oobsize / num_chunks) & ~1;
-
- if (bfrom) {
- for (i = 0; i < num_chunks - 1; i++)
- memcpy16_fromio(d + i * oob_chunk_size,
- s + i * sparebuf_size,
- oob_chunk_size);
-
- /* the last chunk */
- memcpy16_fromio(d + i * oob_chunk_size,
- s + i * sparebuf_size,
- host->used_oobsize - i * oob_chunk_size);
- } else {
- for (i = 0; i < num_chunks - 1; i++)
- memcpy16_toio(&s[i * sparebuf_size],
- &d[i * oob_chunk_size],
- oob_chunk_size);
-
- /* the last chunk */
- memcpy16_toio(&s[i * sparebuf_size],
- &d[i * oob_chunk_size],
- host->used_oobsize - i * oob_chunk_size);
- }
-}
-
-/*
- * MXC NANDFC can only perform full page+spare or spare-only read/write. When
- * the upper layers perform a read/write buf operation, the saved column address
- * is used to index into the full page. So usually this function is called with
- * column == 0 (unless no column cycle is needed indicated by column == -1)
- */
-static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
-{
- struct nand_chip *nand_chip = mtd_to_nand(mtd);
- struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
-
- /* Write out column address, if necessary */
- if (column != -1) {
- host->devtype_data->send_addr(host, column & 0xff,
- page_addr == -1);
- if (mtd->writesize > 512)
- /* another col addr cycle for 2k page */
- host->devtype_data->send_addr(host,
- (column >> 8) & 0xff,
- false);
- }
-
- /* Write out page address, if necessary */
- if (page_addr != -1) {
- /* paddr_0 - p_addr_7 */
- host->devtype_data->send_addr(host, (page_addr & 0xff), false);
-
- if (mtd->writesize > 512) {
- if (mtd->size >= 0x10000000) {
- /* paddr_8 - paddr_15 */
- host->devtype_data->send_addr(host,
- (page_addr >> 8) & 0xff,
- false);
- host->devtype_data->send_addr(host,
- (page_addr >> 16) & 0xff,
- true);
- } else
- /* paddr_8 - paddr_15 */
- host->devtype_data->send_addr(host,
- (page_addr >> 8) & 0xff, true);
- } else {
- if (nand_chip->options & NAND_ROW_ADDR_3) {
- /* paddr_8 - paddr_15 */
- host->devtype_data->send_addr(host,
- (page_addr >> 8) & 0xff,
- false);
- host->devtype_data->send_addr(host,
- (page_addr >> 16) & 0xff,
- true);
- } else
- /* paddr_8 - paddr_15 */
- host->devtype_data->send_addr(host,
- (page_addr >> 8) & 0xff, true);
- }
- }
-}
-
#define MXC_V1_ECCBYTES 5
static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
@@ -1235,57 +1391,6 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
mxc_do_addr_cycle(mtd, column, page_addr);
break;
- case NAND_CMD_READ0:
- case NAND_CMD_READOOB:
- if (command == NAND_CMD_READ0)
- host->buf_start = column;
- else
- host->buf_start = column + mtd->writesize;
-
- command = NAND_CMD_READ0; /* only READ0 is valid */
-
- host->devtype_data->send_cmd(host, command, false);
- WARN_ONCE(column < 0,
- "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
- command, column, page_addr);
- mxc_do_addr_cycle(mtd, 0, page_addr);
-
- if (mtd->writesize > 512)
- host->devtype_data->send_cmd(host,
- NAND_CMD_READSTART, true);
-
- host->devtype_data->send_page(mtd, NFC_OUTPUT);
-
- memcpy32_fromio(host->data_buf, host->main_area0,
- mtd->writesize);
- copy_spare(mtd, true);
- break;
-
- case NAND_CMD_SEQIN:
- if (column >= mtd->writesize)
- /* call ourself to read a page */
- mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
-
- host->buf_start = column;
-
- host->devtype_data->send_cmd(host, command, false);
- WARN_ONCE(column < -1,
- "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
- command, column, page_addr);
- mxc_do_addr_cycle(mtd, 0, page_addr);
- break;
-
- case NAND_CMD_PAGEPROG:
- memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
- copy_spare(mtd, false);
- host->devtype_data->send_page(mtd, NFC_INPUT);
- host->devtype_data->send_cmd(host, command, true);
- WARN_ONCE(column != -1 || page_addr != -1,
- "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
- command, column, page_addr);
- mxc_do_addr_cycle(mtd, column, page_addr);
- break;
-
case NAND_CMD_READID:
host->devtype_data->send_cmd(host, command, true);
mxc_do_addr_cycle(mtd, column, page_addr);
@@ -1397,6 +1502,7 @@ static struct nand_bbt_descr bbt_mirror_descr = {
/* v1 + irqpending_quirk: i.MX21 */
static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
.preset = preset_v1,
+ .read_page = mxc_nand_read_page_v1,
.send_cmd = send_cmd_v1_v2,
.send_addr = send_addr_v1_v2,
.send_page = send_page_v1,
@@ -1407,7 +1513,7 @@ static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
.get_ecc_status = get_ecc_status_v1,
.ooblayout = &mxc_v1_ooblayout_ops,
.select_chip = mxc_nand_select_chip_v1_v3,
- .correct_data = mxc_nand_correct_data_v1,
+ .enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
.irqpending_quirk = 1,
.needs_ip = 0,
.regs_offset = 0xe00,
@@ -1420,6 +1526,7 @@ static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
.preset = preset_v1,
+ .read_page = mxc_nand_read_page_v1,
.send_cmd = send_cmd_v1_v2,
.send_addr = send_addr_v1_v2,
.send_page = send_page_v1,
@@ -1430,7 +1537,7 @@ static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
.get_ecc_status = get_ecc_status_v1,
.ooblayout = &mxc_v1_ooblayout_ops,
.select_chip = mxc_nand_select_chip_v1_v3,
- .correct_data = mxc_nand_correct_data_v1,
+ .enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
.irqpending_quirk = 0,
.needs_ip = 0,
.regs_offset = 0xe00,
@@ -1444,6 +1551,7 @@ static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
/* v21: i.MX25, i.MX35 */
static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
.preset = preset_v2,
+ .read_page = mxc_nand_read_page_v2_v3,
.send_cmd = send_cmd_v1_v2,
.send_addr = send_addr_v1_v2,
.send_page = send_page_v2,
@@ -1454,8 +1562,8 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
.get_ecc_status = get_ecc_status_v2,
.ooblayout = &mxc_v2_ooblayout_ops,
.select_chip = mxc_nand_select_chip_v2,
- .correct_data = mxc_nand_correct_data_v2_v3,
.setup_data_interface = mxc_nand_v2_setup_data_interface,
+ .enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
.irqpending_quirk = 0,
.needs_ip = 0,
.regs_offset = 0x1e00,
@@ -1469,6 +1577,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
/* v3.2a: i.MX51 */
static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
.preset = preset_v3,
+ .read_page = mxc_nand_read_page_v2_v3,
.send_cmd = send_cmd_v3,
.send_addr = send_addr_v3,
.send_page = send_page_v3,
@@ -1479,7 +1588,7 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
.get_ecc_status = get_ecc_status_v3,
.ooblayout = &mxc_v2_ooblayout_ops,
.select_chip = mxc_nand_select_chip_v1_v3,
- .correct_data = mxc_nand_correct_data_v2_v3,
+ .enable_hwecc = mxc_nand_enable_hwecc_v3,
.irqpending_quirk = 0,
.needs_ip = 1,
.regs_offset = 0,
@@ -1494,6 +1603,7 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
/* v3.2b: i.MX53 */
static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
.preset = preset_v3,
+ .read_page = mxc_nand_read_page_v2_v3,
.send_cmd = send_cmd_v3,
.send_addr = send_addr_v3,
.send_page = send_page_v3,
@@ -1504,7 +1614,7 @@ static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
.get_ecc_status = get_ecc_status_v3,
.ooblayout = &mxc_v2_ooblayout_ops,
.select_chip = mxc_nand_select_chip_v1_v3,
- .correct_data = mxc_nand_correct_data_v2_v3,
+ .enable_hwecc = mxc_nand_enable_hwecc_v3,
.irqpending_quirk = 0,
.needs_ip = 1,
.regs_offset = 0,
@@ -1751,9 +1861,12 @@ static int mxcnd_probe(struct platform_device *pdev)
switch (this->ecc.mode) {
case NAND_ECC_HW:
- this->ecc.calculate = mxc_nand_calculate_ecc;
- this->ecc.hwctl = mxc_nand_enable_hwecc;
- this->ecc.correct = host->devtype_data->correct_data;
+ this->ecc.read_page = mxc_nand_read_page;
+ this->ecc.read_page_raw = mxc_nand_read_page_raw;
+ this->ecc.read_oob = mxc_nand_read_oob;
+ this->ecc.write_page = mxc_nand_write_page_ecc;
+ this->ecc.write_page_raw = mxc_nand_write_page_raw;
+ this->ecc.write_oob = mxc_nand_write_oob;
break;
case NAND_ECC_SOFT:
diff --git a/drivers/mtd/nand/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
index 22f060f38123..22f060f38123 100644
--- a/drivers/mtd/nand/nand_amd.c
+++ b/drivers/mtd/nand/raw/nand_amd.c
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index e70ca16a5118..e70ca16a5118 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 36092850be2c..36092850be2c 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/raw/nand_bch.c
index 505441c9373b..505441c9373b 100644
--- a/drivers/mtd/nand/nand_bch.c
+++ b/drivers/mtd/nand/raw/nand_bch.c
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c
index 7613a0388044..3630f0fe8fa4 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/raw/nand_ecc.c
@@ -2,8 +2,6 @@
* This file contains an ECC algorithm that detects and corrects 1 bit
* errors in a 256 byte block of data.
*
- * drivers/mtd/nand/nand_ecc.c
- *
* Copyright © 2008 Koninklijke Philips Electronics NV.
* Author: Frans Meulenbroeks
*
diff --git a/drivers/mtd/nand/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index d542908a0ebb..d542908a0ebb 100644
--- a/drivers/mtd/nand/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
index 5423c3bb388e..5423c3bb388e 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
diff --git a/drivers/mtd/nand/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
index d290ff2a6d2f..d290ff2a6d2f 100644
--- a/drivers/mtd/nand/nand_macronix.c
+++ b/drivers/mtd/nand/raw/nand_macronix.c
diff --git a/drivers/mtd/nand/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index 02e109ae73f1..02e109ae73f1 100644
--- a/drivers/mtd/nand/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
diff --git a/drivers/mtd/nand/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
index ef022f62f74c..ef022f62f74c 100644
--- a/drivers/mtd/nand/nand_samsung.c
+++ b/drivers/mtd/nand/raw/nand_samsung.c
diff --git a/drivers/mtd/nand/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index 9400d039ddbd..9400d039ddbd 100644
--- a/drivers/mtd/nand/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
diff --git a/drivers/mtd/nand/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 57df857074e6..ab43f027cd23 100644
--- a/drivers/mtd/nand/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -35,6 +35,32 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
(chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
!(chip->id.data[4] & 0x80) /* !BENAND */)
mtd->oobsize = 32 * mtd->writesize >> 9;
+
+ /*
+ * Extract ECC requirements from 6th id byte.
+ * For Toshiba SLC, ecc requrements are as follows:
+ * - 43nm: 1 bit ECC for each 512Byte is required.
+ * - 32nm: 4 bit ECC for each 512Byte is required.
+ * - 24nm: 8 bit ECC for each 512Byte is required.
+ */
+ if (chip->id.len >= 6 && nand_is_slc(chip)) {
+ chip->ecc_step_ds = 512;
+ switch (chip->id.data[5] & 0x7) {
+ case 0x4:
+ chip->ecc_strength_ds = 1;
+ break;
+ case 0x5:
+ chip->ecc_strength_ds = 4;
+ break;
+ case 0x6:
+ chip->ecc_strength_ds = 8;
+ break;
+ default:
+ WARN(1, "Could not get ECC info");
+ chip->ecc_step_ds = 0;
+ break;
+ }
+ }
}
static int toshiba_nand_init(struct nand_chip *chip)
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
index 44322a363ba5..44322a363ba5 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/raw/nandsim.c
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/raw/ndfc.c
index d8a806894937..d8a806894937 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/raw/ndfc.c
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c
index af5b32c9a791..af5b32c9a791 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/raw/nuc900_nand.c
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/raw/omap2.c
index 8cdf7d3d8fa7..8cdf7d3d8fa7 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
diff --git a/drivers/mtd/nand/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c
index a3f32f939cc1..a3f32f939cc1 100644
--- a/drivers/mtd/nand/omap_elm.c
+++ b/drivers/mtd/nand/raw/omap_elm.c
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c
index 5a5aa1f07d07..7825fd3ce66b 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/raw/orion_nand.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand/orion_nand.c
- *
* NAND support for Marvell Orion SoC platforms
*
* Tzachi Perelstein <[email protected]>
diff --git a/drivers/mtd/nand/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c
index d649d5944826..d649d5944826 100644
--- a/drivers/mtd/nand/oxnas_nand.c
+++ b/drivers/mtd/nand/raw/oxnas_nand.c
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c
index a47a7e4bd25a..a47a7e4bd25a 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/raw/pasemi_nand.c
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c
index 925a1323604d..925a1323604d 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/raw/plat_nand.c
diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
index 563b759ffca6..563b759ffca6 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/raw/r852.c
index 595635b9e9de..595635b9e9de 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/raw/r852.c
diff --git a/drivers/mtd/nand/r852.h b/drivers/mtd/nand/raw/r852.h
index 8713c57f6207..8713c57f6207 100644
--- a/drivers/mtd/nand/r852.h
+++ b/drivers/mtd/nand/raw/r852.h
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
index 4c383eeec6f6..b5bc5f106c09 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/raw/s3c2410.c
@@ -1,5 +1,4 @@
-/* linux/drivers/mtd/nand/s3c2410.c
- *
+/*
* Copyright © 2004-2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <[email protected]>
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index c4e7755448e6..c4e7755448e6 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c
index f59c455d9f51..e93df02c825e 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/raw/sharpsl.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand/sharpsl.c
- *
* Copyright (C) 2004 Richard Purdie
* Copyright (C) 2008 Dmitry Baryshkov
*
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/raw/sm_common.c
index c378705c6e2b..c378705c6e2b 100644
--- a/drivers/mtd/nand/sm_common.c
+++ b/drivers/mtd/nand/raw/sm_common.c
diff --git a/drivers/mtd/nand/sm_common.h b/drivers/mtd/nand/raw/sm_common.h
index 1581671b05ae..1581671b05ae 100644
--- a/drivers/mtd/nand/sm_common.h
+++ b/drivers/mtd/nand/raw/sm_common.h
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c
index 575997d0ef8a..9824a9923583 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/raw/socrates_nand.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand/socrates_nand.c
- *
* Copyright © 2008 Ilya Yanok, Emcraft Systems
*
*
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index f5a55c63935c..f5a55c63935c 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
diff --git a/drivers/mtd/nand/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c
index c5bee00b7f5e..c5bee00b7f5e 100644
--- a/drivers/mtd/nand/tango_nand.c
+++ b/drivers/mtd/nand/raw/tango_nand.c
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c
index dcaa924502de..dcaa924502de 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/raw/tmio_nand.c
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
index b567d212fe7d..b567d212fe7d 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/raw/txx9ndfmc.c
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c
index 80d31a58e558..5d7a1f8f580f 100644
--- a/drivers/mtd/nand/vf610_nfc.c
+++ b/drivers/mtd/nand/raw/vf610_nfc.c
@@ -511,21 +511,6 @@ static void vf610_nfc_select_chip(struct mtd_info *mtd, int chip)
vf610_nfc_write(nfc, NFC_ROW_ADDR, tmp);
}
-/* Count the number of 0's in buff up to max_bits */
-static inline int count_written_bits(uint8_t *buff, int size, int max_bits)
-{
- uint32_t *buff32 = (uint32_t *)buff;
- int k, written_bits = 0;
-
- for (k = 0; k < (size / 4); k++) {
- written_bits += hweight32(~buff32[k]);
- if (unlikely(written_bits > max_bits))
- break;
- }
-
- return written_bits;
-}
-
static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat,
uint8_t *oob, int page)
{
@@ -682,7 +667,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
dev_err(nfc->dev,
"Only one NAND chip supported!\n");
err = -EINVAL;
- goto error;
+ goto err_disable_clk;
}
nand_set_flash_node(chip, child);
@@ -692,7 +677,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
if (!nand_get_flash_node(chip)) {
dev_err(nfc->dev, "NAND chip sub-node missing!\n");
err = -ENODEV;
- goto err_clk;
+ goto err_disable_clk;
}
chip->dev_ready = vf610_nfc_dev_ready;
@@ -712,7 +697,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
err = devm_request_irq(nfc->dev, irq, vf610_nfc_irq, 0, DRV_NAME, mtd);
if (err) {
dev_err(nfc->dev, "Error requesting IRQ!\n");
- goto error;
+ goto err_disable_clk;
}
vf610_nfc_preinit_controller(nfc);
@@ -720,7 +705,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
/* first scan to find the device and get the page size */
err = nand_scan_ident(mtd, 1, NULL);
if (err)
- goto error;
+ goto err_disable_clk;
vf610_nfc_init_controller(nfc);
@@ -732,20 +717,20 @@ static int vf610_nfc_probe(struct platform_device *pdev)
if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
dev_err(nfc->dev, "Unsupported flash page size\n");
err = -ENXIO;
- goto error;
+ goto err_disable_clk;
}
if (chip->ecc.mode == NAND_ECC_HW) {
if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
dev_err(nfc->dev, "Unsupported flash with hwecc\n");
err = -ENXIO;
- goto error;
+ goto err_disable_clk;
}
if (chip->ecc.size != mtd->writesize) {
dev_err(nfc->dev, "Step size needs to be page size\n");
err = -ENXIO;
- goto error;
+ goto err_disable_clk;
}
/* Only 64 byte ECC layouts known */
@@ -765,7 +750,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
} else {
dev_err(nfc->dev, "Unsupported ECC strength\n");
err = -ENXIO;
- goto error;
+ goto err_disable_clk;
}
chip->ecc.read_page = vf610_nfc_read_page;
@@ -777,16 +762,19 @@ static int vf610_nfc_probe(struct platform_device *pdev)
/* second phase scan */
err = nand_scan_tail(mtd);
if (err)
- goto error;
+ goto err_disable_clk;
platform_set_drvdata(pdev, mtd);
/* Register device in MTD */
- return mtd_device_register(mtd, NULL, 0);
+ err = mtd_device_register(mtd, NULL, 0);
+ if (err)
+ goto err_cleanup_nand;
+ return 0;
-error:
- of_node_put(nand_get_flash_node(chip));
-err_clk:
+err_cleanup_nand:
+ nand_cleanup(chip);
+err_disable_clk:
clk_disable_unprepare(nfc->clk);
return err;
}
diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c
index 9926b4e3d69d..9926b4e3d69d 100644
--- a/drivers/mtd/nand/xway_nand.c
+++ b/drivers/mtd/nand/raw/xway_nand.c
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index 4237c7cebf02..fa176f5937bb 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -17,7 +17,7 @@
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/mtd/nand_ecc.h>
-#include "nand/sm_common.h"
+#include "nand/raw/sm_common.h"
#include "sm_ftl.h"
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 3bf8f954b642..3102bd754d18 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -1,6 +1,4 @@
/*
- * linux/include/linux/mtd/bbm.h
- *
* NAND family Bad Block Management (BBM) header file
* - Bad Block Table (BBT) implementation
*
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
new file mode 100644
index 000000000000..792ea5c26329
--- /dev/null
+++ b/include/linux/mtd/nand.h
@@ -0,0 +1,731 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2017 - Free Electrons
+ *
+ * Authors:
+ * Boris Brezillon <[email protected]>
+ * Peter Pan <[email protected]>
+ */
+
+#ifndef __LINUX_MTD_NAND_H
+#define __LINUX_MTD_NAND_H
+
+#include <linux/mtd/mtd.h>
+
+/**
+ * struct nand_memory_organization - Memory organization structure
+ * @bits_per_cell: number of bits per NAND cell
+ * @pagesize: page size
+ * @oobsize: OOB area size
+ * @pages_per_eraseblock: number of pages per eraseblock
+ * @eraseblocks_per_lun: number of eraseblocks per LUN (Logical Unit Number)
+ * @planes_per_lun: number of planes per LUN
+ * @luns_per_target: number of LUN per target (target is a synonym for die)
+ * @ntargets: total number of targets exposed by the NAND device
+ */
+struct nand_memory_organization {
+ unsigned int bits_per_cell;
+ unsigned int pagesize;
+ unsigned int oobsize;
+ unsigned int pages_per_eraseblock;
+ unsigned int eraseblocks_per_lun;
+ unsigned int planes_per_lun;
+ unsigned int luns_per_target;
+ unsigned int ntargets;
+};
+
+#define NAND_MEMORG(bpc, ps, os, ppe, epl, ppl, lpt, nt) \
+ { \
+ .bits_per_cell = (bpc), \
+ .pagesize = (ps), \
+ .oobsize = (os), \
+ .pages_per_eraseblock = (ppe), \
+ .eraseblocks_per_lun = (epl), \
+ .planes_per_lun = (ppl), \
+ .luns_per_target = (lpt), \
+ .ntargets = (nt), \
+ }
+
+/**
+ * struct nand_row_converter - Information needed to convert an absolute offset
+ * into a row address
+ * @lun_addr_shift: position of the LUN identifier in the row address
+ * @eraseblock_addr_shift: position of the eraseblock identifier in the row
+ * address
+ */
+struct nand_row_converter {
+ unsigned int lun_addr_shift;
+ unsigned int eraseblock_addr_shift;
+};
+
+/**
+ * struct nand_pos - NAND position object
+ * @target: the NAND target/die
+ * @lun: the LUN identifier
+ * @plane: the plane within the LUN
+ * @eraseblock: the eraseblock within the LUN
+ * @page: the page within the LUN
+ *
+ * These information are usually used by specific sub-layers to select the
+ * appropriate target/die and generate a row address to pass to the device.
+ */
+struct nand_pos {
+ unsigned int target;
+ unsigned int lun;
+ unsigned int plane;
+ unsigned int eraseblock;
+ unsigned int page;
+};
+
+/**
+ * struct nand_page_io_req - NAND I/O request object
+ * @pos: the position this I/O request is targeting
+ * @dataoffs: the offset within the page
+ * @datalen: number of data bytes to read from/write to this page
+ * @databuf: buffer to store data in or get data from
+ * @ooboffs: the OOB offset within the page
+ * @ooblen: the number of OOB bytes to read from/write to this page
+ * @oobbuf: buffer to store OOB data in or get OOB data from
+ *
+ * This object is used to pass per-page I/O requests to NAND sub-layers. This
+ * way all useful information are already formatted in a useful way and
+ * specific NAND layers can focus on translating these information into
+ * specific commands/operations.
+ */
+struct nand_page_io_req {
+ struct nand_pos pos;
+ unsigned int dataoffs;
+ unsigned int datalen;
+ union {
+ const void *out;
+ void *in;
+ } databuf;
+ unsigned int ooboffs;
+ unsigned int ooblen;
+ union {
+ const void *out;
+ void *in;
+ } oobbuf;
+};
+
+/**
+ * struct nand_ecc_req - NAND ECC requirements
+ * @strength: ECC strength
+ * @step_size: ECC step/block size
+ */
+struct nand_ecc_req {
+ unsigned int strength;
+ unsigned int step_size;
+};
+
+#define NAND_ECCREQ(str, stp) { .strength = (str), .step_size = (stp) }
+
+/**
+ * struct nand_bbt - bad block table object
+ * @cache: in memory BBT cache
+ */
+struct nand_bbt {
+ unsigned long *cache;
+};
+
+struct nand_device;
+
+/**
+ * struct nand_ops - NAND operations
+ * @erase: erase a specific block. No need to check if the block is bad before
+ * erasing, this has been taken care of by the generic NAND layer
+ * @markbad: mark a specific block bad. No need to check if the block is
+ * already marked bad, this has been taken care of by the generic
+ * NAND layer. This method should just write the BBM (Bad Block
+ * Marker) so that future call to struct_nand_ops->isbad() return
+ * true
+ * @isbad: check whether a block is bad or not. This method should just read
+ * the BBM and return whether the block is bad or not based on what it
+ * reads
+ *
+ * These are all low level operations that should be implemented by specialized
+ * NAND layers (SPI NAND, raw NAND, ...).
+ */
+struct nand_ops {
+ int (*erase)(struct nand_device *nand, const struct nand_pos *pos);
+ int (*markbad)(struct nand_device *nand, const struct nand_pos *pos);
+ bool (*isbad)(struct nand_device *nand, const struct nand_pos *pos);
+};
+
+/**
+ * struct nand_device - NAND device
+ * @mtd: MTD instance attached to the NAND device
+ * @memorg: memory layout
+ * @eccreq: ECC requirements
+ * @rowconv: position to row address converter
+ * @bbt: bad block table info
+ * @ops: NAND operations attached to the NAND device
+ *
+ * Generic NAND object. Specialized NAND layers (raw NAND, SPI NAND, OneNAND)
+ * should declare their own NAND object embedding a nand_device struct (that's
+ * how inheritance is done).
+ * struct_nand_device->memorg and struct_nand_device->eccreq should be filled
+ * at device detection time to reflect the NAND device
+ * capabilities/requirements. Once this is done nanddev_init() can be called.
+ * It will take care of converting NAND information into MTD ones, which means
+ * the specialized NAND layers should never manually tweak
+ * struct_nand_device->mtd except for the ->_read/write() hooks.
+ */
+struct nand_device {
+ struct mtd_info mtd;
+ struct nand_memory_organization memorg;
+ struct nand_ecc_req eccreq;
+ struct nand_row_converter rowconv;
+ struct nand_bbt bbt;
+ const struct nand_ops *ops;
+};
+
+/**
+ * struct nand_io_iter - NAND I/O iterator
+ * @req: current I/O request
+ * @oobbytes_per_page: maximum number of OOB bytes per page
+ * @dataleft: remaining number of data bytes to read/write
+ * @oobleft: remaining number of OOB bytes to read/write
+ *
+ * Can be used by specialized NAND layers to iterate over all pages covered
+ * by an MTD I/O request, which should greatly simplifies the boiler-plate
+ * code needed to read/write data from/to a NAND device.
+ */
+struct nand_io_iter {
+ struct nand_page_io_req req;
+ unsigned int oobbytes_per_page;
+ unsigned int dataleft;
+ unsigned int oobleft;
+};
+
+/**
+ * mtd_to_nanddev() - Get the NAND device attached to the MTD instance
+ * @mtd: MTD instance
+ *
+ * Return: the NAND device embedding @mtd.
+ */
+static inline struct nand_device *mtd_to_nanddev(struct mtd_info *mtd)
+{
+ return container_of(mtd, struct nand_device, mtd);
+}
+
+/**
+ * nanddev_to_mtd() - Get the MTD device attached to a NAND device
+ * @nand: NAND device
+ *
+ * Return: the MTD device embedded in @nand.
+ */
+static inline struct mtd_info *nanddev_to_mtd(struct nand_device *nand)
+{
+ return &nand->mtd;
+}
+
+/*
+ * nanddev_bits_per_cell() - Get the number of bits per cell
+ * @nand: NAND device
+ *
+ * Return: the number of bits per cell.
+ */
+static inline unsigned int nanddev_bits_per_cell(const struct nand_device *nand)
+{
+ return nand->memorg.bits_per_cell;
+}
+
+/**
+ * nanddev_page_size() - Get NAND page size
+ * @nand: NAND device
+ *
+ * Return: the page size.
+ */
+static inline size_t nanddev_page_size(const struct nand_device *nand)
+{
+ return nand->memorg.pagesize;
+}
+
+/**
+ * nanddev_per_page_oobsize() - Get NAND OOB size
+ * @nand: NAND device
+ *
+ * Return: the OOB size.
+ */
+static inline unsigned int
+nanddev_per_page_oobsize(const struct nand_device *nand)
+{
+ return nand->memorg.oobsize;
+}
+
+/**
+ * nanddev_pages_per_eraseblock() - Get the number of pages per eraseblock
+ * @nand: NAND device
+ *
+ * Return: the number of pages per eraseblock.
+ */
+static inline unsigned int
+nanddev_pages_per_eraseblock(const struct nand_device *nand)
+{
+ return nand->memorg.pages_per_eraseblock;
+}
+
+/**
+ * nanddev_per_page_oobsize() - Get NAND erase block size
+ * @nand: NAND device
+ *
+ * Return: the eraseblock size.
+ */
+static inline size_t nanddev_eraseblock_size(const struct nand_device *nand)
+{
+ return nand->memorg.pagesize * nand->memorg.pages_per_eraseblock;
+}
+
+/**
+ * nanddev_eraseblocks_per_lun() - Get the number of eraseblocks per LUN
+ * @nand: NAND device
+ *
+ * Return: the number of eraseblocks per LUN.
+ */
+static inline unsigned int
+nanddev_eraseblocks_per_lun(const struct nand_device *nand)
+{
+ return nand->memorg.eraseblocks_per_lun;
+}
+
+/**
+ * nanddev_target_size() - Get the total size provided by a single target/die
+ * @nand: NAND device
+ *
+ * Return: the total size exposed by a single target/die in bytes.
+ */
+static inline u64 nanddev_target_size(const struct nand_device *nand)
+{
+ return (u64)nand->memorg.luns_per_target *
+ nand->memorg.eraseblocks_per_lun *
+ nand->memorg.pages_per_eraseblock *
+ nand->memorg.pagesize;
+}
+
+/**
+ * nanddev_ntarget() - Get the total of targets
+ * @nand: NAND device
+ *
+ * Return: the number of targets/dies exposed by @nand.
+ */
+static inline unsigned int nanddev_ntargets(const struct nand_device *nand)
+{
+ return nand->memorg.ntargets;
+}
+
+/**
+ * nanddev_neraseblocks() - Get the total number of erasablocks
+ * @nand: NAND device
+ *
+ * Return: the total number of eraseblocks exposed by @nand.
+ */
+static inline unsigned int nanddev_neraseblocks(const struct nand_device *nand)
+{
+ return (u64)nand->memorg.luns_per_target *
+ nand->memorg.eraseblocks_per_lun *
+ nand->memorg.pages_per_eraseblock;
+}
+
+/**
+ * nanddev_size() - Get NAND size
+ * @nand: NAND device
+ *
+ * Return: the total size (in bytes) exposed by @nand.
+ */
+static inline u64 nanddev_size(const struct nand_device *nand)
+{
+ return nanddev_target_size(nand) * nanddev_ntargets(nand);
+}
+
+/**
+ * nanddev_get_memorg() - Extract memory organization info from a NAND device
+ * @nand: NAND device
+ *
+ * This can be used by the upper layer to fill the memorg info before calling
+ * nanddev_init().
+ *
+ * Return: the memorg object embedded in the NAND device.
+ */
+static inline struct nand_memory_organization *
+nanddev_get_memorg(struct nand_device *nand)
+{
+ return &nand->memorg;
+}
+
+int nanddev_init(struct nand_device *nand, const struct nand_ops *ops,
+ struct module *owner);
+void nanddev_cleanup(struct nand_device *nand);
+
+/**
+ * nanddev_register() - Register a NAND device
+ * @nand: NAND device
+ *
+ * Register a NAND device.
+ * This function is just a wrapper around mtd_device_register()
+ * registering the MTD device embedded in @nand.
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static inline int nanddev_register(struct nand_device *nand)
+{
+ return mtd_device_register(&nand->mtd, NULL, 0);
+}
+
+/**
+ * nanddev_unregister() - Unregister a NAND device
+ * @nand: NAND device
+ *
+ * Unregister a NAND device.
+ * This function is just a wrapper around mtd_device_unregister()
+ * unregistering the MTD device embedded in @nand.
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static inline int nanddev_unregister(struct nand_device *nand)
+{
+ return mtd_device_unregister(&nand->mtd);
+}
+
+/**
+ * nanddev_set_of_node() - Attach a DT node to a NAND device
+ * @nand: NAND device
+ * @np: DT node
+ *
+ * Attach a DT node to a NAND device.
+ */
+static inline void nanddev_set_of_node(struct nand_device *nand,
+ struct device_node *np)
+{
+ mtd_set_of_node(&nand->mtd, np);
+}
+
+/**
+ * nanddev_get_of_node() - Retrieve the DT node attached to a NAND device
+ * @nand: NAND device
+ *
+ * Return: the DT node attached to @nand.
+ */
+static inline struct device_node *nanddev_get_of_node(struct nand_device *nand)
+{
+ return mtd_get_of_node(&nand->mtd);
+}
+
+/**
+ * nanddev_offs_to_pos() - Convert an absolute NAND offset into a NAND position
+ * @nand: NAND device
+ * @offs: absolute NAND offset (usually passed by the MTD layer)
+ * @pos: a NAND position object to fill in
+ *
+ * Converts @offs into a nand_pos representation.
+ *
+ * Return: the offset within the NAND page pointed by @pos.
+ */
+static inline unsigned int nanddev_offs_to_pos(struct nand_device *nand,
+ loff_t offs,
+ struct nand_pos *pos)
+{
+ unsigned int pageoffs;
+ u64 tmp = offs;
+
+ pageoffs = do_div(tmp, nand->memorg.pagesize);
+ pos->page = do_div(tmp, nand->memorg.pages_per_eraseblock);
+ pos->eraseblock = do_div(tmp, nand->memorg.eraseblocks_per_lun);
+ pos->plane = pos->eraseblock % nand->memorg.planes_per_lun;
+ pos->lun = do_div(tmp, nand->memorg.luns_per_target);
+ pos->target = tmp;
+
+ return pageoffs;
+}
+
+/**
+ * nanddev_pos_cmp() - Compare two NAND positions
+ * @a: First NAND position
+ * @b: Second NAND position
+ *
+ * Compares two NAND positions.
+ *
+ * Return: -1 if @a < @b, 0 if @a == @b and 1 if @a > @b.
+ */
+static inline int nanddev_pos_cmp(const struct nand_pos *a,
+ const struct nand_pos *b)
+{
+ if (a->target != b->target)
+ return a->target < b->target ? -1 : 1;
+
+ if (a->lun != b->lun)
+ return a->lun < b->lun ? -1 : 1;
+
+ if (a->eraseblock != b->eraseblock)
+ return a->eraseblock < b->eraseblock ? -1 : 1;
+
+ if (a->page != b->page)
+ return a->page < b->page ? -1 : 1;
+
+ return 0;
+}
+
+/**
+ * nanddev_pos_to_offs() - Convert a NAND position into an absolute offset
+ * @nand: NAND device
+ * @pos: the NAND position to convert
+ *
+ * Converts @pos NAND position into an absolute offset.
+ *
+ * Return: the absolute offset. Note that @pos points to the beginning of a
+ * page, if one wants to point to a specific offset within this page
+ * the returned offset has to be adjusted manually.
+ */
+static inline loff_t nanddev_pos_to_offs(struct nand_device *nand,
+ const struct nand_pos *pos)
+{
+ unsigned int npages;
+
+ npages = pos->page +
+ ((pos->eraseblock +
+ (pos->lun +
+ (pos->target * nand->memorg.luns_per_target)) *
+ nand->memorg.eraseblocks_per_lun) *
+ nand->memorg.pages_per_eraseblock);
+
+ return (loff_t)npages * nand->memorg.pagesize;
+}
+
+/**
+ * nanddev_pos_to_row() - Extract a row address from a NAND position
+ * @nand: NAND device
+ * @pos: the position to convert
+ *
+ * Converts a NAND position into a row address that can then be passed to the
+ * device.
+ *
+ * Return: the row address extracted from @pos.
+ */
+static inline unsigned int nanddev_pos_to_row(struct nand_device *nand,
+ const struct nand_pos *pos)
+{
+ return (pos->lun << nand->rowconv.lun_addr_shift) |
+ (pos->eraseblock << nand->rowconv.eraseblock_addr_shift) |
+ pos->page;
+}
+
+/**
+ * nanddev_pos_next_target() - Move a position to the next target/die
+ * @nand: NAND device
+ * @pos: the position to update
+ *
+ * Updates @pos to point to the start of the next target/die. Useful when you
+ * want to iterate over all targets/dies of a NAND device.
+ */
+static inline void nanddev_pos_next_target(struct nand_device *nand,
+ struct nand_pos *pos)
+{
+ pos->page = 0;
+ pos->plane = 0;
+ pos->eraseblock = 0;
+ pos->lun = 0;
+ pos->target++;
+}
+
+/**
+ * nanddev_pos_next_lun() - Move a position to the next LUN
+ * @nand: NAND device
+ * @pos: the position to update
+ *
+ * Updates @pos to point to the start of the next LUN. Useful when you want to
+ * iterate over all LUNs of a NAND device.
+ */
+static inline void nanddev_pos_next_lun(struct nand_device *nand,
+ struct nand_pos *pos)
+{
+ if (pos->lun >= nand->memorg.luns_per_target - 1)
+ return nanddev_pos_next_target(nand, pos);
+
+ pos->lun++;
+ pos->page = 0;
+ pos->plane = 0;
+ pos->eraseblock = 0;
+}
+
+/**
+ * nanddev_pos_next_eraseblock() - Move a position to the next eraseblock
+ * @nand: NAND device
+ * @pos: the position to update
+ *
+ * Updates @pos to point to the start of the next eraseblock. Useful when you
+ * want to iterate over all eraseblocks of a NAND device.
+ */
+static inline void nanddev_pos_next_eraseblock(struct nand_device *nand,
+ struct nand_pos *pos)
+{
+ if (pos->eraseblock >= nand->memorg.eraseblocks_per_lun - 1)
+ return nanddev_pos_next_lun(nand, pos);
+
+ pos->eraseblock++;
+ pos->page = 0;
+ pos->plane = pos->eraseblock % nand->memorg.planes_per_lun;
+}
+
+/**
+ * nanddev_pos_next_eraseblock() - Move a position to the next page
+ * @nand: NAND device
+ * @pos: the position to update
+ *
+ * Updates @pos to point to the start of the next page. Useful when you want to
+ * iterate over all pages of a NAND device.
+ */
+static inline void nanddev_pos_next_page(struct nand_device *nand,
+ struct nand_pos *pos)
+{
+ if (pos->page >= nand->memorg.pages_per_eraseblock - 1)
+ return nanddev_pos_next_eraseblock(nand, pos);
+
+ pos->page++;
+}
+
+/**
+ * nand_io_iter_init - Initialize a NAND I/O iterator
+ * @nand: NAND device
+ * @offs: absolute offset
+ * @req: MTD request
+ * @iter: NAND I/O iterator
+ *
+ * Initializes a NAND iterator based on the information passed by the MTD
+ * layer.
+ */
+static inline void nanddev_io_iter_init(struct nand_device *nand,
+ loff_t offs, struct mtd_oob_ops *req,
+ struct nand_io_iter *iter)
+{
+ struct mtd_info *mtd = nanddev_to_mtd(nand);
+
+ iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos);
+ iter->req.ooboffs = req->ooboffs;
+ iter->oobbytes_per_page = mtd_oobavail(mtd, req);
+ iter->dataleft = req->len;
+ iter->oobleft = req->ooblen;
+ iter->req.databuf.in = req->datbuf;
+ iter->req.datalen = min_t(unsigned int,
+ nand->memorg.pagesize - iter->req.dataoffs,
+ iter->dataleft);
+ iter->req.oobbuf.in = req->oobbuf;
+ iter->req.ooblen = min_t(unsigned int,
+ iter->oobbytes_per_page - iter->req.ooboffs,
+ iter->oobleft);
+}
+
+/**
+ * nand_io_iter_next_page - Move to the next page
+ * @nand: NAND device
+ * @iter: NAND I/O iterator
+ *
+ * Updates the @iter to point to the next page.
+ */
+static inline void nanddev_io_iter_next_page(struct nand_device *nand,
+ struct nand_io_iter *iter)
+{
+ nanddev_pos_next_page(nand, &iter->req.pos);
+ iter->dataleft -= iter->req.datalen;
+ iter->req.databuf.in += iter->req.datalen;
+ iter->oobleft -= iter->req.ooblen;
+ iter->req.oobbuf.in += iter->req.ooblen;
+ iter->req.dataoffs = 0;
+ iter->req.ooboffs = 0;
+ iter->req.datalen = min_t(unsigned int, nand->memorg.pagesize,
+ iter->dataleft);
+ iter->req.ooblen = min_t(unsigned int, iter->oobbytes_per_page,
+ iter->oobleft);
+}
+
+/**
+ * nand_io_iter_end - Should end iteration or not
+ * @nand: NAND device
+ * @iter: NAND I/O iterator
+ *
+ * Check whether @iter has reached the end of the NAND portion it was asked to
+ * iterate on or not.
+ *
+ * Return: true if @iter has reached the end of the iteration request, false
+ * otherwise.
+ */
+static inline bool nanddev_io_iter_end(struct nand_device *nand,
+ const struct nand_io_iter *iter)
+{
+ if (iter->dataleft || iter->oobleft)
+ return false;
+
+ return true;
+}
+
+/**
+ * nand_io_for_each_page - Iterate over all NAND pages contained in an MTD I/O
+ * request
+ * @nand: NAND device
+ * @start: start address to read/write from
+ * @req: MTD I/O request
+ * @iter: NAND I/O iterator
+ *
+ * Should be used for iterate over pages that are contained in an MTD request.
+ */
+#define nanddev_io_for_each_page(nand, start, req, iter) \
+ for (nanddev_io_iter_init(nand, start, req, iter); \
+ !nanddev_io_iter_end(nand, iter); \
+ nanddev_io_iter_next_page(nand, iter))
+
+bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos);
+bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos);
+int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos);
+int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos);
+
+/* BBT related functions */
+enum nand_bbt_block_status {
+ NAND_BBT_BLOCK_STATUS_UNKNOWN,
+ NAND_BBT_BLOCK_GOOD,
+ NAND_BBT_BLOCK_WORN,
+ NAND_BBT_BLOCK_RESERVED,
+ NAND_BBT_BLOCK_FACTORY_BAD,
+ NAND_BBT_BLOCK_NUM_STATUS,
+};
+
+int nanddev_bbt_init(struct nand_device *nand);
+void nanddev_bbt_cleanup(struct nand_device *nand);
+int nanddev_bbt_update(struct nand_device *nand);
+int nanddev_bbt_get_block_status(const struct nand_device *nand,
+ unsigned int entry);
+int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry,
+ enum nand_bbt_block_status status);
+int nanddev_bbt_markbad(struct nand_device *nand, unsigned int block);
+
+/**
+ * nanddev_bbt_pos_to_entry() - Convert a NAND position into a BBT entry
+ * @nand: NAND device
+ * @pos: the NAND position we want to get BBT entry for
+ *
+ * Return the BBT entry used to store information about the eraseblock pointed
+ * by @pos.
+ *
+ * Return: the BBT entry storing information about eraseblock pointed by @pos.
+ */
+static inline unsigned int nanddev_bbt_pos_to_entry(struct nand_device *nand,
+ const struct nand_pos *pos)
+{
+ return pos->eraseblock +
+ ((pos->lun + (pos->target * nand->memorg.luns_per_target)) *
+ nand->memorg.eraseblocks_per_lun);
+}
+
+/**
+ * nanddev_bbt_is_initialized() - Check if the BBT has been initialized
+ * @nand: NAND device
+ *
+ * Return: true if the BBT has been initialized, false otherwise.
+ */
+static inline bool nanddev_bbt_is_initialized(struct nand_device *nand)
+{
+ return !!nand->bbt.cache;
+}
+
+/* MTD -> NAND helper functions. */
+int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo);
+
+#endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h
index 4d8406c81652..8a2decf7462c 100644
--- a/include/linux/mtd/nand_ecc.h
+++ b/include/linux/mtd/nand_ecc.h
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand_ecc.h
- *
* Copyright (C) 2000-2010 Steven J. Hill <[email protected]>
* David Woodhouse <[email protected]>
* Thomas Gleixner <[email protected]>
diff --git a/include/linux/mtd/ndfc.h b/include/linux/mtd/ndfc.h
index d0558a982628..357e88b3263a 100644
--- a/include/linux/mtd/ndfc.h
+++ b/include/linux/mtd/ndfc.h
@@ -1,6 +1,4 @@
/*
- * linux/include/linux/mtd/ndfc.h
- *
* Copyright (c) 2006 Thomas Gleixner <[email protected]>
*
* This program is free software; you can redistribute it and/or modify