aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/rtc_from4.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/rtc_from4.c')
-rw-r--r--drivers/mtd/nand/rtc_from4.c62
1 files changed, 37 insertions, 25 deletions
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index 6c97bfaea19a..b7083104a05b 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -444,7 +444,8 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
444 * note: see pages 34..37 of data sheet for details. 444 * note: see pages 34..37 of data sheet for details.
445 * 445 *
446 */ 446 */
447static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page) 447static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
448 int state, int status, int page)
448{ 449{
449 int er_stat = 0; 450 int er_stat = 0;
450 int rtn, retlen; 451 int rtn, retlen;
@@ -455,39 +456,50 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s
455 this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1); 456 this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
456 457
457 if (state == FL_ERASING) { 458 if (state == FL_ERASING) {
459
458 for (i = 0; i < 4; i++) { 460 for (i = 0; i < 4; i++) {
459 if (status & 1 << (i + 1)) { 461 if (!(status & 1 << (i + 1)))
460 this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1); 462 continue;
461 rtn = this->read_byte(mtd); 463 this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1),
462 this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); 464 -1, -1);
463 if (!(rtn & ERR_STAT_ECC_AVAILABLE)) { 465 rtn = this->read_byte(mtd);
464 er_stat |= 1 << (i + 1); /* err_ecc_not_avail */ 466 this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
465 } 467
466 } 468 /* err_ecc_not_avail */
469 if (!(rtn & ERR_STAT_ECC_AVAILABLE))
470 er_stat |= 1 << (i + 1);
467 } 471 }
472
468 } else if (state == FL_WRITING) { 473 } else if (state == FL_WRITING) {
474
475 unsigned long corrected = mtd->ecc_stats.corrected;
476
469 /* single bank write logic */ 477 /* single bank write logic */
470 this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1); 478 this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1);
471 rtn = this->read_byte(mtd); 479 rtn = this->read_byte(mtd);
472 this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); 480 this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
481
473 if (!(rtn & ERR_STAT_ECC_AVAILABLE)) { 482 if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
474 er_stat |= 1 << 1; /* err_ecc_not_avail */ 483 /* err_ecc_not_avail */
475 } else { 484 er_stat |= 1 << 1;
476 len = mtd->writesize; 485 goto out;
477 buf = kmalloc(len, GFP_KERNEL);
478 if (!buf) {
479 printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
480 er_stat = 1; /* if we can't check, assume failed */
481 } else {
482 /* recovery read */
483 /* page read */
484 rtn = nand_do_read_ecc(mtd, page, len, &retlen, buf, NULL, this->autooob, 1);
485 if (rtn) { /* if read failed or > 1-bit error corrected */
486 er_stat |= 1 << 1; /* ECC read failed */
487 }
488 kfree(buf);
489 }
490 } 486 }
487
488 len = mtd->writesize;
489 buf = kmalloc(len, GFP_KERNEL);
490 if (!buf) {
491 printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
492 er_stat = 1;
493 goto out;
494 }
495
496 /* recovery read */
497 rtn = nand_do_read(mtd, page, len, &retlen, buf);
498
499 /* if read failed or > 1-bit error corrected */
500 if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) {
501 er_stat |= 1 << 1;
502 kfree(buf);
491 } 503 }
492 504
493 rtn = status; 505 rtn = status;