00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #include <linux/slab.h>
00056 #include <linux/types.h>
00057 #include <linux/mtd/mtd.h>
00058 #include <linux/mtd/nand.h>
00059 #include <linux/mtd/nand_ecc.h>
00060 #include <linux/mtd/compatmac.h>
00061 #include <linux/bitops.h>
00062 #include <linux/delay.h>
00063 #include <linux/vmalloc.h>
00064
00078 static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
00079 {
00080 int i, end = 0;
00081 uint8_t *p = buf;
00082
00083 end = paglen + td->offs;
00084 if (td->options & NAND_BBT_SCANEMPTY) {
00085 for (i = 0; i < end; i++) {
00086 if (p[i] != 0xff)
00087 return -1;
00088 }
00089 }
00090 p += end;
00091
00092
00093 for (i = 0; i < td->len; i++) {
00094 if (p[i] != td->pattern[i])
00095 return -1;
00096 }
00097
00098 if (td->options & NAND_BBT_SCANEMPTY) {
00099 p += td->len;
00100 end += td->len;
00101 for (i = end; i < len; i++) {
00102 if (*p++ != 0xff)
00103 return -1;
00104 }
00105 }
00106 return 0;
00107 }
00108
00119 static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
00120 {
00121 int i;
00122 uint8_t *p = buf;
00123
00124
00125 for (i = 0; i < td->len; i++) {
00126 if (p[td->offs + i] != td->pattern[i])
00127 return -1;
00128 }
00129 return 0;
00130 }
00131
00145 static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
00146 int bits, int offs, int reserved_block_code)
00147 {
00148 int res, i, j, act = 0;
00149 struct nand_chip *this = mtd->priv;
00150 size_t retlen, len, totlen;
00151 loff_t from;
00152 uint8_t msk = (uint8_t) ((1 << bits) - 1);
00153
00154 totlen = (num * bits) >> 3;
00155 from = ((loff_t) page) << this->page_shift;
00156
00157 while (totlen) {
00158 len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
00159 res = mtd->read(mtd, from, len, &retlen, buf);
00160 if (res < 0) {
00161 if (retlen != len) {
00162 printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
00163 return res;
00164 }
00165 printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
00166 }
00167
00168
00169 for (i = 0; i < len; i++) {
00170 uint8_t dat = buf[i];
00171 for (j = 0; j < 8; j += bits, act += 2) {
00172 uint8_t tmp = (dat >> j) & msk;
00173 if (tmp == msk)
00174 continue;
00175 if (reserved_block_code && (tmp == reserved_block_code)) {
00176 printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
00177 ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
00178 this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
00179 mtd->ecc_stats.bbtblocks++;
00180 continue;
00181 }
00182
00183
00184 printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
00185 ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
00186
00187 if (tmp == 0)
00188 this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
00189 else
00190 this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
00191 mtd->ecc_stats.badblocks++;
00192 }
00193 }
00194 totlen -= len;
00195 from += len;
00196 }
00197 return 0;
00198 }
00199
00211 static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
00212 {
00213 struct nand_chip *this = mtd->priv;
00214 int res = 0, i;
00215 int bits;
00216
00217 bits = td->options & NAND_BBT_NRBITS_MSK;
00218 if (td->options & NAND_BBT_PERCHIP) {
00219 int offs = 0;
00220 for (i = 0; i < this->numchips; i++) {
00221 if (chip == -1 || chip == i)
00222 res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code);
00223 if (res)
00224 return res;
00225 offs += this->chipsize >> (this->bbt_erase_shift + 2);
00226 }
00227 } else {
00228 res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code);
00229 if (res)
00230 return res;
00231 }
00232 return 0;
00233 }
00234
00235
00236
00237
00238 static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
00239 size_t len)
00240 {
00241 struct mtd_oob_ops ops;
00242
00243 ops.mode = MTD_OOB_RAW;
00244 ops.ooboffs = 0;
00245 ops.ooblen = mtd->oobsize;
00246 ops.oobbuf = buf;
00247 ops.datbuf = buf;
00248 ops.len = len;
00249
00250 return mtd->read_oob(mtd, offs, &ops);
00251 }
00252
00253
00254
00255
00256 static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
00257 uint8_t *buf, uint8_t *oob)
00258 {
00259 struct mtd_oob_ops ops;
00260
00261 ops.mode = MTD_OOB_PLACE;
00262 ops.ooboffs = 0;
00263 ops.ooblen = mtd->oobsize;
00264 ops.datbuf = buf;
00265 ops.oobbuf = oob;
00266 ops.len = len;
00267
00268 return mtd->write_oob(mtd, offs, &ops);
00269 }
00270
00282 static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
00283 struct nand_bbt_descr *td, struct nand_bbt_descr *md)
00284 {
00285 struct nand_chip *this = mtd->priv;
00286
00287
00288 if (td->options & NAND_BBT_VERSION) {
00289 scan_read_raw(mtd, buf, td->pages[0] << this->page_shift,
00290 mtd->writesize);
00291 td->version[0] = buf[mtd->writesize + td->veroffs];
00292 printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
00293 td->pages[0], td->version[0]);
00294 }
00295
00296
00297 if (md && (md->options & NAND_BBT_VERSION)) {
00298 scan_read_raw(mtd, buf, md->pages[0] << this->page_shift,
00299 mtd->writesize);
00300 md->version[0] = buf[mtd->writesize + md->veroffs];
00301 printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
00302 md->pages[0], md->version[0]);
00303 }
00304 return 1;
00305 }
00306
00307
00308
00309
00310 static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
00311 loff_t offs, uint8_t *buf, size_t readlen,
00312 int scanlen, int len)
00313 {
00314 int ret, j;
00315
00316 ret = scan_read_raw(mtd, buf, offs, readlen);
00317 if (ret)
00318 return ret;
00319
00320 for (j = 0; j < len; j++, buf += scanlen) {
00321 if (check_pattern(buf, scanlen, mtd->writesize, bd))
00322 return 1;
00323 }
00324 return 0;
00325 }
00326
00327
00328
00329
00330 static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
00331 loff_t offs, uint8_t *buf, int len)
00332 {
00333 struct mtd_oob_ops ops;
00334 int j, ret;
00335
00336 ops.len = mtd->oobsize;
00337 ops.ooblen = mtd->oobsize;
00338 ops.oobbuf = buf;
00339 ops.ooboffs = 0;
00340 ops.datbuf = NULL;
00341 ops.mode = MTD_OOB_PLACE;
00342
00343 for (j = 0; j < len; j++) {
00344
00345
00346
00347
00348
00349 ret = mtd->read_oob(mtd, offs, &ops);
00350 if (ret)
00351 return ret;
00352
00353 if (check_short_pattern(buf, bd))
00354 return 1;
00355
00356 offs += mtd->writesize;
00357 }
00358 return 0;
00359 }
00360
00372 static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
00373 struct nand_bbt_descr *bd, int chip)
00374 {
00375 struct nand_chip *this = mtd->priv;
00376 int i, numblocks, len, scanlen;
00377 int startblock;
00378 loff_t from;
00379 size_t readlen;
00380
00381 printk(KERN_INFO "Scanning device for bad blocks\n");
00382
00383 if (bd->options & NAND_BBT_SCANALLPAGES)
00384 len = 1 << (this->bbt_erase_shift - this->page_shift);
00385 else {
00386 if (bd->options & NAND_BBT_SCAN2NDPAGE)
00387 len = 2;
00388 else
00389 len = 1;
00390 }
00391
00392 if (!(bd->options & NAND_BBT_SCANEMPTY)) {
00393
00394 scanlen = 0;
00395 readlen = bd->len;
00396 } else {
00397
00398 scanlen = mtd->writesize + mtd->oobsize;
00399 readlen = len * mtd->writesize;
00400 }
00401
00402 if (chip == -1) {
00403
00404
00405 numblocks = mtd->size >> (this->bbt_erase_shift - 1);
00406 startblock = 0;
00407 from = 0;
00408 } else {
00409 if (chip >= this->numchips) {
00410 printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
00411 chip + 1, this->numchips);
00412 return -EINVAL;
00413 }
00414 numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
00415 startblock = chip * numblocks;
00416 numblocks += startblock;
00417 from = startblock << (this->bbt_erase_shift - 1);
00418 }
00419
00420 for (i = startblock; i < numblocks;) {
00421 int ret;
00422
00423 if (bd->options & NAND_BBT_SCANALLPAGES)
00424 ret = scan_block_full(mtd, bd, from, buf, readlen,
00425 scanlen, len);
00426 else
00427 ret = scan_block_fast(mtd, bd, from, buf, len);
00428
00429 if (ret < 0)
00430 return ret;
00431
00432 if (ret) {
00433 this->bbt[i >> 3] |= 0x03 << (i & 0x6);
00434 printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
00435 i >> 1, (unsigned int)from);
00436 mtd->ecc_stats.badblocks++;
00437 }
00438
00439 i += 2;
00440 from += (1 << this->bbt_erase_shift);
00441 }
00442 return 0;
00443 }
00444
00462 static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
00463 {
00464 struct nand_chip *this = mtd->priv;
00465 int i, chips;
00466 int bits, startblock, block, dir;
00467 int scanlen = mtd->writesize + mtd->oobsize;
00468 int bbtblocks;
00469 int blocktopage = this->bbt_erase_shift - this->page_shift;
00470
00471
00472 if (td->options & NAND_BBT_LASTBLOCK) {
00473 startblock = (mtd->size >> this->bbt_erase_shift) - 1;
00474 dir = -1;
00475 } else {
00476 startblock = 0;
00477 dir = 1;
00478 }
00479
00480
00481 if (td->options & NAND_BBT_PERCHIP) {
00482 chips = this->numchips;
00483 bbtblocks = this->chipsize >> this->bbt_erase_shift;
00484 startblock &= bbtblocks - 1;
00485 } else {
00486 chips = 1;
00487 bbtblocks = mtd->size >> this->bbt_erase_shift;
00488 }
00489
00490
00491 bits = td->options & NAND_BBT_NRBITS_MSK;
00492
00493 for (i = 0; i < chips; i++) {
00494
00495 td->version[i] = 0;
00496 td->pages[i] = -1;
00497
00498 for (block = 0; block < td->maxblocks; block++) {
00499
00500 int actblock = startblock + dir * block;
00501 loff_t offs = actblock << this->bbt_erase_shift;
00502
00503
00504 scan_read_raw(mtd, buf, offs, mtd->writesize);
00505 if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
00506 td->pages[i] = actblock << blocktopage;
00507 if (td->options & NAND_BBT_VERSION) {
00508 td->version[i] = buf[mtd->writesize + td->veroffs];
00509 }
00510 break;
00511 }
00512 }
00513 startblock += this->chipsize >> this->bbt_erase_shift;
00514 }
00515
00516 for (i = 0; i < chips; i++) {
00517 if (td->pages[i] == -1)
00518 printk(KERN_WARNING "Bad block table not found for chip %d\n", i);
00519 else
00520 printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],
00521 td->version[i]);
00522 }
00523 return 0;
00524 }
00525
00535 static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
00536 {
00537
00538 search_bbt(mtd, buf, td);
00539
00540
00541 if (md)
00542 search_bbt(mtd, buf, md);
00543
00544
00545 return 1;
00546 }
00547
00560 static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
00561 struct nand_bbt_descr *td, struct nand_bbt_descr *md,
00562 int chipsel)
00563 {
00564 struct nand_chip *this = mtd->priv;
00565 struct erase_info einfo;
00566 int i, j, res, chip = 0;
00567 int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
00568 int nrchips, bbtoffs, pageoffs, ooboffs;
00569 uint8_t msk[4];
00570 uint8_t rcode = td->reserved_block_code;
00571 size_t retlen, len = 0;
00572 loff_t to;
00573 struct mtd_oob_ops ops;
00574
00575 ops.ooblen = mtd->oobsize;
00576 ops.ooboffs = 0;
00577 ops.datbuf = NULL;
00578 ops.mode = MTD_OOB_PLACE;
00579
00580 if (!rcode)
00581 rcode = 0xff;
00582
00583 if (td->options & NAND_BBT_PERCHIP) {
00584 numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
00585
00586 if (chipsel == -1) {
00587 nrchips = this->numchips;
00588 } else {
00589 nrchips = chipsel + 1;
00590 chip = chipsel;
00591 }
00592 } else {
00593 numblocks = (int)(mtd->size >> this->bbt_erase_shift);
00594 nrchips = 1;
00595 }
00596
00597
00598 for (; chip < nrchips; chip++) {
00599
00600
00601
00602
00603
00604 if (td->pages[chip] != -1) {
00605 page = td->pages[chip];
00606 goto write;
00607 }
00608
00609
00610
00611 if (td->options & NAND_BBT_LASTBLOCK) {
00612 startblock = numblocks * (chip + 1) - 1;
00613 dir = -1;
00614 } else {
00615 startblock = chip * numblocks;
00616 dir = 1;
00617 }
00618
00619 for (i = 0; i < td->maxblocks; i++) {
00620 int block = startblock + dir * i;
00621
00622 switch ((this->bbt[block >> 2] >>
00623 (2 * (block & 0x03))) & 0x03) {
00624 case 0x01:
00625 case 0x03:
00626 continue;
00627 }
00628 page = block <<
00629 (this->bbt_erase_shift - this->page_shift);
00630
00631 if (!md || md->pages[chip] != page)
00632 goto write;
00633 }
00634 printk(KERN_ERR "No space left to write bad block table\n");
00635 return -ENOSPC;
00636 write:
00637
00638
00639 bits = td->options & NAND_BBT_NRBITS_MSK;
00640 msk[2] = ~rcode;
00641 switch (bits) {
00642 case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
00643 msk[3] = 0x01;
00644 break;
00645 case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
00646 msk[3] = 0x03;
00647 break;
00648 case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
00649 msk[3] = 0x0f;
00650 break;
00651 case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
00652 msk[3] = 0xff;
00653 break;
00654 default: return -EINVAL;
00655 }
00656
00657 bbtoffs = chip * (numblocks >> 2);
00658
00659 to = ((loff_t) page) << this->page_shift;
00660
00661
00662 if (td->options & NAND_BBT_SAVECONTENT) {
00663
00664 to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
00665 len = 1 << this->bbt_erase_shift;
00666 res = mtd->read(mtd, to, len, &retlen, buf);
00667 if (res < 0) {
00668 if (retlen != len) {
00669 printk(KERN_INFO "nand_bbt: Error "
00670 "reading block for writing "
00671 "the bad block table\n");
00672 return res;
00673 }
00674 printk(KERN_WARNING "nand_bbt: ECC error "
00675 "while reading block for writing "
00676 "bad block table\n");
00677 }
00678
00679 ops.len = (len >> this->page_shift) * mtd->oobsize;
00680 ops.oobbuf = &buf[len];
00681 res = mtd->read_oob(mtd, to + mtd->writesize, &ops);
00682 if (res < 0 || ops.retlen != ops.len)
00683 goto outerr;
00684
00685
00686 pageoffs = page - (int)(to >> this->page_shift);
00687 offs = pageoffs << this->page_shift;
00688
00689 memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
00690 ooboffs = len + (pageoffs * mtd->oobsize);
00691
00692 } else {
00693
00694 len = (size_t) (numblocks >> sft);
00695
00696 len = (len + (mtd->writesize - 1)) &
00697 ~(mtd->writesize - 1);
00698
00699 memset(buf, 0xff, len +
00700 (len >> this->page_shift)* mtd->oobsize);
00701 offs = 0;
00702 ooboffs = len;
00703
00704 memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
00705 }
00706
00707 if (td->options & NAND_BBT_VERSION)
00708 buf[ooboffs + td->veroffs] = td->version[chip];
00709
00710
00711 for (i = 0; i < numblocks;) {
00712 uint8_t dat;
00713 dat = this->bbt[bbtoffs + (i >> 2)];
00714 for (j = 0; j < 4; j++, i++) {
00715 int sftcnt = (i << (3 - sft)) & sftmsk;
00716
00717 buf[offs + (i >> sft)] &=
00718 ~(msk[dat & 0x03] << sftcnt);
00719 dat >>= 2;
00720 }
00721 }
00722
00723 memset(&einfo, 0, sizeof(einfo));
00724 einfo.mtd = mtd;
00725 einfo.addr = (unsigned long)to;
00726 einfo.len = 1 << this->bbt_erase_shift;
00727 res = nand_erase_nand(mtd, &einfo, 1);
00728 if (res < 0)
00729 goto outerr;
00730
00731 res = scan_write_bbt(mtd, to, len, buf, &buf[len]);
00732 if (res < 0)
00733 goto outerr;
00734
00735 printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
00736 "0x%02X\n", (unsigned int)to, td->version[chip]);
00737
00738
00739 td->pages[chip] = page;
00740 }
00741 return 0;
00742
00743 outerr:
00744 printk(KERN_WARNING
00745 "nand_bbt: Error while writing bad block table %d\n", res);
00746 return res;
00747 }
00748
00757 static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
00758 {
00759 struct nand_chip *this = mtd->priv;
00760
00761 bd->options &= ~NAND_BBT_SCANEMPTY;
00762 return create_bbt(mtd, this->buffers->databuf, bd, -1);
00763 }
00764
00777 static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
00778 {
00779 int i, chips, writeops, chipsel, res;
00780 struct nand_chip *this = mtd->priv;
00781 struct nand_bbt_descr *td = this->bbt_td;
00782 struct nand_bbt_descr *md = this->bbt_md;
00783 struct nand_bbt_descr *rd, *rd2;
00784
00785
00786 if (td->options & NAND_BBT_PERCHIP)
00787 chips = this->numchips;
00788 else
00789 chips = 1;
00790
00791 for (i = 0; i < chips; i++) {
00792 writeops = 0;
00793 rd = NULL;
00794 rd2 = NULL;
00795
00796 chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
00797
00798 if (md) {
00799 if (td->pages[i] == -1 && md->pages[i] == -1) {
00800 writeops = 0x03;
00801 goto create;
00802 }
00803
00804 if (td->pages[i] == -1) {
00805 rd = md;
00806 td->version[i] = md->version[i];
00807 writeops = 1;
00808 goto writecheck;
00809 }
00810
00811 if (md->pages[i] == -1) {
00812 rd = td;
00813 md->version[i] = td->version[i];
00814 writeops = 2;
00815 goto writecheck;
00816 }
00817
00818 if (td->version[i] == md->version[i]) {
00819 rd = td;
00820 if (!(td->options & NAND_BBT_VERSION))
00821 rd2 = md;
00822 goto writecheck;
00823 }
00824
00825 if (((int8_t) (td->version[i] - md->version[i])) > 0) {
00826 rd = td;
00827 md->version[i] = td->version[i];
00828 writeops = 2;
00829 } else {
00830 rd = md;
00831 td->version[i] = md->version[i];
00832 writeops = 1;
00833 }
00834
00835 goto writecheck;
00836
00837 } else {
00838 if (td->pages[i] == -1) {
00839 writeops = 0x01;
00840 goto create;
00841 }
00842 rd = td;
00843 goto writecheck;
00844 }
00845 create:
00846
00847 if (!(td->options & NAND_BBT_CREATE))
00848 continue;
00849
00850
00851 create_bbt(mtd, buf, bd, chipsel);
00852
00853 td->version[i] = 1;
00854 if (md)
00855 md->version[i] = 1;
00856 writecheck:
00857
00858 if (rd)
00859 read_abs_bbt(mtd, buf, rd, chipsel);
00860
00861 if (rd2)
00862 read_abs_bbt(mtd, buf, rd2, chipsel);
00863
00864
00865 if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
00866 res = write_bbt(mtd, buf, td, md, chipsel);
00867 if (res < 0)
00868 return res;
00869 }
00870
00871
00872 if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
00873 res = write_bbt(mtd, buf, md, td, chipsel);
00874 if (res < 0)
00875 return res;
00876 }
00877 }
00878 return 0;
00879 }
00880
00890 static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
00891 {
00892 struct nand_chip *this = mtd->priv;
00893 int i, j, chips, block, nrblocks, update;
00894 uint8_t oldval, newval;
00895
00896
00897 if (td->options & NAND_BBT_PERCHIP) {
00898 chips = this->numchips;
00899 nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
00900 } else {
00901 chips = 1;
00902 nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
00903 }
00904
00905 for (i = 0; i < chips; i++) {
00906 if ((td->options & NAND_BBT_ABSPAGE) ||
00907 !(td->options & NAND_BBT_WRITE)) {
00908 if (td->pages[i] == -1)
00909 continue;
00910 block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
00911 block <<= 1;
00912 oldval = this->bbt[(block >> 3)];
00913 newval = oldval | (0x2 << (block & 0x06));
00914 this->bbt[(block >> 3)] = newval;
00915 if ((oldval != newval) && td->reserved_block_code)
00916 nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1));
00917 continue;
00918 }
00919 update = 0;
00920 if (td->options & NAND_BBT_LASTBLOCK)
00921 block = ((i + 1) * nrblocks) - td->maxblocks;
00922 else
00923 block = i * nrblocks;
00924 block <<= 1;
00925 for (j = 0; j < td->maxblocks; j++) {
00926 oldval = this->bbt[(block >> 3)];
00927 newval = oldval | (0x2 << (block & 0x06));
00928 this->bbt[(block >> 3)] = newval;
00929 if (oldval != newval)
00930 update = 1;
00931 block += 2;
00932 }
00933
00934
00935
00936 if (update && td->reserved_block_code)
00937 nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1));
00938 }
00939 }
00940
00955 int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
00956 {
00957 struct nand_chip *this = mtd->priv;
00958 int len, res = 0;
00959 uint8_t *buf;
00960 struct nand_bbt_descr *td = this->bbt_td;
00961 struct nand_bbt_descr *md = this->bbt_md;
00962
00963 len = mtd->size >> (this->bbt_erase_shift + 2);
00964
00965 this->bbt = kmalloc(len, GFP_KERNEL);
00966 if (!this->bbt) {
00967 printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
00968 return -ENOMEM;
00969 }
00970
00971 memset(this->bbt, 0x00, len);
00972
00973
00974
00975
00976 if (!td) {
00977 if ((res = nand_memory_bbt(mtd, bd))) {
00978 printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
00979 kfree(this->bbt);
00980 this->bbt = NULL;
00981 }
00982 return res;
00983 }
00984
00985
00986 len = (1 << this->bbt_erase_shift);
00987 len += (len >> this->page_shift) * mtd->oobsize;
00988 buf = vmalloc(len);
00989 if (!buf) {
00990 printk(KERN_ERR "nand_bbt: Out of memory\n");
00991 kfree(this->bbt);
00992 this->bbt = NULL;
00993 return -ENOMEM;
00994 }
00995
00996
00997 if (td->options & NAND_BBT_ABSPAGE) {
00998 res = read_abs_bbts(mtd, buf, td, md);
00999 } else {
01000
01001 res = search_read_bbts(mtd, buf, td, md);
01002 }
01003
01004 if (res)
01005 res = check_create(mtd, buf, bd);
01006
01007
01008 mark_bbt_region(mtd, td);
01009 if (md)
01010 mark_bbt_region(mtd, md);
01011
01012 vfree(buf);
01013 return res;
01014 }
01015
01023 int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
01024 {
01025 struct nand_chip *this = mtd->priv;
01026 int len, res = 0, writeops = 0;
01027 int chip, chipsel;
01028 uint8_t *buf;
01029 struct nand_bbt_descr *td = this->bbt_td;
01030 struct nand_bbt_descr *md = this->bbt_md;
01031
01032 if (!this->bbt || !td)
01033 return -EINVAL;
01034
01035 len = mtd->size >> (this->bbt_erase_shift + 2);
01036
01037 len = (1 << this->bbt_erase_shift);
01038 len += (len >> this->page_shift) * mtd->oobsize;
01039
01040 buf = vmalloc(len);
01041 if (!buf) {
01042 printk(KERN_ERR "nand_update_bbt: Out of memory\n");
01043 return -ENOMEM;
01044 }
01045
01046 writeops = md != NULL ? 0x03 : 0x01;
01047
01048
01049 if (td->options & NAND_BBT_PERCHIP) {
01050 chip = (int)(offs >> this->chip_shift);
01051 chipsel = chip;
01052 } else {
01053 chip = 0;
01054 chipsel = -1;
01055 }
01056
01057 td->version[chip]++;
01058 if (md)
01059 md->version[chip]++;
01060
01061
01062 if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
01063 res = write_bbt(mtd, buf, td, md, chipsel);
01064 if (res < 0)
01065 goto out;
01066 }
01067
01068 if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
01069 res = write_bbt(mtd, buf, md, td, chipsel);
01070 }
01071
01072 out:
01073
01074 vfree(buf);
01075 return res;
01076 }
01077
01078
01079
01080 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
01081
01082 static struct nand_bbt_descr smallpage_memorybased = {
01083 .options = NAND_BBT_SCAN2NDPAGE,
01084 .offs = 5,
01085 .len = 1,
01086 .pattern = scan_ff_pattern
01087 };
01088
01089 static struct nand_bbt_descr largepage_memorybased = {
01090 .options = 0,
01091 .offs = 0,
01092 .len = 2,
01093 .pattern = scan_ff_pattern
01094 };
01095
01096 static struct nand_bbt_descr smallpage_flashbased = {
01097 .options = NAND_BBT_SCAN2NDPAGE,
01098 .offs = 5,
01099 .len = 1,
01100 .pattern = scan_ff_pattern
01101 };
01102
01103 static struct nand_bbt_descr largepage_flashbased = {
01104 .options = NAND_BBT_SCAN2NDPAGE,
01105 .offs = 0,
01106 .len = 2,
01107 .pattern = scan_ff_pattern
01108 };
01109
01110 static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
01111
01112 static struct nand_bbt_descr agand_flashbased = {
01113 .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
01114 .offs = 0x20,
01115 .len = 6,
01116 .pattern = scan_agand_pattern
01117 };
01118
01119
01120
01121 static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
01122 static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
01123
01124 static struct nand_bbt_descr bbt_main_descr = {
01125 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
01126 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
01127 .offs = 8,
01128 .len = 4,
01129 .veroffs = 12,
01130 .maxblocks = 4,
01131 .pattern = bbt_pattern
01132 };
01133
01134 static struct nand_bbt_descr bbt_mirror_descr = {
01135 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
01136 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
01137 .offs = 8,
01138 .len = 4,
01139 .veroffs = 12,
01140 .maxblocks = 4,
01141 .pattern = mirror_pattern
01142 };
01143
01152 int nand_default_bbt(struct mtd_info *mtd)
01153 {
01154 struct nand_chip *this = mtd->priv;
01155
01156
01157
01158
01159
01160
01161
01162
01163 if (this->options & NAND_IS_AND) {
01164
01165 if (!this->bbt_td) {
01166 this->bbt_td = &bbt_main_descr;
01167 this->bbt_md = &bbt_mirror_descr;
01168 }
01169 this->options |= NAND_USE_FLASH_BBT;
01170 return nand_scan_bbt(mtd, &agand_flashbased);
01171 }
01172
01173
01174 if (this->options & NAND_USE_FLASH_BBT) {
01175
01176 if (!this->bbt_td) {
01177 this->bbt_td = &bbt_main_descr;
01178 this->bbt_md = &bbt_mirror_descr;
01179 }
01180 if (!this->badblock_pattern) {
01181 this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased;
01182 }
01183 } else {
01184 this->bbt_td = NULL;
01185 this->bbt_md = NULL;
01186 if (!this->badblock_pattern) {
01187 this->badblock_pattern = (mtd->writesize > 512) ?
01188 &largepage_memorybased : &smallpage_memorybased;
01189 }
01190 }
01191 return nand_scan_bbt(mtd, this->badblock_pattern);
01192 }
01193
01201 int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
01202 {
01203 struct nand_chip *this = mtd->priv;
01204 int block;
01205 uint8_t res;
01206
01207
01208 block = (int)(offs >> (this->bbt_erase_shift - 1));
01209 res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
01210
01211 DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
01212 (unsigned int)offs, block >> 1, res);
01213
01214 switch ((int)res) {
01215 case 0x00:
01216 return 0;
01217 case 0x01:
01218 return 1;
01219 case 0x02:
01220 return allowbbt ? 0 : 1;
01221 }
01222 return 1;
01223 }
01224
01225 EXPORT_SYMBOL(nand_scan_bbt);
01226 EXPORT_SYMBOL(nand_default_bbt);