aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/devices/doc2000.c2
-rw-r--r--drivers/mtd/devices/doc2001.c2
-rw-r--r--drivers/mtd/devices/doc2001plus.c2
-rw-r--r--drivers/mtd/inftlcore.c63
-rw-r--r--drivers/mtd/inftlmount.c12
-rw-r--r--drivers/mtd/mtdconcat.c116
-rw-r--r--drivers/mtd/mtdpart.c54
-rw-r--r--drivers/mtd/nand/nand_base.c122
-rw-r--r--drivers/mtd/nand/nand_bbt.c104
-rw-r--r--drivers/mtd/nftlcore.c15
-rw-r--r--drivers/mtd/nftlmount.c12
-rw-r--r--drivers/mtd/onenand/onenand_base.c75
12 files changed, 198 insertions, 381 deletions
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index 6f32942fdf77..d9ba1ee658f6 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -584,8 +584,6 @@ void DoC2k_init(struct mtd_info *mtd)
584 mtd->unpoint = NULL; 584 mtd->unpoint = NULL;
585 mtd->read = doc_read; 585 mtd->read = doc_read;
586 mtd->write = doc_write; 586 mtd->write = doc_write;
587 mtd->read_ecc = doc_read_ecc;
588 mtd->write_ecc = doc_write_ecc;
589 mtd->read_oob = doc_read_oob; 587 mtd->read_oob = doc_read_oob;
590 mtd->write_oob = doc_write_oob; 588 mtd->write_oob = doc_write_oob;
591 mtd->sync = NULL; 589 mtd->sync = NULL;
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index e6eaef28a2b0..579c0b570ae5 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -369,8 +369,6 @@ void DoCMil_init(struct mtd_info *mtd)
369 mtd->unpoint = NULL; 369 mtd->unpoint = NULL;
370 mtd->read = doc_read; 370 mtd->read = doc_read;
371 mtd->write = doc_write; 371 mtd->write = doc_write;
372 mtd->read_ecc = doc_read_ecc;
373 mtd->write_ecc = doc_write_ecc;
374 mtd->read_oob = doc_read_oob; 372 mtd->read_oob = doc_read_oob;
375 mtd->write_oob = doc_write_oob; 373 mtd->write_oob = doc_write_oob;
376 mtd->sync = NULL; 374 mtd->sync = NULL;
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 8422c5e92d27..1ee0c0dcb53b 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -491,8 +491,6 @@ void DoCMilPlus_init(struct mtd_info *mtd)
491 mtd->unpoint = NULL; 491 mtd->unpoint = NULL;
492 mtd->read = doc_read; 492 mtd->read = doc_read;
493 mtd->write = doc_write; 493 mtd->write = doc_write;
494 mtd->read_ecc = doc_read_ecc;
495 mtd->write_ecc = doc_write_ecc;
496 mtd->read_oob = doc_read_oob; 494 mtd->read_oob = doc_read_oob;
497 mtd->write_oob = doc_write_oob; 495 mtd->write_oob = doc_write_oob;
498 mtd->sync = NULL; 496 mtd->sync = NULL;
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index a3b92479719d..ddd12993780d 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -36,6 +36,7 @@
36#include <linux/mtd/mtd.h> 36#include <linux/mtd/mtd.h>
37#include <linux/mtd/nftl.h> 37#include <linux/mtd/nftl.h>
38#include <linux/mtd/inftl.h> 38#include <linux/mtd/inftl.h>
39#include <linux/mtd/nand.h>
39#include <asm/uaccess.h> 40#include <asm/uaccess.h>
40#include <asm/errno.h> 41#include <asm/errno.h>
41#include <asm/io.h> 42#include <asm/io.h>
@@ -79,14 +80,12 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
79 inftl->mbd.devnum = -1; 80 inftl->mbd.devnum = -1;
80 inftl->mbd.blksize = 512; 81 inftl->mbd.blksize = 512;
81 inftl->mbd.tr = tr; 82 inftl->mbd.tr = tr;
82 memcpy(&inftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
83 inftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
84 83
85 if (INFTL_mount(inftl) < 0) { 84 if (INFTL_mount(inftl) < 0) {
86 printk(KERN_WARNING "INFTL: could not mount device\n"); 85 printk(KERN_WARNING "INFTL: could not mount device\n");
87 kfree(inftl); 86 kfree(inftl);
88 return; 87 return;
89 } 88 }
90 89
91 /* OK, it's a new one. Set up all the data structures. */ 90 /* OK, it's a new one. Set up all the data structures. */
92 91
@@ -221,7 +220,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
221 * Scan to find the Erase Unit which holds the actual data for each 220 * Scan to find the Erase Unit which holds the actual data for each
222 * 512-byte block within the Chain. 221 * 512-byte block within the Chain.
223 */ 222 */
224 silly = MAX_LOOPS; 223 silly = MAX_LOOPS;
225 while (thisEUN < inftl->nb_blocks) { 224 while (thisEUN < inftl->nb_blocks) {
226 for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { 225 for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) {
227 if ((BlockMap[block] != 0xffff) || BlockDeleted[block]) 226 if ((BlockMap[block] != 0xffff) || BlockDeleted[block])
@@ -232,7 +231,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
232 (char *)&oob) < 0) 231 (char *)&oob) < 0)
233 status = SECTOR_IGNORE; 232 status = SECTOR_IGNORE;
234 else 233 else
235 status = oob.b.Status | oob.b.Status1; 234 status = oob.b.Status | oob.b.Status1;
236 235
237 switch(status) { 236 switch(status) {
238 case SECTOR_FREE: 237 case SECTOR_FREE:
@@ -282,29 +281,30 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
282 continue; 281 continue;
283 } 282 }
284 283
285 /* 284 /*
286 * Copy only in non free block (free blocks can only 285 * Copy only in non free block (free blocks can only
287 * happen in case of media errors or deleted blocks). 286 * happen in case of media errors or deleted blocks).
288 */ 287 */
289 if (BlockMap[block] == BLOCK_NIL) 288 if (BlockMap[block] == BLOCK_NIL)
290 continue; 289 continue;
291 290
292 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize * 291 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
293 BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE, 292 BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,
294 &retlen, movebuf); 293 &retlen, movebuf);
295 if (ret < 0) { 294 if (ret < 0) {
296 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize * 295 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
297 BlockMap[block]) + (block * SECTORSIZE), 296 BlockMap[block]) + (block * SECTORSIZE),
298 SECTORSIZE, &retlen, movebuf); 297 SECTORSIZE, &retlen, movebuf);
299 if (ret != -EIO) 298 if (ret != -EIO)
300 DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went " 299 DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
301 "away on retry?\n"); 300 "away on retry?\n");
302 } 301 }
303 memset(&oob, 0xff, sizeof(struct inftl_oob)); 302 memset(&oob, 0xff, sizeof(struct inftl_oob));
304 oob.b.Status = oob.b.Status1 = SECTOR_USED; 303 oob.b.Status = oob.b.Status1 = SECTOR_USED;
305 MTD_WRITEECC(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) + 304
306 (block * SECTORSIZE), SECTORSIZE, &retlen, 305 nand_write_raw(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) +
307 movebuf, (char *)&oob, &inftl->oobinfo); 306 (block * SECTORSIZE), SECTORSIZE, &retlen,
307 movebuf, (char *)&oob);
308 } 308 }
309 309
310 /* 310 /*
@@ -329,17 +329,17 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
329 if (thisEUN == targetEUN) 329 if (thisEUN == targetEUN)
330 break; 330 break;
331 331
332 if (INFTL_formatblock(inftl, thisEUN) < 0) { 332 if (INFTL_formatblock(inftl, thisEUN) < 0) {
333 /* 333 /*
334 * Could not erase : mark block as reserved. 334 * Could not erase : mark block as reserved.
335 */ 335 */
336 inftl->PUtable[thisEUN] = BLOCK_RESERVED; 336 inftl->PUtable[thisEUN] = BLOCK_RESERVED;
337 } else { 337 } else {
338 /* Correctly erased : mark it as free */ 338 /* Correctly erased : mark it as free */
339 inftl->PUtable[thisEUN] = BLOCK_FREE; 339 inftl->PUtable[thisEUN] = BLOCK_FREE;
340 inftl->PUtable[prevEUN] = BLOCK_NIL; 340 inftl->PUtable[prevEUN] = BLOCK_NIL;
341 inftl->numfreeEUNs++; 341 inftl->numfreeEUNs++;
342 } 342 }
343 } 343 }
344 344
345 return targetEUN; 345 return targetEUN;
@@ -437,7 +437,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
437 MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + 437 MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
438 blockofs, 8, &retlen, (char *)&bci); 438 blockofs, 8, &retlen, (char *)&bci);
439 439
440 status = bci.Status | bci.Status1; 440 status = bci.Status | bci.Status1;
441 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in " 441 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in "
442 "EUN %d is %x\n", block , writeEUN, status); 442 "EUN %d is %x\n", block , writeEUN, status);
443 443
@@ -670,12 +670,12 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
670 DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n", 670 DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n",
671 thisEUN, thisVUC); 671 thisEUN, thisVUC);
672 672
673 if (INFTL_formatblock(inftl, thisEUN) < 0) { 673 if (INFTL_formatblock(inftl, thisEUN) < 0) {
674 /* 674 /*
675 * Could not erase : mark block as reserved. 675 * Could not erase : mark block as reserved.
676 */ 676 */
677 inftl->PUtable[thisEUN] = BLOCK_RESERVED; 677 inftl->PUtable[thisEUN] = BLOCK_RESERVED;
678 } else { 678 } else {
679 /* Correctly erased : mark it as free */ 679 /* Correctly erased : mark it as free */
680 inftl->PUtable[thisEUN] = BLOCK_FREE; 680 inftl->PUtable[thisEUN] = BLOCK_FREE;
681 inftl->numfreeEUNs++; 681 inftl->numfreeEUNs++;
@@ -784,9 +784,10 @@ static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
784 784
785 memset(&oob, 0xff, sizeof(struct inftl_oob)); 785 memset(&oob, 0xff, sizeof(struct inftl_oob));
786 oob.b.Status = oob.b.Status1 = SECTOR_USED; 786 oob.b.Status = oob.b.Status1 = SECTOR_USED;
787 MTD_WRITEECC(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) + 787
788 blockofs, SECTORSIZE, &retlen, (char *)buffer, 788 nand_write_raw(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) +
789 (char *)&oob, &inftl->oobinfo); 789 blockofs, SECTORSIZE, &retlen, (char *)buffer,
790 (char *)&oob);
790 /* 791 /*
791 * need to write SECTOR_USED flags since they are not written 792 * need to write SECTOR_USED flags since they are not written
792 * in mtd_writeecc 793 * in mtd_writeecc
@@ -804,9 +805,9 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
804 struct INFTLrecord *inftl = (void *)mbd; 805 struct INFTLrecord *inftl = (void *)mbd;
805 unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)]; 806 unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)];
806 unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1); 807 unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
807 unsigned int status; 808 unsigned int status;
808 int silly = MAX_LOOPS; 809 int silly = MAX_LOOPS;
809 struct inftl_bci bci; 810 struct inftl_bci bci;
810 size_t retlen; 811 size_t retlen;
811 812
812 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld," 813 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld,"
@@ -850,7 +851,7 @@ foundit:
850 /* The requested block is not on the media, return all 0x00 */ 851 /* The requested block is not on the media, return all 0x00 */
851 memset(buffer, 0, SECTORSIZE); 852 memset(buffer, 0, SECTORSIZE);
852 } else { 853 } else {
853 size_t retlen; 854 size_t retlen;
854 loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs; 855 loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
855 if (MTD_READ(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen, 856 if (MTD_READ(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen,
856 buffer)) 857 buffer))
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index 43fdc9433882..f89a03795e76 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -350,21 +350,21 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
350 int len, int check_oob) 350 int len, int check_oob)
351{ 351{
352 u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize]; 352 u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize];
353 struct mtd_info *mtd = inftl->mbd.mtd;
353 size_t retlen; 354 size_t retlen;
354 int i; 355 int i;
355 356
356 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=%p,"
357 "address=0x%x,len=%d,check_oob=%d)\n", inftl,
358 address, len, check_oob);
359
360 for (i = 0; i < len; i += SECTORSIZE) { 357 for (i = 0; i < len; i += SECTORSIZE) {
361 if (MTD_READECC(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &inftl->oobinfo) < 0) 358 if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf))
362 return -1; 359 return -1;
363 if (memcmpb(buf, 0xff, SECTORSIZE) != 0) 360 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
364 return -1; 361 return -1;
365 362
366 if (check_oob) { 363 if (check_oob) {
367 if (memcmpb(buf + SECTORSIZE, 0xff, inftl->mbd.mtd->oobsize) != 0) 364 if(mtd->read_oob(mtd, address, mtd->oobsize,
365 &retlen, &buf[SECTORSIZE]) < 0)
366 return -1;
367 if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
368 return -1; 368 return -1;
369 } 369 }
370 address += SECTORSIZE; 370 address += SECTORSIZE;
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index a6fcee2713b0..6d52137988fa 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -143,116 +143,6 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len,
143} 143}
144 144
145static int 145static int
146concat_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
147 size_t * retlen, u_char * buf, u_char * eccbuf,
148 struct nand_oobinfo *oobsel)
149{
150 struct mtd_concat *concat = CONCAT(mtd);
151 int err = -EINVAL;
152 int i;
153
154 *retlen = 0;
155
156 for (i = 0; i < concat->num_subdev; i++) {
157 struct mtd_info *subdev = concat->subdev[i];
158 size_t size, retsize;
159
160 if (from >= subdev->size) {
161 /* Not destined for this subdev */
162 size = 0;
163 from -= subdev->size;
164 continue;
165 }
166
167 if (from + len > subdev->size)
168 /* First part goes into this subdev */
169 size = subdev->size - from;
170 else
171 /* Entire transaction goes into this subdev */
172 size = len;
173
174 if (subdev->read_ecc)
175 err = subdev->read_ecc(subdev, from, size,
176 &retsize, buf, eccbuf, oobsel);
177 else
178 err = -EINVAL;
179
180 if (err)
181 break;
182
183 *retlen += retsize;
184 len -= size;
185 if (len == 0)
186 break;
187
188 err = -EINVAL;
189 buf += size;
190 if (eccbuf) {
191 eccbuf += subdev->oobsize;
192 /* in nand.c at least, eccbufs are
193 tagged with 2 (int)eccstatus'; we
194 must account for these */
195 eccbuf += 2 * (sizeof (int));
196 }
197 from = 0;
198 }
199 return err;
200}
201
202static int
203concat_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
204 size_t * retlen, const u_char * buf, u_char * eccbuf,
205 struct nand_oobinfo *oobsel)
206{
207 struct mtd_concat *concat = CONCAT(mtd);
208 int err = -EINVAL;
209 int i;
210
211 if (!(mtd->flags & MTD_WRITEABLE))
212 return -EROFS;
213
214 *retlen = 0;
215
216 for (i = 0; i < concat->num_subdev; i++) {
217 struct mtd_info *subdev = concat->subdev[i];
218 size_t size, retsize;
219
220 if (to >= subdev->size) {
221 size = 0;
222 to -= subdev->size;
223 continue;
224 }
225 if (to + len > subdev->size)
226 size = subdev->size - to;
227 else
228 size = len;
229
230 if (!(subdev->flags & MTD_WRITEABLE))
231 err = -EROFS;
232 else if (subdev->write_ecc)
233 err = subdev->write_ecc(subdev, to, size,
234 &retsize, buf, eccbuf, oobsel);
235 else
236 err = -EINVAL;
237
238 if (err)
239 break;
240
241 *retlen += retsize;
242 len -= size;
243 if (len == 0)
244 break;
245
246 err = -EINVAL;
247 buf += size;
248 if (eccbuf)
249 eccbuf += subdev->oobsize;
250 to = 0;
251 }
252 return err;
253}
254
255static int
256concat_writev(struct mtd_info *mtd, const struct kvec *vecs, 146concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
257 unsigned long count, loff_t to, size_t * retlen) 147 unsigned long count, loff_t to, size_t * retlen)
258{ 148{
@@ -823,10 +713,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
823 concat->mtd.oobsize = subdev[0]->oobsize; 713 concat->mtd.oobsize = subdev[0]->oobsize;
824 concat->mtd.ecctype = subdev[0]->ecctype; 714 concat->mtd.ecctype = subdev[0]->ecctype;
825 concat->mtd.eccsize = subdev[0]->eccsize; 715 concat->mtd.eccsize = subdev[0]->eccsize;
826 if (subdev[0]->read_ecc)
827 concat->mtd.read_ecc = concat_read_ecc;
828 if (subdev[0]->write_ecc)
829 concat->mtd.write_ecc = concat_write_ecc;
830 if (subdev[0]->writev) 716 if (subdev[0]->writev)
831 concat->mtd.writev = concat_writev; 717 concat->mtd.writev = concat_writev;
832 if (subdev[0]->read_oob) 718 if (subdev[0]->read_oob)
@@ -869,8 +755,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
869 concat->mtd.oobsize != subdev[i]->oobsize || 755 concat->mtd.oobsize != subdev[i]->oobsize ||
870 concat->mtd.ecctype != subdev[i]->ecctype || 756 concat->mtd.ecctype != subdev[i]->ecctype ||
871 concat->mtd.eccsize != subdev[i]->eccsize || 757 concat->mtd.eccsize != subdev[i]->eccsize ||
872 !concat->mtd.read_ecc != !subdev[i]->read_ecc ||
873 !concat->mtd.write_ecc != !subdev[i]->write_ecc ||
874 !concat->mtd.read_oob != !subdev[i]->read_oob || 758 !concat->mtd.read_oob != !subdev[i]->read_oob ||
875 !concat->mtd.write_oob != !subdev[i]->write_oob) { 759 !concat->mtd.write_oob != !subdev[i]->write_oob) {
876 kfree(concat); 760 kfree(concat);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index f418920320d2..a93550ce7978 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -55,12 +55,8 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
55 len = 0; 55 len = 0;
56 else if (from + len > mtd->size) 56 else if (from + len > mtd->size)
57 len = mtd->size - from; 57 len = mtd->size - from;
58 if (part->master->read_ecc == NULL) 58 return part->master->read (part->master, from + part->offset,
59 return part->master->read (part->master, from + part->offset, 59 len, retlen, buf);
60 len, retlen, buf);
61 else
62 return part->master->read_ecc (part->master, from + part->offset,
63 len, retlen, buf, NULL, &mtd->oobinfo);
64} 60}
65 61
66static int part_point (struct mtd_info *mtd, loff_t from, size_t len, 62static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
@@ -74,6 +70,7 @@ static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
74 return part->master->point (part->master, from + part->offset, 70 return part->master->point (part->master, from + part->offset,
75 len, retlen, buf); 71 len, retlen, buf);
76} 72}
73
77static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) 74static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
78{ 75{
79 struct mtd_part *part = PART(mtd); 76 struct mtd_part *part = PART(mtd);
@@ -81,21 +78,6 @@ static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_
81 part->master->unpoint (part->master, addr, from + part->offset, len); 78 part->master->unpoint (part->master, addr, from + part->offset, len);
82} 79}
83 80
84
85static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
86 size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel)
87{
88 struct mtd_part *part = PART(mtd);
89 if (oobsel == NULL)
90 oobsel = &mtd->oobinfo;
91 if (from >= mtd->size)
92 len = 0;
93 else if (from + len > mtd->size)
94 len = mtd->size - from;
95 return part->master->read_ecc (part->master, from + part->offset,
96 len, retlen, buf, eccbuf, oobsel);
97}
98
99static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len, 81static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
100 size_t *retlen, u_char *buf) 82 size_t *retlen, u_char *buf)
101{ 83{
@@ -148,30 +130,8 @@ static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
148 len = 0; 130 len = 0;
149 else if (to + len > mtd->size) 131 else if (to + len > mtd->size)
150 len = mtd->size - to; 132 len = mtd->size - to;
151 if (part->master->write_ecc == NULL) 133 return part->master->write (part->master, to + part->offset,
152 return part->master->write (part->master, to + part->offset, 134 len, retlen, buf);
153 len, retlen, buf);
154 else
155 return part->master->write_ecc (part->master, to + part->offset,
156 len, retlen, buf, NULL, &mtd->oobinfo);
157
158}
159
160static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
161 size_t *retlen, const u_char *buf,
162 u_char *eccbuf, struct nand_oobinfo *oobsel)
163{
164 struct mtd_part *part = PART(mtd);
165 if (!(mtd->flags & MTD_WRITEABLE))
166 return -EROFS;
167 if (oobsel == NULL)
168 oobsel = &mtd->oobinfo;
169 if (to >= mtd->size)
170 len = 0;
171 else if (to + len > mtd->size)
172 len = mtd->size - to;
173 return part->master->write_ecc (part->master, to + part->offset,
174 len, retlen, buf, eccbuf, oobsel);
175} 135}
176 136
177static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len, 137static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
@@ -372,10 +332,6 @@ int add_mtd_partitions(struct mtd_info *master,
372 slave->mtd.unpoint = part_unpoint; 332 slave->mtd.unpoint = part_unpoint;
373 } 333 }
374 334
375 if (master->read_ecc)
376 slave->mtd.read_ecc = part_read_ecc;
377 if (master->write_ecc)
378 slave->mtd.write_ecc = part_write_ecc;
379 if (master->read_oob) 335 if (master->read_oob)
380 slave->mtd.read_oob = part_read_oob; 336 slave->mtd.read_oob = part_read_oob;
381 if (master->write_oob) 337 if (master->write_oob)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index da2f4d16e506..d796eb508b4f 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -139,16 +139,10 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
139 139
140static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, 140static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
141 size_t *retlen, uint8_t *buf); 141 size_t *retlen, uint8_t *buf);
142static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
143 size_t *retlen, uint8_t *buf, uint8_t *eccbuf,
144 struct nand_oobinfo *oobsel);
145static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, 142static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
146 size_t *retlen, uint8_t *buf); 143 size_t *retlen, uint8_t *buf);
147static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, 144static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
148 size_t *retlen, const uint8_t *buf); 145 size_t *retlen, const uint8_t *buf);
149static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
150 size_t *retlen, const uint8_t *buf, uint8_t *eccbuf,
151 struct nand_oobinfo *oobsel);
152static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, 146static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
153 size_t *retlen, const uint8_t *buf); 147 size_t *retlen, const uint8_t *buf);
154static int nand_erase(struct mtd_info *mtd, struct erase_info *instr); 148static int nand_erase(struct mtd_info *mtd, struct erase_info *instr);
@@ -1080,27 +1074,6 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retl
1080} 1074}
1081 1075
1082/** 1076/**
1083 * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc
1084 * @mtd: MTD device structure
1085 * @from: offset to read from
1086 * @len: number of bytes to read
1087 * @retlen: pointer to variable to store the number of read bytes
1088 * @buf: the databuffer to put data
1089 * @oob_buf: filesystem supplied oob data buffer
1090 * @oobsel: oob selection structure
1091 *
1092 * This function simply calls nand_do_read_ecc with flags = 0xff
1093 */
1094static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
1095 size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel)
1096{
1097 /* use userspace supplied oobinfo, if zero */
1098 if (oobsel == NULL)
1099 oobsel = &mtd->oobinfo;
1100 return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff);
1101}
1102
1103/**
1104 * nand_do_read_ecc - [MTD Interface] Read data with ECC 1077 * nand_do_read_ecc - [MTD Interface] Read data with ECC
1105 * @mtd: MTD device structure 1078 * @mtd: MTD device structure
1106 * @from: offset to read from 1079 * @from: offset to read from
@@ -1524,6 +1497,55 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, s
1524} 1497}
1525 1498
1526/** 1499/**
1500 * nand_write_raw - [GENERIC] Write raw data including oob
1501 * @mtd: MTD device structure
1502 * @buf: source buffer
1503 * @to: offset to write to
1504 * @len: number of bytes to write
1505 * @buf: source buffer
1506 * @oob: oob buffer
1507 *
1508 * Write raw data including oob
1509 */
1510int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
1511 uint8_t *buf, uint8_t *oob)
1512{
1513 struct nand_chip *this = mtd->priv;
1514 int page = (int)(to >> this->page_shift);
1515 int chip = (int)(to >> this->chip_shift);
1516 int ret;
1517
1518 *retlen = 0;
1519
1520 /* Do not allow writes past end of device */
1521 if ((to + len) > mtd->size) {
1522 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1523 "beyond end of device\n");
1524 return -EINVAL;
1525 }
1526
1527 /* Grab the lock and see if the device is available */
1528 nand_get_device(this, mtd, FL_WRITING);
1529
1530 this->select_chip(mtd, chip);
1531 this->data_poi = buf;
1532
1533 while (len != *retlen) {
1534 ret = nand_write_page(mtd, this, page, oob, &mtd->oobinfo, 0);
1535 if (ret)
1536 return ret;
1537 page++;
1538 *retlen += mtd->writesize;
1539 this->data_poi += mtd->writesize;
1540 oob += mtd->oobsize;
1541 }
1542
1543 /* Deselect and wake up anyone waiting on the device */
1544 nand_release_device(mtd);
1545 return 0;
1546}
1547
1548/**
1527 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer 1549 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
1528 * @mtd: MTD device structure 1550 * @mtd: MTD device structure
1529 * @fsbuf: buffer given by fs driver 1551 * @fsbuf: buffer given by fs driver
@@ -1585,57 +1607,39 @@ static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct
1585#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 1607#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
1586 1608
1587/** 1609/**
1588 * nand_write - [MTD Interface] compability function for nand_write_ecc 1610 * nand_write - [MTD Interface] NAND write with ECC
1589 * @mtd: MTD device structure
1590 * @to: offset to write to
1591 * @len: number of bytes to write
1592 * @retlen: pointer to variable to store the number of written bytes
1593 * @buf: the data to write
1594 *
1595 * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
1596 *
1597*/
1598static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf)
1599{
1600 return (nand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL));
1601}
1602
1603/**
1604 * nand_write_ecc - [MTD Interface] NAND write with ECC
1605 * @mtd: MTD device structure 1611 * @mtd: MTD device structure
1606 * @to: offset to write to 1612 * @to: offset to write to
1607 * @len: number of bytes to write 1613 * @len: number of bytes to write
1608 * @retlen: pointer to variable to store the number of written bytes 1614 * @retlen: pointer to variable to store the number of written bytes
1609 * @buf: the data to write 1615 * @buf: the data to write
1610 * @eccbuf: filesystem supplied oob data buffer
1611 * @oobsel: oob selection structure
1612 * 1616 *
1613 * NAND write with ECC 1617 * NAND write with ECC
1614 */ 1618 */
1615static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, 1619static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1616 size_t *retlen, const uint8_t *buf, uint8_t *eccbuf, 1620 size_t *retlen, const uint8_t *buf)
1617 struct nand_oobinfo *oobsel)
1618{ 1621{
1619 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; 1622 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
1620 int autoplace = 0, numpages, totalpages; 1623 int autoplace = 0, numpages, totalpages;
1621 struct nand_chip *this = mtd->priv; 1624 struct nand_chip *this = mtd->priv;
1622 uint8_t *oobbuf, *bufstart; 1625 uint8_t *oobbuf, *bufstart, *eccbuf = NULL;
1623 int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); 1626 int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
1627 struct nand_oobinfo *oobsel = &mtd->oobinfo;
1624 1628
1625 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len); 1629 DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
1626 1630
1627 /* Initialize retlen, in case of early exit */ 1631 /* Initialize retlen, in case of early exit */
1628 *retlen = 0; 1632 *retlen = 0;
1629 1633
1630 /* Do not allow write past end of device */ 1634 /* Do not allow write past end of device */
1631 if ((to + len) > mtd->size) { 1635 if ((to + len) > mtd->size) {
1632 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n"); 1636 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n");
1633 return -EINVAL; 1637 return -EINVAL;
1634 } 1638 }
1635 1639
1636 /* reject writes, which are not page aligned */ 1640 /* reject writes, which are not page aligned */
1637 if (NOTALIGNED(to) || NOTALIGNED(len)) { 1641 if (NOTALIGNED(to) || NOTALIGNED(len)) {
1638 printk(KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); 1642 printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n");
1639 return -EINVAL; 1643 return -EINVAL;
1640 } 1644 }
1641 1645
@@ -1651,10 +1655,6 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
1651 if (nand_check_wp(mtd)) 1655 if (nand_check_wp(mtd))
1652 goto out; 1656 goto out;
1653 1657
1654 /* if oobsel is NULL, use chip defaults */
1655 if (oobsel == NULL)
1656 oobsel = &mtd->oobinfo;
1657
1658 /* Autoplace of oob data ? Use the default placement scheme */ 1658 /* Autoplace of oob data ? Use the default placement scheme */
1659 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { 1659 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
1660 oobsel = this->autooob; 1660 oobsel = this->autooob;
@@ -1689,7 +1689,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
1689 */ 1689 */
1690 ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0)); 1690 ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
1691 if (ret) { 1691 if (ret) {
1692 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret); 1692 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret);
1693 goto out; 1693 goto out;
1694 } 1694 }
1695 /* Next oob page */ 1695 /* Next oob page */
@@ -1712,7 +1712,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
1712 ret = nand_verify_pages(mtd, this, startpage, page - startpage, 1712 ret = nand_verify_pages(mtd, this, startpage, page - startpage,
1713 oobbuf, oobsel, chipnr, (eccbuf != NULL)); 1713 oobbuf, oobsel, chipnr, (eccbuf != NULL));
1714 if (ret) { 1714 if (ret) {
1715 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); 1715 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
1716 goto out; 1716 goto out;
1717 } 1717 }
1718 *retlen = written; 1718 *retlen = written;
@@ -1741,7 +1741,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
1741 if (!ret) 1741 if (!ret)
1742 *retlen = written; 1742 *retlen = written;
1743 else 1743 else
1744 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); 1744 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
1745 1745
1746 out: 1746 out:
1747 /* Deselect and wake up anyone waiting on the device */ 1747 /* Deselect and wake up anyone waiting on the device */
@@ -2527,8 +2527,6 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
2527 mtd->unpoint = NULL; 2527 mtd->unpoint = NULL;
2528 mtd->read = nand_read; 2528 mtd->read = nand_read;
2529 mtd->write = nand_write; 2529 mtd->write = nand_write;
2530 mtd->read_ecc = nand_read_ecc;
2531 mtd->write_ecc = nand_write_ecc;
2532 mtd->read_oob = nand_read_oob; 2530 mtd->read_oob = nand_read_oob;
2533 mtd->write_oob = nand_write_oob; 2531 mtd->write_oob = nand_write_oob;
2534 mtd->sync = nand_sync; 2532 mtd->sync = nand_sync;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index fbccb2a25186..ecaaca18d1e0 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -156,7 +156,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
156 156
157 while (totlen) { 157 while (totlen) {
158 len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); 158 len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
159 res = mtd->read_ecc(mtd, from, len, &retlen, buf, NULL, this->autooob); 159 res = mtd->read(mtd, from, len, &retlen, buf);
160 if (res < 0) { 160 if (res < 0) {
161 if (retlen != len) { 161 if (retlen != len) {
162 printk(KERN_INFO "nand_bbt: Error reading bad block table\n"); 162 printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
@@ -471,17 +471,17 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
471 * 471 *
472*/ 472*/
473static int write_bbt(struct mtd_info *mtd, uint8_t *buf, 473static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
474 struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) 474 struct nand_bbt_descr *td, struct nand_bbt_descr *md,
475 int chipsel)
475{ 476{
476 struct nand_chip *this = mtd->priv; 477 struct nand_chip *this = mtd->priv;
477 struct nand_oobinfo oobinfo;
478 struct erase_info einfo; 478 struct erase_info einfo;
479 int i, j, res, chip = 0; 479 int i, j, res, chip = 0;
480 int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; 480 int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
481 int nrchips, bbtoffs, pageoffs; 481 int nrchips, bbtoffs, pageoffs, ooboffs;
482 uint8_t msk[4]; 482 uint8_t msk[4];
483 uint8_t rcode = td->reserved_block_code; 483 uint8_t rcode = td->reserved_block_code;
484 size_t retlen, len = 0; 484 size_t retlen, len = 0, ooblen;
485 loff_t to; 485 loff_t to;
486 486
487 if (!rcode) 487 if (!rcode)
@@ -526,12 +526,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
526 for (i = 0; i < td->maxblocks; i++) { 526 for (i = 0; i < td->maxblocks; i++) {
527 int block = startblock + dir * i; 527 int block = startblock + dir * i;
528 /* Check, if the block is bad */ 528 /* Check, if the block is bad */
529 switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) { 529 switch ((this->bbt[block >> 2] >>
530 (2 * (block & 0x03))) & 0x03) {
530 case 0x01: 531 case 0x01:
531 case 0x03: 532 case 0x03:
532 continue; 533 continue;
533 } 534 }
534 page = block << (this->bbt_erase_shift - this->page_shift); 535 page = block <<
536 (this->bbt_erase_shift - this->page_shift);
535 /* Check, if the block is used by the mirror table */ 537 /* Check, if the block is used by the mirror table */
536 if (!md || md->pages[chip] != page) 538 if (!md || md->pages[chip] != page)
537 goto write; 539 goto write;
@@ -542,11 +544,20 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
542 544
543 /* Set up shift count and masks for the flash table */ 545 /* Set up shift count and masks for the flash table */
544 bits = td->options & NAND_BBT_NRBITS_MSK; 546 bits = td->options & NAND_BBT_NRBITS_MSK;
547 msk[2] = ~rcode;
545 switch (bits) { 548 switch (bits) {
546 case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break; 549 case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
547 case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break; 550 msk[3] = 0x01;
548 case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break; 551 break;
549 case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; 552 case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
553 msk[3] = 0x03;
554 break;
555 case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
556 msk[3] = 0x0f;
557 break;
558 case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
559 msk[3] = 0xff;
560 break;
550 default: return -EINVAL; 561 default: return -EINVAL;
551 } 562 }
552 563
@@ -554,49 +565,55 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
554 565
555 to = ((loff_t) page) << this->page_shift; 566 to = ((loff_t) page) << this->page_shift;
556 567
557 memcpy(&oobinfo, this->autooob, sizeof(oobinfo));
558 oobinfo.useecc = MTD_NANDECC_PLACEONLY;
559
560 /* Must we save the block contents ? */ 568 /* Must we save the block contents ? */
561 if (td->options & NAND_BBT_SAVECONTENT) { 569 if (td->options & NAND_BBT_SAVECONTENT) {
562 /* Make it block aligned */ 570 /* Make it block aligned */
563 to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); 571 to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
564 len = 1 << this->bbt_erase_shift; 572 len = 1 << this->bbt_erase_shift;
565 res = mtd->read_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo); 573 res = mtd->read(mtd, to, len, &retlen, buf);
566 if (res < 0) { 574 if (res < 0) {
567 if (retlen != len) { 575 if (retlen != len) {
568 printk(KERN_INFO 576 printk(KERN_INFO "nand_bbt: Error "
569 "nand_bbt: Error reading block for writing the bad block table\n"); 577 "reading block for writing "
578 "the bad block table\n");
570 return res; 579 return res;
571 } 580 }
572 printk(KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n"); 581 printk(KERN_WARNING "nand_bbt: ECC error "
582 "while reading block for writing "
583 "bad block table\n");
573 } 584 }
585 /* Read oob data */
586 ooblen = (len >> this->page_shift) * mtd->oobsize;
587 res = mtd->read_oob(mtd, to + mtd->writesize, ooblen,
588 &retlen, &buf[len]);
589 if (res < 0 || retlen != ooblen)
590 goto outerr;
591
574 /* Calc the byte offset in the buffer */ 592 /* Calc the byte offset in the buffer */
575 pageoffs = page - (int)(to >> this->page_shift); 593 pageoffs = page - (int)(to >> this->page_shift);
576 offs = pageoffs << this->page_shift; 594 offs = pageoffs << this->page_shift;
577 /* Preset the bbt area with 0xff */ 595 /* Preset the bbt area with 0xff */
578 memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); 596 memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
579 /* Preset the bbt's oob area with 0xff */ 597 ooboffs = len + (pageoffs * mtd->oobsize);
580 memset(&buf[len + pageoffs * mtd->oobsize], 0xff, 598
581 ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
582 if (td->options & NAND_BBT_VERSION) {
583 buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
584 }
585 } else { 599 } else {
586 /* Calc length */ 600 /* Calc length */
587 len = (size_t) (numblocks >> sft); 601 len = (size_t) (numblocks >> sft);
588 /* Make it page aligned ! */ 602 /* Make it page aligned ! */
589 len = (len + (mtd->writesize - 1)) & ~(mtd->writesize - 1); 603 len = (len + (mtd->writesize - 1)) &
604 ~(mtd->writesize - 1);
590 /* Preset the buffer with 0xff */ 605 /* Preset the buffer with 0xff */
591 memset(buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize); 606 memset(buf, 0xff, len +
607 (len >> this->page_shift)* mtd->oobsize);
592 offs = 0; 608 offs = 0;
609 ooboffs = len;
593 /* Pattern is located in oob area of first page */ 610 /* Pattern is located in oob area of first page */
594 memcpy(&buf[len + td->offs], td->pattern, td->len); 611 memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
595 if (td->options & NAND_BBT_VERSION) {
596 buf[len + td->veroffs] = td->version[chip];
597 }
598 } 612 }
599 613
614 if (td->options & NAND_BBT_VERSION)
615 buf[ooboffs + td->veroffs] = td->version[chip];
616
600 /* walk through the memory table */ 617 /* walk through the memory table */
601 for (i = 0; i < numblocks;) { 618 for (i = 0; i < numblocks;) {
602 uint8_t dat; 619 uint8_t dat;
@@ -604,7 +621,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
604 for (j = 0; j < 4; j++, i++) { 621 for (j = 0; j < 4; j++, i++) {
605 int sftcnt = (i << (3 - sft)) & sftmsk; 622 int sftcnt = (i << (3 - sft)) & sftmsk;
606 /* Do not store the reserved bbt blocks ! */ 623 /* Do not store the reserved bbt blocks ! */
607 buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt); 624 buf[offs + (i >> sft)] &=
625 ~(msk[dat & 0x03] << sftcnt);
608 dat >>= 2; 626 dat >>= 2;
609 } 627 }
610 } 628 }
@@ -614,23 +632,25 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
614 einfo.addr = (unsigned long)to; 632 einfo.addr = (unsigned long)to;
615 einfo.len = 1 << this->bbt_erase_shift; 633 einfo.len = 1 << this->bbt_erase_shift;
616 res = nand_erase_nand(mtd, &einfo, 1); 634 res = nand_erase_nand(mtd, &einfo, 1);
617 if (res < 0) { 635 if (res < 0)
618 printk(KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); 636 goto outerr;
619 return res;
620 }
621 637
622 res = mtd->write_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo); 638 res = nand_write_raw(mtd, to, len, &retlen, buf, &buf[len]);
623 if (res < 0) { 639 if (res < 0)
624 printk(KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); 640 goto outerr;
625 return res; 641
626 } 642 printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
627 printk(KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", 643 "0x%02X\n", (unsigned int)to, td->version[chip]);
628 (unsigned int)to, td->version[chip]);
629 644
630 /* Mark it as used */ 645 /* Mark it as used */
631 td->pages[chip] = page; 646 td->pages[chip] = page;
632 } 647 }
633 return 0; 648 return 0;
649
650 outerr:
651 printk(KERN_WARNING
652 "nand_bbt: Error while writing bad block table %d\n", res);
653 return res;
634} 654}
635 655
636/** 656/**
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index d7cd5fa16ba4..dd03349946c2 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -70,8 +70,6 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
70 nftl->mbd.devnum = -1; 70 nftl->mbd.devnum = -1;
71 nftl->mbd.blksize = 512; 71 nftl->mbd.blksize = 512;
72 nftl->mbd.tr = tr; 72 nftl->mbd.tr = tr;
73 memcpy(&nftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
74 nftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
75 73
76 if (NFTL_mount(nftl) < 0) { 74 if (NFTL_mount(nftl) < 0) {
77 printk(KERN_WARNING "NFTL: could not mount device\n"); 75 printk(KERN_WARNING "NFTL: could not mount device\n");
@@ -369,8 +367,11 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
369 } 367 }
370 memset(&oob, 0xff, sizeof(struct nftl_oob)); 368 memset(&oob, 0xff, sizeof(struct nftl_oob));
371 oob.b.Status = oob.b.Status1 = SECTOR_USED; 369 oob.b.Status = oob.b.Status1 = SECTOR_USED;
372 MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512), 370
373 512, &retlen, movebuf, (char *)&oob, &nftl->oobinfo); 371 nand_write_raw(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) +
372 (block * 512), 512, &retlen, movebuf,
373 (char *)&oob);
374
374 } 375 }
375 376
376 /* add the header so that it is now a valid chain */ 377 /* add the header so that it is now a valid chain */
@@ -639,10 +640,10 @@ static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
639 640
640 memset(&oob, 0xff, sizeof(struct nftl_oob)); 641 memset(&oob, 0xff, sizeof(struct nftl_oob));
641 oob.b.Status = oob.b.Status1 = SECTOR_USED; 642 oob.b.Status = oob.b.Status1 = SECTOR_USED;
642 MTD_WRITEECC(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
643 512, &retlen, (char *)buffer, (char *)&oob, &nftl->oobinfo);
644 /* need to write SECTOR_USED flags since they are not written in mtd_writeecc */
645 643
644 nand_write_raw(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) +
645 blockofs, 512, &retlen, (char *)buffer,
646 (char *)&oob);
646 return 0; 647 return 0;
647} 648}
648#endif /* CONFIG_NFTL_RW */ 649#endif /* CONFIG_NFTL_RW */
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
index 3b104ebb219a..90e5e7e97fdc 100644
--- a/drivers/mtd/nftlmount.c
+++ b/drivers/mtd/nftlmount.c
@@ -268,18 +268,22 @@ static int memcmpb(void *a, int c, int n)
268static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, 268static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
269 int check_oob) 269 int check_oob)
270{ 270{
271 int i;
272 size_t retlen;
273 u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize]; 271 u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
272 struct mtd_info *mtd = nftl->mbd.mtd;
273 size_t retlen;
274 int i;
274 275
275 for (i = 0; i < len; i += SECTORSIZE) { 276 for (i = 0; i < len; i += SECTORSIZE) {
276 if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0) 277 if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf))
277 return -1; 278 return -1;
278 if (memcmpb(buf, 0xff, SECTORSIZE) != 0) 279 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
279 return -1; 280 return -1;
280 281
281 if (check_oob) { 282 if (check_oob) {
282 if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0) 283 if(mtd->read_oob(mtd, address, mtd->oobsize,
284 &retlen, &buf[SECTORSIZE]) < 0)
285 return -1;
286 if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
283 return -1; 287 return -1;
284 } 288 }
285 address += SECTORSIZE; 289 address += SECTORSIZE;
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 3a3fe1d8fcdd..7a2419186ff4 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -597,31 +597,28 @@ static void onenand_release_device(struct mtd_info *mtd)
597} 597}
598 598
599/** 599/**
600 * onenand_read_ecc - [MTD Interface] Read data with ECC 600 * onenand_read - [MTD Interface] Read data from flash
601 * @param mtd MTD device structure 601 * @param mtd MTD device structure
602 * @param from offset to read from 602 * @param from offset to read from
603 * @param len number of bytes to read 603 * @param len number of bytes to read
604 * @param retlen pointer to variable to store the number of read bytes 604 * @param retlen pointer to variable to store the number of read bytes
605 * @param buf the databuffer to put data 605 * @param buf the databuffer to put data
606 * @param oob_buf filesystem supplied oob data buffer
607 * @param oobsel oob selection structure
608 * 606 *
609 * OneNAND read with ECC 607 * Read with ecc
610 */ 608*/
611static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, 609static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
612 size_t *retlen, u_char *buf, 610 size_t *retlen, u_char *buf)
613 u_char *oob_buf, struct nand_oobinfo *oobsel)
614{ 611{
615 struct onenand_chip *this = mtd->priv; 612 struct onenand_chip *this = mtd->priv;
616 int read = 0, column; 613 int read = 0, column;
617 int thislen; 614 int thislen;
618 int ret = 0; 615 int ret = 0;
619 616
620 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); 617 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
621 618
622 /* Do not allow reads past end of device */ 619 /* Do not allow reads past end of device */
623 if ((from + len) > mtd->size) { 620 if ((from + len) > mtd->size) {
624 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: Attempt read beyond end of device\n"); 621 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: Attempt read beyond end of device\n");
625 *retlen = 0; 622 *retlen = 0;
626 return -EINVAL; 623 return -EINVAL;
627 } 624 }
@@ -654,7 +651,7 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
654 break; 651 break;
655 652
656 if (ret) { 653 if (ret) {
657 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: read failed = %d\n", ret); 654 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret);
658 goto out; 655 goto out;
659 } 656 }
660 657
@@ -676,22 +673,6 @@ out:
676} 673}
677 674
678/** 675/**
679 * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc
680 * @param mtd MTD device structure
681 * @param from offset to read from
682 * @param len number of bytes to read
683 * @param retlen pointer to variable to store the number of read bytes
684 * @param buf the databuffer to put data
685 *
686 * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL
687*/
688static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
689 size_t *retlen, u_char *buf)
690{
691 return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
692}
693
694/**
695 * onenand_read_oob - [MTD Interface] OneNAND read out-of-band 676 * onenand_read_oob - [MTD Interface] OneNAND read out-of-band
696 * @param mtd MTD device structure 677 * @param mtd MTD device structure
697 * @param from offset to read from 678 * @param from offset to read from
@@ -834,39 +815,36 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
834#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0) 815#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0)
835 816
836/** 817/**
837 * onenand_write_ecc - [MTD Interface] OneNAND write with ECC 818 * onenand_write - [MTD Interface] write buffer to FLASH
838 * @param mtd MTD device structure 819 * @param mtd MTD device structure
839 * @param to offset to write to 820 * @param to offset to write to
840 * @param len number of bytes to write 821 * @param len number of bytes to write
841 * @param retlen pointer to variable to store the number of written bytes 822 * @param retlen pointer to variable to store the number of written bytes
842 * @param buf the data to write 823 * @param buf the data to write
843 * @param eccbuf filesystem supplied oob data buffer
844 * @param oobsel oob selection structure
845 * 824 *
846 * OneNAND write with ECC 825 * Write with ECC
847 */ 826 */
848static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, 827static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
849 size_t *retlen, const u_char *buf, 828 size_t *retlen, const u_char *buf)
850 u_char *eccbuf, struct nand_oobinfo *oobsel)
851{ 829{
852 struct onenand_chip *this = mtd->priv; 830 struct onenand_chip *this = mtd->priv;
853 int written = 0; 831 int written = 0;
854 int ret = 0; 832 int ret = 0;
855 833
856 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); 834 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
857 835
858 /* Initialize retlen, in case of early exit */ 836 /* Initialize retlen, in case of early exit */
859 *retlen = 0; 837 *retlen = 0;
860 838
861 /* Do not allow writes past end of device */ 839 /* Do not allow writes past end of device */
862 if (unlikely((to + len) > mtd->size)) { 840 if (unlikely((to + len) > mtd->size)) {
863 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt write to past end of device\n"); 841 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt write to past end of device\n");
864 return -EINVAL; 842 return -EINVAL;
865 } 843 }
866 844
867 /* Reject writes, which are not page aligned */ 845 /* Reject writes, which are not page aligned */
868 if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { 846 if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
869 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt to write not page aligned data\n"); 847 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt to write not page aligned data\n");
870 return -EINVAL; 848 return -EINVAL;
871 } 849 }
872 850
@@ -888,7 +866,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
888 866
889 ret = this->wait(mtd, FL_WRITING); 867 ret = this->wait(mtd, FL_WRITING);
890 if (ret) { 868 if (ret) {
891 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: write filaed %d\n", ret); 869 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret);
892 goto out; 870 goto out;
893 } 871 }
894 872
@@ -897,7 +875,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
897 /* Only check verify write turn on */ 875 /* Only check verify write turn on */
898 ret = onenand_verify_page(mtd, (u_char *) buf, to); 876 ret = onenand_verify_page(mtd, (u_char *) buf, to);
899 if (ret) { 877 if (ret) {
900 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret); 878 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);
901 goto out; 879 goto out;
902 } 880 }
903 881
@@ -918,23 +896,6 @@ out:
918} 896}
919 897
920/** 898/**
921 * onenand_write - [MTD Interface] compability function for onenand_write_ecc
922 * @param mtd MTD device structure
923 * @param to offset to write to
924 * @param len number of bytes to write
925 * @param retlen pointer to variable to store the number of written bytes
926 * @param buf the data to write
927 *
928 * This function simply calls onenand_write_ecc
929 * with oob buffer and oobsel = NULL
930 */
931static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
932 size_t *retlen, const u_char *buf)
933{
934 return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL);
935}
936
937/**
938 * onenand_write_oob - [MTD Interface] OneNAND write out-of-band 899 * onenand_write_oob - [MTD Interface] OneNAND write out-of-band
939 * @param mtd MTD device structure 900 * @param mtd MTD device structure
940 * @param to offset to write to 901 * @param to offset to write to
@@ -1812,8 +1773,6 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
1812 mtd->unpoint = NULL; 1773 mtd->unpoint = NULL;
1813 mtd->read = onenand_read; 1774 mtd->read = onenand_read;
1814 mtd->write = onenand_write; 1775 mtd->write = onenand_write;
1815 mtd->read_ecc = onenand_read_ecc;
1816 mtd->write_ecc = onenand_write_ecc;
1817 mtd->read_oob = onenand_read_oob; 1776 mtd->read_oob = onenand_read_oob;
1818 mtd->write_oob = onenand_write_oob; 1777 mtd->write_oob = onenand_write_oob;
1819#ifdef CONFIG_MTD_ONENAND_OTP 1778#ifdef CONFIG_MTD_ONENAND_OTP