Merge tag 'for-linus-20140127' of git://git.infradead.org/linux-mtd
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 29 Jan 2014 02:56:37 +0000 (18:56 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 29 Jan 2014 02:56:37 +0000 (18:56 -0800)
Pull MTD updates from Brian Norris:
 - Add me (Brian Norris) as an additional MTD maintainer (it'd be nice to get
   David's "ack" for this; I'm sure he approves, but he's been pretty silent
   lately)
 - Add Ezequiel Garcie as maintainer for the pxa3xx NAND driver
 - Last (?) round of pxa3xx improvements for supporting Armada 370/XP
 - Typical churn in driver boilerplate (OOM messages, printk()'s, devm_*, etc.)
 - Quad read mode support for SPI NOR driver (m25p80)
 - Update Davinci NAND driver to prepare for use on new platforms
 - Begin to kill off NAND_MAX_{PAGE,OOB}SIZE macros; more work is pending
 - Miscellaneous NAND device support (new IDs)
 - Add READ RETRY support for Micron MLC NAND
 - Support new GPMI NAND ECC layout device-tree binding
 - Avoid mapping stack/vmalloc() memory for GPMI NAND DMA

* tag 'for-linus-20140127' of git://git.infradead.org/linux-mtd: (151 commits)
  mtd: gpmi: add sanity check when mapping DMA for read_buf/write_buf
  mtd: gpmi: allocate a proper buffer for non ECC read/write
  mtd: m25p80: Set rx_nbits for Quad SPI transfers
  mtd: m25p80: Enable Quad SPI read transfers for s25fl512s
  mtd: s3c2410: Merge plat/regs-nand.h into s3c2410.c
  mtd: mtdram: add missing 'const'
  mtd: m25p80: assign default read command
  mtd: nuc900_nand: remove redundant return value check of platform_get_resource()
  mtd: plat_nand: remove redundant return value check of platform_get_resource()
  mtd: nand: add Intel manufacturer ID
  mtd: nand: add SanDisk manufacturer ID
  mtd: nand: add support for Samsung K9LCG08U0B
  mtd: nand: pxa3xx: Add support for 2048 bytes page size devices
  mtd: m25p80: Use OPCODE_QUAD_READ_4B for 4-byte addressing
  mtd: nand: don't use {read,write}_buf for 8-bit transfers
  mtd: nand: use __packed shorthand
  mtd: nand: support Micron READ RETRY
  mtd: nand: add generic READ RETRY support
  mtd: nand: add ONFI vendor block for Micron
  mtd: nand: localize ECC failures per page
  ...

76 files changed:
Documentation/devicetree/bindings/arm/davinci/nand.txt [deleted file]
Documentation/devicetree/bindings/mtd/davinci-nand.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/gpmi-nand.txt
Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
Documentation/mtd/nand/pxa3xx-nand.txt [new file with mode: 0644]
MAINTAINERS
arch/arm/plat-samsung/include/plat/regs-nand.h [deleted file]
drivers/mtd/Kconfig
drivers/mtd/afs.c
drivers/mtd/ar7part.c
drivers/mtd/bcm47xxpart.c
drivers/mtd/bcm63xxpart.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/docg3.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/ms02-nv.c
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/devices/mtdram.c
drivers/mtd/lpddr/lpddr_cmds.c
drivers/mtd/maps/ixp4xx.c
drivers/mtd/maps/lantiq-flash.c
drivers/mtd/maps/pxa2xx-flash.c
drivers/mtd/maps/sun_uflash.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/bf5xx_nand.c
drivers/mtd/nand/cafe_nand.c
drivers/mtd/nand/cmx270_nand.c
drivers/mtd/nand/cs553x_nand.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/nand/denali.c
drivers/mtd/nand/denali.h
drivers/mtd/nand/denali_dt.c
drivers/mtd/nand/denali_pci.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsl_ifc_nand.c
drivers/mtd/nand/fsmc_nand.c
drivers/mtd/nand/gpio.c
drivers/mtd/nand/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.h
drivers/mtd/nand/jz4740_nand.c
drivers/mtd/nand/lpc32xx_mlc.c
drivers/mtd/nand/lpc32xx_slc.c
drivers/mtd/nand/mpc5121_nfc.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_ids.c
drivers/mtd/nand/nuc900_nand.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/orion_nand.c
drivers/mtd/nand/pasemi_nand.c
drivers/mtd/nand/plat_nand.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/nand/sharpsl.c
drivers/mtd/nand/tmio_nand.c
drivers/mtd/nand/txx9ndfmc.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/generic.c
drivers/mtd/redboot.c
drivers/mtd/tests/mtd_nandecctest.c
fs/jffs2/malloc.c
include/linux/mtd/mtdram.h
include/linux/mtd/nand.h
include/linux/mtd/partitions.h
include/linux/of_mtd.h
include/linux/platform_data/mtd-nand-omap2.h
include/linux/platform_data/mtd-nand-pxa3xx.h
include/linux/platform_data/mtd-onenand-omap2.h
include/linux/platform_data/mtd-orion_nand.h

diff --git a/Documentation/devicetree/bindings/arm/davinci/nand.txt b/Documentation/devicetree/bindings/arm/davinci/nand.txt
deleted file mode 100644 (file)
index 3545ea7..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-* Texas Instruments Davinci NAND
-
-This file provides information, what the device node for the
-davinci nand interface contain.
-
-Required properties:
-- compatible: "ti,davinci-nand";
-- reg : contain 2 offset/length values:
-        - offset and length for the access window
-        - offset and length for accessing the aemif control registers
-- ti,davinci-chipselect: Indicates on the davinci_nand driver which
-                         chipselect is used for accessing the nand.
-
-Recommended properties :
-- ti,davinci-mask-ale: mask for ale
-- ti,davinci-mask-cle: mask for cle
-- ti,davinci-mask-chipsel: mask for chipselect
-- ti,davinci-ecc-mode: ECC mode valid values for davinci driver:
-               - "none"
-               - "soft"
-               - "hw"
-- ti,davinci-ecc-bits: used ECC bits, currently supported 1 or 4.
-- ti,davinci-nand-buswidth: buswidth 8 or 16
-- ti,davinci-nand-use-bbt: use flash based bad block table support.
-
-nand device bindings may contain additional sub-nodes describing
-partitions of the address space. See partition.txt for more detail.
-
-Example(da850 EVM ):
-nand_cs3@62000000 {
-       compatible = "ti,davinci-nand";
-       reg = <0x62000000 0x807ff
-               0x68000000 0x8000>;
-       ti,davinci-chipselect = <1>;
-       ti,davinci-mask-ale = <0>;
-       ti,davinci-mask-cle = <0>;
-       ti,davinci-mask-chipsel = <0>;
-       ti,davinci-ecc-mode = "hw";
-       ti,davinci-ecc-bits = <4>;
-       ti,davinci-nand-use-bbt;
-
-       partition@180000 {
-               label = "ubifs";
-               reg = <0x180000 0x7e80000>;
-       };
-};
diff --git a/Documentation/devicetree/bindings/mtd/davinci-nand.txt b/Documentation/devicetree/bindings/mtd/davinci-nand.txt
new file mode 100644 (file)
index 0000000..cfb18ab
--- /dev/null
@@ -0,0 +1,94 @@
+Device tree bindings for Texas instruments Davinci/Keystone NAND controller
+
+This file provides information, what the device node for the davinci/keystone
+NAND interface contains.
+
+Documentation:
+Davinci DM646x - http://www.ti.com/lit/ug/sprueq7c/sprueq7c.pdf
+Kestone - http://www.ti.com/lit/ug/sprugz3a/sprugz3a.pdf
+
+Required properties:
+
+- compatible:                  "ti,davinci-nand"
+                               "ti,keystone-nand"
+
+- reg:                         Contains 2 offset/length values:
+                               - offset and length for the access window.
+                               - offset and length for accessing the AEMIF
+                               control registers.
+
+- ti,davinci-chipselect:       number of chipselect. Indicates on the
+                               davinci_nand driver which chipselect is used
+                               for accessing the nand.
+                               Can be in the range [0-3].
+
+Recommended properties :
+
+- ti,davinci-mask-ale:         mask for ALE. Needed for executing address
+                               phase. These offset will be added to the base
+                               address for the chip select space the NAND Flash
+                               device is connected to.
+                               If not set equal to 0x08.
+
+- ti,davinci-mask-cle:         mask for CLE. Needed for executing command
+                               phase. These offset will be added to the base
+                               address for the chip select space the NAND Flash
+                               device is connected to.
+                               If not set equal to 0x10.
+
+- ti,davinci-mask-chipsel:     mask for chipselect address. Needed to mask
+                               addresses for given chipselect.
+
+- nand-ecc-mode:               operation mode of the NAND ecc mode. ECC mode
+                               valid values for davinci driver:
+                               - "none"
+                               - "soft"
+                               - "hw"
+
+- ti,davinci-ecc-bits:         used ECC bits, currently supported 1 or 4.
+
+- nand-bus-width:              buswidth 8 or 16. If not present 8.
+
+- nand-on-flash-bbt:           use flash based bad block table support. OOB
+                               identifier is saved in OOB area. If not present
+                               false.
+
+Deprecated properties:
+
+- ti,davinci-ecc-mode:         operation mode of the NAND ecc mode. ECC mode
+                               valid values for davinci driver:
+                               - "none"
+                               - "soft"
+                               - "hw"
+
+- ti,davinci-nand-buswidth:    buswidth 8 or 16. If not present 8.
+
+- ti,davinci-nand-use-bbt:     use flash based bad block table support. OOB
+                               identifier is saved in OOB area. If not present
+                               false.
+
+Nand device bindings may contain additional sub-nodes describing partitions of
+the address space. See partition.txt for more detail. The NAND Flash timing
+values must be programmed in the chip select’s node of AEMIF
+memory-controller (see Documentation/devicetree/bindings/memory-controllers/
+davinci-aemif.txt).
+
+Example(da850 EVM ):
+
+nand_cs3@62000000 {
+       compatible = "ti,davinci-nand";
+       reg = <0x62000000 0x807ff
+              0x68000000 0x8000>;
+       ti,davinci-chipselect = <1>;
+       ti,davinci-mask-ale = <0>;
+       ti,davinci-mask-cle = <0>;
+       ti,davinci-mask-chipsel = <0>;
+       nand-ecc-mode = "hw";
+       ti,davinci-ecc-bits = <4>;
+       nand-on-flash-bbt;
+
+       partition@180000 {
+               label = "ubifs";
+               reg = <0x180000 0x7e80000>;
+       };
+};
index 551b2a179d016df4bd9bb8e611f38633d57d6640..458d5963468826647d2469c23f542bde3ffe047c 100644 (file)
@@ -17,6 +17,14 @@ Required properties:
 Optional properties:
   - nand-on-flash-bbt: boolean to enable on flash bbt option if not
                        present false
+  - fsl,use-minimum-ecc: Protect this NAND flash with the minimum ECC
+                       strength required. The required ECC strength is
+                       automatically discoverable for some flash
+                       (e.g., according to the ONFI standard).
+                       However, note that if this strength is not
+                       discoverable or this property is not enabled,
+                       the software may chooses an implementation-defined
+                       ECC scheme.
 
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
index f1421e2bbab7387a87e1885794b9688780d6de73..86e0a5601ff5dfb05d9eeed35eb3e638ea58cc7b 100644 (file)
@@ -2,7 +2,9 @@ PXA3xx NAND DT bindings
 
 Required properties:
 
- - compatible:         Should be "marvell,pxa3xx-nand"
+ - compatible:         Should be set to one of the following:
+                       marvell,pxa3xx-nand
+                       marvell,armada370-nand
  - reg:                The register base for the controller
  - interrupts:         The interrupt to map
  - #address-cells:     Set to <1> if the node includes partitions
@@ -13,6 +15,8 @@ Optional properties:
  - marvell,nand-keep-config:   Set to keep the NAND controller config as set
                                by the bootloader
  - num-cs:                     Number of chipselect lines to usw
+ - nand-on-flash-bbt:          boolean to enable on flash bbt option if
+                               not present false
 
 Example:
 
diff --git a/Documentation/mtd/nand/pxa3xx-nand.txt b/Documentation/mtd/nand/pxa3xx-nand.txt
new file mode 100644 (file)
index 0000000..840fd41
--- /dev/null
@@ -0,0 +1,113 @@
+
+About this document
+===================
+
+Some notes about Marvell's NAND controller available in PXA and Armada 370/XP
+SoC (aka NFCv1 and NFCv2), with an emphasis on the latter.
+
+NFCv2 controller background
+===========================
+
+The controller has a 2176 bytes FIFO buffer. Therefore, in order to support
+larger pages, I/O operations on 4 KiB and 8 KiB pages is done with a set of
+chunked transfers.
+
+For instance, if we choose a 2048 data chunk and set "BCH" ECC (see below)
+we'll have this layout in the pages:
+
+  ------------------------------------------------------------------------------
+  | 2048B data | 32B spare | 30B ECC || 2048B data | 32B spare | 30B ECC | ... |
+  ------------------------------------------------------------------------------
+
+The driver reads the data and spare portions independently and builds an internal
+buffer with this layout (in the 4 KiB page case):
+
+  ------------------------------------------
+  |     4096B data     |     64B spare     |
+  ------------------------------------------
+
+Also, for the READOOB command the driver disables the ECC and reads a 'spare + ECC'
+OOB, one per chunk read.
+
+  -------------------------------------------------------------------
+  |     4096B data     |  32B spare | 30B ECC | 32B spare | 30B ECC |
+  -------------------------------------------------------------------
+
+So, in order to achieve reading (for instance), we issue several READ0 commands
+(with some additional controller-specific magic) and read two chunks of 2080B
+(2048 data + 32 spare) each.
+The driver accommodates this data to expose the NAND core a contiguous buffer
+(4096 data + spare) or (4096 + spare + ECC + spare + ECC).
+
+ECC
+===
+
+The controller has built-in hardware ECC capabilities. In addition it is
+configurable between two modes: 1) Hamming, 2) BCH.
+
+Note that the actual BCH mode: BCH-4 or BCH-8 will depend on the way
+the controller is configured to transfer the data.
+
+In the BCH mode the ECC code will be calculated for each transfered chunk
+and expected to be located (when reading/programming) right after the spare
+bytes as the figure above shows.
+
+So, repeating the above scheme, a 2048B data chunk will be followed by 32B
+spare, and then the ECC controller will read/write the ECC code (30B in
+this case):
+
+  ------------------------------------
+  | 2048B data | 32B spare | 30B ECC |
+  ------------------------------------
+
+If the ECC mode is 'BCH' then the ECC is *always* 30 bytes long.
+If the ECC mode is 'Hamming' the ECC is 6 bytes long, for each 512B block.
+So in Hamming mode, a 2048B page will have a 24B ECC.
+
+Despite all of the above, the controller requires the driver to only read or
+write in multiples of 8-bytes, because the data buffer is 64-bits.
+
+OOB
+===
+
+Because of the above scheme, and because the "spare" OOB is really located in
+the middle of a page, spare OOB cannot be read or write independently of the
+data area. In other words, in order to read the OOB (aka READOOB), the entire
+page (aka READ0) has to be read.
+
+In the same sense, in order to write to the spare OOB the driver has to write
+an *entire* page.
+
+Factory bad blocks handling
+===========================
+
+Given the ECC BCH requires to layout the device's pages in a split
+data/OOB/data/OOB way, the controller has a view of the flash page that's
+different from the specified (aka the manufacturer's) view. In other words,
+
+Factory view:
+
+  -----------------------------------------------
+  |                    Data           |x  OOB   |
+  -----------------------------------------------
+
+Driver's view:
+
+  -----------------------------------------------
+  |      Data      | OOB |      Data   x  | OOB |
+  -----------------------------------------------
+
+It can be seen from the above, that the factory bad block marker must be
+searched within the 'data' region, and not in the usual OOB region.
+
+In addition, this means under regular usage the driver will write such
+position (since it belongs to the data region) and every used block is
+likely to be marked as bad.
+
+For this reason, marking the block as bad in the OOB is explicitly
+disabled by using the NAND_BBT_NO_OOB_BBM option in the driver. The rationale
+for this is that there's no point in marking a block as bad, because good
+blocks are also 'marked as bad' (in the OOB BBM sense) under normal usage.
+
+Instead, the driver relies on the bad block table alone, and should only perform
+the bad block scan on the very first time (when the device hasn't been used).
index 9bf651c578062ecbc0cd9a6d95959955882da987..6d73831cfdee11ccc6b1c858a0cd16b22fca0e69 100644 (file)
@@ -5622,10 +5622,11 @@ F:      mm/page_cgroup.c
 
 MEMORY TECHNOLOGY DEVICES (MTD)
 M:     David Woodhouse <dwmw2@infradead.org>
+M:     Brian Norris <computersforpeace@gmail.com>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
 Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
-T:     git git://git.infradead.org/mtd-2.6.git
+T:     git git://git.infradead.org/linux-mtd.git
 S:     Maintained
 F:     drivers/mtd/
 F:     include/linux/mtd/
@@ -6942,6 +6943,12 @@ F:       include/sound/pxa2xx-lib.h
 F:     sound/arm/pxa*
 F:     sound/soc/pxa/
 
+PXA3xx NAND FLASH DRIVER
+M:     Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+L:     linux-mtd@lists.infradead.org
+S:     Maintained
+F:     drivers/mtd/nand/pxa3xx-nand.c
+
 MMP SUPPORT
 M:     Eric Miao <eric.y.miao@gmail.com>
 M:     Haojian Zhuang <haojian.zhuang@gmail.com>
diff --git a/arch/arm/plat-samsung/include/plat/regs-nand.h b/arch/arm/plat-samsung/include/plat/regs-nand.h
deleted file mode 100644 (file)
index 238efea..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-nand.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics <linux@simtec.co.uk>
- *     http://www.simtec.co.uk/products/SWLINUX/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 NAND register definitions
-*/
-
-#ifndef __ASM_ARM_REGS_NAND
-#define __ASM_ARM_REGS_NAND
-
-
-#define S3C2410_NFREG(x) (x)
-
-#define S3C2410_NFCONF  S3C2410_NFREG(0x00)
-#define S3C2410_NFCMD   S3C2410_NFREG(0x04)
-#define S3C2410_NFADDR  S3C2410_NFREG(0x08)
-#define S3C2410_NFDATA  S3C2410_NFREG(0x0C)
-#define S3C2410_NFSTAT  S3C2410_NFREG(0x10)
-#define S3C2410_NFECC   S3C2410_NFREG(0x14)
-
-#define S3C2440_NFCONT   S3C2410_NFREG(0x04)
-#define S3C2440_NFCMD    S3C2410_NFREG(0x08)
-#define S3C2440_NFADDR   S3C2410_NFREG(0x0C)
-#define S3C2440_NFDATA   S3C2410_NFREG(0x10)
-#define S3C2440_NFECCD0  S3C2410_NFREG(0x14)
-#define S3C2440_NFECCD1  S3C2410_NFREG(0x18)
-#define S3C2440_NFECCD   S3C2410_NFREG(0x1C)
-#define S3C2440_NFSTAT   S3C2410_NFREG(0x20)
-#define S3C2440_NFESTAT0 S3C2410_NFREG(0x24)
-#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
-#define S3C2440_NFMECC0  S3C2410_NFREG(0x2C)
-#define S3C2440_NFMECC1  S3C2410_NFREG(0x30)
-#define S3C2440_NFSECC   S3C2410_NFREG(0x34)
-#define S3C2440_NFSBLK   S3C2410_NFREG(0x38)
-#define S3C2440_NFEBLK   S3C2410_NFREG(0x3C)
-
-#define S3C2412_NFSBLK         S3C2410_NFREG(0x20)
-#define S3C2412_NFEBLK         S3C2410_NFREG(0x24)
-#define S3C2412_NFSTAT         S3C2410_NFREG(0x28)
-#define S3C2412_NFMECC_ERR0    S3C2410_NFREG(0x2C)
-#define S3C2412_NFMECC_ERR1    S3C2410_NFREG(0x30)
-#define S3C2412_NFMECC0                S3C2410_NFREG(0x34)
-#define S3C2412_NFMECC1                S3C2410_NFREG(0x38)
-#define S3C2412_NFSECC         S3C2410_NFREG(0x3C)
-
-#define S3C2410_NFCONF_EN          (1<<15)
-#define S3C2410_NFCONF_512BYTE     (1<<14)
-#define S3C2410_NFCONF_4STEP       (1<<13)
-#define S3C2410_NFCONF_INITECC     (1<<12)
-#define S3C2410_NFCONF_nFCE        (1<<11)
-#define S3C2410_NFCONF_TACLS(x)    ((x)<<8)
-#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<4)
-#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<0)
-
-#define S3C2410_NFSTAT_BUSY        (1<<0)
-
-#define S3C2440_NFCONF_BUSWIDTH_8      (0<<0)
-#define S3C2440_NFCONF_BUSWIDTH_16     (1<<0)
-#define S3C2440_NFCONF_ADVFLASH                (1<<3)
-#define S3C2440_NFCONF_TACLS(x)                ((x)<<12)
-#define S3C2440_NFCONF_TWRPH0(x)       ((x)<<8)
-#define S3C2440_NFCONF_TWRPH1(x)       ((x)<<4)
-
-#define S3C2440_NFCONT_LOCKTIGHT       (1<<13)
-#define S3C2440_NFCONT_SOFTLOCK                (1<<12)
-#define S3C2440_NFCONT_ILLEGALACC_EN   (1<<10)
-#define S3C2440_NFCONT_RNBINT_EN       (1<<9)
-#define S3C2440_NFCONT_RN_FALLING      (1<<8)
-#define S3C2440_NFCONT_SPARE_ECCLOCK   (1<<6)
-#define S3C2440_NFCONT_MAIN_ECCLOCK    (1<<5)
-#define S3C2440_NFCONT_INITECC         (1<<4)
-#define S3C2440_NFCONT_nFCE            (1<<1)
-#define S3C2440_NFCONT_ENABLE          (1<<0)
-
-#define S3C2440_NFSTAT_READY           (1<<0)
-#define S3C2440_NFSTAT_nCE             (1<<1)
-#define S3C2440_NFSTAT_RnB_CHANGE      (1<<2)
-#define S3C2440_NFSTAT_ILLEGAL_ACCESS  (1<<3)
-
-#define S3C2412_NFCONF_NANDBOOT                (1<<31)
-#define S3C2412_NFCONF_ECCCLKCON       (1<<30)
-#define S3C2412_NFCONF_ECC_MLC         (1<<24)
-#define S3C2412_NFCONF_TACLS_MASK      (7<<12) /* 1 extra bit of Tacls */
-
-#define S3C2412_NFCONT_ECC4_DIRWR      (1<<18)
-#define S3C2412_NFCONT_LOCKTIGHT       (1<<17)
-#define S3C2412_NFCONT_SOFTLOCK                (1<<16)
-#define S3C2412_NFCONT_ECC4_ENCINT     (1<<13)
-#define S3C2412_NFCONT_ECC4_DECINT     (1<<12)
-#define S3C2412_NFCONT_MAIN_ECC_LOCK   (1<<7)
-#define S3C2412_NFCONT_INIT_MAIN_ECC   (1<<5)
-#define S3C2412_NFCONT_nFCE1           (1<<2)
-#define S3C2412_NFCONT_nFCE0           (1<<1)
-
-#define S3C2412_NFSTAT_ECC_ENCDONE     (1<<7)
-#define S3C2412_NFSTAT_ECC_DECDONE     (1<<6)
-#define S3C2412_NFSTAT_ILLEGAL_ACCESS  (1<<5)
-#define S3C2412_NFSTAT_RnB_CHANGE      (1<<4)
-#define S3C2412_NFSTAT_nFCE1           (1<<3)
-#define S3C2412_NFSTAT_nFCE0           (1<<2)
-#define S3C2412_NFSTAT_Res1            (1<<1)
-#define S3C2412_NFSTAT_READY           (1<<0)
-
-#define S3C2412_NFECCERR_SERRDATA(x)   (((x) >> 21) & 0xf)
-#define S3C2412_NFECCERR_SERRBIT(x)    (((x) >> 18) & 0x7)
-#define S3C2412_NFECCERR_MERRDATA(x)   (((x) >> 7) & 0x3ff)
-#define S3C2412_NFECCERR_MERRBIT(x)    (((x) >> 4) & 0x7)
-#define S3C2412_NFECCERR_SPARE_ERR(x)  (((x) >> 2) & 0x3)
-#define S3C2412_NFECCERR_MAIN_ERR(x)   (((x) >> 2) & 0x3)
-#define S3C2412_NFECCERR_NONE          (0)
-#define S3C2412_NFECCERR_1BIT          (1)
-#define S3C2412_NFECCERR_MULTIBIT      (2)
-#define S3C2412_NFECCERR_ECCAREA       (3)
-
-
-
-#endif /* __ASM_ARM_REGS_NAND */
-
index 5fab4e6e83013c033c01d2465b4f25c756f39dce..5ebcda39f55407e146ab06d811edd5825939a41d 100644 (file)
@@ -157,10 +157,11 @@ config MTD_BCM47XX_PARTS
 
 comment "User Modules And Translation Layers"
 
+#
+# MTD block device support is select'ed if needed
+#
 config MTD_BLKDEVS
-       tristate "Common interface to block layer for MTD 'translation layers'"
-       depends on BLOCK
-       default n
+       tristate
 
 config MTD_BLOCK
        tristate "Caching block device access to MTD devices"
index 5a3942bf109cd9ccded20d42fc4ee62b36a3ad8e..96a33e3f7b000394c1480260246585531c88b920 100644 (file)
@@ -264,7 +264,8 @@ static struct mtd_part_parser afs_parser = {
 
 static int __init afs_parser_init(void)
 {
-       return register_mtd_parser(&afs_parser);
+       register_mtd_parser(&afs_parser);
+       return 0;
 }
 
 static void __exit afs_parser_exit(void)
index ddc0a4287a4b89c8124dd3629b9647e3ca800b74..7c9172ad26210e1d25c9506889e0cbb54212dbfe 100644 (file)
@@ -139,7 +139,8 @@ static struct mtd_part_parser ar7_parser = {
 
 static int __init ar7_parser_init(void)
 {
-       return register_mtd_parser(&ar7_parser);
+       register_mtd_parser(&ar7_parser);
+       return 0;
 }
 
 static void __exit ar7_parser_exit(void)
index 7a6384b0962a9de2c92dffb81f1fc45d6d89a490..de1eb92e42f57f15f197c3ba21d1831ab6dac06f 100644 (file)
  * Amount of bytes we read when analyzing each block of flash memory.
  * Set it big enough to allow detecting partition and reading important data.
  */
-#define BCM47XXPART_BYTES_TO_READ      0x404
+#define BCM47XXPART_BYTES_TO_READ      0x4e8
 
 /* Magics */
 #define BOARD_DATA_MAGIC               0x5246504D      /* MPFR */
+#define BOARD_DATA_MAGIC2              0xBD0D0BBD
+#define CFE_MAGIC                      0x43464531      /* 1EFC */
 #define FACTORY_MAGIC                  0x59544346      /* FCTY */
 #define POT_MAGIC1                     0x54544f50      /* POTT */
 #define POT_MAGIC2                     0x504f          /* OP */
@@ -102,8 +104,9 @@ static int bcm47xxpart_parse(struct mtd_info *master,
                        continue;
                }
 
-               /* CFE has small NVRAM at 0x400 */
-               if (buf[0x400 / 4] == NVRAM_HEADER) {
+               /* Magic or small NVRAM at 0x400 */
+               if ((buf[0x4e0 / 4] == CFE_MAGIC && buf[0x4e4 / 4] == CFE_MAGIC) ||
+                   (buf[0x400 / 4] == NVRAM_HEADER)) {
                        bcm47xxpart_add_part(&parts[curr_part++], "boot",
                                             offset, MTD_WRITEABLE);
                        continue;
@@ -190,6 +193,21 @@ static int bcm47xxpart_parse(struct mtd_info *master,
                                             offset, 0);
                        continue;
                }
+
+               /* Read middle of the block */
+               if (mtd_read(master, offset + 0x8000, 0x4,
+                            &bytes_read, (uint8_t *)buf) < 0) {
+                       pr_err("mtd_read error while parsing (offset: 0x%X)!\n",
+                              offset);
+                       continue;
+               }
+
+               /* Some devices (ex. WNDR3700v3) don't have a standard 'MPFR' */
+               if (buf[0x000 / 4] == BOARD_DATA_MAGIC2) {
+                       bcm47xxpart_add_part(&parts[curr_part++], "board_data",
+                                            offset, MTD_WRITEABLE);
+                       continue;
+               }
        }
 
        /* Look for NVRAM at the end of the last block. */
@@ -243,7 +261,8 @@ static struct mtd_part_parser bcm47xxpart_mtd_parser = {
 
 static int __init bcm47xxpart_init(void)
 {
-       return register_mtd_parser(&bcm47xxpart_mtd_parser);
+       register_mtd_parser(&bcm47xxpart_mtd_parser);
+       return 0;
 }
 
 static void __exit bcm47xxpart_exit(void)
index 5c813907661c3415c979b1176bf937f7c086f2c8..b2443f7031c9afb0bda808a37b6da7e8113d0a61 100644 (file)
@@ -221,7 +221,8 @@ static struct mtd_part_parser bcm63xx_cfe_parser = {
 
 static int __init bcm63xx_cfe_parser_init(void)
 {
-       return register_mtd_parser(&bcm63xx_cfe_parser);
+       register_mtd_parser(&bcm63xx_cfe_parser);
+       return 0;
 }
 
 static void __exit bcm63xx_cfe_parser_exit(void)
index 721caebbc5cc21344a58a710d466205f75f845ef..3e829b37af8d0e0d5c73eff2c03e054ed6516eab 100644 (file)
@@ -395,7 +395,8 @@ static int __init cmdline_parser_init(void)
 {
        if (mtdparts)
                mtdpart_setup(mtdparts);
-       return register_mtd_parser(&cmdline_parser);
+       register_mtd_parser(&cmdline_parser);
+       return 0;
 }
 
 static void __exit cmdline_parser_exit(void)
index 4f091c1a9981c060e3ea2cae43960ade8b4bc2f7..dd5e1018d37b39e9301c9c43e01195f4f363a66c 100644 (file)
@@ -2047,21 +2047,21 @@ static int __init docg3_probe(struct platform_device *pdev)
        ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!ress) {
                dev_err(dev, "No I/O memory resource defined\n");
-               goto noress;
+               return ret;
        }
-       base = ioremap(ress->start, DOC_IOSPACE_SIZE);
+       base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE);
 
        ret = -ENOMEM;
-       cascade = kzalloc(sizeof(*cascade) * DOC_MAX_NBFLOORS,
-                         GFP_KERNEL);
+       cascade = devm_kzalloc(dev, sizeof(*cascade) * DOC_MAX_NBFLOORS,
+                              GFP_KERNEL);
        if (!cascade)
-               goto nomem1;
+               return ret;
        cascade->base = base;
        mutex_init(&cascade->lock);
        cascade->bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T,
                             DOC_ECC_BCH_PRIMPOLY);
        if (!cascade->bch)
-               goto nomem2;
+               return ret;
 
        for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) {
                mtd = doc_probe_device(cascade, floor, dev);
@@ -2101,11 +2101,6 @@ err_probe:
        for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
                if (cascade->floors[floor])
                        doc_release_device(cascade->floors[floor]);
-nomem2:
-       kfree(cascade);
-nomem1:
-       iounmap(base);
-noress:
        return ret;
 }
 
@@ -2119,7 +2114,6 @@ static int __exit docg3_release(struct platform_device *pdev)
 {
        struct docg3_cascade *cascade = platform_get_drvdata(pdev);
        struct docg3 *docg3 = cascade->floors[0]->priv;
-       void __iomem *base = cascade->base;
        int floor;
 
        doc_unregister_sysfs(pdev, cascade);
@@ -2129,8 +2123,6 @@ static int __exit docg3_release(struct platform_device *pdev)
                        doc_release_device(cascade->floors[floor]);
 
        free_bch(docg3->cascade->bch);
-       kfree(cascade);
-       iounmap(base);
        return 0;
 }
 
index 7eda71dbc183b7aa456e60a41f0490c882d94331..ad19139097025b97839fb7cbe123a1261e6cf876 100644 (file)
@@ -41,6 +41,7 @@
 #define        OPCODE_WRSR             0x01    /* Write status register 1 byte */
 #define        OPCODE_NORM_READ        0x03    /* Read data bytes (low frequency) */
 #define        OPCODE_FAST_READ        0x0b    /* Read data bytes (high frequency) */
+#define        OPCODE_QUAD_READ        0x6b    /* Read data bytes */
 #define        OPCODE_PP               0x02    /* Page program (up to 256 bytes) */
 #define        OPCODE_BE_4K            0x20    /* Erase 4KiB block */
 #define        OPCODE_BE_4K_PMC        0xd7    /* Erase 4KiB block on PMC chips */
 #define        OPCODE_CHIP_ERASE       0xc7    /* Erase whole flash chip */
 #define        OPCODE_SE               0xd8    /* Sector erase (usually 64KiB) */
 #define        OPCODE_RDID             0x9f    /* Read JEDEC ID */
+#define        OPCODE_RDCR             0x35    /* Read configuration register */
 
 /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
 #define        OPCODE_NORM_READ_4B     0x13    /* Read data bytes (low frequency) */
 #define        OPCODE_FAST_READ_4B     0x0c    /* Read data bytes (high frequency) */
+#define        OPCODE_QUAD_READ_4B     0x6c    /* Read data bytes */
 #define        OPCODE_PP_4B            0x12    /* Page program (up to 256 bytes) */
 #define        OPCODE_SE_4B            0xdc    /* Sector erase (usually 64KiB) */
 
 #define        SR_BP2                  0x10    /* Block protect 2 */
 #define        SR_SRWD                 0x80    /* SR write protect */
 
+#define SR_QUAD_EN_MX           0x40    /* Macronix Quad I/O */
+
+/* Configuration Register bits. */
+#define CR_QUAD_EN_SPAN                0x2     /* Spansion Quad I/O */
+
 /* Define max times to check status register before we give up. */
 #define        MAX_READY_WAIT_JIFFIES  (40 * HZ)       /* M25P16 specs 40s max chip erase */
 #define        MAX_CMD_SIZE            6
 
 /****************************************************************************/
 
+enum read_type {
+       M25P80_NORMAL = 0,
+       M25P80_FAST,
+       M25P80_QUAD,
+};
+
 struct m25p {
        struct spi_device       *spi;
        struct mutex            lock;
@@ -94,7 +108,7 @@ struct m25p {
        u8                      read_opcode;
        u8                      program_opcode;
        u8                      *command;
-       bool                    fast_read;
+       enum read_type          flash_read;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -130,6 +144,26 @@ static int read_sr(struct m25p *flash)
        return val;
 }
 
+/*
+ * Read configuration register, returning its value in the
+ * location. Return the configuration register value.
+ * Returns negative if error occured.
+ */
+static int read_cr(struct m25p *flash)
+{
+       u8 code = OPCODE_RDCR;
+       int ret;
+       u8 val;
+
+       ret = spi_write_then_read(flash->spi, &code, 1, &val, 1);
+       if (ret < 0) {
+               dev_err(&flash->spi->dev, "error %d reading CR\n", ret);
+               return ret;
+       }
+
+       return val;
+}
+
 /*
  * Write status register 1 byte
  * Returns negative if error occurred.
@@ -219,6 +253,93 @@ static int wait_till_ready(struct m25p *flash)
        return 1;
 }
 
+/*
+ * Write status Register and configuration register with 2 bytes
+ * The first byte will be written to the status register, while the
+ * second byte will be written to the configuration register.
+ * Return negative if error occured.
+ */
+static int write_sr_cr(struct m25p *flash, u16 val)
+{
+       flash->command[0] = OPCODE_WRSR;
+       flash->command[1] = val & 0xff;
+       flash->command[2] = (val >> 8);
+
+       return spi_write(flash->spi, flash->command, 3);
+}
+
+static int macronix_quad_enable(struct m25p *flash)
+{
+       int ret, val;
+       u8 cmd[2];
+       cmd[0] = OPCODE_WRSR;
+
+       val = read_sr(flash);
+       cmd[1] = val | SR_QUAD_EN_MX;
+       write_enable(flash);
+
+       spi_write(flash->spi, &cmd, 2);
+
+       if (wait_till_ready(flash))
+               return 1;
+
+       ret = read_sr(flash);
+       if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) {
+               dev_err(&flash->spi->dev, "Macronix Quad bit not set\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int spansion_quad_enable(struct m25p *flash)
+{
+       int ret;
+       int quad_en = CR_QUAD_EN_SPAN << 8;
+
+       write_enable(flash);
+
+       ret = write_sr_cr(flash, quad_en);
+       if (ret < 0) {
+               dev_err(&flash->spi->dev,
+                       "error while writing configuration register\n");
+               return -EINVAL;
+       }
+
+       /* read back and check it */
+       ret = read_cr(flash);
+       if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
+               dev_err(&flash->spi->dev, "Spansion Quad bit not set\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int set_quad_mode(struct m25p *flash, u32 jedec_id)
+{
+       int status;
+
+       switch (JEDEC_MFR(jedec_id)) {
+       case CFI_MFR_MACRONIX:
+               status = macronix_quad_enable(flash);
+               if (status) {
+                       dev_err(&flash->spi->dev,
+                               "Macronix quad-read not enabled\n");
+                       return -EINVAL;
+               }
+               return status;
+       default:
+               status = spansion_quad_enable(flash);
+               if (status) {
+                       dev_err(&flash->spi->dev,
+                               "Spansion quad-read not enabled\n");
+                       return -EINVAL;
+               }
+               return status;
+       }
+}
+
 /*
  * Erase the whole flash memory
  *
@@ -349,6 +470,35 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
        return 0;
 }
 
+/*
+ * Dummy Cycle calculation for different type of read.
+ * It can be used to support more commands with
+ * different dummy cycle requirements.
+ */
+static inline int m25p80_dummy_cycles_read(struct m25p *flash)
+{
+       switch (flash->flash_read) {
+       case M25P80_FAST:
+       case M25P80_QUAD:
+               return 1;
+       case M25P80_NORMAL:
+               return 0;
+       default:
+               dev_err(&flash->spi->dev, "No valid read type supported\n");
+               return -1;
+       }
+}
+
+static inline unsigned int m25p80_rx_nbits(const struct m25p *flash)
+{
+       switch (flash->flash_read) {
+       case M25P80_QUAD:
+               return 4;
+       default:
+               return 0;
+       }
+}
+
 /*
  * Read an address range from the flash chip.  The address range
  * may be any size provided it is within the physical boundaries.
@@ -360,6 +510,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct spi_transfer t[2];
        struct spi_message m;
        uint8_t opcode;
+       int dummy;
 
        pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
                        __func__, (u32)from, len);
@@ -367,11 +518,18 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        spi_message_init(&m);
        memset(t, 0, (sizeof t));
 
+       dummy =  m25p80_dummy_cycles_read(flash);
+       if (dummy < 0) {
+               dev_err(&flash->spi->dev, "No valid read command supported\n");
+               return -EINVAL;
+       }
+
        t[0].tx_buf = flash->command;
-       t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0);
+       t[0].len = m25p_cmdsz(flash) + dummy;
        spi_message_add_tail(&t[0], &m);
 
        t[1].rx_buf = buf;
+       t[1].rx_nbits = m25p80_rx_nbits(flash);
        t[1].len = len;
        spi_message_add_tail(&t[1], &m);
 
@@ -391,8 +549,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
 
        spi_sync(flash->spi, &m);
 
-       *retlen = m.actual_length - m25p_cmdsz(flash) -
-                       (flash->fast_read ? 1 : 0);
+       *retlen = m.actual_length - m25p_cmdsz(flash) - dummy;
 
        mutex_unlock(&flash->lock);
 
@@ -698,6 +855,7 @@ struct flash_info {
 #define        SST_WRITE       0x04            /* use SST byte programming */
 #define        M25P_NO_FR      0x08            /* Can't do fastread */
 #define        SECT_4K_PMC     0x10            /* OPCODE_BE_4K_PMC works uniformly */
+#define        M25P80_QUAD_READ        0x20    /* Flash supports Quad Read */
 };
 
 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)     \
@@ -775,7 +933,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
        { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
        { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
-       { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) },
+       { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, M25P80_QUAD_READ) },
 
        /* Micron */
        { "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, 0) },
@@ -795,8 +953,8 @@ static const struct spi_device_id m25p_ids[] = {
        { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, 0) },
        { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, 0) },
        { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
-       { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, 0) },
-       { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) },
+       { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, M25P80_QUAD_READ) },
+       { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, M25P80_QUAD_READ) },
        { "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
        { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
        { "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
@@ -851,6 +1009,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
        { "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
 
+       { "m25px16",    INFO(0x207115,  0, 64 * 1024, 32, SECT_4K) },
        { "m25px32",    INFO(0x207116,  0, 64 * 1024, 64, SECT_4K) },
        { "m25px32-s0", INFO(0x207316,  0, 64 * 1024, 64, SECT_4K) },
        { "m25px32-s1", INFO(0x206316,  0, 64 * 1024, 64, SECT_4K) },
@@ -937,6 +1096,7 @@ static int m25p_probe(struct spi_device *spi)
        unsigned                        i;
        struct mtd_part_parser_data     ppdata;
        struct device_node *np = spi->dev.of_node;
+       int ret;
 
        /* Platform data helps sort out which chip type we have, as
         * well as how this board partitions it.  If we don't have
@@ -1051,22 +1211,46 @@ static int m25p_probe(struct spi_device *spi)
        flash->page_size = info->page_size;
        flash->mtd.writebufsize = flash->page_size;
 
-       if (np)
+       if (np) {
                /* If we were instantiated by DT, use it */
-               flash->fast_read = of_property_read_bool(np, "m25p,fast-read");
-       else
+               if (of_property_read_bool(np, "m25p,fast-read"))
+                       flash->flash_read = M25P80_FAST;
+               else
+                       flash->flash_read = M25P80_NORMAL;
+       } else {
                /* If we weren't instantiated by DT, default to fast-read */
-               flash->fast_read = true;
+               flash->flash_read = M25P80_FAST;
+       }
 
        /* Some devices cannot do fast-read, no matter what DT tells us */
        if (info->flags & M25P_NO_FR)
-               flash->fast_read = false;
+               flash->flash_read = M25P80_NORMAL;
+
+       /* Quad-read mode takes precedence over fast/normal */
+       if (spi->mode & SPI_RX_QUAD && info->flags & M25P80_QUAD_READ) {
+               ret = set_quad_mode(flash, info->jedec_id);
+               if (ret) {
+                       dev_err(&flash->spi->dev, "quad mode not supported\n");
+                       return ret;
+               }
+               flash->flash_read = M25P80_QUAD;
+       }
 
        /* Default commands */
-       if (flash->fast_read)
+       switch (flash->flash_read) {
+       case M25P80_QUAD:
+               flash->read_opcode = OPCODE_QUAD_READ;
+               break;
+       case M25P80_FAST:
                flash->read_opcode = OPCODE_FAST_READ;
-       else
+               break;
+       case M25P80_NORMAL:
                flash->read_opcode = OPCODE_NORM_READ;
+               break;
+       default:
+               dev_err(&flash->spi->dev, "No Read opcode defined\n");
+               return -EINVAL;
+       }
 
        flash->program_opcode = OPCODE_PP;
 
@@ -1077,9 +1261,17 @@ static int m25p_probe(struct spi_device *spi)
                flash->addr_width = 4;
                if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) {
                        /* Dedicated 4-byte command set */
-                       flash->read_opcode = flash->fast_read ?
-                               OPCODE_FAST_READ_4B :
-                               OPCODE_NORM_READ_4B;
+                       switch (flash->flash_read) {
+                       case M25P80_QUAD:
+                               flash->read_opcode = OPCODE_QUAD_READ_4B;
+                               break;
+                       case M25P80_FAST:
+                               flash->read_opcode = OPCODE_FAST_READ_4B;
+                               break;
+                       case M25P80_NORMAL:
+                               flash->read_opcode = OPCODE_NORM_READ_4B;
+                               break;
+                       }
                        flash->program_opcode = OPCODE_PP_4B;
                        /* No small sector erase for 4-byte command set */
                        flash->erase_opcode = OPCODE_SE_4B;
index 182849d39c61acb34c40a79ab6bf04e30162da79..5c8b322ba904b1691bf204efc3f4523106dc8f67 100644 (file)
@@ -205,7 +205,7 @@ static int __init ms02nv_init_one(ulong addr)
        mtd->type = MTD_RAM;
        mtd->flags = MTD_CAP_RAM;
        mtd->size = fixsize;
-       mtd->name = (char *)ms02nv_name;
+       mtd->name = ms02nv_name;
        mtd->owner = THIS_MODULE;
        mtd->_read = ms02nv_read;
        mtd->_write = ms02nv_write;
index 4a47b0266d4e587761a2db5c1cd2e1613fc710bc..624069de4f28c067260fc4fec75c35b713fc5c84 100644 (file)
@@ -669,7 +669,6 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
        if (!err)
                return 0;
 
-       spi_set_drvdata(spi, NULL);
        kfree(priv);
        return err;
 }
@@ -899,10 +898,8 @@ static int dataflash_remove(struct spi_device *spi)
        pr_debug("%s: remove\n", dev_name(&spi->dev));
 
        status = mtd_device_unregister(&flash->mtd);
-       if (status == 0) {
-               spi_set_drvdata(spi, NULL);
+       if (status == 0)
                kfree(flash);
-       }
        return status;
 }
 
index ec59d65897fbe38976112ab071741b6c2d3b9189..8e285089229c364ee29c6b4f7c90a872d6e7c693 100644 (file)
@@ -92,7 +92,7 @@ static void __exit cleanup_mtdram(void)
 }
 
 int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
-               unsigned long size, char *name)
+               unsigned long size, const char *name)
 {
        memset(mtd, 0, sizeof(*mtd));
 
index 2ef19aa0086bee62d51a9986ea50f5983461869c..d38b6460d50565c21fa46978d3f2383d13299e6f 100644 (file)
@@ -388,7 +388,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
        wake_up(&chip->wq);
 }
 
-int do_write_buffer(struct map_info *map, struct flchip *chip,
+static int do_write_buffer(struct map_info *map, struct flchip *chip,
                        unsigned long adr, const struct kvec **pvec,
                        unsigned long *pvec_seek, int len)
 {
@@ -469,7 +469,7 @@ int do_write_buffer(struct map_info *map, struct flchip *chip,
        return ret;
 }
 
-int do_erase_oneblock(struct mtd_info *mtd, loff_t adr)
+static int do_erase_oneblock(struct mtd_info *mtd, loff_t adr)
 {
        struct map_info *map = mtd->priv;
        struct lpddr_private *lpddr = map->fldrv_priv;
@@ -748,34 +748,6 @@ static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
        return do_xxlock(mtd, ofs, len, DO_XXLOCK_UNLOCK);
 }
 
-int word_program(struct map_info *map, loff_t adr, uint32_t curval)
-{
-    int ret;
-       struct lpddr_private *lpddr = map->fldrv_priv;
-       int chipnum = adr >> lpddr->chipshift;
-       struct flchip *chip = &lpddr->chips[chipnum];
-
-       mutex_lock(&chip->mutex);
-       ret = get_chip(map, chip, FL_WRITING);
-       if (ret) {
-               mutex_unlock(&chip->mutex);
-               return ret;
-       }
-
-       send_pfow_command(map, LPDDR_WORD_PROGRAM, adr, 0x00, (map_word *)&curval);
-
-       ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->SingleWordProgTime));
-       if (ret)        {
-               printk(KERN_WARNING"%s word_program error at: %llx; val: %x\n",
-                       map->name, adr, curval);
-               goto out;
-       }
-
-out:   put_chip(map, chip);
-       mutex_unlock(&chip->mutex);
-       return ret;
-}
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexey Korolev <akorolev@infradead.org>");
 MODULE_DESCRIPTION("MTD driver for LPDDR flash chips");
index 10debfea81e7147c25fa00e4913bd2d336c24b6a..d6b2451eab1d9f0db5808c3ad837ac2f6f604499 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/init.h>
@@ -162,13 +163,6 @@ static int ixp4xx_flash_remove(struct platform_device *dev)
                mtd_device_unregister(info->mtd);
                map_destroy(info->mtd);
        }
-       if (info->map.virt)
-               iounmap(info->map.virt);
-
-       if (info->res) {
-               release_resource(info->res);
-               kfree(info->res);
-       }
 
        if (plat->exit)
                plat->exit();
@@ -194,7 +188,8 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
                        return err;
        }
 
-       info = kzalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL);
+       info = devm_kzalloc(&dev->dev, sizeof(struct ixp4xx_flash_info),
+                           GFP_KERNEL);
        if(!info) {
                err = -ENOMEM;
                goto Error;
@@ -220,20 +215,9 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
        info->map.write = ixp4xx_probe_write16;
        info->map.copy_from = ixp4xx_copy_from;
 
-       info->res = request_mem_region(dev->resource->start,
-                       resource_size(dev->resource),
-                       "IXP4XXFlash");
-       if (!info->res) {
-               printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n");
-               err = -ENOMEM;
-               goto Error;
-       }
-
-       info->map.virt = ioremap(dev->resource->start,
-                                resource_size(dev->resource));
-       if (!info->map.virt) {
-               printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
-               err = -EIO;
+       info->map.virt = devm_ioremap_resource(&dev->dev, dev->resource);
+       if (IS_ERR(info->map.virt)) {
+               err = PTR_ERR(info->map.virt);
                goto Error;
        }
 
index d7ac65d1d569dee08e325480501e29cc550ef012..93c507a6f86245024d6b1e79a54ca2f8ad8d78b1 100644 (file)
@@ -123,24 +123,28 @@ ltq_mtd_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       ltq_mtd = kzalloc(sizeof(struct ltq_mtd), GFP_KERNEL);
+       ltq_mtd = devm_kzalloc(&pdev->dev, sizeof(struct ltq_mtd), GFP_KERNEL);
+       if (!ltq_mtd)
+               return -ENOMEM;
+
        platform_set_drvdata(pdev, ltq_mtd);
 
        ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!ltq_mtd->res) {
                dev_err(&pdev->dev, "failed to get memory resource\n");
-               err = -ENOENT;
-               goto err_out;
+               return -ENOENT;
        }
 
-       ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL);
+       ltq_mtd->map = devm_kzalloc(&pdev->dev, sizeof(struct map_info),
+                                   GFP_KERNEL);
+       if (!ltq_mtd->map)
+               return -ENOMEM;
+
        ltq_mtd->map->phys = ltq_mtd->res->start;
        ltq_mtd->map->size = resource_size(ltq_mtd->res);
        ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res);
-       if (IS_ERR(ltq_mtd->map->virt)) {
-               err = PTR_ERR(ltq_mtd->map->virt);
-               goto err_out;
-       }
+       if (IS_ERR(ltq_mtd->map->virt))
+               return PTR_ERR(ltq_mtd->map->virt);
 
        ltq_mtd->map->name = ltq_map_name;
        ltq_mtd->map->bankwidth = 2;
@@ -155,8 +159,7 @@ ltq_mtd_probe(struct platform_device *pdev)
 
        if (!ltq_mtd->mtd) {
                dev_err(&pdev->dev, "probing failed\n");
-               err = -ENXIO;
-               goto err_free;
+               return -ENXIO;
        }
 
        ltq_mtd->mtd->owner = THIS_MODULE;
@@ -177,10 +180,6 @@ ltq_mtd_probe(struct platform_device *pdev)
 
 err_destroy:
        map_destroy(ltq_mtd->mtd);
-err_free:
-       kfree(ltq_mtd->map);
-err_out:
-       kfree(ltq_mtd);
        return err;
 }
 
@@ -189,13 +188,9 @@ ltq_mtd_remove(struct platform_device *pdev)
 {
        struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev);
 
-       if (ltq_mtd) {
-               if (ltq_mtd->mtd) {
-                       mtd_device_unregister(ltq_mtd->mtd);
-                       map_destroy(ltq_mtd->mtd);
-               }
-               kfree(ltq_mtd->map);
-               kfree(ltq_mtd);
+       if (ltq_mtd && ltq_mtd->mtd) {
+               mtd_device_unregister(ltq_mtd->mtd);
+               map_destroy(ltq_mtd->mtd);
        }
        return 0;
 }
index 0f55589a56b815af4c00bc521c504db468774fa5..9aad854fe9121aaa821181bffe64e819ec0e8498 100644 (file)
@@ -61,7 +61,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
        if (!info)
                return -ENOMEM;
 
-       info->map.name = (char *) flash->name;
+       info->map.name = flash->name;
        info->map.bankwidth = flash->width;
        info->map.phys = res->start;
        info->map.size = resource_size(res);
index d467f3b11c96c72ded5f3019cc823eb50fc6bd0b..39cc4181f02538a438b8fc427e00e19c1074fde3 100644 (file)
@@ -75,7 +75,7 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp)
 
        up->name = of_get_property(dp, "model", NULL);
        if (up->name && 0 < strlen(up->name))
-               up->map.name = (char *)up->name;
+               up->map.name = up->name;
 
        up->map.phys = op->resource[0].start;
 
index 92311a56939fca8d53e05e178054520f80b3bcec..34c0b16aed5c4e2f7d61a22d3fdeaf2ca066a632 100644 (file)
@@ -313,15 +313,7 @@ static struct attribute *mtd_attrs[] = {
        &dev_attr_bitflip_threshold.attr,
        NULL,
 };
-
-static struct attribute_group mtd_group = {
-       .attrs          = mtd_attrs,
-};
-
-static const struct attribute_group *mtd_groups[] = {
-       &mtd_group,
-       NULL,
-};
+ATTRIBUTE_GROUPS(mtd);
 
 static struct device_type mtd_devtype = {
        .name           = "mtd",
index 6e732c3820c14bf9d07b693a0c1de9bfff0088f0..3c7d6d7623c1cd5557b4dfeb38e80e03fc6e2abc 100644 (file)
@@ -534,7 +534,7 @@ out_register:
        return slave;
 }
 
-int mtd_add_partition(struct mtd_info *master, char *name,
+int mtd_add_partition(struct mtd_info *master, const char *name,
                      long long offset, long long length)
 {
        struct mtd_partition part;
@@ -672,22 +672,19 @@ static struct mtd_part_parser *get_partition_parser(const char *name)
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while (0)
 
-int register_mtd_parser(struct mtd_part_parser *p)
+void register_mtd_parser(struct mtd_part_parser *p)
 {
        spin_lock(&part_parser_lock);
        list_add(&p->list, &part_parsers);
        spin_unlock(&part_parser_lock);
-
-       return 0;
 }
 EXPORT_SYMBOL_GPL(register_mtd_parser);
 
-int deregister_mtd_parser(struct mtd_part_parser *p)
+void deregister_mtd_parser(struct mtd_part_parser *p)
 {
        spin_lock(&part_parser_lock);
        list_del(&p->list);
        spin_unlock(&part_parser_lock);
-       return 0;
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
index 93ae6a6d94f713d6352abd612efd1fed05f43dfd..90ff447bf0437707fe763133532fbb6b89bae7b7 100644 (file)
@@ -95,7 +95,7 @@ config MTD_NAND_OMAP2
          platforms.
 
 config MTD_NAND_OMAP_BCH
-       depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3
+       depends on MTD_NAND_OMAP2
        tristate "Support hardware based BCH error correction"
        default n
        select BCH
@@ -326,11 +326,11 @@ config MTD_NAND_ATMEL
          on Atmel AT91 and AVR32 processors.
 
 config MTD_NAND_PXA3xx
-       tristate "Support for NAND flash devices on PXA3xx"
+       tristate "NAND support on PXA3xx and Armada 370/XP"
        depends on PXA3xx || ARCH_MMP || PLAT_ORION
        help
          This enables the driver for the NAND flash device found on
-         PXA3xx processors
+         PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
 
 config MTD_NAND_SLC_LPC32XX
        tristate "NXP LPC32xx SLC Controller"
@@ -458,17 +458,17 @@ config MTD_NAND_MXC
 
 config MTD_NAND_SH_FLCTL
        tristate "Support for NAND on Renesas SuperH FLCTL"
-       depends on SUPERH || ARCH_SHMOBILE
+       depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
        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 SoC"
-        depends on ARCH_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 processors.
+         DaVinci/Keystone processors.
 
 config MTD_NAND_TXX9NDFMC
        tristate "NAND Flash support for TXx9 SoC"
index 59f08c44abdbc9be920ea62974d19bcdc7884889..c36e9b84487cd36b55d96efd1d17c6db9494c0fc 100644 (file)
@@ -1961,10 +1961,8 @@ static int atmel_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for the device structure (and zero it) */
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
-       if (!host) {
-               printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n");
+       if (!host)
                return -ENOMEM;
-       }
 
        res = platform_driver_register(&atmel_nand_nfc_driver);
        if (res)
@@ -2062,14 +2060,14 @@ static int atmel_nand_probe(struct platform_device *pdev)
                }
 
                if (gpio_get_value(host->board.det_pin)) {
-                       printk(KERN_INFO "No SmartMedia card inserted.\n");
+                       dev_info(&pdev->dev, "No SmartMedia card inserted.\n");
                        res = -ENXIO;
                        goto err_no_card;
                }
        }
 
        if (host->board.on_flash_bbt || on_flash_bbt) {
-               printk(KERN_INFO "atmel_nand: Use On Flash BBT\n");
+               dev_info(&pdev->dev, "Use On Flash BBT\n");
                nand_chip->bbt_options |= NAND_BBT_USE_FLASH;
        }
 
index ae8dd7c4103922fc760786be079b7576ad648893..2880d888cfc5c260aefcdd5caba743d05a292ae6 100644 (file)
@@ -418,10 +418,8 @@ static int au1550nd_probe(struct platform_device *pdev)
        }
 
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx) {
-               dev_err(&pdev->dev, "no memory for NAND context\n");
+       if (!ctx)
                return -ENOMEM;
-       }
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!r) {
@@ -480,6 +478,8 @@ static int au1550nd_probe(struct platform_device *pdev)
 
        mtd_device_register(&ctx->info, pd->parts, pd->num_parts);
 
+       platform_set_drvdata(pdev, ctx);
+
        return 0;
 
 out3:
index 2c42e125720f2141258e064e1fc024fef092057b..94f55dbde995974213b48158048a92553bfc7475 100644 (file)
@@ -745,7 +745,6 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (info == NULL) {
-               dev_err(&pdev->dev, "no memory for flash info\n");
                err = -ENOMEM;
                goto out_err_kzalloc;
        }
index c34985a55101b0606f76ed580f1e13ac562913e2..f2f64addb5e87119d8b72e9122565ae3ec9150f9 100644 (file)
@@ -640,10 +640,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
        pci_set_master(pdev);
 
        mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL);
-       if (!mtd) {
-               dev_warn(&pdev->dev, "failed to alloc mtd_info\n");
+       if (!mtd)
                return  -ENOMEM;
-       }
        cafe = (void *)(&mtd[1]);
 
        mtd->dev.parent = &pdev->dev;
index 39b2ef848811a5d1cf1c7fea98ef8f6168e98c5f..66ec95e6ca6c760c2713a621d14ec09a51446d66 100644 (file)
@@ -164,7 +164,6 @@ static int __init cmx270_init(void)
                                  sizeof(struct nand_chip),
                                  GFP_KERNEL);
        if (!cmx270_nand_mtd) {
-               pr_debug("Unable to allocate CM-X270 NAND MTD device structure.\n");
                ret = -ENOMEM;
                goto err_kzalloc;
        }
index d469a9a1dea0de7ea5f31172995c6e79411e7822..88109d375ae7f65546a2225e894e19ade98c41ba 100644 (file)
@@ -199,7 +199,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
        /* Allocate memory for MTD device structure and private data */
        new_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!new_mtd) {
-               printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n");
                err = -ENOMEM;
                goto out;
        }
index b77a01efb4837ea325988ee6e58e82bd128d7892..a4989ec6292efa0127ba4cc84d13fd07ad09fe4b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/of_device.h>
 #include <linux/of.h>
+#include <linux/of_mtd.h>
 
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
@@ -487,7 +488,7 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
  * ten ECC bytes plus the manufacturer's bad block marker byte, and
  * and not overlapping the default BBT markers.
  */
-static struct nand_ecclayout hwecc4_small __initconst = {
+static struct nand_ecclayout hwecc4_small = {
        .eccbytes = 10,
        .eccpos = { 0, 1, 2, 3, 4,
                /* offset 5 holds the badblock marker */
@@ -503,7 +504,7 @@ static struct nand_ecclayout hwecc4_small __initconst = {
  * storing ten ECC bytes plus the manufacturer's bad block marker byte,
  * and not overlapping the default BBT markers.
  */
-static struct nand_ecclayout hwecc4_2048 __initconst = {
+static struct nand_ecclayout hwecc4_2048 = {
        .eccbytes = 40,
        .eccpos = {
                /* at the end of spare sector */
@@ -534,17 +535,19 @@ static struct davinci_nand_pdata
                struct davinci_nand_pdata *pdata;
                const char *mode;
                u32 prop;
-               int len;
 
                pdata =  devm_kzalloc(&pdev->dev,
                                sizeof(struct davinci_nand_pdata),
                                GFP_KERNEL);
                pdev->dev.platform_data = pdata;
                if (!pdata)
-                       return NULL;
+                       return ERR_PTR(-ENOMEM);
                if (!of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-chipselect", &prop))
                        pdev->id = prop;
+               else
+                       return ERR_PTR(-EINVAL);
+
                if (!of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-mask-ale", &prop))
                        pdata->mask_ale = prop;
@@ -555,6 +558,8 @@ static struct davinci_nand_pdata
                        "ti,davinci-mask-chipsel", &prop))
                        pdata->mask_chipsel = prop;
                if (!of_property_read_string(pdev->dev.of_node,
+                       "nand-ecc-mode", &mode) ||
+                   !of_property_read_string(pdev->dev.of_node,
                        "ti,davinci-ecc-mode", &mode)) {
                        if (!strncmp("none", mode, 4))
                                pdata->ecc_mode = NAND_ECC_NONE;
@@ -566,12 +571,16 @@ static struct davinci_nand_pdata
                if (!of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-ecc-bits", &prop))
                        pdata->ecc_bits = prop;
-               if (!of_property_read_u32(pdev->dev.of_node,
+
+               prop = of_get_nand_bus_width(pdev->dev.of_node);
+               if (0 < prop || !of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-nand-buswidth", &prop))
                        if (prop == 16)
                                pdata->options |= NAND_BUSWIDTH_16;
-               if (of_find_property(pdev->dev.of_node,
-                       "ti,davinci-nand-use-bbt", &len))
+               if (of_property_read_bool(pdev->dev.of_node,
+                       "nand-on-flash-bbt") ||
+                   of_property_read_bool(pdev->dev.of_node,
+                       "ti,davinci-nand-use-bbt"))
                        pdata->bbt_options = NAND_BBT_USE_FLASH;
        }
 
@@ -585,7 +594,7 @@ static struct davinci_nand_pdata
 }
 #endif
 
-static int __init nand_davinci_probe(struct platform_device *pdev)
+static int nand_davinci_probe(struct platform_device *pdev)
 {
        struct davinci_nand_pdata       *pdata;
        struct davinci_nand_info        *info;
@@ -598,6 +607,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        nand_ecc_modes_t                ecc_mode;
 
        pdata = nand_davinci_get_pdata(pdev);
+       if (IS_ERR(pdata))
+               return PTR_ERR(pdata);
+
        /* insist on board-specific configuration */
        if (!pdata)
                return -ENODEV;
@@ -607,11 +619,8 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                return -ENODEV;
 
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
-       if (!info) {
-               dev_err(&pdev->dev, "unable to allocate memory\n");
-               ret = -ENOMEM;
-               goto err_nomem;
-       }
+       if (!info)
+               return -ENOMEM;
 
        platform_set_drvdata(pdev, info);
 
@@ -619,19 +628,23 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        if (!res1 || !res2) {
                dev_err(&pdev->dev, "resource missing\n");
-               ret = -EINVAL;
-               goto err_nomem;
+               return -EINVAL;
        }
 
        vaddr = devm_ioremap_resource(&pdev->dev, res1);
-       if (IS_ERR(vaddr)) {
-               ret = PTR_ERR(vaddr);
-               goto err_ioremap;
-       }
-       base = devm_ioremap_resource(&pdev->dev, res2);
-       if (IS_ERR(base)) {
-               ret = PTR_ERR(base);
-               goto err_ioremap;
+       if (IS_ERR(vaddr))
+               return PTR_ERR(vaddr);
+
+       /*
+        * This registers range is used to setup NAND settings. In case with
+        * TI AEMIF driver, the same memory address range is requested already
+        * by AEMIF, so we cannot request it twice, just ioremap.
+        * The AEMIF and NAND drivers not use the same registers in this range.
+        */
+       base = devm_ioremap(&pdev->dev, res2->start, resource_size(res2));
+       if (!base) {
+               dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res2);
+               return -EADDRNOTAVAIL;
        }
 
        info->dev               = &pdev->dev;
@@ -699,7 +712,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                        spin_unlock_irq(&davinci_nand_lock);
 
                        if (ret == -EBUSY)
-                               goto err_ecc;
+                               return ret;
 
                        info->chip.ecc.calculate = nand_davinci_calculate_4bit;
                        info->chip.ecc.correct = nand_davinci_correct_4bit;
@@ -715,8 +728,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                info->chip.ecc.strength = pdata->ecc_bits;
                break;
        default:
-               ret = -EINVAL;
-               goto err_ecc;
+               return -EINVAL;
        }
        info->chip.ecc.mode = ecc_mode;
 
@@ -724,7 +736,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        if (IS_ERR(info->clk)) {
                ret = PTR_ERR(info->clk);
                dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
-               goto err_clk;
+               return ret;
        }
 
        ret = clk_prepare_enable(info->clk);
@@ -753,7 +765,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                                                        info->core_chipsel);
        if (ret < 0) {
                dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
-               goto err_timing;
+               goto err;
        }
 
        spin_lock_irq(&davinci_nand_lock);
@@ -769,7 +781,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1, NULL);
        if (ret < 0) {
                dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
-               goto err_scan;
+               goto err;
        }
 
        /* Update ECC layout if needed ... for 1-bit HW ECC, the default
@@ -783,7 +795,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                if (!chunks || info->mtd.oobsize < 16) {
                        dev_dbg(&pdev->dev, "too small\n");
                        ret = -EINVAL;
-                       goto err_scan;
+                       goto err;
                }
 
                /* For small page chips, preserve the manufacturer's
@@ -814,7 +826,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                dev_warn(&pdev->dev, "no 4-bit ECC support yet "
                                "for 4KiB-page NAND\n");
                ret = -EIO;
-               goto err_scan;
+               goto err;
 
 syndrome_done:
                info->chip.ecc.layout = &info->ecclayout;
@@ -822,7 +834,7 @@ syndrome_done:
 
        ret = nand_scan_tail(&info->mtd);
        if (ret < 0)
-               goto err_scan;
+               goto err;
 
        if (pdata->parts)
                ret = mtd_device_parse_register(&info->mtd, NULL, NULL,
@@ -835,7 +847,7 @@ syndrome_done:
                                                NULL, 0);
        }
        if (ret < 0)
-               goto err_scan;
+               goto err;
 
        val = davinci_nand_readl(info, NRCSR_OFFSET);
        dev_info(&pdev->dev, "controller rev. %d.%d\n",
@@ -843,8 +855,7 @@ syndrome_done:
 
        return 0;
 
-err_scan:
-err_timing:
+err:
        clk_disable_unprepare(info->clk);
 
 err_clk_enable:
@@ -852,15 +863,10 @@ err_clk_enable:
        if (ecc_mode == NAND_ECC_HW_SYNDROME)
                ecc4_busy = false;
        spin_unlock_irq(&davinci_nand_lock);
-
-err_ecc:
-err_clk:
-err_ioremap:
-err_nomem:
        return ret;
 }
 
-static int __exit nand_davinci_remove(struct platform_device *pdev)
+static int nand_davinci_remove(struct platform_device *pdev)
 {
        struct davinci_nand_info *info = platform_get_drvdata(pdev);
 
@@ -877,7 +883,8 @@ static int __exit nand_davinci_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver nand_davinci_driver = {
-       .remove         = __exit_p(nand_davinci_remove),
+       .probe          = nand_davinci_probe,
+       .remove         = nand_davinci_remove,
        .driver         = {
                .name   = "davinci_nand",
                .owner  = THIS_MODULE,
@@ -886,7 +893,7 @@ static struct platform_driver nand_davinci_driver = {
 };
 MODULE_ALIAS("platform:davinci_nand");
 
-module_platform_driver_probe(nand_davinci_driver, nand_davinci_probe);
+module_platform_driver(nand_davinci_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Texas Instruments");
index 370b9dd7a2786841f3180d732321c99416030559..c07cd573ad3af0dd4fa1e91f36c4a44259bbd5e7 100644 (file)
@@ -125,7 +125,6 @@ static void reset_buf(struct denali_nand_info *denali)
 
 static void write_byte_to_buf(struct denali_nand_info *denali, uint8_t byte)
 {
-       BUG_ON(denali->buf.tail >= sizeof(denali->buf.buf));
        denali->buf.buf[denali->buf.tail++] = byte;
 }
 
@@ -897,7 +896,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 /* this function examines buffers to see if they contain data that
  * indicate that the buffer is part of an erased region of flash.
  */
-bool is_erased(uint8_t *buf, int len)
+static bool is_erased(uint8_t *buf, int len)
 {
        int i = 0;
        for (i = 0; i < len; i++)
@@ -1429,20 +1428,12 @@ int denali_init(struct denali_nand_info *denali)
                }
        }
 
-       /* Is 32-bit DMA supported? */
-       ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
-       if (ret) {
-               pr_err("Spectra: no usable DMA configuration\n");
-               return ret;
-       }
-       denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
-                                            DENALI_BUF_SIZE,
-                                            DMA_BIDIRECTIONAL);
+       /* allocate a temporary buffer for nand_scan_ident() */
+       denali->buf.buf = devm_kzalloc(denali->dev, PAGE_SIZE,
+                                       GFP_DMA | GFP_KERNEL);
+       if (!denali->buf.buf)
+               return -ENOMEM;
 
-       if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
-               dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
-               return -EIO;
-       }
        denali->mtd.dev.parent = denali->dev;
        denali_hw_init(denali);
        denali_drv_init(denali);
@@ -1475,12 +1466,29 @@ int denali_init(struct denali_nand_info *denali)
                goto failed_req_irq;
        }
 
-       /* MTD supported page sizes vary by kernel. We validate our
-        * kernel supports the device here.
-        */
-       if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
-               ret = -ENODEV;
-               pr_err("Spectra: device size not supported by this version of MTD.");
+       /* allocate the right size buffer now */
+       devm_kfree(denali->dev, denali->buf.buf);
+       denali->buf.buf = devm_kzalloc(denali->dev,
+                            denali->mtd.writesize + denali->mtd.oobsize,
+                            GFP_KERNEL);
+       if (!denali->buf.buf) {
+               ret = -ENOMEM;
+               goto failed_req_irq;
+       }
+
+       /* Is 32-bit DMA supported? */
+       ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
+       if (ret) {
+               pr_err("Spectra: no usable DMA configuration\n");
+               goto failed_req_irq;
+       }
+
+       denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
+                            denali->mtd.writesize + denali->mtd.oobsize,
+                            DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
+               dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
+               ret = -EIO;
                goto failed_req_irq;
        }
 
@@ -1602,7 +1610,8 @@ EXPORT_SYMBOL(denali_init);
 void denali_remove(struct denali_nand_info *denali)
 {
        denali_irq_cleanup(denali->irq, denali);
-       dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+       dma_unmap_single(denali->dev, denali->buf.dma_buf,
+                       denali->mtd.writesize + denali->mtd.oobsize,
                        DMA_BIDIRECTIONAL);
 }
 EXPORT_SYMBOL(denali_remove);
index cec5712862c9d01c50c417cad96f0bf3aa9a60ec..96681746242171fcbb5fdb4ab6beb6a77be3e54b 100644 (file)
 
 #define ECC_SECTOR_SIZE     512
 
-#define DENALI_BUF_SIZE                (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE)
-
 struct nand_buf {
        int head;
        int tail;
-       uint8_t buf[DENALI_BUF_SIZE];
+       uint8_t *buf;
        dma_addr_t dma_buf;
 };
 
index 92530244e2cbfdf48ecc2aa2282b90d12a98d0ad..babb02c4b2204ed0c5881a3577084c2ea826d5df 100644 (file)
@@ -108,7 +108,7 @@ static int denali_dt_probe(struct platform_device *ofdev)
                denali->dev->dma_mask = NULL;
        }
 
-       dt->clk = clk_get(&ofdev->dev, NULL);
+       dt->clk = devm_clk_get(&ofdev->dev, NULL);
        if (IS_ERR(dt->clk)) {
                dev_err(&ofdev->dev, "no clk available\n");
                return PTR_ERR(dt->clk);
@@ -124,7 +124,6 @@ static int denali_dt_probe(struct platform_device *ofdev)
 
 out_disable_clk:
        clk_disable_unprepare(dt->clk);
-       clk_put(dt->clk);
 
        return ret;
 }
@@ -135,7 +134,6 @@ static int denali_dt_remove(struct platform_device *ofdev)
 
        denali_remove(&dt->denali);
        clk_disable(dt->clk);
-       clk_put(dt->clk);
 
        return 0;
 }
index 033f177a6369b2d240b499f33df0b6bd925ed4d2..6e2f387b823f694e59e368bc987850a986c7d0c2 100644 (file)
@@ -21,7 +21,7 @@
 #define DENALI_NAND_NAME    "denali-nand-pci"
 
 /* List of platforms this NAND controller has be integrated into */
-static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = {
+static const struct pci_device_id denali_pci_ids[] = {
        { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
        { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
        { /* end: all zeroes */ }
@@ -131,7 +131,6 @@ static struct pci_driver denali_pci_driver = {
 
 static int denali_init_pci(void)
 {
-       pr_info("Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__);
        return pci_register_driver(&denali_pci_driver);
 }
 module_init(denali_init_pci);
index b68a4959f700af3e2768af69e6dd9afd0f94c8e1..fec31d71b84e03d7a84cbaf15b4558c16d413e0a 100644 (file)
@@ -1058,7 +1058,6 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
 
        buf = kmalloc(mtd->writesize, GFP_KERNEL);
        if (!buf) {
-               printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
                return 0;
        }
        if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1)))
@@ -1166,7 +1165,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
 
        buf = kmalloc(mtd->writesize, GFP_KERNEL);
        if (!buf) {
-               printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
                return 0;
        }
 
@@ -1440,10 +1438,13 @@ static int __init doc_probe(unsigned long physadr)
        int reg, len, numchips;
        int ret = 0;
 
+       if (!request_mem_region(physadr, DOC_IOREMAP_LEN, NULL))
+               return -EBUSY;
        virtadr = ioremap(physadr, DOC_IOREMAP_LEN);
        if (!virtadr) {
                printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr);
-               return -EIO;
+               ret = -EIO;
+               goto error_ioremap;
        }
 
        /* It's not possible to cleanly detect the DiskOnChip - the
@@ -1561,7 +1562,6 @@ static int __init doc_probe(unsigned long physadr)
            sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr));
        mtd = kzalloc(len, GFP_KERNEL);
        if (!mtd) {
-               printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
                ret = -ENOMEM;
                goto fail;
        }
@@ -1629,6 +1629,10 @@ static int __init doc_probe(unsigned long physadr)
        WriteDOC(save_control, virtadr, DOCControl);
  fail:
        iounmap(virtadr);
+
+error_ioremap:
+       release_mem_region(physadr, DOC_IOREMAP_LEN);
+
        return ret;
 }
 
@@ -1645,6 +1649,7 @@ static void release_nanddoc(void)
                nextmtd = doc->nextdoc;
                nand_release(mtd);
                iounmap(doc->virtadr);
+               release_mem_region(doc->physadr, DOC_IOREMAP_LEN);
                kfree(mtd);
        }
 }
index c966fc7474ced5fc8423b9440340f1d9b5072bbc..bcf60800c3ce7f5e0489972ebe7a3e3f83d225df 100644 (file)
@@ -847,7 +847,6 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
        if (!fsl_lbc_ctrl_dev->nand) {
                elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
                if (!elbc_fcm_ctrl) {
-                       dev_err(dev, "failed to allocate memory\n");
                        mutex_unlock(&fsl_elbc_nand_mutex);
                        ret = -ENOMEM;
                        goto err;
@@ -875,7 +874,7 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
                goto err;
        }
 
-       priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
+       priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
        if (!priv->mtd.name) {
                ret = -ENOMEM;
                goto err;
index 43355779cff583975721e5c7bd7770bc055aa1c3..90ca7e75d6f038e4cefb365ee2a436eac4ac8cc2 100644 (file)
@@ -1060,7 +1060,6 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
        if (!fsl_ifc_ctrl_dev->nand) {
                ifc_nand_ctrl = kzalloc(sizeof(*ifc_nand_ctrl), GFP_KERNEL);
                if (!ifc_nand_ctrl) {
-                       dev_err(&dev->dev, "failed to allocate memory\n");
                        mutex_unlock(&fsl_ifc_nand_mutex);
                        return -ENOMEM;
                }
@@ -1101,7 +1100,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
                    IFC_NAND_EVTER_INTR_FTOERIR_EN |
                    IFC_NAND_EVTER_INTR_WPERIR_EN,
                    &ifc->ifc_nand.nand_evter_intr_en);
-       priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
+       priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
        if (!priv->mtd.name) {
                ret = -ENOMEM;
                goto err;
index 8b2752263db9a5549742bb36c3dcee48999b8b62..1550692973dc2ebcaa6864bc3e2c51607872b818 100644 (file)
@@ -889,10 +889,8 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
 
        pdata->nand_timings = devm_kzalloc(&pdev->dev,
                                sizeof(*pdata->nand_timings), GFP_KERNEL);
-       if (!pdata->nand_timings) {
-               dev_err(&pdev->dev, "no memory for nand_timing\n");
+       if (!pdata->nand_timings)
                return -ENOMEM;
-       }
        of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings,
                                                sizeof(*pdata->nand_timings));
 
@@ -950,10 +948,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for the device structure (and zero it) */
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
-       if (!host) {
-               dev_err(&pdev->dev, "failed to allocate device structure\n");
+       if (!host)
                return -ENOMEM;
-       }
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
        host->data_va = devm_ioremap_resource(&pdev->dev, res);
@@ -1108,8 +1104,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
                        host->ecc_place = &fsmc_ecc4_lp_place;
                        break;
                default:
-                       printk(KERN_WARNING "No oob scheme defined for "
-                              "oobsize %d\n", mtd->oobsize);
+                       dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
+                                mtd->oobsize);
                        BUG();
                }
        } else {
@@ -1124,8 +1120,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
                        nand->ecc.layout = &fsmc_ecc1_128_layout;
                        break;
                default:
-                       printk(KERN_WARNING "No oob scheme defined for "
-                              "oobsize %d\n", mtd->oobsize);
+                       dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
+                                mtd->oobsize);
                        BUG();
                }
        }
index e826f898241f92b24704ba7103fc0cdd970a63d1..8e6148aa4539a290b4b3a4cda8883f1bbba58f92 100644 (file)
@@ -132,13 +132,17 @@ static int gpio_nand_get_config_of(const struct device *dev,
 
 static struct resource *gpio_nand_get_io_sync_of(struct platform_device *pdev)
 {
-       struct resource *r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL);
+       struct resource *r;
        u64 addr;
 
-       if (!r || of_property_read_u64(pdev->dev.of_node,
+       if (of_property_read_u64(pdev->dev.of_node,
                                       "gpio-control-nand,io-sync-reg", &addr))
                return NULL;
 
+       r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL);
+       if (!r)
+               return NULL;
+
        r->start = addr;
        r->end = r->start + 0x3;
        r->flags = IORESOURCE_MEM;
@@ -211,10 +215,8 @@ static int gpio_nand_probe(struct platform_device *pdev)
                return -EINVAL;
 
        gpiomtd = devm_kzalloc(&pdev->dev, sizeof(*gpiomtd), GFP_KERNEL);
-       if (!gpiomtd) {
-               dev_err(&pdev->dev, "failed to create NAND MTD\n");
+       if (!gpiomtd)
                return -ENOMEM;
-       }
 
        chip = &gpiomtd->nand_chip;
 
index aaced29727fb0437f6a0c142253b04cbc0ca82d0..dd1df605a1d61ec8a43ffb5515ea50ce2f3c9b69 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/slab.h>
 
 #include "gpmi-nand.h"
 #include "gpmi-regs.h"
@@ -207,30 +208,41 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
        u32 reg;
        int i;
 
-       pr_err("Show GPMI registers :\n");
+       dev_err(this->dev, "Show GPMI registers :\n");
        for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
                reg = readl(r->gpmi_regs + i * 0x10);
-               pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+               dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
        }
 
        /* start to print out the BCH info */
-       pr_err("Show BCH registers :\n");
+       dev_err(this->dev, "Show BCH registers :\n");
        for (i = 0; i <= HW_BCH_VERSION / 0x10 + 1; i++) {
                reg = readl(r->bch_regs + i * 0x10);
-               pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+               dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
        }
-       pr_err("BCH Geometry :\n");
-       pr_err("GF length              : %u\n", geo->gf_len);
-       pr_err("ECC Strength           : %u\n", geo->ecc_strength);
-       pr_err("Page Size in Bytes     : %u\n", geo->page_size);
-       pr_err("Metadata Size in Bytes : %u\n", geo->metadata_size);
-       pr_err("ECC Chunk Size in Bytes: %u\n", geo->ecc_chunk_size);
-       pr_err("ECC Chunk Count        : %u\n", geo->ecc_chunk_count);
-       pr_err("Payload Size in Bytes  : %u\n", geo->payload_size);
-       pr_err("Auxiliary Size in Bytes: %u\n", geo->auxiliary_size);
-       pr_err("Auxiliary Status Offset: %u\n", geo->auxiliary_status_offset);
-       pr_err("Block Mark Byte Offset : %u\n", geo->block_mark_byte_offset);
-       pr_err("Block Mark Bit Offset  : %u\n", geo->block_mark_bit_offset);
+       dev_err(this->dev, "BCH Geometry :\n"
+               "GF length              : %u\n"
+               "ECC Strength           : %u\n"
+               "Page Size in Bytes     : %u\n"
+               "Metadata Size in Bytes : %u\n"
+               "ECC Chunk Size in Bytes: %u\n"
+               "ECC Chunk Count        : %u\n"
+               "Payload Size in Bytes  : %u\n"
+               "Auxiliary Size in Bytes: %u\n"
+               "Auxiliary Status Offset: %u\n"
+               "Block Mark Byte Offset : %u\n"
+               "Block Mark Bit Offset  : %u\n",
+               geo->gf_len,
+               geo->ecc_strength,
+               geo->page_size,
+               geo->metadata_size,
+               geo->ecc_chunk_size,
+               geo->ecc_chunk_count,
+               geo->payload_size,
+               geo->auxiliary_size,
+               geo->auxiliary_status_offset,
+               geo->block_mark_byte_offset,
+               geo->block_mark_bit_offset);
 }
 
 /* Configures the geometry for BCH.  */
@@ -265,8 +277,8 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
        * On the other hand, the MX28 needs the reset, because one case has been
        * seen where the BCH produced ECC errors constantly after 10000
-       * consecutive reboots. The latter case has not been seen on the MX23 yet,
-       * still we don't know if it could happen there as well.
+       * consecutive reboots. The latter case has not been seen on the MX23
+       * yet, still we don't know if it could happen there as well.
        */
        ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
        if (ret)
@@ -353,7 +365,7 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
        improved_timing_is_available =
                (target.tREA_in_ns  >= 0) &&
                (target.tRLOH_in_ns >= 0) &&
-               (target.tRHOH_in_ns >= 0) ;
+               (target.tRHOH_in_ns >= 0);
 
        /* Inspect the clock. */
        nfc->clock_frequency_in_hz = clk_get_rate(r->clock[0]);
@@ -911,10 +923,14 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
        struct resources  *r = &this->resources;
        struct nand_chip *nand = &this->nand;
        struct mtd_info  *mtd = &this->mtd;
-       uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
+       uint8_t *feature;
        unsigned long rate;
        int ret;
 
+       feature = kzalloc(ONFI_SUBFEATURE_PARAM_LEN, GFP_KERNEL);
+       if (!feature)
+               return -ENOMEM;
+
        nand->select_chip(mtd, 0);
 
        /* [1] send SET FEATURE commond to NAND */
@@ -942,11 +958,13 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
 
        this->flags |= GPMI_ASYNC_EDO_ENABLED;
        this->timing_mode = mode;
+       kfree(feature);
        dev_info(this->dev, "enable the asynchronous EDO mode %d\n", mode);
        return 0;
 
 err_out:
        nand->select_chip(mtd, -1);
+       kfree(feature);
        dev_err(this->dev, "mode:%d ,failed in set feature.\n", mode);
        return -EINVAL;
 }
@@ -986,7 +1004,7 @@ void gpmi_begin(struct gpmi_nand_data *this)
        /* Enable the clock. */
        ret = gpmi_enable_clk(this);
        if (ret) {
-               pr_err("We failed in enable the clk\n");
+               dev_err(this->dev, "We failed in enable the clk\n");
                goto err_out;
        }
 
@@ -1003,7 +1021,7 @@ void gpmi_begin(struct gpmi_nand_data *this)
        /* [1] Set HW_GPMI_TIMING0 */
        reg = BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) |
                BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles)         |
-               BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles)       ;
+               BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles);
 
        writel(reg, gpmi_regs + HW_GPMI_TIMING0);
 
@@ -1090,7 +1108,7 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
                mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
                reg = readl(r->gpmi_regs + HW_GPMI_STAT);
        } else
-               pr_err("unknow arch.\n");
+               dev_err(this->dev, "unknow arch.\n");
        return reg & mask;
 }
 
@@ -1121,10 +1139,8 @@ int gpmi_send_command(struct gpmi_nand_data *this)
        desc = dmaengine_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] send out the COMMAND + ADDRESS string stored in @buffer */
        sgl = &this->cmd_sgl;
@@ -1134,11 +1150,8 @@ int gpmi_send_command(struct gpmi_nand_data *this)
        desc = dmaengine_prep_slave_sg(channel,
                                sgl, 1, DMA_MEM_TO_DEV,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [3] submit the DMA */
        set_dma_type(this, DMA_FOR_COMMAND);
@@ -1167,20 +1180,17 @@ int gpmi_send_data(struct gpmi_nand_data *this)
        pio[1] = 0;
        desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] send DMA request */
        prepare_data_dma(this, DMA_TO_DEVICE);
        desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
                                        1, DMA_MEM_TO_DEV,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
+
        /* [3] submit the DMA */
        set_dma_type(this, DMA_FOR_WRITE_DATA);
        return start_dma_without_bch_irq(this, desc);
@@ -1204,20 +1214,16 @@ int gpmi_read_data(struct gpmi_nand_data *this)
        desc = dmaengine_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] : send DMA request */
        prepare_data_dma(this, DMA_FROM_DEVICE);
        desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
                                        1, DMA_DEV_TO_MEM,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [3] : submit the DMA */
        set_dma_type(this, DMA_FOR_READ_DATA);
@@ -1262,10 +1268,9 @@ int gpmi_send_page(struct gpmi_nand_data *this,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE,
                                        DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
+
        set_dma_type(this, DMA_FOR_WRITE_ECC_PAGE);
        return start_dma_with_bch_irq(this, desc);
 }
@@ -1297,10 +1302,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
        desc = dmaengine_prep_slave_sg(channel,
                                (struct scatterlist *)pio, 2,
                                DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] Enable the BCH block and read. */
        command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ;
@@ -1327,10 +1330,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [3] Disable the BCH block */
        command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
@@ -1348,10 +1349,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                                (struct scatterlist *)pio, 3,
                                DMA_TRANS_NONE,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 3 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [4] submit the DMA */
        set_dma_type(this, DMA_FOR_READ_ECC_PAGE);
index dabbc14db5630d8592268012fc067559179aa0f8..ca6369fe91ff31fc89bd382dca62261774310ff0 100644 (file)
@@ -18,9 +18,6 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -352,6 +349,9 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
 
 int common_nfc_set_geometry(struct gpmi_nand_data *this)
 {
+       if (of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc")
+               && set_geometry_by_ecc_info(this))
+               return 0;
        return legacy_set_geometry(this);
 }
 
@@ -367,25 +367,28 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
        struct scatterlist *sgl = &this->data_sgl;
        int ret;
 
-       this->direct_dma_map_ok = true;
-
        /* first try to map the upper buffer directly */
-       sg_init_one(sgl, this->upper_buf, this->upper_len);
-       ret = dma_map_sg(this->dev, sgl, 1, dr);
-       if (ret == 0) {
-               /* We have to use our own DMA buffer. */
-               sg_init_one(sgl, this->data_buffer_dma, PAGE_SIZE);
-
-               if (dr == DMA_TO_DEVICE)
-                       memcpy(this->data_buffer_dma, this->upper_buf,
-                               this->upper_len);
-
+       if (virt_addr_valid(this->upper_buf) &&
+               !object_is_on_stack(this->upper_buf)) {
+               sg_init_one(sgl, this->upper_buf, this->upper_len);
                ret = dma_map_sg(this->dev, sgl, 1, dr);
                if (ret == 0)
-                       pr_err("DMA mapping failed.\n");
+                       goto map_fail;
 
-               this->direct_dma_map_ok = false;
+               this->direct_dma_map_ok = true;
+               return;
        }
+
+map_fail:
+       /* We have to use our own DMA buffer. */
+       sg_init_one(sgl, this->data_buffer_dma, this->upper_len);
+
+       if (dr == DMA_TO_DEVICE)
+               memcpy(this->data_buffer_dma, this->upper_buf, this->upper_len);
+
+       dma_map_sg(this->dev, sgl, 1, dr);
+
+       this->direct_dma_map_ok = false;
 }
 
 /* This will be called after the DMA operation is finished. */
@@ -416,7 +419,7 @@ static void dma_irq_callback(void *param)
                break;
 
        default:
-               pr_err("in wrong DMA operation.\n");
+               dev_err(this->dev, "in wrong DMA operation.\n");
        }
 
        complete(dma_c);
@@ -438,7 +441,8 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this,
        /* Wait for the interrupt from the DMA block. */
        err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
        if (!err) {
-               pr_err("DMA timeout, last DMA :%d\n", this->last_dma_type);
+               dev_err(this->dev, "DMA timeout, last DMA :%d\n",
+                       this->last_dma_type);
                gpmi_dump_info(this);
                return -ETIMEDOUT;
        }
@@ -467,7 +471,8 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this,
        /* Wait for the interrupt from the BCH block. */
        err = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
        if (!err) {
-               pr_err("BCH timeout, last DMA :%d\n", this->last_dma_type);
+               dev_err(this->dev, "BCH timeout, last DMA :%d\n",
+                       this->last_dma_type);
                gpmi_dump_info(this);
                return -ETIMEDOUT;
        }
@@ -483,70 +488,38 @@ static int acquire_register_block(struct gpmi_nand_data *this,
        void __iomem *p;
 
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
-       if (!r) {
-               pr_err("Can't get resource for %s\n", res_name);
-               return -ENODEV;
-       }
-
-       p = ioremap(r->start, resource_size(r));
-       if (!p) {
-               pr_err("Can't remap %s\n", res_name);
-               return -ENOMEM;
-       }
+       p = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(p))
+               return PTR_ERR(p);
 
        if (!strcmp(res_name, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME))
                res->gpmi_regs = p;
        else if (!strcmp(res_name, GPMI_NAND_BCH_REGS_ADDR_RES_NAME))
                res->bch_regs = p;
        else
-               pr_err("unknown resource name : %s\n", res_name);
+               dev_err(this->dev, "unknown resource name : %s\n", res_name);
 
        return 0;
 }
 
-static void release_register_block(struct gpmi_nand_data *this)
-{
-       struct resources *res = &this->resources;
-       if (res->gpmi_regs)
-               iounmap(res->gpmi_regs);
-       if (res->bch_regs)
-               iounmap(res->bch_regs);
-       res->gpmi_regs = NULL;
-       res->bch_regs = NULL;
-}
-
 static int acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
 {
        struct platform_device *pdev = this->pdev;
-       struct resources *res = &this->resources;
        const char *res_name = GPMI_NAND_BCH_INTERRUPT_RES_NAME;
        struct resource *r;
        int err;
 
        r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
        if (!r) {
-               pr_err("Can't get resource for %s\n", res_name);
+               dev_err(this->dev, "Can't get resource for %s\n", res_name);
                return -ENODEV;
        }
 
-       err = request_irq(r->start, irq_h, 0, res_name, this);
-       if (err) {
-               pr_err("Can't own %s\n", res_name);
-               return err;
-       }
-
-       res->bch_low_interrupt = r->start;
-       res->bch_high_interrupt = r->end;
-       return 0;
-}
-
-static void release_bch_irq(struct gpmi_nand_data *this)
-{
-       struct resources *res = &this->resources;
-       int i = res->bch_low_interrupt;
+       err = devm_request_irq(this->dev, r->start, irq_h, 0, res_name, this);
+       if (err)
+               dev_err(this->dev, "error requesting BCH IRQ\n");
 
-       for (; i <= res->bch_high_interrupt; i++)
-               free_irq(i, this);
+       return err;
 }
 
 static void release_dma_channels(struct gpmi_nand_data *this)
@@ -567,7 +540,7 @@ static int acquire_dma_channels(struct gpmi_nand_data *this)
        /* request dma channel */
        dma_chan = dma_request_slave_channel(&pdev->dev, "rx-tx");
        if (!dma_chan) {
-               pr_err("Failed to request DMA channel.\n");
+               dev_err(this->dev, "Failed to request DMA channel.\n");
                goto acquire_err;
        }
 
@@ -579,21 +552,6 @@ acquire_err:
        return -EINVAL;
 }
 
-static void gpmi_put_clks(struct gpmi_nand_data *this)
-{
-       struct resources *r = &this->resources;
-       struct clk *clk;
-       int i;
-
-       for (i = 0; i < GPMI_CLK_MAX; i++) {
-               clk = r->clock[i];
-               if (clk) {
-                       clk_put(clk);
-                       r->clock[i] = NULL;
-               }
-       }
-}
-
 static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = {
        "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
 };
@@ -606,7 +564,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
        int err, i;
 
        /* The main clock is stored in the first. */
-       r->clock[0] = clk_get(this->dev, "gpmi_io");
+       r->clock[0] = devm_clk_get(this->dev, "gpmi_io");
        if (IS_ERR(r->clock[0])) {
                err = PTR_ERR(r->clock[0]);
                goto err_clock;
@@ -622,7 +580,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
                if (extra_clks[i - 1] == NULL)
                        break;
 
-               clk = clk_get(this->dev, extra_clks[i - 1]);
+               clk = devm_clk_get(this->dev, extra_clks[i - 1]);
                if (IS_ERR(clk)) {
                        err = PTR_ERR(clk);
                        goto err_clock;
@@ -644,7 +602,6 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
 
 err_clock:
        dev_dbg(this->dev, "failed in finding the clocks.\n");
-       gpmi_put_clks(this);
        return err;
 }
 
@@ -666,7 +623,7 @@ static int acquire_resources(struct gpmi_nand_data *this)
 
        ret = acquire_dma_channels(this);
        if (ret)
-               goto exit_dma_channels;
+               goto exit_regs;
 
        ret = gpmi_get_clks(this);
        if (ret)
@@ -675,18 +632,12 @@ static int acquire_resources(struct gpmi_nand_data *this)
 
 exit_clock:
        release_dma_channels(this);
-exit_dma_channels:
-       release_bch_irq(this);
 exit_regs:
-       release_register_block(this);
        return ret;
 }
 
 static void release_resources(struct gpmi_nand_data *this)
 {
-       gpmi_put_clks(this);
-       release_register_block(this);
-       release_bch_irq(this);
        release_dma_channels(this);
 }
 
@@ -732,8 +683,7 @@ static int read_page_prepare(struct gpmi_nand_data *this,
                                                length, DMA_FROM_DEVICE);
                if (dma_mapping_error(dev, dest_phys)) {
                        if (alt_size < length) {
-                               pr_err("%s, Alternate buffer is too small\n",
-                                       __func__);
+                               dev_err(dev, "Alternate buffer is too small\n");
                                return -ENOMEM;
                        }
                        goto map_failed;
@@ -783,8 +733,7 @@ static int send_page_prepare(struct gpmi_nand_data *this,
                                                DMA_TO_DEVICE);
                if (dma_mapping_error(dev, source_phys)) {
                        if (alt_size < length) {
-                               pr_err("%s, Alternate buffer is too small\n",
-                                       __func__);
+                               dev_err(dev, "Alternate buffer is too small\n");
                                return -ENOMEM;
                        }
                        goto map_failed;
@@ -837,14 +786,23 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 {
        struct bch_geometry *geo = &this->bch_geometry;
        struct device *dev = this->dev;
+       struct mtd_info *mtd = &this->mtd;
 
        /* [1] Allocate a command buffer. PAGE_SIZE is enough. */
        this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
        if (this->cmd_buffer == NULL)
                goto error_alloc;
 
-       /* [2] Allocate a read/write data buffer. PAGE_SIZE is enough. */
-       this->data_buffer_dma = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
+       /*
+        * [2] Allocate a read/write data buffer.
+        *     The gpmi_alloc_dma_buffer can be called twice.
+        *     We allocate a PAGE_SIZE length buffer if gpmi_alloc_dma_buffer
+        *     is called before the nand_scan_ident; and we allocate a buffer
+        *     of the real NAND page size when the gpmi_alloc_dma_buffer is
+        *     called after the nand_scan_ident.
+        */
+       this->data_buffer_dma = kzalloc(mtd->writesize ?: PAGE_SIZE,
+                                       GFP_DMA | GFP_KERNEL);
        if (this->data_buffer_dma == NULL)
                goto error_alloc;
 
@@ -872,7 +830,6 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 
 error_alloc:
        gpmi_free_dma_buffer(this);
-       pr_err("Error allocating DMA buffers!\n");
        return -ENOMEM;
 }
 
@@ -904,7 +861,8 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
 
        ret = gpmi_send_command(this);
        if (ret)
-               pr_err("Chip: %u, Error %d\n", this->current_chip, ret);
+               dev_err(this->dev, "Chip: %u, Error %d\n",
+                       this->current_chip, ret);
 
        this->command_length = 0;
 }
@@ -935,7 +893,7 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
        struct nand_chip *chip = mtd->priv;
        struct gpmi_nand_data *this = chip->priv;
 
-       pr_debug("len is %d\n", len);
+       dev_dbg(this->dev, "len is %d\n", len);
        this->upper_buf = buf;
        this->upper_len = len;
 
@@ -947,7 +905,7 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
        struct nand_chip *chip = mtd->priv;
        struct gpmi_nand_data *this = chip->priv;
 
-       pr_debug("len is %d\n", len);
+       dev_dbg(this->dev, "len is %d\n", len);
        this->upper_buf = (uint8_t *)buf;
        this->upper_len = len;
 
@@ -1026,13 +984,13 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
        unsigned int  max_bitflips = 0;
        int           ret;
 
-       pr_debug("page number is : %d\n", page);
+       dev_dbg(this->dev, "page number is : %d\n", page);
        ret = read_page_prepare(this, buf, mtd->writesize,
                                        this->payload_virt, this->payload_phys,
                                        nfc_geo->payload_size,
                                        &payload_virt, &payload_phys);
        if (ret) {
-               pr_err("Inadequate DMA buffer\n");
+               dev_err(this->dev, "Inadequate DMA buffer\n");
                ret = -ENOMEM;
                return ret;
        }
@@ -1046,7 +1004,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
                        nfc_geo->payload_size,
                        payload_virt, payload_phys);
        if (ret) {
-               pr_err("Error in ECC-based read: %d\n", ret);
+               dev_err(this->dev, "Error in ECC-based read: %d\n", ret);
                return ret;
        }
 
@@ -1102,7 +1060,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        dma_addr_t auxiliary_phys;
        int        ret;
 
-       pr_debug("ecc write page.\n");
+       dev_dbg(this->dev, "ecc write page.\n");
        if (this->swap_block_mark) {
                /*
                 * If control arrives here, we're doing block mark swapping.
@@ -1132,7 +1090,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                nfc_geo->payload_size,
                                &payload_virt, &payload_phys);
                if (ret) {
-                       pr_err("Inadequate payload DMA buffer\n");
+                       dev_err(this->dev, "Inadequate payload DMA buffer\n");
                        return 0;
                }
 
@@ -1142,7 +1100,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                nfc_geo->auxiliary_size,
                                &auxiliary_virt, &auxiliary_phys);
                if (ret) {
-                       pr_err("Inadequate auxiliary DMA buffer\n");
+                       dev_err(this->dev, "Inadequate auxiliary DMA buffer\n");
                        goto exit_auxiliary;
                }
        }
@@ -1150,7 +1108,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        /* Ask the NFC. */
        ret = gpmi_send_page(this, payload_phys, auxiliary_phys);
        if (ret)
-               pr_err("Error in ECC-based write: %d\n", ret);
+               dev_err(this->dev, "Error in ECC-based write: %d\n", ret);
 
        if (!this->swap_block_mark) {
                send_page_end(this, chip->oob_poi, mtd->oobsize,
@@ -1240,7 +1198,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
 {
        struct gpmi_nand_data *this = chip->priv;
 
-       pr_debug("page number is %d\n", page);
+       dev_dbg(this->dev, "page number is %d\n", page);
        /* clear the OOB buffer */
        memset(chip->oob_poi, ~0, mtd->oobsize);
 
@@ -1453,7 +1411,6 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
 
        /* Write the NCB fingerprint into the page buffer. */
        memset(buffer, ~0, mtd->writesize);
-       memset(chip->oob_poi, ~0, mtd->oobsize);
        memcpy(buffer + 12, fingerprint, strlen(fingerprint));
 
        /* Loop through the first search area, writing NCB fingerprints. */
@@ -1568,7 +1525,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
        /* Set up the NFC geometry which is used by BCH. */
        ret = bch_set_geometry(this);
        if (ret) {
-               pr_err("Error setting BCH geometry : %d\n", ret);
+               dev_err(this->dev, "Error setting BCH geometry : %d\n", ret);
                return ret;
        }
 
@@ -1576,20 +1533,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
        return gpmi_alloc_dma_buffer(this);
 }
 
-static int gpmi_pre_bbt_scan(struct gpmi_nand_data  *this)
-{
-       /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
-       if (GPMI_IS_MX23(this))
-               this->swap_block_mark = false;
-       else
-               this->swap_block_mark = true;
-
-       /* Set up the medium geometry */
-       return gpmi_set_geometry(this);
-
-}
-
-static void gpmi_nfc_exit(struct gpmi_nand_data *this)
+static void gpmi_nand_exit(struct gpmi_nand_data *this)
 {
        nand_release(&this->mtd);
        gpmi_free_dma_buffer(this);
@@ -1603,8 +1547,11 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
        struct bch_geometry *bch_geo = &this->bch_geometry;
        int ret;
 
-       /* Prepare for the BBT scan. */
-       ret = gpmi_pre_bbt_scan(this);
+       /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
+       this->swap_block_mark = !GPMI_IS_MX23(this);
+
+       /* Set up the medium geometry */
+       ret = gpmi_set_geometry(this);
        if (ret)
                return ret;
 
@@ -1629,7 +1576,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
        return 0;
 }
 
-static int gpmi_nfc_init(struct gpmi_nand_data *this)
+static int gpmi_nand_init(struct gpmi_nand_data *this)
 {
        struct mtd_info  *mtd = &this->mtd;
        struct nand_chip *chip = &this->nand;
@@ -1693,7 +1640,7 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this)
        return 0;
 
 err_out:
-       gpmi_nfc_exit(this);
+       gpmi_nand_exit(this);
        return ret;
 }
 
@@ -1728,15 +1675,13 @@ static int gpmi_nand_probe(struct platform_device *pdev)
        if (of_id) {
                pdev->id_entry = of_id->data;
        } else {
-               pr_err("Failed to find the right device id.\n");
+               dev_err(&pdev->dev, "Failed to find the right device id.\n");
                return -ENODEV;
        }
 
        this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL);
-       if (!this) {
-               pr_err("Failed to allocate per-device memory\n");
+       if (!this)
                return -ENOMEM;
-       }
 
        platform_set_drvdata(pdev, this);
        this->pdev  = pdev;
@@ -1750,7 +1695,7 @@ static int gpmi_nand_probe(struct platform_device *pdev)
        if (ret)
                goto exit_nfc_init;
 
-       ret = gpmi_nfc_init(this);
+       ret = gpmi_nand_init(this);
        if (ret)
                goto exit_nfc_init;
 
@@ -1770,7 +1715,7 @@ static int gpmi_nand_remove(struct platform_device *pdev)
 {
        struct gpmi_nand_data *this = platform_get_drvdata(pdev);
 
-       gpmi_nfc_exit(this);
+       gpmi_nand_exit(this);
        release_resources(this);
        return 0;
 }
index a7685e3a87486b86713fef19da82e9bbad3c6253..4c801fa1872530e681e801d2adaee333d4acffb4 100644 (file)
@@ -26,8 +26,6 @@
 struct resources {
        void __iomem  *gpmi_regs;
        void __iomem  *bch_regs;
-       unsigned int  bch_low_interrupt;
-       unsigned int  bch_high_interrupt;
        unsigned int  dma_low_channel;
        unsigned int  dma_high_channel;
        struct clk    *clock[GPMI_CLK_MAX];
index a264b888c66cc9153e0f160af0c50e4675826a93..a2c804de156bc71d31407020b9ffb133a408b4f1 100644 (file)
@@ -416,10 +416,8 @@ static int jz_nand_probe(struct platform_device *pdev)
        uint8_t nand_maf_id = 0, nand_dev_id = 0;
 
        nand = kzalloc(sizeof(*nand), GFP_KERNEL);
-       if (!nand) {
-               dev_err(&pdev->dev, "Failed to allocate device structure.\n");
+       if (!nand)
                return -ENOMEM;
-       }
 
        ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
        if (ret)
index 327d96c035050ce178711f03ee8ff4dd527a1fb3..687478c9f09c9a92aee00bdc595f6b5a8757bc0c 100644 (file)
@@ -539,20 +539,6 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
        return 0;
 }
 
-static int lpc32xx_write_page(struct mtd_info *mtd, struct nand_chip *chip,
-                       uint32_t offset, int data_len, const uint8_t *buf,
-                       int oob_required, int page, int cached, int raw)
-{
-       int res;
-
-       chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
-       res = lpc32xx_write_page_lowlevel(mtd, chip, buf, oob_required);
-       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-       lpc32xx_waitfunc(mtd, chip);
-
-       return res;
-}
-
 static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
                            int page)
 {
@@ -627,10 +613,8 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
        struct device_node *np = dev->of_node;
 
        ncfg = devm_kzalloc(dev, sizeof(*ncfg), GFP_KERNEL);
-       if (!ncfg) {
-               dev_err(dev, "could not allocate memory for platform data\n");
+       if (!ncfg)
                return NULL;
-       }
 
        of_property_read_u32(np, "nxp,tcea-delay", &ncfg->tcea_delay);
        of_property_read_u32(np, "nxp,busy-delay", &ncfg->busy_delay);
@@ -666,10 +650,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for the device structure (and zero it) */
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
-       if (!host) {
-               dev_err(&pdev->dev, "failed to allocate device structure.\n");
+       if (!host)
                return -ENOMEM;
-       }
 
        rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        host->io_base = devm_ioremap_resource(&pdev->dev, rc);
@@ -732,9 +714,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        nand_chip->ecc.write_oob = lpc32xx_write_oob;
        nand_chip->ecc.read_oob = lpc32xx_read_oob;
        nand_chip->ecc.strength = 4;
-       nand_chip->write_page = lpc32xx_write_page;
        nand_chip->waitfunc = lpc32xx_waitfunc;
 
+       nand_chip->options = NAND_NO_SUBPAGE_WRITE;
        nand_chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
        nand_chip->bbt_td = &lpc32xx_nand_bbt;
        nand_chip->bbt_md = &lpc32xx_nand_bbt_mirror;
@@ -764,14 +746,12 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 
        host->dma_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
        if (!host->dma_buf) {
-               dev_err(&pdev->dev, "Error allocating dma_buf memory\n");
                res = -ENOMEM;
                goto err_exit3;
        }
 
        host->dummy_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
        if (!host->dummy_buf) {
-               dev_err(&pdev->dev, "Error allocating dummy_buf memory\n");
                res = -ENOMEM;
                goto err_exit3;
        }
index 23e6974ccd205ec23a7bf19adcea54ffb3304bfa..53a6742e3da39a2e1e43be81cf11be943c07a886 100644 (file)
@@ -725,10 +725,8 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev)
        struct device_node *np = dev->of_node;
 
        ncfg = devm_kzalloc(dev, sizeof(*ncfg), GFP_KERNEL);
-       if (!ncfg) {
-               dev_err(dev, "could not allocate memory for NAND config\n");
+       if (!ncfg)
                return NULL;
-       }
 
        of_property_read_u32(np, "nxp,wdr-clks", &ncfg->wdr_clks);
        of_property_read_u32(np, "nxp,wwidth", &ncfg->wwidth);
@@ -772,10 +770,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for the device structure (and zero it) */
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
-       if (!host) {
-               dev_err(&pdev->dev, "failed to allocate device structure\n");
+       if (!host)
                return -ENOMEM;
-       }
        host->io_base_dma = rc->start;
 
        host->io_base = devm_ioremap_resource(&pdev->dev, rc);
@@ -791,8 +787,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        }
        if (host->ncfg->wp_gpio == -EPROBE_DEFER)
                return -EPROBE_DEFER;
-       if (gpio_is_valid(host->ncfg->wp_gpio) &&
-                       gpio_request(host->ncfg->wp_gpio, "NAND WP")) {
+       if (gpio_is_valid(host->ncfg->wp_gpio) && devm_gpio_request(&pdev->dev,
+                       host->ncfg->wp_gpio, "NAND WP")) {
                dev_err(&pdev->dev, "GPIO not available\n");
                return -EBUSY;
        }
@@ -808,7 +804,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        mtd->dev.parent = &pdev->dev;
 
        /* Get NAND clock */
-       host->clk = clk_get(&pdev->dev, NULL);
+       host->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(host->clk)) {
                dev_err(&pdev->dev, "Clock failure\n");
                res = -ENOENT;
@@ -858,7 +854,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        host->data_buf = devm_kzalloc(&pdev->dev, host->dma_buf_len,
                                      GFP_KERNEL);
        if (host->data_buf == NULL) {
-               dev_err(&pdev->dev, "Error allocating memory\n");
                res = -ENOMEM;
                goto err_exit2;
        }
@@ -927,10 +922,8 @@ err_exit3:
        dma_release_channel(host->dma_chan);
 err_exit2:
        clk_disable(host->clk);
-       clk_put(host->clk);
 err_exit1:
        lpc32xx_wp_enable(host);
-       gpio_free(host->ncfg->wp_gpio);
 
        return res;
 }
@@ -953,9 +946,7 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
        writel(tmp, SLC_CTRL(host->io_base));
 
        clk_disable(host->clk);
-       clk_put(host->clk);
        lpc32xx_wp_enable(host);
-       gpio_free(host->ncfg->wp_gpio);
 
        return 0;
 }
index 439bc389641841dc05f79ab638f7010e4a9cd053..61e2abc216ad321bf742ee2dcc1e57e3693c4192 100644 (file)
@@ -653,10 +653,8 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        }
 
        prv = devm_kzalloc(dev, sizeof(*prv), GFP_KERNEL);
-       if (!prv) {
-               dev_err(dev, "Memory exhausted!\n");
+       if (!prv)
                return -ENOMEM;
-       }
 
        mtd = &prv->mtd;
        chip = &prv->chip;
@@ -786,7 +784,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        /* Detect NAND chips */
        if (nand_scan(mtd, be32_to_cpup(chips_no))) {
                dev_err(dev, "NAND Flash not found !\n");
-               devm_free_irq(dev, prv->irq, mtd);
                retval = -ENXIO;
                goto error;
        }
@@ -811,7 +808,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 
        default:
                dev_err(dev, "Unsupported NAND flash!\n");
-               devm_free_irq(dev, prv->irq, mtd);
                retval = -ENXIO;
                goto error;
        }
@@ -822,7 +818,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
        if (retval) {
                dev_err(dev, "Error adding MTD device!\n");
-               devm_free_irq(dev, prv->irq, mtd);
                goto error;
        }
 
@@ -836,11 +831,8 @@ static int mpc5121_nfc_remove(struct platform_device *op)
 {
        struct device *dev = &op->dev;
        struct mtd_info *mtd = dev_get_drvdata(dev);
-       struct nand_chip *chip = mtd->priv;
-       struct mpc5121_nfc_prv *prv = chip->priv;
 
        nand_release(mtd);
-       devm_free_irq(dev, prv->irq, mtd);
        mpc5121_nfc_free(dev, mtd);
 
        return 0;
index 9dfdb06c508b05439cd93a71ce5c30ef8558335e..e9a4835c4dd9887f8546c5e95ce298674d5182a3 100644 (file)
@@ -677,7 +677,6 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
                ecc_stat >>= 4;
        } while (--no_subpages);
 
-       mtd->ecc_stats.corrected += ret;
        pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
 
        return ret;
@@ -1400,12 +1399,15 @@ static int mxcnd_probe(struct platform_device *pdev)
        int err = 0;
 
        /* Allocate memory for MTD device structure and private data */
-       host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host) +
-                       NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE, GFP_KERNEL);
+       host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host),
+                       GFP_KERNEL);
        if (!host)
                return -ENOMEM;
 
-       host->data_buf = (uint8_t *)(host + 1);
+       /* allocate a temporary buffer for the nand_scan_ident() */
+       host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
+       if (!host->data_buf)
+               return -ENOMEM;
 
        host->dev = &pdev->dev;
        /* structures must be linked */
@@ -1512,7 +1514,9 @@ static int mxcnd_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       clk_prepare_enable(host->clk);
+       err = clk_prepare_enable(host->clk);
+       if (err)
+               return err;
        host->clk_act = 1;
 
        /*
@@ -1531,6 +1535,15 @@ static int mxcnd_probe(struct platform_device *pdev)
                goto escan;
        }
 
+       /* allocate the right size buffer now */
+       devm_kfree(&pdev->dev, (void *)host->data_buf);
+       host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
+                                       GFP_KERNEL);
+       if (!host->data_buf) {
+               err = -ENOMEM;
+               goto escan;
+       }
+
        /* Call preset again, with correct writesize this time */
        host->devtype_data->preset(mtd);
 
@@ -1576,6 +1589,8 @@ static int mxcnd_remove(struct platform_device *pdev)
        struct mxc_nand_host *host = platform_get_drvdata(pdev);
 
        nand_release(&host->mtd);
+       if (host->clk_act)
+               clk_disable_unprepare(host->clk);
 
        return 0;
 }
index bd39f7b67906f65db526cbd0d1d27bb84ad93277..59eba5d2c68574fae787d36d2bd9e5ed29eb9f25 100644 (file)
@@ -29,6 +29,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -201,6 +203,51 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
        }
 }
 
+/**
+ * nand_write_byte - [DEFAULT] write single byte to chip
+ * @mtd: MTD device structure
+ * @byte: value to write
+ *
+ * Default function to write a byte to I/O[7:0]
+ */
+static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
+{
+       struct nand_chip *chip = mtd->priv;
+
+       chip->write_buf(mtd, &byte, 1);
+}
+
+/**
+ * nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16
+ * @mtd: MTD device structure
+ * @byte: value to write
+ *
+ * Default function to write a byte to I/O[7:0] on a 16-bit wide chip.
+ */
+static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
+{
+       struct nand_chip *chip = mtd->priv;
+       uint16_t word = byte;
+
+       /*
+        * It's not entirely clear what should happen to I/O[15:8] when writing
+        * a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads:
+        *
+        *    When the host supports a 16-bit bus width, only data is
+        *    transferred at the 16-bit width. All address and command line
+        *    transfers shall use only the lower 8-bits of the data bus. During
+        *    command transfers, the host may place any value on the upper
+        *    8-bits of the data bus. During address transfers, the host shall
+        *    set the upper 8-bits of the data bus to 00h.
+        *
+        * One user of the write_byte callback is nand_onfi_set_features. The
+        * four parameters are specified to be written to I/O[7:0], but this is
+        * neither an address nor a command transfer. Let's assume a 0 on the
+        * upper I/O lines is OK.
+        */
+       chip->write_buf(mtd, (uint8_t *)&word, 2);
+}
+
 /**
  * nand_write_buf - [DEFAULT] write buffer to chip
  * @mtd: MTD device structure
@@ -1407,6 +1454,30 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
        return NULL;
 }
 
+/**
+ * nand_setup_read_retry - [INTERN] Set the READ RETRY mode
+ * @mtd: MTD device structure
+ * @retry_mode: the retry mode to use
+ *
+ * Some vendors supply a special command to shift the Vt threshold, to be used
+ * when there are too many bitflips in a page (i.e., ECC error). After setting
+ * a new threshold, the host should retry reading the page.
+ */
+static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
+{
+       struct nand_chip *chip = mtd->priv;
+
+       pr_debug("setting READ RETRY mode %d\n", retry_mode);
+
+       if (retry_mode >= chip->read_retries)
+               return -EINVAL;
+
+       if (!chip->setup_read_retry)
+               return -EOPNOTSUPP;
+
+       return chip->setup_read_retry(mtd, retry_mode);
+}
+
 /**
  * nand_do_read_ops - [INTERN] Read data with ECC
  * @mtd: MTD device structure
@@ -1420,7 +1491,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 {
        int chipnr, page, realpage, col, bytes, aligned, oob_required;
        struct nand_chip *chip = mtd->priv;
-       struct mtd_ecc_stats stats;
        int ret = 0;
        uint32_t readlen = ops->len;
        uint32_t oobreadlen = ops->ooblen;
@@ -1429,8 +1499,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 
        uint8_t *bufpoi, *oob, *buf;
        unsigned int max_bitflips = 0;
-
-       stats = mtd->ecc_stats;
+       int retry_mode = 0;
+       bool ecc_fail = false;
 
        chipnr = (int)(from >> chip->chip_shift);
        chip->select_chip(mtd, chipnr);
@@ -1445,6 +1515,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
        oob_required = oob ? 1 : 0;
 
        while (1) {
+               unsigned int ecc_failures = mtd->ecc_stats.failed;
+
                bytes = min(mtd->writesize - col, readlen);
                aligned = (bytes == mtd->writesize);
 
@@ -1452,6 +1524,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                if (realpage != chip->pagebuf || oob) {
                        bufpoi = aligned ? buf : chip->buffers->databuf;
 
+read_retry:
                        chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
 
                        /*
@@ -1481,7 +1554,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                        /* Transfer not aligned data */
                        if (!aligned) {
                                if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
-                                   !(mtd->ecc_stats.failed - stats.failed) &&
+                                   !(mtd->ecc_stats.failed - ecc_failures) &&
                                    (ops->mode != MTD_OPS_RAW)) {
                                        chip->pagebuf = realpage;
                                        chip->pagebuf_bitflips = ret;
@@ -1492,8 +1565,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                                memcpy(buf, chip->buffers->databuf + col, bytes);
                        }
 
-                       buf += bytes;
-
                        if (unlikely(oob)) {
                                int toread = min(oobreadlen, max_oobsize);
 
@@ -1511,6 +1582,25 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                                else
                                        nand_wait_ready(mtd);
                        }
+
+                       if (mtd->ecc_stats.failed - ecc_failures) {
+                               if (retry_mode + 1 <= chip->read_retries) {
+                                       retry_mode++;
+                                       ret = nand_setup_read_retry(mtd,
+                                                       retry_mode);
+                                       if (ret < 0)
+                                               break;
+
+                                       /* Reset failures; retry */
+                                       mtd->ecc_stats.failed = ecc_failures;
+                                       goto read_retry;
+                               } else {
+                                       /* No more retry modes; real failure */
+                                       ecc_fail = true;
+                               }
+                       }
+
+                       buf += bytes;
                } else {
                        memcpy(buf, chip->buffers->databuf + col, bytes);
                        buf += bytes;
@@ -1520,6 +1610,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 
                readlen -= bytes;
 
+               /* Reset to retry mode 0 */
+               if (retry_mode) {
+                       ret = nand_setup_read_retry(mtd, 0);
+                       if (ret < 0)
+                               break;
+                       retry_mode = 0;
+               }
+
                if (!readlen)
                        break;
 
@@ -1545,7 +1643,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
        if (ret < 0)
                return ret;
 
-       if (mtd->ecc_stats.failed - stats.failed)
+       if (ecc_fail)
                return -EBADMSG;
 
        return max_bitflips;
@@ -2716,6 +2814,7 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
                        int addr, uint8_t *subfeature_param)
 {
        int status;
+       int i;
 
        if (!chip->onfi_version ||
            !(le16_to_cpu(chip->onfi_params.opt_cmd)
@@ -2723,7 +2822,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
                return -EINVAL;
 
        chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
-       chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+       for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
+               chip->write_byte(mtd, subfeature_param[i]);
+
        status = chip->waitfunc(mtd, chip);
        if (status & NAND_STATUS_FAIL)
                return -EIO;
@@ -2740,6 +2841,8 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
                        int addr, uint8_t *subfeature_param)
 {
+       int i;
+
        if (!chip->onfi_version ||
            !(le16_to_cpu(chip->onfi_params.opt_cmd)
              & ONFI_OPT_CMD_SET_GET_FEATURES))
@@ -2749,7 +2852,8 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
        memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
 
        chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
-       chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+       for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
+               *subfeature_param++ = chip->read_byte(mtd);
        return 0;
 }
 
@@ -2812,6 +2916,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
                chip->block_markbad = nand_default_block_markbad;
        if (!chip->write_buf || chip->write_buf == nand_write_buf)
                chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
+       if (!chip->write_byte || chip->write_byte == nand_write_byte)
+               chip->write_byte = busw ? nand_write_byte16 : nand_write_byte;
        if (!chip->read_buf || chip->read_buf == nand_read_buf)
                chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
        if (!chip->scan_bbt)
@@ -2926,6 +3032,30 @@ ext_out:
        return ret;
 }
 
+static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
+{
+       struct nand_chip *chip = mtd->priv;
+       uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
+
+       return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
+                       feature);
+}
+
+/*
+ * Configure chip properties from Micron vendor-specific ONFI table
+ */
+static void nand_onfi_detect_micron(struct nand_chip *chip,
+               struct nand_onfi_params *p)
+{
+       struct nand_onfi_vendor_micron *micron = (void *)p->vendor;
+
+       if (le16_to_cpu(p->vendor_revision) < 1)
+               return;
+
+       chip->read_retries = micron->read_retry_options;
+       chip->setup_read_retry = nand_setup_read_retry_micron;
+}
+
 /*
  * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
  */
@@ -2979,7 +3109,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
                chip->onfi_version = 10;
 
        if (!chip->onfi_version) {
-               pr_info("%s: unsupported ONFI version: %d\n", __func__, val);
+               pr_info("unsupported ONFI version: %d\n", val);
                return 0;
        }
 
@@ -3032,6 +3162,9 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
                pr_warn("Could not retrieve ONFI ECC requirements\n");
        }
 
+       if (p->jedec_id == NAND_MFR_MICRON)
+               nand_onfi_detect_micron(chip, p);
+
        return 1;
 }
 
@@ -3152,9 +3285,12 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
                        mtd->oobsize = 512;
                        break;
                case 6:
-               default: /* Other cases are "reserved" (unknown) */
                        mtd->oobsize = 640;
                        break;
+               case 7:
+               default: /* Other cases are "reserved" (unknown) */
+                       mtd->oobsize = 1024;
+                       break;
                }
                extid >>= 2;
                /* Calc blocksize */
@@ -3325,6 +3461,9 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
 
                *busw = type->options & NAND_BUSWIDTH_16;
 
+               if (!mtd->name)
+                       mtd->name = type->name;
+
                return true;
        }
        return false;
@@ -3372,8 +3511,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                id_data[i] = chip->read_byte(mtd);
 
        if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
-               pr_info("%s: second ID read did not match "
-                       "%02x,%02x against %02x,%02x\n", __func__,
+               pr_info("second ID read did not match %02x,%02x against %02x,%02x\n",
                        *maf_id, *dev_id, id_data[0], id_data[1]);
                return ERR_PTR(-ENODEV);
        }
@@ -3440,10 +3578,10 @@ ident_done:
                 * Check, if buswidth is correct. Hardware drivers should set
                 * chip correct!
                 */
-               pr_info("NAND device: Manufacturer ID:"
-                       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
-                       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
-               pr_warn("NAND bus width %d instead %d bit\n",
+               pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
+                       *maf_id, *dev_id);
+               pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, mtd->name);
+               pr_warn("bus width %d instead %d bit\n",
                           (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
                           busw ? 16 : 8);
                return ERR_PTR(-EINVAL);
@@ -3472,14 +3610,13 @@ ident_done:
        if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
                chip->cmdfunc = nand_command_lp;
 
-       pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)\n",
-               *maf_id, *dev_id, nand_manuf_ids[maf_idx].name,
+       pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
+               *maf_id, *dev_id);
+       pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
                chip->onfi_version ? chip->onfi_params.model : type->name);
-
-       pr_info("NAND device: %dMiB, %s, page size: %d, OOB size: %d\n",
+       pr_info("%dMiB, %s, page size: %d, OOB size: %d\n",
                (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
                mtd->writesize, mtd->oobsize);
-
        return type;
 }
 
@@ -3535,7 +3672,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
                chip->select_chip(mtd, -1);
        }
        if (i > 1)
-               pr_info("%d NAND chips detected\n", i);
+               pr_info("%d chips detected\n", i);
 
        /* Store the number of chips and calc total size for mtd */
        chip->numchips = i;
index a87b0a3afa351a1b8f8991836cb99af930d858da..daa2faacd7d09f99422fa3f64fc6947a7f4f92cc 100644 (file)
@@ -169,6 +169,8 @@ struct nand_manufacturers nand_manuf_ids[] = {
        {NAND_MFR_AMD, "AMD/Spansion"},
        {NAND_MFR_MACRONIX, "Macronix"},
        {NAND_MFR_EON, "Eon"},
+       {NAND_MFR_SANDISK, "SanDisk"},
+       {NAND_MFR_INTEL, "Intel"},
        {0x0, "Unknown"}
 };
 
index 52115151e4a7f325491a3dbf6f16ccd87221b37a..9ee09a8177c67feae055da60dcb033e9bf76f4c4 100644 (file)
@@ -241,12 +241,10 @@ static int nuc900_nand_probe(struct platform_device *pdev)
 {
        struct nuc900_nand *nuc900_nand;
        struct nand_chip *chip;
-       int retval;
        struct resource *res;
 
-       retval = 0;
-
-       nuc900_nand = kzalloc(sizeof(struct nuc900_nand), GFP_KERNEL);
+       nuc900_nand = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_nand),
+                                  GFP_KERNEL);
        if (!nuc900_nand)
                return -ENOMEM;
        chip = &(nuc900_nand->chip);
@@ -255,11 +253,9 @@ static int nuc900_nand_probe(struct platform_device *pdev)
        nuc900_nand->mtd.owner  = THIS_MODULE;
        spin_lock_init(&nuc900_nand->lock);
 
-       nuc900_nand->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(nuc900_nand->clk)) {
-               retval = -ENOENT;
-               goto fail1;
-       }
+       nuc900_nand->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(nuc900_nand->clk))
+               return -ENOENT;
        clk_enable(nuc900_nand->clk);
 
        chip->cmdfunc           = nuc900_nand_command_lp;
@@ -272,57 +268,29 @@ static int nuc900_nand_probe(struct platform_device *pdev)
        chip->ecc.mode          = NAND_ECC_SOFT;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               retval = -ENXIO;
-               goto fail1;
-       }
-
-       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-               retval = -EBUSY;
-               goto fail1;
-       }
-
-       nuc900_nand->reg = ioremap(res->start, resource_size(res));
-       if (!nuc900_nand->reg) {
-               retval = -ENOMEM;
-               goto fail2;
-       }
+       nuc900_nand->reg = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(nuc900_nand->reg))
+               return PTR_ERR(nuc900_nand->reg);
 
        nuc900_nand_enable(nuc900_nand);
 
-       if (nand_scan(&(nuc900_nand->mtd), 1)) {
-               retval = -ENXIO;
-               goto fail3;
-       }
+       if (nand_scan(&(nuc900_nand->mtd), 1))
+               return -ENXIO;
 
        mtd_device_register(&(nuc900_nand->mtd), partitions,
                            ARRAY_SIZE(partitions));
 
        platform_set_drvdata(pdev, nuc900_nand);
 
-       return retval;
-
-fail3: iounmap(nuc900_nand->reg);
-fail2: release_mem_region(res->start, resource_size(res));
-fail1: kfree(nuc900_nand);
-       return retval;
+       return 0;
 }
 
 static int nuc900_nand_remove(struct platform_device *pdev)
 {
        struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
-       struct resource *res;
 
        nand_release(&nuc900_nand->mtd);
-       iounmap(nuc900_nand->reg);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
        clk_disable(nuc900_nand->clk);
-       clk_put(nuc900_nand->clk);
-
-       kfree(nuc900_nand);
 
        return 0;
 }
index f77725009907751e62963f02a6ce52b10e41e366..ef4190a02b7bd591af7c97be8ee1e3caecf6f83c 100644 (file)
@@ -1730,13 +1730,7 @@ static int omap_nand_probe(struct platform_device *pdev)
                break;
 
        case NAND_OMAP_POLLED:
-               if (nand_chip->options & NAND_BUSWIDTH_16) {
-                       nand_chip->read_buf   = omap_read_buf16;
-                       nand_chip->write_buf  = omap_write_buf16;
-               } else {
-                       nand_chip->read_buf   = omap_read_buf8;
-                       nand_chip->write_buf  = omap_write_buf8;
-               }
+               /* Use nand_base defaults for {read,write}_buf */
                break;
 
        case NAND_OMAP_PREFETCH_DMA:
index a393a5b6ce1e5028155a415ae33db88067a7bfff..dd7fe817eafb319ebc9ae92b2cbbac8613b38add 100644 (file)
@@ -87,7 +87,6 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 
        nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL);
        if (!nc) {
-               printk(KERN_ERR "orion_nand: failed to allocate device structure.\n");
                ret = -ENOMEM;
                goto no_res;
        }
@@ -101,7 +100,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 
        io_base = ioremap(res->start, resource_size(res));
        if (!io_base) {
-               printk(KERN_ERR "orion_nand: ioremap failed\n");
+               dev_err(&pdev->dev, "ioremap failed\n");
                ret = -EIO;
                goto no_res;
        }
@@ -110,7 +109,6 @@ static int __init orion_nand_probe(struct platform_device *pdev)
                board = devm_kzalloc(&pdev->dev, sizeof(struct orion_nand_data),
                                        GFP_KERNEL);
                if (!board) {
-                       printk(KERN_ERR "orion_nand: failed to allocate board structure.\n");
                        ret = -ENOMEM;
                        goto no_res;
                }
index 4d174366a0f09ec2ebecd99fc8241fc978a05caa..90f871acb0efec737c918532bbdd350ca7969220 100644 (file)
@@ -223,7 +223,7 @@ MODULE_DEVICE_TABLE(of, pasemi_nand_match);
 static struct platform_driver pasemi_nand_driver =
 {
        .driver = {
-               .name = (char*)driver_name,
+               .name = driver_name,
                .owner = THIS_MODULE,
                .of_match_table = pasemi_nand_match,
        },
index cad4cdc9df399a70c77640be5a634b837996790d..0b068a5c0bff3c05aa2eba8e1ae93a01f6b8db98 100644 (file)
@@ -9,6 +9,7 @@
  *
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -47,30 +48,16 @@ static int plat_nand_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENXIO;
-
        /* Allocate memory for the device structure (and zero it) */
-       data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL);
-       if (!data) {
-               dev_err(&pdev->dev, "failed to allocate device structure.\n");
+       data = devm_kzalloc(&pdev->dev, sizeof(struct plat_nand_data),
+                           GFP_KERNEL);
+       if (!data)
                return -ENOMEM;
-       }
-
-       if (!request_mem_region(res->start, resource_size(res),
-                               dev_name(&pdev->dev))) {
-               dev_err(&pdev->dev, "request_mem_region failed\n");
-               err = -EBUSY;
-               goto out_free;
-       }
 
-       data->io_base = ioremap(res->start, resource_size(res));
-       if (data->io_base == NULL) {
-               dev_err(&pdev->dev, "ioremap failed\n");
-               err = -EIO;
-               goto out_release_io;
-       }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->io_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(data->io_base))
+               return PTR_ERR(data->io_base);
 
        data->chip.priv = &data;
        data->mtd.priv = &data->chip;
@@ -122,11 +109,6 @@ static int plat_nand_probe(struct platform_device *pdev)
 out:
        if (pdata->ctrl.remove)
                pdata->ctrl.remove(pdev);
-       iounmap(data->io_base);
-out_release_io:
-       release_mem_region(res->start, resource_size(res));
-out_free:
-       kfree(data);
        return err;
 }
 
@@ -137,16 +119,10 @@ static int plat_nand_remove(struct platform_device *pdev)
 {
        struct plat_nand_data *data = platform_get_drvdata(pdev);
        struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
-       struct resource *res;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
        nand_release(&data->mtd);
        if (pdata->ctrl.remove)
                pdata->ctrl.remove(pdev);
-       iounmap(data->io_base);
-       release_mem_region(res->start, resource_size(res));
-       kfree(data);
 
        return 0;
 }
index 4b3aaa898a8b6b3a4975d2218370711981cb59c4..2a7a0b27ac38dccc511abd296742a767ef183133 100644 (file)
@@ -7,6 +7,8 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * See Documentation/mtd/nand/pxa3xx-nand.txt for more details.
  */
 
 #include <linux/kernel.h>
@@ -24,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_mtd.h>
 
 #if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
 #define ARCH_HAS_DMA
@@ -35,6 +38,7 @@
 
 #include <linux/platform_data/mtd-nand-pxa3xx.h>
 
+#define NAND_DEV_READY_TIMEOUT  50
 #define        CHIP_DELAY_TIMEOUT      (2 * HZ/10)
 #define NAND_STOP_DELAY                (2 * HZ/50)
 #define PAGE_CHUNK_SIZE                (2048)
@@ -54,6 +58,7 @@
 #define NDPCR          (0x18) /* Page Count Register */
 #define NDBDR0         (0x1C) /* Bad Block Register 0 */
 #define NDBDR1         (0x20) /* Bad Block Register 1 */
+#define NDECCCTRL      (0x28) /* ECC control */
 #define NDDB           (0x40) /* Data Buffer */
 #define NDCB0          (0x48) /* Command Buffer0 */
 #define NDCB1          (0x4C) /* Command Buffer1 */
@@ -80,6 +85,9 @@
 #define NDCR_INT_MASK           (0xFFF)
 
 #define NDSR_MASK              (0xfff)
+#define NDSR_ERR_CNT_OFF       (16)
+#define NDSR_ERR_CNT_MASK       (0x1f)
+#define NDSR_ERR_CNT(sr)       ((sr >> NDSR_ERR_CNT_OFF) & NDSR_ERR_CNT_MASK)
 #define NDSR_RDY                (0x1 << 12)
 #define NDSR_FLASH_RDY          (0x1 << 11)
 #define NDSR_CS0_PAGED         (0x1 << 10)
@@ -88,8 +96,8 @@
 #define NDSR_CS1_CMDD          (0x1 << 7)
 #define NDSR_CS0_BBD           (0x1 << 6)
 #define NDSR_CS1_BBD           (0x1 << 5)
-#define NDSR_DBERR             (0x1 << 4)
-#define NDSR_SBERR             (0x1 << 3)
+#define NDSR_UNCORERR          (0x1 << 4)
+#define NDSR_CORERR            (0x1 << 3)
 #define NDSR_WRDREQ            (0x1 << 2)
 #define NDSR_RDDREQ            (0x1 << 1)
 #define NDSR_WRCMDREQ          (0x1)
 #define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS          (0x1 << 25)
 #define NDCB0_CSEL             (0x1 << 24)
+#define NDCB0_EXT_CMD_TYPE_MASK        (0x7 << 29)
+#define NDCB0_EXT_CMD_TYPE(x)  (((x) << 29) & NDCB0_EXT_CMD_TYPE_MASK)
 #define NDCB0_CMD_TYPE_MASK    (0x7 << 21)
 #define NDCB0_CMD_TYPE(x)      (((x) << 21) & NDCB0_CMD_TYPE_MASK)
 #define NDCB0_NC               (0x1 << 20)
 #define NDCB0_CMD1_MASK                (0xff)
 #define NDCB0_ADDR_CYC_SHIFT   (16)
 
+#define EXT_CMD_TYPE_DISPATCH  6 /* Command dispatch */
+#define EXT_CMD_TYPE_NAKED_RW  5 /* Naked read or Naked write */
+#define EXT_CMD_TYPE_READ      4 /* Read */
+#define EXT_CMD_TYPE_DISP_WR   4 /* Command dispatch with write */
+#define EXT_CMD_TYPE_FINAL     3 /* Final command */
+#define EXT_CMD_TYPE_LAST_RW   1 /* Last naked read/write */
+#define EXT_CMD_TYPE_MONO      0 /* Monolithic read/write */
+
 /* macros for registers read/write */
 #define nand_writel(info, off, val)    \
        __raw_writel((val), (info)->mmio_base + (off))
@@ -120,9 +138,9 @@ enum {
        ERR_NONE        = 0,
        ERR_DMABUSERR   = -1,
        ERR_SENDCMD     = -2,
-       ERR_DBERR       = -3,
+       ERR_UNCORERR    = -3,
        ERR_BBERR       = -4,
-       ERR_SBERR       = -5,
+       ERR_CORERR      = -5,
 };
 
 enum {
@@ -149,7 +167,6 @@ struct pxa3xx_nand_host {
        void                    *info_data;
 
        /* page size of attached chip */
-       unsigned int            page_size;
        int                     use_ecc;
        int                     cs;
 
@@ -167,11 +184,13 @@ struct pxa3xx_nand_info {
        struct clk              *clk;
        void __iomem            *mmio_base;
        unsigned long           mmio_phys;
-       struct completion       cmd_complete;
+       struct completion       cmd_complete, dev_ready;
 
        unsigned int            buf_start;
        unsigned int            buf_count;
        unsigned int            buf_size;
+       unsigned int            data_buff_pos;
+       unsigned int            oob_buff_pos;
 
        /* DMA information */
        int                     drcmr_dat;
@@ -195,13 +214,18 @@ struct pxa3xx_nand_info {
 
        int                     cs;
        int                     use_ecc;        /* use HW ECC ? */
+       int                     ecc_bch;        /* using BCH ECC? */
        int                     use_dma;        /* use DMA ? */
        int                     use_spare;      /* use spare ? */
-       int                     is_ready;
+       int                     need_wait;
 
-       unsigned int            page_size;      /* page size of attached chip */
-       unsigned int            data_size;      /* data size in FIFO */
+       unsigned int            data_size;      /* data to be read from FIFO */
+       unsigned int            chunk_size;     /* split commands chunk size */
        unsigned int            oob_size;
+       unsigned int            spare_size;
+       unsigned int            ecc_size;
+       unsigned int            ecc_err_cnt;
+       unsigned int            max_bitflips;
        int                     retcode;
 
        /* cached register value */
@@ -239,6 +263,64 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 { "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
 };
 
+static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
+static u8 bbt_mirror_pattern[] = {'1', 't', 'b', 'B', 'V', 'M' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
+       .offs = 8,
+       .len = 6,
+       .veroffs = 14,
+       .maxblocks = 8,         /* Last 8 blocks in each chip */
+       .pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
+       .offs = 8,
+       .len = 6,
+       .veroffs = 14,
+       .maxblocks = 8,         /* Last 8 blocks in each chip */
+       .pattern = bbt_mirror_pattern
+};
+
+static struct nand_ecclayout ecc_layout_2KB_bch4bit = {
+       .eccbytes = 32,
+       .eccpos = {
+               32, 33, 34, 35, 36, 37, 38, 39,
+               40, 41, 42, 43, 44, 45, 46, 47,
+               48, 49, 50, 51, 52, 53, 54, 55,
+               56, 57, 58, 59, 60, 61, 62, 63},
+       .oobfree = { {2, 30} }
+};
+
+static struct nand_ecclayout ecc_layout_4KB_bch4bit = {
+       .eccbytes = 64,
+       .eccpos = {
+               32,  33,  34,  35,  36,  37,  38,  39,
+               40,  41,  42,  43,  44,  45,  46,  47,
+               48,  49,  50,  51,  52,  53,  54,  55,
+               56,  57,  58,  59,  60,  61,  62,  63,
+               96,  97,  98,  99,  100, 101, 102, 103,
+               104, 105, 106, 107, 108, 109, 110, 111,
+               112, 113, 114, 115, 116, 117, 118, 119,
+               120, 121, 122, 123, 124, 125, 126, 127},
+       /* Bootrom looks in bytes 0 & 5 for bad blocks */
+       .oobfree = { {6, 26}, { 64, 32} }
+};
+
+static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
+       .eccbytes = 128,
+       .eccpos = {
+               32,  33,  34,  35,  36,  37,  38,  39,
+               40,  41,  42,  43,  44,  45,  46,  47,
+               48,  49,  50,  51,  52,  53,  54,  55,
+               56,  57,  58,  59,  60,  61,  62,  63},
+       .oobfree = { }
+};
+
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
@@ -256,6 +338,29 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)      (int)((ns) * (clk / 1000000) / 1000)
 
+static struct of_device_id pxa3xx_nand_dt_ids[] = {
+       {
+               .compatible = "marvell,pxa3xx-nand",
+               .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
+       },
+       {
+               .compatible = "marvell,armada370-nand",
+               .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
+
+static enum pxa3xx_nand_variant
+pxa3xx_nand_get_variant(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+                       of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
+       if (!of_id)
+               return PXA3XX_NAND_VARIANT_PXA;
+       return (enum pxa3xx_nand_variant)of_id->data;
+}
+
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
                                   const struct pxa3xx_nand_timing *t)
 {
@@ -280,25 +385,23 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
        nand_writel(info, NDTR1CS0, ndtr1);
 }
 
-static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
+/*
+ * Set the data and OOB size, depending on the selected
+ * spare and ECC configuration.
+ * Only applicable to READ0, READOOB and PAGEPROG commands.
+ */
+static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info,
+                               struct mtd_info *mtd)
 {
-       struct pxa3xx_nand_host *host = info->host[info->cs];
        int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
 
-       info->data_size = host->page_size;
-       if (!oob_enable) {
-               info->oob_size = 0;
+       info->data_size = mtd->writesize;
+       if (!oob_enable)
                return;
-       }
 
-       switch (host->page_size) {
-       case 2048:
-               info->oob_size = (info->use_ecc) ? 40 : 64;
-               break;
-       case 512:
-               info->oob_size = (info->use_ecc) ? 8 : 16;
-               break;
-       }
+       info->oob_size = info->spare_size;
+       if (!info->use_ecc)
+               info->oob_size += info->ecc_size;
 }
 
 /**
@@ -313,10 +416,15 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 
        ndcr = info->reg_ndcr;
 
-       if (info->use_ecc)
+       if (info->use_ecc) {
                ndcr |= NDCR_ECC_EN;
-       else
+               if (info->ecc_bch)
+                       nand_writel(info, NDECCCTRL, 0x1);
+       } else {
                ndcr &= ~NDCR_ECC_EN;
+               if (info->ecc_bch)
+                       nand_writel(info, NDECCCTRL, 0x0);
+       }
 
        if (info->use_dma)
                ndcr |= NDCR_DMA_EN;
@@ -375,26 +483,39 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
 
 static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
+       unsigned int do_bytes = min(info->data_size, info->chunk_size);
+
        switch (info->state) {
        case STATE_PIO_WRITING:
-               __raw_writesl(info->mmio_base + NDDB, info->data_buff,
-                               DIV_ROUND_UP(info->data_size, 4));
+               __raw_writesl(info->mmio_base + NDDB,
+                             info->data_buff + info->data_buff_pos,
+                             DIV_ROUND_UP(do_bytes, 4));
+
                if (info->oob_size > 0)
-                       __raw_writesl(info->mmio_base + NDDB, info->oob_buff,
-                                       DIV_ROUND_UP(info->oob_size, 4));
+                       __raw_writesl(info->mmio_base + NDDB,
+                                     info->oob_buff + info->oob_buff_pos,
+                                     DIV_ROUND_UP(info->oob_size, 4));
                break;
        case STATE_PIO_READING:
-               __raw_readsl(info->mmio_base + NDDB, info->data_buff,
-                               DIV_ROUND_UP(info->data_size, 4));
+               __raw_readsl(info->mmio_base + NDDB,
+                            info->data_buff + info->data_buff_pos,
+                            DIV_ROUND_UP(do_bytes, 4));
+
                if (info->oob_size > 0)
-                       __raw_readsl(info->mmio_base + NDDB, info->oob_buff,
-                                       DIV_ROUND_UP(info->oob_size, 4));
+                       __raw_readsl(info->mmio_base + NDDB,
+                                    info->oob_buff + info->oob_buff_pos,
+                                    DIV_ROUND_UP(info->oob_size, 4));
                break;
        default:
                dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
                                info->state);
                BUG();
        }
+
+       /* Update buffer pointers for multi-page read/write */
+       info->data_buff_pos += do_bytes;
+       info->oob_buff_pos += info->oob_size;
+       info->data_size -= do_bytes;
 }
 
 #ifdef ARCH_HAS_DMA
@@ -452,7 +573,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
        struct pxa3xx_nand_info *info = devid;
-       unsigned int status, is_completed = 0;
+       unsigned int status, is_completed = 0, is_ready = 0;
        unsigned int ready, cmd_done;
 
        if (info->cs == 0) {
@@ -465,10 +586,25 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 
        status = nand_readl(info, NDSR);
 
-       if (status & NDSR_DBERR)
-               info->retcode = ERR_DBERR;
-       if (status & NDSR_SBERR)
-               info->retcode = ERR_SBERR;
+       if (status & NDSR_UNCORERR)
+               info->retcode = ERR_UNCORERR;
+       if (status & NDSR_CORERR) {
+               info->retcode = ERR_CORERR;
+               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 &&
+                   info->ecc_bch)
+                       info->ecc_err_cnt = NDSR_ERR_CNT(status);
+               else
+                       info->ecc_err_cnt = 1;
+
+               /*
+                * Each chunk composing a page is corrected independently,
+                * and we need to store maximum number of corrected bitflips
+                * to return it to the MTD layer in ecc.read_page().
+                */
+               info->max_bitflips = max_t(unsigned int,
+                                          info->max_bitflips,
+                                          info->ecc_err_cnt);
+       }
        if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
                /* whether use dma to transfer data */
                if (info->use_dma) {
@@ -488,8 +624,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
                is_completed = 1;
        }
        if (status & ready) {
-               info->is_ready = 1;
                info->state = STATE_READY;
+               is_ready = 1;
        }
 
        if (status & NDSR_WRCMDREQ) {
@@ -518,6 +654,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
        nand_writel(info, NDSR, status);
        if (is_completed)
                complete(&info->cmd_complete);
+       if (is_ready)
+               complete(&info->dev_ready);
 NORMAL_IRQ_EXIT:
        return IRQ_HANDLED;
 }
@@ -530,51 +668,94 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
        return 1;
 }
 
-static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
-               uint16_t column, int page_addr)
+static void set_command_address(struct pxa3xx_nand_info *info,
+               unsigned int page_size, uint16_t column, int page_addr)
 {
-       int addr_cycle, exec_cmd;
-       struct pxa3xx_nand_host *host;
-       struct mtd_info *mtd;
+       /* small page addr setting */
+       if (page_size < PAGE_CHUNK_SIZE) {
+               info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+                               | (column & 0xFF);
 
-       host = info->host[info->cs];
-       mtd = host->mtd;
-       addr_cycle = 0;
-       exec_cmd = 1;
+               info->ndcb2 = 0;
+       } else {
+               info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+                               | (column & 0xFFFF);
+
+               if (page_addr & 0xFF0000)
+                       info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+               else
+                       info->ndcb2 = 0;
+       }
+}
+
+static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
+{
+       struct pxa3xx_nand_host *host = info->host[info->cs];
+       struct mtd_info *mtd = host->mtd;
 
        /* reset data and oob column point to handle data */
        info->buf_start         = 0;
        info->buf_count         = 0;
        info->oob_size          = 0;
+       info->data_buff_pos     = 0;
+       info->oob_buff_pos      = 0;
        info->use_ecc           = 0;
        info->use_spare         = 1;
-       info->is_ready          = 0;
        info->retcode           = ERR_NONE;
-       if (info->cs != 0)
-               info->ndcb0 = NDCB0_CSEL;
-       else
-               info->ndcb0 = 0;
+       info->ecc_err_cnt       = 0;
+       info->ndcb3             = 0;
+       info->need_wait         = 0;
 
        switch (command) {
        case NAND_CMD_READ0:
        case NAND_CMD_PAGEPROG:
                info->use_ecc = 1;
        case NAND_CMD_READOOB:
-               pxa3xx_set_datasize(info);
+               pxa3xx_set_datasize(info, mtd);
                break;
        case NAND_CMD_PARAM:
                info->use_spare = 0;
                break;
-       case NAND_CMD_SEQIN:
-               exec_cmd = 0;
-               break;
        default:
                info->ndcb1 = 0;
                info->ndcb2 = 0;
-               info->ndcb3 = 0;
                break;
        }
 
+       /*
+        * If we are about to issue a read command, or about to set
+        * the write address, then clean the data buffer.
+        */
+       if (command == NAND_CMD_READ0 ||
+           command == NAND_CMD_READOOB ||
+           command == NAND_CMD_SEQIN) {
+
+               info->buf_count = mtd->writesize + mtd->oobsize;
+               memset(info->data_buff, 0xFF, info->buf_count);
+       }
+
+}
+
+static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
+               int ext_cmd_type, uint16_t column, int page_addr)
+{
+       int addr_cycle, exec_cmd;
+       struct pxa3xx_nand_host *host;
+       struct mtd_info *mtd;
+
+       host = info->host[info->cs];
+       mtd = host->mtd;
+       addr_cycle = 0;
+       exec_cmd = 1;
+
+       if (info->cs != 0)
+               info->ndcb0 = NDCB0_CSEL;
+       else
+               info->ndcb0 = 0;
+
+       if (command == NAND_CMD_SEQIN)
+               exec_cmd = 0;
+
        addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
                                    + host->col_addr_cycles);
 
@@ -589,30 +770,42 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                if (command == NAND_CMD_READOOB)
                        info->buf_start += mtd->writesize;
 
-               /* Second command setting for large pages */
-               if (host->page_size >= PAGE_CHUNK_SIZE)
+               /*
+                * Multiple page read needs an 'extended command type' field,
+                * which is either naked-read or last-read according to the
+                * state.
+                */
+               if (mtd->writesize == PAGE_CHUNK_SIZE) {
                        info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8);
+               } else if (mtd->writesize > PAGE_CHUNK_SIZE) {
+                       info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8)
+                                       | NDCB0_LEN_OVRD
+                                       | NDCB0_EXT_CMD_TYPE(ext_cmd_type);
+                       info->ndcb3 = info->chunk_size +
+                                     info->oob_size;
+               }
+
+               set_command_address(info, mtd->writesize, column, page_addr);
+               break;
 
        case NAND_CMD_SEQIN:
-               /* small page addr setting */
-               if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
-                       info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
-                                       | (column & 0xFF);
 
-                       info->ndcb2 = 0;
-               } else {
-                       info->ndcb1 = ((page_addr & 0xFFFF) << 16)
-                                       | (column & 0xFFFF);
+               info->buf_start = column;
+               set_command_address(info, mtd->writesize, 0, page_addr);
 
-                       if (page_addr & 0xFF0000)
-                               info->ndcb2 = (page_addr & 0xFF0000) >> 16;
-                       else
-                               info->ndcb2 = 0;
+               /*
+                * Multiple page programming needs to execute the initial
+                * SEQIN command that sets the page address.
+                */
+               if (mtd->writesize > PAGE_CHUNK_SIZE) {
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                               | NDCB0_EXT_CMD_TYPE(ext_cmd_type)
+                               | addr_cycle
+                               | command;
+                       /* No data transfer in this case */
+                       info->data_size = 0;
+                       exec_cmd = 1;
                }
-
-               info->buf_count = mtd->writesize + mtd->oobsize;
-               memset(info->data_buff, 0xFF, info->buf_count);
-
                break;
 
        case NAND_CMD_PAGEPROG:
@@ -622,13 +815,40 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                        break;
                }
 
-               info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
-                               | NDCB0_AUTO_RS
-                               | NDCB0_ST_ROW_EN
-                               | NDCB0_DBC
-                               | (NAND_CMD_PAGEPROG << 8)
-                               | NAND_CMD_SEQIN
-                               | addr_cycle;
+               /* Second command setting for large pages */
+               if (mtd->writesize > PAGE_CHUNK_SIZE) {
+                       /*
+                        * Multiple page write uses the 'extended command'
+                        * field. This can be used to issue a command dispatch
+                        * or a naked-write depending on the current stage.
+                        */
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                                       | NDCB0_LEN_OVRD
+                                       | NDCB0_EXT_CMD_TYPE(ext_cmd_type);
+                       info->ndcb3 = info->chunk_size +
+                                     info->oob_size;
+
+                       /*
+                        * This is the command dispatch that completes a chunked
+                        * page program operation.
+                        */
+                       if (info->data_size == 0) {
+                               info->ndcb0 = NDCB0_CMD_TYPE(0x1)
+                                       | NDCB0_EXT_CMD_TYPE(ext_cmd_type)
+                                       | command;
+                               info->ndcb1 = 0;
+                               info->ndcb2 = 0;
+                               info->ndcb3 = 0;
+                       }
+               } else {
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                                       | NDCB0_AUTO_RS
+                                       | NDCB0_ST_ROW_EN
+                                       | NDCB0_DBC
+                                       | (NAND_CMD_PAGEPROG << 8)
+                                       | NAND_CMD_SEQIN
+                                       | addr_cycle;
+               }
                break;
 
        case NAND_CMD_PARAM:
@@ -691,8 +911,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
        return exec_cmd;
 }
 
-static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
-                               int column, int page_addr)
+static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+                        int column, int page_addr)
 {
        struct pxa3xx_nand_host *host = mtd->priv;
        struct pxa3xx_nand_info *info = host->info_data;
@@ -717,10 +937,15 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
                nand_writel(info, NDTR1CS0, info->ndtr1cs0);
        }
 
+       prepare_start_command(info, command);
+
        info->state = STATE_PREPARED;
-       exec_cmd = prepare_command_pool(info, command, column, page_addr);
+       exec_cmd = prepare_set_command(info, command, 0, column, page_addr);
+
        if (exec_cmd) {
                init_completion(&info->cmd_complete);
+               init_completion(&info->dev_ready);
+               info->need_wait = 1;
                pxa3xx_nand_start(info);
 
                ret = wait_for_completion_timeout(&info->cmd_complete,
@@ -734,6 +959,117 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
        info->state = STATE_IDLE;
 }
 
+static void nand_cmdfunc_extended(struct mtd_info *mtd,
+                                 const unsigned command,
+                                 int column, int page_addr)
+{
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
+       int ret, exec_cmd, ext_cmd_type;
+
+       /*
+        * if this is a x16 device then convert the input
+        * "byte" address into a "word" address appropriate
+        * for indexing a word-oriented device
+        */
+       if (info->reg_ndcr & NDCR_DWIDTH_M)
+               column /= 2;
+
+       /*
+        * There may be different NAND chip hooked to
+        * different chip select, so check whether
+        * chip select has been changed, if yes, reset the timing
+        */
+       if (info->cs != host->cs) {
+               info->cs = host->cs;
+               nand_writel(info, NDTR0CS0, info->ndtr0cs0);
+               nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+       }
+
+       /* Select the extended command for the first command */
+       switch (command) {
+       case NAND_CMD_READ0:
+       case NAND_CMD_READOOB:
+               ext_cmd_type = EXT_CMD_TYPE_MONO;
+               break;
+       case NAND_CMD_SEQIN:
+               ext_cmd_type = EXT_CMD_TYPE_DISPATCH;
+               break;
+       case NAND_CMD_PAGEPROG:
+               ext_cmd_type = EXT_CMD_TYPE_NAKED_RW;
+               break;
+       default:
+               ext_cmd_type = 0;
+               break;
+       }
+
+       prepare_start_command(info, command);
+
+       /*
+        * Prepare the "is ready" completion before starting a command
+        * transaction sequence. If the command is not executed the
+        * completion will be completed, see below.
+        *
+        * We can do that inside the loop because the command variable
+        * is invariant and thus so is the exec_cmd.
+        */
+       info->need_wait = 1;
+       init_completion(&info->dev_ready);
+       do {
+               info->state = STATE_PREPARED;
+               exec_cmd = prepare_set_command(info, command, ext_cmd_type,
+                                              column, page_addr);
+               if (!exec_cmd) {
+                       info->need_wait = 0;
+                       complete(&info->dev_ready);
+                       break;
+               }
+
+               init_completion(&info->cmd_complete);
+               pxa3xx_nand_start(info);
+
+               ret = wait_for_completion_timeout(&info->cmd_complete,
+                               CHIP_DELAY_TIMEOUT);
+               if (!ret) {
+                       dev_err(&info->pdev->dev, "Wait time out!!!\n");
+                       /* Stop State Machine for next command cycle */
+                       pxa3xx_nand_stop(info);
+                       break;
+               }
+
+               /* Check if the sequence is complete */
+               if (info->data_size == 0 && command != NAND_CMD_PAGEPROG)
+                       break;
+
+               /*
+                * After a splitted program command sequence has issued
+                * the command dispatch, the command sequence is complete.
+                */
+               if (info->data_size == 0 &&
+                   command == NAND_CMD_PAGEPROG &&
+                   ext_cmd_type == EXT_CMD_TYPE_DISPATCH)
+                       break;
+
+               if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) {
+                       /* Last read: issue a 'last naked read' */
+                       if (info->data_size == info->chunk_size)
+                               ext_cmd_type = EXT_CMD_TYPE_LAST_RW;
+                       else
+                               ext_cmd_type = EXT_CMD_TYPE_NAKED_RW;
+
+               /*
+                * If a splitted program command has no more data to transfer,
+                * the command dispatch must be issued to complete.
+                */
+               } else if (command == NAND_CMD_PAGEPROG &&
+                          info->data_size == 0) {
+                               ext_cmd_type = EXT_CMD_TYPE_DISPATCH;
+               }
+       } while (1);
+
+       info->state = STATE_IDLE;
+}
+
 static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
                struct nand_chip *chip, const uint8_t *buf, int oob_required)
 {
@@ -753,20 +1089,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
        chip->read_buf(mtd, buf, mtd->writesize);
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 
-       if (info->retcode == ERR_SBERR) {
-               switch (info->use_ecc) {
-               case 1:
-                       mtd->ecc_stats.corrected++;
-                       break;
-               case 0:
-               default:
-                       break;
-               }
-       } else if (info->retcode == ERR_DBERR) {
+       if (info->retcode == ERR_CORERR && info->use_ecc) {
+               mtd->ecc_stats.corrected += info->ecc_err_cnt;
+
+       } else if (info->retcode == ERR_UNCORERR) {
                /*
                 * for blank page (all 0xff), HW will calculate its ECC as
                 * 0, which is different from the ECC information within
-                * OOB, ignore such double bit errors
+                * OOB, ignore such uncorrectable errors
                 */
                if (is_buf_blank(buf, mtd->writesize))
                        info->retcode = ERR_NONE;
@@ -774,7 +1104,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
                        mtd->ecc_stats.failed++;
        }
 
-       return 0;
+       return info->max_bitflips;
 }
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
@@ -833,21 +1163,27 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
        struct pxa3xx_nand_host *host = mtd->priv;
        struct pxa3xx_nand_info *info = host->info_data;
+       int ret;
+
+       if (info->need_wait) {
+               ret = wait_for_completion_timeout(&info->dev_ready,
+                               CHIP_DELAY_TIMEOUT);
+               info->need_wait = 0;
+               if (!ret) {
+                       dev_err(&info->pdev->dev, "Ready time out!!!\n");
+                       return NAND_STATUS_FAIL;
+               }
+       }
 
        /* pxa3xx_nand_send_command has waited for command complete */
        if (this->state == FL_WRITING || this->state == FL_ERASING) {
                if (info->retcode == ERR_NONE)
                        return 0;
-               else {
-                       /*
-                        * any error make it return 0x01 which will tell
-                        * the caller the erase and write fail
-                        */
-                       return 0x01;
-               }
+               else
+                       return NAND_STATUS_FAIL;
        }
 
-       return 0;
+       return NAND_STATUS_READY;
 }
 
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
@@ -869,7 +1205,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
        }
 
        /* calculate flash information */
-       host->page_size = f->page_size;
        host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
        /* calculate addressing information */
@@ -906,13 +1241,15 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
        uint32_t ndcr = nand_readl(info, NDCR);
 
        if (ndcr & NDCR_PAGE_SZ) {
-               host->page_size = 2048;
+               /* Controller's FIFO size */
+               info->chunk_size = 2048;
                host->read_id_bytes = 4;
        } else {
-               host->page_size = 512;
+               info->chunk_size = 512;
                host->read_id_bytes = 2;
        }
 
+       /* Set an initial chunk size */
        info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
        info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
        info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
@@ -988,18 +1325,89 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
        struct mtd_info *mtd;
+       struct nand_chip *chip;
        int ret;
+
        mtd = info->host[info->cs]->mtd;
+       chip = mtd->priv;
+
        /* use the common timing to make a try */
        ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
        if (ret)
                return ret;
 
-       pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
-       if (info->is_ready)
-               return 0;
+       chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+       ret = chip->waitfunc(mtd, chip);
+       if (ret & NAND_STATUS_FAIL)
+               return -ENODEV;
+
+       return 0;
+}
 
-       return -ENODEV;
+static int pxa_ecc_init(struct pxa3xx_nand_info *info,
+                       struct nand_ecc_ctrl *ecc,
+                       int strength, int ecc_stepsize, int page_size)
+{
+       if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) {
+               info->chunk_size = 2048;
+               info->spare_size = 40;
+               info->ecc_size = 24;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = 512;
+               ecc->strength = 1;
+               return 1;
+
+       } else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) {
+               info->chunk_size = 512;
+               info->spare_size = 8;
+               info->ecc_size = 8;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = 512;
+               ecc->strength = 1;
+               return 1;
+
+       /*
+        * Required ECC: 4-bit correction per 512 bytes
+        * Select: 16-bit correction per 2048 bytes
+        */
+       } else if (strength == 4 && ecc_stepsize == 512 && page_size == 2048) {
+               info->ecc_bch = 1;
+               info->chunk_size = 2048;
+               info->spare_size = 32;
+               info->ecc_size = 32;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = info->chunk_size;
+               ecc->layout = &ecc_layout_2KB_bch4bit;
+               ecc->strength = 16;
+               return 1;
+
+       } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) {
+               info->ecc_bch = 1;
+               info->chunk_size = 2048;
+               info->spare_size = 32;
+               info->ecc_size = 32;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = info->chunk_size;
+               ecc->layout = &ecc_layout_4KB_bch4bit;
+               ecc->strength = 16;
+               return 1;
+
+       /*
+        * Required ECC: 8-bit correction per 512 bytes
+        * Select: 16-bit correction per 1024 bytes
+        */
+       } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) {
+               info->ecc_bch = 1;
+               info->chunk_size = 1024;
+               info->spare_size = 0;
+               info->ecc_size = 32;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = info->chunk_size;
+               ecc->layout = &ecc_layout_4KB_bch8bit;
+               ecc->strength = 16;
+               return 1;
+       }
+       return 0;
 }
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
@@ -1014,6 +1422,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
        uint32_t id = -1;
        uint64_t chipsize;
        int i, ret, num;
+       uint16_t ecc_strength, ecc_step;
 
        if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
                goto KEEP_CONFIG;
@@ -1072,15 +1481,60 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
        pxa3xx_flash_ids[1].name = NULL;
        def = pxa3xx_flash_ids;
 KEEP_CONFIG:
-       chip->ecc.mode = NAND_ECC_HW;
-       chip->ecc.size = host->page_size;
-       chip->ecc.strength = 1;
-
        if (info->reg_ndcr & NDCR_DWIDTH_M)
                chip->options |= NAND_BUSWIDTH_16;
 
+       /* Device detection must be done with ECC disabled */
+       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+               nand_writel(info, NDECCCTRL, 0x0);
+
        if (nand_scan_ident(mtd, 1, def))
                return -ENODEV;
+
+       if (pdata->flash_bbt) {
+               /*
+                * We'll use a bad block table stored in-flash and don't
+                * allow writing the bad block marker to the flash.
+                */
+               chip->bbt_options |= NAND_BBT_USE_FLASH |
+                                    NAND_BBT_NO_OOB_BBM;
+               chip->bbt_td = &bbt_main_descr;
+               chip->bbt_md = &bbt_mirror_descr;
+       }
+
+       /*
+        * If the page size is bigger than the FIFO size, let's check
+        * we are given the right variant and then switch to the extended
+        * (aka splitted) command handling,
+        */
+       if (mtd->writesize > PAGE_CHUNK_SIZE) {
+               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) {
+                       chip->cmdfunc = nand_cmdfunc_extended;
+               } else {
+                       dev_err(&info->pdev->dev,
+                               "unsupported page size on this variant\n");
+                       return -ENODEV;
+               }
+       }
+
+       ecc_strength = chip->ecc_strength_ds;
+       ecc_step = chip->ecc_step_ds;
+
+       /* Set default ECC strength requirements on non-ONFI devices */
+       if (ecc_strength < 1 && ecc_step < 1) {
+               ecc_strength = 1;
+               ecc_step = 512;
+       }
+
+       ret = pxa_ecc_init(info, &chip->ecc, ecc_strength,
+                          ecc_step, mtd->writesize);
+       if (!ret) {
+               dev_err(&info->pdev->dev,
+                       "ECC strength %d at page size %d is not supported\n",
+                       chip->ecc_strength_ds, mtd->writesize);
+               return -ENODEV;
+       }
+
        /* calculate addressing information */
        if (mtd->writesize >= 2048)
                host->col_addr_cycles = 2;
@@ -1121,6 +1575,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
                return -ENOMEM;
 
        info->pdev = pdev;
+       info->variant = pxa3xx_nand_get_variant(pdev);
        for (cs = 0; cs < pdata->num_cs; cs++) {
                mtd = (struct mtd_info *)((unsigned int)&info[1] +
                      (sizeof(*mtd) + sizeof(*host)) * cs);
@@ -1138,11 +1593,12 @@ static int alloc_nand_resource(struct platform_device *pdev)
                chip->controller        = &info->controller;
                chip->waitfunc          = pxa3xx_nand_waitfunc;
                chip->select_chip       = pxa3xx_nand_select_chip;
-               chip->cmdfunc           = pxa3xx_nand_cmdfunc;
                chip->read_word         = pxa3xx_nand_read_word;
                chip->read_byte         = pxa3xx_nand_read_byte;
                chip->read_buf          = pxa3xx_nand_read_buf;
                chip->write_buf         = pxa3xx_nand_write_buf;
+               chip->options           |= NAND_NO_SUBPAGE_WRITE;
+               chip->cmdfunc           = nand_cmdfunc;
        }
 
        spin_lock_init(&chip->controller->lock);
@@ -1254,25 +1710,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id pxa3xx_nand_dt_ids[] = {
-       {
-               .compatible = "marvell,pxa3xx-nand",
-               .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
-       },
-       {}
-};
-MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
-
-static enum pxa3xx_nand_variant
-pxa3xx_nand_get_variant(struct platform_device *pdev)
-{
-       const struct of_device_id *of_id =
-                       of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
-       if (!of_id)
-               return PXA3XX_NAND_VARIANT_PXA;
-       return (enum pxa3xx_nand_variant)of_id->data;
-}
-
 static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
 {
        struct pxa3xx_nand_platform_data *pdata;
@@ -1292,6 +1729,7 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
        if (of_get_property(np, "marvell,nand-keep-config", NULL))
                pdata->keep_config = 1;
        of_property_read_u32(np, "num-cs", &pdata->num_cs);
+       pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
 
        pdev->dev.platform_data = pdata;
 
@@ -1329,7 +1767,6 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
        }
 
        info = platform_get_drvdata(pdev);
-       info->variant = pxa3xx_nand_get_variant(pdev);
        probe_success = 0;
        for (cs = 0; cs < pdata->num_cs; cs++) {
                struct mtd_info *mtd = info->host[cs]->mtd;
index d65cbe903d4015e37076f0505db987ee4383e0d5..f0918e7411d99147fd67c26c48a8672cb237437f 100644 (file)
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include <plat/regs-nand.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 
+#define S3C2410_NFREG(x) (x)
+
+#define S3C2410_NFCONF         S3C2410_NFREG(0x00)
+#define S3C2410_NFCMD          S3C2410_NFREG(0x04)
+#define S3C2410_NFADDR         S3C2410_NFREG(0x08)
+#define S3C2410_NFDATA         S3C2410_NFREG(0x0C)
+#define S3C2410_NFSTAT         S3C2410_NFREG(0x10)
+#define S3C2410_NFECC          S3C2410_NFREG(0x14)
+#define S3C2440_NFCONT         S3C2410_NFREG(0x04)
+#define S3C2440_NFCMD          S3C2410_NFREG(0x08)
+#define S3C2440_NFADDR         S3C2410_NFREG(0x0C)
+#define S3C2440_NFDATA         S3C2410_NFREG(0x10)
+#define S3C2440_NFSTAT         S3C2410_NFREG(0x20)
+#define S3C2440_NFMECC0                S3C2410_NFREG(0x2C)
+#define S3C2412_NFSTAT         S3C2410_NFREG(0x28)
+#define S3C2412_NFMECC0                S3C2410_NFREG(0x34)
+#define S3C2410_NFCONF_EN              (1<<15)
+#define S3C2410_NFCONF_INITECC         (1<<12)
+#define S3C2410_NFCONF_nFCE            (1<<11)
+#define S3C2410_NFCONF_TACLS(x)                ((x)<<8)
+#define S3C2410_NFCONF_TWRPH0(x)       ((x)<<4)
+#define S3C2410_NFCONF_TWRPH1(x)       ((x)<<0)
+#define S3C2410_NFSTAT_BUSY            (1<<0)
+#define S3C2440_NFCONF_TACLS(x)                ((x)<<12)
+#define S3C2440_NFCONF_TWRPH0(x)       ((x)<<8)
+#define S3C2440_NFCONF_TWRPH1(x)       ((x)<<4)
+#define S3C2440_NFCONT_INITECC         (1<<4)
+#define S3C2440_NFCONT_nFCE            (1<<1)
+#define S3C2440_NFCONT_ENABLE          (1<<0)
+#define S3C2440_NFSTAT_READY           (1<<0)
+#define S3C2412_NFCONF_NANDBOOT                (1<<31)
+#define S3C2412_NFCONT_INIT_MAIN_ECC   (1<<5)
+#define S3C2412_NFCONT_nFCE0           (1<<1)
+#define S3C2412_NFSTAT_READY           (1<<0)
+
 /* new oob placement block for use with hardware ecc generation
  */
 
@@ -919,7 +953,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
        if (info == NULL) {
-               dev_err(&pdev->dev, "no memory for flash info\n");
                err = -ENOMEM;
                goto exit_error;
        }
@@ -974,7 +1007,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
        size = nr_sets * sizeof(*info->mtds);
        info->mtds = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
        if (info->mtds == NULL) {
-               dev_err(&pdev->dev, "failed to allocate mtd storage\n");
                err = -ENOMEM;
                goto exit_error;
        }
index a3c84ebbe39227dac06bae3d0f9014849cf48b17..d72783dd7b962f798f1256067e3d4d9f5a1c5366 100644 (file)
@@ -151,7 +151,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
        dma_cap_set(DMA_SLAVE, mask);
 
        flctl->chan_fifo0_tx = dma_request_channel(mask, shdma_chan_filter,
-                                           (void *)pdata->slave_id_fifo0_tx);
+                               (void *)(uintptr_t)pdata->slave_id_fifo0_tx);
        dev_dbg(&pdev->dev, "%s: TX: got channel %p\n", __func__,
                flctl->chan_fifo0_tx);
 
@@ -168,7 +168,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
                goto err;
 
        flctl->chan_fifo0_rx = dma_request_channel(mask, shdma_chan_filter,
-                                           (void *)pdata->slave_id_fifo0_rx);
+                               (void *)(uintptr_t)pdata->slave_id_fifo0_rx);
        dev_dbg(&pdev->dev, "%s: RX: got channel %p\n", __func__,
                flctl->chan_fifo0_rx);
 
@@ -1021,7 +1021,6 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_OF
 struct flctl_soc_config {
        unsigned long flcmncr_val;
        unsigned has_hwecc:1;
@@ -1059,10 +1058,8 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
 
        pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data),
                                                                GFP_KERNEL);
-       if (!pdata) {
-               dev_err(dev, "%s: failed to allocate config data\n", __func__);
+       if (!pdata)
                return NULL;
-       }
 
        /* set SoC specific options */
        pdata->flcmncr_val = config->flcmncr_val;
@@ -1080,12 +1077,6 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
 
        return pdata;
 }
-#else /* CONFIG_OF */
-static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
-{
-       return NULL;
-}
-#endif /* CONFIG_OF */
 
 static int flctl_probe(struct platform_device *pdev)
 {
@@ -1094,38 +1085,30 @@ static int flctl_probe(struct platform_device *pdev)
        struct mtd_info *flctl_mtd;
        struct nand_chip *nand;
        struct sh_flctl_platform_data *pdata;
-       int ret = -ENXIO;
+       int ret;
        int irq;
        struct mtd_part_parser_data ppdata = {};
 
-       flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
-       if (!flctl) {
-               dev_err(&pdev->dev, "failed to allocate driver data\n");
+       flctl = devm_kzalloc(&pdev->dev, sizeof(struct sh_flctl), GFP_KERNEL);
+       if (!flctl)
                return -ENOMEM;
-       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "failed to get I/O memory\n");
-               goto err_iomap;
-       }
-
-       flctl->reg = ioremap(res->start, resource_size(res));
-       if (flctl->reg == NULL) {
-               dev_err(&pdev->dev, "failed to remap I/O memory\n");
-               goto err_iomap;
-       }
+       flctl->reg = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(flctl->reg))
+               return PTR_ERR(flctl->reg);
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(&pdev->dev, "failed to get flste irq data\n");
-               goto err_flste;
+               return -ENXIO;
        }
 
-       ret = request_irq(irq, flctl_handle_flste, IRQF_SHARED, "flste", flctl);
+       ret = devm_request_irq(&pdev->dev, irq, flctl_handle_flste, IRQF_SHARED,
+                              "flste", flctl);
        if (ret) {
                dev_err(&pdev->dev, "request interrupt failed.\n");
-               goto err_flste;
+               return ret;
        }
 
        if (pdev->dev.of_node)
@@ -1135,8 +1118,7 @@ static int flctl_probe(struct platform_device *pdev)
 
        if (!pdata) {
                dev_err(&pdev->dev, "no setup data defined\n");
-               ret = -EINVAL;
-               goto err_pdata;
+               return -EINVAL;
        }
 
        platform_set_drvdata(pdev, flctl);
@@ -1190,12 +1172,6 @@ static int flctl_probe(struct platform_device *pdev)
 err_chip:
        flctl_release_dma(flctl);
        pm_runtime_disable(&pdev->dev);
-err_pdata:
-       free_irq(irq, flctl);
-err_flste:
-       iounmap(flctl->reg);
-err_iomap:
-       kfree(flctl);
        return ret;
 }
 
@@ -1206,9 +1182,6 @@ static int flctl_remove(struct platform_device *pdev)
        flctl_release_dma(flctl);
        nand_release(&flctl->mtd);
        pm_runtime_disable(&pdev->dev);
-       free_irq(platform_get_irq(pdev, 0), flctl);
-       iounmap(flctl->reg);
-       kfree(flctl);
 
        return 0;
 }
index 87908d760feb067c3cb179b35bfa5a3c462ab737..e81059b58382f23af69848211415c4095ea36edf 100644 (file)
@@ -121,10 +121,8 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for MTD device structure and private data */
        sharpsl = kzalloc(sizeof(struct sharpsl_nand), GFP_KERNEL);
-       if (!sharpsl) {
-               printk("Unable to allocate SharpSL NAND MTD device structure.\n");
+       if (!sharpsl)
                return -ENOMEM;
-       }
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!r) {
@@ -136,7 +134,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
        /* map physical address */
        sharpsl->io = ioremap(r->start, resource_size(r));
        if (!sharpsl->io) {
-               printk("ioremap to access Sharp SL NAND chip failed\n");
+               dev_err(&pdev->dev, "ioremap to access Sharp SL NAND chip failed\n");
                err = -EIO;
                goto err_ioremap;
        }
index a3747c914d5718abd342f53f8253e2d4c0ea3353..fb8fd35fa668516dcb763037e164691482eca9ea 100644 (file)
@@ -371,11 +371,9 @@ static int tmio_probe(struct platform_device *dev)
        if (data == NULL)
                dev_warn(&dev->dev, "NULL platform data!\n");
 
-       tmio = kzalloc(sizeof *tmio, GFP_KERNEL);
-       if (!tmio) {
-               retval = -ENOMEM;
-               goto err_kzalloc;
-       }
+       tmio = devm_kzalloc(&dev->dev, sizeof(*tmio), GFP_KERNEL);
+       if (!tmio)
+               return -ENOMEM;
 
        tmio->dev = dev;
 
@@ -385,22 +383,18 @@ static int tmio_probe(struct platform_device *dev)
        mtd->priv = nand_chip;
        mtd->name = "tmio-nand";
 
-       tmio->ccr = ioremap(ccr->start, resource_size(ccr));
-       if (!tmio->ccr) {
-               retval = -EIO;
-               goto err_iomap_ccr;
-       }
+       tmio->ccr = devm_ioremap(&dev->dev, ccr->start, resource_size(ccr));
+       if (!tmio->ccr)
+               return -EIO;
 
        tmio->fcr_base = fcr->start & 0xfffff;
-       tmio->fcr = ioremap(fcr->start, resource_size(fcr));
-       if (!tmio->fcr) {
-               retval = -EIO;
-               goto err_iomap_fcr;
-       }
+       tmio->fcr = devm_ioremap(&dev->dev, fcr->start, resource_size(fcr));
+       if (!tmio->fcr)
+               return -EIO;
 
        retval = tmio_hw_init(dev, tmio);
        if (retval)
-               goto err_hwinit;
+               return retval;
 
        /* Set address of NAND IO lines */
        nand_chip->IO_ADDR_R = tmio->fcr;
@@ -428,7 +422,8 @@ static int tmio_probe(struct platform_device *dev)
        /* 15 us command delay time */
        nand_chip->chip_delay = 15;
 
-       retval = request_irq(irq, &tmio_irq, 0, dev_name(&dev->dev), tmio);
+       retval = devm_request_irq(&dev->dev, irq, &tmio_irq, 0,
+                                 dev_name(&dev->dev), tmio);
        if (retval) {
                dev_err(&dev->dev, "request_irq error %d\n", retval);
                goto err_irq;
@@ -440,7 +435,7 @@ static int tmio_probe(struct platform_device *dev)
        /* Scan to find existence of the device */
        if (nand_scan(mtd, 1)) {
                retval = -ENODEV;
-               goto err_scan;
+               goto err_irq;
        }
        /* Register the partitions */
        retval = mtd_device_parse_register(mtd, NULL, NULL,
@@ -451,18 +446,8 @@ static int tmio_probe(struct platform_device *dev)
 
        nand_release(mtd);
 
-err_scan:
-       if (tmio->irq)
-               free_irq(tmio->irq, tmio);
 err_irq:
        tmio_hw_stop(dev, tmio);
-err_hwinit:
-       iounmap(tmio->fcr);
-err_iomap_fcr:
-       iounmap(tmio->ccr);
-err_iomap_ccr:
-       kfree(tmio);
-err_kzalloc:
        return retval;
 }
 
@@ -471,12 +456,7 @@ static int tmio_remove(struct platform_device *dev)
        struct tmio_nand *tmio = platform_get_drvdata(dev);
 
        nand_release(&tmio->mtd);
-       if (tmio->irq)
-               free_irq(tmio->irq, tmio);
        tmio_hw_stop(dev, tmio);
-       iounmap(tmio->fcr);
-       iounmap(tmio->ccr);
-       kfree(tmio);
        return 0;
 }
 
index 235714a421dd6770851f2f5026522123f46dbefc..c1622a5ba8140710bf7807a31a622c283c45ad4b 100644 (file)
@@ -319,11 +319,8 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
                        continue;
                txx9_priv = kzalloc(sizeof(struct txx9ndfmc_priv),
                                    GFP_KERNEL);
-               if (!txx9_priv) {
-                       dev_err(&dev->dev, "Unable to allocate "
-                               "TXx9 NDFMC MTD device structure.\n");
+               if (!txx9_priv)
                        continue;
-               }
                chip = &txx9_priv->chip;
                mtd = &txx9_priv->mtd;
                mtd->owner = THIS_MODULE;
index d64f8c30945fbcd8e2d09a5b8342e75c081cd343..aa26c32e1bc28943426992eba09fddc207cf104d 100644 (file)
@@ -81,7 +81,7 @@ static int parse_ofpart_partitions(struct mtd_info *master,
                partname = of_get_property(pp, "label", &len);
                if (!partname)
                        partname = of_get_property(pp, "name", &len);
-               (*pparts)[i].name = (char *)partname;
+               (*pparts)[i].name = partname;
 
                if (of_get_property(pp, "read-only", &len))
                        (*pparts)[i].mask_flags |= MTD_WRITEABLE;
@@ -152,7 +152,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
                if (names && (plen > 0)) {
                        int len = strlen(names) + 1;
 
-                       (*pparts)[i].name = (char *)names;
+                       (*pparts)[i].name = names;
                        plen -= len;
                        names += len;
                } else {
@@ -173,18 +173,9 @@ static struct mtd_part_parser ofoldpart_parser = {
 
 static int __init ofpart_parser_init(void)
 {
-       int rc;
-       rc = register_mtd_parser(&ofpart_parser);
-       if (rc)
-               goto out;
-
-       rc = register_mtd_parser(&ofoldpart_parser);
-       if (!rc)
-               return 0;
-
-       deregister_mtd_parser(&ofoldpart_parser);
-out:
-       return rc;
+       register_mtd_parser(&ofpart_parser);
+       register_mtd_parser(&ofoldpart_parser);
+       return 0;
 }
 
 static void __exit ofpart_parser_exit(void)
index 63699fffc96de24b3098f629ea495184103386c8..8e1919b6f07449f007c0b1766f4ffcde5db4c0f1 100644 (file)
@@ -58,7 +58,7 @@ static int generic_onenand_probe(struct platform_device *pdev)
                goto out_release_mem_region;
        }
 
-       info->onenand.mmcontrol = pdata ? pdata->mmcontrol : 0;
+       info->onenand.mmcontrol = pdata ? pdata->mmcontrol : NULL;
        info->onenand.irq = platform_get_irq(pdev, 0);
 
        info->mtd.name = dev_name(&pdev->dev);
index 580035c803d693eb38b8f37750a85d57f70cadfa..5da911ebdf495152c68c52af72d0784f0a8ede54 100644 (file)
@@ -300,7 +300,8 @@ MODULE_ALIAS("RedBoot");
 
 static int __init redboot_parser_init(void)
 {
-       return register_mtd_parser(&redboot_parser);
+       register_mtd_parser(&redboot_parser);
+       return 0;
 }
 
 static void __exit redboot_parser_exit(void)
index 70106607c247289b6328c9ff99321d64ffc49c81..e579f9027c47d82bb1e4d577ddd13128324a0075 100644 (file)
@@ -19,7 +19,7 @@
  * or detected.
  */
 
-#if defined(CONFIG_MTD_NAND) || defined(CONFIG_MTD_NAND_MODULE)
+#if IS_ENABLED(CONFIG_MTD_NAND)
 
 struct nand_ecc_test {
        const char *name;
index 4f47aa24b5562001cf8983d6c7634c373d50206b..b8fd651307a42e2fce3d15dfcc1976e2526932ab 100644 (file)
@@ -288,6 +288,8 @@ struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
        struct jffs2_xattr_datum *xd;
        xd = kmem_cache_zalloc(xattr_datum_cache, GFP_KERNEL);
        dbg_memalloc("%p\n", xd);
+       if (!xd)
+               return NULL;
 
        xd->class = RAWNODE_CLASS_XATTR_DATUM;
        xd->node = (void *)xd;
@@ -306,6 +308,8 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
        struct jffs2_xattr_ref *ref;
        ref = kmem_cache_zalloc(xattr_ref_cache, GFP_KERNEL);
        dbg_memalloc("%p\n", ref);
+       if (!ref)
+               return NULL;
 
        ref->class = RAWNODE_CLASS_XATTR_REF;
        ref->node = (void *)ref;
index 68891313875d756a4151aa54847214277e62ba79..628a6a21ddf035063c07051c95b25b24686fb246 100644 (file)
@@ -3,6 +3,6 @@
 
 #include <linux/mtd/mtd.h>
 int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
-                       unsigned long size, char *name);
+                       unsigned long size, const char *name);
 
 #endif /* __MTD_MTDRAM_H__ */
index 9e6c8f9f306e016923a0c32d3ae0e2d9f0ce0d1f..32f8612469d8d2d2c5a659f9326551bcbbd8806b 100644 (file)
@@ -219,6 +219,9 @@ struct nand_chip;
 /* ONFI feature address */
 #define ONFI_FEATURE_ADDR_TIMING_MODE  0x1
 
+/* Vendor-specific feature address (Micron) */
+#define ONFI_FEATURE_ADDR_READ_RETRY   0x89
+
 /* ONFI subfeature parameters length */
 #define ONFI_SUBFEATURE_PARAM_LEN      4
 
@@ -279,16 +282,17 @@ struct nand_onfi_params {
        __le16 io_pin_capacitance_typ;
        __le16 input_pin_capacitance_typ;
        u8 input_pin_capacitance_max;
-       u8 driver_strenght_support;
+       u8 driver_strength_support;
        __le16 t_int_r;
        __le16 t_ald;
        u8 reserved4[7];
 
        /* vendor */
-       u8 reserved5[90];
+       __le16 vendor_revision;
+       u8 vendor[88];
 
        __le16 crc;
-} __attribute__((packed));
+} __packed;
 
 #define ONFI_CRC_BASE  0x4F4E
 
@@ -326,6 +330,26 @@ struct onfi_ext_param_page {
         */
 } __packed;
 
+struct nand_onfi_vendor_micron {
+       u8 two_plane_read;
+       u8 read_cache;
+       u8 read_unique_id;
+       u8 dq_imped;
+       u8 dq_imped_num_settings;
+       u8 dq_imped_feat_addr;
+       u8 rb_pulldown_strength;
+       u8 rb_pulldown_strength_feat_addr;
+       u8 rb_pulldown_strength_num_settings;
+       u8 otp_mode;
+       u8 otp_page_start;
+       u8 otp_data_prot_addr;
+       u8 otp_num_pages;
+       u8 otp_feat_addr;
+       u8 read_retry_options;
+       u8 reserved[72];
+       u8 param_revision;
+} __packed;
+
 /**
  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
  * @lock:               protection lock
@@ -432,6 +456,8 @@ struct nand_buffers {
  *                     flash device.
  * @read_byte:         [REPLACEABLE] read one byte from the chip
  * @read_word:         [REPLACEABLE] read one word from the chip
+ * @write_byte:                [REPLACEABLE] write a single byte to the chip on the
+ *                     low 8 I/O lines
  * @write_buf:         [REPLACEABLE] write data from the buffer to the chip
  * @read_buf:          [REPLACEABLE] read data from the chip into the buffer
  * @select_chip:       [REPLACEABLE] select chip nr
@@ -451,6 +477,8 @@ struct nand_buffers {
  *                     commands to the chip.
  * @waitfunc:          [REPLACEABLE] hardwarespecific function for wait on
  *                     ready.
+ * @setup_read_retry:  [FLASHSPECIFIC] flash (vendor) specific function for
+ *                     setting the read-retry mode. Mostly needed for MLC NAND.
  * @ecc:               [BOARDSPECIFIC] ECC control structure
  * @buffers:           buffer structure for read/write
  * @hwcontrol:         platform-specific hardware control structure
@@ -497,6 +525,7 @@ struct nand_buffers {
  *                     non 0 if ONFI supported.
  * @onfi_params:       [INTERN] holds the ONFI page parameter when ONFI is
  *                     supported, 0 otherwise.
+ * @read_retries:      [INTERN] the number of read retry modes supported
  * @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
  * @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
  * @bbt:               [INTERN] bad block table pointer
@@ -521,6 +550,7 @@ struct nand_chip {
 
        uint8_t (*read_byte)(struct mtd_info *mtd);
        u16 (*read_word)(struct mtd_info *mtd);
+       void (*write_byte)(struct mtd_info *mtd, uint8_t byte);
        void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
        void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
        void (*select_chip)(struct mtd_info *mtd, int chip);
@@ -544,6 +574,7 @@ struct nand_chip {
                        int feature_addr, uint8_t *subfeature_para);
        int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
                        int feature_addr, uint8_t *subfeature_para);
+       int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode);
 
        int chip_delay;
        unsigned int options;
@@ -568,6 +599,8 @@ struct nand_chip {
        int onfi_version;
        struct nand_onfi_params onfi_params;
 
+       int read_retries;
+
        flstate_t state;
 
        uint8_t *oob_poi;
@@ -600,6 +633,8 @@ struct nand_chip {
 #define NAND_MFR_AMD           0x01
 #define NAND_MFR_MACRONIX      0xc2
 #define NAND_MFR_EON           0x92
+#define NAND_MFR_SANDISK       0x45
+#define NAND_MFR_INTEL         0x89
 
 /* The maximum expected count of bytes in the NAND ID sequence */
 #define NAND_MAX_ID_LEN 8
index 1f8d24bdafdac2bc28789c777315068311368765..6a35e6de5da174fc7b9f82f67be421f4d74a1cc3 100644 (file)
@@ -37,7 +37,7 @@
  */
 
 struct mtd_partition {
-       char *name;                     /* identifier string */
+       const char *name;               /* identifier string */
        uint64_t size;                  /* partition size */
        uint64_t offset;                /* offset within the master MTD space */
        uint32_t mask_flags;            /* master MTD flags to mask out for this partition */
@@ -76,11 +76,11 @@ struct mtd_part_parser {
                        struct mtd_part_parser_data *);
 };
 
-extern int register_mtd_parser(struct mtd_part_parser *parser);
-extern int deregister_mtd_parser(struct mtd_part_parser *parser);
+extern void register_mtd_parser(struct mtd_part_parser *parser);
+extern void deregister_mtd_parser(struct mtd_part_parser *parser);
 
 int mtd_is_partition(const struct mtd_info *mtd);
-int mtd_add_partition(struct mtd_info *master, char *name,
+int mtd_add_partition(struct mtd_info *master, const char *name,
                      long long offset, long long length);
 int mtd_del_partition(struct mtd_info *master, int partno);
 uint64_t mtd_get_device_size(const struct mtd_info *mtd);
index 6f10e938ff7e74d4db19b991a55193f5073946e7..cb32d9c1e8dc83502e39143a8c25913bab3193d5 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef __LINUX_OF_MTD_H
-#define __LINUX_OF_NET_H
+#define __LINUX_OF_MTD_H
 
 #ifdef CONFIG_OF_MTD
 
index 4da5bfa2147f245ab980c3a1514647ef40eecf4b..3e9dd6676b9799aba4999d422a624f9a3a991b44 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/plat-omap/include/mach/nand.h
- *
  * Copyright (C) 2006 Micron Technology Inc.
  *
  * This program is free software; you can redistribute it and/or modify
index ffb801998e5dfa10c450f99b2dbb943e8f7a05d4..a941471249299c842a7cfea12de9a4091d2e44e2 100644 (file)
@@ -55,6 +55,9 @@ struct pxa3xx_nand_platform_data {
        /* indicate how many chip selects will be used */
        int     num_cs;
 
+       /* use an flash-based bad block table */
+       bool    flash_bbt;
+
        const struct mtd_partition              *parts[NUM_CHIP_SELECT];
        unsigned int                            nr_parts[NUM_CHIP_SELECT];
 
index e9a9fb188f972555172349a8e0250ac237c7db5d..56ff0e6f5ad1dae5bfe9d774a71cb85a32856afa 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/plat-omap/include/mach/onenand.h
- *
  * Copyright (C) 2006 Nokia Corporation
  * Author: Juha Yrjola
  *
index 9f3c180834d141a269f7c4ec84c8021532029c9c..a7ce77c7c1a8e5d5d7009e9122c1684fa3b70d95 100644 (file)
@@ -1,13 +1,11 @@
 /*
- * arch/arm/plat-orion/include/plat/orion_nand.h
- *
  * This file is licensed under the terms of the GNU General Public
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __PLAT_ORION_NAND_H
-#define __PLAT_ORION_NAND_H
+#ifndef __MTD_ORION_NAND_H
+#define __MTD_ORION_NAND_H
 
 /*
  * Device bus NAND private data