os/linux-2.6-tag--devboard-R2_10-4/drivers/mtd/nand/nand_bbt.c

Go to the documentation of this file.
00001 /*
00002  *  drivers/mtd/nand_bbt.c
00003  *
00004  *  Overview:
00005  *   Bad block table support for the NAND driver
00006  *
00007  *  Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
00008  *
00009  * $Id: nand_bbt.c,v 1.1.1.1 2008/11/27 20:04:01 elphel Exp $
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License version 2 as
00013  * published by the Free Software Foundation.
00014  *
00015  * Description:
00016  *
00017  * When nand_scan_bbt is called, then it tries to find the bad block table
00018  * depending on the options in the bbt descriptor(s). If a bbt is found
00019  * then the contents are read and the memory based bbt is created. If a
00020  * mirrored bbt is selected then the mirror is searched too and the
00021  * versions are compared. If the mirror has a greater version number
00022  * than the mirror bbt is used to build the memory based bbt.
00023  * If the tables are not versioned, then we "or" the bad block information.
00024  * If one of the bbt's is out of date or does not exist it is (re)created.
00025  * If no bbt exists at all then the device is scanned for factory marked
00026  * good / bad blocks and the bad block tables are created.
00027  *
00028  * For manufacturer created bbts like the one found on M-SYS DOC devices
00029  * the bbt is searched and read but never created
00030  *
00031  * The autogenerated bad block table is located in the last good blocks
00032  * of the device. The table is mirrored, so it can be updated eventually.
00033  * The table is marked in the oob area with an ident pattern and a version
00034  * number which indicates which of both tables is more up to date.
00035  *
00036  * The table uses 2 bits per block
00037  * 11b:         block is good
00038  * 00b:         block is factory marked bad
00039  * 01b, 10b:    block is marked bad due to wear
00040  *
00041  * The memory bad block table uses the following scheme:
00042  * 00b:         block is good
00043  * 01b:         block is marked bad due to wear
00044  * 10b:         block is reserved (to protect the bbt area)
00045  * 11b:         block is factory marked bad
00046  *
00047  * Multichip devices like DOC store the bad block info per floor.
00048  *
00049  * Following assumptions are made:
00050  * - bbts start at a page boundary, if autolocated on a block boundary
00051  * - the space necessary for a bbt in FLASH does not exceed a block boundary
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         /* Compare the pattern */
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         /* Compare the pattern */
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                 /* Analyse data */
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                                 /* Leave it for now, if its matured we can move this
00183                                  * message to MTD_DEBUG_LEVEL0 */
00184                                 printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
00185                                        ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
00186                                 /* Factory marked bad or worn out ? */
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  * Scan read raw data from flash
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  * Scan write data with oob to flash
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         /* Read the primary version, if available */
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         /* Read the mirror version, if available */
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  * Scan a given block full
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  * Scan a given block partially
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                  * Read the full oob until read_oob is fixed to
00346                  * handle single byte reads for 16 bit
00347                  * buswidth
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                 /* We need only read few bytes from the OOB area */
00394                 scanlen = 0;
00395                 readlen = bd->len;
00396         } else {
00397                 /* Full page content should be read */
00398                 scanlen = mtd->writesize + mtd->oobsize;
00399                 readlen = len * mtd->writesize;
00400         }
00401 
00402         if (chip == -1) {
00403                 /* Note that numblocks is 2 * (real numblocks) here, see i+=2
00404                  * below as it makes shifting and masking less painful */
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         /* Search direction top -> down ? */
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         /* Do we have a bbt per chip ? */
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         /* Number of bits for each erase block in the bbt */
00491         bits = td->options & NAND_BBT_NRBITS_MSK;
00492 
00493         for (i = 0; i < chips; i++) {
00494                 /* Reset version information */
00495                 td->version[i] = 0;
00496                 td->pages[i] = -1;
00497                 /* Scan the maximum number of blocks */
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                         /* Read first page */
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         /* Check, if we found a bbt for each requested chip */
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         /* Search the primary table */
00538         search_bbt(mtd, buf, td);
00539 
00540         /* Search the mirror table */
00541         if (md)
00542                 search_bbt(mtd, buf, md);
00543 
00544         /* Force result check */
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         /* Write bad block table per chip rather than per device ? */
00583         if (td->options & NAND_BBT_PERCHIP) {
00584                 numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
00585                 /* Full device write or specific chip ? */
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         /* Loop through the chips */
00598         for (; chip < nrchips; chip++) {
00599 
00600                 /* There was already a version of the table, reuse the page
00601                  * This applies for absolute placement too, as we have the
00602                  * page nr. in td->pages.
00603                  */
00604                 if (td->pages[chip] != -1) {
00605                         page = td->pages[chip];
00606                         goto write;
00607                 }
00608 
00609                 /* Automatic placement of the bad block table */
00610                 /* Search direction top -> down ? */
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                         /* Check, if the block is bad */
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                         /* Check, if the block is used by the mirror table */
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                 /* Set up shift count and masks for the flash table */
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                 /* Must we save the block contents ? */
00662                 if (td->options & NAND_BBT_SAVECONTENT) {
00663                         /* Make it block aligned */
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                         /* Read oob data */
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                         /* Calc the byte offset in the buffer */
00686                         pageoffs = page - (int)(to >> this->page_shift);
00687                         offs = pageoffs << this->page_shift;
00688                         /* Preset the bbt area with 0xff */
00689                         memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
00690                         ooboffs = len + (pageoffs * mtd->oobsize);
00691 
00692                 } else {
00693                         /* Calc length */
00694                         len = (size_t) (numblocks >> sft);
00695                         /* Make it page aligned ! */
00696                         len = (len + (mtd->writesize - 1)) &
00697                                 ~(mtd->writesize - 1);
00698                         /* Preset the buffer with 0xff */
00699                         memset(buf, 0xff, len +
00700                                (len >> this->page_shift)* mtd->oobsize);
00701                         offs = 0;
00702                         ooboffs = len;
00703                         /* Pattern is located in oob area of first page */
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                 /* walk through the memory table */
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                                 /* Do not store the reserved bbt blocks ! */
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                 /* Mark it as used */
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         /* Do we have a bbt per chip ? */
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                 /* Per chip or per device ? */
00796                 chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
00797                 /* Mirrored table avilable ? */
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                 /* Create the bad block table by scanning the device ? */
00847                 if (!(td->options & NAND_BBT_CREATE))
00848                         continue;
00849 
00850                 /* Create the table in memory by scanning the chip(s) */
00851                 create_bbt(mtd, buf, bd, chipsel);
00852 
00853                 td->version[i] = 1;
00854                 if (md)
00855                         md->version[i] = 1;
00856         writecheck:
00857                 /* read back first ? */
00858                 if (rd)
00859                         read_abs_bbt(mtd, buf, rd, chipsel);
00860                 /* If they weren't versioned, read both. */
00861                 if (rd2)
00862                         read_abs_bbt(mtd, buf, rd2, chipsel);
00863 
00864                 /* Write the bad block table to the device ? */
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                 /* Write the mirror bad block table to the device ? */
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         /* Do we have a bbt per chip ? */
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                 /* If we want reserved blocks to be recorded to flash, and some
00934                    new ones have been marked, then we need to update the stored
00935                    bbts.  This should only happen once. */
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         /* Allocate memory (2bit per block) */
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         /* Clear the memory bad block table */
00971         memset(this->bbt, 0x00, len);
00972 
00973         /* If no primary table decriptor is given, scan the device
00974          * to build a memory based bad block table
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         /* Allocate a temporary buffer for one eraseblock incl. oob */
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         /* Is the bbt at a given page ? */
00997         if (td->options & NAND_BBT_ABSPAGE) {
00998                 res = read_abs_bbts(mtd, buf, td, md);
00999         } else {
01000                 /* Search the bad block table using a pattern in oob */
01001                 res = search_read_bbts(mtd, buf, td, md);
01002         }
01003 
01004         if (res)
01005                 res = check_create(mtd, buf, bd);
01006 
01007         /* Prevent the bbt regions from erasing / writing */
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         /* Allocate a temporary buffer for one eraseblock incl. oob */
01037         len = (1 << this->bbt_erase_shift);
01038         len += (len >> this->page_shift) * mtd->oobsize;
01039 //      buf = kmalloc(len, GFP_KERNEL);
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         /* Do we have a bbt per chip ? */
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         /* Write the bad block table to the device ? */
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         /* Write the mirror bad block table to the device ? */
01068         if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
01069                 res = write_bbt(mtd, buf, md, td, chipsel);
01070         }
01071 
01072  out:
01073 //      kfree(buf);
01074         vfree(buf);
01075         return res;
01076 }
01077 
01078 /* Define some generic bad / good block scan pattern which are used
01079  * while scanning a device for factory marked good / bad blocks. */
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 /* Generic flash bbt decriptors
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         /* Default for AG-AND. We must use a flash based
01157          * bad block table as the devices have factory marked
01158          * _good_ blocks. Erasing those blocks leads to loss
01159          * of the good / bad information, so we _must_ store
01160          * this information in a good / bad table during
01161          * startup
01162          */
01163         if (this->options & NAND_IS_AND) {
01164                 /* Use the default pattern descriptors */
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         /* Is a flash based bad block table requested ? */
01174         if (this->options & NAND_USE_FLASH_BBT) {
01175                 /* Use the default pattern descriptors */
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         /* Get block number * 2 */
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);

Generated on Fri Nov 28 00:06:24 2008 for elphel by  doxygen 1.5.1