summaryrefslogtreecommitdiffstats
path: root/linux-2.4.x/include/linux/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'linux-2.4.x/include/linux/mtd')
-rw-r--r--linux-2.4.x/include/linux/mtd/bbm.h122
-rw-r--r--linux-2.4.x/include/linux/mtd/blktrans.h72
-rw-r--r--linux-2.4.x/include/linux/mtd/cfi.h584
-rw-r--r--linux-2.4.x/include/linux/mtd/cfi_endian.h8
-rw-r--r--linux-2.4.x/include/linux/mtd/compatmac.h349
-rw-r--r--linux-2.4.x/include/linux/mtd/doc2000.h97
-rw-r--r--linux-2.4.x/include/linux/mtd/flashchip.h36
-rw-r--r--linux-2.4.x/include/linux/mtd/ftl.h6
-rw-r--r--linux-2.4.x/include/linux/mtd/gen_probe.h8
-rw-r--r--linux-2.4.x/include/linux/mtd/inftl.h62
-rw-r--r--linux-2.4.x/include/linux/mtd/jedec.h21
-rw-r--r--linux-2.4.x/include/linux/mtd/map.h432
-rw-r--r--linux-2.4.x/include/linux/mtd/mtd.h227
-rw-r--r--linux-2.4.x/include/linux/mtd/nand.h540
-rw-r--r--linux-2.4.x/include/linux/mtd/nand_ecc.h18
-rw-r--r--linux-2.4.x/include/linux/mtd/nftl.h88
-rw-r--r--linux-2.4.x/include/linux/mtd/onenand.h161
-rw-r--r--linux-2.4.x/include/linux/mtd/onenand_regs.h190
-rw-r--r--linux-2.4.x/include/linux/mtd/partitions.h47
-rw-r--r--linux-2.4.x/include/linux/mtd/physmap.h61
-rw-r--r--linux-2.4.x/include/linux/mtd/plat-ram.h35
-rw-r--r--linux-2.4.x/include/linux/mtd/pmc551.h14
-rw-r--r--linux-2.4.x/include/linux/mtd/xip.h102
23 files changed, 2465 insertions, 815 deletions
diff --git a/linux-2.4.x/include/linux/mtd/bbm.h b/linux-2.4.x/include/linux/mtd/bbm.h
new file mode 100644
index 0000000..7a7fbe8
--- /dev/null
+++ b/linux-2.4.x/include/linux/mtd/bbm.h
@@ -0,0 +1,122 @@
+/*
+ * linux/include/linux/mtd/bbm.h
+ *
+ * NAND family Bad Block Management (BBM) header file
+ * - Bad Block Table (BBT) implementation
+ *
+ * Copyright (c) 2005 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * Copyright (c) 2000-2005
+ * Thomas Gleixner <tglx@linuxtronix.de>
+ *
+ */
+#ifndef __LINUX_MTD_BBM_H
+#define __LINUX_MTD_BBM_H
+
+/* The maximum number of NAND chips in an array */
+#define NAND_MAX_CHIPS 8
+
+/**
+ * struct nand_bbt_descr - bad block table descriptor
+ * @param options options for this descriptor
+ * @param 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
+ * @param offs offset of the pattern in the oob area of the page
+ * @param veroffs offset of the bbt version counter in the oob are of the page
+ * @param version version read from the bbt page during scan
+ * @param len length of the pattern, if 0 no pattern check is performed
+ * @param 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.
+ * @param reserved_block_code if non-0, this pattern denotes a reserved
+ * (rather than bad) block in the stored bbt
+ * @param 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
+
+/*
+ * Constants for oob configuration
+ */
+#define ONENAND_BADBLOCK_POS 0
+
+/**
+ * struct bbt_info - [GENERIC] Bad Block Table data structure
+ * @param bbt_erase_shift [INTERN] number of address bits in a bbt entry
+ * @param badblockpos [INTERN] position of the bad block marker in the oob area
+ * @param bbt [INTERN] bad block table pointer
+ * @param badblock_pattern [REPLACEABLE] bad block scan pattern used for initial bad block scan
+ * @param priv [OPTIONAL] pointer to private bbm date
+ */
+struct bbm_info {
+ int bbt_erase_shift;
+ int badblockpos;
+ int options;
+
+ uint8_t *bbt;
+
+ int (*isbad_bbt)(struct mtd_info *mtd, loff_t ofs, int allowbbt);
+
+ /* TODO Add more NAND specific fileds */
+ struct nand_bbt_descr *badblock_pattern;
+
+ void *priv;
+};
+
+/* OneNAND BBT interface */
+extern int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int onenand_default_bbt(struct mtd_info *mtd);
+
+#endif /* __LINUX_MTD_BBM_H */
diff --git a/linux-2.4.x/include/linux/mtd/blktrans.h b/linux-2.4.x/include/linux/mtd/blktrans.h
new file mode 100644
index 0000000..23c00e4
--- /dev/null
+++ b/linux-2.4.x/include/linux/mtd/blktrans.h
@@ -0,0 +1,72 @@
+/*
+ * $Id: blktrans.h,v 1.7 2006/03/29 08:26:28 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 <linux/mutex.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 mutex lock;
+ 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/linux-2.4.x/include/linux/mtd/cfi.h b/linux-2.4.x/include/linux/mtd/cfi.h
index 7d6b316..abf45ef 100644
--- a/linux-2.4.x/include/linux/mtd/cfi.h
+++ b/linux-2.4.x/include/linux/mtd/cfi.h
@@ -1,7 +1,7 @@
-/* Common Flash Interface structures
+/* Common Flash Interface structures
* See http://support.intel.com/design/flash/technote/index.htm
- * $Id: cfi.h,v 1.25 2001/09/04 07:06:21 dwmw2 Exp $
+ * $Id: cfi.h,v 1.58 2005/11/29 20:01:30 gleixner Exp $
*/
#ifndef __MTD_CFI_H__
@@ -12,150 +12,83 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/mtd/flashchip.h>
+#include <linux/mtd/map.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
-
+#define cfi_interleave(cfi) 1
+#define cfi_interleave_is_1(cfi) (cfi_interleave(cfi) == 1)
+#else
+#define cfi_interleave_is_1(cfi) (0)
#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)
+#ifdef CONFIG_MTD_CFI_I2
+# ifdef cfi_interleave
+# undef cfi_interleave
+# define cfi_interleave(cfi) ((cfi)->interleave)
# else
-# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_1
+# define cfi_interleave(cfi) 2
# endif
-# define cfi_interleave_is_1() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_1)
+#define cfi_interleave_is_2(cfi) (cfi_interleave(cfi) == 2)
#else
-# define cfi_interleave_is_1() (0)
+#define cfi_interleave_is_2(cfi) (0)
#endif
-#ifdef CFIDEV_INTERLEAVE_2
-# ifdef CFIDEV_INTERLEAVE
-# undef CFIDEV_INTERLEAVE
-# define CFIDEV_INTERLEAVE (cfi->interleave)
+#ifdef CONFIG_MTD_CFI_I4
+# ifdef cfi_interleave
+# undef cfi_interleave
+# define cfi_interleave(cfi) ((cfi)->interleave)
# else
-# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_2
+# define cfi_interleave(cfi) 4
# endif
-# define cfi_interleave_is_2() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_2)
+#define cfi_interleave_is_4(cfi) (cfi_interleave(cfi) == 4)
#else
-# define cfi_interleave_is_2() (0)
+#define cfi_interleave_is_4(cfi) (0)
#endif
-#ifdef CFIDEV_INTERLEAVE_4
-# ifdef CFIDEV_INTERLEAVE
-# undef CFIDEV_INTERLEAVE
-# define CFIDEV_INTERLEAVE (cfi->interleave)
+#ifdef CONFIG_MTD_CFI_I8
+# ifdef cfi_interleave
+# undef cfi_interleave
+# define cfi_interleave(cfi) ((cfi)->interleave)
# else
-# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_4
+# define cfi_interleave(cfi) 8
# endif
-# define cfi_interleave_is_4() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_4)
+#define cfi_interleave_is_8(cfi) (cfi_interleave(cfi) == 8)
#else
-# define cfi_interleave_is_4() (0)
+#define cfi_interleave_is_8(cfi) (0)
#endif
-#ifndef CFIDEV_INTERLEAVE
-#error You must define at least one interleave to support!
+static inline int cfi_interleave_supported(int i)
+{
+ switch (i) {
+#ifdef CONFIG_MTD_CFI_I1
+ case 1:
#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)
+#ifdef CONFIG_MTD_CFI_I2
+ case 2:
#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)
+#ifdef CONFIG_MTD_CFI_I4
+ case 4:
#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)
+#ifdef CONFIG_MTD_CFI_I8
+ case 8:
#endif
+ return 1;
+
+ default:
+ return 0;
+ }
+}
-#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.
+/* 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.
@@ -163,84 +96,147 @@
/* Basic Query Structure */
struct cfi_ident {
- __u8 qry[3];
- __u16 P_ID;
- __u16 P_ADR;
- __u16 A_ID;
- __u16 A_ADR;
- __u8 VccMin;
- __u8 VccMax;
- __u8 VppMin;
- __u8 VppMax;
- __u8 WordWriteTimeoutTyp;
- __u8 BufWriteTimeoutTyp;
- __u8 BlockEraseTimeoutTyp;
- __u8 ChipEraseTimeoutTyp;
- __u8 WordWriteTimeoutMax;
- __u8 BufWriteTimeoutMax;
- __u8 BlockEraseTimeoutMax;
- __u8 ChipEraseTimeoutMax;
- __u8 DevSize;
- __u16 InterfaceDesc;
- __u16 MaxBufWriteSize;
- __u8 NumEraseRegions;
- __u32 EraseRegionInfo[0]; /* Not host ordered */
+ 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 {
- __u8 pri[3];
- __u8 MajorVersion;
- __u8 MinorVersion;
+ 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 {
- __u8 pri[3];
- __u8 MajorVersion;
- __u8 MinorVersion;
- __u32 FeatureSupport;
- __u8 SuspendCmdSupport;
- __u16 BlkStatusRegMask;
- __u8 VccOptimal;
- __u8 VppOptimal;
+ 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_otpinfo {
+ uint32_t ProtRegAddr;
+ uint16_t FactGroups;
+ uint8_t FactProtRegSize;
+ uint16_t UserGroups;
+ uint8_t UserProtRegSize;
+} __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));
+
+struct cfi_intelext_programming_regioninfo {
+ uint8_t ProgRegShift;
+ uint8_t Reserved1;
+ uint8_t ControlValid;
+ uint8_t Reserved2;
+ uint8_t ControlInvalid;
+ uint8_t Reserved3;
+} __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 {
- __u8 NumFields;
- __u32 ProtField[1]; /* Not host ordered */
+ uint8_t NumFields;
+ uint32_t ProtField[1]; /* Not host ordered */
} __attribute__((packed));
struct cfi_bri_query {
- __u8 PageModeReadCap;
- __u8 NumFields;
- __u32 ConfField[1]; /* Not host ordered */
+ uint8_t PageModeReadCap;
+ uint8_t NumFields;
+ uint32_t ConfField[1]; /* Not host ordered */
} __attribute__((packed));
-#define P_ID_NONE 0
-#define P_ID_INTEL_EXT 1
-#define P_ID_AMD_STD 2
-#define P_ID_INTEL_STD 3
-#define P_ID_AMD_EXT 4
-#define P_ID_MITSUBISHI_STD 256
-#define P_ID_MITSUBISHI_EXT 257
-#define P_ID_RESERVED 65535
+#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 0
-#define CFI_MODE_JEDEC 1
+#define CFI_MODE_CFI 1
+#define CFI_MODE_JEDEC 0
struct cfi_private {
- __u16 cmdset;
+ 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;
- int fast_prog;
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. */
@@ -251,83 +247,145 @@ struct cfi_private {
struct flchip chips[0]; /* per-chip data structure for each chip */
};
-#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)
+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.
+ * 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 __u32 cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi)
+static inline map_word cfi_build_cmd(u_long 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);
- }
+ 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)
-/*
- * Read a value according to the bus width.
- */
-static inline __u32 cfi_read(struct map_info *map, __u32 addr)
+static inline unsigned long cfi_merge_status(map_word val, struct map_info *map,
+ struct cfi_private *cfi)
{
- 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);
+ int wordwidth, words_per_bus, chip_mode, chips_per_word;
+ unsigned long onestat, res = 0;
+ 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 {
- return 0;
+ wordwidth = map_bankwidth(map);
+ words_per_bus = 1;
}
-}
-/*
- * Write a value according to the bus width.
- */
+ chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
+ chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
-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);
+ onestat = val.x[0];
+ /* Or all status words together */
+ for (i=1; i < words_per_bus; i++) {
+ onestat |= val.x[i];
+ }
+
+ res = onestat;
+ switch(chips_per_word) {
+ default: BUG();
+#if BITS_PER_LONG >= 64
+ case 8:
+ res |= (onestat >> (chip_mode * 32));
+#endif
+ case 4:
+ res |= (onestat >> (chip_mode * 16));
+ case 2:
+ res |= (onestat >> (chip_mode * 8));
+ case 1:
+ ;
+ }
+
+ /* Last, determine what the bit-pattern should be for a single
+ device, according to chip mode and endianness... */
+ switch (chip_mode) {
+ case 1:
+ break;
+ case 2:
+ res = cfi16_to_cpu(res);
+ break;
+ case 4:
+ res = cfi32_to_cpu(res);
+ break;
+ default: BUG();
}
+ return res;
}
+#define MERGESTATUS(x) cfi_merge_status((x), map, cfi)
+
+
/*
* Sends a CFI command to a bank of flash for the given geometry.
*
@@ -335,59 +393,87 @@ static inline void cfi_write(struct map_info *map, __u32 val, __u32 addr)
* 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,
+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, __u32 *prev_val)
+ int type, map_word *prev_val)
{
- __u32 val;
- __u32 addr = base + cfi_build_cmd_addr(cmd_addr, CFIDEV_INTERLEAVE, type);
+ 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 = cfi_read(map, addr);
+ *prev_val = map_read(map, addr);
- cfi_write(map, val, addr);
+ map_write(map, val, addr);
return addr - base;
}
-static inline __u8 cfi_read_query(struct map_info *map, __u32 addr)
+static inline uint8_t cfi_read_query(struct map_info *map, uint32_t 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));
+ 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 {
- return 0;
+ /* 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)
+static inline uint16_t cfi_read_query16(struct map_info *map, uint32_t addr)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- if (current->need_resched) {
- unsigned long t = us * HZ / 1000000;
- if (t < 1)
- t = 1;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(t);
+ map_word val = map_read(map, addr);
+
+ if (map_bankwidth_is_1(map)) {
+ return val.x[0] & 0xff;
+ } 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]);
}
- 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)
+static inline void cfi_udelay(int us)
{
- spin_unlock_bh(mutex);
+ if (us >= 1000) {
+ msleep((us+999)/1000);
+ } else {
+ udelay(us);
+ cond_resched();
+ }
}
+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/linux-2.4.x/include/linux/mtd/cfi_endian.h b/linux-2.4.x/include/linux/mtd/cfi_endian.h
index 9f3b041..25724f7 100644
--- a/linux-2.4.x/include/linux/mtd/cfi_endian.h
+++ b/linux-2.4.x/include/linux/mtd/cfi_endian.h
@@ -1,5 +1,5 @@
/*
- * $Id: cfi_endian.h,v 1.10 2001/06/18 11:00:46 abz Exp $
+ * $Id: cfi_endian.h,v 1.11 2002/01/30 23:20:48 awozniak Exp $
*
*/
@@ -30,22 +30,28 @@
#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/linux-2.4.x/include/linux/mtd/compatmac.h b/linux-2.4.x/include/linux/mtd/compatmac.h
index 9c9a227..5433d1f 100644
--- a/linux-2.4.x/include/linux/mtd/compatmac.h
+++ b/linux-2.4.x/include/linux/mtd/compatmac.h
@@ -1,202 +1,249 @@
-
/*
- * mtd/include/compatmac.h
- *
- * $Id: compatmac.h,v 1.4 2000/07/03 10:01:38 dwmw2 Exp $
+ * $Id: compatmac.h,v 1.80 2005/11/07 11:14:54 gleixner Exp $
*
* Extensions and omissions from the normal 'linux/compatmac.h'
- * files. hopefully this will end up empty as the 'real' one
+ * files. hopefully this will end up empty as the 'real' one
* becomes fully-featured.
*/
-
-/* First, include the parts which the kernel is good enough to provide
- * to us
- */
-
#ifndef __LINUX_MTD_COMPATMAC_H__
#define __LINUX_MTD_COMPATMAC_H__
-#include <linux/compatmac.h>
-#include <linux/types.h> /* used later in this header */
-#include <linux/module.h>
-#ifndef LINUX_VERSION_CODE
#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
+#error "This kernel is too old: not supported by this file"
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-#include <linux/vmalloc.h>
+ /* O(1) scheduler stuff. */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5) && !defined(__rh_config_h__)
+#include <linux/sched.h>
+static inline void __recalc_sigpending(void)
+{
+ recalc_sigpending(current);
+}
+#undef recalc_sigpending
+#define recalc_sigpending() __recalc_sigpending ()
+
+#define set_user_nice(tsk, n) do { (tsk)->nice = n; } while(0)
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,0,0)
-# error "This kernel is too old: not supported by this file"
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)
+
+#ifndef yield
+#define yield() do { set_current_state(TASK_RUNNING); schedule(); } while(0)
#endif
-/* Modularization issues */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,18)
-# define __USE_OLD_SYMTAB__
-# define EXPORT_NO_SYMBOLS register_symtab(NULL);
-# define REGISTER_SYMTAB(tab) register_symtab(tab)
-#else
-# define REGISTER_SYMTAB(tab) /* nothing */
+#ifndef minor
+#define major(d) (MAJOR(to_kdev_t(d)))
+#define minor(d) (MINOR(to_kdev_t(d)))
#endif
-#ifdef __USE_OLD_SYMTAB__
-# define __MODULE_STRING(s) /* nothing */
-# define MODULE_PARM(v,t) /* nothing */
-# define MODULE_PARM_DESC(v,t) /* nothing */
-# define MODULE_AUTHOR(n) /* nothing */
-# define MODULE_DESCRIPTION(d) /* nothing */
-# define MODULE_SUPPORTED_DEVICE(n) /* nothing */
+#ifndef mk_kdev
+#define mk_kdev(ma,mi) MKDEV(ma,mi)
+#define kdev_t_to_nr(x) (x)
#endif
-/*
- * "select" changed in 2.1.23. The implementation is twin, but this
- * header is new
- */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,22)
-# include <linux/poll.h>
-#else
-# define __USE_OLD_SELECT__
+#define need_resched() (current->need_resched)
+#define cond_resched() do { if need_resched() { yield(); } } while(0)
+
+#endif /* < 2.4.20 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,73)
+#define iminor(i) minor((i)->i_rdev)
+#define imajor(i) major((i)->i_rdev)
+#define old_encode_dev(d) ( (major(d)<<8) | minor(d) )
+#define old_decode_dev(rdev) (kdev_t_to_nr(mk_kdev((rdev)>>8, (rdev)&0xff)))
+#define old_valid_dev(d) (1)
#endif
-/* Other change in the fops are solved using pseudo-types */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-# define lseek_t long long
-# define lseek_off_t long long
-#else
-# define lseek_t int
-# define lseek_off_t off_t
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61)
+
+#include <linux/sched.h>
+
+#ifdef __rh_config_h__
+#define sigmask_lock sighand->siglock
+#define sig sighand
#endif
-/* changed the prototype of read/write */
+static inline void __daemonize_modvers(void)
+{
+ daemonize();
+
+ spin_lock_irq(&current->sigmask_lock);
+ sigfillset(&current->blocked);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sigmask_lock);
+}
+#undef daemonize
+#define daemonize(fmt, ...) do { \
+ snprintf(current->comm, sizeof(current->comm), fmt ,##__VA_ARGS__); \
+ __daemonize_modvers(); \
+ } while(0)
+
+static inline int dequeue_signal_lock(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+{
+ unsigned long flags;
+ unsigned long ret;
+
+ spin_lock_irqsave(&current->sigmask_lock, flags);
+ ret = dequeue_signal(mask, info);
+ spin_unlock_irqrestore(&current->sigmask_lock, flags);
+
+ return ret;
+}
+
+static inline int allow_signal(int sig)
+{
+ if (sig < 1 || sig > _NSIG)
+ return -EINVAL;
+
+ spin_lock_irq(&current->sigmask_lock);
+ sigdelset(&current->blocked, sig);
+ recalc_sigpending();
+ /* Make sure the kernel neither eats it now converts to SIGKILL */
+ current->sig->action[sig-1].sa.sa_handler = (void *)2;
+ spin_unlock_irq(&current->sigmask_lock);
+ return 0;
+}
+static inline int disallow_signal(int sig)
+{
+ if (sig < 1 || sig > _NSIG)
+ return -EINVAL;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) || defined(__alpha__)
-# define count_t unsigned long
-# define read_write_t long
-#else
-# define count_t int
-# define read_write_t int
+ spin_lock_irq(&current->sigmask_lock);
+ sigaddset(&current->blocked, sig);
+ recalc_sigpending();
+
+ current->sig->action[sig-1].sa.sa_handler = SIG_DFL;
+ spin_unlock_irq(&current->sigmask_lock);
+ return 0;
+}
+
+#define PF_FREEZE 0
+#define refrigerator(x) do { ; } while(0)
#endif
+ /* Module bits */
+
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,31)
-# define release_t void
-# define release_return(x) return
-#else
-# define release_t int
-# define release_return(x) return (x)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
+#define try_module_get(m) try_inc_mod_count(m)
+#define __module_get(m) do { if (!try_inc_mod_count(m)) BUG(); } while(0)
+#define module_put(m) do { if (m) __MOD_DEC_USE_COUNT((struct module *)(m)); } while(0)
+#define set_module_owner(x) do { x->owner = THIS_MODULE; } while(0)
#endif
-#if LINUX_VERSION_CODE < 0x20300
-#define __exit
+
+ /* Random filesystem stuff, only for JFFS2 really */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5)
+#define parent_ino(d) ((d)->d_parent->d_inode->i_ino)
#endif
-#if LINUX_VERSION_CODE < 0x20200
-#define __init
-#else
-#include <linux/init.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,12)
+#define PageUptodate(x) Page_Uptodate(x)
#endif
-#if LINUX_VERSION_CODE < 0x20300
-#define init_MUTEX(x) do {*(x) = MUTEX;} while (0)
-#define RQFUNC_ARG void
-#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0)
-#else
-#define RQFUNC_ARG request_queue_t *q
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)
+#define get_seconds() CURRENT_TIME
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)
-#define __MOD_INC_USE_COUNT(mod) \
- (atomic_inc(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED|MOD_USED_ONCE)
-#define __MOD_DEC_USE_COUNT(mod) \
- (atomic_dec(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,53)
+#define generic_file_readonly_mmap generic_file_mmap
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,70)
+
+#include <linux/kmod.h>
+#include <linux/string.h>
+
+static inline char *strlcpy(char *dest, const char *src, int len)
+{
+ dest[len-1] = 0;
+ return strncpy(dest, src, len-1);
+}
+
+static inline int do_old_request_module(const char *mod)
+{
+ return request_module(mod);
+}
+#undef request_module
+#define request_module(fmt, ...) \
+ ({ char modname[32]; snprintf(modname, 31, fmt ,##__VA_ARGS__); do_old_request_module(modname); })
+
+#endif /* 2.5.70 */
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)
+#define kvec iovec
+#define __user
+#endif
-#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL
-#define init_waitqueue_head init_waitqueue
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,28)
+#define msleep(x) \
+ set_current_state(TASK_UNINTERRUPTIBLE); \
+ schedule_timeout((x)*(HZ/1000));
+#endif
-static inline int try_inc_mod_count(struct module *mod)
+#ifndef __iomem
+#define __iomem
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+#define CURRENT_TIME_SEC ((struct timespec) { xtime.tv_sec, 0 })
+#include <linux/sched.h>
+#include <linux/suspend.h>
+static inline int try_to_freeze(unsigned long refrigerator_flags)
{
- if (mod)
- __MOD_INC_USE_COUNT(mod);
- return 1;
+ if (unlikely(current->flags & PF_FREEZE)) {
+ refrigerator(refrigerator_flags);
+ return 1;
+ } else
+ return 0;
}
#endif
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
+#define try_to_freeze() try_to_freeze(0)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
+typedef struct class_simple class;
+#define class_device_create(cs, dev, device, fmt, ...) class_simple_device_add((struct class_simple *)cs, dev, device, fmt, __VA_ARGS__)
+#define class_device_destroy(cs, dev) class_simple_device_remove(dev)
+#define class_create(owner, name) (struct class *)class_simple_create(owner, name)
+#define class_destroy(cs) class_simple_destroy((struct class_simple *)cs)
+#endif
-/* Yes, I'm aware that it's a fairly ugly hack.
- Until the __constant_* macros appear in Linus' own kernels, this is
- the way it has to be done.
- DW 19/1/00
+#ifndef list_for_each_entry_safe
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
*/
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
-#include <asm/byteorder.h>
-
-#ifndef __constant_cpu_to_le16
-
-#ifdef __BIG_ENDIAN
-#define __constant_cpu_to_le64(x) ___swab64((x))
-#define __constant_le64_to_cpu(x) ___swab64((x))
-#define __constant_cpu_to_le32(x) ___swab32((x))
-#define __constant_le32_to_cpu(x) ___swab32((x))
-#define __constant_cpu_to_le16(x) ___swab16((x))
-#define __constant_le16_to_cpu(x) ___swab16((x))
-#define __constant_cpu_to_be64(x) ((__u64)(x))
-#define __constant_be64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_be32(x) ((__u32)(x))
-#define __constant_be32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_be16(x) ((__u16)(x))
-#define __constant_be16_to_cpu(x) ((__u16)(x))
-#else
-#ifdef __LITTLE_ENDIAN
-#define __constant_cpu_to_le64(x) ((__u64)(x))
-#define __constant_le64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_le32(x) ((__u32)(x))
-#define __constant_le32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_le16(x) ((__u16)(x))
-#define __constant_le16_to_cpu(x) ((__u16)(x))
-#define __constant_cpu_to_be64(x) ___swab64((x))
-#define __constant_be64_to_cpu(x) ___swab64((x))
-#define __constant_cpu_to_be32(x) ___swab32((x))
-#define __constant_be32_to_cpu(x) ___swab32((x))
-#define __constant_cpu_to_be16(x) ___swab16((x))
-#define __constant_be16_to_cpu(x) ___swab16((x))
-#else
-#error No (recognised) endianness defined (unless it,s PDP)
-#endif /* __LITTLE_ENDIAN */
-#endif /* __BIG_ENDIAN */
-
-#endif /* ifndef __constant_cpu_to_le16 */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
- #define mod_init_t int __init
- #define mod_exit_t void
-#else
- #define mod_init_t static int __init
- #define mod_exit_t static void __exit
-#endif
-
-#ifndef THIS_MODULE
-#ifdef MODULE
-#define THIS_MODULE (&__this_module)
-#else
-#define THIS_MODULE (NULL)
-#endif
-#endif
-
-#if LINUX_VERSION_CODE < 0x20300
-#include <linux/interrupt.h>
-#define spin_lock_bh(lock) do {start_bh_atomic();spin_lock(lock);} while(0)
-#define spin_unlock_bh(lock) do {spin_unlock(lock);end_bh_atomic();} while(0)
-#else
-#include <asm/softirq.h>
-#include <linux/spinlock.h>
#endif
-#endif /* __LINUX_MTD_COMPATMAC_H__ */
-
+#ifndef DEFINE_SPINLOCK
+#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
+#endif
+#ifndef DEFINE_RWLOCK
+#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
+#endif
+#endif /* __LINUX_MTD_COMPATMAC_H__ */
diff --git a/linux-2.4.x/include/linux/mtd/doc2000.h b/linux-2.4.x/include/linux/mtd/doc2000.h
index 6161f2c..244954e 100644
--- a/linux-2.4.x/include/linux/mtd/doc2000.h
+++ b/linux-2.4.x/include/linux/mtd/doc2000.h
@@ -1,13 +1,21 @@
-
-/* Linux driver for Disk-On-Chip 2000 */
-/* (c) 1999 Machine Vision Holdings, Inc. */
-/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2000.h,v 1.15 2001/09/19 00:22:15 dwmw2 Exp $ */
+/*
+ * 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.26 2006/03/29 08:26:28 dwmw2 Exp $
+ *
+ * Released under GPL
+ */
#ifndef __MTD_DOC2000_H__
#define __MTD_DOC2000_H__
#include <linux/mtd/mtd.h>
+#include <linux/mutex.h>
#define DoC_Sig1 0
#define DoC_Sig2 1
@@ -38,22 +46,51 @@
#define DoC_Mil_CDSN_IO 0x0800
#define DoC_2k_CDSN_IO 0x1800
-/* How to access the device?
- * On ARM, it'll be mmap'd directly with 32-bit wide accesses.
+#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
+ * 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; wmb();} while(0)
+#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)(*(__u16 *)(((unsigned long)adr)+((reg)<<1))))
-#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0)
+#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(((unsigned long)adr) + (reg))
-#define WriteDOC_(d, adr, reg) writeb(d, ((unsigned long)adr) + (reg))
+#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
@@ -71,13 +108,21 @@
#define DOC_MODE_RESERVED1 2
#define DOC_MODE_RESERVED2 3
-#define DOC_MODE_MDWREN 4
#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
@@ -93,6 +138,10 @@
#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)
@@ -107,34 +156,38 @@ struct Nand {
#define MAX_FLOORS 4
#define MAX_CHIPS 4
-#define MAX_FLOORS_MIL 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;
- unsigned long virtadr;
+ void __iomem *virtadr;
unsigned long totlen;
- char ChipID; /* Type of DiskOnChip */
+ 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;
+ struct mutex lock;
};
int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]);
diff --git a/linux-2.4.x/include/linux/mtd/flashchip.h b/linux-2.4.x/include/linux/mtd/flashchip.h
index 4cdccad..a293a3b 100644
--- a/linux-2.4.x/include/linux/mtd/flashchip.h
+++ b/linux-2.4.x/include/linux/mtd/flashchip.h
@@ -1,12 +1,12 @@
-/*
+/*
* struct flchip definition
- *
- * Contains information about the location and state of a given flash device
+ *
+ * Contains information about the location and state of a given flash device
*
* (C) 2000 Red Hat. GPLd.
*
- * $Id: flashchip.h,v 1.7 2001/01/18 03:52:36 nico Exp $
+ * $Id: flashchip.h,v 1.18 2005/11/07 11:14:54 gleixner Exp $
*
*/
@@ -15,11 +15,11 @@
/* 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
+ * has asm/spinlock.h, or 2.4, which has linux/spinlock.h
*/
#include <linux/sched.h>
-typedef enum {
+typedef enum {
FL_READY,
FL_STATUS,
FL_CFI_QUERY,
@@ -29,6 +29,7 @@ typedef enum {
FL_ERASE_SUSPENDED,
FL_WRITING,
FL_WRITING_TO_BUFFER,
+ FL_OTP_WRITE,
FL_WRITE_SUSPENDING,
FL_WRITE_SUSPENDED,
FL_PM_SUSPENDED,
@@ -36,13 +37,17 @@ typedef enum {
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. */
+/* 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 */
@@ -54,8 +59,14 @@ struct flchip {
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;
+
+ unsigned int write_suspended:1;
+ unsigned 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
@@ -63,8 +74,17 @@ struct flchip {
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/linux-2.4.x/include/linux/mtd/ftl.h b/linux-2.4.x/include/linux/mtd/ftl.h
index ae017ef..d996091 100644
--- a/linux-2.4.x/include/linux/mtd/ftl.h
+++ b/linux-2.4.x/include/linux/mtd/ftl.h
@@ -1,6 +1,6 @@
/*
- * $Id: ftl.h,v 1.5 2001/06/02 20:35:51 dwmw2 Exp $
- *
+ * $Id: ftl.h,v 1.7 2005/11/07 11:14:54 gleixner Exp $
+ *
* Derived from (and probably identical to):
* ftl.h 1.7 1999/10/25 20:23:17
*
@@ -12,7 +12,7 @@
* 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.
+ * 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
diff --git a/linux-2.4.x/include/linux/mtd/gen_probe.h b/linux-2.4.x/include/linux/mtd/gen_probe.h
index 43c3a08..256e734 100644
--- a/linux-2.4.x/include/linux/mtd/gen_probe.h
+++ b/linux-2.4.x/include/linux/mtd/gen_probe.h
@@ -1,21 +1,21 @@
/*
* (C) 2001, 2001 Red Hat, Inc.
* GPL'd
- * $Id: gen_probe.h,v 1.1 2001/09/02 18:50:13 dwmw2 Exp $
+ * $Id: gen_probe.h,v 1.4 2005/11/07 11:14:54 gleixner 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/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,
- struct flchip *chips, struct cfi_private *cfi);
-
+ unsigned long *chip_map, struct cfi_private *cfi);
};
struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp);
diff --git a/linux-2.4.x/include/linux/mtd/inftl.h b/linux-2.4.x/include/linux/mtd/inftl.h
new file mode 100644
index 0000000..9dbf209
--- /dev/null
+++ b/linux-2.4.x/include/linux/mtd/inftl.h
@@ -0,0 +1,62 @@
+/*
+ * inftl.h -- defines to support the Inverse NAND Flash Translation Layer
+ *
+ * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
+ *
+ * $Id: inftl.h,v 1.8 2006/03/29 08:27:08 dwmw2 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 96
+#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);
+
+extern char inftlmountrev[];
+
+void INFTL_dumptables(struct INFTLrecord *s);
+void INFTL_dumpVUchains(struct INFTLrecord *s);
+
+#endif /* __KERNEL__ */
+
+#endif /* __MTD_INFTL_H__ */
diff --git a/linux-2.4.x/include/linux/mtd/jedec.h b/linux-2.4.x/include/linux/mtd/jedec.h
index 75271b8..9006feb 100644
--- a/linux-2.4.x/include/linux/mtd/jedec.h
+++ b/linux-2.4.x/include/linux/mtd/jedec.h
@@ -1,20 +1,19 @@
/* JEDEC Flash Interface.
- * This is an older type of interface for self programming flash. It is
+ * 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.2 2001/11/06 14:37:36 dwmw2 Exp $
+ * $Id: jedec.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $
*/
#ifndef __LINUX_MTD_JEDEC_H__
#define __LINUX_MTD_JEDEC_H__
#include <linux/types.h>
-#include <linux/mtd/map.h>
#define MAX_JEDEC_CHIPS 16
@@ -34,16 +33,16 @@ 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;
@@ -52,16 +51,16 @@ struct jedec_flash_chip
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
+ 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];
+
+ struct jedec_flash_chip chips[MAX_JEDEC_CHIPS];
};
#endif
diff --git a/linux-2.4.x/include/linux/mtd/map.h b/linux-2.4.x/include/linux/mtd/map.h
index 94ffed2..fedfbc8 100644
--- a/linux-2.4.x/include/linux/mtd/map.h
+++ b/linux-2.4.x/include/linux/mtd/map.h
@@ -1,27 +1,183 @@
/* Overhauled routines for dealing with different mmap regions of flash */
-/* $Id: map.h,v 1.25 2001/09/09 15:04:17 dwmw2 Exp $ */
+/* $Id: map.h,v 1.54 2005/11/07 11:14:54 gleixner Exp $ */
#ifndef __LINUX_MTD_MAP_H__
#define __LINUX_MTD_MAP_H__
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/mtd/mtd.h>
-#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/string.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 driver which deals with a mapped device - generally either
- do_cfi_probe() or do_ram_probe(), either of which will return a
- struct mtd_info if they liked what they saw. At which point, you
- fill in the mtd->module with your own module address, and register
- it.
-
+ 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
+ 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.
*/
@@ -29,34 +185,45 @@
struct map_info {
char *name;
unsigned long size;
- int buswidth; /* in octets */
- __u8 (*read8)(struct map_info *, unsigned long);
- __u16 (*read16)(struct map_info *, unsigned long);
- __u32 (*read32)(struct map_info *, unsigned long);
- /* If it returned a 'long' I'd call it readl.
- * It doesn't.
- * I won't.
- * dwmw2 */
-
+ 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 (*write8)(struct map_info *, __u8, unsigned long);
- void (*write16)(struct map_info *, __u16, unsigned long);
- void (*write32)(struct map_info *, __u32, unsigned long);
+
+ 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);
- /* We put these two here rather than a single void *map_priv,
- because we want mappers to be able to have quickly-accessible
- cache for the 'currently-mapped page' without the _extra_
- redirection that would be necessary. If you need more than
- two longs, turn the second into a pointer. dwmw2 */
+
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 *);
@@ -68,27 +235,204 @@ struct mtd_chip_driver {
void register_mtd_chip_driver(struct mtd_chip_driver *);
void unregister_mtd_chip_driver(struct mtd_chip_driver *);
-struct mtd_info *do_map_probe(char *name, struct map_info *map);
+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_clr(struct map_info *map, map_word val1, map_word val2)
+{
+ map_word r;
+ int i;
-/*
- * Destroy an MTD device which was created for a map device.
- * Make sure the MTD device is already unregistered before calling this
- */
-static inline void map_destroy(struct mtd_info *mtd)
+ 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)
{
- struct map_info *map = mtd->priv;
+ map_word r;
+ int i;
+
+ for (i=0; i<map_words(map); i++) {
+ r.x[i] = val1.x[i] | val2.x[i];
+ }
+ return r;
+}
- if (map->fldrv->destroy)
- map->fldrv->destroy(mtd);
-#ifdef CONFIG_MODULES
- if (map->fldrv->module)
- __MOD_DEC_USE_COUNT(map->fldrv->module);
+#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
- kfree(mtd);
+ else if (map_bankwidth_is_large(map))
+ memcpy(r.x, ptr, map->bankwidth);
+
+ return r;
}
-#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)
+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;
+}
+
+#if BITS_PER_LONG < 64
+#define MAP_FF_LIMIT 4
+#else
+#define MAP_FF_LIMIT 8
+#endif
+
+static inline map_word map_word_ff(struct map_info *map)
+{
+ map_word r;
+ int i;
+
+ if (map_bankwidth(map) < MAP_FF_LIMIT) {
+ int bw = 8 * map_bankwidth(map);
+ r.x[0] = (1 << bw) - 1;
+ } else {
+ 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) ({ (void)(map); 1; })
+
+#endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */
#endif /* __LINUX_MTD_MAP_H__ */
diff --git a/linux-2.4.x/include/linux/mtd/mtd.h b/linux-2.4.x/include/linux/mtd/mtd.h
index b186e6c..fbc075b 100644
--- a/linux-2.4.x/include/linux/mtd/mtd.h
+++ b/linux-2.4.x/include/linux/mtd/mtd.h
@@ -1,123 +1,45 @@
-
-/* $Id: mtd.h,v 1.33 2001/06/09 00:08:59 dwmw2 Exp $ */
+/*
+ * $Id: mtd.h,v 1.62 2005/11/29 20:01:30 gleixner Exp $
+ *
+ * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
+ *
+ * Released under GPL
+ */
#ifndef __MTD_MTD_H__
#define __MTD_MTD_H__
-#ifdef __KERNEL__
+#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/mtd/compatmac.h>
#include <linux/module.h>
#include <linux/uio.h>
+#include <linux/notifier.h>
-#endif /* __KERNEL__ */
-
-struct erase_info_user {
- u_int32_t start;
- u_int32_t length;
-};
-
-struct mtd_oob_buf {
- u_int32_t start;
- u_int32_t length;
- unsigned char *ptr;
-};
-
+#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_ABSENT 0
-#define MTD_RAM 1
-#define MTD_ROM 2
-#define MTD_NORFLASH 3
-#define MTD_NANDFLASH 4
-#define MTD_PEROM 5
-#define MTD_OTHER 14
-#define MTD_UNKNOWN 15
-
-
-
-#define MTD_CLEAR_BITS 1 // Bits can be cleared (flash)
-#define MTD_SET_BITS 2 // Bits can be set
-#define MTD_ERASEABLE 4 // Has an erase function
-#define MTD_WRITEB_WRITEABLE 8 // Direct IO is possible
-#define MTD_VOLATILE 16 // Set for RAMs
-#define MTD_XIP 32 // eXecute-In-Place possible
-#define MTD_OOB 64 // Out-of-band data (NAND flash)
-#define MTD_ECC 128 // Device capable of automatic ECC
-
-// Some common devices / combinations of capabilities
-#define MTD_CAP_ROM 0
-#define MTD_CAP_RAM (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
-#define MTD_CAP_NORFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE)
-#define MTD_CAP_NANDFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB)
-#define MTD_WRITEABLE (MTD_CLEAR_BITS|MTD_SET_BITS)
-
-
-// Types of automatic ECC/Checksum available
-#define MTD_ECC_NONE 0 // No automatic ECC available
-#define MTD_ECC_RS_DiskOnChip 1 // Automatic ECC on DiskOnChip
-#define MTD_ECC_SW 2 // SW ECC for Toshiba & Samsung devices
-
-struct mtd_info_user {
- u_char type;
- 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)
-#define MEMERASE _IOW('M', 2, struct erase_info_user)
-#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
-#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)
-#define MEMREADDATA _IOWR('M', 9, struct mtd_oob_buf)
-#define MEMWRITEDATA _IOWR('M', 10, struct mtd_oob_buf)
-
-#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 */
-
-
-#else /* __KERNEL__ */
-
-
#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;
@@ -150,45 +72,75 @@ struct mtd_info {
u_int32_t ecctype;
u_int32_t eccsize;
+ /*
+ * Reuse some of the above unused fields in the case of NOR flash
+ * with configurable programming regions to avoid modifying the
+ * user visible structure layout/size. Only valid when the
+ * MTD_PROGRAM_REGIONS flag is set.
+ * (Maybe we should have an union for those?)
+ */
+#define MTD_PROGREGION_SIZE(mtd) (mtd)->oobblock
+#define MTD_PROGREGION_CTRLMODE_VALID(mtd) (mtd)->oobsize
+#define MTD_PROGREGION_CTRLMODE_INVALID(mtd) (mtd)->ecctype
+
// 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;
+ u_int32_t oobavail; // Number of bytes in OOB area available for fs
+
/* Data for variable erase regions. If numeraseregions is zero,
- * it means that the whole device has erasesize as given above.
+ * it means that the whole device has erasesize as given above.
*/
int numeraseregions;
- struct mtd_erase_region_info *eraseregions;
+ 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);
/* 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);
+ 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);
- int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf);
+ 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);
- /* iovec-based read/write methods. We need these especially for NAND flash,
+ /*
+ * 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 (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
+ int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+ int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
+ int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+ int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+ int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
+
+ /* 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
+ NB: The 'count' parameter is the number of _vectors_, each of
which contains an (ofs, len) tuple.
*/
- int (*readv) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, size_t *retlen);
- int (*writev) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen);
+ 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);
@@ -201,7 +153,16 @@ struct mtd_info {
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);
+
+ struct notifier_block reboot_notifier; /* default mode before reboot */
+
void *priv;
+
+ struct module *owner;
+ int usecount;
};
@@ -210,39 +171,27 @@ struct mtd_info {
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);
-
-static inline struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
-{
- struct mtd_info *ret;
-
- ret = __get_mtd_device(mtd, num);
-
- if (ret && ret->module && !try_inc_mod_count(ret->module))
- return NULL;
+extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
- return ret;
-}
-
-static inline void put_mtd_device(struct mtd_info *mtd)
-{
- if (mtd->module)
- __MOD_DEC_USE_COUNT(mtd->module);
-}
+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 mtd_notifier *next;
+ 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);
-#ifndef MTDC
#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)
@@ -254,8 +203,18 @@ extern int unregister_mtd_user (struct mtd_notifier *old);
#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)
-#endif /* MTDC */
+#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
@@ -266,14 +225,14 @@ extern int unregister_mtd_user (struct mtd_notifier *old);
#define MTD_DEBUG_LEVEL3 (3) /* Noisy */
#ifdef CONFIG_MTD_DEBUG
-#define DEBUG(n, args...) \
- if (n <= CONFIG_MTD_DEBUG_VERBOSE) { \
- printk(KERN_INFO args); \
- }
+#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...)
-#endif /* CONFIG_MTD_DEBUG */
+#define DEBUG(n, args...) do { } while(0)
-#endif /* __KERNEL__ */
+#endif /* CONFIG_MTD_DEBUG */
#endif /* __MTD_MTD_H__ */
diff --git a/linux-2.4.x/include/linux/mtd/nand.h b/linux-2.4.x/include/linux/mtd/nand.h
index 8c678ab..5127728 100644
--- a/linux-2.4.x/include/linux/mtd/nand.h
+++ b/linux-2.4.x/include/linux/mtd/nand.h
@@ -2,9 +2,10 @@
* linux/include/linux/mtd/nand.h
*
* Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
- * Steven J. Hill <sjhill@cotw.com>
+ * Steven J. Hill <sjhill@realitydiluted.com>
+ * Thomas Gleixner <tglx@linutronix.de>
*
- * $Id: nand.h,v 1.8 2000/10/30 17:16:17 sjhill Exp $
+ * $Id: nand.h,v 1.77 2005/12/16 15:41:33 vwool 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
@@ -23,17 +24,83 @@
* 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
+ * 01-17-2005 dmarlin added extended commands for AG-AND device and added option
+ * for BBT_AUTO_REFRESH.
+ * 01-20-2005 dmarlin added optional pointer to hardware specific callback for
+ * extra error status checks.
+ *
+ * 11-01-2005 vwool NAND page layouts introduces for HW ECC handling
*/
#ifndef __LINUX_MTD_NAND_H
#define __LINUX_MTD_NAND_H
#include <linux/config.h>
-#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/mtd/mtd.h>
-/*
- * Searches for a NAND device
+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.
*/
-extern int nand_scan (struct mtd_info *mtd);
+#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
@@ -44,12 +111,148 @@ extern int nand_scan (struct mtd_info *mtd);
#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
+
+/* Extended commands for AG-AND device */
+/*
+ * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but
+ * there is no way to distinguish that from NAND_CMD_READ0
+ * until the remaining sequence of commands has been completed
+ * so add a high order bit and mask it off in the command.
+ */
+#define NAND_CMD_DEPLETE1 0x100
+#define NAND_CMD_DEPLETE2 0x38
+#define NAND_CMD_STATUS_MULTI 0x71
+#define NAND_CMD_STATUS_ERROR 0x72
+/* multi-bank error status (banks 0-3) */
+#define NAND_CMD_STATUS_ERROR0 0x73
+#define NAND_CMD_STATUS_ERROR1 0x74
+#define NAND_CMD_STATUS_ERROR2 0x75
+#define NAND_CMD_STATUS_ERROR3 0x76
+#define NAND_CMD_STATUS_RESET 0x7f
+#define NAND_CMD_STATUS_CLEAR 0xff
+
+/* 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 6 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
+
+struct page_layout_item {
+ int length;
+ enum {
+ ITEM_TYPE_DATA,
+ ITEM_TYPE_OOB,
+ ITEM_TYPE_ECC,
+ } type;
+};
+
+/*
+ * 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
+#define NAND_ECC_WRITESYN 3
+#define NAND_ECC_READOOB 4
+#define NAND_ECC_WRITEOOB 5
+
+/* Bit mask for flags passed to do_nand_read_ecc */
+#define NAND_GET_DEVICE 0x80
+
+
+/* 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
+/* Chip requires that BBT is periodically rewritten to prevent
+ * bits from adjacent blocks from 'leaking' in altering data.
+ * This happens with the Renesas AG-AND chips, possibly others. */
+#define BBT_AUTO_REFRESH 0x00000080
+
+/* 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
+/* This option skips the bbt scan during initialization. */
+#define NAND_SKIP_BBTSCAN 0x00040000
+/* This option specifies that a whole NAND page is to be written in
+ * nand_write_oob. This is needed for some HW ECC generators that need a
+ * whole page to be written to generate ECC properly */
+#define NAND_COMPLEX_OOB_WRITE 0x00080000
+
+/* 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 {
@@ -57,55 +260,143 @@ typedef enum {
FL_READING,
FL_WRITING,
FL_ERASING,
- FL_SYNCING
+ FL_SYNCING,
+ FL_CACHEDPRG,
+ FL_PM_SUSPENDED,
} nand_state_t;
-/*
- * NAND Private Flash Chip Data
- *
- * Structure overview:
- *
- * IO_ADDR - address to access the 8 I/O lines to the flash device
- *
- * CTRL_ADDR - address where ALE, CLE and CE control bits are accessed
- *
- * CLE - location in control word for Command Latch Enable bit
- *
- * ALE - location in control word for Address Latch Enable bit
- *
- * NCE - location in control word for nChip Enable bit
- *
- * chip_lock - spinlock used to protect access to this structure
- *
- * wq - wait queue to sleep on if a NAND operation is in progress
- *
- * state - give the current state of the NAND device
- *
- * page_shift - number of address bits in a page (column address bits)
- *
- * data_buf - data buffer passed to/from MTD user modules
- *
- * ecc_code_buf - used only for holding calculated or read ECCs for
- * a page read or written when ECC is in use
- *
- * reserved - padding to make structure fall on word boundary if
- * when ECC is in use
+/* 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
+ * @wq: wait queue to sleep on if a NAND operation is in progress
+ * used instead of the per chip wait queue when a hw controller is available
+ */
+struct nand_hw_control {
+ spinlock_t lock;
+ struct nand_chip *active;
+ wait_queue_head_t wq;
+};
+
+/**
+ * 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
+ * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks
+ * (determine if errors are correctable)
*/
+
struct nand_chip {
- unsigned long IO_ADDR;
- unsigned long CTRL_ADDR;
- unsigned int CLE;
- unsigned int ALE;
- unsigned int NCE;
- spinlock_t chip_lock;
+ 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;
- u_char *data_buf;
-#ifdef CONFIG_MTD_NAND_ECC
- u_char ecc_code_buf[6];
- u_char reserved[2];
-#endif
+ 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;
+ struct page_layout_item *layout;
+ int layout_allocated;
+ 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;
+ int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
};
/*
@@ -113,42 +404,129 @@ struct nand_chip {
*/
#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
+#define NAND_MFR_HYNIX 0xad
-/*
- * NAND Flash Device ID Structure
- *
- * Structure overview:
- *
- * name - Complete name of device
- *
- * manufacture_id - manufacturer ID code of device.
+/**
+ * struct nand_flash_dev - NAND Flash Device ID Structure
*
- * model_id - model ID code of device.
- *
- * chipshift - total number of address bits for the device which
- * is used to calculate address offsets and the total
- * number of bytes the device is capable of.
- *
- * page256 - denotes if flash device has 256 byte pages or not.
- *
- * pageadrlen - number of bytes minus one needed to hold the
- * complete address into the flash array. Keep in
- * mind that when a read or write is done to a
- * specific address, the address is input serially
- * 8 bits at a time. This structure member is used
- * by the read/write routines as a loop index for
- * shifting the address out 8 bits at a time.
- *
- * erasesize - size of an erase block in the flash device.
+ * @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 manufacture_id;
- int model_id;
- int chipshift;
- char page256;
- char pageadrlen;
+ 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);
+extern int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf, u_char * oob_buf,
+ struct nand_oobinfo *oobsel, int flags);
+
+/*
+* Constants for oob configuration
+*/
+#define NAND_SMALL_BADBLOCK_POS 5
+#define NAND_LARGE_BADBLOCK_POS 0
+
#endif /* __LINUX_MTD_NAND_H */
diff --git a/linux-2.4.x/include/linux/mtd/nand_ecc.h b/linux-2.4.x/include/linux/mtd/nand_ecc.h
index f3f1d7e..12c5bc3 100644
--- a/linux-2.4.x/include/linux/mtd/nand_ecc.h
+++ b/linux-2.4.x/include/linux/mtd/nand_ecc.h
@@ -1,9 +1,9 @@
/*
* drivers/mtd/nand_ecc.h
*
- * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
*
- * $Id: nand_ecc.h,v 1.1 2000/10/12 00:57:15 sjhill Exp $
+ * $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
@@ -12,17 +12,19 @@
* 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);
+#ifndef __MTD_NAND_ECC_H__
+#define __MTD_NAND_ECC_H__
+
+struct mtd_info;
/*
* Calculate 3 byte ECC code for 256 byte block
*/
-void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
+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 (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
+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/linux-2.4.x/include/linux/mtd/nftl.h b/linux-2.4.x/include/linux/mtd/nftl.h
index 3483a8c..d35d2c2 100644
--- a/linux-2.4.x/include/linux/mtd/nftl.h
+++ b/linux-2.4.x/include/linux/mtd/nftl.h
@@ -1,81 +1,16 @@
-
-/* Defines for NAND Flash Translation Layer */
-/* (c) 1999 Machine Vision Holdings, Inc. */
-/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: nftl.h,v 1.10 2000/12/29 00:25:38 dwmw2 Exp $ */
+/*
+ * $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__
-#ifndef __BOOT__
#include <linux/mtd/mtd.h>
-#endif
-
-/* Block Control Information */
-
-struct nftl_bci {
- unsigned char ECCSig[6];
- __u8 Status;
- __u8 Status1;
-}__attribute__((packed));
-
-/* Unit Control Information */
+#include <linux/mtd/blktrans.h>
-struct nftl_uci0 {
- __u16 VirtUnitNum;
- __u16 ReplUnitNum;
- __u16 SpareVirtUnitNum;
- __u16 SpareReplUnitNum;
-} __attribute__((packed));
-
-struct nftl_uci1 {
- __u32 WearInfo;
- __u16 EraseMark;
- __u16 EraseMark1;
-} __attribute__((packed));
-
-struct nftl_uci2 {
- __u16 FoldMark;
- __u16 FoldMark1;
- __u32 unused;
-} __attribute__((packed));
-
-union nftl_uci {
- struct nftl_uci0 a;
- struct nftl_uci1 b;
- struct nftl_uci2 c;
-};
-
-struct nftl_oob {
- struct nftl_bci b;
- union nftl_uci u;
-};
-
-/* NFTL Media Header */
-
-struct NFTLMediaHeader {
- char DataOrgID[6];
- __u16 NumEraseUnits;
- __u16 FirstPhysicalEUN;
- __u32 FormattedSize;
- unsigned char UnitSizeFactor;
-} __attribute__((packed));
-
-#define MAX_ERASE_ZONES (8192 - 512)
-
-#define ERASE_MARK 0x3c69
-#define SECTOR_FREE 0xff
-#define SECTOR_USED 0x55
-#define SECTOR_IGNORE 0x11
-#define SECTOR_DELETED 0x00
-
-#define FOLD_MARK_IN_PROGRESS 0x5555
-
-#define ZONE_GOOD 0xff
-#define ZONE_BAD_ORIGINAL 0
-#define ZONE_BAD_MARKED 7
-
-#ifdef __KERNEL__
+#include <mtd/nftl-user.h>
/* these info are used in ReplUnitTable */
#define BLOCK_NIL 0xffff /* last block of a chain */
@@ -84,8 +19,7 @@ struct NFTLMediaHeader {
#define BLOCK_RESERVED 0xfffc /* bios block or bad block */
struct NFTLrecord {
- struct mtd_info *mtd;
- struct semaphore mutex;
+ struct mtd_blktrans_dev mbd;
__u16 MediaUnit, SpareMediaUnit;
__u32 EraseSize;
struct NFTLMediaHeader MediaHdr;
@@ -97,13 +31,13 @@ struct NFTLrecord {
__u16 lastEUN; /* should be suppressed */
__u16 numfreeEUNs;
__u16 LastFreeEUN; /* To speed up finding a free EUN */
- __u32 long nr_sects;
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);
@@ -114,9 +48,7 @@ int NFTL_formatblock(struct NFTLrecord *s, int block);
#endif
#define MAX_NFTLS 16
-#define MAX_SECTORS_PER_UNIT 32
+#define MAX_SECTORS_PER_UNIT 64
#define NFTL_PARTN_BITS 4
-#endif /* __KERNEL__ */
-
#endif /* __MTD_NFTL_H__ */
diff --git a/linux-2.4.x/include/linux/mtd/onenand.h b/linux-2.4.x/include/linux/mtd/onenand.h
new file mode 100644
index 0000000..d259e0a
--- /dev/null
+++ b/linux-2.4.x/include/linux/mtd/onenand.h
@@ -0,0 +1,161 @@
+/*
+ * linux/include/linux/mtd/onenand.h
+ *
+ * Copyright (C) 2005 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * $Id: onenand.h,v 1.13 2006/02/22 00:26:38 kmpark 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.
+ */
+
+#ifndef __LINUX_MTD_ONENAND_H
+#define __LINUX_MTD_ONENAND_H
+
+#include <linux/spinlock.h>
+#include <linux/mtd/onenand_regs.h>
+#include <linux/mtd/bbm.h>
+
+#define MAX_BUFFERRAM 2
+
+/* Scan and identify a OneNAND device */
+extern int onenand_scan(struct mtd_info *mtd, int max_chips);
+/* Free resources held by the OneNAND device */
+extern void onenand_release(struct mtd_info *mtd);
+
+/**
+ * onenand_state_t - chip states
+ * Enumeration for OneNAND flash chip state
+ */
+typedef enum {
+ FL_READY,
+ FL_READING,
+ FL_WRITING,
+ FL_ERASING,
+ FL_SYNCING,
+ FL_UNLOCKING,
+ FL_LOCKING,
+ FL_RESETING,
+ FL_OTPING,
+ FL_PM_SUSPENDED,
+} onenand_state_t;
+
+/**
+ * struct onenand_bufferram - OneNAND BufferRAM Data
+ * @param block block address in BufferRAM
+ * @param page page address in BufferRAM
+ * @param valid valid flag
+ */
+struct onenand_bufferram {
+ int block;
+ int page;
+ int valid;
+};
+
+/**
+ * struct onenand_chip - OneNAND Private Flash Chip Data
+ * @param base [BOARDSPECIFIC] address to access OneNAND
+ * @param chipsize [INTERN] the size of one chip for multichip arrays
+ * @param device_id [INTERN] device ID
+ * @param verstion_id [INTERN] version ID
+ * @param options [BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about
+ * @param erase_shift [INTERN] number of address bits in a block
+ * @param page_shift [INTERN] number of address bits in a page
+ * @param ppb_shift [INTERN] number of address bits in a pages per block
+ * @param page_mask [INTERN] a page per block mask
+ * @param bufferam_index [INTERN] BufferRAM index
+ * @param bufferam [INTERN] BufferRAM info
+ * @param readw [REPLACEABLE] hardware specific function for read short
+ * @param writew [REPLACEABLE] hardware specific function for write short
+ * @param command [REPLACEABLE] hardware specific function for writing commands to the chip
+ * @param wait [REPLACEABLE] hardware specific function for wait on ready
+ * @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area
+ * @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area
+ * @param read_word [REPLACEABLE] hardware specific function for read register of OneNAND
+ * @param write_word [REPLACEABLE] hardware specific function for write register of OneNAND
+ * @param scan_bbt [REPLACEALBE] hardware specific function for scaning Bad block Table
+ * @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip
+ * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress
+ * @param state [INTERN] the current state of the OneNAND device
+ * @param autooob [REPLACEABLE] the default (auto)placement scheme
+ * @param bbm [REPLACEABLE] pointer to Bad Block Management
+ * @param priv [OPTIONAL] pointer to private chip date
+ */
+struct onenand_chip {
+ void __iomem *base;
+ unsigned int chipsize;
+ unsigned int device_id;
+ unsigned int density_mask;
+ unsigned int options;
+
+ unsigned int erase_shift;
+ unsigned int page_shift;
+ unsigned int ppb_shift; /* Pages per block shift */
+ unsigned int page_mask;
+
+ unsigned int bufferram_index;
+ struct onenand_bufferram bufferram[MAX_BUFFERRAM];
+
+ int (*command)(struct mtd_info *mtd, int cmd, loff_t address, size_t len);
+ int (*wait)(struct mtd_info *mtd, int state);
+ int (*read_bufferram)(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset, size_t count);
+ int (*write_bufferram)(struct mtd_info *mtd, int area,
+ const unsigned char *buffer, int offset, size_t count);
+ unsigned short (*read_word)(void __iomem *addr);
+ void (*write_word)(unsigned short value, void __iomem *addr);
+ void (*mmcontrol)(struct mtd_info *mtd, int sync_read);
+ int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
+ int (*scan_bbt)(struct mtd_info *mtd);
+
+ spinlock_t chip_lock;
+ wait_queue_head_t wq;
+ onenand_state_t state;
+ unsigned char *page_buf;
+
+ struct nand_oobinfo *autooob;
+
+ void *bbm;
+
+ void *priv;
+};
+
+/*
+ * Helper macros
+ */
+#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index)
+#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
+#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
+
+#define ONENAND_GET_SYS_CFG1(this) \
+ (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
+#define ONENAND_SET_SYS_CFG1(v, this) \
+ (this->write_word(v, this->base + ONENAND_REG_SYS_CFG1))
+
+/* Check byte access in OneNAND */
+#define ONENAND_CHECK_BYTE_ACCESS(addr) (addr & 0x1)
+
+/*
+ * Options bits
+ */
+#define ONENAND_CONT_LOCK (0x0001)
+#define ONENAND_PAGEBUF_ALLOC (0x1000)
+
+/*
+ * OneNAND Flash Manufacturer ID Codes
+ */
+#define ONENAND_MFR_SAMSUNG 0xec
+
+/**
+ * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
+ * @param name: Manufacturer name
+ * @param id: manufacturer ID code of device.
+*/
+struct onenand_manufacturers {
+ int id;
+ char *name;
+};
+
+#endif /* __LINUX_MTD_ONENAND_H */
diff --git a/linux-2.4.x/include/linux/mtd/onenand_regs.h b/linux-2.4.x/include/linux/mtd/onenand_regs.h
new file mode 100644
index 0000000..32dacb4
--- /dev/null
+++ b/linux-2.4.x/include/linux/mtd/onenand_regs.h
@@ -0,0 +1,190 @@
+/*
+ * linux/include/linux/mtd/onenand_regs.h
+ *
+ * OneNAND Register header file
+ *
+ * Copyright (C) 2005 Samsung Electronics
+ *
+ * $Id: onenand_regs.h,v 1.4 2006/02/22 00:26:38 kmpark 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.
+ */
+
+#ifndef __ONENAND_REG_H
+#define __ONENAND_REG_H
+
+/* Memory Address Map Translation (Word order) */
+#define ONENAND_MEMORY_MAP(x) ((x) << 1)
+
+/*
+ * External BufferRAM area
+ */
+#define ONENAND_BOOTRAM ONENAND_MEMORY_MAP(0x0000)
+#define ONENAND_DATARAM ONENAND_MEMORY_MAP(0x0200)
+#define ONENAND_SPARERAM ONENAND_MEMORY_MAP(0x8010)
+
+/*
+ * OneNAND Registers
+ */
+#define ONENAND_REG_MANUFACTURER_ID ONENAND_MEMORY_MAP(0xF000)
+#define ONENAND_REG_DEVICE_ID ONENAND_MEMORY_MAP(0xF001)
+#define ONENAND_REG_VERSION_ID ONENAND_MEMORY_MAP(0xF002)
+#define ONENAND_REG_DATA_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF003)
+#define ONENAND_REG_BOOT_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF004)
+#define ONENAND_REG_NUM_BUFFERS ONENAND_MEMORY_MAP(0xF005)
+#define ONENAND_REG_TECHNOLOGY ONENAND_MEMORY_MAP(0xF006)
+
+#define ONENAND_REG_START_ADDRESS1 ONENAND_MEMORY_MAP(0xF100)
+#define ONENAND_REG_START_ADDRESS2 ONENAND_MEMORY_MAP(0xF101)
+#define ONENAND_REG_START_ADDRESS3 ONENAND_MEMORY_MAP(0xF102)
+#define ONENAND_REG_START_ADDRESS4 ONENAND_MEMORY_MAP(0xF103)
+#define ONENAND_REG_START_ADDRESS5 ONENAND_MEMORY_MAP(0xF104)
+#define ONENAND_REG_START_ADDRESS6 ONENAND_MEMORY_MAP(0xF105)
+#define ONENAND_REG_START_ADDRESS7 ONENAND_MEMORY_MAP(0xF106)
+#define ONENAND_REG_START_ADDRESS8 ONENAND_MEMORY_MAP(0xF107)
+
+#define ONENAND_REG_START_BUFFER ONENAND_MEMORY_MAP(0xF200)
+#define ONENAND_REG_COMMAND ONENAND_MEMORY_MAP(0xF220)
+#define ONENAND_REG_SYS_CFG1 ONENAND_MEMORY_MAP(0xF221)
+#define ONENAND_REG_SYS_CFG2 ONENAND_MEMORY_MAP(0xF222)
+#define ONENAND_REG_CTRL_STATUS ONENAND_MEMORY_MAP(0xF240)
+#define ONENAND_REG_INTERRUPT ONENAND_MEMORY_MAP(0xF241)
+#define ONENAND_REG_START_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24C)
+#define ONENAND_REG_END_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24D)
+#define ONENAND_REG_WP_STATUS ONENAND_MEMORY_MAP(0xF24E)
+
+#define ONENAND_REG_ECC_STATUS ONENAND_MEMORY_MAP(0xFF00)
+#define ONENAND_REG_ECC_M0 ONENAND_MEMORY_MAP(0xFF01)
+#define ONENAND_REG_ECC_S0 ONENAND_MEMORY_MAP(0xFF02)
+#define ONENAND_REG_ECC_M1 ONENAND_MEMORY_MAP(0xFF03)
+#define ONENAND_REG_ECC_S1 ONENAND_MEMORY_MAP(0xFF04)
+#define ONENAND_REG_ECC_M2 ONENAND_MEMORY_MAP(0xFF05)
+#define ONENAND_REG_ECC_S2 ONENAND_MEMORY_MAP(0xFF06)
+#define ONENAND_REG_ECC_M3 ONENAND_MEMORY_MAP(0xFF07)
+#define ONENAND_REG_ECC_S3 ONENAND_MEMORY_MAP(0xFF08)
+
+/*
+ * Device ID Register F001h (R)
+ */
+#define ONENAND_DEVICE_DENSITY_SHIFT (4)
+#define ONENAND_DEVICE_IS_DDP (1 << 3)
+#define ONENAND_DEVICE_IS_DEMUX (1 << 2)
+#define ONENAND_DEVICE_VCC_MASK (0x3)
+
+#define ONENAND_DEVICE_DENSITY_512Mb (0x002)
+
+/*
+ * Version ID Register F002h (R)
+ */
+#define ONENAND_VERSION_PROCESS_SHIFT (8)
+
+/*
+ * Start Address 1 F100h (R/W)
+ */
+#define ONENAND_DDP_SHIFT (15)
+
+/*
+ * Start Address 8 F107h (R/W)
+ */
+#define ONENAND_FPA_MASK (0x3f)
+#define ONENAND_FPA_SHIFT (2)
+#define ONENAND_FSA_MASK (0x03)
+
+/*
+ * Start Buffer Register F200h (R/W)
+ */
+#define ONENAND_BSA_MASK (0x03)
+#define ONENAND_BSA_SHIFT (8)
+#define ONENAND_BSA_BOOTRAM (0 << 2)
+#define ONENAND_BSA_DATARAM0 (2 << 2)
+#define ONENAND_BSA_DATARAM1 (3 << 2)
+#define ONENAND_BSC_MASK (0x03)
+
+/*
+ * Command Register F220h (R/W)
+ */
+#define ONENAND_CMD_READ (0x00)
+#define ONENAND_CMD_READOOB (0x13)
+#define ONENAND_CMD_PROG (0x80)
+#define ONENAND_CMD_PROGOOB (0x1A)
+#define ONENAND_CMD_UNLOCK (0x23)
+#define ONENAND_CMD_LOCK (0x2A)
+#define ONENAND_CMD_LOCK_TIGHT (0x2C)
+#define ONENAND_CMD_ERASE (0x94)
+#define ONENAND_CMD_RESET (0xF0)
+#define ONENAND_CMD_OTP_ACCESS (0x65)
+#define ONENAND_CMD_READID (0x90)
+
+/* NOTE: Those are not *REAL* commands */
+#define ONENAND_CMD_BUFFERRAM (0x1978)
+
+/*
+ * System Configuration 1 Register F221h (R, R/W)
+ */
+#define ONENAND_SYS_CFG1_SYNC_READ (1 << 15)
+#define ONENAND_SYS_CFG1_BRL_7 (7 << 12)
+#define ONENAND_SYS_CFG1_BRL_6 (6 << 12)
+#define ONENAND_SYS_CFG1_BRL_5 (5 << 12)
+#define ONENAND_SYS_CFG1_BRL_4 (4 << 12)
+#define ONENAND_SYS_CFG1_BRL_3 (3 << 12)
+#define ONENAND_SYS_CFG1_BRL_10 (2 << 12)
+#define ONENAND_SYS_CFG1_BRL_9 (1 << 12)
+#define ONENAND_SYS_CFG1_BRL_8 (0 << 12)
+#define ONENAND_SYS_CFG1_BRL_SHIFT (12)
+#define ONENAND_SYS_CFG1_BL_32 (4 << 9)
+#define ONENAND_SYS_CFG1_BL_16 (3 << 9)
+#define ONENAND_SYS_CFG1_BL_8 (2 << 9)
+#define ONENAND_SYS_CFG1_BL_4 (1 << 9)
+#define ONENAND_SYS_CFG1_BL_CONT (0 << 9)
+#define ONENAND_SYS_CFG1_BL_SHIFT (9)
+#define ONENAND_SYS_CFG1_NO_ECC (1 << 8)
+#define ONENAND_SYS_CFG1_RDY (1 << 7)
+#define ONENAND_SYS_CFG1_INT (1 << 6)
+#define ONENAND_SYS_CFG1_IOBE (1 << 5)
+#define ONENAND_SYS_CFG1_RDY_CONF (1 << 4)
+
+/*
+ * Controller Status Register F240h (R)
+ */
+#define ONENAND_CTRL_ONGO (1 << 15)
+#define ONENAND_CTRL_LOCK (1 << 14)
+#define ONENAND_CTRL_LOAD (1 << 13)
+#define ONENAND_CTRL_PROGRAM (1 << 12)
+#define ONENAND_CTRL_ERASE (1 << 11)
+#define ONENAND_CTRL_ERROR (1 << 10)
+#define ONENAND_CTRL_RSTB (1 << 7)
+#define ONENAND_CTRL_OTP_L (1 << 6)
+#define ONENAND_CTRL_OTP_BL (1 << 5)
+
+/*
+ * Interrupt Status Register F241h (R)
+ */
+#define ONENAND_INT_MASTER (1 << 15)
+#define ONENAND_INT_READ (1 << 7)
+#define ONENAND_INT_WRITE (1 << 6)
+#define ONENAND_INT_ERASE (1 << 5)
+#define ONENAND_INT_RESET (1 << 4)
+#define ONENAND_INT_CLEAR (0 << 0)
+
+/*
+ * NAND Flash Write Protection Status Register F24Eh (R)
+ */
+#define ONENAND_WP_US (1 << 2)
+#define ONENAND_WP_LS (1 << 1)
+#define ONENAND_WP_LTS (1 << 0)
+
+/*
+ * ECC Status Reigser FF00h (R)
+ */
+#define ONENAND_ECC_1BIT (1 << 0)
+#define ONENAND_ECC_2BIT (1 << 1)
+#define ONENAND_ECC_2BIT_ALL (0xAAAA)
+
+/*
+ * One-Time Programmable (OTP)
+ */
+#define ONENAND_OTP_LOCK_OFFSET (14)
+
+#endif /* __ONENAND_REG_H */
diff --git a/linux-2.4.x/include/linux/mtd/partitions.h b/linux-2.4.x/include/linux/mtd/partitions.h
index 7c55241..b03f512 100644
--- a/linux-2.4.x/include/linux/mtd/partitions.h
+++ b/linux-2.4.x/include/linux/mtd/partitions.h
@@ -5,7 +5,7 @@
*
* This code is GPL
*
- * $Id: partitions.h,v 1.8 2002/03/08 16:34:36 rkaiser Exp $
+ * $Id: partitions.h,v 1.17 2005/11/07 11:14:55 gleixner Exp $
*/
#ifndef MTD_PARTITIONS_H
@@ -16,32 +16,33 @@
/*
* 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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 */
+ 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 mtd_info **mtdp; /* pointer to store the MTD object */
+ 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)
@@ -49,8 +50,26 @@ struct mtd_partition {
#define MTDPART_SIZ_FULL (0)
-int add_mtd_partitions(struct mtd_info *, struct mtd_partition *, int);
+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/linux-2.4.x/include/linux/mtd/physmap.h b/linux-2.4.x/include/linux/mtd/physmap.h
new file mode 100644
index 0000000..c7b8bcd
--- /dev/null
+++ b/linux-2.4.x/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.4 2005/11/07 11:14:55 gleixner 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/linux-2.4.x/include/linux/mtd/plat-ram.h b/linux-2.4.x/include/linux/mtd/plat-ram.h
new file mode 100644
index 0000000..2332eda
--- /dev/null
+++ b/linux-2.4.x/include/linux/mtd/plat-ram.h
@@ -0,0 +1,35 @@
+/* linux/include/mtd/plat-ram.h
+ *
+ * (c) 2004 Simtec Electronics
+ * http://www.simtec.co.uk/products/SWLINUX/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Generic platform device based RAM map
+ *
+ * $Id: plat-ram.h,v 1.2 2005/01/24 00:37:40 bjd 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.
+ *
+ */
+
+#ifndef __LINUX_MTD_PLATRAM_H
+#define __LINUX_MTD_PLATRAM_H __FILE__
+
+#define PLATRAM_RO (0)
+#define PLATRAM_RW (1)
+
+struct platdata_mtd_ram {
+ char *mapname;
+ char **probes;
+ struct mtd_partition *partitions;
+ int nr_partitions;
+ int bankwidth;
+
+ /* control callbacks */
+
+ void (*set_rw)(struct device *dev, int to);
+};
+
+#endif /* __LINUX_MTD_PLATRAM_H */
diff --git a/linux-2.4.x/include/linux/mtd/pmc551.h b/linux-2.4.x/include/linux/mtd/pmc551.h
index 640d3eb..a7f6d20 100644
--- a/linux-2.4.x/include/linux/mtd/pmc551.h
+++ b/linux-2.4.x/include/linux/mtd/pmc551.h
@@ -1,5 +1,5 @@
/*
- * $Id: pmc551.h,v 1.4 2001/06/12 16:19:38 major Exp $
+ * $Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $
*
* PMC551 PCI Mezzanine Ram Device
*
@@ -7,7 +7,7 @@
* Mark Ferrell
* Copyright 1999,2000 Nortel Networks
*
- * License:
+ * 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
*/
@@ -17,7 +17,7 @@
#include <linux/mtd/mtd.h>
-#define PMC551_VERSION "$Id: pmc551.h,v 1.4 2001/06/12 16:19:38 major Exp $\n"\
+#define PMC551_VERSION "$Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $\n"\
"Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
/*
@@ -30,16 +30,16 @@ struct mypriv {
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 *);
+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 *);
+static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
/*
@@ -50,7 +50,7 @@ static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_cha
#endif
#ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC
-#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200
+#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200
#endif
diff --git a/linux-2.4.x/include/linux/mtd/xip.h b/linux-2.4.x/include/linux/mtd/xip.h
new file mode 100644
index 0000000..220d50b
--- /dev/null
+++ b/linux-2.4.x/include/linux/mtd/xip.h
@@ -0,0 +1,102 @@
+/*
+ * 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.5 2005/11/07 11:14:55 gleixner Exp $
+ */
+
+#ifndef __LINUX_MTD_XIP_H__
+#define __LINUX_MTD_XIP_H__
+
+#include <linux/config.h>
+
+#ifdef CONFIG_MTD_XIP
+
+/*
+ * We really don't want gcc to guess anything.
+ * We absolutely _need_ proper inlining.
+ */
+#include <linux/compiler.h>
+
+/*
+ * 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 noinline __attribute__ ((__section__ (".data")))
+
+/*
+ * 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.
+ *
+ * xip_iprefetch()
+ *
+ * Macro to fill instruction prefetch
+ * e.g. a series of nops: asm volatile (".rep 8; nop; .endr");
+ */
+
+#include <asm/mtd-xip.h>
+
+#ifndef xip_irqpending
+
+#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
+
+#ifndef xip_iprefetch
+#define xip_iprefetch() do { } while (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.
+ * This should not rely upon standard kernel code.
+ */
+#ifndef xip_cpu_idle
+#define xip_cpu_idle() do { } while (0)
+#endif
+
+#else
+
+#define __xipram
+
+#endif /* CONFIG_MTD_XIP */
+
+#endif /* __LINUX_MTD_XIP_H__ */