Merge tag 'for-linus-20131112' of git://git.infradead.org/linux-mtd
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Nov 2013 03:31:43 +0000 (12:31 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Nov 2013 03:31:43 +0000 (12:31 +0900)
Pull MTD changes from Brian Norris:
 - Unify some compile-time differences so that we have fewer uses of
   #ifdef CONFIG_OF in atmel_nand
 - Other general cleanups (removing unused functions, options,
   variables, fields; use correct interfaces)
 - Fix BUG() for new odd-sized NAND, which report non-power-of-2
   dimensions via ONFI
 - Miscellaneous driver fixes (SPI NOR flash; BCM47xx NAND flash; etc.)
 - Improve differentiation between SLC and MLC NAND -- this clarifies an
   ABI issue regarding the MTD "type" (in sysfs and in the MEMGETINFO
   ioctl), where the MTD_MLCNANDFLASH type was present but
   inconsistently used
 - Extend GPMI NAND to support multi-chip-select NAND for some platforms
 - Many improvements to the OMAP2/3 NAND driver, including an expanded
   DT binding to bring us closer to mainline support for some OMAP
   systems
 - Fix a deadlock in the error path of the Atmel NAND driver probe
 - Correct the error codes from MTD mmap() to conform to POSIX and the
   Linux Programmer's Manual.  This is an acknowledged change in the MTD
   ABI, but I can't imagine somebody relying on the non-standard -ENOSYS
   error code specifically.  Am I just being unimaginative? :)
 - Fix a few important GPMI NAND bugs (one regression from 3.12 and one
   long-standing race condition)
 - More? Read the log!

* tag 'for-linus-20131112' of git://git.infradead.org/linux-mtd: (98 commits)
  mtd: gpmi: fix the NULL pointer
  mtd: gpmi: fix kernel BUG due to racing DMA operations
  mtd: mtdchar: return expected errors on mmap() call
  mtd: gpmi: only scan two chips for imx6
  mtd: gpmi: Use devm_kzalloc()
  mtd: atmel_nand: fix bug driver will in a dead lock if no nand detected
  mtd: nand: use a local variable to simplify the nand_scan_tail
  mtd: nand: remove deprecated IRQF_DISABLED
  mtd: dataflash: Say if we find a device we don't support
  mtd: nand: omap: fix error return code in omap_nand_probe()
  mtd: nand_bbt: kill NAND_BBT_SCANALLPAGES
  mtd: m25p80: fixup device removal failure path
  mtd: mxc_nand: Include linux/of.h header
  mtd: remove duplicated include from mtdcore.c
  mtd: m25p80: add support for Macronix mx25l3255e
  mtd: nand: omap: remove selection of BCH ecc-scheme via KConfig
  mtd: nand: omap: updated devm_xx for all resource allocation and free calls
  mtd: nand: omap: use drivers/mtd/nand/nand_bch.c wrapper for BCH ECC instead of lib/bch.c
  mtd: nand: omap: clean-up ecc layout for BCH ecc schemes
  mtd: nand: omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe
  ...

1  2 
arch/arm/mach-omap2/gpmc.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsl_ifc_nand.c
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/socrates_nand.c

@@@ -1341,14 -1341,6 +1341,6 @@@ static void __maybe_unused gpmc_read_ti
  
  #ifdef CONFIG_MTD_NAND
  
- static const char * const nand_ecc_opts[] = {
-       [OMAP_ECC_HAMMING_CODE_DEFAULT]         = "sw",
-       [OMAP_ECC_HAMMING_CODE_HW]              = "hw",
-       [OMAP_ECC_HAMMING_CODE_HW_ROMCODE]      = "hw-romcode",
-       [OMAP_ECC_BCH4_CODE_HW]                 = "bch4",
-       [OMAP_ECC_BCH8_CODE_HW]                 = "bch8",
- };
  static const char * const nand_xfer_types[] = {
        [NAND_OMAP_PREFETCH_POLLED]             = "prefetch-polled",
        [NAND_OMAP_POLLED]                      = "polled",
@@@ -1378,13 -1370,41 +1370,41 @@@ static int gpmc_probe_nand_child(struc
        gpmc_nand_data->cs = val;
        gpmc_nand_data->of_node = child;
  
-       if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
-               for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
-                       if (!strcasecmp(s, nand_ecc_opts[val])) {
-                               gpmc_nand_data->ecc_opt = val;
-                               break;
-                       }
+       /* Detect availability of ELM module */
+       gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
+       if (gpmc_nand_data->elm_of_node == NULL)
+               gpmc_nand_data->elm_of_node =
+                                       of_parse_phandle(child, "elm_id", 0);
+       if (gpmc_nand_data->elm_of_node == NULL)
+               pr_warn("%s: ti,elm-id property not found\n", __func__);
+       /* select ecc-scheme for NAND */
+       if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
+               pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
+               return -ENODEV;
+       }
+       if (!strcmp(s, "ham1") || !strcmp(s, "sw") ||
+               !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
+               gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_HAM1_CODE_HW;
+       else if (!strcmp(s, "bch4"))
+               if (gpmc_nand_data->elm_of_node)
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH4_CODE_HW;
+               else
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
+       else if (!strcmp(s, "bch8"))
+               if (gpmc_nand_data->elm_of_node)
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH8_CODE_HW;
+               else
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+       else
+               pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
  
+       /* select data transfer mode for NAND controller */
        if (!of_property_read_string(child, "ti,nand-xfer-type", &s))
                for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++)
                        if (!strcasecmp(s, nand_xfer_types[val])) {
        return ret;
  }
  
 +/*
 + * REVISIT: Add timing support from slls644g.pdf
 + */
 +static int gpmc_probe_8250(struct platform_device *pdev,
 +                              struct device_node *child)
 +{
 +      struct resource res;
 +      unsigned long base;
 +      int ret, cs;
 +
 +      if (of_property_read_u32(child, "reg", &cs) < 0) {
 +              dev_err(&pdev->dev, "%s has no 'reg' property\n",
 +                      child->full_name);
 +              return -ENODEV;
 +      }
 +
 +      if (of_address_to_resource(child, 0, &res) < 0) {
 +              dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
 +                      child->full_name);
 +              return -ENODEV;
 +      }
 +
 +      ret = gpmc_cs_request(cs, resource_size(&res), &base);
 +      if (ret < 0) {
 +              dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
 +              return ret;
 +      }
 +
 +      if (of_platform_device_create(child, NULL, &pdev->dev))
 +              return 0;
 +
 +      dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
 +
 +      return -ENODEV;
 +}
 +
  static int gpmc_probe_dt(struct platform_device *pdev)
  {
        int ret;
                else if (of_node_cmp(child->name, "ethernet") == 0 ||
                         of_node_cmp(child->name, "nor") == 0)
                        ret = gpmc_probe_generic_child(pdev, child);
 +              else if (of_node_cmp(child->name, "8250") == 0)
 +                      ret = gpmc_probe_8250(pdev, child);
  
                if (WARN(ret < 0, "%s: probing gpmc child %s failed\n",
                         __func__, child->full_name))
@@@ -1062,56 -1062,28 +1062,28 @@@ static void atmel_pmecc_core_init(struc
  }
  
  /*
-  * Get ECC requirement in ONFI parameters, returns -1 if ONFI
-  * parameters is not supported.
-  * return 0 if success to get the ECC requirement.
-  */
- static int get_onfi_ecc_param(struct nand_chip *chip,
-               int *ecc_bits, int *sector_size)
- {
-       *ecc_bits = *sector_size = 0;
-       if (chip->onfi_params.ecc_bits == 0xff)
-               /* TODO: the sector_size and ecc_bits need to be find in
-                * extended ecc parameter, currently we don't support it.
-                */
-               return -1;
-       *ecc_bits = chip->onfi_params.ecc_bits;
-       /* The default sector size (ecc codeword size) is 512 */
-       *sector_size = 512;
-       return 0;
- }
- /*
-  * Get ecc requirement from ONFI parameters ecc requirement.
+  * Get minimum ecc requirements from NAND.
   * If pmecc-cap, pmecc-sector-size in DTS are not specified, this function
-  * will set them according to ONFI ecc requirement. Otherwise, use the
+  * will set them according to minimum ecc requirement. Otherwise, use the
   * value in DTS file.
   * return 0 if success. otherwise return error code.
   */
  static int pmecc_choose_ecc(struct atmel_nand_host *host,
                int *cap, int *sector_size)
  {
-       /* Get ECC requirement from ONFI parameters */
-       *cap = *sector_size = 0;
-       if (host->nand_chip.onfi_version) {
-               if (!get_onfi_ecc_param(&host->nand_chip, cap, sector_size))
-                       dev_info(host->dev, "ONFI params, minimum required ECC: %d bits in %d bytes\n",
+       /* Get minimum ECC requirements */
+       if (host->nand_chip.ecc_strength_ds) {
+               *cap = host->nand_chip.ecc_strength_ds;
+               *sector_size = host->nand_chip.ecc_step_ds;
+               dev_info(host->dev, "minimum ECC: %d bits in %d bytes\n",
                                *cap, *sector_size);
-               else
-                       dev_info(host->dev, "NAND chip ECC reqirement is in Extended ONFI parameter, we don't support yet.\n");
        } else {
-               dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes");
-       }
-       if (*cap == 0 && *sector_size == 0) {
                *cap = 2;
                *sector_size = 512;
+               dev_info(host->dev, "can't detect min. ECC, assume 2 bits in 512 bytes\n");
        }
  
-       /* If dts file doesn't specify then use the one in ONFI parameters */
+       /* If device tree doesn't specify, use NAND's minimum ECC parameters */
        if (host->pmecc_corr_cap == 0) {
                /* use the most fitable ecc bits (the near bigger one ) */
                if (*cap <= 2)
        return 0;
  }
  
 -static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
 +static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
                                         struct atmel_nand_host *host)
  {
        struct mtd_info *mtd = &host->mtd;
@@@ -1449,7 -1421,6 +1421,6 @@@ static void atmel_nand_hwctl(struct mtd
                ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
  }
  
- #if defined(CONFIG_OF)
  static int atmel_of_init_port(struct atmel_nand_host *host,
                              struct device_node *np)
  {
        u32 offset[2];
        int ecc_mode;
        struct atmel_nand_data *board = &host->board;
-       enum of_gpio_flags flags;
+       enum of_gpio_flags flags = 0;
  
        if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) {
                if (val >= 32) {
  
        return 0;
  }
- #else
- static int atmel_of_init_port(struct atmel_nand_host *host,
-                             struct device_node *np)
- {
-       return -EINVAL;
- }
- #endif
  
 -static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
 +static int atmel_hw_nand_init_params(struct platform_device *pdev,
                                         struct atmel_nand_host *host)
  {
        struct mtd_info *mtd = &host->mtd;
@@@ -1987,7 -1951,7 +1951,7 @@@ static struct platform_driver atmel_nan
  /*
   * Probe for the NAND device.
   */
 -static int __init atmel_nand_probe(struct platform_device *pdev)
 +static int atmel_nand_probe(struct platform_device *pdev)
  {
        struct atmel_nand_host *host;
        struct mtd_info *mtd;
        mtd = &host->mtd;
        nand_chip = &host->nand_chip;
        host->dev = &pdev->dev;
-       if (pdev->dev.of_node) {
+       if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+               /* Only when CONFIG_OF is enabled of_node can be parsed */
                res = atmel_of_init_port(host, pdev->dev.of_node);
                if (res)
                        goto err_nand_ioremap;
@@@ -2177,14 -2142,13 +2142,13 @@@ err_no_card
        if (host->dma_chan)
                dma_release_channel(host->dma_chan);
  err_nand_ioremap:
-       platform_driver_unregister(&atmel_nand_nfc_driver);
        return res;
  }
  
  /*
   * Remove a NAND device.
   */
 -static int __exit atmel_nand_remove(struct platform_device *pdev)
 +static int atmel_nand_remove(struct platform_device *pdev)
  {
        struct atmel_nand_host *host = platform_get_drvdata(pdev);
        struct mtd_info *mtd = &host->mtd;
        return 0;
  }
  
- #if defined(CONFIG_OF)
  static const struct of_device_id atmel_nand_dt_ids[] = {
        { .compatible = "atmel,at91rm9200-nand" },
        { /* sentinel */ }
  };
  
  MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids);
- #endif
  
  static int atmel_nand_nfc_probe(struct platform_device *pdev)
  {
        return 0;
  }
  
- #if defined(CONFIG_OF)
- static struct of_device_id atmel_nand_nfc_match[] = {
+ static const struct of_device_id atmel_nand_nfc_match[] = {
        { .compatible = "atmel,sama5d3-nfc" },
        { /* sentinel */ }
  };
- #endif
+ MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);
  
  static struct platform_driver atmel_nand_nfc_driver = {
        .driver = {
  };
  
  static struct platform_driver atmel_nand_driver = {
 -      .remove         = __exit_p(atmel_nand_remove),
 +      .probe          = atmel_nand_probe,
 +      .remove         = atmel_nand_remove,
        .driver         = {
                .name   = "atmel_nand",
                .owner  = THIS_MODULE,
        },
  };
  
 -module_platform_driver_probe(atmel_nand_driver, atmel_nand_probe);
 +module_platform_driver(atmel_nand_driver);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Rick Bronson");
@@@ -28,7 -28,6 +28,7 @@@
  #include <linux/kernel.h>
  #include <linux/string.h>
  #include <linux/ioport.h>
 +#include <linux/of_address.h>
  #include <linux/of_platform.h>
  #include <linux/platform_device.h>
  #include <linux/slab.h>
@@@ -651,8 -650,6 +651,6 @@@ static int fsl_elbc_chip_init_tail(stru
                chip->page_shift);
        dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
                chip->phys_erase_shift);
-       dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
-               chip->ecclayout);
        dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
                chip->ecc.mode);
        dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
@@@ -24,7 -24,6 +24,7 @@@
  #include <linux/types.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
 +#include <linux/of_address.h>
  #include <linux/slab.h>
  #include <linux/mtd/mtd.h>
  #include <linux/mtd/nand.h>
@@@ -136,6 -135,69 +136,69 @@@ static struct nand_ecclayout oob_4096_e
        .oobfree = { {2, 6}, {136, 82} },
  };
  
+ /* 8192-byte page size with 4-bit ECC */
+ static struct nand_ecclayout oob_8192_ecc4 = {
+       .eccbytes = 128,
+       .eccpos = {
+               8, 9, 10, 11, 12, 13, 14, 15,
+               16, 17, 18, 19, 20, 21, 22, 23,
+               24, 25, 26, 27, 28, 29, 30, 31,
+               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,
+               64, 65, 66, 67, 68, 69, 70, 71,
+               72, 73, 74, 75, 76, 77, 78, 79,
+               80, 81, 82, 83, 84, 85, 86, 87,
+               88, 89, 90, 91, 92, 93, 94, 95,
+               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,
+               128, 129, 130, 131, 132, 133, 134, 135,
+       },
+       .oobfree = { {2, 6}, {136, 208} },
+ };
+ /* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
+ static struct nand_ecclayout oob_8192_ecc8 = {
+       .eccbytes = 256,
+       .eccpos = {
+               8, 9, 10, 11, 12, 13, 14, 15,
+               16, 17, 18, 19, 20, 21, 22, 23,
+               24, 25, 26, 27, 28, 29, 30, 31,
+               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,
+               64, 65, 66, 67, 68, 69, 70, 71,
+               72, 73, 74, 75, 76, 77, 78, 79,
+               80, 81, 82, 83, 84, 85, 86, 87,
+               88, 89, 90, 91, 92, 93, 94, 95,
+               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,
+               128, 129, 130, 131, 132, 133, 134, 135,
+               136, 137, 138, 139, 140, 141, 142, 143,
+               144, 145, 146, 147, 148, 149, 150, 151,
+               152, 153, 154, 155, 156, 157, 158, 159,
+               160, 161, 162, 163, 164, 165, 166, 167,
+               168, 169, 170, 171, 172, 173, 174, 175,
+               176, 177, 178, 179, 180, 181, 182, 183,
+               184, 185, 186, 187, 188, 189, 190, 191,
+               192, 193, 194, 195, 196, 197, 198, 199,
+               200, 201, 202, 203, 204, 205, 206, 207,
+               208, 209, 210, 211, 212, 213, 214, 215,
+               216, 217, 218, 219, 220, 221, 222, 223,
+               224, 225, 226, 227, 228, 229, 230, 231,
+               232, 233, 234, 235, 236, 237, 238, 239,
+               240, 241, 242, 243, 244, 245, 246, 247,
+               248, 249, 250, 251, 252, 253, 254, 255,
+               256, 257, 258, 259, 260, 261, 262, 263,
+       },
+       .oobfree = { {2, 6}, {264, 80} },
+ };
  
  /*
   * Generic flash bbt descriptors
@@@ -442,20 -504,29 +505,29 @@@ static void fsl_ifc_cmdfunc(struct mtd_
                if (mtd->writesize > 512) {
                        nand_fcr0 =
                                (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
-                               (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT);
+                               (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
+                               (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
  
                        iowrite32be(
-                               (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                               (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
-                               (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
-                               (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
-                               (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT),
-                               &ifc->ifc_nand.nand_fir0);
+                                (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                                (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+                                (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+                                (IFC_FIR_OP_WBCD  << IFC_NAND_FIR0_OP3_SHIFT) |
+                                (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT),
+                                &ifc->ifc_nand.nand_fir0);
+                       iowrite32be(
+                                (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
+                                (IFC_FIR_OP_RDSTAT <<
+                                       IFC_NAND_FIR1_OP6_SHIFT) |
+                                (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT),
+                                &ifc->ifc_nand.nand_fir1);
                } else {
                        nand_fcr0 = ((NAND_CMD_PAGEPROG <<
                                        IFC_NAND_FCR0_CMD1_SHIFT) |
                                    (NAND_CMD_SEQIN <<
-                                       IFC_NAND_FCR0_CMD2_SHIFT));
+                                       IFC_NAND_FCR0_CMD2_SHIFT) |
+                                   (NAND_CMD_STATUS <<
+                                       IFC_NAND_FCR0_CMD3_SHIFT));
  
                        iowrite32be(
                                (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
                                (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
                                (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT),
                                &ifc->ifc_nand.nand_fir0);
-                       iowrite32be(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT,
-                                   &ifc->ifc_nand.nand_fir1);
+                       iowrite32be(
+                                (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
+                                (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
+                                (IFC_FIR_OP_RDSTAT <<
+                                       IFC_NAND_FIR1_OP7_SHIFT) |
+                                (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT),
+                                 &ifc->ifc_nand.nand_fir1);
  
                        if (column >= mtd->writesize)
                                nand_fcr0 |=
@@@ -719,8 -795,6 +796,6 @@@ static int fsl_ifc_chip_init_tail(struc
                                                        chip->page_shift);
        dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__,
                                                        chip->phys_erase_shift);
-       dev_dbg(priv->dev, "%s: nand->ecclayout = %p\n", __func__,
-                                                       chip->ecclayout);
        dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__,
                                                        chip->ecc.mode);
        dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__,
@@@ -873,11 -947,25 +948,25 @@@ static int fsl_ifc_chip_init(struct fsl
                } else {
                        layout = &oob_4096_ecc8;
                        chip->ecc.bytes = 16;
+                       chip->ecc.strength = 8;
                }
  
                priv->bufnum_mask = 1;
                break;
  
+       case CSOR_NAND_PGS_8K:
+               if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
+                   CSOR_NAND_ECC_MODE_4) {
+                       layout = &oob_8192_ecc4;
+               } else {
+                       layout = &oob_8192_ecc8;
+                       chip->ecc.bytes = 16;
+                       chip->ecc.strength = 8;
+               }
+               priv->bufnum_mask = 0;
+       break;
        default:
                dev_err(priv->dev, "bad csor %#x: bad page size\n", csor);
                return -ENODEV;
@@@ -908,7 -996,6 +997,6 @@@ static int fsl_ifc_chip_remove(struct f
                iounmap(priv->vbase);
  
        ifc_nand_ctrl->chips[priv->bank] = NULL;
-       dev_set_drvdata(priv->dev, NULL);
  
        return 0;
  }
@@@ -1083,25 -1170,7 +1171,7 @@@ static struct platform_driver fsl_ifc_n
        .remove      = fsl_ifc_nand_remove,
  };
  
- static int __init fsl_ifc_nand_init(void)
- {
-       int ret;
-       ret = platform_driver_register(&fsl_ifc_nand_driver);
-       if (ret)
-               printk(KERN_ERR "fsl-ifc: Failed to register platform"
-                               "driver\n");
-       return ret;
- }
- static void __exit fsl_ifc_nand_exit(void)
- {
-       platform_driver_unregister(&fsl_ifc_nand_driver);
- }
- module_init(fsl_ifc_nand_init);
- module_exit(fsl_ifc_nand_exit);
+ module_platform_driver(fsl_ifc_nand_driver);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Freescale");
@@@ -575,7 -575,7 +575,7 @@@ static int alloc_device(struct nandsim 
                cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
                if (IS_ERR(cfile))
                        return PTR_ERR(cfile);
 -              if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) {
 +              if (!cfile->f_op->read && !cfile->f_op->aio_read) {
                        NS_ERR("alloc_device: cache file not readable\n");
                        err = -EINVAL;
                        goto err_close;
@@@ -2372,7 -2372,7 +2372,7 @@@ static int __init ns_init_module(void
        if ((retval = init_nandsim(nsmtd)) != 0)
                goto err_exit;
  
-       if ((retval = nand_default_bbt(nsmtd)) != 0)
+       if ((retval = chip->scan_bbt(nsmtd)) != 0)
                goto err_exit;
  
        if ((retval = parse_badblocks(nand, nsmtd)) != 0)
@@@ -15,7 -15,6 +15,7 @@@
  #include <linux/mtd/mtd.h>
  #include <linux/mtd/nand.h>
  #include <linux/mtd/partitions.h>
 +#include <linux/of_address.h>
  #include <linux/of_platform.h>
  #include <linux/io.h>
  
@@@ -150,17 -149,13 +150,13 @@@ static int socrates_nand_probe(struct p
        struct mtd_part_parser_data ppdata;
  
        /* Allocate memory for the device structure (and zero it) */
-       host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL);
-       if (!host) {
-               printk(KERN_ERR
-                      "socrates_nand: failed to allocate device structure.\n");
+       host = devm_kzalloc(&ofdev->dev, sizeof(*host), GFP_KERNEL);
+       if (!host)
                return -ENOMEM;
-       }
  
        host->io_base = of_iomap(ofdev->dev.of_node, 0);
        if (host->io_base == NULL) {
-               printk(KERN_ERR "socrates_nand: ioremap failed\n");
-               kfree(host);
+               dev_err(&ofdev->dev, "ioremap failed\n");
                return -EIO;
        }
  
        nand_release(mtd);
  
  out:
-       dev_set_drvdata(&ofdev->dev, NULL);
        iounmap(host->io_base);
-       kfree(host);
        return res;
  }
  
@@@ -228,9 -221,7 +222,7 @@@ static int socrates_nand_remove(struct 
  
        nand_release(mtd);
  
-       dev_set_drvdata(&ofdev->dev, NULL);
        iounmap(host->io_base);
-       kfree(host);
  
        return 0;
  }