Linux-2.6.12-rc2

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

Let it rip!
This commit is contained in:
Linus Torvalds
2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
/*
* $Id: blktrans.h,v 1.5 2003/06/23 12:00:08 dwmw2 Exp $
*
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
*
* Interface to Linux block layer for MTD 'translation layers'.
*
*/
#ifndef __MTD_TRANS_H__
#define __MTD_TRANS_H__
#include <asm/semaphore.h>
struct hd_geometry;
struct mtd_info;
struct mtd_blktrans_ops;
struct file;
struct inode;
struct mtd_blktrans_dev {
struct mtd_blktrans_ops *tr;
struct list_head list;
struct mtd_info *mtd;
struct semaphore sem;
int devnum;
int blksize;
unsigned long size;
int readonly;
void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */
};
struct blkcore_priv; /* Differs for 2.4 and 2.5 kernels; private */
struct mtd_blktrans_ops {
char *name;
int major;
int part_bits;
/* Access functions */
int (*readsect)(struct mtd_blktrans_dev *dev,
unsigned long block, char *buffer);
int (*writesect)(struct mtd_blktrans_dev *dev,
unsigned long block, char *buffer);
/* Block layer ioctls */
int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
int (*flush)(struct mtd_blktrans_dev *dev);
/* Called with mtd_table_mutex held; no race with add/remove */
int (*open)(struct mtd_blktrans_dev *dev);
int (*release)(struct mtd_blktrans_dev *dev);
/* Called on {de,}registration and on subsequent addition/removal
of devices, with mtd_table_mutex held. */
void (*add_mtd)(struct mtd_blktrans_ops *tr, struct mtd_info *mtd);
void (*remove_dev)(struct mtd_blktrans_dev *dev);
struct list_head devs;
struct list_head list;
struct module *owner;
struct mtd_blkcore_priv *blkcore_priv;
};
extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr);
extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr);
extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
#endif /* __MTD_TRANS_H__ */

394
include/linux/mtd/cfi.h Normal file
View File

@@ -0,0 +1,394 @@
/* Common Flash Interface structures
* See http://support.intel.com/design/flash/technote/index.htm
* $Id: cfi.h,v 1.50 2004/11/20 12:46:51 dwmw2 Exp $
*/
#ifndef __MTD_CFI_H__
#define __MTD_CFI_H__
#include <linux/config.h>
#include <linux/version.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/mtd/flashchip.h>
#include <linux/mtd/map.h>
#include <linux/mtd/cfi_endian.h>
#ifdef CONFIG_MTD_CFI_I1
#define cfi_interleave(cfi) 1
#define cfi_interleave_is_1(cfi) (cfi_interleave(cfi) == 1)
#else
#define cfi_interleave_is_1(cfi) (0)
#endif
#ifdef CONFIG_MTD_CFI_I2
# ifdef cfi_interleave
# undef cfi_interleave
# define cfi_interleave(cfi) ((cfi)->interleave)
# else
# define cfi_interleave(cfi) 2
# endif
#define cfi_interleave_is_2(cfi) (cfi_interleave(cfi) == 2)
#else
#define cfi_interleave_is_2(cfi) (0)
#endif
#ifdef CONFIG_MTD_CFI_I4
# ifdef cfi_interleave
# undef cfi_interleave
# define cfi_interleave(cfi) ((cfi)->interleave)
# else
# define cfi_interleave(cfi) 4
# endif
#define cfi_interleave_is_4(cfi) (cfi_interleave(cfi) == 4)
#else
#define cfi_interleave_is_4(cfi) (0)
#endif
#ifdef CONFIG_MTD_CFI_I8
# ifdef cfi_interleave
# undef cfi_interleave
# define cfi_interleave(cfi) ((cfi)->interleave)
# else
# define cfi_interleave(cfi) 8
# endif
#define cfi_interleave_is_8(cfi) (cfi_interleave(cfi) == 8)
#else
#define cfi_interleave_is_8(cfi) (0)
#endif
static inline int cfi_interleave_supported(int i)
{
switch (i) {
#ifdef CONFIG_MTD_CFI_I1
case 1:
#endif
#ifdef CONFIG_MTD_CFI_I2
case 2:
#endif
#ifdef CONFIG_MTD_CFI_I4
case 4:
#endif
#ifdef CONFIG_MTD_CFI_I8
case 8:
#endif
return 1;
default:
return 0;
}
}
/* NB: these values must represents the number of bytes needed to meet the
* device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes.
* These numbers are used in calculations.
*/
#define CFI_DEVICETYPE_X8 (8 / 8)
#define CFI_DEVICETYPE_X16 (16 / 8)
#define CFI_DEVICETYPE_X32 (32 / 8)
#define CFI_DEVICETYPE_X64 (64 / 8)
/* NB: We keep these structures in memory in HOST byteorder, except
* where individually noted.
*/
/* Basic Query Structure */
struct cfi_ident {
uint8_t qry[3];
uint16_t P_ID;
uint16_t P_ADR;
uint16_t A_ID;
uint16_t A_ADR;
uint8_t VccMin;
uint8_t VccMax;
uint8_t VppMin;
uint8_t VppMax;
uint8_t WordWriteTimeoutTyp;
uint8_t BufWriteTimeoutTyp;
uint8_t BlockEraseTimeoutTyp;
uint8_t ChipEraseTimeoutTyp;
uint8_t WordWriteTimeoutMax;
uint8_t BufWriteTimeoutMax;
uint8_t BlockEraseTimeoutMax;
uint8_t ChipEraseTimeoutMax;
uint8_t DevSize;
uint16_t InterfaceDesc;
uint16_t MaxBufWriteSize;
uint8_t NumEraseRegions;
uint32_t EraseRegionInfo[0]; /* Not host ordered */
} __attribute__((packed));
/* Extended Query Structure for both PRI and ALT */
struct cfi_extquery {
uint8_t pri[3];
uint8_t MajorVersion;
uint8_t MinorVersion;
} __attribute__((packed));
/* Vendor-Specific PRI for Intel/Sharp Extended Command Set (0x0001) */
struct cfi_pri_intelext {
uint8_t pri[3];
uint8_t MajorVersion;
uint8_t MinorVersion;
uint32_t FeatureSupport; /* if bit 31 is set then an additional uint32_t feature
block follows - FIXME - not currently supported */
uint8_t SuspendCmdSupport;
uint16_t BlkStatusRegMask;
uint8_t VccOptimal;
uint8_t VppOptimal;
uint8_t NumProtectionFields;
uint16_t ProtRegAddr;
uint8_t FactProtRegSize;
uint8_t UserProtRegSize;
uint8_t extra[0];
} __attribute__((packed));
struct cfi_intelext_blockinfo {
uint16_t NumIdentBlocks;
uint16_t BlockSize;
uint16_t MinBlockEraseCycles;
uint8_t BitsPerCell;
uint8_t BlockCap;
} __attribute__((packed));
struct cfi_intelext_regioninfo {
uint16_t NumIdentPartitions;
uint8_t NumOpAllowed;
uint8_t NumOpAllowedSimProgMode;
uint8_t NumOpAllowedSimEraMode;
uint8_t NumBlockTypes;
struct cfi_intelext_blockinfo BlockTypes[1];
} __attribute__((packed));
/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */
struct cfi_pri_amdstd {
uint8_t pri[3];
uint8_t MajorVersion;
uint8_t MinorVersion;
uint8_t SiliconRevision; /* bits 1-0: Address Sensitive Unlock */
uint8_t EraseSuspend;
uint8_t BlkProt;
uint8_t TmpBlkUnprotect;
uint8_t BlkProtUnprot;
uint8_t SimultaneousOps;
uint8_t BurstMode;
uint8_t PageMode;
uint8_t VppMin;
uint8_t VppMax;
uint8_t TopBottom;
} __attribute__((packed));
struct cfi_pri_query {
uint8_t NumFields;
uint32_t ProtField[1]; /* Not host ordered */
} __attribute__((packed));
struct cfi_bri_query {
uint8_t PageModeReadCap;
uint8_t NumFields;
uint32_t ConfField[1]; /* Not host ordered */
} __attribute__((packed));
#define P_ID_NONE 0x0000
#define P_ID_INTEL_EXT 0x0001
#define P_ID_AMD_STD 0x0002
#define P_ID_INTEL_STD 0x0003
#define P_ID_AMD_EXT 0x0004
#define P_ID_WINBOND 0x0006
#define P_ID_ST_ADV 0x0020
#define P_ID_MITSUBISHI_STD 0x0100
#define P_ID_MITSUBISHI_EXT 0x0101
#define P_ID_SST_PAGE 0x0102
#define P_ID_INTEL_PERFORMANCE 0x0200
#define P_ID_INTEL_DATA 0x0210
#define P_ID_RESERVED 0xffff
#define CFI_MODE_CFI 1
#define CFI_MODE_JEDEC 0
struct cfi_private {
uint16_t cmdset;
void *cmdset_priv;
int interleave;
int device_type;
int cfi_mode; /* Are we a JEDEC device pretending to be CFI? */
int addr_unlock1;
int addr_unlock2;
struct mtd_info *(*cmdset_setup)(struct map_info *);
struct cfi_ident *cfiq; /* For now only one. We insist that all devs
must be of the same type. */
int mfr, id;
int numchips;
unsigned long chipshift; /* Because they're of the same type */
const char *im_name; /* inter_module name for cmdset_setup */
struct flchip chips[0]; /* per-chip data structure for each chip */
};
/*
* Returns the command address according to the given geometry.
*/
static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type)
{
return (cmd_ofs * type) * interleave;
}
/*
* Transforms the CFI command for the given geometry (bus width & interleave).
* It looks too long to be inline, but in the common case it should almost all
* get optimised away.
*/
static inline map_word cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi)
{
map_word val = { {0} };
int wordwidth, words_per_bus, chip_mode, chips_per_word;
unsigned long onecmd;
int i;
/* We do it this way to give the compiler a fighting chance
of optimising away all the crap for 'bankwidth' larger than
an unsigned long, in the common case where that support is
disabled */
if (map_bankwidth_is_large(map)) {
wordwidth = sizeof(unsigned long);
words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
} else {
wordwidth = map_bankwidth(map);
words_per_bus = 1;
}
chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
/* First, determine what the bit-pattern should be for a single
device, according to chip mode and endianness... */
switch (chip_mode) {
default: BUG();
case 1:
onecmd = cmd;
break;
case 2:
onecmd = cpu_to_cfi16(cmd);
break;
case 4:
onecmd = cpu_to_cfi32(cmd);
break;
}
/* Now replicate it across the size of an unsigned long, or
just to the bus width as appropriate */
switch (chips_per_word) {
default: BUG();
#if BITS_PER_LONG >= 64
case 8:
onecmd |= (onecmd << (chip_mode * 32));
#endif
case 4:
onecmd |= (onecmd << (chip_mode * 16));
case 2:
onecmd |= (onecmd << (chip_mode * 8));
case 1:
;
}
/* And finally, for the multi-word case, replicate it
in all words in the structure */
for (i=0; i < words_per_bus; i++) {
val.x[i] = onecmd;
}
return val;
}
#define CMD(x) cfi_build_cmd((x), map, cfi)
/*
* Sends a CFI command to a bank of flash for the given geometry.
*
* Returns the offset in flash where the command was written.
* If prev_val is non-null, it will be set to the value at the command address,
* before the command was written.
*/
static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base,
struct map_info *map, struct cfi_private *cfi,
int type, map_word *prev_val)
{
map_word val;
uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type);
val = cfi_build_cmd(cmd, map, cfi);
if (prev_val)
*prev_val = map_read(map, addr);
map_write(map, val, addr);
return addr - base;
}
static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr)
{
map_word val = map_read(map, addr);
if (map_bankwidth_is_1(map)) {
return val.x[0];
} else if (map_bankwidth_is_2(map)) {
return cfi16_to_cpu(val.x[0]);
} else {
/* No point in a 64-bit byteswap since that would just be
swapping the responses from different chips, and we are
only interested in one chip (a representative sample) */
return cfi32_to_cpu(val.x[0]);
}
}
static inline void cfi_udelay(int us)
{
if (us >= 1000) {
msleep((us+999)/1000);
} else {
udelay(us);
cond_resched();
}
}
static inline void cfi_spin_lock(spinlock_t *mutex)
{
spin_lock_bh(mutex);
}
static inline void cfi_spin_unlock(spinlock_t *mutex)
{
spin_unlock_bh(mutex);
}
struct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t size,
const char* name);
struct cfi_fixup {
uint16_t mfr;
uint16_t id;
void (*fixup)(struct mtd_info *mtd, void* param);
void* param;
};
#define CFI_MFR_ANY 0xffff
#define CFI_ID_ANY 0xffff
#define CFI_MFR_AMD 0x0001
#define CFI_MFR_ST 0x0020 /* STMicroelectronics */
void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);
typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
unsigned long adr, int len, void *thunk);
int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
loff_t ofs, size_t len, void *thunk);
#endif /* __MTD_CFI_H__ */

View File

@@ -0,0 +1,57 @@
/*
* $Id: cfi_endian.h,v 1.11 2002/01/30 23:20:48 awozniak Exp $
*
*/
#include <asm/byteorder.h>
#ifndef CONFIG_MTD_CFI_ADV_OPTIONS
#define CFI_HOST_ENDIAN
#else
#ifdef CONFIG_MTD_CFI_NOSWAP
#define CFI_HOST_ENDIAN
#endif
#ifdef CONFIG_MTD_CFI_LE_BYTE_SWAP
#define CFI_LITTLE_ENDIAN
#endif
#ifdef CONFIG_MTD_CFI_BE_BYTE_SWAP
#define CFI_BIG_ENDIAN
#endif
#endif
#if defined(CFI_LITTLE_ENDIAN)
#define cpu_to_cfi8(x) (x)
#define cfi8_to_cpu(x) (x)
#define cpu_to_cfi16(x) cpu_to_le16(x)
#define cpu_to_cfi32(x) cpu_to_le32(x)
#define cpu_to_cfi64(x) cpu_to_le64(x)
#define cfi16_to_cpu(x) le16_to_cpu(x)
#define cfi32_to_cpu(x) le32_to_cpu(x)
#define cfi64_to_cpu(x) le64_to_cpu(x)
#elif defined (CFI_BIG_ENDIAN)
#define cpu_to_cfi8(x) (x)
#define cfi8_to_cpu(x) (x)
#define cpu_to_cfi16(x) cpu_to_be16(x)
#define cpu_to_cfi32(x) cpu_to_be32(x)
#define cpu_to_cfi64(x) cpu_to_be64(x)
#define cfi16_to_cpu(x) be16_to_cpu(x)
#define cfi32_to_cpu(x) be32_to_cpu(x)
#define cfi64_to_cpu(x) be64_to_cpu(x)
#elif defined (CFI_HOST_ENDIAN)
#define cpu_to_cfi8(x) (x)
#define cfi8_to_cpu(x) (x)
#define cpu_to_cfi16(x) (x)
#define cpu_to_cfi32(x) (x)
#define cpu_to_cfi64(x) (x)
#define cfi16_to_cpu(x) (x)
#define cfi32_to_cpu(x) (x)
#define cfi64_to_cpu(x) (x)
#else
#error No CFI endianness defined
#endif

View File

@@ -0,0 +1,10 @@
#ifndef __LINUX_MTD_COMPATMAC_H__
#define __LINUX_MTD_COMPATMAC_H__
/* Nothing to see here. We write 2.5-compatible code and this
file makes it all OK in older kernels, but it's empty in _current_
kernels. Include guard just to make GCC ignore it in future inclusions
anyway... */
#endif /* __LINUX_MTD_COMPATMAC_H__ */

View File

@@ -0,0 +1,23 @@
/*
* MTD device concatenation layer definitions
*
* (C) 2002 Robert Kaiser <rkaiser@sysgo.de>
*
* This code is GPL
*
* $Id: concat.h,v 1.1 2002/03/08 16:34:36 rkaiser Exp $
*/
#ifndef MTD_CONCAT_H
#define MTD_CONCAT_H
struct mtd_info *mtd_concat_create(
struct mtd_info *subdev[], /* subdevices to concatenate */
int num_devs, /* number of subdevices */
char *name); /* name for the new device */
void mtd_concat_destroy(struct mtd_info *mtd);
#endif

195
include/linux/mtd/doc2000.h Normal file
View File

@@ -0,0 +1,195 @@
/*
* Linux driver for Disk-On-Chip devices
*
* Copyright (C) 1999 Machine Vision Holdings, Inc.
* Copyright (C) 2001-2003 David Woodhouse <dwmw2@infradead.org>
* Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com>
* Copyright (C) 2002-2003 SnapGear Inc
*
* $Id: doc2000.h,v 1.24 2005/01/05 12:40:38 dwmw2 Exp $
*
* Released under GPL
*/
#ifndef __MTD_DOC2000_H__
#define __MTD_DOC2000_H__
#include <linux/mtd/mtd.h>
#include <asm/semaphore.h>
#define DoC_Sig1 0
#define DoC_Sig2 1
#define DoC_ChipID 0x1000
#define DoC_DOCStatus 0x1001
#define DoC_DOCControl 0x1002
#define DoC_FloorSelect 0x1003
#define DoC_CDSNControl 0x1004
#define DoC_CDSNDeviceSelect 0x1005
#define DoC_ECCConf 0x1006
#define DoC_2k_ECCStatus 0x1007
#define DoC_CDSNSlowIO 0x100d
#define DoC_ECCSyndrome0 0x1010
#define DoC_ECCSyndrome1 0x1011
#define DoC_ECCSyndrome2 0x1012
#define DoC_ECCSyndrome3 0x1013
#define DoC_ECCSyndrome4 0x1014
#define DoC_ECCSyndrome5 0x1015
#define DoC_AliasResolution 0x101b
#define DoC_ConfigInput 0x101c
#define DoC_ReadPipeInit 0x101d
#define DoC_WritePipeTerm 0x101e
#define DoC_LastDataRead 0x101f
#define DoC_NOP 0x1020
#define DoC_Mil_CDSN_IO 0x0800
#define DoC_2k_CDSN_IO 0x1800
#define DoC_Mplus_NOP 0x1002
#define DoC_Mplus_AliasResolution 0x1004
#define DoC_Mplus_DOCControl 0x1006
#define DoC_Mplus_AccessStatus 0x1008
#define DoC_Mplus_DeviceSelect 0x1008
#define DoC_Mplus_Configuration 0x100a
#define DoC_Mplus_OutputControl 0x100c
#define DoC_Mplus_FlashControl 0x1020
#define DoC_Mplus_FlashSelect 0x1022
#define DoC_Mplus_FlashCmd 0x1024
#define DoC_Mplus_FlashAddress 0x1026
#define DoC_Mplus_FlashData0 0x1028
#define DoC_Mplus_FlashData1 0x1029
#define DoC_Mplus_ReadPipeInit 0x102a
#define DoC_Mplus_LastDataRead 0x102c
#define DoC_Mplus_LastDataRead1 0x102d
#define DoC_Mplus_WritePipeTerm 0x102e
#define DoC_Mplus_ECCSyndrome0 0x1040
#define DoC_Mplus_ECCSyndrome1 0x1041
#define DoC_Mplus_ECCSyndrome2 0x1042
#define DoC_Mplus_ECCSyndrome3 0x1043
#define DoC_Mplus_ECCSyndrome4 0x1044
#define DoC_Mplus_ECCSyndrome5 0x1045
#define DoC_Mplus_ECCConf 0x1046
#define DoC_Mplus_Toggle 0x1046
#define DoC_Mplus_DownloadStatus 0x1074
#define DoC_Mplus_CtrlConfirm 0x1076
#define DoC_Mplus_Power 0x1fff
/* How to access the device?
* On ARM, it'll be mmap'd directly with 32-bit wide accesses.
* On PPC, it's mmap'd and 16-bit wide.
* Others use readb/writeb
*/
#if defined(__arm__)
#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2))))
#define WriteDOC_(d, adr, reg) do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0)
#define DOC_IOREMAP_LEN 0x8000
#elif defined(__ppc__)
#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u16 *)(((unsigned long)adr)+((reg)<<1))))
#define WriteDOC_(d, adr, reg) do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0)
#define DOC_IOREMAP_LEN 0x4000
#else
#define ReadDOC_(adr, reg) readb((void __iomem *)(adr) + (reg))
#define WriteDOC_(d, adr, reg) writeb(d, (void __iomem *)(adr) + (reg))
#define DOC_IOREMAP_LEN 0x2000
#endif
#if defined(__i386__) || defined(__x86_64__)
#define USE_MEMCPY
#endif
/* These are provided to directly use the DoC_xxx defines */
#define ReadDOC(adr, reg) ReadDOC_(adr,DoC_##reg)
#define WriteDOC(d, adr, reg) WriteDOC_(d,adr,DoC_##reg)
#define DOC_MODE_RESET 0
#define DOC_MODE_NORMAL 1
#define DOC_MODE_RESERVED1 2
#define DOC_MODE_RESERVED2 3
#define DOC_MODE_CLR_ERR 0x80
#define DOC_MODE_RST_LAT 0x10
#define DOC_MODE_BDECT 0x08
#define DOC_MODE_MDWREN 0x04
#define DOC_ChipID_Doc2k 0x20
#define DOC_ChipID_Doc2kTSOP 0x21 /* internal number for MTD */
#define DOC_ChipID_DocMil 0x30
#define DOC_ChipID_DocMilPlus32 0x40
#define DOC_ChipID_DocMilPlus16 0x41
#define CDSN_CTRL_FR_B 0x80
#define CDSN_CTRL_FR_B0 0x40
#define CDSN_CTRL_FR_B1 0x80
#define CDSN_CTRL_ECC_IO 0x20
#define CDSN_CTRL_FLASH_IO 0x10
#define CDSN_CTRL_WP 0x08
#define CDSN_CTRL_ALE 0x04
#define CDSN_CTRL_CLE 0x02
#define CDSN_CTRL_CE 0x01
#define DOC_ECC_RESET 0
#define DOC_ECC_ERROR 0x80
#define DOC_ECC_RW 0x20
#define DOC_ECC__EN 0x08
#define DOC_TOGGLE_BIT 0x04
#define DOC_ECC_RESV 0x02
#define DOC_ECC_IGNORE 0x01
#define DOC_FLASH_CE 0x80
#define DOC_FLASH_WP 0x40
#define DOC_FLASH_BANK 0x02
/* We have to also set the reserved bit 1 for enable */
#define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV)
#define DOC_ECC_DIS (DOC_ECC_RESV)
struct Nand {
char floor, chip;
unsigned long curadr;
unsigned char curmode;
/* Also some erase/write/pipeline info when we get that far */
};
#define MAX_FLOORS 4
#define MAX_CHIPS 4
#define MAX_FLOORS_MIL 1
#define MAX_CHIPS_MIL 1
#define MAX_FLOORS_MPLUS 2
#define MAX_CHIPS_MPLUS 1
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
struct DiskOnChip {
unsigned long physadr;
void __iomem *virtadr;
unsigned long totlen;
unsigned char ChipID; /* Type of DiskOnChip */
int ioreg;
unsigned long mfr; /* Flash IDs - only one type of flash per device */
unsigned long id;
int chipshift;
char page256;
char pageadrlen;
char interleave; /* Internal interleaving - Millennium Plus style */
unsigned long erasesize;
int curfloor;
int curchip;
int numchips;
struct Nand *chips;
struct mtd_info *nextdoc;
struct semaphore lock;
};
int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]);
#endif /* __MTD_DOC2000_H__ */

View File

@@ -0,0 +1,89 @@
/*
* struct flchip definition
*
* Contains information about the location and state of a given flash device
*
* (C) 2000 Red Hat. GPLd.
*
* $Id: flashchip.h,v 1.15 2004/11/05 22:41:06 nico Exp $
*
*/
#ifndef __MTD_FLASHCHIP_H__
#define __MTD_FLASHCHIP_H__
/* For spinlocks. sched.h includes spinlock.h from whichever directory it
* happens to be in - so we don't have to care whether we're on 2.2, which
* has asm/spinlock.h, or 2.4, which has linux/spinlock.h
*/
#include <linux/sched.h>
typedef enum {
FL_READY,
FL_STATUS,
FL_CFI_QUERY,
FL_JEDEC_QUERY,
FL_ERASING,
FL_ERASE_SUSPENDING,
FL_ERASE_SUSPENDED,
FL_WRITING,
FL_WRITING_TO_BUFFER,
FL_WRITE_SUSPENDING,
FL_WRITE_SUSPENDED,
FL_PM_SUSPENDED,
FL_SYNCING,
FL_UNLOADING,
FL_LOCKING,
FL_UNLOCKING,
FL_POINT,
FL_XIP_WHILE_ERASING,
FL_XIP_WHILE_WRITING,
FL_UNKNOWN
} flstate_t;
/* NOTE: confusingly, this can be used to refer to more than one chip at a time,
if they're interleaved. This can even refer to individual partitions on
the same physical chip when present. */
struct flchip {
unsigned long start; /* Offset within the map */
// unsigned long len;
/* We omit len for now, because when we group them together
we insist that they're all of the same size, and the chip size
is held in the next level up. If we get more versatile later,
it'll make it a damn sight harder to find which chip we want from
a given offset, and we'll want to add the per-chip length field
back in.
*/
int ref_point_counter;
flstate_t state;
flstate_t oldstate;
int write_suspended:1;
int erase_suspended:1;
unsigned long in_progress_block_addr;
spinlock_t *mutex;
spinlock_t _spinlock; /* We do it like this because sometimes they'll be shared. */
wait_queue_head_t wq; /* Wait on here when we're waiting for the chip
to be ready */
int word_write_time;
int buffer_write_time;
int erase_time;
void *priv;
};
/* This is used to handle contention on write/erase operations
between partitions of the same physical chip. */
struct flchip_shared {
spinlock_t lock;
struct flchip *writing;
struct flchip *erasing;
};
#endif /* __MTD_FLASHCHIP_H__ */

76
include/linux/mtd/ftl.h Normal file
View File

@@ -0,0 +1,76 @@
/*
* $Id: ftl.h,v 1.6 2003/01/24 13:20:04 dwmw2 Exp $
*
* Derived from (and probably identical to):
* ftl.h 1.7 1999/10/25 20:23:17
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_FTL_H
#define _LINUX_FTL_H
typedef struct erase_unit_header_t {
u_int8_t LinkTargetTuple[5];
u_int8_t DataOrgTuple[10];
u_int8_t NumTransferUnits;
u_int32_t EraseCount;
u_int16_t LogicalEUN;
u_int8_t BlockSize;
u_int8_t EraseUnitSize;
u_int16_t FirstPhysicalEUN;
u_int16_t NumEraseUnits;
u_int32_t FormattedSize;
u_int32_t FirstVMAddress;
u_int16_t NumVMPages;
u_int8_t Flags;
u_int8_t Code;
u_int32_t SerialNumber;
u_int32_t AltEUHOffset;
u_int32_t BAMOffset;
u_int8_t Reserved[12];
u_int8_t EndTuple[2];
} erase_unit_header_t;
/* Flags in erase_unit_header_t */
#define HIDDEN_AREA 0x01
#define REVERSE_POLARITY 0x02
#define DOUBLE_BAI 0x04
/* Definitions for block allocation information */
#define BLOCK_FREE(b) ((b) == 0xffffffff)
#define BLOCK_DELETED(b) (((b) == 0) || ((b) == 0xfffffffe))
#define BLOCK_TYPE(b) ((b) & 0x7f)
#define BLOCK_ADDRESS(b) ((b) & ~0x7f)
#define BLOCK_NUMBER(b) ((b) >> 9)
#define BLOCK_CONTROL 0x30
#define BLOCK_DATA 0x40
#define BLOCK_REPLACEMENT 0x60
#define BLOCK_BAD 0x70
#endif /* _LINUX_FTL_H */

View File

@@ -0,0 +1,23 @@
/*
* (C) 2001, 2001 Red Hat, Inc.
* GPL'd
* $Id: gen_probe.h,v 1.3 2004/10/20 22:10:33 dwmw2 Exp $
*/
#ifndef __LINUX_MTD_GEN_PROBE_H__
#define __LINUX_MTD_GEN_PROBE_H__
#include <linux/mtd/flashchip.h>
#include <linux/mtd/map.h>
#include <linux/mtd/cfi.h>
#include <linux/bitops.h>
struct chip_probe {
char *name;
int (*probe_chip)(struct map_info *map, __u32 base,
unsigned long *chip_map, struct cfi_private *cfi);
};
struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp);
#endif /* __LINUX_MTD_GEN_PROBE_H__ */

View File

@@ -0,0 +1,98 @@
/* $Id: iflash.h,v 1.2 2000/11/13 18:01:54 dwmw2 Exp $ */
#ifndef __MTD_IFLASH_H__
#define __MTD_IFLASH_H__
/* Extended CIS registers for Series 2 and 2+ cards */
/* The registers are all offsets from 0x4000 */
#define CISREG_CSR 0x0100
#define CISREG_WP 0x0104
#define CISREG_RDYBSY 0x0140
/* Extended CIS registers for Series 2 cards */
#define CISREG_SLEEP 0x0118
#define CISREG_RDY_MASK 0x0120
#define CISREG_RDY_STATUS 0x0130
/* Extended CIS registers for Series 2+ cards */
#define CISREG_VCR 0x010c
/* Card Status Register */
#define CSR_SRESET 0x20 /* Soft reset */
#define CSR_CMWP 0x10 /* Common memory write protect */
#define CSR_PWRDOWN 0x08 /* Power down status */
#define CSR_CISWP 0x04 /* Common memory CIS WP */
#define CSR_WP 0x02 /* Mechanical write protect */
#define CSR_READY 0x01 /* Ready/busy status */
/* Write Protection Register */
#define WP_BLKEN 0x04 /* Enable block locking */
#define WP_CMWP 0x02 /* Common memory write protect */
#define WP_CISWP 0x01 /* Common memory CIS WP */
/* Voltage Control Register */
#define VCR_VCC_LEVEL 0x80 /* 0 = 5V, 1 = 3.3V */
#define VCR_VPP_VALID 0x02 /* Vpp Valid */
#define VCR_VPP_GEN 0x01 /* Integrated Vpp generator */
/* Ready/Busy Mode Register */
#define RDYBSY_RACK 0x02 /* Ready acknowledge */
#define RDYBSY_MODE 0x01 /* 1 = high performance */
#define LOW(x) ((x) & 0xff)
/* 28F008SA-Compatible Command Set */
#define IF_READ_ARRAY 0xffff
#define IF_INTEL_ID 0x9090
#define IF_READ_CSR 0x7070
#define IF_CLEAR_CSR 0x5050
#define IF_WRITE 0x4040
#define IF_BLOCK_ERASE 0x2020
#define IF_ERASE_SUSPEND 0xb0b0
#define IF_CONFIRM 0xd0d0
/* 28F016SA Performance Enhancement Commands */
#define IF_READ_PAGE 0x7575
#define IF_PAGE_SWAP 0x7272
#define IF_SINGLE_LOAD 0x7474
#define IF_SEQ_LOAD 0xe0e0
#define IF_PAGE_WRITE 0x0c0c
#define IF_RDY_MODE 0x9696
#define IF_RDY_LEVEL 0x0101
#define IF_RDY_PULSE_WRITE 0x0202
#define IF_RDY_PULSE_ERASE 0x0303
#define IF_RDY_DISABLE 0x0404
#define IF_LOCK_BLOCK 0x7777
#define IF_UPLOAD_STATUS 0x9797
#define IF_READ_ESR 0x7171
#define IF_ERASE_UNLOCKED 0xa7a7
#define IF_SLEEP 0xf0f0
#define IF_ABORT 0x8080
#define IF_UPLOAD_DEVINFO 0x9999
/* Definitions for Compatible Status Register */
#define CSR_WR_READY 0x8080 /* Write state machine status */
#define CSR_ERA_SUSPEND 0x4040 /* Erase suspend status */
#define CSR_ERA_ERR 0x2020 /* Erase status */
#define CSR_WR_ERR 0x1010 /* Data write status */
#define CSR_VPP_LOW 0x0808 /* Vpp status */
/* Definitions for Global Status Register */
#define GSR_WR_READY 0x8080 /* Write state machine status */
#define GSR_OP_SUSPEND 0x4040 /* Operation suspend status */
#define GSR_OP_ERR 0x2020 /* Device operation status */
#define GSR_SLEEP 0x1010 /* Device sleep status */
#define GSR_QUEUE_FULL 0x0808 /* Queue status */
#define GSR_PAGE_AVAIL 0x0404 /* Page buffer available status */
#define GSR_PAGE_READY 0x0202 /* Page buffer status */
#define GSR_PAGE_SELECT 0x0101 /* Page buffer select status */
/* Definitions for Block Status Register */
#define BSR_READY 0x8080 /* Block status */
#define BSR_UNLOCK 0x4040 /* Block lock status */
#define BSR_FAILED 0x2020 /* Block operation status */
#define BSR_ABORTED 0x1010 /* Operation abort status */
#define BSR_QUEUE_FULL 0x0808 /* Queue status */
#define BSR_VPP_LOW 0x0404 /* Vpp status */
#endif /* __MTD_IFLASH_H__ */

57
include/linux/mtd/inftl.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* inftl.h -- defines to support the Inverse NAND Flash Translation Layer
*
* (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
*
* $Id: inftl.h,v 1.6 2004/06/30 14:49:00 dbrown Exp $
*/
#ifndef __MTD_INFTL_H__
#define __MTD_INFTL_H__
#ifndef __KERNEL__
#error This is a kernel header. Perhaps include nftl-user.h instead?
#endif
#include <linux/mtd/blktrans.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nftl.h>
#include <mtd/inftl-user.h>
#ifndef INFTL_MAJOR
#define INFTL_MAJOR 94
#endif
#define INFTL_PARTN_BITS 4
#ifdef __KERNEL__
struct INFTLrecord {
struct mtd_blktrans_dev mbd;
__u16 MediaUnit;
__u32 EraseSize;
struct INFTLMediaHeader MediaHdr;
int usecount;
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
__u16 numvunits;
__u16 firstEUN;
__u16 lastEUN;
__u16 numfreeEUNs;
__u16 LastFreeEUN; /* To speed up finding a free EUN */
int head,sect,cyl;
__u16 *PUtable; /* Physical Unit Table */
__u16 *VUtable; /* Virtual Unit Table */
unsigned int nb_blocks; /* number of physical blocks */
unsigned int nb_boot_blocks; /* number of blocks used by the bios */
struct erase_info instr;
struct nand_oobinfo oobinfo;
};
int INFTL_mount(struct INFTLrecord *s);
int INFTL_formatblock(struct INFTLrecord *s, int block);
#endif /* __KERNEL__ */
#endif /* __MTD_INFTL_H__ */

66
include/linux/mtd/jedec.h Normal file
View File

@@ -0,0 +1,66 @@
/* JEDEC Flash Interface.
* This is an older type of interface for self programming flash. It is
* commonly use in older AMD chips and is obsolete compared with CFI.
* It is called JEDEC because the JEDEC association distributes the ID codes
* for the chips.
*
* See the AMD flash databook for information on how to operate the interface.
*
* $Id: jedec.h,v 1.3 2003/05/21 11:51:01 dwmw2 Exp $
*/
#ifndef __LINUX_MTD_JEDEC_H__
#define __LINUX_MTD_JEDEC_H__
#include <linux/types.h>
#define MAX_JEDEC_CHIPS 16
// Listing of all supported chips and their information
struct JEDECTable
{
__u16 jedec;
char *name;
unsigned long size;
unsigned long sectorsize;
__u32 capabilities;
};
// JEDEC being 0 is the end of the chip array
struct jedec_flash_chip
{
__u16 jedec;
unsigned long size;
unsigned long sectorsize;
// *(__u8*)(base + (adder << addrshift)) = data << datashift
// Address size = size << addrshift
unsigned long base; // Byte 0 of the flash, will be unaligned
unsigned int datashift; // Useful for 32bit/16bit accesses
unsigned int addrshift;
unsigned long offset; // linerized start. base==offset for unbanked, uninterleaved flash
__u32 capabilities;
// These markers are filled in by the flash_chip_scan function
unsigned long start;
unsigned long length;
};
struct jedec_private
{
unsigned long size; // Total size of all the devices
/* Bank handling. If sum(bank_fill) == size then this is linear flash.
Otherwise the mapping has holes in it. bank_fill may be used to
find the holes, but in the common symetric case
bank_fill[0] == bank_fill[*], thus addresses may be computed
mathmatically. bank_fill must be powers of two */
unsigned is_banked;
unsigned long bank_fill[MAX_JEDEC_CHIPS];
struct jedec_flash_chip chips[MAX_JEDEC_CHIPS];
};
#endif

412
include/linux/mtd/map.h Normal file
View File

@@ -0,0 +1,412 @@
/* Overhauled routines for dealing with different mmap regions of flash */
/* $Id: map.h,v 1.46 2005/01/05 17:09:44 dwmw2 Exp $ */
#ifndef __LINUX_MTD_MAP_H__
#define __LINUX_MTD_MAP_H__
#include <linux/config.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/mtd/compatmac.h>
#include <asm/unaligned.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/bug.h>
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
#define map_bankwidth(map) 1
#define map_bankwidth_is_1(map) (map_bankwidth(map) == 1)
#define map_bankwidth_is_large(map) (0)
#define map_words(map) (1)
#define MAX_MAP_BANKWIDTH 1
#else
#define map_bankwidth_is_1(map) (0)
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
# ifdef map_bankwidth
# undef map_bankwidth
# define map_bankwidth(map) ((map)->bankwidth)
# else
# define map_bankwidth(map) 2
# define map_bankwidth_is_large(map) (0)
# define map_words(map) (1)
# endif
#define map_bankwidth_is_2(map) (map_bankwidth(map) == 2)
#undef MAX_MAP_BANKWIDTH
#define MAX_MAP_BANKWIDTH 2
#else
#define map_bankwidth_is_2(map) (0)
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
# ifdef map_bankwidth
# undef map_bankwidth
# define map_bankwidth(map) ((map)->bankwidth)
# else
# define map_bankwidth(map) 4
# define map_bankwidth_is_large(map) (0)
# define map_words(map) (1)
# endif
#define map_bankwidth_is_4(map) (map_bankwidth(map) == 4)
#undef MAX_MAP_BANKWIDTH
#define MAX_MAP_BANKWIDTH 4
#else
#define map_bankwidth_is_4(map) (0)
#endif
/* ensure we never evaluate anything shorted than an unsigned long
* to zero, and ensure we'll never miss the end of an comparison (bjd) */
#define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1))/ sizeof(unsigned long))
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
# ifdef map_bankwidth
# undef map_bankwidth
# define map_bankwidth(map) ((map)->bankwidth)
# if BITS_PER_LONG < 64
# undef map_bankwidth_is_large
# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
# undef map_words
# define map_words(map) map_calc_words(map)
# endif
# else
# define map_bankwidth(map) 8
# define map_bankwidth_is_large(map) (BITS_PER_LONG < 64)
# define map_words(map) map_calc_words(map)
# endif
#define map_bankwidth_is_8(map) (map_bankwidth(map) == 8)
#undef MAX_MAP_BANKWIDTH
#define MAX_MAP_BANKWIDTH 8
#else
#define map_bankwidth_is_8(map) (0)
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
# ifdef map_bankwidth
# undef map_bankwidth
# define map_bankwidth(map) ((map)->bankwidth)
# undef map_bankwidth_is_large
# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
# undef map_words
# define map_words(map) map_calc_words(map)
# else
# define map_bankwidth(map) 16
# define map_bankwidth_is_large(map) (1)
# define map_words(map) map_calc_words(map)
# endif
#define map_bankwidth_is_16(map) (map_bankwidth(map) == 16)
#undef MAX_MAP_BANKWIDTH
#define MAX_MAP_BANKWIDTH 16
#else
#define map_bankwidth_is_16(map) (0)
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
# ifdef map_bankwidth
# undef map_bankwidth
# define map_bankwidth(map) ((map)->bankwidth)
# undef map_bankwidth_is_large
# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
# undef map_words
# define map_words(map) map_calc_words(map)
# else
# define map_bankwidth(map) 32
# define map_bankwidth_is_large(map) (1)
# define map_words(map) map_calc_words(map)
# endif
#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
#undef MAX_MAP_BANKWIDTH
#define MAX_MAP_BANKWIDTH 32
#else
#define map_bankwidth_is_32(map) (0)
#endif
#ifndef map_bankwidth
#error "No bus width supported. What's the point?"
#endif
static inline int map_bankwidth_supported(int w)
{
switch (w) {
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
case 1:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
case 2:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
case 4:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
case 8:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
case 16:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
case 32:
#endif
return 1;
default:
return 0;
}
}
#define MAX_MAP_LONGS ( ((MAX_MAP_BANKWIDTH*8) + BITS_PER_LONG - 1) / BITS_PER_LONG )
typedef union {
unsigned long x[MAX_MAP_LONGS];
} map_word;
/* The map stuff is very simple. You fill in your struct map_info with
a handful of routines for accessing the device, making sure they handle
paging etc. correctly if your device needs it. Then you pass it off
to a chip probe routine -- either JEDEC or CFI probe or both -- via
do_map_probe(). If a chip is recognised, the probe code will invoke the
appropriate chip driver (if present) and return a struct mtd_info.
At which point, you fill in the mtd->module with your own module
address, and register it with the MTD core code. Or you could partition
it and register the partitions instead, or keep it for your own private
use; whatever.
The mtd->priv field will point to the struct map_info, and any further
private data required by the chip driver is linked from the
mtd->priv->fldrv_priv field. This allows the map driver to get at
the destructor function map->fldrv_destroy() when it's tired
of living.
*/
struct map_info {
char *name;
unsigned long size;
unsigned long phys;
#define NO_XIP (-1UL)
void __iomem *virt;
void *cached;
int bankwidth; /* in octets. This isn't necessarily the width
of actual bus cycles -- it's the repeat interval
in bytes, before you are talking to the first chip again.
*/
#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
map_word (*read)(struct map_info *, unsigned long);
void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
void (*write)(struct map_info *, const map_word, unsigned long);
void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
/* We can perhaps put in 'point' and 'unpoint' methods, if we really
want to enable XIP for non-linear mappings. Not yet though. */
#endif
/* It's possible for the map driver to use cached memory in its
copy_from implementation (and _only_ with copy_from). However,
when the chip driver knows some flash area has changed contents,
it will signal it to the map driver through this routine to let
the map driver invalidate the corresponding cache as needed.
If there is no cache to care about this can be set to NULL. */
void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
/* set_vpp() must handle being reentered -- enable, enable, disable
must leave it enabled. */
void (*set_vpp)(struct map_info *, int);
unsigned long map_priv_1;
unsigned long map_priv_2;
void *fldrv_priv;
struct mtd_chip_driver *fldrv;
};
struct mtd_chip_driver {
struct mtd_info *(*probe)(struct map_info *map);
void (*destroy)(struct mtd_info *);
struct module *module;
char *name;
struct list_head list;
};
void register_mtd_chip_driver(struct mtd_chip_driver *);
void unregister_mtd_chip_driver(struct mtd_chip_driver *);
struct mtd_info *do_map_probe(const char *name, struct map_info *map);
void map_destroy(struct mtd_info *mtd);
#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0)
#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0)
#define INVALIDATE_CACHED_RANGE(map, from, size) \
do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0)
static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2)
{
int i;
for (i=0; i<map_words(map); i++) {
if (val1.x[i] != val2.x[i])
return 0;
}
return 1;
}
static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2)
{
map_word r;
int i;
for (i=0; i<map_words(map); i++) {
r.x[i] = val1.x[i] & val2.x[i];
}
return r;
}
static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2)
{
map_word r;
int i;
for (i=0; i<map_words(map); i++) {
r.x[i] = val1.x[i] | val2.x[i];
}
return r;
}
#define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b))
static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
{
int i;
for (i=0; i<map_words(map); i++) {
if (val1.x[i] & val2.x[i])
return 1;
}
return 0;
}
static inline map_word map_word_load(struct map_info *map, const void *ptr)
{
map_word r;
if (map_bankwidth_is_1(map))
r.x[0] = *(unsigned char *)ptr;
else if (map_bankwidth_is_2(map))
r.x[0] = get_unaligned((uint16_t *)ptr);
else if (map_bankwidth_is_4(map))
r.x[0] = get_unaligned((uint32_t *)ptr);
#if BITS_PER_LONG >= 64
else if (map_bankwidth_is_8(map))
r.x[0] = get_unaligned((uint64_t *)ptr);
#endif
else if (map_bankwidth_is_large(map))
memcpy(r.x, ptr, map->bankwidth);
return r;
}
static inline map_word map_word_load_partial(struct map_info *map, map_word orig, const unsigned char *buf, int start, int len)
{
int i;
if (map_bankwidth_is_large(map)) {
char *dest = (char *)&orig;
memcpy(dest+start, buf, len);
} else {
for (i=start; i < start+len; i++) {
int bitpos;
#ifdef __LITTLE_ENDIAN
bitpos = i*8;
#else /* __BIG_ENDIAN */
bitpos = (map_bankwidth(map)-1-i)*8;
#endif
orig.x[0] &= ~(0xff << bitpos);
orig.x[0] |= buf[i-start] << bitpos;
}
}
return orig;
}
static inline map_word map_word_ff(struct map_info *map)
{
map_word r;
int i;
for (i=0; i<map_words(map); i++) {
r.x[i] = ~0UL;
}
return r;
}
static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
{
map_word r;
if (map_bankwidth_is_1(map))
r.x[0] = __raw_readb(map->virt + ofs);
else if (map_bankwidth_is_2(map))
r.x[0] = __raw_readw(map->virt + ofs);
else if (map_bankwidth_is_4(map))
r.x[0] = __raw_readl(map->virt + ofs);
#if BITS_PER_LONG >= 64
else if (map_bankwidth_is_8(map))
r.x[0] = __raw_readq(map->virt + ofs);
#endif
else if (map_bankwidth_is_large(map))
memcpy_fromio(r.x, map->virt+ofs, map->bankwidth);
return r;
}
static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
{
if (map_bankwidth_is_1(map))
__raw_writeb(datum.x[0], map->virt + ofs);
else if (map_bankwidth_is_2(map))
__raw_writew(datum.x[0], map->virt + ofs);
else if (map_bankwidth_is_4(map))
__raw_writel(datum.x[0], map->virt + ofs);
#if BITS_PER_LONG >= 64
else if (map_bankwidth_is_8(map))
__raw_writeq(datum.x[0], map->virt + ofs);
#endif
else if (map_bankwidth_is_large(map))
memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
mb();
}
static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
if (map->cached)
memcpy(to, (char *)map->cached + from, len);
else
memcpy_fromio(to, map->virt + from, len);
}
static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
memcpy_toio(map->virt + to, from, len);
}
#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
#define map_read(map, ofs) (map)->read(map, ofs)
#define map_copy_from(map, to, from, len) (map)->copy_from(map, to, from, len)
#define map_write(map, datum, ofs) (map)->write(map, datum, ofs)
#define map_copy_to(map, to, from, len) (map)->copy_to(map, to, from, len)
extern void simple_map_init(struct map_info *);
#define map_is_linear(map) (map->phys != NO_XIP)
#else
#define map_read(map, ofs) inline_map_read(map, ofs)
#define map_copy_from(map, to, from, len) inline_map_copy_from(map, to, from, len)
#define map_write(map, datum, ofs) inline_map_write(map, datum, ofs)
#define map_copy_to(map, to, from, len) inline_map_copy_to(map, to, from, len)
#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
#define map_is_linear(map) (1)
#endif /* !CONFIG_MTD_COMPLEX_MAPPINGS */
#endif /* __LINUX_MTD_MAP_H__ */

226
include/linux/mtd/mtd.h Normal file
View File

@@ -0,0 +1,226 @@
/*
* $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
*
* Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
*
* Released under GPL
*/
#ifndef __MTD_MTD_H__
#define __MTD_MTD_H__
#ifndef __KERNEL__
#error This is a kernel header. Perhaps include mtd-user.h instead?
#endif
#include <linux/config.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/uio.h>
#include <linux/mtd/compatmac.h>
#include <mtd/mtd-abi.h>
#define MTD_CHAR_MAJOR 90
#define MTD_BLOCK_MAJOR 31
#define MAX_MTD_DEVICES 16
#define MTD_ERASE_PENDING 0x01
#define MTD_ERASING 0x02
#define MTD_ERASE_SUSPEND 0x04
#define MTD_ERASE_DONE 0x08
#define MTD_ERASE_FAILED 0x10
/* If the erase fails, fail_addr might indicate exactly which block failed. If
fail_addr = 0xffffffff, the failure was not at the device level or was not
specific to any particular block. */
struct erase_info {
struct mtd_info *mtd;
u_int32_t addr;
u_int32_t len;
u_int32_t fail_addr;
u_long time;
u_long retries;
u_int dev;
u_int cell;
void (*callback) (struct erase_info *self);
u_long priv;
u_char state;
struct erase_info *next;
};
struct mtd_erase_region_info {
u_int32_t offset; /* At which this region starts, from the beginning of the MTD */
u_int32_t erasesize; /* For this region */
u_int32_t numblocks; /* Number of blocks of erasesize in this region */
};
struct mtd_info {
u_char type;
u_int32_t flags;
u_int32_t size; // Total size of the MTD
/* "Major" erase size for the device. Na<4E>ve users may take this
* to be the only erase size available, or may use the more detailed
* information below if they desire
*/
u_int32_t erasesize;
u_int32_t oobblock; // Size of OOB blocks (e.g. 512)
u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
u_int32_t oobavail; // Number of bytes in OOB area available for fs
u_int32_t ecctype;
u_int32_t eccsize;
// Kernel-only stuff starts here.
char *name;
int index;
// oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO)
struct nand_oobinfo oobinfo;
/* Data for variable erase regions. If numeraseregions is zero,
* it means that the whole device has erasesize as given above.
*/
int numeraseregions;
struct mtd_erase_region_info *eraseregions;
/* This really shouldn't be here. It can go away in 2.5 */
u_int32_t bank_size;
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
/* This stuff for eXecute-In-Place */
int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
/*
* Methods to access the protection register area, present in some
* flash devices. The user data is one time programmable but the
* factory data is read only.
*/
int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
/* This function is not yet implemented */
int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
/* kvec-based read/write methods. We need these especially for NAND flash,
with its limited number of write cycles per erase.
NB: The 'count' parameter is the number of _vectors_, each of
which contains an (ofs, len) tuple.
*/
int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from,
size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to,
size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
/* Sync */
void (*sync) (struct mtd_info *mtd);
/* Chip-supported device locking */
int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
/* Power Management functions */
int (*suspend) (struct mtd_info *mtd);
void (*resume) (struct mtd_info *mtd);
/* Bad block management functions */
int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
void *priv;
struct module *owner;
int usecount;
};
/* Kernel-side ioctl definitions */
extern int add_mtd_device(struct mtd_info *mtd);
extern int del_mtd_device (struct mtd_info *mtd);
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
extern void put_mtd_device(struct mtd_info *mtd);
struct mtd_notifier {
void (*add)(struct mtd_info *mtd);
void (*remove)(struct mtd_info *mtd);
struct list_head list;
};
extern void register_mtd_user (struct mtd_notifier *new);
extern int unregister_mtd_user (struct mtd_notifier *old);
int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen);
int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
unsigned long count, loff_t from, size_t *retlen);
#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args)
#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args)
#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args)
#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0)
#ifdef CONFIG_MTD_PARTITIONS
void mtd_erase_callback(struct erase_info *instr);
#else
static inline void mtd_erase_callback(struct erase_info *instr)
{
if (instr->callback)
instr->callback(instr);
}
#endif
/*
* Debugging macro and defines
*/
#define MTD_DEBUG_LEVEL0 (0) /* Quiet */
#define MTD_DEBUG_LEVEL1 (1) /* Audible */
#define MTD_DEBUG_LEVEL2 (2) /* Loud */
#define MTD_DEBUG_LEVEL3 (3) /* Noisy */
#ifdef CONFIG_MTD_DEBUG
#define DEBUG(n, args...) \
do { \
if (n <= CONFIG_MTD_DEBUG_VERBOSE) \
printk(KERN_INFO args); \
} while(0)
#else /* CONFIG_MTD_DEBUG */
#define DEBUG(n, args...) do { } while(0)
#endif /* CONFIG_MTD_DEBUG */
#endif /* __MTD_MTD_H__ */

469
include/linux/mtd/nand.h Normal file
View File

@@ -0,0 +1,469 @@
/*
* linux/include/linux/mtd/nand.h
*
* Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
* Steven J. Hill <sjhill@realitydiluted.com>
* Thomas Gleixner <tglx@linutronix.de>
*
* $Id: nand.h,v 1.68 2004/11/12 10:40:37 gleixner Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Info:
* Contains standard defines and IDs for NAND flash devices
*
* Changelog:
* 01-31-2000 DMW Created
* 09-18-2000 SJH Moved structure out of the Disk-On-Chip drivers
* so it can be used by other NAND flash device
* drivers. I also changed the copyright since none
* of the original contents of this file are specific
* to DoC devices. David can whack me with a baseball
* bat later if I did something naughty.
* 10-11-2000 SJH Added private NAND flash structure for driver
* 10-24-2000 SJH Added prototype for 'nand_scan' function
* 10-29-2001 TG changed nand_chip structure to support
* hardwarespecific function for accessing control lines
* 02-21-2002 TG added support for different read/write adress and
* ready/busy line access function
* 02-26-2002 TG added chip_delay to nand_chip structure to optimize
* command delay times for different chips
* 04-28-2002 TG OOB config defines moved from nand.c to avoid duplicate
* defines in jffs2/wbuf.c
* 08-07-2002 TG forced bad block location to byte 5 of OOB, even if
* CONFIG_MTD_NAND_ECC_JFFS2 is not set
* 08-10-2002 TG extensions to nand_chip structure to support HW-ECC
*
* 08-29-2002 tglx nand_chip structure: data_poi for selecting
* internal / fs-driver buffer
* support for 6byte/512byte hardware ECC
* read_ecc, write_ecc extended for different oob-layout
* oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
* NAND_YAFFS_OOB
* 11-25-2002 tglx Added Manufacturer code FUJITSU, NATIONAL
* Split manufacturer and device ID structures
*
* 02-08-2004 tglx added option field to nand structure for chip anomalities
* 05-25-2004 tglx added bad block table support, ST-MICRO manufacturer id
* update of nand_chip structure description
*/
#ifndef __LINUX_MTD_NAND_H
#define __LINUX_MTD_NAND_H
#include <linux/config.h>
#include <linux/wait.h>
#include <linux/spinlock.h>
#include <linux/mtd/mtd.h>
struct mtd_info;
/* Scan and identify a NAND device */
extern int nand_scan (struct mtd_info *mtd, int max_chips);
/* Free resources held by the NAND device */
extern void nand_release (struct mtd_info *mtd);
/* Read raw data from the device without ECC */
extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
/* The maximum number of NAND chips in an array */
#define NAND_MAX_CHIPS 8
/* This constant declares the max. oobsize / page, which
* is supported now. If you add a chip with bigger oobsize/page
* adjust this accordingly.
*/
#define NAND_MAX_OOBSIZE 64
/*
* Constants for hardware specific CLE/ALE/NCE function
*/
/* Select the chip by setting nCE to low */
#define NAND_CTL_SETNCE 1
/* Deselect the chip by setting nCE to high */
#define NAND_CTL_CLRNCE 2
/* Select the command latch by setting CLE to high */
#define NAND_CTL_SETCLE 3
/* Deselect the command latch by setting CLE to low */
#define NAND_CTL_CLRCLE 4
/* Select the address latch by setting ALE to high */
#define NAND_CTL_SETALE 5
/* Deselect the address latch by setting ALE to low */
#define NAND_CTL_CLRALE 6
/* Set write protection by setting WP to high. Not used! */
#define NAND_CTL_SETWP 7
/* Clear write protection by setting WP to low. Not used! */
#define NAND_CTL_CLRWP 8
/*
* Standard NAND flash commands
*/
#define NAND_CMD_READ0 0
#define NAND_CMD_READ1 1
#define NAND_CMD_PAGEPROG 0x10
#define NAND_CMD_READOOB 0x50
#define NAND_CMD_ERASE1 0x60
#define NAND_CMD_STATUS 0x70
#define NAND_CMD_STATUS_MULTI 0x71
#define NAND_CMD_SEQIN 0x80
#define NAND_CMD_READID 0x90
#define NAND_CMD_ERASE2 0xd0
#define NAND_CMD_RESET 0xff
/* Extended commands for large page devices */
#define NAND_CMD_READSTART 0x30
#define NAND_CMD_CACHEDPROG 0x15
/* Status bits */
#define NAND_STATUS_FAIL 0x01
#define NAND_STATUS_FAIL_N1 0x02
#define NAND_STATUS_TRUE_READY 0x20
#define NAND_STATUS_READY 0x40
#define NAND_STATUS_WP 0x80
/*
* Constants for ECC_MODES
*/
/* No ECC. Usage is not recommended ! */
#define NAND_ECC_NONE 0
/* Software ECC 3 byte ECC per 256 Byte data */
#define NAND_ECC_SOFT 1
/* Hardware ECC 3 byte ECC per 256 Byte data */
#define NAND_ECC_HW3_256 2
/* Hardware ECC 3 byte ECC per 512 Byte data */
#define NAND_ECC_HW3_512 3
/* Hardware ECC 3 byte ECC per 512 Byte data */
#define NAND_ECC_HW6_512 4
/* Hardware ECC 8 byte ECC per 512 Byte data */
#define NAND_ECC_HW8_512 6
/* Hardware ECC 12 byte ECC per 2048 Byte data */
#define NAND_ECC_HW12_2048 7
/*
* Constants for Hardware ECC
*/
/* Reset Hardware ECC for read */
#define NAND_ECC_READ 0
/* Reset Hardware ECC for write */
#define NAND_ECC_WRITE 1
/* Enable Hardware ECC before syndrom is read back from flash */
#define NAND_ECC_READSYN 2
/* Option constants for bizarre disfunctionality and real
* features
*/
/* Chip can not auto increment pages */
#define NAND_NO_AUTOINCR 0x00000001
/* Buswitdh is 16 bit */
#define NAND_BUSWIDTH_16 0x00000002
/* Device supports partial programming without padding */
#define NAND_NO_PADDING 0x00000004
/* Chip has cache program function */
#define NAND_CACHEPRG 0x00000008
/* Chip has copy back function */
#define NAND_COPYBACK 0x00000010
/* AND Chip which has 4 banks and a confusing page / block
* assignment. See Renesas datasheet for further information */
#define NAND_IS_AND 0x00000020
/* Chip has a array of 4 pages which can be read without
* additional ready /busy waits */
#define NAND_4PAGE_ARRAY 0x00000040
/* Options valid for Samsung large page devices */
#define NAND_SAMSUNG_LP_OPTIONS \
(NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
/* Macros to identify the above */
#define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR))
#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
/* Mask to zero out the chip options, which come from the id table */
#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR)
/* Non chip related options */
/* Use a flash based bad block table. This option is passed to the
* default bad block table function. */
#define NAND_USE_FLASH_BBT 0x00010000
/* The hw ecc generator provides a syndrome instead a ecc value on read
* This can only work if we have the ecc bytes directly behind the
* data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
#define NAND_HWECC_SYNDROME 0x00020000
/* Options set by nand scan */
/* Nand scan has allocated oob_buf */
#define NAND_OOBBUF_ALLOC 0x40000000
/* Nand scan has allocated data_buf */
#define NAND_DATABUF_ALLOC 0x80000000
/*
* nand_state_t - chip states
* Enumeration for NAND flash chip state
*/
typedef enum {
FL_READY,
FL_READING,
FL_WRITING,
FL_ERASING,
FL_SYNCING,
FL_CACHEDPRG,
} nand_state_t;
/* Keep gcc happy */
struct nand_chip;
/**
* struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices
* @lock: protection lock
* @active: the mtd device which holds the controller currently
*/
struct nand_hw_control {
spinlock_t lock;
struct nand_chip *active;
};
/**
* struct nand_chip - NAND Private Flash Chip Data
* @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
* @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
* @read_byte: [REPLACEABLE] read one byte from the chip
* @write_byte: [REPLACEABLE] write one byte to the chip
* @read_word: [REPLACEABLE] read one word from the chip
* @write_word: [REPLACEABLE] write one word to the chip
* @write_buf: [REPLACEABLE] write data from the buffer to the chip
* @read_buf: [REPLACEABLE] read data from the chip into the buffer
* @verify_buf: [REPLACEABLE] verify buffer contents against the chip data
* @select_chip: [REPLACEABLE] select chip nr
* @block_bad: [REPLACEABLE] check, if the block is bad
* @block_markbad: [REPLACEABLE] mark the block bad
* @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
* @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
* If set to NULL no access to ready/busy is available and the ready/busy information
* is read from the chip status register
* @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip
* @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready
* @calculate_ecc: [REPLACEABLE] function for ecc calculation or readback from ecc hardware
* @correct_data: [REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
* @enable_hwecc: [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
* be provided if a hardware ECC is available
* @erase_cmd: [INTERN] erase command write function, selectable due to AND support
* @scan_bbt: [REPLACEABLE] function to scan bad block table
* @eccmode: [BOARDSPECIFIC] mode of ecc, see defines
* @eccsize: [INTERN] databytes used per ecc-calculation
* @eccbytes: [INTERN] number of ecc bytes per ecc-calculation step
* @eccsteps: [INTERN] number of ecc calculation steps per page
* @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
* @chip_lock: [INTERN] spinlock used to protect access to this structure and the chip
* @wq: [INTERN] wait queue to sleep on if a NAND operation is in progress
* @state: [INTERN] the current state of the NAND device
* @page_shift: [INTERN] number of address bits in a page (column address bits)
* @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock
* @bbt_erase_shift: [INTERN] number of address bits in a bbt entry
* @chip_shift: [INTERN] number of address bits in one chip
* @data_buf: [INTERN] internal buffer for one page + oob
* @oob_buf: [INTERN] oob buffer for one eraseblock
* @oobdirty: [INTERN] indicates that oob_buf must be reinitialized
* @data_poi: [INTERN] pointer to a data buffer
* @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
* special functionality. See the defines for further explanation
* @badblockpos: [INTERN] position of the bad block marker in the oob area
* @numchips: [INTERN] number of physical chips
* @chipsize: [INTERN] the size of one chip for multichip arrays
* @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
* @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf
* @autooob: [REPLACEABLE] the default (auto)placement scheme
* @bbt: [INTERN] bad block table pointer
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup
* @bbt_md: [REPLACEABLE] bad block table mirror descriptor
* @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan
* @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
* @priv: [OPTIONAL] pointer to private chip date
*/
struct nand_chip {
void __iomem *IO_ADDR_R;
void __iomem *IO_ADDR_W;
u_char (*read_byte)(struct mtd_info *mtd);
void (*write_byte)(struct mtd_info *mtd, u_char byte);
u16 (*read_word)(struct mtd_info *mtd);
void (*write_word)(struct mtd_info *mtd, u16 word);
void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
void (*select_chip)(struct mtd_info *mtd, int chip);
int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
void (*hwcontrol)(struct mtd_info *mtd, int cmd);
int (*dev_ready)(struct mtd_info *mtd);
void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
int (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
void (*enable_hwecc)(struct mtd_info *mtd, int mode);
void (*erase_cmd)(struct mtd_info *mtd, int page);
int (*scan_bbt)(struct mtd_info *mtd);
int eccmode;
int eccsize;
int eccbytes;
int eccsteps;
int chip_delay;
spinlock_t chip_lock;
wait_queue_head_t wq;
nand_state_t state;
int page_shift;
int phys_erase_shift;
int bbt_erase_shift;
int chip_shift;
u_char *data_buf;
u_char *oob_buf;
int oobdirty;
u_char *data_poi;
unsigned int options;
int badblockpos;
int numchips;
unsigned long chipsize;
int pagemask;
int pagebuf;
struct nand_oobinfo *autooob;
uint8_t *bbt;
struct nand_bbt_descr *bbt_td;
struct nand_bbt_descr *bbt_md;
struct nand_bbt_descr *badblock_pattern;
struct nand_hw_control *controller;
void *priv;
};
/*
* NAND Flash Manufacturer ID Codes
*/
#define NAND_MFR_TOSHIBA 0x98
#define NAND_MFR_SAMSUNG 0xec
#define NAND_MFR_FUJITSU 0x04
#define NAND_MFR_NATIONAL 0x8f
#define NAND_MFR_RENESAS 0x07
#define NAND_MFR_STMICRO 0x20
/**
* struct nand_flash_dev - NAND Flash Device ID Structure
*
* @name: Identify the device type
* @id: device ID code
* @pagesize: Pagesize in bytes. Either 256 or 512 or 0
* If the pagesize is 0, then the real pagesize
* and the eraseize are determined from the
* extended id bytes in the chip
* @erasesize: Size of an erase block in the flash device.
* @chipsize: Total chipsize in Mega Bytes
* @options: Bitfield to store chip relevant options
*/
struct nand_flash_dev {
char *name;
int id;
unsigned long pagesize;
unsigned long chipsize;
unsigned long erasesize;
unsigned long options;
};
/**
* struct nand_manufacturers - NAND Flash Manufacturer ID Structure
* @name: Manufacturer name
* @id: manufacturer ID code of device.
*/
struct nand_manufacturers {
int id;
char * name;
};
extern struct nand_flash_dev nand_flash_ids[];
extern struct nand_manufacturers nand_manuf_ids[];
/**
* struct nand_bbt_descr - bad block table descriptor
* @options: options for this descriptor
* @pages: the page(s) where we find the bbt, used with option BBT_ABSPAGE
* when bbt is searched, then we store the found bbts pages here.
* Its an array and supports up to 8 chips now
* @offs: offset of the pattern in the oob area of the page
* @veroffs: offset of the bbt version counter in the oob are of the page
* @version: version read from the bbt page during scan
* @len: length of the pattern, if 0 no pattern check is performed
* @maxblocks: maximum number of blocks to search for a bbt. This number of
* blocks is reserved at the end of the device where the tables are
* written.
* @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
* bad) block in the stored bbt
* @pattern: pattern to identify bad block table or factory marked good /
* bad blocks, can be NULL, if len = 0
*
* Descriptor for the bad block table marker and the descriptor for the
* pattern which identifies good and bad blocks. The assumption is made
* that the pattern and the version count are always located in the oob area
* of the first block.
*/
struct nand_bbt_descr {
int options;
int pages[NAND_MAX_CHIPS];
int offs;
int veroffs;
uint8_t version[NAND_MAX_CHIPS];
int len;
int maxblocks;
int reserved_block_code;
uint8_t *pattern;
};
/* Options for the bad block table descriptors */
/* The number of bits used per block in the bbt on the device */
#define NAND_BBT_NRBITS_MSK 0x0000000F
#define NAND_BBT_1BIT 0x00000001
#define NAND_BBT_2BIT 0x00000002
#define NAND_BBT_4BIT 0x00000004
#define NAND_BBT_8BIT 0x00000008
/* The bad block table is in the last good block of the device */
#define NAND_BBT_LASTBLOCK 0x00000010
/* The bbt is at the given page, else we must scan for the bbt */
#define NAND_BBT_ABSPAGE 0x00000020
/* The bbt is at the given page, else we must scan for the bbt */
#define NAND_BBT_SEARCH 0x00000040
/* bbt is stored per chip on multichip devices */
#define NAND_BBT_PERCHIP 0x00000080
/* bbt has a version counter at offset veroffs */
#define NAND_BBT_VERSION 0x00000100
/* Create a bbt if none axists */
#define NAND_BBT_CREATE 0x00000200
/* Search good / bad pattern through all pages of a block */
#define NAND_BBT_SCANALLPAGES 0x00000400
/* Scan block empty during good / bad block scan */
#define NAND_BBT_SCANEMPTY 0x00000800
/* Write bbt if neccecary */
#define NAND_BBT_WRITE 0x00001000
/* Read and write back block contents when writing bbt */
#define NAND_BBT_SAVECONTENT 0x00002000
/* Search good / bad pattern on the first and the second page */
#define NAND_BBT_SCAN2NDPAGE 0x00004000
/* The maximum number of blocks to scan for a bbt */
#define NAND_BBT_SCAN_MAXBLOCKS 4
extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
extern int nand_default_bbt (struct mtd_info *mtd);
extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
/*
* Constants for oob configuration
*/
#define NAND_SMALL_BADBLOCK_POS 5
#define NAND_LARGE_BADBLOCK_POS 0
#endif /* __LINUX_MTD_NAND_H */

View File

@@ -0,0 +1,30 @@
/*
* drivers/mtd/nand_ecc.h
*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
*
* $Id: nand_ecc.h,v 1.4 2004/06/17 02:35:02 dbrown Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This file is the header for the ECC algorithm.
*/
#ifndef __MTD_NAND_ECC_H__
#define __MTD_NAND_ECC_H__
struct mtd_info;
/*
* Calculate 3 byte ECC code for 256 byte block
*/
int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
/*
* Detect and correct a 1 bit error for 256 byte block
*/
int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
#endif /* __MTD_NAND_ECC_H__ */

54
include/linux/mtd/nftl.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* $Id: nftl.h,v 1.16 2004/06/30 14:49:00 dbrown Exp $
*
* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
*/
#ifndef __MTD_NFTL_H__
#define __MTD_NFTL_H__
#include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h>
#include <mtd/nftl-user.h>
/* these info are used in ReplUnitTable */
#define BLOCK_NIL 0xffff /* last block of a chain */
#define BLOCK_FREE 0xfffe /* free block */
#define BLOCK_NOTEXPLORED 0xfffd /* non explored block, only used during mounting */
#define BLOCK_RESERVED 0xfffc /* bios block or bad block */
struct NFTLrecord {
struct mtd_blktrans_dev mbd;
__u16 MediaUnit, SpareMediaUnit;
__u32 EraseSize;
struct NFTLMediaHeader MediaHdr;
int usecount;
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
__u16 numvunits;
__u16 lastEUN; /* should be suppressed */
__u16 numfreeEUNs;
__u16 LastFreeEUN; /* To speed up finding a free EUN */
int head,sect,cyl;
__u16 *EUNtable; /* [numvunits]: First EUN for each virtual unit */
__u16 *ReplUnitTable; /* [numEUNs]: ReplUnitNumber for each */
unsigned int nb_blocks; /* number of physical blocks */
unsigned int nb_boot_blocks; /* number of blocks used by the bios */
struct erase_info instr;
struct nand_oobinfo oobinfo;
};
int NFTL_mount(struct NFTLrecord *s);
int NFTL_formatblock(struct NFTLrecord *s, int block);
#ifndef NFTL_MAJOR
#define NFTL_MAJOR 93
#endif
#define MAX_NFTLS 16
#define MAX_SECTORS_PER_UNIT 64
#define NFTL_PARTN_BITS 4
#endif /* __MTD_NFTL_H__ */

View File

@@ -0,0 +1,75 @@
/*
* MTD partitioning layer definitions
*
* (C) 2000 Nicolas Pitre <nico@cam.org>
*
* This code is GPL
*
* $Id: partitions.h,v 1.16 2004/11/16 18:34:40 dwmw2 Exp $
*/
#ifndef MTD_PARTITIONS_H
#define MTD_PARTITIONS_H
#include <linux/types.h>
/*
* Partition definition structure:
*
* An array of struct partition is passed along with a MTD object to
* add_mtd_partitions() to create them.
*
* For each partition, these fields are available:
* name: string that will be used to label the partition's MTD device.
* size: the partition size; if defined as MTDPART_SIZ_FULL, the partition
* will extend to the end of the master MTD device.
* offset: absolute starting position within the master MTD device; if
* defined as MTDPART_OFS_APPEND, the partition will start where the
* previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
* mask_flags: contains flags that have to be masked (removed) from the
* master MTD flag set for the corresponding MTD partition.
* For example, to force a read-only partition, simply adding
* MTD_WRITEABLE to the mask_flags will do the trick.
*
* Note: writeable partitions require their size and offset be
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
*/
struct mtd_partition {
char *name; /* identifier string */
u_int32_t size; /* partition size */
u_int32_t offset; /* offset within the master MTD space */
u_int32_t mask_flags; /* master MTD flags to mask out for this partition */
struct nand_oobinfo *oobsel; /* out of band layout for this partition (NAND only)*/
struct mtd_info **mtdp; /* pointer to store the MTD object */
};
#define MTDPART_OFS_NXTBLK (-2)
#define MTDPART_OFS_APPEND (-1)
#define MTDPART_SIZ_FULL (0)
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
int del_mtd_partitions(struct mtd_info *);
/*
* Functions dealing with the various ways of partitioning the space
*/
struct mtd_part_parser {
struct list_head list;
struct module *owner;
const char *name;
int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long);
};
extern int register_mtd_parser(struct mtd_part_parser *parser);
extern int deregister_mtd_parser(struct mtd_part_parser *parser);
extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
struct mtd_partition **pparts, unsigned long origin);
#define put_partition_parser(p) do { module_put((p)->owner); } while(0)
#endif

View File

@@ -0,0 +1,61 @@
/*
* For boards with physically mapped flash and using
* drivers/mtd/maps/physmap.c mapping driver.
*
* $Id: physmap.h,v 1.3 2004/07/21 00:16:15 jwboyer Exp $
*
* Copyright (C) 2003 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#ifndef __LINUX_MTD_PHYSMAP__
#include <linux/config.h>
#if defined(CONFIG_MTD_PHYSMAP)
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
/*
* The map_info for physmap. Board can override size, buswidth, phys,
* (*set_vpp)(), etc in their initial setup routine.
*/
extern struct map_info physmap_map;
/*
* Board needs to specify the exact mapping during their setup time.
*/
static inline void physmap_configure(unsigned long addr, unsigned long size, int bankwidth, void (*set_vpp)(struct map_info *, int) )
{
physmap_map.phys = addr;
physmap_map.size = size;
physmap_map.bankwidth = bankwidth;
physmap_map.set_vpp = set_vpp;
}
#if defined(CONFIG_MTD_PARTITIONS)
/*
* Machines that wish to do flash partition may want to call this function in
* their setup routine.
*
* physmap_set_partitions(mypartitions, num_parts);
*
* Note that one can always override this hard-coded partition with
* command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS).
*/
void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
#endif /* defined(CONFIG_MTD_PARTITIONS) */
#endif /* defined(CONFIG_MTD) */
#endif /* __LINUX_MTD_PHYSMAP__ */

View File

@@ -0,0 +1,79 @@
/*
* $Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $
*
* PMC551 PCI Mezzanine Ram Device
*
* Author:
* Mark Ferrell
* Copyright 1999,2000 Nortel Networks
*
* License:
* As part of this driver was derrived from the slram.c driver it falls
* under the same license, which is GNU General Public License v2
*/
#ifndef __MTD_PMC551_H__
#define __MTD_PMC551_H__
#include <linux/mtd/mtd.h>
#define PMC551_VERSION "$Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $\n"\
"Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
/*
* Our personal and private information
*/
struct mypriv {
struct pci_dev *dev;
u_char *start;
u32 base_map0;
u32 curr_map0;
u32 asize;
struct mtd_info *nextpmc551;
};
/*
* Function Prototypes
*/
static int pmc551_erase(struct mtd_info *, struct erase_info *);
static void pmc551_unpoint(struct mtd_info *, u_char *, loff_t, size_t);
static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
/*
* Define the PCI ID's if the kernel doesn't define them for us
*/
#ifndef PCI_VENDOR_ID_V3_SEMI
#define PCI_VENDOR_ID_V3_SEMI 0x11b0
#endif
#ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC
#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200
#endif
#define PMC551_PCI_MEM_MAP0 0x50
#define PMC551_PCI_MEM_MAP1 0x54
#define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000
#define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0
#define PMC551_PCI_MEM_MAP_REG_EN 0x00000002
#define PMC551_PCI_MEM_MAP_ENABLE 0x00000001
#define PMC551_SDRAM_MA 0x60
#define PMC551_SDRAM_CMD 0x62
#define PMC551_DRAM_CFG 0x64
#define PMC551_SYS_CTRL_REG 0x78
#define PMC551_DRAM_BLK0 0x68
#define PMC551_DRAM_BLK1 0x6c
#define PMC551_DRAM_BLK2 0x70
#define PMC551_DRAM_BLK3 0x74
#define PMC551_DRAM_BLK_GET_SIZE(x) (524288<<((x>>4)&0x0f))
#define PMC551_DRAM_BLK_SET_COL_MUX(x,v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
#define PMC551_DRAM_BLK_SET_ROW_MUX(x,v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
#endif /* __MTD_PMC551_H__ */

107
include/linux/mtd/xip.h Normal file
View File

@@ -0,0 +1,107 @@
/*
* MTD primitives for XIP support
*
* Author: Nicolas Pitre
* Created: Nov 2, 2004
* Copyright: (C) 2004 MontaVista Software, Inc.
*
* This XIP support for MTD has been loosely inspired
* by an earlier patch authored by David Woodhouse.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* $Id: xip.h,v 1.2 2004/12/01 15:49:10 nico Exp $
*/
#ifndef __LINUX_MTD_XIP_H__
#define __LINUX_MTD_XIP_H__
#include <linux/config.h>
#ifdef CONFIG_MTD_XIP
/*
* Function that are modifying the flash state away from array mode must
* obviously not be running from flash. The __xipram is therefore marking
* those functions so they get relocated to ram.
*/
#define __xipram __attribute__ ((__section__ (".data")))
/*
* We really don't want gcc to guess anything.
* We absolutely _need_ proper inlining.
*/
#include <linux/compiler.h>
/*
* Each architecture has to provide the following macros. They must access
* the hardware directly and not rely on any other (XIP) functions since they
* won't be available when used (flash not in array mode).
*
* xip_irqpending()
*
* return non zero when any hardware interrupt is pending.
*
* xip_currtime()
*
* return a platform specific time reference to be used with
* xip_elapsed_since().
*
* xip_elapsed_since(x)
*
* return in usecs the elapsed timebetween now and the reference x as
* returned by xip_currtime().
*
* note 1: convertion to usec can be approximated, as long as the
* returned value is <= the real elapsed time.
* note 2: this should be able to cope with a few seconds without
* overflowing.
*/
#if defined(CONFIG_ARCH_SA1100) || defined(CONFIG_ARCH_PXA)
#include <asm/hardware.h>
#ifdef CONFIG_ARCH_PXA
#include <asm/arch/pxa-regs.h>
#endif
#define xip_irqpending() (ICIP & ICMR)
/* we sample OSCR and convert desired delta to usec (1/4 ~= 1000000/3686400) */
#define xip_currtime() (OSCR)
#define xip_elapsed_since(x) (signed)((OSCR - (x)) / 4)
#else
#warning "missing IRQ and timer primitives for XIP MTD support"
#warning "some of the XIP MTD support code will be disabled"
#warning "your system will therefore be unresponsive when writing or erasing flash"
#define xip_irqpending() (0)
#define xip_currtime() (0)
#define xip_elapsed_since(x) (0)
#endif
/*
* xip_cpu_idle() is used when waiting for a delay equal or larger than
* the system timer tick period. This should put the CPU into idle mode
* to save power and to be woken up only when some interrupts are pending.
* As above, this should not rely upon standard kernel code.
*/
#if defined(CONFIG_CPU_XSCALE)
#define xip_cpu_idle() asm volatile ("mcr p14, 0, %0, c7, c0, 0" :: "r" (1))
#else
#define xip_cpu_idle() do { } while (0)
#endif
#else
#define __xipram
#endif /* CONFIG_MTD_XIP */
#endif /* __LINUX_MTD_XIP_H__ */