aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/inftlcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/inftlcore.c')
-rw-r--r--drivers/mtd/inftlcore.c111
1 files changed, 87 insertions, 24 deletions
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 3396f0e1ac5f..efb1a95aa0a0 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -151,6 +151,69 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev)
151 */ 151 */
152 152
153/* 153/*
154 * Read oob data from flash
155 */
156int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
157 size_t *retlen, uint8_t *buf)
158{
159 struct mtd_oob_ops ops;
160 int res;
161
162 ops.mode = MTD_OOB_PLACE;
163 ops.ooboffs = offs & (mtd->writesize - 1);
164 ops.ooblen = len;
165 ops.oobbuf = buf;
166 ops.datbuf = NULL;
167 ops.len = len;
168
169 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
170 *retlen = ops.retlen;
171 return res;
172}
173
174/*
175 * Write oob data to flash
176 */
177int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
178 size_t *retlen, uint8_t *buf)
179{
180 struct mtd_oob_ops ops;
181 int res;
182
183 ops.mode = MTD_OOB_PLACE;
184 ops.ooboffs = offs & (mtd->writesize - 1);
185 ops.ooblen = len;
186 ops.oobbuf = buf;
187 ops.datbuf = NULL;
188 ops.len = len;
189
190 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
191 *retlen = ops.retlen;
192 return res;
193}
194
195/*
196 * Write data and oob to flash
197 */
198static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
199 size_t *retlen, uint8_t *buf, uint8_t *oob)
200{
201 struct mtd_oob_ops ops;
202 int res;
203
204 ops.mode = MTD_OOB_PLACE;
205 ops.ooboffs = offs;
206 ops.ooblen = mtd->oobsize;
207 ops.oobbuf = oob;
208 ops.datbuf = buf;
209 ops.len = len;
210
211 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
212 *retlen = ops.retlen;
213 return res;
214}
215
216/*
154 * INFTL_findfreeblock: Find a free Erase Unit on the INFTL partition. 217 * INFTL_findfreeblock: Find a free Erase Unit on the INFTL partition.
155 * This function is used when the give Virtual Unit Chain. 218 * This function is used when the give Virtual Unit Chain.
156 */ 219 */
@@ -227,9 +290,9 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
227 if ((BlockMap[block] != 0xffff) || BlockDeleted[block]) 290 if ((BlockMap[block] != 0xffff) || BlockDeleted[block])
228 continue; 291 continue;
229 292
230 if (mtd->read_oob(mtd, (thisEUN * inftl->EraseSize) 293 if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
231 + (block * SECTORSIZE), 16 , &retlen, 294 + (block * SECTORSIZE), 16, &retlen,
232 (char *)&oob) < 0) 295 (char *)&oob) < 0)
233 status = SECTOR_IGNORE; 296 status = SECTOR_IGNORE;
234 else 297 else
235 status = oob.b.Status | oob.b.Status1; 298 status = oob.b.Status | oob.b.Status1;
@@ -304,9 +367,9 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
304 memset(&oob, 0xff, sizeof(struct inftl_oob)); 367 memset(&oob, 0xff, sizeof(struct inftl_oob));
305 oob.b.Status = oob.b.Status1 = SECTOR_USED; 368 oob.b.Status = oob.b.Status1 = SECTOR_USED;
306 369
307 nand_write_raw(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) + 370 inftl_write(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) +
308 (block * SECTORSIZE), SECTORSIZE, &retlen, 371 (block * SECTORSIZE), SECTORSIZE, &retlen,
309 movebuf, (char *)&oob); 372 movebuf, (char *)&oob);
310 } 373 }
311 374
312 /* 375 /*
@@ -437,8 +500,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
437 silly = MAX_LOOPS; 500 silly = MAX_LOOPS;
438 501
439 while (thisEUN <= inftl->lastEUN) { 502 while (thisEUN <= inftl->lastEUN) {
440 mtd->read_oob(mtd, (thisEUN * inftl->EraseSize) + 503 inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
441 blockofs, 8, &retlen, (char *)&bci); 504 blockofs, 8, &retlen, (char *)&bci);
442 505
443 status = bci.Status | bci.Status1; 506 status = bci.Status | bci.Status1;
444 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in " 507 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in "
@@ -525,8 +588,8 @@ hitused:
525 nacs = 0; 588 nacs = 0;
526 thisEUN = inftl->VUtable[thisVUC]; 589 thisEUN = inftl->VUtable[thisVUC];
527 if (thisEUN != BLOCK_NIL) { 590 if (thisEUN != BLOCK_NIL) {
528 mtd->read_oob(mtd, thisEUN * inftl->EraseSize 591 inftl_read_oob(mtd, thisEUN * inftl->EraseSize
529 + 8, 8, &retlen, (char *)&oob.u); 592 + 8, 8, &retlen, (char *)&oob.u);
530 anac = oob.u.a.ANAC + 1; 593 anac = oob.u.a.ANAC + 1;
531 nacs = oob.u.a.NACs + 1; 594 nacs = oob.u.a.NACs + 1;
532 } 595 }
@@ -547,8 +610,8 @@ hitused:
547 oob.u.a.parityPerField = parity; 610 oob.u.a.parityPerField = parity;
548 oob.u.a.discarded = 0xaa; 611 oob.u.a.discarded = 0xaa;
549 612
550 mtd->write_oob(mtd, writeEUN * inftl->EraseSize + 8, 8, 613 inftl_write_oob(mtd, writeEUN * inftl->EraseSize + 8, 8,
551 &retlen, (char *)&oob.u); 614 &retlen, (char *)&oob.u);
552 615
553 /* Also back up header... */ 616 /* Also back up header... */
554 oob.u.b.virtualUnitNo = cpu_to_le16(thisVUC); 617 oob.u.b.virtualUnitNo = cpu_to_le16(thisVUC);
@@ -558,8 +621,8 @@ hitused:
558 oob.u.b.parityPerField = parity; 621 oob.u.b.parityPerField = parity;
559 oob.u.b.discarded = 0xaa; 622 oob.u.b.discarded = 0xaa;
560 623
561 mtd->write_oob(mtd, writeEUN * inftl->EraseSize + 624 inftl_write_oob(mtd, writeEUN * inftl->EraseSize +
562 SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u); 625 SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u);
563 626
564 inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC]; 627 inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC];
565 inftl->VUtable[thisVUC] = writeEUN; 628 inftl->VUtable[thisVUC] = writeEUN;
@@ -610,8 +673,8 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
610 if (BlockUsed[block] || BlockDeleted[block]) 673 if (BlockUsed[block] || BlockDeleted[block])
611 continue; 674 continue;
612 675
613 if (mtd->read_oob(mtd, (thisEUN * inftl->EraseSize) 676 if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
614 + (block * SECTORSIZE), 8 , &retlen, 677 + (block * SECTORSIZE), 8 , &retlen,
615 (char *)&bci) < 0) 678 (char *)&bci) < 0)
616 status = SECTOR_IGNORE; 679 status = SECTOR_IGNORE;
617 else 680 else
@@ -711,8 +774,8 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
711 "block=%d)\n", inftl, block); 774 "block=%d)\n", inftl, block);
712 775
713 while (thisEUN < inftl->nb_blocks) { 776 while (thisEUN < inftl->nb_blocks) {
714 if (mtd->read_oob(mtd, (thisEUN * inftl->EraseSize) + 777 if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
715 blockofs, 8, &retlen, (char *)&bci) < 0) 778 blockofs, 8, &retlen, (char *)&bci) < 0)
716 status = SECTOR_IGNORE; 779 status = SECTOR_IGNORE;
717 else 780 else
718 status = bci.Status | bci.Status1; 781 status = bci.Status | bci.Status1;
@@ -746,10 +809,10 @@ foundit:
746 if (thisEUN != BLOCK_NIL) { 809 if (thisEUN != BLOCK_NIL) {
747 loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs; 810 loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
748 811
749 if (mtd->read_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0) 812 if (inftl_read_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0)
750 return -EIO; 813 return -EIO;
751 bci.Status = bci.Status1 = SECTOR_DELETED; 814 bci.Status = bci.Status1 = SECTOR_DELETED;
752 if (mtd->write_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0) 815 if (inftl_write_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0)
753 return -EIO; 816 return -EIO;
754 INFTL_trydeletechain(inftl, block / (inftl->EraseSize / SECTORSIZE)); 817 INFTL_trydeletechain(inftl, block / (inftl->EraseSize / SECTORSIZE));
755 } 818 }
@@ -790,9 +853,9 @@ static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
790 memset(&oob, 0xff, sizeof(struct inftl_oob)); 853 memset(&oob, 0xff, sizeof(struct inftl_oob));
791 oob.b.Status = oob.b.Status1 = SECTOR_USED; 854 oob.b.Status = oob.b.Status1 = SECTOR_USED;
792 855
793 nand_write_raw(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) + 856 inftl_write(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) +
794 blockofs, SECTORSIZE, &retlen, (char *)buffer, 857 blockofs, SECTORSIZE, &retlen, (char *)buffer,
795 (char *)&oob); 858 (char *)&oob);
796 /* 859 /*
797 * need to write SECTOR_USED flags since they are not written 860 * need to write SECTOR_USED flags since they are not written
798 * in mtd_writeecc 861 * in mtd_writeecc
@@ -820,7 +883,7 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
820 "buffer=%p)\n", inftl, block, buffer); 883 "buffer=%p)\n", inftl, block, buffer);
821 884
822 while (thisEUN < inftl->nb_blocks) { 885 while (thisEUN < inftl->nb_blocks) {
823 if (mtd->read_oob(mtd, (thisEUN * inftl->EraseSize) + 886 if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
824 blockofs, 8, &retlen, (char *)&bci) < 0) 887 blockofs, 8, &retlen, (char *)&bci) < 0)
825 status = SECTOR_IGNORE; 888 status = SECTOR_IGNORE;
826 else 889 else