[MTD] DOC: Fixup read functions and do a little cleanup

The NAND rework resulted in non ECC based reads. Fix it up and
do a bit of cleanup while at it.

Pointed out by Adrian Bunk.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
Thomas Gleixner
2006-06-28 10:11:33 +02:00
parent a39727f212
commit 7f8a894066
3 changed files with 211 additions and 319 deletions

View File

@@ -41,12 +41,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
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,
struct mtd_oob_ops *ops);
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)
static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
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;
volatile char dummy;
loff_t fofs;
unsigned char syndrome[6];
unsigned char syndrome[6], eccbuf[6];
struct DiskOnChip *this = mtd->priv;
void __iomem * docptr = this->virtadr;
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,
WriteDOC(0, docptr, Mplus_FlashControl);
DoC_WaitReady(docptr);
if (eccbuf) {
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
} else {
/* disable the ECC engine */
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
}
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
/* Let the caller know we completed it */
*retlen = len;
ret = 0;
ret = 0;
ReadDOC(docptr, Mplus_ReadPipeInit);
ReadDOC(docptr, Mplus_ReadPipeInit);
if (eccbuf) {
/* Read the data via the internal pipeline through CDSN IO
register, see Pipelined Read Operations 11.3 */
MemReadDOC(docptr, buf, len);
/* Read the data via the internal pipeline through CDSN IO
register, see Pipelined Read Operations 11.3 */
MemReadDOC(docptr, buf, len);
/* Read the ECC data following raw data */
MemReadDOC(docptr, eccbuf, 4);
eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead);
eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead);
/* Read the ECC data following raw data */
MemReadDOC(docptr, eccbuf, 4);
eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead);
eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead);
/* Flush the pipeline */
dummy = ReadDOC(docptr, Mplus_ECCConf);
dummy = ReadDOC(docptr, Mplus_ECCConf);
/* Flush the pipeline */
dummy = ReadDOC(docptr, Mplus_ECCConf);
dummy = ReadDOC(docptr, Mplus_ECCConf);
/* Check the ECC Status */
if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) {
int nb_errors;
/* There was an ECC error */
/* Check the ECC Status */
if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) {
int nb_errors;
/* There was an ECC error */
#ifdef ECC_DEBUG
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
#endif
/* Read the ECC syndrom through the DiskOnChip ECC logic.
These syndrome will be all ZERO when there is no error */
for (i = 0; i < 6; i++)
syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
/* Read the ECC syndrom through the DiskOnChip ECC logic.
These syndrome will be all ZERO when there is no error */
for (i = 0; i < 6; 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
printk("ECC Errors corrected: %x\n", nb_errors);
printk("ECC Errors corrected: %x\n", nb_errors);
#endif
if (nb_errors < 0) {
/* We return error, but have actually done the read. Not that
this can be told to user-space, via sys_read(), but at least
MTD-aware stuff can know about it by checking *retlen */
if (nb_errors < 0) {
/* We return error, but have actually done the
read. Not that this can be told to user-space, via
sys_read(), but at least MTD-aware stuff can know
about it by checking *retlen */
#ifdef ECC_DEBUG
printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
__FILE__, __LINE__, (int)from);
@@ -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]);
#endif
ret = -EIO;
}
}
}
#ifdef PSYCHO_DEBUG
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],
eccbuf[4], eccbuf[5]);
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],
eccbuf[4], eccbuf[5]);
#endif
/* disable the ECC engine */
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 the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
/* Disable flash internally */
WriteDOC(0, docptr, Mplus_FlashSelect);
@@ -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,
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;
loff_t fto;
volatile char dummy;
char eccbuf[6];
struct DiskOnChip *this = mtd->priv;
void __iomem * docptr = this->virtadr;
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,
/* Disable the ECC engine */
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
if (eccbuf) {
if (before) {
/* Write the block status BLOCK_USED (0x5555) */
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);
if (before) {
/* Write the block status BLOCK_USED (0x5555) */
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);
MemWriteDOC(docptr, (unsigned char *) buf, len);
if (eccbuf) {
/* Write ECC data to flash, the ECC info is generated by
the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
DoC_Delay(docptr, 3);
/* Write ECC data to flash, the ECC info is generated by
the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
DoC_Delay(docptr, 3);
/* Read the ECC data through the DiskOnChip ECC logic */
for (i = 0; i < 6; i++)
eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
/* Read the ECC data through the DiskOnChip ECC logic */
for (i = 0; i < 6; i++)
eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
/* disable the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
/* disable the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
/* Write the ECC data to flash */
MemWriteDOC(docptr, eccbuf, 6);
/* Write the ECC data to flash */
MemWriteDOC(docptr, eccbuf, 6);
if (!before) {
/* Write the block status BLOCK_USED (0x5555) */
WriteDOC(0x55, docptr, Mil_CDSN_IO+6);
WriteDOC(0x55, docptr, Mil_CDSN_IO+7);
}
if (!before) {
/* Write the block status BLOCK_USED (0x5555) */
WriteDOC(0x55, docptr, Mil_CDSN_IO+6);
WriteDOC(0x55, docptr, Mil_CDSN_IO+7);
}
#ifdef PSYCHO_DEBUG
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],
eccbuf[4], eccbuf[5]);
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],
eccbuf[4], eccbuf[5]);
#endif
}
WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
WriteDOC(0x00, docptr, Mplus_WritePipeTerm);