diff --git a/MAINTAINERS b/MAINTAINERS
index 3b46f43c338bb5da005ef44de2551dd6c2a995c7..cfd26ddccd7a0997c10ed46e4c15a7dc021c1761 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2648,6 +2648,12 @@ M:	corbet@lwn.net
 L:	video4linux-list@redhat.com
 S:	Maintained
 
+ONENAND FLASH DRIVER
+P:	Kyungmin Park
+M:	kyungmin.park@samsung.com
+L:	linux-mtd@lists.infradead.org
+S:	Maintained
+
 ONSTREAM SCSI TAPE DRIVER
 P:	Willem Riede
 M:	osst@riede.org
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index d28e0fc85e12c2e0bad8810551b1a3a8a4cffd42..479d32b57a1eb54b20b731855274bd9d343a62ae 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -1,5 +1,4 @@
 # drivers/mtd/chips/Kconfig
-# $Id: Kconfig,v 1.18 2005/11/07 11:14:22 gleixner Exp $
 
 menu "RAM/ROM/Flash chip drivers"
 	depends on MTD!=n
@@ -231,45 +230,6 @@ config MTD_ABSENT
 	  the system regardless of media presence.  Device nodes created
 	  with this driver will return -ENODEV upon access.
 
-config MTD_OBSOLETE_CHIPS
-	bool "Older (theoretically obsoleted now) drivers for non-CFI chips"
-	help
-	  This option does not enable any code directly, but will allow you to
-	  select some other chip drivers which are now considered obsolete,
-	  because the generic CONFIG_JEDECPROBE code above should now detect
-	  the chips which are supported by these drivers, and allow the generic
-	  CFI-compatible drivers to drive the chips. Say 'N' here unless you have
-	  already tried the CONFIG_JEDECPROBE method and reported its failure
-	  to the MTD mailing list at <linux-mtd@lists.infradead.org>
-
-config MTD_AMDSTD
-	tristate "AMD compatible flash chip support (non-CFI)"
-	depends on MTD_OBSOLETE_CHIPS && BROKEN
-	help
-	  This option enables support for flash chips using AMD-compatible
-	  commands, including some which are not CFI-compatible and hence
-	  cannot be used with the CONFIG_MTD_CFI_AMDSTD option.
-
-	  It also works on AMD compatible chips that do conform to CFI.
-
-config MTD_SHARP
-	tristate "pre-CFI Sharp chip support"
-	depends on MTD_OBSOLETE_CHIPS
-	help
-	  This option enables support for flash chips using Sharp-compatible
-	  commands, including some which are not CFI-compatible and hence
-	  cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
-
-config MTD_JEDEC
-	tristate "JEDEC device support"
-	depends on MTD_OBSOLETE_CHIPS && BROKEN
-	help
-	  Enable older JEDEC flash interface devices for self
-	  programming flash.  It is commonly used in older AMD chips.  It is
-	  only called JEDEC because the JEDEC association
-	  <http://www.jedec.org/> distributes the identification codes for the
-	  chips.
-
 config MTD_XIP
 	bool "XIP aware MTD support"
 	depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP
diff --git a/drivers/mtd/chips/Makefile b/drivers/mtd/chips/Makefile
index 75bc1c2a0f431b9954447921f03b7246ed2fb395..36582412ccdaeb2c2aea2c0752f8b62e51554154 100644
--- a/drivers/mtd/chips/Makefile
+++ b/drivers/mtd/chips/Makefile
@@ -1,19 +1,15 @@
 #
 # linux/drivers/chips/Makefile
 #
-# $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $
 
 obj-$(CONFIG_MTD)		+= chipreg.o
-obj-$(CONFIG_MTD_AMDSTD)	+= amd_flash.o
 obj-$(CONFIG_MTD_CFI)		+= cfi_probe.o
 obj-$(CONFIG_MTD_CFI_UTIL)	+= cfi_util.o
 obj-$(CONFIG_MTD_CFI_STAA)	+= cfi_cmdset_0020.o
 obj-$(CONFIG_MTD_CFI_AMDSTD)	+= cfi_cmdset_0002.o
 obj-$(CONFIG_MTD_CFI_INTELEXT)	+= cfi_cmdset_0001.o
 obj-$(CONFIG_MTD_GEN_PROBE)	+= gen_probe.o
-obj-$(CONFIG_MTD_JEDEC)		+= jedec.o
 obj-$(CONFIG_MTD_JEDECPROBE)	+= jedec_probe.o
 obj-$(CONFIG_MTD_RAM)		+= map_ram.o
 obj-$(CONFIG_MTD_ROM)		+= map_rom.o
-obj-$(CONFIG_MTD_SHARP)		+= sharp.o
 obj-$(CONFIG_MTD_ABSENT)	+= map_absent.o
diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c
deleted file mode 100644
index e7999f15d85a51881f54a2d49d79506c3a3623d0..0000000000000000000000000000000000000000
--- a/drivers/mtd/chips/amd_flash.c
+++ /dev/null
@@ -1,1396 +0,0 @@
-/*
- * MTD map driver for AMD compatible flash chips (non-CFI)
- *
- * Author: Jonas Holmberg <jonas.holmberg@axis.com>
- *
- * $Id: amd_flash.c,v 1.28 2005/11/07 11:14:22 gleixner Exp $
- *
- * Copyright (c) 2001 Axis Communications AB
- *
- * This file is under GPL.
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/flashchip.h>
-
-/* There's no limit. It exists only to avoid realloc. */
-#define MAX_AMD_CHIPS 8
-
-#define DEVICE_TYPE_X8	(8 / 8)
-#define DEVICE_TYPE_X16	(16 / 8)
-#define DEVICE_TYPE_X32	(32 / 8)
-
-/* Addresses */
-#define ADDR_MANUFACTURER		0x0000
-#define ADDR_DEVICE_ID			0x0001
-#define ADDR_SECTOR_LOCK		0x0002
-#define ADDR_HANDSHAKE			0x0003
-#define ADDR_UNLOCK_1			0x0555
-#define ADDR_UNLOCK_2			0x02AA
-
-/* Commands */
-#define CMD_UNLOCK_DATA_1		0x00AA
-#define CMD_UNLOCK_DATA_2		0x0055
-#define CMD_MANUFACTURER_UNLOCK_DATA	0x0090
-#define CMD_UNLOCK_BYPASS_MODE		0x0020
-#define CMD_PROGRAM_UNLOCK_DATA		0x00A0
-#define CMD_RESET_DATA			0x00F0
-#define CMD_SECTOR_ERASE_UNLOCK_DATA	0x0080
-#define CMD_SECTOR_ERASE_UNLOCK_DATA_2	0x0030
-
-#define CMD_UNLOCK_SECTOR		0x0060
-
-/* Manufacturers */
-#define MANUFACTURER_AMD	0x0001
-#define MANUFACTURER_ATMEL	0x001F
-#define MANUFACTURER_FUJITSU	0x0004
-#define MANUFACTURER_ST		0x0020
-#define MANUFACTURER_SST	0x00BF
-#define MANUFACTURER_TOSHIBA	0x0098
-
-/* AMD */
-#define AM29F800BB	0x2258
-#define AM29F800BT	0x22D6
-#define AM29LV800BB	0x225B
-#define AM29LV800BT	0x22DA
-#define AM29LV160DT	0x22C4
-#define AM29LV160DB	0x2249
-#define AM29BDS323D     0x22D1
-
-/* Atmel */
-#define AT49xV16x	0x00C0
-#define AT49xV16xT	0x00C2
-
-/* Fujitsu */
-#define MBM29LV160TE	0x22C4
-#define MBM29LV160BE	0x2249
-#define MBM29LV800BB	0x225B
-
-/* ST - www.st.com */
-#define M29W800T	0x00D7
-#define M29W160DT	0x22C4
-#define M29W160DB	0x2249
-
-/* SST */
-#define SST39LF800	0x2781
-#define SST39LF160	0x2782
-
-/* Toshiba */
-#define TC58FVT160	0x00C2
-#define TC58FVB160	0x0043
-
-#define D6_MASK	0x40
-
-struct amd_flash_private {
-	int device_type;
-	int interleave;
-	int numchips;
-	unsigned long chipshift;
-	struct flchip chips[0];
-};
-
-struct amd_flash_info {
-	const __u16 mfr_id;
-	const __u16 dev_id;
-	const char *name;
-	const u_long size;
-	const int numeraseregions;
-	const struct mtd_erase_region_info regions[4];
-};
-
-
-
-static int amd_flash_read(struct mtd_info *, loff_t, size_t, size_t *,
-			  u_char *);
-static int amd_flash_write(struct mtd_info *, loff_t, size_t, size_t *,
-			   const u_char *);
-static int amd_flash_erase(struct mtd_info *, struct erase_info *);
-static void amd_flash_sync(struct mtd_info *);
-static int amd_flash_suspend(struct mtd_info *);
-static void amd_flash_resume(struct mtd_info *);
-static void amd_flash_destroy(struct mtd_info *);
-static struct mtd_info *amd_flash_probe(struct map_info *map);
-
-
-static struct mtd_chip_driver amd_flash_chipdrv = {
-	.probe = amd_flash_probe,
-	.destroy = amd_flash_destroy,
-	.name = "amd_flash",
-	.module = THIS_MODULE
-};
-
-static inline __u32 wide_read(struct map_info *map, __u32 addr)
-{
-	if (map->buswidth == 1) {
-		return map_read8(map, addr);
-	} else if (map->buswidth == 2) {
-		return map_read16(map, addr);
-	} else if (map->buswidth == 4) {
-		return map_read32(map, addr);
-        }
-
-	return 0;
-}
-
-static inline void wide_write(struct map_info *map, __u32 val, __u32 addr)
-{
-	if (map->buswidth == 1) {
-		map_write8(map, val, addr);
-	} else if (map->buswidth == 2) {
-		map_write16(map, val, addr);
-	} else if (map->buswidth == 4) {
-		map_write32(map, val, addr);
-	}
-}
-
-static inline __u32 make_cmd(struct map_info *map, __u32 cmd)
-{
-	const struct amd_flash_private *private = map->fldrv_priv;
-	if ((private->interleave == 2) &&
-	    (private->device_type == DEVICE_TYPE_X16)) {
-		cmd |= (cmd << 16);
-	}
-
-	return cmd;
-}
-
-static inline void send_unlock(struct map_info *map, unsigned long base)
-{
-	wide_write(map, (CMD_UNLOCK_DATA_1 << 16) | CMD_UNLOCK_DATA_1,
-		   base + (map->buswidth * ADDR_UNLOCK_1));
-	wide_write(map, (CMD_UNLOCK_DATA_2 << 16) | CMD_UNLOCK_DATA_2,
-		   base + (map->buswidth * ADDR_UNLOCK_2));
-}
-
-static inline void send_cmd(struct map_info *map, unsigned long base, __u32 cmd)
-{
-	send_unlock(map, base);
-	wide_write(map, make_cmd(map, cmd),
-		   base + (map->buswidth * ADDR_UNLOCK_1));
-}
-
-static inline void send_cmd_to_addr(struct map_info *map, unsigned long base,
-				    __u32 cmd, unsigned long addr)
-{
-	send_unlock(map, base);
-	wide_write(map, make_cmd(map, cmd), addr);
-}
-
-static inline int flash_is_busy(struct map_info *map, unsigned long addr,
-				int interleave)
-{
-
-	if ((interleave == 2) && (map->buswidth == 4)) {
-		__u32 read1, read2;
-
-		read1 = wide_read(map, addr);
-		read2 = wide_read(map, addr);
-
-		return (((read1 >> 16) & D6_MASK) !=
-			((read2 >> 16) & D6_MASK)) ||
-		       (((read1 & 0xffff) & D6_MASK) !=
-			((read2 & 0xffff) & D6_MASK));
-	}
-
-	return ((wide_read(map, addr) & D6_MASK) !=
-		(wide_read(map, addr) & D6_MASK));
-}
-
-static inline void unlock_sector(struct map_info *map, unsigned long sect_addr,
-				 int unlock)
-{
-	/* Sector lock address. A6 = 1 for unlock, A6 = 0 for lock */
-	int SLA = unlock ?
-		(sect_addr |  (0x40 * map->buswidth)) :
-		(sect_addr & ~(0x40 * map->buswidth)) ;
-
-	__u32 cmd = make_cmd(map, CMD_UNLOCK_SECTOR);
-
-	wide_write(map, make_cmd(map, CMD_RESET_DATA), 0);
-	wide_write(map, cmd, SLA); /* 1st cycle: write cmd to any address */
-	wide_write(map, cmd, SLA); /* 2nd cycle: write cmd to any address */
-	wide_write(map, cmd, SLA); /* 3rd cycle: write cmd to SLA */
-}
-
-static inline int is_sector_locked(struct map_info *map,
-				   unsigned long sect_addr)
-{
-	int status;
-
-	wide_write(map, CMD_RESET_DATA, 0);
-	send_cmd(map, sect_addr, CMD_MANUFACTURER_UNLOCK_DATA);
-
-	/* status is 0x0000 for unlocked and 0x0001 for locked */
-	status = wide_read(map, sect_addr + (map->buswidth * ADDR_SECTOR_LOCK));
-	wide_write(map, CMD_RESET_DATA, 0);
-	return status;
-}
-
-static int amd_flash_do_unlock(struct mtd_info *mtd, loff_t ofs, size_t len,
-			       int is_unlock)
-{
-	struct map_info *map;
-	struct mtd_erase_region_info *merip;
-	int eraseoffset, erasesize, eraseblocks;
-	int i;
-	int retval = 0;
-	int lock_status;
-
-	map = mtd->priv;
-
-	/* Pass the whole chip through sector by sector and check for each
-	   sector if the sector and the given interval overlap */
-	for(i = 0; i < mtd->numeraseregions; i++) {
-		merip = &mtd->eraseregions[i];
-
-		eraseoffset = merip->offset;
-		erasesize = merip->erasesize;
-		eraseblocks = merip->numblocks;
-
-		if (ofs > eraseoffset + erasesize)
-			continue;
-
-		while (eraseblocks > 0) {
-			if (ofs < eraseoffset + erasesize && ofs + len > eraseoffset) {
-				unlock_sector(map, eraseoffset, is_unlock);
-
-				lock_status = is_sector_locked(map, eraseoffset);
-
-				if (is_unlock && lock_status) {
-					printk("Cannot unlock sector at address %x length %xx\n",
-					       eraseoffset, merip->erasesize);
-					retval = -1;
-				} else if (!is_unlock && !lock_status) {
-					printk("Cannot lock sector at address %x length %x\n",
-					       eraseoffset, merip->erasesize);
-					retval = -1;
-				}
-			}
-			eraseoffset += erasesize;
-			eraseblocks --;
-		}
-	}
-	return retval;
-}
-
-static int amd_flash_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
-	return amd_flash_do_unlock(mtd, ofs, len, 1);
-}
-
-static int amd_flash_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
-	return amd_flash_do_unlock(mtd, ofs, len, 0);
-}
-
-
-/*
- * Reads JEDEC manufacturer ID and device ID and returns the index of the first
- * matching table entry (-1 if not found or alias for already found chip).
- */
-static int probe_new_chip(struct mtd_info *mtd, __u32 base,
-			  struct flchip *chips,
-			  struct amd_flash_private *private,
-			  const struct amd_flash_info *table, int table_size)
-{
-	__u32 mfr_id;
-	__u32 dev_id;
-	struct map_info *map = mtd->priv;
-	struct amd_flash_private temp;
-	int i;
-
-	temp.device_type = DEVICE_TYPE_X16;	// Assume X16 (FIXME)
-	temp.interleave = 2;
-	map->fldrv_priv = &temp;
-
-	/* Enter autoselect mode. */
-	send_cmd(map, base, CMD_RESET_DATA);
-	send_cmd(map, base, CMD_MANUFACTURER_UNLOCK_DATA);
-
-	mfr_id = wide_read(map, base + (map->buswidth * ADDR_MANUFACTURER));
-	dev_id = wide_read(map, base + (map->buswidth * ADDR_DEVICE_ID));
-
-	if ((map->buswidth == 4) && ((mfr_id >> 16) == (mfr_id & 0xffff)) &&
-	    ((dev_id >> 16) == (dev_id & 0xffff))) {
-		mfr_id &= 0xffff;
-		dev_id &= 0xffff;
-	} else {
-		temp.interleave = 1;
-	}
-
-	for (i = 0; i < table_size; i++) {
-		if ((mfr_id == table[i].mfr_id) &&
-		    (dev_id == table[i].dev_id)) {
-			if (chips) {
-				int j;
-
-				/* Is this an alias for an already found chip?
-				 * In that case that chip should be in
-				 * autoselect mode now.
-				 */
-				for (j = 0; j < private->numchips; j++) {
-					__u32 mfr_id_other;
-					__u32 dev_id_other;
-
-					mfr_id_other =
-						wide_read(map, chips[j].start +
-							       (map->buswidth *
-								ADDR_MANUFACTURER
-							       ));
-					dev_id_other =
-						wide_read(map, chips[j].start +
-					    		       (map->buswidth *
-							        ADDR_DEVICE_ID));
-					if (temp.interleave == 2) {
-						mfr_id_other &= 0xffff;
-						dev_id_other &= 0xffff;
-					}
-					if ((mfr_id_other == mfr_id) &&
-					    (dev_id_other == dev_id)) {
-
-						/* Exit autoselect mode. */
-						send_cmd(map, base,
-							 CMD_RESET_DATA);
-
-						return -1;
-					}
-				}
-
-				if (private->numchips == MAX_AMD_CHIPS) {
-					printk(KERN_WARNING
-					       "%s: Too many flash chips "
-					       "detected. Increase "
-					       "MAX_AMD_CHIPS from %d.\n",
-					       map->name, MAX_AMD_CHIPS);
-
-					return -1;
-				}
-
-				chips[private->numchips].start = base;
-				chips[private->numchips].state = FL_READY;
-				chips[private->numchips].mutex =
-					&chips[private->numchips]._spinlock;
-				private->numchips++;
-			}
-
-			printk("%s: Found %d x %ldMiB %s at 0x%x\n", map->name,
-			       temp.interleave, (table[i].size)/(1024*1024),
-			       table[i].name, base);
-
-			mtd->size += table[i].size * temp.interleave;
-			mtd->numeraseregions += table[i].numeraseregions;
-
-			break;
-		}
-	}
-
-	/* Exit autoselect mode. */
-	send_cmd(map, base, CMD_RESET_DATA);
-
-	if (i == table_size) {
-		printk(KERN_DEBUG "%s: unknown flash device at 0x%x, "
-		       "mfr id 0x%x, dev id 0x%x\n", map->name,
-		       base, mfr_id, dev_id);
-		map->fldrv_priv = NULL;
-
-		return -1;
-	}
-
-	private->device_type = temp.device_type;
-	private->interleave = temp.interleave;
-
-	return i;
-}
-
-
-
-static struct mtd_info *amd_flash_probe(struct map_info *map)
-{
-	static const struct amd_flash_info table[] = {
-	{
-		.mfr_id = MANUFACTURER_AMD,
-		.dev_id = AM29LV160DT,
-		.name = "AMD AM29LV160DT",
-		.size = 0x00200000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-			{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_AMD,
-		.dev_id = AM29LV160DB,
-		.name = "AMD AM29LV160DB",
-		.size = 0x00200000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_TOSHIBA,
-		.dev_id = TC58FVT160,
-		.name = "Toshiba TC58FVT160",
-		.size = 0x00200000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-			{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_FUJITSU,
-		.dev_id = MBM29LV160TE,
-		.name = "Fujitsu MBM29LV160TE",
-		.size = 0x00200000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-			{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_TOSHIBA,
-		.dev_id = TC58FVB160,
-		.name = "Toshiba TC58FVB160",
-		.size = 0x00200000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_FUJITSU,
-		.dev_id = MBM29LV160BE,
-		.name = "Fujitsu MBM29LV160BE",
-		.size = 0x00200000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_AMD,
-		.dev_id = AM29LV800BB,
-		.name = "AMD AM29LV800BB",
-		.size = 0x00100000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_AMD,
-		.dev_id = AM29F800BB,
-		.name = "AMD AM29F800BB",
-		.size = 0x00100000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_AMD,
-		.dev_id = AM29LV800BT,
-		.name = "AMD AM29LV800BT",
-		.size = 0x00100000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
-			{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_AMD,
-		.dev_id = AM29F800BT,
-		.name = "AMD AM29F800BT",
-		.size = 0x00100000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
-			{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_AMD,
-		.dev_id = AM29LV800BB,
-		.name = "AMD AM29LV800BB",
-		.size = 0x00100000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
-			{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_FUJITSU,
-		.dev_id = MBM29LV800BB,
-		.name = "Fujitsu MBM29LV800BB",
-		.size = 0x00100000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_ST,
-		.dev_id = M29W800T,
-		.name = "ST M29W800T",
-		.size = 0x00100000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
-			{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks =  1 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_ST,
-		.dev_id = M29W160DT,
-		.name = "ST M29W160DT",
-		.size = 0x00200000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-			{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks =  1 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_ST,
-		.dev_id = M29W160DB,
-		.name = "ST M29W160DB",
-		.size = 0x00200000,
-		.numeraseregions = 4,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x04000, .numblocks =  1 },
-			{ .offset = 0x004000, .erasesize = 0x02000, .numblocks =  2 },
-			{ .offset = 0x008000, .erasesize = 0x08000, .numblocks =  1 },
-			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_AMD,
-		.dev_id = AM29BDS323D,
-		.name = "AMD AM29BDS323D",
-		.size = 0x00400000,
-		.numeraseregions = 3,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 48 },
-			{ .offset = 0x300000, .erasesize = 0x10000, .numblocks = 15 },
-			{ .offset = 0x3f0000, .erasesize = 0x02000, .numblocks =  8 },
-		}
-	}, {
-		.mfr_id = MANUFACTURER_ATMEL,
-		.dev_id = AT49xV16x,
-		.name = "Atmel AT49xV16x",
-		.size = 0x00200000,
-		.numeraseregions = 2,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x02000, .numblocks =  8 },
-			{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
-		}
-	}, {
-		.mfr_id = MANUFACTURER_ATMEL,
-		.dev_id = AT49xV16xT,
-		.name = "Atmel AT49xV16xT",
-		.size = 0x00200000,
-		.numeraseregions = 2,
-		.regions = {
-			{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
-			{ .offset = 0x1F0000, .erasesize = 0x02000, .numblocks =  8 }
-		}
-	}
-	};
-
-	struct mtd_info *mtd;
-	struct flchip chips[MAX_AMD_CHIPS];
-	int table_pos[MAX_AMD_CHIPS];
-	struct amd_flash_private temp;
-	struct amd_flash_private *private;
-	u_long size;
-	unsigned long base;
-	int i;
-	int reg_idx;
-	int offset;
-
-	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
-	if (!mtd) {
-		printk(KERN_WARNING
-		       "%s: kmalloc failed for info structure\n", map->name);
-		return NULL;
-	}
-	mtd->priv = map;
-
-	memset(&temp, 0, sizeof(temp));
-
-	printk("%s: Probing for AMD compatible flash...\n", map->name);
-
-	if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table,
-					   ARRAY_SIZE(table)))
-	    == -1) {
-		printk(KERN_WARNING
-		       "%s: Found no AMD compatible device at location zero\n",
-		       map->name);
-		kfree(mtd);
-
-		return NULL;
-	}
-
-	chips[0].start = 0;
-	chips[0].state = FL_READY;
-	chips[0].mutex = &chips[0]._spinlock;
-	temp.numchips = 1;
-	for (size = mtd->size; size > 1; size >>= 1) {
-		temp.chipshift++;
-	}
-	switch (temp.interleave) {
-		case 2:
-			temp.chipshift += 1;
-			break;
-		case 4:
-			temp.chipshift += 2;
-			break;
-	}
-
-	/* Find out if there are any more chips in the map. */
-	for (base = (1 << temp.chipshift);
-	     base < map->size;
-	     base += (1 << temp.chipshift)) {
-	     	int numchips = temp.numchips;
-		table_pos[numchips] = probe_new_chip(mtd, base, chips,
-			&temp, table, ARRAY_SIZE(table));
-	}
-
-	mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) *
-				    mtd->numeraseregions, GFP_KERNEL);
-	if (!mtd->eraseregions) {
-		printk(KERN_WARNING "%s: Failed to allocate "
-		       "memory for MTD erase region info\n", map->name);
-		kfree(mtd);
-		map->fldrv_priv = NULL;
-		return NULL;
-	}
-
-	reg_idx = 0;
-	offset = 0;
-	for (i = 0; i < temp.numchips; i++) {
-		int dev_size;
-		int j;
-
-		dev_size = 0;
-		for (j = 0; j < table[table_pos[i]].numeraseregions; j++) {
-			mtd->eraseregions[reg_idx].offset = offset +
-				(table[table_pos[i]].regions[j].offset *
-				 temp.interleave);
-			mtd->eraseregions[reg_idx].erasesize =
-				table[table_pos[i]].regions[j].erasesize *
-				temp.interleave;
-			mtd->eraseregions[reg_idx].numblocks =
-				table[table_pos[i]].regions[j].numblocks;
-			if (mtd->erasesize <
-			    mtd->eraseregions[reg_idx].erasesize) {
-				mtd->erasesize =
-					mtd->eraseregions[reg_idx].erasesize;
-			}
-			dev_size += mtd->eraseregions[reg_idx].erasesize *
-				    mtd->eraseregions[reg_idx].numblocks;
-			reg_idx++;
-		}
-		offset += dev_size;
-	}
-	mtd->type = MTD_NORFLASH;
-	mtd->writesize = 1;
-	mtd->flags = MTD_CAP_NORFLASH;
-	mtd->name = map->name;
-	mtd->erase = amd_flash_erase;
-	mtd->read = amd_flash_read;
-	mtd->write = amd_flash_write;
-	mtd->sync = amd_flash_sync;
-	mtd->suspend = amd_flash_suspend;
-	mtd->resume = amd_flash_resume;
-	mtd->lock = amd_flash_lock;
-	mtd->unlock = amd_flash_unlock;
-
-	private = kmalloc(sizeof(*private) + (sizeof(struct flchip) *
-					      temp.numchips), GFP_KERNEL);
-	if (!private) {
-		printk(KERN_WARNING
-		       "%s: kmalloc failed for private structure\n", map->name);
-		kfree(mtd);
-		map->fldrv_priv = NULL;
-		return NULL;
-	}
-	memcpy(private, &temp, sizeof(temp));
-	memcpy(private->chips, chips,
-	       sizeof(struct flchip) * private->numchips);
-	for (i = 0; i < private->numchips; i++) {
-		init_waitqueue_head(&private->chips[i].wq);
-		spin_lock_init(&private->chips[i]._spinlock);
-	}
-
-	map->fldrv_priv = private;
-
-	map->fldrv = &amd_flash_chipdrv;
-
-	__module_get(THIS_MODULE);
-	return mtd;
-}
-
-
-
-static inline int read_one_chip(struct map_info *map, struct flchip *chip,
-			       loff_t adr, size_t len, u_char *buf)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long timeo = jiffies + HZ;
-
-retry:
-	spin_lock_bh(chip->mutex);
-
-	if (chip->state != FL_READY){
-		printk(KERN_INFO "%s: waiting for chip to read, state = %d\n",
-		       map->name, chip->state);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		add_wait_queue(&chip->wq, &wait);
-
-		spin_unlock_bh(chip->mutex);
-
-		schedule();
-		remove_wait_queue(&chip->wq, &wait);
-
-		if(signal_pending(current)) {
-			return -EINTR;
-		}
-
-		timeo = jiffies + HZ;
-
-		goto retry;
-	}
-
-	adr += chip->start;
-
-	chip->state = FL_READY;
-
-	map_copy_from(map, buf, adr, len);
-
-	wake_up(&chip->wq);
-	spin_unlock_bh(chip->mutex);
-
-	return 0;
-}
-
-
-
-static int amd_flash_read(struct mtd_info *mtd, loff_t from, size_t len,
-			  size_t *retlen, u_char *buf)
-{
-	struct map_info *map = mtd->priv;
-	struct amd_flash_private *private = map->fldrv_priv;
-	unsigned long ofs;
-	int chipnum;
-	int ret = 0;
-
-	if ((from + len) > mtd->size) {
-		printk(KERN_WARNING "%s: read request past end of device "
-		       "(0x%lx)\n", map->name, (unsigned long)from + len);
-
-		return -EINVAL;
-	}
-
-	/* Offset within the first chip that the first read should start. */
-	chipnum = (from >> private->chipshift);
-	ofs = from - (chipnum <<  private->chipshift);
-
-	*retlen = 0;
-
-	while (len) {
-		unsigned long this_len;
-
-		if (chipnum >= private->numchips) {
-			break;
-		}
-
-		if ((len + ofs - 1) >> private->chipshift) {
-			this_len = (1 << private->chipshift) - ofs;
-		} else {
-			this_len = len;
-		}
-
-		ret = read_one_chip(map, &private->chips[chipnum], ofs,
-				    this_len, buf);
-		if (ret) {
-			break;
-		}
-
-		*retlen += this_len;
-		len -= this_len;
-		buf += this_len;
-
-		ofs = 0;
-		chipnum++;
-	}
-
-	return ret;
-}
-
-
-
-static int write_one_word(struct map_info *map, struct flchip *chip,
-			  unsigned long adr, __u32 datum)
-{
-	unsigned long timeo = jiffies + HZ;
-	struct amd_flash_private *private = map->fldrv_priv;
-	DECLARE_WAITQUEUE(wait, current);
-	int ret = 0;
-	int times_left;
-
-retry:
-	spin_lock_bh(chip->mutex);
-
-	if (chip->state != FL_READY){
-		printk("%s: waiting for chip to write, state = %d\n",
-		       map->name, chip->state);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		add_wait_queue(&chip->wq, &wait);
-
-		spin_unlock_bh(chip->mutex);
-
-		schedule();
-		remove_wait_queue(&chip->wq, &wait);
-		printk(KERN_INFO "%s: woke up to write\n", map->name);
-		if(signal_pending(current))
-			return -EINTR;
-
-		timeo = jiffies + HZ;
-
-		goto retry;
-	}
-
-	chip->state = FL_WRITING;
-
-	adr += chip->start;
-	ENABLE_VPP(map);
-	send_cmd(map, chip->start, CMD_PROGRAM_UNLOCK_DATA);
-	wide_write(map, datum, adr);
-
-	times_left = 500000;
-	while (times_left-- && flash_is_busy(map, adr, private->interleave)) {
-		if (need_resched()) {
-			spin_unlock_bh(chip->mutex);
-			schedule();
-			spin_lock_bh(chip->mutex);
-		}
-	}
-
-	if (!times_left) {
-		printk(KERN_WARNING "%s: write to 0x%lx timed out!\n",
-		       map->name, adr);
-		ret = -EIO;
-	} else {
-		__u32 verify;
-		if ((verify = wide_read(map, adr)) != datum) {
-			printk(KERN_WARNING "%s: write to 0x%lx failed. "
-			       "datum = %x, verify = %x\n",
-			       map->name, adr, datum, verify);
-			ret = -EIO;
-		}
-	}
-
-	DISABLE_VPP(map);
-	chip->state = FL_READY;
-	wake_up(&chip->wq);
-	spin_unlock_bh(chip->mutex);
-
-	return ret;
-}
-
-
-
-static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len,
-			   size_t *retlen, const u_char *buf)
-{
-	struct map_info *map = mtd->priv;
-	struct amd_flash_private *private = map->fldrv_priv;
-	int ret = 0;
-	int chipnum;
-	unsigned long ofs;
-	unsigned long chipstart;
-
-	*retlen = 0;
-	if (!len) {
-		return 0;
-	}
-
-	chipnum = to >> private->chipshift;
-	ofs = to  - (chipnum << private->chipshift);
-	chipstart = private->chips[chipnum].start;
-
-	/* If it's not bus-aligned, do the first byte write. */
-	if (ofs & (map->buswidth - 1)) {
-		unsigned long bus_ofs = ofs & ~(map->buswidth - 1);
-		int i = ofs - bus_ofs;
-		int n = 0;
-		u_char tmp_buf[4];
-		__u32 datum;
-
-		map_copy_from(map, tmp_buf,
-			       bus_ofs + private->chips[chipnum].start,
-			       map->buswidth);
-		while (len && i < map->buswidth)
-			tmp_buf[i++] = buf[n++], len--;
-
-		if (map->buswidth == 2) {
-			datum = *(__u16*)tmp_buf;
-		} else if (map->buswidth == 4) {
-			datum = *(__u32*)tmp_buf;
-		} else {
-			return -EINVAL;  /* should never happen, but be safe */
-		}
-
-		ret = write_one_word(map, &private->chips[chipnum], bus_ofs,
-				     datum);
-		if (ret) {
-			return ret;
-		}
-
-		ofs += n;
-		buf += n;
-		(*retlen) += n;
-
-		if (ofs >> private->chipshift) {
-			chipnum++;
-			ofs = 0;
-			if (chipnum == private->numchips) {
-				return 0;
-			}
-		}
-	}
-
-	/* We are now aligned, write as much as possible. */
-	while(len >= map->buswidth) {
-		__u32 datum;
-
-		if (map->buswidth == 1) {
-			datum = *(__u8*)buf;
-		} else if (map->buswidth == 2) {
-			datum = *(__u16*)buf;
-		} else if (map->buswidth == 4) {
-			datum = *(__u32*)buf;
-		} else {
-			return -EINVAL;
-		}
-
-		ret = write_one_word(map, &private->chips[chipnum], ofs, datum);
-
-		if (ret) {
-			return ret;
-		}
-
-		ofs += map->buswidth;
-		buf += map->buswidth;
-		(*retlen) += map->buswidth;
-		len -= map->buswidth;
-
-		if (ofs >> private->chipshift) {
-			chipnum++;
-			ofs = 0;
-			if (chipnum == private->numchips) {
-				return 0;
-			}
-			chipstart = private->chips[chipnum].start;
-		}
-	}
-
-	if (len & (map->buswidth - 1)) {
-		int i = 0, n = 0;
-		u_char tmp_buf[2];
-		__u32 datum;
-
-		map_copy_from(map, tmp_buf,
-			       ofs + private->chips[chipnum].start,
-			       map->buswidth);
-		while (len--) {
-			tmp_buf[i++] = buf[n++];
-		}
-
-		if (map->buswidth == 2) {
-			datum = *(__u16*)tmp_buf;
-		} else if (map->buswidth == 4) {
-			datum = *(__u32*)tmp_buf;
-		} else {
-			return -EINVAL;  /* should never happen, but be safe */
-		}
-
-		ret = write_one_word(map, &private->chips[chipnum], ofs, datum);
-
-		if (ret) {
-			return ret;
-		}
-
-		(*retlen) += n;
-	}
-
-	return 0;
-}
-
-
-
-static inline int erase_one_block(struct map_info *map, struct flchip *chip,
-				  unsigned long adr, u_long size)
-{
-	unsigned long timeo = jiffies + HZ;
-	struct amd_flash_private *private = map->fldrv_priv;
-	DECLARE_WAITQUEUE(wait, current);
-
-retry:
-	spin_lock_bh(chip->mutex);
-
-	if (chip->state != FL_READY){
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		add_wait_queue(&chip->wq, &wait);
-
-		spin_unlock_bh(chip->mutex);
-
-		schedule();
-		remove_wait_queue(&chip->wq, &wait);
-
-		if (signal_pending(current)) {
-			return -EINTR;
-		}
-
-		timeo = jiffies + HZ;
-
-		goto retry;
-	}
-
-	chip->state = FL_ERASING;
-
-	adr += chip->start;
-	ENABLE_VPP(map);
-	send_cmd(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA);
-	send_cmd_to_addr(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA_2, adr);
-
-	timeo = jiffies + (HZ * 20);
-
-	spin_unlock_bh(chip->mutex);
-	msleep(1000);
-	spin_lock_bh(chip->mutex);
-
-	while (flash_is_busy(map, adr, private->interleave)) {
-
-		if (chip->state != FL_ERASING) {
-			/* Someone's suspended the erase. Sleep */
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			add_wait_queue(&chip->wq, &wait);
-
-			spin_unlock_bh(chip->mutex);
-			printk(KERN_INFO "%s: erase suspended. Sleeping\n",
-			       map->name);
-			schedule();
-			remove_wait_queue(&chip->wq, &wait);
-
-			if (signal_pending(current)) {
-				return -EINTR;
-			}
-
-			timeo = jiffies + (HZ*2); /* FIXME */
-			spin_lock_bh(chip->mutex);
-			continue;
-		}
-
-		/* OK Still waiting */
-		if (time_after(jiffies, timeo)) {
-			chip->state = FL_READY;
-			spin_unlock_bh(chip->mutex);
-			printk(KERN_WARNING "%s: waiting for erase to complete "
-			       "timed out.\n", map->name);
-			DISABLE_VPP(map);
-
-			return -EIO;
-		}
-
-		/* Latency issues. Drop the lock, wait a while and retry */
-		spin_unlock_bh(chip->mutex);
-
-		if (need_resched())
-			schedule();
-		else
-			udelay(1);
-
-		spin_lock_bh(chip->mutex);
-	}
-
-	/* Verify every single word */
-	{
-		int address;
-		int error = 0;
-		__u8 verify;
-
-		for (address = adr; address < (adr + size); address++) {
-			if ((verify = map_read8(map, address)) != 0xFF) {
-				error = 1;
-				break;
-			}
-		}
-		if (error) {
-			chip->state = FL_READY;
-			spin_unlock_bh(chip->mutex);
-			printk(KERN_WARNING
-			       "%s: verify error at 0x%x, size %ld.\n",
-			       map->name, address, size);
-			DISABLE_VPP(map);
-
-			return -EIO;
-		}
-	}
-
-	DISABLE_VPP(map);
-	chip->state = FL_READY;
-	wake_up(&chip->wq);
-	spin_unlock_bh(chip->mutex);
-
-	return 0;
-}
-
-
-
-static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-	struct map_info *map = mtd->priv;
-	struct amd_flash_private *private = map->fldrv_priv;
-	unsigned long adr, len;
-	int chipnum;
-	int ret = 0;
-	int i;
-	int first;
-	struct mtd_erase_region_info *regions = mtd->eraseregions;
-
-	if (instr->addr > mtd->size) {
-		return -EINVAL;
-	}
-
-	if ((instr->len + instr->addr) > mtd->size) {
-		return -EINVAL;
-	}
-
-	/* Check that both start and end of the requested erase are
-	 * aligned with the erasesize at the appropriate addresses.
-	 */
-
-	i = 0;
-
-        /* Skip all erase regions which are ended before the start of
-           the requested erase. Actually, to save on the calculations,
-           we skip to the first erase region which starts after the
-           start of the requested erase, and then go back one.
-        */
-
-        while ((i < mtd->numeraseregions) &&
-	       (instr->addr >= regions[i].offset)) {
-               i++;
-	}
-        i--;
-
-	/* OK, now i is pointing at the erase region in which this
-	 * erase request starts. Check the start of the requested
-	 * erase range is aligned with the erase size which is in
-	 * effect here.
-	 */
-
-	if (instr->addr & (regions[i].erasesize-1)) {
-		return -EINVAL;
-	}
-
-	/* Remember the erase region we start on. */
-
-	first = i;
-
-	/* Next, check that the end of the requested erase is aligned
-	 * with the erase region at that address.
-	 */
-
-	while ((i < mtd->numeraseregions) &&
-	       ((instr->addr + instr->len) >= regions[i].offset)) {
-                i++;
-	}
-
-	/* As before, drop back one to point at the region in which
-	 * the address actually falls.
-	 */
-
-	i--;
-
-	if ((instr->addr + instr->len) & (regions[i].erasesize-1)) {
-                return -EINVAL;
-	}
-
-	chipnum = instr->addr >> private->chipshift;
-	adr = instr->addr - (chipnum << private->chipshift);
-	len = instr->len;
-
-	i = first;
-
-	while (len) {
-		ret = erase_one_block(map, &private->chips[chipnum], adr,
-				      regions[i].erasesize);
-
-		if (ret) {
-			return ret;
-		}
-
-		adr += regions[i].erasesize;
-		len -= regions[i].erasesize;
-
-		if ((adr % (1 << private->chipshift)) ==
-		    ((regions[i].offset + (regions[i].erasesize *
-		    			   regions[i].numblocks))
-		     % (1 << private->chipshift))) {
-			i++;
-		}
-
-		if (adr >> private->chipshift) {
-			adr = 0;
-			chipnum++;
-			if (chipnum >= private->numchips) {
-				break;
-			}
-		}
-	}
-
-	instr->state = MTD_ERASE_DONE;
-	mtd_erase_callback(instr);
-
-	return 0;
-}
-
-
-
-static void amd_flash_sync(struct mtd_info *mtd)
-{
-	struct map_info *map = mtd->priv;
-	struct amd_flash_private *private = map->fldrv_priv;
-	int i;
-	struct flchip *chip;
-	int ret = 0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	for (i = 0; !ret && (i < private->numchips); i++) {
-		chip = &private->chips[i];
-
-	retry:
-		spin_lock_bh(chip->mutex);
-
-		switch(chip->state) {
-		case FL_READY:
-		case FL_STATUS:
-		case FL_CFI_QUERY:
-		case FL_JEDEC_QUERY:
-			chip->oldstate = chip->state;
-			chip->state = FL_SYNCING;
-			/* No need to wake_up() on this state change -
-			 * as the whole point is that nobody can do anything
-			 * with the chip now anyway.
-			 */
-		case FL_SYNCING:
-			spin_unlock_bh(chip->mutex);
-			break;
-
-		default:
-			/* Not an idle state */
-			add_wait_queue(&chip->wq, &wait);
-
-			spin_unlock_bh(chip->mutex);
-
-			schedule();
-
-		        remove_wait_queue(&chip->wq, &wait);
-
-			goto retry;
-		}
-	}
-
-	/* Unlock the chips again */
-	for (i--; i >= 0; i--) {
-		chip = &private->chips[i];
-
-		spin_lock_bh(chip->mutex);
-
-		if (chip->state == FL_SYNCING) {
-			chip->state = chip->oldstate;
-			wake_up(&chip->wq);
-		}
-		spin_unlock_bh(chip->mutex);
-	}
-}
-
-
-
-static int amd_flash_suspend(struct mtd_info *mtd)
-{
-printk("amd_flash_suspend(): not implemented!\n");
-	return -EINVAL;
-}
-
-
-
-static void amd_flash_resume(struct mtd_info *mtd)
-{
-printk("amd_flash_resume(): not implemented!\n");
-}
-
-
-
-static void amd_flash_destroy(struct mtd_info *mtd)
-{
-	struct map_info *map = mtd->priv;
-	struct amd_flash_private *private = map->fldrv_priv;
-	kfree(private);
-}
-
-int __init amd_flash_init(void)
-{
-	register_mtd_chip_driver(&amd_flash_chipdrv);
-	return 0;
-}
-
-void __exit amd_flash_exit(void)
-{
-	unregister_mtd_chip_driver(&amd_flash_chipdrv);
-}
-
-module_init(amd_flash_init);
-module_exit(amd_flash_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jonas Holmberg <jonas.holmberg@axis.com>");
-MODULE_DESCRIPTION("Old MTD chip driver for AMD flash chips");
diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
deleted file mode 100644
index 14e57b2bf8424ccc287a184bdd9e08a26f7925c4..0000000000000000000000000000000000000000
--- a/drivers/mtd/chips/jedec.c
+++ /dev/null
@@ -1,935 +0,0 @@
-
-/* JEDEC Flash Interface.
- * This is an older type of interface for self programming flash. It is
- * commonly use in older AMD chips and is obsolete compared with CFI.
- * It is called JEDEC because the JEDEC association distributes the ID codes
- * for the chips.
- *
- * See the AMD flash databook for information on how to operate the interface.
- *
- * This code does not support anything wider than 8 bit flash chips, I am
- * not going to guess how to send commands to them, plus I expect they will
- * all speak CFI..
- *
- * $Id: jedec.c,v 1.22 2005/01/05 18:05:11 dwmw2 Exp $
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mtd/jedec.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/compatmac.h>
-
-static struct mtd_info *jedec_probe(struct map_info *);
-static int jedec_probe8(struct map_info *map,unsigned long base,
-		  struct jedec_private *priv);
-static int jedec_probe16(struct map_info *map,unsigned long base,
-		  struct jedec_private *priv);
-static int jedec_probe32(struct map_info *map,unsigned long base,
-		  struct jedec_private *priv);
-static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start,
-			    unsigned long len);
-static int flash_erase(struct mtd_info *mtd, struct erase_info *instr);
-static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
-		       size_t *retlen, const u_char *buf);
-
-static unsigned long my_bank_size;
-
-/* Listing of parts and sizes. We need this table to learn the sector
-   size of the chip and the total length */
-static const struct JEDECTable JEDEC_table[] = {
-	{
-		.jedec		= 0x013D,
-		.name		= "AMD Am29F017D",
-		.size		= 2*1024*1024,
-		.sectorsize	= 64*1024,
-		.capabilities	= MTD_CAP_NORFLASH
-	},
-	{
-		.jedec		= 0x01AD,
-		.name		= "AMD Am29F016",
-		.size		= 2*1024*1024,
-		.sectorsize	= 64*1024,
-		.capabilities	= MTD_CAP_NORFLASH
-	},
-	{
-		.jedec		= 0x01D5,
-		.name		= "AMD Am29F080",
-		.size		= 1*1024*1024,
-		.sectorsize	= 64*1024,
-		.capabilities	= MTD_CAP_NORFLASH
-	},
-	{
-		.jedec		= 0x01A4,
-		.name		= "AMD Am29F040",
-		.size		= 512*1024,
-		.sectorsize	= 64*1024,
-		.capabilities	= MTD_CAP_NORFLASH
-	},
-	{
-		.jedec		= 0x20E3,
-		.name		= "AMD Am29W040B",
-		.size		= 512*1024,
-		.sectorsize	= 64*1024,
-		.capabilities	= MTD_CAP_NORFLASH
-	},
-	{
-		.jedec		= 0xC2AD,
-		.name		= "Macronix MX29F016",
-		.size		= 2*1024*1024,
-		.sectorsize	= 64*1024,
-		.capabilities	= MTD_CAP_NORFLASH
-	},
-	{ .jedec = 0x0 }
-};
-
-static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id);
-static void jedec_sync(struct mtd_info *mtd) {};
-static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
-		      size_t *retlen, u_char *buf);
-static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
-			     size_t *retlen, u_char *buf);
-
-static struct mtd_info *jedec_probe(struct map_info *map);
-
-
-
-static struct mtd_chip_driver jedec_chipdrv = {
-	.probe	= jedec_probe,
-	.name	= "jedec",
-	.module	= THIS_MODULE
-};
-
-/* Probe entry point */
-
-static struct mtd_info *jedec_probe(struct map_info *map)
-{
-   struct mtd_info *MTD;
-   struct jedec_private *priv;
-   unsigned long Base;
-   unsigned long SectorSize;
-   unsigned count;
-   unsigned I,Uniq;
-   char Part[200];
-   memset(&priv,0,sizeof(priv));
-
-   MTD = kzalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL);
-   if (!MTD)
-	   return NULL;
-
-   priv = (struct jedec_private *)&MTD[1];
-
-   my_bank_size = map->size;
-
-   if (map->size/my_bank_size > MAX_JEDEC_CHIPS)
-   {
-      printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n");
-      kfree(MTD);
-      return NULL;
-   }
-
-   for (Base = 0; Base < map->size; Base += my_bank_size)
-   {
-      // Perhaps zero could designate all tests?
-      if (map->buswidth == 0)
-	 map->buswidth = 1;
-
-      if (map->buswidth == 1){
-	 if (jedec_probe8(map,Base,priv) == 0) {
-		 printk("did recognize jedec chip\n");
-		 kfree(MTD);
-	         return NULL;
-	 }
-      }
-      if (map->buswidth == 2)
-	 jedec_probe16(map,Base,priv);
-      if (map->buswidth == 4)
-	 jedec_probe32(map,Base,priv);
-   }
-
-   // Get the biggest sector size
-   SectorSize = 0;
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-	   //	   printk("priv->chips[%d].jedec is %x\n",I,priv->chips[I].jedec);
-	   //	   printk("priv->chips[%d].sectorsize is %lx\n",I,priv->chips[I].sectorsize);
-      if (priv->chips[I].sectorsize > SectorSize)
-	 SectorSize = priv->chips[I].sectorsize;
-   }
-
-   // Quickly ensure that the other sector sizes are factors of the largest
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      if ((SectorSize/priv->chips[I].sectorsize)*priv->chips[I].sectorsize != SectorSize)
-      {
-	 printk("mtd: Failed. Device has incompatible mixed sector sizes\n");
-	 kfree(MTD);
-	 return NULL;
-      }
-   }
-
-   /* Generate a part name that includes the number of different chips and
-      other configuration information */
-   count = 1;
-   strlcpy(Part,map->name,sizeof(Part)-10);
-   strcat(Part," ");
-   Uniq = 0;
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      const struct JEDECTable *JEDEC;
-
-      if (priv->chips[I+1].jedec == priv->chips[I].jedec)
-      {
-	 count++;
-	 continue;
-      }
-
-      // Locate the chip in the jedec table
-      JEDEC = jedec_idtoinf(priv->chips[I].jedec >> 8,priv->chips[I].jedec);
-      if (JEDEC == 0)
-      {
-	 printk("mtd: Internal Error, JEDEC not set\n");
-	 kfree(MTD);
-	 return NULL;
-      }
-
-      if (Uniq != 0)
-	 strcat(Part,",");
-      Uniq++;
-
-      if (count != 1)
-	 sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name);
-      else
-	 sprintf(Part+strlen(Part),"%s",JEDEC->name);
-      if (strlen(Part) > sizeof(Part)*2/3)
-	 break;
-      count = 1;
-   }
-
-   /* Determine if the chips are organized in a linear fashion, or if there
-      are empty banks. Note, the last bank does not count here, only the
-      first banks are important. Holes on non-bank boundaries can not exist
-      due to the way the detection algorithm works. */
-   if (priv->size < my_bank_size)
-      my_bank_size = priv->size;
-   priv->is_banked = 0;
-   //printk("priv->size is %x, my_bank_size is %x\n",priv->size,my_bank_size);
-   //printk("priv->bank_fill[0] is %x\n",priv->bank_fill[0]);
-   if (!priv->size) {
-	   printk("priv->size is zero\n");
-	   kfree(MTD);
-	   return NULL;
-   }
-   if (priv->size/my_bank_size) {
-	   if (priv->size/my_bank_size == 1) {
-		   priv->size = my_bank_size;
-	   }
-	   else {
-		   for (I = 0; I != priv->size/my_bank_size - 1; I++)
-		   {
-		      if (priv->bank_fill[I] != my_bank_size)
-			 priv->is_banked = 1;
-
-		      /* This even could be eliminated, but new de-optimized read/write
-			 functions have to be written */
-		      printk("priv->bank_fill[%d] is %lx, priv->bank_fill[0] is %lx\n",I,priv->bank_fill[I],priv->bank_fill[0]);
-		      if (priv->bank_fill[I] != priv->bank_fill[0])
-		      {
-			 printk("mtd: Failed. Cannot handle unsymmetric banking\n");
-			 kfree(MTD);
-			 return NULL;
-		      }
-		   }
-	   }
-   }
-   if (priv->is_banked == 1)
-      strcat(Part,", banked");
-
-   //   printk("Part: '%s'\n",Part);
-
-   memset(MTD,0,sizeof(*MTD));
-  // strlcpy(MTD->name,Part,sizeof(MTD->name));
-   MTD->name = map->name;
-   MTD->type = MTD_NORFLASH;
-   MTD->flags = MTD_CAP_NORFLASH;
-   MTD->writesize = 1;
-   MTD->erasesize = SectorSize*(map->buswidth);
-   //   printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize);
-   MTD->size = priv->size;
-   //   printk("MTD->size is %x\n",(unsigned int)MTD->size);
-   //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module?
-   MTD->erase = flash_erase;
-   if (priv->is_banked == 1)
-      MTD->read = jedec_read_banked;
-   else
-      MTD->read = jedec_read;
-   MTD->write = flash_write;
-   MTD->sync = jedec_sync;
-   MTD->priv = map;
-   map->fldrv_priv = priv;
-   map->fldrv = &jedec_chipdrv;
-   __module_get(THIS_MODULE);
-   return MTD;
-}
-
-/* Helper for the JEDEC function, JEDEC numbers all have odd parity */
-static int checkparity(u_char C)
-{
-   u_char parity = 0;
-   while (C != 0)
-   {
-      parity ^= C & 1;
-      C >>= 1;
-   }
-
-   return parity == 1;
-}
-
-
-/* Take an array of JEDEC numbers that represent interleved flash chips
-   and process them. Check to make sure they are good JEDEC numbers, look
-   them up and then add them to the chip list */
-static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
-		  unsigned long base,struct jedec_private *priv)
-{
-   unsigned I,J;
-   unsigned long Size;
-   unsigned long SectorSize;
-   const struct JEDECTable *JEDEC;
-
-   // Test #2 JEDEC numbers exhibit odd parity
-   for (I = 0; I != Count; I++)
-   {
-      if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0)
-	 return 0;
-   }
-
-   // Finally, just make sure all the chip sizes are the same
-   JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
-
-   if (JEDEC == 0)
-   {
-      printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
-      return 0;
-   }
-
-   Size = JEDEC->size;
-   SectorSize = JEDEC->sectorsize;
-   for (I = 0; I != Count; I++)
-   {
-      JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
-      if (JEDEC == 0)
-      {
-	 printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
-	 return 0;
-      }
-
-      if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize)
-      {
-	 printk("mtd: Failed. Interleved flash does not have matching characteristics\n");
-	 return 0;
-      }
-   }
-
-   // Load the Chips
-   for (I = 0; I != MAX_JEDEC_CHIPS; I++)
-   {
-      if (priv->chips[I].jedec == 0)
-	 break;
-   }
-
-   if (I + Count > MAX_JEDEC_CHIPS)
-   {
-      printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n");
-      return 0;
-   }
-
-   // Add them to the table
-   for (J = 0; J != Count; J++)
-   {
-      unsigned long Bank;
-
-      JEDEC = jedec_idtoinf(Mfg[J],Id[J]);
-      priv->chips[I].jedec = (Mfg[J] << 8) | Id[J];
-      priv->chips[I].size = JEDEC->size;
-      priv->chips[I].sectorsize = JEDEC->sectorsize;
-      priv->chips[I].base = base + J;
-      priv->chips[I].datashift = J*8;
-      priv->chips[I].capabilities = JEDEC->capabilities;
-      priv->chips[I].offset = priv->size + J;
-
-      // log2 n :|
-      priv->chips[I].addrshift = 0;
-      for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++);
-
-      // Determine how filled this bank is.
-      Bank = base & (~(my_bank_size-1));
-      if (priv->bank_fill[Bank/my_bank_size] < base +
-	  (JEDEC->size << priv->chips[I].addrshift) - Bank)
-	 priv->bank_fill[Bank/my_bank_size] =  base + (JEDEC->size << priv->chips[I].addrshift) - Bank;
-      I++;
-   }
-
-   priv->size += priv->chips[I-1].size*Count;
-
-   return priv->chips[I-1].size;
-}
-
-/* Lookup the chip information from the JEDEC ID table. */
-static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id)
-{
-   __u16 Id = (mfr << 8) | id;
-   unsigned long I = 0;
-   for (I = 0; JEDEC_table[I].jedec != 0; I++)
-      if (JEDEC_table[I].jedec == Id)
-	 return JEDEC_table + I;
-   return NULL;
-}
-
-// Look for flash using an 8 bit bus interface
-static int jedec_probe8(struct map_info *map,unsigned long base,
-		  struct jedec_private *priv)
-{
-   #define flread(x) map_read8(map,base+x)
-   #define flwrite(v,x) map_write8(map,v,base+x)
-
-   const unsigned long AutoSel1 = 0xAA;
-   const unsigned long AutoSel2 = 0x55;
-   const unsigned long AutoSel3 = 0x90;
-   const unsigned long Reset = 0xF0;
-   __u32 OldVal;
-   __u8 Mfg[1];
-   __u8 Id[1];
-   unsigned I;
-   unsigned long Size;
-
-   // Wait for any write/erase operation to settle
-   OldVal = flread(base);
-   for (I = 0; OldVal != flread(base) && I < 10000; I++)
-      OldVal = flread(base);
-
-   // Reset the chip
-   flwrite(Reset,0x555);
-
-   // Send the sequence
-   flwrite(AutoSel1,0x555);
-   flwrite(AutoSel2,0x2AA);
-   flwrite(AutoSel3,0x555);
-
-   //  Get the JEDEC numbers
-   Mfg[0] = flread(0);
-   Id[0] = flread(1);
-   //   printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]);
-
-   Size = handle_jedecs(map,Mfg,Id,1,base,priv);
-   //   printk("handle_jedecs Size is %x\n",(unsigned int)Size);
-   if (Size == 0)
-   {
-      flwrite(Reset,0x555);
-      return 0;
-   }
-
-
-   // Reset.
-   flwrite(Reset,0x555);
-
-   return 1;
-
-   #undef flread
-   #undef flwrite
-}
-
-// Look for flash using a 16 bit bus interface (ie 2 8-bit chips)
-static int jedec_probe16(struct map_info *map,unsigned long base,
-		  struct jedec_private *priv)
-{
-   return 0;
-}
-
-// Look for flash using a 32 bit bus interface (ie 4 8-bit chips)
-static int jedec_probe32(struct map_info *map,unsigned long base,
-		  struct jedec_private *priv)
-{
-   #define flread(x) map_read32(map,base+((x)<<2))
-   #define flwrite(v,x) map_write32(map,v,base+((x)<<2))
-
-   const unsigned long AutoSel1 = 0xAAAAAAAA;
-   const unsigned long AutoSel2 = 0x55555555;
-   const unsigned long AutoSel3 = 0x90909090;
-   const unsigned long Reset = 0xF0F0F0F0;
-   __u32 OldVal;
-   __u8 Mfg[4];
-   __u8 Id[4];
-   unsigned I;
-   unsigned long Size;
-
-   // Wait for any write/erase operation to settle
-   OldVal = flread(base);
-   for (I = 0; OldVal != flread(base) && I < 10000; I++)
-      OldVal = flread(base);
-
-   // Reset the chip
-   flwrite(Reset,0x555);
-
-   // Send the sequence
-   flwrite(AutoSel1,0x555);
-   flwrite(AutoSel2,0x2AA);
-   flwrite(AutoSel3,0x555);
-
-   // Test #1, JEDEC numbers are readable from 0x??00/0x??01
-   if (flread(0) != flread(0x100) ||
-       flread(1) != flread(0x101))
-   {
-      flwrite(Reset,0x555);
-      return 0;
-   }
-
-   // Split up the JEDEC numbers
-   OldVal = flread(0);
-   for (I = 0; I != 4; I++)
-      Mfg[I] = (OldVal >> (I*8));
-   OldVal = flread(1);
-   for (I = 0; I != 4; I++)
-      Id[I] = (OldVal >> (I*8));
-
-   Size = handle_jedecs(map,Mfg,Id,4,base,priv);
-   if (Size == 0)
-   {
-      flwrite(Reset,0x555);
-      return 0;
-   }
-
-   /* Check if there is address wrap around within a single bank, if this
-      returns JEDEC numbers then we assume that it is wrap around. Notice
-      we call this routine with the JEDEC return still enabled, if two or
-      more flashes have a truncated address space the probe test will still
-      work */
-   if (base + (Size<<2)+0x555 < map->size &&
-       base + (Size<<2)+0x555 < (base & (~(my_bank_size-1))) + my_bank_size)
-   {
-      if (flread(base+Size) != flread(base+Size + 0x100) ||
-	  flread(base+Size + 1) != flread(base+Size + 0x101))
-      {
-	 jedec_probe32(map,base+Size,priv);
-      }
-   }
-
-   // Reset.
-   flwrite(0xF0F0F0F0,0x555);
-
-   return 1;
-
-   #undef flread
-   #undef flwrite
-}
-
-/* Linear read. */
-static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
-		      size_t *retlen, u_char *buf)
-{
-   struct map_info *map = mtd->priv;
-
-   map_copy_from(map, buf, from, len);
-   *retlen = len;
-   return 0;
-}
-
-/* Banked read. Take special care to jump past the holes in the bank
-   mapping. This version assumes symetry in the holes.. */
-static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
-			     size_t *retlen, u_char *buf)
-{
-   struct map_info *map = mtd->priv;
-   struct jedec_private *priv = map->fldrv_priv;
-
-   *retlen = 0;
-   while (len > 0)
-   {
-      // Determine what bank and offset into that bank the first byte is
-      unsigned long bank = from & (~(priv->bank_fill[0]-1));
-      unsigned long offset = from & (priv->bank_fill[0]-1);
-      unsigned long get = len;
-      if (priv->bank_fill[0] - offset < len)
-	 get = priv->bank_fill[0] - offset;
-
-      bank /= priv->bank_fill[0];
-      map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get);
-
-      len -= get;
-      *retlen += get;
-      from += get;
-   }
-   return 0;
-}
-
-/* Pass the flags value that the flash return before it re-entered read
-   mode. */
-static void jedec_flash_failed(unsigned char code)
-{
-   /* Bit 5 being high indicates that there was an internal device
-      failure, erasure time limits exceeded or something */
-   if ((code & (1 << 5)) != 0)
-   {
-      printk("mtd: Internal Flash failure\n");
-      return;
-   }
-   printk("mtd: Programming didn't take\n");
-}
-
-/* This uses the erasure function described in the AMD Flash Handbook,
-   it will work for flashes with a fixed sector size only. Flashes with
-   a selection of sector sizes (ie the AMD Am29F800B) will need a different
-   routine. This routine tries to parallize erasing multiple chips/sectors
-   where possible */
-static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-   // Does IO to the currently selected chip
-   #define flread(x) map_read8(map,chip->base+((x)<<chip->addrshift))
-   #define flwrite(v,x) map_write8(map,v,chip->base+((x)<<chip->addrshift))
-
-   unsigned long Time = 0;
-   unsigned long NoTime = 0;
-   unsigned long start = instr->addr, len = instr->len;
-   unsigned int I;
-   struct map_info *map = mtd->priv;
-   struct jedec_private *priv = map->fldrv_priv;
-
-   // Verify the arguments..
-   if (start + len > mtd->size ||
-       (start % mtd->erasesize) != 0 ||
-       (len % mtd->erasesize) != 0 ||
-       (len/mtd->erasesize) == 0)
-      return -EINVAL;
-
-   jedec_flash_chip_scan(priv,start,len);
-
-   // Start the erase sequence on each chip
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      unsigned long off;
-      struct jedec_flash_chip *chip = priv->chips + I;
-
-      if (chip->length == 0)
-	 continue;
-
-      if (chip->start + chip->length > chip->size)
-      {
-	 printk("DIE\n");
-	 return -EIO;
-      }
-
-      flwrite(0xF0,chip->start + 0x555);
-      flwrite(0xAA,chip->start + 0x555);
-      flwrite(0x55,chip->start + 0x2AA);
-      flwrite(0x80,chip->start + 0x555);
-      flwrite(0xAA,chip->start + 0x555);
-      flwrite(0x55,chip->start + 0x2AA);
-
-      /* Once we start selecting the erase sectors the delay between each
-         command must not exceed 50us or it will immediately start erasing
-         and ignore the other sectors */
-      for (off = 0; off < len; off += chip->sectorsize)
-      {
-	 // Check to make sure we didn't timeout
-	 flwrite(0x30,chip->start + off);
-	 if (off == 0)
-	    continue;
-	 if ((flread(chip->start + off) & (1 << 3)) != 0)
-	 {
-	    printk("mtd: Ack! We timed out the erase timer!\n");
-	    return -EIO;
-	 }
-      }
-   }
-
-   /* We could split this into a timer routine and return early, performing
-      background erasure.. Maybe later if the need warrents */
-
-   /* Poll the flash for erasure completion, specs say this can take as long
-      as 480 seconds to do all the sectors (for a 2 meg flash).
-      Erasure time is dependent on chip age, temp and wear.. */
-
-   /* This being a generic routine assumes a 32 bit bus. It does read32s
-      and bundles interleved chips into the same grouping. This will work
-      for all bus widths */
-   Time = 0;
-   NoTime = 0;
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      struct jedec_flash_chip *chip = priv->chips + I;
-      unsigned long off = 0;
-      unsigned todo[4] = {0,0,0,0};
-      unsigned todo_left = 0;
-      unsigned J;
-
-      if (chip->length == 0)
-	 continue;
-
-      /* Find all chips in this data line, realistically this is all
-         or nothing up to the interleve count */
-      for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
-      {
-	 if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
-	     (chip->base & (~((1<<chip->addrshift)-1))))
-	 {
-	    todo_left++;
-	    todo[priv->chips[J].base & ((1<<chip->addrshift)-1)] = 1;
-	 }
-      }
-
-      /*      printk("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1],
-	      (short)todo[2],(short)todo[3]);
-      */
-      while (1)
-      {
-	 __u32 Last[4];
-	 unsigned long Count = 0;
-
-	 /* During erase bit 7 is held low and bit 6 toggles, we watch this,
-	    should it stop toggling or go high then the erase is completed,
-  	    or this is not really flash ;> */
-	 switch (map->buswidth) {
-	 case 1:
-	    Last[0] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
-	    Last[1] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
-	    Last[2] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
-	    break;
-	 case 2:
-	    Last[0] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
-	    Last[1] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
-	    Last[2] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
-	    break;
-	 case 3:
-	    Last[0] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
-	    Last[1] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
-	    Last[2] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
-	    break;
-	 }
-	 Count = 3;
-	 while (todo_left != 0)
-	 {
-	    for (J = 0; J != 4; J++)
-	    {
-	       __u8 Byte1 = (Last[(Count-1)%4] >> (J*8)) & 0xFF;
-	       __u8 Byte2 = (Last[(Count-2)%4] >> (J*8)) & 0xFF;
-	       __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF;
-	       if (todo[J] == 0)
-		  continue;
-
-	       if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2)
-	       {
-//		  printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2);
-		  continue;
-	       }
-
-	       if (Byte1 == Byte2)
-	       {
-		  jedec_flash_failed(Byte3);
-		  return -EIO;
-	       }
-
-	       todo[J] = 0;
-	       todo_left--;
-	    }
-
-/*	    if (NoTime == 0)
-	       Time += HZ/10 - schedule_timeout(HZ/10);*/
-	    NoTime = 0;
-
-	    switch (map->buswidth) {
-	    case 1:
-	       Last[Count % 4] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off);
-	      break;
-	    case 2:
-	       Last[Count % 4] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off);
-	      break;
-	    case 4:
-	       Last[Count % 4] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off);
-	      break;
-	    }
-	    Count++;
-
-/*	    // Count time, max of 15s per sector (according to AMD)
-	    if (Time > 15*len/mtd->erasesize*HZ)
-	    {
-	       printk("mtd: Flash Erase Timed out\n");
-	       return -EIO;
-	    }	    */
-	 }
-
-	 // Skip to the next chip if we used chip erase
-	 if (chip->length == chip->size)
-	    off = chip->size;
-	 else
-	    off += chip->sectorsize;
-
-	 if (off >= chip->length)
-	    break;
-	 NoTime = 1;
-      }
-
-      for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
-      {
-	 if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
-	     (chip->base & (~((1<<chip->addrshift)-1))))
-	    priv->chips[J].length = 0;
-      }
-   }
-
-   //printk("done\n");
-   instr->state = MTD_ERASE_DONE;
-   mtd_erase_callback(instr);
-   return 0;
-
-   #undef flread
-   #undef flwrite
-}
-
-/* This is the simple flash writing function. It writes to every byte, in
-   sequence. It takes care of how to properly address the flash if
-   the flash is interleved. It can only be used if all the chips in the
-   array are identical!*/
-static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
-		       size_t *retlen, const u_char *buf)
-{
-   /* Does IO to the currently selected chip. It takes the bank addressing
-      base (which is divisible by the chip size) adds the necessary lower bits
-      of addrshift (interleave index) and then adds the control register index. */
-   #define flread(x) map_read8(map,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
-   #define flwrite(v,x) map_write8(map,v,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
-
-   struct map_info *map = mtd->priv;
-   struct jedec_private *priv = map->fldrv_priv;
-   unsigned long base;
-   unsigned long off;
-   size_t save_len = len;
-
-   if (start + len > mtd->size)
-      return -EIO;
-
-   //printk("Here");
-
-   //printk("flash_write: start is %x, len is %x\n",start,(unsigned long)len);
-   while (len != 0)
-   {
-      struct jedec_flash_chip *chip = priv->chips;
-      unsigned long bank;
-      unsigned long boffset;
-
-      // Compute the base of the flash.
-      off = ((unsigned long)start) % (chip->size << chip->addrshift);
-      base = start - off;
-
-      // Perform banked addressing translation.
-      bank = base & (~(priv->bank_fill[0]-1));
-      boffset = base & (priv->bank_fill[0]-1);
-      bank = (bank/priv->bank_fill[0])*my_bank_size;
-      base = bank + boffset;
-
-    //  printk("Flasing %X %X %X\n",base,chip->size,len);
-     // printk("off is %x, compare with %x\n",off,chip->size << chip->addrshift);
-
-      // Loop over this page
-      for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++)
-      {
-	 unsigned char oldbyte = map_read8(map,base+off);
-	 unsigned char Last[4];
-	 unsigned long Count = 0;
-
-	 if (oldbyte == *buf) {
-	//	 printk("oldbyte and *buf is %x,len is %x\n",oldbyte,len);
-	    continue;
-	 }
-	 if (((~oldbyte) & *buf) != 0)
-	    printk("mtd: warn: Trying to set a 0 to a 1\n");
-
-	 // Write
-	 flwrite(0xAA,0x555);
-	 flwrite(0x55,0x2AA);
-	 flwrite(0xA0,0x555);
-	 map_write8(map,*buf,base + off);
-	 Last[0] = map_read8(map,base + off);
-	 Last[1] = map_read8(map,base + off);
-	 Last[2] = map_read8(map,base + off);
-
-	 /* Wait for the flash to finish the operation. We store the last 4
-	    status bytes that have been retrieved so we can determine why
-	    it failed. The toggle bits keep toggling when there is a
-	    failure */
-	 for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] &&
-	      Count < 10000; Count++)
-	    Last[Count % 4] = map_read8(map,base + off);
-	 if (Last[(Count - 1) % 4] != *buf)
-	 {
-	    jedec_flash_failed(Last[(Count - 3) % 4]);
-	    return -EIO;
-	 }
-      }
-   }
-   *retlen = save_len;
-   return 0;
-}
-
-/* This is used to enhance the speed of the erase routine,
-   when things are being done to multiple chips it is possible to
-   parallize the operations, particularly full memory erases of multi
-   chip memories benifit */
-static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start,
-		     unsigned long len)
-{
-   unsigned int I;
-
-   // Zero the records
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-      priv->chips[I].start = priv->chips[I].length = 0;
-
-   // Intersect the region with each chip
-   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
-   {
-      struct jedec_flash_chip *chip = priv->chips + I;
-      unsigned long ByteStart;
-      unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift);
-
-      // End is before this chip or the start is after it
-      if (start+len < chip->offset ||
-	  ChipEndByte - (1 << chip->addrshift) < start)
-	 continue;
-
-      if (start < chip->offset)
-      {
-	 ByteStart = chip->offset;
-	 chip->start = 0;
-      }
-      else
-      {
-	 chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift;
-	 ByteStart = start;
-      }
-
-      if (start + len >= ChipEndByte)
-	 chip->length = (ChipEndByte - ByteStart) >> chip->addrshift;
-      else
-	 chip->length = (start + len - ByteStart + (1 << chip->addrshift)-1) >> chip->addrshift;
-   }
-}
-
-int __init jedec_init(void)
-{
-	register_mtd_chip_driver(&jedec_chipdrv);
-	return 0;
-}
-
-static void __exit jedec_exit(void)
-{
-	unregister_mtd_chip_driver(&jedec_chipdrv);
-}
-
-module_init(jedec_init);
-module_exit(jedec_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jason Gunthorpe <jgg@deltatee.com> et al.");
-MODULE_DESCRIPTION("Old MTD chip driver for JEDEC-compliant flash chips");
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
deleted file mode 100644
index c9cd3d21ccfaa98c64d976e29cabc0fef28ee7d0..0000000000000000000000000000000000000000
--- a/drivers/mtd/chips/sharp.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * MTD chip driver for pre-CFI Sharp flash chips
- *
- * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
- *           2000,2001 Lineo, Inc.
- *
- * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $
- *
- * Devices supported:
- *   LH28F016SCT Symmetrical block flash memory, 2Mx8
- *   LH28F008SCT Symmetrical block flash memory, 1Mx8
- *
- * Documentation:
- *   http://www.sharpmeg.com/datasheets/memic/flashcmp/
- *   http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf
- *   016sctl9.pdf
- *
- * Limitations:
- *   This driver only supports 4x1 arrangement of chips.
- *   Not tested on anything but PowerPC.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/cfi.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#define CMD_RESET		0xffffffff
-#define CMD_READ_ID		0x90909090
-#define CMD_READ_STATUS		0x70707070
-#define CMD_CLEAR_STATUS	0x50505050
-#define CMD_BLOCK_ERASE_1	0x20202020
-#define CMD_BLOCK_ERASE_2	0xd0d0d0d0
-#define CMD_BYTE_WRITE		0x40404040
-#define CMD_SUSPEND		0xb0b0b0b0
-#define CMD_RESUME		0xd0d0d0d0
-#define CMD_SET_BLOCK_LOCK_1	0x60606060
-#define CMD_SET_BLOCK_LOCK_2	0x01010101
-#define CMD_SET_MASTER_LOCK_1	0x60606060
-#define CMD_SET_MASTER_LOCK_2	0xf1f1f1f1
-#define CMD_CLEAR_BLOCK_LOCKS_1	0x60606060
-#define CMD_CLEAR_BLOCK_LOCKS_2	0xd0d0d0d0
-
-#define SR_READY		0x80808080 // 1 = ready
-#define SR_ERASE_SUSPEND	0x40404040 // 1 = block erase suspended
-#define SR_ERROR_ERASE		0x20202020 // 1 = error in block erase or clear lock bits
-#define SR_ERROR_WRITE		0x10101010 // 1 = error in byte write or set lock bit
-#define	SR_VPP			0x08080808 // 1 = Vpp is low
-#define SR_WRITE_SUSPEND	0x04040404 // 1 = byte write suspended
-#define SR_PROTECT		0x02020202 // 1 = lock bit set
-#define SR_RESERVED		0x01010101
-
-#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)
-
-/* Configuration options */
-
-#undef AUTOUNLOCK  /* automatically unlocks blocks before erasing */
-
-static struct mtd_info *sharp_probe(struct map_info *);
-
-static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);
-
-static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
-	size_t *retlen, u_char *buf);
-static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len,
-	size_t *retlen, const u_char *buf);
-static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr);
-static void sharp_sync(struct mtd_info *mtd);
-static int sharp_suspend(struct mtd_info *mtd);
-static void sharp_resume(struct mtd_info *mtd);
-static void sharp_destroy(struct mtd_info *mtd);
-
-static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
-	unsigned long adr, __u32 datum);
-static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
-	unsigned long adr);
-#ifdef AUTOUNLOCK
-static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
-	unsigned long adr);
-#endif
-
-
-struct sharp_info{
-	struct flchip *chip;
-	int bogus;
-	int chipshift;
-	int numchips;
-	struct flchip chips[1];
-};
-
-static void sharp_destroy(struct mtd_info *mtd);
-
-static struct mtd_chip_driver sharp_chipdrv = {
-	.probe		= sharp_probe,
-	.destroy	= sharp_destroy,
-	.name		= "sharp",
-	.module		= THIS_MODULE
-};
-
-
-static struct mtd_info *sharp_probe(struct map_info *map)
-{
-	struct mtd_info *mtd = NULL;
-	struct sharp_info *sharp = NULL;
-	int width;
-
-	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
-	if(!mtd)
-		return NULL;
-
-	sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
-	if(!sharp) {
-		kfree(mtd);
-		return NULL;
-	}
-
-	width = sharp_probe_map(map,mtd);
-	if(!width){
-		kfree(mtd);
-		kfree(sharp);
-		return NULL;
-	}
-
-	mtd->priv = map;
-	mtd->type = MTD_NORFLASH;
-	mtd->erase = sharp_erase;
-	mtd->read = sharp_read;
-	mtd->write = sharp_write;
-	mtd->sync = sharp_sync;
-	mtd->suspend = sharp_suspend;
-	mtd->resume = sharp_resume;
-	mtd->flags = MTD_CAP_NORFLASH;
-	mtd->writesize = 1;
-	mtd->name = map->name;
-
-	sharp->chipshift = 23;
-	sharp->numchips = 1;
-	sharp->chips[0].start = 0;
-	sharp->chips[0].state = FL_READY;
-	sharp->chips[0].mutex = &sharp->chips[0]._spinlock;
-	sharp->chips[0].word_write_time = 0;
-	init_waitqueue_head(&sharp->chips[0].wq);
-	spin_lock_init(&sharp->chips[0]._spinlock);
-
-	map->fldrv = &sharp_chipdrv;
-	map->fldrv_priv = sharp;
-
-	__module_get(THIS_MODULE);
-	return mtd;
-}
-
-static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr)
-{
-	map_word map_cmd;
-	map_cmd.x[0] = cmd;
-	map_write(map, map_cmd, adr);
-}
-
-static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
-{
-	map_word tmp, read0, read4;
-	unsigned long base = 0;
-	int width = 4;
-
-	tmp = map_read(map, base+0);
-
-	sharp_send_cmd(map, CMD_READ_ID, base+0);
-
-	read0 = map_read(map, base+0);
-	read4 = map_read(map, base+4);
-	if(read0.x[0] == 0x89898989){
-		printk("Looks like sharp flash\n");
-		switch(read4.x[0]){
-		case 0xaaaaaaaa:
-		case 0xa0a0a0a0:
-			/* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
-			/* a0 - LH28F016SCT-Z4  2Mx8, 32 64k blocks*/
-			mtd->erasesize = 0x10000 * width;
-			mtd->size = 0x200000 * width;
-			return width;
-		case 0xa6a6a6a6:
-			/* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
-			/* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
-			mtd->erasesize = 0x10000 * width;
-			mtd->size = 0x100000 * width;
-			return width;
-#if 0
-		case 0x00000000: /* unknown */
-			/* XX - LH28F004SCT 512kx8, 8 64k blocks*/
-			mtd->erasesize = 0x10000 * width;
-			mtd->size = 0x80000 * width;
-			return width;
-#endif
-		default:
-			printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n",
-				read0.x[0], read4.x[0]);
-		}
-	}else if((map_read(map, base+0).x[0] == CMD_READ_ID)){
-		/* RAM, probably */
-		printk("Looks like RAM\n");
-		map_write(map, tmp, base+0);
-	}else{
-		printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n",
-			read0.x[0], read4.x[0]);
-	}
-
-	return 0;
-}
-
-/* This function returns with the chip->mutex lock held. */
-static int sharp_wait(struct map_info *map, struct flchip *chip)
-{
-	int i;
-	map_word status;
-	unsigned long timeo = jiffies + HZ;
-	DECLARE_WAITQUEUE(wait, current);
-	int adr = 0;
-
-retry:
-	spin_lock_bh(chip->mutex);
-
-	switch(chip->state){
-	case FL_READY:
-		sharp_send_cmd(map, CMD_READ_STATUS, adr);
-		chip->state = FL_STATUS;
-	case FL_STATUS:
-		for(i=0;i<100;i++){
-			status = map_read(map, adr);
-			if((status.x[0] & SR_READY)==SR_READY)
-				break;
-			udelay(1);
-		}
-		break;
-	default:
-		printk("Waiting for chip\n");
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		add_wait_queue(&chip->wq, &wait);
-
-		spin_unlock_bh(chip->mutex);
-
-		schedule();
-		remove_wait_queue(&chip->wq, &wait);
-
-		if(signal_pending(current))
-			return -EINTR;
-
-		timeo = jiffies + HZ;
-
-		goto retry;
-	}
-
-	sharp_send_cmd(map, CMD_RESET, adr);
-
-	chip->state = FL_READY;
-
-	return 0;
-}
-
-static void sharp_release(struct flchip *chip)
-{
-	wake_up(&chip->wq);
-	spin_unlock_bh(chip->mutex);
-}
-
-static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
-	size_t *retlen, u_char *buf)
-{
-	struct map_info *map = mtd->priv;
-	struct sharp_info *sharp = map->fldrv_priv;
-	int chipnum;
-	int ret = 0;
-	int ofs = 0;
-
-	chipnum = (from >> sharp->chipshift);
-	ofs = from & ((1 << sharp->chipshift)-1);
-
-	*retlen = 0;
-
-	while(len){
-		unsigned long thislen;
-
-		if(chipnum>=sharp->numchips)
-			break;
-
-		thislen = len;
-		if(ofs+thislen >= (1<<sharp->chipshift))
-			thislen = (1<<sharp->chipshift) - ofs;
-
-		ret = sharp_wait(map,&sharp->chips[chipnum]);
-		if(ret<0)
-			break;
-
-		map_copy_from(map,buf,ofs,thislen);
-
-		sharp_release(&sharp->chips[chipnum]);
-
-		*retlen += thislen;
-		len -= thislen;
-		buf += thislen;
-
-		ofs = 0;
-		chipnum++;
-	}
-	return ret;
-}
-
-static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
-	size_t *retlen, const u_char *buf)
-{
-	struct map_info *map = mtd->priv;
-	struct sharp_info *sharp = map->fldrv_priv;
-	int ret = 0;
-	int i,j;
-	int chipnum;
-	unsigned long ofs;
-	union { u32 l; unsigned char uc[4]; } tbuf;
-
-	*retlen = 0;
-
-	while(len){
-		tbuf.l = 0xffffffff;
-		chipnum = to >> sharp->chipshift;
-		ofs = to & ((1<<sharp->chipshift)-1);
-
-		j=0;
-		for(i=ofs&3;i<4 && len;i++){
-			tbuf.uc[i] = *buf;
-			buf++;
-			to++;
-			len--;
-			j++;
-		}
-		sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
-		if(ret<0)
-			return ret;
-		(*retlen)+=j;
-	}
-
-	return 0;
-}
-
-static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
-	unsigned long adr, __u32 datum)
-{
-	int ret;
-	int timeo;
-	int try;
-	int i;
-	map_word data, status;
-
-	status.x[0] = 0;
-	ret = sharp_wait(map,chip);
-
-	for(try=0;try<10;try++){
-		sharp_send_cmd(map, CMD_BYTE_WRITE, adr);
-		/* cpu_to_le32 -> hack to fix the writel be->le conversion */
-		data.x[0] = cpu_to_le32(datum);
-		map_write(map, data, adr);
-
-		chip->state = FL_WRITING;
-
-		timeo = jiffies + (HZ/2);
-
-		sharp_send_cmd(map, CMD_READ_STATUS, adr);
-		for(i=0;i<100;i++){
-			status = map_read(map, adr);
-			if((status.x[0] & SR_READY) == SR_READY)
-				break;
-		}
-		if(i==100){
-			printk("sharp: timed out writing\n");
-		}
-
-		if(!(status.x[0] & SR_ERRORS))
-			break;
-
-		printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]);
-
-		sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
-	}
-	sharp_send_cmd(map, CMD_RESET, adr);
-	chip->state = FL_READY;
-
-	wake_up(&chip->wq);
-	spin_unlock_bh(chip->mutex);
-
-	return 0;
-}
-
-static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-	struct map_info *map = mtd->priv;
-	struct sharp_info *sharp = map->fldrv_priv;
-	unsigned long adr,len;
-	int chipnum, ret=0;
-
-//printk("sharp_erase()\n");
-	if(instr->addr & (mtd->erasesize - 1))
-		return -EINVAL;
-	if(instr->len & (mtd->erasesize - 1))
-		return -EINVAL;
-	if(instr->len + instr->addr > mtd->size)
-		return -EINVAL;
-
-	chipnum = instr->addr >> sharp->chipshift;
-	adr = instr->addr & ((1<<sharp->chipshift)-1);
-	len = instr->len;
-
-	while(len){
-		ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
-		if(ret)return ret;
-
-		adr += mtd->erasesize;
-		len -= mtd->erasesize;
-		if(adr >> sharp->chipshift){
-			adr = 0;
-			chipnum++;
-			if(chipnum>=sharp->numchips)
-				break;
-		}
-	}
-
-	instr->state = MTD_ERASE_DONE;
-	mtd_erase_callback(instr);
-
-	return 0;
-}
-
-static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
-	unsigned long adr)
-{
-	int ret;
-	unsigned long timeo;
-	map_word status;
-	DECLARE_WAITQUEUE(wait, current);
-
-	sharp_send_cmd(map, CMD_READ_STATUS, adr);
-	status = map_read(map, adr);
-
-	timeo = jiffies + HZ;
-
-	while(time_before(jiffies, timeo)){
-		sharp_send_cmd(map, CMD_READ_STATUS, adr);
-		status = map_read(map, adr);
-		if((status.x[0] & SR_READY)==SR_READY){
-			ret = 0;
-			goto out;
-		}
-		set_current_state(TASK_INTERRUPTIBLE);
-		add_wait_queue(&chip->wq, &wait);
-
-		//spin_unlock_bh(chip->mutex);
-
-		schedule_timeout(1);
-		schedule();
-		remove_wait_queue(&chip->wq, &wait);
-
-		//spin_lock_bh(chip->mutex);
-
-		if (signal_pending(current)){
-			ret = -EINTR;
-			goto out;
-		}
-
-	}
-	ret = -ETIME;
-out:
-	return ret;
-}
-
-static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
-	unsigned long adr)
-{
-	int ret;
-	//int timeo;
-	map_word status;
-	//int i;
-
-//printk("sharp_erase_oneblock()\n");
-
-#ifdef AUTOUNLOCK
-	/* This seems like a good place to do an unlock */
-	sharp_unlock_oneblock(map,chip,adr);
-#endif
-
-	sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr);
-	sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr);
-
-	chip->state = FL_ERASING;
-
-	ret = sharp_do_wait_for_ready(map,chip,adr);
-	if(ret<0)return ret;
-
-	sharp_send_cmd(map, CMD_READ_STATUS, adr);
-	status = map_read(map, adr);
-
-	if(!(status.x[0] & SR_ERRORS)){
-		sharp_send_cmd(map, CMD_RESET, adr);
-		chip->state = FL_READY;
-		//spin_unlock_bh(chip->mutex);
-		return 0;
-	}
-
-	printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]);
-	sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
-
-	//spin_unlock_bh(chip->mutex);
-
-	return -EIO;
-}
-
-#ifdef AUTOUNLOCK
-static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
-	unsigned long adr)
-{
-	int i;
-	map_word status;
-
-	sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr);
-	sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr);
-
-	udelay(100);
-
-	status = map_read(map, adr);
-	printk("status=%08lx\n", status.x[0]);
-
-	for(i=0;i<1000;i++){
-		//sharp_send_cmd(map, CMD_READ_STATUS, adr);
-		status = map_read(map, adr);
-		if((status.x[0] & SR_READY) == SR_READY)
-			break;
-		udelay(100);
-	}
-	if(i==1000){
-		printk("sharp: timed out unlocking block\n");
-	}
-
-	if(!(status.x[0] & SR_ERRORS)){
-		sharp_send_cmd(map, CMD_RESET, adr);
-		chip->state = FL_READY;
-		return;
-	}
-
-	printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]);
-	sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
-}
-#endif
-
-static void sharp_sync(struct mtd_info *mtd)
-{
-	//printk("sharp_sync()\n");
-}
-
-static int sharp_suspend(struct mtd_info *mtd)
-{
-	printk("sharp_suspend()\n");
-	return -EINVAL;
-}
-
-static void sharp_resume(struct mtd_info *mtd)
-{
-	printk("sharp_resume()\n");
-
-}
-
-static void sharp_destroy(struct mtd_info *mtd)
-{
-	printk("sharp_destroy()\n");
-
-}
-
-static int __init sharp_probe_init(void)
-{
-	printk("MTD Sharp chip driver <ds@lineo.com>\n");
-
-	register_mtd_chip_driver(&sharp_chipdrv);
-
-	return 0;
-}
-
-static void __exit sharp_probe_exit(void)
-{
-	unregister_mtd_chip_driver(&sharp_chipdrv);
-}
-
-module_init(sharp_probe_init);
-module_exit(sharp_probe_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Schleef <ds@schleef.org>");
-MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index fc4cc8ba9e29b98a5df19e0d5119dfefd5455882..be4b9948c762e33b577cbd192dd836ff50c75e46 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -373,7 +373,7 @@ static inline void kill_final_newline(char *str)
 
 #ifndef MODULE
 static int block2mtd_init_called = 0;
-static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
+static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
 #endif
 
 
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 5fcd8b3631ba83760f107ef5edceb3c414a136d2..b665e4ac2208458bc70d1f8dfe9cd00a3a6a58fd 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -358,22 +358,6 @@ config MTD_CFI_FLAGADM
 	  Mapping for the Flaga digital module. If you don't have one, ignore
 	  this setting.
 
-config MTD_BEECH
-	tristate "CFI Flash device mapped on IBM 405LP Beech"
-	depends on MTD_CFI && BEECH
-	help
-	  This enables access routines for the flash chips on the IBM
-	  405LP Beech board. If you have one of these boards and would like
-	  to use the flash chips on it, say 'Y'.
-
-config MTD_ARCTIC
-	tristate "CFI Flash device mapped on IBM 405LP Arctic"
-	depends on MTD_CFI && ARCTIC2
-	help
-	  This enables access routines for the flash chips on the IBM 405LP
-	  Arctic board. If you have one of these boards and would like to
-	  use the flash chips on it, say 'Y'.
-
 config MTD_WALNUT
 	tristate "Flash device mapped on IBM 405GP Walnut"
 	depends on MTD_JEDECPROBE && WALNUT
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index de036c5e61394375721a4fe789a824da6cbcf23e..3acbb5d01ca4edc159238390e1f827ebee431524 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -58,8 +58,6 @@ obj-$(CONFIG_MTD_NETtel)	+= nettel.o
 obj-$(CONFIG_MTD_SCB2_FLASH)	+= scb2_flash.o
 obj-$(CONFIG_MTD_EBONY)		+= ebony.o
 obj-$(CONFIG_MTD_OCOTEA)	+= ocotea.o
-obj-$(CONFIG_MTD_BEECH)		+= beech-mtd.o
-obj-$(CONFIG_MTD_ARCTIC)	+= arctic-mtd.o
 obj-$(CONFIG_MTD_WALNUT)        += walnut.o
 obj-$(CONFIG_MTD_H720X)		+= h720x-flash.o
 obj-$(CONFIG_MTD_SBC8240)	+= sbc8240.o
diff --git a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c
deleted file mode 100644
index 2cc9024362759f2a4bbb0963c53090b19892ea94..0000000000000000000000000000000000000000
--- a/drivers/mtd/maps/arctic-mtd.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * $Id: arctic-mtd.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $
- *
- * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for
- *                              IBM 405LP Arctic boards.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Copyright (C) 2002, International Business Machines Corporation
- * All Rights Reserved.
- *
- * Bishop Brock
- * IBM Research, Austin Center for Low-Power Computing
- * bcbrock@us.ibm.com
- * March 2002
- *
- * modified for Arctic by,
- * David Gibson
- * IBM OzLabs, Canberra, Australia
- * <arctic@gibson.dropbear.id.au>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-#include <asm/ibm4xx.h>
-
-/*
- * 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB)
- * 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB)
- * 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP)
- * 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB)
- */
-
-#define FFS1_SIZE	0x01000000 /* 16MiB */
-#define KERNEL_SIZE	0x00500000 /* 5.12MiB */
-#define FFS2_SIZE	0x00a60000 /* 10.624MiB */
-#define FIRMWARE_SIZE	0x000a0000 /* 640KiB */
-
-
-#define NAME     	"Arctic Linux Flash"
-#define PADDR    	SUBZERO_BOOTFLASH_PADDR
-#define BUSWIDTH	2
-#define SIZE		SUBZERO_BOOTFLASH_SIZE
-#define PARTITIONS	4
-
-/* Flash memories on these boards are memory resources, accessed big-endian. */
-
-{
-  /* do nothing for now */
-}
-
-static struct map_info arctic_mtd_map = {
-	.name		= NAME,
-	.size		= SIZE,
-	.bankwidth	= BUSWIDTH,
-	.phys		= PADDR,
-};
-
-static struct mtd_info *arctic_mtd;
-
-static struct mtd_partition arctic_partitions[PARTITIONS] = {
-	{ .name		= "Filesystem",
-	  .size		= FFS1_SIZE,
-	  .offset	= 0,},
-        { .name		= "Kernel",
-	  .size		= KERNEL_SIZE,
-	  .offset	= FFS1_SIZE,},
-	{ .name		= "Filesystem",
-	  .size		= FFS2_SIZE,
-	  .offset	= FFS1_SIZE + KERNEL_SIZE,},
-	{ .name		= "Firmware",
-	  .size		= FIRMWARE_SIZE,
-	  .offset	= SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,},
-};
-
-static int __init
-init_arctic_mtd(void)
-{
-	int err;
-
-	printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
-
-	arctic_mtd_map.virt = ioremap(PADDR, SIZE);
-
-	if (!arctic_mtd_map.virt) {
-		printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
-		return -EIO;
-	}
-	simple_map_init(&arctic_mtd_map);
-
-	printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
-	arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map);
-
-	if (!arctic_mtd) {
-		iounmap(arctic_mtd_map.virt);
-		return -ENXIO;
-	}
-
-	arctic_mtd->owner = THIS_MODULE;
-
-	err = add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS);
-	if (err) {
-		printk("%s: add_mtd_partitions failed\n", NAME);
-		iounmap(arctic_mtd_map.virt);
-	}
-
-	return err;
-}
-
-static void __exit
-cleanup_arctic_mtd(void)
-{
-	if (arctic_mtd) {
-		del_mtd_partitions(arctic_mtd);
-		map_destroy(arctic_mtd);
-		iounmap((void *) arctic_mtd_map.virt);
-	}
-}
-
-module_init(init_arctic_mtd);
-module_exit(cleanup_arctic_mtd);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Gibson <arctic@gibson.dropbear.id.au>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Arctic boards");
diff --git a/drivers/mtd/maps/beech-mtd.c b/drivers/mtd/maps/beech-mtd.c
deleted file mode 100644
index d76d5981b8639f965aa15d189874163f28449c29..0000000000000000000000000000000000000000
--- a/drivers/mtd/maps/beech-mtd.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * $Id: beech-mtd.c,v 1.11 2005/11/07 11:14:26 gleixner Exp $
- *
- * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for
- *                              IBM 405LP Beech boards.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Copyright (C) 2002, International Business Machines Corporation
- * All Rights Reserved.
- *
- * Bishop Brock
- * IBM Research, Austin Center for Low-Power Computing
- * bcbrock@us.ibm.com
- * March 2002
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-#include <asm/ibm4xx.h>
-
-#define NAME     "Beech Linux Flash"
-#define PADDR    BEECH_BIGFLASH_PADDR
-#define SIZE     BEECH_BIGFLASH_SIZE
-#define BUSWIDTH 1
-
-/* Flash memories on these boards are memory resources, accessed big-endian. */
-
-
-static struct map_info beech_mtd_map = {
-	.name =		NAME,
-	.size =		SIZE,
-	.bankwidth =	BUSWIDTH,
-	.phys =		PADDR
-};
-
-static struct mtd_info *beech_mtd;
-
-static struct mtd_partition beech_partitions[2] = {
-	{
-	      .name = "Linux Kernel",
-	      .size = BEECH_KERNEL_SIZE,
-	      .offset = BEECH_KERNEL_OFFSET
-	}, {
-	      .name = "Free Area",
-	      .size = BEECH_FREE_AREA_SIZE,
-	      .offset = BEECH_FREE_AREA_OFFSET
-	}
-};
-
-static int __init
-init_beech_mtd(void)
-{
-	int err;
-
-	printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
-
-	beech_mtd_map.virt = ioremap(PADDR, SIZE);
-
-	if (!beech_mtd_map.virt) {
-		printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
-		return -EIO;
-	}
-
-	simple_map_init(&beech_mtd_map);
-
-	printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
-	beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map);
-
-	if (!beech_mtd) {
-		iounmap(beech_mtd_map.virt);
-		return -ENXIO;
-	}
-
-	beech_mtd->owner = THIS_MODULE;
-
-	err = add_mtd_partitions(beech_mtd, beech_partitions, 2);
-	if (err) {
-		printk("%s: add_mtd_partitions failed\n", NAME);
-		iounmap(beech_mtd_map.virt);
-	}
-
-	return err;
-}
-
-static void __exit
-cleanup_beech_mtd(void)
-{
-	if (beech_mtd) {
-		del_mtd_partitions(beech_mtd);
-		map_destroy(beech_mtd);
-		iounmap((void *) beech_mtd_map.virt);
-	}
-}
-
-module_init(init_beech_mtd);
-module_exit(cleanup_beech_mtd);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Bishop Brock <bcbrock@us.ibm.com>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Beech boards");
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 72107dc06d6745df15a528febb2cabbe9255a58b..bbb42c35b69b9df05a108f21b0d837f80ca3d7e6 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -186,7 +186,7 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev
 	else {
  		if (strcmp(of_probe, "ROM"))
 			dev_dbg(&dev->dev, "map_probe: don't know probe type "
-			"'%s', mapping as rom\n");
+			"'%s', mapping as rom\n", of_probe);
 		info->mtd = do_map_probe("mtd_rom", &info->map);
 	}
 	if (info->mtd == NULL) {
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 1af989023c6644ca89c8e4107c21fcde8137904d..9c6236852942ec7e98441c5a333c1786a0e83a0c 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -347,7 +347,6 @@ int add_mtd_partitions(struct mtd_info *master,
 		slave->mtd.subpage_sft = master->subpage_sft;
 
 		slave->mtd.name = parts[i].name;
-		slave->mtd.bank_size = master->bank_size;
 		slave->mtd.owner = master->owner;
 
 		slave->mtd.read = part_read;
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index d05873b8c155a8f8c478fc86cd522ca792441451..f1d60b6f048e6f08aa855e19fed1337a292cfe79 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -232,11 +232,13 @@ config MTD_NAND_BASLER_EXCITE
           will be named "excite_nandflash.ko".
 
 config MTD_NAND_CAFE
-       tristate "NAND support for OLPC CAFÉ chip"
-       depends on PCI
-       help
-	 Use NAND flash attached to the CAFÉ chip designed for the $100
-	 laptop.
+	tristate "NAND support for OLPC CAFÉ chip"
+	depends on PCI
+	select REED_SOLOMON
+	select REED_SOLOMON_DEC16
+	help
+	  Use NAND flash attached to the CAFÉ chip designed for the $100
+	  laptop.
 
 config MTD_NAND_CS553X
 	tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
@@ -270,4 +272,13 @@ config MTD_NAND_NANDSIM
 	  The simulator may simulate various NAND flash chips for the
 	  MTD nand layer.
 
+config MTD_NAND_PLATFORM
+	tristate "Support for generic platform NAND driver"
+	depends on MTD_NAND
+	help
+	  This implements a generic NAND driver for on-SOC platform
+	  devices. You will need to provide platform-specific functions
+	  via platform_data.
+
+
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 6872031a3fb25ff45d4e263691133d4698d94c8f..edba1db14bfad6581260b822b60a260063fc542c 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -26,6 +26,6 @@ obj-$(CONFIG_MTD_NAND_NDFC)		+= ndfc.o
 obj-$(CONFIG_MTD_NAND_AT91)		+= at91_nand.o
 obj-$(CONFIG_MTD_NAND_CM_X270)		+= cmx270_nand.o
 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)	+= excite_nandflash.o
+obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
-cafe_nand-objs := cafe.o cafe_ecc.o
diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c
index 14b80cc90a7b789d7af4efe96b549bb105f87e22..512e999177f70cb39c745ac6d454d22e6a4c3bae 100644
--- a/drivers/mtd/nand/at91_nand.c
+++ b/drivers/mtd/nand/at91_nand.c
@@ -82,6 +82,10 @@ static void at91_nand_disable(struct at91_nand_host *host)
 		at91_set_gpio_value(host->board->enable_pin, 1);
 }
 
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+#endif
+
 /*
  * Probe for the NAND device.
  */
@@ -151,6 +155,12 @@ static int __init at91_nand_probe(struct platform_device *pdev)
 #ifdef CONFIG_MTD_PARTITIONS
 	if (host->board->partition_info)
 		partitions = host->board->partition_info(mtd->size, &num_partitions);
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+	else {
+		mtd->name = "at91_nand";
+		num_partitions = parse_mtd_partitions(mtd, part_probes, &partitions, 0);
+	}
+#endif
 
 	if ((!partitions) || (num_partitions == 0)) {
 		printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
diff --git a/drivers/mtd/nand/cafe_ecc.c b/drivers/mtd/nand/cafe_ecc.c
deleted file mode 100644
index ea5c8491d2c57677250b012f1d9261494cead565..0000000000000000000000000000000000000000
--- a/drivers/mtd/nand/cafe_ecc.c
+++ /dev/null
@@ -1,1381 +0,0 @@
-/* Error correction for CAFÉ NAND controller
- *
- * © 2006 Marvell, Inc.
- * Author: Tom Chiou
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-
-static unsigned short gf4096_mul(unsigned short, unsigned short);
-static unsigned short gf64_mul(unsigned short, unsigned short);
-static unsigned short gf4096_inv(unsigned short);
-static unsigned short err_pos(unsigned short);
-static void find_4bit_err_coefs(unsigned short, unsigned short, unsigned short,
-				unsigned short, unsigned short, unsigned short,
-				unsigned short, unsigned short, unsigned short *);
-static void zero_4x5_col3(unsigned short[4][5]);
-static void zero_4x5_col2(unsigned short[4][5]);
-static void zero_4x5_col1(unsigned short[4][5]);
-static void swap_4x5_rows(unsigned short[4][5], int, int, int);
-static void swap_2x3_rows(unsigned short m[2][3]);
-static void solve_4x5(unsigned short m[4][5], unsigned short *, int *);
-static void sort_coefs(int *, unsigned short *, int);
-static void find_4bit_err_pats(unsigned short, unsigned short, unsigned short,
-			       unsigned short, unsigned short, unsigned short,
-			       unsigned short, unsigned short, unsigned short *);
-static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short,
-				unsigned short, unsigned short, unsigned short,
-				unsigned short *);
-static void zero_3x4_col2(unsigned short[3][4]);
-static void zero_3x4_col1(unsigned short[3][4]);
-static void swap_3x4_rows(unsigned short[3][4], int, int, int);
-static void solve_3x4(unsigned short[3][4], unsigned short *, int *);
-static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short,
-			       unsigned short, unsigned short, unsigned short,
-			       unsigned short *);
-
-static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short,
-			       unsigned short, unsigned short *);
-static void find_2x2_soln(unsigned short, unsigned short, unsigned short,
-			  unsigned short, unsigned short, unsigned short,
-			  unsigned short *);
-static void solve_2x3(unsigned short[2][3], unsigned short *);
-static int chk_no_err_only(unsigned short *, unsigned short *);
-static int chk_1_err_only(unsigned short *, unsigned short *);
-static int chk_2_err_only(unsigned short *, unsigned short *);
-static int chk_3_err_only(unsigned short *, unsigned short *);
-static int chk_4_err_only(unsigned short *, unsigned short *);
-
-static unsigned short gf64_mul(unsigned short a, unsigned short b)
-{
-	unsigned short tmp1, tmp2, tmp3, tmp4, tmp5;
-	unsigned short c_bit0, c_bit1, c_bit2, c_bit3, c_bit4, c_bit5, c;
-
-	tmp1 = ((a) ^ (a >> 5));
-	tmp2 = ((a >> 4) ^ (a >> 5));
-	tmp3 = ((a >> 3) ^ (a >> 4));
-	tmp4 = ((a >> 2) ^ (a >> 3));
-	tmp5 = ((a >> 1) ^ (a >> 2));
-
-	c_bit0 = ((a & b) ^ ((a >> 5) & (b >> 1)) ^ ((a >> 4) & (b >> 2)) ^
-		  ((a >> 3) & (b >> 3)) ^ ((a >> 2) & (b >> 4)) ^ ((a >> 1) & (b >> 5))) & 0x1;
-
-	c_bit1 = (((a >> 1) & b) ^ (tmp1 & (b >> 1)) ^ (tmp2 & (b >> 2)) ^
-		  (tmp3 & (b >> 3)) ^ (tmp4 & (b >> 4)) ^ (tmp5 & (b >> 5))) & 0x1;
-
-	c_bit2 = (((a >> 2) & b) ^ ((a >> 1) & (b >> 1)) ^ (tmp1 & (b >> 2)) ^
-		  (tmp2 & (b >> 3)) ^ (tmp3 & (b >> 4)) ^ (tmp4 & (b >> 5))) & 0x1;
-
-	c_bit3 = (((a >> 3) & b) ^ ((a >> 2) & (b >> 1)) ^ ((a >> 1) & (b >> 2)) ^
-		  (tmp1 & (b >> 3)) ^ (tmp2 & (b >> 4)) ^ (tmp3 & (b >> 5))) & 0x1;
-
-	c_bit4 = (((a >> 4) & b) ^ ((a >> 3) & (b >> 1)) ^ ((a >> 2) & (b >> 2)) ^
-		  ((a >> 1) & (b >> 3)) ^ (tmp1 & (b >> 4)) ^ (tmp2 & (b >> 5))) & 0x1;
-
-	c_bit5 = (((a >> 5) & b) ^ ((a >> 4) & (b >> 1)) ^ ((a >> 3) & (b >> 2)) ^
-		  ((a >> 2) & (b >> 3)) ^ ((a >> 1) & (b >> 4)) ^ (tmp1 & (b >> 5))) & 0x1;
-
-	c = c_bit0 | (c_bit1 << 1) | (c_bit2 << 2) | (c_bit3 << 3) | (c_bit4 << 4) | (c_bit5 << 5);
-
-	return c;
-}
-
-static unsigned short gf4096_mul(unsigned short a, unsigned short b)
-{
-	unsigned short ah, al, bh, bl, alxah, blxbh, ablh, albl, ahbh, ahbhB, c;
-
-	ah = (a >> 6) & 0x3f;
-	al = a & 0x3f;
-	bh = (b >> 6) & 0x3f;
-	bl = b & 0x3f;
-	alxah = al ^ ah;
-	blxbh = bl ^ bh;
-
-	ablh = gf64_mul(alxah, blxbh);
-	albl = gf64_mul(al, bl);
-	ahbh = gf64_mul(ah, bh);
-
-	ahbhB = ((ahbh & 0x1) << 5) |
-	    ((ahbh & 0x20) >> 1) |
-	    ((ahbh & 0x10) >> 1) | ((ahbh & 0x8) >> 1) | ((ahbh & 0x4) >> 1) | (((ahbh >> 1) ^ ahbh) & 0x1);
-
-	c = ((ablh ^ albl) << 6) | (ahbhB ^ albl);
-	return c;
-}
-
-static void find_2bit_err_pats(unsigned short s0, unsigned short s1, unsigned short r0, unsigned short r1, unsigned short *pats)
-{
-	find_2x2_soln(0x1, 0x1, r0, r1, s0, s1, pats);
-}
-
-static void find_3bit_err_coefs(unsigned short s0, unsigned short s1,
-				unsigned short s2, unsigned short s3, unsigned short s4, unsigned short s5, unsigned short *coefs)
-{
-	unsigned short m[3][4];
-	int row_order[3];
-
-	row_order[0] = 0;
-	row_order[1] = 1;
-	row_order[2] = 2;
-	m[0][0] = s2;
-	m[0][1] = s1;
-	m[0][2] = s0;
-	m[0][3] = s3;
-	m[1][0] = s3;
-	m[1][1] = s2;
-	m[1][2] = s1;
-	m[1][3] = s4;
-	m[2][0] = s4;
-	m[2][1] = s3;
-	m[2][2] = s2;
-	m[2][3] = s5;
-
-	if (m[0][2] != 0x0) {
-		zero_3x4_col2(m);
-	} else if (m[1][2] != 0x0) {
-		swap_3x4_rows(m, 0, 1, 4);
-		zero_3x4_col2(m);
-	} else if (m[2][2] != 0x0) {
-		swap_3x4_rows(m, 0, 2, 4);
-		zero_3x4_col2(m);
-	} else {
-		printk(KERN_ERR "Error: find_3bit_err_coefs, s0,s1,s2 all zeros!\n");
-	}
-
-	if (m[1][1] != 0x0) {
-		zero_3x4_col1(m);
-	} else if (m[2][1] != 0x0) {
-		swap_3x4_rows(m, 1, 2, 4);
-		zero_3x4_col1(m);
-	} else {
-		printk(KERN_ERR "Error: find_3bit_err_coefs, cannot resolve col 1!\n");
-	}
-
-	/* solve coefs */
-	solve_3x4(m, coefs, row_order);
-}
-
-static void zero_3x4_col2(unsigned short m[3][4])
-{
-	unsigned short minv1, minv2;
-
-	minv1 = gf4096_mul(m[1][2], gf4096_inv(m[0][2]));
-	minv2 = gf4096_mul(m[2][2], gf4096_inv(m[0][2]));
-	m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
-	m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
-	m[1][3] = m[1][3] ^ gf4096_mul(m[0][3], minv1);
-	m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
-	m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
-	m[2][3] = m[2][3] ^ gf4096_mul(m[0][3], minv2);
-}
-
-static void zero_3x4_col1(unsigned short m[3][4])
-{
-	unsigned short minv;
-	minv = gf4096_mul(m[2][1], gf4096_inv(m[1][1]));
-	m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv);
-	m[2][3] = m[2][3] ^ gf4096_mul(m[1][3], minv);
-}
-
-static void swap_3x4_rows(unsigned short m[3][4], int i, int j, int col_width)
-{
-	unsigned short tmp0;
-	int cnt;
-	for (cnt = 0; cnt < col_width; cnt++) {
-		tmp0 = m[i][cnt];
-		m[i][cnt] = m[j][cnt];
-		m[j][cnt] = tmp0;
-	}
-}
-
-static void solve_3x4(unsigned short m[3][4], unsigned short *coefs, int *row_order)
-{
-	unsigned short tmp[3];
-	tmp[0] = gf4096_mul(m[2][3], gf4096_inv(m[2][0]));
-	tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ m[1][3]), gf4096_inv(m[1][1]));
-	tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ gf4096_mul(tmp[1], m[0][1]) ^ m[0][3]), gf4096_inv(m[0][2]));
-	sort_coefs(row_order, tmp, 3);
-	coefs[0] = tmp[0];
-	coefs[1] = tmp[1];
-	coefs[2] = tmp[2];
-}
-
-static void find_3bit_err_pats(unsigned short s0, unsigned short s1,
-			       unsigned short s2, unsigned short r0,
-			       unsigned short r1, unsigned short r2,
-			       unsigned short *pats)
-{
-	find_2x2_soln(r0 ^ r2, r1 ^ r2,
-		      gf4096_mul(r0, r0 ^ r2), gf4096_mul(r1, r1 ^ r2),
-		      gf4096_mul(s0, r2) ^ s1, gf4096_mul(s1, r2) ^ s2, pats);
-	pats[2] = s0 ^ pats[0] ^ pats[1];
-}
-
-static void find_4bit_err_coefs(unsigned short s0, unsigned short s1,
-				unsigned short s2, unsigned short s3,
-				unsigned short s4, unsigned short s5,
-				unsigned short s6, unsigned short s7,
-				unsigned short *coefs)
-{
-	unsigned short m[4][5];
-	int row_order[4];
-
-	row_order[0] = 0;
-	row_order[1] = 1;
-	row_order[2] = 2;
-	row_order[3] = 3;
-
-	m[0][0] = s3;
-	m[0][1] = s2;
-	m[0][2] = s1;
-	m[0][3] = s0;
-	m[0][4] = s4;
-	m[1][0] = s4;
-	m[1][1] = s3;
-	m[1][2] = s2;
-	m[1][3] = s1;
-	m[1][4] = s5;
-	m[2][0] = s5;
-	m[2][1] = s4;
-	m[2][2] = s3;
-	m[2][3] = s2;
-	m[2][4] = s6;
-	m[3][0] = s6;
-	m[3][1] = s5;
-	m[3][2] = s4;
-	m[3][3] = s3;
-	m[3][4] = s7;
-
-	if (m[0][3] != 0x0) {
-		zero_4x5_col3(m);
-	} else if (m[1][3] != 0x0) {
-		swap_4x5_rows(m, 0, 1, 5);
-		zero_4x5_col3(m);
-	} else if (m[2][3] != 0x0) {
-		swap_4x5_rows(m, 0, 2, 5);
-		zero_4x5_col3(m);
-	} else if (m[3][3] != 0x0) {
-		swap_4x5_rows(m, 0, 3, 5);
-		zero_4x5_col3(m);
-	} else {
-		printk(KERN_ERR "Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!\n");
-	}
-
-	if (m[1][2] != 0x0) {
-		zero_4x5_col2(m);
-	} else if (m[2][2] != 0x0) {
-		swap_4x5_rows(m, 1, 2, 5);
-		zero_4x5_col2(m);
-	} else if (m[3][2] != 0x0) {
-		swap_4x5_rows(m, 1, 3, 5);
-		zero_4x5_col2(m);
-	} else {
-		printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 2!\n");
-	}
-
-	if (m[2][1] != 0x0) {
-		zero_4x5_col1(m);
-	} else if (m[3][1] != 0x0) {
-		swap_4x5_rows(m, 2, 3, 5);
-		zero_4x5_col1(m);
-	} else {
-		printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 1!\n");
-	}
-
-	solve_4x5(m, coefs, row_order);
-}
-
-static void zero_4x5_col3(unsigned short m[4][5])
-{
-	unsigned short minv1, minv2, minv3;
-
-	minv1 = gf4096_mul(m[1][3], gf4096_inv(m[0][3]));
-	minv2 = gf4096_mul(m[2][3], gf4096_inv(m[0][3]));
-	minv3 = gf4096_mul(m[3][3], gf4096_inv(m[0][3]));
-
-	m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
-	m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
-	m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv1);
-	m[1][4] = m[1][4] ^ gf4096_mul(m[0][4], minv1);
-	m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
-	m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
-	m[2][2] = m[2][2] ^ gf4096_mul(m[0][2], minv2);
-	m[2][4] = m[2][4] ^ gf4096_mul(m[0][4], minv2);
-	m[3][0] = m[3][0] ^ gf4096_mul(m[0][0], minv3);
-	m[3][1] = m[3][1] ^ gf4096_mul(m[0][1], minv3);
-	m[3][2] = m[3][2] ^ gf4096_mul(m[0][2], minv3);
-	m[3][4] = m[3][4] ^ gf4096_mul(m[0][4], minv3);
-}
-
-static void zero_4x5_col2(unsigned short m[4][5])
-{
-	unsigned short minv2, minv3;
-
-	minv2 = gf4096_mul(m[2][2], gf4096_inv(m[1][2]));
-	minv3 = gf4096_mul(m[3][2], gf4096_inv(m[1][2]));
-
-	m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv2);
-	m[2][1] = m[2][1] ^ gf4096_mul(m[1][1], minv2);
-	m[2][4] = m[2][4] ^ gf4096_mul(m[1][4], minv2);
-	m[3][0] = m[3][0] ^ gf4096_mul(m[1][0], minv3);
-	m[3][1] = m[3][1] ^ gf4096_mul(m[1][1], minv3);
-	m[3][4] = m[3][4] ^ gf4096_mul(m[1][4], minv3);
-}
-
-static void zero_4x5_col1(unsigned short m[4][5])
-{
-	unsigned short minv;
-
-	minv = gf4096_mul(m[3][1], gf4096_inv(m[2][1]));
-
-	m[3][0] = m[3][0] ^ gf4096_mul(m[2][0], minv);
-	m[3][4] = m[3][4] ^ gf4096_mul(m[2][4], minv);
-}
-
-static void swap_4x5_rows(unsigned short m[4][5], int i, int j, int col_width)
-{
-	unsigned short tmp0;
-	int cnt;
-
-	for (cnt = 0; cnt < col_width; cnt++) {
-		tmp0 = m[i][cnt];
-		m[i][cnt] = m[j][cnt];
-		m[j][cnt] = tmp0;
-	}
-}
-
-static void solve_4x5(unsigned short m[4][5], unsigned short *coefs, int *row_order)
-{
-	unsigned short tmp[4];
-
-	tmp[0] = gf4096_mul(m[3][4], gf4096_inv(m[3][0]));
-	tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[2][0]) ^ m[2][4]), gf4096_inv(m[2][1]));
-	tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ gf4096_mul(tmp[1], m[1][1]) ^ m[1][4]), gf4096_inv(m[1][2]));
-	tmp[3] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^
-			gf4096_mul(tmp[1], m[0][1]) ^ gf4096_mul(tmp[2], m[0][2]) ^ m[0][4]), gf4096_inv(m[0][3]));
-	sort_coefs(row_order, tmp, 4);
-	coefs[0] = tmp[0];
-	coefs[1] = tmp[1];
-	coefs[2] = tmp[2];
-	coefs[3] = tmp[3];
-}
-
-static void sort_coefs(int *order, unsigned short *soln, int len)
-{
-	int cnt, start_cnt, least_ord, least_cnt;
-	unsigned short tmp0;
-	for (start_cnt = 0; start_cnt < len; start_cnt++) {
-		for (cnt = start_cnt; cnt < len; cnt++) {
-			if (cnt == start_cnt) {
-				least_ord = order[cnt];
-				least_cnt = start_cnt;
-			} else {
-				if (least_ord > order[cnt]) {
-					least_ord = order[cnt];
-					least_cnt = cnt;
-				}
-			}
-		}
-		if (least_cnt != start_cnt) {
-			tmp0 = order[least_cnt];
-			order[least_cnt] = order[start_cnt];
-			order[start_cnt] = tmp0;
-			tmp0 = soln[least_cnt];
-			soln[least_cnt] = soln[start_cnt];
-			soln[start_cnt] = tmp0;
-		}
-	}
-}
-
-static void find_4bit_err_pats(unsigned short s0, unsigned short s1,
-			       unsigned short s2, unsigned short s3,
-			       unsigned short z1, unsigned short z2,
-			       unsigned short z3, unsigned short z4,
-			       unsigned short *pats)
-{
-	unsigned short z4_z1, z3z4_z3z3, z4_z2, s0z4_s1, z1z4_z1z1,
-		z4_z3, z2z4_z2z2, s1z4_s2, z3z3z4_z3z3z3, z1z1z4_z1z1z1, z2z2z4_z2z2z2, s2z4_s3;
-	unsigned short tmp0, tmp1, tmp2, tmp3;
-
-	z4_z1 = z4 ^ z1;
-	z3z4_z3z3 = gf4096_mul(z3, z4) ^ gf4096_mul(z3, z3);
-	z4_z2 = z4 ^ z2;
-	s0z4_s1 = gf4096_mul(s0, z4) ^ s1;
-	z1z4_z1z1 = gf4096_mul(z1, z4) ^ gf4096_mul(z1, z1);
-	z4_z3 = z4 ^ z3;
-	z2z4_z2z2 = gf4096_mul(z2, z4) ^ gf4096_mul(z2, z2);
-	s1z4_s2 = gf4096_mul(s1, z4) ^ s2;
-	z3z3z4_z3z3z3 = gf4096_mul(gf4096_mul(z3, z3), z4) ^ gf4096_mul(gf4096_mul(z3, z3), z3);
-	z1z1z4_z1z1z1 = gf4096_mul(gf4096_mul(z1, z1), z4) ^ gf4096_mul(gf4096_mul(z1, z1), z1);
-	z2z2z4_z2z2z2 = gf4096_mul(gf4096_mul(z2, z2), z4) ^ gf4096_mul(gf4096_mul(z2, z2), z2);
-	s2z4_s3 = gf4096_mul(s2, z4) ^ s3;
-
-	//find err pat 0,1
-	find_2x2_soln(gf4096_mul(z4_z1, z3z4_z3z3) ^
-		      gf4096_mul(z1z4_z1z1, z4_z3), gf4096_mul(z4_z2,
-							       z3z4_z3z3) ^
-		      gf4096_mul(z2z4_z2z2, z4_z3), gf4096_mul(z1z4_z1z1,
-							       z3z3z4_z3z3z3) ^
-		      gf4096_mul(z1z1z4_z1z1z1, z3z4_z3z3),
-		      gf4096_mul(z2z4_z2z2,
-				 z3z3z4_z3z3z3) ^ gf4096_mul(z2z2z4_z2z2z2,
-							     z3z4_z3z3),
-		      gf4096_mul(s0z4_s1, z3z4_z3z3) ^ gf4096_mul(s1z4_s2,
-								  z4_z3),
-		      gf4096_mul(s1z4_s2, z3z3z4_z3z3z3) ^ gf4096_mul(s2z4_s3, z3z4_z3z3), pats);
-	tmp0 = pats[0];
-	tmp1 = pats[1];
-	tmp2 = pats[0] ^ pats[1] ^ s0;
-	tmp3 = gf4096_mul(pats[0], z1) ^ gf4096_mul(pats[1], z2) ^ s1;
-
-	//find err pat 2,3
-	find_2x2_soln(0x1, 0x1, z3, z4, tmp2, tmp3, pats);
-	pats[2] = pats[0];
-	pats[3] = pats[1];
-	pats[0] = tmp0;
-	pats[1] = tmp1;
-}
-
-static void find_2x2_soln(unsigned short c00, unsigned short c01,
-			  unsigned short c10, unsigned short c11,
-			  unsigned short lval0, unsigned short lval1,
-			  unsigned short *soln)
-{
-	unsigned short m[2][3];
-	m[0][0] = c00;
-	m[0][1] = c01;
-	m[0][2] = lval0;
-	m[1][0] = c10;
-	m[1][1] = c11;
-	m[1][2] = lval1;
-
-	if (m[0][1] != 0x0) {
-		/* */
-	} else if (m[1][1] != 0x0) {
-		swap_2x3_rows(m);
-	} else {
-		printk(KERN_ERR "Warning: find_2bit_err_coefs, s0,s1 all zeros!\n");
-	}
-
-	solve_2x3(m, soln);
-}
-
-static void swap_2x3_rows(unsigned short m[2][3])
-{
-	unsigned short tmp0;
-	int cnt;
-
-	for (cnt = 0; cnt < 3; cnt++) {
-		tmp0 = m[0][cnt];
-		m[0][cnt] = m[1][cnt];
-		m[1][cnt] = tmp0;
-	}
-}
-
-static void solve_2x3(unsigned short m[2][3], unsigned short *coefs)
-{
-	unsigned short minv;
-
-	minv = gf4096_mul(m[1][1], gf4096_inv(m[0][1]));
-	m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv);
-	m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv);
-	coefs[0] = gf4096_mul(m[1][2], gf4096_inv(m[1][0]));
-	coefs[1] = gf4096_mul((gf4096_mul(coefs[0], m[0][0]) ^ m[0][2]), gf4096_inv(m[0][1]));
-}
-
-static unsigned char gf64_inv[64] = {
-	 0,  1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25,
-	61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45,  6,
-	63,  2, 27, 21, 56,  9, 50, 19, 13, 47, 48,  5,  7, 30, 12, 41,
-	42,  4, 38, 18, 10, 29, 17, 60, 36,  8, 59, 58, 55, 16,  3, 32
-};
-
-static unsigned short gf4096_inv(unsigned short din)
-{
-	unsigned short alahxal, ah2B, deno, inv, bl, bh;
-	unsigned short ah, al, ahxal;
-	unsigned short dout;
-
-	ah = (din >> 6) & 0x3f;
-	al = din & 0x3f;
-	ahxal = ah ^ al;
-	ah2B = (((ah ^ (ah >> 3)) & 0x1) << 5) |
-		((ah >> 1) & 0x10) |
-		((((ah >> 5) ^ (ah >> 2)) & 0x1) << 3) |
-		((ah >> 2) & 0x4) | ((((ah >> 4) ^ (ah >> 1)) & 0x1) << 1) | (ah & 0x1);
-	alahxal = gf64_mul(ahxal, al);
-	deno = alahxal ^ ah2B;
-	inv = gf64_inv[deno];
-	bl = gf64_mul(inv, ahxal);
-	bh = gf64_mul(inv, ah);
-	dout = ((bh & 0x3f) << 6) | (bl & 0x3f);
-	return (((bh & 0x3f) << 6) | (bl & 0x3f));
-}
-
-static unsigned short err_pos_lut[4096] = {
-	0xfff, 0x000, 0x451, 0xfff, 0xfff, 0x3cf, 0xfff, 0x041,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x28a, 0xfff, 0x492, 0xfff,
-	0x145, 0xfff, 0xfff, 0x514, 0xfff, 0x082, 0xfff, 0xfff,
-	0xfff, 0x249, 0x38e, 0x410, 0xfff, 0x104, 0x208, 0x1c7,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x2cb, 0xfff, 0xfff, 0xfff,
-	0x0c3, 0x34d, 0x4d3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x186, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x30c, 0x555, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x166, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x385, 0x14e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e1,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x538, 0xfff, 0x16d, 0xfff,
-	0xfff, 0xfff, 0x45b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x29c, 0x2cc, 0x30b, 0x2b3, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0b3, 0xfff, 0x2f7,
-	0xfff, 0x32b, 0xfff, 0xfff, 0xfff, 0xfff, 0x0a7, 0xfff,
-	0xfff, 0x2da, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x07e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x11c, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x22f, 0xfff, 0x1f4, 0xfff, 0xfff,
-	0x2b0, 0x504, 0xfff, 0x114, 0xfff, 0xfff, 0xfff, 0x21d,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x00d, 0x3c4, 0x340, 0x10f,
-	0xfff, 0xfff, 0x266, 0x02e, 0xfff, 0xfff, 0xfff, 0x4f8,
-	0x337, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x07b, 0x168, 0xfff, 0xfff, 0x0fe,
-	0xfff, 0xfff, 0x51a, 0xfff, 0x458, 0xfff, 0x36d, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x073, 0x37d, 0x415, 0x550, 0xfff,
-	0xfff, 0xfff, 0x23b, 0x4b4, 0xfff, 0xfff, 0xfff, 0x1a1,
-	0xfff, 0xfff, 0x3aa, 0xfff, 0x117, 0x04d, 0x341, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x518, 0x03e, 0x0f2, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x363, 0xfff, 0x0b9, 0xfff, 0xfff,
-	0x241, 0xfff, 0xfff, 0x049, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x15f, 0x52d, 0xfff, 0xfff, 0xfff, 0x29e, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x4cf, 0x0fc, 0xfff, 0x36f, 0x3d3, 0xfff,
-	0x228, 0xfff, 0xfff, 0x45e, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x238, 0xfff, 0xfff, 0xfff, 0xfff, 0x47f, 0xfff, 0xfff,
-	0x43a, 0x265, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e8,
-	0xfff, 0xfff, 0x01a, 0xfff, 0xfff, 0xfff, 0xfff, 0x21e,
-	0x1fc, 0x40b, 0xfff, 0xfff, 0xfff, 0x2d0, 0x159, 0xfff,
-	0xfff, 0x313, 0xfff, 0xfff, 0x05c, 0x4cc, 0xfff, 0xfff,
-	0x0f6, 0x3d5, 0xfff, 0xfff, 0xfff, 0x54f, 0xfff, 0xfff,
-	0xfff, 0x172, 0x1e4, 0x07c, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x53c, 0x1ad, 0x535,
-	0x19b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x092, 0xfff, 0x2be, 0xfff, 0xfff, 0x482,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0e6, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x476, 0xfff, 0x51d, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x342, 0x2b5, 0x22e, 0x09a, 0xfff, 0x08d,
-	0x44f, 0x3ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d1, 0xfff,
-	0xfff, 0x543, 0xfff, 0x48f, 0xfff, 0x3d2, 0xfff, 0x0d5,
-	0x113, 0x0ec, 0x427, 0xfff, 0xfff, 0xfff, 0x4c4, 0xfff,
-	0xfff, 0x50a, 0xfff, 0x144, 0xfff, 0x105, 0x39f, 0x294,
-	0x164, 0xfff, 0x31a, 0xfff, 0xfff, 0x49a, 0xfff, 0x130,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x1be, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x49e, 0x371, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x0e8, 0x49c, 0x0f4, 0xfff,
-	0x338, 0x1a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x36c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x1ae, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x31b, 0xfff, 0xfff, 0x2dd, 0x522, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f4,
-	0x3c6, 0x30d, 0xfff, 0xfff, 0xfff, 0xfff, 0x34c, 0x18f,
-	0x30a, 0xfff, 0x01f, 0x079, 0xfff, 0xfff, 0x54d, 0x46b,
-	0x28c, 0x37f, 0xfff, 0xfff, 0xfff, 0xfff, 0x355, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x14f, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x359, 0x3fe, 0x3c5, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x423, 0xfff, 0xfff, 0x34a, 0x22c, 0xfff,
-	0x25a, 0xfff, 0xfff, 0x4ad, 0xfff, 0x28d, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x547, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x2e2, 0xfff, 0xfff, 0x1d5, 0xfff, 0x2a8, 0xfff, 0xfff,
-	0x03f, 0xfff, 0xfff, 0xfff, 0xfff, 0x3eb, 0x0fa, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x55b, 0xfff,
-	0x08e, 0xfff, 0x3ae, 0xfff, 0x3a4, 0xfff, 0x282, 0x158,
-	0xfff, 0x382, 0xfff, 0xfff, 0x499, 0xfff, 0xfff, 0x08a,
-	0xfff, 0xfff, 0xfff, 0x456, 0x3be, 0xfff, 0x1e2, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x559, 0xfff, 0x1a0, 0xfff,
-	0xfff, 0x0b4, 0xfff, 0xfff, 0xfff, 0x2df, 0xfff, 0xfff,
-	0xfff, 0x07f, 0x4f5, 0xfff, 0xfff, 0x27c, 0x133, 0x017,
-	0xfff, 0x3fd, 0xfff, 0xfff, 0xfff, 0x44d, 0x4cd, 0x17a,
-	0x0d7, 0x537, 0xfff, 0xfff, 0x353, 0xfff, 0xfff, 0x351,
-	0x366, 0xfff, 0x44a, 0xfff, 0x1a6, 0xfff, 0xfff, 0xfff,
-	0x291, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1e3,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x389, 0xfff, 0x07a, 0xfff,
-	0x1b6, 0x2ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x24e, 0x074,
-	0xfff, 0xfff, 0x3dc, 0xfff, 0x4e3, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x4eb, 0xfff, 0xfff, 0x3b8, 0x4de, 0xfff, 0x19c,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x262,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x076, 0x4e8, 0x3da,
-	0xfff, 0x531, 0xfff, 0xfff, 0x14a, 0xfff, 0x0a2, 0x433,
-	0x3df, 0x1e9, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e7, 0x285,
-	0x2d8, 0xfff, 0xfff, 0xfff, 0x349, 0x18d, 0x098, 0xfff,
-	0x0df, 0x4bf, 0xfff, 0xfff, 0x0b2, 0xfff, 0x346, 0x24d,
-	0xfff, 0xfff, 0xfff, 0x24f, 0x4fa, 0x2f9, 0xfff, 0xfff,
-	0x3c9, 0xfff, 0x2b4, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x056, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x179, 0xfff, 0x0e9, 0x3f0, 0x33d, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x1fd, 0xfff, 0xfff, 0x526, 0xfff,
-	0xfff, 0xfff, 0x53d, 0xfff, 0xfff, 0xfff, 0x170, 0x331,
-	0xfff, 0x068, 0xfff, 0xfff, 0xfff, 0x3f7, 0xfff, 0x3d8,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x09f, 0x556, 0xfff, 0xfff, 0x02d, 0xfff, 0xfff,
-	0x553, 0xfff, 0xfff, 0xfff, 0x1f0, 0xfff, 0xfff, 0x4d6,
-	0x41e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d5, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x248, 0xfff, 0xfff, 0xfff, 0x0a3,
-	0xfff, 0x217, 0xfff, 0xfff, 0xfff, 0x4f1, 0x209, 0xfff,
-	0xfff, 0x475, 0x234, 0x52b, 0x398, 0xfff, 0x08b, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x2c2, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x268, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x4a3, 0xfff, 0x0aa, 0xfff, 0x1d9, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x155, 0xfff, 0xfff, 0xfff, 0xfff, 0x0bf,
-	0x539, 0xfff, 0xfff, 0x2f1, 0x545, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x2a7, 0x06f, 0xfff, 0x378, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x25e, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x15d, 0x02a, 0xfff, 0xfff, 0x0bc,
-	0x235, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x150, 0xfff, 0x1a9, 0xfff, 0xfff, 0xfff, 0xfff, 0x381,
-	0xfff, 0x04e, 0x270, 0x13f, 0xfff, 0xfff, 0x405, 0xfff,
-	0x3cd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x2ef, 0xfff, 0x06a, 0xfff, 0xfff, 0xfff, 0x34f,
-	0x212, 0xfff, 0xfff, 0x0e2, 0xfff, 0x083, 0x298, 0xfff,
-	0xfff, 0xfff, 0x0c2, 0xfff, 0xfff, 0x52e, 0xfff, 0x488,
-	0xfff, 0xfff, 0xfff, 0x36b, 0xfff, 0xfff, 0xfff, 0x442,
-	0x091, 0xfff, 0x41c, 0xfff, 0xfff, 0x3a5, 0xfff, 0x4e6,
-	0xfff, 0xfff, 0x40d, 0x31d, 0xfff, 0xfff, 0xfff, 0x4c1,
-	0x053, 0xfff, 0x418, 0x13c, 0xfff, 0x350, 0xfff, 0x0ae,
-	0xfff, 0xfff, 0x41f, 0xfff, 0x470, 0xfff, 0x4ca, 0xfff,
-	0xfff, 0xfff, 0x02b, 0x450, 0xfff, 0x1f8, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x293, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x411, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x0b8, 0xfff, 0xfff, 0xfff,
-	0x3e1, 0xfff, 0xfff, 0xfff, 0xfff, 0x43c, 0xfff, 0x2b2,
-	0x2ab, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ec,
-	0xfff, 0xfff, 0xfff, 0x3f8, 0x034, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x11a, 0xfff, 0x541, 0x45c, 0x134,
-	0x1cc, 0xfff, 0xfff, 0xfff, 0x469, 0xfff, 0xfff, 0x44b,
-	0x161, 0xfff, 0xfff, 0xfff, 0x055, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x307, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d1, 0xfff,
-	0xfff, 0xfff, 0x124, 0x37b, 0x26b, 0x336, 0xfff, 0xfff,
-	0x2e4, 0x3cb, 0xfff, 0xfff, 0x0f8, 0x3c8, 0xfff, 0xfff,
-	0xfff, 0x461, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4b5,
-	0x2cf, 0xfff, 0xfff, 0xfff, 0x20f, 0xfff, 0x35a, 0xfff,
-	0x490, 0xfff, 0x185, 0xfff, 0xfff, 0xfff, 0xfff, 0x42e,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x54b, 0xfff, 0xfff, 0xfff,
-	0x146, 0xfff, 0x412, 0xfff, 0xfff, 0xfff, 0x1ff, 0xfff,
-	0xfff, 0x3e0, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d5, 0xfff,
-	0x4df, 0x505, 0xfff, 0x413, 0xfff, 0x1a5, 0xfff, 0x3b2,
-	0xfff, 0xfff, 0xfff, 0x35b, 0xfff, 0x116, 0xfff, 0xfff,
-	0x171, 0x4d0, 0xfff, 0x154, 0x12d, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x468, 0x4db, 0xfff,
-	0xfff, 0x1df, 0xfff, 0xfff, 0xfff, 0xfff, 0x05a, 0xfff,
-	0x0f1, 0x403, 0xfff, 0x22b, 0x2e0, 0xfff, 0xfff, 0xfff,
-	0x2b7, 0x373, 0xfff, 0xfff, 0xfff, 0xfff, 0x13e, 0xfff,
-	0xfff, 0xfff, 0x0d0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x329, 0x1d2, 0x3fa, 0x047, 0xfff, 0x2f2, 0xfff, 0xfff,
-	0x141, 0x0ac, 0x1d7, 0xfff, 0x07d, 0xfff, 0xfff, 0xfff,
-	0x1c1, 0xfff, 0x487, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x045, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x288, 0x0cd, 0xfff, 0xfff, 0xfff, 0xfff, 0x226, 0x1d8,
-	0xfff, 0x153, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4cb,
-	0x528, 0xfff, 0xfff, 0xfff, 0x20a, 0x343, 0x3a1, 0xfff,
-	0xfff, 0xfff, 0x2d7, 0x2d3, 0x1aa, 0x4c5, 0xfff, 0xfff,
-	0xfff, 0x42b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x3e9, 0xfff, 0x20b, 0x260,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x37c, 0x2fd,
-	0xfff, 0xfff, 0x2c8, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x31e, 0xfff, 0x335, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x135, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x35c, 0x4dd, 0x129, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x1ef, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x34e, 0xfff, 0xfff, 0xfff, 0xfff, 0x407, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x3ad, 0xfff, 0xfff, 0xfff,
-	0x379, 0xfff, 0xfff, 0x1d0, 0x38d, 0xfff, 0xfff, 0x1e8,
-	0x184, 0x3c1, 0x1c4, 0xfff, 0x1f9, 0xfff, 0xfff, 0x424,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x1d3, 0x0d4, 0xfff, 0x4e9,
-	0xfff, 0xfff, 0xfff, 0x530, 0x107, 0xfff, 0x106, 0x04f,
-	0xfff, 0xfff, 0x4c7, 0x503, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x15c, 0xfff, 0x23f, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x4f3, 0xfff, 0xfff, 0x3c7,
-	0xfff, 0x278, 0xfff, 0xfff, 0x0a6, 0xfff, 0xfff, 0xfff,
-	0x122, 0x1cf, 0xfff, 0x327, 0xfff, 0x2e5, 0xfff, 0x29d,
-	0xfff, 0xfff, 0x3f1, 0xfff, 0xfff, 0x48d, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x054, 0xfff, 0xfff, 0xfff, 0xfff, 0x178,
-	0x27e, 0x4e0, 0x352, 0x02f, 0x09c, 0xfff, 0x2a0, 0xfff,
-	0xfff, 0x46a, 0x457, 0xfff, 0xfff, 0x501, 0xfff, 0x2ba,
-	0xfff, 0xfff, 0xfff, 0x54e, 0x2e7, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x551, 0xfff, 0xfff, 0x1db, 0x2aa, 0xfff,
-	0xfff, 0x4bc, 0xfff, 0xfff, 0x395, 0xfff, 0x0de, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x455, 0xfff, 0x17e,
-	0xfff, 0x221, 0x4a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x388, 0xfff, 0xfff, 0xfff, 0x308, 0xfff, 0xfff, 0xfff,
-	0x20e, 0x4b9, 0xfff, 0x273, 0x20c, 0x09e, 0xfff, 0x057,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x3f2, 0xfff, 0x1a8, 0x3a6,
-	0x14c, 0xfff, 0xfff, 0x071, 0xfff, 0xfff, 0x53a, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x109, 0xfff, 0xfff, 0x399, 0xfff,
-	0x061, 0x4f0, 0x39e, 0x244, 0xfff, 0x035, 0xfff, 0xfff,
-	0x305, 0x47e, 0x297, 0xfff, 0xfff, 0x2b8, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1bc, 0xfff, 0x2fc,
-	0xfff, 0xfff, 0x554, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b6,
-	0xfff, 0xfff, 0xfff, 0x515, 0x397, 0xfff, 0xfff, 0x12f,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e5,
-	0xfff, 0x4fc, 0xfff, 0xfff, 0x05e, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x0a8, 0x3af, 0x015, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x138, 0xfff, 0xfff, 0xfff, 0x540, 0xfff, 0xfff,
-	0xfff, 0x027, 0x523, 0x2f0, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x16c, 0xfff, 0x27d, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x04c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4dc,
-	0xfff, 0xfff, 0x059, 0x301, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x1a3, 0xfff, 0x15a, 0xfff, 0xfff,
-	0x0a5, 0xfff, 0x435, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x051, 0xfff, 0xfff, 0x131, 0xfff, 0x4f4, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x441, 0xfff, 0x4fb, 0xfff, 0x03b,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ed, 0x274,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d3, 0x55e, 0x1b3,
-	0xfff, 0x0bd, 0xfff, 0xfff, 0xfff, 0xfff, 0x225, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x4b7, 0xfff, 0xfff, 0x2ff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c3, 0xfff,
-	0x383, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f6,
-	0xfff, 0xfff, 0x1ee, 0xfff, 0x03d, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x26f, 0x1dc, 0xfff, 0x0db, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x0ce, 0xfff, 0xfff, 0x127, 0x03a,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x311, 0xfff,
-	0xfff, 0x13d, 0x09d, 0x47b, 0x2a6, 0x50d, 0x510, 0x19a,
-	0xfff, 0x354, 0x414, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x44c, 0x3b0, 0xfff, 0x23d, 0x429, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x4c0, 0x416, 0xfff, 0x05b, 0xfff, 0xfff, 0x137, 0xfff,
-	0x25f, 0x49f, 0xfff, 0x279, 0x013, 0xfff, 0xfff, 0xfff,
-	0x269, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d0, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x077, 0xfff, 0xfff, 0x3fb,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x271, 0x3a0, 0xfff, 0xfff,
-	0x40f, 0xfff, 0xfff, 0x3de, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ab, 0x26a,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x489, 0xfff, 0xfff,
-	0x252, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b7, 0x42f, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b7,
-	0xfff, 0x2bb, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x0f7, 0x01d, 0xfff, 0x067, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x4e2, 0xfff, 0xfff, 0x4bb, 0xfff,
-	0xfff, 0xfff, 0x17b, 0xfff, 0x0ee, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x36e, 0xfff, 0xfff, 0xfff, 0x533, 0xfff,
-	0xfff, 0xfff, 0x4d4, 0x356, 0xfff, 0xfff, 0x375, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x4a4, 0x513, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4ff, 0xfff, 0x2af,
-	0xfff, 0xfff, 0x026, 0xfff, 0x0ad, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x26e, 0xfff, 0xfff, 0xfff, 0xfff, 0x493, 0xfff,
-	0x463, 0x4d2, 0x4be, 0xfff, 0xfff, 0xfff, 0xfff, 0x4f2,
-	0x0b6, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x32d, 0x315, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x13a, 0x4a1, 0xfff, 0x27a, 0xfff, 0xfff, 0xfff,
-	0x47a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x334, 0xfff, 0xfff, 0xfff, 0xfff, 0x54c, 0xfff, 0xfff,
-	0xfff, 0x0c9, 0x007, 0xfff, 0xfff, 0x12e, 0xfff, 0x0ff,
-	0xfff, 0xfff, 0x3f5, 0x509, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x1c3, 0x2ad, 0xfff, 0xfff, 0x47c, 0x261, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x152, 0xfff, 0xfff, 0xfff, 0x339,
-	0xfff, 0x243, 0x1c0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x063, 0xfff, 0xfff, 0x254, 0xfff, 0xfff, 0x173, 0xfff,
-	0x0c7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x362, 0x259, 0x485, 0x374, 0x0dc, 0x3ab, 0xfff,
-	0x1c5, 0x534, 0x544, 0xfff, 0xfff, 0x508, 0xfff, 0x402,
-	0x408, 0xfff, 0x0e7, 0xfff, 0xfff, 0x00a, 0x205, 0xfff,
-	0xfff, 0x2b9, 0xfff, 0xfff, 0xfff, 0x465, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x23a, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x147, 0x19d, 0x115, 0x214, 0xfff, 0x090, 0x368,
-	0xfff, 0x210, 0xfff, 0xfff, 0x280, 0x52a, 0x163, 0x148,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x326, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x2de, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x206, 0x2c1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x189, 0xfff, 0xfff, 0xfff, 0xfff, 0x367, 0xfff, 0x1a4,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x443, 0xfff, 0x27b,
-	0xfff, 0xfff, 0x251, 0x549, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x188, 0x04b, 0xfff, 0xfff, 0xfff, 0x31f,
-	0x4a6, 0xfff, 0x246, 0x1de, 0x156, 0xfff, 0xfff, 0xfff,
-	0x3a9, 0xfff, 0xfff, 0xfff, 0x2fa, 0xfff, 0x128, 0x0d1,
-	0x449, 0x255, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x258, 0xfff, 0xfff, 0xfff,
-	0x532, 0xfff, 0xfff, 0xfff, 0x303, 0x517, 0xfff, 0xfff,
-	0x2a9, 0x24a, 0xfff, 0xfff, 0x231, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x4b6, 0x516, 0xfff, 0xfff, 0x0e4, 0x0eb,
-	0xfff, 0x4e4, 0xfff, 0x275, 0xfff, 0xfff, 0x031, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x025, 0x21a, 0xfff, 0x0cc,
-	0x45f, 0x3d9, 0x289, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x23e, 0xfff, 0xfff, 0xfff, 0x438, 0x097,
-	0x419, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x0a9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x37e, 0x0e0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x431,
-	0x372, 0xfff, 0xfff, 0xfff, 0x1ba, 0x06e, 0xfff, 0x1b1,
-	0xfff, 0xfff, 0x12a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x193, 0xfff, 0xfff, 0xfff, 0xfff, 0x10a,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x048, 0x1b4,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x295, 0x140, 0x108, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x16f, 0xfff, 0x0a4, 0x37a, 0xfff,
-	0x29a, 0xfff, 0x284, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c6,
-	0x2a2, 0x3a3, 0xfff, 0x201, 0xfff, 0xfff, 0xfff, 0x4bd,
-	0x005, 0x54a, 0x3b5, 0x204, 0x2ee, 0x11d, 0x436, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x3ec, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x11f, 0x498, 0x21c, 0xfff,
-	0xfff, 0xfff, 0x3d6, 0xfff, 0x4ab, 0xfff, 0x432, 0x2eb,
-	0x542, 0x4fd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x4ce, 0xfff, 0xfff, 0x2fb, 0xfff,
-	0xfff, 0x2e1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b9, 0x037, 0x0dd,
-	0xfff, 0xfff, 0xfff, 0x2bf, 0x521, 0x496, 0x095, 0xfff,
-	0xfff, 0x328, 0x070, 0x1bf, 0xfff, 0x393, 0xfff, 0xfff,
-	0x102, 0xfff, 0xfff, 0x21b, 0xfff, 0x142, 0x263, 0x519,
-	0xfff, 0x2a5, 0x177, 0xfff, 0x14d, 0x471, 0x4ae, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x1f6, 0xfff, 0x481, 0xfff, 0xfff, 0xfff, 0x151, 0xfff,
-	0xfff, 0xfff, 0x085, 0x33f, 0xfff, 0xfff, 0xfff, 0x084,
-	0xfff, 0xfff, 0xfff, 0x345, 0x3a2, 0xfff, 0xfff, 0x0a0,
-	0x0da, 0x024, 0xfff, 0xfff, 0xfff, 0x1bd, 0xfff, 0x55c,
-	0x467, 0x445, 0xfff, 0xfff, 0xfff, 0x052, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x51e, 0xfff, 0xfff, 0x39d, 0xfff, 0x35f,
-	0xfff, 0x376, 0x3ee, 0xfff, 0xfff, 0xfff, 0xfff, 0x448,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x16a,
-	0xfff, 0x036, 0x38f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x211,
-	0xfff, 0xfff, 0xfff, 0x230, 0xfff, 0xfff, 0x3ba, 0xfff,
-	0xfff, 0xfff, 0x3ce, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x229, 0xfff, 0x176, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x00b, 0xfff, 0x162, 0x018, 0xfff,
-	0xfff, 0x233, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x400, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x12b, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x3f4, 0xfff, 0x0f0, 0xfff, 0x1ac, 0xfff, 0xfff,
-	0x119, 0xfff, 0x2c0, 0xfff, 0xfff, 0xfff, 0x49b, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x23c, 0xfff,
-	0x4b3, 0x010, 0x064, 0xfff, 0xfff, 0x4ba, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x3c2, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x006, 0x196, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x100, 0x191, 0xfff,
-	0x1ea, 0x29f, 0xfff, 0xfff, 0xfff, 0x276, 0xfff, 0xfff,
-	0x2b1, 0x3b9, 0xfff, 0x03c, 0xfff, 0xfff, 0xfff, 0x180,
-	0xfff, 0x08f, 0xfff, 0xfff, 0x19e, 0x019, 0xfff, 0x0b0,
-	0x0fd, 0x332, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x06b, 0x2e8, 0xfff, 0x446, 0xfff, 0xfff, 0x004,
-	0x247, 0x197, 0xfff, 0x112, 0x169, 0x292, 0xfff, 0x302,
-	0xfff, 0xfff, 0x33b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x287, 0x21f, 0xfff, 0x3ea, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e7, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x3a8, 0xfff, 0xfff, 0x2bc, 0xfff,
-	0x484, 0x296, 0xfff, 0x1c9, 0x08c, 0x1e5, 0x48a, 0xfff,
-	0x360, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x1ca, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x10d, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x066, 0x2ea, 0x28b, 0x25b, 0xfff, 0x072,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x2b6, 0xfff, 0xfff, 0x272,
-	0xfff, 0xfff, 0x525, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x2ca, 0xfff, 0xfff, 0xfff, 0x299, 0xfff, 0xfff, 0xfff,
-	0x558, 0x41a, 0xfff, 0x4f7, 0x557, 0xfff, 0x4a0, 0x344,
-	0x12c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x125,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x40e, 0xfff, 0xfff, 0x502, 0xfff, 0x103, 0x3e6, 0xfff,
-	0x527, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x45d, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x44e, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d2, 0x4c9, 0x35e,
-	0x459, 0x2d9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x17d,
-	0x0c4, 0xfff, 0xfff, 0xfff, 0x3ac, 0x390, 0x094, 0xfff,
-	0x483, 0x0ab, 0xfff, 0x253, 0xfff, 0x391, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x123, 0x0ef, 0xfff, 0xfff, 0xfff, 0x330,
-	0x38c, 0xfff, 0xfff, 0x2ae, 0xfff, 0xfff, 0xfff, 0x042,
-	0x012, 0x06d, 0xfff, 0xfff, 0xfff, 0x32a, 0x3db, 0x364,
-	0x2dc, 0xfff, 0x30f, 0x3d7, 0x4a5, 0x050, 0xfff, 0xfff,
-	0x029, 0xfff, 0xfff, 0xfff, 0xfff, 0x1d1, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x480, 0xfff,
-	0x4ed, 0x081, 0x0a1, 0xfff, 0xfff, 0xfff, 0x30e, 0x52f,
-	0x257, 0xfff, 0xfff, 0x447, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x401, 0x3cc, 0xfff, 0xfff, 0x0fb,
-	0x2c9, 0x42a, 0x314, 0x33e, 0x3bd, 0x318, 0xfff, 0x10e,
-	0x2a1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x24c,
-	0x506, 0xfff, 0x267, 0xfff, 0xfff, 0x219, 0xfff, 0x1eb,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x309, 0x3e2, 0x46c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x384, 0xfff, 0xfff, 0xfff, 0xfff, 0x50c, 0xfff, 0x24b,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x038,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x194,
-	0x143, 0x3e3, 0xfff, 0xfff, 0xfff, 0x4c2, 0xfff, 0xfff,
-	0x0e1, 0x25c, 0xfff, 0x237, 0xfff, 0x1fe, 0xfff, 0xfff,
-	0xfff, 0x065, 0x2a4, 0xfff, 0x386, 0x55a, 0x11b, 0xfff,
-	0xfff, 0x192, 0xfff, 0x183, 0x00e, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x4b2, 0x18e, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x486, 0x4ef, 0x0c6, 0x380, 0xfff, 0x4a8, 0xfff,
-	0x0c5, 0xfff, 0xfff, 0xfff, 0xfff, 0x093, 0x1b8, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e6,
-	0xfff, 0x0f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x28e, 0xfff, 0x53b, 0x420, 0x22a, 0x33a, 0xfff, 0x387,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2a3, 0xfff, 0xfff,
-	0xfff, 0x428, 0x500, 0xfff, 0xfff, 0x120, 0x2c6, 0x290,
-	0x2f5, 0x0e3, 0xfff, 0x0b7, 0xfff, 0x319, 0x474, 0xfff,
-	0xfff, 0xfff, 0x529, 0x014, 0xfff, 0x41b, 0x40a, 0x18b,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d9,
-	0xfff, 0x38a, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ce, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x3b1, 0xfff, 0xfff, 0x05d,
-	0x2c4, 0xfff, 0xfff, 0x4af, 0xfff, 0x030, 0xfff, 0xfff,
-	0x203, 0xfff, 0x277, 0x256, 0xfff, 0xfff, 0xfff, 0x4f9,
-	0xfff, 0x2c7, 0xfff, 0x466, 0x016, 0x1cd, 0xfff, 0x167,
-	0xfff, 0xfff, 0x0c8, 0xfff, 0x43d, 0xfff, 0xfff, 0x020,
-	0xfff, 0xfff, 0x232, 0x1cb, 0x1e0, 0xfff, 0xfff, 0x347,
-	0xfff, 0x478, 0xfff, 0x365, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x358, 0xfff, 0x10b, 0xfff, 0x35d, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x452, 0x22d, 0xfff, 0xfff, 0x47d, 0xfff,
-	0x2f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x460, 0xfff,
-	0xfff, 0xfff, 0x50b, 0xfff, 0xfff, 0xfff, 0x2ec, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x4b1, 0x422, 0xfff, 0xfff,
-	0xfff, 0x2d4, 0xfff, 0x239, 0xfff, 0xfff, 0xfff, 0x439,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x491, 0x075, 0xfff, 0xfff, 0xfff, 0x06c, 0xfff,
-	0xfff, 0x0f9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x139, 0xfff, 0x4f6, 0xfff, 0xfff, 0x409, 0xfff,
-	0xfff, 0x15b, 0xfff, 0xfff, 0x348, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x4a2, 0x49d, 0xfff, 0x033, 0x175, 0xfff, 0x039,
-	0xfff, 0x312, 0x40c, 0xfff, 0xfff, 0x325, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x4aa, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0x165, 0x3bc, 0x48c, 0x310, 0x096,
-	0xfff, 0xfff, 0x250, 0x1a2, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x20d, 0x2ac, 0xfff, 0xfff, 0x39b, 0xfff, 0x377, 0xfff,
-	0x512, 0x495, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x357, 0x4ea, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x198, 0xfff, 0xfff, 0xfff, 0x434, 0x04a,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x062, 0xfff, 0x1d6, 0x1c8,
-	0xfff, 0x1f3, 0x281, 0xfff, 0x462, 0xfff, 0xfff, 0xfff,
-	0x4b0, 0xfff, 0x207, 0xfff, 0xfff, 0xfff, 0xfff, 0x3dd,
-	0xfff, 0xfff, 0x55d, 0xfff, 0x552, 0x494, 0x1af, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x227, 0xfff, 0xfff, 0x069,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x43e,
-	0x0b5, 0xfff, 0x524, 0x2d2, 0xfff, 0xfff, 0xfff, 0x28f,
-	0xfff, 0x01b, 0x50e, 0xfff, 0xfff, 0x1bb, 0xfff, 0xfff,
-	0x41d, 0xfff, 0x32e, 0x48e, 0xfff, 0x1f7, 0x224, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x394, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x52c, 0xfff, 0xfff, 0xfff, 0x392, 0xfff, 0x1e7,
-	0xfff, 0xfff, 0x3f9, 0x3a7, 0xfff, 0x51f, 0xfff, 0x0bb,
-	0x118, 0x3ca, 0xfff, 0x1dd, 0xfff, 0x48b, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x50f, 0xfff, 0x0d6, 0xfff, 0x1fa, 0xfff,
-	0x11e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d7, 0xfff, 0x078,
-	0x008, 0xfff, 0x25d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x032, 0x33c, 0xfff, 0x4d9, 0x160, 0xfff, 0xfff, 0x300,
-	0x0b1, 0xfff, 0x322, 0xfff, 0x4ec, 0xfff, 0xfff, 0x200,
-	0x00c, 0x369, 0x473, 0xfff, 0xfff, 0x32c, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x53e, 0x3d4, 0x417, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x34b, 0x001, 0x39a, 0x02c, 0xfff, 0xfff, 0x2ce, 0x00f,
-	0xfff, 0x0ba, 0xfff, 0xfff, 0xfff, 0xfff, 0x060, 0xfff,
-	0x406, 0xfff, 0xfff, 0xfff, 0x4ee, 0x4ac, 0xfff, 0x43f,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x29b, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x216,
-	0x190, 0xfff, 0x396, 0x464, 0xfff, 0xfff, 0x323, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e9, 0xfff, 0x26d,
-	0x2cd, 0x040, 0xfff, 0xfff, 0xfff, 0xfff, 0x38b, 0x3c0,
-	0xfff, 0xfff, 0xfff, 0x1f2, 0xfff, 0x0ea, 0xfff, 0xfff,
-	0x472, 0xfff, 0x1fb, 0xfff, 0xfff, 0x0af, 0x27f, 0xfff,
-	0xfff, 0xfff, 0x479, 0x023, 0xfff, 0x0d8, 0x3b3, 0xfff,
-	0xfff, 0xfff, 0x121, 0xfff, 0xfff, 0x3bf, 0xfff, 0xfff,
-	0x16b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x45a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x0be, 0xfff, 0xfff, 0xfff, 0x111, 0xfff, 0x220,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x09b, 0x218, 0xfff, 0x022, 0x202, 0xfff,
-	0x4c8, 0xfff, 0x0ed, 0xfff, 0xfff, 0x182, 0xfff, 0xfff,
-	0xfff, 0x17f, 0x213, 0xfff, 0x321, 0x36a, 0xfff, 0x086,
-	0xfff, 0xfff, 0xfff, 0x43b, 0x088, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x26c, 0xfff, 0x2f8, 0x3b4, 0xfff, 0xfff, 0xfff,
-	0x132, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x333, 0x444,
-	0x0c1, 0x4d8, 0x46d, 0x264, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x426, 0xfff, 0xfff, 0xfff, 0xfff, 0x2fe, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x011, 0xfff, 0x05f, 0xfff, 0xfff, 0xfff,
-	0xfff, 0x10c, 0x101, 0xfff, 0xfff, 0xfff, 0xfff, 0x110,
-	0xfff, 0x044, 0x304, 0x361, 0x404, 0xfff, 0x51b, 0x099,
-	0xfff, 0x440, 0xfff, 0xfff, 0xfff, 0x222, 0xfff, 0xfff,
-	0xfff, 0xfff, 0x1b5, 0xfff, 0x136, 0x430, 0xfff, 0x1da,
-	0xfff, 0xfff, 0xfff, 0x043, 0xfff, 0x17c, 0xfff, 0xfff,
-	0xfff, 0x01c, 0xfff, 0xfff, 0xfff, 0x425, 0x236, 0xfff,
-	0x317, 0xfff, 0xfff, 0x437, 0x3fc, 0xfff, 0x1f1, 0xfff,
-	0x324, 0xfff, 0xfff, 0x0ca, 0x306, 0xfff, 0x548, 0xfff,
-	0x46e, 0xfff, 0xfff, 0xfff, 0x4b8, 0x1c2, 0x286, 0xfff,
-	0xfff, 0x087, 0x18a, 0x19f, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x18c, 0xfff, 0x215, 0xfff, 0xfff, 0xfff, 0xfff, 0x283,
-	0xfff, 0xfff, 0xfff, 0x126, 0xfff, 0xfff, 0x370, 0xfff,
-	0x53f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x31c, 0xfff,
-	0x4d1, 0xfff, 0xfff, 0xfff, 0x021, 0xfff, 0x157, 0xfff,
-	0xfff, 0x028, 0x16e, 0xfff, 0x421, 0xfff, 0x1c6, 0xfff,
-	0xfff, 0x511, 0xfff, 0xfff, 0x39c, 0x46f, 0x1b2, 0xfff,
-	0xfff, 0x316, 0xfff, 0xfff, 0x009, 0xfff, 0xfff, 0x195,
-	0xfff, 0x240, 0x546, 0xfff, 0xfff, 0x520, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x454, 0xfff, 0xfff, 0xfff,
-	0x3f3, 0xfff, 0xfff, 0x187, 0xfff, 0x4a9, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x51c, 0x453, 0x1e6, 0xfff,
-	0xfff, 0xfff, 0x1b0, 0xfff, 0x477, 0xfff, 0xfff, 0xfff,
-	0x4fe, 0xfff, 0x32f, 0xfff, 0xfff, 0x15e, 0x1d4, 0xfff,
-	0x0e5, 0xfff, 0xfff, 0xfff, 0x242, 0x14b, 0x046, 0xfff,
-	0x3f6, 0x3bb, 0x3e4, 0xfff, 0xfff, 0x2e3, 0xfff, 0x245,
-	0xfff, 0x149, 0xfff, 0xfff, 0xfff, 0x2db, 0xfff, 0xfff,
-	0x181, 0xfff, 0x089, 0x2c5, 0xfff, 0x1f5, 0xfff, 0x2d6,
-	0x507, 0xfff, 0x42d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0x080, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
-	0xfff, 0xfff, 0xfff, 0xfff, 0x3c3, 0x320, 0xfff, 0x1e1,
-	0xfff, 0x0f5, 0x13b, 0xfff, 0xfff, 0xfff, 0x003, 0x4da,
-	0xfff, 0xfff, 0xfff, 0x42c, 0xfff, 0xfff, 0x0cb, 0xfff,
-	0x536, 0x2c3, 0xfff, 0xfff, 0xfff, 0xfff, 0x199, 0xfff,
-	0xfff, 0x0c0, 0xfff, 0x01e, 0x497, 0xfff, 0xfff, 0x3e5,
-	0xfff, 0xfff, 0xfff, 0x0cf, 0xfff, 0x2bd, 0xfff, 0x223,
-	0xfff, 0x3ff, 0xfff, 0x058, 0x174, 0x3ef, 0xfff, 0x002
-};
-
-static unsigned short err_pos(unsigned short din)
-{
-	BUG_ON(din >= ARRAY_SIZE(err_pos_lut));
-	return err_pos_lut[din];
-}
-static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-	if ((chk_syndrome_list[0] | chk_syndrome_list[1] |
-	     chk_syndrome_list[2] | chk_syndrome_list[3] |
-	     chk_syndrome_list[4] | chk_syndrome_list[5] |
-	     chk_syndrome_list[6] | chk_syndrome_list[7]) != 0x0) {
-		return -EINVAL;
-	} else {
-		err_info[0] = 0x0;
-		return 0;
-	}
-}
-static int chk_1_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-	unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
-	tmp0 = gf4096_mul(chk_syndrome_list[1], gf4096_inv(chk_syndrome_list[0]));
-	tmp1 = gf4096_mul(chk_syndrome_list[2], gf4096_inv(chk_syndrome_list[1]));
-	tmp2 = gf4096_mul(chk_syndrome_list[3], gf4096_inv(chk_syndrome_list[2]));
-	tmp3 = gf4096_mul(chk_syndrome_list[4], gf4096_inv(chk_syndrome_list[3]));
-	tmp4 = gf4096_mul(chk_syndrome_list[5], gf4096_inv(chk_syndrome_list[4]));
-	tmp5 = gf4096_mul(chk_syndrome_list[6], gf4096_inv(chk_syndrome_list[5]));
-	tmp6 = gf4096_mul(chk_syndrome_list[7], gf4096_inv(chk_syndrome_list[6]));
-	if ((tmp0 == tmp1) & (tmp1 == tmp2) & (tmp2 == tmp3) & (tmp3 == tmp4) & (tmp4 == tmp5) & (tmp5 == tmp6)) {
-		err_info[0] = 0x1;	// encode 1-symbol error as 0x1
-		err_info[1] = err_pos(tmp0);
-		err_info[1] = (unsigned short)(0x55e - err_info[1]);
-		err_info[5] = chk_syndrome_list[0];
-		return 0;
-	} else
-		return -EINVAL;
-}
-static int chk_2_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-	unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
-	unsigned short coefs[4];
-	unsigned short err_pats[4];
-	int found_num_root = 0;
-	unsigned short bit2_root0, bit2_root1;
-	unsigned short bit2_root0_inv, bit2_root1_inv;
-	unsigned short err_loc_eqn, test_root;
-	unsigned short bit2_loc0, bit2_loc1;
-	unsigned short bit2_pat0, bit2_pat1;
-
-	find_2x2_soln(chk_syndrome_list[1],
-		      chk_syndrome_list[0],
-		      chk_syndrome_list[2], chk_syndrome_list[1], chk_syndrome_list[2], chk_syndrome_list[3], coefs);
-	for (test_root = 0x1; test_root < 0xfff; test_root++) {
-		err_loc_eqn =
-		    gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
-		if (err_loc_eqn == 0x0) {
-			if (found_num_root == 0) {
-				bit2_root0 = test_root;
-				found_num_root = 1;
-			} else if (found_num_root == 1) {
-				bit2_root1 = test_root;
-				found_num_root = 2;
-				break;
-			}
-		}
-	}
-	if (found_num_root != 2)
-		return -EINVAL;
-	else {
-		bit2_root0_inv = gf4096_inv(bit2_root0);
-		bit2_root1_inv = gf4096_inv(bit2_root1);
-		find_2bit_err_pats(chk_syndrome_list[0],
-				   chk_syndrome_list[1], bit2_root0_inv, bit2_root1_inv, err_pats);
-		bit2_pat0 = err_pats[0];
-		bit2_pat1 = err_pats[1];
-		//for(x+1)
-		tmp0 = gf4096_mul(gf4096_mul(bit2_root0_inv, bit2_root0_inv), gf4096_mul(bit2_root0_inv, bit2_root0_inv));	//rinv0^4
-		tmp1 = gf4096_mul(bit2_root0_inv, tmp0);	//rinv0^5
-		tmp2 = gf4096_mul(bit2_root0_inv, tmp1);	//rinv0^6
-		tmp3 = gf4096_mul(bit2_root0_inv, tmp2);	//rinv0^7
-		tmp4 = gf4096_mul(gf4096_mul(bit2_root1_inv, bit2_root1_inv), gf4096_mul(bit2_root1_inv, bit2_root1_inv));	//rinv1^4
-		tmp5 = gf4096_mul(bit2_root1_inv, tmp4);	//rinv1^5
-		tmp6 = gf4096_mul(bit2_root1_inv, tmp5);	//rinv1^6
-		tmp7 = gf4096_mul(bit2_root1_inv, tmp6);	//rinv1^7
-		//check if only 2-bit error
-		if ((chk_syndrome_list[4] ==
-		     (gf4096_mul(bit2_pat0, tmp0) ^
-		      gf4096_mul(bit2_pat1,
-				 tmp4))) & (chk_syndrome_list[5] ==
-					    (gf4096_mul(bit2_pat0, tmp1) ^
-					     gf4096_mul(bit2_pat1,
-							tmp5))) &
-		    (chk_syndrome_list[6] ==
-		     (gf4096_mul(bit2_pat0, tmp2) ^
-		      gf4096_mul(bit2_pat1,
-				 tmp6))) & (chk_syndrome_list[7] ==
-					    (gf4096_mul(bit2_pat0, tmp3) ^ gf4096_mul(bit2_pat1, tmp7)))) {
-			if ((err_pos(bit2_root0_inv) == 0xfff) | (err_pos(bit2_root1_inv) == 0xfff)) {
-				return -EINVAL;
-			} else {
-				bit2_loc0 = 0x55e - err_pos(bit2_root0_inv);
-				bit2_loc1 = 0x55e - err_pos(bit2_root1_inv);
-				err_info[0] = 0x2;	// encode 2-symbol error as 0x2
-				err_info[1] = bit2_loc0;
-				err_info[2] = bit2_loc1;
-				err_info[5] = bit2_pat0;
-				err_info[6] = bit2_pat1;
-				return 0;
-			}
-		} else
-			return -EINVAL;
-	}
-}
-static int chk_3_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-	unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
-	unsigned short coefs[4];
-	unsigned short err_pats[4];
-	int found_num_root = 0;
-	unsigned short bit3_root0, bit3_root1, bit3_root2;
-	unsigned short bit3_root0_inv, bit3_root1_inv, bit3_root2_inv;
-	unsigned short err_loc_eqn, test_root;
-
-	find_3bit_err_coefs(chk_syndrome_list[0], chk_syndrome_list[1],
-			    chk_syndrome_list[2], chk_syndrome_list[3],
-			    chk_syndrome_list[4], chk_syndrome_list[5], coefs);
-
-	for (test_root = 0x1; test_root < 0xfff; test_root++) {
-		err_loc_eqn = gf4096_mul(coefs[2],
-					 gf4096_mul(gf4096_mul(test_root, test_root),
-						    test_root)) ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root))
-			^ gf4096_mul(coefs[0], test_root) ^ 0x1;
-
-		if (err_loc_eqn == 0x0) {
-			if (found_num_root == 0) {
-				bit3_root0 = test_root;
-				found_num_root = 1;
-			} else if (found_num_root == 1) {
-				bit3_root1 = test_root;
-				found_num_root = 2;
-			} else if (found_num_root == 2) {
-				bit3_root2 = test_root;
-				found_num_root = 3;
-				break;
-			}
-		}
-	}
-	if (found_num_root != 3)
-		return -EINVAL;
-	else {
-		bit3_root0_inv = gf4096_inv(bit3_root0);
-		bit3_root1_inv = gf4096_inv(bit3_root1);
-		bit3_root2_inv = gf4096_inv(bit3_root2);
-
-		find_3bit_err_pats(chk_syndrome_list[0], chk_syndrome_list[1],
-				   chk_syndrome_list[2], bit3_root0_inv,
-				   bit3_root1_inv, bit3_root2_inv, err_pats);
-
-		//check if only 3-bit error
-		tmp0 = gf4096_mul(bit3_root0_inv, bit3_root0_inv);
-		tmp0 = gf4096_mul(tmp0, tmp0);
-		tmp0 = gf4096_mul(tmp0, bit3_root0_inv);
-		tmp0 = gf4096_mul(tmp0, bit3_root0_inv);	//rinv0^6
-		tmp1 = gf4096_mul(tmp0, bit3_root0_inv);	//rinv0^7
-		tmp2 = gf4096_mul(bit3_root1_inv, bit3_root1_inv);
-		tmp2 = gf4096_mul(tmp2, tmp2);
-		tmp2 = gf4096_mul(tmp2, bit3_root1_inv);
-		tmp2 = gf4096_mul(tmp2, bit3_root1_inv);	//rinv1^6
-		tmp3 = gf4096_mul(tmp2, bit3_root1_inv);	//rinv1^7
-		tmp4 = gf4096_mul(bit3_root2_inv, bit3_root2_inv);
-		tmp4 = gf4096_mul(tmp4, tmp4);
-		tmp4 = gf4096_mul(tmp4, bit3_root2_inv);
-		tmp4 = gf4096_mul(tmp4, bit3_root2_inv);	//rinv2^6
-		tmp5 = gf4096_mul(tmp4, bit3_root2_inv);	//rinv2^7
-
-		//check if only 3 errors
-		if ((chk_syndrome_list[6] == (gf4096_mul(err_pats[0], tmp0) ^
-					      gf4096_mul(err_pats[1], tmp2) ^
-					      gf4096_mul(err_pats[2], tmp4))) &
-		    (chk_syndrome_list[7] == (gf4096_mul(err_pats[0], tmp1) ^
-					      gf4096_mul(err_pats[1], tmp3) ^ gf4096_mul(err_pats[2], tmp5)))) {
-			if ((err_pos(bit3_root0_inv) == 0xfff) |
-			    (err_pos(bit3_root1_inv) == 0xfff) | (err_pos(bit3_root2_inv) == 0xfff)) {
-				return -EINVAL;
-			} else {
-				err_info[0] = 0x3;
-				err_info[1] = (0x55e - err_pos(bit3_root0_inv));
-				err_info[2] = (0x55e - err_pos(bit3_root1_inv));
-				err_info[3] = (0x55e - err_pos(bit3_root2_inv));
-				err_info[5] = err_pats[0];
-				err_info[6] = err_pats[1];
-				err_info[7] = err_pats[2];
-				return 0;
-			}
-		} else
-			return -EINVAL;
-	}
-}
-static int chk_4_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
-{
-	unsigned short coefs[4];
-	unsigned short err_pats[4];
-	int found_num_root = 0;
-	unsigned short bit4_root0, bit4_root1, bit4_root2, bit4_root3;
-	unsigned short bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv;
-	unsigned short err_loc_eqn, test_root;
-
-	find_4bit_err_coefs(chk_syndrome_list[0],
-			    chk_syndrome_list[1],
-			    chk_syndrome_list[2],
-			    chk_syndrome_list[3],
-			    chk_syndrome_list[4],
-			    chk_syndrome_list[5], chk_syndrome_list[6], chk_syndrome_list[7], coefs);
-
-	for (test_root = 0x1; test_root < 0xfff; test_root++) {
-		err_loc_eqn =
-		    gf4096_mul(coefs[3],
-			       gf4096_mul(gf4096_mul
-					  (gf4096_mul(test_root, test_root),
-					   test_root),
-					  test_root)) ^ gf4096_mul(coefs[2],
-								   gf4096_mul
-								   (gf4096_mul(test_root, test_root), test_root))
-		    ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root)
-		    ^ 0x1;
-		if (err_loc_eqn == 0x0) {
-			if (found_num_root == 0) {
-				bit4_root0 = test_root;
-				found_num_root = 1;
-			} else if (found_num_root == 1) {
-				bit4_root1 = test_root;
-				found_num_root = 2;
-			} else if (found_num_root == 2) {
-				bit4_root2 = test_root;
-				found_num_root = 3;
-			} else {
-				found_num_root = 4;
-				bit4_root3 = test_root;
-				break;
-			}
-		}
-	}
-	if (found_num_root != 4) {
-		return -EINVAL;
-	} else {
-		bit4_root0_inv = gf4096_inv(bit4_root0);
-		bit4_root1_inv = gf4096_inv(bit4_root1);
-		bit4_root2_inv = gf4096_inv(bit4_root2);
-		bit4_root3_inv = gf4096_inv(bit4_root3);
-		find_4bit_err_pats(chk_syndrome_list[0],
-				   chk_syndrome_list[1],
-				   chk_syndrome_list[2],
-				   chk_syndrome_list[3],
-				   bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv, err_pats);
-		err_info[0] = 0x4;
-		err_info[1] = (0x55e - err_pos(bit4_root0_inv));
-		err_info[2] = (0x55e - err_pos(bit4_root1_inv));
-		err_info[3] = (0x55e - err_pos(bit4_root2_inv));
-		err_info[4] = (0x55e - err_pos(bit4_root3_inv));
-		err_info[5] = err_pats[0];
-		err_info[6] = err_pats[1];
-		err_info[7] = err_pats[2];
-		err_info[8] = err_pats[3];
-		return 0;
-	}
-}
-
-void correct_12bit_symbol(unsigned char *buf, unsigned short sym,
-			  unsigned short val)
-{
-	if (unlikely(sym > 1366)) {
-		printk(KERN_ERR "Error: symbol %d out of range; cannot correct\n", sym);
-	} else if (sym == 0) {
-		buf[0] ^= val;
-	} else if (sym & 1) {
-		buf[1+(3*(sym-1))/2] ^= (val >> 4);
-		buf[2+(3*(sym-1))/2] ^= ((val & 0xf) << 4);
-	} else {
-		buf[2+(3*(sym-2))/2] ^= (val >> 8);
-		buf[3+(3*(sym-2))/2] ^= (val & 0xff);
-	}
-}
-
-static int debugecc = 0;
-module_param(debugecc, int, 0644);
-
-int cafe_correct_ecc(unsigned char *buf,
-		     unsigned short *chk_syndrome_list)
-{
-	unsigned short err_info[9];
-	int i;
-
-	if (debugecc) {
-		printk(KERN_WARNING "cafe_correct_ecc invoked. Syndromes %x %x %x %x %x %x %x %x\n",
-		       chk_syndrome_list[0], chk_syndrome_list[1],
-		       chk_syndrome_list[2], chk_syndrome_list[3],
-		       chk_syndrome_list[4], chk_syndrome_list[5],
-		       chk_syndrome_list[6], chk_syndrome_list[7]);
-		for (i=0; i < 2048; i+=16) {
-			printk(KERN_WARNING "D %04x: %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
-			       i,
-			       buf[i], buf[i+1], buf[i+2], buf[i+3],
-			       buf[i+4], buf[i+5], buf[i+6], buf[i+7],
-			       buf[i+8], buf[i+9], buf[i+10], buf[i+11],
-			       buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
-		}
-		for ( ; i < 2112; i+=16) {
-			printk(KERN_WARNING "O   %02x: %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
-			       i - 2048,
-			       buf[i], buf[i+1], buf[i+2], buf[i+3],
-			       buf[i+4], buf[i+5], buf[i+6], buf[i+7],
-			       buf[i+8], buf[i+9], buf[i+10], buf[i+11],
-			       buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
-		}
-	}
-
-
-
-	if (chk_no_err_only(chk_syndrome_list, err_info) &&
-	    chk_1_err_only(chk_syndrome_list, err_info) &&
-	    chk_2_err_only(chk_syndrome_list, err_info) &&
-	    chk_3_err_only(chk_syndrome_list, err_info) &&
-	    chk_4_err_only(chk_syndrome_list, err_info)) {
-		return -EIO;
-	}
-
-	for (i=0; i < err_info[0]; i++) {
-		if (debugecc)
-			printk(KERN_WARNING "Correct symbol %d with 0x%03x\n",
-			       err_info[1+i], err_info[5+i]);
-
-		correct_12bit_symbol(buf, err_info[1+i], err_info[5+i]);
-	}
-
-	return err_info[0];
-}
-
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe_nand.c
similarity index 88%
rename from drivers/mtd/nand/cafe.c
rename to drivers/mtd/nand/cafe_nand.c
index c328a7514510d836e843b6657e4bf1f71340389b..cff969d05d4a1824cb18fda1808f89a9f9700000 100644
--- a/drivers/mtd/nand/cafe.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -11,6 +11,7 @@
 #undef DEBUG
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
+#include <linux/rslib.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -46,13 +47,14 @@
 #define CAFE_GLOBAL_IRQ_MASK	0x300c
 #define CAFE_NAND_RESET		0x3034
 
-int cafe_correct_ecc(unsigned char *buf,
-		     unsigned short *chk_syndrome_list);
+/* Missing from the datasheet: bit 19 of CTRL1 sets CE0 vs. CE1 */
+#define CTRL1_CHIPSELECT	(1<<19)
 
 struct cafe_priv {
 	struct nand_chip nand;
 	struct pci_dev *pdev;
 	void __iomem *mmio;
+	struct rs_control *rs;
 	uint32_t ctl1;
 	uint32_t ctl2;
 	int datalen;
@@ -195,8 +197,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 
 	cafe->data_pos = cafe->datalen = 0;
 
-	/* Set command valid bit */
-	ctl1 = 0x80000000 | command;
+	/* Set command valid bit, mask in the chip select bit  */
+	ctl1 = 0x80000000 | command | (cafe->ctl1 & CTRL1_CHIPSELECT);
 
 	/* Set RD or WR bits as appropriate */
 	if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) {
@@ -309,8 +311,16 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 
 static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
 {
-	//struct cafe_priv *cafe = mtd->priv;
-	//	cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
+	struct cafe_priv *cafe = mtd->priv;
+
+	cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
+
+	/* Mask the appropriate bit into the stored value of ctl1
+	   which will be used by cafe_nand_cmdfunc() */
+	if (chipnr)
+		cafe->ctl1 |= CTRL1_CHIPSELECT;
+	else
+		cafe->ctl1 &= ~CTRL1_CHIPSELECT;
 }
 
 static int cafe_nand_interrupt(int irq, void *id)
@@ -374,28 +384,66 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 
 	if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
-		unsigned short syn[8];
-		int i;
+		unsigned short syn[8], pat[4];
+		int pos[4];
+		u8 *oob = chip->oob_poi;
+		int i, n;
 
 		for (i=0; i<8; i+=2) {
 			uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2));
-			syn[i] = tmp & 0xfff;
-			syn[i+1] = (tmp >> 16) & 0xfff;
+			syn[i] = cafe->rs->index_of[tmp & 0xfff];
+			syn[i+1] = cafe->rs->index_of[(tmp >> 16) & 0xfff];
+		}
+
+		n = decode_rs16(cafe->rs, NULL, NULL, 1367, syn, 0, pos, 0,
+		                pat);
+
+		for (i = 0; i < n; i++) {
+			int p = pos[i];
+
+			/* The 12-bit symbols are mapped to bytes here */
+
+			if (p > 1374) {
+				/* out of range */
+				n = -1374;
+			} else if (p == 0) {
+				/* high four bits do not correspond to data */
+				if (pat[i] > 0xff)
+					n = -2048;
+				else
+					buf[0] ^= pat[i];
+			} else if (p == 1365) {
+				buf[2047] ^= pat[i] >> 4;
+				oob[0] ^= pat[i] << 4;
+			} else if (p > 1365) {
+				if ((p & 1) == 1) {
+					oob[3*p/2 - 2048] ^= pat[i] >> 4;
+					oob[3*p/2 - 2047] ^= pat[i] << 4;
+				} else {
+					oob[3*p/2 - 2049] ^= pat[i] >> 8;
+					oob[3*p/2 - 2048] ^= pat[i];
+				}
+			} else if ((p & 1) == 1) {
+				buf[3*p/2] ^= pat[i] >> 4;
+				buf[3*p/2 + 1] ^= pat[i] << 4;
+			} else {
+				buf[3*p/2 - 1] ^= pat[i] >> 8;
+				buf[3*p/2] ^= pat[i];
+			}
 		}
 
-		if ((i = cafe_correct_ecc(buf, syn)) < 0) {
+		if (n < 0) {
 			dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n",
 				cafe_readl(cafe, NAND_ADDR2) * 2048);
-			for (i=0; i< 0x5c; i+=4)
+			for (i = 0; i < 0x5c; i += 4)
 				printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
 			mtd->ecc_stats.failed++;
 		} else {
-			dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", i);
-			mtd->ecc_stats.corrected += i;
+			dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n);
+			mtd->ecc_stats.corrected += n;
 		}
 	}
 
-
 	return 0;
 }
 
@@ -416,7 +464,7 @@ static uint8_t cafe_mirror_pattern_512[] = { 0xBC };
 
 static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+		| NAND_BBT_2BIT | NAND_BBT_VERSION,
 	.offs =	14,
 	.len = 4,
 	.veroffs = 18,
@@ -426,7 +474,7 @@ static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
 
 static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = {
 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+		| NAND_BBT_2BIT | NAND_BBT_VERSION,
 	.offs =	14,
 	.len = 4,
 	.veroffs = 18,
@@ -442,7 +490,7 @@ static struct nand_ecclayout cafe_oobinfo_512 = {
 
 static struct nand_bbt_descr cafe_bbt_main_descr_512 = {
 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+		| NAND_BBT_2BIT | NAND_BBT_VERSION,
 	.offs =	14,
 	.len = 1,
 	.veroffs = 15,
@@ -452,7 +500,7 @@ static struct nand_bbt_descr cafe_bbt_main_descr_512 = {
 
 static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+		| NAND_BBT_2BIT | NAND_BBT_VERSION,
 	.offs =	14,
 	.len = 1,
 	.veroffs = 15,
@@ -525,6 +573,48 @@ static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 	return 0;
 }
 
+/* F_2[X]/(X**6+X+1)  */
+static unsigned short __devinit gf64_mul(u8 a, u8 b)
+{
+	u8 c;
+	unsigned int i;
+
+	c = 0;
+	for (i = 0; i < 6; i++) {
+		if (a & 1)
+			c ^= b;
+		a >>= 1;
+		b <<= 1;
+		if ((b & 0x40) != 0)
+			b ^= 0x43;
+	}
+
+	return c;
+}
+
+/* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X]  */
+static u16 __devinit gf4096_mul(u16 a, u16 b)
+{
+	u8 ah, al, bh, bl, ch, cl;
+
+	ah = a >> 6;
+	al = a & 0x3f;
+	bh = b >> 6;
+	bl = b & 0x3f;
+
+	ch = gf64_mul(ah ^ al, bh ^ bl) ^ gf64_mul(al, bl);
+	cl = gf64_mul(gf64_mul(ah, bh), 0x21) ^ gf64_mul(al, bl);
+
+	return (ch << 6) ^ cl;
+}
+
+static int __devinit cafe_mul(int x)
+{
+	if (x == 0)
+		return 1;
+	return gf4096_mul(x, 0xe01);
+}
+
 static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
@@ -564,6 +654,12 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 	}
 	cafe->nand.buffers = (void *)cafe->dmabuf + 2112;
 
+	cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8);
+	if (!cafe->rs) {
+		err = -ENOMEM;
+		goto out_ior;
+	}
+
 	cafe->nand.cmdfunc = cafe_nand_cmdfunc;
 	cafe->nand.dev_ready = cafe_device_ready;
 	cafe->nand.read_byte = cafe_read_byte;
@@ -646,7 +742,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 		cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
 
 	/* Scan to find existence of the device */
-	if (nand_scan_ident(mtd, 1)) {
+	if (nand_scan_ident(mtd, 2)) {
 		err = -ENXIO;
 		goto out_irq;
 	}
@@ -713,6 +809,7 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev)
 	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
 	free_irq(pdev->irq, mtd);
 	nand_release(mtd);
+	free_rs(cafe->rs);
 	pci_iounmap(pdev, cafe->mmio);
 	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
 	kfree(mtd);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 04de315e4937c0e650025983b4364ad647c69dac..7e68203fe1ba1c46c779d55a5ae2c9151c5659bf 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -303,28 +303,27 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 	struct nand_chip *chip = mtd->priv;
 	u16 bad;
 
+	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
+
 	if (getchip) {
-		page = (int)(ofs >> chip->page_shift);
 		chipnr = (int)(ofs >> chip->chip_shift);
 
 		nand_get_device(chip, mtd, FL_READING);
 
 		/* Select the NAND device */
 		chip->select_chip(mtd, chipnr);
-	} else
-		page = (int)(ofs >> chip->page_shift);
+	}
 
 	if (chip->options & NAND_BUSWIDTH_16) {
 		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
-			      page & chip->pagemask);
+			      page);
 		bad = cpu_to_le16(chip->read_word(mtd));
 		if (chip->badblockpos & 0x1)
 			bad >>= 8;
 		if ((bad & 0xFF) != 0xff)
 			res = 1;
 	} else {
-		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
-			      page & chip->pagemask);
+		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page);
 		if (chip->read_byte(mtd) != 0xff)
 			res = 1;
 	}
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
new file mode 100644
index 0000000000000000000000000000000000000000..cd725fc5e813e7b11f03207944fbb14be33229a6
--- /dev/null
+++ b/drivers/mtd/nand/plat_nand.c
@@ -0,0 +1,150 @@
+/*
+ * Generic NAND driver
+ *
+ * Author: Vitaly Wool <vitalywool@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+struct plat_nand_data {
+	struct nand_chip	chip;
+	struct mtd_info		mtd;
+	void __iomem		*io_base;
+#ifdef CONFIG_MTD_PARTITIONS
+	int			nr_parts;
+	struct mtd_partition	*parts;
+#endif
+};
+
+/*
+ * Probe for the NAND device.
+ */
+static int __init plat_nand_probe(struct platform_device *pdev)
+{
+	struct platform_nand_data *pdata = pdev->dev.platform_data;
+	struct plat_nand_data *data;
+	int res = 0;
+
+	/* Allocate memory for the device structure (and zero it) */
+	data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL);
+	if (!data) {
+		dev_err(&pdev->dev, "failed to allocate device structure.\n");
+		return -ENOMEM;
+	}
+
+	data->io_base = ioremap(pdev->resource[0].start,
+				pdev->resource[0].end - pdev->resource[0].start + 1);
+	if (data->io_base == NULL) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		kfree(data);
+		return -EIO;
+	}
+
+	data->chip.priv = &data;
+	data->mtd.priv = &data->chip;
+	data->mtd.owner = THIS_MODULE;
+
+	data->chip.IO_ADDR_R = data->io_base;
+	data->chip.IO_ADDR_W = data->io_base;
+	data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl;
+	data->chip.dev_ready = pdata->ctrl.dev_ready;
+	data->chip.select_chip = pdata->ctrl.select_chip;
+	data->chip.chip_delay = pdata->chip.chip_delay;
+	data->chip.options |= pdata->chip.options;
+
+	data->chip.ecc.hwctl = pdata->ctrl.hwcontrol;
+	data->chip.ecc.layout = pdata->chip.ecclayout;
+	data->chip.ecc.mode = NAND_ECC_SOFT;
+
+	platform_set_drvdata(pdev, data);
+
+	/* Scan to find existance of the device */
+	if (nand_scan(&data->mtd, 1)) {
+		res = -ENXIO;
+		goto out;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	if (pdata->chip.part_probe_types) {
+		res = parse_mtd_partitions(&data->mtd,
+					pdata->chip.part_probe_types,
+					&data->parts, 0);
+		if (res > 0) {
+			add_mtd_partitions(&data->mtd, data->parts, res);
+			return 0;
+		}
+	}
+	if (pdata->chip.partitions) {
+		data->parts = pdata->chip.partitions;
+		res = add_mtd_partitions(&data->mtd, data->parts,
+			pdata->chip.nr_partitions);
+	} else
+#endif
+	res = add_mtd_device(&data->mtd);
+
+	if (!res)
+		return res;
+
+	nand_release(&data->mtd);
+out:
+	platform_set_drvdata(pdev, NULL);
+	iounmap(data->io_base);
+	kfree(data);
+	return res;
+}
+
+/*
+ * Remove a NAND device.
+ */
+static int __devexit plat_nand_remove(struct platform_device *pdev)
+{
+	struct plat_nand_data *data = platform_get_drvdata(pdev);
+	struct platform_nand_data *pdata = pdev->dev.platform_data;
+
+	nand_release(&data->mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+	if (data->parts && data->parts != pdata->chip.partitions)
+		kfree(data->parts);
+#endif
+	iounmap(data->io_base);
+	kfree(data);
+
+	return 0;
+}
+
+static struct platform_driver plat_nand_driver = {
+	.probe		= plat_nand_probe,
+	.remove		= plat_nand_remove,
+	.driver		= {
+		.name	= "gen_nand",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init plat_nand_init(void)
+{
+	return platform_driver_register(&plat_nand_driver);
+}
+
+static void __exit plat_nand_exit(void)
+{
+	platform_driver_unregister(&plat_nand_driver);
+}
+
+module_init(plat_nand_init);
+module_exit(plat_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vitaly Wool");
+MODULE_DESCRIPTION("Simple generic NAND driver");
diff --git a/fs/jffs2/histo_mips.h b/fs/jffs2/histo_mips.h
deleted file mode 100644
index fa3dac19a109eeb2cb1a1c481dda948979e6946a..0000000000000000000000000000000000000000
--- a/fs/jffs2/histo_mips.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#define BIT_DIVIDER_MIPS 1043
-static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 6aff38930b50619475e4e2974341427f185298b8..4884d5edfe658282d626c6674497231a9ff4d20a 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -219,9 +219,9 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
 				struct jffs2_tmp_dnode_info *tn)
 {
 	uint32_t fn_end = tn->fn->ofs + tn->fn->size;
-	struct jffs2_tmp_dnode_info *insert_point = NULL, *this;
+	struct jffs2_tmp_dnode_info *this;
 
-	dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version);
+	dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
 
 	/* If a node has zero dsize, we only have to keep if it if it might be the
 	   node with highest version -- i.e. the one which will end up as f->metadata.
@@ -240,23 +240,16 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
 
 	/* Find the earliest node which _may_ be relevant to this one */
 	this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs);
-	if (!this) {
-		/* First addition to empty tree. $DEITY how I love the easy cases */
-		rb_link_node(&tn->rb, NULL, &rii->tn_root.rb_node);
-		rb_insert_color(&tn->rb, &rii->tn_root);
-		dbg_readinode("keep new frag\n");
-		return 0;
-	}
-
-	/* If we add a new node it'll be somewhere under here. */
-	insert_point = this;
-
-	/* If the node is coincident with another at a lower address,
-	   back up until the other node is found. It may be relevant */
-	while (tn->overlapped)
-		tn = tn_prev(tn);
+	if (this) {
+		/* If the node is coincident with another at a lower address,
+		   back up until the other node is found. It may be relevant */
+		while (this->overlapped)
+			this = tn_prev(this);
 
-	dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
+		/* First node should never be marked overlapped */
+		BUG_ON(!this);
+		dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
+	}
 
 	while (this) {
 		if (this->fn->ofs > fn_end)
@@ -274,11 +267,10 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
 				return 0;
 			} else {
 				/* Who cares if the new one is good; keep it for now anyway. */
+				dbg_readinode("Like new node. Throw away old\n");
 				rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
-				/* Same overlapping from in front and behind */
-				tn->overlapped = this->overlapped;
 				jffs2_kill_tn(c, this);
-				dbg_readinode("Like new node. Throw away old\n");
+				/* Same overlapping from in front and behind */
 				return 0;
 			}
 		}
@@ -291,13 +283,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
 				jffs2_kill_tn(c, tn);
 				return 0;
 			}
-			/* ... and is good. Kill 'this'... */
-			rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
-			tn->overlapped = this->overlapped;
-			jffs2_kill_tn(c, this);
-			/* ... and any subsequent nodes which are also overlapped */
-			this = tn_next(tn);
-			while (this && this->fn->ofs + this->fn->size < fn_end) {
+			/* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */
+			while (this && this->fn->ofs + this->fn->size <= fn_end) {
 				struct jffs2_tmp_dnode_info *next = tn_next(this);
 				if (this->version < tn->version) {
 					tn_erase(this, &rii->tn_root);
@@ -308,8 +295,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
 				}
 				this = next;
 			}
-			dbg_readinode("Done inserting new\n");
-			return 0;
+			dbg_readinode("Done killing overlapped nodes\n");
+			continue;
 		}
 		if (this->version > tn->version &&
 		    this->fn->ofs <= tn->fn->ofs &&
@@ -321,29 +308,21 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
 				return 0;
 			}
 			/* ... but 'this' was bad. Replace it... */
-			rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
 			dbg_readinode("Bad CRC on old overlapping node. Kill it\n");
+			tn_erase(this, &rii->tn_root);
 			jffs2_kill_tn(c, this);
-			return 0;
+			break;
 		}
-		/* We want to be inserted under the last node which is
-		   either at a lower offset _or_ has a smaller range */
-		if (this->fn->ofs < tn->fn->ofs ||
-		    (this->fn->ofs == tn->fn->ofs &&
-		     this->fn->size <= tn->fn->size))
-			insert_point = this;
 
 		this = tn_next(this);
 	}
-	dbg_readinode("insert_point %p, ver %d, 0x%x-0x%x, ov %d\n",
-		      insert_point, insert_point->version, insert_point->fn->ofs,
-		      insert_point->fn->ofs+insert_point->fn->size,
-		      insert_point->overlapped);
+
 	/* We neither completely obsoleted nor were completely
-	   obsoleted by an earlier node. Insert under insert_point */
+	   obsoleted by an earlier node. Insert into the tree */
 	{
-		struct rb_node *parent = &insert_point->rb;
-		struct rb_node **link = &parent;
+		struct rb_node *parent;
+		struct rb_node **link = &rii->tn_root.rb_node;
+		struct jffs2_tmp_dnode_info *insert_point = NULL;
 
 		while (*link) {
 			parent = *link;
@@ -359,6 +338,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
 		rb_link_node(&tn->rb, &insert_point->rb, link);
 		rb_insert_color(&tn->rb, &rii->tn_root);
 	}
+
 	/* If there's anything behind that overlaps us, note it */
 	this = tn_prev(tn);
 	if (this) {
@@ -457,7 +437,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
 	this = tn_last(&rii->tn_root);
 	while (this) {
 		dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs,
-			     this->fn->ofs+this->fn->size, this->overlapped);
+			      this->fn->ofs+this->fn->size, this->overlapped);
 		this = tn_prev(this);
 	}
 #endif
@@ -483,7 +463,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
 			vers_next = tn_prev(this);
 			eat_last(&ver_root, &this->rb);
 			if (check_tn_node(c, this)) {
-				dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n",
+				dbg_readinode("node ver %d, 0x%x-0x%x failed CRC\n",
 					     this->version, this->fn->ofs,
 					     this->fn->ofs+this->fn->size);
 				jffs2_kill_tn(c, this);
@@ -496,7 +476,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
 					high_ver = this->version;
 					rii->latest_ref = this->fn->raw;
 				}
-				dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n",
+				dbg_readinode("Add %p (v %d, 0x%x-0x%x, ov %d) to fragtree\n",
 					     this, this->version, this->fn->ofs,
 					     this->fn->ofs+this->fn->size, this->overlapped);
 
@@ -850,7 +830,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
 		return ret;
 	}
 #ifdef JFFS2_DBG_READINODE_MESSAGES
-	dbg_readinode("After adding ver %d:\n", tn->version);
+	dbg_readinode("After adding ver %d:\n", je32_to_cpu(rd->version));
 	tn = tn_first(&rii->tn_root);
 	while (tn) {
 		dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n",
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index c556e85a565cea44fbceca308514fa51e5c80c3e..91d1d0f1c66c72c1d0c925d383f8e2a02973e2c4 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -637,7 +637,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
 
 	memset(c->wbuf,0xff,c->wbuf_pagesize);
 	/* adjust write buffer offset, else we get a non contiguous write bug */
-	c->wbuf_ofs += c->wbuf_pagesize;
+	if (SECTOR_ADDR(c->wbuf_ofs) == SECTOR_ADDR(c->wbuf_ofs+c->wbuf_pagesize))
+		c->wbuf_ofs += c->wbuf_pagesize;
+	else
+		c->wbuf_ofs = 0xffffffff;
 	c->wbuf_len = 0;
 	return 0;
 }
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 45d482ce8397cf2920ac44919121bf3cb334100a..fd64ccfbce02874fd2600b79dc02d84767bde7ae 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -9,10 +9,6 @@
 #ifndef __MTD_MTD_H__
 #define __MTD_MTD_H__
 
-#ifndef __KERNEL__
-#error This is a kernel header. Perhaps include mtd-user.h instead?
-#endif
-
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/uio.h>
@@ -137,9 +133,6 @@ struct mtd_info {
 	int numeraseregions;
 	struct mtd_erase_region_info *eraseregions;
 
-	/* This really shouldn't be here. It can go away in 2.5 */
-	u_int32_t bank_size;
-
 	int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
 
 	/* This stuff for eXecute-In-Place */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index cf197ad62da6cd8801102946609ad1bd3fd5549b..d2365c8dcacc86ebf872a2124b3dc16201c09877 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -560,6 +560,7 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
  * @chip_delay:		R/B delay value in us
  * @options:		Option flags, e.g. 16bit buswidth
  * @ecclayout:		ecc layout info structure
+ * @part_probe_types:	NULL-terminated array of probe types
  * @priv:		hardware controller specific settings
  */
 struct platform_nand_chip {
@@ -570,6 +571,7 @@ struct platform_nand_chip {
 	struct nand_ecclayout	*ecclayout;
 	int			chip_delay;
 	unsigned int		options;
+	const char		**part_probe_types;
 	void			*priv;
 };
 
@@ -578,6 +580,8 @@ struct platform_nand_chip {
  * @hwcontrol:		platform specific hardware control structure
  * @dev_ready:		platform specific function to read ready/busy pin
  * @select_chip:	platform specific chip select function
+ * @cmd_ctrl:		platform specific function for controlling
+ *			ALE/CLE/nCE. Also used to write command and address
  * @priv:		private data to transport driver specific settings
  *
  * All fields are optional and depend on the hardware driver requirements
@@ -586,9 +590,21 @@ struct platform_nand_ctrl {
 	void		(*hwcontrol)(struct mtd_info *mtd, int cmd);
 	int		(*dev_ready)(struct mtd_info *mtd);
 	void		(*select_chip)(struct mtd_info *mtd, int chip);
+	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
+				    unsigned int ctrl);
 	void		*priv;
 };
 
+/**
+ * struct platform_nand_data - container structure for platform-specific data
+ * @chip:		chip level chip structure
+ * @ctrl:		controller level device structure
+ */
+struct platform_nand_data {
+	struct platform_nand_chip	chip;
+	struct platform_nand_ctrl	ctrl;
+};
+
 /* Some helpers to access the data structures */
 static inline
 struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
diff --git a/include/linux/rslib.h b/include/linux/rslib.h
index ace25acfdc97375d0d403afb4bf12c08443e6309..746580c1939c028d8f8ef8dc6bb460e5ed6dfc17 100644
--- a/include/linux/rslib.h
+++ b/include/linux/rslib.h
@@ -34,6 +34,7 @@
  * @prim:	Primitive element, index form
  * @iprim:	prim-th root of 1, index form
  * @gfpoly:	The primitive generator polynominal
+ * @gffunc:	Function to generate the field, if non-canonical representation
  * @users:	Users of this structure
  * @list:	List entry for the rs control list
 */
@@ -48,6 +49,7 @@ struct rs_control {
 	int 		prim;
 	int 		iprim;
 	int		gfpoly;
+	int		(*gffunc)(int);
 	int		users;
 	struct list_head list;
 };
@@ -77,6 +79,8 @@ int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len,
 /* Create or get a matching rs control structure */
 struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
 			   int nroots);
+struct rs_control *init_rs_non_canonical(int symsize, int (*func)(int),
+                                         int fcr, int prim, int nroots);
 
 /* Release a rs control structure */
 void free_rs(struct rs_control *rs);
diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c
index a4b730a2180cc129a46df390c4707ee247cf012f..5b0d8522b7ca16882b54cee337536a665cb825d0 100644
--- a/lib/reed_solomon/reed_solomon.c
+++ b/lib/reed_solomon/reed_solomon.c
@@ -56,6 +56,7 @@ static DEFINE_MUTEX(rslistlock);
  * rs_init - Initialize a Reed-Solomon codec
  * @symsize:	symbol size, bits (1-8)
  * @gfpoly:	Field generator polynomial coefficients
+ * @gffunc:	Field generator function
  * @fcr:	first root of RS code generator polynomial, index form
  * @prim:	primitive element to generate polynomial roots
  * @nroots:	RS code generator polynomial degree (number of roots)
@@ -63,8 +64,8 @@ static DEFINE_MUTEX(rslistlock);
  * Allocate a control structure and the polynom arrays for faster
  * en/decoding. Fill the arrays according to the given parameters.
  */
-static struct rs_control *rs_init(int symsize, int gfpoly, int fcr,
-				   int prim, int nroots)
+static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int),
+                                  int fcr, int prim, int nroots)
 {
 	struct rs_control *rs;
 	int i, j, sr, root, iprim;
@@ -82,6 +83,7 @@ static struct rs_control *rs_init(int symsize, int gfpoly, int fcr,
 	rs->prim = prim;
 	rs->nroots = nroots;
 	rs->gfpoly = gfpoly;
+	rs->gffunc = gffunc;
 
 	/* Allocate the arrays */
 	rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL);
@@ -99,17 +101,26 @@ static struct rs_control *rs_init(int symsize, int gfpoly, int fcr,
 	/* Generate Galois field lookup tables */
 	rs->index_of[0] = rs->nn;	/* log(zero) = -inf */
 	rs->alpha_to[rs->nn] = 0;	/* alpha**-inf = 0 */
-	sr = 1;
-	for (i = 0; i < rs->nn; i++) {
-		rs->index_of[sr] = i;
-		rs->alpha_to[i] = sr;
-		sr <<= 1;
-		if (sr & (1 << symsize))
-			sr ^= gfpoly;
-		sr &= rs->nn;
+	if (gfpoly) {
+		sr = 1;
+		for (i = 0; i < rs->nn; i++) {
+			rs->index_of[sr] = i;
+			rs->alpha_to[i] = sr;
+			sr <<= 1;
+			if (sr & (1 << symsize))
+				sr ^= gfpoly;
+			sr &= rs->nn;
+		}
+	} else {
+		sr = gffunc(0);
+		for (i = 0; i < rs->nn; i++) {
+			rs->index_of[sr] = i;
+			rs->alpha_to[i] = sr;
+			sr = gffunc(sr);
+		}
 	}
 	/* If it's not primitive, exit */
-	if(sr != 1)
+	if(sr != rs->alpha_to[0])
 		goto errpol;
 
 	/* Find prim-th root of 1, used in decoding */
@@ -173,18 +184,22 @@ void free_rs(struct rs_control *rs)
 }
 
 /**
- * init_rs - Find a matching or allocate a new rs control structure
+ * init_rs_internal - Find a matching or allocate a new rs control structure
  *  @symsize:	the symbol size (number of bits)
  *  @gfpoly:	the extended Galois field generator polynomial coefficients,
  *		with the 0th coefficient in the low order bit. The polynomial
  *		must be primitive;
+ *  @gffunc:	pointer to function to generate the next field element,
+ *		or the multiplicative identity element if given 0.  Used
+ *		instead of gfpoly if gfpoly is 0
  *  @fcr:  	the first consecutive root of the rs code generator polynomial
  *		in index form
  *  @prim:	primitive element to generate polynomial roots
  *  @nroots:	RS code generator polynomial degree (number of roots)
  */
-struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
-			   int nroots)
+static struct rs_control *init_rs_internal(int symsize, int gfpoly,
+                                           int (*gffunc)(int), int fcr,
+                                           int prim, int nroots)
 {
 	struct list_head	*tmp;
 	struct rs_control	*rs;
@@ -208,6 +223,8 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
 			continue;
 		if (gfpoly != rs->gfpoly)
 			continue;
+		if (gffunc != rs->gffunc)
+			continue;
 		if (fcr != rs->fcr)
 			continue;
 		if (prim != rs->prim)
@@ -220,7 +237,7 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
 	}
 
 	/* Create a new one */
-	rs = rs_init(symsize, gfpoly, fcr, prim, nroots);
+	rs = rs_init(symsize, gfpoly, gffunc, fcr, prim, nroots);
 	if (rs) {
 		rs->users = 1;
 		list_add(&rs->list, &rslist);
@@ -230,6 +247,42 @@ out:
 	return rs;
 }
 
+/**
+ * init_rs - Find a matching or allocate a new rs control structure
+ *  @symsize:	the symbol size (number of bits)
+ *  @gfpoly:	the extended Galois field generator polynomial coefficients,
+ *		with the 0th coefficient in the low order bit. The polynomial
+ *		must be primitive;
+ *  @fcr:  	the first consecutive root of the rs code generator polynomial
+ *		in index form
+ *  @prim:	primitive element to generate polynomial roots
+ *  @nroots:	RS code generator polynomial degree (number of roots)
+ */
+struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim,
+                           int nroots)
+{
+	return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots);
+}
+
+/**
+ * init_rs_non_canonical - Find a matching or allocate a new rs control
+ *                         structure, for fields with non-canonical
+ *                         representation
+ *  @symsize:	the symbol size (number of bits)
+ *  @gffunc:	pointer to function to generate the next field element,
+ *		or the multiplicative identity element if given 0.  Used
+ *		instead of gfpoly if gfpoly is 0
+ *  @fcr:  	the first consecutive root of the rs code generator polynomial
+ *		in index form
+ *  @prim:	primitive element to generate polynomial roots
+ *  @nroots:	RS code generator polynomial degree (number of roots)
+ */
+struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int),
+                                         int fcr, int prim, int nroots)
+{
+	return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots);
+}
+
 #ifdef CONFIG_REED_SOLOMON_ENC8
 /**
  *  encode_rs8 - Calculate the parity for data values (8bit data width)
@@ -321,6 +374,7 @@ EXPORT_SYMBOL_GPL(decode_rs16);
 #endif
 
 EXPORT_SYMBOL_GPL(init_rs);
+EXPORT_SYMBOL_GPL(init_rs_non_canonical);
 EXPORT_SYMBOL_GPL(free_rs);
 
 MODULE_LICENSE("GPL");