aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid A. Marlin <dmarlin@redhat.com>2005-01-24 15:40:15 -0500
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-05-23 06:10:36 -0400
commited3786a599f5639c99dfcceaef1b064ab5e2e9f9 (patch)
tree88330679a6fc7b84853e16e234f44c8d585a67b5
parent068e3c0a002c79a5e3cc7c42cb749c4bb126288c (diff)
[MTD] rtc_from4 error status check, disable virtual erase blocks
Added routine to perform extra error status checks on erase and write failures to determine if errors are correctable. Added option to prevent JFFS2 from using virtual erase blocks. Performed minor cleanup on whitespace and comments. Signed-off-by: David A. Marlin <dmarlin@redhat.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/mtd/nand/rtc_from4.c94
1 files changed, 89 insertions, 5 deletions
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index a4d8d2e62e9e..031051cbde76 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -6,7 +6,7 @@
6 * Derived from drivers/mtd/nand/spia.c 6 * Derived from drivers/mtd/nand/spia.c
7 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) 7 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
8 * 8 *
9 * $Id: rtc_from4.c,v 1.8 2005/01/17 19:44:36 dmarlin Exp $ 9 * $Id: rtc_from4.c,v 1.9 2005/01/24 20:40:11 dmarlin Exp $
10 * 10 *
11 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
@@ -83,9 +83,14 @@ static struct mtd_info *rtc_from4_mtd = NULL;
83#define RTC_FROM4_RS_ECC_CHK (RTC_FROM4_NAND_ADDR_FPGA | 0x00000070) 83#define RTC_FROM4_RS_ECC_CHK (RTC_FROM4_NAND_ADDR_FPGA | 0x00000070)
84#define RTC_FROM4_RS_ECC_CHK_ERROR (1 << 7) 84#define RTC_FROM4_RS_ECC_CHK_ERROR (1 << 7)
85 85
86#define ERR_STAT_ECC_AVAILABLE 0x20
87
86/* Undefine for software ECC */ 88/* Undefine for software ECC */
87#define RTC_FROM4_HWECC 1 89#define RTC_FROM4_HWECC 1
88 90
91/* Define as 1 for no virtual erase blocks (in JFFS2) */
92#define RTC_FROM4_NO_VIRTBLOCKS 0
93
89/* 94/*
90 * Module stuff 95 * Module stuff
91 */ 96 */
@@ -267,7 +272,6 @@ static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip)
267} 272}
268 273
269 274
270
271/* 275/*
272 * rtc_from4_nand_device_ready - hardware specific ready/busy check 276 * rtc_from4_nand_device_ready - hardware specific ready/busy check
273 * @mtd: MTD device structure 277 * @mtd: MTD device structure
@@ -363,6 +367,7 @@ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
363 367
364} 368}
365 369
370
366/* 371/*
367 * rtc_from4_calculate_ecc - hardware specific code to read ECC code 372 * rtc_from4_calculate_ecc - hardware specific code to read ECC code
368 * @mtd: MTD device structure 373 * @mtd: MTD device structure
@@ -390,6 +395,7 @@ static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_c
390 ecc_code[7] |= 0x0f; /* set the last four bits (not used) */ 395 ecc_code[7] |= 0x0f; /* set the last four bits (not used) */
391} 396}
392 397
398
393/* 399/*
394 * rtc_from4_correct_data - hardware specific code to correct data using ECC code 400 * rtc_from4_correct_data - hardware specific code to correct data using ECC code
395 * @mtd: MTD device structure 401 * @mtd: MTD device structure
@@ -399,10 +405,8 @@ static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_c
399 * 405 *
400 * The FPGA tells us fast, if there's an error or not. If no, we go back happy 406 * The FPGA tells us fast, if there's an error or not. If no, we go back happy
401 * else we read the ecc results from the fpga and call the rs library to decode 407 * else we read the ecc results from the fpga and call the rs library to decode
402 * and hopefully correct the error 408 * and hopefully correct the error.
403 * 409 *
404 * For now I use the code, which we read from the FLASH to use the RS lib,
405 * as the syndrom conversion has a unresolved issue.
406 */ 410 */
407static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2) 411static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2)
408{ 412{
@@ -457,8 +461,79 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
457 } 461 }
458 return res; 462 return res;
459} 463}
464
465
466/**
467 * rtc_from4_errstat - perform additional error status checks
468 * @mtd: MTD device structure
469 * @this: NAND chip structure
470 * @state: state or the operation
471 * @status: status code returned from read status
472 * @page: startpage inside the chip, must be called with (page & this->pagemask)
473 *
474 * Perform additional error status checks on erase and write failures
475 * to determine if errors are correctable. For this device, correctable
476 * 1-bit errors on erase and write are considered acceptable.
477 *
478 * note: see pages 34..37 of data sheet for details.
479 *
480 */
481static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page)
482{
483 int er_stat=0;
484 int rtn, retlen;
485 size_t len;
486 uint8_t *buf;
487 int i;
488
489 this->cmdfunc (mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
490
491 if (state == FL_ERASING) {
492 for (i=0; i<4; i++) {
493 if (status & 1<<(i+1)) {
494 this->cmdfunc (mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);
495 rtn = this->read_byte(mtd);
496 this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
497 if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
498 er_stat |= 1<<(i+1); /* err_ecc_not_avail */
499 }
500 }
501 }
502 } else if (state == FL_WRITING) {
503 /* single bank write logic */
504 this->cmdfunc (mtd, NAND_CMD_STATUS_ERROR, -1, -1);
505 rtn = this->read_byte(mtd);
506 this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
507 if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
508 er_stat |= 1<<1; /* err_ecc_not_avail */
509 } else {
510 len = mtd->oobblock;
511 buf = kmalloc (len, GFP_KERNEL);
512 if (!buf) {
513 printk (KERN_ERR "rtc_from4_errstat: Out of memory!\n");
514 er_stat = 1; /* if we can't check, assume failed */
515 } else {
516 /* recovery read */
517 /* page read */
518 rtn = nand_do_read_ecc (mtd, page, len, &retlen, buf, NULL, this->autooob, 1);
519 if (rtn) { /* if read failed or > 1-bit error corrected */
520 er_stat |= 1<<1; /* ECC read failed */
521 }
522 kfree(buf);
523 }
524 }
525 }
526
527 rtn = status;
528 if (er_stat == 0) { /* if ECC is available */
529 rtn = (status & ~NAND_STATUS_FAIL); /* clear the error bit */
530 }
531
532 return rtn;
533}
460#endif 534#endif
461 535
536
462/* 537/*
463 * Main initialization routine 538 * Main initialization routine
464 */ 539 */
@@ -518,6 +593,8 @@ int __init rtc_from4_init (void)
518 593
519 this->eccmode = NAND_ECC_HW8_512; 594 this->eccmode = NAND_ECC_HW8_512;
520 this->options |= NAND_HWECC_SYNDROME; 595 this->options |= NAND_HWECC_SYNDROME;
596 /* return the status of extra status and ECC checks */
597 this->errstat = rtc_from4_errstat;
521 /* set the nand_oobinfo to support FPGA H/W error detection */ 598 /* set the nand_oobinfo to support FPGA H/W error detection */
522 this->autooob = &rtc_from4_nand_oobinfo; 599 this->autooob = &rtc_from4_nand_oobinfo;
523 this->enable_hwecc = rtc_from4_enable_hwecc; 600 this->enable_hwecc = rtc_from4_enable_hwecc;
@@ -544,6 +621,13 @@ int __init rtc_from4_init (void)
544 deplete(rtc_from4_mtd, i); 621 deplete(rtc_from4_mtd, i);
545 } 622 }
546 623
624#if RTC_FROM4_NO_VIRTBLOCKS
625 /* use a smaller erase block to minimize wasted space when a block is bad */
626 /* note: this uses eight times as much RAM as using the default and makes */
627 /* mounts take four times as long. */
628 rtc_from4_mtd->flags |= MTD_NO_VIRTBLOCKS;
629#endif
630
547 /* Register the partitions */ 631 /* Register the partitions */
548 add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS); 632 add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
549 633