diff options
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 299 |
1 files changed, 215 insertions, 84 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 44d5b128911f..1bd71a598c79 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -28,6 +28,24 @@ | |||
28 | * among multiple independend devices. Suggestions and initial patch | 28 | * among multiple independend devices. Suggestions and initial patch |
29 | * from Ben Dooks <ben-mtd@fluff.org> | 29 | * from Ben Dooks <ben-mtd@fluff.org> |
30 | * | 30 | * |
31 | * 12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb" issue. | ||
32 | * Basically, any block not rewritten may lose data when surrounding blocks | ||
33 | * are rewritten many times. JFFS2 ensures this doesn't happen for blocks | ||
34 | * it uses, but the Bad Block Table(s) may not be rewritten. To ensure they | ||
35 | * do not lose data, force them to be rewritten when some of the surrounding | ||
36 | * blocks are erased. Rather than tracking a specific nearby block (which | ||
37 | * could itself go bad), use a page address 'mask' to select several blocks | ||
38 | * in the same area, and rewrite the BBT when any of them are erased. | ||
39 | * | ||
40 | * 01-03-2005 dmarlin: added support for the device recovery command sequence for Renesas | ||
41 | * AG-AND chips. If there was a sudden loss of power during an erase operation, | ||
42 | * a "device recovery" operation must be performed when power is restored | ||
43 | * to ensure correct operation. | ||
44 | * | ||
45 | * 01-20-2005 dmarlin: added support for optional hardware specific callback routine to | ||
46 | * perform extra error status checks on erase and write failures. This required | ||
47 | * adding a wrapper function for nand_read_ecc. | ||
48 | * | ||
31 | * Credits: | 49 | * Credits: |
32 | * David Woodhouse for adding multichip support | 50 | * David Woodhouse for adding multichip support |
33 | * | 51 | * |
@@ -41,7 +59,7 @@ | |||
41 | * The AG-AND chips have nice features for speed improvement, | 59 | * The AG-AND chips have nice features for speed improvement, |
42 | * which are not supported yet. Read / program 4 pages in one go. | 60 | * which are not supported yet. Read / program 4 pages in one go. |
43 | * | 61 | * |
44 | * $Id: nand_base.c,v 1.126 2004/12/13 11:22:25 lavinen Exp $ | 62 | * $Id: nand_base.c,v 1.146 2005/06/17 15:02:06 gleixner Exp $ |
45 | * | 63 | * |
46 | * This program is free software; you can redistribute it and/or modify | 64 | * This program is free software; you can redistribute it and/or modify |
47 | * it under the terms of the GNU General Public License version 2 as | 65 | * it under the terms of the GNU General Public License version 2 as |
@@ -149,17 +167,21 @@ static void nand_release_device (struct mtd_info *mtd) | |||
149 | 167 | ||
150 | /* De-select the NAND device */ | 168 | /* De-select the NAND device */ |
151 | this->select_chip(mtd, -1); | 169 | this->select_chip(mtd, -1); |
152 | /* Do we have a hardware controller ? */ | 170 | |
153 | if (this->controller) { | 171 | if (this->controller) { |
172 | /* Release the controller and the chip */ | ||
154 | spin_lock(&this->controller->lock); | 173 | spin_lock(&this->controller->lock); |
155 | this->controller->active = NULL; | 174 | this->controller->active = NULL; |
175 | this->state = FL_READY; | ||
176 | wake_up(&this->controller->wq); | ||
156 | spin_unlock(&this->controller->lock); | 177 | spin_unlock(&this->controller->lock); |
178 | } else { | ||
179 | /* Release the chip */ | ||
180 | spin_lock(&this->chip_lock); | ||
181 | this->state = FL_READY; | ||
182 | wake_up(&this->wq); | ||
183 | spin_unlock(&this->chip_lock); | ||
157 | } | 184 | } |
158 | /* Release the chip */ | ||
159 | spin_lock (&this->chip_lock); | ||
160 | this->state = FL_READY; | ||
161 | wake_up (&this->wq); | ||
162 | spin_unlock (&this->chip_lock); | ||
163 | } | 185 | } |
164 | 186 | ||
165 | /** | 187 | /** |
@@ -443,7 +465,8 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
443 | 465 | ||
444 | /* Get block number */ | 466 | /* Get block number */ |
445 | block = ((int) ofs) >> this->bbt_erase_shift; | 467 | block = ((int) ofs) >> this->bbt_erase_shift; |
446 | this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); | 468 | if (this->bbt) |
469 | this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); | ||
447 | 470 | ||
448 | /* Do we have a flash based bad block table ? */ | 471 | /* Do we have a flash based bad block table ? */ |
449 | if (this->options & NAND_USE_FLASH_BBT) | 472 | if (this->options & NAND_USE_FLASH_BBT) |
@@ -466,7 +489,7 @@ static int nand_check_wp (struct mtd_info *mtd) | |||
466 | struct nand_chip *this = mtd->priv; | 489 | struct nand_chip *this = mtd->priv; |
467 | /* Check the WP bit */ | 490 | /* Check the WP bit */ |
468 | this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); | 491 | this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); |
469 | return (this->read_byte(mtd) & 0x80) ? 0 : 1; | 492 | return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; |
470 | } | 493 | } |
471 | 494 | ||
472 | /** | 495 | /** |
@@ -490,6 +513,22 @@ static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, i | |||
490 | return nand_isbad_bbt (mtd, ofs, allowbbt); | 513 | return nand_isbad_bbt (mtd, ofs, allowbbt); |
491 | } | 514 | } |
492 | 515 | ||
516 | /* | ||
517 | * Wait for the ready pin, after a command | ||
518 | * The timeout is catched later. | ||
519 | */ | ||
520 | static void nand_wait_ready(struct mtd_info *mtd) | ||
521 | { | ||
522 | struct nand_chip *this = mtd->priv; | ||
523 | unsigned long timeo = jiffies + 2; | ||
524 | |||
525 | /* wait until command is processed or timeout occures */ | ||
526 | do { | ||
527 | if (this->dev_ready(mtd)) | ||
528 | return; | ||
529 | } while (time_before(jiffies, timeo)); | ||
530 | } | ||
531 | |||
493 | /** | 532 | /** |
494 | * nand_command - [DEFAULT] Send command to NAND device | 533 | * nand_command - [DEFAULT] Send command to NAND device |
495 | * @mtd: MTD device structure | 534 | * @mtd: MTD device structure |
@@ -571,7 +610,7 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in | |||
571 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 610 | this->hwcontrol(mtd, NAND_CTL_SETCLE); |
572 | this->write_byte(mtd, NAND_CMD_STATUS); | 611 | this->write_byte(mtd, NAND_CMD_STATUS); |
573 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | 612 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); |
574 | while ( !(this->read_byte(mtd) & 0x40)); | 613 | while ( !(this->read_byte(mtd) & NAND_STATUS_READY)); |
575 | return; | 614 | return; |
576 | 615 | ||
577 | /* This applies to read commands */ | 616 | /* This applies to read commands */ |
@@ -585,12 +624,11 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in | |||
585 | return; | 624 | return; |
586 | } | 625 | } |
587 | } | 626 | } |
588 | |||
589 | /* Apply this short delay always to ensure that we do wait tWB in | 627 | /* Apply this short delay always to ensure that we do wait tWB in |
590 | * any case on any machine. */ | 628 | * any case on any machine. */ |
591 | ndelay (100); | 629 | ndelay (100); |
592 | /* wait until command is processed */ | 630 | |
593 | while (!this->dev_ready(mtd)); | 631 | nand_wait_ready(mtd); |
594 | } | 632 | } |
595 | 633 | ||
596 | /** | 634 | /** |
@@ -619,7 +657,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
619 | /* Begin command latch cycle */ | 657 | /* Begin command latch cycle */ |
620 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 658 | this->hwcontrol(mtd, NAND_CTL_SETCLE); |
621 | /* Write out the command to the device. */ | 659 | /* Write out the command to the device. */ |
622 | this->write_byte(mtd, command); | 660 | this->write_byte(mtd, (command & 0xff)); |
623 | /* End command latch cycle */ | 661 | /* End command latch cycle */ |
624 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | 662 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); |
625 | 663 | ||
@@ -647,8 +685,8 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
647 | 685 | ||
648 | /* | 686 | /* |
649 | * program and erase have their own busy handlers | 687 | * program and erase have their own busy handlers |
650 | * status and sequential in needs no delay | 688 | * status, sequential in, and deplete1 need no delay |
651 | */ | 689 | */ |
652 | switch (command) { | 690 | switch (command) { |
653 | 691 | ||
654 | case NAND_CMD_CACHEDPROG: | 692 | case NAND_CMD_CACHEDPROG: |
@@ -657,8 +695,19 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
657 | case NAND_CMD_ERASE2: | 695 | case NAND_CMD_ERASE2: |
658 | case NAND_CMD_SEQIN: | 696 | case NAND_CMD_SEQIN: |
659 | case NAND_CMD_STATUS: | 697 | case NAND_CMD_STATUS: |
698 | case NAND_CMD_DEPLETE1: | ||
660 | return; | 699 | return; |
661 | 700 | ||
701 | /* | ||
702 | * read error status commands require only a short delay | ||
703 | */ | ||
704 | case NAND_CMD_STATUS_ERROR: | ||
705 | case NAND_CMD_STATUS_ERROR0: | ||
706 | case NAND_CMD_STATUS_ERROR1: | ||
707 | case NAND_CMD_STATUS_ERROR2: | ||
708 | case NAND_CMD_STATUS_ERROR3: | ||
709 | udelay(this->chip_delay); | ||
710 | return; | ||
662 | 711 | ||
663 | case NAND_CMD_RESET: | 712 | case NAND_CMD_RESET: |
664 | if (this->dev_ready) | 713 | if (this->dev_ready) |
@@ -667,7 +716,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
667 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 716 | this->hwcontrol(mtd, NAND_CTL_SETCLE); |
668 | this->write_byte(mtd, NAND_CMD_STATUS); | 717 | this->write_byte(mtd, NAND_CMD_STATUS); |
669 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | 718 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); |
670 | while ( !(this->read_byte(mtd) & 0x40)); | 719 | while ( !(this->read_byte(mtd) & NAND_STATUS_READY)); |
671 | return; | 720 | return; |
672 | 721 | ||
673 | case NAND_CMD_READ0: | 722 | case NAND_CMD_READ0: |
@@ -690,12 +739,12 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
690 | return; | 739 | return; |
691 | } | 740 | } |
692 | } | 741 | } |
693 | 742 | ||
694 | /* Apply this short delay always to ensure that we do wait tWB in | 743 | /* Apply this short delay always to ensure that we do wait tWB in |
695 | * any case on any machine. */ | 744 | * any case on any machine. */ |
696 | ndelay (100); | 745 | ndelay (100); |
697 | /* wait until command is processed */ | 746 | |
698 | while (!this->dev_ready(mtd)); | 747 | nand_wait_ready(mtd); |
699 | } | 748 | } |
700 | 749 | ||
701 | /** | 750 | /** |
@@ -708,37 +757,34 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
708 | */ | 757 | */ |
709 | static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) | 758 | static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) |
710 | { | 759 | { |
711 | struct nand_chip *active = this; | 760 | struct nand_chip *active; |
712 | 761 | spinlock_t *lock; | |
762 | wait_queue_head_t *wq; | ||
713 | DECLARE_WAITQUEUE (wait, current); | 763 | DECLARE_WAITQUEUE (wait, current); |
714 | 764 | ||
715 | /* | 765 | lock = (this->controller) ? &this->controller->lock : &this->chip_lock; |
716 | * Grab the lock and see if the device is available | 766 | wq = (this->controller) ? &this->controller->wq : &this->wq; |
717 | */ | ||
718 | retry: | 767 | retry: |
768 | active = this; | ||
769 | spin_lock(lock); | ||
770 | |||
719 | /* Hardware controller shared among independend devices */ | 771 | /* Hardware controller shared among independend devices */ |
720 | if (this->controller) { | 772 | if (this->controller) { |
721 | spin_lock (&this->controller->lock); | ||
722 | if (this->controller->active) | 773 | if (this->controller->active) |
723 | active = this->controller->active; | 774 | active = this->controller->active; |
724 | else | 775 | else |
725 | this->controller->active = this; | 776 | this->controller->active = this; |
726 | spin_unlock (&this->controller->lock); | ||
727 | } | 777 | } |
728 | 778 | if (active == this && this->state == FL_READY) { | |
729 | if (active == this) { | 779 | this->state = new_state; |
730 | spin_lock (&this->chip_lock); | 780 | spin_unlock(lock); |
731 | if (this->state == FL_READY) { | 781 | return; |
732 | this->state = new_state; | 782 | } |
733 | spin_unlock (&this->chip_lock); | 783 | set_current_state(TASK_UNINTERRUPTIBLE); |
734 | return; | 784 | add_wait_queue(wq, &wait); |
735 | } | 785 | spin_unlock(lock); |
736 | } | 786 | schedule(); |
737 | set_current_state (TASK_UNINTERRUPTIBLE); | 787 | remove_wait_queue(wq, &wait); |
738 | add_wait_queue (&active->wq, &wait); | ||
739 | spin_unlock (&active->chip_lock); | ||
740 | schedule (); | ||
741 | remove_wait_queue (&active->wq, &wait); | ||
742 | goto retry; | 788 | goto retry; |
743 | } | 789 | } |
744 | 790 | ||
@@ -785,7 +831,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | |||
785 | if (this->read_byte(mtd) & NAND_STATUS_READY) | 831 | if (this->read_byte(mtd) & NAND_STATUS_READY) |
786 | break; | 832 | break; |
787 | } | 833 | } |
788 | yield (); | 834 | cond_resched(); |
789 | } | 835 | } |
790 | status = (int) this->read_byte(mtd); | 836 | status = (int) this->read_byte(mtd); |
791 | return status; | 837 | return status; |
@@ -871,8 +917,14 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa | |||
871 | if (!cached) { | 917 | if (!cached) { |
872 | /* call wait ready function */ | 918 | /* call wait ready function */ |
873 | status = this->waitfunc (mtd, this, FL_WRITING); | 919 | status = this->waitfunc (mtd, this, FL_WRITING); |
920 | |||
921 | /* See if operation failed and additional status checks are available */ | ||
922 | if ((status & NAND_STATUS_FAIL) && (this->errstat)) { | ||
923 | status = this->errstat(mtd, this, FL_WRITING, status, page); | ||
924 | } | ||
925 | |||
874 | /* See if device thinks it succeeded */ | 926 | /* See if device thinks it succeeded */ |
875 | if (status & 0x01) { | 927 | if (status & NAND_STATUS_FAIL) { |
876 | DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page); | 928 | DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page); |
877 | return -EIO; | 929 | return -EIO; |
878 | } | 930 | } |
@@ -975,7 +1027,7 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int | |||
975 | if (!this->dev_ready) | 1027 | if (!this->dev_ready) |
976 | udelay (this->chip_delay); | 1028 | udelay (this->chip_delay); |
977 | else | 1029 | else |
978 | while (!this->dev_ready(mtd)); | 1030 | nand_wait_ready(mtd); |
979 | 1031 | ||
980 | /* All done, return happy */ | 1032 | /* All done, return happy */ |
981 | if (!numpages) | 1033 | if (!numpages) |
@@ -997,23 +1049,24 @@ out: | |||
997 | #endif | 1049 | #endif |
998 | 1050 | ||
999 | /** | 1051 | /** |
1000 | * nand_read - [MTD Interface] MTD compability function for nand_read_ecc | 1052 | * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc |
1001 | * @mtd: MTD device structure | 1053 | * @mtd: MTD device structure |
1002 | * @from: offset to read from | 1054 | * @from: offset to read from |
1003 | * @len: number of bytes to read | 1055 | * @len: number of bytes to read |
1004 | * @retlen: pointer to variable to store the number of read bytes | 1056 | * @retlen: pointer to variable to store the number of read bytes |
1005 | * @buf: the databuffer to put data | 1057 | * @buf: the databuffer to put data |
1006 | * | 1058 | * |
1007 | * This function simply calls nand_read_ecc with oob buffer and oobsel = NULL | 1059 | * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL |
1008 | */ | 1060 | * and flags = 0xff |
1061 | */ | ||
1009 | static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) | 1062 | static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) |
1010 | { | 1063 | { |
1011 | return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL); | 1064 | return nand_do_read_ecc (mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff); |
1012 | } | 1065 | } |
1013 | 1066 | ||
1014 | 1067 | ||
1015 | /** | 1068 | /** |
1016 | * nand_read_ecc - [MTD Interface] Read data with ECC | 1069 | * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc |
1017 | * @mtd: MTD device structure | 1070 | * @mtd: MTD device structure |
1018 | * @from: offset to read from | 1071 | * @from: offset to read from |
1019 | * @len: number of bytes to read | 1072 | * @len: number of bytes to read |
@@ -1022,11 +1075,39 @@ static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * re | |||
1022 | * @oob_buf: filesystem supplied oob data buffer | 1075 | * @oob_buf: filesystem supplied oob data buffer |
1023 | * @oobsel: oob selection structure | 1076 | * @oobsel: oob selection structure |
1024 | * | 1077 | * |
1025 | * NAND read with ECC | 1078 | * This function simply calls nand_do_read_ecc with flags = 0xff |
1026 | */ | 1079 | */ |
1027 | static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | 1080 | static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, |
1028 | size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel) | 1081 | size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel) |
1029 | { | 1082 | { |
1083 | /* use userspace supplied oobinfo, if zero */ | ||
1084 | if (oobsel == NULL) | ||
1085 | oobsel = &mtd->oobinfo; | ||
1086 | return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff); | ||
1087 | } | ||
1088 | |||
1089 | |||
1090 | /** | ||
1091 | * nand_do_read_ecc - [MTD Interface] Read data with ECC | ||
1092 | * @mtd: MTD device structure | ||
1093 | * @from: offset to read from | ||
1094 | * @len: number of bytes to read | ||
1095 | * @retlen: pointer to variable to store the number of read bytes | ||
1096 | * @buf: the databuffer to put data | ||
1097 | * @oob_buf: filesystem supplied oob data buffer (can be NULL) | ||
1098 | * @oobsel: oob selection structure | ||
1099 | * @flags: flag to indicate if nand_get_device/nand_release_device should be preformed | ||
1100 | * and how many corrected error bits are acceptable: | ||
1101 | * bits 0..7 - number of tolerable errors | ||
1102 | * bit 8 - 0 == do not get/release chip, 1 == get/release chip | ||
1103 | * | ||
1104 | * NAND read with ECC | ||
1105 | */ | ||
1106 | int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | ||
1107 | size_t * retlen, u_char * buf, u_char * oob_buf, | ||
1108 | struct nand_oobinfo *oobsel, int flags) | ||
1109 | { | ||
1110 | |||
1030 | int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1; | 1111 | int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1; |
1031 | int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0; | 1112 | int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0; |
1032 | struct nand_chip *this = mtd->priv; | 1113 | struct nand_chip *this = mtd->priv; |
@@ -1051,12 +1132,9 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1051 | } | 1132 | } |
1052 | 1133 | ||
1053 | /* Grab the lock and see if the device is available */ | 1134 | /* Grab the lock and see if the device is available */ |
1054 | nand_get_device (this, mtd ,FL_READING); | 1135 | if (flags & NAND_GET_DEVICE) |
1136 | nand_get_device (this, mtd, FL_READING); | ||
1055 | 1137 | ||
1056 | /* use userspace supplied oobinfo, if zero */ | ||
1057 | if (oobsel == NULL) | ||
1058 | oobsel = &mtd->oobinfo; | ||
1059 | |||
1060 | /* Autoplace of oob data ? Use the default placement scheme */ | 1138 | /* Autoplace of oob data ? Use the default placement scheme */ |
1061 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) | 1139 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) |
1062 | oobsel = this->autooob; | 1140 | oobsel = this->autooob; |
@@ -1118,7 +1196,8 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1118 | } | 1196 | } |
1119 | 1197 | ||
1120 | /* get oob area, if we have no oob buffer from fs-driver */ | 1198 | /* get oob area, if we have no oob buffer from fs-driver */ |
1121 | if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE) | 1199 | if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE || |
1200 | oobsel->useecc == MTD_NANDECC_AUTOPL_USR) | ||
1122 | oob_data = &this->data_buf[end]; | 1201 | oob_data = &this->data_buf[end]; |
1123 | 1202 | ||
1124 | eccsteps = this->eccsteps; | 1203 | eccsteps = this->eccsteps; |
@@ -1155,7 +1234,8 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1155 | /* We calc error correction directly, it checks the hw | 1234 | /* We calc error correction directly, it checks the hw |
1156 | * generator for an error, reads back the syndrome and | 1235 | * generator for an error, reads back the syndrome and |
1157 | * does the error correction on the fly */ | 1236 | * does the error correction on the fly */ |
1158 | if (this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]) == -1) { | 1237 | ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]); |
1238 | if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { | ||
1159 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " | 1239 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " |
1160 | "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); | 1240 | "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); |
1161 | ecc_failed++; | 1241 | ecc_failed++; |
@@ -1194,7 +1274,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1194 | p[i] = ecc_status; | 1274 | p[i] = ecc_status; |
1195 | } | 1275 | } |
1196 | 1276 | ||
1197 | if (ecc_status == -1) { | 1277 | if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { |
1198 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); | 1278 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); |
1199 | ecc_failed++; | 1279 | ecc_failed++; |
1200 | } | 1280 | } |
@@ -1206,14 +1286,14 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1206 | /* without autoplace. Legacy mode used by YAFFS1 */ | 1286 | /* without autoplace. Legacy mode used by YAFFS1 */ |
1207 | switch(oobsel->useecc) { | 1287 | switch(oobsel->useecc) { |
1208 | case MTD_NANDECC_AUTOPLACE: | 1288 | case MTD_NANDECC_AUTOPLACE: |
1289 | case MTD_NANDECC_AUTOPL_USR: | ||
1209 | /* Walk through the autoplace chunks */ | 1290 | /* Walk through the autoplace chunks */ |
1210 | for (i = 0, j = 0; j < mtd->oobavail; i++) { | 1291 | for (i = 0; oobsel->oobfree[i][1]; i++) { |
1211 | int from = oobsel->oobfree[i][0]; | 1292 | int from = oobsel->oobfree[i][0]; |
1212 | int num = oobsel->oobfree[i][1]; | 1293 | int num = oobsel->oobfree[i][1]; |
1213 | memcpy(&oob_buf[oob], &oob_data[from], num); | 1294 | memcpy(&oob_buf[oob], &oob_data[from], num); |
1214 | j+= num; | 1295 | oob += num; |
1215 | } | 1296 | } |
1216 | oob += mtd->oobavail; | ||
1217 | break; | 1297 | break; |
1218 | case MTD_NANDECC_PLACE: | 1298 | case MTD_NANDECC_PLACE: |
1219 | /* YAFFS1 legacy mode */ | 1299 | /* YAFFS1 legacy mode */ |
@@ -1239,7 +1319,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1239 | if (!this->dev_ready) | 1319 | if (!this->dev_ready) |
1240 | udelay (this->chip_delay); | 1320 | udelay (this->chip_delay); |
1241 | else | 1321 | else |
1242 | while (!this->dev_ready(mtd)); | 1322 | nand_wait_ready(mtd); |
1243 | 1323 | ||
1244 | if (read == len) | 1324 | if (read == len) |
1245 | break; | 1325 | break; |
@@ -1264,7 +1344,8 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1264 | } | 1344 | } |
1265 | 1345 | ||
1266 | /* Deselect and wake up anyone waiting on the device */ | 1346 | /* Deselect and wake up anyone waiting on the device */ |
1267 | nand_release_device(mtd); | 1347 | if (flags & NAND_GET_DEVICE) |
1348 | nand_release_device(mtd); | ||
1268 | 1349 | ||
1269 | /* | 1350 | /* |
1270 | * Return success, if no ECC failures, else -EBADMSG | 1351 | * Return success, if no ECC failures, else -EBADMSG |
@@ -1337,7 +1418,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t | |||
1337 | if (!this->dev_ready) | 1418 | if (!this->dev_ready) |
1338 | udelay (this->chip_delay); | 1419 | udelay (this->chip_delay); |
1339 | else | 1420 | else |
1340 | while (!this->dev_ready(mtd)); | 1421 | nand_wait_ready(mtd); |
1341 | 1422 | ||
1342 | /* Read more ? */ | 1423 | /* Read more ? */ |
1343 | if (i < len) { | 1424 | if (i < len) { |
@@ -1417,7 +1498,7 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, | |||
1417 | if (!this->dev_ready) | 1498 | if (!this->dev_ready) |
1418 | udelay (this->chip_delay); | 1499 | udelay (this->chip_delay); |
1419 | else | 1500 | else |
1420 | while (!this->dev_ready(mtd)); | 1501 | nand_wait_ready(mtd); |
1421 | 1502 | ||
1422 | /* Check, if the chip supports auto page increment */ | 1503 | /* Check, if the chip supports auto page increment */ |
1423 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) | 1504 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) |
@@ -1567,6 +1648,8 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
1567 | oobsel = this->autooob; | 1648 | oobsel = this->autooob; |
1568 | autoplace = 1; | 1649 | autoplace = 1; |
1569 | } | 1650 | } |
1651 | if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) | ||
1652 | autoplace = 1; | ||
1570 | 1653 | ||
1571 | /* Setup variables and oob buffer */ | 1654 | /* Setup variables and oob buffer */ |
1572 | totalpages = len >> this->page_shift; | 1655 | totalpages = len >> this->page_shift; |
@@ -1733,7 +1816,7 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * | |||
1733 | status = this->waitfunc (mtd, this, FL_WRITING); | 1816 | status = this->waitfunc (mtd, this, FL_WRITING); |
1734 | 1817 | ||
1735 | /* See if device thinks it succeeded */ | 1818 | /* See if device thinks it succeeded */ |
1736 | if (status & 0x01) { | 1819 | if (status & NAND_STATUS_FAIL) { |
1737 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page); | 1820 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page); |
1738 | ret = -EIO; | 1821 | ret = -EIO; |
1739 | goto out; | 1822 | goto out; |
@@ -1841,6 +1924,8 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig | |||
1841 | oobsel = this->autooob; | 1924 | oobsel = this->autooob; |
1842 | autoplace = 1; | 1925 | autoplace = 1; |
1843 | } | 1926 | } |
1927 | if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) | ||
1928 | autoplace = 1; | ||
1844 | 1929 | ||
1845 | /* Setup start page */ | 1930 | /* Setup start page */ |
1846 | page = (int) (to >> this->page_shift); | 1931 | page = (int) (to >> this->page_shift); |
@@ -1987,6 +2072,7 @@ static int nand_erase (struct mtd_info *mtd, struct erase_info *instr) | |||
1987 | return nand_erase_nand (mtd, instr, 0); | 2072 | return nand_erase_nand (mtd, instr, 0); |
1988 | } | 2073 | } |
1989 | 2074 | ||
2075 | #define BBT_PAGE_MASK 0xffffff3f | ||
1990 | /** | 2076 | /** |
1991 | * nand_erase_intern - [NAND Interface] erase block(s) | 2077 | * nand_erase_intern - [NAND Interface] erase block(s) |
1992 | * @mtd: MTD device structure | 2078 | * @mtd: MTD device structure |
@@ -1999,6 +2085,10 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb | |||
1999 | { | 2085 | { |
2000 | int page, len, status, pages_per_block, ret, chipnr; | 2086 | int page, len, status, pages_per_block, ret, chipnr; |
2001 | struct nand_chip *this = mtd->priv; | 2087 | struct nand_chip *this = mtd->priv; |
2088 | int rewrite_bbt[NAND_MAX_CHIPS]={0}; /* flags to indicate the page, if bbt needs to be rewritten. */ | ||
2089 | unsigned int bbt_masked_page; /* bbt mask to compare to page being erased. */ | ||
2090 | /* It is used to see if the current page is in the same */ | ||
2091 | /* 256 block group and the same bank as the bbt. */ | ||
2002 | 2092 | ||
2003 | DEBUG (MTD_DEBUG_LEVEL3, | 2093 | DEBUG (MTD_DEBUG_LEVEL3, |
2004 | "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); | 2094 | "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); |
@@ -2044,6 +2134,13 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb | |||
2044 | goto erase_exit; | 2134 | goto erase_exit; |
2045 | } | 2135 | } |
2046 | 2136 | ||
2137 | /* if BBT requires refresh, set the BBT page mask to see if the BBT should be rewritten */ | ||
2138 | if (this->options & BBT_AUTO_REFRESH) { | ||
2139 | bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK; | ||
2140 | } else { | ||
2141 | bbt_masked_page = 0xffffffff; /* should not match anything */ | ||
2142 | } | ||
2143 | |||
2047 | /* Loop through the pages */ | 2144 | /* Loop through the pages */ |
2048 | len = instr->len; | 2145 | len = instr->len; |
2049 | 2146 | ||
@@ -2066,13 +2163,26 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb | |||
2066 | 2163 | ||
2067 | status = this->waitfunc (mtd, this, FL_ERASING); | 2164 | status = this->waitfunc (mtd, this, FL_ERASING); |
2068 | 2165 | ||
2166 | /* See if operation failed and additional status checks are available */ | ||
2167 | if ((status & NAND_STATUS_FAIL) && (this->errstat)) { | ||
2168 | status = this->errstat(mtd, this, FL_ERASING, status, page); | ||
2169 | } | ||
2170 | |||
2069 | /* See if block erase succeeded */ | 2171 | /* See if block erase succeeded */ |
2070 | if (status & 0x01) { | 2172 | if (status & NAND_STATUS_FAIL) { |
2071 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page); | 2173 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page); |
2072 | instr->state = MTD_ERASE_FAILED; | 2174 | instr->state = MTD_ERASE_FAILED; |
2073 | instr->fail_addr = (page << this->page_shift); | 2175 | instr->fail_addr = (page << this->page_shift); |
2074 | goto erase_exit; | 2176 | goto erase_exit; |
2075 | } | 2177 | } |
2178 | |||
2179 | /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */ | ||
2180 | if (this->options & BBT_AUTO_REFRESH) { | ||
2181 | if (((page & BBT_PAGE_MASK) == bbt_masked_page) && | ||
2182 | (page != this->bbt_td->pages[chipnr])) { | ||
2183 | rewrite_bbt[chipnr] = (page << this->page_shift); | ||
2184 | } | ||
2185 | } | ||
2076 | 2186 | ||
2077 | /* Increment page address and decrement length */ | 2187 | /* Increment page address and decrement length */ |
2078 | len -= (1 << this->phys_erase_shift); | 2188 | len -= (1 << this->phys_erase_shift); |
@@ -2083,6 +2193,13 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb | |||
2083 | chipnr++; | 2193 | chipnr++; |
2084 | this->select_chip(mtd, -1); | 2194 | this->select_chip(mtd, -1); |
2085 | this->select_chip(mtd, chipnr); | 2195 | this->select_chip(mtd, chipnr); |
2196 | |||
2197 | /* if BBT requires refresh and BBT-PERCHIP, | ||
2198 | * set the BBT page mask to see if this BBT should be rewritten */ | ||
2199 | if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) { | ||
2200 | bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK; | ||
2201 | } | ||
2202 | |||
2086 | } | 2203 | } |
2087 | } | 2204 | } |
2088 | instr->state = MTD_ERASE_DONE; | 2205 | instr->state = MTD_ERASE_DONE; |
@@ -2097,6 +2214,18 @@ erase_exit: | |||
2097 | /* Deselect and wake up anyone waiting on the device */ | 2214 | /* Deselect and wake up anyone waiting on the device */ |
2098 | nand_release_device(mtd); | 2215 | nand_release_device(mtd); |
2099 | 2216 | ||
2217 | /* if BBT requires refresh and erase was successful, rewrite any selected bad block tables */ | ||
2218 | if ((this->options & BBT_AUTO_REFRESH) && (!ret)) { | ||
2219 | for (chipnr = 0; chipnr < this->numchips; chipnr++) { | ||
2220 | if (rewrite_bbt[chipnr]) { | ||
2221 | /* update the BBT for chip */ | ||
2222 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n", | ||
2223 | chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]); | ||
2224 | nand_update_bbt (mtd, rewrite_bbt[chipnr]); | ||
2225 | } | ||
2226 | } | ||
2227 | } | ||
2228 | |||
2100 | /* Return more or less happy */ | 2229 | /* Return more or less happy */ |
2101 | return ret; | 2230 | return ret; |
2102 | } | 2231 | } |
@@ -2168,7 +2297,7 @@ static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs) | |||
2168 | */ | 2297 | */ |
2169 | int nand_scan (struct mtd_info *mtd, int maxchips) | 2298 | int nand_scan (struct mtd_info *mtd, int maxchips) |
2170 | { | 2299 | { |
2171 | int i, j, nand_maf_id, nand_dev_id, busw; | 2300 | int i, nand_maf_id, nand_dev_id, busw, maf_id; |
2172 | struct nand_chip *this = mtd->priv; | 2301 | struct nand_chip *this = mtd->priv; |
2173 | 2302 | ||
2174 | /* Get buswidth to select the correct functions*/ | 2303 | /* Get buswidth to select the correct functions*/ |
@@ -2256,12 +2385,18 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2256 | busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16; | 2385 | busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16; |
2257 | } | 2386 | } |
2258 | 2387 | ||
2388 | /* Try to identify manufacturer */ | ||
2389 | for (maf_id = 0; nand_manuf_ids[maf_id].id != 0x0; maf_id++) { | ||
2390 | if (nand_manuf_ids[maf_id].id == nand_maf_id) | ||
2391 | break; | ||
2392 | } | ||
2393 | |||
2259 | /* Check, if buswidth is correct. Hardware drivers should set | 2394 | /* Check, if buswidth is correct. Hardware drivers should set |
2260 | * this correct ! */ | 2395 | * this correct ! */ |
2261 | if (busw != (this->options & NAND_BUSWIDTH_16)) { | 2396 | if (busw != (this->options & NAND_BUSWIDTH_16)) { |
2262 | printk (KERN_INFO "NAND device: Manufacturer ID:" | 2397 | printk (KERN_INFO "NAND device: Manufacturer ID:" |
2263 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, | 2398 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, |
2264 | nand_manuf_ids[i].name , mtd->name); | 2399 | nand_manuf_ids[maf_id].name , mtd->name); |
2265 | printk (KERN_WARNING | 2400 | printk (KERN_WARNING |
2266 | "NAND bus width %d instead %d bit\n", | 2401 | "NAND bus width %d instead %d bit\n", |
2267 | (this->options & NAND_BUSWIDTH_16) ? 16 : 8, | 2402 | (this->options & NAND_BUSWIDTH_16) ? 16 : 8, |
@@ -2300,14 +2435,9 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2300 | if (mtd->oobblock > 512 && this->cmdfunc == nand_command) | 2435 | if (mtd->oobblock > 512 && this->cmdfunc == nand_command) |
2301 | this->cmdfunc = nand_command_lp; | 2436 | this->cmdfunc = nand_command_lp; |
2302 | 2437 | ||
2303 | /* Try to identify manufacturer */ | ||
2304 | for (j = 0; nand_manuf_ids[j].id != 0x0; j++) { | ||
2305 | if (nand_manuf_ids[j].id == nand_maf_id) | ||
2306 | break; | ||
2307 | } | ||
2308 | printk (KERN_INFO "NAND device: Manufacturer ID:" | 2438 | printk (KERN_INFO "NAND device: Manufacturer ID:" |
2309 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, | 2439 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, |
2310 | nand_manuf_ids[j].name , nand_flash_ids[i].name); | 2440 | nand_manuf_ids[maf_id].name , nand_flash_ids[i].name); |
2311 | break; | 2441 | break; |
2312 | } | 2442 | } |
2313 | 2443 | ||
@@ -2388,12 +2518,9 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2388 | 2518 | ||
2389 | /* The number of bytes available for the filesystem to place fs dependend | 2519 | /* The number of bytes available for the filesystem to place fs dependend |
2390 | * oob data */ | 2520 | * oob data */ |
2391 | if (this->options & NAND_BUSWIDTH_16) { | 2521 | mtd->oobavail = 0; |
2392 | mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2); | 2522 | for (i = 0; this->autooob->oobfree[i][1]; i++) |
2393 | if (this->autooob->eccbytes & 0x01) | 2523 | mtd->oobavail += this->autooob->oobfree[i][1]; |
2394 | mtd->oobavail--; | ||
2395 | } else | ||
2396 | mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1); | ||
2397 | 2524 | ||
2398 | /* | 2525 | /* |
2399 | * check ECC mode, default to software | 2526 | * check ECC mode, default to software |
@@ -2524,6 +2651,10 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2524 | memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); | 2651 | memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); |
2525 | 2652 | ||
2526 | mtd->owner = THIS_MODULE; | 2653 | mtd->owner = THIS_MODULE; |
2654 | |||
2655 | /* Check, if we should skip the bad block table scan */ | ||
2656 | if (this->options & NAND_SKIP_BBTSCAN) | ||
2657 | return 0; | ||
2527 | 2658 | ||
2528 | /* Build bad block table */ | 2659 | /* Build bad block table */ |
2529 | return this->scan_bbt (mtd); | 2660 | return this->scan_bbt (mtd); |
@@ -2555,8 +2686,8 @@ void nand_release (struct mtd_info *mtd) | |||
2555 | kfree (this->data_buf); | 2686 | kfree (this->data_buf); |
2556 | } | 2687 | } |
2557 | 2688 | ||
2558 | EXPORT_SYMBOL (nand_scan); | 2689 | EXPORT_SYMBOL_GPL (nand_scan); |
2559 | EXPORT_SYMBOL (nand_release); | 2690 | EXPORT_SYMBOL_GPL (nand_release); |
2560 | 2691 | ||
2561 | MODULE_LICENSE ("GPL"); | 2692 | MODULE_LICENSE ("GPL"); |
2562 | MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); | 2693 | MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); |