[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:
@@ -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);
|
||||
|
Reference in New Issue
Block a user