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
00060
00061 #define BBT_LEN_1 1024
00062
00063 #define BBT_LEN_2 (512 * 1024)
00064 char bbt_b_1[BBT_LEN_1];
00065 #define bbt_b_2 (void *)(0xc4000000 - BBT_LEN_2)
00066
00067 #if 0
00068 #include <linux/slab.h>
00069 #endif
00070
00071 #if 0
00072 #include <linux/mtd/mtd.h>
00073 #include <linux/mtd/nand.h>
00074 #include <linux/mtd/nand_ecc.h>
00075 #include <linux/mtd/compatmac.h>
00076 #include <linux/bitops.h>
00077 #include <linux/delay.h>
00078 #endif
00079
00080 #include "mtd_nand.h"
00081
00082 #include "nand_ecc.h"
00083
00084
00085 #define dprintf if(0)printf
00086
00087 #if 0
00088 #include <linux/delay.h>
00089 #include <linux/errno.h>
00090 #include <linux/sched.h>
00091 #include <linux/slab.h>
00092 #include <linux/types.h>
00093 #endif
00094
00095
00096 #include <axisrfl/mtd.h>
00097 #include <axisrfl/mtd_nand.h>
00098 #include <axisrfl/nand_ecc.h>
00099
00100 #include <axisrfl/funcs.h>
00101
00102
00103 #include <bitops.h>
00104
00105 #include <hal_intr.h>
00106 #include <string.h>
00107
00108 #if 0
00109 #include <linux/mtd/compatmac.h>
00110 #include <linux/interrupt.h>
00111 #include <linux/bitops.h>
00112 #include <asm/io.h>
00113
00114 #ifdef CONFIG_MTD_PARTITIONS
00115 #include <linux/mtd/partitions.h>
00116
00117 #endif
00118 #endif
00119
00120
00121
00122 #include <axisrfl/linuxerr.h>
00123
00124 #define udelay(x) HAL_DELAY_US(x)
00125 #undef nop
00126 #define nop() __asm__("nop")
00127
00128 #define ndelay(x) do { nop(); nop(); nop(); nop(); \
00129 nop(); nop(); nop(); nop(); } while (0)
00130
00131 #define GPIO_SYNC 0
00132
00133 #undef DEBUG
00134 #define DEBUG(n, args...) do { } while(0)
00135
00136 #define D(x) x
00137
00138
00152 static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
00153 {
00154 int i, end = 0;
00155 uint8_t *p = buf;
00156
00157 end = paglen + td->offs;
00158 if (td->options & NAND_BBT_SCANEMPTY) {
00159 for (i = 0; i < end; i++) {
00160 if (p[i] != 0xff)
00161 return -1;
00162 }
00163 }
00164 p += end;
00165
00166
00167 for (i = 0; i < td->len; i++) {
00168 if (p[i] != td->pattern[i])
00169 return -1;
00170 }
00171
00172 if (td->options & NAND_BBT_SCANEMPTY) {
00173 p += td->len;
00174 end += td->len;
00175 for (i = end; i < len; i++) {
00176 if (*p++ != 0xff)
00177 return -1;
00178 }
00179 }
00180 return 0;
00181 }
00182
00193 static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td)
00194 {
00195 int i;
00196 uint8_t *p = buf;
00197
00198
00199 for (i = 0; i < td->len; i++) {
00200 if (p[td->offs + i] != td->pattern[i])
00201 return -1;
00202 }
00203 return 0;
00204 }
00205
00219 size_t min(size_t a, size_t b) {
00220 if(a < b)
00221 return a;
00222 return b;
00223 }
00224
00225 static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
00226 int bits, int offs, int reserved_block_code)
00227 {
00228 int res, i, j, act = 0;
00229 struct nand_chip *this = mtd->priv;
00230 size_t retlen, len, totlen;
00231 loff_t from;
00232 uint8_t msk = (uint8_t) ((1 << bits) - 1);
00233
00234 totlen = (num * bits) >> 3;
00235 from = ((loff_t)page) << this->page_shift;
00236
00237 while (totlen) {
00238 len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
00239 res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
00240 if (res < 0) {
00241 if (retlen != len) {
00242 printf ("nand_bbt: Error reading bad block table\n");
00243 return res;
00244 }
00245 printf ("nand_bbt: ECC error while reading bad block table\n");
00246 }
00247
00248
00249 for (i = 0; i < len; i++) {
00250 uint8_t dat = buf[i];
00251 for (j = 0; j < 8; j += bits, act += 2) {
00252 uint8_t tmp = (dat >> j) & msk;
00253 if (tmp == msk)
00254 continue;
00255 if (reserved_block_code &&
00256 (tmp == reserved_block_code)) {
00257 printf ( "nand_read_bbt: Reserved block at 0x%08x\n",
00258 ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
00259 this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
00260 continue;
00261 }
00262
00263
00264 printf ( "nand_read_bbt: Bad block at 0x%08x\n",
00265 ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
00266
00267 if (tmp == 0)
00268 this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
00269 else
00270 this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
00271 }
00272 }
00273 totlen -= len;
00274 from += len;
00275 }
00276 return 0;
00277 }
00278
00290 static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
00291 {
00292 struct nand_chip *this = mtd->priv;
00293 int res = 0, i;
00294 int bits;
00295
00296 bits = td->options & NAND_BBT_NRBITS_MSK;
00297 if (td->options & NAND_BBT_PERCHIP) {
00298 int offs = 0;
00299 for (i = 0; i < this->numchips; i++) {
00300 if (chip == -1 || chip == i)
00301 res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code);
00302 if (res)
00303 return res;
00304 offs += this->chipsize >> (this->bbt_erase_shift + 2);
00305 }
00306 } else {
00307 res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code);
00308 if (res)
00309 return res;
00310 }
00311 return 0;
00312 }
00313
00325 static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td,
00326 struct nand_bbt_descr *md)
00327 {
00328 struct nand_chip *this = mtd->priv;
00329
00330
00331 if (td->options & NAND_BBT_VERSION) {
00332 nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
00333 td->version[0] = buf[mtd->oobblock + td->veroffs];
00334 printf ( "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
00335 }
00336
00337
00338 if (md && (md->options & NAND_BBT_VERSION)) {
00339 nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
00340 md->version[0] = buf[mtd->oobblock + md->veroffs];
00341 printf ( "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
00342 }
00343
00344 return 1;
00345 }
00346
00358 static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
00359 {
00360 struct nand_chip *this = mtd->priv;
00361 int i, j, numblocks, len, scanlen;
00362 int startblock;
00363 loff_t from;
00364 size_t readlen, ooblen;
00365
00366 printf ( "Scanning device for bad blocks\n");
00367
00368 if (bd->options & NAND_BBT_SCANALLPAGES)
00369 len = 1 << (this->bbt_erase_shift - this->page_shift);
00370 else {
00371 if (bd->options & NAND_BBT_SCAN2NDPAGE)
00372 len = 2;
00373 else
00374 len = 1;
00375 }
00376
00377 if (!(bd->options & NAND_BBT_SCANEMPTY)) {
00378
00379 scanlen = ooblen = 0;
00380 readlen = bd->len;
00381 } else {
00382
00383 scanlen = mtd->oobblock + mtd->oobsize;
00384 readlen = len * mtd->oobblock;
00385 ooblen = len * mtd->oobsize;
00386 }
00387
00388 if (chip == -1) {
00389
00390
00391 numblocks = mtd->size >> (this->bbt_erase_shift - 1);
00392 startblock = 0;
00393 from = 0;
00394 } else {
00395 if (chip >= this->numchips) {
00396 printf ( "create_bbt(): chipnr (%d) > available chips (%d)\n",
00397 chip + 1, this->numchips);
00398 return -1;
00399 }
00400 numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
00401 startblock = chip * numblocks;
00402 numblocks += startblock;
00403 from = startblock << (this->bbt_erase_shift - 1);
00404 }
00405
00406 for (i = startblock; i < numblocks;) {
00407 int ret;
00408
00409
00410
00411
00412
00413
00414 for (j = 0; j < len; j++) {
00415
00416 size_t retlen;
00417
00418
00419
00420 ret = mtd->read_oob(mtd, from + j * mtd->oobblock,
00421 mtd->oobsize, &retlen, buf);
00422 if (ret)
00423 return ret;
00424
00425 if (check_short_pattern (buf, bd)) {
00426 this->bbt[i >> 3] |= 0x03 << (i & 0x6);
00427 printf ( "1 Bad eraseblock %d at 0x%08x\n",
00428 i >> 1, (unsigned int) from);
00429 break;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 }
00442 i += 2;
00443 from += (1 << this->bbt_erase_shift);
00444 }
00445 return 0;
00446 }
00447
00465 static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
00466 {
00467 struct nand_chip *this = mtd->priv;
00468 int i, chips;
00469 int bits, startblock, block, dir;
00470 int scanlen = mtd->oobblock + mtd->oobsize;
00471 int bbtblocks;
00472
00473
00474 if (td->options & NAND_BBT_LASTBLOCK) {
00475 startblock = (mtd->size >> this->bbt_erase_shift) -1;
00476 dir = -1;
00477 } else {
00478 startblock = 0;
00479 dir = 1;
00480 }
00481
00482
00483 if (td->options & NAND_BBT_PERCHIP) {
00484 chips = this->numchips;
00485 bbtblocks = this->chipsize >> this->bbt_erase_shift;
00486 startblock &= bbtblocks - 1;
00487 } else {
00488 chips = 1;
00489 bbtblocks = mtd->size >> this->bbt_erase_shift;
00490 }
00491
00492
00493 bits = td->options & NAND_BBT_NRBITS_MSK;
00494
00495 for (i = 0; i < chips; i++) {
00496
00497 td->version[i] = 0;
00498 td->pages[i] = -1;
00499
00500 for (block = 0; block < td->maxblocks; block++) {
00501 int actblock = startblock + dir * block;
00502
00503 nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
00504 if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
00505 td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
00506 if (td->options & NAND_BBT_VERSION) {
00507 td->version[i] = buf[mtd->oobblock + td->veroffs];
00508 }
00509 break;
00510 }
00511 }
00512 startblock += this->chipsize >> this->bbt_erase_shift;
00513 }
00514
00515 for (i = 0; i < chips; i++) {
00516 if (td->pages[i] == -1)
00517 printf ( "Bad block table not found for chip %d\n", i);
00518 else
00519 printf ( "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]);
00520 }
00521 return 0;
00522 }
00523
00533 static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
00534 struct nand_bbt_descr *td, struct nand_bbt_descr *md)
00535 {
00536
00537 search_bbt (mtd, buf, td);
00538
00539
00540 if (md)
00541 search_bbt (mtd, buf, md);
00542
00543
00544 return 1;
00545 }
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, int chipsel)
00562 {
00563 struct nand_chip *this = mtd->priv;
00564 struct nand_oobinfo oobinfo;
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;
00569 uint8_t msk[4];
00570 uint8_t rcode = td->reserved_block_code;
00571 size_t retlen, len = 0;
00572 loff_t to;
00573
00574 if (!rcode)
00575 rcode = 0xff;
00576
00577 if (td->options & NAND_BBT_PERCHIP) {
00578 numblocks = (int) (this->chipsize >> this->bbt_erase_shift);
00579
00580 if (chipsel == -1) {
00581 nrchips = this->numchips;
00582 } else {
00583 nrchips = chipsel + 1;
00584 chip = chipsel;
00585 }
00586 } else {
00587 numblocks = (int) (mtd->size >> this->bbt_erase_shift);
00588 nrchips = 1;
00589 }
00590
00591
00592 for (; chip < nrchips; chip++) {
00593
00594
00595
00596
00597
00598 if (td->pages[chip] != -1) {
00599 page = td->pages[chip];
00600 goto write;
00601 }
00602
00603
00604
00605 if (td->options & NAND_BBT_LASTBLOCK) {
00606 startblock = numblocks * (chip + 1) - 1;
00607 dir = -1;
00608 } else {
00609 startblock = chip * numblocks;
00610 dir = 1;
00611 }
00612
00613 for (i = 0; i < td->maxblocks; i++) {
00614 int block = startblock + dir * i;
00615
00616 switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) {
00617 case 0x01:
00618 case 0x03:
00619 continue;
00620 }
00621 page = block << (this->bbt_erase_shift - this->page_shift);
00622
00623 if (!md || md->pages[chip] != page)
00624 goto write;
00625 }
00626 printf ( "No space left to write bad block table\n");
00627 return -1;
00628 write:
00629
00630
00631 bits = td->options & NAND_BBT_NRBITS_MSK;
00632 switch (bits) {
00633 case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break;
00634 case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break;
00635 case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break;
00636 case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
00637 default: return -1;
00638 }
00639
00640 bbtoffs = chip * (numblocks >> 2);
00641
00642 to = ((loff_t) page) << this->page_shift;
00643
00644 memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
00645 oobinfo.useecc = MTD_NANDECC_PLACEONLY;
00646
00647
00648 if (td->options & NAND_BBT_SAVECONTENT) {
00649
00650 to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
00651 len = 1 << this->bbt_erase_shift;
00652 res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
00653 if (res < 0) {
00654 if (retlen != len) {
00655 printf ( "nand_bbt: Error reading block for writing the bad block table\n");
00656 return res;
00657 }
00658 printf ( "nand_bbt: ECC error while reading block for writing bad block table\n");
00659 }
00660
00661 pageoffs = page - (int)(to >> this->page_shift);
00662 offs = pageoffs << this->page_shift;
00663
00664 memset (&buf[offs], 0xff, (size_t)(numblocks >> sft));
00665
00666 memset (&buf[len + pageoffs * mtd->oobsize], 0xff,
00667 ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
00668 if (td->options & NAND_BBT_VERSION) {
00669 buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
00670 }
00671 } else {
00672
00673 len = (size_t) (numblocks >> sft);
00674
00675 len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1);
00676
00677 memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
00678 offs = 0;
00679
00680 memcpy (&buf[len + td->offs], td->pattern, td->len);
00681 if (td->options & NAND_BBT_VERSION) {
00682 buf[len + td->veroffs] = td->version[chip];
00683 }
00684 }
00685
00686
00687 for (i = 0; i < numblocks; ) {
00688 uint8_t dat;
00689 dat = this->bbt[bbtoffs + (i >> 2)];
00690 for (j = 0; j < 4; j++ , i++) {
00691 int sftcnt = (i << (3 - sft)) & sftmsk;
00692
00693 buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
00694 dat >>= 2;
00695 }
00696 }
00697
00698 memset (&einfo, 0, sizeof (einfo));
00699 einfo.mtd = mtd;
00700 einfo.addr = (unsigned long) to;
00701 einfo.len = 1 << this->bbt_erase_shift;
00702 res = nand_erase_nand (mtd, &einfo, 1);
00703 if (res < 0) {
00704 printf ( "nand_bbt: Error during block erase: %d\n", res);
00705 return res;
00706 }
00707
00708 res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
00709 if (res < 0) {
00710 printf ( "nand_bbt: Error while writing bad block table %d\n", res);
00711 return res;
00712 }
00713 printf ( "Bad block table written to 0x%08x, version 0x%02X\n",
00714 (unsigned int) to, td->version[chip]);
00715
00716
00717 td->pages[chip] = page;
00718 }
00719 return 0;
00720 }
00721
00730 static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
00731 {
00732 struct nand_chip *this = mtd->priv;
00733
00734 bd->options &= ~NAND_BBT_SCANEMPTY;
00735 return create_bbt (mtd, this->data_buf, bd, -1);
00736 }
00737
00750 static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
00751 {
00752 int i, chips, writeops, chipsel, res;
00753 struct nand_chip *this = mtd->priv;
00754 struct nand_bbt_descr *td = this->bbt_td;
00755 struct nand_bbt_descr *md = this->bbt_md;
00756 struct nand_bbt_descr *rd, *rd2;
00757
00758
00759 if (td->options & NAND_BBT_PERCHIP)
00760 chips = this->numchips;
00761 else
00762 chips = 1;
00763
00764 for (i = 0; i < chips; i++) {
00765 writeops = 0;
00766 rd = NULL;
00767 rd2 = NULL;
00768
00769 chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
00770
00771 if (md) {
00772 if (td->pages[i] == -1 && md->pages[i] == -1) {
00773 writeops = 0x03;
00774 goto create;
00775 }
00776
00777 if (td->pages[i] == -1) {
00778 rd = md;
00779 td->version[i] = md->version[i];
00780 writeops = 1;
00781 goto writecheck;
00782 }
00783
00784 if (md->pages[i] == -1) {
00785 rd = td;
00786 md->version[i] = td->version[i];
00787 writeops = 2;
00788 goto writecheck;
00789 }
00790
00791 if (td->version[i] == md->version[i]) {
00792 rd = td;
00793 if (!(td->options & NAND_BBT_VERSION))
00794 rd2 = md;
00795 goto writecheck;
00796 }
00797
00798 if (((int8_t) (td->version[i] - md->version[i])) > 0) {
00799 rd = td;
00800 md->version[i] = td->version[i];
00801 writeops = 2;
00802 } else {
00803 rd = md;
00804 td->version[i] = md->version[i];
00805 writeops = 1;
00806 }
00807
00808 goto writecheck;
00809
00810 } else {
00811 if (td->pages[i] == -1) {
00812 writeops = 0x01;
00813 goto create;
00814 }
00815 rd = td;
00816 goto writecheck;
00817 }
00818 create:
00819
00820 if (!(td->options & NAND_BBT_CREATE))
00821 continue;
00822
00823
00824 create_bbt (mtd, buf, bd, chipsel);
00825
00826 td->version[i] = 1;
00827 if (md)
00828 md->version[i] = 1;
00829 writecheck:
00830
00831 if (rd)
00832 read_abs_bbt (mtd, buf, rd, chipsel);
00833
00834 if (rd2)
00835 read_abs_bbt (mtd, buf, rd2, chipsel);
00836
00837
00838 if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
00839 res = write_bbt (mtd, buf, td, md, chipsel);
00840 if (res < 0)
00841 return res;
00842 }
00843
00844
00845 if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
00846 res = write_bbt (mtd, buf, md, td, chipsel);
00847 if (res < 0)
00848 return res;
00849 }
00850 }
00851 return 0;
00852 }
00853
00863 static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
00864 {
00865 struct nand_chip *this = mtd->priv;
00866 int i, j, chips, block, nrblocks, update;
00867 uint8_t oldval, newval;
00868
00869
00870 if (td->options & NAND_BBT_PERCHIP) {
00871 chips = this->numchips;
00872 nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
00873 } else {
00874 chips = 1;
00875 nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
00876 }
00877
00878 for (i = 0; i < chips; i++) {
00879 if ((td->options & NAND_BBT_ABSPAGE) ||
00880 !(td->options & NAND_BBT_WRITE)) {
00881 if (td->pages[i] == -1) continue;
00882 block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
00883 block <<= 1;
00884 oldval = this->bbt[(block >> 3)];
00885 newval = oldval | (0x2 << (block & 0x06));
00886 this->bbt[(block >> 3)] = newval;
00887 if ((oldval != newval) && td->reserved_block_code)
00888 nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1));
00889 continue;
00890 }
00891 update = 0;
00892 if (td->options & NAND_BBT_LASTBLOCK)
00893 block = ((i + 1) * nrblocks) - td->maxblocks;
00894 else
00895 block = i * nrblocks;
00896 block <<= 1;
00897 for (j = 0; j < td->maxblocks; j++) {
00898 oldval = this->bbt[(block >> 3)];
00899 newval = oldval | (0x2 << (block & 0x06));
00900 this->bbt[(block >> 3)] = newval;
00901 if (oldval != newval) update = 1;
00902 block += 2;
00903 }
00904
00905
00906
00907 if (update && td->reserved_block_code)
00908 nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1));
00909 }
00910 }
00911
00926 int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
00927 {
00928 struct nand_chip *this = mtd->priv;
00929 int len, res = 0;
00930 uint8_t *buf;
00931 struct nand_bbt_descr *td = this->bbt_td;
00932 struct nand_bbt_descr *md = this->bbt_md;
00933
00934 len = mtd->size >> (this->bbt_erase_shift + 2);
00935
00936
00937
00938 this->bbt = NULL;
00939 if(len <= BBT_LEN_1)
00940 this->bbt = bbt_b_1;
00941 if (!this->bbt) {
00942 printf ( "nand_scan_bbt: Out of memory\n");
00943 return -ENOMEM;
00944 }
00945
00946 memset (this->bbt, 0x00, len);
00947
00948
00949
00950
00951 if (!td) {
00952 if ((res = nand_memory_bbt(mtd, bd))) {
00953 printf ( "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
00954
00955 this->bbt = NULL;
00956 }
00957 return res;
00958 }
00959
00960
00961 len = (1 << this->bbt_erase_shift);
00962 len += (len >> this->page_shift) * mtd->oobsize;
00963
00964
00965 buf = NULL;
00966 if(len <= BBT_LEN_2)
00967 buf = bbt_b_2;
00968 if (!buf) {
00969 printf ( "nand_bbt: Out of memory\n");
00970
00971 this->bbt = NULL;
00972 return -ENOMEM;
00973 }
00974
00975
00976 if (td->options & NAND_BBT_ABSPAGE) {
00977 res = read_abs_bbts (mtd, buf, td, md);
00978 } else {
00979
00980 res = search_read_bbts (mtd, buf, td, md);
00981 }
00982
00983 if (res)
00984 res = check_create (mtd, buf, bd);
00985
00986
00987 mark_bbt_region (mtd, td);
00988 if (md)
00989 mark_bbt_region (mtd, md);
00990
00991
00992 return res;
00993 }
00994
00995
01003 int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
01004 {
01005 struct nand_chip *this = mtd->priv;
01006 int len, res = 0, writeops = 0;
01007 int chip, chipsel;
01008 uint8_t *buf;
01009 struct nand_bbt_descr *td = this->bbt_td;
01010 struct nand_bbt_descr *md = this->bbt_md;
01011
01012 if (!this->bbt || !td)
01013 return -1;
01014
01015 len = mtd->size >> (this->bbt_erase_shift + 2);
01016
01017 len = (1 << this->bbt_erase_shift);
01018 len += (len >> this->page_shift) * mtd->oobsize;
01019
01020
01021 buf = NULL;
01022 if(len <= BBT_LEN_2)
01023 buf = bbt_b_2;
01024 if (!buf) {
01025 printf ( "nand_update_bbt: Out of memory\n");
01026 return -ENOMEM;
01027 }
01028
01029 writeops = md != NULL ? 0x03 : 0x01;
01030
01031
01032 if (td->options & NAND_BBT_PERCHIP) {
01033 chip = (int) (offs >> this->chip_shift);
01034 chipsel = chip;
01035 } else {
01036 chip = 0;
01037 chipsel = -1;
01038 }
01039
01040 td->version[chip]++;
01041 if (md)
01042 md->version[chip]++;
01043
01044
01045 if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
01046 res = write_bbt (mtd, buf, td, md, chipsel);
01047 if (res < 0)
01048 goto out;
01049 }
01050
01051 if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
01052 res = write_bbt (mtd, buf, md, td, chipsel);
01053 }
01054
01055 out:
01056
01057 return res;
01058 }
01059
01060
01061
01062 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
01063
01064 static struct nand_bbt_descr smallpage_memorybased = {
01065 .options = NAND_BBT_SCAN2NDPAGE,
01066 .offs = 5,
01067 .len = 1,
01068 .pattern = scan_ff_pattern
01069 };
01070
01071 static struct nand_bbt_descr largepage_memorybased = {
01072 .options = 0,
01073 .offs = 0,
01074 .len = 2,
01075 .pattern = scan_ff_pattern
01076 };
01077
01078 static struct nand_bbt_descr smallpage_flashbased = {
01079 .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
01080 .offs = 5,
01081 .len = 1,
01082 .pattern = scan_ff_pattern
01083 };
01084
01085 static struct nand_bbt_descr largepage_flashbased = {
01086 .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
01087 .offs = 0,
01088 .len = 2,
01089 .pattern = scan_ff_pattern
01090 };
01091
01092 static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
01093
01094 static struct nand_bbt_descr agand_flashbased = {
01095 .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
01096 .offs = 0x20,
01097 .len = 6,
01098 .pattern = scan_agand_pattern
01099 };
01100
01101
01102
01103 static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
01104 static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
01105
01106 static struct nand_bbt_descr bbt_main_descr = {
01107 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
01108 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
01109 .offs = 8,
01110 .len = 4,
01111 .veroffs = 12,
01112 .maxblocks = 4,
01113 .pattern = bbt_pattern
01114 };
01115
01116 static struct nand_bbt_descr bbt_mirror_descr = {
01117 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
01118 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
01119 .offs = 8,
01120 .len = 4,
01121 .veroffs = 12,
01122 .maxblocks = 4,
01123 .pattern = mirror_pattern
01124 };
01125
01134 int nand_default_bbt (struct mtd_info *mtd)
01135 {
01136 struct nand_chip *this = mtd->priv;
01137
01138
01139
01140
01141
01142
01143
01144
01145 if (this->options & NAND_IS_AND) {
01146
01147 if (!this->bbt_td) {
01148 this->bbt_td = &bbt_main_descr;
01149 this->bbt_md = &bbt_mirror_descr;
01150 }
01151 this->options |= NAND_USE_FLASH_BBT;
01152 return nand_scan_bbt (mtd, &agand_flashbased);
01153 }
01154
01155
01156
01157 if (this->options & NAND_USE_FLASH_BBT) {
01158
01159 if (!this->bbt_td) {
01160 this->bbt_td = &bbt_main_descr;
01161 this->bbt_md = &bbt_mirror_descr;
01162 }
01163 if (!this->badblock_pattern) {
01164 this->badblock_pattern = (mtd->oobblock > 512) ?
01165 &largepage_flashbased : &smallpage_flashbased;
01166 }
01167 } else {
01168 this->bbt_td = NULL;
01169 this->bbt_md = NULL;
01170 if (!this->badblock_pattern) {
01171 this->badblock_pattern = (mtd->oobblock > 512) ?
01172 &largepage_memorybased : &smallpage_memorybased;
01173 }
01174 }
01175 return nand_scan_bbt (mtd, this->badblock_pattern);
01176 }
01177
01185 int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
01186 {
01187 struct nand_chip *this = mtd->priv;
01188 int block;
01189 uint8_t res;
01190
01191
01192 block = (int) (offs >> (this->bbt_erase_shift - 1));
01193 res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
01194
01195 DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
01196 (unsigned int)offs, block >> 1, res);
01197
01198 switch ((int)res) {
01199 case 0x00: return 0;
01200 case 0x01: return 1;
01201 case 0x02: return allowbbt ? 0 : 1;
01202 }
01203 return 1;
01204 }
01205
01206 EXPORT_SYMBOL (nand_scan_bbt);
01207 EXPORT_SYMBOL (nand_default_bbt);