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.c140
1 files changed, 132 insertions, 8 deletions
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index 02305a2adca7..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.7 2004/11/04 12:53:10 gleixner 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,13 +83,18 @@ 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 */
92static void __iomem *rtc_from4_fio_base = P2SEGADDR(RTC_FROM4_FIO_BASE); 97static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);
93 98
94const static struct mtd_partition partition_info[] = { 99const static struct mtd_partition partition_info[] = {
95 { 100 {
@@ -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
@@ -286,6 +290,40 @@ static int rtc_from4_nand_device_ready(struct mtd_info *mtd)
286 290
287} 291}
288 292
293
294/*
295 * deplete - code to perform device recovery in case there was a power loss
296 * @mtd: MTD device structure
297 * @chip: Chip to select (0 == slot 3, 1 == slot 4)
298 *
299 * If there was a sudden loss of power during an erase operation, a
300 * "device recovery" operation must be performed when power is restored
301 * to ensure correct operation. This routine performs the required steps
302 * for the requested chip.
303 *
304 * See page 86 of the data sheet for details.
305 *
306 */
307static void deplete(struct mtd_info *mtd, int chip)
308{
309 struct nand_chip *this = mtd->priv;
310
311 /* wait until device is ready */
312 while (!this->dev_ready(mtd));
313
314 this->select_chip(mtd, chip);
315
316 /* Send the commands for device recovery, phase 1 */
317 this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);
318 this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);
319
320 /* Send the commands for device recovery, phase 2 */
321 this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);
322 this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);
323
324}
325
326
289#ifdef RTC_FROM4_HWECC 327#ifdef RTC_FROM4_HWECC
290/* 328/*
291 * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function 329 * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function
@@ -329,6 +367,7 @@ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
329 367
330} 368}
331 369
370
332/* 371/*
333 * rtc_from4_calculate_ecc - hardware specific code to read ECC code 372 * rtc_from4_calculate_ecc - hardware specific code to read ECC code
334 * @mtd: MTD device structure 373 * @mtd: MTD device structure
@@ -356,6 +395,7 @@ static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_c
356 ecc_code[7] |= 0x0f; /* set the last four bits (not used) */ 395 ecc_code[7] |= 0x0f; /* set the last four bits (not used) */
357} 396}
358 397
398
359/* 399/*
360 * 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
361 * @mtd: MTD device structure 401 * @mtd: MTD device structure
@@ -365,16 +405,14 @@ static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_c
365 * 405 *
366 * 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
367 * 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
368 * and hopefully correct the error 408 * and hopefully correct the error.
369 * 409 *
370 * For now I use the code, which we read from the FLASH to use the RS lib,
371 * as the syndrom conversion has a unresolved issue.
372 */ 410 */
373static 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)
374{ 412{
375 int i, j, res; 413 int i, j, res;
376 unsigned short status; 414 unsigned short status;
377 uint16_t par[6], syn[6], tmp; 415 uint16_t par[6], syn[6];
378 uint8_t ecc[8]; 416 uint8_t ecc[8];
379 volatile unsigned short *rs_ecc; 417 volatile unsigned short *rs_ecc;
380 418
@@ -416,15 +454,86 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
416 } 454 }
417 455
418 /* Let the library code do its magic.*/ 456 /* Let the library code do its magic.*/
419 res = decode_rs8(rs_decoder, buf, par, 512, syn, 0, NULL, 0xff, NULL); 457 res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL);
420 if (res > 0) { 458 if (res > 0) {
421 DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " 459 DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: "
422 "ECC corrected %d errors on read\n", res); 460 "ECC corrected %d errors on read\n", res);
423 } 461 }
424 return res; 462 return res;
425} 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}
426#endif 534#endif
427 535
536
428/* 537/*
429 * Main initialization routine 538 * Main initialization routine
430 */ 539 */
@@ -432,6 +541,7 @@ int __init rtc_from4_init (void)
432{ 541{
433 struct nand_chip *this; 542 struct nand_chip *this;
434 unsigned short bcr1, bcr2, wcr2; 543 unsigned short bcr1, bcr2, wcr2;
544 int i;
435 545
436 /* Allocate memory for MTD device structure and private data */ 546 /* Allocate memory for MTD device structure and private data */
437 rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), 547 rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip),
@@ -483,6 +593,8 @@ int __init rtc_from4_init (void)
483 593
484 this->eccmode = NAND_ECC_HW8_512; 594 this->eccmode = NAND_ECC_HW8_512;
485 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;
486 /* set the nand_oobinfo to support FPGA H/W error detection */ 598 /* set the nand_oobinfo to support FPGA H/W error detection */
487 this->autooob = &rtc_from4_nand_oobinfo; 599 this->autooob = &rtc_from4_nand_oobinfo;
488 this->enable_hwecc = rtc_from4_enable_hwecc; 600 this->enable_hwecc = rtc_from4_enable_hwecc;
@@ -504,6 +616,18 @@ int __init rtc_from4_init (void)
504 return -ENXIO; 616 return -ENXIO;
505 } 617 }
506 618
619 /* Perform 'device recovery' for each chip in case there was a power loss. */
620 for (i=0; i < this->numchips; i++) {
621 deplete(rtc_from4_mtd, i);
622 }
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
507 /* Register the partitions */ 631 /* Register the partitions */
508 add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS); 632 add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
509 633