aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_base.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-28 21:26:58 -0400
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-29 09:06:51 -0400
commit8593fbc68b0df1168995de76d1af38eb62fd6b62 (patch)
treedd244def53d2be4f1fbff9f74eac404fab8e240f /drivers/mtd/nand/nand_base.c
parentf4a43cfcecfcaeeaa40a9dbc1d1378298c22446e (diff)
[MTD] Rework the out of band handling completely
Hopefully the last iteration on this! The handling of out of band data on NAND was accompanied by tons of fruitless discussions and halfarsed patches to make it work for a particular problem. Sufficiently annoyed by I all those "I know it better" mails and the resonable amount of discarded "it solves my problem" patches, I finally decided to go for the big rework. After removing the _ecc variants of mtd read/write functions the solution to satisfy the various requirements was to refactor the read/write _oob functions in mtd. The major change is that read/write_oob now takes a pointer to an operation descriptor structure "struct mtd_oob_ops".instead of having a function with at least seven arguments. read/write_oob which should probably renamed to a more descriptive name, can do the following tasks: - read/write out of band data - read/write data content and out of band data - read/write raw data content and out of band data (ecc disabled) struct mtd_oob_ops has a mode field, which determines the oob handling mode. Aside of the MTD_OOB_RAW mode, which is intended to be especially for diagnostic purposes and some internal functions e.g. bad block table creation, the other two modes are for mtd clients: MTD_OOB_PLACE puts/gets the given oob data exactly to/from the place which is described by the ooboffs and ooblen fields of the mtd_oob_ops strcuture. It's up to the caller to make sure that the byte positions are not used by the ECC placement algorithms. MTD_OOB_AUTO puts/gets the given oob data automaticaly to/from the places in the out of band area which are described by the oobfree tuples in the ecclayout data structre which is associated to the devicee. The decision whether data plus oob or oob only handling is done depends on the setting of the datbuf member of the data structure. When datbuf == NULL then the internal read/write_oob functions are selected, otherwise the read/write data routines are invoked. Tested on a few platforms with all variants. Please be aware of possible regressions for your particular device / application scenario Disclaimer: Any whining will be ignored from those who just contributed "hot air blurb" and never sat down to tackle the underlying problem of the mess in the NAND driver grown over time and the big chunk of work to fix up the existing users. The problem was not the holiness of the existing MTD interfaces. The problems was the lack of time to go for the big overhaul. It's easy to add more mess to the existing one, but it takes alot of effort to go for a real solution. Improvements and bugfixes are welcome! Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r--drivers/mtd/nand/nand_base.c542
1 files changed, 320 insertions, 222 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index e922b829c4be..b8e6e1579cf1 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -81,23 +81,12 @@ static struct nand_ecclayout nand_oob_64 = {
81 .length = 38}} 81 .length = 38}}
82}; 82};
83 83
84/* This is used for padding purposes in nand_write_oob */
85static uint8_t ffchars[] = {
86 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
87 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
88 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
89 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
90 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
91 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
92 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94};
95
96static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
97 size_t *retlen, const uint8_t *buf);
98static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, 84static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
99 int new_state); 85 int new_state);
100 86
87static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
88 struct mtd_oob_ops *ops);
89
101/* 90/*
102 * For devices which display every fart in the system on a seperate LED. Is 91 * For devices which display every fart in the system on a seperate LED. Is
103 * compiled away when LED support is disabled. 92 * compiled away when LED support is disabled.
@@ -358,7 +347,6 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
358{ 347{
359 struct nand_chip *chip = mtd->priv; 348 struct nand_chip *chip = mtd->priv;
360 uint8_t buf[2] = { 0, 0 }; 349 uint8_t buf[2] = { 0, 0 };
361 size_t retlen;
362 int block; 350 int block;
363 351
364 /* Get block number */ 352 /* Get block number */
@@ -371,8 +359,13 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
371 return nand_update_bbt(mtd, ofs); 359 return nand_update_bbt(mtd, ofs);
372 360
373 /* We write two bytes, so we dont have to mess with 16 bit access */ 361 /* We write two bytes, so we dont have to mess with 16 bit access */
374 ofs += mtd->oobsize + (chip->badblockpos & ~0x01); 362 ofs += mtd->oobsize;
375 return nand_write_oob(mtd, ofs, 2, &retlen, buf); 363 chip->ops.len = 2;
364 chip->ops.datbuf = NULL;
365 chip->ops.oobbuf = buf;
366 chip->ops.ooboffs = chip->badblockpos & ~0x01;
367
368 return nand_do_write_oob(mtd, ofs, &chip->ops);
376} 369}
377 370
378/** 371/**
@@ -740,6 +733,20 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip, int state)
740} 733}
741 734
742/** 735/**
736 * nand_read_page_raw - [Intern] read raw page data without ecc
737 * @mtd: mtd info structure
738 * @chip: nand chip info structure
739 * @buf: buffer to store read data
740 */
741static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
742 uint8_t *buf)
743{
744 chip->read_buf(mtd, buf, mtd->writesize);
745 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
746 return 0;
747}
748
749/**
743 * nand_read_page_swecc - {REPLACABLE] software ecc based page read function 750 * nand_read_page_swecc - {REPLACABLE] software ecc based page read function
744 * @mtd: mtd info structure 751 * @mtd: mtd info structure
745 * @chip: nand chip info structure 752 * @chip: nand chip info structure
@@ -756,11 +763,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
756 uint8_t *ecc_code = chip->buffers.ecccode; 763 uint8_t *ecc_code = chip->buffers.ecccode;
757 int *eccpos = chip->ecc.layout->eccpos; 764 int *eccpos = chip->ecc.layout->eccpos;
758 765
759 chip->read_buf(mtd, buf, mtd->writesize); 766 nand_read_page_raw(mtd, chip, buf);
760 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
761
762 if (chip->ecc.mode == NAND_ECC_NONE)
763 return 0;
764 767
765 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) 768 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
766 chip->ecc.calculate(mtd, p, &ecc_calc[i]); 769 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
@@ -882,18 +885,50 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
882} 885}
883 886
884/** 887/**
885 * nand_do_read - [Internal] Read data with ECC 888 * nand_transfer_oob - [Internal] Transfer oob to client buffer
889 * @chip: nand chip structure
890 * @ops: oob ops structure
891 */
892static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
893 struct mtd_oob_ops *ops)
894{
895 size_t len = ops->ooblen;
896
897 switch(ops->mode) {
898
899 case MTD_OOB_PLACE:
900 case MTD_OOB_RAW:
901 memcpy(oob, chip->oob_poi + ops->ooboffs, len);
902 return oob + len;
903
904 case MTD_OOB_AUTO: {
905 struct nand_oobfree *free = chip->ecc.layout->oobfree;
906 size_t bytes;
907
908 for(; free->length && len; free++, len -= bytes) {
909 bytes = min(len, free->length);
910
911 memcpy(oob, chip->oob_poi + free->offset, bytes);
912 oob += bytes;
913 }
914 return oob;
915 }
916 default:
917 BUG();
918 }
919 return NULL;
920}
921
922/**
923 * nand_do_read_ops - [Internal] Read data with ECC
886 * 924 *
887 * @mtd: MTD device structure 925 * @mtd: MTD device structure
888 * @from: offset to read from 926 * @from: offset to read from
889 * @len: number of bytes to read
890 * @retlen: pointer to variable to store the number of read bytes
891 * @buf: the databuffer to put data
892 * 927 *
893 * Internal function. Called with chip held. 928 * Internal function. Called with chip held.
894 */ 929 */
895int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, 930static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
896 size_t *retlen, uint8_t *buf) 931 struct mtd_oob_ops *ops)
897{ 932{
898 int chipnr, page, realpage, col, bytes, aligned; 933 int chipnr, page, realpage, col, bytes, aligned;
899 struct nand_chip *chip = mtd->priv; 934 struct nand_chip *chip = mtd->priv;
@@ -901,8 +936,8 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
901 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; 936 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
902 int sndcmd = 1; 937 int sndcmd = 1;
903 int ret = 0; 938 int ret = 0;
904 uint32_t readlen = len; 939 uint32_t readlen = ops->len;
905 uint8_t *bufpoi; 940 uint8_t *bufpoi, *oob, *buf;
906 941
907 stats = mtd->ecc_stats; 942 stats = mtd->ecc_stats;
908 943
@@ -915,12 +950,15 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
915 col = (int)(from & (mtd->writesize - 1)); 950 col = (int)(from & (mtd->writesize - 1));
916 chip->oob_poi = chip->buffers.oobrbuf; 951 chip->oob_poi = chip->buffers.oobrbuf;
917 952
953 buf = ops->datbuf;
954 oob = ops->oobbuf;
955
918 while(1) { 956 while(1) {
919 bytes = min(mtd->writesize - col, readlen); 957 bytes = min(mtd->writesize - col, readlen);
920 aligned = (bytes == mtd->writesize); 958 aligned = (bytes == mtd->writesize);
921 959
922 /* Is the current page in the buffer ? */ 960 /* Is the current page in the buffer ? */
923 if (realpage != chip->pagebuf) { 961 if (realpage != chip->pagebuf || oob) {
924 bufpoi = aligned ? buf : chip->buffers.databuf; 962 bufpoi = aligned ? buf : chip->buffers.databuf;
925 963
926 if (likely(sndcmd)) { 964 if (likely(sndcmd)) {
@@ -939,6 +977,16 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
939 memcpy(buf, chip->buffers.databuf + col, bytes); 977 memcpy(buf, chip->buffers.databuf + col, bytes);
940 } 978 }
941 979
980 buf += bytes;
981
982 if (unlikely(oob)) {
983 /* Raw mode does data:oob:data:oob */
984 if (ops->mode != MTD_OOB_RAW)
985 oob = nand_transfer_oob(chip, oob, ops);
986 else
987 buf = nand_transfer_oob(chip, buf, ops);
988 }
989
942 if (!(chip->options & NAND_NO_READRDY)) { 990 if (!(chip->options & NAND_NO_READRDY)) {
943 /* 991 /*
944 * Apply delay or wait for ready/busy pin. Do 992 * Apply delay or wait for ready/busy pin. Do
@@ -952,10 +1000,11 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
952 else 1000 else
953 nand_wait_ready(mtd); 1001 nand_wait_ready(mtd);
954 } 1002 }
955 } else 1003 } else {
956 memcpy(buf, chip->buffers.databuf + col, bytes); 1004 memcpy(buf, chip->buffers.databuf + col, bytes);
1005 buf += bytes;
1006 }
957 1007
958 buf += bytes;
959 readlen -= bytes; 1008 readlen -= bytes;
960 1009
961 if (!readlen) 1010 if (!readlen)
@@ -981,7 +1030,7 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
981 sndcmd = 1; 1030 sndcmd = 1;
982 } 1031 }
983 1032
984 *retlen = len - (size_t) readlen; 1033 ops->retlen = ops->len - (size_t) readlen;
985 1034
986 if (ret) 1035 if (ret)
987 return ret; 1036 return ret;
@@ -1002,57 +1051,49 @@ int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
1002static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, 1051static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
1003 size_t *retlen, uint8_t *buf) 1052 size_t *retlen, uint8_t *buf)
1004{ 1053{
1054 struct nand_chip *chip = mtd->priv;
1005 int ret; 1055 int ret;
1006 1056
1007 *retlen = 0;
1008 /* Do not allow reads past end of device */ 1057 /* Do not allow reads past end of device */
1009 if ((from + len) > mtd->size) 1058 if ((from + len) > mtd->size)
1010 return -EINVAL; 1059 return -EINVAL;
1011 if (!len) 1060 if (!len)
1012 return 0; 1061 return 0;
1013 1062
1014 nand_get_device(mtd->priv, mtd, FL_READING); 1063 nand_get_device(chip, mtd, FL_READING);
1015 1064
1016 ret = nand_do_read(mtd, from, len, retlen, buf); 1065 chip->ops.len = len;
1066 chip->ops.datbuf = buf;
1067 chip->ops.oobbuf = NULL;
1068
1069 ret = nand_do_read_ops(mtd, from, &chip->ops);
1017 1070
1018 nand_release_device(mtd); 1071 nand_release_device(mtd);
1019 1072
1073 *retlen = chip->ops.retlen;
1020 return ret; 1074 return ret;
1021} 1075}
1022 1076
1023/** 1077/**
1024 * nand_read_oob - [MTD Interface] NAND read out-of-band 1078 * nand_do_read_oob - [Intern] NAND read out-of-band
1025 * @mtd: MTD device structure 1079 * @mtd: MTD device structure
1026 * @from: offset to read from 1080 * @from: offset to read from
1027 * @len: number of bytes to read 1081 * @ops: oob operations description structure
1028 * @retlen: pointer to variable to store the number of read bytes
1029 * @buf: the databuffer to put data
1030 * 1082 *
1031 * NAND read out-of-band data from the spare area 1083 * NAND read out-of-band data from the spare area
1032 */ 1084 */
1033static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, 1085static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1034 size_t *retlen, uint8_t *buf) 1086 struct mtd_oob_ops *ops)
1035{ 1087{
1036 int col, page, realpage, chipnr, sndcmd = 1; 1088 int col, page, realpage, chipnr, sndcmd = 1;
1037 struct nand_chip *chip = mtd->priv; 1089 struct nand_chip *chip = mtd->priv;
1038 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; 1090 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1039 int readlen = len; 1091 int direct, bytes, readlen = ops->len;
1092 uint8_t *bufpoi, *buf = ops->oobbuf;
1040 1093
1041 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", 1094 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n",
1042 (unsigned int)from, (int)len); 1095 (unsigned int)from, (int)len);
1043 1096
1044 /* Initialize return length value */
1045 *retlen = 0;
1046
1047 /* Do not allow reads past end of device */
1048 if ((from + len) > mtd->size) {
1049 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1050 "Attempt read beyond end of device\n");
1051 return -EINVAL;
1052 }
1053
1054 nand_get_device(chip, mtd, FL_READING);
1055
1056 chipnr = (int)(from >> chip->chip_shift); 1097 chipnr = (int)(from >> chip->chip_shift);
1057 chip->select_chip(mtd, chipnr); 1098 chip->select_chip(mtd, chipnr);
1058 1099
@@ -1060,20 +1101,31 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
1060 realpage = (int)(from >> chip->page_shift); 1101 realpage = (int)(from >> chip->page_shift);
1061 page = realpage & chip->pagemask; 1102 page = realpage & chip->pagemask;
1062 1103
1063 /* Mask to get column */ 1104 if (ops->mode != MTD_OOB_AUTO) {
1064 col = from & (mtd->oobsize - 1); 1105 col = ops->ooboffs;
1106 direct = 1;
1107 } else {
1108 col = 0;
1109 direct = 0;
1110 }
1065 1111
1066 while(1) { 1112 while(1) {
1067 int bytes = min((int)(mtd->oobsize - col), readlen); 1113 bytes = direct ? ops->ooblen : mtd->oobsize;
1114 bufpoi = direct ? buf : chip->buffers.oobrbuf;
1068 1115
1069 if (likely(sndcmd)) { 1116 if (likely(sndcmd)) {
1070 chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page); 1117 chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page);
1071 sndcmd = 0; 1118 sndcmd = 0;
1072 } 1119 }
1073 1120
1074 chip->read_buf(mtd, buf, bytes); 1121 chip->read_buf(mtd, bufpoi, bytes);
1075 1122
1076 readlen -= bytes; 1123 if (unlikely(!direct))
1124 buf = nand_transfer_oob(chip, buf, ops);
1125 else
1126 buf += ops->ooblen;
1127
1128 readlen -= ops->ooblen;
1077 if (!readlen) 1129 if (!readlen)
1078 break; 1130 break;
1079 1131
@@ -1090,10 +1142,6 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
1090 nand_wait_ready(mtd); 1142 nand_wait_ready(mtd);
1091 } 1143 }
1092 1144
1093 buf += bytes;
1094 bytes = mtd->oobsize;
1095 col = 0;
1096
1097 /* Increment page address */ 1145 /* Increment page address */
1098 realpage++; 1146 realpage++;
1099 1147
@@ -1112,81 +1160,76 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
1112 sndcmd = 1; 1160 sndcmd = 1;
1113 } 1161 }
1114 1162
1115 /* Deselect and wake up anyone waiting on the device */ 1163 ops->retlen = ops->len;
1116 nand_release_device(mtd);
1117
1118 *retlen = len;
1119 return 0; 1164 return 0;
1120} 1165}
1121 1166
1122/** 1167/**
1123 * nand_read_raw - [GENERIC] Read raw data including oob into buffer 1168 * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band
1124 * @mtd: MTD device structure 1169 * @mtd: MTD device structure
1125 * @buf: temporary buffer
1126 * @from: offset to read from 1170 * @from: offset to read from
1127 * @len: number of bytes to read 1171 * @ops: oob operation description structure
1128 * @ooblen: number of oob data bytes to read
1129 * 1172 *
1130 * Read raw data including oob into buffer 1173 * NAND read data and/or out-of-band data
1131 */ 1174 */
1132int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, 1175static int nand_read_oob(struct mtd_info *mtd, loff_t from,
1133 size_t ooblen) 1176 struct mtd_oob_ops *ops)
1134{ 1177{
1178 int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
1179 uint8_t *buf) = NULL;
1135 struct nand_chip *chip = mtd->priv; 1180 struct nand_chip *chip = mtd->priv;
1136 int page = (int)(from >> chip->page_shift); 1181 int ret = -ENOTSUPP;
1137 int chipnr = (int)(from >> chip->chip_shift); 1182
1138 int sndcmd = 1; 1183 ops->retlen = 0;
1139 int cnt = 0;
1140 int pagesize = mtd->writesize + mtd->oobsize;
1141 int blockcheck;
1142 1184
1143 /* Do not allow reads past end of device */ 1185 /* Do not allow reads past end of device */
1144 if ((from + len) > mtd->size) { 1186 if ((from + ops->len) > mtd->size) {
1145 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: " 1187 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1146 "Attempt read beyond end of device\n"); 1188 "Attempt read beyond end of device\n");
1147 return -EINVAL; 1189 return -EINVAL;
1148 } 1190 }
1149 1191
1150 /* Grab the lock and see if the device is available */
1151 nand_get_device(chip, mtd, FL_READING); 1192 nand_get_device(chip, mtd, FL_READING);
1152 1193
1153 chip->select_chip(mtd, chipnr); 1194 switch(ops->mode) {
1154 1195 case MTD_OOB_PLACE:
1155 /* Add requested oob length */ 1196 case MTD_OOB_AUTO:
1156 len += ooblen; 1197 break;
1157 blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1158 1198
1159 while (len) { 1199 case MTD_OOB_RAW:
1160 if (likely(sndcmd)) { 1200 /* Replace the read_page algorithm temporary */
1161 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, 1201 read_page = chip->ecc.read_page;
1162 page & chip->pagemask); 1202 chip->ecc.read_page = nand_read_page_raw;
1163 sndcmd = 0; 1203 break;
1164 }
1165 1204
1166 chip->read_buf(mtd, &buf[cnt], pagesize); 1205 default:
1206 goto out;
1207 }
1167 1208
1168 len -= pagesize; 1209 if (!ops->datbuf)
1169 cnt += pagesize; 1210 ret = nand_do_read_oob(mtd, from, ops);
1170 page++; 1211 else
1212 ret = nand_do_read_ops(mtd, from, ops);
1171 1213
1172 if (!(chip->options & NAND_NO_READRDY)) { 1214 if (unlikely(ops->mode == MTD_OOB_RAW))
1173 if (!chip->dev_ready) 1215 chip->ecc.read_page = read_page;
1174 udelay(chip->chip_delay); 1216 out:
1175 else 1217 nand_release_device(mtd);
1176 nand_wait_ready(mtd); 1218 return ret;
1177 } 1219}
1178 1220
1179 /*
1180 * Check, if the chip supports auto page increment or if we
1181 * cross a block boundary.
1182 */
1183 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck))
1184 sndcmd = 1;
1185 }
1186 1221
1187 /* Deselect and wake up anyone waiting on the device */ 1222/**
1188 nand_release_device(mtd); 1223 * nand_write_page_raw - [Intern] raw page write function
1189 return 0; 1224 * @mtd: mtd info structure
1225 * @chip: nand chip info structure
1226 * @buf: data buffer
1227 */
1228static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
1229 const uint8_t *buf)
1230{
1231 chip->write_buf(mtd, buf, mtd->writesize);
1232 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1190} 1233}
1191 1234
1192/** 1235/**
@@ -1205,17 +1248,14 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
1205 const uint8_t *p = buf; 1248 const uint8_t *p = buf;
1206 int *eccpos = chip->ecc.layout->eccpos; 1249 int *eccpos = chip->ecc.layout->eccpos;
1207 1250
1208 if (chip->ecc.mode != NAND_ECC_NONE) { 1251 /* Software ecc calculation */
1209 /* Software ecc calculation */ 1252 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
1210 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) 1253 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
1211 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
1212 1254
1213 for (i = 0; i < chip->ecc.total; i++) 1255 for (i = 0; i < chip->ecc.total; i++)
1214 chip->oob_poi[eccpos[i]] = ecc_calc[i]; 1256 chip->oob_poi[eccpos[i]] = ecc_calc[i];
1215 }
1216 1257
1217 chip->write_buf(mtd, buf, mtd->writesize); 1258 nand_write_page_raw(mtd, chip, buf);
1218 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1219} 1259}
1220 1260
1221/** 1261/**
@@ -1342,51 +1382,77 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
1342 return 0; 1382 return 0;
1343} 1383}
1344 1384
1385/**
1386 * nand_fill_oob - [Internal] Transfer client buffer to oob
1387 * @chip: nand chip structure
1388 * @oob: oob data buffer
1389 * @ops: oob ops structure
1390 */
1391static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
1392 struct mtd_oob_ops *ops)
1393{
1394 size_t len = ops->ooblen;
1395
1396 switch(ops->mode) {
1397
1398 case MTD_OOB_PLACE:
1399 case MTD_OOB_RAW:
1400 memcpy(chip->oob_poi + ops->ooboffs, oob, len);
1401 return oob + len;
1402
1403 case MTD_OOB_AUTO: {
1404 struct nand_oobfree *free = chip->ecc.layout->oobfree;
1405 size_t bytes;
1406
1407 for(; free->length && len; free++, len -= bytes) {
1408 bytes = min(len, free->length);
1409 memcpy(chip->oob_poi + free->offset, oob, bytes);
1410 oob += bytes;
1411 }
1412 return oob;
1413 }
1414 default:
1415 BUG();
1416 }
1417 return NULL;
1418}
1419
1345#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 1420#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
1346 1421
1347/** 1422/**
1348 * nand_write - [MTD Interface] NAND write with ECC 1423 * nand_do_write_ops - [Internal] NAND write with ECC
1349 * @mtd: MTD device structure 1424 * @mtd: MTD device structure
1350 * @to: offset to write to 1425 * @to: offset to write to
1351 * @len: number of bytes to write 1426 * @ops: oob operations description structure
1352 * @retlen: pointer to variable to store the number of written bytes
1353 * @buf: the data to write
1354 * 1427 *
1355 * NAND write with ECC 1428 * NAND write with ECC
1356 */ 1429 */
1357static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, 1430static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1358 size_t *retlen, const uint8_t *buf) 1431 struct mtd_oob_ops *ops)
1359{ 1432{
1360 int chipnr, realpage, page, blockmask; 1433 int chipnr, realpage, page, blockmask;
1361 struct nand_chip *chip = mtd->priv; 1434 struct nand_chip *chip = mtd->priv;
1362 uint32_t writelen = len; 1435 uint32_t writelen = ops->len;
1436 uint8_t *oob = ops->oobbuf;
1437 uint8_t *buf = ops->datbuf;
1363 int bytes = mtd->writesize; 1438 int bytes = mtd->writesize;
1364 int ret = -EIO; 1439 int ret;
1365 1440
1366 *retlen = 0; 1441 ops->retlen = 0;
1367
1368 /* Do not allow write past end of device */
1369 if ((to + len) > mtd->size) {
1370 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: "
1371 "Attempt to write past end of page\n");
1372 return -EINVAL;
1373 }
1374 1442
1375 /* reject writes, which are not page aligned */ 1443 /* reject writes, which are not page aligned */
1376 if (NOTALIGNED(to) || NOTALIGNED(len)) { 1444 if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
1377 printk(KERN_NOTICE "nand_write: " 1445 printk(KERN_NOTICE "nand_write: "
1378 "Attempt to write not page aligned data\n"); 1446 "Attempt to write not page aligned data\n");
1379 return -EINVAL; 1447 return -EINVAL;
1380 } 1448 }
1381 1449
1382 if (!len) 1450 if (!writelen)
1383 return 0; 1451 return 0;
1384 1452
1385 nand_get_device(chip, mtd, FL_WRITING);
1386
1387 /* Check, if it is write protected */ 1453 /* Check, if it is write protected */
1388 if (nand_check_wp(mtd)) 1454 if (nand_check_wp(mtd))
1389 goto out; 1455 return -EIO;
1390 1456
1391 chipnr = (int)(to >> chip->chip_shift); 1457 chipnr = (int)(to >> chip->chip_shift);
1392 chip->select_chip(mtd, chipnr); 1458 chip->select_chip(mtd, chipnr);
@@ -1397,7 +1463,7 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1397 1463
1398 /* Invalidate the page cache, when we write to the cached page */ 1464 /* Invalidate the page cache, when we write to the cached page */
1399 if (to <= (chip->pagebuf << chip->page_shift) && 1465 if (to <= (chip->pagebuf << chip->page_shift) &&
1400 (chip->pagebuf << chip->page_shift) < (to + len)) 1466 (chip->pagebuf << chip->page_shift) < (to + ops->len))
1401 chip->pagebuf = -1; 1467 chip->pagebuf = -1;
1402 1468
1403 chip->oob_poi = chip->buffers.oobwbuf; 1469 chip->oob_poi = chip->buffers.oobwbuf;
@@ -1405,6 +1471,9 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1405 while(1) { 1471 while(1) {
1406 int cached = writelen > bytes && page != blockmask; 1472 int cached = writelen > bytes && page != blockmask;
1407 1473
1474 if (unlikely(oob))
1475 oob = nand_fill_oob(chip, oob, ops);
1476
1408 ret = nand_write_page(mtd, chip, buf, page, cached); 1477 ret = nand_write_page(mtd, chip, buf, page, cached);
1409 if (ret) 1478 if (ret)
1410 break; 1479 break;
@@ -1424,94 +1493,74 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1424 chip->select_chip(mtd, chipnr); 1493 chip->select_chip(mtd, chipnr);
1425 } 1494 }
1426 } 1495 }
1427 out: 1496
1428 *retlen = len - writelen; 1497 if (unlikely(oob))
1429 nand_release_device(mtd); 1498 memset(chip->oob_poi, 0xff, mtd->oobsize);
1499
1500 ops->retlen = ops->len - writelen;
1430 return ret; 1501 return ret;
1431} 1502}
1432 1503
1433/** 1504/**
1434 * nand_write_raw - [GENERIC] Write raw data including oob 1505 * nand_write - [MTD Interface] NAND write with ECC
1435 * @mtd: MTD device structure 1506 * @mtd: MTD device structure
1436 * @buf: source buffer
1437 * @to: offset to write to 1507 * @to: offset to write to
1438 * @len: number of bytes to write 1508 * @len: number of bytes to write
1439 * @buf: source buffer 1509 * @retlen: pointer to variable to store the number of written bytes
1440 * @oob: oob buffer 1510 * @buf: the data to write
1441 * 1511 *
1442 * Write raw data including oob 1512 * NAND write with ECC
1443 */ 1513 */
1444int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 1514static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1445 const uint8_t *buf, uint8_t *oob) 1515 size_t *retlen, const uint8_t *buf)
1446{ 1516{
1447 struct nand_chip *chip = mtd->priv; 1517 struct nand_chip *chip = mtd->priv;
1448 int page = (int)(to >> chip->page_shift);
1449 int chipnr = (int)(to >> chip->chip_shift);
1450 int ret; 1518 int ret;
1451 1519
1452 *retlen = 0; 1520 /* Do not allow reads past end of device */
1453 1521 if ((to + len) > mtd->size)
1454 /* Do not allow writes past end of device */
1455 if ((to + len) > mtd->size) {
1456 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1457 "beyond end of device\n");
1458 return -EINVAL; 1522 return -EINVAL;
1459 } 1523 if (!len)
1524 return 0;
1460 1525
1461 /* Grab the lock and see if the device is available */ 1526 nand_get_device(chip, mtd, FL_READING);
1462 nand_get_device(chip, mtd, FL_WRITING);
1463 1527
1464 chip->select_chip(mtd, chipnr); 1528 chip->ops.len = len;
1465 chip->oob_poi = oob; 1529 chip->ops.datbuf = (uint8_t *)buf;
1530 chip->ops.oobbuf = NULL;
1466 1531
1467 while (len != *retlen) { 1532 ret = nand_do_write_ops(mtd, to, &chip->ops);
1468 ret = nand_write_page(mtd, chip, buf, page, 0);
1469 if (ret)
1470 return ret;
1471 page++;
1472 *retlen += mtd->writesize;
1473 buf += mtd->writesize;
1474 chip->oob_poi += mtd->oobsize;
1475 }
1476 1533
1477 /* Deselect and wake up anyone waiting on the device */
1478 nand_release_device(mtd); 1534 nand_release_device(mtd);
1479 return 0; 1535
1536 *retlen = chip->ops.retlen;
1537 return ret;
1480} 1538}
1481EXPORT_SYMBOL_GPL(nand_write_raw);
1482 1539
1483/** 1540/**
1484 * nand_write_oob - [MTD Interface] NAND write out-of-band 1541 * nand_do_write_oob - [MTD Interface] NAND write out-of-band
1485 * @mtd: MTD device structure 1542 * @mtd: MTD device structure
1486 * @to: offset to write to 1543 * @to: offset to write to
1487 * @len: number of bytes to write 1544 * @ops: oob operation description structure
1488 * @retlen: pointer to variable to store the number of written bytes
1489 * @buf: the data to write
1490 * 1545 *
1491 * NAND write out-of-band 1546 * NAND write out-of-band
1492 */ 1547 */
1493static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, 1548static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
1494 size_t *retlen, const uint8_t *buf) 1549 struct mtd_oob_ops *ops)
1495{ 1550{
1496 int column, page, status, ret = -EIO, chipnr; 1551 int chipnr, page, status;
1497 struct nand_chip *chip = mtd->priv; 1552 struct nand_chip *chip = mtd->priv;
1498 1553
1499 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", 1554 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
1500 (unsigned int)to, (int)len); 1555 (unsigned int)to, (int)ops->len);
1501
1502 /* Initialize return length value */
1503 *retlen = 0;
1504 1556
1505 /* Do not allow write past end of page */ 1557 /* Do not allow write past end of page */
1506 column = to & (mtd->oobsize - 1); 1558 if ((ops->ooboffs + ops->len) > mtd->oobsize) {
1507 if ((column + len) > mtd->oobsize) {
1508 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " 1559 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1509 "Attempt to write past end of page\n"); 1560 "Attempt to write past end of page\n");
1510 return -EINVAL; 1561 return -EINVAL;
1511 } 1562 }
1512 1563
1513 nand_get_device(chip, mtd, FL_WRITING);
1514
1515 chipnr = (int)(to >> chip->chip_shift); 1564 chipnr = (int)(to >> chip->chip_shift);
1516 chip->select_chip(mtd, chipnr); 1565 chip->select_chip(mtd, chipnr);
1517 1566
@@ -1528,26 +1577,27 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1528 1577
1529 /* Check, if it is write protected */ 1578 /* Check, if it is write protected */
1530 if (nand_check_wp(mtd)) 1579 if (nand_check_wp(mtd))
1531 goto out; 1580 return -EROFS;
1532 1581
1533 /* Invalidate the page cache, if we write to the cached page */ 1582 /* Invalidate the page cache, if we write to the cached page */
1534 if (page == chip->pagebuf) 1583 if (page == chip->pagebuf)
1535 chip->pagebuf = -1; 1584 chip->pagebuf = -1;
1536 1585
1537 if (NAND_MUST_PAD(chip)) { 1586 if (ops->mode == MTD_OOB_AUTO || NAND_MUST_PAD(chip)) {
1587 chip->oob_poi = chip->buffers.oobwbuf;
1588 memset(chip->oob_poi, 0xff, mtd->oobsize);
1589 nand_fill_oob(chip, ops->oobbuf, ops);
1538 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, 1590 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize,
1539 page & chip->pagemask); 1591 page & chip->pagemask);
1540 /* prepad 0xff for partial programming */ 1592 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1541 chip->write_buf(mtd, ffchars, column); 1593 memset(chip->oob_poi, 0xff, mtd->oobsize);
1542 /* write data */
1543 chip->write_buf(mtd, buf, len);
1544 /* postpad 0xff for partial programming */
1545 chip->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
1546 } else { 1594 } else {
1547 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column, 1595 chip->cmdfunc(mtd, NAND_CMD_SEQIN,
1596 mtd->writesize + ops->ooboffs,
1548 page & chip->pagemask); 1597 page & chip->pagemask);
1549 chip->write_buf(mtd, buf, len); 1598 chip->write_buf(mtd, ops->oobbuf, ops->len);
1550 } 1599 }
1600
1551 /* Send command to program the OOB data */ 1601 /* Send command to program the OOB data */
1552 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); 1602 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1553 1603
@@ -1557,27 +1607,75 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1557 if (status & NAND_STATUS_FAIL) { 1607 if (status & NAND_STATUS_FAIL) {
1558 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " 1608 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1559 "Failed write, page 0x%08x\n", page); 1609 "Failed write, page 0x%08x\n", page);
1560 ret = -EIO; 1610 return -EIO;
1561 goto out;
1562 } 1611 }
1563 *retlen = len; 1612 ops->retlen = ops->len;
1564 1613
1565#ifdef CONFIG_MTD_NAND_VERIFY_WRITE 1614#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1566 /* Send command to read back the data */ 1615 if (ops->mode != MTD_OOB_AUTO) {
1567 chip->cmdfunc(mtd, NAND_CMD_READOOB, column, page & chip->pagemask); 1616 /* Send command to read back the data */
1617 chip->cmdfunc(mtd, NAND_CMD_READOOB, ops->ooboffs,
1618 page & chip->pagemask);
1568 1619
1569 if (chip->verify_buf(mtd, buf, len)) { 1620 if (chip->verify_buf(mtd, ops->oobbuf, ops->len)) {
1570 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " 1621 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1571 "Failed write verify, page 0x%08x\n", page); 1622 "Failed write verify, page 0x%08x\n", page);
1572 ret = -EIO; 1623 return -EIO;
1573 goto out; 1624 }
1574 } 1625 }
1575#endif 1626#endif
1576 ret = 0; 1627 return 0;
1628}
1629
1630/**
1631 * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
1632 * @mtd: MTD device structure
1633 * @from: offset to read from
1634 * @ops: oob operation description structure
1635 */
1636static int nand_write_oob(struct mtd_info *mtd, loff_t to,
1637 struct mtd_oob_ops *ops)
1638{
1639 void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
1640 const uint8_t *buf) = NULL;
1641 struct nand_chip *chip = mtd->priv;
1642 int ret = -ENOTSUPP;
1643
1644 ops->retlen = 0;
1645
1646 /* Do not allow writes past end of device */
1647 if ((to + ops->len) > mtd->size) {
1648 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1649 "Attempt read beyond end of device\n");
1650 return -EINVAL;
1651 }
1652
1653 nand_get_device(chip, mtd, FL_READING);
1654
1655 switch(ops->mode) {
1656 case MTD_OOB_PLACE:
1657 case MTD_OOB_AUTO:
1658 break;
1659
1660 case MTD_OOB_RAW:
1661 /* Replace the write_page algorithm temporary */
1662 write_page = chip->ecc.write_page;
1663 chip->ecc.write_page = nand_write_page_raw;
1664 break;
1665
1666 default:
1667 goto out;
1668 }
1669
1670 if (!ops->datbuf)
1671 ret = nand_do_write_oob(mtd, to, ops);
1672 else
1673 ret = nand_do_write_ops(mtd, to, ops);
1674
1675 if (unlikely(ops->mode == MTD_OOB_RAW))
1676 chip->ecc.write_page = write_page;
1577 out: 1677 out:
1578 /* Deselect and wake up anyone waiting on the device */
1579 nand_release_device(mtd); 1678 nand_release_device(mtd);
1580
1581 return ret; 1679 return ret;
1582} 1680}
1583 1681
@@ -2191,8 +2289,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
2191 case NAND_ECC_NONE: 2289 case NAND_ECC_NONE:
2192 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " 2290 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2193 "This is not recommended !!\n"); 2291 "This is not recommended !!\n");
2194 chip->ecc.read_page = nand_read_page_swecc; 2292 chip->ecc.read_page = nand_read_page_raw;
2195 chip->ecc.write_page = nand_write_page_swecc; 2293 chip->ecc.write_page = nand_write_page_raw;
2196 chip->ecc.size = mtd->writesize; 2294 chip->ecc.size = mtd->writesize;
2197 chip->ecc.bytes = 0; 2295 chip->ecc.bytes = 0;
2198 break; 2296 break;