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
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;
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
uint8_t calc_ecc[6];
volatile u_char dummy;
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
* 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 rtn, retlen;
......@@ -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);
if (state == FL_ERASING) {
for (i = 0; i < 4; i++) {
if (status & 1 << (i + 1)) {
this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);
rtn = this->read_byte(mtd);
this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
er_stat |= 1 << (i + 1); /* err_ecc_not_avail */
}
}
if (!(status & 1 << (i + 1)))
continue;
this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1),
-1, -1);
rtn = this->read_byte(mtd);
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) {
unsigned long corrected = mtd->ecc_stats.corrected;
/* single bank write logic */
this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1);
rtn = this->read_byte(mtd);
this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
er_stat |= 1 << 1; /* err_ecc_not_avail */
} else {
len = mtd->writesize;
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);
}
/* err_ecc_not_avail */
er_stat |= 1 << 1;
goto out;
}
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;
......
......@@ -479,14 +479,14 @@ struct nand_bbt_descr {
/* 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);
extern int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, uint8_t * buf, uint8_t * oob_buf,
struct nand_oobinfo *oobsel, int flags);
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);
extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, uint8_t * buf);
/*
* 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