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

* git://git.infradead.org/mtd-2.6: (97 commits)
  mtd: kill CONFIG_MTD_PARTITIONS
  mtd: remove add_mtd_partitions, add_mtd_device and friends
  mtd: convert remaining users to mtd_device_register()
  mtd: samsung onenand: convert to mtd_device_register()
  mtd: omap2 onenand: convert to mtd_device_register()
  mtd: txx9ndfmc: convert to mtd_device_register()
  mtd: tmio_nand: convert to mtd_device_register()
  mtd: socrates_nand: convert to mtd_device_register()
  mtd: sharpsl: convert to mtd_device_register()
  mtd: s3c2410 nand: convert to mtd_device_register()
  mtd: ppchameleonevb: convert to mtd_device_register()
  mtd: orion_nand: convert to mtd_device_register()
  mtd: omap2: convert to mtd_device_register()
  mtd: nomadik_nand: convert to mtd_device_register()
  mtd: ndfc: convert to mtd_device_register()
  mtd: mxc_nand: convert to mtd_device_register()
  mtd: mpc5121_nfc: convert to mtd_device_register()
  mtd: jz4740_nand: convert to mtd_device_register()
  mtd: h1910: convert to mtd_device_register()
  mtd: fsmc_nand: convert to mtd_device_register()
  ...

Fixed up trivial conflicts in
 - drivers/mtd/maps/integrator-flash.c: removed in ARM tree
 - drivers/mtd/maps/physmap.c: addition of afs partition probe type
   clashing with removal of CONFIG_MTD_PARTITIONS
diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl
index 6f242d5..17910e2 100644
--- a/Documentation/DocBook/mtdnand.tmpl
+++ b/Documentation/DocBook/mtdnand.tmpl
@@ -189,8 +189,7 @@
 		<title>Partition defines</title>
 		<para>
 			If you want to divide your device into partitions, then
-			enable the configuration switch CONFIG_MTD_PARTITIONS and define
-			a partitioning scheme suitable to your board.
+			define a partitioning scheme suitable to your board.
 		</para>
 		<programlisting>
 #define NUM_PARTITIONS 2
diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c
index af7b68a..88cc422 100644
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -84,7 +84,6 @@
 	.init	= gemini_timer_init,
 };
 
-#ifdef CONFIG_MTD_PARTITIONS
 static struct mtd_partition wbd111_partitions[] = {
 	{
 		.name		= "RedBoot",
@@ -116,11 +115,7 @@
 		.mask_flags	= MTD_WRITEABLE,
 	}
 };
-#define wbd111_num_partitions	ARRAY_SIZE(wbd111_partitions)
-#else
-#define wbd111_partitions	NULL
-#define wbd111_num_partitions	0
-#endif /* CONFIG_MTD_PARTITIONS */
+#define wbd111_num_partitions  ARRAY_SIZE(wbd111_partitions)
 
 static void __init wbd111_init(void)
 {
diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c
index 99e5bbe..3a22034 100644
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -84,7 +84,6 @@
 	.init	= gemini_timer_init,
 };
 
-#ifdef CONFIG_MTD_PARTITIONS
 static struct mtd_partition wbd222_partitions[] = {
 	{
 		.name		= "RedBoot",
@@ -116,11 +115,7 @@
 		.mask_flags	= MTD_WRITEABLE,
 	}
 };
-#define wbd222_num_partitions	ARRAY_SIZE(wbd222_partitions)
-#else
-#define wbd222_partitions	NULL
-#define wbd222_num_partitions	0
-#endif /* CONFIG_MTD_PARTITIONS */
+#define wbd222_num_partitions  ARRAY_SIZE(wbd222_partitions)
 
 static void __init wbd222_init(void)
 {
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 1407833..dca4f7f 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -60,7 +60,6 @@
 #if defined(CONFIG_MTD_NAND_PLATFORM) || \
     defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
 
-#ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
 
 static struct mtd_partition ixdp425_partitions[] = {
@@ -74,7 +73,6 @@
 		.size	= MTDPART_SIZ_FULL
 	},
 };
-#endif
 
 static void
 ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -103,11 +101,9 @@
 		.nr_chips		= 1,
 		.chip_delay		= 30,
 		.options		= NAND_NO_AUTOINCR,
-#ifdef CONFIG_MTD_PARTITIONS
 		.part_probe_types 	= part_probes,
 		.partitions	 	= ixdp425_partitions,
 		.nr_partitions	 	= ARRAY_SIZE(ixdp425_partitions),
-#endif
 	},
 	.ctrl = {
 		.cmd_ctrl 		= ixdp425_flash_nand_cmd_ctrl
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 2fc9f94..cd19309 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -153,7 +153,6 @@
 	bool "Iskratel Electronics XCEP"
 	select PXA25x
 	select MTD
-	select MTD_PARTITIONS
 	select MTD_PHYSMAP
 	select MTD_CFI_INTELEXT
 	select MTD_CFI
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index 44440cb..dabc141 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -58,8 +58,6 @@
 #include <plat/cpu.h>
 #include <plat/gpio-cfg.h>
 
-#ifdef CONFIG_MTD_PARTITIONS
-
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/map.h>
@@ -113,7 +111,6 @@
 	.num_resources	= 1,
 	.resource	= &amlm5900_nor_resource,
 };
-#endif
 
 static struct map_desc amlm5900_iodesc[] __initdata = {
 };
@@ -158,9 +155,7 @@
  	&s3c_device_rtc,
 	&s3c_device_usbgadget,
         &s3c_device_sdi,
-#ifdef CONFIG_MTD_PARTITIONS
 	&amlm5900_device_nor,
-#endif
 };
 
 static void __init amlm5900_map_io(void)
diff --git a/arch/arm/mach-s3c2410/mach-tct_hammer.c b/arch/arm/mach-s3c2410/mach-tct_hammer.c
index a15d062..43c2b83 100644
--- a/arch/arm/mach-s3c2410/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c2410/mach-tct_hammer.c
@@ -49,8 +49,6 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 
-#ifdef CONFIG_MTD_PARTITIONS
-
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/map.h>
@@ -91,8 +89,6 @@
 	.resource	= &tct_hammer_nor_resource,
 };
 
-#endif
-
 static struct map_desc tct_hammer_iodesc[] __initdata = {
 };
 
@@ -133,9 +129,7 @@
 	&s3c_device_rtc,
 	&s3c_device_usbgadget,
 	&s3c_device_sdi,
-#ifdef CONFIG_MTD_PARTITIONS
 	&tct_hammer_device_nor,
-#endif
 };
 
 static void __init tct_hammer_map_io(void)
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index e16dc45..76db1d4 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -382,7 +382,6 @@
 #endif
 
 #if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
-#ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 
 static struct mtd_partition bfin_plat_nand_partitions[] = {
@@ -396,7 +395,6 @@
 		.offset = MTDPART_OFS_APPEND,
 	},
 };
-#endif
 
 #define BFIN_NAND_PLAT_CLE 2
 #define BFIN_NAND_PLAT_ALE 1
@@ -423,11 +421,9 @@
 	.chip = {
 		.nr_chips = 1,
 		.chip_delay = 30,
-#ifdef CONFIG_MTD_PARTITIONS
 		.part_probe_types = part_probes,
 		.partitions = bfin_plat_nand_partitions,
 		.nr_partitions = ARRAY_SIZE(bfin_plat_nand_partitions),
-#endif
 	},
 	.ctrl = {
 		.cmd_ctrl  = bfin_plat_nand_cmd_ctrl,
diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c
index 3926cd9..9231a94 100644
--- a/arch/blackfin/mach-bf561/boards/acvilon.c
+++ b/arch/blackfin/mach-bf561/boards/acvilon.c
@@ -243,7 +243,6 @@
 
 #if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
 
-#ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
 
 static struct mtd_partition bfin_plat_nand_partitions[] = {
@@ -257,7 +256,6 @@
 	     .offset = MTDPART_OFS_APPEND,
 	     },
 };
-#endif
 
 #define BFIN_NAND_PLAT_CLE 2
 #define BFIN_NAND_PLAT_ALE 3
@@ -286,11 +284,9 @@
 	.chip = {
 		 .nr_chips = 1,
 		 .chip_delay = 30,
-#ifdef CONFIG_MTD_PARTITIONS
 		 .part_probe_types = part_probes,
 		 .partitions = bfin_plat_nand_partitions,
 		 .nr_partitions = ARRAY_SIZE(bfin_plat_nand_partitions),
-#endif
 		 },
 	.ctrl = {
 		 .cmd_ctrl = bfin_plat_nand_cmd_ctrl,
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index b6b94a2..17addac 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -270,7 +270,6 @@
 	select MTD_JEDECPROBE if ETRAX_ARCH_V32
 	select MTD_CHAR
 	select MTD_BLOCK
-	select MTD_PARTITIONS
 	select MTD_COMPLEX_MAPPINGS
 	help
 	  This option enables MTD mapping of flash devices.  Needed to use
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c
index ed708e1..a4bbdfd 100644
--- a/arch/cris/arch-v10/drivers/axisflashmap.c
+++ b/arch/cris/arch-v10/drivers/axisflashmap.c
@@ -372,7 +372,7 @@
 #ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE
 	if (mymtd) {
 		main_partition.size = mymtd->size;
-		err = add_mtd_partitions(mymtd, &main_partition, 1);
+		err = mtd_device_register(mymtd, &main_partition, 1);
 		if (err)
 			panic("axisflashmap: Could not initialize "
 			      "partition for whole main mtd device!\n");
@@ -382,10 +382,12 @@
         if (mymtd) {
 		if (use_default_ptable) {
 			printk(KERN_INFO " Using default partition table.\n");
-			err = add_mtd_partitions(mymtd, axis_default_partitions,
-						 NUM_DEFAULT_PARTITIONS);
+			err = mtd_device_register(mymtd,
+						  axis_default_partitions,
+						  NUM_DEFAULT_PARTITIONS);
 		} else {
-			err = add_mtd_partitions(mymtd, axis_partitions, pidx);
+			err = mtd_device_register(mymtd, axis_partitions,
+						  pidx);
 		}
 
 		if (err)
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 1633b12..41a2732 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -405,7 +405,6 @@
 	select MTD_JEDECPROBE
 	select MTD_CHAR
 	select MTD_BLOCK
-	select MTD_PARTITIONS
 	select MTD_COMPLEX_MAPPINGS
 	help
 	  This option enables MTD mapping of flash devices.  Needed to use
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c
index 7b155f8..a2bde37 100644
--- a/arch/cris/arch-v32/drivers/axisflashmap.c
+++ b/arch/cris/arch-v32/drivers/axisflashmap.c
@@ -561,7 +561,7 @@
 #ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE
 	if (main_mtd) {
 		main_partition.size = main_mtd->size;
-		err = add_mtd_partitions(main_mtd, &main_partition, 1);
+		err = mtd_device_register(main_mtd, &main_partition, 1);
 		if (err)
 			panic("axisflashmap: Could not initialize "
 			      "partition for whole main mtd device!\n");
@@ -597,7 +597,8 @@
 			mtd_ram->erasesize = (main_mtd ? main_mtd->erasesize :
 				CONFIG_ETRAX_PTABLE_SECTOR);
 		} else {
-			err = add_mtd_partitions(main_mtd, &partition[part], 1);
+			err = mtd_device_register(main_mtd, &partition[part],
+						  1);
 			if (err)
 				panic("axisflashmap: Could not add mtd "
 					"partition %d\n", part);
@@ -633,7 +634,7 @@
 #ifndef CONFIG_ETRAX_VCS_SIM
 	if (aux_mtd) {
 		aux_partition.size = aux_mtd->size;
-		err = add_mtd_partitions(aux_mtd, &aux_partition, 1);
+		err = mtd_device_register(aux_mtd, &aux_partition, 1);
 		if (err)
 			panic("axisflashmap: Could not initialize "
 			      "aux mtd device!\n");
diff --git a/arch/mips/cavium-octeon/flash_setup.c b/arch/mips/cavium-octeon/flash_setup.c
index 008f657..0ee02f5 100644
--- a/arch/mips/cavium-octeon/flash_setup.c
+++ b/arch/mips/cavium-octeon/flash_setup.c
@@ -16,7 +16,6 @@
 
 static struct map_info flash_map;
 static struct mtd_info *mymtd;
-#ifdef CONFIG_MTD_PARTITIONS
 static int nr_parts;
 static struct mtd_partition *parts;
 static const char *part_probe_types[] = {
@@ -26,7 +25,6 @@
 #endif
 	NULL
 };
-#endif
 
 /**
  * Module/ driver initialization.
@@ -63,17 +61,10 @@
 		if (mymtd) {
 			mymtd->owner = THIS_MODULE;
 
-#ifdef CONFIG_MTD_PARTITIONS
 			nr_parts = parse_mtd_partitions(mymtd,
 							part_probe_types,
 							&parts, 0);
-			if (nr_parts > 0)
-				add_mtd_partitions(mymtd, parts, nr_parts);
-			else
-				add_mtd_device(mymtd);
-#else
-			add_mtd_device(mymtd);
-#endif
+			mtd_device_register(mymtd, parts, nr_parts);
 		} else {
 			pr_err("Failed to register MTD device for flash\n");
 		}
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index 812816c..ec38e00 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -639,7 +639,6 @@
 		.flags = IORESOURCE_MEM,
 	};
 	struct platform_device *pdev;
-#ifdef CONFIG_MTD_PARTITIONS
 	static struct mtd_partition parts[2];
 	struct physmap_flash_data pdata_part;
 
@@ -658,7 +657,7 @@
 		pdata_part.parts = parts;
 		pdata = &pdata_part;
 	}
-#endif
+
 	pdev = platform_device_alloc("physmap-flash", no);
 	if (!pdev ||
 	    platform_device_add_resources(pdev, &res, 1) ||
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index bc50d5e..4be8373 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -33,20 +33,6 @@
 	  should normally be compiled as kernel modules. The modules perform
 	  various checks and verifications when loaded.
 
-config MTD_PARTITIONS
-	bool "MTD partitioning support"
-	help
-	  If you have a device which needs to divide its flash chip(s) up
-	  into multiple 'partitions', each of which appears to the user as
-	  a separate MTD device, you require this option to be enabled. If
-	  unsure, say 'Y'.
-
-	  Note, however, that you don't need this option for the DiskOnChip
-	  devices. Partitioning on NFTL 'devices' is a different - that's the
-	  'normal' form of partitioning used on a block device.
-
-if MTD_PARTITIONS
-
 config MTD_REDBOOT_PARTS
 	tristate "RedBoot partition table parsing"
 	---help---
@@ -99,7 +85,7 @@
 
 config MTD_CMDLINE_PARTS
 	bool "Command line partition table parsing"
-	depends on MTD_PARTITIONS = "y" && MTD = "y"
+	depends on MTD = "y"
 	---help---
 	  Allow generic configuration of the MTD partition tables via the kernel
 	  command line. Multiple flash resources are supported for hardware where
@@ -163,8 +149,6 @@
 	---help---
 	  TI AR7 partitioning support
 
-endif # MTD_PARTITIONS
-
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index d578095..39664c4 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -4,8 +4,7 @@
 
 # Core functionality.
 obj-$(CONFIG_MTD)		+= mtd.o
-mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o
-mtd-$(CONFIG_MTD_PARTITIONS)	+= mtdpart.o
+mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o
 mtd-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
 
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 09cb7c8..e1e122f 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -812,12 +812,9 @@
 			        break;
 
 			if (time_after(jiffies, timeo)) {
-				/* Urgh. Resume and pretend we weren't here.  */
-				map_write(map, CMD(0xd0), adr);
-				/* Make sure we're in 'read status' mode if it had finished */
-				map_write(map, CMD(0x70), adr);
-				chip->state = FL_ERASING;
-				chip->oldstate = FL_READY;
+				/* Urgh. Resume and pretend we weren't here.
+				 * Make sure we're in 'read status' mode if it had finished */
+				put_chip(map, chip, adr);
 				printk(KERN_ERR "%s: Chip not ready after erase "
 				       "suspended: status = 0x%lx\n", map->name, status.x[0]);
 				return -EIO;
@@ -997,7 +994,6 @@
 
 	switch(chip->oldstate) {
 	case FL_ERASING:
-		chip->state = chip->oldstate;
 		/* What if one interleaved chip has finished and the
 		   other hasn't? The old code would leave the finished
 		   one in READY mode. That's bad, and caused -EROFS
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 0b49266..23175ed 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -462,13 +462,14 @@
 			cfi_fixup_major_minor(cfi, extp);
 
 			/*
-			 * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4
+			 * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5
 			 * see: http://cs.ozerki.net/zap/pub/axim-x5/docs/cfi_r20.pdf, page 19 
 			 *      http://www.spansion.com/Support/AppNotes/cfi_100_20011201.pdf
 			 *      http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf
+			 *      http://www.spansion.com/Support/Datasheets/S29GL_128S_01GS_00_02_e.pdf
 			 */
 			if (extp->MajorVersion != '1' ||
-			    (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '4'))) {
+			    (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '5'))) {
 				printk(KERN_ERR "  Unknown Amd/Fujitsu Extended Query "
 				       "version %c.%c (%#02x/%#02x).\n",
 				       extp->MajorVersion, extp->MinorVersion,
@@ -710,9 +711,7 @@
 				 * there was an error (so leave the erase
 				 * routine to recover from it) or we trying to
 				 * use the erase-in-progress sector. */
-				map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
-				chip->state = FL_ERASING;
-				chip->oldstate = FL_READY;
+				put_chip(map, chip, adr);
 				printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
 				return -EIO;
 			}
@@ -762,7 +761,6 @@
 
 	switch(chip->oldstate) {
 	case FL_ERASING:
-		chip->state = chip->oldstate;
 		map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
 		chip->oldstate = FL_READY;
 		chip->state = FL_ERASING;
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index ed56ad3..179814a 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -296,6 +296,7 @@
 				/* make sure we're in 'read status' mode */
 				map_write(map, CMD(0x70), cmd_addr);
 				chip->state = FL_ERASING;
+				wake_up(&chip->wq);
 				mutex_unlock(&chip->mutex);
 				printk(KERN_ERR "Chip not ready after erase "
 				       "suspended: status = 0x%lx\n", status.x[0]);
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 97183c8..b78f231 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -294,7 +294,7 @@
 	dev->mtd.priv = dev;
 	dev->mtd.owner = THIS_MODULE;
 
-	if (add_mtd_device(&dev->mtd)) {
+	if (mtd_device_register(&dev->mtd, NULL, 0)) {
 		/* Device didn't get added, so free the entry */
 		goto devinit_err;
 	}
@@ -465,7 +465,7 @@
 	list_for_each_safe(pos, next, &blkmtd_device_list) {
 		struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list);
 		block2mtd_sync(&dev->mtd);
-		del_mtd_device(&dev->mtd);
+		mtd_device_unregister(&dev->mtd);
 		INFO("mtd%d: [%s] removed", dev->mtd.index,
 				dev->mtd.name + strlen("block2mtd: "));
 		list_del(&dev->list);
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index 5bf5f46..f7fbf60 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -597,7 +597,7 @@
 		doc2klist = mtd;
 		mtd->size = this->totlen;
 		mtd->erasesize = this->erasesize;
-		add_mtd_device(mtd);
+		mtd_device_register(mtd, NULL, 0);
 		return;
 	}
 }
@@ -1185,7 +1185,7 @@
 		this = mtd->priv;
 		doc2klist = this->nextdoc;
 
-		del_mtd_device(mtd);
+		mtd_device_unregister(mtd);
 
 		iounmap(this->virtadr);
 		kfree(this->chips);
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index 0990f78..241192f 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -376,7 +376,7 @@
 		this->nextdoc = docmillist;
 		docmillist = mtd;
 		mtd->size  = this->totlen;
-		add_mtd_device(mtd);
+		mtd_device_register(mtd, NULL, 0);
 		return;
 	}
 }
@@ -826,7 +826,7 @@
 		this = mtd->priv;
 		docmillist = this->nextdoc;
 
-		del_mtd_device(mtd);
+		mtd_device_unregister(mtd);
 
 		iounmap(this->virtadr);
 		kfree(this->chips);
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 8b36fa7..09ae0ad 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -499,7 +499,7 @@
 		docmilpluslist = mtd;
 		mtd->size  = this->totlen;
 		mtd->erasesize = this->erasesize;
-		add_mtd_device(mtd);
+		mtd_device_register(mtd, NULL, 0);
 		return;
 	}
 }
@@ -1091,7 +1091,7 @@
 		this = mtd->priv;
 		docmilpluslist = this->nextdoc;
 
-		del_mtd_device(mtd);
+		mtd_device_unregister(mtd);
 
 		iounmap(this->virtadr);
 		kfree(this->chips);
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index 4b829f9..772a0ff 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -684,9 +684,10 @@
 #endif
 
 #ifndef HAVE_PARTITIONS
-   result = add_mtd_device (&mtd);
+   result = mtd_device_register(&mtd, NULL, 0);
 #else
-   result = add_mtd_partitions (&mtd,lart_partitions, ARRAY_SIZE(lart_partitions));
+   result = mtd_device_register(&mtd, lart_partitions,
+                                ARRAY_SIZE(lart_partitions));
 #endif
 
    return (result);
@@ -695,9 +696,9 @@
 static void __exit lart_flash_exit (void)
 {
 #ifndef HAVE_PARTITIONS
-   del_mtd_device (&mtd);
+   mtd_device_unregister(&mtd);
 #else
-   del_mtd_partitions (&mtd);
+   mtd_device_unregister(&mtd);
 #endif
 }
 
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 3fb981d..35180e4 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 #include <linux/mod_devicetable.h>
 
+#include <linux/mtd/cfi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
@@ -55,6 +56,9 @@
 #define	OPCODE_EN4B		0xb7	/* Enter 4-byte mode */
 #define	OPCODE_EX4B		0xe9	/* Exit 4-byte mode */
 
+/* Used for Spansion flashes only. */
+#define	OPCODE_BRWR		0x17	/* Bank register write */
+
 /* Status Register bits. */
 #define	SR_WIP			1	/* Write in progress */
 #define	SR_WEL			2	/* Write enable latch */
@@ -76,6 +80,8 @@
 #define FAST_READ_DUMMY_BYTE 0
 #endif
 
+#define JEDEC_MFR(_jedec_id)	((_jedec_id) >> 16)
+
 /****************************************************************************/
 
 struct m25p {
@@ -158,11 +164,18 @@
 /*
  * Enable/disable 4-byte addressing mode.
  */
-static inline int set_4byte(struct m25p *flash, int enable)
+static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable)
 {
-	u8	code = enable ? OPCODE_EN4B : OPCODE_EX4B;
-
-	return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+	switch (JEDEC_MFR(jedec_id)) {
+	case CFI_MFR_MACRONIX:
+		flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B;
+		return spi_write(flash->spi, flash->command, 1);
+	default:
+		/* Spansion style */
+		flash->command[0] = OPCODE_BRWR;
+		flash->command[1] = enable << 7;
+		return spi_write(flash->spi, flash->command, 2);
+	}
 }
 
 /*
@@ -668,6 +681,7 @@
 	/* Macronix */
 	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
 	{ "mx25l8005",   INFO(0xc22014, 0, 64 * 1024,  16, 0) },
+	{ "mx25l1606e",  INFO(0xc22015, 0, 64 * 1024,  32, SECT_4K) },
 	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, 0) },
 	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, 0) },
 	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
@@ -684,6 +698,10 @@
 	{ "s25sl032a",  INFO(0x010215,      0,  64 * 1024,  64, 0) },
 	{ "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, SECT_4K) },
 	{ "s25sl064a",  INFO(0x010216,      0,  64 * 1024, 128, 0) },
+	{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
+	{ "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, 0) },
+	{ "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) },
+	{ "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
 	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
 	{ "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
 	{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, 0) },
@@ -729,7 +747,10 @@
 	{ "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
 	{ "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
 
-	{ "m25px64", INFO(0x207117,  0, 64 * 1024, 128, 0) },
+	{ "m25px32",    INFO(0x207116,  0, 64 * 1024, 64, SECT_4K) },
+	{ "m25px32-s0", INFO(0x207316,  0, 64 * 1024, 64, SECT_4K) },
+	{ "m25px32-s1", INFO(0x206316,  0, 64 * 1024, 64, SECT_4K) },
+	{ "m25px64",    INFO(0x207117,  0, 64 * 1024, 128, 0) },
 
 	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
 	{ "w25x10", INFO(0xef3011, 0, 64 * 1024,  2,  SECT_4K) },
@@ -804,6 +825,8 @@
 	struct m25p			*flash;
 	struct flash_info		*info;
 	unsigned			i;
+	struct mtd_partition		*parts = NULL;
+	int				nr_parts = 0;
 
 	/* Platform data helps sort out which chip type we have, as
 	 * well as how this board partitions it.  If we don't have
@@ -868,9 +891,9 @@
 	 * up with the software protection bits set
 	 */
 
-	if (info->jedec_id >> 16 == 0x1f ||
-	    info->jedec_id >> 16 == 0x89 ||
-	    info->jedec_id >> 16 == 0xbf) {
+	if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL ||
+	    JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL ||
+	    JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) {
 		write_enable(flash);
 		write_sr(flash, 0);
 	}
@@ -888,7 +911,7 @@
 	flash->mtd.read = m25p80_read;
 
 	/* sst flash chips use AAI word program */
-	if (info->jedec_id >> 16 == 0xbf)
+	if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
 		flash->mtd.write = sst_write;
 	else
 		flash->mtd.write = m25p80_write;
@@ -914,7 +937,7 @@
 		/* enable 4-byte addressing if the device exceeds 16MiB */
 		if (flash->mtd.size > 0x1000000) {
 			flash->addr_width = 4;
-			set_4byte(flash, 1);
+			set_4byte(flash, info->jedec_id, 1);
 		} else
 			flash->addr_width = 3;
 	}
@@ -945,48 +968,41 @@
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	if (mtd_has_partitions()) {
-		struct mtd_partition	*parts = NULL;
-		int			nr_parts = 0;
+	if (mtd_has_cmdlinepart()) {
+		static const char *part_probes[]
+			= { "cmdlinepart", NULL, };
 
-		if (mtd_has_cmdlinepart()) {
-			static const char *part_probes[]
-					= { "cmdlinepart", NULL, };
+		nr_parts = parse_mtd_partitions(&flash->mtd,
+						part_probes, &parts, 0);
+	}
 
-			nr_parts = parse_mtd_partitions(&flash->mtd,
-					part_probes, &parts, 0);
-		}
-
-		if (nr_parts <= 0 && data && data->parts) {
-			parts = data->parts;
-			nr_parts = data->nr_parts;
-		}
+	if (nr_parts <= 0 && data && data->parts) {
+		parts = data->parts;
+		nr_parts = data->nr_parts;
+	}
 
 #ifdef CONFIG_MTD_OF_PARTS
-		if (nr_parts <= 0 && spi->dev.of_node) {
-			nr_parts = of_mtd_parse_partitions(&spi->dev,
-					spi->dev.of_node, &parts);
-		}
+	if (nr_parts <= 0 && spi->dev.of_node) {
+		nr_parts = of_mtd_parse_partitions(&spi->dev,
+						   spi->dev.of_node, &parts);
+	}
 #endif
 
-		if (nr_parts > 0) {
-			for (i = 0; i < nr_parts; i++) {
-				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-					"{.name = %s, .offset = 0x%llx, "
-						".size = 0x%llx (%lldKiB) }\n",
-					i, parts[i].name,
-					(long long)parts[i].offset,
-					(long long)parts[i].size,
-					(long long)(parts[i].size >> 10));
-			}
-			flash->partitioned = 1;
-			return add_mtd_partitions(&flash->mtd, parts, nr_parts);
+	if (nr_parts > 0) {
+		for (i = 0; i < nr_parts; i++) {
+			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
+			      "{.name = %s, .offset = 0x%llx, "
+			      ".size = 0x%llx (%lldKiB) }\n",
+			      i, parts[i].name,
+			      (long long)parts[i].offset,
+			      (long long)parts[i].size,
+			      (long long)(parts[i].size >> 10));
 		}
-	} else if (data && data->nr_parts)
-		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
-				data->nr_parts, data->name);
+		flash->partitioned = 1;
+	}
 
-	return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
+	return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ?
+		-ENODEV : 0;
 }
 
 
@@ -996,10 +1012,7 @@
 	int		status;
 
 	/* Clean up MTD stuff. */
-	if (mtd_has_partitions() && flash->partitioned)
-		status = del_mtd_partitions(&flash->mtd);
-	else
-		status = del_mtd_device(&flash->mtd);
+	status = mtd_device_unregister(&flash->mtd);
 	if (status == 0) {
 		kfree(flash->command);
 		kfree(flash);
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c
index 6a9a24a..8423fb6 100644
--- a/drivers/mtd/devices/ms02-nv.c
+++ b/drivers/mtd/devices/ms02-nv.c
@@ -220,7 +220,7 @@
 	mtd->writesize = 1;
 
 	ret = -EIO;
-	if (add_mtd_device(mtd)) {
+	if (mtd_device_register(mtd, NULL, 0)) {
 		printk(KERN_ERR
 			"ms02-nv: Unable to register MTD device, aborting!\n");
 		goto err_out_csr_res;
@@ -262,7 +262,7 @@
 
 	root_ms02nv_mtd = mp->next;
 
-	del_mtd_device(mtd);
+	mtd_device_unregister(mtd);
 
 	release_resource(mp->resource.csr);
 	kfree(mp->resource.csr);
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index c5015cc..13749d4 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -637,6 +637,8 @@
 	struct flash_platform_data	*pdata = spi->dev.platform_data;
 	char				*otp_tag = "";
 	int				err = 0;
+	struct mtd_partition		*parts;
+	int				nr_parts = 0;
 
 	priv = kzalloc(sizeof *priv, GFP_KERNEL);
 	if (!priv)
@@ -675,33 +677,25 @@
 			pagesize, otp_tag);
 	dev_set_drvdata(&spi->dev, priv);
 
-	if (mtd_has_partitions()) {
-		struct mtd_partition	*parts;
-		int			nr_parts = 0;
+	if (mtd_has_cmdlinepart()) {
+		static const char *part_probes[] = { "cmdlinepart", NULL, };
 
-		if (mtd_has_cmdlinepart()) {
-			static const char *part_probes[]
-					= { "cmdlinepart", NULL, };
+		nr_parts = parse_mtd_partitions(device, part_probes, &parts,
+						0);
+	}
 
-			nr_parts = parse_mtd_partitions(device,
-					part_probes, &parts, 0);
-		}
+	if (nr_parts <= 0 && pdata && pdata->parts) {
+		parts = pdata->parts;
+		nr_parts = pdata->nr_parts;
+	}
 
-		if (nr_parts <= 0 && pdata && pdata->parts) {
-			parts = pdata->parts;
-			nr_parts = pdata->nr_parts;
-		}
+	if (nr_parts > 0) {
+		priv->partitioned = 1;
+		err = mtd_device_register(device, parts, nr_parts);
+		goto out;
+	}
 
-		if (nr_parts > 0) {
-			priv->partitioned = 1;
-			err = add_mtd_partitions(device, parts, nr_parts);
-			goto out;
-		}
-	} else if (pdata && pdata->nr_parts)
-		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
-				pdata->nr_parts, device->name);
-
-	if (add_mtd_device(device) == 1)
+	if (mtd_device_register(device, NULL, 0) == 1)
 		err = -ENODEV;
 
 out:
@@ -939,10 +933,7 @@
 
 	DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev));
 
-	if (mtd_has_partitions() && flash->partitioned)
-		status = del_mtd_partitions(&flash->mtd);
-	else
-		status = del_mtd_device(&flash->mtd);
+	status = mtd_device_unregister(&flash->mtd);
 	if (status == 0) {
 		dev_set_drvdata(&spi->dev, NULL);
 		kfree(flash);
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
index 1483e18..2562689 100644
--- a/drivers/mtd/devices/mtdram.c
+++ b/drivers/mtd/devices/mtdram.c
@@ -104,7 +104,7 @@
 static void __exit cleanup_mtdram(void)
 {
 	if (mtd_info) {
-		del_mtd_device(mtd_info);
+		mtd_device_unregister(mtd_info);
 		vfree(mtd_info->priv);
 		kfree(mtd_info);
 	}
@@ -133,9 +133,8 @@
 	mtd->read = ram_read;
 	mtd->write = ram_write;
 
-	if (add_mtd_device(mtd)) {
+	if (mtd_device_register(mtd, NULL, 0))
 		return -EIO;
-	}
 
 	return 0;
 }
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 8d28fa0..23423bd 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -115,7 +115,7 @@
 	struct phram_mtd_list *this, *safe;
 
 	list_for_each_entry_safe(this, safe, &phram_list, list) {
-		del_mtd_device(&this->mtd);
+		mtd_device_unregister(&this->mtd);
 		iounmap(this->mtd.priv);
 		kfree(this->mtd.name);
 		kfree(this);
@@ -153,7 +153,7 @@
 	new->mtd.writesize = 1;
 
 	ret = -EAGAIN;
-	if (add_mtd_device(&new->mtd)) {
+	if (mtd_device_register(&new->mtd, NULL, 0)) {
 		pr_err("Failed to register new device\n");
 		goto out2;
 	}
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index 41b8cdc..ecff765 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -798,7 +798,7 @@
 		mtd->writesize = 1;
 		mtd->owner = THIS_MODULE;
 
-		if (add_mtd_device(mtd)) {
+		if (mtd_device_register(mtd, NULL, 0)) {
 			printk(KERN_NOTICE "pmc551: Failed to register new device\n");
 			pci_iounmap(PCI_Device, priv->start);
 			kfree(mtd->priv);
@@ -806,7 +806,7 @@
 			break;
 		}
 
-		/* Keep a reference as the add_mtd_device worked */
+		/* Keep a reference as the mtd_device_register worked */
 		pci_dev_get(PCI_Device);
 
 		printk(KERN_NOTICE "Registered pmc551 memory device.\n");
@@ -856,7 +856,7 @@
 		pci_dev_put(priv->dev);
 
 		kfree(mtd->priv);
-		del_mtd_device(mtd);
+		mtd_device_unregister(mtd);
 		kfree(mtd);
 		found++;
 	}
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index 592016a..e585263 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -210,7 +210,7 @@
 	(*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ;
 	(*curmtd)->mtdinfo->writesize = 1;
 
-	if (add_mtd_device((*curmtd)->mtdinfo))	{
+	if (mtd_device_register((*curmtd)->mtdinfo, NULL, 0))	{
 		E("slram: Failed to register new device\n");
 		iounmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start);
 		kfree((*curmtd)->mtdinfo->priv);
@@ -231,7 +231,7 @@
 
 	while (slram_mtdlist) {
 		nextitem = slram_mtdlist->next;
-		del_mtd_device(slram_mtdlist->mtdinfo);
+		mtd_device_unregister(slram_mtdlist->mtdinfo);
 		iounmap(((slram_priv_t *)slram_mtdlist->mtdinfo->priv)->start);
 		kfree(slram_mtdlist->mtdinfo->priv);
 		kfree(slram_mtdlist->mtdinfo);
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index c163e61..1e2c430 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -66,7 +66,7 @@
 
 #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd)
 
-static struct flash_info __initdata sst25l_flash_info[] = {
+static struct flash_info __devinitdata sst25l_flash_info[] = {
 	{"sst25lf020a", 0xbf43, 256, 1024, 4096},
 	{"sst25lf040a",	0xbf44,	256, 2048, 4096},
 };
@@ -381,6 +381,8 @@
 	struct sst25l_flash *flash;
 	struct flash_platform_data *data;
 	int ret, i;
+	struct mtd_partition *parts = NULL;
+	int nr_parts = 0;
 
 	flash_info = sst25l_match_device(spi);
 	if (!flash_info)
@@ -420,46 +422,37 @@
 	      flash->mtd.erasesize, flash->mtd.erasesize / 1024,
 	      flash->mtd.numeraseregions);
 
-	if (mtd_has_partitions()) {
-		struct mtd_partition *parts = NULL;
-		int nr_parts = 0;
 
-		if (mtd_has_cmdlinepart()) {
-			static const char *part_probes[] =
-				{"cmdlinepart", NULL};
+	if (mtd_has_cmdlinepart()) {
+		static const char *part_probes[] = {"cmdlinepart", NULL};
 
-			nr_parts = parse_mtd_partitions(&flash->mtd,
-							part_probes,
-							&parts, 0);
-		}
-
-		if (nr_parts <= 0 && data && data->parts) {
-			parts = data->parts;
-			nr_parts = data->nr_parts;
-		}
-
-		if (nr_parts > 0) {
-			for (i = 0; i < nr_parts; i++) {
-				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-				      "{.name = %s, .offset = 0x%llx, "
-				      ".size = 0x%llx (%lldKiB) }\n",
-				      i, parts[i].name,
-				      (long long)parts[i].offset,
-				      (long long)parts[i].size,
-				      (long long)(parts[i].size >> 10));
-			}
-
-			flash->partitioned = 1;
-			return add_mtd_partitions(&flash->mtd,
-						  parts, nr_parts);
-		}
-
-	} else if (data && data->nr_parts) {
-		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
-			 data->nr_parts, data->name);
+		nr_parts = parse_mtd_partitions(&flash->mtd,
+						part_probes,
+						&parts, 0);
 	}
 
-	ret = add_mtd_device(&flash->mtd);
+	if (nr_parts <= 0 && data && data->parts) {
+		parts = data->parts;
+		nr_parts = data->nr_parts;
+	}
+
+	if (nr_parts > 0) {
+		for (i = 0; i < nr_parts; i++) {
+			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
+			      "{.name = %s, .offset = 0x%llx, "
+			      ".size = 0x%llx (%lldKiB) }\n",
+			      i, parts[i].name,
+			      (long long)parts[i].offset,
+			      (long long)parts[i].size,
+			      (long long)(parts[i].size >> 10));
+		}
+
+		flash->partitioned = 1;
+		return mtd_device_register(&flash->mtd, parts,
+					   nr_parts);
+	}
+
+	ret = mtd_device_register(&flash->mtd, NULL, 0);
 	if (ret == 1) {
 		kfree(flash);
 		dev_set_drvdata(&spi->dev, NULL);
@@ -469,15 +462,12 @@
 	return 0;
 }
 
-static int __exit sst25l_remove(struct spi_device *spi)
+static int __devexit sst25l_remove(struct spi_device *spi)
 {
 	struct sst25l_flash *flash = dev_get_drvdata(&spi->dev);
 	int ret;
 
-	if (mtd_has_partitions() && flash->partitioned)
-		ret = del_mtd_partitions(&flash->mtd);
-	else
-		ret = del_mtd_device(&flash->mtd);
+	ret = mtd_device_unregister(&flash->mtd);
 	if (ret == 0)
 		kfree(flash);
 	return ret;
@@ -490,7 +480,7 @@
 		.owner	= THIS_MODULE,
 	},
 	.probe		= sst25l_probe,
-	.remove		= __exit_p(sst25l_remove),
+	.remove		= __devexit_p(sst25l_remove),
 };
 
 static int __init sst25l_init(void)
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
index 1267992..65655dd 100644
--- a/drivers/mtd/lpddr/lpddr_cmds.c
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -313,12 +313,7 @@
 		if (ret) {
 			/* Oops. something got wrong. */
 			/* Resume and pretend we weren't here.  */
-			map_write(map, CMD(LPDDR_RESUME),
-				map->pfow_base + PFOW_COMMAND_CODE);
-			map_write(map, CMD(LPDDR_START_EXECUTION),
-				map->pfow_base + PFOW_COMMAND_EXECUTE);
-			chip->state = FL_ERASING;
-			chip->oldstate = FL_READY;
+			put_chip(map, chip);
 			printk(KERN_ERR "%s: suspend operation failed."
 					"State may be wrong \n", map->name);
 			return -EIO;
@@ -383,7 +378,6 @@
 
 	switch (chip->oldstate) {
 	case FL_ERASING:
-		chip->state = chip->oldstate;
 		map_write(map, CMD(LPDDR_RESUME),
 				map->pfow_base + PFOW_COMMAND_CODE);
 		map_write(map, CMD(LPDDR_START_EXECUTION),
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 5069111..c0c328c 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -82,7 +82,6 @@
 config MTD_PMC_MSP_EVM
 	tristate "CFI Flash device mapped on PMC-Sierra MSP"
 	depends on PMC_MSP && MTD_CFI
-	select MTD_PARTITIONS
 	help
 	  This provides a 'mapping' driver which supports the way
 	  in which user-programmable flash chips are connected on the
@@ -122,7 +121,7 @@
 
 config MTD_NETSC520
 	tristate "CFI Flash device mapped on AMD NetSc520"
-	depends on X86 && MTD_CFI && MTD_PARTITIONS
+	depends on X86 && MTD_CFI
 	help
 	  This enables access routines for the flash chips on the AMD NetSc520
 	  demonstration board. If you have one of these boards and would like
@@ -131,7 +130,6 @@
 config MTD_TS5500
 	tristate "JEDEC Flash device mapped on Technologic Systems TS-5500"
 	depends on X86
-	select MTD_PARTITIONS
 	select MTD_JEDECPROBE
 	select MTD_CFI_AMDSTD
 	help
@@ -149,7 +147,7 @@
 
 config MTD_SBC_GXX
 	tristate "CFI Flash device mapped on Arcom SBC-GXx boards"
-	depends on X86 && MTD_CFI_INTELEXT && MTD_PARTITIONS && MTD_COMPLEX_MAPPINGS
+	depends on X86 && MTD_CFI_INTELEXT && MTD_COMPLEX_MAPPINGS
 	help
 	  This provides a driver for the on-board flash of Arcom Control
 	  Systems' SBC-GXn family of boards, formerly known as SBC-MediaGX.
@@ -161,7 +159,6 @@
 config MTD_PXA2XX
 	tristate "CFI Flash device mapped on Intel XScale PXA2xx based boards"
 	depends on (PXA25x || PXA27x) && MTD_CFI_INTELEXT
-	select MTD_PARTITIONS
 	help
 	  This provides a driver for the NOR flash attached to a PXA2xx chip.
 
@@ -185,7 +182,7 @@
 
 config MTD_SCx200_DOCFLASH
 	tristate "Flash device mapped with DOCCS on NatSemi SCx200"
-	depends on SCx200 && MTD_CFI && MTD_PARTITIONS
+	depends on SCx200 && MTD_CFI
 	help
 	  Enable support for a flash chip mapped using the DOCCS signal on a
 	  National Semiconductor SCx200 processor.
@@ -247,7 +244,7 @@
 
 config MTD_NETtel
 	tristate "CFI flash device on SnapGear/SecureEdge"
-	depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE
+	depends on X86 && MTD_JEDECPROBE
 	help
 	  Support for flash chips on NETtel/SecureEdge/SnapGear boards.
 
@@ -269,7 +266,7 @@
 
 config MTD_DILNETPC
 	tristate "CFI Flash device mapped on DIL/Net PC"
-	depends on X86 && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
+	depends on X86 && MTD_CFI_INTELEXT && BROKEN
 	help
 	  MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP".
 	  For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm>
@@ -355,7 +352,7 @@
 
 config MTD_SA1100
 	tristate "CFI Flash device mapped on StrongARM SA11x0"
-	depends on MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS
+	depends on MTD_CFI && ARCH_SA1100
 	help
 	  This enables access to the flash chips on most platforms based on
 	  the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
@@ -389,7 +386,7 @@
 
 config MTD_FORTUNET
 	tristate "CFI Flash device mapped on the FortuNet board"
-	depends on MTD_CFI && MTD_PARTITIONS && SA1100_FORTUNET
+	depends on MTD_CFI && SA1100_FORTUNET
 	help
 	  This enables access to the Flash on the FortuNet board.  If you
 	  have such a board, say 'Y'.
@@ -461,7 +458,6 @@
 config MTD_BFIN_ASYNC
 	tristate "Blackfin BF533-STAMP Flash Chip Support"
 	depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS
-	select MTD_PARTITIONS
 	default y
 	help
 	  Map driver which allows for simultaneous utilization of
@@ -473,7 +469,6 @@
 	tristate "GPIO-assisted Flash Chip Support"
 	depends on GENERIC_GPIO || GPIOLIB
 	depends on MTD_COMPLEX_MAPPINGS
-	select MTD_PARTITIONS
 	help
 	  Map driver which allows flashes to be partially physically addressed
 	  and assisted by GPIOs.
@@ -482,14 +477,13 @@
 
 config MTD_UCLINUX
 	bool "Generic uClinux RAM/ROM filesystem support"
-	depends on MTD_PARTITIONS && MTD_RAM=y && !MMU
+	depends on MTD_RAM=y && !MMU
 	help
 	  Map driver to support image based filesystems for uClinux.
 
 config MTD_WRSBC8260
 	tristate "Map driver for WindRiver PowerQUICC II MPC82xx board"
 	depends on (SBC82xx || SBC8560)
-	select MTD_PARTITIONS
 	select MTD_MAP_BANK_WIDTH_4
 	select MTD_MAP_BANK_WIDTH_1
 	select MTD_CFI_I1
@@ -502,7 +496,6 @@
 config MTD_DMV182
         tristate "Map driver for Dy-4 SVME/DMV-182 board."
         depends on DMV182
-        select MTD_PARTITIONS
 	select MTD_MAP_BANK_WIDTH_32
 	select MTD_CFI_I8
 	select MTD_CFI_AMDSTD
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index 92de7e3..e2875d6 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -82,7 +82,7 @@
 		if (map->rsrc.parent) {
 			release_resource(&map->rsrc);
 		}
-		del_mtd_device(map->mtd);
+		mtd_device_unregister(map->mtd);
 		map_destroy(map->mtd);
 		list_del(&map->list);
 		kfree(map);
@@ -262,7 +262,7 @@
 
 		/* Now that the mtd devices is complete claim and export it */
 		map->mtd->owner = THIS_MODULE;
-		if (add_mtd_device(map->mtd)) {
+		if (mtd_device_register(map->mtd, NULL, 0)) {
 			map_destroy(map->mtd);
 			map->mtd = NULL;
 			goto out;
diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c
index 5366418..e5bfd0e 100644
--- a/drivers/mtd/maps/autcpu12-nvram.c
+++ b/drivers/mtd/maps/autcpu12-nvram.c
@@ -88,7 +88,7 @@
 	sram_mtd->owner = THIS_MODULE;
 	sram_mtd->erasesize = 16;
 
-	if (add_mtd_device(sram_mtd)) {
+	if (mtd_device_register(sram_mtd, NULL, 0)) {
 		printk("NV-RAM device addition failed\n");
 		err = -ENOMEM;
 		goto out_probe;
@@ -111,7 +111,7 @@
 static void __exit cleanup_autcpu12_maps(void)
 {
 	if (sram_mtd) {
-		del_mtd_device(sram_mtd);
+		mtd_device_unregister(sram_mtd);
 		map_destroy(sram_mtd);
 		iounmap((void *)autcpu12_sram_map.virt);
 	}
diff --git a/drivers/mtd/maps/bcm963xx-flash.c b/drivers/mtd/maps/bcm963xx-flash.c
index 1f30495..608967f 100644
--- a/drivers/mtd/maps/bcm963xx-flash.c
+++ b/drivers/mtd/maps/bcm963xx-flash.c
@@ -224,8 +224,8 @@
 		goto err_probe;
 	}
 
-	return add_mtd_partitions(bcm963xx_mtd_info, parsed_parts,
-						parsed_nr_parts);
+	return mtd_device_register(bcm963xx_mtd_info, parsed_parts,
+				   parsed_nr_parts);
 
 err_probe:
 	iounmap(bcm963xx_map.virt);
@@ -235,7 +235,7 @@
 static int bcm963xx_remove(struct platform_device *pdev)
 {
 	if (bcm963xx_mtd_info) {
-		del_mtd_partitions(bcm963xx_mtd_info);
+		mtd_device_unregister(bcm963xx_mtd_info);
 		map_destroy(bcm963xx_mtd_info);
 	}
 
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index 85dd181..d4297a9 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -41,9 +41,7 @@
 	uint32_t flash_ambctl0, flash_ambctl1;
 	uint32_t save_ambctl0, save_ambctl1;
 	unsigned long irq_flags;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *parts;
-#endif
 };
 
 static void switch_to_flash(struct async_state *state)
@@ -124,9 +122,7 @@
 	switch_back(state);
 }
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
-#endif
 
 static int __devinit bfin_flash_probe(struct platform_device *pdev)
 {
@@ -169,22 +165,17 @@
 		return -ENXIO;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
 	if (ret > 0) {
 		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
-		add_mtd_partitions(state->mtd, pdata->parts, ret);
+		mtd_device_register(state->mtd, pdata->parts, ret);
 		state->parts = pdata->parts;
-
 	} else if (pdata->nr_parts) {
 		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
-		add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts);
-
-	} else
-#endif
-	{
+		mtd_device_register(state->mtd, pdata->parts, pdata->nr_parts);
+	} else {
 		pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
-		add_mtd_device(state->mtd);
+		mtd_device_register(state->mtd, NULL, 0);
 	}
 
 	platform_set_drvdata(pdev, state);
@@ -196,10 +187,8 @@
 {
 	struct async_state *state = platform_get_drvdata(pdev);
 	gpio_free(state->enet_flash_pin);
-#ifdef CONFIG_MTD_PARTITIONS
-	del_mtd_partitions(state->mtd);
+	mtd_device_unregister(state->mtd);
 	kfree(state->parts);
-#endif
 	map_destroy(state->mtd);
 	kfree(state);
 	return 0;
diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c
index 8d92d8d..c29cbf8 100644
--- a/drivers/mtd/maps/cdb89712.c
+++ b/drivers/mtd/maps/cdb89712.c
@@ -75,7 +75,7 @@
 
 	flash_mtd->owner = THIS_MODULE;
 
-	if (add_mtd_device(flash_mtd)) {
+	if (mtd_device_register(flash_mtd, NULL, 0)) {
 		printk("FLASH device addition failed\n");
 		err = -ENOMEM;
 		goto out_probe;
@@ -141,7 +141,7 @@
 	sram_mtd->owner = THIS_MODULE;
 	sram_mtd->erasesize = 16;
 
-	if (add_mtd_device(sram_mtd)) {
+	if (mtd_device_register(sram_mtd, NULL, 0)) {
 		printk("SRAM device addition failed\n");
 		err = -ENOMEM;
 		goto out_probe;
@@ -209,7 +209,7 @@
 	bootrom_mtd->owner = THIS_MODULE;
 	bootrom_mtd->erasesize = 0x10000;
 
-	if (add_mtd_device(bootrom_mtd)) {
+	if (mtd_device_register(bootrom_mtd, NULL, 0)) {
 		printk("BootROM device addition failed\n");
 		err = -ENOMEM;
 		goto out_probe;
@@ -249,21 +249,21 @@
 static void __exit cleanup_cdb89712_maps(void)
 {
 	if (sram_mtd) {
-		del_mtd_device(sram_mtd);
+		mtd_device_unregister(sram_mtd);
 		map_destroy(sram_mtd);
 		iounmap((void *)cdb89712_sram_map.virt);
 		release_resource (&cdb89712_sram_resource);
 	}
 
 	if (flash_mtd) {
-		del_mtd_device(flash_mtd);
+		mtd_device_unregister(flash_mtd);
 		map_destroy(flash_mtd);
 		iounmap((void *)cdb89712_flash_map.virt);
 		release_resource (&cdb89712_flash_resource);
 	}
 
 	if (bootrom_mtd) {
-		del_mtd_device(bootrom_mtd);
+		mtd_device_unregister(bootrom_mtd);
 		map_destroy(bootrom_mtd);
 		iounmap((void *)cdb89712_bootrom_map.virt);
 		release_resource (&cdb89712_bootrom_resource);
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
index 23f551d..06f9c98 100644
--- a/drivers/mtd/maps/ceiva.c
+++ b/drivers/mtd/maps/ceiva.c
@@ -224,7 +224,7 @@
 {
 	int i;
 
-	del_mtd_partitions(mtd);
+	mtd_device_unregister(mtd);
 
 	if (mtd != clps[0].mtd)
 		mtd_concat_destroy(mtd);
@@ -292,11 +292,11 @@
 	if (nr_parts == 0) {
 		printk(KERN_NOTICE "clps flash: no partition info "
 			"available, registering whole flash\n");
-		add_mtd_device(mtd);
+		mtd_device_register(mtd, NULL, 0);
 	} else {
 		printk(KERN_NOTICE "clps flash: using %s partition "
 			"definition\n", part_type);
-		add_mtd_partitions(mtd, parsed_parts, nr_parts);
+		mtd_device_register(mtd, parsed_parts, nr_parts);
 	}
 
 	/* Always succeeds. */
diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c
index f71343c..d16fc9d 100644
--- a/drivers/mtd/maps/cfi_flagadm.c
+++ b/drivers/mtd/maps/cfi_flagadm.c
@@ -107,7 +107,7 @@
 	mymtd = do_map_probe("cfi_probe", &flagadm_map);
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
-		add_mtd_partitions(mymtd, flagadm_parts, PARTITION_COUNT);
+		mtd_device_register(mymtd, flagadm_parts, PARTITION_COUNT);
 		printk(KERN_NOTICE "FlagaDM flash device initialized\n");
 		return 0;
 	}
@@ -119,7 +119,7 @@
 static void __exit cleanup_flagadm(void)
 {
 	if (mymtd) {
-		del_mtd_partitions(mymtd);
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 	if (flagadm_map.virt) {
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 5fdb7b2..3d0e762 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -94,7 +94,7 @@
 		if (map->rsrc.parent)
 			release_resource(&map->rsrc);
 
-		del_mtd_device(map->mtd);
+		mtd_device_unregister(map->mtd);
 		map_destroy(map->mtd);
 		list_del(&map->list);
 		kfree(map);
@@ -291,7 +291,7 @@
 
 		/* Now that the mtd devices is complete claim and export it */
 		map->mtd->owner = THIS_MODULE;
-		if (add_mtd_device(map->mtd)) {
+		if (mtd_device_register(map->mtd, NULL, 0)) {
 			map_destroy(map->mtd);
 			map->mtd = NULL;
 			goto out;
diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c
index cfacfa6..85bdece 100644
--- a/drivers/mtd/maps/dbox2-flash.c
+++ b/drivers/mtd/maps/dbox2-flash.c
@@ -93,7 +93,7 @@
 		mymtd->owner = THIS_MODULE;
 
                 /* Create MTD devices for each partition. */
-	        add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
+		mtd_device_register(mymtd, partition_info, NUM_PARTITIONS);
 
 		return 0;
 	}
@@ -105,7 +105,7 @@
 static void __exit cleanup_dbox2_flash(void)
 {
 	if (mymtd) {
-		del_mtd_partitions(mymtd);
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 	if (dbox2_flash_map.virt) {
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c
index b3cb3a1..7a9e198 100644
--- a/drivers/mtd/maps/dc21285.c
+++ b/drivers/mtd/maps/dc21285.c
@@ -145,17 +145,13 @@
 
 
 /* Partition stuff */
-#ifdef CONFIG_MTD_PARTITIONS
 static struct mtd_partition *dc21285_parts;
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
-#endif
 
 static int __init init_dc21285(void)
 {
 
-#ifdef CONFIG_MTD_PARTITIONS
 	int nrparts;
-#endif
 
 	/* Determine bankwidth */
 	switch (*CSR_SA110_CNTL & (3<<14)) {
@@ -204,13 +200,8 @@
 
 	dc21285_mtd->owner = THIS_MODULE;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0);
-	if (nrparts > 0)
-		add_mtd_partitions(dc21285_mtd, dc21285_parts, nrparts);
-	else
-#endif
-		add_mtd_device(dc21285_mtd);
+	mtd_device_register(dc21285_mtd, dc21285_parts, nrparts);
 
 	if(machine_is_ebsa285()) {
 		/*
@@ -232,14 +223,9 @@
 
 static void __exit cleanup_dc21285(void)
 {
-#ifdef CONFIG_MTD_PARTITIONS
-	if (dc21285_parts) {
-		del_mtd_partitions(dc21285_mtd);
+	mtd_device_unregister(dc21285_mtd);
+	if (dc21285_parts)
 		kfree(dc21285_parts);
-	} else
-#endif
-		del_mtd_device(dc21285_mtd);
-
 	map_destroy(dc21285_mtd);
 	iounmap(dc21285_map.virt);
 }
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c
index 0713e3a..3e393f0 100644
--- a/drivers/mtd/maps/dilnetpc.c
+++ b/drivers/mtd/maps/dilnetpc.c
@@ -450,7 +450,7 @@
 	partition_info[2].mtdp = &lowlvl_parts[1];
 	partition_info[3].mtdp = &lowlvl_parts[3];
 
-	add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
+	mtd_device_register(mymtd, partition_info, NUM_PARTITIONS);
 
 	/*
 	** now create a virtual MTD device by concatenating the for partitions
@@ -463,7 +463,8 @@
 		** we do not supply mtd pointers in higlvl_partition_info, so
 		** add_mtd_partitions() will register the devices.
 		*/
-		add_mtd_partitions(merged_mtd, higlvl_partition_info, NUM_HIGHLVL_PARTITIONS);
+		mtd_device_register(merged_mtd, higlvl_partition_info,
+				    NUM_HIGHLVL_PARTITIONS);
 	}
 
 	return 0;
@@ -472,12 +473,12 @@
 static void __exit cleanup_dnpc(void)
 {
 	if(merged_mtd) {
-		del_mtd_partitions(merged_mtd);
+		mtd_device_unregister(merged_mtd);
 		mtd_concat_destroy(merged_mtd);
 	}
 
 	if (mymtd) {
-		del_mtd_partitions(mymtd);
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 	if (dnpc_map.virt) {
diff --git a/drivers/mtd/maps/dmv182.c b/drivers/mtd/maps/dmv182.c
index d171674..6538ac6 100644
--- a/drivers/mtd/maps/dmv182.c
+++ b/drivers/mtd/maps/dmv182.c
@@ -120,7 +120,7 @@
 		   this_mtd->size >> 20, FLASH_BASE_ADDR);
 
 	this_mtd->owner = THIS_MODULE;
-	add_mtd_partitions(this_mtd, partitions, num_parts);
+	mtd_device_register(this_mtd, partitions, num_parts);
 
 	return 0;
 }
@@ -129,7 +129,7 @@
 {
 	if (this_mtd)
 	{
-		del_mtd_partitions(this_mtd);
+		mtd_device_unregister(this_mtd);
 		map_destroy(this_mtd);
 	}
 
diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
index be9e90b..fe42a21 100644
--- a/drivers/mtd/maps/edb7312.c
+++ b/drivers/mtd/maps/edb7312.c
@@ -15,10 +15,7 @@
 #include <asm/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
-
-#ifdef CONFIG_MTD_PARTITIONS
 #include <linux/mtd/partitions.h>
-#endif
 
 #define WINDOW_ADDR 0x00000000      /* physical properties of flash */
 #define WINDOW_SIZE 0x01000000
@@ -40,8 +37,6 @@
 	.phys = WINDOW_ADDR,
 };
 
-#ifdef CONFIG_MTD_PARTITIONS
-
 /*
  * MTD partitioning stuff
  */
@@ -66,8 +61,6 @@
 
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
-#endif
-
 static int                   mtd_parts_nb = 0;
 static struct mtd_partition *mtd_parts    = 0;
 
@@ -96,27 +89,24 @@
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
 
-#ifdef CONFIG_MTD_PARTITIONS
 		mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID);
 		if (mtd_parts_nb > 0)
-		  part_type = "detected";
+			part_type = "detected";
 
-		if (mtd_parts_nb == 0)
-		{
+		if (mtd_parts_nb == 0) {
 			mtd_parts = static_partitions;
 			mtd_parts_nb = ARRAY_SIZE(static_partitions);
 			part_type = "static";
 		}
-#endif
-		add_mtd_device(mymtd);
+
 		if (mtd_parts_nb == 0)
-		  printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
+			printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
 		else
-		{
 			printk(KERN_NOTICE MSG_PREFIX
 			       "using %s partition definition\n", part_type);
-			add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb);
-		}
+		/* Register the whole device first. */
+		mtd_device_register(mymtd, NULL, 0);
+		mtd_device_register(mymtd, mtd_parts, mtd_parts_nb);
 		return 0;
 	}
 
@@ -127,7 +117,7 @@
 static void __exit cleanup_edb7312nor(void)
 {
 	if (mymtd) {
-		del_mtd_device(mymtd);
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 	if (edb7312nor_map.virt) {
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
index 4feb750..08322b1 100644
--- a/drivers/mtd/maps/esb2rom.c
+++ b/drivers/mtd/maps/esb2rom.c
@@ -128,7 +128,7 @@
 	list_for_each_entry_safe(map, scratch, &window->maps, list) {
 		if (map->rsrc.parent)
 			release_resource(&map->rsrc);
-		del_mtd_device(map->mtd);
+		mtd_device_unregister(map->mtd);
 		map_destroy(map->mtd);
 		list_del(&map->list);
 		kfree(map);
@@ -352,7 +352,7 @@
 
 		/* Now that the mtd devices is complete claim and export it */
 		map->mtd->owner = THIS_MODULE;
-		if (add_mtd_device(map->mtd)) {
+		if (mtd_device_register(map->mtd, NULL, 0)) {
 			map_destroy(map->mtd);
 			map->mtd = NULL;
 			goto out;
diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c
index 1e43124..956e2e4 100644
--- a/drivers/mtd/maps/fortunet.c
+++ b/drivers/mtd/maps/fortunet.c
@@ -243,8 +243,9 @@
 					&map_regions[ix].map_info);
 			}
 			map_regions[ix].mymtd->owner = THIS_MODULE;
-			add_mtd_partitions(map_regions[ix].mymtd,
-				map_regions[ix].parts,map_regions_parts[ix]);
+			mtd_device_register(map_regions[ix].mymtd,
+					    map_regions[ix].parts,
+					    map_regions_parts[ix]);
 		}
 	}
 	if(iy)
@@ -261,7 +262,7 @@
 		{
 			if( map_regions[ix].mymtd )
 			{
-				del_mtd_partitions( map_regions[ix].mymtd );
+				mtd_device_unregister(map_regions[ix].mymtd);
 				map_destroy( map_regions[ix].mymtd );
 			}
 			iounmap((void *)map_regions[ix].map_info.virt);
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index af5707a..7568c5f 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -155,9 +155,7 @@
 	memcpy_toio(map->virt + (to % state->win_size), from, len);
 }
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
-#endif
 
 /**
  * gpio_flash_probe() - setup a mapping for a GPIO assisted flash
@@ -189,7 +187,7 @@
  */
 static int __devinit gpio_flash_probe(struct platform_device *pdev)
 {
-	int ret;
+	int nr_parts;
 	size_t i, arr_size;
 	struct physmap_flash_data *pdata;
 	struct resource *memory;
@@ -254,24 +252,21 @@
 		return -ENXIO;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
-	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
-	if (ret > 0) {
+	nr_parts = parse_mtd_partitions(state->mtd, part_probe_types,
+					&pdata->parts, 0);
+	if (nr_parts > 0) {
 		pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n");
-		add_mtd_partitions(state->mtd, pdata->parts, ret);
 		kfree(pdata->parts);
-
 	} else if (pdata->nr_parts) {
 		pr_devinit(KERN_NOTICE PFX "Using board partition definition\n");
-		add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts);
-
-	} else
-#endif
-	{
+		nr_parts = pdata->nr_parts;
+	} else {
 		pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n");
-		add_mtd_device(state->mtd);
+		nr_parts = 0;
 	}
 
+	mtd_device_register(state->mtd, pdata->parts, nr_parts);
+
 	return 0;
 }
 
@@ -282,9 +277,7 @@
 	do {
 		gpio_free(state->gpio_addrs[i]);
 	} while (++i < state->gpio_count);
-#ifdef CONFIG_MTD_PARTITIONS
-	del_mtd_partitions(state->mtd);
-#endif
+	mtd_device_unregister(state->mtd);
 	map_destroy(state->mtd);
 	kfree(state);
 	return 0;
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c
index 72c724f..7f03586 100644
--- a/drivers/mtd/maps/h720x-flash.c
+++ b/drivers/mtd/maps/h720x-flash.c
@@ -92,18 +92,16 @@
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
 
-#ifdef CONFIG_MTD_PARTITIONS
 		nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
 		if (nr_mtd_parts > 0)
 			part_type = "command line";
-#endif
 		if (nr_mtd_parts <= 0) {
 			mtd_parts = h720x_partitions;
 			nr_mtd_parts = NUM_PARTITIONS;
 			part_type = "builtin";
 		}
 		printk(KERN_INFO "Using %s partition table\n", part_type);
-		add_mtd_partitions(mymtd, mtd_parts, nr_mtd_parts);
+		mtd_device_register(mymtd, mtd_parts, nr_mtd_parts);
 		return 0;
 	}
 
@@ -118,7 +116,7 @@
 {
 
 	if (mymtd) {
-		del_mtd_partitions(mymtd);
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
index 1337a41..6689dcb 100644
--- a/drivers/mtd/maps/ichxrom.c
+++ b/drivers/mtd/maps/ichxrom.c
@@ -67,7 +67,7 @@
 	list_for_each_entry_safe(map, scratch, &window->maps, list) {
 		if (map->rsrc.parent)
 			release_resource(&map->rsrc);
-		del_mtd_device(map->mtd);
+		mtd_device_unregister(map->mtd);
 		map_destroy(map->mtd);
 		list_del(&map->list);
 		kfree(map);
@@ -287,7 +287,7 @@
 
 		/* Now that the mtd devices is complete claim and export it */
 		map->mtd->owner = THIS_MODULE;
-		if (add_mtd_device(map->mtd)) {
+		if (mtd_device_register(map->mtd, NULL, 0)) {
 			map_destroy(map->mtd);
 			map->mtd = NULL;
 			goto out;
diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
index 998a27d..404a50c 100644
--- a/drivers/mtd/maps/impa7.c
+++ b/drivers/mtd/maps/impa7.c
@@ -15,10 +15,7 @@
 #include <asm/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
-
-#ifdef CONFIG_MTD_PARTITIONS
 #include <linux/mtd/partitions.h>
-#endif
 
 #define WINDOW_ADDR0 0x00000000      /* physical properties of flash */
 #define WINDOW_SIZE0 0x00800000
@@ -49,8 +46,6 @@
 	},
 };
 
-#ifdef CONFIG_MTD_PARTITIONS
-
 /*
  * MTD partitioning stuff
  */
@@ -66,8 +61,6 @@
 static int mtd_parts_nb[NUM_FLASHBANKS];
 static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
 
-#endif
-
 static const char *probes[] = { "cmdlinepart", NULL };
 
 static int __init init_impa7(void)
@@ -104,7 +97,6 @@
 		if (impa7_mtd[i]) {
 			impa7_mtd[i]->owner = THIS_MODULE;
 			devicesfound++;
-#ifdef CONFIG_MTD_PARTITIONS
 			mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i],
 							       probes,
 							       &mtd_parts[i],
@@ -120,12 +112,8 @@
 			printk(KERN_NOTICE MSG_PREFIX
 			       "using %s partition definition\n",
 			       part_type);
-			add_mtd_partitions(impa7_mtd[i],
-					   mtd_parts[i], mtd_parts_nb[i]);
-#else
-			add_mtd_device(impa7_mtd[i]);
-
-#endif
+			mtd_device_register(impa7_mtd[i],
+					    mtd_parts[i], mtd_parts_nb[i]);
 		}
 		else
 			iounmap((void *)impa7_map[i].virt);
@@ -138,11 +126,7 @@
 	int i;
 	for (i=0; i<NUM_FLASHBANKS; i++) {
 		if (impa7_mtd[i]) {
-#ifdef CONFIG_MTD_PARTITIONS
-			del_mtd_partitions(impa7_mtd[i]);
-#else
-			del_mtd_device(impa7_mtd[i]);
-#endif
+			mtd_device_unregister(impa7_mtd[i]);
 			map_destroy(impa7_mtd[i]);
 			iounmap((void *)impa7_map[i].virt);
 			impa7_map[i].virt = 0;
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index fc19985..d2f47be 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -66,33 +66,18 @@
 
 static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
 {
-	if (p->nr_parts > 0) {
-#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
-		del_mtd_partitions(p->info);
-#endif
-	} else
-		del_mtd_device(p->info);
+	mtd_device_unregister(p->info);
 }
 
 static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
 {
-	int err = 0;
-#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
 	struct mtd_partition *parts;
 	static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 	/* register the flash bank */
-#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
 	/* partition the flash bank */
 	p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0);
-	if (p->nr_parts > 0)
-		err = add_mtd_partitions(p->info, parts, p->nr_parts);
-#endif
-	if (p->nr_parts <= 0)
-		err = add_mtd_device(p->info);
-
-	return err;
+	return mtd_device_register(p->info, parts, p->nr_parts);
 }
 
 static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index 9639d83..c00b917 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -119,7 +119,7 @@
 		return 0;
 
 	if (info->mtd) {
-		del_mtd_partitions(info->mtd);
+		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
 	if (info->map.map_priv_1)
@@ -230,7 +230,7 @@
 
 	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
 	if (err > 0) {
-		err = add_mtd_partitions(info->mtd, info->partitions, err);
+		err = mtd_device_register(info->mtd, info->partitions, err);
 		if(err)
 			dev_err(&dev->dev, "Could not parse partitions\n");
 	}
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 1f9fde0..155b219 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -162,7 +162,7 @@
 		return 0;
 
 	if (info->mtd) {
-		del_mtd_partitions(info->mtd);
+		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
 	if (info->map.virt)
@@ -252,10 +252,8 @@
 	/* Use the fast version */
 	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 {
@@ -263,18 +261,16 @@
 		nr_parts = plat->nr_parts;
 		part_type = "static";
 	}
-	if (nr_parts == 0) {
+	if (nr_parts == 0)
 		printk(KERN_NOTICE "IXP4xx flash: no partition info "
 			"available, registering whole flash\n");
-		err = add_mtd_device(info->mtd);
-	} else {
+	else
 		printk(KERN_NOTICE "IXP4xx flash: using %s partition "
 			"definition\n", part_type);
-		err = add_mtd_partitions(info->mtd, info->partitions, nr_parts);
 
-		if(err)
-			printk(KERN_ERR "Could not parse partitions\n");
-	}
+	err = mtd_device_register(info->mtd, info->partitions, nr_parts);
+	if (err)
+		printk(KERN_ERR "Could not parse partitions\n");
 
 	if (err)
 		goto Error;
diff --git a/drivers/mtd/maps/l440gx.c b/drivers/mtd/maps/l440gx.c
index 9e05450..dd0360b 100644
--- a/drivers/mtd/maps/l440gx.c
+++ b/drivers/mtd/maps/l440gx.c
@@ -138,7 +138,7 @@
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
 
-		add_mtd_device(mymtd);
+		mtd_device_register(mymtd, NULL, 0);
 		return 0;
 	}
 
@@ -148,7 +148,7 @@
 
 static void __exit cleanup_l440gx(void)
 {
-	del_mtd_device(mymtd);
+	mtd_device_unregister(mymtd);
 	map_destroy(mymtd);
 
 	iounmap(l440gx_map.virt);
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
index ee25480..5936c46 100644
--- a/drivers/mtd/maps/latch-addr-flash.c
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -112,18 +112,9 @@
 	latch_addr_data = dev->dev.platform_data;
 
 	if (info->mtd != NULL) {
-		if (mtd_has_partitions()) {
-			if (info->nr_parts) {
-				del_mtd_partitions(info->mtd);
-				kfree(info->parts);
-			} else if (latch_addr_data->nr_parts) {
-				del_mtd_partitions(info->mtd);
-			} else {
-				del_mtd_device(info->mtd);
-			}
-		} else {
-			del_mtd_device(info->mtd);
-		}
+		if (info->nr_parts)
+			kfree(info->parts);
+		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
 
@@ -215,23 +206,21 @@
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	if (mtd_has_partitions()) {
-
-		err = parse_mtd_partitions(info->mtd,
-					   (const char **)part_probe_types,
-					   &info->parts, 0);
-		if (err > 0) {
-			add_mtd_partitions(info->mtd, info->parts, err);
-			return 0;
-		}
-		if (latch_addr_data->nr_parts) {
-			pr_notice("Using latch-addr-flash partition information\n");
-			add_mtd_partitions(info->mtd, latch_addr_data->parts,
-					latch_addr_data->nr_parts);
-			return 0;
-		}
+	err = parse_mtd_partitions(info->mtd, (const char **)part_probe_types,
+				   &info->parts, 0);
+	if (err > 0) {
+		mtd_device_register(info->mtd, info->parts, err);
+		return 0;
 	}
-	add_mtd_device(info->mtd);
+	if (latch_addr_data->nr_parts) {
+		pr_notice("Using latch-addr-flash partition information\n");
+		mtd_device_register(info->mtd,
+				    latch_addr_data->parts,
+				    latch_addr_data->nr_parts);
+		return 0;
+	}
+
+	mtd_device_register(info->mtd, NULL, 0);
 	return 0;
 
 iounmap:
diff --git a/drivers/mtd/maps/mbx860.c b/drivers/mtd/maps/mbx860.c
index 0eb5a7c..93fa56c 100644
--- a/drivers/mtd/maps/mbx860.c
+++ b/drivers/mtd/maps/mbx860.c
@@ -69,8 +69,8 @@
 	mymtd = do_map_probe("jedec_probe", &mbx_map);
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
-		add_mtd_device(mymtd);
-                add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
+		mtd_device_register(mymtd, NULL, 0);
+		mtd_device_register(mymtd, partition_info, NUM_PARTITIONS);
 		return 0;
 	}
 
@@ -81,7 +81,7 @@
 static void __exit cleanup_mbx(void)
 {
 	if (mymtd) {
-		del_mtd_device(mymtd);
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 	if (mbx_map.virt) {
diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c
index c0cb319..81dc259 100644
--- a/drivers/mtd/maps/netsc520.c
+++ b/drivers/mtd/maps/netsc520.c
@@ -116,14 +116,14 @@
 	}
 
 	mymtd->owner = THIS_MODULE;
-	add_mtd_partitions( mymtd, partition_info, NUM_PARTITIONS );
+	mtd_device_register(mymtd, partition_info, NUM_PARTITIONS);
 	return 0;
 }
 
 static void __exit cleanup_netsc520(void)
 {
 	if (mymtd) {
-		del_mtd_partitions(mymtd);
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 	if (netsc520_map.virt) {
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index a97133e..eadcfff 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -383,13 +383,13 @@
 		/* No BIOS regions when AMD boot */
 		num_intel_partitions -= 2;
 	}
-	rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions,
-		num_intel_partitions);
+	rc = mtd_device_register(intel_mtd, nettel_intel_partitions,
+				 num_intel_partitions);
 #endif
 
 	if (amd_mtd) {
-		rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions,
-			num_amd_partitions);
+		rc = mtd_device_register(amd_mtd, nettel_amd_partitions,
+					 num_amd_partitions);
 	}
 
 #ifdef CONFIG_MTD_CFI_INTELEXT
@@ -419,7 +419,7 @@
 	unregister_reboot_notifier(&nettel_notifier_block);
 #endif
 	if (amd_mtd) {
-		del_mtd_partitions(amd_mtd);
+		mtd_device_unregister(amd_mtd);
 		map_destroy(amd_mtd);
 	}
 	if (nettel_mmcrp) {
@@ -432,7 +432,7 @@
 	}
 #ifdef CONFIG_MTD_CFI_INTELEXT
 	if (intel_mtd) {
-		del_mtd_partitions(intel_mtd);
+		mtd_device_unregister(intel_mtd);
 		map_destroy(intel_mtd);
 	}
 	if (nettel_intel_map.virt) {
diff --git a/drivers/mtd/maps/octagon-5066.c b/drivers/mtd/maps/octagon-5066.c
index 23fe178..807ac2a 100644
--- a/drivers/mtd/maps/octagon-5066.c
+++ b/drivers/mtd/maps/octagon-5066.c
@@ -175,7 +175,7 @@
 	int i;
 	for (i=0; i<2; i++) {
 		if (oct5066_mtd[i]) {
-			del_mtd_device(oct5066_mtd[i]);
+			mtd_device_unregister(oct5066_mtd[i]);
 			map_destroy(oct5066_mtd[i]);
 		}
 	}
@@ -220,7 +220,7 @@
 			oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]);
 		if (oct5066_mtd[i]) {
 			oct5066_mtd[i]->owner = THIS_MODULE;
-			add_mtd_device(oct5066_mtd[i]);
+			mtd_device_register(oct5066_mtd[i], NULL, 0);
 		}
 	}
 
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
index 48f4cf5..1d005a3 100644
--- a/drivers/mtd/maps/pci.c
+++ b/drivers/mtd/maps/pci.c
@@ -313,7 +313,7 @@
 		goto release;
 
 	mtd->owner = THIS_MODULE;
-	add_mtd_device(mtd);
+	mtd_device_register(mtd, NULL, 0);
 
 	pci_set_drvdata(dev, mtd);
 
@@ -336,7 +336,7 @@
 	struct mtd_info *mtd = pci_get_drvdata(dev);
 	struct map_pci_info *map = mtd->priv;
 
-	del_mtd_device(mtd);
+	mtd_device_unregister(mtd);
 	map_destroy(mtd);
 	map->exit(dev, map);
 	kfree(map);
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 33dc282..bbe168b 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -630,7 +630,7 @@
 		dev->pcmcia_map.copy_to = pcmcia_copy_to;
 	}
 
-	if(add_mtd_device(mtd)) {
+	if (mtd_device_register(mtd, NULL, 0)) {
 		map_destroy(mtd);
 		dev->mtd_info = NULL;
 		dev_err(&dev->p_dev->dev,
@@ -669,7 +669,7 @@
 	DEBUG(3, "link=0x%p", link);
 
 	if(dev->mtd_info) {
-		del_mtd_device(dev->mtd_info);
+		mtd_device_unregister(dev->mtd_info);
 		dev_info(&dev->p_dev->dev, "mtd%d: Removing\n",
 			 dev->mtd_info->index);
 		map_destroy(dev->mtd_info);
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 1a9b94f..f64cee4 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -27,10 +27,8 @@
 	struct mtd_info		*mtd[MAX_RESOURCES];
 	struct mtd_info		*cmtd;
 	struct map_info		map[MAX_RESOURCES];
-#ifdef CONFIG_MTD_PARTITIONS
 	int			nr_parts;
 	struct mtd_partition	*parts;
-#endif
 };
 
 static int physmap_flash_remove(struct platform_device *dev)
@@ -47,18 +45,9 @@
 	physmap_data = dev->dev.platform_data;
 
 	if (info->cmtd) {
-#ifdef CONFIG_MTD_PARTITIONS
-		if (info->nr_parts || physmap_data->nr_parts) {
-			del_mtd_partitions(info->cmtd);
-
-			if (info->nr_parts)
-				kfree(info->parts);
-		} else {
-			del_mtd_device(info->cmtd);
-		}
-#else
-		del_mtd_device(info->cmtd);
-#endif
+		mtd_device_unregister(info->cmtd);
+		if (info->nr_parts)
+			kfree(info->parts);
 		if (info->cmtd != info->mtd[0])
 			mtd_concat_destroy(info->cmtd);
 	}
@@ -92,10 +81,8 @@
 					"qinfo_probe",
 					"map_rom",
 					NULL };
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", "afs",
 					  NULL };
-#endif
 
 static int physmap_flash_probe(struct platform_device *dev)
 {
@@ -188,24 +175,23 @@
 	if (err)
 		goto err_out;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				&info->parts, 0);
+				   &info->parts, 0);
 	if (err > 0) {
-		add_mtd_partitions(info->cmtd, info->parts, err);
+		mtd_device_register(info->cmtd, info->parts, err);
 		info->nr_parts = err;
 		return 0;
 	}
 
 	if (physmap_data->nr_parts) {
 		printk(KERN_NOTICE "Using physmap partition information\n");
-		add_mtd_partitions(info->cmtd, physmap_data->parts,
-				   physmap_data->nr_parts);
+		mtd_device_register(info->cmtd, physmap_data->parts,
+				    physmap_data->nr_parts);
 		return 0;
 	}
-#endif
 
-	add_mtd_device(info->cmtd);
+	mtd_device_register(info->cmtd, NULL, 0);
+
 	return 0;
 
 err_out:
@@ -269,14 +255,12 @@
 	physmap_flash_data.set_vpp = set_vpp;
 }
 
-#ifdef CONFIG_MTD_PARTITIONS
 void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
 {
 	physmap_flash_data.nr_parts = num_parts;
 	physmap_flash_data.parts = parts;
 }
 #endif
-#endif
 
 static int __init physmap_init(void)
 {
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index c1d3346..d251d1d 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -34,16 +34,12 @@
 
 struct of_flash {
 	struct mtd_info		*cmtd;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition	*parts;
-#endif
 	int list_size; /* number of elements in of_flash_list */
 	struct of_flash_list	list[0];
 };
 
-#ifdef CONFIG_MTD_PARTITIONS
 #define OF_FLASH_PARTS(info)	((info)->parts)
-
 static int parse_obsolete_partitions(struct platform_device *dev,
 				     struct of_flash *info,
 				     struct device_node *dp)
@@ -89,10 +85,6 @@
 
 	return nr_parts;
 }
-#else /* MTD_PARTITIONS */
-#define	OF_FLASH_PARTS(info)		(0)
-#define parse_partitions(info, dev)	(0)
-#endif /* MTD_PARTITIONS */
 
 static int of_flash_remove(struct platform_device *dev)
 {
@@ -105,17 +97,14 @@
 	dev_set_drvdata(&dev->dev, NULL);
 
 	if (info->cmtd != info->list[0].mtd) {
-		del_mtd_device(info->cmtd);
+		mtd_device_unregister(info->cmtd);
 		mtd_concat_destroy(info->cmtd);
 	}
 
 	if (info->cmtd) {
-		if (OF_FLASH_PARTS(info)) {
-			del_mtd_partitions(info->cmtd);
+		if (OF_FLASH_PARTS(info))
 			kfree(OF_FLASH_PARTS(info));
-		} else {
-			del_mtd_device(info->cmtd);
-		}
+		mtd_device_unregister(info->cmtd);
 	}
 
 	for (i = 0; i < info->list_size; i++) {
@@ -172,7 +161,6 @@
 	}
 }
 
-#ifdef CONFIG_MTD_PARTITIONS
 /* When partitions are set we look for a linux,part-probe property which
    specifies the list of partition probers to use. If none is given then the
    default is use. These take precedence over other device tree
@@ -212,14 +200,11 @@
 	if (probes != part_probe_types_def)
 		kfree(probes);
 }
-#endif
 
 static struct of_device_id of_flash_match[];
 static int __devinit of_flash_probe(struct platform_device *dev)
 {
-#ifdef CONFIG_MTD_PARTITIONS
 	const char **part_probe_types;
-#endif
 	const struct of_device_id *match;
 	struct device_node *dp = dev->dev.of_node;
 	struct resource res;
@@ -346,7 +331,6 @@
 	if (err)
 		goto err_out;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	part_probe_types = of_get_probes(dp);
 	err = parse_mtd_partitions(info->cmtd, part_probe_types,
 				   &info->parts, 0);
@@ -356,13 +340,11 @@
 	}
 	of_free_probes(part_probe_types);
 
-#ifdef CONFIG_MTD_OF_PARTS
 	if (err == 0) {
 		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
 		if (err < 0)
 			goto err_out;
 	}
-#endif
 
 	if (err == 0) {
 		err = parse_obsolete_partitions(dev, info, dp);
@@ -370,11 +352,7 @@
 			goto err_out;
 	}
 
-	if (err > 0)
-		add_mtd_partitions(info->cmtd, info->parts, err);
-	else
-#endif
-		add_mtd_device(info->cmtd);
+	mtd_device_register(info->cmtd, info->parts, err);
 
 	kfree(mtd_list);
 
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 76a76be..9ca1ecc 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -94,14 +94,11 @@
 		return 0;
 
 	if (info->mtd) {
-#ifdef CONFIG_MTD_PARTITIONS
+		mtd_device_unregister(info->mtd);
 		if (info->partitions) {
-			del_mtd_partitions(info->mtd);
 			if (info->free_partitions)
 				kfree(info->partitions);
 		}
-#endif
-		del_mtd_device(info->mtd);
 		map_destroy(info->mtd);
 	}
 
@@ -231,7 +228,6 @@
 	/* check to see if there are any available partitions, or wether
 	 * to add this device whole */
 
-#ifdef CONFIG_MTD_PARTITIONS
 	if (!pdata->nr_partitions) {
 		/* try to probe using the supplied probe type */
 		if (pdata->probes) {
@@ -239,24 +235,22 @@
 					   &info->partitions, 0);
 			info->free_partitions = 1;
 			if (err > 0)
-				err = add_mtd_partitions(info->mtd,
+				err = mtd_device_register(info->mtd,
 					info->partitions, err);
 		}
 	}
 	/* use the static mapping */
 	else
-		err = add_mtd_partitions(info->mtd, pdata->partitions,
-				pdata->nr_partitions);
-#endif /* CONFIG_MTD_PARTITIONS */
-
-	if (add_mtd_device(info->mtd)) {
-		dev_err(&pdev->dev, "add_mtd_device() failed\n");
-		err = -ENOMEM;
-	}
-
+		err = mtd_device_register(info->mtd, pdata->partitions,
+					  pdata->nr_partitions);
 	if (!err)
 		dev_info(&pdev->dev, "registered mtd device\n");
 
+	/* add the whole device. */
+	err = mtd_device_register(info->mtd, NULL, 0);
+	if (err)
+		dev_err(&pdev->dev, "failed to register the entire device\n");
+
 	return err;
 
  exit_free:
diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c
index 64aea6a..744ca5c 100644
--- a/drivers/mtd/maps/pmcmsp-flash.c
+++ b/drivers/mtd/maps/pmcmsp-flash.c
@@ -173,7 +173,7 @@
 		msp_flash[i] = do_map_probe("cfi_probe", &msp_maps[i]);
 		if (msp_flash[i]) {
 			msp_flash[i]->owner = THIS_MODULE;
-			add_mtd_partitions(msp_flash[i], msp_parts[i], pcnt);
+			mtd_device_register(msp_flash[i], msp_parts[i], pcnt);
 		} else {
 			printk(KERN_ERR "map probe failed for flash\n");
 			ret = -ENXIO;
@@ -188,7 +188,7 @@
 
 cleanup_loop:
 	while (i--) {
-		del_mtd_partitions(msp_flash[i]);
+		mtd_device_unregister(msp_flash[i]);
 		map_destroy(msp_flash[i]);
 		kfree(msp_maps[i].name);
 		iounmap(msp_maps[i].virt);
@@ -207,7 +207,7 @@
 	int i;
 
 	for (i = 0; i < fcnt; i++) {
-		del_mtd_partitions(msp_flash[i]);
+		mtd_device_unregister(msp_flash[i]);
 		map_destroy(msp_flash[i]);
 		iounmap((void *)msp_maps[i].virt);
 
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index d8ae634..f59d62f 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -104,23 +104,18 @@
 	}
 	info->mtd->owner = THIS_MODULE;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	ret = parse_mtd_partitions(info->mtd, probes, &parts, 0);
 
 	if (ret > 0) {
 		info->nr_parts = ret;
 		info->parts = parts;
 	}
-#endif
 
-	if (info->nr_parts) {
-		add_mtd_partitions(info->mtd, info->parts,
-				   info->nr_parts);
-	} else {
+	if (!info->nr_parts)
 		printk("Registering %s as whole device\n",
 		       info->map.name);
-		add_mtd_device(info->mtd);
-	}
+
+	mtd_device_register(info->mtd, info->parts, info->nr_parts);
 
 	platform_set_drvdata(pdev, info);
 	return 0;
@@ -132,12 +127,7 @@
 
 	platform_set_drvdata(dev, NULL);
 
-#ifdef CONFIG_MTD_PARTITIONS
-	if (info->nr_parts)
-		del_mtd_partitions(info->mtd);
-	else
-#endif
-		del_mtd_device(info->mtd);
+	mtd_device_unregister(info->mtd);
 
 	map_destroy(info->mtd);
 	iounmap(info->map.virt);
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index 83ed645..761fb45 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -25,10 +25,8 @@
 struct rbtx4939_flash_info {
 	struct mtd_info *mtd;
 	struct map_info map;
-#ifdef CONFIG_MTD_PARTITIONS
 	int nr_parts;
 	struct mtd_partition *parts;
-#endif
 };
 
 static int rbtx4939_flash_remove(struct platform_device *dev)
@@ -41,28 +39,18 @@
 	platform_set_drvdata(dev, NULL);
 
 	if (info->mtd) {
-#ifdef CONFIG_MTD_PARTITIONS
 		struct rbtx4939_flash_data *pdata = dev->dev.platform_data;
 
-		if (info->nr_parts) {
-			del_mtd_partitions(info->mtd);
+		if (info->nr_parts)
 			kfree(info->parts);
-		} else if (pdata->nr_parts)
-			del_mtd_partitions(info->mtd);
-		else
-			del_mtd_device(info->mtd);
-#else
-		del_mtd_device(info->mtd);
-#endif
+		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
 	return 0;
 }
 
 static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probe_types[] = { "cmdlinepart", NULL };
-#endif
 
 static int rbtx4939_flash_probe(struct platform_device *dev)
 {
@@ -120,23 +108,21 @@
 	if (err)
 		goto err_out;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	err = parse_mtd_partitions(info->mtd, part_probe_types,
 				&info->parts, 0);
 	if (err > 0) {
-		add_mtd_partitions(info->mtd, info->parts, err);
+		mtd_device_register(info->mtd, info->parts, err);
 		info->nr_parts = err;
 		return 0;
 	}
 
 	if (pdata->nr_parts) {
 		pr_notice("Using rbtx4939 partition information\n");
-		add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
+		mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
 		return 0;
 	}
-#endif
 
-	add_mtd_device(info->mtd);
+	mtd_device_register(info->mtd, NULL, 0);
 	return 0;
 
 err_out:
diff --git a/drivers/mtd/maps/rpxlite.c b/drivers/mtd/maps/rpxlite.c
index 3e3ef53..ed88225 100644
--- a/drivers/mtd/maps/rpxlite.c
+++ b/drivers/mtd/maps/rpxlite.c
@@ -36,7 +36,7 @@
 	mymtd = do_map_probe("cfi_probe", &rpxlite_map);
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
-		add_mtd_device(mymtd);
+		mtd_device_register(mymtd, NULL, 0);
 		return 0;
 	}
 
@@ -47,7 +47,7 @@
 static void __exit cleanup_rpxlite(void)
 {
 	if (mymtd) {
-		del_mtd_device(mymtd);
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 	if (rpxlite_map.virt) {
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index da875908..a9b5e0e 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -226,12 +226,7 @@
 	int i;
 
 	if (info->mtd) {
-		if (info->nr_parts == 0)
-			del_mtd_device(info->mtd);
-#ifdef CONFIG_MTD_PARTITIONS
-		else
-			del_mtd_partitions(info->mtd);
-#endif
+		mtd_device_unregister(info->mtd);
 		if (info->mtd != info->subdev[0].mtd)
 			mtd_concat_destroy(info->mtd);
 	}
@@ -363,28 +358,24 @@
 	/*
 	 * Partition selection stuff.
 	 */
-#ifdef CONFIG_MTD_PARTITIONS
 	nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
 	if (nr_parts > 0) {
 		info->parts = parts;
 		part_type = "dynamic";
-	} else
-#endif
-	{
+	} else {
 		parts = plat->parts;
 		nr_parts = plat->nr_parts;
 		part_type = "static";
 	}
 
-	if (nr_parts == 0) {
+	if (nr_parts == 0)
 		printk(KERN_NOTICE "SA1100 flash: no partition info "
 			"available, registering whole flash\n");
-		add_mtd_device(info->mtd);
-	} else {
+	else
 		printk(KERN_NOTICE "SA1100 flash: using %s partition "
 			"definition\n", part_type);
-		add_mtd_partitions(info->mtd, parts, nr_parts);
-	}
+
+	mtd_device_register(info->mtd, parts, nr_parts);
 
 	info->nr_parts = nr_parts;
 
diff --git a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c
index 04b2781..556a2df 100644
--- a/drivers/mtd/maps/sbc_gxx.c
+++ b/drivers/mtd/maps/sbc_gxx.c
@@ -182,7 +182,7 @@
 static void cleanup_sbc_gxx(void)
 {
 	if( all_mtd ) {
-		del_mtd_partitions( all_mtd );
+		mtd_device_unregister(all_mtd);
 		map_destroy( all_mtd );
 	}
 
@@ -223,7 +223,7 @@
 	all_mtd->owner = THIS_MODULE;
 
 	/* Create MTD devices for each partition. */
-	add_mtd_partitions(all_mtd, partition_info, NUM_PARTITIONS );
+	mtd_device_register(all_mtd, partition_info, NUM_PARTITIONS);
 
 	return 0;
 }
diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c
index 4d8aaaf..8fead8e 100644
--- a/drivers/mtd/maps/sc520cdp.c
+++ b/drivers/mtd/maps/sc520cdp.c
@@ -266,10 +266,10 @@
 		/* Combine the two flash banks into a single MTD device & register it: */
 		merged_mtd = mtd_concat_create(mymtd, 2, "SC520CDP Flash Banks #0 and #1");
 		if(merged_mtd)
-			add_mtd_device(merged_mtd);
+			mtd_device_register(merged_mtd, NULL, 0);
 	}
 	if(devices_found == 3) /* register the third (DIL-Flash) device */
-		add_mtd_device(mymtd[2]);
+		mtd_device_register(mymtd[2], NULL, 0);
 	return(devices_found ? 0 : -ENXIO);
 }
 
@@ -278,11 +278,11 @@
 	int i;
 
 	if (merged_mtd) {
-		del_mtd_device(merged_mtd);
+		mtd_device_unregister(merged_mtd);
 		mtd_concat_destroy(merged_mtd);
 	}
 	if (mymtd[2])
-		del_mtd_device(mymtd[2]);
+		mtd_device_unregister(mymtd[2]);
 
 	for (i = 0; i < NUM_FLASH_BANKS; i++) {
 		if (mymtd[i])
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
index 7e329f0..d88c842 100644
--- a/drivers/mtd/maps/scb2_flash.c
+++ b/drivers/mtd/maps/scb2_flash.c
@@ -180,7 +180,7 @@
 
 	scb2_mtd->owner = THIS_MODULE;
 	if (scb2_fixup_mtd(scb2_mtd) < 0) {
-		del_mtd_device(scb2_mtd);
+		mtd_device_unregister(scb2_mtd);
 		map_destroy(scb2_mtd);
 		iounmap(scb2_ioaddr);
 		if (!region_fail)
@@ -192,7 +192,7 @@
 	       (unsigned long long)scb2_mtd->size,
 	       (unsigned long long)(SCB2_WINDOW - scb2_mtd->size));
 
-	add_mtd_device(scb2_mtd);
+	mtd_device_register(scb2_mtd, NULL, 0);
 
 	return 0;
 }
@@ -207,7 +207,7 @@
 	if (scb2_mtd->lock)
 		scb2_mtd->lock(scb2_mtd, 0, scb2_mtd->size);
 
-	del_mtd_device(scb2_mtd);
+	mtd_device_unregister(scb2_mtd);
 	map_destroy(scb2_mtd);
 
 	iounmap(scb2_ioaddr);
diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c
index 027e628..f1c1f73 100644
--- a/drivers/mtd/maps/scx200_docflash.c
+++ b/drivers/mtd/maps/scx200_docflash.c
@@ -44,7 +44,6 @@
 
 static struct mtd_info *mymtd;
 
-#ifdef CONFIG_MTD_PARTITIONS
 static struct mtd_partition partition_info[] = {
 	{
 		.name   = "DOCCS Boot kernel",
@@ -68,8 +67,6 @@
 	},
 };
 #define NUM_PARTITIONS ARRAY_SIZE(partition_info)
-#endif
-
 
 static struct map_info scx200_docflash_map = {
 	.name      = "NatSemi SCx200 DOCCS Flash",
@@ -198,24 +195,17 @@
 
 	mymtd->owner = THIS_MODULE;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	partition_info[3].offset = mymtd->size-partition_info[3].size;
 	partition_info[2].size = partition_info[3].offset-partition_info[2].offset;
-	add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
-#else
-	add_mtd_device(mymtd);
-#endif
+	mtd_device_register(mymtd, partition_info, NUM_PARTITIONS);
+
 	return 0;
 }
 
 static void __exit cleanup_scx200_docflash(void)
 {
 	if (mymtd) {
-#ifdef CONFIG_MTD_PARTITIONS
-		del_mtd_partitions(mymtd);
-#else
-		del_mtd_device(mymtd);
-#endif
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 	if (scx200_docflash_map.virt) {
diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c
index 0eb41d9..cbf6bad 100644
--- a/drivers/mtd/maps/solutionengine.c
+++ b/drivers/mtd/maps/solutionengine.c
@@ -89,7 +89,7 @@
 	eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map);
 	if (eprom_mtd) {
 		eprom_mtd->owner = THIS_MODULE;
-		add_mtd_device(eprom_mtd);
+		mtd_device_register(eprom_mtd, NULL, 0);
 	}
 
 	nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
@@ -104,9 +104,9 @@
 #endif /* CONFIG_MTD_SUPERH_RESERVE */
 
 	if (nr_parts > 0)
-		add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
+		mtd_device_register(flash_mtd, parsed_parts, nr_parts);
 	else
-		add_mtd_device(flash_mtd);
+		mtd_device_register(flash_mtd, NULL, 0);
 
 	return 0;
 }
@@ -114,14 +114,14 @@
 static void __exit cleanup_soleng_maps(void)
 {
 	if (eprom_mtd) {
-		del_mtd_device(eprom_mtd);
+		mtd_device_unregister(eprom_mtd);
 		map_destroy(eprom_mtd);
 	}
 
 	if (parsed_parts)
-		del_mtd_partitions(flash_mtd);
+		mtd_device_unregister(flash_mtd);
 	else
-		del_mtd_device(flash_mtd);
+		mtd_device_unregister(flash_mtd);
 	map_destroy(flash_mtd);
 }
 
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index 3f1cb32..2d66234 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -101,7 +101,7 @@
 
 	up->mtd->owner = THIS_MODULE;
 
-	add_mtd_device(up->mtd);
+	mtd_device_register(up->mtd, NULL, 0);
 
 	dev_set_drvdata(&op->dev, up);
 
@@ -126,7 +126,7 @@
 	struct uflash_dev *up = dev_get_drvdata(&op->dev);
 
 	if (up->mtd) {
-		del_mtd_device(up->mtd);
+		mtd_device_unregister(up->mtd);
 		map_destroy(up->mtd);
 	}
 	if (up->map.virt) {
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
index 0718dfb..d785879 100644
--- a/drivers/mtd/maps/tqm8xxl.c
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -62,7 +62,6 @@
  * "struct map_desc *_io_desc" for the corresponding machine.
  */
 
-#ifdef CONFIG_MTD_PARTITIONS
 /* Currently, TQM8xxL has up to 8MiB flash */
 static unsigned long tqm8xxl_max_flash_size = 0x00800000;
 
@@ -107,7 +106,6 @@
 	  //.size = MTDPART_SIZ_FULL,
 	}
 };
-#endif
 
 static int __init init_tqm_mtd(void)
 {
@@ -188,7 +186,6 @@
 		goto error_mem;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 	/*
 	 * Select Static partition definitions
 	 */
@@ -201,21 +198,14 @@
 	part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions);
 
 	for(idx = 0; idx < num_banks ; idx++) {
-		if (part_banks[idx].nums == 0) {
+		if (part_banks[idx].nums == 0)
 			printk(KERN_NOTICE "TQM flash%d: no partition info available, registering whole flash at once\n", idx);
-			add_mtd_device(mtd_banks[idx]);
-		} else {
+		else
 			printk(KERN_NOTICE "TQM flash%d: Using %s partition definition\n",
 					idx, part_banks[idx].type);
-			add_mtd_partitions(mtd_banks[idx], part_banks[idx].mtd_part,
-								part_banks[idx].nums);
-		}
+		mtd_device_register(mtd_banks[idx], part_banks[idx].mtd_part,
+		part_banks[idx].nums);
 	}
-#else
-	printk(KERN_NOTICE "TQM flash: registering %d whole flash banks at once\n", num_banks);
-	for(idx = 0 ; idx < num_banks ; idx++)
-		add_mtd_device(mtd_banks[idx]);
-#endif
 	return 0;
 error_mem:
 	for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
@@ -237,7 +227,7 @@
 	for(idx = 0 ; idx < num_banks ; idx++) {
 		/* destroy mtd_info previously allocated */
 		if (mtd_banks[idx]) {
-			del_mtd_partitions(mtd_banks[idx]);
+			mtd_device_unregister(mtd_banks[idx]);
 			map_destroy(mtd_banks[idx]);
 		}
 		/* release map_info not used anymore */
diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c
index e02dfa9..d1d671d 100644
--- a/drivers/mtd/maps/ts5500_flash.c
+++ b/drivers/mtd/maps/ts5500_flash.c
@@ -89,7 +89,7 @@
 	}
 
 	mymtd->owner = THIS_MODULE;
-	add_mtd_partitions(mymtd, ts5500_partitions, NUM_PARTITIONS);
+	mtd_device_register(mymtd, ts5500_partitions, NUM_PARTITIONS);
 
 	return 0;
 
@@ -102,7 +102,7 @@
 static void __exit cleanup_ts5500_map(void)
 {
 	if (mymtd) {
-		del_mtd_partitions(mymtd);
+		mtd_device_unregister(mymtd);
 		map_destroy(mymtd);
 	}
 
diff --git a/drivers/mtd/maps/tsunami_flash.c b/drivers/mtd/maps/tsunami_flash.c
index 77a8bfc..1de390e 100644
--- a/drivers/mtd/maps/tsunami_flash.c
+++ b/drivers/mtd/maps/tsunami_flash.c
@@ -76,7 +76,7 @@
 	struct mtd_info *mtd;
 	mtd = tsunami_flash_mtd;
 	if (mtd) {
-		del_mtd_device(mtd);
+		mtd_device_unregister(mtd);
 		map_destroy(mtd);
 	}
 	tsunami_flash_mtd = 0;
@@ -97,7 +97,7 @@
 	}
 	if (tsunami_flash_mtd) {
 		tsunami_flash_mtd->owner = THIS_MODULE;
-		add_mtd_device(tsunami_flash_mtd);
+		mtd_device_register(tsunami_flash_mtd, NULL, 0);
 		return 0;
 	}
 	return -ENXIO;
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 3500929..6793074 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -89,11 +89,7 @@
 	mtd->priv = mapp;
 
 	uclinux_ram_mtdinfo = mtd;
-#ifdef CONFIG_MTD_PARTITIONS
-	add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS);
-#else
-	add_mtd_device(mtd);
-#endif
+	mtd_device_register(mtd, uclinux_romfs, NUM_PARTITIONS);
 
 	return(0);
 }
@@ -103,11 +99,7 @@
 static void __exit uclinux_mtd_cleanup(void)
 {
 	if (uclinux_ram_mtdinfo) {
-#ifdef CONFIG_MTD_PARTITIONS
-		del_mtd_partitions(uclinux_ram_mtdinfo);
-#else
-		del_mtd_device(uclinux_ram_mtdinfo);
-#endif
+		mtd_device_unregister(uclinux_ram_mtdinfo);
 		map_destroy(uclinux_ram_mtdinfo);
 		uclinux_ram_mtdinfo = NULL;
 	}
diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c
index 6adaa6a..5e68de7 100644
--- a/drivers/mtd/maps/vmax301.c
+++ b/drivers/mtd/maps/vmax301.c
@@ -138,7 +138,7 @@
 
 	for (i=0; i<2; i++) {
 		if (vmax_mtd[i]) {
-			del_mtd_device(vmax_mtd[i]);
+			mtd_device_unregister(vmax_mtd[i]);
 			map_destroy(vmax_mtd[i]);
 		}
 	}
@@ -176,7 +176,7 @@
 			vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]);
 		if (vmax_mtd[i]) {
 			vmax_mtd[i]->owner = THIS_MODULE;
-			add_mtd_device(vmax_mtd[i]);
+			mtd_device_register(vmax_mtd[i], NULL, 0);
 		}
 	}
 
diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
index 4afc167..3a04b07 100644
--- a/drivers/mtd/maps/vmu-flash.c
+++ b/drivers/mtd/maps/vmu-flash.c
@@ -563,7 +563,7 @@
 		goto fail_cache_create;
 	part_cur->pcache = pcache;
 
-	error = add_mtd_device(mtd_cur);
+	error = mtd_device_register(mtd_cur, NULL, 0);
 	if (error)
 		goto fail_mtd_register;
 
@@ -709,7 +709,7 @@
 	for (x = 0; x < card->partitions; x++) {
 		mpart = ((card->mtd)[x]).priv;
 		mpart->mdev = NULL;
-		del_mtd_device(&((card->mtd)[x]));
+		mtd_device_unregister(&((card->mtd)[x]));
 		kfree(((card->parts)[x]).name);
 	}
 	kfree(card->parts);
diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c
index 933a2b6..901ce96 100644
--- a/drivers/mtd/maps/wr_sbc82xx_flash.c
+++ b/drivers/mtd/maps/wr_sbc82xx_flash.c
@@ -132,17 +132,20 @@
 		nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
 						&sbcmtd_parts[i], 0);
 		if (nr_parts > 0) {
-			add_mtd_partitions (sbcmtd[i], sbcmtd_parts[i], nr_parts);
+			mtd_device_register(sbcmtd[i], sbcmtd_parts[i],
+					    nr_parts);
 			continue;
 		}
 
 		/* No partitioning detected. Use default */
 		if (i == 2) {
-			add_mtd_device(sbcmtd[i]);
+			mtd_device_register(sbcmtd[i], NULL, 0);
 		} else if (i == bigflash) {
-			add_mtd_partitions (sbcmtd[i], bigflash_parts, ARRAY_SIZE(bigflash_parts));
+			mtd_device_register(sbcmtd[i], bigflash_parts,
+					    ARRAY_SIZE(bigflash_parts));
 		} else {
-			add_mtd_partitions (sbcmtd[i], smallflash_parts, ARRAY_SIZE(smallflash_parts));
+			mtd_device_register(sbcmtd[i], smallflash_parts,
+					    ARRAY_SIZE(smallflash_parts));
 		}
 	}
 	return 0;
@@ -157,9 +160,9 @@
 			continue;
 
 		if (i<2 || sbcmtd_parts[i])
-			del_mtd_partitions(sbcmtd[i]);
+			mtd_device_unregister(sbcmtd[i]);
 		else
-			del_mtd_device(sbcmtd[i]);
+			mtd_device_unregister(sbcmtd[i]);
 
 		kfree(sbcmtd_parts[i]);
 		map_destroy(sbcmtd[i]);
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index a534e1f..ca38569 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -221,15 +221,33 @@
 	kref_get(&dev->ref);
 	__module_get(dev->tr->owner);
 
-	if (dev->mtd) {
-		ret = dev->tr->open ? dev->tr->open(dev) : 0;
-		__get_mtd_device(dev->mtd);
+	if (!dev->mtd)
+		goto unlock;
+
+	if (dev->tr->open) {
+		ret = dev->tr->open(dev);
+		if (ret)
+			goto error_put;
 	}
 
+	ret = __get_mtd_device(dev->mtd);
+	if (ret)
+		goto error_release;
+
 unlock:
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
 	return ret;
+
+error_release:
+	if (dev->tr->release)
+		dev->tr->release(dev);
+error_put:
+	module_put(dev->tr->owner);
+	kref_put(&dev->ref, blktrans_dev_release);
+	mutex_unlock(&dev->lock);
+	blktrans_dev_put(dev);
+	return ret;
 }
 
 static int blktrans_release(struct gendisk *disk, fmode_t mode)
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 4c36ef6..3f92731 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -166,10 +166,23 @@
 	return 0;
 } /* mtd_close */
 
-/* FIXME: This _really_ needs to die. In 2.5, we should lock the
-   userspace buffer down and use it directly with readv/writev.
-*/
-#define MAX_KMALLOC_SIZE 0x20000
+/* Back in June 2001, dwmw2 wrote:
+ *
+ *   FIXME: This _really_ needs to die. In 2.5, we should lock the
+ *   userspace buffer down and use it directly with readv/writev.
+ *
+ * The implementation below, using mtd_kmalloc_up_to, mitigates
+ * allocation failures when the system is under low-memory situations
+ * or if memory is highly fragmented at the cost of reducing the
+ * performance of the requested transfer due to a smaller buffer size.
+ *
+ * A more complex but more memory-efficient implementation based on
+ * get_user_pages and iovecs to cover extents of those pages is a
+ * longer-term goal, as intimated by dwmw2 above. However, for the
+ * write case, this requires yet more complex head and tail transfer
+ * handling when those head and tail offsets and sizes are such that
+ * alignment requirements are not met in the NAND subdriver.
+ */
 
 static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)
 {
@@ -179,6 +192,7 @@
 	size_t total_retlen=0;
 	int ret=0;
 	int len;
+	size_t size = count;
 	char *kbuf;
 
 	DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
@@ -189,23 +203,12 @@
 	if (!count)
 		return 0;
 
-	/* FIXME: Use kiovec in 2.5 to lock down the user's buffers
-	   and pass them directly to the MTD functions */
-
-	if (count > MAX_KMALLOC_SIZE)
-		kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
-	else
-		kbuf=kmalloc(count, GFP_KERNEL);
-
+	kbuf = mtd_kmalloc_up_to(mtd, &size);
 	if (!kbuf)
 		return -ENOMEM;
 
 	while (count) {
-
-		if (count > MAX_KMALLOC_SIZE)
-			len = MAX_KMALLOC_SIZE;
-		else
-			len = count;
+		len = min_t(size_t, count, size);
 
 		switch (mfi->mode) {
 		case MTD_MODE_OTP_FACTORY:
@@ -268,6 +271,7 @@
 {
 	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_info *mtd = mfi->mtd;
+	size_t size = count;
 	char *kbuf;
 	size_t retlen;
 	size_t total_retlen=0;
@@ -285,20 +289,12 @@
 	if (!count)
 		return 0;
 
-	if (count > MAX_KMALLOC_SIZE)
-		kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
-	else
-		kbuf=kmalloc(count, GFP_KERNEL);
-
+	kbuf = mtd_kmalloc_up_to(mtd, &size);
 	if (!kbuf)
 		return -ENOMEM;
 
 	while (count) {
-
-		if (count > MAX_KMALLOC_SIZE)
-			len = MAX_KMALLOC_SIZE;
-		else
-			len = count;
+		len = min_t(size_t, count, size);
 
 		if (copy_from_user(kbuf, buf, len)) {
 			kfree(kbuf);
@@ -512,7 +508,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_MTD_PARTITIONS
 static int mtd_blkpg_ioctl(struct mtd_info *mtd,
 			   struct blkpg_ioctl_arg __user *arg)
 {
@@ -548,8 +543,6 @@
 		return -EINVAL;
 	}
 }
-#endif
-
 
 static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 {
@@ -941,7 +934,6 @@
 		break;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 	case BLKPG:
 	{
 		ret = mtd_blkpg_ioctl(mtd,
@@ -955,7 +947,6 @@
 		ret = 0;
 		break;
 	}
-#endif
 
 	default:
 		ret = -ENOTTY;
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 5060e60..e601672 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -319,7 +319,7 @@
 	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
 
-	ops->retlen = 0;
+	ops->retlen = ops->oobretlen = 0;
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
@@ -334,7 +334,7 @@
 			devops.len = subdev->size - to;
 
 		err = subdev->write_oob(subdev, to, &devops);
-		ops->retlen += devops.retlen;
+		ops->retlen += devops.oobretlen;
 		if (err)
 			return err;
 
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index da69bc8..c510aff 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
+#include <linux/seq_file.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/major.h>
@@ -37,6 +38,7 @@
 #include <linux/gfp.h>
 
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
 
 #include "mtdcore.h"
 /*
@@ -391,7 +393,7 @@
  *	if the requested device does not appear to be present in the list.
  */
 
-int del_mtd_device (struct mtd_info *mtd)
+int del_mtd_device(struct mtd_info *mtd)
 {
 	int ret;
 	struct mtd_notifier *not;
@@ -427,6 +429,50 @@
 }
 
 /**
+ * mtd_device_register - register an MTD device.
+ *
+ * @master: the MTD device to register
+ * @parts: the partitions to register - only valid if nr_parts > 0
+ * @nr_parts: the number of partitions in parts.  If zero then the full MTD
+ *            device is registered
+ *
+ * Register an MTD device with the system and optionally, a number of
+ * partitions.  If nr_parts is 0 then the whole device is registered, otherwise
+ * only the partitions are registered.  To register both the full device *and*
+ * the partitions, call mtd_device_register() twice, once with nr_parts == 0
+ * and once equal to the number of partitions.
+ */
+int mtd_device_register(struct mtd_info *master,
+			const struct mtd_partition *parts,
+			int nr_parts)
+{
+	return parts ? add_mtd_partitions(master, parts, nr_parts) :
+		add_mtd_device(master);
+}
+EXPORT_SYMBOL_GPL(mtd_device_register);
+
+/**
+ * mtd_device_unregister - unregister an existing MTD device.
+ *
+ * @master: the MTD device to unregister.  This will unregister both the master
+ *          and any partitions if registered.
+ */
+int mtd_device_unregister(struct mtd_info *master)
+{
+	int err;
+
+	err = del_mtd_partitions(master);
+	if (err)
+		return err;
+
+	if (!device_is_registered(&master->dev))
+		return 0;
+
+	return del_mtd_device(master);
+}
+EXPORT_SYMBOL_GPL(mtd_device_unregister);
+
+/**
  *	register_mtd_user - register a 'user' of MTD devices.
  *	@new: pointer to notifier info structure
  *
@@ -443,7 +489,7 @@
 
 	list_add(&new->list, &mtd_notifiers);
 
- 	__module_get(THIS_MODULE);
+	__module_get(THIS_MODULE);
 
 	mtd_for_each_device(mtd)
 		new->add(mtd);
@@ -532,7 +578,6 @@
 		return -ENODEV;
 
 	if (mtd->get_device) {
-
 		err = mtd->get_device(mtd);
 
 		if (err) {
@@ -570,21 +615,13 @@
 	if (!mtd)
 		goto out_unlock;
 
-	if (!try_module_get(mtd->owner))
+	err = __get_mtd_device(mtd);
+	if (err)
 		goto out_unlock;
 
-	if (mtd->get_device) {
-		err = mtd->get_device(mtd);
-		if (err)
-			goto out_put;
-	}
-
-	mtd->usecount++;
 	mutex_unlock(&mtd_table_mutex);
 	return mtd;
 
-out_put:
-	module_put(mtd->owner);
 out_unlock:
 	mutex_unlock(&mtd_table_mutex);
 	return ERR_PTR(err);
@@ -638,8 +675,54 @@
 	return ret;
 }
 
-EXPORT_SYMBOL_GPL(add_mtd_device);
-EXPORT_SYMBOL_GPL(del_mtd_device);
+/**
+ * mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size
+ * @size: A pointer to the ideal or maximum size of the allocation. Points
+ *        to the actual allocation size on success.
+ *
+ * This routine attempts to allocate a contiguous kernel buffer up to
+ * the specified size, backing off the size of the request exponentially
+ * until the request succeeds or until the allocation size falls below
+ * the system page size. This attempts to make sure it does not adversely
+ * impact system performance, so when allocating more than one page, we
+ * ask the memory allocator to avoid re-trying, swapping, writing back
+ * or performing I/O.
+ *
+ * Note, this function also makes sure that the allocated buffer is aligned to
+ * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value.
+ *
+ * This is called, for example by mtd_{read,write} and jffs2_scan_medium,
+ * to handle smaller (i.e. degraded) buffer allocations under low- or
+ * fragmented-memory situations where such reduced allocations, from a
+ * requested ideal, are allowed.
+ *
+ * Returns a pointer to the allocated buffer on success; otherwise, NULL.
+ */
+void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
+{
+	gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
+		       __GFP_NORETRY | __GFP_NO_KSWAPD;
+	size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
+	void *kbuf;
+
+	*size = min_t(size_t, *size, KMALLOC_MAX_SIZE);
+
+	while (*size > min_alloc) {
+		kbuf = kmalloc(*size, flags);
+		if (kbuf)
+			return kbuf;
+
+		*size >>= 1;
+		*size = ALIGN(*size, mtd->writesize);
+	}
+
+	/*
+	 * For the last resort allocation allow 'kmalloc()' to do all sorts of
+	 * things (write-back, dropping caches, etc) by using GFP_KERNEL.
+	 */
+	return kmalloc(*size, GFP_KERNEL);
+}
+
 EXPORT_SYMBOL_GPL(get_mtd_device);
 EXPORT_SYMBOL_GPL(get_mtd_device_nm);
 EXPORT_SYMBOL_GPL(__get_mtd_device);
@@ -648,6 +731,7 @@
 EXPORT_SYMBOL_GPL(register_mtd_user);
 EXPORT_SYMBOL_GPL(unregister_mtd_user);
 EXPORT_SYMBOL_GPL(default_mtd_writev);
+EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to);
 
 #ifdef CONFIG_PROC_FS
 
@@ -656,44 +740,32 @@
 
 static struct proc_dir_entry *proc_mtd;
 
-static inline int mtd_proc_info(char *buf, struct mtd_info *this)
-{
-	return sprintf(buf, "mtd%d: %8.8llx %8.8x \"%s\"\n", this->index,
-		       (unsigned long long)this->size,
-		       this->erasesize, this->name);
-}
-
-static int mtd_read_proc (char *page, char **start, off_t off, int count,
-			  int *eof, void *data_unused)
+static int mtd_proc_show(struct seq_file *m, void *v)
 {
 	struct mtd_info *mtd;
-	int len, l;
-        off_t   begin = 0;
 
+	seq_puts(m, "dev:    size   erasesize  name\n");
 	mutex_lock(&mtd_table_mutex);
-
-	len = sprintf(page, "dev:    size   erasesize  name\n");
 	mtd_for_each_device(mtd) {
-		l = mtd_proc_info(page + len, mtd);
-                len += l;
-                if (len+begin > off+count)
-                        goto done;
-                if (len+begin < off) {
-                        begin += len;
-                        len = 0;
-                }
-        }
-
-        *eof = 1;
-
-done:
+		seq_printf(m, "mtd%d: %8.8llx %8.8x \"%s\"\n",
+			   mtd->index, (unsigned long long)mtd->size,
+			   mtd->erasesize, mtd->name);
+	}
 	mutex_unlock(&mtd_table_mutex);
-        if (off >= len+begin)
-                return 0;
-        *start = page + (off-begin);
-        return ((count < begin+len-off) ? count : begin+len-off);
+	return 0;
 }
 
+static int mtd_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mtd_proc_show, NULL);
+}
+
+static const struct file_operations mtd_proc_ops = {
+	.open		= mtd_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 #endif /* CONFIG_PROC_FS */
 
 /*====================================================================*/
@@ -734,8 +806,7 @@
 		goto err_bdi3;
 
 #ifdef CONFIG_PROC_FS
-	if ((proc_mtd = create_proc_entry( "mtd", 0, NULL )))
-		proc_mtd->read_proc = mtd_read_proc;
+	proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops);
 #endif /* CONFIG_PROC_FS */
 	return 0;
 
@@ -753,7 +824,7 @@
 static void __exit cleanup_mtd(void)
 {
 #ifdef CONFIG_PROC_FS
-        if (proc_mtd)
+	if (proc_mtd)
 		remove_proc_entry( "mtd", NULL);
 #endif /* CONFIG_PROC_FS */
 	class_unregister(&mtd_class);
diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h
index 6a64fde..0ed6126 100644
--- a/drivers/mtd/mtdcore.h
+++ b/drivers/mtd/mtdcore.h
@@ -10,6 +10,12 @@
 extern struct mutex mtd_table_mutex;
 extern struct mtd_info *__mtd_next_device(int i);
 
+extern int add_mtd_device(struct mtd_info *mtd);
+extern int del_mtd_device(struct mtd_info *mtd);
+extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *,
+			      int);
+extern int del_mtd_partitions(struct mtd_info *);
+
 #define mtd_for_each_device(mtd)			\
 	for ((mtd) = __mtd_next_device(0);		\
 	     (mtd) != NULL;				\
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 0a47601..630be3e 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -31,6 +31,8 @@
 #include <linux/mtd/partitions.h>
 #include <linux/err.h>
 
+#include "mtdcore.h"
+
 /* Our partition linked list */
 static LIST_HEAD(mtd_partitions);
 static DEFINE_MUTEX(mtd_partitions_mutex);
@@ -376,7 +378,6 @@
 
 	return err;
 }
-EXPORT_SYMBOL(del_mtd_partitions);
 
 static struct mtd_part *allocate_partition(struct mtd_info *master,
 			const struct mtd_partition *part, int partno,
@@ -671,7 +672,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(add_mtd_partitions);
 
 static DEFINE_SPINLOCK(part_parser_lock);
 static LIST_HEAD(part_parsers);
@@ -722,11 +722,8 @@
 		parser = get_partition_parser(*types);
 		if (!parser && !request_module("%s", *types))
 				parser = get_partition_parser(*types);
-		if (!parser) {
-			printk(KERN_NOTICE "%s partition parsing not available\n",
-			       *types);
+		if (!parser)
 			continue;
-		}
 		ret = (*parser->parse_fn)(master, pparts, origin);
 		if (ret > 0) {
 			printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c
index fed215c..fd78853 100644
--- a/drivers/mtd/mtdswap.c
+++ b/drivers/mtd/mtdswap.c
@@ -1450,7 +1450,13 @@
 	}
 
 	oinfo = mtd->ecclayout;
-	if (!mtd->oobsize || !oinfo || oinfo->oobavail < MTDSWAP_OOBSIZE) {
+	if (!oinfo) {
+		printk(KERN_ERR "%s: mtd%d does not have OOB\n",
+			MTDSWAP_PREFIX, mtd->index);
+		return;
+	}
+
+	if (!mtd->oobsize || oinfo->oobavail < MTDSWAP_OOBSIZE) {
 		printk(KERN_ERR "%s: Not enough free bytes in OOB, "
 			"%d available, %zu needed.\n",
 			MTDSWAP_PREFIX, oinfo->oobavail, MTDSWAP_OOBSIZE);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index edec457..4c34252 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -92,7 +92,7 @@
 
 config MTD_NAND_H1900
 	tristate "iPAQ H1900 flash"
-	depends on ARCH_PXA && MTD_PARTITIONS
+	depends on ARCH_PXA
 	help
 	  This enables the driver for the iPAQ h1900 flash.
 
@@ -419,7 +419,6 @@
 
 config MTD_NAND_NANDSIM
 	tristate "Support for NAND Flash Simulator"
-	depends on MTD_PARTITIONS
 	help
 	  The simulator may simulate various NAND flash chips for the
 	  MTD nand layer.
@@ -513,7 +512,7 @@
 
 config MTD_NAND_NUC900
 	tristate "Support for NAND on Nuvoton NUC9xx/w90p910 evaluation boards."
-	depends on ARCH_W90X900 && MTD_PARTITIONS
+	depends on ARCH_W90X900
 	help
 	  This enables the driver for the NAND Flash on evaluation board based
 	  on w90p910 / NUC9xx.
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c
index 8691e04..eb40ea8 100644
--- a/drivers/mtd/nand/alauda.c
+++ b/drivers/mtd/nand/alauda.c
@@ -120,7 +120,7 @@
 	struct alauda *al = container_of(kref, struct alauda, kref);
 
 	if (al->mtd) {
-		del_mtd_device(al->mtd);
+		mtd_device_unregister(al->mtd);
 		kfree(al->mtd);
 	}
 	usb_put_dev(al->dev);
@@ -592,7 +592,7 @@
 	mtd->priv = al;
 	mtd->owner = THIS_MODULE;
 
-	err = add_mtd_device(mtd);
+	err = mtd_device_register(mtd, NULL, 0);
 	if (err) {
 		err = -ENFILE;
 		goto error;
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index bc65bf7..78017eb 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -235,8 +235,8 @@
 	}
 
 	/* Register the partitions */
-	add_mtd_partitions(ams_delta_mtd, partition_info,
-			   ARRAY_SIZE(partition_info));
+	mtd_device_register(ams_delta_mtd, partition_info,
+			    ARRAY_SIZE(partition_info));
 
 	goto out;
 
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 950646a..b300705 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -30,6 +30,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 
+#include <linux/dmaengine.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
 
@@ -494,11 +495,8 @@
 	struct resource *regs;
 	struct resource *mem;
 	int res;
-
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *partitions = NULL;
 	int num_partitions = 0;
-#endif
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
@@ -656,7 +654,6 @@
 		goto err_scan_tail;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 	mtd->name = "atmel_nand";
 	num_partitions = parse_mtd_partitions(mtd, part_probes,
@@ -672,17 +669,11 @@
 		goto err_no_partitions;
 	}
 
-	res = add_mtd_partitions(mtd, partitions, num_partitions);
-#else
-	res = add_mtd_device(mtd);
-#endif
-
+	res = mtd_device_register(mtd, partitions, num_partitions);
 	if (!res)
 		return res;
 
-#ifdef CONFIG_MTD_PARTITIONS
 err_no_partitions:
-#endif
 	nand_release(mtd);
 err_scan_tail:
 err_scan_ident:
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 5d513b5..e7767ee 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -581,7 +581,8 @@
 	}
 
 	/* Register the partitions */
-	add_mtd_partitions(au1550_mtd, partition_info, ARRAY_SIZE(partition_info));
+	mtd_device_register(au1550_mtd, partition_info,
+			    ARRAY_SIZE(partition_info));
 
 	return 0;
 
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index 0911cf0..eddc9a2 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -185,20 +185,20 @@
 	/* Register the partitions */
 	switch (autcpu12_mtd->size) {
 		case SZ_16M:
-			add_mtd_partitions(autcpu12_mtd, partition_info16k,
-					   NUM_PARTITIONS16K);
+			mtd_device_register(autcpu12_mtd, partition_info16k,
+					    NUM_PARTITIONS16K);
 			break;
 		case SZ_32M:
-			add_mtd_partitions(autcpu12_mtd, partition_info32k,
-					   NUM_PARTITIONS32K);
+			mtd_device_register(autcpu12_mtd, partition_info32k,
+					    NUM_PARTITIONS32K);
 			break;
 		case SZ_64M:
-			add_mtd_partitions(autcpu12_mtd, partition_info64k,
-					   NUM_PARTITIONS64K);
+			mtd_device_register(autcpu12_mtd, partition_info64k,
+					    NUM_PARTITIONS64K);
 			break;
 		case SZ_128M:
-			add_mtd_partitions(autcpu12_mtd, partition_info128k,
-					   NUM_PARTITIONS128K);
+			mtd_device_register(autcpu12_mtd, partition_info128k,
+					    NUM_PARTITIONS128K);
 			break;
 		default:
 			printk("Unsupported SmartMedia device\n");
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index dfe262c..9ec2807 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -52,9 +52,7 @@
 static const __devinitconst char gBanner[] = KERN_INFO \
 	"BCM UMI MTD NAND Driver: 1.00\n";
 
-#ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 #if NAND_ECC_BCH
 static uint8_t scan_ff_pattern[] = { 0xff };
@@ -509,7 +507,7 @@
 			kfree(board_mtd);
 			return -EIO;
 		}
-		add_mtd_partitions(board_mtd, partition_info, nr_partitions);
+		mtd_device_register(board_mtd, partition_info, nr_partitions);
 	}
 
 	/* Return happy */
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 79947be..dd899cb 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -659,15 +659,10 @@
 static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
 {
 	struct mtd_info *mtd = &info->mtd;
-
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *parts = info->platform->partitions;
 	int nr = info->platform->nr_partitions;
 
-	return add_mtd_partitions(mtd, parts, nr);
-#else
-	return add_mtd_device(mtd);
-#endif
+	return mtd_device_register(mtd, parts, nr);
 }
 
 static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index e06c898..87ebb4e 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -90,9 +90,7 @@
 static int timing[3];
 module_param_array(timing, int, &numtimings, 0644);
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
-#endif
 
 /* Hrm. Why isn't this already conditional on something in the struct device? */
 #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
@@ -632,10 +630,8 @@
 	struct cafe_priv *cafe;
 	uint32_t ctrl;
 	int err = 0;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *parts;
 	int nr_parts;
-#endif
 
 	/* Very old versions shared the same PCI ident for all three
 	   functions on the chip. Verify the class too... */
@@ -804,9 +800,8 @@
 	pci_set_drvdata(pdev, mtd);
 
 	/* We register the whole device first, separate from the partitions */
-	add_mtd_device(mtd);
+	mtd_device_register(mtd, NULL, 0);
 
-#ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 	mtd->name = "cafe_nand";
 #endif
@@ -814,9 +809,8 @@
 	if (nr_parts > 0) {
 		cafe->parts = parts;
 		dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts);
-		add_mtd_partitions(mtd, parts, nr_parts);
+		mtd_device_register(mtd, parts, nr_parts);
 	}
-#endif
 	goto out;
 
  out_irq:
@@ -838,7 +832,6 @@
 	struct mtd_info *mtd = pci_get_drvdata(pdev);
 	struct cafe_priv *cafe = mtd->priv;
 
-	del_mtd_device(mtd);
 	/* Disable NAND IRQ in global IRQ mask register */
 	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
 	free_irq(pdev->irq, mtd);
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index 6e64952..6fc043a 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -238,7 +238,7 @@
 
 	/* Register the partitions */
 	pr_notice("Using %s partition definition\n", part_type);
-	ret = add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
+	ret = mtd_device_register(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
 	if (ret)
 		goto err_scan;
 
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index 71c35a0..f59ad1f 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -277,22 +277,15 @@
 	return 0;
 }
 
-
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
-
 
 static int __init cs553x_init(void)
 {
 	int err = -ENXIO;
 	int i;
 	uint64_t val;
-
-#ifdef CONFIG_MTD_PARTITIONS
 	int mtd_parts_nb = 0;
 	struct mtd_partition *mtd_parts = NULL;
-#endif
 
 	/* If the CPU isn't a Geode GX or LX, abort */
 	if (!is_geode())
@@ -324,17 +317,11 @@
 		if (cs553x_mtd[i]) {
 
 			/* If any devices registered, return success. Else the last error. */
-#ifdef CONFIG_MTD_PARTITIONS
 			mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], part_probes, &mtd_parts, 0);
-			if (mtd_parts_nb > 0) {
+			if (mtd_parts_nb > 0)
 				printk(KERN_NOTICE "Using command line partition definition\n");
-				add_mtd_partitions(cs553x_mtd[i], mtd_parts, mtd_parts_nb);
-			} else {
-				add_mtd_device(cs553x_mtd[i]);
-			}
-#else
-			add_mtd_device(cs553x_mtd[i]);
-#endif
+			mtd_device_register(cs553x_mtd[i], mtd_parts,
+					    mtd_parts_nb);
 			err = 0;
 		}
 	}
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index aff3468..1f34951 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -530,6 +530,8 @@
 	int				ret;
 	uint32_t			val;
 	nand_ecc_modes_t		ecc_mode;
+	struct mtd_partition		*mtd_parts = NULL;
+	int				mtd_parts_nb = 0;
 
 	/* insist on board-specific configuration */
 	if (!pdata)
@@ -749,41 +751,33 @@
 	if (ret < 0)
 		goto err_scan;
 
-	if (mtd_has_partitions()) {
-		struct mtd_partition	*mtd_parts = NULL;
-		int			mtd_parts_nb = 0;
+	if (mtd_has_cmdlinepart()) {
+		static const char *probes[] __initconst = {
+			"cmdlinepart", NULL
+		};
 
-		if (mtd_has_cmdlinepart()) {
-			static const char *probes[] __initconst =
-				{ "cmdlinepart", NULL };
+		mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes,
+						    &mtd_parts, 0);
+	}
 
-			mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes,
-							    &mtd_parts, 0);
-		}
+	if (mtd_parts_nb <= 0) {
+		mtd_parts = pdata->parts;
+		mtd_parts_nb = pdata->nr_parts;
+	}
 
-		if (mtd_parts_nb <= 0) {
-			mtd_parts = pdata->parts;
-			mtd_parts_nb = pdata->nr_parts;
-		}
-
-		/* Register any partitions */
-		if (mtd_parts_nb > 0) {
-			ret = add_mtd_partitions(&info->mtd,
-					mtd_parts, mtd_parts_nb);
-			if (ret == 0)
-				info->partitioned = true;
-		}
-
-	} else if (pdata->nr_parts) {
-		dev_warn(&pdev->dev, "ignoring %d default partitions on %s\n",
-				pdata->nr_parts, info->mtd.name);
+	/* Register any partitions */
+	if (mtd_parts_nb > 0) {
+		ret = mtd_device_register(&info->mtd, mtd_parts,
+					  mtd_parts_nb);
+		if (ret == 0)
+			info->partitioned = true;
 	}
 
 	/* If there's no partition info, just package the whole chip
 	 * as a single MTD device.
 	 */
 	if (!info->partitioned)
-		ret = add_mtd_device(&info->mtd) ? -ENODEV : 0;
+		ret = mtd_device_register(&info->mtd, NULL, 0) ? -ENODEV : 0;
 
 	if (ret < 0)
 		goto err_scan;
@@ -824,10 +818,7 @@
 	struct davinci_nand_info *info = platform_get_drvdata(pdev);
 	int status;
 
-	if (mtd_has_partitions() && info->partitioned)
-		status = del_mtd_partitions(&info->mtd);
-	else
-		status = del_mtd_device(&info->mtd);
+	status = mtd_device_unregister(&info->mtd);
 
 	spin_lock_irq(&davinci_nand_lock);
 	if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 4633f09..d527621 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -19,6 +19,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -44,16 +45,16 @@
 
 /* We define a macro here that combines all interrupts this driver uses into
  * a single constant value, for convenience. */
-#define DENALI_IRQ_ALL	(INTR_STATUS0__DMA_CMD_COMP | \
-			INTR_STATUS0__ECC_TRANSACTION_DONE | \
-			INTR_STATUS0__ECC_ERR | \
-			INTR_STATUS0__PROGRAM_FAIL | \
-			INTR_STATUS0__LOAD_COMP | \
-			INTR_STATUS0__PROGRAM_COMP | \
-			INTR_STATUS0__TIME_OUT | \
-			INTR_STATUS0__ERASE_FAIL | \
-			INTR_STATUS0__RST_COMP | \
-			INTR_STATUS0__ERASE_COMP)
+#define DENALI_IRQ_ALL	(INTR_STATUS__DMA_CMD_COMP | \
+			INTR_STATUS__ECC_TRANSACTION_DONE | \
+			INTR_STATUS__ECC_ERR | \
+			INTR_STATUS__PROGRAM_FAIL | \
+			INTR_STATUS__LOAD_COMP | \
+			INTR_STATUS__PROGRAM_COMP | \
+			INTR_STATUS__TIME_OUT | \
+			INTR_STATUS__ERASE_FAIL | \
+			INTR_STATUS__RST_COMP | \
+			INTR_STATUS__ERASE_COMP)
 
 /* indicates whether or not the internal value for the flash bank is
  * valid or not */
@@ -95,30 +96,6 @@
 	{ /* end: all zeroes */ }
 };
 
-
-/* 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,
-						  INTR_STATUS3};
-
-static const uint32_t device_reset_banks[4] = {DEVICE_RESET__BANK0,
-							DEVICE_RESET__BANK1,
-							DEVICE_RESET__BANK2,
-							DEVICE_RESET__BANK3};
-
-static const uint32_t operation_timeout[4] = {INTR_STATUS0__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,
-							INTR_STATUS1__RST_COMP,
-							INTR_STATUS2__RST_COMP,
-							INTR_STATUS3__RST_COMP};
-
 /* forward declarations */
 static void clear_interrupts(struct denali_nand_info *denali);
 static uint32_t wait_for_irq(struct denali_nand_info *denali,
@@ -180,19 +157,17 @@
 static void reset_bank(struct denali_nand_info *denali)
 {
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = reset_complete[denali->flash_bank] |
-			    operation_timeout[denali->flash_bank];
-	int bank = 0;
+	uint32_t irq_mask = INTR_STATUS__RST_COMP |
+			    INTR_STATUS__TIME_OUT;
 
 	clear_interrupts(denali);
 
-	bank = device_reset_banks[denali->flash_bank];
-	iowrite32(bank, denali->flash_reg + DEVICE_RESET);
+	iowrite32(1 << denali->flash_bank, denali->flash_reg + DEVICE_RESET);
 
 	irq_status = wait_for_irq(denali, irq_mask);
 
-	if (irq_status & operation_timeout[denali->flash_bank])
-		dev_err(&denali->dev->dev, "reset bank failed.\n");
+	if (irq_status & INTR_STATUS__TIME_OUT)
+		dev_err(denali->dev, "reset bank failed.\n");
 }
 
 /* Reset the flash controller */
@@ -200,29 +175,28 @@
 {
 	uint32_t i;
 
-	dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n",
+	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
 		       __FILE__, __LINE__, __func__);
 
-	for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++)
-		iowrite32(reset_complete[i] | operation_timeout[i],
-		denali->flash_reg + intr_status_addresses[i]);
+	for (i = 0 ; i < denali->max_banks; i++)
+		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
+		denali->flash_reg + INTR_STATUS(i));
 
-	for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) {
-		iowrite32(device_reset_banks[i],
-				denali->flash_reg + DEVICE_RESET);
+	for (i = 0 ; i < denali->max_banks; i++) {
+		iowrite32(1 << i, denali->flash_reg + DEVICE_RESET);
 		while (!(ioread32(denali->flash_reg +
-				intr_status_addresses[i]) &
-			(reset_complete[i] | operation_timeout[i])))
+				INTR_STATUS(i)) &
+			(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT)))
 			cpu_relax();
-		if (ioread32(denali->flash_reg + intr_status_addresses[i]) &
-			operation_timeout[i])
-			dev_dbg(&denali->dev->dev,
+		if (ioread32(denali->flash_reg + INTR_STATUS(i)) &
+			INTR_STATUS__TIME_OUT)
+			dev_dbg(denali->dev,
 			"NAND Reset operation timed out on bank %d\n", i);
 	}
 
-	for (i = 0; i < LLD_MAX_FLASH_BANKS; i++)
-		iowrite32(reset_complete[i] | operation_timeout[i],
-			denali->flash_reg + intr_status_addresses[i]);
+	for (i = 0; i < denali->max_banks; i++)
+		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
+			denali->flash_reg + INTR_STATUS(i));
 
 	return PASS;
 }
@@ -254,7 +228,7 @@
 	uint16_t acc_clks;
 	uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt;
 
-	dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n",
+	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
 		       __FILE__, __LINE__, __func__);
 
 	en_lo = CEIL_DIV(Trp[mode], CLK_X);
@@ -291,7 +265,7 @@
 		acc_clks++;
 
 	if ((data_invalid - acc_clks * CLK_X) < 2)
-		dev_warn(&denali->dev->dev, "%s, Line %d: Warning!\n",
+		dev_warn(denali->dev, "%s, Line %d: Warning!\n",
 			__FILE__, __LINE__);
 
 	addr_2_data = CEIL_DIV(Tadl[mode], CLK_X);
@@ -419,7 +393,7 @@
 #endif
 		break;
 	default:
-		dev_warn(&denali->dev->dev,
+		dev_warn(denali->dev,
 			"Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
 			"Will use default parameter values instead.\n",
 			device_id);
@@ -431,17 +405,17 @@
  */
 static void find_valid_banks(struct denali_nand_info *denali)
 {
-	uint32_t id[LLD_MAX_FLASH_BANKS];
+	uint32_t id[denali->max_banks];
 	int i;
 
 	denali->total_used_banks = 1;
-	for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) {
+	for (i = 0; i < denali->max_banks; i++) {
 		index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90);
 		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]);
 
-		dev_dbg(&denali->dev->dev,
+		dev_dbg(denali->dev,
 			"Return 1st ID for bank[%d]: %x\n", i, id[i]);
 
 		if (i == 0) {
@@ -461,16 +435,27 @@
 		 * Multichip support is not enabled.
 		 */
 		if (denali->total_used_banks != 1) {
-			dev_err(&denali->dev->dev,
+			dev_err(denali->dev,
 					"Sorry, Intel CE4100 only supports "
 					"a single NAND device.\n");
 			BUG();
 		}
 	}
-	dev_dbg(&denali->dev->dev,
+	dev_dbg(denali->dev,
 		"denali->total_used_banks: %d\n", denali->total_used_banks);
 }
 
+/*
+ * Use the configuration feature register to determine the maximum number of
+ * banks that the hardware supports.
+ */
+static void detect_max_banks(struct denali_nand_info *denali)
+{
+	uint32_t features = ioread32(denali->flash_reg + FEATURES);
+
+	denali->max_banks = 2 << (features & FEATURES__N_BANKS);
+}
+
 static void detect_partition_feature(struct denali_nand_info *denali)
 {
 	/* For MRST platform, denali->fwblks represent the
@@ -480,15 +465,15 @@
 	 * blocks it can't touch.
 	 * */
 	if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) {
-		if ((ioread32(denali->flash_reg + PERM_SRC_ID_1) &
-			PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) {
+		if ((ioread32(denali->flash_reg + PERM_SRC_ID(1)) &
+			PERM_SRC_ID__SRCID) == SPECTRA_PARTITION_ID) {
 			denali->fwblks =
-			    ((ioread32(denali->flash_reg + MIN_MAX_BANK_1) &
-			      MIN_MAX_BANK_1__MIN_VALUE) *
+			    ((ioread32(denali->flash_reg + MIN_MAX_BANK(1)) &
+			      MIN_MAX_BANK__MIN_VALUE) *
 			     denali->blksperchip)
 			    +
-			    (ioread32(denali->flash_reg + MIN_BLK_ADDR_1) &
-			    MIN_BLK_ADDR_1__VALUE);
+			    (ioread32(denali->flash_reg + MIN_BLK_ADDR(1)) &
+			    MIN_BLK_ADDR__VALUE);
 		} else
 			denali->fwblks = SPECTRA_START_BLOCK;
 	} else
@@ -501,7 +486,7 @@
 	uint32_t id_bytes[5], addr;
 	uint8_t i, maf_id, device_id;
 
-	dev_dbg(&denali->dev->dev,
+	dev_dbg(denali->dev,
 			"%s, Line %d, Function: %s\n",
 			__FILE__, __LINE__, __func__);
 
@@ -530,7 +515,7 @@
 		get_hynix_nand_para(denali, device_id);
 	}
 
-	dev_info(&denali->dev->dev,
+	dev_info(denali->dev,
 			"Dump timing register values:"
 			"acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
 			"we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
@@ -560,7 +545,7 @@
 static void denali_set_intr_modes(struct denali_nand_info *denali,
 					uint16_t INT_ENABLE)
 {
-	dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n",
+	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
 		       __FILE__, __LINE__, __func__);
 
 	if (INT_ENABLE)
@@ -580,6 +565,7 @@
 static void denali_irq_init(struct denali_nand_info *denali)
 {
 	uint32_t int_mask = 0;
+	int i;
 
 	/* Disable global interrupts */
 	denali_set_intr_modes(denali, false);
@@ -587,10 +573,8 @@
 	int_mask = DENALI_IRQ_ALL;
 
 	/* Clear all status bits */
-	iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS0);
-	iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS1);
-	iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS2);
-	iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS3);
+	for (i = 0; i < denali->max_banks; ++i)
+		iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS(i));
 
 	denali_irq_enable(denali, int_mask);
 }
@@ -604,10 +588,10 @@
 static void denali_irq_enable(struct denali_nand_info *denali,
 							uint32_t int_mask)
 {
-	iowrite32(int_mask, denali->flash_reg + INTR_EN0);
-	iowrite32(int_mask, denali->flash_reg + INTR_EN1);
-	iowrite32(int_mask, denali->flash_reg + INTR_EN2);
-	iowrite32(int_mask, denali->flash_reg + INTR_EN3);
+	int i;
+
+	for (i = 0; i < denali->max_banks; ++i)
+		iowrite32(int_mask, denali->flash_reg + INTR_EN(i));
 }
 
 /* This function only returns when an interrupt that this driver cares about
@@ -624,7 +608,7 @@
 {
 	uint32_t intr_status_reg = 0;
 
-	intr_status_reg = intr_status_addresses[denali->flash_bank];
+	intr_status_reg = INTR_STATUS(denali->flash_bank);
 
 	iowrite32(irq_mask, denali->flash_reg + intr_status_reg);
 }
@@ -645,7 +629,7 @@
 {
 	uint32_t intr_status_reg = 0;
 
-	intr_status_reg = intr_status_addresses[denali->flash_bank];
+	intr_status_reg = INTR_STATUS(denali->flash_bank);
 
 	return ioread32(denali->flash_reg + intr_status_reg);
 }
@@ -754,7 +738,7 @@
 		 irq_mask = 0;
 
 	if (op == DENALI_READ)
-		irq_mask = INTR_STATUS0__LOAD_COMP;
+		irq_mask = INTR_STATUS__LOAD_COMP;
 	else if (op == DENALI_WRITE)
 		irq_mask = 0;
 	else
@@ -800,7 +784,7 @@
 			irq_status = wait_for_irq(denali, irq_mask);
 
 			if (irq_status == 0) {
-				dev_err(&denali->dev->dev,
+				dev_err(denali->dev,
 						"cmd, page, addr on timeout "
 						"(0x%x, 0x%x, 0x%x)\n",
 						cmd, denali->page, addr);
@@ -861,8 +845,8 @@
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__PROGRAM_COMP |
-						INTR_STATUS0__PROGRAM_FAIL;
+	uint32_t irq_mask = INTR_STATUS__PROGRAM_COMP |
+						INTR_STATUS__PROGRAM_FAIL;
 	int status = 0;
 
 	denali->page = page;
@@ -875,11 +859,11 @@
 		irq_status = wait_for_irq(denali, irq_mask);
 
 		if (irq_status == 0) {
-			dev_err(&denali->dev->dev, "OOB write failed\n");
+			dev_err(denali->dev, "OOB write failed\n");
 			status = -EIO;
 		}
 	} else {
-		dev_err(&denali->dev->dev, "unable to send pipeline command\n");
+		dev_err(denali->dev, "unable to send pipeline command\n");
 		status = -EIO;
 	}
 	return status;
@@ -889,7 +873,7 @@
 static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	uint32_t irq_mask = INTR_STATUS0__LOAD_COMP,
+	uint32_t irq_mask = INTR_STATUS__LOAD_COMP,
 			 irq_status = 0, addr = 0x0, cmd = 0x0;
 
 	denali->page = page;
@@ -904,7 +888,7 @@
 		irq_status = wait_for_irq(denali, irq_mask);
 
 		if (irq_status == 0)
-			dev_err(&denali->dev->dev, "page on OOB timeout %d\n",
+			dev_err(denali->dev, "page on OOB timeout %d\n",
 					denali->page);
 
 		/* We set the device back to MAIN_ACCESS here as I observed
@@ -944,7 +928,7 @@
 {
 	bool check_erased_page = false;
 
-	if (irq_status & INTR_STATUS0__ECC_ERR) {
+	if (irq_status & INTR_STATUS__ECC_ERR) {
 		/* read the ECC errors. we'll ignore them for now */
 		uint32_t err_address = 0, err_correction_info = 0;
 		uint32_t err_byte = 0, err_sector = 0, err_device = 0;
@@ -995,7 +979,7 @@
 		 * for a while for this interrupt
 		 * */
 		while (!(read_interrupt_status(denali) &
-				INTR_STATUS0__ECC_TRANSACTION_DONE))
+				INTR_STATUS__ECC_TRANSACTION_DONE))
 			cpu_relax();
 		clear_interrupts(denali);
 		denali_set_intr_modes(denali, true);
@@ -1045,14 +1029,13 @@
 			const uint8_t *buf, bool raw_xfer)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	struct pci_dev *pci_dev = denali->dev;
 
 	dma_addr_t addr = denali->buf.dma_buf;
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP |
-						INTR_STATUS0__PROGRAM_FAIL;
+	uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP |
+						INTR_STATUS__PROGRAM_FAIL;
 
 	/* if it is a raw xfer, we want to disable ecc, and send
 	 * the spare area.
@@ -1071,7 +1054,7 @@
 			mtd->oobsize);
 	}
 
-	pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE);
+	dma_sync_single_for_device(denali->dev, addr, size, DMA_TO_DEVICE);
 
 	clear_interrupts(denali);
 	denali_enable_dma(denali, true);
@@ -1082,16 +1065,16 @@
 	irq_status = wait_for_irq(denali, irq_mask);
 
 	if (irq_status == 0) {
-		dev_err(&denali->dev->dev,
+		dev_err(denali->dev,
 				"timeout on write_page (type = %d)\n",
 				raw_xfer);
 		denali->status =
-			(irq_status & INTR_STATUS0__PROGRAM_FAIL) ?
+			(irq_status & INTR_STATUS__PROGRAM_FAIL) ?
 			NAND_STATUS_FAIL : PASS;
 	}
 
 	denali_enable_dma(denali, false);
-	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE);
+	dma_sync_single_for_cpu(denali->dev, addr, size, DMA_TO_DEVICE);
 }
 
 /* NAND core entry points */
@@ -1139,18 +1122,17 @@
 			    uint8_t *buf, int page)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	struct pci_dev *pci_dev = denali->dev;
 
 	dma_addr_t addr = denali->buf.dma_buf;
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__ECC_TRANSACTION_DONE |
-			    INTR_STATUS0__ECC_ERR;
+	uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE |
+			    INTR_STATUS__ECC_ERR;
 	bool check_erased_page = false;
 
 	if (page != denali->page) {
-		dev_err(&denali->dev->dev, "IN %s: page %d is not"
+		dev_err(denali->dev, "IN %s: page %d is not"
 				" equal to denali->page %d, investigate!!",
 				__func__, page, denali->page);
 		BUG();
@@ -1159,7 +1141,7 @@
 	setup_ecc_for_xfer(denali, true, false);
 
 	denali_enable_dma(denali, true);
-	pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE);
 
 	clear_interrupts(denali);
 	denali_setup_dma(denali, DENALI_READ);
@@ -1167,7 +1149,7 @@
 	/* wait for operation to complete */
 	irq_status = wait_for_irq(denali, irq_mask);
 
-	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE);
 
 	memcpy(buf, denali->buf.buf, mtd->writesize);
 
@@ -1192,16 +1174,15 @@
 				uint8_t *buf, int page)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	struct pci_dev *pci_dev = denali->dev;
 
 	dma_addr_t addr = denali->buf.dma_buf;
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP;
+	uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
 
 	if (page != denali->page) {
-		dev_err(&denali->dev->dev, "IN %s: page %d is not"
+		dev_err(denali->dev, "IN %s: page %d is not"
 				" equal to denali->page %d, investigate!!",
 				__func__, page, denali->page);
 		BUG();
@@ -1210,7 +1191,7 @@
 	setup_ecc_for_xfer(denali, false, true);
 	denali_enable_dma(denali, true);
 
-	pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE);
 
 	clear_interrupts(denali);
 	denali_setup_dma(denali, DENALI_READ);
@@ -1218,7 +1199,7 @@
 	/* wait for operation to complete */
 	irq_status = wait_for_irq(denali, irq_mask);
 
-	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE);
 
 	denali_enable_dma(denali, false);
 
@@ -1271,10 +1252,10 @@
 	index_addr(denali, (uint32_t)cmd, 0x1);
 
 	/* wait for erase to complete or failure to occur */
-	irq_status = wait_for_irq(denali, INTR_STATUS0__ERASE_COMP |
-					INTR_STATUS0__ERASE_FAIL);
+	irq_status = wait_for_irq(denali, INTR_STATUS__ERASE_COMP |
+					INTR_STATUS__ERASE_FAIL);
 
-	denali->status = (irq_status & INTR_STATUS0__ERASE_FAIL) ?
+	denali->status = (irq_status & INTR_STATUS__ERASE_FAIL) ?
 						NAND_STATUS_FAIL : PASS;
 }
 
@@ -1330,7 +1311,7 @@
 				uint8_t *ecc_code)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(&denali->dev->dev,
+	dev_err(denali->dev,
 			"denali_ecc_calculate called unexpectedly\n");
 	BUG();
 	return -EIO;
@@ -1340,7 +1321,7 @@
 				uint8_t *read_ecc, uint8_t *calc_ecc)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(&denali->dev->dev,
+	dev_err(denali->dev,
 			"denali_ecc_correct called unexpectedly\n");
 	BUG();
 	return -EIO;
@@ -1349,7 +1330,7 @@
 static void denali_ecc_hwctl(struct mtd_info *mtd, int mode)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(&denali->dev->dev,
+	dev_err(denali->dev,
 			"denali_ecc_hwctl called unexpectedly\n");
 	BUG();
 }
@@ -1375,6 +1356,7 @@
 	/* Should set value for these registers when init */
 	iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES);
 	iowrite32(1, denali->flash_reg + ECC_ENABLE);
+	detect_max_banks(denali);
 	denali_nand_timing_set(denali);
 	denali_irq_init(denali);
 }
@@ -1484,24 +1466,22 @@
 	}
 
 	/* Is 32-bit DMA supported? */
-	ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32));
-
+	ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
 	if (ret) {
 		printk(KERN_ERR "Spectra: no usable DMA configuration\n");
 		goto failed_enable_dev;
 	}
-	denali->buf.dma_buf =
-		pci_map_single(dev, denali->buf.buf,
-						DENALI_BUF_SIZE,
-						PCI_DMA_BIDIRECTIONAL);
+	denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf,
+					     DENALI_BUF_SIZE,
+					     DMA_BIDIRECTIONAL);
 
-	if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) {
+	if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) {
 		dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n");
 		goto failed_enable_dev;
 	}
 
 	pci_set_master(dev);
-	denali->dev = dev;
+	denali->dev = &dev->dev;
 	denali->mtd.dev.parent = &dev->dev;
 
 	ret = pci_request_regions(dev, DENALI_NAND_NAME);
@@ -1554,7 +1534,7 @@
 	/* scan for NAND devices attached to the controller
 	 * 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)) {
+	if (nand_scan_ident(&denali->mtd, denali->max_banks, NULL)) {
 		ret = -ENXIO;
 		goto failed_req_irq;
 	}
@@ -1664,7 +1644,7 @@
 		goto failed_req_irq;
 	}
 
-	ret = add_mtd_device(&denali->mtd);
+	ret = mtd_device_register(&denali->mtd, NULL, 0);
 	if (ret) {
 		dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n",
 				ret);
@@ -1681,8 +1661,8 @@
 failed_req_regions:
 	pci_release_regions(dev);
 failed_dma_map:
-	pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
-							PCI_DMA_BIDIRECTIONAL);
+	dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+			 DMA_BIDIRECTIONAL);
 failed_enable_dev:
 	pci_disable_device(dev);
 failed_alloc_memery:
@@ -1696,7 +1676,7 @@
 	struct denali_nand_info *denali = pci_get_drvdata(dev);
 
 	nand_release(&denali->mtd);
-	del_mtd_device(&denali->mtd);
+	mtd_device_unregister(&denali->mtd);
 
 	denali_irq_cleanup(dev->irq, denali);
 
@@ -1704,8 +1684,8 @@
 	iounmap(denali->flash_mem);
 	pci_release_regions(dev);
 	pci_disable_device(dev);
-	pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
-							PCI_DMA_BIDIRECTIONAL);
+	dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+			 DMA_BIDIRECTIONAL);
 	pci_set_drvdata(dev, NULL);
 	kfree(denali);
 }
@@ -1721,8 +1701,7 @@
 
 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\n");
 	return pci_register_driver(&denali_pci_driver);
 }
 
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 3918bcb..fabb9d5 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -211,185 +211,46 @@
 #define TRANSFER_MODE				0x400
 #define     TRANSFER_MODE__VALUE			0x0003
 
-#define INTR_STATUS0				0x410
-#define     INTR_STATUS0__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_STATUS0__ECC_ERR			0x0002
-#define     INTR_STATUS0__DMA_CMD_COMP			0x0004
-#define     INTR_STATUS0__TIME_OUT			0x0008
-#define     INTR_STATUS0__PROGRAM_FAIL			0x0010
-#define     INTR_STATUS0__ERASE_FAIL			0x0020
-#define     INTR_STATUS0__LOAD_COMP			0x0040
-#define     INTR_STATUS0__PROGRAM_COMP			0x0080
-#define     INTR_STATUS0__ERASE_COMP			0x0100
-#define     INTR_STATUS0__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_STATUS0__LOCKED_BLK			0x0400
-#define     INTR_STATUS0__UNSUP_CMD			0x0800
-#define     INTR_STATUS0__INT_ACT			0x1000
-#define     INTR_STATUS0__RST_COMP			0x2000
-#define     INTR_STATUS0__PIPE_CMD_ERR			0x4000
-#define     INTR_STATUS0__PAGE_XFER_INC			0x8000
+#define INTR_STATUS(__bank)	(0x410 + ((__bank) * 0x50))
+#define INTR_EN(__bank)		(0x420 + ((__bank) * 0x50))
 
-#define INTR_EN0					0x420
-#define     INTR_EN0__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_EN0__ECC_ERR				0x0002
-#define     INTR_EN0__DMA_CMD_COMP			0x0004
-#define     INTR_EN0__TIME_OUT				0x0008
-#define     INTR_EN0__PROGRAM_FAIL			0x0010
-#define     INTR_EN0__ERASE_FAIL			0x0020
-#define     INTR_EN0__LOAD_COMP				0x0040
-#define     INTR_EN0__PROGRAM_COMP			0x0080
-#define     INTR_EN0__ERASE_COMP			0x0100
-#define     INTR_EN0__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN0__LOCKED_BLK			0x0400
-#define     INTR_EN0__UNSUP_CMD				0x0800
-#define     INTR_EN0__INT_ACT				0x1000
-#define     INTR_EN0__RST_COMP				0x2000
-#define     INTR_EN0__PIPE_CMD_ERR			0x4000
-#define     INTR_EN0__PAGE_XFER_INC			0x8000
+#define     INTR_STATUS__ECC_TRANSACTION_DONE		0x0001
+#define     INTR_STATUS__ECC_ERR			0x0002
+#define     INTR_STATUS__DMA_CMD_COMP			0x0004
+#define     INTR_STATUS__TIME_OUT			0x0008
+#define     INTR_STATUS__PROGRAM_FAIL			0x0010
+#define     INTR_STATUS__ERASE_FAIL			0x0020
+#define     INTR_STATUS__LOAD_COMP			0x0040
+#define     INTR_STATUS__PROGRAM_COMP			0x0080
+#define     INTR_STATUS__ERASE_COMP			0x0100
+#define     INTR_STATUS__PIPE_CPYBCK_CMD_COMP		0x0200
+#define     INTR_STATUS__LOCKED_BLK			0x0400
+#define     INTR_STATUS__UNSUP_CMD			0x0800
+#define     INTR_STATUS__INT_ACT			0x1000
+#define     INTR_STATUS__RST_COMP			0x2000
+#define     INTR_STATUS__PIPE_CMD_ERR			0x4000
+#define     INTR_STATUS__PAGE_XFER_INC			0x8000
 
-#define PAGE_CNT0				0x430
-#define     PAGE_CNT0__VALUE				0x00ff
+#define     INTR_EN__ECC_TRANSACTION_DONE		0x0001
+#define     INTR_EN__ECC_ERR				0x0002
+#define     INTR_EN__DMA_CMD_COMP			0x0004
+#define     INTR_EN__TIME_OUT				0x0008
+#define     INTR_EN__PROGRAM_FAIL			0x0010
+#define     INTR_EN__ERASE_FAIL				0x0020
+#define     INTR_EN__LOAD_COMP				0x0040
+#define     INTR_EN__PROGRAM_COMP			0x0080
+#define     INTR_EN__ERASE_COMP				0x0100
+#define     INTR_EN__PIPE_CPYBCK_CMD_COMP		0x0200
+#define     INTR_EN__LOCKED_BLK				0x0400
+#define     INTR_EN__UNSUP_CMD				0x0800
+#define     INTR_EN__INT_ACT				0x1000
+#define     INTR_EN__RST_COMP				0x2000
+#define     INTR_EN__PIPE_CMD_ERR			0x4000
+#define     INTR_EN__PAGE_XFER_INC			0x8000
 
-#define ERR_PAGE_ADDR0				0x440
-#define     ERR_PAGE_ADDR0__VALUE			0xffff
-
-#define ERR_BLOCK_ADDR0				0x450
-#define     ERR_BLOCK_ADDR0__VALUE			0xffff
-
-#define INTR_STATUS1				0x460
-#define     INTR_STATUS1__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_STATUS1__ECC_ERR			0x0002
-#define     INTR_STATUS1__DMA_CMD_COMP			0x0004
-#define     INTR_STATUS1__TIME_OUT			0x0008
-#define     INTR_STATUS1__PROGRAM_FAIL			0x0010
-#define     INTR_STATUS1__ERASE_FAIL			0x0020
-#define     INTR_STATUS1__LOAD_COMP			0x0040
-#define     INTR_STATUS1__PROGRAM_COMP			0x0080
-#define     INTR_STATUS1__ERASE_COMP			0x0100
-#define     INTR_STATUS1__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_STATUS1__LOCKED_BLK			0x0400
-#define     INTR_STATUS1__UNSUP_CMD			0x0800
-#define     INTR_STATUS1__INT_ACT			0x1000
-#define     INTR_STATUS1__RST_COMP			0x2000
-#define     INTR_STATUS1__PIPE_CMD_ERR			0x4000
-#define     INTR_STATUS1__PAGE_XFER_INC			0x8000
-
-#define INTR_EN1					0x470
-#define     INTR_EN1__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_EN1__ECC_ERR				0x0002
-#define     INTR_EN1__DMA_CMD_COMP			0x0004
-#define     INTR_EN1__TIME_OUT				0x0008
-#define     INTR_EN1__PROGRAM_FAIL			0x0010
-#define     INTR_EN1__ERASE_FAIL			0x0020
-#define     INTR_EN1__LOAD_COMP				0x0040
-#define     INTR_EN1__PROGRAM_COMP			0x0080
-#define     INTR_EN1__ERASE_COMP			0x0100
-#define     INTR_EN1__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN1__LOCKED_BLK			0x0400
-#define     INTR_EN1__UNSUP_CMD				0x0800
-#define     INTR_EN1__INT_ACT				0x1000
-#define     INTR_EN1__RST_COMP				0x2000
-#define     INTR_EN1__PIPE_CMD_ERR			0x4000
-#define     INTR_EN1__PAGE_XFER_INC			0x8000
-
-#define PAGE_CNT1				0x480
-#define     PAGE_CNT1__VALUE				0x00ff
-
-#define ERR_PAGE_ADDR1				0x490
-#define     ERR_PAGE_ADDR1__VALUE			0xffff
-
-#define ERR_BLOCK_ADDR1				0x4a0
-#define     ERR_BLOCK_ADDR1__VALUE			0xffff
-
-#define INTR_STATUS2				0x4b0
-#define     INTR_STATUS2__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_STATUS2__ECC_ERR			0x0002
-#define     INTR_STATUS2__DMA_CMD_COMP			0x0004
-#define     INTR_STATUS2__TIME_OUT			0x0008
-#define     INTR_STATUS2__PROGRAM_FAIL			0x0010
-#define     INTR_STATUS2__ERASE_FAIL			0x0020
-#define     INTR_STATUS2__LOAD_COMP			0x0040
-#define     INTR_STATUS2__PROGRAM_COMP			0x0080
-#define     INTR_STATUS2__ERASE_COMP			0x0100
-#define     INTR_STATUS2__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_STATUS2__LOCKED_BLK			0x0400
-#define     INTR_STATUS2__UNSUP_CMD			0x0800
-#define     INTR_STATUS2__INT_ACT			0x1000
-#define     INTR_STATUS2__RST_COMP			0x2000
-#define     INTR_STATUS2__PIPE_CMD_ERR			0x4000
-#define     INTR_STATUS2__PAGE_XFER_INC			0x8000
-
-#define INTR_EN2					0x4c0
-#define     INTR_EN2__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_EN2__ECC_ERR				0x0002
-#define     INTR_EN2__DMA_CMD_COMP			0x0004
-#define     INTR_EN2__TIME_OUT				0x0008
-#define     INTR_EN2__PROGRAM_FAIL			0x0010
-#define     INTR_EN2__ERASE_FAIL			0x0020
-#define     INTR_EN2__LOAD_COMP				0x0040
-#define     INTR_EN2__PROGRAM_COMP			0x0080
-#define     INTR_EN2__ERASE_COMP			0x0100
-#define     INTR_EN2__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN2__LOCKED_BLK			0x0400
-#define     INTR_EN2__UNSUP_CMD				0x0800
-#define     INTR_EN2__INT_ACT				0x1000
-#define     INTR_EN2__RST_COMP				0x2000
-#define     INTR_EN2__PIPE_CMD_ERR			0x4000
-#define     INTR_EN2__PAGE_XFER_INC			0x8000
-
-#define PAGE_CNT2				0x4d0
-#define     PAGE_CNT2__VALUE				0x00ff
-
-#define ERR_PAGE_ADDR2				0x4e0
-#define     ERR_PAGE_ADDR2__VALUE			0xffff
-
-#define ERR_BLOCK_ADDR2				0x4f0
-#define     ERR_BLOCK_ADDR2__VALUE			0xffff
-
-#define INTR_STATUS3				0x500
-#define     INTR_STATUS3__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_STATUS3__ECC_ERR			0x0002
-#define     INTR_STATUS3__DMA_CMD_COMP			0x0004
-#define     INTR_STATUS3__TIME_OUT			0x0008
-#define     INTR_STATUS3__PROGRAM_FAIL			0x0010
-#define     INTR_STATUS3__ERASE_FAIL			0x0020
-#define     INTR_STATUS3__LOAD_COMP			0x0040
-#define     INTR_STATUS3__PROGRAM_COMP			0x0080
-#define     INTR_STATUS3__ERASE_COMP			0x0100
-#define     INTR_STATUS3__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_STATUS3__LOCKED_BLK			0x0400
-#define     INTR_STATUS3__UNSUP_CMD			0x0800
-#define     INTR_STATUS3__INT_ACT			0x1000
-#define     INTR_STATUS3__RST_COMP			0x2000
-#define     INTR_STATUS3__PIPE_CMD_ERR			0x4000
-#define     INTR_STATUS3__PAGE_XFER_INC			0x8000
-
-#define INTR_EN3					0x510
-#define     INTR_EN3__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_EN3__ECC_ERR				0x0002
-#define     INTR_EN3__DMA_CMD_COMP			0x0004
-#define     INTR_EN3__TIME_OUT				0x0008
-#define     INTR_EN3__PROGRAM_FAIL			0x0010
-#define     INTR_EN3__ERASE_FAIL			0x0020
-#define     INTR_EN3__LOAD_COMP				0x0040
-#define     INTR_EN3__PROGRAM_COMP			0x0080
-#define     INTR_EN3__ERASE_COMP			0x0100
-#define     INTR_EN3__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN3__LOCKED_BLK			0x0400
-#define     INTR_EN3__UNSUP_CMD				0x0800
-#define     INTR_EN3__INT_ACT				0x1000
-#define     INTR_EN3__RST_COMP				0x2000
-#define     INTR_EN3__PIPE_CMD_ERR			0x4000
-#define     INTR_EN3__PAGE_XFER_INC			0x8000
-
-#define PAGE_CNT3				0x520
-#define     PAGE_CNT3__VALUE				0x00ff
-
-#define ERR_PAGE_ADDR3				0x530
-#define     ERR_PAGE_ADDR3__VALUE			0xffff
-
-#define ERR_BLOCK_ADDR3				0x540
-#define     ERR_BLOCK_ADDR3__VALUE			0xffff
+#define PAGE_CNT(__bank)	(0x430 + ((__bank) * 0x50))
+#define ERR_PAGE_ADDR(__bank)	(0x440 + ((__bank) * 0x50))
+#define ERR_BLOCK_ADDR(__bank)	(0x450 + ((__bank) * 0x50))
 
 #define DATA_INTR				0x550
 #define     DATA_INTR__WRITE_SPACE_AV			0x0001
@@ -484,141 +345,23 @@
 #define     PTN_INTR_EN__ACCESS_ERROR_BANK3		0x0010
 #define     PTN_INTR_EN__REG_ACCESS_ERROR		0x0020
 
-#define PERM_SRC_ID_0				0x830
-#define     PERM_SRC_ID_0__SRCID			0x00ff
-#define     PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_0__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_0__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_0__PARTITION_VALID		0x8000
+#define PERM_SRC_ID(__bank)	(0x830 + ((__bank) * 0x40))
+#define     PERM_SRC_ID__SRCID				0x00ff
+#define     PERM_SRC_ID__DIRECT_ACCESS_ACTIVE		0x0800
+#define     PERM_SRC_ID__WRITE_ACTIVE			0x2000
+#define     PERM_SRC_ID__READ_ACTIVE			0x4000
+#define     PERM_SRC_ID__PARTITION_VALID		0x8000
 
-#define MIN_BLK_ADDR_0				0x840
-#define     MIN_BLK_ADDR_0__VALUE			0xffff
+#define MIN_BLK_ADDR(__bank)	(0x840 + ((__bank) * 0x40))
+#define     MIN_BLK_ADDR__VALUE				0xffff
 
-#define MAX_BLK_ADDR_0				0x850
-#define     MAX_BLK_ADDR_0__VALUE			0xffff
+#define MAX_BLK_ADDR(__bank)	(0x850 + ((__bank) * 0x40))
+#define     MAX_BLK_ADDR__VALUE				0xffff
 
-#define MIN_MAX_BANK_0				0x860
-#define     MIN_MAX_BANK_0__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_0__MAX_VALUE			0x000c
+#define MIN_MAX_BANK(__bank)	(0x860 + ((__bank) * 0x40))
+#define     MIN_MAX_BANK__MIN_VALUE			0x0003
+#define     MIN_MAX_BANK__MAX_VALUE			0x000c
 
-#define PERM_SRC_ID_1				0x870
-#define     PERM_SRC_ID_1__SRCID			0x00ff
-#define     PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_1__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_1__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_1__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_1				0x880
-#define     MIN_BLK_ADDR_1__VALUE			0xffff
-
-#define MAX_BLK_ADDR_1				0x890
-#define     MAX_BLK_ADDR_1__VALUE			0xffff
-
-#define MIN_MAX_BANK_1				0x8a0
-#define     MIN_MAX_BANK_1__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_1__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_2				0x8b0
-#define     PERM_SRC_ID_2__SRCID			0x00ff
-#define     PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_2__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_2__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_2__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_2				0x8c0
-#define     MIN_BLK_ADDR_2__VALUE			0xffff
-
-#define MAX_BLK_ADDR_2				0x8d0
-#define     MAX_BLK_ADDR_2__VALUE			0xffff
-
-#define MIN_MAX_BANK_2				0x8e0
-#define     MIN_MAX_BANK_2__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_2__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_3				0x8f0
-#define     PERM_SRC_ID_3__SRCID			0x00ff
-#define     PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_3__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_3__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_3__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_3				0x900
-#define     MIN_BLK_ADDR_3__VALUE			0xffff
-
-#define MAX_BLK_ADDR_3				0x910
-#define     MAX_BLK_ADDR_3__VALUE			0xffff
-
-#define MIN_MAX_BANK_3				0x920
-#define     MIN_MAX_BANK_3__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_3__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_4				0x930
-#define     PERM_SRC_ID_4__SRCID			0x00ff
-#define     PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_4__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_4__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_4__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_4				0x940
-#define     MIN_BLK_ADDR_4__VALUE			0xffff
-
-#define MAX_BLK_ADDR_4				0x950
-#define     MAX_BLK_ADDR_4__VALUE			0xffff
-
-#define MIN_MAX_BANK_4				0x960
-#define     MIN_MAX_BANK_4__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_4__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_5				0x970
-#define     PERM_SRC_ID_5__SRCID			0x00ff
-#define     PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_5__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_5__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_5__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_5				0x980
-#define     MIN_BLK_ADDR_5__VALUE			0xffff
-
-#define MAX_BLK_ADDR_5				0x990
-#define     MAX_BLK_ADDR_5__VALUE			0xffff
-
-#define MIN_MAX_BANK_5				0x9a0
-#define     MIN_MAX_BANK_5__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_5__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_6				0x9b0
-#define     PERM_SRC_ID_6__SRCID			0x00ff
-#define     PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_6__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_6__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_6__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_6				0x9c0
-#define     MIN_BLK_ADDR_6__VALUE			0xffff
-
-#define MAX_BLK_ADDR_6				0x9d0
-#define     MAX_BLK_ADDR_6__VALUE			0xffff
-
-#define MIN_MAX_BANK_6				0x9e0
-#define     MIN_MAX_BANK_6__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_6__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_7				0x9f0
-#define     PERM_SRC_ID_7__SRCID			0x00ff
-#define     PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_7__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_7__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_7__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_7				0xa00
-#define     MIN_BLK_ADDR_7__VALUE			0xffff
-
-#define MAX_BLK_ADDR_7				0xa10
-#define     MAX_BLK_ADDR_7__VALUE			0xffff
-
-#define MIN_MAX_BANK_7				0xa20
-#define     MIN_MAX_BANK_7__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_7__MAX_VALUE			0x000c
 
 /* ffsdefs.h */
 #define CLEAR 0                 /*use this to clear a field instead of "fail"*/
@@ -711,7 +454,6 @@
 #define READ_WRITE_ENABLE_HIGH_COUNT    22
 
 #define ECC_SECTOR_SIZE     512
-#define LLD_MAX_FLASH_BANKS     4
 
 #define DENALI_BUF_SIZE		(NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE)
 
@@ -732,7 +474,7 @@
 	int status;
 	int platform;
 	struct nand_buf buf;
-	struct pci_dev *dev;
+	struct device *dev;
 	int total_used_banks;
 	uint32_t block;  /* stored for future use */
 	uint16_t page;
@@ -751,6 +493,7 @@
 	uint32_t totalblks;
 	uint32_t blksperchip;
 	uint32_t bbtskipbytes;
+	uint32_t max_banks;
 };
 
 #endif /*_LLD_NAND_*/
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 657b9f4..7837728 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1360,11 +1360,9 @@
 	   At least as nand_bbt.c is currently written. */
 	if ((ret = nand_scan_bbt(mtd, NULL)))
 		return ret;
-	add_mtd_device(mtd);
-#ifdef CONFIG_MTD_PARTITIONS
+	mtd_device_register(mtd, NULL, 0);
 	if (!no_autopart)
-		add_mtd_partitions(mtd, parts, numparts);
-#endif
+		mtd_device_register(mtd, parts, numparts);
 	return 0;
 }
 
@@ -1419,11 +1417,9 @@
 	   autopartitioning, but I want to give it more thought. */
 	if (!numparts)
 		return -EIO;
-	add_mtd_device(mtd);
-#ifdef CONFIG_MTD_PARTITIONS
+	mtd_device_register(mtd, NULL, 0);
 	if (!no_autopart)
-		add_mtd_partitions(mtd, parts, numparts);
-#endif
+		mtd_device_register(mtd, parts, numparts);
 	return 0;
 }
 
@@ -1678,9 +1674,9 @@
 		/* DBB note: i believe nand_release is necessary here, as
 		   buffers may have been allocated in nand_base.  Check with
 		   Thomas. FIX ME! */
-		/* nand_release will call del_mtd_device, but we haven't yet
-		   added it.  This is handled without incident by
-		   del_mtd_device, as far as I can tell. */
+		/* nand_release will call mtd_device_unregister, but we
+		   haven't yet added it.  This is handled without incident by
+		   mtd_device_unregister, as far as I can tell. */
 		nand_release(mtd);
 		kfree(mtd);
 		goto fail;
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 86366bf..8400d0f 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -55,7 +55,6 @@
 static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR;
 static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR;
 
-#ifdef CONFIG_MTD_PARTITIONS
 /*
  * Define static partitions for flash device
  */
@@ -67,8 +66,6 @@
 
 #define NUM_PARTITIONS 1
 
-#endif
-
 /*
  *	hardware specific access to control-lines
  *
@@ -101,9 +98,7 @@
 	return 1;
 }
 
-#ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /*
  * Main initialization routine
@@ -162,14 +157,12 @@
 		kfree(ep7312_mtd);
 		return -ENXIO;
 	}
-#ifdef CONFIG_MTD_PARTITIONS
 	ep7312_mtd->name = "edb7312-nand";
 	mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 		part_type = "command line";
 	else
 		mtd_parts_nb = 0;
-#endif
 	if (mtd_parts_nb == 0) {
 		mtd_parts = partition_info;
 		mtd_parts_nb = NUM_PARTITIONS;
@@ -178,7 +171,7 @@
 
 	/* Register the partitions */
 	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	add_mtd_partitions(ep7312_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_register(ep7312_mtd, mtd_parts, mtd_parts_nb);
 
 	/* Return happy */
 	return 0;
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 537e380..0bb254c 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -841,12 +841,9 @@
 	struct fsl_elbc_mtd *priv;
 	struct resource res;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
-
-#ifdef CONFIG_MTD_PARTITIONS
 	static const char *part_probe_types[]
 		= { "cmdlinepart", "RedBoot", NULL };
 	struct mtd_partition *parts;
-#endif
 	int ret;
 	int bank;
 	struct device *dev;
@@ -935,26 +932,19 @@
 	if (ret)
 		goto err;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	/* First look for RedBoot table or partitions on the command
 	 * line, these take precedence over device tree information */
 	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0);
 	if (ret < 0)
 		goto err;
 
-#ifdef CONFIG_MTD_OF_PARTS
 	if (ret == 0) {
 		ret = of_mtd_parse_partitions(priv->dev, node, &parts);
 		if (ret < 0)
 			goto err;
 	}
-#endif
 
-	if (ret > 0)
-		add_mtd_partitions(&priv->mtd, parts, ret);
-	else
-#endif
-		add_mtd_device(&priv->mtd);
+	mtd_device_register(&priv->mtd, parts, ret);
 
 	printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
 	       (unsigned long long)res.start, priv->bank);
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 073ee02..23752fd 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -33,10 +33,7 @@
 	struct mtd_info mtd;
 	struct nand_chip chip;
 	int last_ctrl;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *parts;
-#endif
-
 	struct fsl_upm upm;
 	uint8_t upm_addr_offset;
 	uint8_t upm_cmd_offset;
@@ -161,9 +158,7 @@
 {
 	int ret;
 	struct device_node *flash_np;
-#ifdef CONFIG_MTD_PARTITIONS
 	static const char *part_types[] = { "cmdlinepart", NULL, };
-#endif
 
 	fun->chip.IO_ADDR_R = fun->io_base;
 	fun->chip.IO_ADDR_W = fun->io_base;
@@ -197,7 +192,6 @@
 	if (ret)
 		goto err;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
 
 #ifdef CONFIG_MTD_OF_PARTS
@@ -207,11 +201,7 @@
 			goto err;
 	}
 #endif
-	if (ret > 0)
-		ret = add_mtd_partitions(&fun->mtd, fun->parts, ret);
-	else
-#endif
-		ret = add_mtd_device(&fun->mtd);
+	ret = mtd_device_register(&fun->mtd, fun->parts, ret);
 err:
 	of_node_put(flash_np);
 	return ret;
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 0d45ef3..e9b275a 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -120,8 +120,6 @@
 	}
 };
 
-
-#ifdef CONFIG_MTD_PARTITIONS
 /*
  * Default partition tables to be used if the partition information not
  * provided through platform data.
@@ -182,7 +180,6 @@
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
-#endif
 
 /**
  * struct fsmc_nand_data - structure for FSMC NAND device state
@@ -719,7 +716,6 @@
 	 * platform data,
 	 * default partition information present in driver.
 	 */
-#ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 	/*
 	 * Check if partition info passed via command line
@@ -777,19 +773,10 @@
 	}
 #endif
 
-	if (host->partitions) {
-		ret = add_mtd_partitions(&host->mtd, host->partitions,
-				host->nr_partitions);
-		if (ret)
-			goto err_probe;
-	}
-#else
-	dev_info(&pdev->dev, "Registering %s as whole device\n", mtd->name);
-	if (!add_mtd_device(mtd)) {
-		ret = -ENXIO;
+	ret = mtd_device_register(&host->mtd, host->partitions,
+				  host->nr_partitions);
+	if (ret)
 		goto err_probe;
-	}
-#endif
 
 	platform_set_drvdata(pdev, host);
 	dev_info(&pdev->dev, "FSMC NAND driver registration successful\n");
@@ -835,11 +822,7 @@
 	platform_set_drvdata(pdev, NULL);
 
 	if (host) {
-#ifdef CONFIG_MTD_PARTITIONS
-		del_mtd_partitions(&host->mtd);
-#else
-		del_mtd_device(&host->mtd);
-#endif
+		mtd_device_unregister(&host->mtd);
 		clk_disable(host->clk);
 		clk_put(host->clk);
 
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
index 0cde618..2c2060b 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/gpio.c
@@ -316,8 +316,8 @@
 		gpiomtd->plat.adjust_parts(&gpiomtd->plat,
 					   gpiomtd->mtd_info.size);
 
-	add_mtd_partitions(&gpiomtd->mtd_info, gpiomtd->plat.parts,
-			   gpiomtd->plat.num_parts);
+	mtd_device_register(&gpiomtd->mtd_info, gpiomtd->plat.parts,
+			    gpiomtd->plat.num_parts);
 	platform_set_drvdata(dev, gpiomtd);
 
 	return 0;
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index f8ce79b..02a03e6 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -38,7 +38,6 @@
  * Module stuff
  */
 
-#ifdef CONFIG_MTD_PARTITIONS
 /*
  * Define static partitions for flash device
  */
@@ -50,8 +49,6 @@
 
 #define NUM_PARTITIONS 1
 
-#endif
-
 /*
  *	hardware specific access to control-lines
  *
@@ -154,7 +151,7 @@
 
 	/* Register the partitions */
 	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_register(h1910_nand_mtd, mtd_parts, mtd_parts_nb);
 
 	/* Return happy */
 	return 0;
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index cea38a5..6e813da 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -299,10 +299,8 @@
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *partition_info;
 	int num_partitions = 0;
-#endif
 
 	nand = kzalloc(sizeof(*nand), GFP_KERNEL);
 	if (!nand) {
@@ -375,7 +373,6 @@
 		goto err_gpio_free;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 	num_partitions = parse_mtd_partitions(mtd, part_probes,
 						&partition_info, 0);
@@ -384,12 +381,7 @@
 		num_partitions = pdata->num_partitions;
 		partition_info = pdata->partitions;
 	}
-
-	if (num_partitions > 0)
-		ret = add_mtd_partitions(mtd, partition_info, num_partitions);
-	else
-#endif
-	ret = add_mtd_device(mtd);
+	ret = mtd_device_register(mtd, partition_info, num_partitions);
 
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to add mtd device\n");
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 0b81b5b..2f7c930 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -131,9 +131,7 @@
 
 static void mpc5121_nfc_done(struct mtd_info *mtd);
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL };
-#endif
 
 /* Read NFC register */
 static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
@@ -658,9 +656,7 @@
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
 	struct mtd_info *mtd;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *parts;
-#endif
 	struct nand_chip *chip;
 	unsigned long regs_paddr, regs_size;
 	const __be32 *chips_no;
@@ -841,7 +837,6 @@
 	dev_set_drvdata(dev, mtd);
 
 	/* Register device in MTD */
-#ifdef CONFIG_MTD_PARTITIONS
 	retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0);
 #ifdef CONFIG_MTD_OF_PARTS
 	if (retval == 0)
@@ -854,12 +849,7 @@
 		goto error;
 	}
 
-	if (retval > 0)
-		retval = add_mtd_partitions(mtd, parts, retval);
-	else
-#endif
-		retval = add_mtd_device(mtd);
-
+	retval = mtd_device_register(mtd, parts, retval);
 	if (retval) {
 		dev_err(dev, "Error adding MTD device!\n");
 		devm_free_irq(dev, prv->irq, mtd);
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 42a95fb..90df34c 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -56,8 +56,14 @@
 #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_V21_UNLOCKSTART_BLKADDR0	(host->regs + 0x20)
+#define NFC_V21_UNLOCKSTART_BLKADDR1	(host->regs + 0x24)
+#define NFC_V21_UNLOCKSTART_BLKADDR2	(host->regs + 0x28)
+#define NFC_V21_UNLOCKSTART_BLKADDR3	(host->regs + 0x2c)
+#define NFC_V21_UNLOCKEND_BLKADDR0	(host->regs + 0x22)
+#define NFC_V21_UNLOCKEND_BLKADDR1	(host->regs + 0x26)
+#define NFC_V21_UNLOCKEND_BLKADDR2	(host->regs + 0x2a)
+#define NFC_V21_UNLOCKEND_BLKADDR3	(host->regs + 0x2e)
 #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)
@@ -152,6 +158,7 @@
 	int			clk_act;
 	int			irq;
 	int			eccsize;
+	int			active_cs;
 
 	struct completion	op_completion;
 
@@ -236,9 +243,7 @@
 	}
 };
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
-#endif
 
 static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
 {
@@ -445,7 +450,7 @@
 	for (i = 0; i < bufs; i++) {
 
 		/* NANDFC buffer 0 is used for page read/write */
-		writew(i, NFC_V1_V2_BUF_ADDR);
+		writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
 
 		writew(ops, NFC_V1_V2_CONFIG2);
 
@@ -470,7 +475,7 @@
 	struct nand_chip *this = &host->nand;
 
 	/* NANDFC buffer 0 is used for device ID output */
-	writew(0x0, NFC_V1_V2_BUF_ADDR);
+	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
 
 	writew(NFC_ID, NFC_V1_V2_CONFIG2);
 
@@ -505,7 +510,7 @@
 	uint32_t store;
 	uint16_t ret;
 
-	writew(0x0, NFC_V1_V2_BUF_ADDR);
+	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
 
 	/*
 	 * The device status is stored in main_area0. To
@@ -686,24 +691,24 @@
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
 
-	switch (chip) {
-	case -1:
+	if (chip == -1) {
 		/* Disable the NFC clock */
 		if (host->clk_act) {
 			clk_disable(host->clk);
 			host->clk_act = 0;
 		}
-		break;
-	case 0:
-		/* Enable the NFC clock */
-		if (!host->clk_act) {
-			clk_enable(host->clk);
-			host->clk_act = 1;
-		}
-		break;
+		return;
+	}
 
-	default:
-		break;
+	if (!host->clk_act) {
+		/* Enable the NFC clock */
+		clk_enable(host->clk);
+		host->clk_act = 1;
+	}
+
+	if (nfc_is_v21()) {
+		host->active_cs = chip;
+		writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
 	}
 }
 
@@ -834,8 +839,14 @@
 
 	/* Blocks to be unlocked */
 	if (nfc_is_v21()) {
-		writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR);
-		writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR);
+		writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
+		writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
+		writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
+		writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
+		writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
+		writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
+		writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
+		writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
 	} else if (nfc_is_v1()) {
 		writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
 		writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR);
@@ -1200,7 +1211,7 @@
 		irq_control_v1_v2(host, 1);
 
 	/* first scan to find the device and get the page size */
-	if (nand_scan_ident(mtd, 1, NULL)) {
+	if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
 		err = -ENXIO;
 		goto escan;
 	}
@@ -1220,18 +1231,15 @@
 	}
 
 	/* Register the partitions */
-#ifdef CONFIG_MTD_PARTITIONS
 	nr_parts =
 	    parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
 	if (nr_parts > 0)
-		add_mtd_partitions(mtd, host->parts, nr_parts);
+		mtd_device_register(mtd, host->parts, nr_parts);
 	else if (pdata->parts)
-		add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
-	else
-#endif
-	{
+		mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
+	else {
 		pr_info("Registering %s as whole device\n", mtd->name);
-		add_mtd_device(mtd);
+		mtd_device_register(mtd, NULL, 0);
 	}
 
 	platform_set_drvdata(pdev, host);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index c54a4cb..a46e9bb 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -47,10 +47,7 @@
 #include <linux/bitops.h>
 #include <linux/leds.h>
 #include <linux/io.h>
-
-#ifdef CONFIG_MTD_PARTITIONS
 #include <linux/mtd/partitions.h>
-#endif
 
 /* Define default oob placement schemes for large and small page devices */
 static struct nand_ecclayout nand_oob_8 = {
@@ -976,9 +973,6 @@
 	ret = __nand_unlock(mtd, ofs, len, 0);
 
 out:
-	/* de-select the NAND device */
-	chip->select_chip(mtd, -1);
-
 	nand_release_device(mtd);
 
 	return ret;
@@ -1046,9 +1040,6 @@
 	ret = __nand_unlock(mtd, ofs, len, 0x1);
 
 out:
-	/* de-select the NAND device */
-	chip->select_chip(mtd, -1);
-
 	nand_release_device(mtd);
 
 	return ret;
@@ -3112,6 +3103,8 @@
 		chip->chip_shift += 32 - 1;
 	}
 
+	chip->badblockbits = 8;
+
 	/* Set the bad block position */
 	if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16))
 		chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
@@ -3539,12 +3532,7 @@
 	if (chip->ecc.mode == NAND_ECC_SOFT_BCH)
 		nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
 
-#ifdef CONFIG_MTD_PARTITIONS
-	/* Deregister partitions */
-	del_mtd_partitions(mtd);
-#endif
-	/* Deregister the device */
-	del_mtd_device(mtd);
+	mtd_device_unregister(mtd);
 
 	/* Free bad block table memory */
 	kfree(chip->bbt);
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index af46428..ccbeaa1 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1276,20 +1276,6 @@
  * while scanning a device for factory marked good / bad blocks. */
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
 
-static struct nand_bbt_descr smallpage_flashbased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = NAND_SMALL_BADBLOCK_POS,
-	.len = 1,
-	.pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr largepage_flashbased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = NAND_LARGE_BADBLOCK_POS,
-	.len = 2,
-	.pattern = scan_ff_pattern
-};
-
 static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
 
 static struct nand_bbt_descr agand_flashbased = {
@@ -1355,10 +1341,6 @@
  * 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)
 {
@@ -1422,15 +1404,14 @@
 				this->bbt_md = &bbt_mirror_descr;
 			}
 		}
-		if (!this->badblock_pattern) {
-			this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased;
-		}
 	} else {
 		this->bbt_td = NULL;
 		this->bbt_md = NULL;
-		if (!this->badblock_pattern)
-			nand_create_default_bbt_descr(this);
 	}
+
+	if (!this->badblock_pattern)
+		nand_create_default_bbt_descr(this);
+
 	return nand_scan_bbt(mtd, this->badblock_pattern);
 }
 
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 893d95b..357e8c5 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -2383,7 +2383,9 @@
 		goto err_exit;
 
 	/* Register NAND partitions */
-	if ((retval = add_mtd_partitions(nsmtd, &nand->partitions[0], nand->nbparts)) != 0)
+	retval = mtd_device_register(nsmtd, &nand->partitions[0],
+				     nand->nbparts);
+	if (retval != 0)
 		goto err_exit;
 
         return 0;
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index bbe6d45..ea2dea8 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -33,6 +33,7 @@
 #include <linux/of_platform.h>
 #include <asm/io.h>
 
+#define NDFC_MAX_CS    4
 
 struct ndfc_controller {
 	struct platform_device *ofdev;
@@ -41,17 +42,16 @@
 	struct nand_chip chip;
 	int chip_select;
 	struct nand_hw_control ndfc_control;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *parts;
-#endif
 };
 
-static struct ndfc_controller ndfc_ctrl;
+static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
 
 static void ndfc_select_chip(struct mtd_info *mtd, int chip)
 {
 	uint32_t ccr;
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *nchip = mtd->priv;
+	struct ndfc_controller *ndfc = nchip->priv;
 
 	ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
 	if (chip >= 0) {
@@ -64,7 +64,8 @@
 
 static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 
 	if (cmd == NAND_CMD_NONE)
 		return;
@@ -77,7 +78,8 @@
 
 static int ndfc_ready(struct mtd_info *mtd)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 
 	return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
 }
@@ -85,7 +87,8 @@
 static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
 {
 	uint32_t ccr;
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 
 	ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
 	ccr |= NDFC_CCR_RESET_ECC;
@@ -96,7 +99,8 @@
 static int ndfc_calculate_ecc(struct mtd_info *mtd,
 			      const u_char *dat, u_char *ecc_code)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 	uint32_t ecc;
 	uint8_t *p = (uint8_t *)&ecc;
 
@@ -119,7 +123,8 @@
  */
 static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 	uint32_t *p = (uint32_t *) buf;
 
 	for(;len > 0; len -= 4)
@@ -128,7 +133,8 @@
 
 static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 	uint32_t *p = (uint32_t *) buf;
 
 	for(;len > 0; len -= 4)
@@ -137,7 +143,8 @@
 
 static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = mtd->priv;
+	struct ndfc_controller *ndfc = chip->priv;
 	uint32_t *p = (uint32_t *) buf;
 
 	for(;len > 0; len -= 4)
@@ -152,13 +159,11 @@
 static int ndfc_chip_init(struct ndfc_controller *ndfc,
 			  struct device_node *node)
 {
-#ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 	static const char *part_types[] = { "cmdlinepart", NULL };
 #else
 	static const char *part_types[] = { NULL };
 #endif
-#endif
 	struct device_node *flash_np;
 	struct nand_chip *chip = &ndfc->chip;
 	int ret;
@@ -179,6 +184,7 @@
 	chip->ecc.mode = NAND_ECC_HW;
 	chip->ecc.size = 256;
 	chip->ecc.bytes = 3;
+	chip->priv = ndfc;
 
 	ndfc->mtd.priv = chip;
 	ndfc->mtd.owner = THIS_MODULE;
@@ -198,25 +204,18 @@
 	if (ret)
 		goto err;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0);
 	if (ret < 0)
 		goto err;
 
-#ifdef CONFIG_MTD_OF_PARTS
 	if (ret == 0) {
 		ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
 					      &ndfc->parts);
 		if (ret < 0)
 			goto err;
 	}
-#endif
 
-	if (ret > 0)
-		ret = add_mtd_partitions(&ndfc->mtd, ndfc->parts, ret);
-	else
-#endif
-		ret = add_mtd_device(&ndfc->mtd);
+	ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
 
 err:
 	of_node_put(flash_np);
@@ -227,15 +226,10 @@
 
 static int __devinit ndfc_probe(struct platform_device *ofdev)
 {
-	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct ndfc_controller *ndfc;
 	const __be32 *reg;
 	u32 ccr;
-	int err, len;
-
-	spin_lock_init(&ndfc->ndfc_control.lock);
-	init_waitqueue_head(&ndfc->ndfc_control.wq);
-	ndfc->ofdev = ofdev;
-	dev_set_drvdata(&ofdev->dev, ndfc);
+	int err, len, cs;
 
 	/* Read the reg property to get the chip select */
 	reg = of_get_property(ofdev->dev.of_node, "reg", &len);
@@ -243,7 +237,20 @@
 		dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
 		return -ENOENT;
 	}
-	ndfc->chip_select = be32_to_cpu(reg[0]);
+
+	cs = be32_to_cpu(reg[0]);
+	if (cs >= NDFC_MAX_CS) {
+		dev_err(&ofdev->dev, "invalid CS number (%d)\n", cs);
+		return -EINVAL;
+	}
+
+	ndfc = &ndfc_ctrl[cs];
+	ndfc->chip_select = cs;
+
+	spin_lock_init(&ndfc->ndfc_control.lock);
+	init_waitqueue_head(&ndfc->ndfc_control.wq);
+	ndfc->ofdev = ofdev;
+	dev_set_drvdata(&ofdev->dev, ndfc);
 
 	ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0);
 	if (!ndfc->ndfcbase) {
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c
index a045a4a..b6a5c86 100644
--- a/drivers/mtd/nand/nomadik_nand.c
+++ b/drivers/mtd/nand/nomadik_nand.c
@@ -158,12 +158,7 @@
 		goto err_unmap;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
-	add_mtd_partitions(&host->mtd, pdata->parts, pdata->nparts);
-#else
-	pr_info("Registering %s as whole device\n", mtd->name);
-	add_mtd_device(mtd);
-#endif
+	mtd_device_register(&host->mtd, pdata->parts, pdata->nparts);
 
 	platform_set_drvdata(pdev, host);
 	return 0;
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
index 6eddf73..9c30a0b 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/nuc900_nand.c
@@ -321,8 +321,8 @@
 		goto fail3;
 	}
 
-	add_mtd_partitions(&(nuc900_nand->mtd), partitions,
-						ARRAY_SIZE(partitions));
+	mtd_device_register(&(nuc900_nand->mtd), partitions,
+			    ARRAY_SIZE(partitions));
 
 	platform_set_drvdata(pdev, nuc900_nand);
 
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index da9a351..0db2c0e 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -94,9 +94,7 @@
 #define P4e_s(a)	(TF(a & NAND_Ecc_P4e)		<< 0)
 #define P4o_s(a)	(TF(a & NAND_Ecc_P4o)		<< 1)
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /* oob info generated runtime depending on ecc algorithm and layout selected */
 static struct nand_ecclayout omap_oobinfo;
@@ -263,11 +261,10 @@
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
-			omap_read_buf16(mtd, buf, len);
+			omap_read_buf16(mtd, (u_char *)p, len);
 		else
-			omap_read_buf8(mtd, buf, len);
+			omap_read_buf8(mtd, (u_char *)p, len);
 	} else {
-		p = (u32 *) buf;
 		do {
 			r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
 			r_count = r_count >> 2;
@@ -293,7 +290,7 @@
 						struct omap_nand_info, mtd);
 	uint32_t w_count = 0;
 	int i = 0, ret = 0;
-	u16 *p;
+	u16 *p = (u16 *)buf;
 	unsigned long tim, limit;
 
 	/* take care of subpage writes */
@@ -309,11 +306,10 @@
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
-			omap_write_buf16(mtd, buf, len);
+			omap_write_buf16(mtd, (u_char *)p, len);
 		else
-			omap_write_buf8(mtd, buf, len);
+			omap_write_buf8(mtd, (u_char *)p, len);
 	} else {
-		p = (u16 *) buf;
 		while (len) {
 			w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
 			w_count = w_count >> 1;
@@ -1073,9 +1069,9 @@
 	/* DIP switches on some boards change between 8 and 16 bit
 	 * bus widths for flash.  Try the other width if the first try fails.
 	 */
-	if (nand_scan(&info->mtd, 1)) {
+	if (nand_scan_ident(&info->mtd, 1, NULL)) {
 		info->nand.options ^= NAND_BUSWIDTH_16;
-		if (nand_scan(&info->mtd, 1)) {
+		if (nand_scan_ident(&info->mtd, 1, NULL)) {
 			err = -ENXIO;
 			goto out_release_mem_region;
 		}
@@ -1101,15 +1097,19 @@
 		info->nand.ecc.layout = &omap_oobinfo;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
+	/* second phase scan */
+	if (nand_scan_tail(&info->mtd)) {
+		err = -ENXIO;
+		goto out_release_mem_region;
+	}
+
 	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
 	if (err > 0)
-		add_mtd_partitions(&info->mtd, info->parts, err);
+		mtd_device_register(&info->mtd, info->parts, err);
 	else if (pdata->parts)
-		add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
+		mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
 	else
-#endif
-		add_mtd_device(&info->mtd);
+		mtd_device_register(&info->mtd, NULL, 0);
 
 	platform_set_drvdata(pdev, &info->mtd);
 
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index da6e753..7794d06 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -21,9 +21,7 @@
 #include <mach/hardware.h>
 #include <plat/orion_nand.h>
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
@@ -83,10 +81,8 @@
 	struct resource *res;
 	void __iomem *io_base;
 	int ret = 0;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *partitions = NULL;
 	int num_part = 0;
-#endif
 
 	nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL);
 	if (!nc) {
@@ -136,7 +132,6 @@
 		goto no_dev;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 	mtd->name = "orion_nand";
 	num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0);
@@ -147,14 +142,7 @@
 		partitions = board->parts;
 	}
 
-	if (partitions && num_part > 0)
-		ret = add_mtd_partitions(mtd, partitions, num_part);
-	else
-		ret = add_mtd_device(mtd);
-#else
-	ret = add_mtd_device(mtd);
-#endif
-
+	ret = mtd_device_register(mtd, partitions, num_part);
 	if (ret) {
 		nand_release(mtd);
 		goto no_dev;
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 20bfe5f..b1aa41b 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -163,7 +163,7 @@
 		goto out_lpc;
 	}
 
-	if (add_mtd_device(pasemi_nand_mtd)) {
+	if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) {
 		printk(KERN_ERR "pasemi_nand: Unable to register MTD device\n");
 		err = -ENODEV;
 		goto out_lpc;
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index caf5a73..633c04b 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -21,10 +21,8 @@
 	struct nand_chip	chip;
 	struct mtd_info		mtd;
 	void __iomem		*io_base;
-#ifdef CONFIG_MTD_PARTITIONS
 	int			nr_parts;
 	struct mtd_partition	*parts;
-#endif
 };
 
 /*
@@ -101,13 +99,12 @@
 		goto out;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 	if (pdata->chip.part_probe_types) {
 		err = parse_mtd_partitions(&data->mtd,
 					pdata->chip.part_probe_types,
 					&data->parts, 0);
 		if (err > 0) {
-			add_mtd_partitions(&data->mtd, data->parts, err);
+			mtd_device_register(&data->mtd, data->parts, err);
 			return 0;
 		}
 	}
@@ -115,11 +112,10 @@
 		pdata->chip.set_parts(data->mtd.size, &pdata->chip);
 	if (pdata->chip.partitions) {
 		data->parts = pdata->chip.partitions;
-		err = add_mtd_partitions(&data->mtd, data->parts,
+		err = mtd_device_register(&data->mtd, data->parts,
 			pdata->chip.nr_partitions);
 	} else
-#endif
-	err = add_mtd_device(&data->mtd);
+		err = mtd_device_register(&data->mtd, NULL, 0);
 
 	if (!err)
 		return err;
@@ -149,10 +145,8 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	nand_release(&data->mtd);
-#ifdef CONFIG_MTD_PARTITIONS
 	if (data->parts && data->parts != pdata->chip.partitions)
 		kfree(data->parts);
-#endif
 	if (pdata->ctrl.remove)
 		pdata->ctrl.remove(pdev);
 	iounmap(data->io_base);
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index cc86584..3bbb796 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -73,7 +73,6 @@
 __setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase);
 #endif
 
-#ifdef CONFIG_MTD_PARTITIONS
 /*
  * Define static partitions for flash devices
  */
@@ -101,7 +100,6 @@
 #define NUM_PARTITIONS 1
 
 extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id);
-#endif
 
 /*
  *	hardware specific access to control-lines
@@ -189,10 +187,8 @@
 }
 #endif
 
-#ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
 const char *part_probes_evb[] = { "cmdlinepart", NULL };
-#endif
 
 /*
  * Main initialization routine
@@ -284,14 +280,13 @@
 		this->chip_delay = NAND_SMALL_DELAY_US;
 #endif
 
-#ifdef CONFIG_MTD_PARTITIONS
 	ppchameleon_mtd->name = "ppchameleon-nand";
 	mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 		part_type = "command line";
 	else
 		mtd_parts_nb = 0;
-#endif
+
 	if (mtd_parts_nb == 0) {
 		if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
 			mtd_parts = partition_info_me;
@@ -303,7 +298,7 @@
 
 	/* Register the partitions */
 	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_register(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
 
  nand_evb_init:
 	/****************************
@@ -385,14 +380,14 @@
 			iounmap(ppchameleon_fio_base);
 		return -ENXIO;
 	}
-#ifdef CONFIG_MTD_PARTITIONS
+
 	ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
 	mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 		part_type = "command line";
 	else
 		mtd_parts_nb = 0;
-#endif
+
 	if (mtd_parts_nb == 0) {
 		mtd_parts = partition_info_evb;
 		mtd_parts_nb = NUM_PARTITIONS;
@@ -401,7 +396,7 @@
 
 	/* Register the partitions */
 	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	add_mtd_partitions(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_register(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb);
 
 	/* Return happy */
 	return 0;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index ff07012..1fb3b3a 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1119,10 +1119,7 @@
 	clk_put(info->clk);
 
 	if (mtd) {
-		del_mtd_device(mtd);
-#ifdef CONFIG_MTD_PARTITIONS
-		del_mtd_partitions(mtd);
-#endif
+		mtd_device_unregister(mtd);
 		kfree(mtd);
 	}
 	return 0;
@@ -1149,7 +1146,6 @@
 		return -ENODEV;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 	if (mtd_has_cmdlinepart()) {
 		const char *probes[] = { "cmdlinepart", NULL };
 		struct mtd_partition *parts;
@@ -1158,13 +1154,10 @@
 		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
 
 		if (nr_parts)
-			return add_mtd_partitions(info->mtd, parts, nr_parts);
+			return mtd_device_register(info->mtd, parts, nr_parts);
 	}
 
-	return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
-#else
-	return 0;
-#endif
+	return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index 67440b5..c9f9127 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -580,7 +580,8 @@
 #endif
 
 	/* Register the partitions */
-	ret = add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
+	ret = mtd_device_register(rtc_from4_mtd, partition_info,
+				  NUM_PARTITIONS);
 	if (ret)
 		goto err_3;
 
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 33d832d..4405468 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -55,7 +55,7 @@
 #endif
 
 #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
-static int clock_stop = 1;
+static const int clock_stop = 1;
 #else
 static const int clock_stop = 0;
 #endif
@@ -96,6 +96,12 @@
 	TYPE_S3C2440,
 };
 
+enum s3c_nand_clk_state {
+	CLOCK_DISABLE	= 0,
+	CLOCK_ENABLE,
+	CLOCK_SUSPEND,
+};
+
 /* overview of the s3c2410 nand state */
 
 /**
@@ -111,6 +117,7 @@
  * @mtd_count: The number of MTDs created from this controller.
  * @save_sel: The contents of @sel_reg to be saved over suspend.
  * @clk_rate: The clock rate from @clk.
+ * @clk_state: The current clock state.
  * @cpu_type: The exact type of this controller.
  */
 struct s3c2410_nand_info {
@@ -129,6 +136,7 @@
 	int				mtd_count;
 	unsigned long			save_sel;
 	unsigned long			clk_rate;
+	enum s3c_nand_clk_state		clk_state;
 
 	enum s3c_cpu_type		cpu_type;
 
@@ -159,11 +167,33 @@
 	return dev->dev.platform_data;
 }
 
-static inline int allow_clk_stop(struct s3c2410_nand_info *info)
+static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
 {
 	return clock_stop;
 }
 
+/**
+ * s3c2410_nand_clk_set_state - Enable, disable or suspend NAND clock.
+ * @info: The controller instance.
+ * @new_state: State to which clock should be set.
+ */
+static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
+		enum s3c_nand_clk_state new_state)
+{
+	if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND)
+		return;
+
+	if (info->clk_state == CLOCK_ENABLE) {
+		if (new_state != CLOCK_ENABLE)
+			clk_disable(info->clk);
+	} else {
+		if (new_state == CLOCK_ENABLE)
+			clk_enable(info->clk);
+	}
+
+	info->clk_state = new_state;
+}
+
 /* timing calculations */
 
 #define NS_IN_KHZ 1000000
@@ -333,8 +363,8 @@
 	nmtd = this->priv;
 	info = nmtd->info;
 
-	if (chip != -1 && allow_clk_stop(info))
-		clk_enable(info->clk);
+	if (chip != -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 
 	cur = readl(info->sel_reg);
 
@@ -356,8 +386,8 @@
 
 	writel(cur, info->sel_reg);
 
-	if (chip == -1 && allow_clk_stop(info))
-		clk_disable(info->clk);
+	if (chip == -1)
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 }
 
 /* s3c2410_nand_hwcontrol
@@ -694,8 +724,7 @@
 	/* free the common resources */
 
 	if (info->clk != NULL && !IS_ERR(info->clk)) {
-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
 		clk_put(info->clk);
 	}
 
@@ -715,7 +744,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 				      struct s3c2410_nand_mtd *mtd,
@@ -725,7 +753,7 @@
 	int nr_part = 0;
 
 	if (set == NULL)
-		return add_mtd_device(&mtd->mtd);
+		return mtd_device_register(&mtd->mtd, NULL, 0);
 
 	mtd->mtd.name = set->name;
 	nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0);
@@ -735,19 +763,8 @@
 		part_info = set->partitions;
 	}
 
-	if (nr_part > 0 && part_info)
-		return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
-
-	return add_mtd_device(&mtd->mtd);
+	return mtd_device_register(&mtd->mtd, part_info, nr_part);
 }
-#else
-static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
-				      struct s3c2410_nand_mtd *mtd,
-				      struct s3c2410_nand_set *set)
-{
-	return add_mtd_device(&mtd->mtd);
-}
-#endif
 
 /**
  * s3c2410_nand_init_chip - initialise a single instance of an chip
@@ -947,7 +964,7 @@
 		goto exit_error;
 	}
 
-	clk_enable(info->clk);
+	s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 
 	/* allocate and map the resource */
 
@@ -1026,9 +1043,9 @@
 		goto exit_error;
 	}
 
-	if (allow_clk_stop(info)) {
+	if (allow_clk_suspend(info)) {
 		dev_info(&pdev->dev, "clock idle support enabled\n");
-		clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 	}
 
 	pr_debug("initialised ok\n");
@@ -1059,8 +1076,7 @@
 
 		writel(info->save_sel | info->sel_bit, info->sel_reg);
 
-		if (!allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
 	}
 
 	return 0;
@@ -1072,7 +1088,7 @@
 	unsigned long sel;
 
 	if (info) {
-		clk_enable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 		s3c2410_nand_inithw(info);
 
 		/* Restore the state of the nFCE line. */
@@ -1082,8 +1098,7 @@
 		sel |= info->save_sel & info->sel_bit;
 		writel(sel, info->sel_reg);
 
-		if (allow_clk_stop(info))
-			clk_disable(info->clk);
+		s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
 	}
 
 	return 0;
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 81bbb5e..93b1f74 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -867,7 +867,7 @@
 	if (ret)
 		goto err;
 
-	add_mtd_partitions(flctl_mtd, pdata->parts, pdata->nr_parts);
+	mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts);
 
 	return 0;
 
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 54ec754..19e24ed 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -103,9 +103,7 @@
 	return readb(sharpsl->io + ECCCNTR) != 0;
 }
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /*
  * Main initialization routine
@@ -113,10 +111,8 @@
 static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
 {
 	struct nand_chip *this;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *sharpsl_partition_info;
 	int nr_partitions;
-#endif
 	struct resource *r;
 	int err = 0;
 	struct sharpsl_nand *sharpsl;
@@ -188,18 +184,14 @@
 
 	/* Register the partitions */
 	sharpsl->mtd.name = "sharpsl-nand";
-#ifdef CONFIG_MTD_PARTITIONS
 	nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0);
 	if (nr_partitions <= 0) {
 		nr_partitions = data->nr_partitions;
 		sharpsl_partition_info = data->partitions;
 	}
 
-	if (nr_partitions > 0)
-		err = add_mtd_partitions(&sharpsl->mtd, sharpsl_partition_info, nr_partitions);
-	else
-#endif
-	err = add_mtd_device(&sharpsl->mtd);
+	err = mtd_device_register(&sharpsl->mtd, sharpsl_partition_info,
+				  nr_partitions);
 	if (err)
 		goto err_add;
 
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c
index 57cc80c..b6332e8 100644
--- a/drivers/mtd/nand/sm_common.c
+++ b/drivers/mtd/nand/sm_common.c
@@ -139,7 +139,7 @@
 	if (ret)
 		return ret;
 
-	return add_mtd_device(mtd);
+	return mtd_device_register(mtd, NULL, 0);
 }
 EXPORT_SYMBOL_GPL(sm_register_device);
 
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index a853548..ca2d055 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -155,9 +155,7 @@
 	return 1;
 }
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /*
  * Probe for the NAND device.
@@ -168,11 +166,8 @@
 	struct mtd_info *mtd;
 	struct nand_chip *nand_chip;
 	int res;
-
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *partitions = NULL;
 	int num_partitions = 0;
-#endif
 
 	/* Allocate memory for the device structure (and zero it) */
 	host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL);
@@ -230,7 +225,6 @@
 		goto out;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 	num_partitions = parse_mtd_partitions(mtd, part_probes,
 					      &partitions, 0);
@@ -240,7 +234,6 @@
 	}
 #endif
 
-#ifdef CONFIG_MTD_OF_PARTS
 	if (num_partitions == 0) {
 		num_partitions = of_mtd_parse_partitions(&ofdev->dev,
 							 ofdev->dev.of_node,
@@ -250,19 +243,12 @@
 			goto release;
 		}
 	}
-#endif
-	if (partitions && (num_partitions > 0))
-		res = add_mtd_partitions(mtd, partitions, num_partitions);
-	else
-#endif
-		res = add_mtd_device(mtd);
 
+	res = mtd_device_register(mtd, partitions, num_partitions);
 	if (!res)
 		return res;
 
-#ifdef CONFIG_MTD_PARTITIONS
 release:
-#endif
 	nand_release(mtd);
 
 out:
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
index 0cc6d0a..bef76cd 100644
--- a/drivers/mtd/nand/spia.c
+++ b/drivers/mtd/nand/spia.c
@@ -149,7 +149,7 @@
 	}
 
 	/* Register the partitions */
-	add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS);
+	mtd_device_register(spia_mtd, partition_info, NUM_PARTITIONS);
 
 	/* Return happy */
 	return 0;
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index c004e47..11e8371 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -381,10 +381,8 @@
 	struct tmio_nand *tmio;
 	struct mtd_info *mtd;
 	struct nand_chip *nand_chip;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *parts;
 	int nbparts = 0;
-#endif
 	int retval;
 
 	if (data == NULL)
@@ -463,7 +461,6 @@
 		goto err_scan;
 	}
 	/* Register the partitions */
-#ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_CMDLINE_PARTS
 	nbparts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
 #endif
@@ -472,12 +469,7 @@
 		nbparts = data->num_partitions;
 	}
 
-	if (nbparts)
-		retval = add_mtd_partitions(mtd, parts, nbparts);
-	else
-#endif
-	retval = add_mtd_device(mtd);
-
+	retval = mtd_device_register(mtd, parts, nbparts);
 	if (!retval)
 		return retval;
 
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index ca270a4..bfba4e3 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -74,9 +74,7 @@
 	unsigned char hold;	/* in gbusclock */
 	unsigned char spw;	/* in gbusclock */
 	struct nand_hw_control hw_control;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *parts[MAX_TXX9NDFMC_DEV];
-#endif
 };
 
 static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
@@ -289,9 +287,7 @@
 static int __init txx9ndfmc_probe(struct platform_device *dev)
 {
 	struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
-#ifdef CONFIG_MTD_PARTITIONS
 	static const char *probes[] = { "cmdlinepart", NULL };
-#endif
 	int hold, spw;
 	int i;
 	struct txx9ndfmc_drvdata *drvdata;
@@ -337,9 +333,7 @@
 		struct txx9ndfmc_priv *txx9_priv;
 		struct nand_chip *chip;
 		struct mtd_info *mtd;
-#ifdef CONFIG_MTD_PARTITIONS
 		int nr_parts;
-#endif
 
 		if (!(plat->ch_mask & (1 << i)))
 			continue;
@@ -399,13 +393,9 @@
 		}
 		mtd->name = txx9_priv->mtdname;
 
-#ifdef CONFIG_MTD_PARTITIONS
 		nr_parts = parse_mtd_partitions(mtd, probes,
 						&drvdata->parts[i], 0);
-		if (nr_parts > 0)
-			add_mtd_partitions(mtd, drvdata->parts[i], nr_parts);
-#endif
-		add_mtd_device(mtd);
+		mtd_device_register(mtd, drvdata->parts[i], nr_parts);
 		drvdata->mtds[i] = mtd;
 	}
 
@@ -431,9 +421,7 @@
 		txx9_priv = chip->priv;
 
 		nand_release(mtd);
-#ifdef CONFIG_MTD_PARTITIONS
 		kfree(drvdata->parts[i]);
-#endif
 		kfree(txx9_priv->mtdname);
 		kfree(txx9_priv);
 	}
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 4f42619..772ad29 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -1,7 +1,6 @@
 menuconfig MTD_ONENAND
 	tristate "OneNAND Device Support"
 	depends on MTD
-	select MTD_PARTITIONS
 	help
 	  This enables support for accessing all type of OneNAND flash
 	  devices. For further information see
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index ac08750..2d70d35 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -30,9 +30,7 @@
  */
 #define DRIVER_NAME	"onenand-flash"
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL,  };
-#endif
 
 struct onenand_info {
 	struct mtd_info		mtd;
@@ -75,15 +73,13 @@
 		goto out_iounmap;
 	}
 
-#ifdef CONFIG_MTD_PARTITIONS
 	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
 	if (err > 0)
-		add_mtd_partitions(&info->mtd, info->parts, err);
+		mtd_device_register(&info->mtd, info->parts, err);
 	else if (err <= 0 && pdata && pdata->parts)
-		add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
+		mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
 	else
-#endif
-		err = add_mtd_device(&info->mtd);
+		err = mtd_device_register(&info->mtd, NULL, 0);
 
 	platform_set_drvdata(pdev, info);
 
@@ -108,11 +104,7 @@
 	platform_set_drvdata(pdev, NULL);
 
 	if (info) {
-		if (info->parts)
-			del_mtd_partitions(&info->mtd);
-		else
-			del_mtd_device(&info->mtd);
-
+		mtd_device_unregister(&info->mtd);
 		onenand_release(&info->mtd);
 		release_mem_region(res->start, size);
 		iounmap(info->onenand.base);
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 1fcb41a..a916dec 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -67,9 +67,7 @@
 	struct regulator *regulator;
 };
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL,  };
-#endif
 
 static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 {
@@ -755,15 +753,13 @@
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
 		goto err_release_regulator;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
 	if (r > 0)
-		r = add_mtd_partitions(&c->mtd, c->parts, r);
+		r = mtd_device_register(&c->mtd, c->parts, r);
 	else if (pdata->parts != NULL)
-		r = add_mtd_partitions(&c->mtd, pdata->parts, pdata->nr_parts);
+		r = mtd_device_register(&c->mtd, pdata->parts, pdata->nr_parts);
 	else
-#endif
-		r = add_mtd_device(&c->mtd);
+		r = mtd_device_register(&c->mtd, NULL, 0);
 	if (r)
 		goto err_release_onenand;
 
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 56a8b20..ac9e959 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -65,11 +65,11 @@
 			"	   : 2 -> 1st Block lock"
 			"	   : 3 -> BOTH OTP Block and 1st Block lock");
 
-/**
- *  onenand_oob_128 - oob info for Flex-Onenand with 4KB page
- *  For now, we expose only 64 out of 80 ecc bytes
+/*
+ * flexonenand_oob_128 - oob info for Flex-Onenand with 4KB page
+ * For now, we expose only 64 out of 80 ecc bytes
  */
-static struct nand_ecclayout onenand_oob_128 = {
+static struct nand_ecclayout flexonenand_oob_128 = {
 	.eccbytes	= 64,
 	.eccpos		= {
 		6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
@@ -86,6 +86,35 @@
 	}
 };
 
+/*
+ * onenand_oob_128 - oob info for OneNAND with 4KB page
+ *
+ * Based on specification:
+ * 4Gb M-die OneNAND Flash (KFM4G16Q4M, KFN8G16Q4M). Rev. 1.3, Apr. 2010
+ *
+ * For eccpos we expose only 64 bytes out of 72 (see struct nand_ecclayout)
+ *
+ * oobfree uses the spare area fields marked as
+ * "Managed by internal ECC logic for Logical Sector Number area"
+ */
+static struct nand_ecclayout onenand_oob_128 = {
+	.eccbytes	= 64,
+	.eccpos		= {
+		7, 8, 9, 10, 11, 12, 13, 14, 15,
+		23, 24, 25, 26, 27, 28, 29, 30, 31,
+		39, 40, 41, 42, 43, 44, 45, 46, 47,
+		55, 56, 57, 58, 59, 60, 61, 62, 63,
+		71, 72, 73, 74, 75, 76, 77, 78, 79,
+		87, 88, 89, 90, 91, 92, 93, 94, 95,
+		103, 104, 105, 106, 107, 108, 109, 110, 111,
+		119
+	},
+	.oobfree	= {
+		{2, 3}, {18, 3}, {34, 3}, {50, 3},
+		{66, 3}, {82, 3}, {98, 3}, {114, 3}
+	}
+};
+
 /**
  * onenand_oob_64 - oob info for large (2KB) page
  */
@@ -2424,7 +2453,7 @@
 		len -= block_size;
 		addr += block_size;
 
-		if (addr == region_end) {
+		if (region && addr == region_end) {
 			if (!len)
 				break;
 			region++;
@@ -4018,8 +4047,13 @@
 	 */
 	switch (mtd->oobsize) {
 	case 128:
-		this->ecclayout = &onenand_oob_128;
-		mtd->subpage_sft = 0;
+		if (FLEXONENAND(this)) {
+			this->ecclayout = &flexonenand_oob_128;
+			mtd->subpage_sft = 0;
+		} else {
+			this->ecclayout = &onenand_oob_128;
+			mtd->subpage_sft = 2;
+		}
 		break;
 	case 64:
 		this->ecclayout = &onenand_oob_64;
@@ -4108,12 +4142,8 @@
 {
 	struct onenand_chip *this = mtd->priv;
 
-#ifdef CONFIG_MTD_PARTITIONS
 	/* Deregister partitions */
-	del_mtd_partitions (mtd);
-#endif
-	/* Deregister the device */
-	del_mtd_device (mtd);
+	mtd_device_unregister(mtd);
 
 	/* Free bad block table memory, if allocated */
 	if (this->bbm) {
diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c
index 5ef3bd5..85399e3 100644
--- a/drivers/mtd/onenand/onenand_sim.c
+++ b/drivers/mtd/onenand/onenand_sim.c
@@ -539,7 +539,8 @@
 		return -ENXIO;
 	}
 
-	add_mtd_partitions(&info->mtd, info->parts, ARRAY_SIZE(os_partitions));
+	mtd_device_register(&info->mtd, info->parts,
+			    ARRAY_SIZE(os_partitions));
 
 	return 0;
 }
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index a4c74a9..3306b5b 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -147,9 +147,7 @@
 	struct resource *dma_res;
 	unsigned long	phys_base;
 	struct completion	complete;
-#ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition *parts;
-#endif
 };
 
 #define CMD_MAP_00(dev, addr)		(dev->cmd_map(MAP_00, ((addr) << 1)))
@@ -159,9 +157,7 @@
 
 static struct s3c_onenand *onenand;
 
-#ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "cmdlinepart", NULL, };
-#endif
 
 static inline int s3c_read_reg(int offset)
 {
@@ -1021,15 +1017,13 @@
 	if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
 		dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
 
-#ifdef CONFIG_MTD_PARTITIONS
 	err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0);
 	if (err > 0)
-		add_mtd_partitions(mtd, onenand->parts, err);
+		mtd_device_register(mtd, onenand->parts, err);
 	else if (err <= 0 && pdata && pdata->parts)
-		add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
+		mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
 	else
-#endif
-		err = add_mtd_device(mtd);
+		err = mtd_device_register(mtd, NULL, 0);
 
 	platform_set_drvdata(pdev, mtd);
 
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index 9aa8158..941bc3c 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -365,7 +365,7 @@
 			vi->vol_id);
 	mutex_unlock(&devices_mutex);
 
-	if (add_mtd_device(mtd)) {
+	if (mtd_device_register(mtd, NULL, 0)) {
 		err_msg("cannot add MTD device");
 		kfree(mtd->name);
 		kfree(gluebi);
@@ -407,7 +407,7 @@
 		return err;
 
 	mtd = &gluebi->mtd;
-	err = del_mtd_device(mtd);
+	err = mtd_device_unregister(mtd);
 	if (err) {
 		err_msg("cannot remove fake MTD device %d, UBI device %d, "
 			"volume %d, error %d", mtd->index, gluebi->ubi_num,
@@ -524,7 +524,7 @@
 		int err;
 		struct mtd_info *mtd = &gluebi->mtd;
 
-		err = del_mtd_device(mtd);
+		err = mtd_device_unregister(mtd);
 		if (err)
 			err_msg("error %d while removing gluebi MTD device %d, "
 				"UBI device %d, volume %d - ignoring", err,
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c
index e646bfc..b630448 100644
--- a/drivers/net/sfc/mtd.c
+++ b/drivers/net/sfc/mtd.c
@@ -216,7 +216,7 @@
 	int rc;
 
 	for (;;) {
-		rc = del_mtd_device(&part->mtd);
+		rc = mtd_device_unregister(&part->mtd);
 		if (rc != -EBUSY)
 			break;
 		ssleep(1);
@@ -268,7 +268,7 @@
 		part->mtd.write = efx_mtd->ops->write;
 		part->mtd.sync = efx_mtd_sync;
 
-		if (add_mtd_device(&part->mtd))
+		if (mtd_device_register(&part->mtd, NULL, 0))
 			goto fail;
 	}
 
@@ -280,7 +280,7 @@
 		--part;
 		efx_mtd_remove_partition(part);
 	}
-	/* add_mtd_device() returns 1 if the MTD table is full */
+	/* mtd_device_register() returns 1 if the MTD table is full */
 	return -ENOMEM;
 }
 
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 05f7332..9a1e86f 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -75,7 +75,6 @@
 				   struct nameidata *nd)
 {
 	struct jffs2_inode_info *dir_f;
-	struct jffs2_sb_info *c;
 	struct jffs2_full_dirent *fd = NULL, *fd_list;
 	uint32_t ino = 0;
 	struct inode *inode = NULL;
@@ -86,7 +85,6 @@
 		return ERR_PTR(-ENAMETOOLONG);
 
 	dir_f = JFFS2_INODE_INFO(dir_i);
-	c = JFFS2_SB_INFO(dir_i->i_sb);
 
 	mutex_lock(&dir_f->sem);
 
@@ -119,7 +117,6 @@
 static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
 	struct jffs2_inode_info *f;
-	struct jffs2_sb_info *c;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct jffs2_full_dirent *fd;
 	unsigned long offset, curofs;
@@ -127,7 +124,6 @@
 	D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_path.dentry->d_inode->i_ino));
 
 	f = JFFS2_INODE_INFO(inode);
-	c = JFFS2_SB_INFO(inode->i_sb);
 
 	offset = filp->f_pos;
 
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index b632ddd..8d8cd34 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -94,7 +94,7 @@
 	uint32_t buf_size = 0;
 	struct jffs2_summary *s = NULL; /* summary info collected by the scan process */
 #ifndef __ECOS
-	size_t pointlen;
+	size_t pointlen, try_size;
 
 	if (c->mtd->point) {
 		ret = c->mtd->point(c->mtd, 0, c->mtd->size, &pointlen,
@@ -113,18 +113,21 @@
 		/* For NAND it's quicker to read a whole eraseblock at a time,
 		   apparently */
 		if (jffs2_cleanmarker_oob(c))
-			buf_size = c->sector_size;
+			try_size = c->sector_size;
 		else
-			buf_size = PAGE_SIZE;
+			try_size = PAGE_SIZE;
 
-		/* Respect kmalloc limitations */
-		if (buf_size > 128*1024)
-			buf_size = 128*1024;
+		D1(printk(KERN_DEBUG "Trying to allocate readbuf of %zu "
+			"bytes\n", try_size));
 
-		D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size));
-		flashbuf = kmalloc(buf_size, GFP_KERNEL);
+		flashbuf = mtd_kmalloc_up_to(c->mtd, &try_size);
 		if (!flashbuf)
 			return -ENOMEM;
+
+		D1(printk(KERN_DEBUG "Allocated readbuf of %zu bytes\n",
+			try_size));
+
+		buf_size = (uint32_t)try_size;
 	}
 
 	if (jffs2_sum_active()) {
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 9d5306b..2541fb8 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -322,9 +322,12 @@
 
 	/* Kernel-side ioctl definitions */
 
-extern int add_mtd_device(struct mtd_info *mtd);
-extern int del_mtd_device (struct mtd_info *mtd);
+struct mtd_partition;
 
+extern int mtd_device_register(struct mtd_info *master,
+			       const struct mtd_partition *parts,
+			       int nr_parts);
+extern int mtd_device_unregister(struct mtd_info *master);
 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 extern int __get_mtd_device(struct mtd_info *mtd);
 extern void __put_mtd_device(struct mtd_info *mtd);
@@ -348,15 +351,9 @@
 int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
 		      unsigned long count, loff_t from, size_t *retlen);
 
-#ifdef CONFIG_MTD_PARTITIONS
+void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
+
 void mtd_erase_callback(struct erase_info *instr);
-#else
-static inline void mtd_erase_callback(struct erase_info *instr)
-{
-	if (instr->callback)
-		instr->callback(instr);
-}
-#endif
 
 /*
  * Debugging macro and defines
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index d441927..c2b9ac4 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -237,9 +237,9 @@
  * If passed additionally to NAND_USE_FLASH_BBT then BBT code will not touch
  * the OOB area.
  */
-#define NAND_USE_FLASH_BBT_NO_OOB	0x00100000
+#define NAND_USE_FLASH_BBT_NO_OOB	0x00800000
 /* Create an empty BBT with no vendor information if the BBT is available */
-#define NAND_CREATE_EMPTY_BBT		0x00200000
+#define NAND_CREATE_EMPTY_BBT		0x01000000
 
 /* Options set by nand scan */
 /* Nand scan has allocated controller struct */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 4a0a8ba..3a6f037 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -16,7 +16,7 @@
  * Partition definition structure:
  *
  * An array of struct partition is passed along with a MTD object to
- * add_mtd_partitions() to create them.
+ * mtd_device_register() to create them.
  *
  * For each partition, these fields are available:
  * name: string that will be used to label the partition's MTD device.
@@ -49,9 +49,6 @@
 
 struct mtd_info;
 
-int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
-int del_mtd_partitions(struct mtd_info *);
-
 /*
  * Functions dealing with the various ways of partitioning the space
  */
@@ -73,14 +70,17 @@
 struct device;
 struct device_node;
 
+#ifdef CONFIG_MTD_OF_PARTS
 int __devinit of_mtd_parse_partitions(struct device *dev,
                                       struct device_node *node,
                                       struct mtd_partition **pparts);
-
-#ifdef CONFIG_MTD_PARTITIONS
-static inline int mtd_has_partitions(void) { return 1; }
 #else
-static inline int mtd_has_partitions(void) { return 0; }
+static inline int of_mtd_parse_partitions(struct device *dev,
+					  struct device_node *node,
+					  struct mtd_partition **pparts)
+{
+	return 0;
+}
 #endif
 
 #ifdef CONFIG_MTD_CMDLINE_PARTS
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
index 49b9590..d40bfa1 100644
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -37,8 +37,6 @@
 void physmap_configure(unsigned long addr, unsigned long size,
 		int bankwidth, void (*set_vpp)(struct map_info *, int) );
 
-#ifdef CONFIG_MTD_PARTITIONS
-
 /*
  * Machines that wish to do flash partition may want to call this function in
  * their setup routine.
@@ -50,6 +48,4 @@
  */
 void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
 
-#endif /* defined(CONFIG_MTD_PARTITIONS) */
-
 #endif /* __LINUX_MTD_PHYSMAP__ */