Merge tag 'for-linus-20141215' of git://git.infradead.org/linux-mtd
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 Dec 2014 17:59:26 +0000 (09:59 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 Dec 2014 17:59:26 +0000 (09:59 -0800)
Pull MTD updates from Brian Norris:
 "Summary:
   - Add device tree support for DoC3

   - SPI NOR:
        Refactoring, for better layering between spi-nor.c and its
        driver users (e.g., m25p80.c)

        New flash device support

        Support 6-byte ID strings

   - NAND:
        New NAND driver for Allwinner SoC's (sunxi)

        GPMI NAND: add support for raw (no ECC) access, for testing
        purposes

        Add ATO manufacturer ID

        A few odd driver fixes

   - MTD tests:
        Allow testers to compensate for OOB bitflips in oobtest

        Fix a torturetest regression

   - nandsim: Support longer ID byte strings

  And more"

* tag 'for-linus-20141215' of git://git.infradead.org/linux-mtd: (63 commits)
  mtd: tests: abort torturetest on erase errors
  mtd: physmap_of: fix potential NULL dereference
  mtd: spi-nor: allow NULL as chip name and try to auto detect it
  mtd: nand: gpmi: add raw oob access functions
  mtd: nand: gpmi: add proper raw access support
  mtd: nand: gpmi: add gpmi_copy_bits function
  mtd: spi-nor: factor out write_enable() for erase commands
  mtd: spi-nor: add support for s25fl128s
  mtd: spi-nor: remove the jedec_id/ext_id
  mtd: spi-nor: add id/id_len for flash_info{}
  mtd: nand: correct the comment of function nand_block_isreserved()
  jffs2: Drop bogus if in comment
  mtd: atmel_nand: replace memcpy32_toio/memcpy32_fromio with memcpy
  mtd: cafe_nand: drop duplicate .write_page implementation
  mtd: m25p80: Add support for serial flash Spansion S25FL132K
  MTD: m25p80: fix inconsistency in m25p_ids compared to spi_nor_ids
  mtd: spi-nor: improve wait-till-ready timeout loop
  mtd: delete unnecessary checks before two function calls
  mtd: nand: omap: Fix NAND enumeration on 3430 LDP
  mtd: nand: add ATO manufacturer info
  ...

1  2 
drivers/mtd/devices/docg3.c
drivers/mtd/maps/physmap_of.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/fsl_ifc_nand.c
drivers/mtd/nand/gpio.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/orion_nand.c
drivers/mtd/spi-nor/fsl-quadspi.c

@@@ -22,6 -22,7 +22,7 @@@
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/errno.h>
+ #include <linux/of.h>
  #include <linux/platform_device.h>
  #include <linux/string.h>
  #include <linux/slab.h>
@@@ -1655,22 -1656,21 +1656,21 @@@ static int dbg_flashctrl_show(struct se
  {
        struct docg3 *docg3 = (struct docg3 *)s->private;
  
-       int pos = 0;
        u8 fctrl;
  
        mutex_lock(&docg3->cascade->lock);
        fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
        mutex_unlock(&docg3->cascade->lock);
  
-       pos += seq_printf(s,
-                "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n",
-                fctrl,
-                fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-",
-                fctrl & DOC_CTRL_CE ? "active" : "inactive",
-                fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-",
-                fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-",
-                fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready");
-       return pos;
+       seq_printf(s, "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n",
+                  fctrl,
+                  fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-",
+                  fctrl & DOC_CTRL_CE ? "active" : "inactive",
+                  fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-",
+                  fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-",
+                  fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready");
+       return 0;
  }
  DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show);
  
@@@ -1678,58 -1678,56 +1678,56 @@@ static int dbg_asicmode_show(struct seq
  {
        struct docg3 *docg3 = (struct docg3 *)s->private;
  
-       int pos = 0, pctrl, mode;
+       int pctrl, mode;
  
        mutex_lock(&docg3->cascade->lock);
        pctrl = doc_register_readb(docg3, DOC_ASICMODE);
        mode = pctrl & 0x03;
        mutex_unlock(&docg3->cascade->lock);
  
-       pos += seq_printf(s,
-                        "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (",
-                        pctrl,
-                        pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0,
-                        pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0,
-                        pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0,
-                        pctrl & DOC_ASICMODE_MDWREN ? 1 : 0,
-                        pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0,
-                        mode >> 1, mode & 0x1);
+       seq_printf(s,
+                  "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (",
+                  pctrl,
+                  pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0,
+                  pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0,
+                  pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0,
+                  pctrl & DOC_ASICMODE_MDWREN ? 1 : 0,
+                  pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0,
+                  mode >> 1, mode & 0x1);
  
        switch (mode) {
        case DOC_ASICMODE_RESET:
-               pos += seq_puts(s, "reset");
+               seq_puts(s, "reset");
                break;
        case DOC_ASICMODE_NORMAL:
-               pos += seq_puts(s, "normal");
+               seq_puts(s, "normal");
                break;
        case DOC_ASICMODE_POWERDOWN:
-               pos += seq_puts(s, "powerdown");
+               seq_puts(s, "powerdown");
                break;
        }
-       pos += seq_puts(s, ")\n");
-       return pos;
+       seq_puts(s, ")\n");
+       return 0;
  }
  DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show);
  
  static int dbg_device_id_show(struct seq_file *s, void *p)
  {
        struct docg3 *docg3 = (struct docg3 *)s->private;
-       int pos = 0;
        int id;
  
        mutex_lock(&docg3->cascade->lock);
        id = doc_register_readb(docg3, DOC_DEVICESELECT);
        mutex_unlock(&docg3->cascade->lock);
  
-       pos += seq_printf(s, "DeviceId = %d\n", id);
-       return pos;
+       seq_printf(s, "DeviceId = %d\n", id);
+       return 0;
  }
  DEBUGFS_RO_ATTR(device_id, dbg_device_id_show);
  
  static int dbg_protection_show(struct seq_file *s, void *p)
  {
        struct docg3 *docg3 = (struct docg3 *)s->private;
-       int pos = 0;
        int protect, dps0, dps0_low, dps0_high, dps1, dps1_low, dps1_high;
  
        mutex_lock(&docg3->cascade->lock);
        dps1_high = doc_register_readw(docg3, DOC_DPS1_ADDRHIGH);
        mutex_unlock(&docg3->cascade->lock);
  
-       pos += seq_printf(s, "Protection = 0x%02x (",
-                        protect);
+       seq_printf(s, "Protection = 0x%02x (", protect);
        if (protect & DOC_PROTECT_FOUNDRY_OTP_LOCK)
-               pos += seq_puts(s, "FOUNDRY_OTP_LOCK,");
+               seq_puts(s, "FOUNDRY_OTP_LOCK,");
        if (protect & DOC_PROTECT_CUSTOMER_OTP_LOCK)
-               pos += seq_puts(s, "CUSTOMER_OTP_LOCK,");
+               seq_puts(s, "CUSTOMER_OTP_LOCK,");
        if (protect & DOC_PROTECT_LOCK_INPUT)
-               pos += seq_puts(s, "LOCK_INPUT,");
+               seq_puts(s, "LOCK_INPUT,");
        if (protect & DOC_PROTECT_STICKY_LOCK)
-               pos += seq_puts(s, "STICKY_LOCK,");
+               seq_puts(s, "STICKY_LOCK,");
        if (protect & DOC_PROTECT_PROTECTION_ENABLED)
-               pos += seq_puts(s, "PROTECTION ON,");
+               seq_puts(s, "PROTECTION ON,");
        if (protect & DOC_PROTECT_IPL_DOWNLOAD_LOCK)
-               pos += seq_puts(s, "IPL_DOWNLOAD_LOCK,");
+               seq_puts(s, "IPL_DOWNLOAD_LOCK,");
        if (protect & DOC_PROTECT_PROTECTION_ERROR)
-               pos += seq_puts(s, "PROTECT_ERR,");
+               seq_puts(s, "PROTECT_ERR,");
        else
-               pos += seq_puts(s, "NO_PROTECT_ERR");
-       pos += seq_puts(s, ")\n");
-       pos += seq_printf(s, "DPS0 = 0x%02x : "
-                        "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
-                        "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
-                        dps0, dps0_low, dps0_high,
-                        !!(dps0 & DOC_DPS_OTP_PROTECTED),
-                        !!(dps0 & DOC_DPS_READ_PROTECTED),
-                        !!(dps0 & DOC_DPS_WRITE_PROTECTED),
-                        !!(dps0 & DOC_DPS_HW_LOCK_ENABLED),
-                        !!(dps0 & DOC_DPS_KEY_OK));
-       pos += seq_printf(s, "DPS1 = 0x%02x : "
-                        "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
-                        "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
-                        dps1, dps1_low, dps1_high,
-                        !!(dps1 & DOC_DPS_OTP_PROTECTED),
-                        !!(dps1 & DOC_DPS_READ_PROTECTED),
-                        !!(dps1 & DOC_DPS_WRITE_PROTECTED),
-                        !!(dps1 & DOC_DPS_HW_LOCK_ENABLED),
-                        !!(dps1 & DOC_DPS_KEY_OK));
-       return pos;
+               seq_puts(s, "NO_PROTECT_ERR");
+       seq_puts(s, ")\n");
+       seq_printf(s, "DPS0 = 0x%02x : Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+                  dps0, dps0_low, dps0_high,
+                  !!(dps0 & DOC_DPS_OTP_PROTECTED),
+                  !!(dps0 & DOC_DPS_READ_PROTECTED),
+                  !!(dps0 & DOC_DPS_WRITE_PROTECTED),
+                  !!(dps0 & DOC_DPS_HW_LOCK_ENABLED),
+                  !!(dps0 & DOC_DPS_KEY_OK));
+       seq_printf(s, "DPS1 = 0x%02x : Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+                  dps1, dps1_low, dps1_high,
+                  !!(dps1 & DOC_DPS_OTP_PROTECTED),
+                  !!(dps1 & DOC_DPS_READ_PROTECTED),
+                  !!(dps1 & DOC_DPS_WRITE_PROTECTED),
+                  !!(dps1 & DOC_DPS_HW_LOCK_ENABLED),
+                  !!(dps1 & DOC_DPS_KEY_OK));
+       return 0;
  }
  DEBUGFS_RO_ATTR(protection, dbg_protection_show);
  
@@@ -2126,9 -2119,19 +2119,18 @@@ static int __exit docg3_release(struct 
        return 0;
  }
  
+ #ifdef CONFIG_OF
+ static struct of_device_id docg3_dt_ids[] = {
+       { .compatible = "m-systems,diskonchip-g3" },
+       {}
+ };
+ MODULE_DEVICE_TABLE(of, docg3_dt_ids);
+ #endif
  static struct platform_driver g3_driver = {
        .driver         = {
                .name   = "docg3",
 -              .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(docg3_dt_ids),
        },
        .suspend        = docg3_suspend,
        .resume         = docg3_resume,
@@@ -47,14 -47,12 +47,12 @@@ static int of_flash_remove(struct platf
                return 0;
        dev_set_drvdata(&dev->dev, NULL);
  
-       if (info->cmtd != info->list[0].mtd) {
+       if (info->cmtd) {
                mtd_device_unregister(info->cmtd);
-               mtd_concat_destroy(info->cmtd);
+               if (info->cmtd != info->list[0].mtd)
+                       mtd_concat_destroy(info->cmtd);
        }
  
-       if (info->cmtd)
-               mtd_device_unregister(info->cmtd);
        for (i = 0; i < info->list_size; i++) {
                if (info->list[i].mtd)
                        map_destroy(info->list[i].mtd);
@@@ -354,6 -352,7 +352,6 @@@ MODULE_DEVICE_TABLE(of, of_flash_match)
  static struct platform_driver of_flash_driver = {
        .driver = {
                .name = "of-flash",
 -              .owner = THIS_MODULE,
                .of_match_table = of_flash_match,
        },
        .probe          = of_flash_probe,
@@@ -92,7 -92,7 +92,7 @@@ static struct nand_ecclayout atmel_oobi
  struct atmel_nfc {
        void __iomem            *base_cmd_regs;
        void __iomem            *hsmc_regs;
-       void __iomem            *sram_bank0;
+       void                    *sram_bank0;
        dma_addr_t              sram_bank0_phys;
        bool                    use_nfc_sram;
        bool                    write_by_sram;
        struct completion       comp_xfer_done;
  
        /* Point to the sram bank which include readed data via NFC */
-       void __iomem            *data_in_sram;
+       void                    *data_in_sram;
        bool                    will_write_sram;
  };
  static struct atmel_nfc       nand_nfc;
@@@ -127,6 -127,7 +127,7 @@@ struct atmel_nand_host 
        bool                    has_pmecc;
        u8                      pmecc_corr_cap;
        u16                     pmecc_sector_size;
+       bool                    has_no_lookup_table;
        u32                     pmecc_lookup_table_offset;
        u32                     pmecc_lookup_table_offset_512;
        u32                     pmecc_lookup_table_offset_1024;
@@@ -256,26 -257,6 +257,6 @@@ static int atmel_nand_set_enable_ready_
        return res;
  }
  
- static void memcpy32_fromio(void *trg, const void __iomem  *src, size_t size)
- {
-       int i;
-       u32 *t = trg;
-       const __iomem u32 *s = src;
-       for (i = 0; i < (size >> 2); i++)
-               *t++ = readl_relaxed(s++);
- }
- static void memcpy32_toio(void __iomem *trg, const void *src, int size)
- {
-       int i;
-       u32 __iomem *t = trg;
-       const u32 *s = src;
-       for (i = 0; i < (size >> 2); i++)
-               writel_relaxed(*s++, t++);
- }
  /*
   * Minimal-overhead PIO for data access.
   */
@@@ -285,7 -266,7 +266,7 @@@ static void atmel_read_buf8(struct mtd_
        struct atmel_nand_host *host = nand_chip->priv;
  
        if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) {
-               memcpy32_fromio(buf, host->nfc->data_in_sram, len);
+               memcpy(buf, host->nfc->data_in_sram, len);
                host->nfc->data_in_sram += len;
        } else {
                __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
@@@ -298,7 -279,7 +279,7 @@@ static void atmel_read_buf16(struct mtd
        struct atmel_nand_host *host = nand_chip->priv;
  
        if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) {
-               memcpy32_fromio(buf, host->nfc->data_in_sram, len);
+               memcpy(buf, host->nfc->data_in_sram, len);
                host->nfc->data_in_sram += len;
        } else {
                __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
@@@ -1112,12 -1093,66 +1093,66 @@@ static int pmecc_choose_ecc(struct atme
        return 0;
  }
  
+ static inline int deg(unsigned int poly)
+ {
+       /* polynomial degree is the most-significant bit index */
+       return fls(poly) - 1;
+ }
+ static int build_gf_tables(int mm, unsigned int poly,
+               int16_t *index_of, int16_t *alpha_to)
+ {
+       unsigned int i, x = 1;
+       const unsigned int k = 1 << deg(poly);
+       unsigned int nn = (1 << mm) - 1;
+       /* primitive polynomial must be of degree m */
+       if (k != (1u << mm))
+               return -EINVAL;
+       for (i = 0; i < nn; i++) {
+               alpha_to[i] = x;
+               index_of[x] = i;
+               if (i && (x == 1))
+                       /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
+                       return -EINVAL;
+               x <<= 1;
+               if (x & k)
+                       x ^= poly;
+       }
+       alpha_to[nn] = 1;
+       index_of[0] = 0;
+       return 0;
+ }
+ static uint16_t *create_lookup_table(struct device *dev, int sector_size)
+ {
+       int degree = (sector_size == 512) ?
+                       PMECC_GF_DIMENSION_13 :
+                       PMECC_GF_DIMENSION_14;
+       unsigned int poly = (sector_size == 512) ?
+                       PMECC_GF_13_PRIMITIVE_POLY :
+                       PMECC_GF_14_PRIMITIVE_POLY;
+       int table_size = (sector_size == 512) ?
+                       PMECC_LOOKUP_TABLE_SIZE_512 :
+                       PMECC_LOOKUP_TABLE_SIZE_1024;
+       int16_t *addr = devm_kzalloc(dev, 2 * table_size * sizeof(uint16_t),
+                       GFP_KERNEL);
+       if (addr && build_gf_tables(degree, poly, addr, addr + table_size))
+               return NULL;
+       return addr;
+ }
  static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
                                         struct atmel_nand_host *host)
  {
        struct mtd_info *mtd = &host->mtd;
        struct nand_chip *nand_chip = &host->nand_chip;
        struct resource *regs, *regs_pmerr, *regs_rom;
+       uint16_t *galois_table;
        int cap, sector_size, err_no;
  
        err_no = pmecc_choose_ecc(host, &cap, &sector_size);
        regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
        host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev, regs_rom);
        if (IS_ERR(host->pmecc_rom_base)) {
-               err_no = PTR_ERR(host->pmecc_rom_base);
-               goto err;
+               if (!host->has_no_lookup_table)
+                       /* Don't display the information again */
+                       dev_err(host->dev, "Can not get I/O resource for ROM, will build a lookup table in runtime!\n");
+               host->has_no_lookup_table = true;
+       }
+       if (host->has_no_lookup_table) {
+               /* Build the look-up table in runtime */
+               galois_table = create_lookup_table(host->dev, sector_size);
+               if (!galois_table) {
+                       dev_err(host->dev, "Failed to build a lookup table in runtime!\n");
+                       err_no = -EINVAL;
+                       goto err;
+               }
+               host->pmecc_rom_base = (void __iomem *)galois_table;
+               host->pmecc_lookup_table_offset = 0;
        }
  
        nand_chip->ecc.size = sector_size;
@@@ -1501,8 -1552,10 +1552,10 @@@ static int atmel_of_init_port(struct at
  
        if (of_property_read_u32_array(np, "atmel,pmecc-lookup-table-offset",
                        offset, 2) != 0) {
-               dev_err(host->dev, "Cannot get PMECC lookup table offset\n");
-               return -EINVAL;
+               dev_err(host->dev, "Cannot get PMECC lookup table offset, will build a lookup table in runtime.\n");
+               host->has_no_lookup_table = true;
+               /* Will build a lookup table and initialize the offset later */
+               return 0;
        }
        if (!offset[0] && !offset[1]) {
                dev_err(host->dev, "Invalid PMECC lookup table offset\n");
@@@ -1899,7 -1952,7 +1952,7 @@@ static int nfc_sram_write_page(struct m
        int cfg, len;
        int status = 0;
        struct atmel_nand_host *host = chip->priv;
-       void __iomem *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host);
+       void *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host);
  
        /* Subpage write is not supported */
        if (offset || (data_len < mtd->writesize))
        if (use_dma) {
                if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) != 0)
                        /* Fall back to use cpu copy */
-                       memcpy32_toio(sram, buf, len);
+                       memcpy(sram, buf, len);
        } else {
-               memcpy32_toio(sram, buf, len);
+               memcpy(sram, buf, len);
        }
  
        cfg = nfc_readl(host->nfc->hsmc_regs, CFG);
        if (unlikely(raw) && oob_required) {
-               memcpy32_toio(sram + len, chip->oob_poi, mtd->oobsize);
+               memcpy(sram + len, chip->oob_poi, mtd->oobsize);
                len += mtd->oobsize;
                nfc_writel(host->nfc->hsmc_regs, CFG, cfg | NFC_CFG_WSPARE);
        } else {
@@@ -2260,7 -2313,8 +2313,8 @@@ static int atmel_nand_nfc_probe(struct 
  
        nfc_sram = platform_get_resource(pdev, IORESOURCE_MEM, 2);
        if (nfc_sram) {
-               nfc->sram_bank0 = devm_ioremap_resource(&pdev->dev, nfc_sram);
+               nfc->sram_bank0 = (void * __force)
+                               devm_ioremap_resource(&pdev->dev, nfc_sram);
                if (IS_ERR(nfc->sram_bank0)) {
                        dev_warn(&pdev->dev, "Fail to ioremap the NFC sram with error: %ld. So disable NFC sram.\n",
                                        PTR_ERR(nfc->sram_bank0));
@@@ -2312,6 -2366,7 +2366,6 @@@ MODULE_DEVICE_TABLE(of, atmel_nand_nfc_
  static struct platform_driver atmel_nand_nfc_driver = {
        .driver = {
                .name = "atmel_nand_nfc",
 -              .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(atmel_nand_nfc_match),
        },
        .probe = atmel_nand_nfc_probe,
@@@ -2323,6 -2378,7 +2377,6 @@@ static struct platform_driver atmel_nan
        .remove         = atmel_nand_remove,
        .driver         = {
                .name   = "atmel_nand",
 -              .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(atmel_nand_dt_ids),
        },
  };
@@@ -31,7 -31,6 +31,6 @@@
  #include <linux/mtd/nand_ecc.h>
  #include <linux/fsl_ifc.h>
  
- #define FSL_IFC_V1_1_0        0x01010000
  #define ERR_BYTE              0xFF /* Value returned for read
                                        bytes when read failed  */
  #define IFC_TIMEOUT_MSECS     500  /* Maximum number of mSecs to wait
@@@ -877,7 -876,7 +876,7 @@@ static int fsl_ifc_chip_init(struct fsl
        struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
        struct nand_chip *chip = &priv->chip;
        struct nand_ecclayout *layout;
-       u32 csor, ver;
+       u32 csor;
  
        /* Fill in fsl_ifc_mtd structure */
        priv->mtd.priv = chip;
                chip->ecc.mode = NAND_ECC_SOFT;
        }
  
-       ver = ioread32be(&ifc->ifc_rev);
-       if (ver == FSL_IFC_V1_1_0)
+       if (ctrl->version == FSL_IFC_VERSION_1_1_0)
                fsl_ifc_sram_init(priv);
  
        return 0;
@@@ -1045,12 -1043,12 +1043,12 @@@ static int fsl_ifc_nand_probe(struct pl
        }
  
        /* find which chip select it is connected to */
-       for (bank = 0; bank < FSL_IFC_BANK_COUNT; bank++) {
+       for (bank = 0; bank < fsl_ifc_ctrl_dev->banks; bank++) {
                if (match_bank(ifc, bank, res.start))
                        break;
        }
  
-       if (bank >= FSL_IFC_BANK_COUNT) {
+       if (bank >= fsl_ifc_ctrl_dev->banks) {
                dev_err(&dev->dev, "%s: address did not match any chip selects\n",
                        __func__);
                return -ENODEV;
@@@ -1167,6 -1165,7 +1165,6 @@@ static const struct of_device_id fsl_if
  static struct platform_driver fsl_ifc_nand_driver = {
        .driver = {
                .name   = "fsl,ifc-nand",
 -              .owner = THIS_MODULE,
                .of_match_table = fsl_ifc_nand_match,
        },
        .probe       = fsl_ifc_nand_probe,
diff --combined drivers/mtd/nand/gpio.c
@@@ -8,7 -8,9 +8,9 @@@
   *
   * © 2004 Simtec Electronics
   *
-  * Device driver for NAND connected via GPIO
+  * Device driver for NAND flash that uses a memory mapped interface to
+  * read/write the NAND commands and data, and GPIO pins for control signals
+  * (the DT binding refers to this as "GPIO assisted NAND flash")
   *
   * 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
@@@ -308,6 -310,7 +310,6 @@@ static struct platform_driver gpio_nand
        .remove         = gpio_nand_remove,
        .driver         = {
                .name   = "gpio-nand",
 -              .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(gpio_nand_id_table),
        },
  };
@@@ -280,14 -280,10 +280,10 @@@ static void memcpy32_fromio(void *trg, 
                *t++ = __raw_readl(s++);
  }
  
- static void memcpy32_toio(void __iomem *trg, const void *src, int size)
+ static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
  {
-       int i;
-       u32 __iomem *t = trg;
-       const u32 *s = src;
-       for (i = 0; i < (size >> 2); i++)
-               __raw_writel(*s++, t++);
+       /* __iowrite32_copy use 32bit size values so divide by 4 */
+       __iowrite32_copy(trg, src, size / 4);
  }
  
  static int check_int_v3(struct mxc_nand_host *host)
@@@ -1600,6 -1596,7 +1596,6 @@@ static int mxcnd_remove(struct platform
  static struct platform_driver mxcnd_driver = {
        .driver = {
                   .name = DRIVER_NAME,
 -                 .owner = THIS_MODULE,
                   .of_match_table = of_match_ptr(mxcnd_dt_ids),
        },
        .id_table = mxcnd_devtype,
diff --combined drivers/mtd/nand/omap2.c
@@@ -144,11 -144,13 +144,13 @@@ static u_char bch8_vector[] = {0xf3, 0x
        0xac, 0x6b, 0xff, 0x99, 0x7b};
  static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
  
- /* oob info generated runtime depending on ecc algorithm and layout selected */
- static struct nand_ecclayout omap_oobinfo;
+ /* Shared among all NAND instances to synchronize access to the ECC Engine */
+ static struct nand_hw_control omap_gpmc_controller = {
+       .lock = __SPIN_LOCK_UNLOCKED(omap_gpmc_controller.lock),
+       .wq = __WAIT_QUEUE_HEAD_INITIALIZER(omap_gpmc_controller.wq),
+ };
  
  struct omap_nand_info {
-       struct nand_hw_control          controller;
        struct omap_nand_platform_data  *pdata;
        struct mtd_info                 mtd;
        struct nand_chip                nand;
        u_char                          *buf;
        int                                     buf_len;
        struct gpmc_nand_regs           reg;
+       /* generated at runtime depending on ECC algorithm and layout selected */
+       struct nand_ecclayout           oobinfo;
        /* fields specific for BCHx_HW ECC scheme */
        struct device                   *elm_dev;
        struct device_node              *of_node;
@@@ -1686,9 -1690,6 +1690,6 @@@ static int omap_nand_probe(struct platf
  
        platform_set_drvdata(pdev, info);
  
-       spin_lock_init(&info->controller.lock);
-       init_waitqueue_head(&info->controller.wq);
        info->pdev              = pdev;
        info->gpmc_cs           = pdata->cs;
        info->reg               = pdata->reg;
  
        info->phys_base = res->start;
  
-       nand_chip->controller = &info->controller;
+       nand_chip->controller = &omap_gpmc_controller;
  
        nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R;
        nand_chip->cmd_ctrl  = omap_hwcontrol;
                goto return_error;
        }
  
-       /* check for small page devices */
-       if ((mtd->oobsize < 64) && (pdata->ecc_opt != OMAP_ECC_HAM1_CODE_HW)) {
-               dev_err(&info->pdev->dev, "small page devices are not supported\n");
-               err = -EINVAL;
-               goto return_error;
-       }
        /* re-populate low-level callbacks based on xfer modes */
        switch (pdata->xfer_type) {
        case NAND_OMAP_PREFETCH_POLLED:
        }
  
        /* populate MTD interface based on ECC scheme */
-       ecclayout               = &omap_oobinfo;
+       ecclayout               = &info->oobinfo;
        switch (info->ecc_opt) {
        case OMAP_ECC_HAM1_CODE_SW:
                nand_chip->ecc.mode = NAND_ECC_SOFT;
@@@ -2095,6 -2089,7 +2089,6 @@@ static struct platform_driver omap_nand
        .remove         = omap_nand_remove,
        .driver         = {
                .name   = DRIVER_NAME,
 -              .owner  = THIS_MODULE,
        },
  };
  
@@@ -19,7 -19,7 +19,7 @@@
  #include <linux/mtd/partitions.h>
  #include <linux/clk.h>
  #include <linux/err.h>
- #include <asm/io.h>
+ #include <linux/io.h>
  #include <asm/sizes.h>
  #include <linux/platform_data/mtd-orion_nand.h>
  
@@@ -85,33 -85,24 +85,24 @@@ static int __init orion_nand_probe(stru
        int ret = 0;
        u32 val = 0;
  
-       nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL);
-       if (!nc) {
-               ret = -ENOMEM;
-               goto no_res;
-       }
+       nc = devm_kzalloc(&pdev->dev,
+                       sizeof(struct nand_chip) + sizeof(struct mtd_info),
+                       GFP_KERNEL);
+       if (!nc)
+               return -ENOMEM;
        mtd = (struct mtd_info *)(nc + 1);
  
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               goto no_res;
-       }
+       io_base = devm_ioremap_resource(&pdev->dev, res);
  
-       io_base = ioremap(res->start, resource_size(res));
-       if (!io_base) {
-               dev_err(&pdev->dev, "ioremap failed\n");
-               ret = -EIO;
-               goto no_res;
-       }
+       if (IS_ERR(io_base))
+               return PTR_ERR(io_base);
  
        if (pdev->dev.of_node) {
                board = devm_kzalloc(&pdev->dev, sizeof(struct orion_nand_data),
                                        GFP_KERNEL);
-               if (!board) {
-                       ret = -ENOMEM;
-                       goto no_res;
-               }
+               if (!board)
+                       return -ENOMEM;
                if (!of_property_read_u32(pdev->dev.of_node, "cle", &val))
                        board->cle = (u8)val;
                else
@@@ -185,9 -176,6 +176,6 @@@ no_dev
                clk_disable_unprepare(clk);
                clk_put(clk);
        }
-       iounmap(io_base);
- no_res:
-       kfree(nc);
  
        return ret;
  }
  static int orion_nand_remove(struct platform_device *pdev)
  {
        struct mtd_info *mtd = platform_get_drvdata(pdev);
-       struct nand_chip *nc = mtd->priv;
        struct clk *clk;
  
        nand_release(mtd);
  
-       iounmap(nc->IO_ADDR_W);
-       kfree(nc);
        clk = clk_get(&pdev->dev, NULL);
        if (!IS_ERR(clk)) {
                clk_disable_unprepare(clk);
@@@ -224,6 -207,7 +207,6 @@@ static struct platform_driver orion_nan
        .remove         = orion_nand_remove,
        .driver         = {
                .name   = "orion_nand",
 -              .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(orion_nand_of_match_table),
        },
  };
@@@ -719,16 -719,10 +719,10 @@@ static int fsl_qspi_read(struct spi_no
  {
        struct fsl_qspi *q = nor->priv;
        u8 cmd = nor->read_opcode;
-       int ret;
  
        dev_dbg(q->dev, "cmd [%x],read from (0x%p, 0x%.8x, 0x%.8x),len:%d\n",
                cmd, q->ahb_base, q->chip_base_addr, (unsigned int)from, len);
  
-       /* Wait until the previous command is finished. */
-       ret = nor->wait_till_ready(nor);
-       if (ret)
-               return ret;
        /* Read out the data directly from the AHB buffer.*/
        memcpy(buf, q->ahb_base + q->chip_base_addr + from, len);
  
@@@ -744,16 -738,6 +738,6 @@@ static int fsl_qspi_erase(struct spi_no
        dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n",
                nor->mtd->erasesize / 1024, q->chip_base_addr, (u32)offs);
  
-       /* Wait until finished previous write command. */
-       ret = nor->wait_till_ready(nor);
-       if (ret)
-               return ret;
-       /* Send write enable, then erase commands. */
-       ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0);
-       if (ret)
-               return ret;
        ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0);
        if (ret)
                return ret;
@@@ -849,9 -833,8 +833,8 @@@ static int fsl_qspi_probe(struct platfo
  
        ret = clk_prepare_enable(q->clk);
        if (ret) {
-               clk_disable_unprepare(q->clk_en);
                dev_err(dev, "can not enable the qspi clock\n");
-               goto map_failed;
+               goto clk_failed;
        }
  
        /* find the irq */
                nor->prepare = fsl_qspi_prep;
                nor->unprepare = fsl_qspi_unprep;
  
-               if (of_modalias_node(np, modalias, sizeof(modalias)) < 0)
+               ret = of_modalias_node(np, modalias, sizeof(modalias));
+               if (ret < 0)
                        goto map_failed;
  
                ret = of_property_read_u32(np, "spi-max-frequency",
@@@ -964,6 -948,7 +948,7 @@@ last_init_failed
  
  irq_failed:
        clk_disable_unprepare(q->clk);
+ clk_failed:
        clk_disable_unprepare(q->clk_en);
  map_failed:
        dev_err(dev, "Freescale QuadSPI probe failed\n");
@@@ -991,6 -976,7 +976,6 @@@ static struct platform_driver fsl_qspi_
        .driver = {
                .name   = "fsl-quadspi",
                .bus    = &platform_bus_type,
 -              .owner  = THIS_MODULE,
                .of_match_table = fsl_qspi_dt_ids,
        },
        .probe          = fsl_qspi_probe,