diff options
author | Thomas Gleixner <tglx@cruncher.tec.linutronix.de> | 2006-05-26 12:52:08 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@cruncher.tec.linutronix.de> | 2006-05-26 12:52:08 -0400 |
commit | f75e5097ef298c5a0aa106faa211d1afdc92dc3d (patch) | |
tree | 0de4534e9ae54cf5d17ea9ef20acefb931167eee /drivers/mtd | |
parent | e4d222ff18bca6322f032088a21e9c4a4c038b85 (diff) |
[MTD] NAND modularize write function
Modularize the write function and reorganaize the internal buffer
management. Remove obsolete chip options and fixup all affected
users.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/edb7312.c | 3 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 775 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/rtc_from4.c | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/toto.c | 2 |
6 files changed, 263 insertions, 522 deletions
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 83af6f05cd00..82262a4a4208 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -1666,7 +1666,7 @@ static int __init doc_probe(unsigned long physadr) | |||
1666 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; | 1666 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; |
1667 | nand->ecc.size = 512; | 1667 | nand->ecc.size = 512; |
1668 | nand->ecc.bytes = 6; | 1668 | nand->ecc.bytes = 6; |
1669 | nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; | 1669 | nand->options = NAND_USE_FLASH_BBT; |
1670 | 1670 | ||
1671 | doc->physadr = physadr; | 1671 | doc->physadr = physadr; |
1672 | doc->virtadr = virtadr; | 1672 | doc->virtadr = virtadr; |
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c index ba5a2174a408..516c0e5e564c 100644 --- a/drivers/mtd/nand/edb7312.c +++ b/drivers/mtd/nand/edb7312.c | |||
@@ -198,9 +198,6 @@ static void __exit ep7312_cleanup(void) | |||
198 | /* Release resources, unregister device */ | 198 | /* Release resources, unregister device */ |
199 | nand_release(ap7312_mtd); | 199 | nand_release(ap7312_mtd); |
200 | 200 | ||
201 | /* Free internal data buffer */ | ||
202 | kfree(this->data_buf); | ||
203 | |||
204 | /* Free the MTD device structure */ | 201 | /* Free the MTD device structure */ |
205 | kfree(ep7312_mtd); | 202 | kfree(ep7312_mtd); |
206 | } | 203 | } |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 2b29b47e2af4..cead9fc4f99f 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -88,37 +88,8 @@ static uint8_t ffchars[] = { | |||
88 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 88 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | /* | ||
92 | * NAND low-level MTD interface functions | ||
93 | */ | ||
94 | static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len); | ||
95 | static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len); | ||
96 | static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len); | ||
97 | |||
98 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
99 | size_t *retlen, uint8_t *buf); | ||
100 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, | ||
101 | size_t *retlen, uint8_t *buf); | ||
102 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
103 | size_t *retlen, const uint8_t *buf); | ||
104 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, | 91 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, |
105 | size_t *retlen, const uint8_t *buf); | 92 | size_t *retlen, const uint8_t *buf); |
106 | static int nand_erase(struct mtd_info *mtd, struct erase_info *instr); | ||
107 | static void nand_sync(struct mtd_info *mtd); | ||
108 | |||
109 | /* Some internal functions */ | ||
110 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | ||
111 | int page, uint8_t * oob_buf, | ||
112 | struct nand_oobinfo *oobsel, int mode); | ||
113 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE | ||
114 | static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *chip, | ||
115 | int page, int numpages, uint8_t *oob_buf, | ||
116 | struct nand_oobinfo *oobsel, int chipnr, | ||
117 | int oobmode); | ||
118 | #else | ||
119 | #define nand_verify_pages(...) (0) | ||
120 | #endif | ||
121 | |||
122 | static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, | 93 | static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, |
123 | int new_state); | 94 | int new_state); |
124 | 95 | ||
@@ -262,7 +233,6 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
262 | for (i = 0; i < len; i++) | 233 | for (i = 0; i < len; i++) |
263 | if (buf[i] != readb(chip->IO_ADDR_R)) | 234 | if (buf[i] != readb(chip->IO_ADDR_R)) |
264 | return -EFAULT; | 235 | return -EFAULT; |
265 | |||
266 | return 0; | 236 | return 0; |
267 | } | 237 | } |
268 | 238 | ||
@@ -767,215 +737,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip, int state) | |||
767 | } | 737 | } |
768 | 738 | ||
769 | /** | 739 | /** |
770 | * nand_write_page - [GENERIC] write one page | ||
771 | * @mtd: MTD device structure | ||
772 | * @this: NAND chip structure | ||
773 | * @page: startpage inside the chip, must be called with (page & chip->pagemask) | ||
774 | * @oob_buf: out of band data buffer | ||
775 | * @oobsel: out of band selecttion structre | ||
776 | * @cached: 1 = enable cached programming if supported by chip | ||
777 | * | ||
778 | * Nand_page_program function is used for write and writev ! | ||
779 | * This function will always program a full page of data | ||
780 | * If you call it with a non page aligned buffer, you're lost :) | ||
781 | * | ||
782 | * Cached programming is not supported yet. | ||
783 | */ | ||
784 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, int page, | ||
785 | uint8_t *oob_buf, struct nand_oobinfo *oobsel, int cached) | ||
786 | { | ||
787 | int i, status; | ||
788 | uint8_t ecc_code[32]; | ||
789 | int eccmode = oobsel->useecc ? chip->ecc.mode : NAND_ECC_NONE; | ||
790 | int *oob_config = oobsel->eccpos; | ||
791 | int datidx = 0, eccidx = 0, eccsteps = chip->ecc.steps; | ||
792 | int eccbytes = 0; | ||
793 | |||
794 | /* FIXME: Enable cached programming */ | ||
795 | cached = 0; | ||
796 | |||
797 | /* Send command to begin auto page programming */ | ||
798 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); | ||
799 | |||
800 | /* Write out complete page of data, take care of eccmode */ | ||
801 | switch (eccmode) { | ||
802 | /* No ecc, write all */ | ||
803 | case NAND_ECC_NONE: | ||
804 | printk(KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); | ||
805 | chip->write_buf(mtd, chip->data_poi, mtd->writesize); | ||
806 | break; | ||
807 | |||
808 | /* Software ecc 3/256, write all */ | ||
809 | case NAND_ECC_SOFT: | ||
810 | for (; eccsteps; eccsteps--) { | ||
811 | chip->ecc.calculate(mtd, &chip->data_poi[datidx], ecc_code); | ||
812 | for (i = 0; i < 3; i++, eccidx++) | ||
813 | oob_buf[oob_config[eccidx]] = ecc_code[i]; | ||
814 | datidx += chip->ecc.size; | ||
815 | } | ||
816 | chip->write_buf(mtd, chip->data_poi, mtd->writesize); | ||
817 | break; | ||
818 | default: | ||
819 | eccbytes = chip->ecc.bytes; | ||
820 | for (; eccsteps; eccsteps--) { | ||
821 | /* enable hardware ecc logic for write */ | ||
822 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); | ||
823 | chip->write_buf(mtd, &chip->data_poi[datidx], chip->ecc.size); | ||
824 | chip->ecc.calculate(mtd, &chip->data_poi[datidx], ecc_code); | ||
825 | for (i = 0; i < eccbytes; i++, eccidx++) | ||
826 | oob_buf[oob_config[eccidx]] = ecc_code[i]; | ||
827 | /* If the hardware ecc provides syndromes then | ||
828 | * the ecc code must be written immidiately after | ||
829 | * the data bytes (words) */ | ||
830 | if (chip->options & NAND_HWECC_SYNDROME) | ||
831 | chip->write_buf(mtd, ecc_code, eccbytes); | ||
832 | datidx += chip->ecc.size; | ||
833 | } | ||
834 | break; | ||
835 | } | ||
836 | |||
837 | /* Write out OOB data */ | ||
838 | if (chip->options & NAND_HWECC_SYNDROME) | ||
839 | chip->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes); | ||
840 | else | ||
841 | chip->write_buf(mtd, oob_buf, mtd->oobsize); | ||
842 | |||
843 | /* Send command to actually program the data */ | ||
844 | chip->cmdfunc(mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1); | ||
845 | |||
846 | if (!cached) { | ||
847 | /* call wait ready function */ | ||
848 | status = chip->waitfunc(mtd, chip, FL_WRITING); | ||
849 | |||
850 | /* See if operation failed and additional status checks are available */ | ||
851 | if ((status & NAND_STATUS_FAIL) && (chip->errstat)) { | ||
852 | status = chip->errstat(mtd, chip, FL_WRITING, status, page); | ||
853 | } | ||
854 | |||
855 | /* See if device thinks it succeeded */ | ||
856 | if (status & NAND_STATUS_FAIL) { | ||
857 | DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page); | ||
858 | return -EIO; | ||
859 | } | ||
860 | } else { | ||
861 | /* FIXME: Implement cached programming ! */ | ||
862 | /* wait until cache is ready */ | ||
863 | // status = chip->waitfunc (mtd, this, FL_CACHEDRPG); | ||
864 | } | ||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE | ||
869 | /** | ||
870 | * nand_verify_pages - [GENERIC] verify the chip contents after a write | ||
871 | * @mtd: MTD device structure | ||
872 | * @this: NAND chip structure | ||
873 | * @page: startpage inside the chip, must be called with (page & chip->pagemask) | ||
874 | * @numpages: number of pages to verify | ||
875 | * @oob_buf: out of band data buffer | ||
876 | * @oobsel: out of band selecttion structre | ||
877 | * @chipnr: number of the current chip | ||
878 | * @oobmode: 1 = full buffer verify, 0 = ecc only | ||
879 | * | ||
880 | * The NAND device assumes that it is always writing to a cleanly erased page. | ||
881 | * Hence, it performs its internal write verification only on bits that | ||
882 | * transitioned from 1 to 0. The device does NOT verify the whole page on a | ||
883 | * byte by byte basis. It is possible that the page was not completely erased | ||
884 | * or the page is becoming unusable due to wear. The read with ECC would catch | ||
885 | * the error later when the ECC page check fails, but we would rather catch | ||
886 | * it early in the page write stage. Better to write no data than invalid data. | ||
887 | */ | ||
888 | static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *chip, int page, int numpages, | ||
889 | uint8_t *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode) | ||
890 | { | ||
891 | int i, j, datidx = 0, oobofs = 0, res = -EIO; | ||
892 | int eccsteps = chip->ecc.steps; | ||
893 | int hweccbytes; | ||
894 | uint8_t oobdata[64]; | ||
895 | |||
896 | hweccbytes = (chip->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; | ||
897 | |||
898 | /* Send command to read back the first page */ | ||
899 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | ||
900 | |||
901 | for (;;) { | ||
902 | for (j = 0; j < eccsteps; j++) { | ||
903 | /* Loop through and verify the data */ | ||
904 | if (chip->verify_buf(mtd, &chip->data_poi[datidx], mtd->eccsize)) { | ||
905 | DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); | ||
906 | goto out; | ||
907 | } | ||
908 | datidx += mtd->eccsize; | ||
909 | /* Have we a hw generator layout ? */ | ||
910 | if (!hweccbytes) | ||
911 | continue; | ||
912 | if (chip->verify_buf(mtd, &chip->oob_buf[oobofs], hweccbytes)) { | ||
913 | DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); | ||
914 | goto out; | ||
915 | } | ||
916 | oobofs += hweccbytes; | ||
917 | } | ||
918 | |||
919 | /* check, if we must compare all data or if we just have to | ||
920 | * compare the ecc bytes | ||
921 | */ | ||
922 | if (oobmode) { | ||
923 | if (chip->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) { | ||
924 | DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); | ||
925 | goto out; | ||
926 | } | ||
927 | } else { | ||
928 | /* Read always, else autoincrement fails */ | ||
929 | chip->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps); | ||
930 | |||
931 | if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) { | ||
932 | int ecccnt = oobsel->eccbytes; | ||
933 | |||
934 | for (i = 0; i < ecccnt; i++) { | ||
935 | int idx = oobsel->eccpos[i]; | ||
936 | if (oobdata[idx] != oob_buf[oobofs + idx]) { | ||
937 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed ECC write verify, page 0x%08x, %6i bytes were succesful\n", | ||
938 | __FUNCTION__, page, i); | ||
939 | goto out; | ||
940 | } | ||
941 | } | ||
942 | } | ||
943 | } | ||
944 | oobofs += mtd->oobsize - hweccbytes * eccsteps; | ||
945 | page++; | ||
946 | numpages--; | ||
947 | |||
948 | /* Apply delay or wait for ready/busy pin | ||
949 | * Do this before the AUTOINCR check, so no problems | ||
950 | * arise if a chip which does auto increment | ||
951 | * is marked as NOAUTOINCR by the board driver. | ||
952 | * Do this also before returning, so the chip is | ||
953 | * ready for the next command. | ||
954 | */ | ||
955 | if (!chip->dev_ready) | ||
956 | udelay(chip->chip_delay); | ||
957 | else | ||
958 | nand_wait_ready(mtd); | ||
959 | |||
960 | /* All done, return happy */ | ||
961 | if (!numpages) | ||
962 | return 0; | ||
963 | |||
964 | /* Check, if the chip supports auto page increment */ | ||
965 | if (!NAND_CANAUTOINCR(chip)) | ||
966 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); | ||
967 | } | ||
968 | /* | ||
969 | * Terminate the read command. We come here in case of an error | ||
970 | * So we must issue a reset command. | ||
971 | */ | ||
972 | out: | ||
973 | chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | ||
974 | return res; | ||
975 | } | ||
976 | #endif | ||
977 | |||
978 | /** | ||
979 | * nand_read_page_swecc - {REPLACABLE] software ecc based page read function | 740 | * nand_read_page_swecc - {REPLACABLE] software ecc based page read function |
980 | * @mtd: mtd info structure | 741 | * @mtd: mtd info structure |
981 | * @chip: nand chip info structure | 742 | * @chip: nand chip info structure |
@@ -988,12 +749,12 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
988 | int eccbytes = chip->ecc.bytes; | 749 | int eccbytes = chip->ecc.bytes; |
989 | int eccsteps = chip->ecc.steps; | 750 | int eccsteps = chip->ecc.steps; |
990 | uint8_t *p = buf; | 751 | uint8_t *p = buf; |
991 | uint8_t *ecc_calc = chip->oob_buf + mtd->oobsize; | 752 | uint8_t *ecc_calc = chip->buffers.ecccalc; |
992 | uint8_t *ecc_code = ecc_calc + mtd->oobsize; | 753 | uint8_t *ecc_code = chip->buffers.ecccode; |
993 | int *eccpos = chip->autooob->eccpos; | 754 | int *eccpos = chip->autooob->eccpos; |
994 | 755 | ||
995 | chip->read_buf(mtd, buf, mtd->writesize); | 756 | chip->read_buf(mtd, buf, mtd->writesize); |
996 | chip->read_buf(mtd, chip->oob_buf, mtd->oobsize); | 757 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
997 | 758 | ||
998 | if (chip->ecc.mode == NAND_ECC_NONE) | 759 | if (chip->ecc.mode == NAND_ECC_NONE) |
999 | return 0; | 760 | return 0; |
@@ -1002,7 +763,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1002 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 763 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
1003 | 764 | ||
1004 | for (i = 0; i < chip->ecc.total; i++) | 765 | for (i = 0; i < chip->ecc.total; i++) |
1005 | ecc_code[i] = chip->oob_buf[eccpos[i]]; | 766 | ecc_code[i] = chip->oob_poi[eccpos[i]]; |
1006 | 767 | ||
1007 | eccsteps = chip->ecc.steps; | 768 | eccsteps = chip->ecc.steps; |
1008 | p = buf; | 769 | p = buf; |
@@ -1034,8 +795,8 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1034 | int eccbytes = chip->ecc.bytes; | 795 | int eccbytes = chip->ecc.bytes; |
1035 | int eccsteps = chip->ecc.steps; | 796 | int eccsteps = chip->ecc.steps; |
1036 | uint8_t *p = buf; | 797 | uint8_t *p = buf; |
1037 | uint8_t *ecc_calc = chip->oob_buf + mtd->oobsize; | 798 | uint8_t *ecc_calc = chip->buffers.ecccalc; |
1038 | uint8_t *ecc_code = ecc_calc + mtd->oobsize; | 799 | uint8_t *ecc_code = chip->buffers.ecccode; |
1039 | int *eccpos = chip->autooob->eccpos; | 800 | int *eccpos = chip->autooob->eccpos; |
1040 | 801 | ||
1041 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 802 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
@@ -1043,10 +804,10 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1043 | chip->read_buf(mtd, p, eccsize); | 804 | chip->read_buf(mtd, p, eccsize); |
1044 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 805 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
1045 | } | 806 | } |
1046 | chip->read_buf(mtd, chip->oob_buf, mtd->oobsize); | 807 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
1047 | 808 | ||
1048 | for (i = 0; i < chip->ecc.total; i++) | 809 | for (i = 0; i < chip->ecc.total; i++) |
1049 | ecc_code[i] = chip->oob_buf[eccpos[i]]; | 810 | ecc_code[i] = chip->oob_poi[eccpos[i]]; |
1050 | 811 | ||
1051 | eccsteps = chip->ecc.steps; | 812 | eccsteps = chip->ecc.steps; |
1052 | p = buf; | 813 | p = buf; |
@@ -1070,7 +831,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1070 | * @buf: buffer to store read data | 831 | * @buf: buffer to store read data |
1071 | * | 832 | * |
1072 | * The hw generator calculates the error syndrome automatically. Therefor | 833 | * The hw generator calculates the error syndrome automatically. Therefor |
1073 | * we need a special oob layout and . | 834 | * we need a special oob layout and handling. |
1074 | */ | 835 | */ |
1075 | static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 836 | static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
1076 | uint8_t *buf) | 837 | uint8_t *buf) |
@@ -1079,7 +840,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1079 | int eccbytes = chip->ecc.bytes; | 840 | int eccbytes = chip->ecc.bytes; |
1080 | int eccsteps = chip->ecc.steps; | 841 | int eccsteps = chip->ecc.steps; |
1081 | uint8_t *p = buf; | 842 | uint8_t *p = buf; |
1082 | uint8_t *oob = chip->oob_buf; | 843 | uint8_t *oob = chip->oob_poi; |
1083 | 844 | ||
1084 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 845 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
1085 | int stat; | 846 | int stat; |
@@ -1110,7 +871,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1110 | } | 871 | } |
1111 | 872 | ||
1112 | /* Calculate remaining oob bytes */ | 873 | /* Calculate remaining oob bytes */ |
1113 | i = oob - chip->oob_buf; | 874 | i = oob - chip->oob_poi; |
1114 | if (i) | 875 | if (i) |
1115 | chip->read_buf(mtd, oob, i); | 876 | chip->read_buf(mtd, oob, i); |
1116 | 877 | ||
@@ -1149,6 +910,7 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
1149 | page = realpage & chip->pagemask; | 910 | page = realpage & chip->pagemask; |
1150 | 911 | ||
1151 | col = (int)(from & (mtd->writesize - 1)); | 912 | col = (int)(from & (mtd->writesize - 1)); |
913 | chip->oob_poi = chip->buffers.oobrbuf; | ||
1152 | 914 | ||
1153 | while(1) { | 915 | while(1) { |
1154 | bytes = min(mtd->writesize - col, readlen); | 916 | bytes = min(mtd->writesize - col, readlen); |
@@ -1156,7 +918,7 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
1156 | 918 | ||
1157 | /* Is the current page in the buffer ? */ | 919 | /* Is the current page in the buffer ? */ |
1158 | if (realpage != chip->pagebuf) { | 920 | if (realpage != chip->pagebuf) { |
1159 | bufpoi = aligned ? buf : chip->data_buf; | 921 | bufpoi = aligned ? buf : chip->buffers.databuf; |
1160 | 922 | ||
1161 | if (likely(sndcmd)) { | 923 | if (likely(sndcmd)) { |
1162 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); | 924 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); |
@@ -1171,7 +933,7 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
1171 | /* Transfer not aligned data */ | 933 | /* Transfer not aligned data */ |
1172 | if (!aligned) { | 934 | if (!aligned) { |
1173 | chip->pagebuf = realpage; | 935 | chip->pagebuf = realpage; |
1174 | memcpy(buf, chip->data_buf + col, bytes); | 936 | memcpy(buf, chip->buffers.databuf + col, bytes); |
1175 | } | 937 | } |
1176 | 938 | ||
1177 | if (!(chip->options & NAND_NO_READRDY)) { | 939 | if (!(chip->options & NAND_NO_READRDY)) { |
@@ -1188,7 +950,7 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
1188 | nand_wait_ready(mtd); | 950 | nand_wait_ready(mtd); |
1189 | } | 951 | } |
1190 | } else | 952 | } else |
1191 | memcpy(buf, chip->data_buf + col, bytes); | 953 | memcpy(buf, chip->buffers.databuf + col, bytes); |
1192 | 954 | ||
1193 | buf += bytes; | 955 | buf += bytes; |
1194 | readlen -= bytes; | 956 | readlen -= bytes; |
@@ -1392,10 +1154,11 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, | |||
1392 | blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; | 1154 | blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; |
1393 | 1155 | ||
1394 | while (len) { | 1156 | while (len) { |
1395 | if (sndcmd) | 1157 | if (likely(sndcmd)) { |
1396 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, | 1158 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, |
1397 | page & chip->pagemask); | 1159 | page & chip->pagemask); |
1398 | sndcmd = 0; | 1160 | sndcmd = 0; |
1161 | } | ||
1399 | 1162 | ||
1400 | chip->read_buf(mtd, &buf[cnt], pagesize); | 1163 | chip->read_buf(mtd, &buf[cnt], pagesize); |
1401 | 1164 | ||
@@ -1403,10 +1166,12 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, | |||
1403 | cnt += pagesize; | 1166 | cnt += pagesize; |
1404 | page++; | 1167 | page++; |
1405 | 1168 | ||
1406 | if (!chip->dev_ready) | 1169 | if (!(chip->options & NAND_NO_READRDY)) { |
1407 | udelay(chip->chip_delay); | 1170 | if (!chip->dev_ready) |
1408 | else | 1171 | udelay(chip->chip_delay); |
1409 | nand_wait_ready(mtd); | 1172 | else |
1173 | nand_wait_ready(mtd); | ||
1174 | } | ||
1410 | 1175 | ||
1411 | /* | 1176 | /* |
1412 | * Check, if the chip supports auto page increment or if we | 1177 | * Check, if the chip supports auto page increment or if we |
@@ -1422,112 +1187,156 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, | |||
1422 | } | 1187 | } |
1423 | 1188 | ||
1424 | /** | 1189 | /** |
1425 | * nand_write_raw - [GENERIC] Write raw data including oob | 1190 | * nand_write_page_swecc - {REPLACABLE] software ecc based page write function |
1426 | * @mtd: MTD device structure | 1191 | * @mtd: mtd info structure |
1427 | * @buf: source buffer | 1192 | * @chip: nand chip info structure |
1428 | * @to: offset to write to | 1193 | * @buf: data buffer |
1429 | * @len: number of bytes to write | ||
1430 | * @buf: source buffer | ||
1431 | * @oob: oob buffer | ||
1432 | * | ||
1433 | * Write raw data including oob | ||
1434 | */ | 1194 | */ |
1435 | int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, | 1195 | static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, |
1436 | uint8_t *buf, uint8_t *oob) | 1196 | const uint8_t *buf) |
1437 | { | 1197 | { |
1438 | struct nand_chip *chip = mtd->priv; | 1198 | int i, eccsize = chip->ecc.size; |
1439 | int page = (int)(to >> chip->page_shift); | 1199 | int eccbytes = chip->ecc.bytes; |
1440 | int chipnr = (int)(to >> chip->chip_shift); | 1200 | int eccsteps = chip->ecc.steps; |
1441 | int ret; | 1201 | uint8_t *ecc_calc = chip->buffers.ecccalc; |
1202 | const uint8_t *p = buf; | ||
1203 | int *eccpos = chip->autooob->eccpos; | ||
1442 | 1204 | ||
1443 | *retlen = 0; | 1205 | if (chip->ecc.mode != NAND_ECC_NONE) { |
1206 | /* Software ecc calculation */ | ||
1207 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) | ||
1208 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | ||
1444 | 1209 | ||
1445 | /* Do not allow writes past end of device */ | 1210 | for (i = 0; i < chip->ecc.total; i++) |
1446 | if ((to + len) > mtd->size) { | 1211 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; |
1447 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write " | ||
1448 | "beyond end of device\n"); | ||
1449 | return -EINVAL; | ||
1450 | } | 1212 | } |
1451 | 1213 | ||
1452 | /* Grab the lock and see if the device is available */ | 1214 | chip->write_buf(mtd, buf, mtd->writesize); |
1453 | nand_get_device(chip, mtd, FL_WRITING); | 1215 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
1216 | } | ||
1454 | 1217 | ||
1455 | chip->select_chip(mtd, chipnr); | 1218 | /** |
1456 | chip->data_poi = buf; | 1219 | * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function |
1220 | * @mtd: mtd info structure | ||
1221 | * @chip: nand chip info structure | ||
1222 | * @buf: data buffer | ||
1223 | */ | ||
1224 | static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | ||
1225 | const uint8_t *buf) | ||
1226 | { | ||
1227 | int i, eccsize = chip->ecc.size; | ||
1228 | int eccbytes = chip->ecc.bytes; | ||
1229 | int eccsteps = chip->ecc.steps; | ||
1230 | uint8_t *ecc_calc = chip->buffers.ecccalc; | ||
1231 | const uint8_t *p = buf; | ||
1232 | int *eccpos = chip->autooob->eccpos; | ||
1457 | 1233 | ||
1458 | while (len != *retlen) { | 1234 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
1459 | ret = nand_write_page(mtd, chip, page, oob, &mtd->oobinfo, 0); | 1235 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); |
1460 | if (ret) | 1236 | chip->write_buf(mtd, p, mtd->writesize); |
1461 | return ret; | 1237 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
1462 | page++; | ||
1463 | *retlen += mtd->writesize; | ||
1464 | chip->data_poi += mtd->writesize; | ||
1465 | oob += mtd->oobsize; | ||
1466 | } | 1238 | } |
1467 | 1239 | ||
1468 | /* Deselect and wake up anyone waiting on the device */ | 1240 | for (i = 0; i < chip->ecc.total; i++) |
1469 | nand_release_device(mtd); | 1241 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; |
1470 | return 0; | 1242 | |
1243 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
1471 | } | 1244 | } |
1472 | EXPORT_SYMBOL_GPL(nand_write_raw); | ||
1473 | 1245 | ||
1474 | /** | 1246 | /** |
1475 | * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer | 1247 | * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write |
1476 | * @mtd: MTD device structure | 1248 | * @mtd: mtd info structure |
1477 | * @fsbuf: buffer given by fs driver | 1249 | * @chip: nand chip info structure |
1478 | * @oobsel: out of band selection structre | 1250 | * @buf: data buffer |
1479 | * @autoplace: 1 = place given buffer into the oob bytes | ||
1480 | * @numpages: number of pages to prepare | ||
1481 | * | ||
1482 | * Return: | ||
1483 | * 1. Filesystem buffer available and autoplacement is off, | ||
1484 | * return filesystem buffer | ||
1485 | * 2. No filesystem buffer or autoplace is off, return internal | ||
1486 | * buffer | ||
1487 | * 3. Filesystem buffer is given and autoplace selected | ||
1488 | * put data from fs buffer into internal buffer and | ||
1489 | * retrun internal buffer | ||
1490 | * | ||
1491 | * Note: The internal buffer is filled with 0xff. This must | ||
1492 | * be done only once, when no autoplacement happens | ||
1493 | * Autoplacement sets the buffer dirty flag, which | ||
1494 | * forces the 0xff fill before using the buffer again. | ||
1495 | * | 1251 | * |
1496 | */ | 1252 | * The hw generator calculates the error syndrome automatically. Therefor |
1497 | static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct nand_oobinfo *oobsel, | 1253 | * we need a special oob layout and handling. |
1498 | int autoplace, int numpages) | 1254 | */ |
1255 | static void nand_write_page_syndrome(struct mtd_info *mtd, | ||
1256 | struct nand_chip *chip, const uint8_t *buf) | ||
1499 | { | 1257 | { |
1500 | struct nand_chip *chip = mtd->priv; | 1258 | int i, eccsize = chip->ecc.size; |
1501 | int i, len, ofs; | 1259 | int eccbytes = chip->ecc.bytes; |
1260 | int eccsteps = chip->ecc.steps; | ||
1261 | const uint8_t *p = buf; | ||
1262 | uint8_t *oob = chip->oob_poi; | ||
1502 | 1263 | ||
1503 | /* Zero copy fs supplied buffer */ | 1264 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
1504 | if (fsbuf && !autoplace) | ||
1505 | return fsbuf; | ||
1506 | 1265 | ||
1507 | /* Check, if the buffer must be filled with ff again */ | 1266 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); |
1508 | if (chip->oobdirty) { | 1267 | chip->write_buf(mtd, p, eccsize); |
1509 | memset(chip->oob_buf, 0xff, mtd->oobsize << (chip->phys_erase_shift - chip->page_shift)); | ||
1510 | chip->oobdirty = 0; | ||
1511 | } | ||
1512 | 1268 | ||
1513 | /* If we have no autoplacement or no fs buffer use the internal one */ | 1269 | if (chip->ecc.prepad) { |
1514 | if (!autoplace || !fsbuf) | 1270 | chip->write_buf(mtd, oob, chip->ecc.prepad); |
1515 | return chip->oob_buf; | 1271 | oob += chip->ecc.prepad; |
1516 | 1272 | } | |
1517 | /* Walk through the pages and place the data */ | 1273 | |
1518 | chip->oobdirty = 1; | 1274 | chip->ecc.calculate(mtd, p, oob); |
1519 | ofs = 0; | 1275 | chip->write_buf(mtd, oob, eccbytes); |
1520 | while (numpages--) { | 1276 | oob += eccbytes; |
1521 | for (i = 0, len = 0; len < mtd->oobavail; i++) { | 1277 | |
1522 | int to = ofs + oobsel->oobfree[i][0]; | 1278 | if (chip->ecc.postpad) { |
1523 | int num = oobsel->oobfree[i][1]; | 1279 | chip->write_buf(mtd, oob, chip->ecc.postpad); |
1524 | memcpy(&chip->oob_buf[to], fsbuf, num); | 1280 | oob += chip->ecc.postpad; |
1525 | len += num; | ||
1526 | fsbuf += num; | ||
1527 | } | 1281 | } |
1528 | ofs += mtd->oobavail; | ||
1529 | } | 1282 | } |
1530 | return chip->oob_buf; | 1283 | |
1284 | /* Calculate remaining oob bytes */ | ||
1285 | i = oob - chip->oob_poi; | ||
1286 | if (i) | ||
1287 | chip->write_buf(mtd, oob, i); | ||
1288 | } | ||
1289 | |||
1290 | /** | ||
1291 | * nand_write_page - [INTERNAL] write one page | ||
1292 | * @mtd: MTD device structure | ||
1293 | * @chip: NAND chip descriptor | ||
1294 | * @buf: the data to write | ||
1295 | * @page: page number to write | ||
1296 | * @cached: cached programming | ||
1297 | */ | ||
1298 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | ||
1299 | const uint8_t *buf, int page, int cached) | ||
1300 | { | ||
1301 | int status; | ||
1302 | |||
1303 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); | ||
1304 | |||
1305 | chip->ecc.write_page(mtd, chip, buf); | ||
1306 | |||
1307 | /* | ||
1308 | * Cached progamming disabled for now, Not sure if its worth the | ||
1309 | * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s) | ||
1310 | */ | ||
1311 | cached = 0; | ||
1312 | |||
1313 | if (!cached || !(chip->options & NAND_CACHEPRG)) { | ||
1314 | |||
1315 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | ||
1316 | status = chip->waitfunc(mtd, chip, FL_WRITING); | ||
1317 | /* | ||
1318 | * See if operation failed and additional status checks are | ||
1319 | * available | ||
1320 | */ | ||
1321 | if ((status & NAND_STATUS_FAIL) && (chip->errstat)) | ||
1322 | status = chip->errstat(mtd, chip, FL_WRITING, status, | ||
1323 | page); | ||
1324 | |||
1325 | if (status & NAND_STATUS_FAIL) | ||
1326 | return -EIO; | ||
1327 | } else { | ||
1328 | chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1); | ||
1329 | status = chip->waitfunc(mtd, chip, FL_WRITING); | ||
1330 | } | ||
1331 | |||
1332 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE | ||
1333 | /* Send command to read back the data */ | ||
1334 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | ||
1335 | |||
1336 | if (chip->verify_buf(mtd, buf, mtd->writesize)) | ||
1337 | return -EIO; | ||
1338 | #endif | ||
1339 | return 0; | ||
1531 | } | 1340 | } |
1532 | 1341 | ||
1533 | #define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 | 1342 | #define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 |
@@ -1545,137 +1354,128 @@ static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct | |||
1545 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, | 1354 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, |
1546 | size_t *retlen, const uint8_t *buf) | 1355 | size_t *retlen, const uint8_t *buf) |
1547 | { | 1356 | { |
1548 | int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; | 1357 | int chipnr, realpage, page, blockmask; |
1549 | int autoplace = 0, numpages, totalpages; | ||
1550 | struct nand_chip *chip = mtd->priv; | 1358 | struct nand_chip *chip = mtd->priv; |
1551 | uint8_t *oobbuf, *bufstart, *eccbuf = NULL; | 1359 | uint32_t writelen = len; |
1552 | int ppblock = (1 << (chip->phys_erase_shift - chip->page_shift)); | 1360 | int bytes = mtd->writesize; |
1553 | struct nand_oobinfo *oobsel = &mtd->oobinfo; | 1361 | int ret = -EIO; |
1554 | |||
1555 | DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len); | ||
1556 | 1362 | ||
1557 | /* Initialize retlen, in case of early exit */ | ||
1558 | *retlen = 0; | 1363 | *retlen = 0; |
1559 | 1364 | ||
1560 | /* Do not allow write past end of device */ | 1365 | /* Do not allow write past end of device */ |
1561 | if ((to + len) > mtd->size) { | 1366 | if ((to + len) > mtd->size) { |
1562 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n"); | 1367 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write: " |
1368 | "Attempt to write past end of page\n"); | ||
1563 | return -EINVAL; | 1369 | return -EINVAL; |
1564 | } | 1370 | } |
1565 | 1371 | ||
1566 | /* reject writes, which are not page aligned */ | 1372 | /* reject writes, which are not page aligned */ |
1567 | if (NOTALIGNED(to) || NOTALIGNED(len)) { | 1373 | if (NOTALIGNED(to) || NOTALIGNED(len)) { |
1568 | printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n"); | 1374 | printk(KERN_NOTICE "nand_write: " |
1375 | "Attempt to write not page aligned data\n"); | ||
1569 | return -EINVAL; | 1376 | return -EINVAL; |
1570 | } | 1377 | } |
1571 | 1378 | ||
1572 | /* Grab the lock and see if the device is available */ | 1379 | if (!len) |
1573 | nand_get_device(chip, mtd, FL_WRITING); | 1380 | return 0; |
1574 | 1381 | ||
1575 | /* Calculate chipnr */ | 1382 | nand_get_device(chip, mtd, FL_WRITING); |
1576 | chipnr = (int)(to >> chip->chip_shift); | ||
1577 | /* Select the NAND device */ | ||
1578 | chip->select_chip(mtd, chipnr); | ||
1579 | 1383 | ||
1580 | /* Check, if it is write protected */ | 1384 | /* Check, if it is write protected */ |
1581 | if (nand_check_wp(mtd)) | 1385 | if (nand_check_wp(mtd)) |
1582 | goto out; | 1386 | goto out; |
1583 | 1387 | ||
1584 | /* Autoplace of oob data ? Use the default placement scheme */ | 1388 | chipnr = (int)(to >> chip->chip_shift); |
1585 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { | 1389 | chip->select_chip(mtd, chipnr); |
1586 | oobsel = chip->autooob; | ||
1587 | autoplace = 1; | ||
1588 | } | ||
1589 | if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) | ||
1590 | autoplace = 1; | ||
1591 | 1390 | ||
1592 | /* Setup variables and oob buffer */ | 1391 | realpage = (int)(to >> chip->page_shift); |
1593 | totalpages = len >> chip->page_shift; | 1392 | page = realpage & chip->pagemask; |
1594 | page = (int)(to >> chip->page_shift); | 1393 | blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; |
1595 | /* Invalidate the page cache, if we write to the cached page */ | 1394 | |
1596 | if (page <= chip->pagebuf && chip->pagebuf < (page + totalpages)) | 1395 | /* Invalidate the page cache, when we write to the cached page */ |
1396 | if (to <= (chip->pagebuf << chip->page_shift) && | ||
1397 | (chip->pagebuf << chip->page_shift) < (to + len)) | ||
1597 | chip->pagebuf = -1; | 1398 | chip->pagebuf = -1; |
1598 | 1399 | ||
1599 | /* Set it relative to chip */ | 1400 | chip->oob_poi = chip->buffers.oobwbuf; |
1600 | page &= chip->pagemask; | ||
1601 | startpage = page; | ||
1602 | /* Calc number of pages we can write in one go */ | ||
1603 | numpages = min(ppblock - (startpage & (ppblock - 1)), totalpages); | ||
1604 | oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages); | ||
1605 | bufstart = (uint8_t *) buf; | ||
1606 | |||
1607 | /* Loop until all data is written */ | ||
1608 | while (written < len) { | ||
1609 | |||
1610 | chip->data_poi = (uint8_t *) &buf[written]; | ||
1611 | /* Write one page. If this is the last page to write | ||
1612 | * or the last page in this block, then use the | ||
1613 | * real pageprogram command, else select cached programming | ||
1614 | * if supported by the chip. | ||
1615 | */ | ||
1616 | ret = nand_write_page(mtd, chip, page, &oobbuf[oob], oobsel, (--numpages > 0)); | ||
1617 | if (ret) { | ||
1618 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret); | ||
1619 | goto out; | ||
1620 | } | ||
1621 | /* Next oob page */ | ||
1622 | oob += mtd->oobsize; | ||
1623 | /* Update written bytes count */ | ||
1624 | written += mtd->writesize; | ||
1625 | if (written == len) | ||
1626 | goto cmp; | ||
1627 | 1401 | ||
1628 | /* Increment page address */ | 1402 | while(1) { |
1629 | page++; | 1403 | int cached = writelen > bytes && page != blockmask; |
1630 | 1404 | ||
1631 | /* Have we hit a block boundary ? Then we have to verify and | 1405 | ret = nand_write_page(mtd, chip, buf, page, cached); |
1632 | * if verify is ok, we have to setup the oob buffer for | 1406 | if (ret) |
1633 | * the next pages. | 1407 | break; |
1634 | */ | 1408 | |
1635 | if (!(page & (ppblock - 1))) { | 1409 | writelen -= bytes; |
1636 | int ofs; | 1410 | if (!writelen) |
1637 | chip->data_poi = bufstart; | 1411 | break; |
1638 | ret = nand_verify_pages(mtd, chip, startpage, page - startpage, | 1412 | |
1639 | oobbuf, oobsel, chipnr, (eccbuf != NULL)); | 1413 | buf += bytes; |
1640 | if (ret) { | 1414 | realpage++; |
1641 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret); | 1415 | |
1642 | goto out; | 1416 | page = realpage & chip->pagemask; |
1643 | } | 1417 | /* Check, if we cross a chip boundary */ |
1644 | *retlen = written; | 1418 | if (!page) { |
1645 | 1419 | chipnr++; | |
1646 | ofs = autoplace ? mtd->oobavail : mtd->oobsize; | 1420 | chip->select_chip(mtd, -1); |
1647 | if (eccbuf) | 1421 | chip->select_chip(mtd, chipnr); |
1648 | eccbuf += (page - startpage) * ofs; | ||
1649 | totalpages -= page - startpage; | ||
1650 | numpages = min(totalpages, ppblock); | ||
1651 | page &= chip->pagemask; | ||
1652 | startpage = page; | ||
1653 | oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages); | ||
1654 | oob = 0; | ||
1655 | /* Check, if we cross a chip boundary */ | ||
1656 | if (!page) { | ||
1657 | chipnr++; | ||
1658 | chip->select_chip(mtd, -1); | ||
1659 | chip->select_chip(mtd, chipnr); | ||
1660 | } | ||
1661 | } | 1422 | } |
1662 | } | 1423 | } |
1663 | /* Verify the remaining pages */ | ||
1664 | cmp: | ||
1665 | chip->data_poi = bufstart; | ||
1666 | ret = nand_verify_pages(mtd, chip, startpage, totalpages, oobbuf, oobsel, chipnr, (eccbuf != NULL)); | ||
1667 | if (!ret) | ||
1668 | *retlen = written; | ||
1669 | else | ||
1670 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret); | ||
1671 | |||
1672 | out: | 1424 | out: |
1673 | /* Deselect and wake up anyone waiting on the device */ | 1425 | *retlen = len - writelen; |
1674 | nand_release_device(mtd); | 1426 | nand_release_device(mtd); |
1675 | |||
1676 | return ret; | 1427 | return ret; |
1677 | } | 1428 | } |
1678 | 1429 | ||
1430 | /** | ||
1431 | * nand_write_raw - [GENERIC] Write raw data including oob | ||
1432 | * @mtd: MTD device structure | ||
1433 | * @buf: source buffer | ||
1434 | * @to: offset to write to | ||
1435 | * @len: number of bytes to write | ||
1436 | * @buf: source buffer | ||
1437 | * @oob: oob buffer | ||
1438 | * | ||
1439 | * Write raw data including oob | ||
1440 | */ | ||
1441 | int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, | ||
1442 | const uint8_t *buf, uint8_t *oob) | ||
1443 | { | ||
1444 | struct nand_chip *chip = mtd->priv; | ||
1445 | int page = (int)(to >> chip->page_shift); | ||
1446 | int chipnr = (int)(to >> chip->chip_shift); | ||
1447 | int ret; | ||
1448 | |||
1449 | *retlen = 0; | ||
1450 | |||
1451 | /* Do not allow writes past end of device */ | ||
1452 | if ((to + len) > mtd->size) { | ||
1453 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write " | ||
1454 | "beyond end of device\n"); | ||
1455 | return -EINVAL; | ||
1456 | } | ||
1457 | |||
1458 | /* Grab the lock and see if the device is available */ | ||
1459 | nand_get_device(chip, mtd, FL_WRITING); | ||
1460 | |||
1461 | chip->select_chip(mtd, chipnr); | ||
1462 | chip->oob_poi = oob; | ||
1463 | |||
1464 | while (len != *retlen) { | ||
1465 | ret = nand_write_page(mtd, chip, buf, page, 0); | ||
1466 | if (ret) | ||
1467 | return ret; | ||
1468 | page++; | ||
1469 | *retlen += mtd->writesize; | ||
1470 | buf += mtd->writesize; | ||
1471 | chip->oob_poi += mtd->oobsize; | ||
1472 | } | ||
1473 | |||
1474 | /* Deselect and wake up anyone waiting on the device */ | ||
1475 | nand_release_device(mtd); | ||
1476 | return 0; | ||
1477 | } | ||
1478 | EXPORT_SYMBOL_GPL(nand_write_raw); | ||
1679 | 1479 | ||
1680 | /** | 1480 | /** |
1681 | * nand_write_oob - [MTD Interface] NAND write out-of-band | 1481 | * nand_write_oob - [MTD Interface] NAND write out-of-band |
@@ -2082,64 +1882,6 @@ static void nand_resume(struct mtd_info *mtd) | |||
2082 | } | 1882 | } |
2083 | 1883 | ||
2084 | /* | 1884 | /* |
2085 | * Free allocated data structures | ||
2086 | */ | ||
2087 | static void nand_free_kmem(struct nand_chip *chip) | ||
2088 | { | ||
2089 | /* Buffer allocated by nand_scan ? */ | ||
2090 | if (chip->options & NAND_OOBBUF_ALLOC) | ||
2091 | kfree(chip->oob_buf); | ||
2092 | /* Buffer allocated by nand_scan ? */ | ||
2093 | if (chip->options & NAND_DATABUF_ALLOC) | ||
2094 | kfree(chip->data_buf); | ||
2095 | /* Controller allocated by nand_scan ? */ | ||
2096 | if (chip->options & NAND_CONTROLLER_ALLOC) | ||
2097 | kfree(chip->controller); | ||
2098 | } | ||
2099 | |||
2100 | /* | ||
2101 | * Allocate buffers and data structures | ||
2102 | */ | ||
2103 | static int nand_allocate_kmem(struct mtd_info *mtd, struct nand_chip *chip) | ||
2104 | { | ||
2105 | size_t len; | ||
2106 | |||
2107 | if (!chip->oob_buf) { | ||
2108 | len = mtd->oobsize << | ||
2109 | (chip->phys_erase_shift - chip->page_shift); | ||
2110 | chip->oob_buf = kmalloc(len, GFP_KERNEL); | ||
2111 | if (!chip->oob_buf) | ||
2112 | goto outerr; | ||
2113 | chip->options |= NAND_OOBBUF_ALLOC; | ||
2114 | } | ||
2115 | |||
2116 | if (!chip->data_buf) { | ||
2117 | len = mtd->writesize + mtd->oobsize; | ||
2118 | chip->data_buf = kmalloc(len, GFP_KERNEL); | ||
2119 | if (!chip->data_buf) | ||
2120 | goto outerr; | ||
2121 | chip->options |= NAND_DATABUF_ALLOC; | ||
2122 | } | ||
2123 | |||
2124 | if (!chip->controller) { | ||
2125 | chip->controller = kzalloc(sizeof(struct nand_hw_control), | ||
2126 | GFP_KERNEL); | ||
2127 | if (!chip->controller) | ||
2128 | goto outerr; | ||
2129 | |||
2130 | spin_lock_init(&chip->controller->lock); | ||
2131 | init_waitqueue_head(&chip->controller->wq); | ||
2132 | chip->options |= NAND_CONTROLLER_ALLOC; | ||
2133 | } | ||
2134 | return 0; | ||
2135 | |||
2136 | outerr: | ||
2137 | printk(KERN_ERR "nand_scan(): Cannot allocate buffers\n"); | ||
2138 | nand_free_kmem(chip); | ||
2139 | return -ENOMEM; | ||
2140 | } | ||
2141 | |||
2142 | /* | ||
2143 | * Set default functions | 1885 | * Set default functions |
2144 | */ | 1886 | */ |
2145 | static void nand_set_defaults(struct nand_chip *chip, int busw) | 1887 | static void nand_set_defaults(struct nand_chip *chip, int busw) |
@@ -2174,6 +1916,13 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) | |||
2174 | chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf; | 1916 | chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf; |
2175 | if (!chip->scan_bbt) | 1917 | if (!chip->scan_bbt) |
2176 | chip->scan_bbt = nand_default_bbt; | 1918 | chip->scan_bbt = nand_default_bbt; |
1919 | |||
1920 | if (!chip->controller) { | ||
1921 | chip->controller = &chip->hwcontrol; | ||
1922 | spin_lock_init(&chip->controller->lock); | ||
1923 | init_waitqueue_head(&chip->controller->wq); | ||
1924 | } | ||
1925 | |||
2177 | } | 1926 | } |
2178 | 1927 | ||
2179 | /* | 1928 | /* |
@@ -2321,8 +2070,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2321 | * This fills out all the uninitialized function pointers | 2070 | * This fills out all the uninitialized function pointers |
2322 | * with the defaults. | 2071 | * with the defaults. |
2323 | * The flash ID is read and the mtd/chip structures are | 2072 | * The flash ID is read and the mtd/chip structures are |
2324 | * filled with the appropriate values. Buffers are allocated if | 2073 | * filled with the appropriate values. |
2325 | * they are not provided by the board driver | ||
2326 | * The mtd->owner field must be set to the module of the caller | 2074 | * The mtd->owner field must be set to the module of the caller |
2327 | * | 2075 | * |
2328 | */ | 2076 | */ |
@@ -2369,13 +2117,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
2369 | chip->numchips = i; | 2117 | chip->numchips = i; |
2370 | mtd->size = i * chip->chipsize; | 2118 | mtd->size = i * chip->chipsize; |
2371 | 2119 | ||
2372 | /* Allocate buffers and data structures */ | 2120 | /* Preset the internal oob write buffer */ |
2373 | if (nand_allocate_kmem(mtd, chip)) | 2121 | memset(chip->buffers.oobwbuf, 0xff, mtd->oobsize); |
2374 | return -ENOMEM; | ||
2375 | |||
2376 | /* Preset the internal oob buffer */ | ||
2377 | memset(chip->oob_buf, 0xff, | ||
2378 | mtd->oobsize << (chip->phys_erase_shift - chip->page_shift)); | ||
2379 | 2122 | ||
2380 | /* | 2123 | /* |
2381 | * If no default placement scheme is given, select an appropriate one | 2124 | * If no default placement scheme is given, select an appropriate one |
@@ -2415,6 +2158,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
2415 | /* Use standard hwecc read page function ? */ | 2158 | /* Use standard hwecc read page function ? */ |
2416 | if (!chip->ecc.read_page) | 2159 | if (!chip->ecc.read_page) |
2417 | chip->ecc.read_page = nand_read_page_hwecc; | 2160 | chip->ecc.read_page = nand_read_page_hwecc; |
2161 | if (!chip->ecc.write_page) | ||
2162 | chip->ecc.write_page = nand_write_page_hwecc; | ||
2418 | 2163 | ||
2419 | case NAND_ECC_HW_SYNDROME: | 2164 | case NAND_ECC_HW_SYNDROME: |
2420 | if (!chip->ecc.calculate || !chip->ecc.correct || | 2165 | if (!chip->ecc.calculate || !chip->ecc.correct || |
@@ -2423,9 +2168,11 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
2423 | "Hardware ECC not possible\n"); | 2168 | "Hardware ECC not possible\n"); |
2424 | BUG(); | 2169 | BUG(); |
2425 | } | 2170 | } |
2426 | /* Use standard syndrome read page function ? */ | 2171 | /* Use standard syndrome read/write page function ? */ |
2427 | if (!chip->ecc.read_page) | 2172 | if (!chip->ecc.read_page) |
2428 | chip->ecc.read_page = nand_read_page_syndrome; | 2173 | chip->ecc.read_page = nand_read_page_syndrome; |
2174 | if (!chip->ecc.write_page) | ||
2175 | chip->ecc.write_page = nand_write_page_syndrome; | ||
2429 | 2176 | ||
2430 | if (mtd->writesize >= chip->ecc.size) | 2177 | if (mtd->writesize >= chip->ecc.size) |
2431 | break; | 2178 | break; |
@@ -2438,6 +2185,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
2438 | chip->ecc.calculate = nand_calculate_ecc; | 2185 | chip->ecc.calculate = nand_calculate_ecc; |
2439 | chip->ecc.correct = nand_correct_data; | 2186 | chip->ecc.correct = nand_correct_data; |
2440 | chip->ecc.read_page = nand_read_page_swecc; | 2187 | chip->ecc.read_page = nand_read_page_swecc; |
2188 | chip->ecc.write_page = nand_write_page_swecc; | ||
2441 | chip->ecc.size = 256; | 2189 | chip->ecc.size = 256; |
2442 | chip->ecc.bytes = 3; | 2190 | chip->ecc.bytes = 3; |
2443 | break; | 2191 | break; |
@@ -2446,6 +2194,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
2446 | printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " | 2194 | printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " |
2447 | "This is not recommended !!\n"); | 2195 | "This is not recommended !!\n"); |
2448 | chip->ecc.read_page = nand_read_page_swecc; | 2196 | chip->ecc.read_page = nand_read_page_swecc; |
2197 | chip->ecc.write_page = nand_write_page_swecc; | ||
2449 | chip->ecc.size = mtd->writesize; | 2198 | chip->ecc.size = mtd->writesize; |
2450 | chip->ecc.bytes = 0; | 2199 | chip->ecc.bytes = 0; |
2451 | break; | 2200 | break; |
@@ -2522,8 +2271,6 @@ void nand_release(struct mtd_info *mtd) | |||
2522 | 2271 | ||
2523 | /* Free bad block table memory */ | 2272 | /* Free bad block table memory */ |
2524 | kfree(chip->bbt); | 2273 | kfree(chip->bbt); |
2525 | /* Free buffers */ | ||
2526 | nand_free_kmem(chip); | ||
2527 | } | 2274 | } |
2528 | 2275 | ||
2529 | EXPORT_SYMBOL_GPL(nand_scan); | 2276 | EXPORT_SYMBOL_GPL(nand_scan); |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index ecaaca18d1e0..40f99304df76 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -666,7 +666,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b | |||
666 | struct nand_chip *this = mtd->priv; | 666 | struct nand_chip *this = mtd->priv; |
667 | 667 | ||
668 | bd->options &= ~NAND_BBT_SCANEMPTY; | 668 | bd->options &= ~NAND_BBT_SCANEMPTY; |
669 | return create_bbt(mtd, this->data_buf, bd, -1); | 669 | return create_bbt(mtd, this->buffers.databuf, bd, -1); |
670 | } | 670 | } |
671 | 671 | ||
672 | /** | 672 | /** |
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index b7083104a05b..de6de91fbad9 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c | |||
@@ -571,7 +571,6 @@ static int __init rtc_from4_init(void) | |||
571 | this->ecc.mode = NAND_ECC_HW_SYNDROME; | 571 | this->ecc.mode = NAND_ECC_HW_SYNDROME; |
572 | this->ecc.size = 512; | 572 | this->ecc.size = 512; |
573 | this->ecc.bytes = 8; | 573 | this->ecc.bytes = 8; |
574 | this->options |= NAND_HWECC_SYNDROME; | ||
575 | /* return the status of extra status and ECC checks */ | 574 | /* return the status of extra status and ECC checks */ |
576 | this->errstat = rtc_from4_errstat; | 575 | this->errstat = rtc_from4_errstat; |
577 | /* set the nand_oobinfo to support FPGA H/W error detection */ | 576 | /* set the nand_oobinfo to support FPGA H/W error detection */ |
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c index a9cf0190c27a..f9e2d4a0ab8c 100644 --- a/drivers/mtd/nand/toto.c +++ b/drivers/mtd/nand/toto.c | |||
@@ -175,8 +175,6 @@ static int __init toto_init(void) | |||
175 | 175 | ||
176 | goto out; | 176 | goto out; |
177 | 177 | ||
178 | out_buf: | ||
179 | kfree(this->data_buf); | ||
180 | out_mtd: | 178 | out_mtd: |
181 | kfree(toto_mtd); | 179 | kfree(toto_mtd); |
182 | out: | 180 | out: |