diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 18:38:57 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 18:38:57 -0800 |
| commit | a5287abe398b74df9040d6dcd8356cf53a174e84 (patch) | |
| tree | 181a6ce3feb61fabc1dd3ca2d452074a419df431 /include/linux/mtd | |
| parent | 4fdbe71c852f4b44203913c93a5d3a8a12041167 (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.h | 298 | ||||
| -rw-r--r-- | include/linux/mtd/cfi_endian.h | 141 | ||||
| -rw-r--r-- | include/linux/mtd/doc2000.h | 20 | ||||
| -rw-r--r-- | include/linux/mtd/flashchip.h | 7 | ||||
| -rw-r--r-- | include/linux/mtd/map.h | 55 | ||||
| -rw-r--r-- | include/linux/mtd/mapped.h | 92 | ||||
| -rw-r--r-- | include/linux/mtd/mtd.h | 73 | ||||
| -rw-r--r-- | include/linux/mtd/nand_ecc.h | 28 | ||||
| -rw-r--r-- | include/linux/mtd/nftl.h | 3 | ||||
| -rw-r--r-- | include/linux/mtd/partitions.h | 20 |
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 *); |
