aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nftlcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nftlcore.c')
-rw-r--r--drivers/mtd/nftlcore.c92
1 files changed, 76 insertions, 16 deletions
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index 359533b33d9b..f6ffe7949b26 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -134,6 +134,69 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev)
134 kfree(nftl); 134 kfree(nftl);
135} 135}
136 136
137/*
138 * Read oob data from flash
139 */
140int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
141 size_t *retlen, uint8_t *buf)
142{
143 struct mtd_oob_ops ops;
144 int res;
145
146 ops.mode = MTD_OOB_PLACE;
147 ops.ooboffs = offs & (mtd->writesize - 1);
148 ops.ooblen = len;
149 ops.oobbuf = buf;
150 ops.datbuf = NULL;
151 ops.len = len;
152
153 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
154 *retlen = ops.retlen;
155 return res;
156}
157
158/*
159 * Write oob data to flash
160 */
161int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
162 size_t *retlen, uint8_t *buf)
163{
164 struct mtd_oob_ops ops;
165 int res;
166
167 ops.mode = MTD_OOB_PLACE;
168 ops.ooboffs = offs & (mtd->writesize - 1);
169 ops.ooblen = len;
170 ops.oobbuf = buf;
171 ops.datbuf = NULL;
172 ops.len = len;
173
174 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
175 *retlen = ops.retlen;
176 return res;
177}
178
179/*
180 * Write data and oob to flash
181 */
182static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
183 size_t *retlen, uint8_t *buf, uint8_t *oob)
184{
185 struct mtd_oob_ops ops;
186 int res;
187
188 ops.mode = MTD_OOB_PLACE;
189 ops.ooboffs = offs;
190 ops.ooblen = mtd->oobsize;
191 ops.oobbuf = oob;
192 ops.datbuf = buf;
193 ops.len = len;
194
195 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
196 *retlen = ops.retlen;
197 return res;
198}
199
137#ifdef CONFIG_NFTL_RW 200#ifdef CONFIG_NFTL_RW
138 201
139/* Actual NFTL access routines */ 202/* Actual NFTL access routines */
@@ -216,7 +279,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
216 279
217 targetEUN = thisEUN; 280 targetEUN = thisEUN;
218 for (block = 0; block < nftl->EraseSize / 512; block ++) { 281 for (block = 0; block < nftl->EraseSize / 512; block ++) {
219 mtd->read_oob(mtd, (thisEUN * nftl->EraseSize) + 282 nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
220 (block * 512), 16 , &retlen, 283 (block * 512), 16 , &retlen,
221 (char *)&oob); 284 (char *)&oob);
222 if (block == 2) { 285 if (block == 2) {
@@ -333,7 +396,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
333 longer one */ 396 longer one */
334 oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); 397 oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
335 oob.u.c.unused = 0xffffffff; 398 oob.u.c.unused = 0xffffffff;
336 mtd->write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, 399 nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
337 8, &retlen, (char *)&oob.u); 400 8, &retlen, (char *)&oob.u);
338 } 401 }
339 402
@@ -369,17 +432,15 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
369 memset(&oob, 0xff, sizeof(struct nftl_oob)); 432 memset(&oob, 0xff, sizeof(struct nftl_oob));
370 oob.b.Status = oob.b.Status1 = SECTOR_USED; 433 oob.b.Status = oob.b.Status1 = SECTOR_USED;
371 434
372 nand_write_raw(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 435 nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) +
373 (block * 512), 512, &retlen, movebuf, 436 (block * 512), 512, &retlen, movebuf, (char *)&oob);
374 (char *)&oob);
375
376 } 437 }
377 438
378 /* add the header so that it is now a valid chain */ 439 /* add the header so that it is now a valid chain */
379 oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); 440 oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
380 oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; 441 oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
381 442
382 mtd->write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, 443 nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8,
383 8, &retlen, (char *)&oob.u); 444 8, &retlen, (char *)&oob.u);
384 445
385 /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ 446 /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
@@ -499,7 +560,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
499 560
500 lastEUN = writeEUN; 561 lastEUN = writeEUN;
501 562
502 mtd->read_oob(mtd, 563 nftl_read_oob(mtd,
503 (writeEUN * nftl->EraseSize) + blockofs, 564 (writeEUN * nftl->EraseSize) + blockofs,
504 8, &retlen, (char *)&bci); 565 8, &retlen, (char *)&bci);
505 566
@@ -588,12 +649,12 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
588 nftl->ReplUnitTable[writeEUN] = BLOCK_NIL; 649 nftl->ReplUnitTable[writeEUN] = BLOCK_NIL;
589 650
590 /* ... and on the flash itself */ 651 /* ... and on the flash itself */
591 mtd->read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8, 652 nftl_read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
592 &retlen, (char *)&oob.u); 653 &retlen, (char *)&oob.u);
593 654
594 oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); 655 oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
595 656
596 mtd->write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8, 657 nftl_write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
597 &retlen, (char *)&oob.u); 658 &retlen, (char *)&oob.u);
598 659
599 /* we link the new block to the chain only after the 660 /* we link the new block to the chain only after the
@@ -603,13 +664,13 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
603 /* Both in our cache... */ 664 /* Both in our cache... */
604 nftl->ReplUnitTable[lastEUN] = writeEUN; 665 nftl->ReplUnitTable[lastEUN] = writeEUN;
605 /* ... and on the flash itself */ 666 /* ... and on the flash itself */
606 mtd->read_oob(mtd, (lastEUN * nftl->EraseSize) + 8, 667 nftl_read_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
607 8, &retlen, (char *)&oob.u); 668 8, &retlen, (char *)&oob.u);
608 669
609 oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum 670 oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum
610 = cpu_to_le16(writeEUN); 671 = cpu_to_le16(writeEUN);
611 672
612 mtd->write_oob(mtd, (lastEUN * nftl->EraseSize) + 8, 673 nftl_write_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
613 8, &retlen, (char *)&oob.u); 674 8, &retlen, (char *)&oob.u);
614 } 675 }
615 676
@@ -643,9 +704,8 @@ static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
643 memset(&oob, 0xff, sizeof(struct nftl_oob)); 704 memset(&oob, 0xff, sizeof(struct nftl_oob));
644 oob.b.Status = oob.b.Status1 = SECTOR_USED; 705 oob.b.Status = oob.b.Status1 = SECTOR_USED;
645 706
646 nand_write_raw(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + 707 nftl_write(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
647 blockofs, 512, &retlen, (char *)buffer, 708 512, &retlen, (char *)buffer, (char *)&oob);
648 (char *)&oob);
649 return 0; 709 return 0;
650} 710}
651#endif /* CONFIG_NFTL_RW */ 711#endif /* CONFIG_NFTL_RW */
@@ -667,7 +727,7 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
667 727
668 if (thisEUN != BLOCK_NIL) { 728 if (thisEUN != BLOCK_NIL) {
669 while (thisEUN < nftl->nb_blocks) { 729 while (thisEUN < nftl->nb_blocks) {
670 if (mtd->read_oob(mtd, (thisEUN * nftl->EraseSize) + 730 if (nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
671 blockofs, 8, &retlen, 731 blockofs, 8, &retlen,
672 (char *)&bci) < 0) 732 (char *)&bci) < 0)
673 status = SECTOR_IGNORE; 733 status = SECTOR_IGNORE;