Commit f5bbdacc authored by Thomas Gleixner's avatar Thomas Gleixner Committed by David Woodhouse

[MTD] NAND Modularize read function

Split the core of the read function out and implement
seperate handling functions for software and hardware
ECC.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 9577f44a
...@@ -968,12 +968,14 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsign ...@@ -968,12 +968,14 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsign
return 0; return 0;
} }
static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *isnull)
{ {
int i, ret = 0; int i, ret = 0;
struct nand_chip *this = mtd->priv; struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv; struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr; void __iomem *docptr = doc->virtadr;
uint8_t calc_ecc[6];
volatile u_char dummy; volatile u_char dummy;
int emptymatch = 1; int emptymatch = 1;
......
This diff is collapsed.
...@@ -444,7 +444,8 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha ...@@ -444,7 +444,8 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
* note: see pages 34..37 of data sheet for details. * note: see pages 34..37 of data sheet for details.
* *
*/ */
static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page) static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
int state, int status, int page)
{ {
int er_stat = 0; int er_stat = 0;
int rtn, retlen; int rtn, retlen;
...@@ -455,39 +456,50 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s ...@@ -455,39 +456,50 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s
this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1); this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
if (state == FL_ERASING) { if (state == FL_ERASING) {
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (status & 1 << (i + 1)) { if (!(status & 1 << (i + 1)))
this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1); continue;
rtn = this->read_byte(mtd); this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1),
this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); -1, -1);
if (!(rtn & ERR_STAT_ECC_AVAILABLE)) { rtn = this->read_byte(mtd);
er_stat |= 1 << (i + 1); /* err_ecc_not_avail */ this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
}
} /* err_ecc_not_avail */
if (!(rtn & ERR_STAT_ECC_AVAILABLE))
er_stat |= 1 << (i + 1);
} }
} else if (state == FL_WRITING) { } else if (state == FL_WRITING) {
unsigned long corrected = mtd->ecc_stats.corrected;
/* single bank write logic */ /* single bank write logic */
this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1); this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1);
rtn = this->read_byte(mtd); rtn = this->read_byte(mtd);
this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
if (!(rtn & ERR_STAT_ECC_AVAILABLE)) { if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
er_stat |= 1 << 1; /* err_ecc_not_avail */ /* err_ecc_not_avail */
} else { er_stat |= 1 << 1;
len = mtd->writesize; goto out;
buf = kmalloc(len, GFP_KERNEL);
if (!buf) {
printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
er_stat = 1; /* if we can't check, assume failed */
} else {
/* recovery read */
/* page read */
rtn = nand_do_read_ecc(mtd, page, len, &retlen, buf, NULL, this->autooob, 1);
if (rtn) { /* if read failed or > 1-bit error corrected */
er_stat |= 1 << 1; /* ECC read failed */
}
kfree(buf);
}
} }
len = mtd->writesize;
buf = kmalloc(len, GFP_KERNEL);
if (!buf) {
printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
er_stat = 1;
goto out;
}
/* recovery read */
rtn = nand_do_read(mtd, page, len, &retlen, buf);
/* if read failed or > 1-bit error corrected */
if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) {
er_stat |= 1 << 1;
kfree(buf);
} }
rtn = status; rtn = status;
......
...@@ -479,14 +479,14 @@ struct nand_bbt_descr { ...@@ -479,14 +479,14 @@ struct nand_bbt_descr {
/* The maximum number of blocks to scan for a bbt */ /* The maximum number of blocks to scan for a bbt */
#define NAND_BBT_SCAN_MAXBLOCKS 4 #define NAND_BBT_SCAN_MAXBLOCKS 4
extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd); 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_update_bbt(struct mtd_info *mtd, loff_t offs);
extern int nand_default_bbt (struct mtd_info *mtd); 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_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt); extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
extern int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, int allowbbt);
size_t * retlen, uint8_t * buf, uint8_t * oob_buf, extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
struct nand_oobinfo *oobsel, int flags); size_t * retlen, uint8_t * buf);
/* /*
* Constants for oob configuration * Constants for oob configuration
......
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