summaryrefslogtreecommitdiff
path: root/include/linux/mtd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 18:38:57 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 18:38:57 -0800
commita5287abe398b74df9040d6dcd8356cf53a174e84 (patch)
tree181a6ce3feb61fabc1dd3ca2d452074a419df431 /include/linux/mtd
parent4fdbe71c852f4b44203913c93a5d3a8a12041167 (diff)
v2.4.5.2 -> v2.4.5.3
- remember to increment the version number - Chris Mason: reiserfs mark_journal_new and bh leak fix - Richard Gooch: devfs update - Alexander Viro: further FS cleanup (superblock list) - David Woodhouse: MTD update - Kai Germaschewski: ISDN update (stanford checker fixes etc) - Rich Baum: gcc-3.0 warning fixes - Jeff Garzik: network driver updates - Geert Uytterhoeven: m68k fbdev logo merge glitch fix - Andrea Arcangeli: fix signal return path - David Miller: Sparc updates - Johannes Erdfelt: USB update - Carsten Otte, Andries Brouwer: don't clear blk_size unconditionally on partition check - Martin Frey: alpha Sable irq fix - Paul Mackerras: PPC softirq update - Patrick Mochel: PCI power management infrastructure - Robert Siemer: miroSOUND driver update - Neil Brown: knfsd updates, including ability to export ReiserFS filesystems - Trond Myklebust: NFS readdir fixup, don't update atime on client - Andrew Morton: truncate_inode_pages speedup - Paul Menage: make inode quota count all inodes..
Diffstat (limited to 'include/linux/mtd')
-rw-r--r--include/linux/mtd/cfi.h298
-rw-r--r--include/linux/mtd/cfi_endian.h141
-rw-r--r--include/linux/mtd/doc2000.h20
-rw-r--r--include/linux/mtd/flashchip.h7
-rw-r--r--include/linux/mtd/map.h55
-rw-r--r--include/linux/mtd/mapped.h92
-rw-r--r--include/linux/mtd/mtd.h73
-rw-r--r--include/linux/mtd/nand_ecc.h28
-rw-r--r--include/linux/mtd/nftl.h3
-rw-r--r--include/linux/mtd/partitions.h20
10 files changed, 563 insertions, 174 deletions
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index 4ce69eee899a..bda9f0ae74b6 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -1,14 +1,160 @@
/* Common Flash Interface structures
* See http://support.intel.com/design/flash/technote/index.htm
- * $Id: cfi.h,v 1.6 2000/07/03 13:29:16 dwmw2 Exp $
+ * $Id: cfi.h,v 1.21 2001/06/03 01:32:57 nico Exp $
*/
#ifndef __MTD_CFI_H__
#define __MTD_CFI_H__
+#include <linux/config.h>
+#include <linux/delay.h>
#include <linux/types.h>
#include <linux/mtd/flashchip.h>
+#include <linux/mtd/cfi_endian.h>
+
+/*
+ * You can optimize the code size and performance by defining only
+ * the geometry(ies) available on your hardware.
+ * CFIDEV_INTERLEAVE_n, where represents the interleave (number of chips to fill the bus width)
+ * CFIDEV_BUSWIDTH_n, where n is the bus width in bytes (1, 2 or 4 bytes)
+ *
+ * By default, all (known) geometries are supported.
+ */
+
+#ifndef CONFIG_MTD_CFI_GEOMETRY
+
+#define CFIDEV_INTERLEAVE_1 (1)
+#define CFIDEV_INTERLEAVE_2 (2)
+#define CFIDEV_INTERLEAVE_4 (4)
+
+#define CFIDEV_BUSWIDTH_1 (1)
+#define CFIDEV_BUSWIDTH_2 (2)
+#define CFIDEV_BUSWIDTH_4 (4)
+
+#else
+
+#ifdef CONFIG_MTD_CFI_I1
+#define CFIDEV_INTERLEAVE_1 (1)
+#endif
+#ifdef CONFIG_MTD_CFI_I2
+#define CFIDEV_INTERLEAVE_2 (2)
+#endif
+#ifdef CONFIG_MTD_CFI_I4
+#define CFIDEV_INTERLEAVE_4 (4)
+#endif
+
+#ifdef CONFIG_MTD_CFI_B1
+#define CFIDEV_BUSWIDTH_1 (1)
+#endif
+#ifdef CONFIG_MTD_CFI_B2
+#define CFIDEV_BUSWIDTH_2 (2)
+#endif
+#ifdef CONFIG_MTD_CFI_B4
+#define CFIDEV_BUSWIDTH_4 (4)
+#endif
+
+#endif
+
+/*
+ * The following macros are used to select the code to execute:
+ * cfi_buswidth_is_*()
+ * cfi_interleave_is_*()
+ * [where * is either 1, 2 or 4]
+ * Those macros should be used with 'if' statements. If only one of few
+ * geometry arrangements are selected, they expand to constants thus allowing
+ * the compiler (most of them being 0) to optimize away all the unneeded code,
+ * while still validating the syntax (which is not possible with embedded
+ * #if ... #endif constructs).
+ */
+
+#ifdef CFIDEV_INTERLEAVE_1
+# ifdef CFIDEV_INTERLEAVE
+# undef CFIDEV_INTERLEAVE
+# define CFIDEV_INTERLEAVE (cfi->interleave)
+# else
+# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_1
+# endif
+# define cfi_interleave_is_1() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_1)
+#else
+# define cfi_interleave_is_1() (0)
+#endif
+
+#ifdef CFIDEV_INTERLEAVE_2
+# ifdef CFIDEV_INTERLEAVE
+# undef CFIDEV_INTERLEAVE
+# define CFIDEV_INTERLEAVE (cfi->interleave)
+# else
+# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_2
+# endif
+# define cfi_interleave_is_2() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_2)
+#else
+# define cfi_interleave_is_2() (0)
+#endif
+
+#ifdef CFIDEV_INTERLEAVE_4
+# ifdef CFIDEV_INTERLEAVE
+# undef CFIDEV_INTERLEAVE
+# define CFIDEV_INTERLEAVE (cfi->interleave)
+# else
+# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_4
+# endif
+# define cfi_interleave_is_4() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_4)
+#else
+# define cfi_interleave_is_4() (0)
+#endif
+
+#ifndef CFIDEV_INTERLEAVE
+#error You must define at least one interleave to support!
+#endif
+
+#ifdef CFIDEV_BUSWIDTH_1
+# ifdef CFIDEV_BUSWIDTH
+# undef CFIDEV_BUSWIDTH
+# define CFIDEV_BUSWIDTH (map->buswidth)
+# else
+# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_1
+# endif
+# define cfi_buswidth_is_1() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_1)
+#else
+# define cfi_buswidth_is_1() (0)
+#endif
+
+#ifdef CFIDEV_BUSWIDTH_2
+# ifdef CFIDEV_BUSWIDTH
+# undef CFIDEV_BUSWIDTH
+# define CFIDEV_BUSWIDTH (map->buswidth)
+# else
+# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_2
+# endif
+# define cfi_buswidth_is_2() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_2)
+#else
+# define cfi_buswidth_is_2() (0)
+#endif
+
+#ifdef CFIDEV_BUSWIDTH_4
+# ifdef CFIDEV_BUSWIDTH
+# undef CFIDEV_BUSWIDTH
+# define CFIDEV_BUSWIDTH (map->buswidth)
+# else
+# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_4
+# endif
+# define cfi_buswidth_is_4() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_4)
+#else
+# define cfi_buswidth_is_4() (0)
+#endif
+
+#ifndef CFIDEV_BUSWIDTH
+#error You must define at least one bus width to support!
+#endif
+
+/* 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)
/* NB: We keep these structures in memory in HOST byteorder, except
* where individually noted.
@@ -37,7 +183,7 @@ struct cfi_ident {
__u16 InterfaceDesc;
__u16 MaxBufWriteSize;
__u8 NumEraseRegions;
- __u32 EraseRegionInfo[1]; /* Not host ordered */
+ __u32 EraseRegionInfo[0]; /* Not host ordered */
} __attribute__((packed));
/* Extended Query Structure for both PRI and ALT */
@@ -82,20 +228,164 @@ struct cfi_bri_query {
#define P_ID_RESERVED 65535
+#define CFI_MODE_CFI 0
+#define CFI_MODE_JEDEC 1
+
struct cfi_private {
__u16 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;
+ int fast_prog;
struct mtd_info *(*cmdset_setup)(struct map_info *);
- struct cfi_ident cfiq; /* For now only one. We insist that all devs
+ struct cfi_ident *cfiq; /* For now only one. We insist that all devs
must be of the same type. */
+ __u8 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 */
- /* do not add extra fields after "chips" */
};
#define MAX_CFI_CHIPS 8 /* Entirely arbitrary to avoid realloc() */
+/*
+ * Returns the command address according to the given geometry.
+ */
+static inline __u32 cfi_build_cmd_addr(__u32 cmd_ofs, int interleave, int type)
+{
+ return (cmd_ofs * type) * interleave;
+}
+
+/*
+ * Transforms the CFI command for the given geometry (bus width & interleave.
+ */
+static inline __u32 cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi)
+{
+ __u32 val = 0;
+
+ if (cfi_buswidth_is_1()) {
+ /* 1 x8 device */
+ val = cmd;
+ } else if (cfi_buswidth_is_2()) {
+ if (cfi_interleave_is_1()) {
+ /* 1 x16 device in x16 mode */
+ val = cpu_to_cfi16(cmd);
+ } else if (cfi_interleave_is_2()) {
+ /* 2 (x8, x16 or x32) devices in x8 mode */
+ val = cpu_to_cfi16((cmd << 8) | cmd);
+ }
+ } else if (cfi_buswidth_is_4()) {
+ if (cfi_interleave_is_1()) {
+ /* 1 x32 device in x32 mode */
+ val = cpu_to_cfi32(cmd);
+ } else if (cfi_interleave_is_2()) {
+ /* 2 x16 device in x16 mode */
+ val = cpu_to_cfi32((cmd << 16) | cmd);
+ } else if (cfi_interleave_is_4()) {
+ /* 4 (x8, x16 or x32) devices in x8 mode */
+ val = (cmd << 16) | cmd;
+ val = cpu_to_cfi32((val << 8) | val);
+ }
+ }
+ return val;
+}
+#define CMD(x) cfi_build_cmd((x), map, cfi)
+
+/*
+ * Read a value according to the bus width.
+ */
+
+static inline __u32 cfi_read(struct map_info *map, __u32 addr)
+{
+ if (cfi_buswidth_is_1()) {
+ return map->read8(map, addr);
+ } else if (cfi_buswidth_is_2()) {
+ return map->read16(map, addr);
+ } else if (cfi_buswidth_is_4()) {
+ return map->read32(map, addr);
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * Write a value according to the bus width.
+ */
+
+static inline void cfi_write(struct map_info *map, __u32 val, __u32 addr)
+{
+ if (cfi_buswidth_is_1()) {
+ map->write8(map, val, addr);
+ } else if (cfi_buswidth_is_2()) {
+ map->write16(map, val, addr);
+ } else if (cfi_buswidth_is_4()) {
+ map->write32(map, val, addr);
+ }
+}
+
+/*
+ * 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 __u32 cfi_send_gen_cmd(u_char cmd, __u32 cmd_addr, __u32 base,
+ struct map_info *map, struct cfi_private *cfi,
+ int type, __u32 *prev_val)
+{
+ __u32 val;
+ __u32 addr = base + cfi_build_cmd_addr(cmd_addr, CFIDEV_INTERLEAVE, type);
+
+ val = cfi_build_cmd(cmd, map, cfi);
+
+ if (prev_val)
+ *prev_val = cfi_read(map, addr);
+
+ cfi_write(map, val, addr);
+
+ return addr - base;
+}
+
+static inline __u8 cfi_read_query(struct map_info *map, __u32 addr)
+{
+ if (cfi_buswidth_is_1()) {
+ return map->read8(map, addr);
+ } else if (cfi_buswidth_is_2()) {
+ return cfi16_to_cpu(map->read16(map, addr));
+ } else if (cfi_buswidth_is_4()) {
+ return cfi32_to_cpu(map->read32(map, addr));
+ } else {
+ return 0;
+ }
+}
+
+#ifndef min
+#define min(x,y) ( (x)<(y)?(x):(y) )
+#endif
+
+static inline void cfi_udelay(int us)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
+ if (current->need_resched)
+ schedule();
+ else
+#endif
+ udelay(us);
+}
+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);
+}
+
+
#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 000000000000..052139bf210d
--- /dev/null
+++ b/include/linux/mtd/cfi_endian.h
@@ -0,0 +1,141 @@
+/*
+ * $Id: cfi_endian.h,v 1.9 2001/04/23 21:19:11 nico Exp $
+ *
+ * It seems that some helpful people decided to make life easier
+ * for software engineers who aren't capable of dealing with the
+ * concept of byteswapping, and advise engineers to swap the bytes
+ * by wiring the data lines up to flash chips from BE hosts backwards.
+ *
+ * So we have ugly stuff here to disable the byteswapping where necessary.
+ * I'm not going to try to do this dynamically.
+ *
+ * At first I thought these guys were on crack, but then I discovered the
+ * LART.
+ *
+ */
+
+#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
+
+#ifdef CONFIG_MTD_CFI_LART_BIT_SWAP
+#define CFI_LART_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 cfi16_to_cpu(x) le16_to_cpu(x)
+#define cfi32_to_cpu(x) le32_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 cfi16_to_cpu(x) be16_to_cpu(x)
+#define cfi32_to_cpu(x) be32_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 cfi16_to_cpu(x) (x)
+#define cfi32_to_cpu(x) (x)
+#elif defined (CFI_LART_ENDIAN)
+/*
+ Fuck me backwards. The data line mapping on LART is as follows:
+
+ U2 CPU | U3 CPU
+ 0 20 | 0 12
+ 1 22 | 1 14
+ 2 19 | 2 11
+ 3 17 | 3 9
+ 4 24 | 4 0
+ 5 26 | 5 2
+ 6 31 | 6 7
+ 7 29 | 7 5
+ 8 21 | 8 13
+ 9 23 | 9 15
+ 10 18 | 10 10
+ 11 16 | 11 8
+ 12 25 | 12 1
+ 13 27 | 13 3
+ 14 30 | 14 6
+ 15 28 | 15 4
+
+ For historical reference: the reason why the LART has this strange
+ mapping is that the designer of the board wanted address lines to
+ be as short as possible. Why? Because in that way you don't need
+ drivers in the address lines so the memory access time can be held
+ short. -- Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
+*/
+/* cpu_to_cfi16() and cfi16_to_cpu() are not needed because the LART
+ * only has 32 bit wide Flash memory. -- Erik
+ */
+#define cpu_to_cfi16(x) (x)
+#define cfi16_to_cpu(x) (x)
+static inline __u32 cfi32_to_cpu(__u32 x)
+{
+ __u32 ret;
+
+ ret = (x & 0x08009000) >> 11;
+ ret |= (x & 0x00002000) >> 10;
+ ret |= (x & 0x04004000) >> 8;
+ ret |= (x & 0x00000010) >> 4;
+ ret |= (x & 0x91000820) >> 3;
+ ret |= (x & 0x22080080) >> 2;
+ ret |= (x & 0x40000400);
+ ret |= (x & 0x00040040) << 1;
+ ret |= (x & 0x00110000) << 4;
+ ret |= (x & 0x00220100) << 5;
+ ret |= (x & 0x00800208) << 6;
+ ret |= (x & 0x00400004) << 9;
+ ret |= (x & 0x00000001) << 12;
+ ret |= (x & 0x00000002) << 13;
+
+ return ret;
+}
+static inline __u32 cpu_to_cfi32(__u32 x)
+{
+ __u32 ret;
+
+ ret = (x & 0x00010012) << 11;
+ ret |= (x & 0x00000008) << 10;
+ ret |= (x & 0x00040040) << 8;
+ ret |= (x & 0x00000001) << 4;
+ ret |= (x & 0x12200104) << 3;
+ ret |= (x & 0x08820020) << 2;
+ ret |= (x & 0x40000400);
+ ret |= (x & 0x00080080) >> 1;
+ ret |= (x & 0x01100000) >> 4;
+ ret |= (x & 0x04402000) >> 5;
+ ret |= (x & 0x20008200) >> 6;
+ ret |= (x & 0x80000800) >> 9;
+ ret |= (x & 0x00001000) >> 12;
+ ret |= (x & 0x00004000) >> 13;
+
+ return ret;
+}
+#else
+#error No CFI endianness defined
+#endif
diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h
index 696938aa1853..c8e143a1f723 100644
--- a/include/linux/mtd/doc2000.h
+++ b/include/linux/mtd/doc2000.h
@@ -2,7 +2,7 @@
/* Linux driver for Disk-On-Chip 2000 */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2000.h,v 1.12 2000/11/03 12:43:43 dwmw2 Exp $ */
+/* $Id: doc2000.h,v 1.13 2001/05/29 12:03:45 dwmw2 Exp $ */
#ifndef __MTD_DOC2000_H__
#define __MTD_DOC2000_H__
@@ -43,15 +43,19 @@
* On PPC, it's mmap'd and 16-bit wide.
* Others use readb/writeb
*/
-#if defined(__arm__)
-#define ReadDOC_(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+(reg<<2))))
-#define WriteDOC_(d, adr, reg) do{ *(__u32 *)(((unsigned long)adr)+(reg<<2)) = (__u32)d} while(0)
+#if defined(__arm__)
+#define ReadDOC_(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+((reg)<<2))))
+#define WriteDOC_(d, adr, reg) do{ *(__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)(*(__u16 *)(((unsigned long)adr)+(reg<<1))))
-#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+(reg<<1)) = (__u16)d} while(0)
+#define ReadDOC_(adr, reg) ((unsigned char)(*(__u16 *)(((unsigned long)adr)+((reg)<<1))))
+#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0)
+#define DOC_IOREMAP_LEN 0x4000
#else
-#define ReadDOC_(adr, reg) readb(((unsigned long)adr) + reg)
-#define WriteDOC_(d, adr, reg) writeb(d, ((unsigned long)adr) + reg)
+#define ReadDOC_(adr, reg) readb(((unsigned long)adr) + (reg))
+#define WriteDOC_(d, adr, reg) writeb(d, ((unsigned long)adr) + (reg))
+#define DOC_IOREMAP_LEN 0x2000
+
#endif
#if defined(__i386__)
diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h
index 17c7cec2ccd2..4cdccad20abe 100644
--- a/include/linux/mtd/flashchip.h
+++ b/include/linux/mtd/flashchip.h
@@ -6,7 +6,7 @@
*
* (C) 2000 Red Hat. GPLd.
*
- * $Id: flashchip.h,v 1.4 2000/07/03 12:58:41 dwmw2 Exp $
+ * $Id: flashchip.h,v 1.7 2001/01/18 03:52:36 nico Exp $
*
*/
@@ -25,12 +25,17 @@ typedef enum {
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_UNKNOWN
} flstate_t;
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 71fc46b1a7fa..84553406e6b1 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -1,6 +1,6 @@
/* Overhauled routines for dealing with different mmap regions of flash */
-/* $Id: map.h,v 1.10.2.2 2001/01/09 00:44:51 dwmw2 Exp $ */
+/* $Id: map.h,v 1.24 2001/06/09 19:53:16 dwmw2 Exp $ */
#ifndef __LINUX_MTD_MAP_H__
#define __LINUX_MTD_MAP_H__
@@ -53,47 +53,23 @@ struct map_info {
unsigned long map_priv_1;
unsigned long map_priv_2;
void *fldrv_priv;
- void (*fldrv_destroy)(struct mtd_info *);
- const char *im_name;
+ struct mtd_chip_driver *fldrv;
};
-#ifdef CONFIG_MODULES
-/*
- * Probe for the contents of a map device and make an MTD structure
- * if anything is recognised. Doesn't register it because the calling
- * map driver needs to set the 'module' field first.
- */
-static inline struct mtd_info *do_map_probe(struct map_info *map, const char *funcname, const char *modname)
-{
- struct mtd_info *(*probe_p)(struct map_info *);
- struct mtd_info *mtd = NULL;
- if ((probe_p = inter_module_get_request(modname, funcname)))
- mtd = (*probe_p)(map); /* map->im_name is set by probe */
-
- return mtd;
-}
+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 *);
-/*
- * Commonly-used probe functions for different types of chip.
- */
-#define do_cfi_probe(x) do_map_probe(x, "cfi_probe", "cfi_probe")
-#define do_jedec_probe(x) do_map_probe(x, "jedec_probe", "jedec_probe")
-#define do_ram_probe(x) do_map_probe(x, "map_ram_probe", "map_ram")
-#define do_rom_probe(x) do_map_probe(x, "map_rom_probe", "map_rom")
-#else
- /* without module support, call probe function directly */
-extern struct mtd_info *cfi_probe(struct map_info *);
-extern struct mtd_info *jedec_probe(struct map_info *);
-extern struct mtd_info *map_ram_probe(struct map_info *);
-extern struct mtd_info *map_rom_probe(struct map_info *);
+struct mtd_info *do_map_probe(char *name, struct map_info *map);
-#define do_cfi_probe(x) cfi_probe(x)
-#define do_jedec_probe(x) jedec_probe(x)
-#define do_ram_probe(x) map_ram_probe(x)
-#define do_rom_probe(x) map_rom_probe(x)
-#endif
/*
* Destroy an MTD device which was created for a map device.
@@ -103,8 +79,11 @@ static inline void map_destroy(struct mtd_info *mtd)
{
struct map_info *map = mtd->priv;
- map->fldrv_destroy(mtd);
- inter_module_put(map->im_name);
+ map->fldrv->destroy(mtd);
+#ifdef CONFIG_MODULES
+ if (map->fldrv->module)
+ __MOD_DEC_USE_COUNT(map->fldrv->module);
+#endif
kfree(mtd);
}
diff --git a/include/linux/mtd/mapped.h b/include/linux/mtd/mapped.h
deleted file mode 100644
index 81668b71e916..000000000000
--- a/include/linux/mtd/mapped.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// -*- mode: cpp; mode: fold -*-
-// Description /*{{{*/
-// $Id: mapped.h,v 1.2 2000/03/14 17:13:12 dwmw2 Exp $
-/* ######################################################################
-
- Memory Mapped MTD Routines
-
- These routines are support routines for memory mapped chips, with
- routines to support common sorts of flash. For devices that are based
- on a memory mapped interface these routines provide everything necessary,
- only a window changing function is required by the low level implementation.
-
- The entry point to setup and register a memory mapped MTD device,
- mtd_mapped_setup will perform a detection sequence that can determine
- the type size and configuration of many sorts of chip setups.
-
- ROMs and RAMs are detected and passed off to very simple routines, Flash
- writing and erasing is handled as well.
-
- ##################################################################### */
- /*}}}*/
-#ifndef __MTD_FLASH_H__
-#define __MTD_FLASH_H__
-
-#include <linux/types.h>
-#include <linux/mtd/mtd.h>
-
-// MTD flags for ordinary flash
-struct JEDECTable
-{
- u_short jedec;
- char *name;
- u_long size;
- u_long sectorsize;
- u_long capabilities;
-};
-
-// JEDEC being 0 is the end of the chip array
-struct flash_chip
-{
- u_short jedec;
- u_long size;
- u_long sectorsize;
- u_long base;
- u_long capabilities;
-
- // These markers are filled in by the flash_chip_scan function
- u_long start;
- u_long length;
-};
-
-struct mapped_mtd_info
-{
- struct mtd_info mtd;
- u_long pagesize; // Size of the memory window
- u_long maxsize; // Maximum MTD size in pages
- u_char mfr,id;
- char part[100]; // Part Catalogue number if available
- int *lock;
- // Multiple chip support, only used if this is type MTD_FLASH
- u_char interleve; // Address chip interleve (0 = concatination)
- struct flash_chip chips[5];
-
- // Operations
- unsigned long (*page)(struct mapped_mtd_info *map,unsigned long page);
- int (*jedec_sense)(struct mapped_mtd_info *map);
-};
-
-extern struct JEDECTable mtd_JEDEC_table[];
-
-// Automatic configurators
-extern int mtd_mapped_setup(struct mapped_mtd_info *map);
-extern int mtd_mapped_remove(struct mapped_mtd_info *map);
-
-// Generic functions
-extern int flash_jedec(struct mapped_mtd_info *map);
-extern int flash_erase(struct mtd_info *map, struct erase_info *instr);
-extern int flash_write(struct mtd_info *map, loff_t start, size_t len,
- size_t *retlen, const u_char *buf);
-extern int rom_read(struct mtd_info *map, loff_t start, size_t len,
- size_t *retlen, u_char *buf);
-extern int ram_write(struct mtd_info *map, loff_t start, size_t len,
- size_t *retlen, const u_char *buf);
-
-// Helpers
-extern int page_jump(struct mapped_mtd_info *map,unsigned long start,
- unsigned long len,unsigned long *buffer,
- unsigned long *size);
-extern void flash_chip_scan(struct mapped_mtd_info *map,unsigned long start,
- unsigned long len);
-
-#endif /* __MTD_FLASH_H__ */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index a703b853e56a..ae5bfe3e10fb 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -1,5 +1,5 @@
-/* $Id: mtd.h,v 1.26 2000/10/30 17:18:04 sjhill Exp $ */
+/* $Id: mtd.h,v 1.33 2001/06/09 00:08:59 dwmw2 Exp $ */
#ifndef __MTD_MTD_H__
#define __MTD_MTD_H__
@@ -16,13 +16,13 @@
#endif /* __KERNEL__ */
struct erase_info_user {
- unsigned long start;
- unsigned long length;
+ u_int32_t start;
+ u_int32_t length;
};
struct mtd_oob_buf {
- loff_t start;
- ssize_t length;
+ u_int32_t start;
+ u_int32_t length;
unsigned char *ptr;
};
@@ -68,13 +68,21 @@ struct mtd_oob_buf {
struct mtd_info_user {
u_char type;
- u_long flags;
- u_long size; // Total size of the MTD
- u_long erasesize;
- u_long oobblock; // Size of OOB blocks (e.g. 512)
- u_long oobsize; // Amount of OOB data per block (e.g. 16)
- u_long ecctype;
- u_long eccsize;
+ u_int32_t flags;
+ u_int32_t size; // Total size of the MTD
+ 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 ecctype;
+ u_int32_t eccsize;
+};
+
+struct region_info_user {
+ 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 in this region */
+ u_int32_t regionindex;
};
#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
@@ -83,11 +91,14 @@ struct mtd_info_user {
#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
#define MEMLOCK _IOW('M', 5, struct erase_info_user)
#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
+#define MEMGETREGIONCOUNT _IOR('M', 7, int)
+#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user)
#ifndef __KERNEL__
typedef struct mtd_info_user mtd_info_t;
typedef struct erase_info_user erase_info_t;
+typedef struct region_info_user region_info_t;
/* User-space ioctl definitions */
@@ -103,8 +114,8 @@ typedef struct erase_info_user erase_info_t;
struct erase_info {
struct mtd_info *mtd;
- u_long addr;
- u_long len;
+ u_int32_t addr;
+ u_int32_t len;
u_long time;
u_long retries;
u_int dev;
@@ -115,22 +126,40 @@ struct erase_info {
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_long flags;
- u_long size; // Total size of the MTD
- u_long erasesize;
- u_long oobblock; // Size of OOB blocks (e.g. 512)
- u_long oobsize; // Amount of OOB data per block (e.g. 16)
- u_long ecctype;
- u_long eccsize;
+ 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 ecctype;
+ u_int32_t eccsize;
// Kernel-only stuff starts here.
char *name;
int index;
- u_long bank_size;
+ /* 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;
struct module *module;
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h
new file mode 100644
index 000000000000..f3f1d7e0f6aa
--- /dev/null
+++ b/include/linux/mtd/nand_ecc.h
@@ -0,0 +1,28 @@
+/*
+ * drivers/mtd/nand_ecc.h
+ *
+ * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
+ *
+ * $Id: nand_ecc.h,v 1.1 2000/10/12 00:57:15 sjhill 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.
+ */
+
+/*
+ * Creates non-inverted ECC code from line parity
+ */
+void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code);
+
+/*
+ * Calculate 3 byte ECC code for 256 byte block
+ */
+void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
+
+/*
+ * Detect and correct a 1 bit error for 256 byte block
+ */
+int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h
index ae00ceb0ba2a..3483a8c4022d 100644
--- a/include/linux/mtd/nftl.h
+++ b/include/linux/mtd/nftl.h
@@ -2,7 +2,7 @@
/* Defines for NAND Flash Translation Layer */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: nftl.h,v 1.9 2000/11/07 05:48:49 ollie Exp $ */
+/* $Id: nftl.h,v 1.10 2000/12/29 00:25:38 dwmw2 Exp $ */
#ifndef __MTD_NFTL_H__
#define __MTD_NFTL_H__
@@ -115,6 +115,7 @@ int NFTL_formatblock(struct NFTLrecord *s, int block);
#define MAX_NFTLS 16
#define MAX_SECTORS_PER_UNIT 32
+#define NFTL_PARTN_BITS 4
#endif /* __KERNEL__ */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index a92023886008..1d3351cc1eca 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -5,7 +5,7 @@
*
* This code is GPL
*
- * $Id: partitions.h,v 1.3 2000/11/10 23:35:12 nico Exp $
+ * $Id: partitions.h,v 1.6 2001/03/17 17:10:21 dwmw2 Exp $
*/
#ifndef MTD_PARTITIONS_H
@@ -22,10 +22,11 @@
*
* 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 0, the partition will extend to the end of the
- * master MTD device.
- * offset: absolute starting position within the master MTD device; if 0,
- * partition will start where the previous one ended.
+ * 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.
* 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
@@ -37,11 +38,14 @@
struct mtd_partition {
char *name; /* identifier string */
- u_long size; /* partition size */
- u_long offset; /* offset within the master MTD space */
- u_long mask_flags; /* master MTD flags to mask out for this partition */
+ 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 */
};
+#define MTDPART_OFS_APPEND (-1)
+#define MTDPART_SIZ_FULL (0)
+
int add_mtd_partitions(struct mtd_info *, struct mtd_partition *, int);
int del_mtd_partitions(struct mtd_info *);