Browse Source

Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6: (79 commits)
  mtd: Remove obsolete <mtd/compatmac.h> include
  mtd: Update copyright notices
  jffs2: Update copyright notices
  mtd-physmap: add support users can assign the probe type in board files
  mtd: remove redwood map driver
  mxc_nand: Add v3 (i.MX51) Support
  mxc_nand: support 8bit ecc
  mxc_nand: fix correct_data function
  mxc_nand: add V1_V2 namespace to registers
  mxc_nand: factor out a check_int function
  mxc_nand: make some internally used functions overwriteable
  mxc_nand: rework get_dev_status
  mxc_nand: remove 0xe00 offset from registers
  mtd: denali: Add multi connected NAND support
  mtd: denali: Remove set_ecc_config function
  mtd: denali: Remove unuseful code in get_xx_nand_para functions
  mtd: denali: Remove device_info_tag structure
  mtd: m25p80: add support for the Winbond W25Q32 SPI flash chip
  mtd: m25p80: add support for the Intel/Numonyx {16,32,64}0S33B SPI flash chips
  mtd: m25p80: add support for the EON EN25P{32, 64} SPI flash chips
  ...

Fix up trivial conflicts in drivers/mtd/maps/{Kconfig,redwood.c} due to
redwood driver removal.
Linus Torvalds 15 years ago
parent
commit
e8a89cebdb
100 changed files with 1842 additions and 1520 deletions
  1. 0 3
      arch/blackfin/include/asm/nand.h
  2. 7 5
      drivers/mtd/Kconfig
  3. 1 1
      drivers/mtd/afs.c
  4. 20 11
      drivers/mtd/chips/cfi_cmdset_0001.c
  5. 13 4
      drivers/mtd/chips/cfi_cmdset_0002.c
  6. 0 1
      drivers/mtd/chips/cfi_cmdset_0020.c
  7. 2 2
      drivers/mtd/chips/cfi_probe.c
  8. 0 1
      drivers/mtd/chips/cfi_util.c
  9. 0 1
      drivers/mtd/chips/chipreg.c
  10. 0 1
      drivers/mtd/chips/map_absent.c
  11. 0 1
      drivers/mtd/chips/map_ram.c
  12. 0 1
      drivers/mtd/chips/map_rom.c
  13. 16 1
      drivers/mtd/cmdlinepart.c
  14. 0 1
      drivers/mtd/devices/docecc.c
  15. 0 1
      drivers/mtd/devices/docprobe.c
  16. 29 14
      drivers/mtd/devices/m25p80.c
  17. 6 6
      drivers/mtd/devices/mtd_dataflash.c
  18. 0 1
      drivers/mtd/devices/mtdram.c
  19. 0 1
      drivers/mtd/devices/pmc551.c
  20. 1 1
      drivers/mtd/devices/sst25l.c
  21. 1 1
      drivers/mtd/ftl.c
  22. 3 3
      drivers/mtd/inftlcore.c
  23. 2 3
      drivers/mtd/inftlmount.c
  24. 10 10
      drivers/mtd/lpddr/lpddr_cmds.c
  25. 0 8
      drivers/mtd/maps/Kconfig
  26. 0 1
      drivers/mtd/maps/Makefile
  27. 27 8
      drivers/mtd/maps/ixp4xx.c
  28. 9 5
      drivers/mtd/maps/physmap.c
  29. 3 3
      drivers/mtd/maps/physmap_of.c
  30. 0 131
      drivers/mtd/maps/redwood.c
  31. 21 5
      drivers/mtd/mtd_blkdevs.c
  32. 17 2
      drivers/mtd/mtdblock.c
  33. 17 2
      drivers/mtd/mtdblock_ro.c
  34. 56 3
      drivers/mtd/mtdchar.c
  35. 28 10
      drivers/mtd/mtdconcat.c
  36. 17 4
      drivers/mtd/mtdcore.c
  37. 1 1
      drivers/mtd/mtdoops.c
  38. 26 5
      drivers/mtd/mtdpart.c
  39. 2 0
      drivers/mtd/mtdsuper.c
  40. 16 17
      drivers/mtd/nand/Kconfig
  41. 1 1
      drivers/mtd/nand/atmel_nand.c
  42. 72 45
      drivers/mtd/nand/bf5xx_nand.c
  43. 17 0
      drivers/mtd/nand/davinci_nand.c
  44. 475 765
      drivers/mtd/nand/denali.c
  45. 49 91
      drivers/mtd/nand/denali.h
  46. 3 3
      drivers/mtd/nand/diskonchip.c
  47. 425 175
      drivers/mtd/nand/mxc_nand.c
  48. 61 18
      drivers/mtd/nand/nand_base.c
  49. 75 28
      drivers/mtd/nand/nand_bbt.c
  50. 4 0
      drivers/mtd/nand/nand_ids.c
  51. 7 7
      drivers/mtd/nand/nandsim.c
  52. 1 1
      drivers/mtd/nand/plat_nand.c
  53. 3 3
      drivers/mtd/nand/r852.c
  54. 0 1
      drivers/mtd/nand/rtc_from4.c
  55. 6 9
      drivers/mtd/nand/s3c2410.c
  56. 1 1
      drivers/mtd/nand/sm_common.c
  57. 18 7
      drivers/mtd/nftlcore.c
  58. 2 1
      drivers/mtd/nftlmount.c
  59. 2 2
      drivers/mtd/ofpart.c
  60. 2 2
      drivers/mtd/onenand/Kconfig
  61. 35 14
      drivers/mtd/onenand/onenand_base.c
  62. 0 1
      drivers/mtd/onenand/onenand_bbt.c
  63. 8 13
      drivers/mtd/onenand/samsung.c
  64. 18 0
      drivers/mtd/redboot.c
  65. 1 1
      drivers/mtd/rfd_ftl.c
  66. 1 1
      drivers/mtd/ssfdc.c
  67. 4 5
      drivers/mtd/tests/mtd_pagetest.c
  68. 1 0
      fs/jffs2/background.c
  69. 1 0
      fs/jffs2/build.c
  70. 3 2
      fs/jffs2/compr.c
  71. 1 0
      fs/jffs2/compr.h
  72. 1 0
      fs/jffs2/compr_lzo.c
  73. 1 0
      fs/jffs2/compr_rtime.c
  74. 1 0
      fs/jffs2/compr_rubin.c
  75. 1 0
      fs/jffs2/compr_zlib.c
  76. 1 0
      fs/jffs2/debug.c
  77. 1 0
      fs/jffs2/debug.h
  78. 1 0
      fs/jffs2/dir.c
  79. 1 0
      fs/jffs2/erase.c
  80. 1 0
      fs/jffs2/file.c
  81. 1 0
      fs/jffs2/fs.c
  82. 1 0
      fs/jffs2/gc.c
  83. 1 0
      fs/jffs2/ioctl.c
  84. 1 0
      fs/jffs2/jffs2_fs_i.h
  85. 1 0
      fs/jffs2/jffs2_fs_sb.h
  86. 0 1
      fs/jffs2/nodelist.h
  87. 2 1
      include/linux/jffs2.h
  88. 22 2
      include/linux/mtd/bbm.h
  89. 14 2
      include/linux/mtd/blktrans.h
  90. 17 3
      include/linux/mtd/cfi.h
  91. 19 0
      include/linux/mtd/cfi_endian.h
  92. 0 10
      include/linux/mtd/compatmac.h
  93. 15 2
      include/linux/mtd/concat.h
  94. 18 5
      include/linux/mtd/doc2000.h
  95. 16 5
      include/linux/mtd/flashchip.h
  96. 17 2
      include/linux/mtd/gen_probe.h
  97. 18 1
      include/linux/mtd/map.h
  98. 16 3
      include/linux/mtd/mtd.h
  99. 3 5
      include/linux/mtd/nand.h
  100. 3 1
      include/linux/mtd/nand_ecc.h

+ 0 - 3
arch/blackfin/include/asm/nand.h

@@ -15,8 +15,6 @@
  * partitions	 = mtd partition list
  * partitions	 = mtd partition list
  */
  */
 
 
-#define NFC_PG_SIZE_256		0
-#define NFC_PG_SIZE_512		1
 #define NFC_PG_SIZE_OFFSET	9
 #define NFC_PG_SIZE_OFFSET	9
 
 
 #define NFC_NWIDTH_8		0
 #define NFC_NWIDTH_8		0
@@ -30,7 +28,6 @@
 
 
 struct bf5xx_nand_platform {
 struct bf5xx_nand_platform {
 	/* NAND chip information */
 	/* NAND chip information */
-	unsigned short		page_size;
 	unsigned short		data_width;
 	unsigned short		data_width;
 
 
 	/* RD/WR strobe delay timing information, all times in SCLK cycles */
 	/* RD/WR strobe delay timing information, all times in SCLK cycles */

+ 7 - 5
drivers/mtd/Kconfig

@@ -311,15 +311,17 @@ config SM_FTL
 	select MTD_BLKDEVS
 	select MTD_BLKDEVS
 	select MTD_NAND_ECC
 	select MTD_NAND_ECC
 	help
 	help
-	  This enables new and very EXPERMENTAL support for SmartMedia/xD
+	  This enables EXPERIMENTAL R/W support for SmartMedia/xD
 	  FTL (Flash translation layer).
 	  FTL (Flash translation layer).
-	  Write support isn't yet well tested, therefore this code IS likely to
-	  eat your card, so please don't use it together with valuable data.
-	  Use readonly driver (CONFIG_SSFDC) instead.
+	  Write support is only lightly tested, therefore this driver
+	  isn't recommended to use with valuable data (anyway if you have
+	  valuable data, do backups regardless of software/hardware you
+	  use, because you never know what will eat your data...)
+	  If you only need R/O access, you can use older R/O driver
+	  (CONFIG_SSFDC)
 
 
 config MTD_OOPS
 config MTD_OOPS
 	tristate "Log panic/oops to an MTD buffer"
 	tristate "Log panic/oops to an MTD buffer"
-	depends on MTD
 	help
 	help
 	  This enables panic and oops messages to be logged to a circular
 	  This enables panic and oops messages to be logged to a circular
 	  buffer in a flash partition where it can be read back at some
 	  buffer in a flash partition where it can be read back at some

+ 1 - 1
drivers/mtd/afs.c

@@ -2,7 +2,7 @@
 
 
     drivers/mtd/afs.c: ARM Flash Layout/Partitioning
     drivers/mtd/afs.c: ARM Flash Layout/Partitioning
 
 
-    Copyright (C) 2000 ARM Limited
+    Copyright © 2000 ARM Limited
 
 
    This program is free software; you can redistribute it and/or modify
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by

+ 20 - 11
drivers/mtd/chips/cfi_cmdset_0001.c

@@ -34,7 +34,6 @@
 #include <linux/mtd/xip.h>
 #include <linux/mtd/xip.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/compatmac.h>
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/cfi.h>
 
 
 /* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */
 /* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */
@@ -63,6 +62,8 @@ static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *);
 static void cfi_intelext_sync (struct mtd_info *);
 static void cfi_intelext_sync (struct mtd_info *);
 static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs,
+				  uint64_t len);
 #ifdef CONFIG_MTD_OTP
 #ifdef CONFIG_MTD_OTP
 static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
@@ -448,6 +449,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
 	mtd->sync    = cfi_intelext_sync;
 	mtd->sync    = cfi_intelext_sync;
 	mtd->lock    = cfi_intelext_lock;
 	mtd->lock    = cfi_intelext_lock;
 	mtd->unlock  = cfi_intelext_unlock;
 	mtd->unlock  = cfi_intelext_unlock;
+	mtd->is_locked = cfi_intelext_is_locked;
 	mtd->suspend = cfi_intelext_suspend;
 	mtd->suspend = cfi_intelext_suspend;
 	mtd->resume  = cfi_intelext_resume;
 	mtd->resume  = cfi_intelext_resume;
 	mtd->flags   = MTD_CAP_NORFLASH;
 	mtd->flags   = MTD_CAP_NORFLASH;
@@ -717,7 +719,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
 		chip = &newcfi->chips[0];
 		chip = &newcfi->chips[0];
 		for (i = 0; i < cfi->numchips; i++) {
 		for (i = 0; i < cfi->numchips; i++) {
 			shared[i].writing = shared[i].erasing = NULL;
 			shared[i].writing = shared[i].erasing = NULL;
-			spin_lock_init(&shared[i].lock);
+			mutex_init(&shared[i].lock);
 			for (j = 0; j < numparts; j++) {
 			for (j = 0; j < numparts; j++) {
 				*chip = cfi->chips[i];
 				*chip = cfi->chips[i];
 				chip->start += j << partshift;
 				chip->start += j << partshift;
@@ -886,7 +888,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 		 */
 		 */
 		struct flchip_shared *shared = chip->priv;
 		struct flchip_shared *shared = chip->priv;
 		struct flchip *contender;
 		struct flchip *contender;
-		spin_lock(&shared->lock);
+		mutex_lock(&shared->lock);
 		contender = shared->writing;
 		contender = shared->writing;
 		if (contender && contender != chip) {
 		if (contender && contender != chip) {
 			/*
 			/*
@@ -899,7 +901,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 			 * get_chip returns success we're clear to go ahead.
 			 * get_chip returns success we're clear to go ahead.
 			 */
 			 */
 			ret = mutex_trylock(&contender->mutex);
 			ret = mutex_trylock(&contender->mutex);
-			spin_unlock(&shared->lock);
+			mutex_unlock(&shared->lock);
 			if (!ret)
 			if (!ret)
 				goto retry;
 				goto retry;
 			mutex_unlock(&chip->mutex);
 			mutex_unlock(&chip->mutex);
@@ -914,7 +916,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 				mutex_unlock(&contender->mutex);
 				mutex_unlock(&contender->mutex);
 				return ret;
 				return ret;
 			}
 			}
-			spin_lock(&shared->lock);
+			mutex_lock(&shared->lock);
 
 
 			/* We should not own chip if it is already
 			/* We should not own chip if it is already
 			 * in FL_SYNCING state. Put contender and retry. */
 			 * in FL_SYNCING state. Put contender and retry. */
@@ -930,7 +932,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 		 * on this chip. Sleep. */
 		 * on this chip. Sleep. */
 		if (mode == FL_ERASING && shared->erasing
 		if (mode == FL_ERASING && shared->erasing
 		    && shared->erasing->oldstate == FL_ERASING) {
 		    && shared->erasing->oldstate == FL_ERASING) {
-			spin_unlock(&shared->lock);
+			mutex_unlock(&shared->lock);
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			add_wait_queue(&chip->wq, &wait);
 			add_wait_queue(&chip->wq, &wait);
 			mutex_unlock(&chip->mutex);
 			mutex_unlock(&chip->mutex);
@@ -944,7 +946,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 		shared->writing = chip;
 		shared->writing = chip;
 		if (mode == FL_ERASING)
 		if (mode == FL_ERASING)
 			shared->erasing = chip;
 			shared->erasing = chip;
-		spin_unlock(&shared->lock);
+		mutex_unlock(&shared->lock);
 	}
 	}
 	ret = chip_ready(map, chip, adr, mode);
 	ret = chip_ready(map, chip, adr, mode);
 	if (ret == -EAGAIN)
 	if (ret == -EAGAIN)
@@ -959,7 +961,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 
 
 	if (chip->priv) {
 	if (chip->priv) {
 		struct flchip_shared *shared = chip->priv;
 		struct flchip_shared *shared = chip->priv;
-		spin_lock(&shared->lock);
+		mutex_lock(&shared->lock);
 		if (shared->writing == chip && chip->oldstate == FL_READY) {
 		if (shared->writing == chip && chip->oldstate == FL_READY) {
 			/* We own the ability to write, but we're done */
 			/* We own the ability to write, but we're done */
 			shared->writing = shared->erasing;
 			shared->writing = shared->erasing;
@@ -967,7 +969,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 				/* give back ownership to who we loaned it from */
 				/* give back ownership to who we loaned it from */
 				struct flchip *loaner = shared->writing;
 				struct flchip *loaner = shared->writing;
 				mutex_lock(&loaner->mutex);
 				mutex_lock(&loaner->mutex);
-				spin_unlock(&shared->lock);
+				mutex_unlock(&shared->lock);
 				mutex_unlock(&chip->mutex);
 				mutex_unlock(&chip->mutex);
 				put_chip(map, loaner, loaner->start);
 				put_chip(map, loaner, loaner->start);
 				mutex_lock(&chip->mutex);
 				mutex_lock(&chip->mutex);
@@ -985,11 +987,11 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 			 * Don't let the switch below mess things up since
 			 * Don't let the switch below mess things up since
 			 * we don't have ownership to resume anything.
 			 * we don't have ownership to resume anything.
 			 */
 			 */
-			spin_unlock(&shared->lock);
+			mutex_unlock(&shared->lock);
 			wake_up(&chip->wq);
 			wake_up(&chip->wq);
 			return;
 			return;
 		}
 		}
-		spin_unlock(&shared->lock);
+		mutex_unlock(&shared->lock);
 	}
 	}
 
 
 	switch(chip->oldstate) {
 	switch(chip->oldstate) {
@@ -2139,6 +2141,13 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	return ret;
 	return ret;
 }
 }
 
 
+static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs,
+				  uint64_t len)
+{
+	return cfi_varsize_frob(mtd, do_getlockstatus_oneblock,
+				ofs, len, NULL) ? 1 : 0;
+}
+
 #ifdef CONFIG_MTD_OTP
 #ifdef CONFIG_MTD_OTP
 
 
 typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,
 typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,

+ 13 - 4
drivers/mtd/chips/cfi_cmdset_0002.c

@@ -33,7 +33,6 @@
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/reboot.h>
-#include <linux/mtd/compatmac.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/cfi.h>
@@ -417,16 +416,26 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
 			 */
 			 */
 			cfi_fixup_major_minor(cfi, extp);
 			cfi_fixup_major_minor(cfi, extp);
 
 
+			/*
+			 * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4
+			 * see: http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_r20.pdf, page 19
+			 *      http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_100_20011201.pdf
+			 *      http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf
+			 */
 			if (extp->MajorVersion != '1' ||
 			if (extp->MajorVersion != '1' ||
-			    (extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
+			    (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '4'))) {
 				printk(KERN_ERR "  Unknown Amd/Fujitsu Extended Query "
 				printk(KERN_ERR "  Unknown Amd/Fujitsu Extended Query "
-				       "version %c.%c.\n",  extp->MajorVersion,
-				       extp->MinorVersion);
+				       "version %c.%c (%#02x/%#02x).\n",
+				       extp->MajorVersion, extp->MinorVersion,
+				       extp->MajorVersion, extp->MinorVersion);
 				kfree(extp);
 				kfree(extp);
 				kfree(mtd);
 				kfree(mtd);
 				return NULL;
 				return NULL;
 			}
 			}
 
 
+			printk(KERN_INFO "  Amd/Fujitsu Extended Query version %c.%c.\n",
+			       extp->MajorVersion, extp->MinorVersion);
+
 			/* Install our own private info structure */
 			/* Install our own private info structure */
 			cfi->cmdset_priv = extp;
 			cfi->cmdset_priv = extp;
 
 

+ 0 - 1
drivers/mtd/chips/cfi_cmdset_0020.c

@@ -33,7 +33,6 @@
 #include <linux/mtd/map.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/compatmac.h>
 
 
 
 
 static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);

+ 2 - 2
drivers/mtd/chips/cfi_probe.c

@@ -235,9 +235,9 @@ static int __xipram cfi_chip_setup(struct map_info *map,
 	cfi_qry_mode_off(base, map, cfi);
 	cfi_qry_mode_off(base, map, cfi);
 	xip_allowed(base, map);
 	xip_allowed(base, map);
 
 
-	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
+	printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. Manufacturer ID %#08x Chip ID %#08x\n",
 	       map->name, cfi->interleave, cfi->device_type*8, base,
 	       map->name, cfi->interleave, cfi->device_type*8, base,
-	       map->bankwidth*8);
+	       map->bankwidth*8, cfi->mfr, cfi->id);
 
 
 	return 1;
 	return 1;
 }
 }

+ 0 - 1
drivers/mtd/chips/cfi_util.c

@@ -22,7 +22,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/cfi.h>
-#include <linux/mtd/compatmac.h>
 
 
 int __xipram cfi_qry_present(struct map_info *map, __u32 base,
 int __xipram cfi_qry_present(struct map_info *map, __u32 base,
 			     struct cfi_private *cfi)
 			     struct cfi_private *cfi)

+ 0 - 1
drivers/mtd/chips/chipreg.c

@@ -10,7 +10,6 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/compatmac.h>
 
 
 static DEFINE_SPINLOCK(chip_drvs_lock);
 static DEFINE_SPINLOCK(chip_drvs_lock);
 static LIST_HEAD(chip_drvs_list);
 static LIST_HEAD(chip_drvs_list);

+ 0 - 1
drivers/mtd/chips/map_absent.c

@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/map.h>
-#include <linux/mtd/compatmac.h>
 
 
 static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);

+ 0 - 1
drivers/mtd/chips/map_ram.c

@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/map.h>
-#include <linux/mtd/compatmac.h>
 
 
 
 
 static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);

+ 0 - 1
drivers/mtd/chips/map_rom.c

@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/map.h>
-#include <linux/mtd/compatmac.h>
 
 
 static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);

+ 16 - 1
drivers/mtd/cmdlinepart.c

@@ -1,7 +1,22 @@
 /*
 /*
  * Read flash partition table from command line
  * Read flash partition table from command line
  *
  *
- * Copyright 2002 SYSGO Real-Time Solutions GmbH
+ * Copyright © 2002      SYSGO Real-Time Solutions GmbH
+ * Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
  * The format for the command line is as follows:
  * The format for the command line is as follows:
  *
  *

+ 0 - 1
drivers/mtd/devices/docecc.c

@@ -31,7 +31,6 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/types.h>
 
 
-#include <linux/mtd/compatmac.h> /* for min() in older kernels */
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/doc2000.h>
 #include <linux/mtd/doc2000.h>
 
 

+ 0 - 1
drivers/mtd/devices/docprobe.c

@@ -49,7 +49,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/doc2000.h>
 #include <linux/mtd/doc2000.h>
-#include <linux/mtd/compatmac.h>
 
 
 /* Where to look for the devices? */
 /* Where to look for the devices? */
 #ifndef CONFIG_MTD_DOCPROBE_ADDRESS
 #ifndef CONFIG_MTD_DOCPROBE_ADDRESS

+ 29 - 14
drivers/mtd/devices/m25p80.c

@@ -16,6 +16,8 @@
  */
  */
 
 
 #include <linux/init.h>
 #include <linux/init.h>
+#include <linux/err.h>
+#include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
@@ -639,8 +641,18 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
 	{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
 	{ "at26df321",  INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
 	{ "at26df321",  INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
 
 
+	/* EON -- en25pxx */
+	{ "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
+	{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
+
+	/* Intel/Numonyx -- xxxs33b */
+	{ "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, 0) },
+	{ "320s33b",  INFO(0x898912, 0, 64 * 1024,  64, 0) },
+	{ "640s33b",  INFO(0x898913, 0, 64 * 1024, 128, 0) },
+
 	/* Macronix */
 	/* Macronix */
 	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
 	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
+	{ "mx25l8005",   INFO(0xc22014, 0, 64 * 1024,  16, 0) },
 	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, 0) },
 	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, 0) },
 	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, 0) },
 	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, 0) },
 	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
 	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
@@ -680,6 +692,16 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "m25p64",  INFO(0x202017,  0,  64 * 1024, 128, 0) },
 	{ "m25p64",  INFO(0x202017,  0,  64 * 1024, 128, 0) },
 	{ "m25p128", INFO(0x202018,  0, 256 * 1024,  64, 0) },
 	{ "m25p128", INFO(0x202018,  0, 256 * 1024,  64, 0) },
 
 
+	{ "m25p05-nonjedec",  INFO(0, 0,  32 * 1024,   2, 0) },
+	{ "m25p10-nonjedec",  INFO(0, 0,  32 * 1024,   4, 0) },
+	{ "m25p20-nonjedec",  INFO(0, 0,  64 * 1024,   4, 0) },
+	{ "m25p40-nonjedec",  INFO(0, 0,  64 * 1024,   8, 0) },
+	{ "m25p80-nonjedec",  INFO(0, 0,  64 * 1024,  16, 0) },
+	{ "m25p16-nonjedec",  INFO(0, 0,  64 * 1024,  32, 0) },
+	{ "m25p32-nonjedec",  INFO(0, 0,  64 * 1024,  64, 0) },
+	{ "m25p64-nonjedec",  INFO(0, 0,  64 * 1024, 128, 0) },
+	{ "m25p128-nonjedec", INFO(0, 0, 256 * 1024,  64, 0) },
+
 	{ "m45pe10", INFO(0x204011,  0, 64 * 1024,    2, 0) },
 	{ "m45pe10", INFO(0x204011,  0, 64 * 1024,    2, 0) },
 	{ "m45pe80", INFO(0x204014,  0, 64 * 1024,   16, 0) },
 	{ "m45pe80", INFO(0x204014,  0, 64 * 1024,   16, 0) },
 	{ "m45pe16", INFO(0x204015,  0, 64 * 1024,   32, 0) },
 	{ "m45pe16", INFO(0x204015,  0, 64 * 1024,   32, 0) },
@@ -694,6 +716,7 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "w25x80", INFO(0xef3014, 0, 64 * 1024,  16, SECT_4K) },
 	{ "w25x80", INFO(0xef3014, 0, 64 * 1024,  16, SECT_4K) },
 	{ "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
 	{ "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
 	{ "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
 	{ "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
+	{ "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
 	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
 	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
 
 
 	/* Catalyst / On Semiconductor -- non-JEDEC */
 	/* Catalyst / On Semiconductor -- non-JEDEC */
@@ -723,7 +746,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 	if (tmp < 0) {
 	if (tmp < 0) {
 		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
 		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
 			dev_name(&spi->dev), tmp);
 			dev_name(&spi->dev), tmp);
-		return NULL;
+		return ERR_PTR(tmp);
 	}
 	}
 	jedec = id[0];
 	jedec = id[0];
 	jedec = jedec << 8;
 	jedec = jedec << 8;
@@ -731,14 +754,6 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 	jedec = jedec << 8;
 	jedec = jedec << 8;
 	jedec |= id[2];
 	jedec |= id[2];
 
 
-	/*
-	 * Some chips (like Numonyx M25P80) have JEDEC and non-JEDEC variants,
-	 * which depend on technology process. Officially RDID command doesn't
-	 * exist for non-JEDEC chips, but for compatibility they return ID 0.
-	 */
-	if (jedec == 0)
-		return NULL;
-
 	ext_jedec = id[3] << 8 | id[4];
 	ext_jedec = id[3] << 8 | id[4];
 
 
 	for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
 	for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
@@ -749,7 +764,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 			return &m25p_ids[tmp];
 			return &m25p_ids[tmp];
 		}
 		}
 	}
 	}
-	return NULL;
+	return ERR_PTR(-ENODEV);
 }
 }
 
 
 
 
@@ -794,9 +809,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
 		const struct spi_device_id *jid;
 		const struct spi_device_id *jid;
 
 
 		jid = jedec_probe(spi);
 		jid = jedec_probe(spi);
-		if (!jid) {
-			dev_info(&spi->dev, "non-JEDEC variant of %s\n",
-				 id->name);
+		if (IS_ERR(jid)) {
+			return PTR_ERR(jid);
 		} else if (jid != id) {
 		} else if (jid != id) {
 			/*
 			/*
 			 * JEDEC knows better, so overwrite platform ID. We
 			 * JEDEC knows better, so overwrite platform ID. We
@@ -826,11 +840,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	dev_set_drvdata(&spi->dev, flash);
 	dev_set_drvdata(&spi->dev, flash);
 
 
 	/*
 	/*
-	 * Atmel and SST serial flash tend to power
+	 * Atmel, SST and Intel/Numonyx serial flash tend to power
 	 * up with the software protection bits set
 	 * up with the software protection bits set
 	 */
 	 */
 
 
 	if (info->jedec_id >> 16 == 0x1f ||
 	if (info->jedec_id >> 16 == 0x1f ||
+	    info->jedec_id >> 16 == 0x89 ||
 	    info->jedec_id >> 16 == 0xbf) {
 	    info->jedec_id >> 16 == 0xbf) {
 		write_enable(flash);
 		write_enable(flash);
 		write_sr(flash, 0);
 		write_sr(flash, 0);

+ 6 - 6
drivers/mtd/devices/mtd_dataflash.c

@@ -141,7 +141,7 @@ static int dataflash_waitready(struct spi_device *spi)
  */
  */
 static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
 static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	struct spi_device	*spi = priv->spi;
 	struct spi_device	*spi = priv->spi;
 	struct spi_transfer	x = { .tx_dma = 0, };
 	struct spi_transfer	x = { .tx_dma = 0, };
 	struct spi_message	msg;
 	struct spi_message	msg;
@@ -231,7 +231,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
 static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 			       size_t *retlen, u_char *buf)
 			       size_t *retlen, u_char *buf)
 {
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	struct spi_transfer	x[2] = { { .tx_dma = 0, }, };
 	struct spi_transfer	x[2] = { { .tx_dma = 0, }, };
 	struct spi_message	msg;
 	struct spi_message	msg;
 	unsigned int		addr;
 	unsigned int		addr;
@@ -304,7 +304,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
 static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
 				size_t * retlen, const u_char * buf)
 				size_t * retlen, const u_char * buf)
 {
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	struct spi_device	*spi = priv->spi;
 	struct spi_device	*spi = priv->spi;
 	struct spi_transfer	x[2] = { { .tx_dma = 0, }, };
 	struct spi_transfer	x[2] = { { .tx_dma = 0, }, };
 	struct spi_message	msg;
 	struct spi_message	msg;
@@ -515,7 +515,7 @@ static ssize_t otp_read(struct spi_device *spi, unsigned base,
 static int dataflash_read_fact_otp(struct mtd_info *mtd,
 static int dataflash_read_fact_otp(struct mtd_info *mtd,
 		loff_t from, size_t len, size_t *retlen, u_char *buf)
 		loff_t from, size_t len, size_t *retlen, u_char *buf)
 {
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	int			status;
 	int			status;
 
 
 	/* 64 bytes, from 0..63 ... start at 64 on-chip */
 	/* 64 bytes, from 0..63 ... start at 64 on-chip */
@@ -532,7 +532,7 @@ static int dataflash_read_fact_otp(struct mtd_info *mtd,
 static int dataflash_read_user_otp(struct mtd_info *mtd,
 static int dataflash_read_user_otp(struct mtd_info *mtd,
 		loff_t from, size_t len, size_t *retlen, u_char *buf)
 		loff_t from, size_t len, size_t *retlen, u_char *buf)
 {
 {
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	int			status;
 	int			status;
 
 
 	/* 64 bytes, from 0..63 ... start at 0 on-chip */
 	/* 64 bytes, from 0..63 ... start at 0 on-chip */
@@ -553,7 +553,7 @@ static int dataflash_write_user_otp(struct mtd_info *mtd,
 	const size_t		l = 4 + 64;
 	const size_t		l = 4 + 64;
 	uint8_t			*scratch;
 	uint8_t			*scratch;
 	struct spi_transfer	t;
 	struct spi_transfer	t;
-	struct dataflash	*priv = (struct dataflash *)mtd->priv;
+	struct dataflash	*priv = mtd->priv;
 	int			status;
 	int			status;
 
 
 	if (len > 64)
 	if (len > 64)

+ 0 - 1
drivers/mtd/devices/mtdram.c

@@ -14,7 +14,6 @@
 #include <linux/ioport.h>
 #include <linux/ioport.h>
 #include <linux/vmalloc.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/init.h>
-#include <linux/mtd/compatmac.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtdram.h>
 #include <linux/mtd/mtdram.h>
 
 

+ 0 - 1
drivers/mtd/devices/pmc551.c

@@ -98,7 +98,6 @@
 
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/pmc551.h>
 #include <linux/mtd/pmc551.h>
-#include <linux/mtd/compatmac.h>
 
 
 static struct mtd_info *pmc551list;
 static struct mtd_info *pmc551list;
 
 

+ 1 - 1
drivers/mtd/devices/sst25l.c

@@ -454,7 +454,7 @@ static int __init sst25l_probe(struct spi_device *spi)
 						  parts, nr_parts);
 						  parts, nr_parts);
 		}
 		}
 
 
-	} else if (data->nr_parts) {
+	} else if (data && data->nr_parts) {
 		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
 		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
 			 data->nr_parts, data->name);
 			 data->nr_parts, data->name);
 	}
 	}

+ 1 - 1
drivers/mtd/ftl.c

@@ -26,7 +26,7 @@
 
 
     The initial developer of the original code is David A. Hinds
     The initial developer of the original code is David A. Hinds
     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
-    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
+    are Copyright © 1999 David A. Hinds.  All Rights Reserved.
 
 
     Alternatively, the contents of this file may be used under the
     Alternatively, the contents of this file may be used under the
     terms of the GNU General Public License version 2 (the "GPL"), in
     terms of the GNU General Public License version 2 (the "GPL"), in

+ 3 - 3
drivers/mtd/inftlcore.c

@@ -1,11 +1,11 @@
 /*
 /*
  * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL)
  * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL)
  *
  *
- * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
+ * Copyright © 2002, Greg Ungerer (gerg@snapgear.com)
  *
  *
  * Based heavily on the nftlcore.c code which is:
  * Based heavily on the nftlcore.c code which is:
- * (c) 1999 Machine Vision Holdings, Inc.
- * Author: David Woodhouse <dwmw2@infradead.org>
+ * Copyright © 1999 Machine Vision Holdings, Inc.
+ * Copyright © 1999 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by

+ 2 - 3
drivers/mtd/inftlmount.c

@@ -2,11 +2,11 @@
  * inftlmount.c -- INFTL mount code with extensive checks.
  * inftlmount.c -- INFTL mount code with extensive checks.
  *
  *
  * Author: Greg Ungerer (gerg@snapgear.com)
  * Author: Greg Ungerer (gerg@snapgear.com)
- * (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com)
+ * Copyright © 2002-2003, Greg Ungerer (gerg@snapgear.com)
  *
  *
  * Based heavily on the nftlmount.c code which is:
  * Based heavily on the nftlmount.c code which is:
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
- * Copyright (C) 2000 Netgem S.A.
+ * Copyright © 2000 Netgem S.A.
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
@@ -34,7 +34,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nftl.h>
 #include <linux/mtd/nftl.h>
 #include <linux/mtd/inftl.h>
 #include <linux/mtd/inftl.h>
-#include <linux/mtd/compatmac.h>
 
 
 /*
 /*
  * find_boot_record: Find the INFTL Media Header and its Spare copy which
  * find_boot_record: Find the INFTL Media Header and its Spare copy which

+ 10 - 10
drivers/mtd/lpddr/lpddr_cmds.c

@@ -98,7 +98,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
 	numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum;
 	numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum;
 	for (i = 0; i < numchips; i++) {
 	for (i = 0; i < numchips; i++) {
 		shared[i].writing = shared[i].erasing = NULL;
 		shared[i].writing = shared[i].erasing = NULL;
-		spin_lock_init(&shared[i].lock);
+		mutex_init(&shared[i].lock);
 		for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) {
 		for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) {
 			*chip = lpddr->chips[i];
 			*chip = lpddr->chips[i];
 			chip->start += j << lpddr->chipshift;
 			chip->start += j << lpddr->chipshift;
@@ -217,7 +217,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
 		 */
 		 */
 		struct flchip_shared *shared = chip->priv;
 		struct flchip_shared *shared = chip->priv;
 		struct flchip *contender;
 		struct flchip *contender;
-		spin_lock(&shared->lock);
+		mutex_lock(&shared->lock);
 		contender = shared->writing;
 		contender = shared->writing;
 		if (contender && contender != chip) {
 		if (contender && contender != chip) {
 			/*
 			/*
@@ -230,7 +230,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
 			 * get_chip returns success we're clear to go ahead.
 			 * get_chip returns success we're clear to go ahead.
 			 */
 			 */
 			ret = mutex_trylock(&contender->mutex);
 			ret = mutex_trylock(&contender->mutex);
-			spin_unlock(&shared->lock);
+			mutex_unlock(&shared->lock);
 			if (!ret)
 			if (!ret)
 				goto retry;
 				goto retry;
 			mutex_unlock(&chip->mutex);
 			mutex_unlock(&chip->mutex);
@@ -245,7 +245,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
 				mutex_unlock(&contender->mutex);
 				mutex_unlock(&contender->mutex);
 				return ret;
 				return ret;
 			}
 			}
-			spin_lock(&shared->lock);
+			mutex_lock(&shared->lock);
 
 
 			/* We should not own chip if it is already in FL_SYNCING
 			/* We should not own chip if it is already in FL_SYNCING
 			 * state. Put contender and retry. */
 			 * state. Put contender and retry. */
@@ -261,7 +261,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
 		   Must sleep in such a case. */
 		   Must sleep in such a case. */
 		if (mode == FL_ERASING && shared->erasing
 		if (mode == FL_ERASING && shared->erasing
 		    && shared->erasing->oldstate == FL_ERASING) {
 		    && shared->erasing->oldstate == FL_ERASING) {
-			spin_unlock(&shared->lock);
+			mutex_unlock(&shared->lock);
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			add_wait_queue(&chip->wq, &wait);
 			add_wait_queue(&chip->wq, &wait);
 			mutex_unlock(&chip->mutex);
 			mutex_unlock(&chip->mutex);
@@ -275,7 +275,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
 		shared->writing = chip;
 		shared->writing = chip;
 		if (mode == FL_ERASING)
 		if (mode == FL_ERASING)
 			shared->erasing = chip;
 			shared->erasing = chip;
-		spin_unlock(&shared->lock);
+		mutex_unlock(&shared->lock);
 	}
 	}
 
 
 	ret = chip_ready(map, chip, mode);
 	ret = chip_ready(map, chip, mode);
@@ -348,7 +348,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
 {
 {
 	if (chip->priv) {
 	if (chip->priv) {
 		struct flchip_shared *shared = chip->priv;
 		struct flchip_shared *shared = chip->priv;
-		spin_lock(&shared->lock);
+		mutex_lock(&shared->lock);
 		if (shared->writing == chip && chip->oldstate == FL_READY) {
 		if (shared->writing == chip && chip->oldstate == FL_READY) {
 			/* We own the ability to write, but we're done */
 			/* We own the ability to write, but we're done */
 			shared->writing = shared->erasing;
 			shared->writing = shared->erasing;
@@ -356,7 +356,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
 				/* give back the ownership */
 				/* give back the ownership */
 				struct flchip *loaner = shared->writing;
 				struct flchip *loaner = shared->writing;
 				mutex_lock(&loaner->mutex);
 				mutex_lock(&loaner->mutex);
-				spin_unlock(&shared->lock);
+				mutex_unlock(&shared->lock);
 				mutex_unlock(&chip->mutex);
 				mutex_unlock(&chip->mutex);
 				put_chip(map, loaner);
 				put_chip(map, loaner);
 				mutex_lock(&chip->mutex);
 				mutex_lock(&chip->mutex);
@@ -374,11 +374,11 @@ static void put_chip(struct map_info *map, struct flchip *chip)
 			 * Don't let the switch below mess things up since
 			 * Don't let the switch below mess things up since
 			 * we don't have ownership to resume anything.
 			 * we don't have ownership to resume anything.
 			 */
 			 */
-			spin_unlock(&shared->lock);
+			mutex_unlock(&shared->lock);
 			wake_up(&chip->wq);
 			wake_up(&chip->wq);
 			return;
 			return;
 		}
 		}
-		spin_unlock(&shared->lock);
+		mutex_unlock(&shared->lock);
 	}
 	}
 
 
 	switch (chip->oldstate) {
 	switch (chip->oldstate) {

+ 0 - 8
drivers/mtd/maps/Kconfig

@@ -319,14 +319,6 @@ config MTD_CFI_FLAGADM
 	  Mapping for the Flaga digital module. If you don't have one, ignore
 	  Mapping for the Flaga digital module. If you don't have one, ignore
 	  this setting.
 	  this setting.
 
 
-config MTD_REDWOOD
-	tristate "CFI Flash devices mapped on IBM Redwood"
-	depends on MTD_CFI
-	help
-	  This enables access routines for the flash chips on the IBM
-	  Redwood board. If you have one of these boards and would like to
-	  use the flash chips on it, say 'Y'.
-
 config MTD_SOLUTIONENGINE
 config MTD_SOLUTIONENGINE
 	tristate "CFI Flash device mapped on Hitachi SolutionEngine"
 	tristate "CFI Flash device mapped on Hitachi SolutionEngine"
 	depends on SUPERH && SOLUTION_ENGINE && MTD_CFI && MTD_REDBOOT_PARTS
 	depends on SUPERH && SOLUTION_ENGINE && MTD_CFI && MTD_REDBOOT_PARTS

+ 0 - 1
drivers/mtd/maps/Makefile

@@ -44,7 +44,6 @@ obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o
 obj-$(CONFIG_MTD_EDB7312)	+= edb7312.o
 obj-$(CONFIG_MTD_EDB7312)	+= edb7312.o
 obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
 obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
 obj-$(CONFIG_MTD_FORTUNET)	+= fortunet.o
 obj-$(CONFIG_MTD_FORTUNET)	+= fortunet.o
-obj-$(CONFIG_MTD_REDWOOD)	+= redwood.o
 obj-$(CONFIG_MTD_UCLINUX)	+= uclinux.o
 obj-$(CONFIG_MTD_UCLINUX)	+= uclinux.o
 obj-$(CONFIG_MTD_NETtel)	+= nettel.o
 obj-$(CONFIG_MTD_NETtel)	+= nettel.o
 obj-$(CONFIG_MTD_SCB2_FLASH)	+= scb2_flash.o
 obj-$(CONFIG_MTD_SCB2_FLASH)	+= scb2_flash.o

+ 27 - 8
drivers/mtd/maps/ixp4xx.c

@@ -118,7 +118,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to,
 		*dest++ = BYTE1(data);
 		*dest++ = BYTE1(data);
 		src += 2;
 		src += 2;
 		len -= 2;
 		len -= 2;
-        }
+	}
 
 
 	if (len > 0)
 	if (len > 0)
 		*dest++ = BYTE0(flash_read16(src));
 		*dest++ = BYTE0(flash_read16(src));
@@ -185,6 +185,8 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 {
 {
 	struct flash_platform_data *plat = dev->dev.platform_data;
 	struct flash_platform_data *plat = dev->dev.platform_data;
 	struct ixp4xx_flash_info *info;
 	struct ixp4xx_flash_info *info;
+	const char *part_type = NULL;
+	int nr_parts = 0;
 	int err = -1;
 	int err = -1;
 
 
 	if (!plat)
 	if (!plat)
@@ -218,9 +220,9 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 	 */
 	 */
 	info->map.bankwidth = 2;
 	info->map.bankwidth = 2;
 	info->map.name = dev_name(&dev->dev);
 	info->map.name = dev_name(&dev->dev);
-	info->map.read = ixp4xx_read16,
-	info->map.write = ixp4xx_probe_write16,
-	info->map.copy_from = ixp4xx_copy_from,
+	info->map.read = ixp4xx_read16;
+	info->map.write = ixp4xx_probe_write16;
+	info->map.copy_from = ixp4xx_copy_from;
 
 
 	info->res = request_mem_region(dev->resource->start,
 	info->res = request_mem_region(dev->resource->start,
 			resource_size(dev->resource),
 			resource_size(dev->resource),
@@ -248,11 +250,28 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 	info->mtd->owner = THIS_MODULE;
 	info->mtd->owner = THIS_MODULE;
 
 
 	/* Use the fast version */
 	/* Use the fast version */
-	info->map.write = ixp4xx_write16,
+	info->map.write = ixp4xx_write16;
+
+#ifdef CONFIG_MTD_PARTITIONS
+	nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions,
+					dev->resource->start);
+#endif
+	if (nr_parts > 0) {
+		part_type = "dynamic";
+	} else {
+		info->partitions = plat->parts;
+		nr_parts = plat->nr_parts;
+		part_type = "static";
+	}
+	if (nr_parts == 0) {
+		printk(KERN_NOTICE "IXP4xx flash: no partition info "
+			"available, registering whole flash\n");
+		err = add_mtd_device(info->mtd);
+	} else {
+		printk(KERN_NOTICE "IXP4xx flash: using %s partition "
+			"definition\n", part_type);
+		err = add_mtd_partitions(info->mtd, info->partitions, nr_parts);
 
 
-	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start);
-	if (err > 0) {
-		err = add_mtd_partitions(info->mtd, info->partitions, err);
 		if(err)
 		if(err)
 			printk(KERN_ERR "Could not parse partitions\n");
 			printk(KERN_ERR "Could not parse partitions\n");
 	}
 	}

+ 9 - 5
drivers/mtd/maps/physmap.c

@@ -106,12 +106,12 @@ static int physmap_flash_probe(struct platform_device *dev)
 
 
 	for (i = 0; i < dev->num_resources; i++) {
 	for (i = 0; i < dev->num_resources; i++) {
 		printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
 		printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
-		       (unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1),
+		       (unsigned long long)resource_size(&dev->resource[i]),
 		       (unsigned long long)dev->resource[i].start);
 		       (unsigned long long)dev->resource[i].start);
 
 
 		if (!devm_request_mem_region(&dev->dev,
 		if (!devm_request_mem_region(&dev->dev,
 			dev->resource[i].start,
 			dev->resource[i].start,
-			dev->resource[i].end - dev->resource[i].start + 1,
+			resource_size(&dev->resource[i]),
 			dev_name(&dev->dev))) {
 			dev_name(&dev->dev))) {
 			dev_err(&dev->dev, "Could not reserve memory region\n");
 			dev_err(&dev->dev, "Could not reserve memory region\n");
 			err = -ENOMEM;
 			err = -ENOMEM;
@@ -120,7 +120,7 @@ static int physmap_flash_probe(struct platform_device *dev)
 
 
 		info->map[i].name = dev_name(&dev->dev);
 		info->map[i].name = dev_name(&dev->dev);
 		info->map[i].phys = dev->resource[i].start;
 		info->map[i].phys = dev->resource[i].start;
-		info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1;
+		info->map[i].size = resource_size(&dev->resource[i]);
 		info->map[i].bankwidth = physmap_data->width;
 		info->map[i].bankwidth = physmap_data->width;
 		info->map[i].set_vpp = physmap_data->set_vpp;
 		info->map[i].set_vpp = physmap_data->set_vpp;
 		info->map[i].pfow_base = physmap_data->pfow_base;
 		info->map[i].pfow_base = physmap_data->pfow_base;
@@ -136,8 +136,12 @@ static int physmap_flash_probe(struct platform_device *dev)
 		simple_map_init(&info->map[i]);
 		simple_map_init(&info->map[i]);
 
 
 		probe_type = rom_probe_types;
 		probe_type = rom_probe_types;
-		for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++)
-			info->mtd[i] = do_map_probe(*probe_type, &info->map[i]);
+		if (physmap_data->probe_type == NULL) {
+			for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++)
+				info->mtd[i] = do_map_probe(*probe_type, &info->map[i]);
+		} else
+			info->mtd[i] = do_map_probe(physmap_data->probe_type, &info->map[i]);
+
 		if (info->mtd[i] == NULL) {
 		if (info->mtd[i] == NULL) {
 			dev_err(&dev->dev, "map_probe failed\n");
 			dev_err(&dev->dev, "map_probe failed\n");
 			err = -ENXIO;
 			err = -ENXIO;

+ 3 - 3
drivers/mtd/maps/physmap_of.c

@@ -353,7 +353,7 @@ static int __devinit of_flash_probe(struct of_device *dev,
 				   &info->parts, 0);
 				   &info->parts, 0);
 	if (err < 0) {
 	if (err < 0) {
 		of_free_probes(part_probe_types);
 		of_free_probes(part_probe_types);
-		return err;
+		goto err_out;
 	}
 	}
 	of_free_probes(part_probe_types);
 	of_free_probes(part_probe_types);
 
 
@@ -361,14 +361,14 @@ static int __devinit of_flash_probe(struct of_device *dev,
 	if (err == 0) {
 	if (err == 0) {
 		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
 		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
 		if (err < 0)
 		if (err < 0)
-			return err;
+			goto err_out;
 	}
 	}
 #endif
 #endif
 
 
 	if (err == 0) {
 	if (err == 0) {
 		err = parse_obsolete_partitions(dev, info, dp);
 		err = parse_obsolete_partitions(dev, info, dp);
 		if (err < 0)
 		if (err < 0)
-			return err;
+			goto err_out;
 	}
 	}
 
 
 	if (err > 0)
 	if (err > 0)

+ 0 - 131
drivers/mtd/maps/redwood.c

@@ -1,131 +0,0 @@
-/*
- * drivers/mtd/maps/redwood.c
- *
- * FLASH map for the IBM Redwood 4/5/6 boards.
- *
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- * 2001-2003 (c) MontaVista, Software, Inc. 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.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-
-#define WINDOW_ADDR 0xffc00000
-#define WINDOW_SIZE 0x00400000
-
-#define RW_PART0_OF	0
-#define RW_PART0_SZ	0x10000
-#define RW_PART1_OF	RW_PART0_SZ
-#define RW_PART1_SZ	0x200000 - 0x10000
-#define RW_PART2_OF	0x200000
-#define RW_PART2_SZ	0x10000
-#define RW_PART3_OF	0x210000
-#define RW_PART3_SZ	0x200000 - (0x10000 + 0x20000)
-#define RW_PART4_OF	0x3e0000
-#define RW_PART4_SZ	0x20000
-
-static struct mtd_partition redwood_flash_partitions[] = {
-	{
-		.name = "Redwood OpenBIOS Vital Product Data",
-		.offset = RW_PART0_OF,
-		.size = RW_PART0_SZ,
-		.mask_flags = MTD_WRITEABLE	/* force read-only */
-	},
-	{
-		.name = "Redwood kernel",
-		.offset = RW_PART1_OF,
-		.size = RW_PART1_SZ
-	},
-	{
-		.name = "Redwood OpenBIOS non-volatile storage",
-		.offset = RW_PART2_OF,
-		.size = RW_PART2_SZ,
-		.mask_flags = MTD_WRITEABLE	/* force read-only */
-	},
-	{
-		.name = "Redwood filesystem",
-		.offset = RW_PART3_OF,
-		.size = RW_PART3_SZ
-	},
-	{
-		.name = "Redwood OpenBIOS",
-		.offset = RW_PART4_OF,
-		.size = RW_PART4_SZ,
-		.mask_flags = MTD_WRITEABLE	/* force read-only */
-	}
-};
-
-struct map_info redwood_flash_map = {
-	.name = "IBM Redwood",
-	.size = WINDOW_SIZE,
-	.bankwidth = 2,
-	.phys = WINDOW_ADDR,
-};
-
-
-#define NUM_REDWOOD_FLASH_PARTITIONS ARRAY_SIZE(redwood_flash_partitions)
-
-static struct mtd_info *redwood_mtd;
-
-static int __init init_redwood_flash(void)
-{
-	int err;
-
-	printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n",
-			WINDOW_SIZE, WINDOW_ADDR);
-
-	redwood_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
-
-	if (!redwood_flash_map.virt) {
-		printk("init_redwood_flash: failed to ioremap\n");
-		return -EIO;
-	}
-	simple_map_init(&redwood_flash_map);
-
-	redwood_mtd = do_map_probe("cfi_probe",&redwood_flash_map);
-
-	if (redwood_mtd) {
-		redwood_mtd->owner = THIS_MODULE;
-		err = add_mtd_partitions(redwood_mtd,
-				redwood_flash_partitions,
-				NUM_REDWOOD_FLASH_PARTITIONS);
-		if (err) {
-			printk("init_redwood_flash: add_mtd_partitions failed\n");
-			iounmap(redwood_flash_map.virt);
-		}
-		return err;
-
-	}
-
-	iounmap(redwood_flash_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_redwood_flash(void)
-{
-	if (redwood_mtd) {
-		del_mtd_partitions(redwood_mtd);
-		/* moved iounmap after map_destroy - armin */
-		map_destroy(redwood_mtd);
-		iounmap((void *)redwood_flash_map.virt);
-	}
-}
-
-module_init(init_redwood_flash);
-module_exit(cleanup_redwood_flash);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("MontaVista Software <source@mvista.com>");
-MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards");

+ 21 - 5
drivers/mtd/mtd_blkdevs.c

@@ -1,7 +1,21 @@
 /*
 /*
- * (C) 2003 David Woodhouse <dwmw2@infradead.org>
+ * Interface to Linux block layer for MTD 'translation layers'.
  *
  *
- * Interface to Linux 2.5 block layer for MTD 'translation layers'.
+ * Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
  */
  */
 
 
@@ -245,6 +259,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
 	switch (cmd) {
 	switch (cmd) {
 	case BLKFLSBUF:
 	case BLKFLSBUF:
 		ret = dev->tr->flush ? dev->tr->flush(dev) : 0;
 		ret = dev->tr->flush ? dev->tr->flush(dev) : 0;
+		break;
 	default:
 	default:
 		ret = -ENOTTY;
 		ret = -ENOTTY;
 	}
 	}
@@ -409,13 +424,14 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
 		BUG();
 		BUG();
 	}
 	}
 
 
-	/* Stop new requests to arrive */
-	del_gendisk(old->disk);
-
 	if (old->disk_attributes)
 	if (old->disk_attributes)
 		sysfs_remove_group(&disk_to_dev(old->disk)->kobj,
 		sysfs_remove_group(&disk_to_dev(old->disk)->kobj,
 						old->disk_attributes);
 						old->disk_attributes);
 
 
+	/* Stop new requests to arrive */
+	del_gendisk(old->disk);
+
+
 	/* Stop the thread */
 	/* Stop the thread */
 	kthread_stop(old->thread);
 	kthread_stop(old->thread);
 
 

+ 17 - 2
drivers/mtd/mtdblock.c

@@ -1,8 +1,23 @@
 /*
 /*
  * Direct MTD block device access
  * Direct MTD block device access
  *
  *
- * (C) 2000-2003 Nicolas Pitre <nico@fluxnic.net>
- * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
+ * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
+ * Copyright © 2000-2003 Nicolas Pitre <nico@fluxnic.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
  */
 
 
 #include <linux/fs.h>
 #include <linux/fs.h>

+ 17 - 2
drivers/mtd/mtdblock_ro.c

@@ -1,7 +1,22 @@
 /*
 /*
- * (C) 2003 David Woodhouse <dwmw2@infradead.org>
- *
  * Simple read-only (writable only for RAM) mtdblock driver
  * Simple read-only (writable only for RAM) mtdblock driver
+ *
+ * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
  */
 
 
 #include <linux/init.h>
 #include <linux/init.h>

+ 56 - 3
drivers/mtd/mtdchar.c

@@ -1,5 +1,19 @@
 /*
 /*
- * Character-device access to raw MTD devices.
+ * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
  */
  */
 
 
@@ -18,7 +32,7 @@
 #include <linux/mount.h>
 #include <linux/mount.h>
 
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/compatmac.h>
+#include <linux/mtd/map.h>
 
 
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 
 
@@ -675,6 +689,20 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 		break;
 		break;
 	}
 	}
 
 
+	case MEMISLOCKED:
+	{
+		struct erase_info_user einfo;
+
+		if (copy_from_user(&einfo, argp, sizeof(einfo)))
+			return -EFAULT;
+
+		if (!mtd->is_locked)
+			ret = -EOPNOTSUPP;
+		else
+			ret = mtd->is_locked(mtd, einfo.start, einfo.length);
+		break;
+	}
+
 	/* Legacy interface */
 	/* Legacy interface */
 	case MEMGETOOBSEL:
 	case MEMGETOOBSEL:
 	{
 	{
@@ -950,9 +978,34 @@ static int mtd_mmap(struct file *file, struct vm_area_struct *vma)
 #ifdef CONFIG_MMU
 #ifdef CONFIG_MMU
 	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_info *mtd = mfi->mtd;
 	struct mtd_info *mtd = mfi->mtd;
+	struct map_info *map = mtd->priv;
+	unsigned long start;
+	unsigned long off;
+	u32 len;
+
+	if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) {
+		off = vma->vm_pgoff << PAGE_SHIFT;
+		start = map->phys;
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
+		start &= PAGE_MASK;
+		if ((vma->vm_end - vma->vm_start + off) > len)
+			return -EINVAL;
+
+		off += start;
+		vma->vm_pgoff = off >> PAGE_SHIFT;
+		vma->vm_flags |= VM_IO | VM_RESERVED;
+
+#ifdef pgprot_noncached
+		if (file->f_flags & O_DSYNC || off >= __pa(high_memory))
+			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
+		if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+				       vma->vm_end - vma->vm_start,
+				       vma->vm_page_prot))
+			return -EAGAIN;
 
 
-	if (mtd->type == MTD_RAM || mtd->type == MTD_ROM)
 		return 0;
 		return 0;
+	}
 	return -ENOSYS;
 	return -ENOSYS;
 #else
 #else
 	return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS;
 	return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS;

+ 28 - 10
drivers/mtd/mtdconcat.c

@@ -1,11 +1,25 @@
 /*
 /*
  * MTD device concatenation layer
  * MTD device concatenation layer
  *
  *
- * (C) 2002 Robert Kaiser <rkaiser@sysgo.de>
+ * Copyright © 2002 Robert Kaiser <rkaiser@sysgo.de>
+ * Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * NAND support by Christian Gan <cgan@iders.ca>
  * NAND support by Christian Gan <cgan@iders.ca>
  *
  *
- * This code is GPL
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
  */
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
@@ -540,10 +554,12 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		else
 		else
 			size = len;
 			size = len;
 
 
-		err = subdev->lock(subdev, ofs, size);
-
-		if (err)
-			break;
+		if (subdev->lock) {
+			err = subdev->lock(subdev, ofs, size);
+			if (err)
+				break;
+		} else
+			err = -EOPNOTSUPP;
 
 
 		len -= size;
 		len -= size;
 		if (len == 0)
 		if (len == 0)
@@ -578,10 +594,12 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		else
 		else
 			size = len;
 			size = len;
 
 
-		err = subdev->unlock(subdev, ofs, size);
-
-		if (err)
-			break;
+		if (subdev->unlock) {
+			err = subdev->unlock(subdev, ofs, size);
+			if (err)
+				break;
+		} else
+			err = -EOPNOTSUPP;
 
 
 		len -= size;
 		len -= size;
 		if (len == 0)
 		if (len == 0)

+ 17 - 4
drivers/mtd/mtdcore.c

@@ -2,9 +2,23 @@
  * Core registration and callback routines for MTD
  * Core registration and callback routines for MTD
  * drivers and users.
  * drivers and users.
  *
  *
- * bdi bits are:
- * Copyright © 2006 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
+ * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
+ * Copyright © 2006      Red Hat UK Limited 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
  */
 
 
 #include <linux/module.h>
 #include <linux/module.h>
@@ -17,7 +31,6 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/ioctl.h>
 #include <linux/ioctl.h>
 #include <linux/init.h>
 #include <linux/init.h>
-#include <linux/mtd/compatmac.h>
 #include <linux/proc_fs.h>
 #include <linux/proc_fs.h>
 #include <linux/idr.h>
 #include <linux/idr.h>
 #include <linux/backing-dev.h>
 #include <linux/backing-dev.h>

+ 1 - 1
drivers/mtd/mtdoops.c

@@ -1,7 +1,7 @@
 /*
 /*
  * MTD Oops/Panic logger
  * MTD Oops/Panic logger
  *
  *
- * Copyright (C) 2007 Nokia Corporation. All rights reserved.
+ * Copyright © 2007 Nokia Corporation. All rights reserved.
  *
  *
  * Author: Richard Purdie <rpurdie@openedhand.com>
  * Author: Richard Purdie <rpurdie@openedhand.com>
  *
  *

+ 26 - 5
drivers/mtd/mtdpart.c

@@ -1,12 +1,24 @@
 /*
 /*
  * Simple MTD partitioning layer
  * Simple MTD partitioning layer
  *
  *
- * (C) 2000 Nicolas Pitre <nico@fluxnic.net>
+ * Copyright © 2000 Nicolas Pitre <nico@fluxnic.net>
+ * Copyright © 2002 Thomas Gleixner <gleixner@linutronix.de>
+ * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
- * This code is GPL
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
- * 	02-21-2002	Thomas Gleixner <gleixner@autronix.de>
- *			added support for read_oob, write_oob
  */
  */
 
 
 #include <linux/module.h>
 #include <linux/module.h>
@@ -17,7 +29,6 @@
 #include <linux/kmod.h>
 #include <linux/kmod.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/partitions.h>
-#include <linux/mtd/compatmac.h>
 
 
 /* Our partition linked list */
 /* Our partition linked list */
 static LIST_HEAD(mtd_partitions);
 static LIST_HEAD(mtd_partitions);
@@ -264,6 +275,14 @@ static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	return part->master->unlock(part->master, ofs + part->offset, len);
 	return part->master->unlock(part->master, ofs + part->offset, len);
 }
 }
 
 
+static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+	struct mtd_part *part = PART(mtd);
+	if ((len + ofs) > mtd->size)
+		return -EINVAL;
+	return part->master->is_locked(part->master, ofs + part->offset, len);
+}
+
 static void part_sync(struct mtd_info *mtd)
 static void part_sync(struct mtd_info *mtd)
 {
 {
 	struct mtd_part *part = PART(mtd);
 	struct mtd_part *part = PART(mtd);
@@ -402,6 +421,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 		slave->mtd.lock = part_lock;
 		slave->mtd.lock = part_lock;
 	if (master->unlock)
 	if (master->unlock)
 		slave->mtd.unlock = part_unlock;
 		slave->mtd.unlock = part_unlock;
+	if (master->is_locked)
+		slave->mtd.is_locked = part_is_locked;
 	if (master->block_isbad)
 	if (master->block_isbad)
 		slave->mtd.block_isbad = part_block_isbad;
 		slave->mtd.block_isbad = part_block_isbad;
 	if (master->block_markbad)
 	if (master->block_markbad)

+ 2 - 0
drivers/mtd/mtdsuper.c

@@ -1,6 +1,8 @@
 /* MTD-based superblock management
 /* MTD-based superblock management
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved.
  * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved.
+ * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
+ *
  * Written by:  David Howells <dhowells@redhat.com>
  * Written by:  David Howells <dhowells@redhat.com>
  *              David Woodhouse <dwmw2@infradead.org>
  *              David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 16 - 17
drivers/mtd/nand/Kconfig

@@ -37,7 +37,6 @@ config MTD_SM_COMMON
 
 
 config MTD_NAND_MUSEUM_IDS
 config MTD_NAND_MUSEUM_IDS
 	bool "Enable chip ids for obsolete ancient NAND devices"
 	bool "Enable chip ids for obsolete ancient NAND devices"
-	depends on MTD_NAND
 	default n
 	default n
 	help
 	help
 	  Enable this option only when your board has first generation
 	  Enable this option only when your board has first generation
@@ -61,6 +60,7 @@ config MTD_NAND_DENALI
 config MTD_NAND_DENALI_SCRATCH_REG_ADDR
 config MTD_NAND_DENALI_SCRATCH_REG_ADDR
         hex "Denali NAND size scratch register address"
         hex "Denali NAND size scratch register address"
         default "0xFF108018"
         default "0xFF108018"
+        depends on MTD_NAND_DENALI
         help
         help
           Some platforms place the NAND chip size in a scratch register
           Some platforms place the NAND chip size in a scratch register
           because (some versions of) the driver aren't able to automatically
           because (some versions of) the driver aren't able to automatically
@@ -101,13 +101,13 @@ config MTD_NAND_AMS_DELTA
 
 
 config MTD_NAND_OMAP2
 config MTD_NAND_OMAP2
 	tristate "NAND Flash device on OMAP2 and OMAP3"
 	tristate "NAND Flash device on OMAP2 and OMAP3"
-	depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3)
+	depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3)
 	help
 	help
           Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
           Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
 
 
 config MTD_NAND_OMAP_PREFETCH
 config MTD_NAND_OMAP_PREFETCH
 	bool "GPMC prefetch support for NAND Flash device"
 	bool "GPMC prefetch support for NAND Flash device"
-	depends on MTD_NAND && MTD_NAND_OMAP2
+	depends on MTD_NAND_OMAP2
 	default y
 	default y
 	help
 	help
 	 The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
 	 The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
@@ -146,7 +146,7 @@ config MTD_NAND_AU1550
 
 
 config MTD_NAND_BF5XX
 config MTD_NAND_BF5XX
 	tristate "Blackfin on-chip NAND Flash Controller driver"
 	tristate "Blackfin on-chip NAND Flash Controller driver"
-	depends on (BF54x || BF52x) && MTD_NAND
+	depends on BF54x || BF52x
 	help
 	help
 	  This enables the Blackfin on-chip NAND flash controller
 	  This enables the Blackfin on-chip NAND flash controller
 
 
@@ -236,7 +236,7 @@ config MTD_NAND_S3C2410_CLKSTOP
 
 
 config MTD_NAND_BCM_UMI
 config MTD_NAND_BCM_UMI
 	tristate "NAND Flash support for BCM Reference Boards"
 	tristate "NAND Flash support for BCM Reference Boards"
-	depends on ARCH_BCMRING && MTD_NAND
+	depends on ARCH_BCMRING
 	help
 	help
 	  This enables the NAND flash controller on the BCM UMI block.
 	  This enables the NAND flash controller on the BCM UMI block.
 
 
@@ -395,7 +395,7 @@ endchoice
 
 
 config MTD_NAND_PXA3xx
 config MTD_NAND_PXA3xx
 	tristate "Support for NAND flash devices on PXA3xx"
 	tristate "Support for NAND flash devices on PXA3xx"
-	depends on MTD_NAND && (PXA3xx || ARCH_MMP)
+	depends on PXA3xx || ARCH_MMP
 	help
 	help
 	  This enables the driver for the NAND flash device found on
 	  This enables the driver for the NAND flash device found on
 	  PXA3xx processors
 	  PXA3xx processors
@@ -409,18 +409,18 @@ config MTD_NAND_PXA3xx_BUILTIN
 
 
 config MTD_NAND_CM_X270
 config MTD_NAND_CM_X270
 	tristate "Support for NAND Flash on CM-X270 modules"
 	tristate "Support for NAND Flash on CM-X270 modules"
-	depends on MTD_NAND && MACH_ARMCORE
+	depends on MACH_ARMCORE
 
 
 config MTD_NAND_PASEMI
 config MTD_NAND_PASEMI
 	tristate "NAND support for PA Semi PWRficient"
 	tristate "NAND support for PA Semi PWRficient"
-	depends on MTD_NAND && PPC_PASEMI
+	depends on PPC_PASEMI
 	help
 	help
 	  Enables support for NAND Flash interface on PA Semi PWRficient
 	  Enables support for NAND Flash interface on PA Semi PWRficient
 	  based boards
 	  based boards
 
 
 config MTD_NAND_TMIO
 config MTD_NAND_TMIO
 	tristate "NAND Flash device on Toshiba Mobile IO Controller"
 	tristate "NAND Flash device on Toshiba Mobile IO Controller"
-	depends on MTD_NAND && MFD_TMIO
+	depends on MFD_TMIO
 	help
 	help
 	  Support for NAND flash connected to a Toshiba Mobile IO
 	  Support for NAND flash connected to a Toshiba Mobile IO
 	  Controller in some PDAs, including the Sharp SL6000x.
 	  Controller in some PDAs, including the Sharp SL6000x.
@@ -434,7 +434,6 @@ config MTD_NAND_NANDSIM
 
 
 config MTD_NAND_PLATFORM
 config MTD_NAND_PLATFORM
 	tristate "Support for generic platform NAND driver"
 	tristate "Support for generic platform NAND driver"
-	depends on MTD_NAND
 	help
 	help
 	  This implements a generic NAND driver for on-SOC platform
 	  This implements a generic NAND driver for on-SOC platform
 	  devices. You will need to provide platform-specific functions
 	  devices. You will need to provide platform-specific functions
@@ -442,14 +441,14 @@ config MTD_NAND_PLATFORM
 
 
 config MTD_ALAUDA
 config MTD_ALAUDA
 	tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
 	tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
-	depends on MTD_NAND && USB
+	depends on USB
 	help
 	help
 	  These two (and possibly other) Alauda-based cardreaders for
 	  These two (and possibly other) Alauda-based cardreaders for
 	  SmartMedia and xD allow raw flash access.
 	  SmartMedia and xD allow raw flash access.
 
 
 config MTD_NAND_ORION
 config MTD_NAND_ORION
 	tristate "NAND Flash support for Marvell Orion SoC"
 	tristate "NAND Flash support for Marvell Orion SoC"
-	depends on PLAT_ORION && MTD_NAND
+	depends on PLAT_ORION
 	help
 	help
 	  This enables the NAND flash controller on Orion machines.
 	  This enables the NAND flash controller on Orion machines.
 
 
@@ -458,7 +457,7 @@ config MTD_NAND_ORION
 
 
 config MTD_NAND_FSL_ELBC
 config MTD_NAND_FSL_ELBC
 	tristate "NAND support for Freescale eLBC controllers"
 	tristate "NAND support for Freescale eLBC controllers"
-	depends on MTD_NAND && PPC_OF
+	depends on PPC_OF
 	help
 	help
 	  Various Freescale chips, including the 8313, include a NAND Flash
 	  Various Freescale chips, including the 8313, include a NAND Flash
 	  Controller Module with built-in hardware ECC capabilities.
 	  Controller Module with built-in hardware ECC capabilities.
@@ -467,7 +466,7 @@ config MTD_NAND_FSL_ELBC
 
 
 config MTD_NAND_FSL_UPM
 config MTD_NAND_FSL_UPM
 	tristate "Support for NAND on Freescale UPM"
 	tristate "Support for NAND on Freescale UPM"
-	depends on MTD_NAND && (PPC_83xx || PPC_85xx)
+	depends on PPC_83xx || PPC_85xx
 	select FSL_LBC
 	select FSL_LBC
 	help
 	help
 	  Enables support for NAND Flash chips wired onto Freescale PowerPC
 	  Enables support for NAND Flash chips wired onto Freescale PowerPC
@@ -482,7 +481,7 @@ config MTD_NAND_MPC5121_NFC
 
 
 config MTD_NAND_MXC
 config MTD_NAND_MXC
 	tristate "MXC NAND support"
 	tristate "MXC NAND support"
-	depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3
+	depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX51
 	help
 	help
 	  This enables the driver for the NAND flash controller on the
 	  This enables the driver for the NAND flash controller on the
 	  MXC processors.
 	  MXC processors.
@@ -495,7 +494,7 @@ config MTD_NAND_NOMADIK
 
 
 config MTD_NAND_SH_FLCTL
 config MTD_NAND_SH_FLCTL
 	tristate "Support for NAND on Renesas SuperH FLCTL"
 	tristate "Support for NAND on Renesas SuperH FLCTL"
-	depends on MTD_NAND && (SUPERH || ARCH_SHMOBILE)
+	depends on SUPERH || ARCH_SHMOBILE
 	help
 	help
 	  Several Renesas SuperH CPU has FLCTL. This option enables support
 	  Several Renesas SuperH CPU has FLCTL. This option enables support
 	  for NAND Flash using FLCTL.
 	  for NAND Flash using FLCTL.
@@ -515,7 +514,7 @@ config MTD_NAND_TXX9NDFMC
 
 
 config MTD_NAND_SOCRATES
 config MTD_NAND_SOCRATES
 	tristate "Support for NAND on Socrates board"
 	tristate "Support for NAND on Socrates board"
-	depends on MTD_NAND && SOCRATES
+	depends on SOCRATES
 	help
 	help
 	  Enables support for NAND Flash chips wired onto Socrates board.
 	  Enables support for NAND Flash chips wired onto Socrates board.
 
 

+ 1 - 1
drivers/mtd/nand/atmel_nand.c

@@ -364,7 +364,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
 	}
 	}
 }
 }
 
 
-#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
 static const char *part_probes[] = { "cmdlinepart", NULL };
 static const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
 #endif
 
 

+ 72 - 45
drivers/mtd/nand/bf5xx_nand.c

@@ -20,9 +20,6 @@
  *		- DMA supported in ECC_HW
  *		- DMA supported in ECC_HW
  *		- YAFFS tested as rootfs in both ECC_HW and ECC_SW
  *		- YAFFS tested as rootfs in both ECC_HW and ECC_SW
  *
  *
- * TODO:
- * 	Enable JFFS2 over NAND as rootfs
- *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * the Free Software Foundation; either version 2 of the License, or
@@ -206,7 +203,7 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd,
 
 
 	if (ctrl & NAND_CLE)
 	if (ctrl & NAND_CLE)
 		bfin_write_NFC_CMD(cmd);
 		bfin_write_NFC_CMD(cmd);
-	else
+	else if (ctrl & NAND_ALE)
 		bfin_write_NFC_ADDR(cmd);
 		bfin_write_NFC_ADDR(cmd);
 	SSYNC();
 	SSYNC();
 }
 }
@@ -218,9 +215,9 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd,
  */
  */
 static int bf5xx_nand_devready(struct mtd_info *mtd)
 static int bf5xx_nand_devready(struct mtd_info *mtd)
 {
 {
-	unsigned short val = bfin_read_NFC_IRQSTAT();
+	unsigned short val = bfin_read_NFC_STAT();
 
 
-	if ((val & NBUSYIRQ) == NBUSYIRQ)
+	if ((val & NBUSY) == NBUSY)
 		return 1;
 		return 1;
 	else
 	else
 		return 0;
 		return 0;
@@ -317,18 +314,16 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
 static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 					u_char *read_ecc, u_char *calc_ecc)
 					u_char *read_ecc, u_char *calc_ecc)
 {
 {
-	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-	struct bf5xx_nand_platform *plat = info->platform;
-	unsigned short page_size = (plat->page_size ? 512 : 256);
+	struct nand_chip *chip = mtd->priv;
 	int ret;
 	int ret;
 
 
 	ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
 	ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
 
 
-	/* If page size is 512, correct second 256 bytes */
-	if (page_size == 512) {
+	/* If ecc size is 512, correct second 256 bytes */
+	if (chip->ecc.size == 512) {
 		dat += 256;
 		dat += 256;
-		read_ecc += 8;
-		calc_ecc += 8;
+		read_ecc += 3;
+		calc_ecc += 3;
 		ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
 		ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
 	}
 	}
 
 
@@ -344,13 +339,12 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
 		const u_char *dat, u_char *ecc_code)
 		const u_char *dat, u_char *ecc_code)
 {
 {
 	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
 	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-	struct bf5xx_nand_platform *plat = info->platform;
-	u16 page_size = (plat->page_size ? 512 : 256);
+	struct nand_chip *chip = mtd->priv;
 	u16 ecc0, ecc1;
 	u16 ecc0, ecc1;
 	u32 code[2];
 	u32 code[2];
 	u8 *p;
 	u8 *p;
 
 
-	/* first 4 bytes ECC code for 256 page size */
+	/* first 3 bytes ECC code for 256 page size */
 	ecc0 = bfin_read_NFC_ECC0();
 	ecc0 = bfin_read_NFC_ECC0();
 	ecc1 = bfin_read_NFC_ECC1();
 	ecc1 = bfin_read_NFC_ECC1();
 
 
@@ -358,12 +352,11 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
 
 
 	dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
 	dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
 
 
-	/* first 3 bytes in ecc_code for 256 page size */
 	p = (u8 *) code;
 	p = (u8 *) code;
 	memcpy(ecc_code, p, 3);
 	memcpy(ecc_code, p, 3);
 
 
-	/* second 4 bytes ECC code for 512 page size */
-	if (page_size == 512) {
+	/* second 3 bytes ECC code for 512 ecc size */
+	if (chip->ecc.size == 512) {
 		ecc0 = bfin_read_NFC_ECC2();
 		ecc0 = bfin_read_NFC_ECC2();
 		ecc1 = bfin_read_NFC_ECC3();
 		ecc1 = bfin_read_NFC_ECC3();
 		code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
 		code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
@@ -483,8 +476,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
 				uint8_t *buf, int is_read)
 				uint8_t *buf, int is_read)
 {
 {
 	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
 	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-	struct bf5xx_nand_platform *plat = info->platform;
-	unsigned short page_size = (plat->page_size ? 512 : 256);
+	struct nand_chip *chip = mtd->priv;
 	unsigned short val;
 	unsigned short val;
 
 
 	dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
 	dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
@@ -498,10 +490,10 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
 	 */
 	 */
 	if (is_read)
 	if (is_read)
 		invalidate_dcache_range((unsigned int)buf,
 		invalidate_dcache_range((unsigned int)buf,
-				(unsigned int)(buf + page_size));
+				(unsigned int)(buf + chip->ecc.size));
 	else
 	else
 		flush_dcache_range((unsigned int)buf,
 		flush_dcache_range((unsigned int)buf,
-				(unsigned int)(buf + page_size));
+				(unsigned int)(buf + chip->ecc.size));
 
 
 	/*
 	/*
 	 * This register must be written before each page is
 	 * This register must be written before each page is
@@ -510,6 +502,8 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
 	 */
 	 */
 	bfin_write_NFC_RST(ECC_RST);
 	bfin_write_NFC_RST(ECC_RST);
 	SSYNC();
 	SSYNC();
+	while (bfin_read_NFC_RST() & ECC_RST)
+		cpu_relax();
 
 
 	disable_dma(CH_NFC);
 	disable_dma(CH_NFC);
 	clear_dma_irqstat(CH_NFC);
 	clear_dma_irqstat(CH_NFC);
@@ -520,13 +514,13 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
 
 
 	/* The DMAs have different size on BF52x and BF54x */
 	/* The DMAs have different size on BF52x and BF54x */
 #ifdef CONFIG_BF52x
 #ifdef CONFIG_BF52x
-	set_dma_x_count(CH_NFC, (page_size >> 1));
+	set_dma_x_count(CH_NFC, (chip->ecc.size >> 1));
 	set_dma_x_modify(CH_NFC, 2);
 	set_dma_x_modify(CH_NFC, 2);
 	val = DI_EN | WDSIZE_16;
 	val = DI_EN | WDSIZE_16;
 #endif
 #endif
 
 
 #ifdef CONFIG_BF54x
 #ifdef CONFIG_BF54x
-	set_dma_x_count(CH_NFC, (page_size >> 2));
+	set_dma_x_count(CH_NFC, (chip->ecc.size >> 2));
 	set_dma_x_modify(CH_NFC, 4);
 	set_dma_x_modify(CH_NFC, 4);
 	val = DI_EN | WDSIZE_32;
 	val = DI_EN | WDSIZE_32;
 #endif
 #endif
@@ -548,12 +542,11 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
 					uint8_t *buf, int len)
 					uint8_t *buf, int len)
 {
 {
 	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
 	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-	struct bf5xx_nand_platform *plat = info->platform;
-	unsigned short page_size = (plat->page_size ? 512 : 256);
+	struct nand_chip *chip = mtd->priv;
 
 
 	dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
 	dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
 
 
-	if (len == page_size)
+	if (len == chip->ecc.size)
 		bf5xx_nand_dma_rw(mtd, buf, 1);
 		bf5xx_nand_dma_rw(mtd, buf, 1);
 	else
 	else
 		bf5xx_nand_read_buf(mtd, buf, len);
 		bf5xx_nand_read_buf(mtd, buf, len);
@@ -563,17 +556,32 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
 				const uint8_t *buf, int len)
 				const uint8_t *buf, int len)
 {
 {
 	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
 	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-	struct bf5xx_nand_platform *plat = info->platform;
-	unsigned short page_size = (plat->page_size ? 512 : 256);
+	struct nand_chip *chip = mtd->priv;
 
 
 	dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
 	dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
 
 
-	if (len == page_size)
+	if (len == chip->ecc.size)
 		bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0);
 		bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0);
 	else
 	else
 		bf5xx_nand_write_buf(mtd, buf, len);
 		bf5xx_nand_write_buf(mtd, buf, len);
 }
 }
 
 
+static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+		uint8_t *buf, int page)
+{
+	bf5xx_nand_read_buf(mtd, buf, mtd->writesize);
+	bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	return 0;
+}
+
+static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+		const uint8_t *buf)
+{
+	bf5xx_nand_write_buf(mtd, buf, mtd->writesize);
+	bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
 /*
 /*
  * System initialization functions
  * System initialization functions
  */
  */
@@ -627,15 +635,14 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
 
 
 	/* setup NFC_CTL register */
 	/* setup NFC_CTL register */
 	dev_info(info->device,
 	dev_info(info->device,
-		"page_size=%d, data_width=%d, wr_dly=%d, rd_dly=%d\n",
-		(plat->page_size ? 512 : 256),
+		"data_width=%d, wr_dly=%d, rd_dly=%d\n",
 		(plat->data_width ? 16 : 8),
 		(plat->data_width ? 16 : 8),
 		plat->wr_dly, plat->rd_dly);
 		plat->wr_dly, plat->rd_dly);
 
 
-	val = (plat->page_size << NFC_PG_SIZE_OFFSET) |
+	val = (1 << NFC_PG_SIZE_OFFSET) |
 		(plat->data_width << NFC_NWIDTH_OFFSET) |
 		(plat->data_width << NFC_NWIDTH_OFFSET) |
 		(plat->rd_dly << NFC_RDDLY_OFFSET) |
 		(plat->rd_dly << NFC_RDDLY_OFFSET) |
-		(plat->rd_dly << NFC_WRDLY_OFFSET);
+		(plat->wr_dly << NFC_WRDLY_OFFSET);
 	dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val);
 	dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val);
 
 
 	bfin_write_NFC_CTL(val);
 	bfin_write_NFC_CTL(val);
@@ -698,6 +705,33 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
+static int bf5xx_nand_scan(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	int ret;
+
+	ret = nand_scan_ident(mtd, 1);
+	if (ret)
+		return ret;
+
+	if (hardware_ecc) {
+		/*
+		 * for nand with page size > 512B, think it as several sections with 512B
+		 */
+		if (likely(mtd->writesize >= 512)) {
+			chip->ecc.size = 512;
+			chip->ecc.bytes = 6;
+		} else {
+			chip->ecc.size = 256;
+			chip->ecc.bytes = 3;
+			bfin_write_NFC_CTL(bfin_read_NFC_CTL() & ~(1 << NFC_PG_SIZE_OFFSET));
+			SSYNC();
+		}
+	}
+
+	return	nand_scan_tail(mtd);
+}
+
 /*
 /*
  * bf5xx_nand_probe
  * bf5xx_nand_probe
  *
  *
@@ -783,27 +817,20 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
 		chip->badblock_pattern = &bootrom_bbt;
 		chip->badblock_pattern = &bootrom_bbt;
 		chip->ecc.layout = &bootrom_ecclayout;
 		chip->ecc.layout = &bootrom_ecclayout;
 #endif
 #endif
-
-		if (plat->page_size == NFC_PG_SIZE_256) {
-			chip->ecc.bytes = 3;
-			chip->ecc.size = 256;
-		} else if (plat->page_size == NFC_PG_SIZE_512) {
-			chip->ecc.bytes = 6;
-			chip->ecc.size = 512;
-		}
-
 		chip->read_buf      = bf5xx_nand_dma_read_buf;
 		chip->read_buf      = bf5xx_nand_dma_read_buf;
 		chip->write_buf     = bf5xx_nand_dma_write_buf;
 		chip->write_buf     = bf5xx_nand_dma_write_buf;
 		chip->ecc.calculate = bf5xx_nand_calculate_ecc;
 		chip->ecc.calculate = bf5xx_nand_calculate_ecc;
 		chip->ecc.correct   = bf5xx_nand_correct_data;
 		chip->ecc.correct   = bf5xx_nand_correct_data;
 		chip->ecc.mode	    = NAND_ECC_HW;
 		chip->ecc.mode	    = NAND_ECC_HW;
 		chip->ecc.hwctl	    = bf5xx_nand_enable_hwecc;
 		chip->ecc.hwctl	    = bf5xx_nand_enable_hwecc;
+		chip->ecc.read_page_raw = bf5xx_nand_read_page_raw;
+		chip->ecc.write_page_raw = bf5xx_nand_write_page_raw;
 	} else {
 	} else {
 		chip->ecc.mode	    = NAND_ECC_SOFT;
 		chip->ecc.mode	    = NAND_ECC_SOFT;
 	}
 	}
 
 
 	/* scan hardware nand chip and setup mtd info data struct */
 	/* scan hardware nand chip and setup mtd info data struct */
-	if (nand_scan(mtd, 1)) {
+	if (bf5xx_nand_scan(mtd)) {
 		err = -ENXIO;
 		err = -ENXIO;
 		goto out_err_nand_scan;
 		goto out_err_nand_scan;
 	}
 	}

+ 17 - 0
drivers/mtd/nand/davinci_nand.c

@@ -311,7 +311,9 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
 	unsigned short ecc10[8];
 	unsigned short ecc10[8];
 	unsigned short *ecc16;
 	unsigned short *ecc16;
 	u32 syndrome[4];
 	u32 syndrome[4];
+	u32 ecc_state;
 	unsigned num_errors, corrected;
 	unsigned num_errors, corrected;
+	unsigned long timeo = jiffies + msecs_to_jiffies(100);
 
 
 	/* All bytes 0xff?  It's an erased page; ignore its ECC. */
 	/* All bytes 0xff?  It's an erased page; ignore its ECC. */
 	for (i = 0; i < 10; i++) {
 	for (i = 0; i < 10; i++) {
@@ -361,6 +363,21 @@ compare:
 	 */
 	 */
 	davinci_nand_writel(info, NANDFCR_OFFSET,
 	davinci_nand_writel(info, NANDFCR_OFFSET,
 			davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13));
 			davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13));
+
+	/*
+	 * ECC_STATE field reads 0x3 (Error correction complete) immediately
+	 * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately
+	 * begin trying to poll for the state, you may fall right out of your
+	 * loop without any of the correction calculations having taken place.
+	 * The recommendation from the hardware team is to wait till ECC_STATE
+	 * reads less than 4, which means ECC HW has entered correction state.
+	 */
+	do {
+		ecc_state = (davinci_nand_readl(info,
+				NANDFSR_OFFSET) >> 8) & 0x0f;
+		cpu_relax();
+	} while ((ecc_state < 4) && time_before(jiffies, timeo));
+
 	for (;;) {
 	for (;;) {
 		u32	fsr = davinci_nand_readl(info, NANDFSR_OFFSET);
 		u32	fsr = davinci_nand_readl(info, NANDFSR_OFFSET);
 
 

+ 475 - 765
drivers/mtd/nand/denali.c

@@ -21,6 +21,7 @@
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
 #include <linux/module.h>
@@ -29,15 +30,15 @@
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 
-/* We define a module parameter that allows the user to override 
+/* We define a module parameter that allows the user to override
  * the hardware and decide what timing mode should be used.
  * the hardware and decide what timing mode should be used.
  */
  */
 #define NAND_DEFAULT_TIMINGS	-1
 #define NAND_DEFAULT_TIMINGS	-1
 
 
 static int onfi_timing_mode = NAND_DEFAULT_TIMINGS;
 static int onfi_timing_mode = NAND_DEFAULT_TIMINGS;
 module_param(onfi_timing_mode, int, S_IRUGO);
 module_param(onfi_timing_mode, int, S_IRUGO);
-MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 indicates"
-					" use default timings");
+MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
+			" -1 indicates use default timings");
 
 
 #define DENALI_NAND_NAME    "denali-nand"
 #define DENALI_NAND_NAME    "denali-nand"
 
 
@@ -54,13 +55,13 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 indicates
 			INTR_STATUS0__RST_COMP | \
 			INTR_STATUS0__RST_COMP | \
 			INTR_STATUS0__ERASE_COMP)
 			INTR_STATUS0__ERASE_COMP)
 
 
-/* indicates whether or not the internal value for the flash bank is 
+/* indicates whether or not the internal value for the flash bank is
    valid or not */
    valid or not */
-#define CHIP_SELECT_INVALID 	-1
+#define CHIP_SELECT_INVALID	-1
 
 
 #define SUPPORT_8BITECC		1
 #define SUPPORT_8BITECC		1
 
 
-/* This macro divides two integers and rounds fractional values up 
+/* This macro divides two integers and rounds fractional values up
  * to the nearest integer value. */
  * to the nearest integer value. */
 #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y)))
 #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y)))
 
 
@@ -83,7 +84,7 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 indicates
 #define ADDR_CYCLE	1
 #define ADDR_CYCLE	1
 #define STATUS_CYCLE	2
 #define STATUS_CYCLE	2
 
 
-/* this is a helper macro that allows us to 
+/* this is a helper macro that allows us to
  * format the bank into the proper bits for the controller */
  * format the bank into the proper bits for the controller */
 #define BANK(x) ((x) << 24)
 #define BANK(x) ((x) << 24)
 
 
@@ -95,59 +96,64 @@ static const struct pci_device_id denali_pci_ids[] = {
 };
 };
 
 
 
 
-/* these are static lookup tables that give us easy access to 
-   registers in the NAND controller.  
+/* these are static lookup tables that give us easy access to
+   registers in the NAND controller.
  */
  */
-static const uint32_t intr_status_addresses[4] = {INTR_STATUS0, 
-						  INTR_STATUS1, 
-					     	  INTR_STATUS2, 
+static const uint32_t intr_status_addresses[4] = {INTR_STATUS0,
+						  INTR_STATUS1,
+						  INTR_STATUS2,
 						  INTR_STATUS3};
 						  INTR_STATUS3};
 
 
 static const uint32_t device_reset_banks[4] = {DEVICE_RESET__BANK0,
 static const uint32_t device_reset_banks[4] = {DEVICE_RESET__BANK0,
-                                               DEVICE_RESET__BANK1,
-                                               DEVICE_RESET__BANK2,
-                                               DEVICE_RESET__BANK3};
+							DEVICE_RESET__BANK1,
+							DEVICE_RESET__BANK2,
+							DEVICE_RESET__BANK3};
 
 
 static const uint32_t operation_timeout[4] = {INTR_STATUS0__TIME_OUT,
 static const uint32_t operation_timeout[4] = {INTR_STATUS0__TIME_OUT,
-                        		      INTR_STATUS1__TIME_OUT,
-		                              INTR_STATUS2__TIME_OUT,
-		                              INTR_STATUS3__TIME_OUT};
+							INTR_STATUS1__TIME_OUT,
+							INTR_STATUS2__TIME_OUT,
+							INTR_STATUS3__TIME_OUT};
 
 
 static const uint32_t reset_complete[4] = {INTR_STATUS0__RST_COMP,
 static const uint32_t reset_complete[4] = {INTR_STATUS0__RST_COMP,
-                		           INTR_STATUS1__RST_COMP,
-		                           INTR_STATUS2__RST_COMP,
-		                           INTR_STATUS3__RST_COMP};
+							INTR_STATUS1__RST_COMP,
+							INTR_STATUS2__RST_COMP,
+							INTR_STATUS3__RST_COMP};
 
 
 /* specifies the debug level of the driver */
 /* specifies the debug level of the driver */
-static int nand_debug_level = 0;
+static int nand_debug_level;
 
 
 /* forward declarations */
 /* forward declarations */
 static void clear_interrupts(struct denali_nand_info *denali);
 static void clear_interrupts(struct denali_nand_info *denali);
-static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask);
-static void denali_irq_enable(struct denali_nand_info *denali, uint32_t int_mask);
+static uint32_t wait_for_irq(struct denali_nand_info *denali,
+							uint32_t irq_mask);
+static void denali_irq_enable(struct denali_nand_info *denali,
+							uint32_t int_mask);
 static uint32_t read_interrupt_status(struct denali_nand_info *denali);
 static uint32_t read_interrupt_status(struct denali_nand_info *denali);
 
 
 #define DEBUG_DENALI 0
 #define DEBUG_DENALI 0
 
 
 /* This is a wrapper for writing to the denali registers.
 /* This is a wrapper for writing to the denali registers.
  * this allows us to create debug information so we can
  * this allows us to create debug information so we can
- * observe how the driver is programming the device. 
+ * observe how the driver is programming the device.
  * it uses standard linux convention for (val, addr) */
  * it uses standard linux convention for (val, addr) */
 static void denali_write32(uint32_t value, void *addr)
 static void denali_write32(uint32_t value, void *addr)
 {
 {
-	iowrite32(value, addr);	
+	iowrite32(value, addr);
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-	printk(KERN_ERR "wrote: 0x%x -> 0x%x\n", value, (uint32_t)((uint32_t)addr & 0x1fff));
+	printk(KERN_INFO "wrote: 0x%x -> 0x%x\n", value,
+			(uint32_t)((uint32_t)addr & 0x1fff));
 #endif
 #endif
-} 
+}
 
 
-/* Certain operations for the denali NAND controller use an indexed mode to read/write 
-   data. The operation is performed by writing the address value of the command to 
-   the device memory followed by the data. This function abstracts this common 
-   operation. 
+/* Certain operations for the denali NAND controller use
+ * an indexed mode to read/write data. The operation is
+ * performed by writing the address value of the command
+ * to the device memory followed by the data. This function
+ * abstracts this common operation.
 */
 */
-static void index_addr(struct denali_nand_info *denali, uint32_t address, uint32_t data)
+static void index_addr(struct denali_nand_info *denali,
+				uint32_t address, uint32_t data)
 {
 {
 	denali_write32(address, denali->flash_mem);
 	denali_write32(address, denali->flash_mem);
 	denali_write32(data, denali->flash_mem + 0x10);
 	denali_write32(data, denali->flash_mem + 0x10);
@@ -161,7 +167,7 @@ static void index_addr_read_data(struct denali_nand_info *denali,
 	*pdata = ioread32(denali->flash_mem + 0x10);
 	*pdata = ioread32(denali->flash_mem + 0x10);
 }
 }
 
 
-/* We need to buffer some data for some of the NAND core routines. 
+/* We need to buffer some data for some of the NAND core routines.
  * The operations manage buffering that data. */
  * The operations manage buffering that data. */
 static void reset_buf(struct denali_nand_info *denali)
 static void reset_buf(struct denali_nand_info *denali)
 {
 {
@@ -183,7 +189,7 @@ static void read_status(struct denali_nand_info *denali)
 	reset_buf(denali);
 	reset_buf(denali);
 
 
 	/* initiate a device status read */
 	/* initiate a device status read */
-	cmd = MODE_11 | BANK(denali->flash_bank); 
+	cmd = MODE_11 | BANK(denali->flash_bank);
 	index_addr(denali, cmd | COMMAND_CYCLE, 0x70);
 	index_addr(denali, cmd | COMMAND_CYCLE, 0x70);
 	denali_write32(cmd | STATUS_CYCLE, denali->flash_mem);
 	denali_write32(cmd | STATUS_CYCLE, denali->flash_mem);
 
 
@@ -191,7 +197,8 @@ static void read_status(struct denali_nand_info *denali)
 	write_byte_to_buf(denali, ioread32(denali->flash_mem + 0x10));
 	write_byte_to_buf(denali, ioread32(denali->flash_mem + 0x10));
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-	printk("device reporting status value of 0x%2x\n", denali->buf.buf[0]);
+	printk(KERN_INFO "device reporting status value of 0x%2x\n",
+			denali->buf.buf[0]);
 #endif
 #endif
 }
 }
 
 
@@ -199,7 +206,7 @@ static void read_status(struct denali_nand_info *denali)
 static void reset_bank(struct denali_nand_info *denali)
 static void reset_bank(struct denali_nand_info *denali)
 {
 {
 	uint32_t irq_status = 0;
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = reset_complete[denali->flash_bank] | 
+	uint32_t irq_mask = reset_complete[denali->flash_bank] |
 			    operation_timeout[denali->flash_bank];
 			    operation_timeout[denali->flash_bank];
 	int bank = 0;
 	int bank = 0;
 
 
@@ -209,15 +216,13 @@ static void reset_bank(struct denali_nand_info *denali)
 	denali_write32(bank, denali->flash_reg + DEVICE_RESET);
 	denali_write32(bank, denali->flash_reg + DEVICE_RESET);
 
 
 	irq_status = wait_for_irq(denali, irq_mask);
 	irq_status = wait_for_irq(denali, irq_mask);
-	
+
 	if (irq_status & operation_timeout[denali->flash_bank])
 	if (irq_status & operation_timeout[denali->flash_bank])
-	{
 		printk(KERN_ERR "reset bank failed.\n");
 		printk(KERN_ERR "reset bank failed.\n");
-	}
 }
 }
 
 
 /* Reset the flash controller */
 /* Reset the flash controller */
-static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali)
+static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 {
 {
 	uint32_t i;
 	uint32_t i;
 
 
@@ -229,8 +234,10 @@ static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali)
 		denali->flash_reg + intr_status_addresses[i]);
 		denali->flash_reg + intr_status_addresses[i]);
 
 
 	for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) {
 	for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) {
-		denali_write32(device_reset_banks[i], denali->flash_reg + DEVICE_RESET);
-		while (!(ioread32(denali->flash_reg + intr_status_addresses[i]) &
+		denali_write32(device_reset_banks[i],
+				denali->flash_reg + DEVICE_RESET);
+		while (!(ioread32(denali->flash_reg +
+						intr_status_addresses[i]) &
 			(reset_complete[i] | operation_timeout[i])))
 			(reset_complete[i] | operation_timeout[i])))
 			;
 			;
 		if (ioread32(denali->flash_reg + intr_status_addresses[i]) &
 		if (ioread32(denali->flash_reg + intr_status_addresses[i]) &
@@ -246,11 +253,12 @@ static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali)
 	return PASS;
 	return PASS;
 }
 }
 
 
-/* this routine calculates the ONFI timing values for a given mode and programs
- * the clocking register accordingly. The mode is determined by the get_onfi_nand_para
-   routine.
+/* this routine calculates the ONFI timing values for a given mode and
+ * programs the clocking register accordingly. The mode is determined by
+ * the get_onfi_nand_para routine.
  */
  */
-static void NAND_ONFi_Timing_Mode(struct denali_nand_info *denali, uint16_t mode)
+static void nand_onfi_timing_set(struct denali_nand_info *denali,
+								uint16_t mode)
 {
 {
 	uint16_t Trea[6] = {40, 30, 25, 20, 20, 16};
 	uint16_t Trea[6] = {40, 30, 25, 20, 20, 16};
 	uint16_t Trp[6] = {50, 25, 17, 15, 12, 10};
 	uint16_t Trp[6] = {50, 25, 17, 15, 12, 10};
@@ -347,136 +355,24 @@ static void NAND_ONFi_Timing_Mode(struct denali_nand_info *denali, uint16_t mode
 	denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT);
 	denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT);
 }
 }
 
 
-/* configures the initial ECC settings for the controller */
-static void set_ecc_config(struct denali_nand_info *denali)
-{
-#if SUPPORT_8BITECC
-	if ((ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE) < 4096) ||
-		(ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE) <= 128))
-		denali_write32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
-
-	if ((ioread32(denali->flash_reg + ECC_CORRECTION) & ECC_CORRECTION__VALUE)
-		== 1) {
-		denali->dev_info.wECCBytesPerSector = 4;
-		denali->dev_info.wECCBytesPerSector *= denali->dev_info.wDevicesConnected;
-		denali->dev_info.wNumPageSpareFlag =
-			denali->dev_info.wPageSpareSize -
-			denali->dev_info.wPageDataSize /
-			(ECC_SECTOR_SIZE * denali->dev_info.wDevicesConnected) *
-			denali->dev_info.wECCBytesPerSector
-			- denali->dev_info.wSpareSkipBytes;
-	} else {
-		denali->dev_info.wECCBytesPerSector =
-			(ioread32(denali->flash_reg + ECC_CORRECTION) &
-			ECC_CORRECTION__VALUE) * 13 / 8;
-		if ((denali->dev_info.wECCBytesPerSector) % 2 == 0)
-			denali->dev_info.wECCBytesPerSector += 2;
-		else
-			denali->dev_info.wECCBytesPerSector += 1;
-
-		denali->dev_info.wECCBytesPerSector *= denali->dev_info.wDevicesConnected;
-		denali->dev_info.wNumPageSpareFlag = denali->dev_info.wPageSpareSize -
-			denali->dev_info.wPageDataSize /
-			(ECC_SECTOR_SIZE * denali->dev_info.wDevicesConnected) *
-			denali->dev_info.wECCBytesPerSector
-			- denali->dev_info.wSpareSkipBytes;
-	}
-}
-
 /* queries the NAND device to see what ONFI modes it supports. */
 /* queries the NAND device to see what ONFI modes it supports. */
 static uint16_t get_onfi_nand_para(struct denali_nand_info *denali)
 static uint16_t get_onfi_nand_para(struct denali_nand_info *denali)
 {
 {
 	int i;
 	int i;
-	uint16_t blks_lun_l, blks_lun_h, n_of_luns;
-	uint32_t blockperlun, id;
-
-	denali_write32(DEVICE_RESET__BANK0, denali->flash_reg + DEVICE_RESET);
-
-	while (!((ioread32(denali->flash_reg + INTR_STATUS0) &
-		INTR_STATUS0__RST_COMP) |
-		(ioread32(denali->flash_reg + INTR_STATUS0) &
-		INTR_STATUS0__TIME_OUT)))
-		;
-
-	if (ioread32(denali->flash_reg + INTR_STATUS0) & INTR_STATUS0__RST_COMP) {
-		denali_write32(DEVICE_RESET__BANK1, denali->flash_reg + DEVICE_RESET);
-		while (!((ioread32(denali->flash_reg + INTR_STATUS1) &
-			INTR_STATUS1__RST_COMP) |
-			(ioread32(denali->flash_reg + INTR_STATUS1) &
-			INTR_STATUS1__TIME_OUT)))
-			;
-
-		if (ioread32(denali->flash_reg + INTR_STATUS1) &
-			INTR_STATUS1__RST_COMP) {
-			denali_write32(DEVICE_RESET__BANK2,
-				denali->flash_reg + DEVICE_RESET);
-			while (!((ioread32(denali->flash_reg + INTR_STATUS2) &
-				INTR_STATUS2__RST_COMP) |
-				(ioread32(denali->flash_reg + INTR_STATUS2) &
-				INTR_STATUS2__TIME_OUT)))
-				;
-
-			if (ioread32(denali->flash_reg + INTR_STATUS2) &
-				INTR_STATUS2__RST_COMP) {
-				denali_write32(DEVICE_RESET__BANK3,
-					denali->flash_reg + DEVICE_RESET);
-				while (!((ioread32(denali->flash_reg + INTR_STATUS3) &
-					INTR_STATUS3__RST_COMP) |
-					(ioread32(denali->flash_reg + INTR_STATUS3) &
-					INTR_STATUS3__TIME_OUT)))
-					;
-			} else {
-				printk(KERN_ERR "Getting a time out for bank 2!\n");
-			}
-		} else {
-			printk(KERN_ERR "Getting a time out for bank 1!\n");
-		}
-	}
-
-	denali_write32(INTR_STATUS0__TIME_OUT, denali->flash_reg + INTR_STATUS0);
-	denali_write32(INTR_STATUS1__TIME_OUT, denali->flash_reg + INTR_STATUS1);
-	denali_write32(INTR_STATUS2__TIME_OUT, denali->flash_reg + INTR_STATUS2);
-	denali_write32(INTR_STATUS3__TIME_OUT, denali->flash_reg + INTR_STATUS3);
-
-	denali->dev_info.wONFIDevFeatures =
-		ioread32(denali->flash_reg + ONFI_DEVICE_FEATURES);
-	denali->dev_info.wONFIOptCommands =
-		ioread32(denali->flash_reg + ONFI_OPTIONAL_COMMANDS);
-	denali->dev_info.wONFITimingMode =
-		ioread32(denali->flash_reg + ONFI_TIMING_MODE);
-	denali->dev_info.wONFIPgmCacheTimingMode =
-		ioread32(denali->flash_reg + ONFI_PGM_CACHE_TIMING_MODE);
-
-	n_of_luns = ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) &
-		ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS;
-	blks_lun_l = ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L);
-	blks_lun_h = ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U);
-
-	blockperlun = (blks_lun_h << 16) | blks_lun_l;
-
-	denali->dev_info.wTotalBlocks = n_of_luns * blockperlun;
-
+	/* we needn't to do a reset here because driver has already
+	 * reset all the banks before
+	 * */
 	if (!(ioread32(denali->flash_reg + ONFI_TIMING_MODE) &
 	if (!(ioread32(denali->flash_reg + ONFI_TIMING_MODE) &
 		ONFI_TIMING_MODE__VALUE))
 		ONFI_TIMING_MODE__VALUE))
 		return FAIL;
 		return FAIL;
 
 
 	for (i = 5; i > 0; i--) {
 	for (i = 5; i > 0; i--) {
-		if (ioread32(denali->flash_reg + ONFI_TIMING_MODE) & (0x01 << i))
+		if (ioread32(denali->flash_reg + ONFI_TIMING_MODE) &
+			(0x01 << i))
 			break;
 			break;
 	}
 	}
 
 
-	NAND_ONFi_Timing_Mode(denali, i);
-
-	index_addr(denali, MODE_11 | 0, 0x90);
-	index_addr(denali, MODE_11 | 1, 0);
-
-	for (i = 0; i < 3; i++)
-		index_addr_read_data(denali, MODE_11 | 2, &id);
-
-	nand_dbg_print(NAND_DBG_DEBUG, "3rd ID: 0x%x\n", id);
-
-	denali->dev_info.MLCDevice = id & 0x0C;
+	nand_onfi_timing_set(denali, i);
 
 
 	/* By now, all the ONFI devices we know support the page cache */
 	/* By now, all the ONFI devices we know support the page cache */
 	/* rw feature. So here we enable the pipeline_rw_ahead feature */
 	/* rw feature. So here we enable the pipeline_rw_ahead feature */
@@ -486,25 +382,10 @@ static uint16_t get_onfi_nand_para(struct denali_nand_info *denali)
 	return PASS;
 	return PASS;
 }
 }
 
 
-static void get_samsung_nand_para(struct denali_nand_info *denali)
+static void get_samsung_nand_para(struct denali_nand_info *denali,
+							uint8_t device_id)
 {
 {
-	uint8_t no_of_planes;
-	uint32_t blk_size;
-	uint64_t plane_size, capacity;
-	uint32_t id_bytes[5];
-	int i;
-
-	index_addr(denali, (uint32_t)(MODE_11 | 0), 0x90);
-	index_addr(denali, (uint32_t)(MODE_11 | 1), 0);
-	for (i = 0; i < 5; i++)
-		index_addr_read_data(denali, (uint32_t)(MODE_11 | 2), &id_bytes[i]);
-
-	nand_dbg_print(NAND_DBG_DEBUG,
-		"ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
-		id_bytes[0], id_bytes[1], id_bytes[2],
-		id_bytes[3], id_bytes[4]);
-
-	if ((id_bytes[1] & 0xff) == 0xd3) { /* Samsung K9WAG08U1A */
+	if (device_id == 0xd3) { /* Samsung K9WAG08U1A */
 		/* Set timing register values according to datasheet */
 		/* Set timing register values according to datasheet */
 		denali_write32(5, denali->flash_reg + ACC_CLKS);
 		denali_write32(5, denali->flash_reg + ACC_CLKS);
 		denali_write32(20, denali->flash_reg + RE_2_WE);
 		denali_write32(20, denali->flash_reg + RE_2_WE);
@@ -514,19 +395,10 @@ static void get_samsung_nand_para(struct denali_nand_info *denali)
 		denali_write32(2, denali->flash_reg + RDWR_EN_HI_CNT);
 		denali_write32(2, denali->flash_reg + RDWR_EN_HI_CNT);
 		denali_write32(2, denali->flash_reg + CS_SETUP_CNT);
 		denali_write32(2, denali->flash_reg + CS_SETUP_CNT);
 	}
 	}
-
-	no_of_planes = 1 << ((id_bytes[4] & 0x0c) >> 2);
-	plane_size  = (uint64_t)64 << ((id_bytes[4] & 0x70) >> 4);
-	blk_size = 64 << ((ioread32(denali->flash_reg + DEVICE_PARAM_1) & 0x30) >> 4);
-	capacity = (uint64_t)128 * plane_size * no_of_planes;
-
-	do_div(capacity, blk_size);
-	denali->dev_info.wTotalBlocks = capacity;
 }
 }
 
 
 static void get_toshiba_nand_para(struct denali_nand_info *denali)
 static void get_toshiba_nand_para(struct denali_nand_info *denali)
 {
 {
-	void __iomem *scratch_reg;
 	uint32_t tmp;
 	uint32_t tmp;
 
 
 	/* Workaround to fix a controller bug which reports a wrong */
 	/* Workaround to fix a controller bug which reports a wrong */
@@ -536,81 +408,52 @@ static void get_toshiba_nand_para(struct denali_nand_info *denali)
 		denali_write32(216, denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
 		denali_write32(216, denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
 		tmp = ioread32(denali->flash_reg + DEVICES_CONNECTED) *
 		tmp = ioread32(denali->flash_reg + DEVICES_CONNECTED) *
 			ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
 			ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
-		denali_write32(tmp, denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
+		denali_write32(tmp,
+				denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
 #if SUPPORT_15BITECC
 #if SUPPORT_15BITECC
 		denali_write32(15, denali->flash_reg + ECC_CORRECTION);
 		denali_write32(15, denali->flash_reg + ECC_CORRECTION);
 #elif SUPPORT_8BITECC
 #elif SUPPORT_8BITECC
 		denali_write32(8, denali->flash_reg + ECC_CORRECTION);
 		denali_write32(8, denali->flash_reg + ECC_CORRECTION);
 #endif
 #endif
 	}
 	}
-
-	/* As Toshiba NAND can not provide it's block number, */
-	/* so here we need user to provide the correct block */
-	/* number in a scratch register before the Linux NAND */
-	/* driver is loaded. If no valid value found in the scratch */
-	/* register, then we use default block number value */
-	scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE);
-	if (!scratch_reg) {
-		printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d",
-			__FILE__, __LINE__);
-		denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
-	} else {
-		nand_dbg_print(NAND_DBG_WARN,
-			"Spectra: ioremap reg address: 0x%p\n", scratch_reg);
-		denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg);
-		if (denali->dev_info.wTotalBlocks < 512)
-			denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
-		iounmap(scratch_reg);
-	}
 }
 }
 
 
-static void get_hynix_nand_para(struct denali_nand_info *denali)
+static void get_hynix_nand_para(struct denali_nand_info *denali,
+							uint8_t device_id)
 {
 {
-	void __iomem *scratch_reg;
 	uint32_t main_size, spare_size;
 	uint32_t main_size, spare_size;
 
 
-	switch (denali->dev_info.wDeviceID) {
+	switch (device_id) {
 	case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */
 	case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */
 	case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */
 	case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */
 		denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK);
 		denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK);
 		denali_write32(4096, denali->flash_reg + DEVICE_MAIN_AREA_SIZE);
 		denali_write32(4096, denali->flash_reg + DEVICE_MAIN_AREA_SIZE);
 		denali_write32(224, denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
 		denali_write32(224, denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
-		main_size = 4096 * ioread32(denali->flash_reg + DEVICES_CONNECTED);
-		spare_size = 224 * ioread32(denali->flash_reg + DEVICES_CONNECTED);
-		denali_write32(main_size, denali->flash_reg + LOGICAL_PAGE_DATA_SIZE);
-		denali_write32(spare_size, denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
+		main_size = 4096 *
+			ioread32(denali->flash_reg + DEVICES_CONNECTED);
+		spare_size = 224 *
+			ioread32(denali->flash_reg + DEVICES_CONNECTED);
+		denali_write32(main_size,
+				denali->flash_reg + LOGICAL_PAGE_DATA_SIZE);
+		denali_write32(spare_size,
+				denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
 		denali_write32(0, denali->flash_reg + DEVICE_WIDTH);
 		denali_write32(0, denali->flash_reg + DEVICE_WIDTH);
 #if SUPPORT_15BITECC
 #if SUPPORT_15BITECC
 		denali_write32(15, denali->flash_reg + ECC_CORRECTION);
 		denali_write32(15, denali->flash_reg + ECC_CORRECTION);
 #elif SUPPORT_8BITECC
 #elif SUPPORT_8BITECC
 		denali_write32(8, denali->flash_reg + ECC_CORRECTION);
 		denali_write32(8, denali->flash_reg + ECC_CORRECTION);
 #endif
 #endif
-		denali->dev_info.MLCDevice  = 1;
 		break;
 		break;
 	default:
 	default:
 		nand_dbg_print(NAND_DBG_WARN,
 		nand_dbg_print(NAND_DBG_WARN,
 			"Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
 			"Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
 			"Will use default parameter values instead.\n",
 			"Will use default parameter values instead.\n",
-			denali->dev_info.wDeviceID);
-	}
-
-	scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE);
-	if (!scratch_reg) {
-		printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d",
-			__FILE__, __LINE__);
-		denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
-	} else {
-		nand_dbg_print(NAND_DBG_WARN,
-			"Spectra: ioremap reg address: 0x%p\n", scratch_reg);
-		denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg);
-		if (denali->dev_info.wTotalBlocks < 512)
-			denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
-		iounmap(scratch_reg);
+			device_id);
 	}
 	}
 }
 }
 
 
 /* determines how many NAND chips are connected to the controller. Note for
 /* determines how many NAND chips are connected to the controller. Note for
-   Intel CE4100 devices we don't support more than one device. 
+   Intel CE4100 devices we don't support more than one device.
  */
  */
 static void find_valid_banks(struct denali_nand_info *denali)
 static void find_valid_banks(struct denali_nand_info *denali)
 {
 {
@@ -621,7 +464,8 @@ static void find_valid_banks(struct denali_nand_info *denali)
 	for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) {
 	for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) {
 		index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90);
 		index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90);
 		index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0);
 		index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0);
-		index_addr_read_data(denali, (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]);
+		index_addr_read_data(denali,
+				(uint32_t)(MODE_11 | (i << 24) | 2), &id[i]);
 
 
 		nand_dbg_print(NAND_DBG_DEBUG,
 		nand_dbg_print(NAND_DBG_DEBUG,
 			"Return 1st ID for bank[%d]: %x\n", i, id[i]);
 			"Return 1st ID for bank[%d]: %x\n", i, id[i]);
@@ -637,14 +481,12 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		}
 		}
 	}
 	}
 
 
-	if (denali->platform == INTEL_CE4100)
-	{
+	if (denali->platform == INTEL_CE4100) {
 		/* Platform limitations of the CE4100 device limit
 		/* Platform limitations of the CE4100 device limit
 		 * users to a single chip solution for NAND.
 		 * users to a single chip solution for NAND.
-                 * Multichip support is not enabled. 
-		 */ 
-		if (denali->total_used_banks != 1)
-		{
+		 * Multichip support is not enabled.
+		 */
+		if (denali->total_used_banks != 1) {
 			printk(KERN_ERR "Sorry, Intel CE4100 only supports "
 			printk(KERN_ERR "Sorry, Intel CE4100 only supports "
 					"a single NAND device.\n");
 					"a single NAND device.\n");
 			BUG();
 			BUG();
@@ -656,150 +498,60 @@ static void find_valid_banks(struct denali_nand_info *denali)
 
 
 static void detect_partition_feature(struct denali_nand_info *denali)
 static void detect_partition_feature(struct denali_nand_info *denali)
 {
 {
+	/* For MRST platform, denali->fwblks represent the
+	 * number of blocks firmware is taken,
+	 * FW is in protect partition and MTD driver has no
+	 * permission to access it. So let driver know how many
+	 * blocks it can't touch.
+	 * */
 	if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) {
 	if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) {
 		if ((ioread32(denali->flash_reg + PERM_SRC_ID_1) &
 		if ((ioread32(denali->flash_reg + PERM_SRC_ID_1) &
 			PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) {
 			PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) {
-			denali->dev_info.wSpectraStartBlock =
+			denali->fwblks =
 			    ((ioread32(denali->flash_reg + MIN_MAX_BANK_1) &
 			    ((ioread32(denali->flash_reg + MIN_MAX_BANK_1) &
 			      MIN_MAX_BANK_1__MIN_VALUE) *
 			      MIN_MAX_BANK_1__MIN_VALUE) *
-			     denali->dev_info.wTotalBlocks)
+			     denali->blksperchip)
 			    +
 			    +
 			    (ioread32(denali->flash_reg + MIN_BLK_ADDR_1) &
 			    (ioread32(denali->flash_reg + MIN_BLK_ADDR_1) &
 			    MIN_BLK_ADDR_1__VALUE);
 			    MIN_BLK_ADDR_1__VALUE);
-
-			denali->dev_info.wSpectraEndBlock =
-			    (((ioread32(denali->flash_reg + MIN_MAX_BANK_1) &
-			       MIN_MAX_BANK_1__MAX_VALUE) >> 2) *
-			     denali->dev_info.wTotalBlocks)
-			    +
-			    (ioread32(denali->flash_reg + MAX_BLK_ADDR_1) &
-			    MAX_BLK_ADDR_1__VALUE);
-
-			denali->dev_info.wTotalBlocks *= denali->total_used_banks;
-
-			if (denali->dev_info.wSpectraEndBlock >=
-			    denali->dev_info.wTotalBlocks) {
-				denali->dev_info.wSpectraEndBlock =
-				    denali->dev_info.wTotalBlocks - 1;
-			}
-
-			denali->dev_info.wDataBlockNum =
-				denali->dev_info.wSpectraEndBlock -
-				denali->dev_info.wSpectraStartBlock + 1;
-		} else {
-			denali->dev_info.wTotalBlocks *= denali->total_used_banks;
-			denali->dev_info.wSpectraStartBlock = SPECTRA_START_BLOCK;
-			denali->dev_info.wSpectraEndBlock =
-				denali->dev_info.wTotalBlocks - 1;
-			denali->dev_info.wDataBlockNum =
-				denali->dev_info.wSpectraEndBlock -
-				denali->dev_info.wSpectraStartBlock + 1;
-		}
-	} else {
-		denali->dev_info.wTotalBlocks *= denali->total_used_banks;
-		denali->dev_info.wSpectraStartBlock = SPECTRA_START_BLOCK;
-		denali->dev_info.wSpectraEndBlock = denali->dev_info.wTotalBlocks - 1;
-		denali->dev_info.wDataBlockNum =
-			denali->dev_info.wSpectraEndBlock -
-			denali->dev_info.wSpectraStartBlock + 1;
-	}
+		} else
+			denali->fwblks = SPECTRA_START_BLOCK;
+	} else
+		denali->fwblks = SPECTRA_START_BLOCK;
 }
 }
 
 
-static void dump_device_info(struct denali_nand_info *denali)
-{
-	nand_dbg_print(NAND_DBG_DEBUG, "denali->dev_info:\n");
-	nand_dbg_print(NAND_DBG_DEBUG, "DeviceMaker: 0x%x\n",
-		denali->dev_info.wDeviceMaker);
-	nand_dbg_print(NAND_DBG_DEBUG, "DeviceID: 0x%x\n",
-		denali->dev_info.wDeviceID);
-	nand_dbg_print(NAND_DBG_DEBUG, "DeviceType: 0x%x\n",
-		denali->dev_info.wDeviceType);
-	nand_dbg_print(NAND_DBG_DEBUG, "SpectraStartBlock: %d\n",
-		denali->dev_info.wSpectraStartBlock);
-	nand_dbg_print(NAND_DBG_DEBUG, "SpectraEndBlock: %d\n",
-		denali->dev_info.wSpectraEndBlock);
-	nand_dbg_print(NAND_DBG_DEBUG, "TotalBlocks: %d\n",
-		denali->dev_info.wTotalBlocks);
-	nand_dbg_print(NAND_DBG_DEBUG, "PagesPerBlock: %d\n",
-		denali->dev_info.wPagesPerBlock);
-	nand_dbg_print(NAND_DBG_DEBUG, "PageSize: %d\n",
-		denali->dev_info.wPageSize);
-	nand_dbg_print(NAND_DBG_DEBUG, "PageDataSize: %d\n",
-		denali->dev_info.wPageDataSize);
-	nand_dbg_print(NAND_DBG_DEBUG, "PageSpareSize: %d\n",
-		denali->dev_info.wPageSpareSize);
-	nand_dbg_print(NAND_DBG_DEBUG, "NumPageSpareFlag: %d\n",
-		denali->dev_info.wNumPageSpareFlag);
-	nand_dbg_print(NAND_DBG_DEBUG, "ECCBytesPerSector: %d\n",
-		denali->dev_info.wECCBytesPerSector);
-	nand_dbg_print(NAND_DBG_DEBUG, "BlockSize: %d\n",
-		denali->dev_info.wBlockSize);
-	nand_dbg_print(NAND_DBG_DEBUG, "BlockDataSize: %d\n",
-		denali->dev_info.wBlockDataSize);
-	nand_dbg_print(NAND_DBG_DEBUG, "DataBlockNum: %d\n",
-		denali->dev_info.wDataBlockNum);
-	nand_dbg_print(NAND_DBG_DEBUG, "PlaneNum: %d\n",
-		denali->dev_info.bPlaneNum);
-	nand_dbg_print(NAND_DBG_DEBUG, "DeviceMainAreaSize: %d\n",
-		denali->dev_info.wDeviceMainAreaSize);
-	nand_dbg_print(NAND_DBG_DEBUG, "DeviceSpareAreaSize: %d\n",
-		denali->dev_info.wDeviceSpareAreaSize);
-	nand_dbg_print(NAND_DBG_DEBUG, "DevicesConnected: %d\n",
-		denali->dev_info.wDevicesConnected);
-	nand_dbg_print(NAND_DBG_DEBUG, "DeviceWidth: %d\n",
-		denali->dev_info.wDeviceWidth);
-	nand_dbg_print(NAND_DBG_DEBUG, "HWRevision: 0x%x\n",
-		denali->dev_info.wHWRevision);
-	nand_dbg_print(NAND_DBG_DEBUG, "HWFeatures: 0x%x\n",
-		denali->dev_info.wHWFeatures);
-	nand_dbg_print(NAND_DBG_DEBUG, "ONFIDevFeatures: 0x%x\n",
-		denali->dev_info.wONFIDevFeatures);
-	nand_dbg_print(NAND_DBG_DEBUG, "ONFIOptCommands: 0x%x\n",
-		denali->dev_info.wONFIOptCommands);
-	nand_dbg_print(NAND_DBG_DEBUG, "ONFITimingMode: 0x%x\n",
-		denali->dev_info.wONFITimingMode);
-	nand_dbg_print(NAND_DBG_DEBUG, "ONFIPgmCacheTimingMode: 0x%x\n",
-		denali->dev_info.wONFIPgmCacheTimingMode);
-	nand_dbg_print(NAND_DBG_DEBUG, "MLCDevice: %s\n",
-		denali->dev_info.MLCDevice ? "Yes" : "No");
-	nand_dbg_print(NAND_DBG_DEBUG, "SpareSkipBytes: %d\n",
-		denali->dev_info.wSpareSkipBytes);
-	nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageNumber: %d\n",
-		denali->dev_info.nBitsInPageNumber);
-	nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageDataSize: %d\n",
-		denali->dev_info.nBitsInPageDataSize);
-	nand_dbg_print(NAND_DBG_DEBUG, "BitsInBlockDataSize: %d\n",
-		denali->dev_info.nBitsInBlockDataSize);
-}
-
-static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali)
+static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 {
 {
 	uint16_t status = PASS;
 	uint16_t status = PASS;
-	uint8_t no_of_planes;
+	uint32_t id_bytes[5], addr;
+	uint8_t i, maf_id, device_id;
 
 
 	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
 	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
 		       __FILE__, __LINE__, __func__);
 		       __FILE__, __LINE__, __func__);
 
 
-	denali->dev_info.wDeviceMaker = ioread32(denali->flash_reg + MANUFACTURER_ID);
-	denali->dev_info.wDeviceID = ioread32(denali->flash_reg + DEVICE_ID);
-	denali->dev_info.bDeviceParam0 = ioread32(denali->flash_reg + DEVICE_PARAM_0);
-	denali->dev_info.bDeviceParam1 = ioread32(denali->flash_reg + DEVICE_PARAM_1);
-	denali->dev_info.bDeviceParam2 = ioread32(denali->flash_reg + DEVICE_PARAM_2);
-
-	denali->dev_info.MLCDevice = ioread32(denali->flash_reg + DEVICE_PARAM_0) & 0x0c;
+	/* Use read id method to get device ID and other
+	 * params. For some NAND chips, controller can't
+	 * report the correct device ID by reading from
+	 * DEVICE_ID register
+	 * */
+	addr = (uint32_t)MODE_11 | BANK(denali->flash_bank);
+	index_addr(denali, (uint32_t)addr | 0, 0x90);
+	index_addr(denali, (uint32_t)addr | 1, 0);
+	for (i = 0; i < 5; i++)
+		index_addr_read_data(denali, addr | 2, &id_bytes[i]);
+	maf_id = id_bytes[0];
+	device_id = id_bytes[1];
 
 
 	if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) &
 	if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) &
 		ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */
 		ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */
 		if (FAIL == get_onfi_nand_para(denali))
 		if (FAIL == get_onfi_nand_para(denali))
 			return FAIL;
 			return FAIL;
-	} else if (denali->dev_info.wDeviceMaker == 0xEC) { /* Samsung NAND */
-		get_samsung_nand_para(denali);
-	} else if (denali->dev_info.wDeviceMaker == 0x98) { /* Toshiba NAND */
+	} else if (maf_id == 0xEC) { /* Samsung NAND */
+		get_samsung_nand_para(denali, device_id);
+	} else if (maf_id == 0x98) { /* Toshiba NAND */
 		get_toshiba_nand_para(denali);
 		get_toshiba_nand_para(denali);
-	} else if (denali->dev_info.wDeviceMaker == 0xAD) { /* Hynix NAND */
-		get_hynix_nand_para(denali);
-	} else {
-		denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
+	} else if (maf_id == 0xAD) { /* Hynix NAND */
+		get_hynix_nand_para(denali, device_id);
 	}
 	}
 
 
 	nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:"
 	nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:"
@@ -814,88 +566,20 @@ static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali)
 			ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
 			ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
 			ioread32(denali->flash_reg + CS_SETUP_CNT));
 			ioread32(denali->flash_reg + CS_SETUP_CNT));
 
 
-	denali->dev_info.wHWRevision = ioread32(denali->flash_reg + REVISION);
-	denali->dev_info.wHWFeatures = ioread32(denali->flash_reg + FEATURES);
-
-	denali->dev_info.wDeviceMainAreaSize =
-		ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE);
-	denali->dev_info.wDeviceSpareAreaSize =
-		ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
-
-	denali->dev_info.wPageDataSize =
-		ioread32(denali->flash_reg + LOGICAL_PAGE_DATA_SIZE);
-
-	/* Note: When using the Micon 4K NAND device, the controller will report
-	 * Page Spare Size as 216 bytes. But Micron's Spec say it's 218 bytes.
-	 * And if force set it to 218 bytes, the controller can not work
-	 * correctly. So just let it be. But keep in mind that this bug may
-	 * cause
-	 * other problems in future.       - Yunpeng  2008-10-10
-	 */
-	denali->dev_info.wPageSpareSize =
-		ioread32(denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
-
-	denali->dev_info.wPagesPerBlock = ioread32(denali->flash_reg + PAGES_PER_BLOCK);
-
-	denali->dev_info.wPageSize =
-	    denali->dev_info.wPageDataSize + denali->dev_info.wPageSpareSize;
-	denali->dev_info.wBlockSize =
-	    denali->dev_info.wPageSize * denali->dev_info.wPagesPerBlock;
-	denali->dev_info.wBlockDataSize =
-	    denali->dev_info.wPagesPerBlock * denali->dev_info.wPageDataSize;
-
-	denali->dev_info.wDeviceWidth = ioread32(denali->flash_reg + DEVICE_WIDTH);
-	denali->dev_info.wDeviceType =
-		((ioread32(denali->flash_reg + DEVICE_WIDTH) > 0) ? 16 : 8);
-
-	denali->dev_info.wDevicesConnected = ioread32(denali->flash_reg + DEVICES_CONNECTED);
-
-	denali->dev_info.wSpareSkipBytes =
-		ioread32(denali->flash_reg + SPARE_AREA_SKIP_BYTES) *
-		denali->dev_info.wDevicesConnected;
-
-	denali->dev_info.nBitsInPageNumber =
-		ilog2(denali->dev_info.wPagesPerBlock);
-	denali->dev_info.nBitsInPageDataSize =
-		ilog2(denali->dev_info.wPageDataSize);
-	denali->dev_info.nBitsInBlockDataSize =
-		ilog2(denali->dev_info.wBlockDataSize);
-
-	set_ecc_config(denali);
-
-	no_of_planes = ioread32(denali->flash_reg + NUMBER_OF_PLANES) &
-		NUMBER_OF_PLANES__VALUE;
-
-	switch (no_of_planes) {
-	case 0:
-	case 1:
-	case 3:
-	case 7:
-		denali->dev_info.bPlaneNum = no_of_planes + 1;
-		break;
-	default:
-		status = FAIL;
-		break;
-	}
-
 	find_valid_banks(denali);
 	find_valid_banks(denali);
 
 
 	detect_partition_feature(denali);
 	detect_partition_feature(denali);
 
 
-	dump_device_info(denali);
-
 	/* If the user specified to override the default timings
 	/* If the user specified to override the default timings
-	 * with a specific ONFI mode, we apply those changes here. 
+	 * with a specific ONFI mode, we apply those changes here.
 	 */
 	 */
 	if (onfi_timing_mode != NAND_DEFAULT_TIMINGS)
 	if (onfi_timing_mode != NAND_DEFAULT_TIMINGS)
-	{
-		NAND_ONFi_Timing_Mode(denali, onfi_timing_mode);
-	}
+		nand_onfi_timing_set(denali, onfi_timing_mode);
 
 
 	return status;
 	return status;
 }
 }
 
 
-static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali,
+static void denali_set_intr_modes(struct denali_nand_info *denali,
 					uint16_t INT_ENABLE)
 					uint16_t INT_ENABLE)
 {
 {
 	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
 	nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
@@ -912,7 +596,7 @@ static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali,
  */
  */
 static inline bool is_flash_bank_valid(int flash_bank)
 static inline bool is_flash_bank_valid(int flash_bank)
 {
 {
-	return (flash_bank >= 0 && flash_bank < 4); 
+	return (flash_bank >= 0 && flash_bank < 4);
 }
 }
 
 
 static void denali_irq_init(struct denali_nand_info *denali)
 static void denali_irq_init(struct denali_nand_info *denali)
@@ -920,7 +604,7 @@ static void denali_irq_init(struct denali_nand_info *denali)
 	uint32_t int_mask = 0;
 	uint32_t int_mask = 0;
 
 
 	/* Disable global interrupts */
 	/* Disable global interrupts */
-	NAND_LLD_Enable_Disable_Interrupts(denali, false);
+	denali_set_intr_modes(denali, false);
 
 
 	int_mask = DENALI_IRQ_ALL;
 	int_mask = DENALI_IRQ_ALL;
 
 
@@ -935,11 +619,12 @@ static void denali_irq_init(struct denali_nand_info *denali)
 
 
 static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali)
 static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali)
 {
 {
-	NAND_LLD_Enable_Disable_Interrupts(denali, false);
+	denali_set_intr_modes(denali, false);
 	free_irq(irqnum, denali);
 	free_irq(irqnum, denali);
 }
 }
 
 
-static void denali_irq_enable(struct denali_nand_info *denali, uint32_t int_mask)
+static void denali_irq_enable(struct denali_nand_info *denali,
+							uint32_t int_mask)
 {
 {
 	denali_write32(int_mask, denali->flash_reg + INTR_EN0);
 	denali_write32(int_mask, denali->flash_reg + INTR_EN0);
 	denali_write32(int_mask, denali->flash_reg + INTR_EN1);
 	denali_write32(int_mask, denali->flash_reg + INTR_EN1);
@@ -948,15 +633,16 @@ static void denali_irq_enable(struct denali_nand_info *denali, uint32_t int_mask
 }
 }
 
 
 /* This function only returns when an interrupt that this driver cares about
 /* This function only returns when an interrupt that this driver cares about
- * occurs. This is to reduce the overhead of servicing interrupts 
+ * occurs. This is to reduce the overhead of servicing interrupts
  */
  */
 static inline uint32_t denali_irq_detected(struct denali_nand_info *denali)
 static inline uint32_t denali_irq_detected(struct denali_nand_info *denali)
 {
 {
-	return (read_interrupt_status(denali) & DENALI_IRQ_ALL);
+	return read_interrupt_status(denali) & DENALI_IRQ_ALL;
 }
 }
 
 
 /* Interrupts are cleared by writing a 1 to the appropriate status bit */
 /* Interrupts are cleared by writing a 1 to the appropriate status bit */
-static inline void clear_interrupt(struct denali_nand_info *denali, uint32_t irq_mask)
+static inline void clear_interrupt(struct denali_nand_info *denali,
+							uint32_t irq_mask)
 {
 {
 	uint32_t intr_status_reg = 0;
 	uint32_t intr_status_reg = 0;
 
 
@@ -995,17 +681,15 @@ static void print_irq_log(struct denali_nand_info *denali)
 {
 {
 	int i = 0;
 	int i = 0;
 
 
-	printk("ISR debug log index = %X\n", denali->idx);
+	printk(KERN_INFO "ISR debug log index = %X\n", denali->idx);
 	for (i = 0; i < 32; i++)
 	for (i = 0; i < 32; i++)
-	{
-		printk("%08X: %08X\n", i, denali->irq_debug_array[i]);
-	}
+		printk(KERN_INFO "%08X: %08X\n", i, denali->irq_debug_array[i]);
 }
 }
 #endif
 #endif
 
 
-/* This is the interrupt service routine. It handles all interrupts 
- * sent to this device. Note that on CE4100, this is a shared 
- * interrupt. 
+/* This is the interrupt service routine. It handles all interrupts
+ * sent to this device. Note that on CE4100, this is a shared
+ * interrupt.
  */
  */
 static irqreturn_t denali_isr(int irq, void *dev_id)
 static irqreturn_t denali_isr(int irq, void *dev_id)
 {
 {
@@ -1015,20 +699,20 @@ static irqreturn_t denali_isr(int irq, void *dev_id)
 
 
 	spin_lock(&denali->irq_lock);
 	spin_lock(&denali->irq_lock);
 
 
-	/* check to see if a valid NAND chip has 
-         * been selected. 
+	/* check to see if a valid NAND chip has
+	 * been selected.
 	 */
 	 */
-	if (is_flash_bank_valid(denali->flash_bank))
-	{
-		/* check to see if controller generated 
+	if (is_flash_bank_valid(denali->flash_bank)) {
+		/* check to see if controller generated
 		 * the interrupt, since this is a shared interrupt */
 		 * the interrupt, since this is a shared interrupt */
-		if ((irq_status = denali_irq_detected(denali)) != 0)
-		{
+		irq_status = denali_irq_detected(denali);
+		if (irq_status != 0) {
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-			denali->irq_debug_array[denali->idx++] = 0x10000000 | irq_status;
+			denali->irq_debug_array[denali->idx++] =
+				0x10000000 | irq_status;
 			denali->idx %= 32;
 			denali->idx %= 32;
 
 
-			printk("IRQ status = 0x%04x\n", irq_status);
+			printk(KERN_INFO "IRQ status = 0x%04x\n", irq_status);
 #endif
 #endif
 			/* handle interrupt */
 			/* handle interrupt */
 			/* first acknowledge it */
 			/* first acknowledge it */
@@ -1054,61 +738,62 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 	bool retry = false;
 	bool retry = false;
 	unsigned long timeout = msecs_to_jiffies(1000);
 	unsigned long timeout = msecs_to_jiffies(1000);
 
 
-	do
-	{
+	do {
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-		printk("waiting for 0x%x\n", irq_mask);
+		printk(KERN_INFO "waiting for 0x%x\n", irq_mask);
 #endif
 #endif
-		comp_res = wait_for_completion_timeout(&denali->complete, timeout);
+		comp_res =
+			wait_for_completion_timeout(&denali->complete, timeout);
 		spin_lock_irq(&denali->irq_lock);
 		spin_lock_irq(&denali->irq_lock);
 		intr_status = denali->irq_status;
 		intr_status = denali->irq_status;
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-		denali->irq_debug_array[denali->idx++] = 0x20000000 | (irq_mask << 16) | intr_status;
+		denali->irq_debug_array[denali->idx++] =
+			0x20000000 | (irq_mask << 16) | intr_status;
 		denali->idx %= 32;
 		denali->idx %= 32;
 #endif
 #endif
 
 
-		if (intr_status & irq_mask)
-		{
+		if (intr_status & irq_mask) {
 			denali->irq_status &= ~irq_mask;
 			denali->irq_status &= ~irq_mask;
 			spin_unlock_irq(&denali->irq_lock);
 			spin_unlock_irq(&denali->irq_lock);
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-			if (retry) printk("status on retry = 0x%x\n", intr_status);
+			if (retry)
+				printk(KERN_INFO "status on retry = 0x%x\n",
+						intr_status);
 #endif
 #endif
 			/* our interrupt was detected */
 			/* our interrupt was detected */
 			break;
 			break;
-		}
-		else 
-		{
-			/* these are not the interrupts you are looking for - 
-		           need to wait again */
+		} else {
+			/* these are not the interrupts you are looking for -
+			 * need to wait again */
 			spin_unlock_irq(&denali->irq_lock);
 			spin_unlock_irq(&denali->irq_lock);
 #if DEBUG_DENALI
 #if DEBUG_DENALI
 			print_irq_log(denali);
 			print_irq_log(denali);
-			printk("received irq nobody cared: irq_status = 0x%x,"
-				" irq_mask = 0x%x, timeout = %ld\n", intr_status, irq_mask, comp_res);
+			printk(KERN_INFO "received irq nobody cared:"
+					" irq_status = 0x%x, irq_mask = 0x%x,"
+					" timeout = %ld\n", intr_status,
+					irq_mask, comp_res);
 #endif
 #endif
 			retry = true;
 			retry = true;
 		}
 		}
 	} while (comp_res != 0);
 	} while (comp_res != 0);
 
 
-	if (comp_res == 0)
-	{
+	if (comp_res == 0) {
 		/* timeout */
 		/* timeout */
-		printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n", 
-	       			intr_status, irq_mask);
+		printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n",
+				intr_status, irq_mask);
 
 
 		intr_status = 0;
 		intr_status = 0;
 	}
 	}
 	return intr_status;
 	return intr_status;
 }
 }
 
 
-/* This helper function setups the registers for ECC and whether or not 
+/* This helper function setups the registers for ECC and whether or not
    the spare area will be transfered. */
    the spare area will be transfered. */
-static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, 
+static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en,
 				bool transfer_spare)
 				bool transfer_spare)
 {
 {
-	int ecc_en_flag = 0, transfer_spare_flag = 0; 
+	int ecc_en_flag = 0, transfer_spare_flag = 0;
 
 
 	/* set ECC, transfer spare bits if needed */
 	/* set ECC, transfer spare bits if needed */
 	ecc_en_flag = ecc_en ? ECC_ENABLE__FLAG : 0;
 	ecc_en_flag = ecc_en ? ECC_ENABLE__FLAG : 0;
@@ -1116,85 +801,85 @@ static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en,
 
 
 	/* Enable spare area/ECC per user's request. */
 	/* Enable spare area/ECC per user's request. */
 	denali_write32(ecc_en_flag, denali->flash_reg + ECC_ENABLE);
 	denali_write32(ecc_en_flag, denali->flash_reg + ECC_ENABLE);
-	denali_write32(transfer_spare_flag, denali->flash_reg + TRANSFER_SPARE_REG);
+	denali_write32(transfer_spare_flag,
+			denali->flash_reg + TRANSFER_SPARE_REG);
 }
 }
 
 
-/* sends a pipeline command operation to the controller. See the Denali NAND 
-   controller's user guide for more information (section 4.2.3.6). 
+/* sends a pipeline command operation to the controller. See the Denali NAND
+   controller's user guide for more information (section 4.2.3.6).
  */
  */
-static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool ecc_en, 
-					bool transfer_spare, int access_type, 
-					int op)
+static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
+							bool ecc_en,
+							bool transfer_spare,
+							int access_type,
+							int op)
 {
 {
 	int status = PASS;
 	int status = PASS;
-	uint32_t addr = 0x0, cmd = 0x0, page_count = 1, irq_status = 0, 
+	uint32_t addr = 0x0, cmd = 0x0, page_count = 1, irq_status = 0,
 		 irq_mask = 0;
 		 irq_mask = 0;
 
 
-	if (op == DENALI_READ) irq_mask = INTR_STATUS0__LOAD_COMP;
-	else if (op == DENALI_WRITE) irq_mask = 0;
-	else BUG();
+	if (op == DENALI_READ)
+		irq_mask = INTR_STATUS0__LOAD_COMP;
+	else if (op == DENALI_WRITE)
+		irq_mask = 0;
+	else
+		BUG();
 
 
 	setup_ecc_for_xfer(denali, ecc_en, transfer_spare);
 	setup_ecc_for_xfer(denali, ecc_en, transfer_spare);
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
 	spin_lock_irq(&denali->irq_lock);
 	spin_lock_irq(&denali->irq_lock);
-	denali->irq_debug_array[denali->idx++] = 0x40000000 | ioread32(denali->flash_reg + ECC_ENABLE) | (access_type << 4);
+	denali->irq_debug_array[denali->idx++] =
+		0x40000000 | ioread32(denali->flash_reg + ECC_ENABLE) |
+		(access_type << 4);
 	denali->idx %= 32;
 	denali->idx %= 32;
 	spin_unlock_irq(&denali->irq_lock);
 	spin_unlock_irq(&denali->irq_lock);
 #endif
 #endif
 
 
 
 
 	/* clear interrupts */
 	/* clear interrupts */
-	clear_interrupts(denali);	
+	clear_interrupts(denali);
 
 
 	addr = BANK(denali->flash_bank) | denali->page;
 	addr = BANK(denali->flash_bank) | denali->page;
 
 
-	if (op == DENALI_WRITE && access_type != SPARE_ACCESS)
-	{
-		cmd = MODE_01 | addr; 
+	if (op == DENALI_WRITE && access_type != SPARE_ACCESS) {
+		cmd = MODE_01 | addr;
 		denali_write32(cmd, denali->flash_mem);
 		denali_write32(cmd, denali->flash_mem);
-	}
-	else if (op == DENALI_WRITE && access_type == SPARE_ACCESS)
-	{
+	} else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) {
 		/* read spare area */
 		/* read spare area */
-		cmd = MODE_10 | addr; 
+		cmd = MODE_10 | addr;
 		index_addr(denali, (uint32_t)cmd, access_type);
 		index_addr(denali, (uint32_t)cmd, access_type);
 
 
-		cmd = MODE_01 | addr; 
+		cmd = MODE_01 | addr;
 		denali_write32(cmd, denali->flash_mem);
 		denali_write32(cmd, denali->flash_mem);
-	}
-	else if (op == DENALI_READ)
-	{
+	} else if (op == DENALI_READ) {
 		/* setup page read request for access type */
 		/* setup page read request for access type */
-		cmd = MODE_10 | addr; 
+		cmd = MODE_10 | addr;
 		index_addr(denali, (uint32_t)cmd, access_type);
 		index_addr(denali, (uint32_t)cmd, access_type);
 
 
 		/* page 33 of the NAND controller spec indicates we should not
 		/* page 33 of the NAND controller spec indicates we should not
-		   use the pipeline commands in Spare area only mode. So we 
+		   use the pipeline commands in Spare area only mode. So we
 		   don't.
 		   don't.
 		 */
 		 */
-		if (access_type == SPARE_ACCESS)
-		{
+		if (access_type == SPARE_ACCESS) {
 			cmd = MODE_01 | addr;
 			cmd = MODE_01 | addr;
 			denali_write32(cmd, denali->flash_mem);
 			denali_write32(cmd, denali->flash_mem);
-		}
-		else
-		{
-			index_addr(denali, (uint32_t)cmd, 0x2000 | op | page_count);
-	
-			/* wait for command to be accepted  
-			 * can always use status0 bit as the mask is identical for each
+		} else {
+			index_addr(denali, (uint32_t)cmd,
+					0x2000 | op | page_count);
+
+			/* wait for command to be accepted
+			 * can always use status0 bit as the
+			 * mask is identical for each
 			 * bank. */
 			 * bank. */
 			irq_status = wait_for_irq(denali, irq_mask);
 			irq_status = wait_for_irq(denali, irq_mask);
 
 
-			if (irq_status == 0)
-			{
+			if (irq_status == 0) {
 				printk(KERN_ERR "cmd, page, addr on timeout "
 				printk(KERN_ERR "cmd, page, addr on timeout "
-					"(0x%x, 0x%x, 0x%x)\n", cmd, denali->page, addr);
+					"(0x%x, 0x%x, 0x%x)\n", cmd,
+					denali->page, addr);
 				status = FAIL;
 				status = FAIL;
-			}
-			else
-			{
+			} else {
 				cmd = MODE_01 | addr;
 				cmd = MODE_01 | addr;
 				denali_write32(cmd, denali->flash_mem);
 				denali_write32(cmd, denali->flash_mem);
 			}
 			}
@@ -1204,36 +889,35 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool ecc_en
 }
 }
 
 
 /* helper function that simply writes a buffer to the flash */
 /* helper function that simply writes a buffer to the flash */
-static int write_data_to_flash_mem(struct denali_nand_info *denali, const uint8_t *buf, 
-					int len) 
+static int write_data_to_flash_mem(struct denali_nand_info *denali,
+							const uint8_t *buf,
+							int len)
 {
 {
 	uint32_t i = 0, *buf32;
 	uint32_t i = 0, *buf32;
 
 
-	/* verify that the len is a multiple of 4. see comment in 
-	 * read_data_from_flash_mem() */	
+	/* verify that the len is a multiple of 4. see comment in
+	 * read_data_from_flash_mem() */
 	BUG_ON((len % 4) != 0);
 	BUG_ON((len % 4) != 0);
 
 
 	/* write the data to the flash memory */
 	/* write the data to the flash memory */
 	buf32 = (uint32_t *)buf;
 	buf32 = (uint32_t *)buf;
 	for (i = 0; i < len / 4; i++)
 	for (i = 0; i < len / 4; i++)
-	{
 		denali_write32(*buf32++, denali->flash_mem + 0x10);
 		denali_write32(*buf32++, denali->flash_mem + 0x10);
-	}
-	return i*4; /* intent is to return the number of bytes read */ 
+	return i*4; /* intent is to return the number of bytes read */
 }
 }
 
 
 /* helper function that simply reads a buffer from the flash */
 /* helper function that simply reads a buffer from the flash */
-static int read_data_from_flash_mem(struct denali_nand_info *denali, uint8_t *buf, 
-					int len)
+static int read_data_from_flash_mem(struct denali_nand_info *denali,
+								uint8_t *buf,
+								int len)
 {
 {
 	uint32_t i = 0, *buf32;
 	uint32_t i = 0, *buf32;
 
 
 	/* we assume that len will be a multiple of 4, if not
 	/* we assume that len will be a multiple of 4, if not
 	 * it would be nice to know about it ASAP rather than
 	 * it would be nice to know about it ASAP rather than
-	 * have random failures... 
-         *	
-	 * This assumption is based on the fact that this 
-	 * function is designed to be used to read flash pages, 
+	 * have random failures...
+	 * This assumption is based on the fact that this
+	 * function is designed to be used to read flash pages,
 	 * which are typically multiples of 4...
 	 * which are typically multiples of 4...
 	 */
 	 */
 
 
@@ -1242,10 +926,8 @@ static int read_data_from_flash_mem(struct denali_nand_info *denali, uint8_t *bu
 	/* transfer the data from the flash */
 	/* transfer the data from the flash */
 	buf32 = (uint32_t *)buf;
 	buf32 = (uint32_t *)buf;
 	for (i = 0; i < len / 4; i++)
 	for (i = 0; i < len / 4; i++)
-	{
 		*buf32++ = ioread32(denali->flash_mem + 0x10);
 		*buf32++ = ioread32(denali->flash_mem + 0x10);
-	}
-	return i*4; /* intent is to return the number of bytes read */ 
+	return i*4; /* intent is to return the number of bytes read */
 }
 }
 
 
 /* writes OOB data to the device */
 /* writes OOB data to the device */
@@ -1253,38 +935,35 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 {
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 	uint32_t irq_status = 0;
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__PROGRAM_COMP | 
+	uint32_t irq_mask = INTR_STATUS0__PROGRAM_COMP |
 						INTR_STATUS0__PROGRAM_FAIL;
 						INTR_STATUS0__PROGRAM_FAIL;
 	int status = 0;
 	int status = 0;
 
 
 	denali->page = page;
 	denali->page = page;
 
 
-	if (denali_send_pipeline_cmd(denali, false, false, SPARE_ACCESS, 
-							DENALI_WRITE) == PASS) 
-	{
+	if (denali_send_pipeline_cmd(denali, false, false, SPARE_ACCESS,
+							DENALI_WRITE) == PASS) {
 		write_data_to_flash_mem(denali, buf, mtd->oobsize);
 		write_data_to_flash_mem(denali, buf, mtd->oobsize);
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
 		spin_lock_irq(&denali->irq_lock);
 		spin_lock_irq(&denali->irq_lock);
-		denali->irq_debug_array[denali->idx++] = 0x80000000 | mtd->oobsize;
+		denali->irq_debug_array[denali->idx++] =
+			0x80000000 | mtd->oobsize;
 		denali->idx %= 32;
 		denali->idx %= 32;
 		spin_unlock_irq(&denali->irq_lock);
 		spin_unlock_irq(&denali->irq_lock);
 #endif
 #endif
 
 
-	
+
 		/* wait for operation to complete */
 		/* wait for operation to complete */
 		irq_status = wait_for_irq(denali, irq_mask);
 		irq_status = wait_for_irq(denali, irq_mask);
 
 
-		if (irq_status == 0)
-		{
+		if (irq_status == 0) {
 			printk(KERN_ERR "OOB write failed\n");
 			printk(KERN_ERR "OOB write failed\n");
 			status = -EIO;
 			status = -EIO;
 		}
 		}
-	}
-	else 
-	{ 	
+	} else {
 		printk(KERN_ERR "unable to send pipeline command\n");
 		printk(KERN_ERR "unable to send pipeline command\n");
-		status = -EIO; 
+		status = -EIO;
 	}
 	}
 	return status;
 	return status;
 }
 }
@@ -1293,60 +972,56 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 {
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	uint32_t irq_mask = INTR_STATUS0__LOAD_COMP, irq_status = 0, addr = 0x0, cmd = 0x0;
+	uint32_t irq_mask = INTR_STATUS0__LOAD_COMP,
+			 irq_status = 0, addr = 0x0, cmd = 0x0;
 
 
 	denali->page = page;
 	denali->page = page;
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-	printk("read_oob %d\n", page);
+	printk(KERN_INFO "read_oob %d\n", page);
 #endif
 #endif
-	if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS, 
-							DENALI_READ) == PASS) 
-	{
-		read_data_from_flash_mem(denali, buf, mtd->oobsize);	
+	if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS,
+							DENALI_READ) == PASS) {
+		read_data_from_flash_mem(denali, buf, mtd->oobsize);
 
 
-		/* wait for command to be accepted  
+		/* wait for command to be accepted
 		 * can always use status0 bit as the mask is identical for each
 		 * can always use status0 bit as the mask is identical for each
 		 * bank. */
 		 * bank. */
 		irq_status = wait_for_irq(denali, irq_mask);
 		irq_status = wait_for_irq(denali, irq_mask);
 
 
 		if (irq_status == 0)
 		if (irq_status == 0)
-		{
-			printk(KERN_ERR "page on OOB timeout %d\n", denali->page);
-		}
+			printk(KERN_ERR "page on OOB timeout %d\n",
+					denali->page);
 
 
 		/* We set the device back to MAIN_ACCESS here as I observed
 		/* We set the device back to MAIN_ACCESS here as I observed
 		 * instability with the controller if you do a block erase
 		 * instability with the controller if you do a block erase
 		 * and the last transaction was a SPARE_ACCESS. Block erase
 		 * and the last transaction was a SPARE_ACCESS. Block erase
 		 * is reliable (according to the MTD test infrastructure)
 		 * is reliable (according to the MTD test infrastructure)
-		 * if you are in MAIN_ACCESS. 
+		 * if you are in MAIN_ACCESS.
 		 */
 		 */
 		addr = BANK(denali->flash_bank) | denali->page;
 		addr = BANK(denali->flash_bank) | denali->page;
-		cmd = MODE_10 | addr; 
+		cmd = MODE_10 | addr;
 		index_addr(denali, (uint32_t)cmd, MAIN_ACCESS);
 		index_addr(denali, (uint32_t)cmd, MAIN_ACCESS);
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
 		spin_lock_irq(&denali->irq_lock);
 		spin_lock_irq(&denali->irq_lock);
-		denali->irq_debug_array[denali->idx++] = 0x60000000 | mtd->oobsize;
+		denali->irq_debug_array[denali->idx++] =
+			0x60000000 | mtd->oobsize;
 		denali->idx %= 32;
 		denali->idx %= 32;
 		spin_unlock_irq(&denali->irq_lock);
 		spin_unlock_irq(&denali->irq_lock);
 #endif
 #endif
 	}
 	}
 }
 }
 
 
-/* this function examines buffers to see if they contain data that 
+/* this function examines buffers to see if they contain data that
  * indicate that the buffer is part of an erased region of flash.
  * indicate that the buffer is part of an erased region of flash.
  */
  */
 bool is_erased(uint8_t *buf, int len)
 bool is_erased(uint8_t *buf, int len)
 {
 {
 	int i = 0;
 	int i = 0;
 	for (i = 0; i < len; i++)
 	for (i = 0; i < len; i++)
-	{	
 		if (buf[i] != 0xFF)
 		if (buf[i] != 0xFF)
-		{
 			return false;
 			return false;
-		}
-	}
 	return true;
 	return true;
 }
 }
 #define ECC_SECTOR_SIZE 512
 #define ECC_SECTOR_SIZE 512
@@ -1358,65 +1033,59 @@ bool is_erased(uint8_t *buf, int len)
 #define ECC_ERR_DEVICE(x)	((x) & ERR_CORRECTION_INFO__DEVICE_NR >> 8)
 #define ECC_ERR_DEVICE(x)	((x) & ERR_CORRECTION_INFO__DEVICE_NR >> 8)
 #define ECC_LAST_ERR(x)		((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO)
 #define ECC_LAST_ERR(x)		((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO)
 
 
-static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, 
+static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
 			uint8_t *oobbuf, uint32_t irq_status)
 			uint8_t *oobbuf, uint32_t irq_status)
 {
 {
 	bool check_erased_page = false;
 	bool check_erased_page = false;
 
 
-	if (irq_status & INTR_STATUS0__ECC_ERR)
-	{
+	if (irq_status & INTR_STATUS0__ECC_ERR) {
 		/* read the ECC errors. we'll ignore them for now */
 		/* read the ECC errors. we'll ignore them for now */
 		uint32_t err_address = 0, err_correction_info = 0;
 		uint32_t err_address = 0, err_correction_info = 0;
 		uint32_t err_byte = 0, err_sector = 0, err_device = 0;
 		uint32_t err_byte = 0, err_sector = 0, err_device = 0;
 		uint32_t err_correction_value = 0;
 		uint32_t err_correction_value = 0;
 
 
-		do 
-		{
-			err_address = ioread32(denali->flash_reg + 
+		do {
+			err_address = ioread32(denali->flash_reg +
 						ECC_ERROR_ADDRESS);
 						ECC_ERROR_ADDRESS);
 			err_sector = ECC_SECTOR(err_address);
 			err_sector = ECC_SECTOR(err_address);
 			err_byte = ECC_BYTE(err_address);
 			err_byte = ECC_BYTE(err_address);
 
 
 
 
-			err_correction_info = ioread32(denali->flash_reg + 
+			err_correction_info = ioread32(denali->flash_reg +
 						ERR_CORRECTION_INFO);
 						ERR_CORRECTION_INFO);
-			err_correction_value = 
+			err_correction_value =
 				ECC_CORRECTION_VALUE(err_correction_info);
 				ECC_CORRECTION_VALUE(err_correction_info);
 			err_device = ECC_ERR_DEVICE(err_correction_info);
 			err_device = ECC_ERR_DEVICE(err_correction_info);
 
 
-			if (ECC_ERROR_CORRECTABLE(err_correction_info))
-			{
+			if (ECC_ERROR_CORRECTABLE(err_correction_info)) {
 				/* offset in our buffer is computed as:
 				/* offset in our buffer is computed as:
-				   sector number * sector size + offset in 
+				   sector number * sector size + offset in
 				   sector
 				   sector
 				 */
 				 */
-				int offset = err_sector * ECC_SECTOR_SIZE + 
+				int offset = err_sector * ECC_SECTOR_SIZE +
 								err_byte;
 								err_byte;
-				if (offset < denali->mtd.writesize)
-				{
+				if (offset < denali->mtd.writesize) {
 					/* correct the ECC error */
 					/* correct the ECC error */
 					buf[offset] ^= err_correction_value;
 					buf[offset] ^= err_correction_value;
 					denali->mtd.ecc_stats.corrected++;
 					denali->mtd.ecc_stats.corrected++;
-				}
-				else
-				{
+				} else {
 					/* bummer, couldn't correct the error */
 					/* bummer, couldn't correct the error */
 					printk(KERN_ERR "ECC offset invalid\n");
 					printk(KERN_ERR "ECC offset invalid\n");
 					denali->mtd.ecc_stats.failed++;
 					denali->mtd.ecc_stats.failed++;
 				}
 				}
-			}
-			else
-			{
-				/* if the error is not correctable, need to 
-				 * look at the page to see if it is an erased page.
-				 * if so, then it's not a real ECC error */	
+			} else {
+				/* if the error is not correctable, need to
+				 * look at the page to see if it is an erased
+				 * page. if so, then it's not a real ECC error
+				 * */
 				check_erased_page = true;
 				check_erased_page = true;
 			}
 			}
 
 
-#if DEBUG_DENALI 
-			printk("Detected ECC error in page %d: err_addr = 0x%08x,"
-				" info to fix is 0x%08x\n", denali->page, err_address, 
-				err_correction_info);
+#if DEBUG_DENALI
+			printk(KERN_INFO "Detected ECC error in page %d:"
+					" err_addr = 0x%08x, info to fix is"
+					" 0x%08x\n", denali->page, err_address,
+					err_correction_info);
 #endif
 #endif
 		} while (!ECC_LAST_ERR(err_correction_info));
 		} while (!ECC_LAST_ERR(err_correction_info));
 	}
 	}
@@ -1428,7 +1097,8 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en)
 {
 {
 	uint32_t reg_val = 0x0;
 	uint32_t reg_val = 0x0;
 
 
-	if (en) reg_val = DMA_ENABLE__FLAG;
+	if (en)
+		reg_val = DMA_ENABLE__FLAG;
 
 
 	denali_write32(reg_val, denali->flash_reg + DMA_ENABLE);
 	denali_write32(reg_val, denali->flash_reg + DMA_ENABLE);
 	ioread32(denali->flash_reg + DMA_ENABLE);
 	ioread32(denali->flash_reg + DMA_ENABLE);
@@ -1458,9 +1128,9 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op)
 	index_addr(denali, mode | 0x14000, 0x2400);
 	index_addr(denali, mode | 0x14000, 0x2400);
 }
 }
 
 
-/* writes a page. user specifies type, and this function handles the 
+/* writes a page. user specifies type, and this function handles the
    configuration details. */
    configuration details. */
-static void write_page(struct mtd_info *mtd, struct nand_chip *chip, 
+static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 			const uint8_t *buf, bool raw_xfer)
 			const uint8_t *buf, bool raw_xfer)
 {
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
@@ -1470,7 +1140,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 
 	uint32_t irq_status = 0;
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP | 
+	uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP |
 						INTR_STATUS0__PROGRAM_FAIL;
 						INTR_STATUS0__PROGRAM_FAIL;
 
 
 	/* if it is a raw xfer, we want to disable ecc, and send
 	/* if it is a raw xfer, we want to disable ecc, and send
@@ -1483,74 +1153,73 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	/* copy buffer into DMA buffer */
 	/* copy buffer into DMA buffer */
 	memcpy(denali->buf.buf, buf, mtd->writesize);
 	memcpy(denali->buf.buf, buf, mtd->writesize);
 
 
-	if (raw_xfer)
-	{
+	if (raw_xfer) {
 		/* transfer the data to the spare area */
 		/* transfer the data to the spare area */
-		memcpy(denali->buf.buf + mtd->writesize, 
-			chip->oob_poi, 
-			mtd->oobsize); 
+		memcpy(denali->buf.buf + mtd->writesize,
+			chip->oob_poi,
+			mtd->oobsize);
 	}
 	}
 
 
 	pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE);
 	pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE);
 
 
 	clear_interrupts(denali);
 	clear_interrupts(denali);
-	denali_enable_dma(denali, true);	
+	denali_enable_dma(denali, true);
 
 
 	denali_setup_dma(denali, DENALI_WRITE);
 	denali_setup_dma(denali, DENALI_WRITE);
 
 
 	/* wait for operation to complete */
 	/* wait for operation to complete */
 	irq_status = wait_for_irq(denali, irq_mask);
 	irq_status = wait_for_irq(denali, irq_mask);
 
 
-	if (irq_status == 0)
-	{
-		printk(KERN_ERR "timeout on write_page (type = %d)\n", raw_xfer);
-		denali->status = 
-	   	   (irq_status & INTR_STATUS0__PROGRAM_FAIL) ? NAND_STATUS_FAIL : 
-						   	     PASS;
+	if (irq_status == 0) {
+		printk(KERN_ERR "timeout on write_page"
+				" (type = %d)\n", raw_xfer);
+		denali->status =
+			(irq_status & INTR_STATUS0__PROGRAM_FAIL) ?
+			NAND_STATUS_FAIL : PASS;
 	}
 	}
 
 
-	denali_enable_dma(denali, false);	
+	denali_enable_dma(denali, false);
 	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE);
 	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE);
 }
 }
 
 
 /* NAND core entry points */
 /* NAND core entry points */
 
 
-/* this is the callback that the NAND core calls to write a page. Since 
-   writing a page with ECC or without is similar, all the work is done 
+/* this is the callback that the NAND core calls to write a page. Since
+   writing a page with ECC or without is similar, all the work is done
    by write_page above.   */
    by write_page above.   */
-static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, 
+static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 				const uint8_t *buf)
 				const uint8_t *buf)
 {
 {
 	/* for regular page writes, we let HW handle all the ECC
 	/* for regular page writes, we let HW handle all the ECC
-         * data written to the device. */
+	 * data written to the device. */
 	write_page(mtd, chip, buf, false);
 	write_page(mtd, chip, buf, false);
 }
 }
 
 
-/* This is the callback that the NAND core calls to write a page without ECC. 
+/* This is the callback that the NAND core calls to write a page without ECC.
    raw access is similiar to ECC page writes, so all the work is done in the
    raw access is similiar to ECC page writes, so all the work is done in the
-   write_page() function above. 
+   write_page() function above.
  */
  */
-static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, 
+static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 					const uint8_t *buf)
 					const uint8_t *buf)
 {
 {
-	/* for raw page writes, we want to disable ECC and simply write 
+	/* for raw page writes, we want to disable ECC and simply write
 	   whatever data is in the buffer. */
 	   whatever data is in the buffer. */
 	write_page(mtd, chip, buf, true);
 	write_page(mtd, chip, buf, true);
 }
 }
 
 
-static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, 
+static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
 			    int page)
 			    int page)
 {
 {
-	return write_oob_data(mtd, chip->oob_poi, page);	
+	return write_oob_data(mtd, chip->oob_poi, page);
 }
 }
 
 
-static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, 
+static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
 			   int page, int sndcmd)
 			   int page, int sndcmd)
 {
 {
 	read_oob_data(mtd, chip->oob_poi, page);
 	read_oob_data(mtd, chip->oob_poi, page);
 
 
-	return 0; /* notify NAND core to send command to 
-                   * NAND device. */
+	return 0; /* notify NAND core to send command to
+			   NAND device. */
 }
 }
 
 
 static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
@@ -1563,7 +1232,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 
 	uint32_t irq_status = 0;
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__ECC_TRANSACTION_DONE | 
+	uint32_t irq_mask = INTR_STATUS0__ECC_TRANSACTION_DONE |
 			    INTR_STATUS0__ECC_ERR;
 			    INTR_STATUS0__ECC_ERR;
 	bool check_erased_page = false;
 	bool check_erased_page = false;
 
 
@@ -1581,26 +1250,20 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
 	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
 
 
 	memcpy(buf, denali->buf.buf, mtd->writesize);
 	memcpy(buf, denali->buf.buf, mtd->writesize);
-	
+
 	check_erased_page = handle_ecc(denali, buf, chip->oob_poi, irq_status);
 	check_erased_page = handle_ecc(denali, buf, chip->oob_poi, irq_status);
 	denali_enable_dma(denali, false);
 	denali_enable_dma(denali, false);
 
 
-	if (check_erased_page)
-	{
+	if (check_erased_page) {
 		read_oob_data(&denali->mtd, chip->oob_poi, denali->page);
 		read_oob_data(&denali->mtd, chip->oob_poi, denali->page);
 
 
 		/* check ECC failures that may have occurred on erased pages */
 		/* check ECC failures that may have occurred on erased pages */
-		if (check_erased_page)
-		{
+		if (check_erased_page) {
 			if (!is_erased(buf, denali->mtd.writesize))
 			if (!is_erased(buf, denali->mtd.writesize))
-			{
 				denali->mtd.ecc_stats.failed++;
 				denali->mtd.ecc_stats.failed++;
-			}
 			if (!is_erased(buf, denali->mtd.oobsize))
 			if (!is_erased(buf, denali->mtd.oobsize))
-			{
 				denali->mtd.ecc_stats.failed++;
 				denali->mtd.ecc_stats.failed++;
-			}
-		}	
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -1616,7 +1279,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 
 
 	uint32_t irq_status = 0;
 	uint32_t irq_status = 0;
 	uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP;
 	uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP;
-						
+
 	setup_ecc_for_xfer(denali, false, true);
 	setup_ecc_for_xfer(denali, false, true);
 	denali_enable_dma(denali, true);
 	denali_enable_dma(denali, true);
 
 
@@ -1644,12 +1307,10 @@ static uint8_t denali_read_byte(struct mtd_info *mtd)
 	uint8_t result = 0xff;
 	uint8_t result = 0xff;
 
 
 	if (denali->buf.head < denali->buf.tail)
 	if (denali->buf.head < denali->buf.tail)
-	{
 		result = denali->buf.buf[denali->buf.head++];
 		result = denali->buf.buf[denali->buf.head++];
-	}
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-	printk("read byte -> 0x%02x\n", result);
+	printk(KERN_INFO "read byte -> 0x%02x\n", result);
 #endif
 #endif
 	return result;
 	return result;
 }
 }
@@ -1658,7 +1319,7 @@ static void denali_select_chip(struct mtd_info *mtd, int chip)
 {
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-	printk("denali select chip %d\n", chip);
+	printk(KERN_INFO "denali select chip %d\n", chip);
 #endif
 #endif
 	spin_lock_irq(&denali->irq_lock);
 	spin_lock_irq(&denali->irq_lock);
 	denali->flash_bank = chip;
 	denali->flash_bank = chip;
@@ -1672,7 +1333,7 @@ static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
 	denali->status = 0;
 	denali->status = 0;
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-	printk("waitfunc %d\n", status);
+	printk(KERN_INFO "waitfunc %d\n", status);
 #endif
 #endif
 	return status;
 	return status;
 }
 }
@@ -1684,76 +1345,74 @@ static void denali_erase(struct mtd_info *mtd, int page)
 	uint32_t cmd = 0x0, irq_status = 0;
 	uint32_t cmd = 0x0, irq_status = 0;
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-	printk("erase page: %d\n", page);
+	printk(KERN_INFO "erase page: %d\n", page);
 #endif
 #endif
 	/* clear interrupts */
 	/* clear interrupts */
-	clear_interrupts(denali);	
+	clear_interrupts(denali);
 
 
 	/* setup page read request for access type */
 	/* setup page read request for access type */
 	cmd = MODE_10 | BANK(denali->flash_bank) | page;
 	cmd = MODE_10 | BANK(denali->flash_bank) | page;
 	index_addr(denali, (uint32_t)cmd, 0x1);
 	index_addr(denali, (uint32_t)cmd, 0x1);
 
 
 	/* wait for erase to complete or failure to occur */
 	/* wait for erase to complete or failure to occur */
-	irq_status = wait_for_irq(denali, INTR_STATUS0__ERASE_COMP | 
+	irq_status = wait_for_irq(denali, INTR_STATUS0__ERASE_COMP |
 					INTR_STATUS0__ERASE_FAIL);
 					INTR_STATUS0__ERASE_FAIL);
 
 
-	denali->status = (irq_status & INTR_STATUS0__ERASE_FAIL) ? NAND_STATUS_FAIL : 
-								 PASS;
+	denali->status = (irq_status & INTR_STATUS0__ERASE_FAIL) ?
+						NAND_STATUS_FAIL : PASS;
 }
 }
 
 
-static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, 
+static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
 			   int page)
 			   int page)
 {
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
+	uint32_t addr, id;
+	int i;
 
 
 #if DEBUG_DENALI
 #if DEBUG_DENALI
-	printk("cmdfunc: 0x%x %d %d\n", cmd, col, page);
+	printk(KERN_INFO "cmdfunc: 0x%x %d %d\n", cmd, col, page);
 #endif
 #endif
-	switch (cmd)
-	{ 
-		case NAND_CMD_PAGEPROG:
-			break;
-		case NAND_CMD_STATUS:
-			read_status(denali);
-			break;
-		case NAND_CMD_READID:
-			reset_buf(denali);
-			if (denali->flash_bank < denali->total_used_banks)
-			{
-				/* write manufacturer information into nand 
-				   buffer for NAND subsystem to fetch.
-  			         */ 
-	                        write_byte_to_buf(denali, denali->dev_info.wDeviceMaker);
-	                        write_byte_to_buf(denali, denali->dev_info.wDeviceID);
-	                        write_byte_to_buf(denali, denali->dev_info.bDeviceParam0);
-	                        write_byte_to_buf(denali, denali->dev_info.bDeviceParam1);
-	                        write_byte_to_buf(denali, denali->dev_info.bDeviceParam2);
-			}
-			else 
-			{
-				int i;
-				for (i = 0; i < 5; i++) 
-					write_byte_to_buf(denali, 0xff);
-			}
-			break;
-		case NAND_CMD_READ0:
-		case NAND_CMD_SEQIN:
-			denali->page = page;
-			break;
-		case NAND_CMD_RESET:
-			reset_bank(denali);
-			break;
-		case NAND_CMD_READOOB:
-			/* TODO: Read OOB data */
-			break;
-		default:
-			printk(KERN_ERR ": unsupported command received 0x%x\n", cmd);
-			break;
+	switch (cmd) {
+	case NAND_CMD_PAGEPROG:
+		break;
+	case NAND_CMD_STATUS:
+		read_status(denali);
+		break;
+	case NAND_CMD_READID:
+		reset_buf(denali);
+		/*sometimes ManufactureId read from register is not right
+		 * e.g. some of Micron MT29F32G08QAA MLC NAND chips
+		 * So here we send READID cmd to NAND insteand
+		 * */
+		addr = (uint32_t)MODE_11 | BANK(denali->flash_bank);
+		index_addr(denali, (uint32_t)addr | 0, 0x90);
+		index_addr(denali, (uint32_t)addr | 1, 0);
+		for (i = 0; i < 5; i++) {
+			index_addr_read_data(denali,
+						(uint32_t)addr | 2,
+						&id);
+			write_byte_to_buf(denali, id);
+		}
+		break;
+	case NAND_CMD_READ0:
+	case NAND_CMD_SEQIN:
+		denali->page = page;
+		break;
+	case NAND_CMD_RESET:
+		reset_bank(denali);
+		break;
+	case NAND_CMD_READOOB:
+		/* TODO: Read OOB data */
+		break;
+	default:
+		printk(KERN_ERR ": unsupported command"
+				" received 0x%x\n", cmd);
+		break;
 	}
 	}
 }
 }
 
 
 /* stubs for ECC functions not used by the NAND core */
 /* stubs for ECC functions not used by the NAND core */
-static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, 
+static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
 				uint8_t *ecc_code)
 				uint8_t *ecc_code)
 {
 {
 	printk(KERN_ERR "denali_ecc_calculate called unexpectedly\n");
 	printk(KERN_ERR "denali_ecc_calculate called unexpectedly\n");
@@ -1761,7 +1420,7 @@ static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
 	return -EIO;
 	return -EIO;
 }
 }
 
 
-static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, 
+static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
 				uint8_t *read_ecc, uint8_t *calc_ecc)
 				uint8_t *read_ecc, uint8_t *calc_ecc)
 {
 {
 	printk(KERN_ERR "denali_ecc_correct called unexpectedly\n");
 	printk(KERN_ERR "denali_ecc_correct called unexpectedly\n");
@@ -1779,10 +1438,18 @@ static void denali_ecc_hwctl(struct mtd_info *mtd, int mode)
 /* Initialization code to bring the device up to a known good state */
 /* Initialization code to bring the device up to a known good state */
 static void denali_hw_init(struct denali_nand_info *denali)
 static void denali_hw_init(struct denali_nand_info *denali)
 {
 {
+	/* tell driver how many bit controller will skip before
+	 * writing ECC code in OOB, this register may be already
+	 * set by firmware. So we read this value out.
+	 * if this value is 0, just let it be.
+	 * */
+	denali->bbtskipbytes = ioread32(denali->flash_reg +
+						SPARE_AREA_SKIP_BYTES);
 	denali_irq_init(denali);
 	denali_irq_init(denali);
-	NAND_Flash_Reset(denali);
+	denali_nand_reset(denali);
 	denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED);
 	denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED);
-	denali_write32(CHIP_EN_DONT_CARE__FLAG, denali->flash_reg + CHIP_ENABLE_DONT_CARE);
+	denali_write32(CHIP_EN_DONT_CARE__FLAG,
+			denali->flash_reg + CHIP_ENABLE_DONT_CARE);
 
 
 	denali_write32(0x0, denali->flash_reg + SPARE_AREA_SKIP_BYTES);
 	denali_write32(0x0, denali->flash_reg + SPARE_AREA_SKIP_BYTES);
 	denali_write32(0xffff, denali->flash_reg + SPARE_AREA_MARKER);
 	denali_write32(0xffff, denali->flash_reg + SPARE_AREA_MARKER);
@@ -1792,25 +1459,18 @@ static void denali_hw_init(struct denali_nand_info *denali)
 	denali_write32(1, denali->flash_reg + ECC_ENABLE);
 	denali_write32(1, denali->flash_reg + ECC_ENABLE);
 }
 }
 
 
-/* ECC layout for SLC devices. Denali spec indicates SLC fixed at 4 bytes */
-#define ECC_BYTES_SLC   4 * (2048 / ECC_SECTOR_SIZE)
-static struct nand_ecclayout nand_oob_slc = {
-	.eccbytes = 4,
-	.eccpos = { 0, 1, 2, 3 }, /* not used */
-	.oobfree = {{ 
-			.offset = ECC_BYTES_SLC, 
-			.length = 64 - ECC_BYTES_SLC  
-		   }}
+/* Althogh controller spec said SLC ECC is forceb to be 4bit,
+ * but denali controller in MRST only support 15bit and 8bit ECC
+ * correction
+ * */
+#define ECC_8BITS	14
+static struct nand_ecclayout nand_8bit_oob = {
+	.eccbytes = 14,
 };
 };
 
 
-#define ECC_BYTES_MLC   14 * (2048 / ECC_SECTOR_SIZE)
-static struct nand_ecclayout nand_oob_mlc_14bit = {
-	.eccbytes = 14,
-	.eccpos = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13 }, /* not used */
-	.oobfree = {{ 
-			.offset = ECC_BYTES_MLC, 
-			.length = 64 - ECC_BYTES_MLC  
-		   }}
+#define ECC_15BITS	26
+static struct nand_ecclayout nand_15bit_oob = {
+	.eccbytes = 26,
 };
 };
 
 
 static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
 static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
@@ -1842,12 +1502,12 @@ void denali_drv_init(struct denali_nand_info *denali)
 	denali->idx = 0;
 	denali->idx = 0;
 
 
 	/* setup interrupt handler */
 	/* setup interrupt handler */
-	/* the completion object will be used to notify 
+	/* the completion object will be used to notify
 	 * the callee that the interrupt is done */
 	 * the callee that the interrupt is done */
 	init_completion(&denali->complete);
 	init_completion(&denali->complete);
 
 
 	/* the spinlock will be used to synchronize the ISR
 	/* the spinlock will be used to synchronize the ISR
-	 * with any element that might be access shared 
+	 * with any element that might be access shared
 	 * data (interrupt status) */
 	 * data (interrupt status) */
 	spin_lock_init(&denali->irq_lock);
 	spin_lock_init(&denali->irq_lock);
 
 
@@ -1880,13 +1540,12 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	}
 	}
 
 
 	if (id->driver_data == INTEL_CE4100) {
 	if (id->driver_data == INTEL_CE4100) {
-		/* Due to a silicon limitation, we can only support 
-		 * ONFI timing mode 1 and below. 
-		 */ 
-		if (onfi_timing_mode < -1 || onfi_timing_mode > 1)
-		{
-			printk("Intel CE4100 only supports ONFI timing mode 1 "
-				"or below\n");
+		/* Due to a silicon limitation, we can only support
+		 * ONFI timing mode 1 and below.
+		 */
+		if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
+			printk(KERN_ERR "Intel CE4100 only supports"
+					" ONFI timing mode 1 or below\n");
 			ret = -EINVAL;
 			ret = -EINVAL;
 			goto failed_enable;
 			goto failed_enable;
 		}
 		}
@@ -1905,7 +1564,9 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 			mem_base = csr_base + csr_len;
 			mem_base = csr_base + csr_len;
 			mem_len = csr_len;
 			mem_len = csr_len;
 			nand_dbg_print(NAND_DBG_WARN,
 			nand_dbg_print(NAND_DBG_WARN,
-				       "Spectra: No second BAR for PCI device; assuming %08Lx\n",
+				       "Spectra: No second"
+					   " BAR for PCI device;"
+					   " assuming %08Lx\n",
 				       (uint64_t)csr_base);
 				       (uint64_t)csr_base);
 		}
 		}
 	}
 	}
@@ -1913,16 +1574,16 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	/* Is 32-bit DMA supported? */
 	/* Is 32-bit DMA supported? */
 	ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32));
 	ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32));
 
 
-	if (ret)
-	{
+	if (ret) {
 		printk(KERN_ERR "Spectra: no usable DMA configuration\n");
 		printk(KERN_ERR "Spectra: no usable DMA configuration\n");
 		goto failed_enable;
 		goto failed_enable;
 	}
 	}
-	denali->buf.dma_buf = pci_map_single(dev, denali->buf.buf, DENALI_BUF_SIZE, 
-					 PCI_DMA_BIDIRECTIONAL);
+	denali->buf.dma_buf =
+		pci_map_single(dev, denali->buf.buf,
+						DENALI_BUF_SIZE,
+						PCI_DMA_BIDIRECTIONAL);
 
 
-	if (pci_dma_mapping_error(dev, denali->buf.dma_buf))
-	{
+	if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) {
 		printk(KERN_ERR "Spectra: failed to map DMA buffer\n");
 		printk(KERN_ERR "Spectra: failed to map DMA buffer\n");
 		goto failed_enable;
 		goto failed_enable;
 	}
 	}
@@ -1970,22 +1631,11 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	}
 	}
 
 
 	/* now that our ISR is registered, we can enable interrupts */
 	/* now that our ISR is registered, we can enable interrupts */
-	NAND_LLD_Enable_Disable_Interrupts(denali, true);
+	denali_set_intr_modes(denali, true);
 
 
 	pci_set_drvdata(dev, denali);
 	pci_set_drvdata(dev, denali);
 
 
-	NAND_Read_Device_ID(denali);
-
-	/* MTD supported page sizes vary by kernel. We validate our 
-           kernel supports the device here.
-	 */
-	if (denali->dev_info.wPageSize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE)
-	{
-		ret = -ENODEV;
-		printk(KERN_ERR "Spectra: device size not supported by this "
-			"version of MTD.");
-		goto failed_nand;
-	}
+	denali_nand_timing_set(denali);
 
 
 	nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:"
 	nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:"
 			"acc_clks: %d, re_2_we: %d, we_2_re: %d,"
 			"acc_clks: %d, re_2_we: %d, we_2_re: %d,"
@@ -2009,18 +1659,46 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	denali->nand.read_byte = denali_read_byte;
 	denali->nand.read_byte = denali_read_byte;
 	denali->nand.waitfunc = denali_waitfunc;
 	denali->nand.waitfunc = denali_waitfunc;
 
 
-	/* scan for NAND devices attached to the controller 
+	/* scan for NAND devices attached to the controller
 	 * this is the first stage in a two step process to register
 	 * this is the first stage in a two step process to register
-	 * with the nand subsystem */	
-	if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL))
-	{
+	 * with the nand subsystem */
+	if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) {
 		ret = -ENXIO;
 		ret = -ENXIO;
 		goto failed_nand;
 		goto failed_nand;
 	}
 	}
-	
-	/* second stage of the NAND scan 
-	 * this stage requires information regarding ECC and 
-         * bad block management. */
+
+	/* 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;
+		printk(KERN_ERR "Spectra: device size not supported by this "
+			"version of MTD.");
+		goto failed_nand;
+	}
+
+	/* support for multi nand
+	 * MTD known nothing about multi nand,
+	 * so we should tell it the real pagesize
+	 * and anything necessery
+	 */
+	denali->devnum = ioread32(denali->flash_reg + DEVICES_CONNECTED);
+	denali->nand.chipsize <<= (denali->devnum - 1);
+	denali->nand.page_shift += (denali->devnum - 1);
+	denali->nand.pagemask = (denali->nand.chipsize >>
+						denali->nand.page_shift) - 1;
+	denali->nand.bbt_erase_shift += (denali->devnum - 1);
+	denali->nand.phys_erase_shift = denali->nand.bbt_erase_shift;
+	denali->nand.chip_shift += (denali->devnum - 1);
+	denali->mtd.writesize <<= (denali->devnum - 1);
+	denali->mtd.oobsize <<= (denali->devnum - 1);
+	denali->mtd.erasesize <<= (denali->devnum - 1);
+	denali->mtd.size = denali->nand.numchips * denali->nand.chipsize;
+	denali->bbtskipbytes *= denali->devnum;
+
+	/* second stage of the NAND scan
+	 * this stage requires information regarding ECC and
+	 * bad block management. */
 
 
 	/* Bad block management */
 	/* Bad block management */
 	denali->nand.bbt_td = &bbt_main_descr;
 	denali->nand.bbt_td = &bbt_main_descr;
@@ -2030,26 +1708,57 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
 	denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
 	denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
 	denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
 
 
-	if (denali->dev_info.MLCDevice)
-	{
-		denali->nand.ecc.layout = &nand_oob_mlc_14bit;
-		denali->nand.ecc.bytes = ECC_BYTES_MLC;
-	}
-	else /* SLC */
-	{
-		denali->nand.ecc.layout = &nand_oob_slc;
-		denali->nand.ecc.bytes = ECC_BYTES_SLC;
+	/* Denali Controller only support 15bit and 8bit ECC in MRST,
+	 * so just let controller do 15bit ECC for MLC and 8bit ECC for
+	 * SLC if possible.
+	 * */
+	if (denali->nand.cellinfo & 0xc &&
+			(denali->mtd.oobsize > (denali->bbtskipbytes +
+			ECC_15BITS * (denali->mtd.writesize /
+			ECC_SECTOR_SIZE)))) {
+		/* if MLC OOB size is large enough, use 15bit ECC*/
+		denali->nand.ecc.layout = &nand_15bit_oob;
+		denali->nand.ecc.bytes = ECC_15BITS;
+		denali_write32(15, denali->flash_reg + ECC_CORRECTION);
+	} else if (denali->mtd.oobsize < (denali->bbtskipbytes +
+			ECC_8BITS * (denali->mtd.writesize /
+			ECC_SECTOR_SIZE))) {
+		printk(KERN_ERR "Your NAND chip OOB is not large enough to"
+				" contain 8bit ECC correction codes");
+		goto failed_nand;
+	} else {
+		denali->nand.ecc.layout = &nand_8bit_oob;
+		denali->nand.ecc.bytes = ECC_8BITS;
+		denali_write32(8, denali->flash_reg + ECC_CORRECTION);
 	}
 	}
 
 
-	/* These functions are required by the NAND core framework, otherwise, 
-           the NAND core will assert. However, we don't need them, so we'll stub 
-           them out. */
+	denali->nand.ecc.bytes *= denali->devnum;
+	denali->nand.ecc.layout->eccbytes *=
+		denali->mtd.writesize / ECC_SECTOR_SIZE;
+	denali->nand.ecc.layout->oobfree[0].offset =
+		denali->bbtskipbytes + denali->nand.ecc.layout->eccbytes;
+	denali->nand.ecc.layout->oobfree[0].length =
+		denali->mtd.oobsize - denali->nand.ecc.layout->eccbytes -
+		denali->bbtskipbytes;
+
+	/* Let driver know the total blocks number and
+	 * how many blocks contained by each nand chip.
+	 * blksperchip will help driver to know how many
+	 * blocks is taken by FW.
+	 * */
+	denali->totalblks = denali->mtd.size >>
+				denali->nand.phys_erase_shift;
+	denali->blksperchip = denali->totalblks / denali->nand.numchips;
+
+	/* These functions are required by the NAND core framework, otherwise,
+	 * the NAND core will assert. However, we don't need them, so we'll stub
+	 * them out. */
 	denali->nand.ecc.calculate = denali_ecc_calculate;
 	denali->nand.ecc.calculate = denali_ecc_calculate;
 	denali->nand.ecc.correct = denali_ecc_correct;
 	denali->nand.ecc.correct = denali_ecc_correct;
 	denali->nand.ecc.hwctl = denali_ecc_hwctl;
 	denali->nand.ecc.hwctl = denali_ecc_hwctl;
 
 
 	/* override the default read operations */
 	/* override the default read operations */
-	denali->nand.ecc.size = denali->mtd.writesize;
+	denali->nand.ecc.size = ECC_SECTOR_SIZE * denali->devnum;
 	denali->nand.ecc.read_page = denali_read_page;
 	denali->nand.ecc.read_page = denali_read_page;
 	denali->nand.ecc.read_page_raw = denali_read_page_raw;
 	denali->nand.ecc.read_page_raw = denali_read_page_raw;
 	denali->nand.ecc.write_page = denali_write_page;
 	denali->nand.ecc.write_page = denali_write_page;
@@ -2058,15 +1767,15 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	denali->nand.ecc.write_oob = denali_write_oob;
 	denali->nand.ecc.write_oob = denali_write_oob;
 	denali->nand.erase_cmd = denali_erase;
 	denali->nand.erase_cmd = denali_erase;
 
 
-	if (nand_scan_tail(&denali->mtd))
-	{
+	if (nand_scan_tail(&denali->mtd)) {
 		ret = -ENXIO;
 		ret = -ENXIO;
 		goto failed_nand;
 		goto failed_nand;
 	}
 	}
 
 
 	ret = add_mtd_device(&denali->mtd);
 	ret = add_mtd_device(&denali->mtd);
 	if (ret) {
 	if (ret) {
-		printk(KERN_ERR "Spectra: Failed to register MTD device: %d\n", ret);
+		printk(KERN_ERR "Spectra: Failed to register"
+				" MTD device: %d\n", ret);
 		goto failed_nand;
 		goto failed_nand;
 	}
 	}
 	return 0;
 	return 0;
@@ -2079,7 +1788,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
  failed_remap_csr:
  failed_remap_csr:
 	pci_release_regions(dev);
 	pci_release_regions(dev);
  failed_req_csr:
  failed_req_csr:
-	pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, 
+	pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
 							PCI_DMA_BIDIRECTIONAL);
 							PCI_DMA_BIDIRECTIONAL);
  failed_enable:
  failed_enable:
 	kfree(denali);
 	kfree(denali);
@@ -2103,7 +1812,7 @@ static void denali_pci_remove(struct pci_dev *dev)
 	iounmap(denali->flash_mem);
 	iounmap(denali->flash_mem);
 	pci_release_regions(dev);
 	pci_release_regions(dev);
 	pci_disable_device(dev);
 	pci_disable_device(dev);
-	pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, 
+	pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
 							PCI_DMA_BIDIRECTIONAL);
 							PCI_DMA_BIDIRECTIONAL);
 	pci_set_drvdata(dev, NULL);
 	pci_set_drvdata(dev, NULL);
 	kfree(denali);
 	kfree(denali);
@@ -2120,7 +1829,8 @@ static struct pci_driver denali_pci_driver = {
 
 
 static int __devinit denali_init(void)
 static int __devinit denali_init(void)
 {
 {
-	printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__);
+	printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n",
+			__DATE__, __TIME__);
 	return pci_register_driver(&denali_pci_driver);
 	return pci_register_driver(&denali_pci_driver);
 }
 }
 
 

+ 49 - 91
drivers/mtd/nand/denali.h

@@ -17,7 +17,7 @@
  *
  *
  */
  */
 
 
-#include <linux/mtd/nand.h> 
+#include <linux/mtd/nand.h>
 
 
 #define DEVICE_RESET				0x0
 #define DEVICE_RESET				0x0
 #define     DEVICE_RESET__BANK0				0x0001
 #define     DEVICE_RESET__BANK0				0x0001
@@ -29,7 +29,7 @@
 #define     TRANSFER_SPARE_REG__FLAG			0x0001
 #define     TRANSFER_SPARE_REG__FLAG			0x0001
 
 
 #define LOAD_WAIT_CNT				0x20
 #define LOAD_WAIT_CNT				0x20
-#define     LOAD_WAIT_CNT__VALUE				0xffff
+#define     LOAD_WAIT_CNT__VALUE			0xffff
 
 
 #define PROGRAM_WAIT_CNT			0x30
 #define PROGRAM_WAIT_CNT			0x30
 #define     PROGRAM_WAIT_CNT__VALUE			0xffff
 #define     PROGRAM_WAIT_CNT__VALUE			0xffff
@@ -83,7 +83,7 @@
 #define RE_2_WE					0x120
 #define RE_2_WE					0x120
 #define     RE_2_WE__VALUE				0x003f
 #define     RE_2_WE__VALUE				0x003f
 
 
-#define ACC_CLKS    				0x130
+#define ACC_CLKS				0x130
 #define     ACC_CLKS__VALUE				0x000f
 #define     ACC_CLKS__VALUE				0x000f
 
 
 #define NUMBER_OF_PLANES			0x140
 #define NUMBER_OF_PLANES			0x140
@@ -140,7 +140,7 @@
 #define DEVICES_CONNECTED			0x250
 #define DEVICES_CONNECTED			0x250
 #define     DEVICES_CONNECTED__VALUE			0x0007
 #define     DEVICES_CONNECTED__VALUE			0x0007
 
 
-#define DIE_MASK					0x260
+#define DIE_MASK				0x260
 #define     DIE_MASK__VALUE				0x00ff
 #define     DIE_MASK__VALUE				0x00ff
 
 
 #define FIRST_BLOCK_OF_NEXT_PLANE		0x270
 #define FIRST_BLOCK_OF_NEXT_PLANE		0x270
@@ -152,7 +152,7 @@
 #define RE_2_RE					0x290
 #define RE_2_RE					0x290
 #define     RE_2_RE__VALUE				0x003f
 #define     RE_2_RE__VALUE				0x003f
 
 
-#define MANUFACTURER_ID			0x300
+#define MANUFACTURER_ID				0x300
 #define     MANUFACTURER_ID__VALUE			0x00ff
 #define     MANUFACTURER_ID__VALUE			0x00ff
 
 
 #define DEVICE_ID				0x310
 #define DEVICE_ID				0x310
@@ -173,13 +173,13 @@
 #define LOGICAL_PAGE_SPARE_SIZE			0x360
 #define LOGICAL_PAGE_SPARE_SIZE			0x360
 #define     LOGICAL_PAGE_SPARE_SIZE__VALUE		0xffff
 #define     LOGICAL_PAGE_SPARE_SIZE__VALUE		0xffff
 
 
-#define REVISION					0x370
+#define REVISION				0x370
 #define     REVISION__VALUE				0xffff
 #define     REVISION__VALUE				0xffff
 
 
 #define ONFI_DEVICE_FEATURES			0x380
 #define ONFI_DEVICE_FEATURES			0x380
 #define     ONFI_DEVICE_FEATURES__VALUE			0x003f
 #define     ONFI_DEVICE_FEATURES__VALUE			0x003f
 
 
-#define ONFI_OPTIONAL_COMMANDS		0x390
+#define ONFI_OPTIONAL_COMMANDS			0x390
 #define     ONFI_OPTIONAL_COMMANDS__VALUE		0x003f
 #define     ONFI_OPTIONAL_COMMANDS__VALUE		0x003f
 
 
 #define ONFI_TIMING_MODE			0x3a0
 #define ONFI_TIMING_MODE			0x3a0
@@ -201,12 +201,12 @@
 #define FEATURES					0x3f0
 #define FEATURES					0x3f0
 #define     FEATURES__N_BANKS				0x0003
 #define     FEATURES__N_BANKS				0x0003
 #define     FEATURES__ECC_MAX_ERR			0x003c
 #define     FEATURES__ECC_MAX_ERR			0x003c
-#define     FEATURES__DMA					0x0040
+#define     FEATURES__DMA				0x0040
 #define     FEATURES__CMD_DMA				0x0080
 #define     FEATURES__CMD_DMA				0x0080
 #define     FEATURES__PARTITION				0x0100
 #define     FEATURES__PARTITION				0x0100
 #define     FEATURES__XDMA_SIDEBAND			0x0200
 #define     FEATURES__XDMA_SIDEBAND			0x0200
 #define     FEATURES__GPREG				0x0400
 #define     FEATURES__GPREG				0x0400
-#define     FEATURES__INDEX_ADDR				0x0800
+#define     FEATURES__INDEX_ADDR			0x0800
 
 
 #define TRANSFER_MODE				0x400
 #define TRANSFER_MODE				0x400
 #define     TRANSFER_MODE__VALUE			0x0003
 #define     TRANSFER_MODE__VALUE			0x0003
@@ -235,12 +235,12 @@
 #define     INTR_EN0__DMA_CMD_COMP			0x0004
 #define     INTR_EN0__DMA_CMD_COMP			0x0004
 #define     INTR_EN0__TIME_OUT				0x0008
 #define     INTR_EN0__TIME_OUT				0x0008
 #define     INTR_EN0__PROGRAM_FAIL			0x0010
 #define     INTR_EN0__PROGRAM_FAIL			0x0010
-#define     INTR_EN0__ERASE_FAIL				0x0020
+#define     INTR_EN0__ERASE_FAIL			0x0020
 #define     INTR_EN0__LOAD_COMP				0x0040
 #define     INTR_EN0__LOAD_COMP				0x0040
 #define     INTR_EN0__PROGRAM_COMP			0x0080
 #define     INTR_EN0__PROGRAM_COMP			0x0080
-#define     INTR_EN0__ERASE_COMP				0x0100
+#define     INTR_EN0__ERASE_COMP			0x0100
 #define     INTR_EN0__PIPE_CPYBCK_CMD_COMP		0x0200
 #define     INTR_EN0__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN0__LOCKED_BLK				0x0400
+#define     INTR_EN0__LOCKED_BLK			0x0400
 #define     INTR_EN0__UNSUP_CMD				0x0800
 #define     INTR_EN0__UNSUP_CMD				0x0800
 #define     INTR_EN0__INT_ACT				0x1000
 #define     INTR_EN0__INT_ACT				0x1000
 #define     INTR_EN0__RST_COMP				0x2000
 #define     INTR_EN0__RST_COMP				0x2000
@@ -253,7 +253,7 @@
 #define ERR_PAGE_ADDR0				0x440
 #define ERR_PAGE_ADDR0				0x440
 #define     ERR_PAGE_ADDR0__VALUE			0xffff
 #define     ERR_PAGE_ADDR0__VALUE			0xffff
 
 
-#define ERR_BLOCK_ADDR0			0x450
+#define ERR_BLOCK_ADDR0				0x450
 #define     ERR_BLOCK_ADDR0__VALUE			0xffff
 #define     ERR_BLOCK_ADDR0__VALUE			0xffff
 
 
 #define INTR_STATUS1				0x460
 #define INTR_STATUS1				0x460
@@ -280,12 +280,12 @@
 #define     INTR_EN1__DMA_CMD_COMP			0x0004
 #define     INTR_EN1__DMA_CMD_COMP			0x0004
 #define     INTR_EN1__TIME_OUT				0x0008
 #define     INTR_EN1__TIME_OUT				0x0008
 #define     INTR_EN1__PROGRAM_FAIL			0x0010
 #define     INTR_EN1__PROGRAM_FAIL			0x0010
-#define     INTR_EN1__ERASE_FAIL				0x0020
+#define     INTR_EN1__ERASE_FAIL			0x0020
 #define     INTR_EN1__LOAD_COMP				0x0040
 #define     INTR_EN1__LOAD_COMP				0x0040
 #define     INTR_EN1__PROGRAM_COMP			0x0080
 #define     INTR_EN1__PROGRAM_COMP			0x0080
-#define     INTR_EN1__ERASE_COMP				0x0100
+#define     INTR_EN1__ERASE_COMP			0x0100
 #define     INTR_EN1__PIPE_CPYBCK_CMD_COMP		0x0200
 #define     INTR_EN1__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN1__LOCKED_BLK				0x0400
+#define     INTR_EN1__LOCKED_BLK			0x0400
 #define     INTR_EN1__UNSUP_CMD				0x0800
 #define     INTR_EN1__UNSUP_CMD				0x0800
 #define     INTR_EN1__INT_ACT				0x1000
 #define     INTR_EN1__INT_ACT				0x1000
 #define     INTR_EN1__RST_COMP				0x2000
 #define     INTR_EN1__RST_COMP				0x2000
@@ -298,7 +298,7 @@
 #define ERR_PAGE_ADDR1				0x490
 #define ERR_PAGE_ADDR1				0x490
 #define     ERR_PAGE_ADDR1__VALUE			0xffff
 #define     ERR_PAGE_ADDR1__VALUE			0xffff
 
 
-#define ERR_BLOCK_ADDR1			0x4a0
+#define ERR_BLOCK_ADDR1				0x4a0
 #define     ERR_BLOCK_ADDR1__VALUE			0xffff
 #define     ERR_BLOCK_ADDR1__VALUE			0xffff
 
 
 #define INTR_STATUS2				0x4b0
 #define INTR_STATUS2				0x4b0
@@ -325,12 +325,12 @@
 #define     INTR_EN2__DMA_CMD_COMP			0x0004
 #define     INTR_EN2__DMA_CMD_COMP			0x0004
 #define     INTR_EN2__TIME_OUT				0x0008
 #define     INTR_EN2__TIME_OUT				0x0008
 #define     INTR_EN2__PROGRAM_FAIL			0x0010
 #define     INTR_EN2__PROGRAM_FAIL			0x0010
-#define     INTR_EN2__ERASE_FAIL				0x0020
+#define     INTR_EN2__ERASE_FAIL			0x0020
 #define     INTR_EN2__LOAD_COMP				0x0040
 #define     INTR_EN2__LOAD_COMP				0x0040
 #define     INTR_EN2__PROGRAM_COMP			0x0080
 #define     INTR_EN2__PROGRAM_COMP			0x0080
-#define     INTR_EN2__ERASE_COMP				0x0100
+#define     INTR_EN2__ERASE_COMP			0x0100
 #define     INTR_EN2__PIPE_CPYBCK_CMD_COMP		0x0200
 #define     INTR_EN2__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN2__LOCKED_BLK				0x0400
+#define     INTR_EN2__LOCKED_BLK			0x0400
 #define     INTR_EN2__UNSUP_CMD				0x0800
 #define     INTR_EN2__UNSUP_CMD				0x0800
 #define     INTR_EN2__INT_ACT				0x1000
 #define     INTR_EN2__INT_ACT				0x1000
 #define     INTR_EN2__RST_COMP				0x2000
 #define     INTR_EN2__RST_COMP				0x2000
@@ -343,7 +343,7 @@
 #define ERR_PAGE_ADDR2				0x4e0
 #define ERR_PAGE_ADDR2				0x4e0
 #define     ERR_PAGE_ADDR2__VALUE			0xffff
 #define     ERR_PAGE_ADDR2__VALUE			0xffff
 
 
-#define ERR_BLOCK_ADDR2			0x4f0
+#define ERR_BLOCK_ADDR2				0x4f0
 #define     ERR_BLOCK_ADDR2__VALUE			0xffff
 #define     ERR_BLOCK_ADDR2__VALUE			0xffff
 
 
 #define INTR_STATUS3				0x500
 #define INTR_STATUS3				0x500
@@ -370,12 +370,12 @@
 #define     INTR_EN3__DMA_CMD_COMP			0x0004
 #define     INTR_EN3__DMA_CMD_COMP			0x0004
 #define     INTR_EN3__TIME_OUT				0x0008
 #define     INTR_EN3__TIME_OUT				0x0008
 #define     INTR_EN3__PROGRAM_FAIL			0x0010
 #define     INTR_EN3__PROGRAM_FAIL			0x0010
-#define     INTR_EN3__ERASE_FAIL				0x0020
+#define     INTR_EN3__ERASE_FAIL			0x0020
 #define     INTR_EN3__LOAD_COMP				0x0040
 #define     INTR_EN3__LOAD_COMP				0x0040
 #define     INTR_EN3__PROGRAM_COMP			0x0080
 #define     INTR_EN3__PROGRAM_COMP			0x0080
-#define     INTR_EN3__ERASE_COMP				0x0100
+#define     INTR_EN3__ERASE_COMP			0x0100
 #define     INTR_EN3__PIPE_CPYBCK_CMD_COMP		0x0200
 #define     INTR_EN3__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN3__LOCKED_BLK				0x0400
+#define     INTR_EN3__LOCKED_BLK			0x0400
 #define     INTR_EN3__UNSUP_CMD				0x0800
 #define     INTR_EN3__UNSUP_CMD				0x0800
 #define     INTR_EN3__INT_ACT				0x1000
 #define     INTR_EN3__INT_ACT				0x1000
 #define     INTR_EN3__RST_COMP				0x2000
 #define     INTR_EN3__RST_COMP				0x2000
@@ -388,7 +388,7 @@
 #define ERR_PAGE_ADDR3				0x530
 #define ERR_PAGE_ADDR3				0x530
 #define     ERR_PAGE_ADDR3__VALUE			0xffff
 #define     ERR_PAGE_ADDR3__VALUE			0xffff
 
 
-#define ERR_BLOCK_ADDR3			0x540
+#define ERR_BLOCK_ADDR3				0x540
 #define     ERR_BLOCK_ADDR3__VALUE			0xffff
 #define     ERR_BLOCK_ADDR3__VALUE			0xffff
 
 
 #define DATA_INTR				0x550
 #define DATA_INTR				0x550
@@ -412,9 +412,9 @@
 #define     GPREG_3__VALUE				0xffff
 #define     GPREG_3__VALUE				0xffff
 
 
 #define ECC_THRESHOLD				0x600
 #define ECC_THRESHOLD				0x600
-#define     ECC_THRESHOLD__VALUE				0x03ff
+#define     ECC_THRESHOLD__VALUE			0x03ff
 
 
-#define ECC_ERROR_BLOCK_ADDRESS		0x610
+#define ECC_ERROR_BLOCK_ADDRESS			0x610
 #define     ECC_ERROR_BLOCK_ADDRESS__VALUE		0xffff
 #define     ECC_ERROR_BLOCK_ADDRESS__VALUE		0xffff
 
 
 #define ECC_ERROR_PAGE_ADDRESS			0x620
 #define ECC_ERROR_PAGE_ADDRESS			0x620
@@ -466,7 +466,7 @@
 #define     CHNL_ACTIVE__CHANNEL3			0x0008
 #define     CHNL_ACTIVE__CHANNEL3			0x0008
 
 
 #define ACTIVE_SRC_ID				0x800
 #define ACTIVE_SRC_ID				0x800
-#define     ACTIVE_SRC_ID__VALUE				0x00ff
+#define     ACTIVE_SRC_ID__VALUE			0x00ff
 
 
 #define PTN_INTR					0x810
 #define PTN_INTR					0x810
 #define     PTN_INTR__CONFIG_ERROR			0x0001
 #define     PTN_INTR__CONFIG_ERROR			0x0001
@@ -485,7 +485,7 @@
 #define     PTN_INTR_EN__REG_ACCESS_ERROR		0x0020
 #define     PTN_INTR_EN__REG_ACCESS_ERROR		0x0020
 
 
 #define PERM_SRC_ID_0				0x830
 #define PERM_SRC_ID_0				0x830
-#define     PERM_SRC_ID_0__SRCID				0x00ff
+#define     PERM_SRC_ID_0__SRCID			0x00ff
 #define     PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_0__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_0__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_0__READ_ACTIVE			0x4000
 #define     PERM_SRC_ID_0__READ_ACTIVE			0x4000
@@ -502,7 +502,7 @@
 #define     MIN_MAX_BANK_0__MAX_VALUE			0x000c
 #define     MIN_MAX_BANK_0__MAX_VALUE			0x000c
 
 
 #define PERM_SRC_ID_1				0x870
 #define PERM_SRC_ID_1				0x870
-#define     PERM_SRC_ID_1__SRCID				0x00ff
+#define     PERM_SRC_ID_1__SRCID			0x00ff
 #define     PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_1__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_1__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_1__READ_ACTIVE			0x4000
 #define     PERM_SRC_ID_1__READ_ACTIVE			0x4000
@@ -519,7 +519,7 @@
 #define     MIN_MAX_BANK_1__MAX_VALUE			0x000c
 #define     MIN_MAX_BANK_1__MAX_VALUE			0x000c
 
 
 #define PERM_SRC_ID_2				0x8b0
 #define PERM_SRC_ID_2				0x8b0
-#define     PERM_SRC_ID_2__SRCID				0x00ff
+#define     PERM_SRC_ID_2__SRCID			0x00ff
 #define     PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_2__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_2__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_2__READ_ACTIVE			0x4000
 #define     PERM_SRC_ID_2__READ_ACTIVE			0x4000
@@ -536,7 +536,7 @@
 #define     MIN_MAX_BANK_2__MAX_VALUE			0x000c
 #define     MIN_MAX_BANK_2__MAX_VALUE			0x000c
 
 
 #define PERM_SRC_ID_3				0x8f0
 #define PERM_SRC_ID_3				0x8f0
-#define     PERM_SRC_ID_3__SRCID				0x00ff
+#define     PERM_SRC_ID_3__SRCID			0x00ff
 #define     PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_3__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_3__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_3__READ_ACTIVE			0x4000
 #define     PERM_SRC_ID_3__READ_ACTIVE			0x4000
@@ -553,7 +553,7 @@
 #define     MIN_MAX_BANK_3__MAX_VALUE			0x000c
 #define     MIN_MAX_BANK_3__MAX_VALUE			0x000c
 
 
 #define PERM_SRC_ID_4				0x930
 #define PERM_SRC_ID_4				0x930
-#define     PERM_SRC_ID_4__SRCID				0x00ff
+#define     PERM_SRC_ID_4__SRCID			0x00ff
 #define     PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_4__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_4__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_4__READ_ACTIVE			0x4000
 #define     PERM_SRC_ID_4__READ_ACTIVE			0x4000
@@ -570,7 +570,7 @@
 #define     MIN_MAX_BANK_4__MAX_VALUE			0x000c
 #define     MIN_MAX_BANK_4__MAX_VALUE			0x000c
 
 
 #define PERM_SRC_ID_5				0x970
 #define PERM_SRC_ID_5				0x970
-#define     PERM_SRC_ID_5__SRCID				0x00ff
+#define     PERM_SRC_ID_5__SRCID			0x00ff
 #define     PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_5__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_5__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_5__READ_ACTIVE			0x4000
 #define     PERM_SRC_ID_5__READ_ACTIVE			0x4000
@@ -587,7 +587,7 @@
 #define     MIN_MAX_BANK_5__MAX_VALUE			0x000c
 #define     MIN_MAX_BANK_5__MAX_VALUE			0x000c
 
 
 #define PERM_SRC_ID_6				0x9b0
 #define PERM_SRC_ID_6				0x9b0
-#define     PERM_SRC_ID_6__SRCID				0x00ff
+#define     PERM_SRC_ID_6__SRCID			0x00ff
 #define     PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_6__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_6__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_6__READ_ACTIVE			0x4000
 #define     PERM_SRC_ID_6__READ_ACTIVE			0x4000
@@ -604,7 +604,7 @@
 #define     MIN_MAX_BANK_6__MAX_VALUE			0x000c
 #define     MIN_MAX_BANK_6__MAX_VALUE			0x000c
 
 
 #define PERM_SRC_ID_7				0x9f0
 #define PERM_SRC_ID_7				0x9f0
-#define     PERM_SRC_ID_7__SRCID				0x00ff
+#define     PERM_SRC_ID_7__SRCID			0x00ff
 #define     PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE		0x0800
 #define     PERM_SRC_ID_7__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_7__WRITE_ACTIVE			0x2000
 #define     PERM_SRC_ID_7__READ_ACTIVE			0x4000
 #define     PERM_SRC_ID_7__READ_ACTIVE			0x4000
@@ -620,47 +620,6 @@
 #define     MIN_MAX_BANK_7__MIN_VALUE			0x0003
 #define     MIN_MAX_BANK_7__MIN_VALUE			0x0003
 #define     MIN_MAX_BANK_7__MAX_VALUE			0x000c
 #define     MIN_MAX_BANK_7__MAX_VALUE			0x000c
 
 
-/* flash.h */
-struct device_info_tag {
-        uint16_t wDeviceMaker;
-        uint16_t wDeviceID;
-	uint8_t  bDeviceParam0;
-	uint8_t  bDeviceParam1;
-	uint8_t  bDeviceParam2;
-        uint32_t wDeviceType;
-        uint32_t wSpectraStartBlock;
-        uint32_t wSpectraEndBlock;
-        uint32_t wTotalBlocks;
-        uint16_t wPagesPerBlock;
-        uint16_t wPageSize;
-        uint16_t wPageDataSize;
-        uint16_t wPageSpareSize;
-        uint16_t wNumPageSpareFlag;
-        uint16_t wECCBytesPerSector;
-        uint32_t wBlockSize;
-        uint32_t wBlockDataSize;
-        uint32_t wDataBlockNum;
-        uint8_t bPlaneNum;
-        uint16_t wDeviceMainAreaSize;
-        uint16_t wDeviceSpareAreaSize;
-        uint16_t wDevicesConnected;
-        uint16_t wDeviceWidth;
-        uint16_t wHWRevision;
-        uint16_t wHWFeatures;
-
-        uint16_t wONFIDevFeatures;
-        uint16_t wONFIOptCommands;
-        uint16_t wONFITimingMode;
-        uint16_t wONFIPgmCacheTimingMode;
-
-        uint16_t MLCDevice;
-        uint16_t wSpareSkipBytes;
-
-        uint8_t nBitsInPageNumber;
-        uint8_t nBitsInPageDataSize;
-        uint8_t nBitsInBlockDataSize;
-};
-
 /* ffsdefs.h */
 /* ffsdefs.h */
 #define CLEAR 0                 /*use this to clear a field instead of "fail"*/
 #define CLEAR 0                 /*use this to clear a field instead of "fail"*/
 #define SET   1                 /*use this to set a field instead of "pass"*/
 #define SET   1                 /*use this to set a field instead of "pass"*/
@@ -684,11 +643,11 @@ struct device_info_tag {
 #define NAND_DBG_TRACE 3
 #define NAND_DBG_TRACE 3
 
 
 #ifdef VERBOSE
 #ifdef VERBOSE
-#define nand_dbg_print(level, args...)                  \
-        do {                                            \
-                if (level <= nand_debug_level)          \
-                        printk(KERN_ALERT args);        \
-        } while (0)
+#define nand_dbg_print(level, args...)				\
+	do {							\
+			if (level <= nand_debug_level)		\
+				printk(KERN_ALERT args);	\
+	} while (0)
 #else
 #else
 #define nand_dbg_print(level, args...)
 #define nand_dbg_print(level, args...)
 #endif
 #endif
@@ -772,10 +731,9 @@ struct device_info_tag {
 #define ECC_SECTOR_SIZE     512
 #define ECC_SECTOR_SIZE     512
 #define LLD_MAX_FLASH_BANKS     4
 #define LLD_MAX_FLASH_BANKS     4
 
 
-#define DENALI_BUF_SIZE		NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE
+#define DENALI_BUF_SIZE		(NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE)
 
 
-struct nand_buf
-{
+struct nand_buf {
 	int head;
 	int head;
 	int tail;
 	int tail;
 	uint8_t buf[DENALI_BUF_SIZE];
 	uint8_t buf[DENALI_BUF_SIZE];
@@ -788,7 +746,6 @@ struct nand_buf
 struct denali_nand_info {
 struct denali_nand_info {
 	struct mtd_info mtd;
 	struct mtd_info mtd;
 	struct nand_chip nand;
 	struct nand_chip nand;
-	struct device_info_tag dev_info;
 	int flash_bank; /* currently selected chip */
 	int flash_bank; /* currently selected chip */
 	int status;
 	int status;
 	int platform;
 	int platform;
@@ -806,11 +763,12 @@ struct denali_nand_info {
 	uint32_t irq_status;
 	uint32_t irq_status;
 	int irq_debug_array[32];
 	int irq_debug_array[32];
 	int idx;
 	int idx;
-};
 
 
-static uint16_t  NAND_Flash_Reset(struct denali_nand_info *denali);
-static uint16_t  NAND_Read_Device_ID(struct denali_nand_info *denali);
-static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali, uint16_t INT_ENABLE);
+	uint32_t devnum;	/* represent how many nands connected */
+	uint32_t fwblks; /* represent how many blocks FW used */
+	uint32_t totalblks;
+	uint32_t blksperchip;
+	uint32_t bbtskipbytes;
+};
 
 
 #endif /*_LLD_NAND_*/
 #endif /*_LLD_NAND_*/
-

+ 3 - 3
drivers/mtd/nand/diskonchip.c

@@ -29,7 +29,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/doc2000.h>
 #include <linux/mtd/doc2000.h>
-#include <linux/mtd/compatmac.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/inftl.h>
 #include <linux/mtd/inftl.h>
 
 
@@ -146,6 +145,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 	uint8_t parity;
 	uint8_t parity;
 	uint16_t ds[4], s[5], tmp, errval[8], syn[4];
 	uint16_t ds[4], s[5], tmp, errval[8], syn[4];
 
 
+	memset(syn, 0, sizeof(syn));
 	/* Convert the ecc bytes into words */
 	/* Convert the ecc bytes into words */
 	ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8);
 	ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8);
 	ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6);
 	ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6);
@@ -169,9 +169,9 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 			s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
 			s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
 	}
 	}
 
 
-	/* Calc s[i] = s[i] / alpha^(v + i) */
+	/* Calc syn[i] = s[i] / alpha^(v + i) */
 	for (i = 0; i < NROOTS; i++) {
 	for (i = 0; i < NROOTS; i++) {
-		if (syn[i])
+		if (s[i])
 			syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
 			syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
 	}
 	}
 	/* Call the decoder library */
 	/* Call the decoder library */

+ 425 - 175
drivers/mtd/nand/mxc_nand.c

@@ -39,60 +39,96 @@
 
 
 #define nfc_is_v21()		(cpu_is_mx25() || cpu_is_mx35())
 #define nfc_is_v21()		(cpu_is_mx25() || cpu_is_mx35())
 #define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
 #define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
+#define nfc_is_v3_2()		cpu_is_mx51()
+#define nfc_is_v3()		nfc_is_v3_2()
 
 
 /* Addresses for NFC registers */
 /* Addresses for NFC registers */
-#define NFC_BUF_SIZE		0xE00
-#define NFC_BUF_ADDR		0xE04
-#define NFC_FLASH_ADDR		0xE06
-#define NFC_FLASH_CMD		0xE08
-#define NFC_CONFIG		0xE0A
-#define NFC_ECC_STATUS_RESULT	0xE0C
-#define NFC_RSLTMAIN_AREA	0xE0E
-#define NFC_RSLTSPARE_AREA	0xE10
-#define NFC_WRPROT		0xE12
-#define NFC_V1_UNLOCKSTART_BLKADDR	0xe14
-#define NFC_V1_UNLOCKEND_BLKADDR	0xe16
-#define NFC_V21_UNLOCKSTART_BLKADDR	0xe20
-#define NFC_V21_UNLOCKEND_BLKADDR	0xe22
-#define NFC_NF_WRPRST		0xE18
-#define NFC_CONFIG1		0xE1A
-#define NFC_CONFIG2		0xE1C
-
-/* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
- * for Command operation */
-#define NFC_CMD            0x1
-
-/* Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
- * for Address operation */
-#define NFC_ADDR           0x2
-
-/* Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
- * for Input operation */
-#define NFC_INPUT          0x4
-
-/* Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
- * for Data Output operation */
-#define NFC_OUTPUT         0x8
-
-/* Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
- * for Read ID operation */
-#define NFC_ID             0x10
-
-/* Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
- * for Read Status operation */
-#define NFC_STATUS         0x20
-
-/* Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
- * Status operation */
-#define NFC_INT            0x8000
-
-#define NFC_SP_EN           (1 << 2)
-#define NFC_ECC_EN          (1 << 3)
-#define NFC_INT_MSK         (1 << 4)
-#define NFC_BIG             (1 << 5)
-#define NFC_RST             (1 << 6)
-#define NFC_CE              (1 << 7)
-#define NFC_ONE_CYCLE       (1 << 8)
+#define NFC_V1_V2_BUF_SIZE		(host->regs + 0x00)
+#define NFC_V1_V2_BUF_ADDR		(host->regs + 0x04)
+#define NFC_V1_V2_FLASH_ADDR		(host->regs + 0x06)
+#define NFC_V1_V2_FLASH_CMD		(host->regs + 0x08)
+#define NFC_V1_V2_CONFIG		(host->regs + 0x0a)
+#define NFC_V1_V2_ECC_STATUS_RESULT	(host->regs + 0x0c)
+#define NFC_V1_V2_RSLTMAIN_AREA		(host->regs + 0x0e)
+#define NFC_V1_V2_RSLTSPARE_AREA	(host->regs + 0x10)
+#define NFC_V1_V2_WRPROT		(host->regs + 0x12)
+#define NFC_V1_UNLOCKSTART_BLKADDR	(host->regs + 0x14)
+#define NFC_V1_UNLOCKEND_BLKADDR	(host->regs + 0x16)
+#define NFC_V21_UNLOCKSTART_BLKADDR	(host->regs + 0x20)
+#define NFC_V21_UNLOCKEND_BLKADDR	(host->regs + 0x22)
+#define NFC_V1_V2_NF_WRPRST		(host->regs + 0x18)
+#define NFC_V1_V2_CONFIG1		(host->regs + 0x1a)
+#define NFC_V1_V2_CONFIG2		(host->regs + 0x1c)
+
+#define NFC_V2_CONFIG1_ECC_MODE_4	(1 << 0)
+#define NFC_V1_V2_CONFIG1_SP_EN		(1 << 2)
+#define NFC_V1_V2_CONFIG1_ECC_EN	(1 << 3)
+#define NFC_V1_V2_CONFIG1_INT_MSK	(1 << 4)
+#define NFC_V1_V2_CONFIG1_BIG		(1 << 5)
+#define NFC_V1_V2_CONFIG1_RST		(1 << 6)
+#define NFC_V1_V2_CONFIG1_CE		(1 << 7)
+#define NFC_V1_V2_CONFIG1_ONE_CYCLE	(1 << 8)
+
+#define NFC_V1_V2_CONFIG2_INT		(1 << 15)
+
+/*
+ * Operation modes for the NFC. Valid for v1, v2 and v3
+ * type controllers.
+ */
+#define NFC_CMD				(1 << 0)
+#define NFC_ADDR			(1 << 1)
+#define NFC_INPUT			(1 << 2)
+#define NFC_OUTPUT			(1 << 3)
+#define NFC_ID				(1 << 4)
+#define NFC_STATUS			(1 << 5)
+
+#define NFC_V3_FLASH_CMD		(host->regs_axi + 0x00)
+#define NFC_V3_FLASH_ADDR0		(host->regs_axi + 0x04)
+
+#define NFC_V3_CONFIG1			(host->regs_axi + 0x34)
+#define NFC_V3_CONFIG1_SP_EN		(1 << 0)
+#define NFC_V3_CONFIG1_RBA(x)		(((x) & 0x7 ) << 4)
+
+#define NFC_V3_ECC_STATUS_RESULT	(host->regs_axi + 0x38)
+
+#define NFC_V3_LAUNCH			(host->regs_axi + 0x40)
+
+#define NFC_V3_WRPROT			(host->regs_ip + 0x0)
+#define NFC_V3_WRPROT_LOCK_TIGHT	(1 << 0)
+#define NFC_V3_WRPROT_LOCK		(1 << 1)
+#define NFC_V3_WRPROT_UNLOCK		(1 << 2)
+#define NFC_V3_WRPROT_BLS_UNLOCK	(2 << 6)
+
+#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0   (host->regs_ip + 0x04)
+
+#define NFC_V3_CONFIG2			(host->regs_ip + 0x24)
+#define NFC_V3_CONFIG2_PS_512			(0 << 0)
+#define NFC_V3_CONFIG2_PS_2048			(1 << 0)
+#define NFC_V3_CONFIG2_PS_4096			(2 << 0)
+#define NFC_V3_CONFIG2_ONE_CYCLE		(1 << 2)
+#define NFC_V3_CONFIG2_ECC_EN			(1 << 3)
+#define NFC_V3_CONFIG2_2CMD_PHASES		(1 << 4)
+#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0		(1 << 5)
+#define NFC_V3_CONFIG2_ECC_MODE_8		(1 << 6)
+#define NFC_V3_CONFIG2_PPB(x)			(((x) & 0x3) << 7)
+#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x)	(((x) & 0x3) << 12)
+#define NFC_V3_CONFIG2_INT_MSK			(1 << 15)
+#define NFC_V3_CONFIG2_ST_CMD(x)		(((x) & 0xff) << 24)
+#define NFC_V3_CONFIG2_SPAS(x)			(((x) & 0xff) << 16)
+
+#define NFC_V3_CONFIG3				(host->regs_ip + 0x28)
+#define NFC_V3_CONFIG3_ADD_OP(x)		(((x) & 0x3) << 0)
+#define NFC_V3_CONFIG3_FW8			(1 << 3)
+#define NFC_V3_CONFIG3_SBB(x)			(((x) & 0x7) << 8)
+#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x)	(((x) & 0x7) << 12)
+#define NFC_V3_CONFIG3_RBB_MODE			(1 << 15)
+#define NFC_V3_CONFIG3_NO_SDMA			(1 << 20)
+
+#define NFC_V3_IPC			(host->regs_ip + 0x2C)
+#define NFC_V3_IPC_CREQ			(1 << 0)
+#define NFC_V3_IPC_INT			(1 << 31)
+
+#define NFC_V3_DELAY_LINE		(host->regs_ip + 0x34)
 
 
 struct mxc_nand_host {
 struct mxc_nand_host {
 	struct mtd_info		mtd;
 	struct mtd_info		mtd;
@@ -102,20 +138,30 @@ struct mxc_nand_host {
 
 
 	void			*spare0;
 	void			*spare0;
 	void			*main_area0;
 	void			*main_area0;
-	void			*main_area1;
 
 
 	void __iomem		*base;
 	void __iomem		*base;
 	void __iomem		*regs;
 	void __iomem		*regs;
+	void __iomem		*regs_axi;
+	void __iomem		*regs_ip;
 	int			status_request;
 	int			status_request;
 	struct clk		*clk;
 	struct clk		*clk;
 	int			clk_act;
 	int			clk_act;
 	int			irq;
 	int			irq;
+	int			eccsize;
 
 
 	wait_queue_head_t	irq_waitq;
 	wait_queue_head_t	irq_waitq;
 
 
 	uint8_t			*data_buf;
 	uint8_t			*data_buf;
 	unsigned int		buf_start;
 	unsigned int		buf_start;
 	int			spare_len;
 	int			spare_len;
+
+	void			(*preset)(struct mtd_info *);
+	void			(*send_cmd)(struct mxc_nand_host *, uint16_t, int);
+	void			(*send_addr)(struct mxc_nand_host *, uint16_t, int);
+	void			(*send_page)(struct mtd_info *, unsigned int);
+	void			(*send_read_id)(struct mxc_nand_host *);
+	uint16_t		(*get_dev_status)(struct mxc_nand_host *);
+	int			(*check_int)(struct mxc_nand_host *);
 };
 };
 
 
 /* OOB placement block for use with hardware ecc generation */
 /* OOB placement block for use with hardware ecc generation */
@@ -175,34 +221,52 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
+static int check_int_v3(struct mxc_nand_host *host)
+{
+	uint32_t tmp;
+
+	tmp = readl(NFC_V3_IPC);
+	if (!(tmp & NFC_V3_IPC_INT))
+		return 0;
+
+	tmp &= ~NFC_V3_IPC_INT;
+	writel(tmp, NFC_V3_IPC);
+
+	return 1;
+}
+
+static int check_int_v1_v2(struct mxc_nand_host *host)
+{
+	uint32_t tmp;
+
+	tmp = readw(NFC_V1_V2_CONFIG2);
+	if (!(tmp & NFC_V1_V2_CONFIG2_INT))
+		return 0;
+
+	writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
+
+	return 1;
+}
+
 /* This function polls the NANDFC to wait for the basic operation to
 /* This function polls the NANDFC to wait for the basic operation to
  * complete by checking the INT bit of config2 register.
  * complete by checking the INT bit of config2 register.
  */
  */
 static void wait_op_done(struct mxc_nand_host *host, int useirq)
 static void wait_op_done(struct mxc_nand_host *host, int useirq)
 {
 {
-	uint16_t tmp;
 	int max_retries = 8000;
 	int max_retries = 8000;
 
 
 	if (useirq) {
 	if (useirq) {
-		if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
+		if (!host->check_int(host)) {
 
 
 			enable_irq(host->irq);
 			enable_irq(host->irq);
 
 
-			wait_event(host->irq_waitq,
-				readw(host->regs + NFC_CONFIG2) & NFC_INT);
-
-			tmp = readw(host->regs + NFC_CONFIG2);
-			tmp  &= ~NFC_INT;
-			writew(tmp, host->regs + NFC_CONFIG2);
+			wait_event(host->irq_waitq, host->check_int(host));
 		}
 		}
 	} else {
 	} else {
 		while (max_retries-- > 0) {
 		while (max_retries-- > 0) {
-			if (readw(host->regs + NFC_CONFIG2) & NFC_INT) {
-				tmp = readw(host->regs + NFC_CONFIG2);
-				tmp  &= ~NFC_INT;
-				writew(tmp, host->regs + NFC_CONFIG2);
+			if (host->check_int(host))
 				break;
 				break;
-			}
+
 			udelay(1);
 			udelay(1);
 		}
 		}
 		if (max_retries < 0)
 		if (max_retries < 0)
@@ -211,21 +275,33 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
 	}
 	}
 }
 }
 
 
+static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
+{
+	/* fill command */
+	writel(cmd, NFC_V3_FLASH_CMD);
+
+	/* send out command */
+	writel(NFC_CMD, NFC_V3_LAUNCH);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, useirq);
+}
+
 /* This function issues the specified command to the NAND device and
 /* This function issues the specified command to the NAND device and
  * waits for completion. */
  * waits for completion. */
-static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
+static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
 {
 {
 	DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
 	DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
 
 
-	writew(cmd, host->regs + NFC_FLASH_CMD);
-	writew(NFC_CMD, host->regs + NFC_CONFIG2);
+	writew(cmd, NFC_V1_V2_FLASH_CMD);
+	writew(NFC_CMD, NFC_V1_V2_CONFIG2);
 
 
 	if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
 	if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
 		int max_retries = 100;
 		int max_retries = 100;
 		/* Reset completion is indicated by NFC_CONFIG2 */
 		/* Reset completion is indicated by NFC_CONFIG2 */
 		/* being set to 0 */
 		/* being set to 0 */
 		while (max_retries-- > 0) {
 		while (max_retries-- > 0) {
-			if (readw(host->regs + NFC_CONFIG2) == 0) {
+			if (readw(NFC_V1_V2_CONFIG2) == 0) {
 				break;
 				break;
 			}
 			}
 			udelay(1);
 			udelay(1);
@@ -239,21 +315,48 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
 	}
 	}
 }
 }
 
 
+static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
+{
+	/* fill address */
+	writel(addr, NFC_V3_FLASH_ADDR0);
+
+	/* send out address */
+	writel(NFC_ADDR, NFC_V3_LAUNCH);
+
+	wait_op_done(host, 0);
+}
+
 /* This function sends an address (or partial address) to the
 /* This function sends an address (or partial address) to the
  * NAND device. The address is used to select the source/destination for
  * NAND device. The address is used to select the source/destination for
  * a NAND command. */
  * a NAND command. */
-static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
+static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
 {
 {
 	DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
 	DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
 
 
-	writew(addr, host->regs + NFC_FLASH_ADDR);
-	writew(NFC_ADDR, host->regs + NFC_CONFIG2);
+	writew(addr, NFC_V1_V2_FLASH_ADDR);
+	writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
 
 
 	/* Wait for operation to complete */
 	/* Wait for operation to complete */
 	wait_op_done(host, islast);
 	wait_op_done(host, islast);
 }
 }
 
 
-static void send_page(struct mtd_info *mtd, unsigned int ops)
+static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint32_t tmp;
+
+	tmp = readl(NFC_V3_CONFIG1);
+	tmp &= ~(7 << 4);
+	writel(tmp, NFC_V3_CONFIG1);
+
+	/* transfer data from NFC ram to nand */
+	writel(ops, NFC_V3_LAUNCH);
+
+	wait_op_done(host, false);
+}
+
+static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops)
 {
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
@@ -267,24 +370,34 @@ static void send_page(struct mtd_info *mtd, unsigned int ops)
 	for (i = 0; i < bufs; i++) {
 	for (i = 0; i < bufs; i++) {
 
 
 		/* NANDFC buffer 0 is used for page read/write */
 		/* NANDFC buffer 0 is used for page read/write */
-		writew(i, host->regs + NFC_BUF_ADDR);
+		writew(i, NFC_V1_V2_BUF_ADDR);
 
 
-		writew(ops, host->regs + NFC_CONFIG2);
+		writew(ops, NFC_V1_V2_CONFIG2);
 
 
 		/* Wait for operation to complete */
 		/* Wait for operation to complete */
 		wait_op_done(host, true);
 		wait_op_done(host, true);
 	}
 	}
 }
 }
 
 
+static void send_read_id_v3(struct mxc_nand_host *host)
+{
+	/* Read ID into main buffer */
+	writel(NFC_ID, NFC_V3_LAUNCH);
+
+	wait_op_done(host, true);
+
+	memcpy(host->data_buf, host->main_area0, 16);
+}
+
 /* Request the NANDFC to perform a read of the NAND device ID. */
 /* Request the NANDFC to perform a read of the NAND device ID. */
-static void send_read_id(struct mxc_nand_host *host)
+static void send_read_id_v1_v2(struct mxc_nand_host *host)
 {
 {
 	struct nand_chip *this = &host->nand;
 	struct nand_chip *this = &host->nand;
 
 
 	/* NANDFC buffer 0 is used for device ID output */
 	/* NANDFC buffer 0 is used for device ID output */
-	writew(0x0, host->regs + NFC_BUF_ADDR);
+	writew(0x0, NFC_V1_V2_BUF_ADDR);
 
 
-	writew(NFC_ID, host->regs + NFC_CONFIG2);
+	writew(NFC_ID, NFC_V1_V2_CONFIG2);
 
 
 	/* Wait for operation to complete */
 	/* Wait for operation to complete */
 	wait_op_done(host, true);
 	wait_op_done(host, true);
@@ -301,29 +414,36 @@ static void send_read_id(struct mxc_nand_host *host)
 	memcpy(host->data_buf, host->main_area0, 16);
 	memcpy(host->data_buf, host->main_area0, 16);
 }
 }
 
 
+static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
+{
+	writew(NFC_STATUS, NFC_V3_LAUNCH);
+	wait_op_done(host, true);
+
+	return readl(NFC_V3_CONFIG1) >> 16;
+}
+
 /* This function requests the NANDFC to perform a read of the
 /* This function requests the NANDFC to perform a read of the
  * NAND device status and returns the current status. */
  * NAND device status and returns the current status. */
-static uint16_t get_dev_status(struct mxc_nand_host *host)
+static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
 {
 {
-	void __iomem *main_buf = host->main_area1;
+	void __iomem *main_buf = host->main_area0;
 	uint32_t store;
 	uint32_t store;
 	uint16_t ret;
 	uint16_t ret;
-	/* Issue status request to NAND device */
 
 
-	/* store the main area1 first word, later do recovery */
-	store = readl(main_buf);
-	/* NANDFC buffer 1 is used for device status to prevent
-	 * corruption of read/write buffer on status requests. */
-	writew(1, host->regs + NFC_BUF_ADDR);
+	writew(0x0, NFC_V1_V2_BUF_ADDR);
 
 
-	writew(NFC_STATUS, host->regs + NFC_CONFIG2);
+	/*
+	 * The device status is stored in main_area0. To
+	 * prevent corruption of the buffer save the value
+	 * and restore it afterwards.
+	 */
+	store = readl(main_buf);
 
 
-	/* Wait for operation to complete */
+	writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
 	wait_op_done(host, true);
 	wait_op_done(host, true);
 
 
-	/* Status is placed in first word of main buffer */
-	/* get status, then recovery area 1 data */
 	ret = readw(main_buf);
 	ret = readw(main_buf);
+
 	writel(store, main_buf);
 	writel(store, main_buf);
 
 
 	return ret;
 	return ret;
@@ -347,7 +467,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 	 */
 	 */
 }
 }
 
 
-static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
 				 u_char *read_ecc, u_char *calc_ecc)
 				 u_char *read_ecc, u_char *calc_ecc)
 {
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct nand_chip *nand_chip = mtd->priv;
@@ -358,7 +478,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 	 * additional correction.  2-Bit errors cannot be corrected by
 	 * additional correction.  2-Bit errors cannot be corrected by
 	 * HW ECC, so we need to return failure
 	 * HW ECC, so we need to return failure
 	 */
 	 */
-	uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT);
+	uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT);
 
 
 	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
 	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
 		DEBUG(MTD_DEBUG_LEVEL0,
 		DEBUG(MTD_DEBUG_LEVEL0,
@@ -369,6 +489,43 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 	return 0;
 	return 0;
 }
 }
 
 
+static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
+				 u_char *read_ecc, u_char *calc_ecc)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	u32 ecc_stat, err;
+	int no_subpages = 1;
+	int ret = 0;
+	u8 ecc_bit_mask, err_limit;
+
+	ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
+	err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
+
+	no_subpages = mtd->writesize >> 9;
+
+	if (nfc_is_v21())
+		ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT);
+	else
+		ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT);
+
+	do {
+		err = ecc_stat & ecc_bit_mask;
+		if (err > err_limit) {
+			printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
+			return -1;
+		} else {
+			ret += err;
+		}
+		ecc_stat >>= 4;
+	} while (--no_subpages);
+
+	mtd->ecc_stats.corrected += ret;
+	pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
+
+	return ret;
+}
+
 static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 				  u_char *ecc_code)
 				  u_char *ecc_code)
 {
 {
@@ -383,7 +540,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
 
 
 	/* Check for status request */
 	/* Check for status request */
 	if (host->status_request)
 	if (host->status_request)
-		return get_dev_status(host) & 0xFF;
+		return host->get_dev_status(host) & 0xFF;
 
 
 	ret = *(uint8_t *)(host->data_buf + host->buf_start);
 	ret = *(uint8_t *)(host->data_buf + host->buf_start);
 	host->buf_start++;
 	host->buf_start++;
@@ -519,71 +676,163 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 		 * we will used the saved column address to index into
 		 * we will used the saved column address to index into
 		 * the full page.
 		 * the full page.
 		 */
 		 */
-		send_addr(host, 0, page_addr == -1);
+		host->send_addr(host, 0, page_addr == -1);
 		if (mtd->writesize > 512)
 		if (mtd->writesize > 512)
 			/* another col addr cycle for 2k page */
 			/* another col addr cycle for 2k page */
-			send_addr(host, 0, false);
+			host->send_addr(host, 0, false);
 	}
 	}
 
 
 	/* Write out page address, if necessary */
 	/* Write out page address, if necessary */
 	if (page_addr != -1) {
 	if (page_addr != -1) {
 		/* paddr_0 - p_addr_7 */
 		/* paddr_0 - p_addr_7 */
-		send_addr(host, (page_addr & 0xff), false);
+		host->send_addr(host, (page_addr & 0xff), false);
 
 
 		if (mtd->writesize > 512) {
 		if (mtd->writesize > 512) {
 			if (mtd->size >= 0x10000000) {
 			if (mtd->size >= 0x10000000) {
 				/* paddr_8 - paddr_15 */
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, false);
-				send_addr(host, (page_addr >> 16) & 0xff, true);
+				host->send_addr(host, (page_addr >> 8) & 0xff, false);
+				host->send_addr(host, (page_addr >> 16) & 0xff, true);
 			} else
 			} else
 				/* paddr_8 - paddr_15 */
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, true);
+				host->send_addr(host, (page_addr >> 8) & 0xff, true);
 		} else {
 		} else {
 			/* One more address cycle for higher density devices */
 			/* One more address cycle for higher density devices */
 			if (mtd->size >= 0x4000000) {
 			if (mtd->size >= 0x4000000) {
 				/* paddr_8 - paddr_15 */
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, false);
-				send_addr(host, (page_addr >> 16) & 0xff, true);
+				host->send_addr(host, (page_addr >> 8) & 0xff, false);
+				host->send_addr(host, (page_addr >> 16) & 0xff, true);
 			} else
 			} else
 				/* paddr_8 - paddr_15 */
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, true);
+				host->send_addr(host, (page_addr >> 8) & 0xff, true);
 		}
 		}
 	}
 	}
 }
 }
 
 
-static void preset(struct mtd_info *mtd)
+/*
+ * v2 and v3 type controllers can do 4bit or 8bit ecc depending
+ * on how much oob the nand chip has. For 8bit ecc we need at least
+ * 26 bytes of oob data per 512 byte block.
+ */
+static int get_eccsize(struct mtd_info *mtd)
+{
+	int oobbytes_per_512 = 0;
+
+	oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
+
+	if (oobbytes_per_512 < 26)
+		return 4;
+	else
+		return 8;
+}
+
+static void preset_v1_v2(struct mtd_info *mtd)
 {
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
 	uint16_t tmp;
 	uint16_t tmp;
 
 
 	/* enable interrupt, disable spare enable */
 	/* enable interrupt, disable spare enable */
-	tmp = readw(host->regs + NFC_CONFIG1);
-	tmp &= ~NFC_INT_MSK;
-	tmp &= ~NFC_SP_EN;
+	tmp = readw(NFC_V1_V2_CONFIG1);
+	tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
+	tmp &= ~NFC_V1_V2_CONFIG1_SP_EN;
 	if (nand_chip->ecc.mode == NAND_ECC_HW) {
 	if (nand_chip->ecc.mode == NAND_ECC_HW) {
-		tmp |= NFC_ECC_EN;
+		tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
+	} else {
+		tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN;
+	}
+
+	if (nfc_is_v21() && mtd->writesize) {
+		host->eccsize = get_eccsize(mtd);
+		if (host->eccsize == 4)
+			tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
 	} else {
 	} else {
-		tmp &= ~NFC_ECC_EN;
+		host->eccsize = 1;
 	}
 	}
-	writew(tmp, host->regs + NFC_CONFIG1);
+
+	writew(tmp, NFC_V1_V2_CONFIG1);
 	/* preset operation */
 	/* preset operation */
 
 
 	/* Unlock the internal RAM Buffer */
 	/* Unlock the internal RAM Buffer */
-	writew(0x2, host->regs + NFC_CONFIG);
+	writew(0x2, NFC_V1_V2_CONFIG);
 
 
 	/* Blocks to be unlocked */
 	/* Blocks to be unlocked */
 	if (nfc_is_v21()) {
 	if (nfc_is_v21()) {
-		writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
-		writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
+		writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR);
+		writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR);
 	} else if (nfc_is_v1()) {
 	} else if (nfc_is_v1()) {
-		writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
-		writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
+		writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
+		writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR);
 	} else
 	} else
 		BUG();
 		BUG();
 
 
 	/* Unlock Block Command for given address range */
 	/* Unlock Block Command for given address range */
-	writew(0x4, host->regs + NFC_WRPROT);
+	writew(0x4, NFC_V1_V2_WRPROT);
+}
+
+static void preset_v3(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxc_nand_host *host = chip->priv;
+	uint32_t config2, config3;
+	int i, addr_phases;
+
+	writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
+	writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
+
+	/* Unlock the internal RAM Buffer */
+	writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
+			NFC_V3_WRPROT);
+
+	/* Blocks to be unlocked */
+	for (i = 0; i < NAND_MAX_CHIPS; i++)
+		writel(0x0 |	(0xffff << 16),
+				NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
+
+	writel(0, NFC_V3_IPC);
+
+	config2 = NFC_V3_CONFIG2_ONE_CYCLE |
+		NFC_V3_CONFIG2_2CMD_PHASES |
+		NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
+		NFC_V3_CONFIG2_ST_CMD(0x70) |
+		NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
+
+	if (chip->ecc.mode == NAND_ECC_HW)
+		config2 |= NFC_V3_CONFIG2_ECC_EN;
+
+	addr_phases = fls(chip->pagemask) >> 3;
+
+	if (mtd->writesize == 2048) {
+		config2 |= NFC_V3_CONFIG2_PS_2048;
+		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
+	} else if (mtd->writesize == 4096) {
+		config2 |= NFC_V3_CONFIG2_PS_4096;
+		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
+	} else {
+		config2 |= NFC_V3_CONFIG2_PS_512;
+		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
+	}
+
+	if (mtd->writesize) {
+		config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
+		host->eccsize = get_eccsize(mtd);
+		if (host->eccsize == 8)
+			config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
+	}
+
+	writel(config2, NFC_V3_CONFIG2);
+
+	config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
+			NFC_V3_CONFIG3_NO_SDMA |
+			NFC_V3_CONFIG3_RBB_MODE |
+			NFC_V3_CONFIG3_SBB(6) | /* Reset default */
+			NFC_V3_CONFIG3_ADD_OP(0);
+
+	if (!(chip->options & NAND_BUSWIDTH_16))
+		config3 |= NFC_V3_CONFIG3_FW8;
+
+	writel(config3, NFC_V3_CONFIG3);
+
+	writel(0, NFC_V3_DELAY_LINE);
 }
 }
 
 
 /* Used by the upper layer to write command to NAND Flash for
 /* Used by the upper layer to write command to NAND Flash for
@@ -604,15 +853,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 	/* Command pre-processing step */
 	/* Command pre-processing step */
 	switch (command) {
 	switch (command) {
 	case NAND_CMD_RESET:
 	case NAND_CMD_RESET:
-		send_cmd(host, command, false);
-		preset(mtd);
+		host->preset(mtd);
+		host->send_cmd(host, command, false);
 		break;
 		break;
 
 
 	case NAND_CMD_STATUS:
 	case NAND_CMD_STATUS:
 		host->buf_start = 0;
 		host->buf_start = 0;
 		host->status_request = true;
 		host->status_request = true;
 
 
-		send_cmd(host, command, true);
+		host->send_cmd(host, command, true);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 		break;
 
 
@@ -625,13 +874,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 
 
 		command = NAND_CMD_READ0; /* only READ0 is valid */
 		command = NAND_CMD_READ0; /* only READ0 is valid */
 
 
-		send_cmd(host, command, false);
+		host->send_cmd(host, command, false);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 
 
 		if (mtd->writesize > 512)
 		if (mtd->writesize > 512)
-			send_cmd(host, NAND_CMD_READSTART, true);
+			host->send_cmd(host, NAND_CMD_READSTART, true);
 
 
-		send_page(mtd, NFC_OUTPUT);
+		host->send_page(mtd, NFC_OUTPUT);
 
 
 		memcpy(host->data_buf, host->main_area0, mtd->writesize);
 		memcpy(host->data_buf, host->main_area0, mtd->writesize);
 		copy_spare(mtd, true);
 		copy_spare(mtd, true);
@@ -644,28 +893,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 
 
 		host->buf_start = column;
 		host->buf_start = column;
 
 
-		send_cmd(host, command, false);
+		host->send_cmd(host, command, false);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 		break;
 
 
 	case NAND_CMD_PAGEPROG:
 	case NAND_CMD_PAGEPROG:
 		memcpy(host->main_area0, host->data_buf, mtd->writesize);
 		memcpy(host->main_area0, host->data_buf, mtd->writesize);
 		copy_spare(mtd, false);
 		copy_spare(mtd, false);
-		send_page(mtd, NFC_INPUT);
-		send_cmd(host, command, true);
+		host->send_page(mtd, NFC_INPUT);
+		host->send_cmd(host, command, true);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 		break;
 
 
 	case NAND_CMD_READID:
 	case NAND_CMD_READID:
-		send_cmd(host, command, true);
+		host->send_cmd(host, command, true);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		mxc_do_addr_cycle(mtd, column, page_addr);
-		send_read_id(host);
+		host->send_read_id(host);
 		host->buf_start = column;
 		host->buf_start = column;
 		break;
 		break;
 
 
 	case NAND_CMD_ERASE1:
 	case NAND_CMD_ERASE1:
 	case NAND_CMD_ERASE2:
 	case NAND_CMD_ERASE2:
-		send_cmd(host, command, false);
+		host->send_cmd(host, command, false);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 
 
 		break;
 		break;
@@ -761,22 +1010,55 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	host->main_area0 = host->base;
 	host->main_area0 = host->base;
-	host->main_area1 = host->base + 0x200;
+
+	if (nfc_is_v1() || nfc_is_v21()) {
+		host->preset = preset_v1_v2;
+		host->send_cmd = send_cmd_v1_v2;
+		host->send_addr = send_addr_v1_v2;
+		host->send_page = send_page_v1_v2;
+		host->send_read_id = send_read_id_v1_v2;
+		host->get_dev_status = get_dev_status_v1_v2;
+		host->check_int = check_int_v1_v2;
+	}
 
 
 	if (nfc_is_v21()) {
 	if (nfc_is_v21()) {
-		host->regs = host->base + 0x1000;
+		host->regs = host->base + 0x1e00;
 		host->spare0 = host->base + 0x1000;
 		host->spare0 = host->base + 0x1000;
 		host->spare_len = 64;
 		host->spare_len = 64;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
 		this->ecc.bytes = 9;
 		this->ecc.bytes = 9;
 	} else if (nfc_is_v1()) {
 	} else if (nfc_is_v1()) {
-		host->regs = host->base;
+		host->regs = host->base + 0xe00;
 		host->spare0 = host->base + 0x800;
 		host->spare0 = host->base + 0x800;
 		host->spare_len = 16;
 		host->spare_len = 16;
 		oob_smallpage = &nandv1_hw_eccoob_smallpage;
 		oob_smallpage = &nandv1_hw_eccoob_smallpage;
 		oob_largepage = &nandv1_hw_eccoob_largepage;
 		oob_largepage = &nandv1_hw_eccoob_largepage;
 		this->ecc.bytes = 3;
 		this->ecc.bytes = 3;
+		host->eccsize = 1;
+	} else if (nfc_is_v3_2()) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		if (!res) {
+			err = -ENODEV;
+			goto eirq;
+		}
+		host->regs_ip = ioremap(res->start, resource_size(res));
+		if (!host->regs_ip) {
+			err = -ENOMEM;
+			goto eirq;
+		}
+		host->regs_axi = host->base + 0x1e00;
+		host->spare0 = host->base + 0x1000;
+		host->spare_len = 64;
+		host->preset = preset_v3;
+		host->send_cmd = send_cmd_v3;
+		host->send_addr = send_addr_v3;
+		host->send_page = send_page_v3;
+		host->send_read_id = send_read_id_v3;
+		host->check_int = check_int_v3;
+		host->get_dev_status = get_dev_status_v3;
+		oob_smallpage = &nandv2_hw_eccoob_smallpage;
+		oob_largepage = &nandv2_hw_eccoob_largepage;
 	} else
 	} else
 		BUG();
 		BUG();
 
 
@@ -786,7 +1068,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	if (pdata->hw_ecc) {
 	if (pdata->hw_ecc) {
 		this->ecc.calculate = mxc_nand_calculate_ecc;
 		this->ecc.calculate = mxc_nand_calculate_ecc;
 		this->ecc.hwctl = mxc_nand_enable_hwecc;
 		this->ecc.hwctl = mxc_nand_enable_hwecc;
-		this->ecc.correct = mxc_nand_correct_data;
+		if (nfc_is_v1())
+			this->ecc.correct = mxc_nand_correct_data_v1;
+		else
+			this->ecc.correct = mxc_nand_correct_data_v2_v3;
 		this->ecc.mode = NAND_ECC_HW;
 		this->ecc.mode = NAND_ECC_HW;
 	} else {
 	} else {
 		this->ecc.mode = NAND_ECC_SOFT;
 		this->ecc.mode = NAND_ECC_SOFT;
@@ -817,6 +1102,9 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 		goto escan;
 		goto escan;
 	}
 	}
 
 
+	/* Call preset again, with correct writesize this time */
+	host->preset(mtd);
+
 	if (mtd->writesize == 2048)
 	if (mtd->writesize == 2048)
 		this->ecc.layout = oob_largepage;
 		this->ecc.layout = oob_largepage;
 
 
@@ -848,6 +1136,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 escan:
 escan:
 	free_irq(host->irq, host);
 	free_irq(host->irq, host);
 eirq:
 eirq:
+	if (host->regs_ip)
+		iounmap(host->regs_ip);
 	iounmap(host->base);
 	iounmap(host->base);
 eres:
 eres:
 	clk_put(host->clk);
 	clk_put(host->clk);
@@ -867,59 +1157,19 @@ static int __devexit mxcnd_remove(struct platform_device *pdev)
 
 
 	nand_release(&host->mtd);
 	nand_release(&host->mtd);
 	free_irq(host->irq, host);
 	free_irq(host->irq, host);
+	if (host->regs_ip)
+		iounmap(host->regs_ip);
 	iounmap(host->base);
 	iounmap(host->base);
 	kfree(host);
 	kfree(host);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-#ifdef CONFIG_PM
-static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
-	int ret = 0;
-
-	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n");
-
-	ret = mtd->suspend(mtd);
-
-	/*
-	 * nand_suspend locks the device for exclusive access, so
-	 * the clock must already be off.
-	 */
-	BUG_ON(!ret && host->clk_act);
-
-	return ret;
-}
-
-static int mxcnd_resume(struct platform_device *pdev)
-{
-	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
-	int ret = 0;
-
-	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
-
-	mtd->resume(mtd);
-
-	return ret;
-}
-
-#else
-# define mxcnd_suspend   NULL
-# define mxcnd_resume    NULL
-#endif				/* CONFIG_PM */
-
 static struct platform_driver mxcnd_driver = {
 static struct platform_driver mxcnd_driver = {
 	.driver = {
 	.driver = {
 		   .name = DRIVER_NAME,
 		   .name = DRIVER_NAME,
-		   },
+	},
 	.remove = __devexit_p(mxcnd_remove),
 	.remove = __devexit_p(mxcnd_remove),
-	.suspend = mxcnd_suspend,
-	.resume = mxcnd_resume,
 };
 };
 
 
 static int __init mxc_nd_init(void)
 static int __init mxc_nd_init(void)

+ 61 - 18
drivers/mtd/nand/nand_base.c

@@ -42,7 +42,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/compatmac.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/leds.h>
 #include <linux/leds.h>
@@ -347,7 +346,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 	struct nand_chip *chip = mtd->priv;
 	struct nand_chip *chip = mtd->priv;
 	u16 bad;
 	u16 bad;
 
 
-	if (chip->options & NAND_BB_LAST_PAGE)
+	if (chip->options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 		ofs += mtd->erasesize - mtd->writesize;
 
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
@@ -397,9 +396,9 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
 {
 	struct nand_chip *chip = mtd->priv;
 	struct nand_chip *chip = mtd->priv;
 	uint8_t buf[2] = { 0, 0 };
 	uint8_t buf[2] = { 0, 0 };
-	int block, ret;
+	int block, ret, i = 0;
 
 
-	if (chip->options & NAND_BB_LAST_PAGE)
+	if (chip->options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 		ofs += mtd->erasesize - mtd->writesize;
 
 
 	/* Get block number */
 	/* Get block number */
@@ -411,17 +410,31 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	if (chip->options & NAND_USE_FLASH_BBT)
 	if (chip->options & NAND_USE_FLASH_BBT)
 		ret = nand_update_bbt(mtd, ofs);
 		ret = nand_update_bbt(mtd, ofs);
 	else {
 	else {
-		/* We write two bytes, so we dont have to mess with 16 bit
-		 * access
-		 */
 		nand_get_device(chip, mtd, FL_WRITING);
 		nand_get_device(chip, mtd, FL_WRITING);
-		ofs += mtd->oobsize;
-		chip->ops.len = chip->ops.ooblen = 2;
-		chip->ops.datbuf = NULL;
-		chip->ops.oobbuf = buf;
-		chip->ops.ooboffs = chip->badblockpos & ~0x01;
 
 
-		ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+		/* Write to first two pages and to byte 1 and 6 if necessary.
+		 * If we write to more than one location, the first error
+		 * encountered quits the procedure. We write two bytes per
+		 * location, so we dont have to mess with 16 bit access.
+		 */
+		do {
+			chip->ops.len = chip->ops.ooblen = 2;
+			chip->ops.datbuf = NULL;
+			chip->ops.oobbuf = buf;
+			chip->ops.ooboffs = chip->badblockpos & ~0x01;
+
+			ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+
+			if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) {
+				chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS
+					& ~0x01;
+				ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+			}
+			i++;
+			ofs += mtd->writesize;
+		} while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) &&
+				i < 2);
+
 		nand_release_device(mtd);
 		nand_release_device(mtd);
 	}
 	}
 	if (!ret)
 	if (!ret)
@@ -2920,9 +2933,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
 		chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
 
 
 	/* Set the bad block position */
 	/* Set the bad block position */
-	chip->badblockpos = mtd->writesize > 512 ?
-		NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
-	chip->badblockbits = 8;
+	if (!(busw & NAND_BUSWIDTH_16) && (*maf_id == NAND_MFR_STMICRO ||
+				(*maf_id == NAND_MFR_SAMSUNG &&
+				 mtd->writesize == 512) ||
+				*maf_id == NAND_MFR_AMD))
+		chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
+	else
+		chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
+
 
 
 	/* Get chip options, preserve non chip based options */
 	/* Get chip options, preserve non chip based options */
 	chip->options &= ~NAND_CHIPOPTIONS_MSK;
 	chip->options &= ~NAND_CHIPOPTIONS_MSK;
@@ -2941,12 +2959,32 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
 
 	/*
 	/*
 	 * Bad block marker is stored in the last page of each block
 	 * Bad block marker is stored in the last page of each block
-	 * on Samsung and Hynix MLC devices
+	 * on Samsung and Hynix MLC devices; stored in first two pages
+	 * of each block on Micron devices with 2KiB pages and on
+	 * SLC Samsung, Hynix, and AMD/Spansion. All others scan only
+	 * the first page.
 	 */
 	 */
 	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
 	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
 			(*maf_id == NAND_MFR_SAMSUNG ||
 			(*maf_id == NAND_MFR_SAMSUNG ||
 			 *maf_id == NAND_MFR_HYNIX))
 			 *maf_id == NAND_MFR_HYNIX))
-		chip->options |= NAND_BB_LAST_PAGE;
+		chip->options |= NAND_BBT_SCANLASTPAGE;
+	else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+				(*maf_id == NAND_MFR_SAMSUNG ||
+				 *maf_id == NAND_MFR_HYNIX ||
+				 *maf_id == NAND_MFR_AMD)) ||
+			(mtd->writesize == 2048 &&
+			 *maf_id == NAND_MFR_MICRON))
+		chip->options |= NAND_BBT_SCAN2NDPAGE;
+
+	/*
+	 * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6
+	 */
+	if (!(busw & NAND_BUSWIDTH_16) &&
+			*maf_id == NAND_MFR_STMICRO &&
+			mtd->writesize == 2048) {
+		chip->options |= NAND_BBT_SCANBYTE1AND6;
+		chip->badblockpos = 0;
+	}
 
 
 	/* Check for AND chips with 4 page planes */
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
 	if (chip->options & NAND_4PAGE_ARRAY)
@@ -3306,6 +3344,11 @@ void nand_release(struct mtd_info *mtd)
 	kfree(chip->bbt);
 	kfree(chip->bbt);
 	if (!(chip->options & NAND_OWN_BUFFERS))
 	if (!(chip->options & NAND_OWN_BUFFERS))
 		kfree(chip->buffers);
 		kfree(chip->buffers);
+
+	/* Free bad block descriptor memory */
+	if (chip->badblock_pattern && chip->badblock_pattern->options
+			& NAND_BBT_DYNAMICSTRUCT)
+		kfree(chip->badblock_pattern);
 }
 }
 
 
 EXPORT_SYMBOL_GPL(nand_lock);
 EXPORT_SYMBOL_GPL(nand_lock);

+ 75 - 28
drivers/mtd/nand/nand_bbt.c

@@ -55,7 +55,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/compatmac.h>
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/vmalloc.h>
@@ -93,6 +92,28 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
 			return -1;
 			return -1;
 	}
 	}
 
 
+	/* Check both positions 1 and 6 for pattern? */
+	if (td->options & NAND_BBT_SCANBYTE1AND6) {
+		if (td->options & NAND_BBT_SCANEMPTY) {
+			p += td->len;
+			end += NAND_SMALL_BADBLOCK_POS - td->offs;
+			/* Check region between positions 1 and 6 */
+			for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len;
+					i++) {
+				if (*p++ != 0xff)
+					return -1;
+			}
+		}
+		else {
+			p += NAND_SMALL_BADBLOCK_POS - td->offs;
+		}
+		/* Compare the pattern */
+		for (i = 0; i < td->len; i++) {
+			if (p[i] != td->pattern[i])
+				return -1;
+		}
+	}
+
 	if (td->options & NAND_BBT_SCANEMPTY) {
 	if (td->options & NAND_BBT_SCANEMPTY) {
 		p += td->len;
 		p += td->len;
 		end += td->len;
 		end += td->len;
@@ -124,6 +145,13 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
 		if (p[td->offs + i] != td->pattern[i])
 		if (p[td->offs + i] != td->pattern[i])
 			return -1;
 			return -1;
 	}
 	}
+	/* Need to check location 1 AND 6? */
+	if (td->options & NAND_BBT_SCANBYTE1AND6) {
+		for (i = 0; i < td->len; i++) {
+			if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i])
+				return -1;
+		}
+	}
 	return 0;
 	return 0;
 }
 }
 
 
@@ -397,12 +425,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 
 	if (bd->options & NAND_BBT_SCANALLPAGES)
 	if (bd->options & NAND_BBT_SCANALLPAGES)
 		len = 1 << (this->bbt_erase_shift - this->page_shift);
 		len = 1 << (this->bbt_erase_shift - this->page_shift);
-	else {
-		if (bd->options & NAND_BBT_SCAN2NDPAGE)
-			len = 2;
-		else
-			len = 1;
-	}
+	else if (bd->options & NAND_BBT_SCAN2NDPAGE)
+		len = 2;
+	else
+		len = 1;
 
 
 	if (!(bd->options & NAND_BBT_SCANEMPTY)) {
 	if (!(bd->options & NAND_BBT_SCANEMPTY)) {
 		/* We need only read few bytes from the OOB area */
 		/* We need only read few bytes from the OOB area */
@@ -432,7 +458,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 		from = (loff_t)startblock << (this->bbt_erase_shift - 1);
 		from = (loff_t)startblock << (this->bbt_erase_shift - 1);
 	}
 	}
 
 
-	if (this->options & NAND_BB_LAST_PAGE)
+	if (this->options & NAND_BBT_SCANLASTPAGE)
 		from += mtd->erasesize - (mtd->writesize * len);
 		from += mtd->erasesize - (mtd->writesize * len);
 
 
 	for (i = startblock; i < numblocks;) {
 	for (i = startblock; i < numblocks;) {
@@ -1092,30 +1118,16 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
  * while scanning a device for factory marked good / bad blocks. */
  * while scanning a device for factory marked good / bad blocks. */
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
 
-static struct nand_bbt_descr smallpage_memorybased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 5,
-	.len = 1,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr largepage_memorybased = {
-	.options = 0,
-	.offs = 0,
-	.len = 2,
-	.pattern = scan_ff_pattern
-};
-
 static struct nand_bbt_descr smallpage_flashbased = {
 static struct nand_bbt_descr smallpage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
 	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 5,
+	.offs = NAND_SMALL_BADBLOCK_POS,
 	.len = 1,
 	.len = 1,
 	.pattern = scan_ff_pattern
 	.pattern = scan_ff_pattern
 };
 };
 
 
 static struct nand_bbt_descr largepage_flashbased = {
 static struct nand_bbt_descr largepage_flashbased = {
 	.options = NAND_BBT_SCAN2NDPAGE,
 	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 0,
+	.offs = NAND_LARGE_BADBLOCK_POS,
 	.len = 2,
 	.len = 2,
 	.pattern = scan_ff_pattern
 	.pattern = scan_ff_pattern
 };
 };
@@ -1154,6 +1166,43 @@ static struct nand_bbt_descr bbt_mirror_descr = {
 	.pattern = mirror_pattern
 	.pattern = mirror_pattern
 };
 };
 
 
+#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \
+		NAND_BBT_SCANBYTE1AND6)
+/**
+ * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure
+ * @this:	NAND chip to create descriptor for
+ *
+ * This function allocates and initializes a nand_bbt_descr for BBM detection
+ * based on the properties of "this". The new descriptor is stored in
+ * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
+ * passed to this function.
+ *
+ * TODO: Handle other flags, replace other static structs
+ *        (e.g. handle NAND_BBT_FLASH for flash-based BBT,
+ *             replace smallpage_flashbased)
+ *
+ */
+static int nand_create_default_bbt_descr(struct nand_chip *this)
+{
+	struct nand_bbt_descr *bd;
+	if (this->badblock_pattern) {
+		printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
+		return -EINVAL;
+	}
+	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
+	if (!bd) {
+		printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n");
+		return -ENOMEM;
+	}
+	bd->options = this->options & BBT_SCAN_OPTIONS;
+	bd->offs = this->badblockpos;
+	bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
+	bd->pattern = scan_ff_pattern;
+	bd->options |= NAND_BBT_DYNAMICSTRUCT;
+	this->badblock_pattern = bd;
+	return 0;
+}
+
 /**
 /**
  * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
  * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
  * @mtd:	MTD device structure
  * @mtd:	MTD device structure
@@ -1196,10 +1245,8 @@ int nand_default_bbt(struct mtd_info *mtd)
 	} else {
 	} else {
 		this->bbt_td = NULL;
 		this->bbt_td = NULL;
 		this->bbt_md = NULL;
 		this->bbt_md = NULL;
-		if (!this->badblock_pattern) {
-			this->badblock_pattern = (mtd->writesize > 512) ?
-			    &largepage_memorybased : &smallpage_memorybased;
-		}
+		if (!this->badblock_pattern)
+			nand_create_default_bbt_descr(this);
 	}
 	}
 	return nand_scan_bbt(mtd, this->badblock_pattern);
 	return nand_scan_bbt(mtd, this->badblock_pattern);
 }
 }

+ 4 - 0
drivers/mtd/nand/nand_ids.c

@@ -85,6 +85,7 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"NAND 128MiB 3,3V 8-bit",	0xD1, 0, 128, 0, LP_OPTIONS},
 	{"NAND 128MiB 3,3V 8-bit",	0xD1, 0, 128, 0, LP_OPTIONS},
 	{"NAND 128MiB 1,8V 16-bit",	0xB1, 0, 128, 0, LP_OPTIONS16},
 	{"NAND 128MiB 1,8V 16-bit",	0xB1, 0, 128, 0, LP_OPTIONS16},
 	{"NAND 128MiB 3,3V 16-bit",	0xC1, 0, 128, 0, LP_OPTIONS16},
 	{"NAND 128MiB 3,3V 16-bit",	0xC1, 0, 128, 0, LP_OPTIONS16},
+	{"NAND 128MiB 1,8V 16-bit",     0xAD, 0, 128, 0, LP_OPTIONS16},
 
 
 	/* 2 Gigabit */
 	/* 2 Gigabit */
 	{"NAND 256MiB 1,8V 8-bit",	0xAA, 0, 256, 0, LP_OPTIONS},
 	{"NAND 256MiB 1,8V 8-bit",	0xAA, 0, 256, 0, LP_OPTIONS},
@@ -110,6 +111,9 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"NAND 2GiB 1,8V 16-bit",	0xB5, 0, 2048, 0, LP_OPTIONS16},
 	{"NAND 2GiB 1,8V 16-bit",	0xB5, 0, 2048, 0, LP_OPTIONS16},
 	{"NAND 2GiB 3,3V 16-bit",	0xC5, 0, 2048, 0, LP_OPTIONS16},
 	{"NAND 2GiB 3,3V 16-bit",	0xC5, 0, 2048, 0, LP_OPTIONS16},
 
 
+	/* 32 Gigabit */
+	{"NAND 4GiB 3,3V 8-bit",	0xD7, 0, 4096, 0, LP_OPTIONS16},
+
 	/*
 	/*
 	 * Renesas AND 1 Gigabit. Those chips do not support extended id and
 	 * Renesas AND 1 Gigabit. Those chips do not support extended id and
 	 * have a strange page/block layout !  The chosen minimum erasesize is
 	 * have a strange page/block layout !  The chosen minimum erasesize is

+ 7 - 7
drivers/mtd/nand/nandsim.c

@@ -553,8 +553,8 @@ static uint64_t divide(uint64_t n, uint32_t d)
  */
  */
 static int init_nandsim(struct mtd_info *mtd)
 static int init_nandsim(struct mtd_info *mtd)
 {
 {
-	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
-	struct nandsim   *ns   = (struct nandsim *)(chip->priv);
+	struct nand_chip *chip = mtd->priv;
+	struct nandsim   *ns   = chip->priv;
 	int i, ret = 0;
 	int i, ret = 0;
 	uint64_t remains;
 	uint64_t remains;
 	uint64_t next_offset;
 	uint64_t next_offset;
@@ -1877,7 +1877,7 @@ static void switch_state(struct nandsim *ns)
 
 
 static u_char ns_nand_read_byte(struct mtd_info *mtd)
 static u_char ns_nand_read_byte(struct mtd_info *mtd)
 {
 {
-        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
+	struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
 	u_char outb = 0x00;
 	u_char outb = 0x00;
 
 
 	/* Sanity and correctness checks */
 	/* Sanity and correctness checks */
@@ -1950,7 +1950,7 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd)
 
 
 static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
 static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
 {
 {
-        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
+	struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
 
 
 	/* Sanity and correctness checks */
 	/* Sanity and correctness checks */
 	if (!ns->lines.ce) {
 	if (!ns->lines.ce) {
@@ -2132,7 +2132,7 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd)
 
 
 static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 {
-        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
+	struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
 
 
 	/* Check that chip is expecting data input */
 	/* Check that chip is expecting data input */
 	if (!(ns->state & STATE_DATAIN_MASK)) {
 	if (!(ns->state & STATE_DATAIN_MASK)) {
@@ -2159,7 +2159,7 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 
 
 static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
 {
-        struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
+	struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
 
 
 	/* Sanity and correctness checks */
 	/* Sanity and correctness checks */
 	if (!ns->lines.ce) {
 	if (!ns->lines.ce) {
@@ -2352,7 +2352,7 @@ module_init(ns_init_module);
  */
  */
 static void __exit ns_cleanup_module(void)
 static void __exit ns_cleanup_module(void)
 {
 {
-	struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv);
+	struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv;
 	int i;
 	int i;
 
 
 	free_nandsim(ns);    /* Free nandsim private resources */
 	free_nandsim(ns);    /* Free nandsim private resources */

+ 1 - 1
drivers/mtd/nand/plat_nand.c

@@ -91,7 +91,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	/* Scan to find existance of the device */
 	/* Scan to find existance of the device */
-	if (nand_scan(&data->mtd, 1)) {
+	if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
 		err = -ENXIO;
 		err = -ENXIO;
 		goto out;
 		goto out;
 	}
 	}

+ 3 - 3
drivers/mtd/nand/r852.c

@@ -64,8 +64,8 @@ static inline void r852_write_reg_dword(struct r852_device *dev,
 /* returns pointer to our private structure */
 /* returns pointer to our private structure */
 static inline struct r852_device *r852_get_dev(struct mtd_info *mtd)
 static inline struct r852_device *r852_get_dev(struct mtd_info *mtd)
 {
 {
-	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
-	return (struct r852_device *)chip->priv;
+	struct nand_chip *chip = mtd->priv;
+	return chip->priv;
 }
 }
 
 
 
 
@@ -380,7 +380,7 @@ void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl)
  */
  */
 int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
 int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
 {
-	struct r852_device *dev = (struct r852_device *)chip->priv;
+	struct r852_device *dev = chip->priv;
 
 
 	unsigned long timeout;
 	unsigned long timeout;
 	int status;
 	int status;

+ 0 - 1
drivers/mtd/nand/rtc_from4.c

@@ -24,7 +24,6 @@
 #include <linux/rslib.h>
 #include <linux/rslib.h>
 #include <linux/bitrev.h>
 #include <linux/bitrev.h>
 #include <linux/module.h>
 #include <linux/module.h>
-#include <linux/mtd/compatmac.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/partitions.h>

+ 6 - 9
drivers/mtd/nand/s3c2410.c

@@ -727,15 +727,12 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 	if (set == NULL)
 	if (set == NULL)
 		return add_mtd_device(&mtd->mtd);
 		return add_mtd_device(&mtd->mtd);
 
 
-	if (set->nr_partitions == 0) {
-		mtd->mtd.name = set->name;
-		nr_part = parse_mtd_partitions(&mtd->mtd, part_probes,
-						&part_info, 0);
-	} else {
-		if (set->nr_partitions > 0 && set->partitions != NULL) {
-			nr_part = set->nr_partitions;
-			part_info = set->partitions;
-		}
+	mtd->mtd.name = set->name;
+	nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0);
+
+	if (nr_part <= 0 && set->nr_partitions > 0) {
+		nr_part = set->nr_partitions;
+		part_info = set->partitions;
 	}
 	}
 
 
 	if (nr_part > 0 && part_info)
 	if (nr_part > 0 && part_info)

+ 1 - 1
drivers/mtd/nand/sm_common.c

@@ -109,7 +109,7 @@ static struct nand_flash_dev nand_xd_flash_ids[] = {
 
 
 int sm_register_device(struct mtd_info *mtd, int smartmedia)
 int sm_register_device(struct mtd_info *mtd, int smartmedia)
 {
 {
-	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	int ret;
 	int ret;
 
 
 	chip->options |= NAND_SKIP_BBTSCAN;
 	chip->options |= NAND_SKIP_BBTSCAN;

+ 18 - 7
drivers/mtd/nftlcore.c

@@ -1,11 +1,22 @@
-/* Linux driver for NAND Flash Translation Layer      */
-/* (c) 1999 Machine Vision Holdings, Inc.             */
-/* Author: David Woodhouse <dwmw2@infradead.org>      */
-
 /*
 /*
-  The contents of this file are distributed under the GNU General
-  Public License version 2. The author places no additional
-  restrictions of any kind on it.
+ * Linux driver for NAND Flash Translation Layer
+ *
+ * Copyright © 1999 Machine Vision Holdings, Inc.
+ * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
 #define PRERELEASE
 #define PRERELEASE

+ 2 - 1
drivers/mtd/nftlmount.c

@@ -2,7 +2,8 @@
  * NFTL mount code with extensive checks
  * NFTL mount code with extensive checks
  *
  *
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
- * Copyright (C) 2000 Netgem S.A.
+ * Copyright © 2000 Netgem S.A.
+ * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by

+ 2 - 2
drivers/mtd/ofpart.c

@@ -1,11 +1,11 @@
 /*
 /*
  * Flash partitions described by the OF (or flattened) device tree
  * Flash partitions described by the OF (or flattened) device tree
  *
  *
- * Copyright (C) 2006 MontaVista Software Inc.
+ * Copyright © 2006 MontaVista Software Inc.
  * Author: Vitaly Wool <vwool@ru.mvista.com>
  * Author: Vitaly Wool <vwool@ru.mvista.com>
  *
  *
  * Revised to handle newer style flash binding by:
  * Revised to handle newer style flash binding by:
- *   Copyright (C) 2007 David Gibson, IBM Corporation.
+ *   Copyright © 2007 David Gibson, IBM Corporation.
  *
  *
  * This program is free software; you can redistribute  it and/or modify it
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * under  the terms of  the GNU General  Public License as published by the

+ 2 - 2
drivers/mtd/onenand/Kconfig

@@ -25,14 +25,14 @@ config MTD_ONENAND_GENERIC
 
 
 config MTD_ONENAND_OMAP2
 config MTD_ONENAND_OMAP2
 	tristate "OneNAND on OMAP2/OMAP3 support"
 	tristate "OneNAND on OMAP2/OMAP3 support"
-	depends on MTD_ONENAND && (ARCH_OMAP2 || ARCH_OMAP3)
+	depends on ARCH_OMAP2 || ARCH_OMAP3
 	help
 	help
 	  Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU
 	  Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU
 	  via the GPMC memory controller.
 	  via the GPMC memory controller.
 
 
 config MTD_ONENAND_SAMSUNG
 config MTD_ONENAND_SAMSUNG
         tristate "OneNAND on Samsung SOC controller support"
         tristate "OneNAND on Samsung SOC controller support"
-        depends on MTD_ONENAND && (ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210)
+        depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210
         help
         help
           Support for a OneNAND flash device connected to an Samsung SOC
           Support for a OneNAND flash device connected to an Samsung SOC
           S3C64XX/S5PC1XX controller.
           S3C64XX/S5PC1XX controller.

+ 35 - 14
drivers/mtd/onenand/onenand_base.c

@@ -377,8 +377,11 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
 
 
 	default:
 	default:
 		block = onenand_block(this, addr);
 		block = onenand_block(this, addr);
-		page = (int) (addr - onenand_addr(this, block)) >> this->page_shift;
-
+		if (FLEXONENAND(this))
+			page = (int) (addr - onenand_addr(this, block))>>\
+				this->page_shift;
+		else
+			page = (int) (addr >> this->page_shift);
 		if (ONENAND_IS_2PLANE(this)) {
 		if (ONENAND_IS_2PLANE(this)) {
 			/* Make the even block number */
 			/* Make the even block number */
 			block &= ~1;
 			block &= ~1;
@@ -3730,17 +3733,16 @@ out:
 }
 }
 
 
 /**
 /**
- * onenand_probe - [OneNAND Interface] Probe the OneNAND device
+ * onenand_chip_probe - [OneNAND Interface] The generic chip probe
  * @param mtd		MTD device structure
  * @param mtd		MTD device structure
  *
  *
  * OneNAND detection method:
  * OneNAND detection method:
  *   Compare the values from command with ones from register
  *   Compare the values from command with ones from register
  */
  */
-static int onenand_probe(struct mtd_info *mtd)
+static int onenand_chip_probe(struct mtd_info *mtd)
 {
 {
 	struct onenand_chip *this = mtd->priv;
 	struct onenand_chip *this = mtd->priv;
-	int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id;
-	int density;
+	int bram_maf_id, bram_dev_id, maf_id, dev_id;
 	int syscfg;
 	int syscfg;
 
 
 	/* Save system configuration 1 */
 	/* Save system configuration 1 */
@@ -3763,12 +3765,6 @@ static int onenand_probe(struct mtd_info *mtd)
 	/* Restore system configuration 1 */
 	/* Restore system configuration 1 */
 	this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
 	this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
 
 
-	/* Workaround */
-	if (syscfg & ONENAND_SYS_CFG1_SYNC_WRITE) {
-		bram_maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
-		bram_dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
-	}
-
 	/* Check manufacturer ID */
 	/* Check manufacturer ID */
 	if (onenand_check_maf(bram_maf_id))
 	if (onenand_check_maf(bram_maf_id))
 		return -ENXIO;
 		return -ENXIO;
@@ -3776,13 +3772,35 @@ static int onenand_probe(struct mtd_info *mtd)
 	/* Read manufacturer and device IDs from Register */
 	/* Read manufacturer and device IDs from Register */
 	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
 	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
 	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
 	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
-	ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
-	this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
 
 
 	/* Check OneNAND device */
 	/* Check OneNAND device */
 	if (maf_id != bram_maf_id || dev_id != bram_dev_id)
 	if (maf_id != bram_maf_id || dev_id != bram_dev_id)
 		return -ENXIO;
 		return -ENXIO;
 
 
+	return 0;
+}
+
+/**
+ * onenand_probe - [OneNAND Interface] Probe the OneNAND device
+ * @param mtd		MTD device structure
+ */
+static int onenand_probe(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+	int maf_id, dev_id, ver_id;
+	int density;
+	int ret;
+
+	ret = this->chip_probe(mtd);
+	if (ret)
+		return ret;
+
+	/* Read manufacturer and device IDs from Register */
+	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
+	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
+	ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
+	this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
+
 	/* Flash device information */
 	/* Flash device information */
 	onenand_print_device_info(dev_id, ver_id);
 	onenand_print_device_info(dev_id, ver_id);
 	this->device_id = dev_id;
 	this->device_id = dev_id;
@@ -3909,6 +3927,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 	if (!this->unlock_all)
 	if (!this->unlock_all)
 		this->unlock_all = onenand_unlock_all;
 		this->unlock_all = onenand_unlock_all;
 
 
+	if (!this->chip_probe)
+		this->chip_probe = onenand_chip_probe;
+
 	if (!this->read_bufferram)
 	if (!this->read_bufferram)
 		this->read_bufferram = onenand_read_bufferram;
 		this->read_bufferram = onenand_read_bufferram;
 	if (!this->write_bufferram)
 	if (!this->write_bufferram)

+ 0 - 1
drivers/mtd/onenand/onenand_bbt.c

@@ -15,7 +15,6 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/onenand.h>
-#include <linux/mtd/compatmac.h>
 
 
 /**
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer

+ 8 - 13
drivers/mtd/onenand/samsung.c

@@ -630,6 +630,12 @@ normal:
 	return 0;
 	return 0;
 }
 }
 
 
+static int s5pc110_chip_probe(struct mtd_info *mtd)
+{
+	/* Now just return 0 */
+	return 0;
+}
+
 static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state)
 static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state)
 {
 {
 	unsigned int flags = INT_ACT | LOAD_CMP;
 	unsigned int flags = INT_ACT | LOAD_CMP;
@@ -757,6 +763,7 @@ static void s3c_onenand_setup(struct mtd_info *mtd)
 		/* Use generic onenand functions */
 		/* Use generic onenand functions */
 		onenand->cmd_map = s5pc1xx_cmd_map;
 		onenand->cmd_map = s5pc1xx_cmd_map;
 		this->read_bufferram = s5pc110_read_bufferram;
 		this->read_bufferram = s5pc110_read_bufferram;
+		this->chip_probe = s5pc110_chip_probe;
 		return;
 		return;
 	} else {
 	} else {
 		BUG();
 		BUG();
@@ -781,7 +788,6 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	struct mtd_info *mtd;
 	struct mtd_info *mtd;
 	struct resource *r;
 	struct resource *r;
 	int size, err;
 	int size, err;
-	unsigned long onenand_ctrl_cfg = 0;
 
 
 	pdata = pdev->dev.platform_data;
 	pdata = pdev->dev.platform_data;
 	/* No need to check pdata. the platform data is optional */
 	/* No need to check pdata. the platform data is optional */
@@ -900,14 +906,6 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 		}
 		}
 
 
 		onenand->phys_base = onenand->base_res->start;
 		onenand->phys_base = onenand->base_res->start;
-
-		onenand_ctrl_cfg = readl(onenand->dma_addr + 0x100);
-		if ((onenand_ctrl_cfg & ONENAND_SYS_CFG1_SYNC_WRITE) &&
-		    onenand->dma_addr)
-			writel(onenand_ctrl_cfg & ~ONENAND_SYS_CFG1_SYNC_WRITE,
-					onenand->dma_addr + 0x100);
-		else
-			onenand_ctrl_cfg = 0;
 	}
 	}
 
 
 	if (onenand_scan(mtd, 1)) {
 	if (onenand_scan(mtd, 1)) {
@@ -915,10 +913,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 		goto scan_failed;
 		goto scan_failed;
 	}
 	}
 
 
-	if (onenand->type == TYPE_S5PC110) {
-		if (onenand_ctrl_cfg && onenand->dma_addr)
-			writel(onenand_ctrl_cfg, onenand->dma_addr + 0x100);
-	} else {
+	if (onenand->type != TYPE_S5PC110) {
 		/* S3C doesn't handle subpage write */
 		/* S3C doesn't handle subpage write */
 		mtd->subpage_sft = 0;
 		mtd->subpage_sft = 0;
 		this->subpagesize = mtd->writesize;
 		this->subpagesize = mtd->writesize;

+ 18 - 0
drivers/mtd/redboot.c

@@ -1,6 +1,24 @@
 /*
 /*
  * Parse RedBoot-style Flash Image System (FIS) tables and
  * Parse RedBoot-style Flash Image System (FIS) tables and
  * produce a Linux partition array to match.
  * produce a Linux partition array to match.
+ *
+ * Copyright © 2001      Red Hat UK Limited
+ * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
  */
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>

+ 1 - 1
drivers/mtd/rfd_ftl.c

@@ -1,7 +1,7 @@
 /*
 /*
  * rfd_ftl.c -- resident flash disk (flash translation layer)
  * rfd_ftl.c -- resident flash disk (flash translation layer)
  *
  *
- * Copyright (C) 2005  Sean Young <sean@mess.org>
+ * Copyright © 2005  Sean Young <sean@mess.org>
  *
  *
  * This type of flash translation layer (FTL) is used by the Embedded BIOS
  * This type of flash translation layer (FTL) is used by the Embedded BIOS
  * by General Software. It is known as the Resident Flash Disk (RFD), see:
  * by General Software. It is known as the Resident Flash Disk (RFD), see:

+ 1 - 1
drivers/mtd/ssfdc.c

@@ -1,6 +1,6 @@
 /*
 /*
  * Linux driver for SSFDC Flash Translation Layer (Read only)
  * Linux driver for SSFDC Flash Translation Layer (Read only)
- * (c) 2005 Eptar srl
+ * © 2005 Eptar srl
  * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com>
  * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com>
  *
  *
  * Based on NTFL and MTDBLOCK_RO drivers
  * Based on NTFL and MTDBLOCK_RO drivers

+ 4 - 5
drivers/mtd/tests/mtd_pagetest.c

@@ -310,7 +310,7 @@ static int crosstest(void)
 static int erasecrosstest(void)
 static int erasecrosstest(void)
 {
 {
 	size_t read = 0, written = 0;
 	size_t read = 0, written = 0;
-	int err = 0, i, ebnum, ok = 1, ebnum2;
+	int err = 0, i, ebnum, ebnum2;
 	loff_t addr0;
 	loff_t addr0;
 	char *readbuf = twopages;
 	char *readbuf = twopages;
 
 
@@ -357,8 +357,7 @@ static int erasecrosstest(void)
 	if (memcmp(writebuf, readbuf, pgsize)) {
 	if (memcmp(writebuf, readbuf, pgsize)) {
 		printk(PRINT_PREF "verify failed!\n");
 		printk(PRINT_PREF "verify failed!\n");
 		errcnt += 1;
 		errcnt += 1;
-		ok = 0;
-		return err;
+		return -1;
 	}
 	}
 
 
 	printk(PRINT_PREF "erasing block %d\n", ebnum);
 	printk(PRINT_PREF "erasing block %d\n", ebnum);
@@ -396,10 +395,10 @@ static int erasecrosstest(void)
 	if (memcmp(writebuf, readbuf, pgsize)) {
 	if (memcmp(writebuf, readbuf, pgsize)) {
 		printk(PRINT_PREF "verify failed!\n");
 		printk(PRINT_PREF "verify failed!\n");
 		errcnt += 1;
 		errcnt += 1;
-		ok = 0;
+		return -1;
 	}
 	}
 
 
-	if (ok && !err)
+	if (!err)
 		printk(PRINT_PREF "erasecrosstest ok\n");
 		printk(PRINT_PREF "erasecrosstest ok\n");
 	return err;
 	return err;
 }
 }

+ 1 - 0
fs/jffs2/background.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/build.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 3 - 2
fs/jffs2/compr.c

@@ -2,11 +2,12 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
- * Created by Arjan van de Ven <arjanv@redhat.com>
- *
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
  * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
  *		    University of Szeged, Hungary
  *		    University of Szeged, Hungary
  *
  *
+ * Created by Arjan van de Ven <arjan@infradead.org>
+ *
  * For licensing information, see the file 'LICENCE' in this directory.
  * For licensing information, see the file 'LICENCE' in this directory.
  *
  *
  */
  */

+ 1 - 0
fs/jffs2/compr.h

@@ -3,6 +3,7 @@
  *
  *
  * Copyright © 2004   Ferenc Havasi <havasi@inf.u-szeged.hu>,
  * Copyright © 2004   Ferenc Havasi <havasi@inf.u-szeged.hu>,
  *		      University of Szeged, Hungary
  *		      University of Szeged, Hungary
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  * For licensing information, see the file 'LICENCE' in this directory.
  *
  *

+ 1 - 0
fs/jffs2/compr_lzo.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2007 Nokia Corporation. All rights reserved.
  * Copyright © 2007 Nokia Corporation. All rights reserved.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by Richard Purdie <rpurdie@openedhand.com>
  * Created by Richard Purdie <rpurdie@openedhand.com>
  *
  *

+ 1 - 0
fs/jffs2/compr_rtime.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by Arjan van de Ven <arjanv@redhat.com>
  * Created by Arjan van de Ven <arjanv@redhat.com>
  *
  *

+ 1 - 0
fs/jffs2/compr_rubin.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by Arjan van de Ven <arjanv@redhat.com>
  * Created by Arjan van de Ven <arjanv@redhat.com>
  *
  *

+ 1 - 0
fs/jffs2/compr_zlib.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/debug.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/debug.h

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/dir.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/erase.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/file.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/fs.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/gc.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/ioctl.c

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/jffs2_fs_i.h

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 1 - 0
fs/jffs2/jffs2_fs_sb.h

@@ -2,6 +2,7 @@
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
  * Copyright © 2001-2007 Red Hat, Inc.
  * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 0 - 1
fs/jffs2/nodelist.h

@@ -24,7 +24,6 @@
 #ifdef __ECOS
 #ifdef __ECOS
 #include "os-ecos.h"
 #include "os-ecos.h"
 #else
 #else
-#include <linux/mtd/compatmac.h> /* For compatibility with older kernels */
 #include "os-linux.h"
 #include "os-linux.h"
 #endif
 #endif
 
 

+ 2 - 1
include/linux/jffs2.h

@@ -1,7 +1,8 @@
 /*
 /*
  * JFFS2 -- Journalling Flash File System, Version 2.
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
  *
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
+ * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  *

+ 22 - 2
include/linux/mtd/bbm.h

@@ -4,12 +4,26 @@
  *  NAND family Bad Block Management (BBM) header file
  *  NAND family Bad Block Management (BBM) header file
  *    - Bad Block Table (BBT) implementation
  *    - Bad Block Table (BBT) implementation
  *
  *
- *  Copyright (c) 2005 Samsung Electronics
+ *  Copyright © 2005 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  *
- *  Copyright (c) 2000-2005
+ *  Copyright © 2000-2005
  *  Thomas Gleixner <tglx@linuxtronix.de>
  *  Thomas Gleixner <tglx@linuxtronix.de>
  *
  *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
  */
 #ifndef __LINUX_MTD_BBM_H
 #ifndef __LINUX_MTD_BBM_H
 #define __LINUX_MTD_BBM_H
 #define __LINUX_MTD_BBM_H
@@ -82,6 +96,12 @@ struct nand_bbt_descr {
 #define NAND_BBT_SAVECONTENT	0x00002000
 #define NAND_BBT_SAVECONTENT	0x00002000
 /* Search good / bad pattern on the first and the second page */
 /* Search good / bad pattern on the first and the second page */
 #define NAND_BBT_SCAN2NDPAGE	0x00004000
 #define NAND_BBT_SCAN2NDPAGE	0x00004000
+/* Search good / bad pattern on the last page of the eraseblock */
+#define NAND_BBT_SCANLASTPAGE	0x00008000
+/* Chip stores bad block marker on BOTH 1st and 6th bytes of OOB */
+#define NAND_BBT_SCANBYTE1AND6 0x00100000
+/* The nand_bbt_descr was created dynamicaly and must be freed */
+#define NAND_BBT_DYNAMICSTRUCT 0x00200000
 
 
 /* The maximum number of blocks to scan for a bbt */
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
 #define NAND_BBT_SCAN_MAXBLOCKS	4

+ 14 - 2
include/linux/mtd/blktrans.h

@@ -1,7 +1,19 @@
 /*
 /*
- * (C) 2003 David Woodhouse <dwmw2@infradead.org>
+ * Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org>
  *
  *
- * Interface to Linux block layer for MTD 'translation layers'.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
  */
  */
 
 

+ 17 - 3
include/linux/mtd/cfi.h

@@ -1,6 +1,20 @@
-
-/* Common Flash Interface structures
- * See http://support.intel.com/design/flash/technote/index.htm
+/*
+ * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
  */
 
 
 #ifndef __MTD_CFI_H__
 #ifndef __MTD_CFI_H__

+ 19 - 0
include/linux/mtd/cfi_endian.h

@@ -1,3 +1,22 @@
+/*
+ * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
 
 
 #ifndef CONFIG_MTD_CFI_ADV_OPTIONS
 #ifndef CONFIG_MTD_CFI_ADV_OPTIONS

+ 0 - 10
include/linux/mtd/compatmac.h

@@ -1,10 +0,0 @@
-
-#ifndef __LINUX_MTD_COMPATMAC_H__
-#define __LINUX_MTD_COMPATMAC_H__
-
-/* Nothing to see here. We write 2.5-compatible code and this
-   file makes it all OK in older kernels, but it's empty in _current_
-   kernels. Include guard just to make GCC ignore it in future inclusions
-   anyway... */
-
-#endif /* __LINUX_MTD_COMPATMAC_H__ */

+ 15 - 2
include/linux/mtd/concat.h

@@ -1,9 +1,22 @@
 /*
 /*
  * MTD device concatenation layer definitions
  * MTD device concatenation layer definitions
  *
  *
- * (C) 2002 Robert Kaiser <rkaiser@sysgo.de>
+ * Copyright © 2002      Robert Kaiser <rkaiser@sysgo.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
- * This code is GPL
  */
  */
 
 
 #ifndef MTD_CONCAT_H
 #ifndef MTD_CONCAT_H

+ 18 - 5
include/linux/mtd/doc2000.h

@@ -1,12 +1,25 @@
 /*
 /*
  * Linux driver for Disk-On-Chip devices
  * Linux driver for Disk-On-Chip devices
  *
  *
- * Copyright (C) 1999 Machine Vision Holdings, Inc.
- * Copyright (C) 2001-2003 David Woodhouse <dwmw2@infradead.org>
- * Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com>
- * Copyright (C) 2002-2003 SnapGear Inc
+ * Copyright © 1999 Machine Vision Holdings, Inc.
+ * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
+ * Copyright © 2002-2003 Greg Ungerer <gerg@snapgear.com>
+ * Copyright © 2002-2003 SnapGear Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
- * Released under GPL
  */
  */
 
 
 #ifndef __MTD_DOC2000_H__
 #ifndef __MTD_DOC2000_H__

+ 16 - 5
include/linux/mtd/flashchip.h

@@ -1,10 +1,21 @@
-
 /*
 /*
- * struct flchip definition
+ * Copyright © 2000      Red Hat UK Limited
+ * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
  *
- * Contains information about the location and state of a given flash device
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
- * (C) 2000 Red Hat. GPLd.
  */
  */
 
 
 #ifndef __MTD_FLASHCHIP_H__
 #ifndef __MTD_FLASHCHIP_H__
@@ -92,7 +103,7 @@ struct flchip {
 /* This is used to handle contention on write/erase operations
 /* This is used to handle contention on write/erase operations
    between partitions of the same physical chip. */
    between partitions of the same physical chip. */
 struct flchip_shared {
 struct flchip_shared {
-	spinlock_t lock;
+	struct mutex lock;
 	struct flchip *writing;
 	struct flchip *writing;
 	struct flchip *erasing;
 	struct flchip *erasing;
 };
 };

+ 17 - 2
include/linux/mtd/gen_probe.h

@@ -1,6 +1,21 @@
 /*
 /*
- * (C) 2001, 2001 Red Hat, Inc.
- * GPL'd
+ * Copyright © 2001      Red Hat UK Limited
+ * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
  */
 
 
 #ifndef __LINUX_MTD_GEN_PROBE_H__
 #ifndef __LINUX_MTD_GEN_PROBE_H__

+ 18 - 1
include/linux/mtd/map.h

@@ -1,3 +1,21 @@
+/*
+ * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
 
 
 /* Overhauled routines for dealing with different mmap regions of flash */
 /* Overhauled routines for dealing with different mmap regions of flash */
 
 
@@ -9,7 +27,6 @@
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/bug.h>
 #include <linux/bug.h>
 
 
-#include <linux/mtd/compatmac.h>
 
 
 #include <asm/unaligned.h>
 #include <asm/unaligned.h>
 #include <asm/system.h>
 #include <asm/system.h>

+ 16 - 3
include/linux/mtd/mtd.h

@@ -1,7 +1,20 @@
 /*
 /*
- * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
+ * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  *
- * Released under GPL
  */
  */
 
 
 #ifndef __MTD_MTD_H__
 #ifndef __MTD_MTD_H__
@@ -13,7 +26,6 @@
 #include <linux/notifier.h>
 #include <linux/notifier.h>
 #include <linux/device.h>
 #include <linux/device.h>
 
 
-#include <linux/mtd/compatmac.h>
 #include <mtd/mtd-abi.h>
 #include <mtd/mtd-abi.h>
 
 
 #include <asm/div64.h>
 #include <asm/div64.h>
@@ -216,6 +228,7 @@ struct mtd_info {
 	/* Chip-supported device locking */
 	/* Chip-supported device locking */
 	int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
 	int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
 	int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
 	int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
+	int (*is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
 
 
 	/* Power Management functions */
 	/* Power Management functions */
 	int (*suspend) (struct mtd_info *mtd);
 	int (*suspend) (struct mtd_info *mtd);

+ 3 - 5
include/linux/mtd/nand.h

@@ -1,9 +1,9 @@
 /*
 /*
  *  linux/include/linux/mtd/nand.h
  *  linux/include/linux/mtd/nand.h
  *
  *
- *  Copyright (c) 2000 David Woodhouse <dwmw2@infradead.org>
- *                     Steven J. Hill <sjhill@realitydiluted.com>
- *		       Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
+ *                        Steven J. Hill <sjhill@realitydiluted.com>
+ *		          Thomas Gleixner <tglx@linutronix.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * 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
  * it under the terms of the GNU General Public License version 2 as
@@ -181,8 +181,6 @@ typedef enum {
 #define NAND_NO_READRDY		0x00000100
 #define NAND_NO_READRDY		0x00000100
 /* Chip does not allow subpage writes */
 /* Chip does not allow subpage writes */
 #define NAND_NO_SUBPAGE_WRITE	0x00000200
 #define NAND_NO_SUBPAGE_WRITE	0x00000200
-/* Chip stores bad block marker on the last page of the eraseblock */
-#define NAND_BB_LAST_PAGE	0x00000400
 
 
 /* Device is one of 'new' xD cards that expose fake nand command set */
 /* Device is one of 'new' xD cards that expose fake nand command set */
 #define NAND_BROKEN_XD		0x00000400
 #define NAND_BROKEN_XD		0x00000400

+ 3 - 1
include/linux/mtd/nand_ecc.h

@@ -1,7 +1,9 @@
 /*
 /*
  *  drivers/mtd/nand_ecc.h
  *  drivers/mtd/nand_ecc.h
  *
  *
- *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
+ *  Copyright (C) 2000-2010 Steven J. Hill <sjhill@realitydiluted.com>
+ *			    David Woodhouse <dwmw2@infradead.org>
+ *			    Thomas Gleixner <tglx@linutronix.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * 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
  * it under the terms of the GNU General Public License version 2 as

Some files were not shown because too many files changed in this diff