Commit 0d178214 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6:
  [JFFS2][XATTR] Fix memory leak in POSIX-ACL support
  fs/jffs2/: make 2 functions static
  [MTD] NAND: Fix broken sharpsl driver
  [JFFS2][XATTR] Fix xd->refcnt race condition
  MTD: kernel-doc fixes + additions
  MTD: fix all kernel-doc warnings
  [MTD] DOC: Fixup read functions and do a little cleanup
parents 67ab33db c7afb0f9
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
for most of the implementations. These functions can be replaced by the for most of the implementations. These functions can be replaced by the
board driver if neccecary. Those functions are called via pointers in the board driver if neccecary. Those functions are called via pointers in the
NAND chip description structure. The board driver can set the functions which NAND chip description structure. The board driver can set the functions which
should be replaced by board dependend functions before calling nand_scan(). should be replaced by board dependent functions before calling nand_scan().
If the function pointer is NULL on entry to nand_scan() then the pointer If the function pointer is NULL on entry to nand_scan() then the pointer
is set to the default function which is suitable for the detected chip type. is set to the default function which is suitable for the detected chip type.
</para></listitem> </para></listitem>
...@@ -133,7 +133,7 @@ ...@@ -133,7 +133,7 @@
[REPLACEABLE]</para><para> [REPLACEABLE]</para><para>
Replaceable members hold hardware related functions which can be Replaceable members hold hardware related functions which can be
provided by the board driver. The board driver can set the functions which provided by the board driver. The board driver can set the functions which
should be replaced by board dependend functions before calling nand_scan(). should be replaced by board dependent functions before calling nand_scan().
If the function pointer is NULL on entry to nand_scan() then the pointer If the function pointer is NULL on entry to nand_scan() then the pointer
is set to the default function which is suitable for the detected chip type. is set to the default function which is suitable for the detected chip type.
</para></listitem> </para></listitem>
...@@ -156,9 +156,8 @@ ...@@ -156,9 +156,8 @@
<title>Basic board driver</title> <title>Basic board driver</title>
<para> <para>
For most boards it will be sufficient to provide just the For most boards it will be sufficient to provide just the
basic functions and fill out some really board dependend basic functions and fill out some really board dependent
members in the nand chip description structure. members in the nand chip description structure.
See drivers/mtd/nand/skeleton for reference.
</para> </para>
<sect1> <sect1>
<title>Basic defines</title> <title>Basic defines</title>
...@@ -1295,7 +1294,9 @@ in this page</entry> ...@@ -1295,7 +1294,9 @@ in this page</entry>
</para> </para>
!Idrivers/mtd/nand/nand_base.c !Idrivers/mtd/nand/nand_base.c
!Idrivers/mtd/nand/nand_bbt.c !Idrivers/mtd/nand/nand_bbt.c
!Idrivers/mtd/nand/nand_ecc.c <!-- No internal functions for kernel-doc:
X!Idrivers/mtd/nand/nand_ecc.c
-->
</chapter> </chapter>
<chapter id="credits"> <chapter id="credits">
......
...@@ -55,10 +55,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -55,10 +55,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf); size_t *retlen, u_char *buf);
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf); size_t *retlen, const u_char *buf);
static int doc_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);
static int doc_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);
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
struct mtd_oob_ops *ops); struct mtd_oob_ops *ops);
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
...@@ -614,18 +610,11 @@ EXPORT_SYMBOL_GPL(DoC2k_init); ...@@ -614,18 +610,11 @@ EXPORT_SYMBOL_GPL(DoC2k_init);
static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, u_char * buf) size_t * retlen, u_char * buf)
{
/* Just a special case of doc_read_ecc */
return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
}
static int doc_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)
{ {
struct DiskOnChip *this = mtd->priv; struct DiskOnChip *this = mtd->priv;
void __iomem *docptr = this->virtadr; void __iomem *docptr = this->virtadr;
struct Nand *mychip; struct Nand *mychip;
unsigned char syndrome[6]; unsigned char syndrome[6], eccbuf[6];
volatile char dummy; volatile char dummy;
int i, len256 = 0, ret=0; int i, len256 = 0, ret=0;
size_t left = len; size_t left = len;
...@@ -673,15 +662,9 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -673,15 +662,9 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP, DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
CDSN_CTRL_ECC_IO); CDSN_CTRL_ECC_IO);
if (eccbuf) { /* Prime the ECC engine */
/* Prime the ECC engine */ WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
WriteDOC(DOC_ECC_RESET, docptr, ECCConf); WriteDOC(DOC_ECC_EN, docptr, ECCConf);
WriteDOC(DOC_ECC_EN, docptr, ECCConf);
} else {
/* disable the ECC engine */
WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
}
/* treat crossing 256-byte sector for 2M x 8bits devices */ /* treat crossing 256-byte sector for 2M x 8bits devices */
if (this->page256 && from + len > (from | 0xff) + 1) { if (this->page256 && from + len > (from | 0xff) + 1) {
...@@ -698,58 +681,59 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -698,58 +681,59 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
/* Let the caller know we completed it */ /* Let the caller know we completed it */
*retlen += len; *retlen += len;
if (eccbuf) { /* Read the ECC data through the DiskOnChip ECC logic */
/* Read the ECC data through the DiskOnChip ECC logic */ /* Note: this will work even with 2M x 8bit devices as */
/* Note: this will work even with 2M x 8bit devices as */ /* they have 8 bytes of OOB per 256 page. mf. */
/* they have 8 bytes of OOB per 256 page. mf. */ DoC_ReadBuf(this, eccbuf, 6);
DoC_ReadBuf(this, eccbuf, 6);
/* Flush the pipeline */
if (DoC_is_Millennium(this)) {
dummy = ReadDOC(docptr, ECCConf);
dummy = ReadDOC(docptr, ECCConf);
i = ReadDOC(docptr, ECCConf);
} else {
dummy = ReadDOC(docptr, 2k_ECCStatus);
dummy = ReadDOC(docptr, 2k_ECCStatus);
i = ReadDOC(docptr, 2k_ECCStatus);
}
/* Check the ECC Status */ /* Flush the pipeline */
if (i & 0x80) { if (DoC_is_Millennium(this)) {
int nb_errors; dummy = ReadDOC(docptr, ECCConf);
/* There was an ECC error */ dummy = ReadDOC(docptr, ECCConf);
i = ReadDOC(docptr, ECCConf);
} else {
dummy = ReadDOC(docptr, 2k_ECCStatus);
dummy = ReadDOC(docptr, 2k_ECCStatus);
i = ReadDOC(docptr, 2k_ECCStatus);
}
/* Check the ECC Status */
if (i & 0x80) {
int nb_errors;
/* There was an ECC error */
#ifdef ECC_DEBUG #ifdef ECC_DEBUG
printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from); printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
#endif #endif
/* Read the ECC syndrom through the DiskOnChip ECC logic. /* Read the ECC syndrom through the DiskOnChip ECC
These syndrome will be all ZERO when there is no error */ logic. These syndrome will be all ZERO when there
for (i = 0; i < 6; i++) { is no error */
syndrome[i] = for (i = 0; i < 6; i++) {
ReadDOC(docptr, ECCSyndrome0 + i); syndrome[i] =
} ReadDOC(docptr, ECCSyndrome0 + i);
nb_errors = doc_decode_ecc(buf, syndrome); }
nb_errors = doc_decode_ecc(buf, syndrome);
#ifdef ECC_DEBUG #ifdef ECC_DEBUG
printk(KERN_ERR "Errors corrected: %x\n", nb_errors); printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
#endif #endif
if (nb_errors < 0) { if (nb_errors < 0) {
/* We return error, but have actually done the read. Not that /* We return error, but have actually done the
this can be told to user-space, via sys_read(), but at least read. Not that this can be told to
MTD-aware stuff can know about it by checking *retlen */ user-space, via sys_read(), but at least
ret = -EIO; MTD-aware stuff can know about it by
} checking *retlen */
ret = -EIO;
} }
}
#ifdef PSYCHO_DEBUG #ifdef PSYCHO_DEBUG
printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
(long)from, eccbuf[0], eccbuf[1], eccbuf[2], (long)from, eccbuf[0], eccbuf[1], eccbuf[2],
eccbuf[3], eccbuf[4], eccbuf[5]); eccbuf[3], eccbuf[4], eccbuf[5]);
#endif #endif
/* disable the ECC engine */ /* disable the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr , ECCConf); WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
}
/* according to 11.4.1, we need to wait for the busy line /* according to 11.4.1, we need to wait for the busy line
* drop if we read to the end of the page. */ * drop if we read to the end of the page. */
...@@ -770,18 +754,11 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -770,18 +754,11 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t * retlen, const u_char * buf) size_t * retlen, const u_char * buf)
{
char eccbuf[6];
return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
}
static int doc_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)
{ {
struct DiskOnChip *this = mtd->priv; struct DiskOnChip *this = mtd->priv;
int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */ int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */
void __iomem *docptr = this->virtadr; void __iomem *docptr = this->virtadr;
unsigned char eccbuf[6];
volatile char dummy; volatile char dummy;
int len256 = 0; int len256 = 0;
struct Nand *mychip; struct Nand *mychip;
...@@ -835,15 +812,9 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -835,15 +812,9 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
DoC_Command(this, NAND_CMD_SEQIN, 0); DoC_Command(this, NAND_CMD_SEQIN, 0);
DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO); DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
if (eccbuf) { /* Prime the ECC engine */
/* Prime the ECC engine */ WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
WriteDOC(DOC_ECC_RESET, docptr, ECCConf); WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
} else {
/* disable the ECC engine */
WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
}
/* treat crossing 256-byte sector for 2M x 8bits devices */ /* treat crossing 256-byte sector for 2M x 8bits devices */
if (this->page256 && to + len > (to | 0xff) + 1) { if (this->page256 && to + len > (to | 0xff) + 1) {
...@@ -873,39 +844,35 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -873,39 +844,35 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
DoC_WriteBuf(this, &buf[len256], len - len256); DoC_WriteBuf(this, &buf[len256], len - len256);
if (eccbuf) { WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, CDSNControl);
WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
CDSNControl);
if (DoC_is_Millennium(this)) {
WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP);
} else {
WriteDOC_(0, docptr, this->ioreg);
WriteDOC_(0, docptr, this->ioreg);
WriteDOC_(0, docptr, this->ioreg);
}
WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr, if (DoC_is_Millennium(this)) {
CDSNControl); WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP);
} else {
WriteDOC_(0, docptr, this->ioreg);
WriteDOC_(0, docptr, this->ioreg);
WriteDOC_(0, docptr, this->ioreg);
}
/* Read the ECC data through the DiskOnChip ECC logic */ WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr,
for (di = 0; di < 6; di++) { CDSNControl);
eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
}
/* Reset the ECC engine */ /* Read the ECC data through the DiskOnChip ECC logic */
WriteDOC(DOC_ECC_DIS, docptr, ECCConf); for (di = 0; di < 6; di++) {
eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
}
/* Reset the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
#ifdef PSYCHO_DEBUG #ifdef PSYCHO_DEBUG
printk printk
("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
eccbuf[4], eccbuf[5]); eccbuf[4], eccbuf[5]);
#endif #endif
}
DoC_Command(this, NAND_CMD_PAGEPROG, 0); DoC_Command(this, NAND_CMD_PAGEPROG, 0);
DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
......
...@@ -37,12 +37,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -37,12 +37,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf); size_t *retlen, u_char *buf);
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf); size_t *retlen, const u_char *buf);
static int doc_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);
static int doc_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);
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
struct mtd_oob_ops *ops); struct mtd_oob_ops *ops);
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
...@@ -396,18 +390,10 @@ EXPORT_SYMBOL_GPL(DoCMil_init); ...@@ -396,18 +390,10 @@ EXPORT_SYMBOL_GPL(DoCMil_init);
static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf) size_t *retlen, u_char *buf)
{
/* Just a special case of doc_read_ecc */
return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
}
static int doc_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 i, ret; int i, ret;
volatile char dummy; volatile char dummy;
unsigned char syndrome[6]; unsigned char syndrome[6], eccbuf[6];
struct DiskOnChip *this = mtd->priv; struct DiskOnChip *this = mtd->priv;
void __iomem *docptr = this->virtadr; void __iomem *docptr = this->virtadr;
struct Nand *mychip = &this->chips[from >> (this->chipshift)]; struct Nand *mychip = &this->chips[from >> (this->chipshift)];
...@@ -437,15 +423,9 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, ...@@ -437,15 +423,9 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00); DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00);
DoC_WaitReady(docptr); DoC_WaitReady(docptr);
if (eccbuf) { /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_RESET, docptr, ECCConf); WriteDOC (DOC_ECC_EN, docptr, ECCConf);
WriteDOC (DOC_ECC_EN, docptr, ECCConf);
} else {
/* disable the ECC engine */
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
}
/* Read the data via the internal pipeline through CDSN IO register, /* Read the data via the internal pipeline through CDSN IO register,
see Pipelined Read Operations 11.3 */ see Pipelined Read Operations 11.3 */
...@@ -465,74 +445,65 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, ...@@ -465,74 +445,65 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
*retlen = len; *retlen = len;
ret = 0; ret = 0;
if (eccbuf) { /* Read the ECC data from Spare Data Area,
/* Read the ECC data from Spare Data Area, see Reed-Solomon EDC/ECC 11.1 */
see Reed-Solomon EDC/ECC 11.1 */ dummy = ReadDOC(docptr, ReadPipeInit);
dummy = ReadDOC(docptr, ReadPipeInit);
#ifndef USE_MEMCPY #ifndef USE_MEMCPY
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
/* N.B. you have to increase the source address in this way or the /* N.B. you have to increase the source address in this way or the
ECC logic will not work properly */ ECC logic will not work properly */
eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
} }
#else #else
memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5); memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5);
#endif #endif
eccbuf[5] = ReadDOC(docptr, LastDataRead); eccbuf[5] = ReadDOC(docptr, LastDataRead);
/* Flush the pipeline */ /* Flush the pipeline */
dummy = ReadDOC(docptr, ECCConf); dummy = ReadDOC(docptr, ECCConf);
dummy = ReadDOC(docptr, ECCConf); dummy = ReadDOC(docptr, ECCConf);
/* Check the ECC Status */ /* Check the ECC Status */
if (ReadDOC(docptr, ECCConf) & 0x80) { if (ReadDOC(docptr, ECCConf) & 0x80) {
int nb_errors; int nb_errors;
/* There was an ECC error */ /* There was an ECC error */
#ifdef ECC_DEBUG #ifdef ECC_DEBUG
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
#endif #endif
/* Read the ECC syndrom through the DiskOnChip ECC logic. /* Read the ECC syndrom through the DiskOnChip ECC logic.
These syndrome will be all ZERO when there is no error */ These syndrome will be all ZERO when there is no error */
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
} }
nb_errors = doc_decode_ecc(buf, syndrome); nb_errors = doc_decode_ecc(buf, syndrome);
#ifdef ECC_DEBUG #ifdef ECC_DEBUG
printk("ECC Errors corrected: %x\n", nb_errors); printk("ECC Errors corrected: %x\n", nb_errors);
#endif #endif
if (nb_errors < 0) { if (nb_errors < 0) {
/* We return error, but have actually done the read. Not that /* We return error, but have actually done the read. Not that
this can be told to user-space, via sys_read(), but at least this can be told to user-space, via sys_read(), but at least
MTD-aware stuff can know about it by checking *retlen */ MTD-aware stuff can know about it by checking *retlen */
ret = -EIO; ret = -EIO;
}
} }
}
#ifdef PSYCHO_DEBUG #ifdef PSYCHO_DEBUG
printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
(long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
eccbuf[4], eccbuf[5]); eccbuf[4], eccbuf[5]);
#endif #endif
/* disable the ECC engine */ /* disable the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr , ECCConf); WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
}
return ret; return ret;
} }
static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf) size_t *retlen, const u_char *buf)
{
char eccbuf[6];
return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
}
static int doc_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 i,ret = 0; int i,ret = 0;
char eccbuf[6];
volatile char dummy; volatile char dummy;
struct DiskOnChip *this = mtd->priv; struct DiskOnChip *this = mtd->priv;
void __iomem *docptr = this->virtadr; void __iomem *docptr = this->virtadr;
...@@ -573,15 +544,9 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, ...@@ -573,15 +544,9 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
DoC_Address(docptr, 3, to, 0x00, 0x00); DoC_Address(docptr, 3, to, 0x00, 0x00);
DoC_WaitReady(docptr); DoC_WaitReady(docptr);
if (eccbuf) { /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_RESET, docptr, ECCConf); WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
} else {
/* disable the ECC engine */
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
}
/* Write the data via the internal pipeline through CDSN IO register, /* Write the data via the internal pipeline through CDSN IO register,
see Pipelined Write Operations 11.2 */ see Pipelined Write Operations 11.2 */
...@@ -596,46 +561,44 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, ...@@ -596,46 +561,44 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
#endif #endif
WriteDOC(0x00, docptr, WritePipeTerm); WriteDOC(0x00, docptr, WritePipeTerm);
if (eccbuf) { /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic
/* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
see Reed-Solomon EDC/ECC 11.1 */ WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP); WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP); WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP);
/* Read the ECC data through the DiskOnChip ECC logic */ /* Read the ECC data through the DiskOnChip ECC logic */
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i); eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i);
} }
/* ignore the ECC engine */ /* ignore the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr , ECCConf); WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
#ifndef USE_MEMCPY #ifndef USE_MEMCPY
/* Write the ECC data to flash */ /* Write the ECC data to flash */
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
/* N.B. you have to increase the source address in this way or the /* N.B. you have to increase the source address in this way or the
ECC logic will not work properly */ ECC logic will not work properly */
WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i); WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i);
} }
#else #else
memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6); memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6);
#endif #endif
/* write the block status BLOCK_USED (0x5555) at the end of ECC data /* write the block status BLOCK_USED (0x5555) at the end of ECC data
FIXME: this is only a hack for programming the IPL area for LinuxBIOS FIXME: this is only a hack for programming the IPL area for LinuxBIOS
and should be replace with proper codes in user space utilities */ and should be replace with proper codes in user space utilities */
WriteDOC(0x55, docptr, Mil_CDSN_IO); WriteDOC(0x55, docptr, Mil_CDSN_IO);
WriteDOC(0x55, docptr, Mil_CDSN_IO + 1); WriteDOC(0x55, docptr, Mil_CDSN_IO + 1);
WriteDOC(0x00, docptr, WritePipeTerm); WriteDOC(0x00, docptr, WritePipeTerm);
#ifdef PSYCHO_DEBUG #ifdef PSYCHO_DEBUG
printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
eccbuf[4], eccbuf[5]); eccbuf[4], eccbuf[5]);
#endif #endif
}
/* Commit the Page Program command and wait for ready /* Commit the Page Program command and wait for ready
see Software Requirement 11.4 item 1.*/ see Software Requirement 11.4 item 1.*/
......
...@@ -41,12 +41,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -41,12 +41,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf); size_t *retlen, u_char *buf);
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf); size_t *retlen, const u_char *buf);
static int doc_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);
static int doc_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);
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
struct mtd_oob_ops *ops); struct mtd_oob_ops *ops);
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
...@@ -594,19 +588,11 @@ static int doc_dumpblk(struct mtd_info *mtd, loff_t from) ...@@ -594,19 +588,11 @@ static int doc_dumpblk(struct mtd_info *mtd, loff_t from)
static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf) size_t *retlen, u_char *buf)
{
/* Just a special case of doc_read_ecc */
return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
}
static int doc_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 ret, i; int ret, i;
volatile char dummy; volatile char dummy;
loff_t fofs; loff_t fofs;
unsigned char syndrome[6]; unsigned char syndrome[6], eccbuf[6];
struct DiskOnChip *this = mtd->priv; struct DiskOnChip *this = mtd->priv;
void __iomem * docptr = this->virtadr; void __iomem * docptr = this->virtadr;
struct Nand *mychip = &this->chips[from >> (this->chipshift)]; struct Nand *mychip = &this->chips[from >> (this->chipshift)];
...@@ -644,56 +630,51 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -644,56 +630,51 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
WriteDOC(0, docptr, Mplus_FlashControl); WriteDOC(0, docptr, Mplus_FlashControl);
DoC_WaitReady(docptr); DoC_WaitReady(docptr);
if (eccbuf) { /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
} else {
/* disable the ECC engine */
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
}
/* Let the caller know we completed it */ /* Let the caller know we completed it */
*retlen = len; *retlen = len;
ret = 0; ret = 0;
ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit);
ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit);
if (eccbuf) { /* Read the data via the internal pipeline through CDSN IO
/* Read the data via the internal pipeline through CDSN IO register, see Pipelined Read Operations 11.3 */
register, see Pipelined Read Operations 11.3 */ MemReadDOC(docptr, buf, len);
MemReadDOC(docptr, buf, len);
/* Read the ECC data following raw data */ /* Read the ECC data following raw data */
MemReadDOC(docptr, eccbuf, 4); MemReadDOC(docptr, eccbuf, 4);
eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead); eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead);
eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead); eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead);
/* Flush the pipeline */ /* Flush the pipeline */
dummy = ReadDOC(docptr, Mplus_ECCConf); dummy = ReadDOC(docptr, Mplus_ECCConf);
dummy = ReadDOC(docptr, Mplus_ECCConf); dummy = ReadDOC(docptr, Mplus_ECCConf);
/* Check the ECC Status */ /* Check the ECC Status */
if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) { if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) {
int nb_errors; int nb_errors;
/* There was an ECC error */ /* There was an ECC error */
#ifdef ECC_DEBUG #ifdef ECC_DEBUG
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
#endif #endif
/* Read the ECC syndrom through the DiskOnChip ECC logic. /* Read the ECC syndrom through the DiskOnChip ECC logic.
These syndrome will be all ZERO when there is no error */ These syndrome will be all ZERO when there is no error */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
nb_errors = doc_decode_ecc(buf, syndrome); nb_errors = doc_decode_ecc(buf, syndrome);
#ifdef ECC_DEBUG #ifdef ECC_DEBUG
printk("ECC Errors corrected: %x\n", nb_errors); printk("ECC Errors corrected: %x\n", nb_errors);
#endif #endif
if (nb_errors < 0) { if (nb_errors < 0) {
/* We return error, but have actually done the read. Not that /* We return error, but have actually done the
this can be told to user-space, via sys_read(), but at least read. Not that this can be told to user-space, via
MTD-aware stuff can know about it by checking *retlen */ sys_read(), but at least MTD-aware stuff can know
about it by checking *retlen */
#ifdef ECC_DEBUG #ifdef ECC_DEBUG
printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n", printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
__FILE__, __LINE__, (int)from); __FILE__, __LINE__, (int)from);
...@@ -707,24 +688,16 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -707,24 +688,16 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
eccbuf[3], eccbuf[4], eccbuf[5]); eccbuf[3], eccbuf[4], eccbuf[5]);
#endif #endif
ret = -EIO; ret = -EIO;
}
} }
}
#ifdef PSYCHO_DEBUG #ifdef PSYCHO_DEBUG
printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
(long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
eccbuf[4], eccbuf[5]); eccbuf[4], eccbuf[5]);
#endif #endif
/* disable the ECC engine */
/* disable the ECC engine */ WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
} else {
/* Read the data via the internal pipeline through CDSN IO
register, see Pipelined Read Operations 11.3 */
MemReadDOC(docptr, buf, len-2);
buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead);
buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead);
}
/* Disable flash internally */ /* Disable flash internally */
WriteDOC(0, docptr, Mplus_FlashSelect); WriteDOC(0, docptr, Mplus_FlashSelect);
...@@ -734,18 +707,11 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -734,18 +707,11 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf) size_t *retlen, const u_char *buf)
{
char eccbuf[6];
return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
}
static int doc_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 i, before, ret = 0; int i, before, ret = 0;
loff_t fto; loff_t fto;
volatile char dummy; volatile char dummy;
char eccbuf[6];
struct DiskOnChip *this = mtd->priv; struct DiskOnChip *this = mtd->priv;
void __iomem * docptr = this->virtadr; void __iomem * docptr = this->virtadr;
struct Nand *mychip = &this->chips[to >> (this->chipshift)]; struct Nand *mychip = &this->chips[to >> (this->chipshift)];
...@@ -795,46 +761,42 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -795,46 +761,42 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
/* Disable the ECC engine */ /* Disable the ECC engine */
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
if (eccbuf) { if (before) {
if (before) { /* Write the block status BLOCK_USED (0x5555) */
/* Write the block status BLOCK_USED (0x5555) */ WriteDOC(0x55, docptr, Mil_CDSN_IO);
WriteDOC(0x55, docptr, Mil_CDSN_IO); WriteDOC(0x55, docptr, Mil_CDSN_IO);
WriteDOC(0x55, docptr, Mil_CDSN_IO);
}
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
} }
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
MemWriteDOC(docptr, (unsigned char *) buf, len); MemWriteDOC(docptr, (unsigned char *) buf, len);
if (eccbuf) { /* Write ECC data to flash, the ECC info is generated by
/* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */ DoC_Delay(docptr, 3);
DoC_Delay(docptr, 3);
/* Read the ECC data through the DiskOnChip ECC logic */ /* Read the ECC data through the DiskOnChip ECC logic */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
/* disable the ECC engine */ /* disable the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
/* Write the ECC data to flash */ /* Write the ECC data to flash */
MemWriteDOC(docptr, eccbuf, 6); MemWriteDOC(docptr, eccbuf, 6);
if (!before) { if (!before) {
/* Write the block status BLOCK_USED (0x5555) */ /* Write the block status BLOCK_USED (0x5555) */
WriteDOC(0x55, docptr, Mil_CDSN_IO+6); WriteDOC(0x55, docptr, Mil_CDSN_IO+6);
WriteDOC(0x55, docptr, Mil_CDSN_IO+7); WriteDOC(0x55, docptr, Mil_CDSN_IO+7);
} }
#ifdef PSYCHO_DEBUG #ifdef PSYCHO_DEBUG
printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
eccbuf[4], eccbuf[5]); eccbuf[4], eccbuf[5]);
#endif #endif
}
WriteDOC(0x00, docptr, Mplus_WritePipeTerm); WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
WriteDOC(0x00, docptr, Mplus_WritePipeTerm); WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
......
...@@ -155,7 +155,7 @@ static u16 nand_read_word(struct mtd_info *mtd) ...@@ -155,7 +155,7 @@ static u16 nand_read_word(struct mtd_info *mtd)
/** /**
* nand_select_chip - [DEFAULT] control CE line * nand_select_chip - [DEFAULT] control CE line
* @mtd: MTD device structure * @mtd: MTD device structure
* @chip: chipnumber to select, -1 for deselect * @chipnr: chipnumber to select, -1 for deselect
* *
* Default select function for 1 chip devices. * Default select function for 1 chip devices.
*/ */
...@@ -542,7 +542,6 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, ...@@ -542,7 +542,6 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
* Send command to NAND device. This is the version for the new large page * Send command to NAND device. This is the version for the new large page
* devices We dont have the separate regions as we have in the small page * devices We dont have the separate regions as we have in the small page
* devices. We must emulate NAND_CMD_READOOB to keep the code compatible. * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
*
*/ */
static void nand_command_lp(struct mtd_info *mtd, unsigned int command, static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
int column, int page_addr) int column, int page_addr)
...@@ -656,7 +655,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, ...@@ -656,7 +655,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
/** /**
* nand_get_device - [GENERIC] Get chip for selected access * nand_get_device - [GENERIC] Get chip for selected access
* @this: the nand chip descriptor * @chip: the nand chip descriptor
* @mtd: MTD device structure * @mtd: MTD device structure
* @new_state: the state which is requested * @new_state: the state which is requested
* *
...@@ -696,13 +695,12 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state) ...@@ -696,13 +695,12 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
/** /**
* nand_wait - [DEFAULT] wait until the command is done * nand_wait - [DEFAULT] wait until the command is done
* @mtd: MTD device structure * @mtd: MTD device structure
* @this: NAND chip structure * @chip: NAND chip structure
* *
* Wait for command done. This applies to erase and program only * Wait for command done. This applies to erase and program only
* Erase can take up to 400ms and program up to 20ms according to * Erase can take up to 400ms and program up to 20ms according to
* general NAND and SmartMedia specs * general NAND and SmartMedia specs
* */
*/
static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
{ {
...@@ -896,6 +894,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -896,6 +894,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
/** /**
* nand_transfer_oob - [Internal] Transfer oob to client buffer * nand_transfer_oob - [Internal] Transfer oob to client buffer
* @chip: nand chip structure * @chip: nand chip structure
* @oob: oob destination address
* @ops: oob ops structure * @ops: oob ops structure
*/ */
static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
...@@ -946,6 +945,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, ...@@ -946,6 +945,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
* *
* @mtd: MTD device structure * @mtd: MTD device structure
* @from: offset to read from * @from: offset to read from
* @ops: oob ops structure
* *
* Internal function. Called with chip held. * Internal function. Called with chip held.
*/ */
...@@ -1760,7 +1760,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, ...@@ -1760,7 +1760,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
/** /**
* nand_write_oob - [MTD Interface] NAND write data and/or out-of-band * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
* @mtd: MTD device structure * @mtd: MTD device structure
* @from: offset to read from * @to: offset to write to
* @ops: oob operation description structure * @ops: oob operation description structure
*/ */
static int nand_write_oob(struct mtd_info *mtd, loff_t to, static int nand_write_oob(struct mtd_info *mtd, loff_t to,
...@@ -2055,7 +2055,7 @@ static void nand_sync(struct mtd_info *mtd) ...@@ -2055,7 +2055,7 @@ static void nand_sync(struct mtd_info *mtd)
/** /**
* nand_block_isbad - [MTD Interface] Check if block at offset is bad * nand_block_isbad - [MTD Interface] Check if block at offset is bad
* @mtd: MTD device structure * @mtd: MTD device structure
* @ofs: offset relative to mtd start * @offs: offset relative to mtd start
*/ */
static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
{ {
......
...@@ -65,8 +65,7 @@ static const u_char nand_ecc_precalc_table[] = { ...@@ -65,8 +65,7 @@ static const u_char nand_ecc_precalc_table[] = {
}; };
/** /**
* nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256-byte block
* for 256 byte block
* @mtd: MTD block structure * @mtd: MTD block structure
* @dat: raw data * @dat: raw data
* @ecc_code: buffer for ECC * @ecc_code: buffer for ECC
......
...@@ -237,11 +237,6 @@ static int __init sharpsl_nand_init(void) ...@@ -237,11 +237,6 @@ static int __init sharpsl_nand_init(void)
} }
} }
if (machine_is_husky() || machine_is_borzoi() || machine_is_akita()) {
/* Need to use small eraseblock size for backward compatibility */
sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS;
}
add_mtd_partitions(sharpsl_mtd, sharpsl_partition_info, nr_partitions); add_mtd_partitions(sharpsl_mtd, sharpsl_partition_info, nr_partitions);
/* Return happy */ /* Return happy */
...@@ -255,8 +250,6 @@ module_init(sharpsl_nand_init); ...@@ -255,8 +250,6 @@ module_init(sharpsl_nand_init);
*/ */
static void __exit sharpsl_nand_cleanup(void) static void __exit sharpsl_nand_cleanup(void)
{ {
struct nand_chip *this = (struct nand_chip *)&sharpsl_mtd[1];
/* Release resources, unregister device */ /* Release resources, unregister device */
nand_release(sharpsl_mtd); nand_release(sharpsl_mtd);
......
...@@ -345,10 +345,8 @@ int jffs2_init_acl(struct inode *inode, struct inode *dir) ...@@ -345,10 +345,8 @@ int jffs2_init_acl(struct inode *inode, struct inode *dir)
return rc; return rc;
} }
void jffs2_clear_acl(struct inode *inode) void jffs2_clear_acl(struct jffs2_inode_info *f)
{ {
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) { if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) {
posix_acl_release(f->i_acl_access); posix_acl_release(f->i_acl_access);
f->i_acl_access = JFFS2_ACL_NOT_CACHED; f->i_acl_access = JFFS2_ACL_NOT_CACHED;
......
...@@ -30,7 +30,7 @@ struct jffs2_acl_header { ...@@ -30,7 +30,7 @@ struct jffs2_acl_header {
extern int jffs2_permission(struct inode *, int, struct nameidata *); extern int jffs2_permission(struct inode *, int, struct nameidata *);
extern int jffs2_acl_chmod(struct inode *); extern int jffs2_acl_chmod(struct inode *);
extern int jffs2_init_acl(struct inode *, struct inode *); extern int jffs2_init_acl(struct inode *, struct inode *);
extern void jffs2_clear_acl(struct inode *); extern void jffs2_clear_acl(struct jffs2_inode_info *);
extern struct xattr_handler jffs2_acl_access_xattr_handler; extern struct xattr_handler jffs2_acl_access_xattr_handler;
extern struct xattr_handler jffs2_acl_default_xattr_handler; extern struct xattr_handler jffs2_acl_default_xattr_handler;
...@@ -40,6 +40,6 @@ extern struct xattr_handler jffs2_acl_default_xattr_handler; ...@@ -40,6 +40,6 @@ extern struct xattr_handler jffs2_acl_default_xattr_handler;
#define jffs2_permission NULL #define jffs2_permission NULL
#define jffs2_acl_chmod(inode) (0) #define jffs2_acl_chmod(inode) (0)
#define jffs2_init_acl(inode,dir) (0) #define jffs2_init_acl(inode,dir) (0)
#define jffs2_clear_acl(inode) #define jffs2_clear_acl(f)
#endif /* CONFIG_JFFS2_FS_POSIX_ACL */ #endif /* CONFIG_JFFS2_FS_POSIX_ACL */
...@@ -190,7 +190,7 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) ...@@ -190,7 +190,7 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
kmem_cache_free(tmp_dnode_info_slab, x); kmem_cache_free(tmp_dnode_info_slab, x);
} }
struct jffs2_raw_node_ref *jffs2_alloc_refblock(void) static struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
{ {
struct jffs2_raw_node_ref *ret; struct jffs2_raw_node_ref *ret;
......
...@@ -426,8 +426,6 @@ char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f); ...@@ -426,8 +426,6 @@ char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f);
/* scan.c */ /* scan.c */
int jffs2_scan_medium(struct jffs2_sb_info *c); int jffs2_scan_medium(struct jffs2_sb_info *c);
void jffs2_rotate_lists(struct jffs2_sb_info *c); void jffs2_rotate_lists(struct jffs2_sb_info *c);
int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf,
uint32_t ofs, uint32_t len);
struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino); struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino);
int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size); int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size);
......
...@@ -968,6 +968,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) ...@@ -968,6 +968,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
struct jffs2_full_dirent *fd, *fds; struct jffs2_full_dirent *fd, *fds;
int deleted; int deleted;
jffs2_clear_acl(f);
jffs2_xattr_delete_inode(c, f->inocache); jffs2_xattr_delete_inode(c, f->inocache);
down(&f->sem); down(&f->sem);
deleted = f->inocache && !f->inocache->nlink; deleted = f->inocache && !f->inocache->nlink;
......
...@@ -274,8 +274,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) ...@@ -274,8 +274,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
return ret; return ret;
} }
int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf, static int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf,
uint32_t ofs, uint32_t len) uint32_t ofs, uint32_t len)
{ {
int ret; int ret;
size_t retlen; size_t retlen;
......
...@@ -50,9 +50,10 @@ ...@@ -50,9 +50,10 @@
* is used to write xdatum to medium. xd->version will be incremented. * is used to write xdatum to medium. xd->version will be incremented.
* create_xattr_datum(c, xprefix, xname, xvalue, xsize) * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
* is used to create new xdatum and write to medium. * is used to create new xdatum and write to medium.
* delete_xattr_datum(c, xd) * unrefer_xattr_datum(c, xd)
* is used to delete a xdatum. It marks xd JFFS2_XFLAGS_DEAD, and allows * is used to delete a xdatum. When nobody refers this xdatum, JFFS2_XFLAGS_DEAD
* GC to reclaim those physical nodes. * is set on xd->flags and chained xattr_dead_list or release it immediately.
* In the first case, the garbage collector release it later.
* -------------------------------------------------- */ * -------------------------------------------------- */
static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
{ {
...@@ -394,22 +395,24 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, ...@@ -394,22 +395,24 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
return xd; return xd;
} }
static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
{ {
/* must be called under down_write(xattr_sem) */ /* must be called under down_write(xattr_sem) */
BUG_ON(atomic_read(&xd->refcnt)); if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) {
uint32_t xid = xd->xid, version = xd->version;
unload_xattr_datum(c, xd); unload_xattr_datum(c, xd);
xd->flags |= JFFS2_XFLAGS_DEAD; xd->flags |= JFFS2_XFLAGS_DEAD;
spin_lock(&c->erase_completion_lock); if (xd->node == (void *)xd) {
if (xd->node == (void *)xd) { BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID));
BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID)); jffs2_free_xattr_datum(xd);
jffs2_free_xattr_datum(xd); } else {
} else { list_add(&xd->xindex, &c->xattr_dead_list);
list_add(&xd->xindex, &c->xattr_dead_list); }
spin_unlock(&c->erase_completion_lock);
dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xid, version);
} }
spin_unlock(&c->erase_completion_lock);
dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xd->xid, xd->version);
} }
/* -------- xref related functions ------------------ /* -------- xref related functions ------------------
...@@ -580,8 +583,7 @@ static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *re ...@@ -580,8 +583,7 @@ static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *re
dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n", dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",
ref->ino, ref->xid, ref->xseqno); ref->ino, ref->xid, ref->xseqno);
if (atomic_dec_and_test(&xd->refcnt)) unrefer_xattr_datum(c, xd);
delete_xattr_datum(c, xd);
} }
void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
...@@ -1119,8 +1121,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, ...@@ -1119,8 +1121,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
ref->next = c->xref_dead_list; ref->next = c->xref_dead_list;
c->xref_dead_list = ref; c->xref_dead_list = ref;
spin_unlock(&c->erase_completion_lock); spin_unlock(&c->erase_completion_lock);
if (atomic_dec_and_test(&xd->refcnt)) unrefer_xattr_datum(c, xd);
delete_xattr_datum(c, xd);
} else { } else {
ref->ic = ic; ref->ic = ic;
ref->xd = xd; ref->xd = xd;
...@@ -1156,8 +1157,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, ...@@ -1156,8 +1157,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
down_write(&c->xattr_sem); down_write(&c->xattr_sem);
if (rc) { if (rc) {
JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
if (atomic_dec_and_test(&xd->refcnt)) unrefer_xattr_datum(c, xd);
delete_xattr_datum(c, xd);
up_write(&c->xattr_sem); up_write(&c->xattr_sem);
return rc; return rc;
} }
...@@ -1170,8 +1170,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, ...@@ -1170,8 +1170,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
ic->xref = ref; ic->xref = ref;
} }
rc = PTR_ERR(newref); rc = PTR_ERR(newref);
if (atomic_dec_and_test(&xd->refcnt)) unrefer_xattr_datum(c, xd);
delete_xattr_datum(c, xd);
} else if (ref) { } else if (ref) {
delete_xattr_ref(c, ref); delete_xattr_ref(c, ref);
} }
......
...@@ -19,21 +19,21 @@ ...@@ -19,21 +19,21 @@
/** /**
* struct nand_bbt_descr - bad block table descriptor * struct nand_bbt_descr - bad block table descriptor
* @param options options for this descriptor * @options: options for this descriptor
* @param pages the page(s) where we find the bbt, used with * @pages: the page(s) where we find the bbt, used with
* option BBT_ABSPAGE when bbt is searched, * option BBT_ABSPAGE when bbt is searched,
* then we store the found bbts pages here. * then we store the found bbts pages here.
* Its an array and supports up to 8 chips now * Its an array and supports up to 8 chips now
* @param offs offset of the pattern in the oob area of the page * @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 * @veroffs: offset of the bbt version counter in the oob area of the page
* @param version version read from the bbt page during scan * @version: version read from the bbt page during scan
* @param len length of the pattern, if 0 no pattern check is performed * @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 * @maxblocks: maximum number of blocks to search for a bbt. This
* blocks is reserved at the end of the device * number of blocks is reserved at the end of the device
* where the tables are written. * where the tables are written.
* @param reserved_block_code if non-0, this pattern denotes a reserved * @reserved_block_code: if non-0, this pattern denotes a reserved
* (rather than bad) block in the stored bbt * (rather than bad) block in the stored bbt
* @param pattern pattern to identify bad block table or factory marked * @pattern: pattern to identify bad block table or factory marked
* good / bad blocks, can be NULL, if len = 0 * good / bad blocks, can be NULL, if len = 0
* *
* Descriptor for the bad block table marker and the descriptor for the * Descriptor for the bad block table marker and the descriptor for the
...@@ -93,12 +93,15 @@ struct nand_bbt_descr { ...@@ -93,12 +93,15 @@ struct nand_bbt_descr {
#define ONENAND_BADBLOCK_POS 0 #define ONENAND_BADBLOCK_POS 0
/** /**
* struct bbt_info - [GENERIC] Bad Block Table data structure * struct bbm_info - [GENERIC] Bad Block Table data structure
* @param bbt_erase_shift [INTERN] number of address bits in a bbt entry * @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 * @badblockpos: [INTERN] position of the bad block marker in the oob area
* @param bbt [INTERN] bad block table pointer * @options: options for this descriptor
* @param badblock_pattern [REPLACEABLE] bad block scan pattern used for initial bad block scan * @bbt: [INTERN] bad block table pointer
* @param priv [OPTIONAL] pointer to private bbm date * @isbad_bbt: function to determine if a block is bad
* @badblock_pattern: [REPLACEABLE] bad block scan pattern used for
* initial bad block scan
* @priv: [OPTIONAL] pointer to private bbm date
*/ */
struct bbm_info { struct bbm_info {
int bbt_erase_shift; int bbt_erase_shift;
......
...@@ -77,11 +77,11 @@ typedef enum { ...@@ -77,11 +77,11 @@ typedef enum {
* *
* @len: number of bytes to write/read. When a data buffer is given * @len: number of bytes to write/read. When a data buffer is given
* (datbuf != NULL) this is the number of data bytes. When * (datbuf != NULL) this is the number of data bytes. When
+ no data buffer is available this is the number of oob bytes. * no data buffer is available this is the number of oob bytes.
* *
* @retlen: number of bytes written/read. When a data buffer is given * @retlen: number of bytes written/read. When a data buffer is given
* (datbuf != NULL) this is the number of data bytes. When * (datbuf != NULL) this is the number of data bytes. When
+ no data buffer is available this is the number of oob bytes. * no data buffer is available this is the number of oob bytes.
* *
* @ooblen: number of oob bytes per page * @ooblen: number of oob bytes per page
* @ooboffs: offset of oob data in the oob area (only relevant when * @ooboffs: offset of oob data in the oob area (only relevant when
......
...@@ -202,7 +202,7 @@ typedef enum { ...@@ -202,7 +202,7 @@ typedef enum {
struct nand_chip; struct nand_chip;
/** /**
* struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
* @lock: protection lock * @lock: protection lock
* @active: the mtd device which holds the controller currently * @active: the mtd device which holds the controller currently
* @wq: wait queue to sleep on if a NAND operation is in progress * @wq: wait queue to sleep on if a NAND operation is in progress
...@@ -223,12 +223,15 @@ struct nand_hw_control { ...@@ -223,12 +223,15 @@ struct nand_hw_control {
* @total: total number of ecc bytes per page * @total: total number of ecc bytes per page
* @prepad: padding information for syndrome based ecc generators * @prepad: padding information for syndrome based ecc generators
* @postpad: padding information for syndrome based ecc generators * @postpad: padding information for syndrome based ecc generators
* @layout: ECC layout control struct pointer
* @hwctl: function to control hardware ecc generator. Must only * @hwctl: function to control hardware ecc generator. Must only
* be provided if an hardware ECC is available * be provided if an hardware ECC is available
* @calculate: function for ecc calculation or readback from ecc hardware * @calculate: function for ecc calculation or readback from ecc hardware
* @correct: function for ecc correction, matching to ecc generator (sw/hw) * @correct: function for ecc correction, matching to ecc generator (sw/hw)
* @read_page: function to read a page according to the ecc generator requirements * @read_page: function to read a page according to the ecc generator requirements
* @write_page: function to write a page according to the ecc generator requirements * @write_page: function to write a page according to the ecc generator requirements
* @read_oob: function to read chip OOB data
* @write_oob: function to write chip OOB data
*/ */
struct nand_ecc_ctrl { struct nand_ecc_ctrl {
nand_ecc_modes_t mode; nand_ecc_modes_t mode;
...@@ -300,11 +303,15 @@ struct nand_buffers { ...@@ -300,11 +303,15 @@ struct nand_buffers {
* @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip
* @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready
* @ecc: [BOARDSPECIFIC] ecc control ctructure * @ecc: [BOARDSPECIFIC] ecc control ctructure
* @buffers: buffer structure for read/write
* @hwcontrol: platform-specific hardware control structure
* @ops: oob operation operands
* @erase_cmd: [INTERN] erase command write function, selectable due to AND support * @erase_cmd: [INTERN] erase command write function, selectable due to AND support
* @scan_bbt: [REPLACEABLE] function to scan bad block table * @scan_bbt: [REPLACEABLE] function to scan bad block table
* @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR) * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
* @wq: [INTERN] wait queue to sleep on if a NAND operation is in progress * @wq: [INTERN] wait queue to sleep on if a NAND operation is in progress
* @state: [INTERN] the current state of the NAND device * @state: [INTERN] the current state of the NAND device
* @oob_poi: poison value buffer
* @page_shift: [INTERN] number of address bits in a page (column address bits) * @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 * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock
* @bbt_erase_shift: [INTERN] number of address bits in a bbt entry * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry
...@@ -400,7 +407,6 @@ struct nand_chip { ...@@ -400,7 +407,6 @@ struct nand_chip {
/** /**
* struct nand_flash_dev - NAND Flash Device ID Structure * struct nand_flash_dev - NAND Flash Device ID Structure
*
* @name: Identify the device type * @name: Identify the device type
* @id: device ID code * @id: device ID code
* @pagesize: Pagesize in bytes. Either 256 or 512 or 0 * @pagesize: Pagesize in bytes. Either 256 or 512 or 0
...@@ -519,9 +525,8 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -519,9 +525,8 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
/** /**
* struct platform_nand_chip - chip level device structure * struct platform_nand_chip - chip level device structure
*
* @nr_chips: max. number of chips to scan for * @nr_chips: max. number of chips to scan for
* @chip_offs: chip number offset * @chip_offset: chip number offset
* @nr_partitions: number of partitions pointed to by partitions (or zero) * @nr_partitions: number of partitions pointed to by partitions (or zero)
* @partitions: mtd partition list * @partitions: mtd partition list
* @chip_delay: R/B delay value in us * @chip_delay: R/B delay value in us
...@@ -542,11 +547,10 @@ struct platform_nand_chip { ...@@ -542,11 +547,10 @@ struct platform_nand_chip {
/** /**
* struct platform_nand_ctrl - controller level device structure * struct platform_nand_ctrl - controller level device structure
*
* @hwcontrol: platform specific hardware control structure * @hwcontrol: platform specific hardware control structure
* @dev_ready: platform specific function to read ready/busy pin * @dev_ready: platform specific function to read ready/busy pin
* @select_chip: platform specific chip select function * @select_chip: platform specific chip select function
* @priv_data: private data to transport driver specific settings * @priv: private data to transport driver specific settings
* *
* All fields are optional and depend on the hardware driver requirements * All fields are optional and depend on the hardware driver requirements
*/ */
......
...@@ -23,7 +23,7 @@ extern int onenand_scan(struct mtd_info *mtd, int max_chips); ...@@ -23,7 +23,7 @@ extern int onenand_scan(struct mtd_info *mtd, int max_chips);
/* Free resources held by the OneNAND device */ /* Free resources held by the OneNAND device */
extern void onenand_release(struct mtd_info *mtd); extern void onenand_release(struct mtd_info *mtd);
/** /*
* onenand_state_t - chip states * onenand_state_t - chip states
* Enumeration for OneNAND flash chip state * Enumeration for OneNAND flash chip state
*/ */
...@@ -42,9 +42,9 @@ typedef enum { ...@@ -42,9 +42,9 @@ typedef enum {
/** /**
* struct onenand_bufferram - OneNAND BufferRAM Data * struct onenand_bufferram - OneNAND BufferRAM Data
* @param block block address in BufferRAM * @block: block address in BufferRAM
* @param page page address in BufferRAM * @page: page address in BufferRAM
* @param valid valid flag * @valid: valid flag
*/ */
struct onenand_bufferram { struct onenand_bufferram {
int block; int block;
...@@ -54,32 +54,43 @@ struct onenand_bufferram { ...@@ -54,32 +54,43 @@ struct onenand_bufferram {
/** /**
* struct onenand_chip - OneNAND Private Flash Chip Data * struct onenand_chip - OneNAND Private Flash Chip Data
* @param base [BOARDSPECIFIC] address to access OneNAND * @base: [BOARDSPECIFIC] address to access OneNAND
* @param chipsize [INTERN] the size of one chip for multichip arrays * @chipsize: [INTERN] the size of one chip for multichip arrays
* @param device_id [INTERN] device ID * @device_id: [INTERN] device ID
* @param verstion_id [INTERN] version ID * @density_mask: chip density, used for DDP devices
* @param options [BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about * @verstion_id: [INTERN] version ID
* @param erase_shift [INTERN] number of address bits in a block * @options: [BOARDSPECIFIC] various chip options. They can
* @param page_shift [INTERN] number of address bits in a page * partly be set to inform onenand_scan about
* @param ppb_shift [INTERN] number of address bits in a pages per block * @erase_shift: [INTERN] number of address bits in a block
* @param page_mask [INTERN] a page per block mask * @page_shift: [INTERN] number of address bits in a page
* @param bufferam_index [INTERN] BufferRAM index * @ppb_shift: [INTERN] number of address bits in a pages per block
* @param bufferam [INTERN] BufferRAM info * @page_mask: [INTERN] a page per block mask
* @param readw [REPLACEABLE] hardware specific function for read short * @bufferram_index: [INTERN] BufferRAM index
* @param writew [REPLACEABLE] hardware specific function for write short * @bufferram: [INTERN] BufferRAM info
* @param command [REPLACEABLE] hardware specific function for writing commands to the chip * @readw: [REPLACEABLE] hardware specific function for read short
* @param wait [REPLACEABLE] hardware specific function for wait on ready * @writew: [REPLACEABLE] hardware specific function for write short
* @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area * @command: [REPLACEABLE] hardware specific function for writing
* @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area * commands to the chip
* @param read_word [REPLACEABLE] hardware specific function for read register of OneNAND * @wait: [REPLACEABLE] hardware specific function for wait on ready
* @param write_word [REPLACEABLE] hardware specific function for write register of OneNAND * @read_bufferram: [REPLACEABLE] hardware specific function for BufferRAM Area
* @param scan_bbt [REPLACEALBE] hardware specific function for scaning Bad block Table * @write_bufferram: [REPLACEABLE] hardware specific function for BufferRAM Area
* @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip * @read_word: [REPLACEABLE] hardware specific function for read
* @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress * register of OneNAND
* @param state [INTERN] the current state of the OneNAND device * @write_word: [REPLACEABLE] hardware specific function for write
* @param ecclayout [REPLACEABLE] the default ecc placement scheme * register of OneNAND
* @param bbm [REPLACEABLE] pointer to Bad Block Management * @mmcontrol: sync burst read function
* @param priv [OPTIONAL] pointer to private chip date * @block_markbad: function to mark a block as bad
* @scan_bbt: [REPLACEALBE] hardware specific function for scanning
* Bad block Table
* @chip_lock: [INTERN] spinlock used to protect access to this
* structure and the chip
* @wq: [INTERN] wait queue to sleep on if a OneNAND
* operation is in progress
* @state: [INTERN] the current state of the OneNAND device
* @page_buf: data buffer
* @ecclayout: [REPLACEABLE] the default ecc placement scheme
* @bbm: [REPLACEABLE] pointer to Bad Block Management
* @priv: [OPTIONAL] pointer to private chip date
*/ */
struct onenand_chip { struct onenand_chip {
void __iomem *base; void __iomem *base;
...@@ -147,9 +158,9 @@ struct onenand_chip { ...@@ -147,9 +158,9 @@ struct onenand_chip {
#define ONENAND_MFR_SAMSUNG 0xec #define ONENAND_MFR_SAMSUNG 0xec
/** /**
* struct nand_manufacturers - NAND Flash Manufacturer ID Structure * struct onenand_manufacturers - NAND Flash Manufacturer ID Structure
* @param name: Manufacturer name * @name: Manufacturer name
* @param id: manufacturer ID code of device. * @id: manufacturer ID code of device.
*/ */
struct onenand_manufacturers { struct onenand_manufacturers {
int id; int id;
......
...@@ -133,7 +133,7 @@ struct nand_ecclayout { ...@@ -133,7 +133,7 @@ struct nand_ecclayout {
}; };
/** /**
* struct mtd_ecc_stats - error correction status * struct mtd_ecc_stats - error correction stats
* *
* @corrected: number of corrected bits * @corrected: number of corrected bits
* @failed: number of uncorrectable errors * @failed: number of uncorrectable errors
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment