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
00056
00057
00058
00059 #include <linux/errno.h>
00060 #include <linux/types.h>
00061 #include <linux/bitops.h>
00062
00063 #include "mtd.h"
00064 #include "nand.h"
00065 #include "nand_ecc.h"
00066 #include "delay.h"
00067
00068
00069
00070 #define BBT_LEN_1 1024
00071
00072 #define BBT_LEN_2 (512 * 1024)
00073
00074 #define bbt_b_1 ((void *)(0xc4000000 - BBT_LEN_2 - 0x02000000 - BBT_LEN_1))
00075 #define bbt_b_2 ((void *)(0xc4000000 - BBT_LEN_2 - 0x02000000))
00076
00077 #if 0
00078 #include <linux/slab.h>
00079 #endif
00080
00081 #if 0
00082 #include <linux/mtd/mtd.h>
00083 #include <linux/mtd/nand.h>
00084 #include <linux/mtd/nand_ecc.h>
00085 #include <linux/mtd/compatmac.h>
00086 #include <linux/bitops.h>
00087 #include <linux/delay.h>
00088 #endif
00089
00090 #include <linux/errno.h>
00091
00092
00093
00094
00095
00096 #define dprintf if(0)printf
00097
00098 #if 0
00099 #include <linux/delay.h>
00100 #include <linux/errno.h>
00101 #include <linux/sched.h>
00102 #include <linux/slab.h>
00103 #include <linux/types.h>
00104 #endif
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 #if 0
00120 #include <linux/mtd/compatmac.h>
00121 #include <linux/interrupt.h>
00122 #include <linux/bitops.h>
00123 #include <asm/io.h>
00124
00125 #ifdef CONFIG_MTD_PARTITIONS
00126 #include <linux/mtd/partitions.h>
00127
00128 #endif
00129 #endif
00130
00131
00132
00133
00134
00135
00136 #undef nop
00137 #define nop() __asm__("nop")
00138
00139
00140
00141 #define GPIO_SYNC 0
00142
00143 #undef DEBUG
00144 #define DEBUG(n, args...) do { } while(0)
00145
00146 #define D(x) x
00147
00148
00162 static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
00163 {
00164 int i, end = 0;
00165 uint8_t *p = buf;
00166
00167 end = paglen + td->offs;
00168 if (td->options & NAND_BBT_SCANEMPTY) {
00169 for (i = 0; i < end; i++) {
00170 if (p[i] != 0xff)
00171 return -1;
00172 }
00173 }
00174 p += end;
00175
00176
00177 for (i = 0; i < td->len; i++) {
00178 if (p[i] != td->pattern[i])
00179 return -1;
00180 }
00181
00182 if (td->options & NAND_BBT_SCANEMPTY) {
00183 p += td->len;
00184 end += td->len;
00185 for (i = end; i < len; i++) {
00186 if (*p++ != 0xff)
00187 return -1;
00188 }
00189 }
00190 return 0;
00191 }
00192
00203 static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td)
00204 {
00205 int i;
00206 uint8_t *p = buf;
00207
00208
00209 for (i = 0; i < td->len; i++) {
00210 if (p[td->offs + i] != td->pattern[i])
00211 return -1;
00212 }
00213 return 0;
00214 }
00215
00229
00230
00231
00232
00233
00234
00235
00236 static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
00237 int bits, int offs, int reserved_block_code)
00238 {
00239 int res, i, j, act = 0;
00240 struct nand_chip *this = mtd->priv;
00241 size_t retlen, len, totlen;
00242 loff_t from;
00243 uint8_t msk = (uint8_t) ((1 << bits) - 1);
00244
00245 totlen = (num * bits) >> 3;
00246 from = ((loff_t)page) << this->page_shift;
00247
00248 while (totlen) {
00249 len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
00250 res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
00251 if (res < 0) {
00252 if (retlen != len) {
00253
00254 return res;
00255 }
00256
00257 }
00258
00259
00260 for (i = 0; i < len; i++) {
00261 uint8_t dat = buf[i];
00262 for (j = 0; j < 8; j += bits, act += 2) {
00263 uint8_t tmp = (dat >> j) & msk;
00264 if (tmp == msk)
00265 continue;
00266 if (reserved_block_code &&
00267 (tmp == reserved_block_code)) {
00268
00269
00270 puts("nand_read_bbt: Reserved block at ");
00271 putx(((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
00272 putnl();
00273 this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
00274 continue;
00275 }
00276
00277
00278
00279
00280 puts("nand_read_bbt: Bad block at ");
00281 putx(((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
00282 putnl();
00283
00284 if (tmp == 0)
00285 this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
00286 else
00287 this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
00288 }
00289 }
00290 totlen -= len;
00291 from += len;
00292 }
00293 return 0;
00294 }
00295
00307 static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
00308 {
00309 struct nand_chip *this = mtd->priv;
00310 int res = 0, i;
00311 int bits;
00312
00313 bits = td->options & NAND_BBT_NRBITS_MSK;
00314 if (td->options & NAND_BBT_PERCHIP) {
00315 int offs = 0;
00316 for (i = 0; i < this->numchips; i++) {
00317 if (chip == -1 || chip == i)
00318 res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code);
00319 if (res)
00320 return res;
00321 offs += this->chipsize >> (this->bbt_erase_shift + 2);
00322 }
00323 } else {
00324 res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code);
00325 if (res)
00326 return res;
00327 }
00328 return 0;
00329 }
00330
00342 static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td,
00343 struct nand_bbt_descr *md)
00344 {
00345 struct nand_chip *this = mtd->priv;
00346
00347
00348 if (td->options & NAND_BBT_VERSION) {
00349 nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
00350 td->version[0] = buf[mtd->oobblock + td->veroffs];
00351
00352 }
00353
00354
00355 if (md && (md->options & NAND_BBT_VERSION)) {
00356 nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
00357 md->version[0] = buf[mtd->oobblock + md->veroffs];
00358
00359 }
00360
00361 return 1;
00362 }
00363
00375 static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
00376 {
00377 struct nand_chip *this = mtd->priv;
00378 int i, j, numblocks, len, scanlen;
00379 int startblock;
00380 loff_t from;
00381 size_t readlen, ooblen;
00382
00383
00384
00385 if (bd->options & NAND_BBT_SCANALLPAGES)
00386 len = 1 << (this->bbt_erase_shift - this->page_shift);
00387 else {
00388 if (bd->options & NAND_BBT_SCAN2NDPAGE)
00389 len = 2;
00390 else
00391 len = 1;
00392 }
00393
00394 if (!(bd->options & NAND_BBT_SCANEMPTY)) {
00395
00396 scanlen = ooblen = 0;
00397 readlen = bd->len;
00398 } else {
00399
00400 scanlen = mtd->oobblock + mtd->oobsize;
00401 readlen = len * mtd->oobblock;
00402 ooblen = len * mtd->oobsize;
00403 }
00404
00405 if (chip == -1) {
00406
00407
00408 numblocks = mtd->size >> (this->bbt_erase_shift - 1);
00409 startblock = 0;
00410 from = 0;
00411 } else {
00412 if (chip >= this->numchips) {
00413
00414
00415 return -1;
00416 }
00417 numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
00418 startblock = chip * numblocks;
00419 numblocks += startblock;
00420 from = startblock << (this->bbt_erase_shift - 1);
00421 }
00422
00423 for (i = startblock; i < numblocks;) {
00424 int ret;
00425
00426
00427
00428
00429
00430
00431 for (j = 0; j < len; j++) {
00432
00433 size_t retlen;
00434
00435
00436
00437 ret = mtd->read_oob(mtd, from + j * mtd->oobblock,
00438 mtd->oobsize, &retlen, buf);
00439 if (ret)
00440 return ret;
00441
00442 if (check_short_pattern (buf, bd)) {
00443 this->bbt[i >> 3] |= 0x03 << (i & 0x6);
00444
00445
00446 break;
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 }
00459 i += 2;
00460 from += (1 << this->bbt_erase_shift);
00461 }
00462 return 0;
00463 }
00464
00482 static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
00483 {
00484 struct nand_chip *this = mtd->priv;
00485 int i, chips;
00486 int bits, startblock, block, dir;
00487 int scanlen = mtd->oobblock + mtd->oobsize;
00488 int bbtblocks;
00489
00490 puts("search_bbt() ...1");
00491 puts("; mtd->size == ");
00492 putx(mtd->size);
00493 putnl();
00494
00495 if (td->options & NAND_BBT_LASTBLOCK) {
00496 startblock = (mtd->size >> this->bbt_erase_shift) -1;
00497 dir = -1;
00498 } else {
00499 startblock = 0;
00500 dir = 1;
00501 }
00502
00503
00504 if (td->options & NAND_BBT_PERCHIP) {
00505 chips = this->numchips;
00506 bbtblocks = this->chipsize >> this->bbt_erase_shift;
00507 startblock &= bbtblocks - 1;
00508 } else {
00509 chips = 1;
00510 bbtblocks = mtd->size >> this->bbt_erase_shift;
00511 }
00512
00513 puts("search_bbt() ...2; ");
00514 puts("maxblocks: ");
00515 putx(td->maxblocks);
00516 puts("; mtd->size == ");
00517 putx(mtd->size);
00518 putnl();
00519
00520 bits = td->options & NAND_BBT_NRBITS_MSK;
00521
00522 for (i = 0; i < chips; i++) {
00523
00524 td->version[i] = 0;
00525 td->pages[i] = -1;
00526
00527 for (block = 0; block < td->maxblocks; block++) {
00528 int actblock = startblock + dir * block;
00529
00530 nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
00531 puts("Block: ");
00532 putx(actblock);
00533 putnl();
00534 if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
00535 td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
00536 if (td->options & NAND_BBT_VERSION) {
00537 td->version[i] = buf[mtd->oobblock + td->veroffs];
00538 }
00539 break;
00540 }
00541 }
00542 startblock += this->chipsize >> this->bbt_erase_shift;
00543 }
00544
00545 puts("Check, if we found a bbt for each requested chip");
00546 putnl();
00548 for (i = 0; i < chips; i++) {
00549 if (td->pages[i] == -1)
00550 puts("Bad block table not found...");
00551
00552 else {
00553 puts("Bad block table found at page");
00554 putx(td->pages[i]);
00555 puts(", version ");
00556 putx(td->version[i]);
00557 }
00558 putnl();
00559
00560 }
00561
00562 return 0;
00563 }
00564
00574 static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
00575 struct nand_bbt_descr *td, struct nand_bbt_descr *md)
00576 {
00577 puts("search_read_bbts() search primary table; mtd->size == ");
00578 putx(mtd->size);
00579 putnl();
00580
00581 search_bbt (mtd, buf, td);
00582
00583
00584 if (md) {
00585 puts("search_read_bbts() search mirror table");
00586 putnl();
00587 search_bbt (mtd, buf, md);
00588 }
00589
00590
00591 return 1;
00592 }
00593
00594
00607 static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
00608 struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
00609 {
00610 struct nand_chip *this = mtd->priv;
00611 struct nand_oobinfo oobinfo;
00612 struct erase_info einfo;
00613 int i, j, res, chip = 0;
00614 int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
00615 int nrchips, bbtoffs, pageoffs;
00616 uint8_t msk[4];
00617 uint8_t rcode = td->reserved_block_code;
00618 size_t retlen, len = 0;
00619 loff_t to;
00620
00621 return 0;
00622 if (!rcode)
00623 rcode = 0xff;
00624
00625 if (td->options & NAND_BBT_PERCHIP) {
00626 numblocks = (int) (this->chipsize >> this->bbt_erase_shift);
00627
00628 if (chipsel == -1) {
00629 nrchips = this->numchips;
00630 } else {
00631 nrchips = chipsel + 1;
00632 chip = chipsel;
00633 }
00634 } else {
00635 numblocks = (int) (mtd->size >> this->bbt_erase_shift);
00636 nrchips = 1;
00637 }
00638
00639
00640 for (; chip < nrchips; chip++) {
00641
00642
00643
00644
00645
00646 if (td->pages[chip] != -1) {
00647 page = td->pages[chip];
00648 goto write;
00649 }
00650
00651
00652
00653 if (td->options & NAND_BBT_LASTBLOCK) {
00654 startblock = numblocks * (chip + 1) - 1;
00655 dir = -1;
00656 } else {
00657 startblock = chip * numblocks;
00658 dir = 1;
00659 }
00660
00661 for (i = 0; i < td->maxblocks; i++) {
00662 int block = startblock + dir * i;
00663
00664 switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) {
00665 case 0x01:
00666 case 0x03:
00667 continue;
00668 }
00669 page = block << (this->bbt_erase_shift - this->page_shift);
00670
00671 if (!md || md->pages[chip] != page)
00672 goto write;
00673 }
00674
00675 return -1;
00676 write:
00677
00678
00679 bits = td->options & NAND_BBT_NRBITS_MSK;
00680 switch (bits) {
00681 case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break;
00682 case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break;
00683 case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break;
00684 case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
00685 default: return -1;
00686 }
00687
00688 bbtoffs = chip * (numblocks >> 2);
00689
00690 to = ((loff_t) page) << this->page_shift;
00691
00692 memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
00693 oobinfo.useecc = MTD_NANDECC_PLACEONLY;
00694
00695
00696 if (td->options & NAND_BBT_SAVECONTENT) {
00697
00698 to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
00699 len = 1 << this->bbt_erase_shift;
00700 res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
00701 if (res < 0) {
00702 if (retlen != len) {
00703
00704 return res;
00705 }
00706
00707 }
00708
00709 pageoffs = page - (int)(to >> this->page_shift);
00710 offs = pageoffs << this->page_shift;
00711
00712 memset (&buf[offs], 0xff, (size_t)(numblocks >> sft));
00713
00714 memset (&buf[len + pageoffs * mtd->oobsize], 0xff,
00715 ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
00716 if (td->options & NAND_BBT_VERSION) {
00717 buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
00718 }
00719 } else {
00720
00721 len = (size_t) (numblocks >> sft);
00722
00723 len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1);
00724
00725 memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
00726 offs = 0;
00727
00728 memcpy (&buf[len + td->offs], td->pattern, td->len);
00729 if (td->options & NAND_BBT_VERSION) {
00730 buf[len + td->veroffs] = td->version[chip];
00731 }
00732 }
00733
00734
00735 for (i = 0; i < numblocks; ) {
00736 uint8_t dat;
00737 dat = this->bbt[bbtoffs + (i >> 2)];
00738 for (j = 0; j < 4; j++ , i++) {
00739 int sftcnt = (i << (3 - sft)) & sftmsk;
00740
00741 buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
00742 dat >>= 2;
00743 }
00744 }
00745
00746 memset (&einfo, 0, sizeof (einfo));
00747 einfo.mtd = mtd;
00748 einfo.addr = (unsigned long) to;
00749 einfo.len = 1 << this->bbt_erase_shift;
00750
00751 if (res < 0) {
00752
00753 return res;
00754 }
00755
00756 res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
00757 if (res < 0) {
00758
00759 return res;
00760 }
00761
00762
00763
00764
00765 td->pages[chip] = page;
00766 }
00767 return 0;
00768 }
00769
00778 static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
00779 {
00780 struct nand_chip *this = mtd->priv;
00781
00782 bd->options &= ~NAND_BBT_SCANEMPTY;
00783 return create_bbt (mtd, this->data_buf, bd, -1);
00784 }
00785
00798 static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
00799 {
00800 int i, chips, writeops, chipsel, res;
00801 struct nand_chip *this = mtd->priv;
00802 struct nand_bbt_descr *td = this->bbt_td;
00803 struct nand_bbt_descr *md = this->bbt_md;
00804 struct nand_bbt_descr *rd, *rd2;
00805
00806
00807 if (td->options & NAND_BBT_PERCHIP)
00808 chips = this->numchips;
00809 else
00810 chips = 1;
00811
00812 for (i = 0; i < chips; i++) {
00813 writeops = 0;
00814 rd = NULL;
00815 rd2 = NULL;
00816
00817 chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
00818
00819 if (md) {
00820 if (td->pages[i] == -1 && md->pages[i] == -1) {
00821 writeops = 0x03;
00822 goto create;
00823 }
00824
00825 if (td->pages[i] == -1) {
00826 rd = md;
00827 td->version[i] = md->version[i];
00828 writeops = 1;
00829 goto writecheck;
00830 }
00831
00832 if (md->pages[i] == -1) {
00833 rd = td;
00834 md->version[i] = td->version[i];
00835 writeops = 2;
00836 goto writecheck;
00837 }
00838
00839 if (td->version[i] == md->version[i]) {
00840 rd = td;
00841 if (!(td->options & NAND_BBT_VERSION))
00842 rd2 = md;
00843 goto writecheck;
00844 }
00845
00846 if (((int8_t) (td->version[i] - md->version[i])) > 0) {
00847 rd = td;
00848 md->version[i] = td->version[i];
00849 writeops = 2;
00850 } else {
00851 rd = md;
00852 td->version[i] = md->version[i];
00853 writeops = 1;
00854 }
00855
00856 goto writecheck;
00857
00858 } else {
00859 if (td->pages[i] == -1) {
00860 writeops = 0x01;
00861 goto create;
00862 }
00863 rd = td;
00864 goto writecheck;
00865 }
00866 create:
00867
00868 if (!(td->options & NAND_BBT_CREATE))
00869 continue;
00870
00871
00872 create_bbt (mtd, buf, bd, chipsel);
00873
00874 td->version[i] = 1;
00875 if (md)
00876 md->version[i] = 1;
00877 writecheck:
00878
00879 if (rd)
00880 read_abs_bbt (mtd, buf, rd, chipsel);
00881
00882 if (rd2)
00883 read_abs_bbt (mtd, buf, rd2, chipsel);
00884
00885
00886 if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
00887 res = write_bbt (mtd, buf, td, md, chipsel);
00888 if (res < 0)
00889 return res;
00890 }
00891
00892
00893 if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
00894 res = write_bbt (mtd, buf, md, td, chipsel);
00895 if (res < 0)
00896 return res;
00897 }
00898 }
00899 return 0;
00900 }
00901
00911 static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
00912 {
00913 struct nand_chip *this = mtd->priv;
00914 int i, j, chips, block, nrblocks, update;
00915 uint8_t oldval, newval;
00916
00917
00918 if (td->options & NAND_BBT_PERCHIP) {
00919 chips = this->numchips;
00920 nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
00921 } else {
00922 chips = 1;
00923 nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
00924 }
00925
00926 for (i = 0; i < chips; i++) {
00927 if ((td->options & NAND_BBT_ABSPAGE) ||
00928 !(td->options & NAND_BBT_WRITE)) {
00929 if (td->pages[i] == -1) continue;
00930 block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
00931 block <<= 1;
00932 oldval = this->bbt[(block >> 3)];
00933 newval = oldval | (0x2 << (block & 0x06));
00934 this->bbt[(block >> 3)] = newval;
00935 if ((oldval != newval) && td->reserved_block_code)
00936 nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1));
00937 continue;
00938 }
00939 update = 0;
00940 if (td->options & NAND_BBT_LASTBLOCK)
00941 block = ((i + 1) * nrblocks) - td->maxblocks;
00942 else
00943 block = i * nrblocks;
00944 block <<= 1;
00945 for (j = 0; j < td->maxblocks; j++) {
00946 oldval = this->bbt[(block >> 3)];
00947 newval = oldval | (0x2 << (block & 0x06));
00948 this->bbt[(block >> 3)] = newval;
00949 if (oldval != newval) update = 1;
00950 block += 2;
00951 }
00952
00953
00954
00955 if (update && td->reserved_block_code)
00956 nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1));
00957 }
00958 }
00959
00974 int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
00975 {
00976 struct nand_chip *this = mtd->priv;
00977 int len, res = 0;
00978 uint8_t *buf;
00979 struct nand_bbt_descr *td = this->bbt_td;
00980 struct nand_bbt_descr *md = this->bbt_md;
00981
00982 puts("scan_bbt()");
00983 puts("; mtd->size == ");
00984 putx(mtd->size);
00985 putnl();
00986 len = mtd->size >> (this->bbt_erase_shift + 2);
00987 puts("scan_bbt() ...01");
00988 puts("; mtd->size == ");
00989 putx(mtd->size);
00990 putnl();
00991
00993
00994 this->bbt = NULL;
00995 puts("len == ");
00996 putx(len);
00997 puts("; and BBT_LEN_1 == ");
00998 putx(BBT_LEN_1);
00999 putnl();
01000 if(len <= BBT_LEN_1)
01001 this->bbt = bbt_b_1;
01002 if (!this->bbt) {
01003
01004 puts("scan_bbt() -ENOMEM ...1");
01005 putnl();
01006 return -ENOMEM;
01007 }
01008
01009 puts("scan_bbt() ...02");
01010 puts("; mtd->size == ");
01011 putx(mtd->size);
01012 putnl();
01013 memset (this->bbt, 0x00, len);
01014 puts("scan_bbt() ...03");
01015 puts("; mtd->size == ");
01016 putx(mtd->size);
01017 putnl();
01018
01019
01020
01021
01022 if (!td) {
01023 if ((res = nand_memory_bbt(mtd, bd))) {
01024
01025
01026 this->bbt = NULL;
01027 }
01028 puts("scan_bbt() nand_memory_bbt()");
01029 putnl();
01030 return res;
01031 }
01032
01033 puts("scan_bbt() ...1");
01034 puts("; mtd->size == ");
01035 putx(mtd->size);
01036 putnl();
01037
01038 len = (1 << this->bbt_erase_shift);
01039 len += (len >> this->page_shift) * mtd->oobsize;
01041
01042 buf = NULL;
01043 if(len <= BBT_LEN_2)
01044 buf = bbt_b_2;
01045 if (!buf) {
01046
01047
01048 this->bbt = NULL;
01049 puts("scan_bbt() -ENOMEM ...2");
01050 putnl();
01051 return -ENOMEM;
01052 }
01053
01054 puts("scan_bbt() ...2");
01055 puts("; mtd->size == ");
01056 putx(mtd->size);
01057 putnl();
01058
01059 if (td->options & NAND_BBT_ABSPAGE) {
01060 puts("scan_bbt() read_abs_bbts()");
01061 putnl();
01062 res = read_abs_bbts (mtd, buf, td, md);
01063 } else {
01064 puts("scan_bbt() search_read_bbts(); mtd->size == ");
01065 putx(mtd->size);
01066 putnl();
01067
01068 res = search_read_bbts (mtd, buf, td, md);
01069 }
01070
01071 if (res)
01072 res = check_create (mtd, buf, bd);
01073
01074
01075 mark_bbt_region (mtd, td);
01076 if (md)
01077 mark_bbt_region (mtd, md);
01078
01079
01080 puts("scan_bbt() ...3");
01081 putnl();
01082 return res;
01083 }
01084
01085
01093 int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
01094 {
01095 struct nand_chip *this = mtd->priv;
01096 int len, res = 0, writeops = 0;
01097 int chip, chipsel;
01098 uint8_t *buf;
01099 struct nand_bbt_descr *td = this->bbt_td;
01100 struct nand_bbt_descr *md = this->bbt_md;
01101
01102 if (!this->bbt || !td)
01103 return -1;
01104
01105 len = mtd->size >> (this->bbt_erase_shift + 2);
01106
01107 len = (1 << this->bbt_erase_shift);
01108 len += (len >> this->page_shift) * mtd->oobsize;
01110
01111 buf = NULL;
01112 if(len <= BBT_LEN_2)
01113 buf = bbt_b_2;
01114 if (!buf) {
01115
01116 return -ENOMEM;
01117 }
01118
01119 writeops = md != NULL ? 0x03 : 0x01;
01120
01121
01122 if (td->options & NAND_BBT_PERCHIP) {
01123 chip = (int) (offs >> this->chip_shift);
01124 chipsel = chip;
01125 } else {
01126 chip = 0;
01127 chipsel = -1;
01128 }
01129
01130 td->version[chip]++;
01131 if (md)
01132 md->version[chip]++;
01133
01134
01135 if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
01136 res = write_bbt (mtd, buf, td, md, chipsel);
01137 if (res < 0)
01138 goto out;
01139 }
01140
01141 if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
01142 res = write_bbt (mtd, buf, md, td, chipsel);
01143 }
01144
01145 out:
01146
01147 return res;
01148 }
01149
01150
01151
01152 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
01153
01154 static struct nand_bbt_descr smallpage_memorybased = {
01155 .options = NAND_BBT_SCAN2NDPAGE,
01156 .offs = 5,
01157 .len = 1,
01158 .pattern = scan_ff_pattern
01159 };
01160
01161 static struct nand_bbt_descr largepage_memorybased = {
01162 .options = 0,
01163 .offs = 0,
01164 .len = 2,
01165 .pattern = scan_ff_pattern
01166 };
01167
01168 static struct nand_bbt_descr smallpage_flashbased = {
01169 .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
01170 .offs = 5,
01171 .len = 1,
01172 .pattern = scan_ff_pattern
01173 };
01174
01175 static struct nand_bbt_descr largepage_flashbased = {
01176 .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
01177 .offs = 0,
01178 .len = 2,
01179 .pattern = scan_ff_pattern
01180 };
01181
01182 static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
01183
01184 static struct nand_bbt_descr agand_flashbased = {
01185 .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
01186 .offs = 0x20,
01187 .len = 6,
01188 .pattern = scan_agand_pattern
01189 };
01190
01191
01192
01193 static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
01194 static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
01195
01196 static struct nand_bbt_descr bbt_main_descr = {
01197 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
01198 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
01199 .offs = 8,
01200 .len = 4,
01201 .veroffs = 12,
01202 .maxblocks = 4,
01203 .pattern = bbt_pattern
01204 };
01205
01206 static struct nand_bbt_descr bbt_mirror_descr = {
01207 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
01208 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
01209 .offs = 8,
01210 .len = 4,
01211 .veroffs = 12,
01212 .maxblocks = 4,
01213 .pattern = mirror_pattern
01214 };
01215
01224 int nand_default_bbt (struct mtd_info *mtd)
01225 {
01226 struct nand_chip *this = mtd->priv;
01227
01228
01229
01230
01231
01232
01233
01234
01235 if (this->options & NAND_IS_AND) {
01236
01237 if (!this->bbt_td) {
01238 this->bbt_td = &bbt_main_descr;
01239 this->bbt_md = &bbt_mirror_descr;
01240 }
01241 this->options |= NAND_USE_FLASH_BBT;
01242 return nand_scan_bbt (mtd, &agand_flashbased);
01243 }
01244
01245
01246
01247 if (this->options & NAND_USE_FLASH_BBT) {
01248
01249 if (!this->bbt_td) {
01250 this->bbt_td = &bbt_main_descr;
01251 this->bbt_md = &bbt_mirror_descr;
01252 }
01253 if (!this->badblock_pattern) {
01254 this->badblock_pattern = (mtd->oobblock > 512) ?
01255 &largepage_flashbased : &smallpage_flashbased;
01256 }
01257 } else {
01258 this->bbt_td = NULL;
01259 this->bbt_md = NULL;
01260 if (!this->badblock_pattern) {
01261 this->badblock_pattern = (mtd->oobblock > 512) ?
01262 &largepage_memorybased : &smallpage_memorybased;
01263 }
01264 }
01265 return nand_scan_bbt (mtd, this->badblock_pattern);
01266 }
01267
01275 int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
01276 {
01277 struct nand_chip *this = mtd->priv;
01278 int block;
01279 uint8_t res;
01280
01281
01282 block = (int) (offs >> (this->bbt_erase_shift - 1));
01283 res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
01284
01285 DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
01286 (unsigned int)offs, block >> 1, res);
01287
01288 switch ((int)res) {
01289 case 0x00: return 0;
01290 case 0x01: return 1;
01291 case 0x02: return allowbbt ? 0 : 1;
01292 }
01293 return 1;
01294 }
01295
01296 EXPORT_SYMBOL (nand_scan_bbt);
01297 EXPORT_SYMBOL (nand_default_bbt);