aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-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