diff options
Diffstat (limited to 'drivers/mtd/inftlcore.c')
-rw-r--r-- | drivers/mtd/inftlcore.c | 111 |
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 | */ | ||
156 | int 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 | */ | ||
177 | int 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 | */ | ||
198 | static 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 |