Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
new file mode 100644
index 0000000..4ebc2e5
--- /dev/null
+++ b/include/linux/mtd/blktrans.h
@@ -0,0 +1,72 @@
+/*
+ * $Id: blktrans.h,v 1.5 2003/06/23 12:00:08 dwmw2 Exp $
+ *
+ * (C) 2003 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Interface to Linux block layer for MTD 'translation layers'.
+ *
+ */
+
+#ifndef __MTD_TRANS_H__
+#define __MTD_TRANS_H__
+
+#include <asm/semaphore.h>
+
+struct hd_geometry;
+struct mtd_info;
+struct mtd_blktrans_ops;
+struct file;
+struct inode;
+
+struct mtd_blktrans_dev {
+	struct mtd_blktrans_ops *tr;
+	struct list_head list;
+	struct mtd_info *mtd;
+	struct semaphore sem;
+	int devnum;
+	int blksize;
+	unsigned long size;
+	int readonly;
+	void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */
+};
+
+struct blkcore_priv; /* Differs for 2.4 and 2.5 kernels; private */
+
+struct mtd_blktrans_ops {
+	char *name;
+	int major;
+	int part_bits;
+
+	/* Access functions */
+	int (*readsect)(struct mtd_blktrans_dev *dev,
+		    unsigned long block, char *buffer);
+	int (*writesect)(struct mtd_blktrans_dev *dev,
+		     unsigned long block, char *buffer);
+
+	/* Block layer ioctls */
+	int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
+	int (*flush)(struct mtd_blktrans_dev *dev);
+
+	/* Called with mtd_table_mutex held; no race with add/remove */
+	int (*open)(struct mtd_blktrans_dev *dev);
+	int (*release)(struct mtd_blktrans_dev *dev);
+
+	/* Called on {de,}registration and on subsequent addition/removal
+	   of devices, with mtd_table_mutex held. */
+	void (*add_mtd)(struct mtd_blktrans_ops *tr, struct mtd_info *mtd);
+	void (*remove_dev)(struct mtd_blktrans_dev *dev);
+
+	struct list_head devs;
+	struct list_head list;
+	struct module *owner;
+
+	struct mtd_blkcore_priv *blkcore_priv;
+};
+
+extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr);
+extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr);
+extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
+extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
+				 
+
+#endif /* __MTD_TRANS_H__ */
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
new file mode 100644
index 0000000..2ed8c58
--- /dev/null
+++ b/include/linux/mtd/cfi.h
@@ -0,0 +1,394 @@
+
+/* Common Flash Interface structures 
+ * See http://support.intel.com/design/flash/technote/index.htm
+ * $Id: cfi.h,v 1.50 2004/11/20 12:46:51 dwmw2 Exp $
+ */
+
+#ifndef __MTD_CFI_H__
+#define __MTD_CFI_H__
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/flashchip.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/cfi_endian.h>
+
+#ifdef CONFIG_MTD_CFI_I1
+#define cfi_interleave(cfi) 1
+#define cfi_interleave_is_1(cfi) (cfi_interleave(cfi) == 1)
+#else
+#define cfi_interleave_is_1(cfi) (0)
+#endif
+
+#ifdef CONFIG_MTD_CFI_I2
+# ifdef cfi_interleave
+#  undef cfi_interleave
+#  define cfi_interleave(cfi) ((cfi)->interleave)
+# else
+#  define cfi_interleave(cfi) 2
+# endif
+#define cfi_interleave_is_2(cfi) (cfi_interleave(cfi) == 2)
+#else
+#define cfi_interleave_is_2(cfi) (0)
+#endif
+
+#ifdef CONFIG_MTD_CFI_I4
+# ifdef cfi_interleave
+#  undef cfi_interleave
+#  define cfi_interleave(cfi) ((cfi)->interleave)
+# else
+#  define cfi_interleave(cfi) 4
+# endif
+#define cfi_interleave_is_4(cfi) (cfi_interleave(cfi) == 4)
+#else
+#define cfi_interleave_is_4(cfi) (0)
+#endif
+
+#ifdef CONFIG_MTD_CFI_I8
+# ifdef cfi_interleave
+#  undef cfi_interleave
+#  define cfi_interleave(cfi) ((cfi)->interleave)
+# else
+#  define cfi_interleave(cfi) 8
+# endif
+#define cfi_interleave_is_8(cfi) (cfi_interleave(cfi) == 8)
+#else
+#define cfi_interleave_is_8(cfi) (0)
+#endif
+
+static inline int cfi_interleave_supported(int i)
+{
+	switch (i) {
+#ifdef CONFIG_MTD_CFI_I1
+	case 1:
+#endif
+#ifdef CONFIG_MTD_CFI_I2
+	case 2:
+#endif
+#ifdef CONFIG_MTD_CFI_I4
+	case 4:
+#endif
+#ifdef CONFIG_MTD_CFI_I8
+	case 8:
+#endif
+		return 1;
+
+	default:
+		return 0;
+	}
+}
+
+
+/* NB: these values must represents the number of bytes needed to meet the 
+ *     device type (x8, x16, x32).  Eg. a 32 bit device is 4 x 8 bytes. 
+ *     These numbers are used in calculations.
+ */
+#define CFI_DEVICETYPE_X8  (8 / 8)
+#define CFI_DEVICETYPE_X16 (16 / 8)
+#define CFI_DEVICETYPE_X32 (32 / 8)
+#define CFI_DEVICETYPE_X64 (64 / 8)
+
+/* NB: We keep these structures in memory in HOST byteorder, except
+ * where individually noted.
+ */
+
+/* Basic Query Structure */
+struct cfi_ident {
+	uint8_t  qry[3];
+	uint16_t P_ID;
+	uint16_t P_ADR;
+	uint16_t A_ID;
+	uint16_t A_ADR;
+	uint8_t  VccMin;
+	uint8_t  VccMax;
+	uint8_t  VppMin;
+	uint8_t  VppMax;
+	uint8_t  WordWriteTimeoutTyp;
+	uint8_t  BufWriteTimeoutTyp;
+	uint8_t  BlockEraseTimeoutTyp;
+	uint8_t  ChipEraseTimeoutTyp;
+	uint8_t  WordWriteTimeoutMax;
+	uint8_t  BufWriteTimeoutMax;
+	uint8_t  BlockEraseTimeoutMax;
+	uint8_t  ChipEraseTimeoutMax;
+	uint8_t  DevSize;
+	uint16_t InterfaceDesc;
+	uint16_t MaxBufWriteSize;
+	uint8_t  NumEraseRegions;
+	uint32_t EraseRegionInfo[0]; /* Not host ordered */
+} __attribute__((packed));
+
+/* Extended Query Structure for both PRI and ALT */
+
+struct cfi_extquery {
+	uint8_t  pri[3];
+	uint8_t  MajorVersion;
+	uint8_t  MinorVersion;
+} __attribute__((packed));
+
+/* Vendor-Specific PRI for Intel/Sharp Extended Command Set (0x0001) */
+
+struct cfi_pri_intelext {
+	uint8_t  pri[3];
+	uint8_t  MajorVersion;
+	uint8_t  MinorVersion;
+	uint32_t FeatureSupport; /* if bit 31 is set then an additional uint32_t feature
+				    block follows - FIXME - not currently supported */
+	uint8_t  SuspendCmdSupport;
+	uint16_t BlkStatusRegMask;
+	uint8_t  VccOptimal;
+	uint8_t  VppOptimal;
+	uint8_t  NumProtectionFields;
+	uint16_t ProtRegAddr;
+	uint8_t  FactProtRegSize;
+	uint8_t  UserProtRegSize;
+	uint8_t  extra[0];
+} __attribute__((packed));
+
+struct cfi_intelext_blockinfo {
+	uint16_t NumIdentBlocks;
+	uint16_t BlockSize;
+	uint16_t MinBlockEraseCycles;
+	uint8_t  BitsPerCell;
+	uint8_t  BlockCap;
+} __attribute__((packed));
+
+struct cfi_intelext_regioninfo {
+	uint16_t NumIdentPartitions;
+	uint8_t  NumOpAllowed;
+	uint8_t  NumOpAllowedSimProgMode;
+	uint8_t  NumOpAllowedSimEraMode;
+	uint8_t  NumBlockTypes;
+	struct cfi_intelext_blockinfo BlockTypes[1];
+} __attribute__((packed));
+
+/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */
+
+struct cfi_pri_amdstd {
+	uint8_t  pri[3];
+	uint8_t  MajorVersion;
+	uint8_t  MinorVersion;
+	uint8_t  SiliconRevision; /* bits 1-0: Address Sensitive Unlock */
+	uint8_t  EraseSuspend;
+	uint8_t  BlkProt;
+	uint8_t  TmpBlkUnprotect;
+	uint8_t  BlkProtUnprot;
+	uint8_t  SimultaneousOps;
+	uint8_t  BurstMode;
+	uint8_t  PageMode;
+	uint8_t  VppMin;
+	uint8_t  VppMax;
+	uint8_t  TopBottom;
+} __attribute__((packed));
+
+struct cfi_pri_query {
+	uint8_t  NumFields;
+	uint32_t ProtField[1]; /* Not host ordered */
+} __attribute__((packed));
+
+struct cfi_bri_query {
+	uint8_t  PageModeReadCap;
+	uint8_t  NumFields;
+	uint32_t ConfField[1]; /* Not host ordered */
+} __attribute__((packed));
+
+#define P_ID_NONE               0x0000
+#define P_ID_INTEL_EXT          0x0001
+#define P_ID_AMD_STD            0x0002
+#define P_ID_INTEL_STD          0x0003
+#define P_ID_AMD_EXT            0x0004
+#define P_ID_WINBOND            0x0006
+#define P_ID_ST_ADV             0x0020
+#define P_ID_MITSUBISHI_STD     0x0100
+#define P_ID_MITSUBISHI_EXT     0x0101
+#define P_ID_SST_PAGE           0x0102
+#define P_ID_INTEL_PERFORMANCE  0x0200
+#define P_ID_INTEL_DATA         0x0210
+#define P_ID_RESERVED           0xffff
+
+
+#define CFI_MODE_CFI	1
+#define CFI_MODE_JEDEC	0
+
+struct cfi_private {
+	uint16_t cmdset;
+	void *cmdset_priv;
+	int interleave;
+	int device_type;
+	int cfi_mode;		/* Are we a JEDEC device pretending to be CFI? */
+	int addr_unlock1;
+	int addr_unlock2;
+	struct mtd_info *(*cmdset_setup)(struct map_info *);
+	struct cfi_ident *cfiq; /* For now only one. We insist that all devs
+				  must be of the same type. */
+	int mfr, id;
+	int numchips;
+	unsigned long chipshift; /* Because they're of the same type */
+	const char *im_name;	 /* inter_module name for cmdset_setup */
+	struct flchip chips[0];  /* per-chip data structure for each chip */
+};
+
+/*
+ * Returns the command address according to the given geometry.
+ */
+static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type)
+{
+	return (cmd_ofs * type) * interleave;
+}
+
+/*
+ * Transforms the CFI command for the given geometry (bus width & interleave).
+ * It looks too long to be inline, but in the common case it should almost all
+ * get optimised away. 
+ */
+static inline map_word cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi)
+{
+	map_word val = { {0} };
+	int wordwidth, words_per_bus, chip_mode, chips_per_word;
+	unsigned long onecmd;
+	int i;
+
+	/* We do it this way to give the compiler a fighting chance 
+	   of optimising away all the crap for 'bankwidth' larger than
+	   an unsigned long, in the common case where that support is
+	   disabled */
+	if (map_bankwidth_is_large(map)) {
+		wordwidth = sizeof(unsigned long);
+		words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
+	} else {
+		wordwidth = map_bankwidth(map);
+		words_per_bus = 1;
+	}
+	
+	chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
+	chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
+
+	/* First, determine what the bit-pattern should be for a single
+	   device, according to chip mode and endianness... */
+	switch (chip_mode) {
+	default: BUG();
+	case 1:
+		onecmd = cmd;
+		break;
+	case 2:
+		onecmd = cpu_to_cfi16(cmd);
+		break;
+	case 4:
+		onecmd = cpu_to_cfi32(cmd);
+		break;
+	}
+
+	/* Now replicate it across the size of an unsigned long, or 
+	   just to the bus width as appropriate */
+	switch (chips_per_word) {
+	default: BUG();
+#if BITS_PER_LONG >= 64
+	case 8:
+		onecmd |= (onecmd << (chip_mode * 32));
+#endif
+	case 4:
+		onecmd |= (onecmd << (chip_mode * 16));
+	case 2:
+		onecmd |= (onecmd << (chip_mode * 8));
+	case 1:
+		;
+	}
+
+	/* And finally, for the multi-word case, replicate it 
+	   in all words in the structure */
+	for (i=0; i < words_per_bus; i++) {
+		val.x[i] = onecmd;
+	}
+
+	return val;
+}
+#define CMD(x)  cfi_build_cmd((x), map, cfi)
+
+/*
+ * Sends a CFI command to a bank of flash for the given geometry.
+ *
+ * Returns the offset in flash where the command was written.
+ * If prev_val is non-null, it will be set to the value at the command address,
+ * before the command was written.
+ */
+static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base,
+				struct map_info *map, struct cfi_private *cfi,
+				int type, map_word *prev_val)
+{
+	map_word val;
+	uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type);
+
+	val = cfi_build_cmd(cmd, map, cfi);
+
+	if (prev_val)
+		*prev_val = map_read(map, addr);
+
+	map_write(map, val, addr);
+
+	return addr - base;
+}
+
+static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr)
+{
+	map_word val = map_read(map, addr);
+
+	if (map_bankwidth_is_1(map)) {
+		return val.x[0];
+	} else if (map_bankwidth_is_2(map)) {
+		return cfi16_to_cpu(val.x[0]);
+	} else {
+		/* No point in a 64-bit byteswap since that would just be
+		   swapping the responses from different chips, and we are
+		   only interested in one chip (a representative sample) */
+		return cfi32_to_cpu(val.x[0]);
+	}
+}
+
+static inline void cfi_udelay(int us)
+{
+	if (us >= 1000) {
+		msleep((us+999)/1000);
+	} else {
+		udelay(us);
+		cond_resched();
+	}
+}
+
+static inline void cfi_spin_lock(spinlock_t *mutex)
+{
+	spin_lock_bh(mutex);
+}
+
+static inline void cfi_spin_unlock(spinlock_t *mutex)
+{
+	spin_unlock_bh(mutex);
+}
+
+struct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t size,
+			     const char* name);
+struct cfi_fixup {
+	uint16_t mfr;
+	uint16_t id;
+	void (*fixup)(struct mtd_info *mtd, void* param);
+	void* param;
+};
+
+#define CFI_MFR_ANY 0xffff
+#define CFI_ID_ANY  0xffff
+
+#define CFI_MFR_AMD 0x0001
+#define CFI_MFR_ST  0x0020 	/* STMicroelectronics */
+
+void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);
+
+typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
+			      unsigned long adr, int len, void *thunk);
+
+int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
+	loff_t ofs, size_t len, void *thunk);
+
+
+#endif /* __MTD_CFI_H__ */
diff --git a/include/linux/mtd/cfi_endian.h b/include/linux/mtd/cfi_endian.h
new file mode 100644
index 0000000..25724f7
--- /dev/null
+++ b/include/linux/mtd/cfi_endian.h
@@ -0,0 +1,57 @@
+/*
+ * $Id: cfi_endian.h,v 1.11 2002/01/30 23:20:48 awozniak Exp $
+ *
+ */
+
+#include <asm/byteorder.h>
+
+#ifndef CONFIG_MTD_CFI_ADV_OPTIONS
+
+#define CFI_HOST_ENDIAN
+
+#else
+
+#ifdef CONFIG_MTD_CFI_NOSWAP
+#define CFI_HOST_ENDIAN
+#endif
+
+#ifdef CONFIG_MTD_CFI_LE_BYTE_SWAP
+#define CFI_LITTLE_ENDIAN
+#endif
+
+#ifdef CONFIG_MTD_CFI_BE_BYTE_SWAP
+#define CFI_BIG_ENDIAN
+#endif
+
+#endif
+
+#if defined(CFI_LITTLE_ENDIAN)
+#define cpu_to_cfi8(x) (x)
+#define cfi8_to_cpu(x) (x)
+#define cpu_to_cfi16(x) cpu_to_le16(x)
+#define cpu_to_cfi32(x) cpu_to_le32(x)
+#define cpu_to_cfi64(x) cpu_to_le64(x)
+#define cfi16_to_cpu(x) le16_to_cpu(x)
+#define cfi32_to_cpu(x) le32_to_cpu(x)
+#define cfi64_to_cpu(x) le64_to_cpu(x)
+#elif defined (CFI_BIG_ENDIAN)
+#define cpu_to_cfi8(x) (x)
+#define cfi8_to_cpu(x) (x)
+#define cpu_to_cfi16(x) cpu_to_be16(x)
+#define cpu_to_cfi32(x) cpu_to_be32(x)
+#define cpu_to_cfi64(x) cpu_to_be64(x)
+#define cfi16_to_cpu(x) be16_to_cpu(x)
+#define cfi32_to_cpu(x) be32_to_cpu(x)
+#define cfi64_to_cpu(x) be64_to_cpu(x)
+#elif defined (CFI_HOST_ENDIAN)
+#define cpu_to_cfi8(x) (x)
+#define cfi8_to_cpu(x) (x)
+#define cpu_to_cfi16(x) (x)
+#define cpu_to_cfi32(x) (x)
+#define cpu_to_cfi64(x) (x)
+#define cfi16_to_cpu(x) (x)
+#define cfi32_to_cpu(x) (x)
+#define cfi64_to_cpu(x) (x)
+#else
+#error No CFI endianness defined
+#endif
diff --git a/include/linux/mtd/compatmac.h b/include/linux/mtd/compatmac.h
new file mode 100644
index 0000000..7d1300d
--- /dev/null
+++ b/include/linux/mtd/compatmac.h
@@ -0,0 +1,10 @@
+
+#ifndef __LINUX_MTD_COMPATMAC_H__
+#define __LINUX_MTD_COMPATMAC_H__
+
+/* Nothing to see here. We write 2.5-compatible code and this
+   file makes it all OK in older kernels, but it's empty in _current_
+   kernels. Include guard just to make GCC ignore it in future inclusions
+   anyway... */
+
+#endif /* __LINUX_MTD_COMPATMAC_H__ */
diff --git a/include/linux/mtd/concat.h b/include/linux/mtd/concat.h
new file mode 100644
index 0000000..ed8dc67
--- /dev/null
+++ b/include/linux/mtd/concat.h
@@ -0,0 +1,23 @@
+/*
+ * MTD device concatenation layer definitions
+ *
+ * (C) 2002 Robert Kaiser <rkaiser@sysgo.de>
+ *
+ * This code is GPL
+ *
+ * $Id: concat.h,v 1.1 2002/03/08 16:34:36 rkaiser Exp $
+ */
+
+#ifndef MTD_CONCAT_H
+#define MTD_CONCAT_H
+
+
+struct mtd_info *mtd_concat_create(
+    struct mtd_info *subdev[],  /* subdevices to concatenate */
+    int num_devs,               /* number of subdevices      */
+    char *name);                /* name for the new device   */
+
+void mtd_concat_destroy(struct mtd_info *mtd);
+
+#endif
+
diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h
new file mode 100644
index 0000000..953e64f
--- /dev/null
+++ b/include/linux/mtd/doc2000.h
@@ -0,0 +1,195 @@
+/* 
+ * Linux driver for Disk-On-Chip devices
+ *
+ * Copyright (C) 1999 Machine Vision Holdings, Inc.   
+ * Copyright (C) 2001-2003 David Woodhouse <dwmw2@infradead.org>
+ * Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com>
+ * Copyright (C) 2002-2003 SnapGear Inc
+ *
+ * $Id: doc2000.h,v 1.24 2005/01/05 12:40:38 dwmw2 Exp $ 
+ *
+ * Released under GPL
+ */
+
+#ifndef __MTD_DOC2000_H__
+#define __MTD_DOC2000_H__
+
+#include <linux/mtd/mtd.h>
+#include <asm/semaphore.h>
+
+#define DoC_Sig1 0
+#define DoC_Sig2 1
+
+#define DoC_ChipID		0x1000
+#define DoC_DOCStatus		0x1001
+#define DoC_DOCControl		0x1002
+#define DoC_FloorSelect		0x1003
+#define DoC_CDSNControl		0x1004
+#define DoC_CDSNDeviceSelect 	0x1005
+#define DoC_ECCConf 		0x1006
+#define DoC_2k_ECCStatus	0x1007
+
+#define DoC_CDSNSlowIO		0x100d
+#define DoC_ECCSyndrome0	0x1010
+#define DoC_ECCSyndrome1	0x1011
+#define DoC_ECCSyndrome2	0x1012
+#define DoC_ECCSyndrome3	0x1013
+#define DoC_ECCSyndrome4	0x1014
+#define DoC_ECCSyndrome5	0x1015
+#define DoC_AliasResolution 	0x101b
+#define DoC_ConfigInput		0x101c
+#define DoC_ReadPipeInit 	0x101d
+#define DoC_WritePipeTerm 	0x101e
+#define DoC_LastDataRead 	0x101f
+#define DoC_NOP 		0x1020
+
+#define DoC_Mil_CDSN_IO 	0x0800
+#define DoC_2k_CDSN_IO 		0x1800
+
+#define DoC_Mplus_NOP			0x1002
+#define DoC_Mplus_AliasResolution	0x1004
+#define DoC_Mplus_DOCControl		0x1006
+#define DoC_Mplus_AccessStatus		0x1008
+#define DoC_Mplus_DeviceSelect		0x1008
+#define DoC_Mplus_Configuration		0x100a
+#define DoC_Mplus_OutputControl		0x100c
+#define DoC_Mplus_FlashControl		0x1020
+#define DoC_Mplus_FlashSelect 		0x1022
+#define DoC_Mplus_FlashCmd		0x1024
+#define DoC_Mplus_FlashAddress		0x1026
+#define DoC_Mplus_FlashData0		0x1028
+#define DoC_Mplus_FlashData1		0x1029
+#define DoC_Mplus_ReadPipeInit		0x102a
+#define DoC_Mplus_LastDataRead		0x102c
+#define DoC_Mplus_LastDataRead1		0x102d
+#define DoC_Mplus_WritePipeTerm 	0x102e
+#define DoC_Mplus_ECCSyndrome0		0x1040
+#define DoC_Mplus_ECCSyndrome1		0x1041
+#define DoC_Mplus_ECCSyndrome2		0x1042
+#define DoC_Mplus_ECCSyndrome3		0x1043
+#define DoC_Mplus_ECCSyndrome4		0x1044
+#define DoC_Mplus_ECCSyndrome5		0x1045
+#define DoC_Mplus_ECCConf 		0x1046
+#define DoC_Mplus_Toggle		0x1046
+#define DoC_Mplus_DownloadStatus	0x1074
+#define DoC_Mplus_CtrlConfirm		0x1076
+#define DoC_Mplus_Power			0x1fff
+
+/* How to access the device? 
+ * On ARM, it'll be mmap'd directly with 32-bit wide accesses. 
+ * On PPC, it's mmap'd and 16-bit wide.
+ * Others use readb/writeb 
+ */
+#if defined(__arm__)
+#define ReadDOC_(adr, reg)      ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2))))
+#define WriteDOC_(d, adr, reg)  do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0)
+#define DOC_IOREMAP_LEN 0x8000
+#elif defined(__ppc__)
+#define ReadDOC_(adr, reg)      ((unsigned char)(*(volatile __u16 *)(((unsigned long)adr)+((reg)<<1))))
+#define WriteDOC_(d, adr, reg)  do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0)
+#define DOC_IOREMAP_LEN 0x4000
+#else
+#define ReadDOC_(adr, reg)      readb((void __iomem *)(adr) + (reg))
+#define WriteDOC_(d, adr, reg)  writeb(d, (void __iomem *)(adr) + (reg))
+#define DOC_IOREMAP_LEN 0x2000
+
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+#define USE_MEMCPY
+#endif
+
+/* These are provided to directly use the DoC_xxx defines */
+#define ReadDOC(adr, reg)      ReadDOC_(adr,DoC_##reg)
+#define WriteDOC(d, adr, reg)  WriteDOC_(d,adr,DoC_##reg)
+
+#define DOC_MODE_RESET 		0
+#define DOC_MODE_NORMAL 	1
+#define DOC_MODE_RESERVED1 	2
+#define DOC_MODE_RESERVED2 	3
+
+#define DOC_MODE_CLR_ERR 	0x80
+#define	DOC_MODE_RST_LAT	0x10
+#define	DOC_MODE_BDECT		0x08
+#define DOC_MODE_MDWREN 	0x04
+
+#define DOC_ChipID_Doc2k 	0x20
+#define DOC_ChipID_Doc2kTSOP 	0x21	/* internal number for MTD */
+#define DOC_ChipID_DocMil 	0x30
+#define DOC_ChipID_DocMilPlus32	0x40
+#define DOC_ChipID_DocMilPlus16	0x41
+
+#define CDSN_CTRL_FR_B 		0x80
+#define CDSN_CTRL_FR_B0		0x40
+#define CDSN_CTRL_FR_B1		0x80
+
+#define CDSN_CTRL_ECC_IO 	0x20
+#define CDSN_CTRL_FLASH_IO 	0x10
+#define CDSN_CTRL_WP 		0x08
+#define CDSN_CTRL_ALE 		0x04
+#define CDSN_CTRL_CLE 		0x02
+#define CDSN_CTRL_CE 		0x01
+
+#define DOC_ECC_RESET 		0
+#define DOC_ECC_ERROR 		0x80
+#define DOC_ECC_RW 		0x20
+#define DOC_ECC__EN 		0x08
+#define DOC_TOGGLE_BIT 		0x04
+#define DOC_ECC_RESV 		0x02
+#define DOC_ECC_IGNORE		0x01
+
+#define DOC_FLASH_CE		0x80
+#define DOC_FLASH_WP		0x40
+#define DOC_FLASH_BANK		0x02
+
+/* We have to also set the reserved bit 1 for enable */
+#define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV)
+#define DOC_ECC_DIS (DOC_ECC_RESV)
+
+struct Nand {
+	char floor, chip;
+	unsigned long curadr;
+	unsigned char curmode;
+	/* Also some erase/write/pipeline info when we get that far */
+};
+
+#define MAX_FLOORS 4
+#define MAX_CHIPS 4
+
+#define MAX_FLOORS_MIL 1
+#define MAX_CHIPS_MIL 1
+
+#define MAX_FLOORS_MPLUS 2
+#define MAX_CHIPS_MPLUS 1
+
+#define ADDR_COLUMN 1
+#define ADDR_PAGE 2
+#define ADDR_COLUMN_PAGE 3
+
+struct DiskOnChip {
+	unsigned long physadr;
+	void __iomem *virtadr;
+	unsigned long totlen;
+	unsigned char ChipID; /* Type of DiskOnChip */
+	int ioreg;
+	
+	unsigned long mfr; /* Flash IDs - only one type of flash per device */
+	unsigned long id;
+	int chipshift;
+	char page256;
+	char pageadrlen;
+	char interleave; /* Internal interleaving - Millennium Plus style */
+	unsigned long erasesize;
+	
+	int curfloor;
+	int curchip;
+	
+	int numchips;
+	struct Nand *chips;
+	struct mtd_info *nextdoc;
+	struct semaphore lock;
+};
+
+int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]);
+
+#endif /* __MTD_DOC2000_H__ */
diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h
new file mode 100644
index 0000000..c66ba81
--- /dev/null
+++ b/include/linux/mtd/flashchip.h
@@ -0,0 +1,89 @@
+
+/* 
+ * struct flchip definition
+ * 
+ * Contains information about the location and state of a given flash device 
+ *
+ * (C) 2000 Red Hat. GPLd.
+ *
+ * $Id: flashchip.h,v 1.15 2004/11/05 22:41:06 nico Exp $
+ *
+ */
+
+#ifndef __MTD_FLASHCHIP_H__
+#define __MTD_FLASHCHIP_H__
+
+/* For spinlocks. sched.h includes spinlock.h from whichever directory it
+ * happens to be in - so we don't have to care whether we're on 2.2, which
+ * has asm/spinlock.h, or 2.4, which has linux/spinlock.h 
+ */
+#include <linux/sched.h>
+
+typedef enum { 
+	FL_READY,
+	FL_STATUS,
+	FL_CFI_QUERY,
+	FL_JEDEC_QUERY,
+	FL_ERASING,
+	FL_ERASE_SUSPENDING,
+	FL_ERASE_SUSPENDED,
+	FL_WRITING,
+	FL_WRITING_TO_BUFFER,
+	FL_WRITE_SUSPENDING,
+	FL_WRITE_SUSPENDED,
+	FL_PM_SUSPENDED,
+	FL_SYNCING,
+	FL_UNLOADING,
+	FL_LOCKING,
+	FL_UNLOCKING,
+	FL_POINT,
+	FL_XIP_WHILE_ERASING,
+	FL_XIP_WHILE_WRITING,
+	FL_UNKNOWN
+} flstate_t;
+
+
+
+/* NOTE: confusingly, this can be used to refer to more than one chip at a time, 
+   if they're interleaved.  This can even refer to individual partitions on
+   the same physical chip when present. */
+
+struct flchip {
+	unsigned long start; /* Offset within the map */
+	//	unsigned long len;
+	/* We omit len for now, because when we group them together
+	   we insist that they're all of the same size, and the chip size
+	   is held in the next level up. If we get more versatile later,
+	   it'll make it a damn sight harder to find which chip we want from
+	   a given offset, and we'll want to add the per-chip length field
+	   back in.
+	*/
+	int ref_point_counter;
+	flstate_t state;
+	flstate_t oldstate;
+
+	int write_suspended:1;
+	int erase_suspended:1;
+	unsigned long in_progress_block_addr;
+
+	spinlock_t *mutex;
+	spinlock_t _spinlock; /* We do it like this because sometimes they'll be shared. */
+	wait_queue_head_t wq; /* Wait on here when we're waiting for the chip
+			     to be ready */
+	int word_write_time;
+	int buffer_write_time;
+	int erase_time;
+
+	void *priv;
+};
+
+/* This is used to handle contention on write/erase operations
+   between partitions of the same physical chip. */
+struct flchip_shared {
+	spinlock_t lock;
+	struct flchip *writing;
+	struct flchip *erasing;
+};
+
+
+#endif /* __MTD_FLASHCHIP_H__ */
diff --git a/include/linux/mtd/ftl.h b/include/linux/mtd/ftl.h
new file mode 100644
index 0000000..3678459
--- /dev/null
+++ b/include/linux/mtd/ftl.h
@@ -0,0 +1,76 @@
+/*
+ * $Id: ftl.h,v 1.6 2003/01/24 13:20:04 dwmw2 Exp $
+ * 
+ * Derived from (and probably identical to):
+ * ftl.h 1.7 1999/10/25 20:23:17
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License. 
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above.  If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL.  If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#ifndef _LINUX_FTL_H
+#define _LINUX_FTL_H
+
+typedef struct erase_unit_header_t {
+    u_int8_t	LinkTargetTuple[5];
+    u_int8_t	DataOrgTuple[10];
+    u_int8_t	NumTransferUnits;
+    u_int32_t	EraseCount;
+    u_int16_t	LogicalEUN;
+    u_int8_t	BlockSize;
+    u_int8_t	EraseUnitSize;
+    u_int16_t	FirstPhysicalEUN;
+    u_int16_t	NumEraseUnits;
+    u_int32_t	FormattedSize;
+    u_int32_t	FirstVMAddress;
+    u_int16_t	NumVMPages;
+    u_int8_t	Flags;
+    u_int8_t	Code;
+    u_int32_t	SerialNumber;
+    u_int32_t	AltEUHOffset;
+    u_int32_t	BAMOffset;
+    u_int8_t	Reserved[12];
+    u_int8_t	EndTuple[2];
+} erase_unit_header_t;
+
+/* Flags in erase_unit_header_t */
+#define HIDDEN_AREA		0x01
+#define REVERSE_POLARITY	0x02
+#define DOUBLE_BAI		0x04
+
+/* Definitions for block allocation information */
+
+#define BLOCK_FREE(b)		((b) == 0xffffffff)
+#define BLOCK_DELETED(b)	(((b) == 0) || ((b) == 0xfffffffe))
+
+#define BLOCK_TYPE(b)		((b) & 0x7f)
+#define BLOCK_ADDRESS(b)	((b) & ~0x7f)
+#define BLOCK_NUMBER(b)		((b) >> 9)
+#define BLOCK_CONTROL		0x30
+#define BLOCK_DATA		0x40
+#define BLOCK_REPLACEMENT	0x60
+#define BLOCK_BAD		0x70
+
+#endif /* _LINUX_FTL_H */
diff --git a/include/linux/mtd/gen_probe.h b/include/linux/mtd/gen_probe.h
new file mode 100644
index 0000000..3d7bdec
--- /dev/null
+++ b/include/linux/mtd/gen_probe.h
@@ -0,0 +1,23 @@
+/*
+ * (C) 2001, 2001 Red Hat, Inc.
+ * GPL'd
+ * $Id: gen_probe.h,v 1.3 2004/10/20 22:10:33 dwmw2 Exp $
+ */
+
+#ifndef __LINUX_MTD_GEN_PROBE_H__
+#define __LINUX_MTD_GEN_PROBE_H__
+
+#include <linux/mtd/flashchip.h>
+#include <linux/mtd/map.h> 
+#include <linux/mtd/cfi.h>
+#include <linux/bitops.h>
+
+struct chip_probe {
+	char *name;
+	int (*probe_chip)(struct map_info *map, __u32 base,
+			  unsigned long *chip_map, struct cfi_private *cfi);
+};
+
+struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp);
+
+#endif /* __LINUX_MTD_GEN_PROBE_H__ */
diff --git a/include/linux/mtd/iflash.h b/include/linux/mtd/iflash.h
new file mode 100644
index 0000000..9aa5b4f
--- /dev/null
+++ b/include/linux/mtd/iflash.h
@@ -0,0 +1,98 @@
+/* $Id: iflash.h,v 1.2 2000/11/13 18:01:54 dwmw2 Exp $ */
+
+#ifndef __MTD_IFLASH_H__
+#define __MTD_IFLASH_H__
+
+/* Extended CIS registers for Series 2 and 2+ cards */
+/* The registers are all offsets from 0x4000 */
+#define CISREG_CSR		0x0100
+#define CISREG_WP		0x0104
+#define CISREG_RDYBSY		0x0140
+
+/* Extended CIS registers for Series 2 cards */
+#define CISREG_SLEEP		0x0118
+#define CISREG_RDY_MASK		0x0120
+#define CISREG_RDY_STATUS	0x0130
+
+/* Extended CIS registers for Series 2+ cards */
+#define CISREG_VCR		0x010c
+
+/* Card Status Register */
+#define CSR_SRESET		0x20	/* Soft reset */
+#define CSR_CMWP		0x10	/* Common memory write protect */
+#define CSR_PWRDOWN		0x08	/* Power down status */
+#define CSR_CISWP		0x04	/* Common memory CIS WP */
+#define CSR_WP			0x02	/* Mechanical write protect */
+#define CSR_READY		0x01	/* Ready/busy status */
+
+/* Write Protection Register */
+#define WP_BLKEN		0x04	/* Enable block locking */
+#define WP_CMWP			0x02	/* Common memory write protect */
+#define WP_CISWP		0x01	/* Common memory CIS WP */
+
+/* Voltage Control Register */
+#define VCR_VCC_LEVEL		0x80	/* 0 = 5V, 1 = 3.3V */
+#define VCR_VPP_VALID		0x02	/* Vpp Valid */
+#define VCR_VPP_GEN		0x01	/* Integrated Vpp generator */
+
+/* Ready/Busy Mode Register */
+#define RDYBSY_RACK		0x02	/* Ready acknowledge */
+#define RDYBSY_MODE		0x01	/* 1 = high performance */
+
+#define LOW(x) ((x) & 0xff)
+
+/* 28F008SA-Compatible Command Set */
+#define IF_READ_ARRAY		0xffff
+#define IF_INTEL_ID		0x9090
+#define IF_READ_CSR		0x7070
+#define IF_CLEAR_CSR		0x5050
+#define IF_WRITE		0x4040
+#define IF_BLOCK_ERASE		0x2020
+#define IF_ERASE_SUSPEND	0xb0b0
+#define IF_CONFIRM		0xd0d0
+
+/* 28F016SA Performance Enhancement Commands */
+#define IF_READ_PAGE		0x7575
+#define IF_PAGE_SWAP		0x7272
+#define IF_SINGLE_LOAD		0x7474
+#define IF_SEQ_LOAD		0xe0e0
+#define IF_PAGE_WRITE		0x0c0c
+#define IF_RDY_MODE		0x9696
+#define IF_RDY_LEVEL		0x0101
+#define IF_RDY_PULSE_WRITE	0x0202
+#define IF_RDY_PULSE_ERASE	0x0303
+#define IF_RDY_DISABLE		0x0404
+#define IF_LOCK_BLOCK		0x7777
+#define IF_UPLOAD_STATUS	0x9797
+#define IF_READ_ESR		0x7171
+#define IF_ERASE_UNLOCKED	0xa7a7
+#define IF_SLEEP		0xf0f0
+#define IF_ABORT		0x8080
+#define IF_UPLOAD_DEVINFO	0x9999
+
+/* Definitions for Compatible Status Register */
+#define CSR_WR_READY		0x8080	/* Write state machine status */
+#define CSR_ERA_SUSPEND		0x4040	/* Erase suspend status */
+#define CSR_ERA_ERR		0x2020	/* Erase status */
+#define CSR_WR_ERR		0x1010	/* Data write status */
+#define CSR_VPP_LOW		0x0808	/* Vpp status */
+
+/* Definitions for Global Status Register */
+#define GSR_WR_READY		0x8080	/* Write state machine status */
+#define GSR_OP_SUSPEND		0x4040	/* Operation suspend status */
+#define GSR_OP_ERR		0x2020	/* Device operation status */
+#define GSR_SLEEP		0x1010	/* Device sleep status */
+#define GSR_QUEUE_FULL		0x0808	/* Queue status */
+#define GSR_PAGE_AVAIL		0x0404	/* Page buffer available status */
+#define GSR_PAGE_READY		0x0202	/* Page buffer status */
+#define GSR_PAGE_SELECT		0x0101	/* Page buffer select status */
+
+/* Definitions for Block Status Register */
+#define BSR_READY		0x8080	/* Block status */
+#define BSR_UNLOCK		0x4040	/* Block lock status */
+#define BSR_FAILED		0x2020	/* Block operation status */
+#define BSR_ABORTED		0x1010	/* Operation abort status */
+#define BSR_QUEUE_FULL		0x0808	/* Queue status */
+#define BSR_VPP_LOW		0x0404	/* Vpp status */
+
+#endif /* __MTD_IFLASH_H__ */
diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h
new file mode 100644
index 0000000..b52c8cb
--- /dev/null
+++ b/include/linux/mtd/inftl.h
@@ -0,0 +1,57 @@
+/*
+ *	inftl.h -- defines to support the Inverse NAND Flash Translation Layer
+ *
+ *	(C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
+ *
+ *	$Id: inftl.h,v 1.6 2004/06/30 14:49:00 dbrown Exp $
+ */
+
+#ifndef __MTD_INFTL_H__
+#define __MTD_INFTL_H__
+
+#ifndef __KERNEL__
+#error This is a kernel header. Perhaps include nftl-user.h instead?
+#endif
+
+#include <linux/mtd/blktrans.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nftl.h>
+
+#include <mtd/inftl-user.h>
+
+#ifndef INFTL_MAJOR
+#define INFTL_MAJOR 94
+#endif
+#define INFTL_PARTN_BITS 4
+
+#ifdef __KERNEL__
+
+struct INFTLrecord {
+	struct mtd_blktrans_dev mbd;
+	__u16 MediaUnit;
+	__u32 EraseSize;
+	struct INFTLMediaHeader MediaHdr;
+	int usecount;
+	unsigned char heads;
+	unsigned char sectors;
+	unsigned short cylinders;
+	__u16 numvunits;
+	__u16 firstEUN;
+	__u16 lastEUN;
+	__u16 numfreeEUNs;
+	__u16 LastFreeEUN; 		/* To speed up finding a free EUN */
+	int head,sect,cyl;
+	__u16 *PUtable;	 		/* Physical Unit Table  */
+	__u16 *VUtable; 		/* Virtual Unit Table */
+        unsigned int nb_blocks;		/* number of physical blocks */
+        unsigned int nb_boot_blocks;	/* number of blocks used by the bios */
+        struct erase_info instr;
+        struct nand_oobinfo oobinfo;
+};
+
+int INFTL_mount(struct INFTLrecord *s);
+int INFTL_formatblock(struct INFTLrecord *s, int block);
+
+#endif /* __KERNEL__ */
+
+#endif /* __MTD_INFTL_H__ */
diff --git a/include/linux/mtd/jedec.h b/include/linux/mtd/jedec.h
new file mode 100644
index 0000000..2ba0f70
--- /dev/null
+++ b/include/linux/mtd/jedec.h
@@ -0,0 +1,66 @@
+
+/* 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.
+ *
+ * $Id: jedec.h,v 1.3 2003/05/21 11:51:01 dwmw2 Exp $
+ */
+
+#ifndef __LINUX_MTD_JEDEC_H__
+#define __LINUX_MTD_JEDEC_H__
+
+#include <linux/types.h>
+
+#define MAX_JEDEC_CHIPS 16
+
+// Listing of all supported chips and their information
+struct JEDECTable
+{
+   __u16 jedec;
+   char *name;
+   unsigned long size;
+   unsigned long sectorsize;
+   __u32 capabilities;
+};
+
+// JEDEC being 0 is the end of the chip array
+struct jedec_flash_chip
+{
+   __u16 jedec;
+   unsigned long size;
+   unsigned long sectorsize;
+   
+   // *(__u8*)(base + (adder << addrshift)) = data << datashift
+   // Address size = size << addrshift
+   unsigned long base;           // Byte 0 of the flash, will be unaligned
+   unsigned int datashift;       // Useful for 32bit/16bit accesses
+   unsigned int addrshift;
+   unsigned long offset;         // linerized start. base==offset for unbanked, uninterleaved flash
+   
+   __u32 capabilities;
+   
+   // These markers are filled in by the flash_chip_scan function
+   unsigned long start;
+   unsigned long length;
+};
+
+struct jedec_private
+{
+   unsigned long size;         // Total size of all the devices
+   
+   /* Bank handling. If sum(bank_fill) == size then this is linear flash.
+      Otherwise the mapping has holes in it. bank_fill may be used to
+      find the holes, but in the common symetric case 
+      bank_fill[0] == bank_fill[*], thus addresses may be computed 
+      mathmatically. bank_fill must be powers of two */
+   unsigned is_banked;
+   unsigned long bank_fill[MAX_JEDEC_CHIPS];
+   
+   struct jedec_flash_chip chips[MAX_JEDEC_CHIPS];  
+};
+
+#endif
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
new file mode 100644
index 0000000..f0268b9
--- /dev/null
+++ b/include/linux/mtd/map.h
@@ -0,0 +1,412 @@
+
+/* Overhauled routines for dealing with different mmap regions of flash */
+/* $Id: map.h,v 1.46 2005/01/05 17:09:44 dwmw2 Exp $ */
+
+#ifndef __LINUX_MTD_MAP_H__
+#define __LINUX_MTD_MAP_H__
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/mtd/compatmac.h>
+#include <asm/unaligned.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/bug.h>
+
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
+#define map_bankwidth(map) 1
+#define map_bankwidth_is_1(map) (map_bankwidth(map) == 1)
+#define map_bankwidth_is_large(map) (0)
+#define map_words(map) (1)
+#define MAX_MAP_BANKWIDTH 1
+#else
+#define map_bankwidth_is_1(map) (0)
+#endif
+
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
+# ifdef map_bankwidth
+#  undef map_bankwidth
+#  define map_bankwidth(map) ((map)->bankwidth)
+# else
+#  define map_bankwidth(map) 2
+#  define map_bankwidth_is_large(map) (0)
+#  define map_words(map) (1)
+# endif
+#define map_bankwidth_is_2(map) (map_bankwidth(map) == 2)
+#undef MAX_MAP_BANKWIDTH
+#define MAX_MAP_BANKWIDTH 2
+#else
+#define map_bankwidth_is_2(map) (0)
+#endif
+
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
+# ifdef map_bankwidth
+#  undef map_bankwidth
+#  define map_bankwidth(map) ((map)->bankwidth)
+# else
+#  define map_bankwidth(map) 4
+#  define map_bankwidth_is_large(map) (0)
+#  define map_words(map) (1)
+# endif
+#define map_bankwidth_is_4(map) (map_bankwidth(map) == 4)
+#undef MAX_MAP_BANKWIDTH
+#define MAX_MAP_BANKWIDTH 4
+#else
+#define map_bankwidth_is_4(map) (0)
+#endif
+
+/* ensure we never evaluate anything shorted than an unsigned long
+ * to zero, and ensure we'll never miss the end of an comparison (bjd) */
+
+#define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1))/ sizeof(unsigned long))
+
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
+# ifdef map_bankwidth
+#  undef map_bankwidth
+#  define map_bankwidth(map) ((map)->bankwidth)
+#  if BITS_PER_LONG < 64
+#   undef map_bankwidth_is_large
+#   define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
+#   undef map_words
+#   define map_words(map) map_calc_words(map)
+#  endif
+# else
+#  define map_bankwidth(map) 8
+#  define map_bankwidth_is_large(map) (BITS_PER_LONG < 64)
+#  define map_words(map) map_calc_words(map)
+# endif
+#define map_bankwidth_is_8(map) (map_bankwidth(map) == 8)
+#undef MAX_MAP_BANKWIDTH
+#define MAX_MAP_BANKWIDTH 8
+#else
+#define map_bankwidth_is_8(map) (0)
+#endif
+
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
+# ifdef map_bankwidth
+#  undef map_bankwidth
+#  define map_bankwidth(map) ((map)->bankwidth)
+#  undef map_bankwidth_is_large
+#  define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
+#  undef map_words
+#  define map_words(map) map_calc_words(map)
+# else
+#  define map_bankwidth(map) 16
+#  define map_bankwidth_is_large(map) (1)
+#  define map_words(map) map_calc_words(map)
+# endif
+#define map_bankwidth_is_16(map) (map_bankwidth(map) == 16)
+#undef MAX_MAP_BANKWIDTH
+#define MAX_MAP_BANKWIDTH 16
+#else
+#define map_bankwidth_is_16(map) (0)
+#endif
+
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
+# ifdef map_bankwidth
+#  undef map_bankwidth
+#  define map_bankwidth(map) ((map)->bankwidth)
+#  undef map_bankwidth_is_large
+#  define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
+#  undef map_words
+#  define map_words(map) map_calc_words(map)
+# else
+#  define map_bankwidth(map) 32
+#  define map_bankwidth_is_large(map) (1)
+#  define map_words(map) map_calc_words(map)
+# endif
+#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
+#undef MAX_MAP_BANKWIDTH
+#define MAX_MAP_BANKWIDTH 32
+#else
+#define map_bankwidth_is_32(map) (0)
+#endif
+
+#ifndef map_bankwidth
+#error "No bus width supported. What's the point?"
+#endif
+
+static inline int map_bankwidth_supported(int w)
+{
+	switch (w) {
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
+	case 1:
+#endif
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
+	case 2:
+#endif
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
+	case 4:
+#endif
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
+	case 8:
+#endif
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
+	case 16:
+#endif
+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
+	case 32:
+#endif
+		return 1;
+
+	default:
+		return 0;
+	}
+}
+
+#define MAX_MAP_LONGS ( ((MAX_MAP_BANKWIDTH*8) + BITS_PER_LONG - 1) / BITS_PER_LONG )
+
+typedef union {
+	unsigned long x[MAX_MAP_LONGS];
+} map_word;
+
+/* The map stuff is very simple. You fill in your struct map_info with
+   a handful of routines for accessing the device, making sure they handle
+   paging etc. correctly if your device needs it. Then you pass it off
+   to a chip probe routine -- either JEDEC or CFI probe or both -- via
+   do_map_probe(). If a chip is recognised, the probe code will invoke the
+   appropriate chip driver (if present) and return a struct mtd_info.
+   At which point, you fill in the mtd->module with your own module 
+   address, and register it with the MTD core code. Or you could partition
+   it and register the partitions instead, or keep it for your own private
+   use; whatever.
+   
+   The mtd->priv field will point to the struct map_info, and any further
+   private data required by the chip driver is linked from the 
+   mtd->priv->fldrv_priv field. This allows the map driver to get at 
+   the destructor function map->fldrv_destroy() when it's tired
+   of living.
+*/
+
+struct map_info {
+	char *name;
+	unsigned long size;
+	unsigned long phys;
+#define NO_XIP (-1UL)
+
+	void __iomem *virt;
+	void *cached;
+
+	int bankwidth; /* in octets. This isn't necessarily the width
+		       of actual bus cycles -- it's the repeat interval
+		      in bytes, before you are talking to the first chip again.
+		      */
+
+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
+	map_word (*read)(struct map_info *, unsigned long);
+	void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
+
+	void (*write)(struct map_info *, const map_word, unsigned long);
+	void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
+
+	/* We can perhaps put in 'point' and 'unpoint' methods, if we really
+	   want to enable XIP for non-linear mappings. Not yet though. */
+#endif
+	/* It's possible for the map driver to use cached memory in its
+	   copy_from implementation (and _only_ with copy_from).  However,
+	   when the chip driver knows some flash area has changed contents,
+	   it will signal it to the map driver through this routine to let
+	   the map driver invalidate the corresponding cache as needed.
+	   If there is no cache to care about this can be set to NULL. */
+	void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
+
+	/* set_vpp() must handle being reentered -- enable, enable, disable 
+	   must leave it enabled. */
+	void (*set_vpp)(struct map_info *, int);
+
+	unsigned long map_priv_1;
+	unsigned long map_priv_2;
+	void *fldrv_priv;
+	struct mtd_chip_driver *fldrv;
+};
+
+struct mtd_chip_driver {
+	struct mtd_info *(*probe)(struct map_info *map);
+	void (*destroy)(struct mtd_info *);
+	struct module *module;
+	char *name;
+	struct list_head list;
+};
+
+void register_mtd_chip_driver(struct mtd_chip_driver *);
+void unregister_mtd_chip_driver(struct mtd_chip_driver *);
+
+struct mtd_info *do_map_probe(const char *name, struct map_info *map);
+void map_destroy(struct mtd_info *mtd);
+
+#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0)
+#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0)
+
+#define INVALIDATE_CACHED_RANGE(map, from, size) \
+	do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0)
+
+
+static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2)
+{
+	int i;
+	for (i=0; i<map_words(map); i++) {
+		if (val1.x[i] != val2.x[i])
+			return 0;
+	}
+	return 1;
+}
+
+static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2)
+{
+	map_word r;
+	int i;
+
+	for (i=0; i<map_words(map); i++) {
+		r.x[i] = val1.x[i] & val2.x[i];
+	}
+	return r;
+}
+
+static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2)
+{
+	map_word r;
+	int i;
+
+	for (i=0; i<map_words(map); i++) {
+		r.x[i] = val1.x[i] | val2.x[i];
+	}
+	return r;
+}
+#define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b))
+
+static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
+{
+	int i;
+
+	for (i=0; i<map_words(map); i++) {
+		if (val1.x[i] & val2.x[i])
+			return 1;
+	}
+	return 0;
+}
+
+static inline map_word map_word_load(struct map_info *map, const void *ptr)
+{
+	map_word r;
+
+	if (map_bankwidth_is_1(map))
+		r.x[0] = *(unsigned char *)ptr;
+	else if (map_bankwidth_is_2(map))
+		r.x[0] = get_unaligned((uint16_t *)ptr);
+	else if (map_bankwidth_is_4(map))
+		r.x[0] = get_unaligned((uint32_t *)ptr);
+#if BITS_PER_LONG >= 64
+	else if (map_bankwidth_is_8(map))
+		r.x[0] = get_unaligned((uint64_t *)ptr);
+#endif
+	else if (map_bankwidth_is_large(map))
+		memcpy(r.x, ptr, map->bankwidth);
+
+	return r;
+}
+
+static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len)
+{
+	int i;
+
+	if (map_bankwidth_is_large(map)) {
+		char *dest = (char *)&orig;
+		memcpy(dest+start, buf, len);
+	} else {
+		for (i=start; i < start+len; i++) {
+			int bitpos;
+#ifdef __LITTLE_ENDIAN
+			bitpos = i*8;
+#else /* __BIG_ENDIAN */
+			bitpos = (map_bankwidth(map)-1-i)*8;
+#endif
+			orig.x[0] &= ~(0xff << bitpos);
+			orig.x[0] |= buf[i-start] << bitpos;
+		}
+	}
+	return orig;
+}
+
+static inline map_word map_word_ff(struct map_info *map)
+{
+	map_word r;
+	int i;
+
+	for (i=0; i<map_words(map); i++) {
+		r.x[i] = ~0UL;
+	}
+	return r;
+}
+static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
+{
+	map_word r;
+
+	if (map_bankwidth_is_1(map))
+		r.x[0] = __raw_readb(map->virt + ofs);
+	else if (map_bankwidth_is_2(map))
+		r.x[0] = __raw_readw(map->virt + ofs);
+	else if (map_bankwidth_is_4(map))
+		r.x[0] = __raw_readl(map->virt + ofs);
+#if BITS_PER_LONG >= 64
+	else if (map_bankwidth_is_8(map))
+		r.x[0] = __raw_readq(map->virt + ofs);
+#endif
+	else if (map_bankwidth_is_large(map))
+		memcpy_fromio(r.x, map->virt+ofs, map->bankwidth);
+
+	return r;
+}
+
+static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
+{
+	if (map_bankwidth_is_1(map))
+		__raw_writeb(datum.x[0], map->virt + ofs);
+	else if (map_bankwidth_is_2(map))
+		__raw_writew(datum.x[0], map->virt + ofs);
+	else if (map_bankwidth_is_4(map))
+		__raw_writel(datum.x[0], map->virt + ofs);
+#if BITS_PER_LONG >= 64
+	else if (map_bankwidth_is_8(map))
+		__raw_writeq(datum.x[0], map->virt + ofs);
+#endif
+	else if (map_bankwidth_is_large(map))
+		memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
+	mb();
+}
+
+static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
+{
+	if (map->cached)
+		memcpy(to, (char *)map->cached + from, len);
+	else
+		memcpy_fromio(to, map->virt + from, len);
+}
+
+static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
+{
+	memcpy_toio(map->virt + to, from, len);
+}
+
+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
+#define map_read(map, ofs) (map)->read(map, ofs)
+#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
+#define map_write(map, datum, ofs) (map)->write(map, datum, ofs)
+#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
+
+extern void simple_map_init(struct map_info *);
+#define map_is_linear(map) (map->phys != NO_XIP)
+
+#else
+#define map_read(map, ofs) inline_map_read(map, ofs)
+#define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len)
+#define map_write(map, datum, ofs) inline_map_write(map, datum, ofs)
+#define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len)
+
+
+#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
+#define map_is_linear(map) (1)
+
+#endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */
+
+#endif /* __LINUX_MTD_MAP_H__ */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
new file mode 100644
index 0000000..b3d1343
--- /dev/null
+++ b/include/linux/mtd/mtd.h
@@ -0,0 +1,226 @@
+/* 
+ * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
+ *
+ * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
+ *
+ * Released under GPL
+ */
+
+#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/config.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/uio.h>
+
+#include <linux/mtd/compatmac.h>
+#include <mtd/mtd-abi.h>
+
+#define MTD_CHAR_MAJOR 90
+#define MTD_BLOCK_MAJOR 31
+#define MAX_MTD_DEVICES 16
+
+#define MTD_ERASE_PENDING      	0x01
+#define MTD_ERASING		0x02
+#define MTD_ERASE_SUSPEND	0x04
+#define MTD_ERASE_DONE          0x08
+#define MTD_ERASE_FAILED        0x10
+
+/* If the erase fails, fail_addr might indicate exactly which block failed.  If
+   fail_addr = 0xffffffff, the failure was not at the device level or was not
+   specific to any particular block. */
+struct erase_info {
+	struct mtd_info *mtd;
+	u_int32_t addr;
+	u_int32_t len;
+	u_int32_t fail_addr;
+	u_long time;
+	u_long retries;
+	u_int dev;
+	u_int cell;
+	void (*callback) (struct erase_info *self);
+	u_long priv;
+	u_char state;
+	struct erase_info *next;
+};
+
+struct mtd_erase_region_info {
+	u_int32_t offset;			/* At which this region starts, from the beginning of the MTD */
+	u_int32_t erasesize;		/* For this region */
+	u_int32_t numblocks;		/* Number of blocks of erasesize in this region */
+};
+
+struct mtd_info {
+	u_char type;
+	u_int32_t flags;
+	u_int32_t size;	 // Total size of the MTD
+
+	/* "Major" erase size for the device. Naïve users may take this
+	 * to be the only erase size available, or may use the more detailed
+	 * information below if they desire
+	 */
+	u_int32_t erasesize;
+
+	u_int32_t oobblock;  // Size of OOB blocks (e.g. 512)
+	u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
+	u_int32_t oobavail;  // Number of bytes in OOB area available for fs 
+	u_int32_t ecctype;
+	u_int32_t eccsize;
+	
+
+	// Kernel-only stuff starts here.
+	char *name;
+	int index;
+
+	// oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO)
+	struct nand_oobinfo oobinfo;
+
+	/* Data for variable erase regions. If numeraseregions is zero,
+	 * it means that the whole device has erasesize as given above. 
+	 */
+	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 */
+	int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
+
+	/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
+	void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
+
+
+	int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+	int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+
+	int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
+	int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
+
+	int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+	int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+
+	/* 
+	 * Methods to access the protection register area, present in some 
+	 * flash devices. The user data is one time programmable but the
+	 * factory data is read only. 
+	 */
+	int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+
+	int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+
+	/* This function is not yet implemented */
+	int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+
+	/* kvec-based read/write methods. We need these especially for NAND flash,
+	   with its limited number of write cycles per erase.
+	   NB: The 'count' parameter is the number of _vectors_, each of 
+	   which contains an (ofs, len) tuple.
+	*/
+	int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
+	int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, 
+		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
+	int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
+	int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, 
+		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
+
+	/* Sync */
+	void (*sync) (struct mtd_info *mtd);
+
+	/* Chip-supported device locking */
+	int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
+	int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
+
+	/* Power Management functions */
+	int (*suspend) (struct mtd_info *mtd);
+	void (*resume) (struct mtd_info *mtd);
+
+	/* Bad block management functions */
+	int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
+	int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
+
+	void *priv;
+
+	struct module *owner;
+	int usecount;
+};
+
+
+	/* Kernel-side ioctl definitions */
+
+extern int add_mtd_device(struct mtd_info *mtd);
+extern int del_mtd_device (struct mtd_info *mtd);
+
+extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
+
+extern void put_mtd_device(struct mtd_info *mtd);
+
+
+struct mtd_notifier {
+	void (*add)(struct mtd_info *mtd);
+	void (*remove)(struct mtd_info *mtd);
+	struct list_head list;
+};
+
+
+extern void register_mtd_user (struct mtd_notifier *new);
+extern int unregister_mtd_user (struct mtd_notifier *old);
+
+int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
+		       unsigned long count, loff_t to, size_t *retlen);
+
+int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
+		      unsigned long count, loff_t from, size_t *retlen);
+
+#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
+#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
+#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
+#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
+#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
+#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args)
+#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args)
+#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args)
+#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
+#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
+#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
+#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd);  } while (0) 
+
+
+#ifdef CONFIG_MTD_PARTITIONS
+void mtd_erase_callback(struct erase_info *instr);
+#else
+static inline void mtd_erase_callback(struct erase_info *instr)
+{
+	if (instr->callback)
+		instr->callback(instr);
+}
+#endif
+
+/*
+ * Debugging macro and defines
+ */
+#define MTD_DEBUG_LEVEL0	(0)	/* Quiet   */
+#define MTD_DEBUG_LEVEL1	(1)	/* Audible */
+#define MTD_DEBUG_LEVEL2	(2)	/* Loud    */
+#define MTD_DEBUG_LEVEL3	(3)	/* Noisy   */
+
+#ifdef CONFIG_MTD_DEBUG
+#define DEBUG(n, args...)				\
+ 	do {						\
+		if (n <= CONFIG_MTD_DEBUG_VERBOSE)	\
+			printk(KERN_INFO args);		\
+	} while(0)
+#else /* CONFIG_MTD_DEBUG */
+#define DEBUG(n, args...) do { } while(0)
+
+#endif /* CONFIG_MTD_DEBUG */
+
+#endif /* __MTD_MTD_H__ */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
new file mode 100644
index 0000000..9a19c65
--- /dev/null
+++ b/include/linux/mtd/nand.h
@@ -0,0 +1,469 @@
+/*
+ *  linux/include/linux/mtd/nand.h
+ *
+ *  Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
+ *                     Steven J. Hill <sjhill@realitydiluted.com>
+ *		       Thomas Gleixner <tglx@linutronix.de>
+ *
+ * $Id: nand.h,v 1.68 2004/11/12 10:40:37 gleixner Exp $
+ *
+ * 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.
+ *
+ *  Info:
+ *   Contains standard defines and IDs for NAND flash devices
+ *
+ *  Changelog:
+ *   01-31-2000 DMW     Created
+ *   09-18-2000 SJH     Moved structure out of the Disk-On-Chip drivers
+ *			so it can be used by other NAND flash device
+ *			drivers. I also changed the copyright since none
+ *			of the original contents of this file are specific
+ *			to DoC devices. David can whack me with a baseball
+ *			bat later if I did something naughty.
+ *   10-11-2000 SJH     Added private NAND flash structure for driver
+ *   10-24-2000 SJH     Added prototype for 'nand_scan' function
+ *   10-29-2001 TG	changed nand_chip structure to support 
+ *			hardwarespecific function for accessing control lines
+ *   02-21-2002 TG	added support for different read/write adress and
+ *			ready/busy line access function
+ *   02-26-2002 TG	added chip_delay to nand_chip structure to optimize
+ *			command delay times for different chips
+ *   04-28-2002 TG	OOB config defines moved from nand.c to avoid duplicate
+ *			defines in jffs2/wbuf.c
+ *   08-07-2002 TG	forced bad block location to byte 5 of OOB, even if
+ *			CONFIG_MTD_NAND_ECC_JFFS2 is not set
+ *   08-10-2002 TG	extensions to nand_chip structure to support HW-ECC
+ *
+ *   08-29-2002 tglx 	nand_chip structure: data_poi for selecting 
+ *			internal / fs-driver buffer
+ *			support for 6byte/512byte hardware ECC
+ *			read_ecc, write_ecc extended for different oob-layout
+ *			oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
+ *			NAND_YAFFS_OOB
+ *  11-25-2002 tglx	Added Manufacturer code FUJITSU, NATIONAL
+ *			Split manufacturer and device ID structures 
+ *
+ *  02-08-2004 tglx 	added option field to nand structure for chip anomalities
+ *  05-25-2004 tglx 	added bad block table support, ST-MICRO manufacturer id
+ *			update of nand_chip structure description
+ */
+#ifndef __LINUX_MTD_NAND_H
+#define __LINUX_MTD_NAND_H
+
+#include <linux/config.h>
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/mtd/mtd.h>
+
+struct mtd_info;
+/* Scan and identify a NAND device */
+extern int nand_scan (struct mtd_info *mtd, int max_chips);
+/* Free resources held by the NAND device */
+extern void nand_release (struct mtd_info *mtd);
+
+/* Read raw data from the device without ECC */
+extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
+
+
+/* The maximum number of NAND chips in an array */
+#define NAND_MAX_CHIPS		8
+
+/* This constant declares the max. oobsize / page, which
+ * is supported now. If you add a chip with bigger oobsize/page
+ * adjust this accordingly.
+ */
+#define NAND_MAX_OOBSIZE	64
+
+/*
+ * Constants for hardware specific CLE/ALE/NCE function
+*/
+/* Select the chip by setting nCE to low */
+#define NAND_CTL_SETNCE 	1
+/* Deselect the chip by setting nCE to high */
+#define NAND_CTL_CLRNCE		2
+/* Select the command latch by setting CLE to high */
+#define NAND_CTL_SETCLE		3
+/* Deselect the command latch by setting CLE to low */
+#define NAND_CTL_CLRCLE		4
+/* Select the address latch by setting ALE to high */
+#define NAND_CTL_SETALE		5
+/* Deselect the address latch by setting ALE to low */
+#define NAND_CTL_CLRALE		6
+/* Set write protection by setting WP to high. Not used! */
+#define NAND_CTL_SETWP		7
+/* Clear write protection by setting WP to low. Not used! */
+#define NAND_CTL_CLRWP		8
+
+/*
+ * Standard NAND flash commands
+ */
+#define NAND_CMD_READ0		0
+#define NAND_CMD_READ1		1
+#define NAND_CMD_PAGEPROG	0x10
+#define NAND_CMD_READOOB	0x50
+#define NAND_CMD_ERASE1		0x60
+#define NAND_CMD_STATUS		0x70
+#define NAND_CMD_STATUS_MULTI	0x71
+#define NAND_CMD_SEQIN		0x80
+#define NAND_CMD_READID		0x90
+#define NAND_CMD_ERASE2		0xd0
+#define NAND_CMD_RESET		0xff
+
+/* Extended commands for large page devices */
+#define NAND_CMD_READSTART	0x30
+#define NAND_CMD_CACHEDPROG	0x15
+
+/* Status bits */
+#define NAND_STATUS_FAIL	0x01
+#define NAND_STATUS_FAIL_N1	0x02
+#define NAND_STATUS_TRUE_READY	0x20
+#define NAND_STATUS_READY	0x40
+#define NAND_STATUS_WP		0x80
+
+/* 
+ * Constants for ECC_MODES
+ */
+
+/* No ECC. Usage is not recommended ! */
+#define NAND_ECC_NONE		0
+/* Software ECC 3 byte ECC per 256 Byte data */
+#define NAND_ECC_SOFT		1
+/* Hardware ECC 3 byte ECC per 256 Byte data */
+#define NAND_ECC_HW3_256	2
+/* Hardware ECC 3 byte ECC per 512 Byte data */
+#define NAND_ECC_HW3_512	3
+/* Hardware ECC 3 byte ECC per 512 Byte data */
+#define NAND_ECC_HW6_512	4
+/* Hardware ECC 8 byte ECC per 512 Byte data */
+#define NAND_ECC_HW8_512	6
+/* Hardware ECC 12 byte ECC per 2048 Byte data */
+#define NAND_ECC_HW12_2048	7
+
+/*
+ * Constants for Hardware ECC
+*/
+/* Reset Hardware ECC for read */
+#define NAND_ECC_READ		0
+/* Reset Hardware ECC for write */
+#define NAND_ECC_WRITE		1
+/* Enable Hardware ECC before syndrom is read back from flash */
+#define NAND_ECC_READSYN	2
+
+/* Option constants for bizarre disfunctionality and real
+*  features
+*/
+/* Chip can not auto increment pages */
+#define NAND_NO_AUTOINCR	0x00000001
+/* Buswitdh is 16 bit */
+#define NAND_BUSWIDTH_16	0x00000002
+/* Device supports partial programming without padding */
+#define NAND_NO_PADDING		0x00000004
+/* Chip has cache program function */
+#define NAND_CACHEPRG		0x00000008
+/* Chip has copy back function */
+#define NAND_COPYBACK		0x00000010
+/* AND Chip which has 4 banks and a confusing page / block 
+ * assignment. See Renesas datasheet for further information */
+#define NAND_IS_AND		0x00000020
+/* Chip has a array of 4 pages which can be read without
+ * additional ready /busy waits */
+#define NAND_4PAGE_ARRAY	0x00000040 
+
+/* Options valid for Samsung large page devices */
+#define NAND_SAMSUNG_LP_OPTIONS \
+	(NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
+
+/* Macros to identify the above */
+#define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR))
+#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
+#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
+#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
+
+/* Mask to zero out the chip options, which come from the id table */
+#define NAND_CHIPOPTIONS_MSK	(0x0000ffff & ~NAND_NO_AUTOINCR)
+
+/* Non chip related options */
+/* Use a flash based bad block table. This option is passed to the
+ * default bad block table function. */
+#define NAND_USE_FLASH_BBT	0x00010000
+/* The hw ecc generator provides a syndrome instead a ecc value on read 
+ * This can only work if we have the ecc bytes directly behind the 
+ * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
+#define NAND_HWECC_SYNDROME	0x00020000
+
+
+/* Options set by nand scan */
+/* Nand scan has allocated oob_buf */
+#define NAND_OOBBUF_ALLOC	0x40000000
+/* Nand scan has allocated data_buf */
+#define NAND_DATABUF_ALLOC	0x80000000
+
+
+/*
+ * nand_state_t - chip states
+ * Enumeration for NAND flash chip state
+ */
+typedef enum {
+	FL_READY,
+	FL_READING,
+	FL_WRITING,
+	FL_ERASING,
+	FL_SYNCING,
+	FL_CACHEDPRG,
+} nand_state_t;
+
+/* Keep gcc happy */
+struct nand_chip;
+
+/**
+ * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices
+ * @lock:               protection lock  
+ * @active:		the mtd device which holds the controller currently
+ */
+struct nand_hw_control {
+	spinlock_t	 lock;
+	struct nand_chip *active;
+};
+
+/**
+ * struct nand_chip - NAND Private Flash Chip Data
+ * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the flash device 
+ * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the flash device 
+ * @read_byte:		[REPLACEABLE] read one byte from the chip
+ * @write_byte:		[REPLACEABLE] write one byte to the chip
+ * @read_word:		[REPLACEABLE] read one word from the chip
+ * @write_word:		[REPLACEABLE] write one word to the chip
+ * @write_buf:		[REPLACEABLE] write data from the buffer to the chip
+ * @read_buf:		[REPLACEABLE] read data from the chip into the buffer
+ * @verify_buf:		[REPLACEABLE] verify buffer contents against the chip data
+ * @select_chip:	[REPLACEABLE] select chip nr
+ * @block_bad:		[REPLACEABLE] check, if the block is bad
+ * @block_markbad:	[REPLACEABLE] mark the block bad
+ * @hwcontrol:		[BOARDSPECIFIC] hardwarespecific function for accesing control-lines
+ * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
+ *			If set to NULL no access to ready/busy is available and the ready/busy information
+ *			is read from the chip status register
+ * @cmdfunc:		[REPLACEABLE] hardwarespecific function for writing commands to the chip
+ * @waitfunc:		[REPLACEABLE] hardwarespecific function for wait on ready
+ * @calculate_ecc: 	[REPLACEABLE] function for ecc calculation or readback from ecc hardware
+ * @correct_data:	[REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
+ * @enable_hwecc:	[BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
+ *			be provided if a hardware ECC is available
+ * @erase_cmd:		[INTERN] erase command write function, selectable due to AND support
+ * @scan_bbt:		[REPLACEABLE] function to scan bad block table
+ * @eccmode:		[BOARDSPECIFIC] mode of ecc, see defines 
+ * @eccsize: 		[INTERN] databytes used per ecc-calculation
+ * @eccbytes: 		[INTERN] number of ecc bytes per ecc-calculation step
+ * @eccsteps:		[INTERN] number of ecc calculation steps per page
+ * @chip_delay:		[BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
+ * @chip_lock:		[INTERN] spinlock used to protect access to this structure and the chip
+ * @wq:			[INTERN] wait queue to sleep on if a NAND operation is in progress
+ * @state: 		[INTERN] the current state of the NAND device
+ * @page_shift:		[INTERN] number of address bits in a page (column address bits)
+ * @phys_erase_shift:	[INTERN] number of address bits in a physical eraseblock
+ * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
+ * @chip_shift:		[INTERN] number of address bits in one chip
+ * @data_buf:		[INTERN] internal buffer for one page + oob 
+ * @oob_buf:		[INTERN] oob buffer for one eraseblock
+ * @oobdirty:		[INTERN] indicates that oob_buf must be reinitialized
+ * @data_poi:		[INTERN] pointer to a data buffer
+ * @options:		[BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
+ *			special functionality. See the defines for further explanation
+ * @badblockpos:	[INTERN] position of the bad block marker in the oob area
+ * @numchips:		[INTERN] number of physical chips
+ * @chipsize:		[INTERN] the size of one chip for multichip arrays
+ * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
+ * @pagebuf:		[INTERN] holds the pagenumber which is currently in data_buf
+ * @autooob:		[REPLACEABLE] the default (auto)placement scheme
+ * @bbt:		[INTERN] bad block table pointer
+ * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup
+ * @bbt_md:		[REPLACEABLE] bad block table mirror descriptor
+ * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial bad block scan 
+ * @controller:		[OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
+ * @priv:		[OPTIONAL] pointer to private chip date
+ */
+ 
+struct nand_chip {
+	void  __iomem	*IO_ADDR_R;
+	void  __iomem 	*IO_ADDR_W;
+	
+	u_char		(*read_byte)(struct mtd_info *mtd);
+	void		(*write_byte)(struct mtd_info *mtd, u_char byte);
+	u16		(*read_word)(struct mtd_info *mtd);
+	void		(*write_word)(struct mtd_info *mtd, u16 word);
+	
+	void		(*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
+	void		(*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
+	int		(*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
+	void		(*select_chip)(struct mtd_info *mtd, int chip);
+	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
+	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
+	void 		(*hwcontrol)(struct mtd_info *mtd, int cmd);
+	int  		(*dev_ready)(struct mtd_info *mtd);
+	void 		(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
+	int 		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
+	int		(*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
+	int 		(*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
+	void		(*enable_hwecc)(struct mtd_info *mtd, int mode);
+	void		(*erase_cmd)(struct mtd_info *mtd, int page);
+	int		(*scan_bbt)(struct mtd_info *mtd);
+	int		eccmode;
+	int		eccsize;
+	int		eccbytes;
+	int		eccsteps;
+	int 		chip_delay;
+	spinlock_t	chip_lock;
+	wait_queue_head_t wq;
+	nand_state_t 	state;
+	int 		page_shift;
+	int		phys_erase_shift;
+	int		bbt_erase_shift;
+	int		chip_shift;
+	u_char 		*data_buf;
+	u_char		*oob_buf;
+	int		oobdirty;
+	u_char		*data_poi;
+	unsigned int	options;
+	int		badblockpos;
+	int		numchips;
+	unsigned long	chipsize;
+	int		pagemask;
+	int		pagebuf;
+	struct nand_oobinfo	*autooob;
+	uint8_t		*bbt;
+	struct nand_bbt_descr	*bbt_td;
+	struct nand_bbt_descr	*bbt_md;
+	struct nand_bbt_descr	*badblock_pattern;
+	struct nand_hw_control  *controller;
+	void		*priv;
+};
+
+/*
+ * NAND Flash Manufacturer ID Codes
+ */
+#define NAND_MFR_TOSHIBA	0x98
+#define NAND_MFR_SAMSUNG	0xec
+#define NAND_MFR_FUJITSU	0x04
+#define NAND_MFR_NATIONAL	0x8f
+#define NAND_MFR_RENESAS	0x07
+#define NAND_MFR_STMICRO	0x20
+
+/**
+ * struct nand_flash_dev - NAND Flash Device ID Structure
+ *
+ * @name:  	Identify the device type
+ * @id:   	device ID code
+ * @pagesize:  	Pagesize in bytes. Either 256 or 512 or 0
+ *		If the pagesize is 0, then the real pagesize 
+ *		and the eraseize are determined from the
+ *		extended id bytes in the chip
+ * @erasesize: 	Size of an erase block in the flash device.
+ * @chipsize:  	Total chipsize in Mega Bytes
+ * @options:	Bitfield to store chip relevant options
+ */
+struct nand_flash_dev {
+	char *name;
+	int id;
+	unsigned long pagesize;
+	unsigned long chipsize;
+	unsigned long erasesize;
+	unsigned long options;
+};
+
+/**
+ * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
+ * @name:	Manufacturer name
+ * @id: 	manufacturer ID code of device.
+*/
+struct nand_manufacturers {
+	int id;
+	char * name;
+};
+
+extern struct nand_flash_dev nand_flash_ids[];
+extern struct nand_manufacturers nand_manuf_ids[];
+
+/** 
+ * struct nand_bbt_descr - bad block table descriptor
+ * @options:	options for this descriptor
+ * @pages:	the page(s) where we find the bbt, used with option BBT_ABSPAGE
+ *		when bbt is searched, then we store the found bbts pages here.
+ *		Its an array and supports up to 8 chips now
+ * @offs:	offset of the pattern in the oob area of the page
+ * @veroffs:	offset of the bbt version counter in the oob are of the page
+ * @version:	version read from the bbt page during scan
+ * @len:	length of the pattern, if 0 no pattern check is performed
+ * @maxblocks:	maximum number of blocks to search for a bbt. This number of
+ *		blocks is reserved at the end of the device where the tables are 
+ *		written.
+ * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
+ *              bad) block in the stored bbt
+ * @pattern:	pattern to identify bad block table or factory marked good / 
+ *		bad blocks, can be NULL, if len = 0
+ *
+ * Descriptor for the bad block table marker and the descriptor for the 
+ * pattern which identifies good and bad blocks. The assumption is made
+ * that the pattern and the version count are always located in the oob area
+ * of the first block.
+ */
+struct nand_bbt_descr {
+	int	options;
+	int	pages[NAND_MAX_CHIPS];
+	int	offs;
+	int	veroffs;
+	uint8_t	version[NAND_MAX_CHIPS];
+	int	len;
+	int 	maxblocks;
+	int	reserved_block_code;
+	uint8_t	*pattern;
+};
+
+/* Options for the bad block table descriptors */
+
+/* The number of bits used per block in the bbt on the device */
+#define NAND_BBT_NRBITS_MSK	0x0000000F
+#define NAND_BBT_1BIT		0x00000001
+#define NAND_BBT_2BIT		0x00000002
+#define NAND_BBT_4BIT		0x00000004
+#define NAND_BBT_8BIT		0x00000008
+/* The bad block table is in the last good block of the device */
+#define	NAND_BBT_LASTBLOCK	0x00000010
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_ABSPAGE	0x00000020
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_SEARCH		0x00000040
+/* bbt is stored per chip on multichip devices */
+#define NAND_BBT_PERCHIP	0x00000080
+/* bbt has a version counter at offset veroffs */
+#define NAND_BBT_VERSION	0x00000100
+/* Create a bbt if none axists */
+#define NAND_BBT_CREATE		0x00000200
+/* Search good / bad pattern through all pages of a block */
+#define NAND_BBT_SCANALLPAGES	0x00000400
+/* Scan block empty during good / bad block scan */
+#define NAND_BBT_SCANEMPTY	0x00000800
+/* Write bbt if neccecary */
+#define NAND_BBT_WRITE		0x00001000
+/* Read and write back block contents when writing bbt */
+#define NAND_BBT_SAVECONTENT	0x00002000
+/* Search good / bad pattern on the first and the second page */
+#define NAND_BBT_SCAN2NDPAGE	0x00004000
+
+/* The maximum number of blocks to scan for a bbt */
+#define NAND_BBT_SCAN_MAXBLOCKS	4
+
+extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
+extern int nand_default_bbt (struct mtd_info *mtd);
+extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
+extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
+
+/*
+* Constants for oob configuration
+*/
+#define NAND_SMALL_BADBLOCK_POS		5
+#define NAND_LARGE_BADBLOCK_POS		0
+
+#endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h
new file mode 100644
index 0000000..12c5bc3
--- /dev/null
+++ b/include/linux/mtd/nand_ecc.h
@@ -0,0 +1,30 @@
+/*
+ *  drivers/mtd/nand_ecc.h
+ *
+ *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
+ *
+ * $Id: nand_ecc.h,v 1.4 2004/06/17 02:35:02 dbrown Exp $
+ *
+ * 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.
+ *
+ * This file is the header for the ECC algorithm.
+ */
+
+#ifndef __MTD_NAND_ECC_H__
+#define __MTD_NAND_ECC_H__
+
+struct mtd_info;
+
+/*
+ * Calculate 3 byte ECC code for 256 byte block
+ */
+int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
+
+/*
+ * Detect and correct a 1 bit error for 256 byte block
+ */
+int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
+
+#endif /* __MTD_NAND_ECC_H__ */
diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h
new file mode 100644
index 0000000..d35d2c2
--- /dev/null
+++ b/include/linux/mtd/nftl.h
@@ -0,0 +1,54 @@
+/*
+ * $Id: nftl.h,v 1.16 2004/06/30 14:49:00 dbrown Exp $
+ *
+ * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
+ */
+
+#ifndef __MTD_NFTL_H__
+#define __MTD_NFTL_H__
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/blktrans.h>
+
+#include <mtd/nftl-user.h>
+
+/* these info are used in ReplUnitTable */
+#define BLOCK_NIL          0xffff /* last block of a chain */
+#define BLOCK_FREE         0xfffe /* free block */
+#define BLOCK_NOTEXPLORED  0xfffd /* non explored block, only used during mounting */
+#define BLOCK_RESERVED     0xfffc /* bios block or bad block */
+
+struct NFTLrecord {
+	struct mtd_blktrans_dev mbd;
+	__u16 MediaUnit, SpareMediaUnit;
+	__u32 EraseSize;
+	struct NFTLMediaHeader MediaHdr;
+	int usecount;
+	unsigned char heads;
+	unsigned char sectors;
+	unsigned short cylinders;
+	__u16 numvunits;
+	__u16 lastEUN;                  /* should be suppressed */
+	__u16 numfreeEUNs;
+	__u16 LastFreeEUN; 		/* To speed up finding a free EUN */
+	int head,sect,cyl;
+	__u16 *EUNtable; 		/* [numvunits]: First EUN for each virtual unit  */
+	__u16 *ReplUnitTable; 		/* [numEUNs]: ReplUnitNumber for each */
+        unsigned int nb_blocks;		/* number of physical blocks */
+        unsigned int nb_boot_blocks;	/* number of blocks used by the bios */
+        struct erase_info instr;
+	struct nand_oobinfo oobinfo;
+};
+
+int NFTL_mount(struct NFTLrecord *s);
+int NFTL_formatblock(struct NFTLrecord *s, int block);
+
+#ifndef NFTL_MAJOR
+#define NFTL_MAJOR 93
+#endif
+
+#define MAX_NFTLS 16
+#define MAX_SECTORS_PER_UNIT 64
+#define NFTL_PARTN_BITS 4
+
+#endif /* __MTD_NFTL_H__ */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
new file mode 100644
index 0000000..50b2edf
--- /dev/null
+++ b/include/linux/mtd/partitions.h
@@ -0,0 +1,75 @@
+/*
+ * MTD partitioning layer definitions
+ *
+ * (C) 2000 Nicolas Pitre <nico@cam.org>
+ *
+ * This code is GPL
+ *
+ * $Id: partitions.h,v 1.16 2004/11/16 18:34:40 dwmw2 Exp $
+ */
+
+#ifndef MTD_PARTITIONS_H
+#define MTD_PARTITIONS_H
+
+#include <linux/types.h>
+
+
+/*
+ * Partition definition structure:
+ * 
+ * An array of struct partition is passed along with a MTD object to
+ * add_mtd_partitions() to create them.
+ *
+ * For each partition, these fields are available:
+ * name: string that will be used to label the partition's MTD device.
+ * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition 
+ * 	will extend to the end of the master MTD device.
+ * offset: absolute starting position within the master MTD device; if 
+ * 	defined as MTDPART_OFS_APPEND, the partition will start where the 
+ * 	previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
+ * mask_flags: contains flags that have to be masked (removed) from the 
+ * 	master MTD flag set for the corresponding MTD partition.
+ * 	For example, to force a read-only partition, simply adding 
+ * 	MTD_WRITEABLE to the mask_flags will do the trick.
+ *
+ * Note: writeable partitions require their size and offset be 
+ * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
+ */ 
+
+struct mtd_partition {
+	char *name;			/* identifier string */
+	u_int32_t size;			/* partition size */
+	u_int32_t offset;		/* offset within the master MTD space */
+	u_int32_t mask_flags;		/* master MTD flags to mask out for this partition */
+	struct nand_oobinfo *oobsel;	/* out of band layout for this partition (NAND only)*/
+	struct mtd_info **mtdp;		/* pointer to store the MTD object */
+};
+
+#define MTDPART_OFS_NXTBLK	(-2)
+#define MTDPART_OFS_APPEND	(-1)
+#define MTDPART_SIZ_FULL	(0)
+
+
+int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
+int del_mtd_partitions(struct mtd_info *);
+
+/*
+ * Functions dealing with the various ways of partitioning the space
+ */
+
+struct mtd_part_parser {
+	struct list_head list;
+	struct module *owner;
+	const char *name;
+	int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long);
+};
+
+extern int register_mtd_parser(struct mtd_part_parser *parser);
+extern int deregister_mtd_parser(struct mtd_part_parser *parser);
+extern int parse_mtd_partitions(struct mtd_info *master, const char **types, 
+				struct mtd_partition **pparts, unsigned long origin);
+
+#define put_partition_parser(p) do { module_put((p)->owner); } while(0)
+
+#endif
+
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
new file mode 100644
index 0000000..05aa4970
--- /dev/null
+++ b/include/linux/mtd/physmap.h
@@ -0,0 +1,61 @@
+/*
+ * For boards with physically mapped flash and using 
+ * drivers/mtd/maps/physmap.c mapping driver.
+ *
+ * $Id: physmap.h,v 1.3 2004/07/21 00:16:15 jwboyer Exp $
+ *
+ * Copyright (C) 2003 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MTD_PHYSMAP__
+
+#include <linux/config.h>
+
+#if defined(CONFIG_MTD_PHYSMAP) 
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+/*
+ * The map_info for physmap.  Board can override size, buswidth, phys,
+ * (*set_vpp)(), etc in their initial setup routine.
+ */
+extern struct map_info physmap_map;
+
+/*
+ * Board needs to specify the exact mapping during their setup time.
+ */
+static inline void physmap_configure(unsigned long addr, unsigned long size, int bankwidth, void (*set_vpp)(struct map_info *, int) )
+{
+	physmap_map.phys = addr;
+	physmap_map.size = size;
+	physmap_map.bankwidth = bankwidth;
+	physmap_map.set_vpp = set_vpp;
+}
+
+#if defined(CONFIG_MTD_PARTITIONS)
+
+/*
+ * Machines that wish to do flash partition may want to call this function in 
+ * their setup routine.  
+ *
+ *	physmap_set_partitions(mypartitions, num_parts);
+ *
+ * Note that one can always override this hard-coded partition with 
+ * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS).
+ */
+void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
+
+#endif /* defined(CONFIG_MTD_PARTITIONS) */
+#endif /* defined(CONFIG_MTD) */
+
+#endif /* __LINUX_MTD_PHYSMAP__ */
+
diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h
new file mode 100644
index 0000000..113e308
--- /dev/null
+++ b/include/linux/mtd/pmc551.h
@@ -0,0 +1,79 @@
+/*
+ * $Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $
+ *
+ * PMC551 PCI Mezzanine Ram Device
+ *
+ * Author:
+ *       Mark Ferrell
+ *       Copyright 1999,2000 Nortel Networks
+ *
+ * License: 
+ *	 As part of this driver was derrived from the slram.c driver it falls
+ *	 under the same license, which is GNU General Public License v2
+ */
+
+#ifndef __MTD_PMC551_H__
+#define __MTD_PMC551_H__
+
+#include <linux/mtd/mtd.h>
+
+#define PMC551_VERSION "$Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $\n"\
+       "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
+
+/*
+ * Our personal and private information
+ */
+struct mypriv {
+        struct pci_dev *dev;
+        u_char *start;
+        u32    base_map0;
+        u32    curr_map0;
+        u32    asize;
+	struct mtd_info *nextpmc551;
+};                       
+
+/*
+ * Function Prototypes
+ */
+static int pmc551_erase(struct mtd_info *, struct erase_info *);
+static void pmc551_unpoint(struct mtd_info *, u_char *, loff_t, size_t);
+static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
+static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
+static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);        
+
+
+/*
+ * Define the PCI ID's if the kernel doesn't define them for us
+ */
+#ifndef PCI_VENDOR_ID_V3_SEMI
+#define PCI_VENDOR_ID_V3_SEMI             0x11b0
+#endif
+
+#ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC
+#define PCI_DEVICE_ID_V3_SEMI_V370PDC     0x0200  
+#endif
+
+
+#define PMC551_PCI_MEM_MAP0	0x50
+#define PMC551_PCI_MEM_MAP1	0x54
+#define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK	0x3ff00000
+#define PMC551_PCI_MEM_MAP_APERTURE_MASK	0x000000f0
+#define PMC551_PCI_MEM_MAP_REG_EN		0x00000002
+#define PMC551_PCI_MEM_MAP_ENABLE		0x00000001
+
+#define PMC551_SDRAM_MA		0x60
+#define PMC551_SDRAM_CMD	0x62
+#define PMC551_DRAM_CFG		0x64
+#define PMC551_SYS_CTRL_REG	0x78
+
+#define PMC551_DRAM_BLK0	0x68
+#define PMC551_DRAM_BLK1	0x6c
+#define PMC551_DRAM_BLK2	0x70
+#define PMC551_DRAM_BLK3	0x74
+#define PMC551_DRAM_BLK_GET_SIZE(x) (524288<<((x>>4)&0x0f))
+#define PMC551_DRAM_BLK_SET_COL_MUX(x,v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
+#define PMC551_DRAM_BLK_SET_ROW_MUX(x,v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
+
+
+#endif /* __MTD_PMC551_H__ */
+
diff --git a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h
new file mode 100644
index 0000000..fc07112
--- /dev/null
+++ b/include/linux/mtd/xip.h
@@ -0,0 +1,107 @@
+/*
+ * MTD primitives for XIP support
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Nov 2, 2004
+ * Copyright:	(C) 2004 MontaVista Software, Inc.
+ *
+ * This XIP support for MTD has been loosely inspired
+ * by an earlier patch authored by David Woodhouse.
+ *
+ * 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.
+ *
+ * $Id: xip.h,v 1.2 2004/12/01 15:49:10 nico Exp $
+ */
+
+#ifndef __LINUX_MTD_XIP_H__
+#define __LINUX_MTD_XIP_H__
+
+#include <linux/config.h>
+
+#ifdef CONFIG_MTD_XIP
+
+/*
+ * Function that are modifying the flash state away from array mode must
+ * obviously not be running from flash.  The __xipram is therefore marking
+ * those functions so they get relocated to ram.
+ */
+#define __xipram __attribute__ ((__section__ (".data")))
+
+/*
+ * We really don't want gcc to guess anything.
+ * We absolutely _need_ proper inlining.
+ */
+#include <linux/compiler.h>
+
+/*
+ * Each architecture has to provide the following macros.  They must access
+ * the hardware directly and not rely on any other (XIP) functions since they
+ * won't be available when used (flash not in array mode).
+ *
+ * xip_irqpending()
+ *
+ * 	return non zero when any hardware interrupt is pending.
+ *
+ * xip_currtime()
+ *
+ * 	return a platform specific time reference to be used with
+ * 	xip_elapsed_since().
+ *
+ * xip_elapsed_since(x)
+ *
+ * 	return in usecs the elapsed timebetween now and the reference x as
+ * 	returned by xip_currtime().
+ *
+ * 	note 1: convertion to usec can be approximated, as long as the
+ * 		returned value is <= the real elapsed time.
+ * 	note 2: this should be able to cope with a few seconds without
+ * 		overflowing.
+ */
+
+#if defined(CONFIG_ARCH_SA1100) || defined(CONFIG_ARCH_PXA)
+
+#include <asm/hardware.h>
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
+#define xip_irqpending()	(ICIP & ICMR)
+
+/* we sample OSCR and convert desired delta to usec (1/4 ~= 1000000/3686400) */
+#define xip_currtime()		(OSCR)
+#define xip_elapsed_since(x)	(signed)((OSCR - (x)) / 4)
+
+#else
+
+#warning "missing IRQ and timer primitives for XIP MTD support"
+#warning "some of the XIP MTD support code will be disabled"
+#warning "your system will therefore be unresponsive when writing or erasing flash"
+
+#define xip_irqpending()	(0)
+#define xip_currtime()		(0)
+#define xip_elapsed_since(x)	(0)
+
+#endif
+
+/*
+ * xip_cpu_idle() is used when waiting for a delay equal or larger than
+ * the system timer tick period.  This should put the CPU into idle mode
+ * to save power and to be woken up only when some interrupts are pending.
+ * As above, this should not rely upon standard kernel code.
+ */
+
+#if defined(CONFIG_CPU_XSCALE)
+#define xip_cpu_idle()  asm volatile ("mcr p14, 0, %0, c7, c0, 0" :: "r" (1))
+#else
+#define xip_cpu_idle()  do { } while (0)
+#endif
+
+#else
+
+#define __xipram
+
+#endif /* CONFIG_MTD_XIP */
+
+#endif /* __LINUX_MTD_XIP_H__ */