1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
293db446aSBoris Brezillon /*
393db446aSBoris Brezillon * Overview:
493db446aSBoris Brezillon * Bad block table support for the NAND driver
593db446aSBoris Brezillon *
693db446aSBoris Brezillon * Copyright © 2004 Thomas Gleixner (tglx@linutronix.de)
793db446aSBoris Brezillon *
893db446aSBoris Brezillon * Description:
993db446aSBoris Brezillon *
1093db446aSBoris Brezillon * When nand_scan_bbt is called, then it tries to find the bad block table
1193db446aSBoris Brezillon * depending on the options in the BBT descriptor(s). If no flash based BBT
1293db446aSBoris Brezillon * (NAND_BBT_USE_FLASH) is specified then the device is scanned for factory
1393db446aSBoris Brezillon * marked good / bad blocks. This information is used to create a memory BBT.
1493db446aSBoris Brezillon * Once a new bad block is discovered then the "factory" information is updated
1593db446aSBoris Brezillon * on the device.
1693db446aSBoris Brezillon * If a flash based BBT is specified then the function first tries to find the
1793db446aSBoris Brezillon * BBT on flash. If a BBT is found then the contents are read and the memory
1893db446aSBoris Brezillon * based BBT is created. If a mirrored BBT is selected then the mirror is
1993db446aSBoris Brezillon * searched too and the versions are compared. If the mirror has a greater
2093db446aSBoris Brezillon * version number, then the mirror BBT is used to build the memory based BBT.
2193db446aSBoris Brezillon * If the tables are not versioned, then we "or" the bad block information.
2293db446aSBoris Brezillon * If one of the BBTs is out of date or does not exist it is (re)created.
2393db446aSBoris Brezillon * If no BBT exists at all then the device is scanned for factory marked
2493db446aSBoris Brezillon * good / bad blocks and the bad block tables are created.
2593db446aSBoris Brezillon *
2693db446aSBoris Brezillon * For manufacturer created BBTs like the one found on M-SYS DOC devices
2793db446aSBoris Brezillon * the BBT is searched and read but never created
2893db446aSBoris Brezillon *
2993db446aSBoris Brezillon * The auto generated bad block table is located in the last good blocks
3093db446aSBoris Brezillon * of the device. The table is mirrored, so it can be updated eventually.
3193db446aSBoris Brezillon * The table is marked in the OOB area with an ident pattern and a version
3293db446aSBoris Brezillon * number which indicates which of both tables is more up to date. If the NAND
3393db446aSBoris Brezillon * controller needs the complete OOB area for the ECC information then the
3493db446aSBoris Brezillon * option NAND_BBT_NO_OOB should be used (along with NAND_BBT_USE_FLASH, of
3593db446aSBoris Brezillon * course): it moves the ident pattern and the version byte into the data area
3693db446aSBoris Brezillon * and the OOB area will remain untouched.
3793db446aSBoris Brezillon *
3893db446aSBoris Brezillon * The table uses 2 bits per block
3993db446aSBoris Brezillon * 11b: block is good
4093db446aSBoris Brezillon * 00b: block is factory marked bad
4193db446aSBoris Brezillon * 01b, 10b: block is marked bad due to wear
4293db446aSBoris Brezillon *
4393db446aSBoris Brezillon * The memory bad block table uses the following scheme:
4493db446aSBoris Brezillon * 00b: block is good
4593db446aSBoris Brezillon * 01b: block is marked bad due to wear
4693db446aSBoris Brezillon * 10b: block is reserved (to protect the bbt area)
4793db446aSBoris Brezillon * 11b: block is factory marked bad
4893db446aSBoris Brezillon *
4993db446aSBoris Brezillon * Multichip devices like DOC store the bad block info per floor.
5093db446aSBoris Brezillon *
5193db446aSBoris Brezillon * Following assumptions are made:
5293db446aSBoris Brezillon * - bbts start at a page boundary, if autolocated on a block boundary
5393db446aSBoris Brezillon * - the space necessary for a bbt in FLASH does not exceed a block boundary
5493db446aSBoris Brezillon */
5593db446aSBoris Brezillon
5693db446aSBoris Brezillon #include <linux/slab.h>
5793db446aSBoris Brezillon #include <linux/types.h>
5893db446aSBoris Brezillon #include <linux/mtd/mtd.h>
5993db446aSBoris Brezillon #include <linux/mtd/bbm.h>
6093db446aSBoris Brezillon #include <linux/bitops.h>
6193db446aSBoris Brezillon #include <linux/delay.h>
6293db446aSBoris Brezillon #include <linux/vmalloc.h>
6393db446aSBoris Brezillon #include <linux/export.h>
6493db446aSBoris Brezillon #include <linux/string.h>
6593db446aSBoris Brezillon
66348d56a8SBoris Brezillon #include "internals.h"
67348d56a8SBoris Brezillon
6893db446aSBoris Brezillon #define BBT_BLOCK_GOOD 0x00
6993db446aSBoris Brezillon #define BBT_BLOCK_WORN 0x01
7093db446aSBoris Brezillon #define BBT_BLOCK_RESERVED 0x02
7193db446aSBoris Brezillon #define BBT_BLOCK_FACTORY_BAD 0x03
7293db446aSBoris Brezillon
7393db446aSBoris Brezillon #define BBT_ENTRY_MASK 0x03
7493db446aSBoris Brezillon #define BBT_ENTRY_SHIFT 2
7593db446aSBoris Brezillon
bbt_get_entry(struct nand_chip * chip,int block)7693db446aSBoris Brezillon static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block)
7793db446aSBoris Brezillon {
7893db446aSBoris Brezillon uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT];
7993db446aSBoris Brezillon entry >>= (block & BBT_ENTRY_MASK) * 2;
8093db446aSBoris Brezillon return entry & BBT_ENTRY_MASK;
8193db446aSBoris Brezillon }
8293db446aSBoris Brezillon
bbt_mark_entry(struct nand_chip * chip,int block,uint8_t mark)8393db446aSBoris Brezillon static inline void bbt_mark_entry(struct nand_chip *chip, int block,
8493db446aSBoris Brezillon uint8_t mark)
8593db446aSBoris Brezillon {
8693db446aSBoris Brezillon uint8_t msk = (mark & BBT_ENTRY_MASK) << ((block & BBT_ENTRY_MASK) * 2);
8793db446aSBoris Brezillon chip->bbt[block >> BBT_ENTRY_SHIFT] |= msk;
8893db446aSBoris Brezillon }
8993db446aSBoris Brezillon
check_pattern_no_oob(uint8_t * buf,struct nand_bbt_descr * td)9093db446aSBoris Brezillon static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
9193db446aSBoris Brezillon {
9293db446aSBoris Brezillon if (memcmp(buf, td->pattern, td->len))
9393db446aSBoris Brezillon return -1;
9493db446aSBoris Brezillon return 0;
9593db446aSBoris Brezillon }
9693db446aSBoris Brezillon
9793db446aSBoris Brezillon /**
9893db446aSBoris Brezillon * check_pattern - [GENERIC] check if a pattern is in the buffer
9993db446aSBoris Brezillon * @buf: the buffer to search
10093db446aSBoris Brezillon * @len: the length of buffer to search
10193db446aSBoris Brezillon * @paglen: the pagelength
10293db446aSBoris Brezillon * @td: search pattern descriptor
10393db446aSBoris Brezillon *
10493db446aSBoris Brezillon * Check for a pattern at the given place. Used to search bad block tables and
10593db446aSBoris Brezillon * good / bad block identifiers.
10693db446aSBoris Brezillon */
check_pattern(uint8_t * buf,int len,int paglen,struct nand_bbt_descr * td)10793db446aSBoris Brezillon static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
10893db446aSBoris Brezillon {
10993db446aSBoris Brezillon if (td->options & NAND_BBT_NO_OOB)
11093db446aSBoris Brezillon return check_pattern_no_oob(buf, td);
11193db446aSBoris Brezillon
11293db446aSBoris Brezillon /* Compare the pattern */
11393db446aSBoris Brezillon if (memcmp(buf + paglen + td->offs, td->pattern, td->len))
11493db446aSBoris Brezillon return -1;
11593db446aSBoris Brezillon
11693db446aSBoris Brezillon return 0;
11793db446aSBoris Brezillon }
11893db446aSBoris Brezillon
11993db446aSBoris Brezillon /**
12093db446aSBoris Brezillon * check_short_pattern - [GENERIC] check if a pattern is in the buffer
12193db446aSBoris Brezillon * @buf: the buffer to search
12293db446aSBoris Brezillon * @td: search pattern descriptor
12393db446aSBoris Brezillon *
12493db446aSBoris Brezillon * Check for a pattern at the given place. Used to search bad block tables and
12593db446aSBoris Brezillon * good / bad block identifiers. Same as check_pattern, but no optional empty
12693db446aSBoris Brezillon * check.
12793db446aSBoris Brezillon */
check_short_pattern(uint8_t * buf,struct nand_bbt_descr * td)12893db446aSBoris Brezillon static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
12993db446aSBoris Brezillon {
13093db446aSBoris Brezillon /* Compare the pattern */
13193db446aSBoris Brezillon if (memcmp(buf + td->offs, td->pattern, td->len))
13293db446aSBoris Brezillon return -1;
13393db446aSBoris Brezillon return 0;
13493db446aSBoris Brezillon }
13593db446aSBoris Brezillon
13693db446aSBoris Brezillon /**
13793db446aSBoris Brezillon * add_marker_len - compute the length of the marker in data area
13893db446aSBoris Brezillon * @td: BBT descriptor used for computation
13993db446aSBoris Brezillon *
14093db446aSBoris Brezillon * The length will be 0 if the marker is located in OOB area.
14193db446aSBoris Brezillon */
add_marker_len(struct nand_bbt_descr * td)14293db446aSBoris Brezillon static u32 add_marker_len(struct nand_bbt_descr *td)
14393db446aSBoris Brezillon {
14493db446aSBoris Brezillon u32 len;
14593db446aSBoris Brezillon
14693db446aSBoris Brezillon if (!(td->options & NAND_BBT_NO_OOB))
14793db446aSBoris Brezillon return 0;
14893db446aSBoris Brezillon
14993db446aSBoris Brezillon len = td->len;
15093db446aSBoris Brezillon if (td->options & NAND_BBT_VERSION)
15193db446aSBoris Brezillon len++;
15293db446aSBoris Brezillon return len;
15393db446aSBoris Brezillon }
15493db446aSBoris Brezillon
15593db446aSBoris Brezillon /**
15693db446aSBoris Brezillon * read_bbt - [GENERIC] Read the bad block table starting from page
157455e7b38SRandy Dunlap * @this: NAND chip object
15893db446aSBoris Brezillon * @buf: temporary buffer
15993db446aSBoris Brezillon * @page: the starting page
16093db446aSBoris Brezillon * @num: the number of bbt descriptors to read
16193db446aSBoris Brezillon * @td: the bbt describtion table
16293db446aSBoris Brezillon * @offs: block number offset in the table
16393db446aSBoris Brezillon *
16493db446aSBoris Brezillon * Read the bad block table starting from page.
16593db446aSBoris Brezillon */
read_bbt(struct nand_chip * this,uint8_t * buf,int page,int num,struct nand_bbt_descr * td,int offs)1660813621bSBoris Brezillon static int read_bbt(struct nand_chip *this, uint8_t *buf, int page, int num,
16793db446aSBoris Brezillon struct nand_bbt_descr *td, int offs)
16893db446aSBoris Brezillon {
1690813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
17093db446aSBoris Brezillon int res, ret = 0, i, j, act = 0;
17193db446aSBoris Brezillon size_t retlen, len, totlen;
17293db446aSBoris Brezillon loff_t from;
17393db446aSBoris Brezillon int bits = td->options & NAND_BBT_NRBITS_MSK;
17493db446aSBoris Brezillon uint8_t msk = (uint8_t)((1 << bits) - 1);
17593db446aSBoris Brezillon u32 marker_len;
17693db446aSBoris Brezillon int reserved_block_code = td->reserved_block_code;
17793db446aSBoris Brezillon
17893db446aSBoris Brezillon totlen = (num * bits) >> 3;
17993db446aSBoris Brezillon marker_len = add_marker_len(td);
18093db446aSBoris Brezillon from = ((loff_t)page) << this->page_shift;
18193db446aSBoris Brezillon
18293db446aSBoris Brezillon while (totlen) {
18393db446aSBoris Brezillon len = min(totlen, (size_t)(1 << this->bbt_erase_shift));
18493db446aSBoris Brezillon if (marker_len) {
18593db446aSBoris Brezillon /*
18693db446aSBoris Brezillon * In case the BBT marker is not in the OOB area it
18793db446aSBoris Brezillon * will be just in the first page.
18893db446aSBoris Brezillon */
18993db446aSBoris Brezillon len -= marker_len;
19093db446aSBoris Brezillon from += marker_len;
19193db446aSBoris Brezillon marker_len = 0;
19293db446aSBoris Brezillon }
19393db446aSBoris Brezillon res = mtd_read(mtd, from, len, &retlen, buf);
19493db446aSBoris Brezillon if (res < 0) {
19593db446aSBoris Brezillon if (mtd_is_eccerr(res)) {
19693db446aSBoris Brezillon pr_info("nand_bbt: ECC error in BBT at 0x%012llx\n",
19793db446aSBoris Brezillon from & ~mtd->writesize);
19893db446aSBoris Brezillon return res;
19993db446aSBoris Brezillon } else if (mtd_is_bitflip(res)) {
20093db446aSBoris Brezillon pr_info("nand_bbt: corrected error in BBT at 0x%012llx\n",
20193db446aSBoris Brezillon from & ~mtd->writesize);
20293db446aSBoris Brezillon ret = res;
20393db446aSBoris Brezillon } else {
20493db446aSBoris Brezillon pr_info("nand_bbt: error reading BBT\n");
20593db446aSBoris Brezillon return res;
20693db446aSBoris Brezillon }
20793db446aSBoris Brezillon }
20893db446aSBoris Brezillon
20993db446aSBoris Brezillon /* Analyse data */
21093db446aSBoris Brezillon for (i = 0; i < len; i++) {
21193db446aSBoris Brezillon uint8_t dat = buf[i];
21293db446aSBoris Brezillon for (j = 0; j < 8; j += bits, act++) {
21393db446aSBoris Brezillon uint8_t tmp = (dat >> j) & msk;
21493db446aSBoris Brezillon if (tmp == msk)
21593db446aSBoris Brezillon continue;
21693db446aSBoris Brezillon if (reserved_block_code && (tmp == reserved_block_code)) {
21793db446aSBoris Brezillon pr_info("nand_read_bbt: reserved block at 0x%012llx\n",
21893db446aSBoris Brezillon (loff_t)(offs + act) <<
21993db446aSBoris Brezillon this->bbt_erase_shift);
22093db446aSBoris Brezillon bbt_mark_entry(this, offs + act,
22193db446aSBoris Brezillon BBT_BLOCK_RESERVED);
22293db446aSBoris Brezillon mtd->ecc_stats.bbtblocks++;
22393db446aSBoris Brezillon continue;
22493db446aSBoris Brezillon }
22593db446aSBoris Brezillon /*
22693db446aSBoris Brezillon * Leave it for now, if it's matured we can
22793db446aSBoris Brezillon * move this message to pr_debug.
22893db446aSBoris Brezillon */
22993db446aSBoris Brezillon pr_info("nand_read_bbt: bad block at 0x%012llx\n",
23093db446aSBoris Brezillon (loff_t)(offs + act) <<
23193db446aSBoris Brezillon this->bbt_erase_shift);
23293db446aSBoris Brezillon /* Factory marked bad or worn out? */
23393db446aSBoris Brezillon if (tmp == 0)
23493db446aSBoris Brezillon bbt_mark_entry(this, offs + act,
23593db446aSBoris Brezillon BBT_BLOCK_FACTORY_BAD);
23693db446aSBoris Brezillon else
23793db446aSBoris Brezillon bbt_mark_entry(this, offs + act,
23893db446aSBoris Brezillon BBT_BLOCK_WORN);
23993db446aSBoris Brezillon mtd->ecc_stats.badblocks++;
24093db446aSBoris Brezillon }
24193db446aSBoris Brezillon }
24293db446aSBoris Brezillon totlen -= len;
24393db446aSBoris Brezillon from += len;
24493db446aSBoris Brezillon }
24593db446aSBoris Brezillon return ret;
24693db446aSBoris Brezillon }
24793db446aSBoris Brezillon
24893db446aSBoris Brezillon /**
24993db446aSBoris Brezillon * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page
2500813621bSBoris Brezillon * @this: NAND chip object
25193db446aSBoris Brezillon * @buf: temporary buffer
25293db446aSBoris Brezillon * @td: descriptor for the bad block table
25393db446aSBoris Brezillon * @chip: read the table for a specific chip, -1 read all chips; applies only if
25493db446aSBoris Brezillon * NAND_BBT_PERCHIP option is set
25593db446aSBoris Brezillon *
25693db446aSBoris Brezillon * Read the bad block table for all chips starting at a given page. We assume
25793db446aSBoris Brezillon * that the bbt bits are in consecutive order.
25893db446aSBoris Brezillon */
read_abs_bbt(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * td,int chip)2590813621bSBoris Brezillon static int read_abs_bbt(struct nand_chip *this, uint8_t *buf,
2600813621bSBoris Brezillon struct nand_bbt_descr *td, int chip)
26193db446aSBoris Brezillon {
2620813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
2636c836d51SBoris Brezillon u64 targetsize = nanddev_target_size(&this->base);
26493db446aSBoris Brezillon int res = 0, i;
26593db446aSBoris Brezillon
26693db446aSBoris Brezillon if (td->options & NAND_BBT_PERCHIP) {
26793db446aSBoris Brezillon int offs = 0;
26832813e28SBoris Brezillon for (i = 0; i < nanddev_ntargets(&this->base); i++) {
26993db446aSBoris Brezillon if (chip == -1 || chip == i)
2700813621bSBoris Brezillon res = read_bbt(this, buf, td->pages[i],
2716c836d51SBoris Brezillon targetsize >> this->bbt_erase_shift,
27293db446aSBoris Brezillon td, offs);
27393db446aSBoris Brezillon if (res)
27493db446aSBoris Brezillon return res;
2756c836d51SBoris Brezillon offs += targetsize >> this->bbt_erase_shift;
27693db446aSBoris Brezillon }
27793db446aSBoris Brezillon } else {
2780813621bSBoris Brezillon res = read_bbt(this, buf, td->pages[0],
27993db446aSBoris Brezillon mtd->size >> this->bbt_erase_shift, td, 0);
28093db446aSBoris Brezillon if (res)
28193db446aSBoris Brezillon return res;
28293db446aSBoris Brezillon }
28393db446aSBoris Brezillon return 0;
28493db446aSBoris Brezillon }
28593db446aSBoris Brezillon
28693db446aSBoris Brezillon /* BBT marker is in the first page, no OOB */
scan_read_data(struct nand_chip * this,uint8_t * buf,loff_t offs,struct nand_bbt_descr * td)2870813621bSBoris Brezillon static int scan_read_data(struct nand_chip *this, uint8_t *buf, loff_t offs,
28893db446aSBoris Brezillon struct nand_bbt_descr *td)
28993db446aSBoris Brezillon {
2900813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
29193db446aSBoris Brezillon size_t retlen;
29293db446aSBoris Brezillon size_t len;
29393db446aSBoris Brezillon
29493db446aSBoris Brezillon len = td->len;
29593db446aSBoris Brezillon if (td->options & NAND_BBT_VERSION)
29693db446aSBoris Brezillon len++;
29793db446aSBoris Brezillon
29893db446aSBoris Brezillon return mtd_read(mtd, offs, len, &retlen, buf);
29993db446aSBoris Brezillon }
30093db446aSBoris Brezillon
30193db446aSBoris Brezillon /**
30293db446aSBoris Brezillon * scan_read_oob - [GENERIC] Scan data+OOB region to buffer
3030813621bSBoris Brezillon * @this: NAND chip object
30493db446aSBoris Brezillon * @buf: temporary buffer
30593db446aSBoris Brezillon * @offs: offset at which to scan
30693db446aSBoris Brezillon * @len: length of data region to read
30793db446aSBoris Brezillon *
30893db446aSBoris Brezillon * Scan read data from data+OOB. May traverse multiple pages, interleaving
30993db446aSBoris Brezillon * page,OOB,page,OOB,... in buf. Completes transfer and returns the "strongest"
31093db446aSBoris Brezillon * ECC condition (error or bitflip). May quit on the first (non-ECC) error.
31193db446aSBoris Brezillon */
scan_read_oob(struct nand_chip * this,uint8_t * buf,loff_t offs,size_t len)3120813621bSBoris Brezillon static int scan_read_oob(struct nand_chip *this, uint8_t *buf, loff_t offs,
31393db446aSBoris Brezillon size_t len)
31493db446aSBoris Brezillon {
3150813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
316*745df179SMichał Kępień struct mtd_oob_ops ops = { };
31793db446aSBoris Brezillon int res, ret = 0;
31893db446aSBoris Brezillon
31993db446aSBoris Brezillon ops.mode = MTD_OPS_PLACE_OOB;
32093db446aSBoris Brezillon ops.ooboffs = 0;
32193db446aSBoris Brezillon ops.ooblen = mtd->oobsize;
32293db446aSBoris Brezillon
32393db446aSBoris Brezillon while (len > 0) {
32493db446aSBoris Brezillon ops.datbuf = buf;
32593db446aSBoris Brezillon ops.len = min(len, (size_t)mtd->writesize);
32693db446aSBoris Brezillon ops.oobbuf = buf + ops.len;
32793db446aSBoris Brezillon
32893db446aSBoris Brezillon res = mtd_read_oob(mtd, offs, &ops);
32993db446aSBoris Brezillon if (res) {
33093db446aSBoris Brezillon if (!mtd_is_bitflip_or_eccerr(res))
33193db446aSBoris Brezillon return res;
33293db446aSBoris Brezillon else if (mtd_is_eccerr(res) || !ret)
33393db446aSBoris Brezillon ret = res;
33493db446aSBoris Brezillon }
33593db446aSBoris Brezillon
33693db446aSBoris Brezillon buf += mtd->oobsize + mtd->writesize;
33793db446aSBoris Brezillon len -= mtd->writesize;
33893db446aSBoris Brezillon offs += mtd->writesize;
33993db446aSBoris Brezillon }
34093db446aSBoris Brezillon return ret;
34193db446aSBoris Brezillon }
34293db446aSBoris Brezillon
scan_read(struct nand_chip * this,uint8_t * buf,loff_t offs,size_t len,struct nand_bbt_descr * td)3430813621bSBoris Brezillon static int scan_read(struct nand_chip *this, uint8_t *buf, loff_t offs,
34493db446aSBoris Brezillon size_t len, struct nand_bbt_descr *td)
34593db446aSBoris Brezillon {
34693db446aSBoris Brezillon if (td->options & NAND_BBT_NO_OOB)
3470813621bSBoris Brezillon return scan_read_data(this, buf, offs, td);
34893db446aSBoris Brezillon else
3490813621bSBoris Brezillon return scan_read_oob(this, buf, offs, len);
35093db446aSBoris Brezillon }
35193db446aSBoris Brezillon
35293db446aSBoris Brezillon /* Scan write data with oob to flash */
scan_write_bbt(struct nand_chip * this,loff_t offs,size_t len,uint8_t * buf,uint8_t * oob)3530813621bSBoris Brezillon static int scan_write_bbt(struct nand_chip *this, loff_t offs, size_t len,
35493db446aSBoris Brezillon uint8_t *buf, uint8_t *oob)
35593db446aSBoris Brezillon {
3560813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
357*745df179SMichał Kępień struct mtd_oob_ops ops = { };
35893db446aSBoris Brezillon
35993db446aSBoris Brezillon ops.mode = MTD_OPS_PLACE_OOB;
36093db446aSBoris Brezillon ops.ooboffs = 0;
36193db446aSBoris Brezillon ops.ooblen = mtd->oobsize;
36293db446aSBoris Brezillon ops.datbuf = buf;
36393db446aSBoris Brezillon ops.oobbuf = oob;
36493db446aSBoris Brezillon ops.len = len;
36593db446aSBoris Brezillon
36693db446aSBoris Brezillon return mtd_write_oob(mtd, offs, &ops);
36793db446aSBoris Brezillon }
36893db446aSBoris Brezillon
bbt_get_ver_offs(struct nand_chip * this,struct nand_bbt_descr * td)3690813621bSBoris Brezillon static u32 bbt_get_ver_offs(struct nand_chip *this, struct nand_bbt_descr *td)
37093db446aSBoris Brezillon {
3710813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
37293db446aSBoris Brezillon u32 ver_offs = td->veroffs;
37393db446aSBoris Brezillon
37493db446aSBoris Brezillon if (!(td->options & NAND_BBT_NO_OOB))
37593db446aSBoris Brezillon ver_offs += mtd->writesize;
37693db446aSBoris Brezillon return ver_offs;
37793db446aSBoris Brezillon }
37893db446aSBoris Brezillon
37993db446aSBoris Brezillon /**
38093db446aSBoris Brezillon * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
3810813621bSBoris Brezillon * @this: NAND chip object
38293db446aSBoris Brezillon * @buf: temporary buffer
38393db446aSBoris Brezillon * @td: descriptor for the bad block table
38493db446aSBoris Brezillon * @md: descriptor for the bad block table mirror
38593db446aSBoris Brezillon *
38693db446aSBoris Brezillon * Read the bad block table(s) for all chips starting at a given page. We
38793db446aSBoris Brezillon * assume that the bbt bits are in consecutive order.
38893db446aSBoris Brezillon */
read_abs_bbts(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * td,struct nand_bbt_descr * md)3890813621bSBoris Brezillon static void read_abs_bbts(struct nand_chip *this, uint8_t *buf,
39093db446aSBoris Brezillon struct nand_bbt_descr *td, struct nand_bbt_descr *md)
39193db446aSBoris Brezillon {
3920813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
39393db446aSBoris Brezillon
39493db446aSBoris Brezillon /* Read the primary version, if available */
39593db446aSBoris Brezillon if (td->options & NAND_BBT_VERSION) {
3960813621bSBoris Brezillon scan_read(this, buf, (loff_t)td->pages[0] << this->page_shift,
39793db446aSBoris Brezillon mtd->writesize, td);
3980813621bSBoris Brezillon td->version[0] = buf[bbt_get_ver_offs(this, td)];
39993db446aSBoris Brezillon pr_info("Bad block table at page %d, version 0x%02X\n",
40093db446aSBoris Brezillon td->pages[0], td->version[0]);
40193db446aSBoris Brezillon }
40293db446aSBoris Brezillon
40393db446aSBoris Brezillon /* Read the mirror version, if available */
40493db446aSBoris Brezillon if (md && (md->options & NAND_BBT_VERSION)) {
4050813621bSBoris Brezillon scan_read(this, buf, (loff_t)md->pages[0] << this->page_shift,
40693db446aSBoris Brezillon mtd->writesize, md);
4070813621bSBoris Brezillon md->version[0] = buf[bbt_get_ver_offs(this, md)];
40893db446aSBoris Brezillon pr_info("Bad block table at page %d, version 0x%02X\n",
40993db446aSBoris Brezillon md->pages[0], md->version[0]);
41093db446aSBoris Brezillon }
41193db446aSBoris Brezillon }
41293db446aSBoris Brezillon
41393db446aSBoris Brezillon /* Scan a given block partially */
scan_block_fast(struct nand_chip * this,struct nand_bbt_descr * bd,loff_t offs,uint8_t * buf)4140813621bSBoris Brezillon static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
415f90da781SFrieder Schrempf loff_t offs, uint8_t *buf)
41693db446aSBoris Brezillon {
4170813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
418f90da781SFrieder Schrempf
419*745df179SMichał Kępień struct mtd_oob_ops ops = { };
420f90da781SFrieder Schrempf int ret, page_offset;
42193db446aSBoris Brezillon
42293db446aSBoris Brezillon ops.ooblen = mtd->oobsize;
42393db446aSBoris Brezillon ops.oobbuf = buf;
42493db446aSBoris Brezillon ops.ooboffs = 0;
42593db446aSBoris Brezillon ops.datbuf = NULL;
42693db446aSBoris Brezillon ops.mode = MTD_OPS_PLACE_OOB;
42793db446aSBoris Brezillon
428f90da781SFrieder Schrempf page_offset = nand_bbm_get_next_page(this, 0);
429f90da781SFrieder Schrempf
430f90da781SFrieder Schrempf while (page_offset >= 0) {
43193db446aSBoris Brezillon /*
43293db446aSBoris Brezillon * Read the full oob until read_oob is fixed to handle single
43393db446aSBoris Brezillon * byte reads for 16 bit buswidth.
43493db446aSBoris Brezillon */
435f90da781SFrieder Schrempf ret = mtd_read_oob(mtd, offs + (page_offset * mtd->writesize),
436f90da781SFrieder Schrempf &ops);
43793db446aSBoris Brezillon /* Ignore ECC errors when checking for BBM */
43893db446aSBoris Brezillon if (ret && !mtd_is_bitflip_or_eccerr(ret))
43993db446aSBoris Brezillon return ret;
44093db446aSBoris Brezillon
44193db446aSBoris Brezillon if (check_short_pattern(buf, bd))
44293db446aSBoris Brezillon return 1;
44393db446aSBoris Brezillon
444f90da781SFrieder Schrempf page_offset = nand_bbm_get_next_page(this, page_offset + 1);
44593db446aSBoris Brezillon }
446f90da781SFrieder Schrempf
44793db446aSBoris Brezillon return 0;
44893db446aSBoris Brezillon }
44993db446aSBoris Brezillon
4501a57b13eSStefan Riedmueller /* Check if a potential BBT block is marked as bad */
bbt_block_checkbad(struct nand_chip * this,struct nand_bbt_descr * td,loff_t offs,uint8_t * buf)4511a57b13eSStefan Riedmueller static int bbt_block_checkbad(struct nand_chip *this, struct nand_bbt_descr *td,
4521a57b13eSStefan Riedmueller loff_t offs, uint8_t *buf)
4531a57b13eSStefan Riedmueller {
4541a57b13eSStefan Riedmueller struct nand_bbt_descr *bd = this->badblock_pattern;
4551a57b13eSStefan Riedmueller
4561a57b13eSStefan Riedmueller /*
4571a57b13eSStefan Riedmueller * No need to check for a bad BBT block if the BBM area overlaps with
4581a57b13eSStefan Riedmueller * the bad block table marker area in OOB since writing a BBM here
4591a57b13eSStefan Riedmueller * invalidates the bad block table marker anyway.
4601a57b13eSStefan Riedmueller */
4611a57b13eSStefan Riedmueller if (!(td->options & NAND_BBT_NO_OOB) &&
4621a57b13eSStefan Riedmueller td->offs >= bd->offs && td->offs < bd->offs + bd->len)
4631a57b13eSStefan Riedmueller return 0;
4641a57b13eSStefan Riedmueller
4651a57b13eSStefan Riedmueller /*
4661a57b13eSStefan Riedmueller * There is no point in checking for a bad block marker if writing
4671a57b13eSStefan Riedmueller * such marker is not supported
4681a57b13eSStefan Riedmueller */
4691a57b13eSStefan Riedmueller if (this->bbt_options & NAND_BBT_NO_OOB_BBM ||
4701a57b13eSStefan Riedmueller this->options & NAND_NO_BBM_QUIRK)
4711a57b13eSStefan Riedmueller return 0;
4721a57b13eSStefan Riedmueller
4731a57b13eSStefan Riedmueller if (scan_block_fast(this, bd, offs, buf) > 0)
4741a57b13eSStefan Riedmueller return 1;
4751a57b13eSStefan Riedmueller
4761a57b13eSStefan Riedmueller return 0;
4771a57b13eSStefan Riedmueller }
4781a57b13eSStefan Riedmueller
47993db446aSBoris Brezillon /**
48093db446aSBoris Brezillon * create_bbt - [GENERIC] Create a bad block table by scanning the device
4810813621bSBoris Brezillon * @this: NAND chip object
48293db446aSBoris Brezillon * @buf: temporary buffer
48393db446aSBoris Brezillon * @bd: descriptor for the good/bad block search pattern
48493db446aSBoris Brezillon * @chip: create the table for a specific chip, -1 read all chips; applies only
48593db446aSBoris Brezillon * if NAND_BBT_PERCHIP option is set
48693db446aSBoris Brezillon *
48793db446aSBoris Brezillon * Create a bad block table by scanning the device for the given good/bad block
48893db446aSBoris Brezillon * identify pattern.
48993db446aSBoris Brezillon */
create_bbt(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * bd,int chip)4900813621bSBoris Brezillon static int create_bbt(struct nand_chip *this, uint8_t *buf,
49193db446aSBoris Brezillon struct nand_bbt_descr *bd, int chip)
49293db446aSBoris Brezillon {
4936c836d51SBoris Brezillon u64 targetsize = nanddev_target_size(&this->base);
4940813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
495f90da781SFrieder Schrempf int i, numblocks, startblock;
49693db446aSBoris Brezillon loff_t from;
49793db446aSBoris Brezillon
49893db446aSBoris Brezillon pr_info("Scanning device for bad blocks\n");
49993db446aSBoris Brezillon
50093db446aSBoris Brezillon if (chip == -1) {
50193db446aSBoris Brezillon numblocks = mtd->size >> this->bbt_erase_shift;
50293db446aSBoris Brezillon startblock = 0;
50393db446aSBoris Brezillon from = 0;
50493db446aSBoris Brezillon } else {
50532813e28SBoris Brezillon if (chip >= nanddev_ntargets(&this->base)) {
50693db446aSBoris Brezillon pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
50732813e28SBoris Brezillon chip + 1, nanddev_ntargets(&this->base));
50893db446aSBoris Brezillon return -EINVAL;
50993db446aSBoris Brezillon }
5106c836d51SBoris Brezillon numblocks = targetsize >> this->bbt_erase_shift;
51193db446aSBoris Brezillon startblock = chip * numblocks;
51293db446aSBoris Brezillon numblocks += startblock;
51393db446aSBoris Brezillon from = (loff_t)startblock << this->bbt_erase_shift;
51493db446aSBoris Brezillon }
51593db446aSBoris Brezillon
51693db446aSBoris Brezillon for (i = startblock; i < numblocks; i++) {
51793db446aSBoris Brezillon int ret;
51893db446aSBoris Brezillon
51993db446aSBoris Brezillon BUG_ON(bd->options & NAND_BBT_NO_OOB);
52093db446aSBoris Brezillon
521f90da781SFrieder Schrempf ret = scan_block_fast(this, bd, from, buf);
52293db446aSBoris Brezillon if (ret < 0)
52393db446aSBoris Brezillon return ret;
52493db446aSBoris Brezillon
52593db446aSBoris Brezillon if (ret) {
52693db446aSBoris Brezillon bbt_mark_entry(this, i, BBT_BLOCK_FACTORY_BAD);
52793db446aSBoris Brezillon pr_warn("Bad eraseblock %d at 0x%012llx\n",
52893db446aSBoris Brezillon i, (unsigned long long)from);
52993db446aSBoris Brezillon mtd->ecc_stats.badblocks++;
53093db446aSBoris Brezillon }
53193db446aSBoris Brezillon
53293db446aSBoris Brezillon from += (1 << this->bbt_erase_shift);
53393db446aSBoris Brezillon }
53493db446aSBoris Brezillon return 0;
53593db446aSBoris Brezillon }
53693db446aSBoris Brezillon
53793db446aSBoris Brezillon /**
53893db446aSBoris Brezillon * search_bbt - [GENERIC] scan the device for a specific bad block table
5390813621bSBoris Brezillon * @this: NAND chip object
54093db446aSBoris Brezillon * @buf: temporary buffer
54193db446aSBoris Brezillon * @td: descriptor for the bad block table
54293db446aSBoris Brezillon *
54393db446aSBoris Brezillon * Read the bad block table by searching for a given ident pattern. Search is
54493db446aSBoris Brezillon * preformed either from the beginning up or from the end of the device
54593db446aSBoris Brezillon * downwards. The search starts always at the start of a block. If the option
54693db446aSBoris Brezillon * NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains
54793db446aSBoris Brezillon * the bad block information of this chip. This is necessary to provide support
54893db446aSBoris Brezillon * for certain DOC devices.
54993db446aSBoris Brezillon *
55093db446aSBoris Brezillon * The bbt ident pattern resides in the oob area of the first page in a block.
55193db446aSBoris Brezillon */
search_bbt(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * td)5520813621bSBoris Brezillon static int search_bbt(struct nand_chip *this, uint8_t *buf,
5530813621bSBoris Brezillon struct nand_bbt_descr *td)
55493db446aSBoris Brezillon {
5556c836d51SBoris Brezillon u64 targetsize = nanddev_target_size(&this->base);
5560813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
55793db446aSBoris Brezillon int i, chips;
55893db446aSBoris Brezillon int startblock, block, dir;
55993db446aSBoris Brezillon int scanlen = mtd->writesize + mtd->oobsize;
56093db446aSBoris Brezillon int bbtblocks;
56193db446aSBoris Brezillon int blocktopage = this->bbt_erase_shift - this->page_shift;
56293db446aSBoris Brezillon
56393db446aSBoris Brezillon /* Search direction top -> down? */
56493db446aSBoris Brezillon if (td->options & NAND_BBT_LASTBLOCK) {
56593db446aSBoris Brezillon startblock = (mtd->size >> this->bbt_erase_shift) - 1;
56693db446aSBoris Brezillon dir = -1;
56793db446aSBoris Brezillon } else {
56893db446aSBoris Brezillon startblock = 0;
56993db446aSBoris Brezillon dir = 1;
57093db446aSBoris Brezillon }
57193db446aSBoris Brezillon
57293db446aSBoris Brezillon /* Do we have a bbt per chip? */
57393db446aSBoris Brezillon if (td->options & NAND_BBT_PERCHIP) {
57432813e28SBoris Brezillon chips = nanddev_ntargets(&this->base);
5756c836d51SBoris Brezillon bbtblocks = targetsize >> this->bbt_erase_shift;
57693db446aSBoris Brezillon startblock &= bbtblocks - 1;
57793db446aSBoris Brezillon } else {
57893db446aSBoris Brezillon chips = 1;
57993db446aSBoris Brezillon bbtblocks = mtd->size >> this->bbt_erase_shift;
58093db446aSBoris Brezillon }
58193db446aSBoris Brezillon
58293db446aSBoris Brezillon for (i = 0; i < chips; i++) {
58393db446aSBoris Brezillon /* Reset version information */
58493db446aSBoris Brezillon td->version[i] = 0;
58593db446aSBoris Brezillon td->pages[i] = -1;
58693db446aSBoris Brezillon /* Scan the maximum number of blocks */
58793db446aSBoris Brezillon for (block = 0; block < td->maxblocks; block++) {
58893db446aSBoris Brezillon
58993db446aSBoris Brezillon int actblock = startblock + dir * block;
59093db446aSBoris Brezillon loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
59193db446aSBoris Brezillon
5921a57b13eSStefan Riedmueller /* Check if block is marked bad */
5931a57b13eSStefan Riedmueller if (bbt_block_checkbad(this, td, offs, buf))
5941a57b13eSStefan Riedmueller continue;
5951a57b13eSStefan Riedmueller
59693db446aSBoris Brezillon /* Read first page */
5970813621bSBoris Brezillon scan_read(this, buf, offs, mtd->writesize, td);
59893db446aSBoris Brezillon if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
59993db446aSBoris Brezillon td->pages[i] = actblock << blocktopage;
60093db446aSBoris Brezillon if (td->options & NAND_BBT_VERSION) {
6010813621bSBoris Brezillon offs = bbt_get_ver_offs(this, td);
60293db446aSBoris Brezillon td->version[i] = buf[offs];
60393db446aSBoris Brezillon }
60493db446aSBoris Brezillon break;
60593db446aSBoris Brezillon }
60693db446aSBoris Brezillon }
6076c836d51SBoris Brezillon startblock += targetsize >> this->bbt_erase_shift;
60893db446aSBoris Brezillon }
60993db446aSBoris Brezillon /* Check, if we found a bbt for each requested chip */
61093db446aSBoris Brezillon for (i = 0; i < chips; i++) {
61193db446aSBoris Brezillon if (td->pages[i] == -1)
61293db446aSBoris Brezillon pr_warn("Bad block table not found for chip %d\n", i);
61393db446aSBoris Brezillon else
61493db446aSBoris Brezillon pr_info("Bad block table found at page %d, version 0x%02X\n",
61593db446aSBoris Brezillon td->pages[i], td->version[i]);
61693db446aSBoris Brezillon }
61793db446aSBoris Brezillon return 0;
61893db446aSBoris Brezillon }
61993db446aSBoris Brezillon
62093db446aSBoris Brezillon /**
62193db446aSBoris Brezillon * search_read_bbts - [GENERIC] scan the device for bad block table(s)
6220813621bSBoris Brezillon * @this: NAND chip object
62393db446aSBoris Brezillon * @buf: temporary buffer
62493db446aSBoris Brezillon * @td: descriptor for the bad block table
62593db446aSBoris Brezillon * @md: descriptor for the bad block table mirror
62693db446aSBoris Brezillon *
62793db446aSBoris Brezillon * Search and read the bad block table(s).
62893db446aSBoris Brezillon */
search_read_bbts(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * td,struct nand_bbt_descr * md)6290813621bSBoris Brezillon static void search_read_bbts(struct nand_chip *this, uint8_t *buf,
63093db446aSBoris Brezillon struct nand_bbt_descr *td,
63193db446aSBoris Brezillon struct nand_bbt_descr *md)
63293db446aSBoris Brezillon {
63393db446aSBoris Brezillon /* Search the primary table */
6340813621bSBoris Brezillon search_bbt(this, buf, td);
63593db446aSBoris Brezillon
63693db446aSBoris Brezillon /* Search the mirror table */
63793db446aSBoris Brezillon if (md)
6380813621bSBoris Brezillon search_bbt(this, buf, md);
63993db446aSBoris Brezillon }
64093db446aSBoris Brezillon
64193db446aSBoris Brezillon /**
64293db446aSBoris Brezillon * get_bbt_block - Get the first valid eraseblock suitable to store a BBT
64393db446aSBoris Brezillon * @this: the NAND device
64493db446aSBoris Brezillon * @td: the BBT description
64593db446aSBoris Brezillon * @md: the mirror BBT descriptor
64693db446aSBoris Brezillon * @chip: the CHIP selector
64793db446aSBoris Brezillon *
64893db446aSBoris Brezillon * This functions returns a positive block number pointing a valid eraseblock
64993db446aSBoris Brezillon * suitable to store a BBT (i.e. in the range reserved for BBT), or -ENOSPC if
65093db446aSBoris Brezillon * all blocks are already used of marked bad. If td->pages[chip] was already
65193db446aSBoris Brezillon * pointing to a valid block we re-use it, otherwise we search for the next
65293db446aSBoris Brezillon * valid one.
65393db446aSBoris Brezillon */
get_bbt_block(struct nand_chip * this,struct nand_bbt_descr * td,struct nand_bbt_descr * md,int chip)65493db446aSBoris Brezillon static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
65593db446aSBoris Brezillon struct nand_bbt_descr *md, int chip)
65693db446aSBoris Brezillon {
6576c836d51SBoris Brezillon u64 targetsize = nanddev_target_size(&this->base);
65893db446aSBoris Brezillon int startblock, dir, page, numblocks, i;
65993db446aSBoris Brezillon
66093db446aSBoris Brezillon /*
66193db446aSBoris Brezillon * There was already a version of the table, reuse the page. This
66293db446aSBoris Brezillon * applies for absolute placement too, as we have the page number in
66393db446aSBoris Brezillon * td->pages.
66493db446aSBoris Brezillon */
66593db446aSBoris Brezillon if (td->pages[chip] != -1)
66693db446aSBoris Brezillon return td->pages[chip] >>
66793db446aSBoris Brezillon (this->bbt_erase_shift - this->page_shift);
66893db446aSBoris Brezillon
6696c836d51SBoris Brezillon numblocks = (int)(targetsize >> this->bbt_erase_shift);
67093db446aSBoris Brezillon if (!(td->options & NAND_BBT_PERCHIP))
67132813e28SBoris Brezillon numblocks *= nanddev_ntargets(&this->base);
67293db446aSBoris Brezillon
67393db446aSBoris Brezillon /*
67493db446aSBoris Brezillon * Automatic placement of the bad block table. Search direction
67593db446aSBoris Brezillon * top -> down?
67693db446aSBoris Brezillon */
67793db446aSBoris Brezillon if (td->options & NAND_BBT_LASTBLOCK) {
67893db446aSBoris Brezillon startblock = numblocks * (chip + 1) - 1;
67993db446aSBoris Brezillon dir = -1;
68093db446aSBoris Brezillon } else {
68193db446aSBoris Brezillon startblock = chip * numblocks;
68293db446aSBoris Brezillon dir = 1;
68393db446aSBoris Brezillon }
68493db446aSBoris Brezillon
68593db446aSBoris Brezillon for (i = 0; i < td->maxblocks; i++) {
68693db446aSBoris Brezillon int block = startblock + dir * i;
68793db446aSBoris Brezillon
68893db446aSBoris Brezillon /* Check, if the block is bad */
68993db446aSBoris Brezillon switch (bbt_get_entry(this, block)) {
69093db446aSBoris Brezillon case BBT_BLOCK_WORN:
69193db446aSBoris Brezillon case BBT_BLOCK_FACTORY_BAD:
69293db446aSBoris Brezillon continue;
69393db446aSBoris Brezillon }
69493db446aSBoris Brezillon
69593db446aSBoris Brezillon page = block << (this->bbt_erase_shift - this->page_shift);
69693db446aSBoris Brezillon
69793db446aSBoris Brezillon /* Check, if the block is used by the mirror table */
69893db446aSBoris Brezillon if (!md || md->pages[chip] != page)
69993db446aSBoris Brezillon return block;
70093db446aSBoris Brezillon }
70193db446aSBoris Brezillon
70293db446aSBoris Brezillon return -ENOSPC;
70393db446aSBoris Brezillon }
70493db446aSBoris Brezillon
70593db446aSBoris Brezillon /**
70693db446aSBoris Brezillon * mark_bbt_block_bad - Mark one of the block reserved for BBT bad
70793db446aSBoris Brezillon * @this: the NAND device
70893db446aSBoris Brezillon * @td: the BBT description
70993db446aSBoris Brezillon * @chip: the CHIP selector
71093db446aSBoris Brezillon * @block: the BBT block to mark
71193db446aSBoris Brezillon *
71293db446aSBoris Brezillon * Blocks reserved for BBT can become bad. This functions is an helper to mark
71393db446aSBoris Brezillon * such blocks as bad. It takes care of updating the in-memory BBT, marking the
71493db446aSBoris Brezillon * block as bad using a bad block marker and invalidating the associated
71593db446aSBoris Brezillon * td->pages[] entry.
71693db446aSBoris Brezillon */
mark_bbt_block_bad(struct nand_chip * this,struct nand_bbt_descr * td,int chip,int block)71793db446aSBoris Brezillon static void mark_bbt_block_bad(struct nand_chip *this,
71893db446aSBoris Brezillon struct nand_bbt_descr *td,
71993db446aSBoris Brezillon int chip, int block)
72093db446aSBoris Brezillon {
72193db446aSBoris Brezillon loff_t to;
72293db446aSBoris Brezillon int res;
72393db446aSBoris Brezillon
72493db446aSBoris Brezillon bbt_mark_entry(this, block, BBT_BLOCK_WORN);
72593db446aSBoris Brezillon
72693db446aSBoris Brezillon to = (loff_t)block << this->bbt_erase_shift;
727cdc784c7SBoris Brezillon res = nand_markbad_bbm(this, to);
72893db446aSBoris Brezillon if (res)
72993db446aSBoris Brezillon pr_warn("nand_bbt: error %d while marking block %d bad\n",
73093db446aSBoris Brezillon res, block);
73193db446aSBoris Brezillon
73293db446aSBoris Brezillon td->pages[chip] = -1;
73393db446aSBoris Brezillon }
73493db446aSBoris Brezillon
73593db446aSBoris Brezillon /**
73693db446aSBoris Brezillon * write_bbt - [GENERIC] (Re)write the bad block table
7370813621bSBoris Brezillon * @this: NAND chip object
73893db446aSBoris Brezillon * @buf: temporary buffer
73993db446aSBoris Brezillon * @td: descriptor for the bad block table
74093db446aSBoris Brezillon * @md: descriptor for the bad block table mirror
74193db446aSBoris Brezillon * @chipsel: selector for a specific chip, -1 for all
74293db446aSBoris Brezillon *
74393db446aSBoris Brezillon * (Re)write the bad block table.
74493db446aSBoris Brezillon */
write_bbt(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * td,struct nand_bbt_descr * md,int chipsel)7450813621bSBoris Brezillon static int write_bbt(struct nand_chip *this, uint8_t *buf,
74693db446aSBoris Brezillon struct nand_bbt_descr *td, struct nand_bbt_descr *md,
74793db446aSBoris Brezillon int chipsel)
74893db446aSBoris Brezillon {
7496c836d51SBoris Brezillon u64 targetsize = nanddev_target_size(&this->base);
7500813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
75193db446aSBoris Brezillon struct erase_info einfo;
75293db446aSBoris Brezillon int i, res, chip = 0;
75393db446aSBoris Brezillon int bits, page, offs, numblocks, sft, sftmsk;
75493db446aSBoris Brezillon int nrchips, pageoffs, ooboffs;
75593db446aSBoris Brezillon uint8_t msk[4];
75693db446aSBoris Brezillon uint8_t rcode = td->reserved_block_code;
75793db446aSBoris Brezillon size_t retlen, len = 0;
75893db446aSBoris Brezillon loff_t to;
759*745df179SMichał Kępień struct mtd_oob_ops ops = { };
76093db446aSBoris Brezillon
76193db446aSBoris Brezillon ops.ooblen = mtd->oobsize;
76293db446aSBoris Brezillon ops.ooboffs = 0;
76393db446aSBoris Brezillon ops.datbuf = NULL;
76493db446aSBoris Brezillon ops.mode = MTD_OPS_PLACE_OOB;
76593db446aSBoris Brezillon
76693db446aSBoris Brezillon if (!rcode)
76793db446aSBoris Brezillon rcode = 0xff;
76893db446aSBoris Brezillon /* Write bad block table per chip rather than per device? */
76993db446aSBoris Brezillon if (td->options & NAND_BBT_PERCHIP) {
7706c836d51SBoris Brezillon numblocks = (int)(targetsize >> this->bbt_erase_shift);
77193db446aSBoris Brezillon /* Full device write or specific chip? */
77293db446aSBoris Brezillon if (chipsel == -1) {
77332813e28SBoris Brezillon nrchips = nanddev_ntargets(&this->base);
77493db446aSBoris Brezillon } else {
77593db446aSBoris Brezillon nrchips = chipsel + 1;
77693db446aSBoris Brezillon chip = chipsel;
77793db446aSBoris Brezillon }
77893db446aSBoris Brezillon } else {
77993db446aSBoris Brezillon numblocks = (int)(mtd->size >> this->bbt_erase_shift);
78093db446aSBoris Brezillon nrchips = 1;
78193db446aSBoris Brezillon }
78293db446aSBoris Brezillon
78393db446aSBoris Brezillon /* Loop through the chips */
78493db446aSBoris Brezillon while (chip < nrchips) {
78593db446aSBoris Brezillon int block;
78693db446aSBoris Brezillon
78793db446aSBoris Brezillon block = get_bbt_block(this, td, md, chip);
78893db446aSBoris Brezillon if (block < 0) {
78993db446aSBoris Brezillon pr_err("No space left to write bad block table\n");
79093db446aSBoris Brezillon res = block;
79193db446aSBoris Brezillon goto outerr;
79293db446aSBoris Brezillon }
79393db446aSBoris Brezillon
79493db446aSBoris Brezillon /*
79593db446aSBoris Brezillon * get_bbt_block() returns a block number, shift the value to
79693db446aSBoris Brezillon * get a page number.
79793db446aSBoris Brezillon */
79893db446aSBoris Brezillon page = block << (this->bbt_erase_shift - this->page_shift);
79993db446aSBoris Brezillon
80093db446aSBoris Brezillon /* Set up shift count and masks for the flash table */
80193db446aSBoris Brezillon bits = td->options & NAND_BBT_NRBITS_MSK;
80293db446aSBoris Brezillon msk[2] = ~rcode;
80393db446aSBoris Brezillon switch (bits) {
80493db446aSBoris Brezillon case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
80593db446aSBoris Brezillon msk[3] = 0x01;
80693db446aSBoris Brezillon break;
80793db446aSBoris Brezillon case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
80893db446aSBoris Brezillon msk[3] = 0x03;
80993db446aSBoris Brezillon break;
81093db446aSBoris Brezillon case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
81193db446aSBoris Brezillon msk[3] = 0x0f;
81293db446aSBoris Brezillon break;
81393db446aSBoris Brezillon case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
81493db446aSBoris Brezillon msk[3] = 0xff;
81593db446aSBoris Brezillon break;
81693db446aSBoris Brezillon default: return -EINVAL;
81793db446aSBoris Brezillon }
81893db446aSBoris Brezillon
81993db446aSBoris Brezillon to = ((loff_t)page) << this->page_shift;
82093db446aSBoris Brezillon
82193db446aSBoris Brezillon /* Must we save the block contents? */
82293db446aSBoris Brezillon if (td->options & NAND_BBT_SAVECONTENT) {
82393db446aSBoris Brezillon /* Make it block aligned */
82493db446aSBoris Brezillon to &= ~(((loff_t)1 << this->bbt_erase_shift) - 1);
82593db446aSBoris Brezillon len = 1 << this->bbt_erase_shift;
82693db446aSBoris Brezillon res = mtd_read(mtd, to, len, &retlen, buf);
82793db446aSBoris Brezillon if (res < 0) {
82893db446aSBoris Brezillon if (retlen != len) {
82993db446aSBoris Brezillon pr_info("nand_bbt: error reading block for writing the bad block table\n");
83093db446aSBoris Brezillon return res;
83193db446aSBoris Brezillon }
83293db446aSBoris Brezillon pr_warn("nand_bbt: ECC error while reading block for writing bad block table\n");
83393db446aSBoris Brezillon }
83493db446aSBoris Brezillon /* Read oob data */
83593db446aSBoris Brezillon ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
83693db446aSBoris Brezillon ops.oobbuf = &buf[len];
83793db446aSBoris Brezillon res = mtd_read_oob(mtd, to + mtd->writesize, &ops);
83893db446aSBoris Brezillon if (res < 0 || ops.oobretlen != ops.ooblen)
83993db446aSBoris Brezillon goto outerr;
84093db446aSBoris Brezillon
84193db446aSBoris Brezillon /* Calc the byte offset in the buffer */
84293db446aSBoris Brezillon pageoffs = page - (int)(to >> this->page_shift);
84393db446aSBoris Brezillon offs = pageoffs << this->page_shift;
84493db446aSBoris Brezillon /* Preset the bbt area with 0xff */
84593db446aSBoris Brezillon memset(&buf[offs], 0xff, (size_t)(numblocks >> sft));
84693db446aSBoris Brezillon ooboffs = len + (pageoffs * mtd->oobsize);
84793db446aSBoris Brezillon
84893db446aSBoris Brezillon } else if (td->options & NAND_BBT_NO_OOB) {
84993db446aSBoris Brezillon ooboffs = 0;
85093db446aSBoris Brezillon offs = td->len;
85193db446aSBoris Brezillon /* The version byte */
85293db446aSBoris Brezillon if (td->options & NAND_BBT_VERSION)
85393db446aSBoris Brezillon offs++;
85493db446aSBoris Brezillon /* Calc length */
85593db446aSBoris Brezillon len = (size_t)(numblocks >> sft);
85693db446aSBoris Brezillon len += offs;
85793db446aSBoris Brezillon /* Make it page aligned! */
85893db446aSBoris Brezillon len = ALIGN(len, mtd->writesize);
85993db446aSBoris Brezillon /* Preset the buffer with 0xff */
86093db446aSBoris Brezillon memset(buf, 0xff, len);
86193db446aSBoris Brezillon /* Pattern is located at the begin of first page */
86293db446aSBoris Brezillon memcpy(buf, td->pattern, td->len);
86393db446aSBoris Brezillon } else {
86493db446aSBoris Brezillon /* Calc length */
86593db446aSBoris Brezillon len = (size_t)(numblocks >> sft);
86693db446aSBoris Brezillon /* Make it page aligned! */
86793db446aSBoris Brezillon len = ALIGN(len, mtd->writesize);
86893db446aSBoris Brezillon /* Preset the buffer with 0xff */
86993db446aSBoris Brezillon memset(buf, 0xff, len +
87093db446aSBoris Brezillon (len >> this->page_shift)* mtd->oobsize);
87193db446aSBoris Brezillon offs = 0;
87293db446aSBoris Brezillon ooboffs = len;
87393db446aSBoris Brezillon /* Pattern is located in oob area of first page */
87493db446aSBoris Brezillon memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
87593db446aSBoris Brezillon }
87693db446aSBoris Brezillon
87793db446aSBoris Brezillon if (td->options & NAND_BBT_VERSION)
87893db446aSBoris Brezillon buf[ooboffs + td->veroffs] = td->version[chip];
87993db446aSBoris Brezillon
88093db446aSBoris Brezillon /* Walk through the memory table */
88193db446aSBoris Brezillon for (i = 0; i < numblocks; i++) {
88293db446aSBoris Brezillon uint8_t dat;
88393db446aSBoris Brezillon int sftcnt = (i << (3 - sft)) & sftmsk;
88493db446aSBoris Brezillon dat = bbt_get_entry(this, chip * numblocks + i);
88593db446aSBoris Brezillon /* Do not store the reserved bbt blocks! */
88693db446aSBoris Brezillon buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt);
88793db446aSBoris Brezillon }
88893db446aSBoris Brezillon
88993db446aSBoris Brezillon memset(&einfo, 0, sizeof(einfo));
89093db446aSBoris Brezillon einfo.addr = to;
89193db446aSBoris Brezillon einfo.len = 1 << this->bbt_erase_shift;
892e4cdf9cbSBoris Brezillon res = nand_erase_nand(this, &einfo, 1);
89393db446aSBoris Brezillon if (res < 0) {
89493db446aSBoris Brezillon pr_warn("nand_bbt: error while erasing BBT block %d\n",
89593db446aSBoris Brezillon res);
89693db446aSBoris Brezillon mark_bbt_block_bad(this, td, chip, block);
89793db446aSBoris Brezillon continue;
89893db446aSBoris Brezillon }
89993db446aSBoris Brezillon
9000813621bSBoris Brezillon res = scan_write_bbt(this, to, len, buf,
9010813621bSBoris Brezillon td->options & NAND_BBT_NO_OOB ?
9020813621bSBoris Brezillon NULL : &buf[len]);
90393db446aSBoris Brezillon if (res < 0) {
90493db446aSBoris Brezillon pr_warn("nand_bbt: error while writing BBT block %d\n",
90593db446aSBoris Brezillon res);
90693db446aSBoris Brezillon mark_bbt_block_bad(this, td, chip, block);
90793db446aSBoris Brezillon continue;
90893db446aSBoris Brezillon }
90993db446aSBoris Brezillon
91093db446aSBoris Brezillon pr_info("Bad block table written to 0x%012llx, version 0x%02X\n",
91193db446aSBoris Brezillon (unsigned long long)to, td->version[chip]);
91293db446aSBoris Brezillon
91393db446aSBoris Brezillon /* Mark it as used */
91493db446aSBoris Brezillon td->pages[chip++] = page;
91593db446aSBoris Brezillon }
91693db446aSBoris Brezillon return 0;
91793db446aSBoris Brezillon
91893db446aSBoris Brezillon outerr:
91993db446aSBoris Brezillon pr_warn("nand_bbt: error while writing bad block table %d\n", res);
92093db446aSBoris Brezillon return res;
92193db446aSBoris Brezillon }
92293db446aSBoris Brezillon
92393db446aSBoris Brezillon /**
92493db446aSBoris Brezillon * nand_memory_bbt - [GENERIC] create a memory based bad block table
9250813621bSBoris Brezillon * @this: NAND chip object
92693db446aSBoris Brezillon * @bd: descriptor for the good/bad block search pattern
92793db446aSBoris Brezillon *
92893db446aSBoris Brezillon * The function creates a memory based bbt by scanning the device for
92993db446aSBoris Brezillon * manufacturer / software marked good / bad blocks.
93093db446aSBoris Brezillon */
nand_memory_bbt(struct nand_chip * this,struct nand_bbt_descr * bd)9310813621bSBoris Brezillon static inline int nand_memory_bbt(struct nand_chip *this,
9320813621bSBoris Brezillon struct nand_bbt_descr *bd)
93393db446aSBoris Brezillon {
934eeab7174SBoris Brezillon u8 *pagebuf = nand_get_data_buf(this);
935eeab7174SBoris Brezillon
936eeab7174SBoris Brezillon return create_bbt(this, pagebuf, bd, -1);
93793db446aSBoris Brezillon }
93893db446aSBoris Brezillon
93993db446aSBoris Brezillon /**
94093db446aSBoris Brezillon * check_create - [GENERIC] create and write bbt(s) if necessary
9410813621bSBoris Brezillon * @this: the NAND device
94293db446aSBoris Brezillon * @buf: temporary buffer
94393db446aSBoris Brezillon * @bd: descriptor for the good/bad block search pattern
94493db446aSBoris Brezillon *
94593db446aSBoris Brezillon * The function checks the results of the previous call to read_bbt and creates
94693db446aSBoris Brezillon * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found
94793db446aSBoris Brezillon * for the chip/device. Update is necessary if one of the tables is missing or
94893db446aSBoris Brezillon * the version nr. of one table is less than the other.
94993db446aSBoris Brezillon */
check_create(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * bd)9500813621bSBoris Brezillon static int check_create(struct nand_chip *this, uint8_t *buf,
9510813621bSBoris Brezillon struct nand_bbt_descr *bd)
95293db446aSBoris Brezillon {
95393db446aSBoris Brezillon int i, chips, writeops, create, chipsel, res, res2;
95493db446aSBoris Brezillon struct nand_bbt_descr *td = this->bbt_td;
95593db446aSBoris Brezillon struct nand_bbt_descr *md = this->bbt_md;
95693db446aSBoris Brezillon struct nand_bbt_descr *rd, *rd2;
95793db446aSBoris Brezillon
95893db446aSBoris Brezillon /* Do we have a bbt per chip? */
95993db446aSBoris Brezillon if (td->options & NAND_BBT_PERCHIP)
96032813e28SBoris Brezillon chips = nanddev_ntargets(&this->base);
96193db446aSBoris Brezillon else
96293db446aSBoris Brezillon chips = 1;
96393db446aSBoris Brezillon
96493db446aSBoris Brezillon for (i = 0; i < chips; i++) {
96593db446aSBoris Brezillon writeops = 0;
96693db446aSBoris Brezillon create = 0;
96793db446aSBoris Brezillon rd = NULL;
96893db446aSBoris Brezillon rd2 = NULL;
96993db446aSBoris Brezillon res = res2 = 0;
97093db446aSBoris Brezillon /* Per chip or per device? */
97193db446aSBoris Brezillon chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
97293db446aSBoris Brezillon /* Mirrored table available? */
97393db446aSBoris Brezillon if (md) {
97493db446aSBoris Brezillon if (td->pages[i] == -1 && md->pages[i] == -1) {
97593db446aSBoris Brezillon create = 1;
97693db446aSBoris Brezillon writeops = 0x03;
97793db446aSBoris Brezillon } else if (td->pages[i] == -1) {
97893db446aSBoris Brezillon rd = md;
97993db446aSBoris Brezillon writeops = 0x01;
98093db446aSBoris Brezillon } else if (md->pages[i] == -1) {
98193db446aSBoris Brezillon rd = td;
98293db446aSBoris Brezillon writeops = 0x02;
98393db446aSBoris Brezillon } else if (td->version[i] == md->version[i]) {
98493db446aSBoris Brezillon rd = td;
98593db446aSBoris Brezillon if (!(td->options & NAND_BBT_VERSION))
98693db446aSBoris Brezillon rd2 = md;
98793db446aSBoris Brezillon } else if (((int8_t)(td->version[i] - md->version[i])) > 0) {
98893db446aSBoris Brezillon rd = td;
98993db446aSBoris Brezillon writeops = 0x02;
99093db446aSBoris Brezillon } else {
99193db446aSBoris Brezillon rd = md;
99293db446aSBoris Brezillon writeops = 0x01;
99393db446aSBoris Brezillon }
99493db446aSBoris Brezillon } else {
99593db446aSBoris Brezillon if (td->pages[i] == -1) {
99693db446aSBoris Brezillon create = 1;
99793db446aSBoris Brezillon writeops = 0x01;
99893db446aSBoris Brezillon } else {
99993db446aSBoris Brezillon rd = td;
100093db446aSBoris Brezillon }
100193db446aSBoris Brezillon }
100293db446aSBoris Brezillon
100393db446aSBoris Brezillon if (create) {
100493db446aSBoris Brezillon /* Create the bad block table by scanning the device? */
100593db446aSBoris Brezillon if (!(td->options & NAND_BBT_CREATE))
100693db446aSBoris Brezillon continue;
100793db446aSBoris Brezillon
100893db446aSBoris Brezillon /* Create the table in memory by scanning the chip(s) */
100993db446aSBoris Brezillon if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY))
10100813621bSBoris Brezillon create_bbt(this, buf, bd, chipsel);
101193db446aSBoris Brezillon
101293db446aSBoris Brezillon td->version[i] = 1;
101393db446aSBoris Brezillon if (md)
101493db446aSBoris Brezillon md->version[i] = 1;
101593db446aSBoris Brezillon }
101693db446aSBoris Brezillon
101793db446aSBoris Brezillon /* Read back first? */
101893db446aSBoris Brezillon if (rd) {
10190813621bSBoris Brezillon res = read_abs_bbt(this, buf, rd, chipsel);
102093db446aSBoris Brezillon if (mtd_is_eccerr(res)) {
102193db446aSBoris Brezillon /* Mark table as invalid */
102293db446aSBoris Brezillon rd->pages[i] = -1;
102393db446aSBoris Brezillon rd->version[i] = 0;
102493db446aSBoris Brezillon i--;
102593db446aSBoris Brezillon continue;
102693db446aSBoris Brezillon }
102793db446aSBoris Brezillon }
102893db446aSBoris Brezillon /* If they weren't versioned, read both */
102993db446aSBoris Brezillon if (rd2) {
10300813621bSBoris Brezillon res2 = read_abs_bbt(this, buf, rd2, chipsel);
103193db446aSBoris Brezillon if (mtd_is_eccerr(res2)) {
103293db446aSBoris Brezillon /* Mark table as invalid */
103393db446aSBoris Brezillon rd2->pages[i] = -1;
103493db446aSBoris Brezillon rd2->version[i] = 0;
103593db446aSBoris Brezillon i--;
103693db446aSBoris Brezillon continue;
103793db446aSBoris Brezillon }
103893db446aSBoris Brezillon }
103993db446aSBoris Brezillon
104093db446aSBoris Brezillon /* Scrub the flash table(s)? */
104193db446aSBoris Brezillon if (mtd_is_bitflip(res) || mtd_is_bitflip(res2))
104293db446aSBoris Brezillon writeops = 0x03;
104393db446aSBoris Brezillon
104493db446aSBoris Brezillon /* Update version numbers before writing */
104593db446aSBoris Brezillon if (md) {
104693db446aSBoris Brezillon td->version[i] = max(td->version[i], md->version[i]);
104793db446aSBoris Brezillon md->version[i] = td->version[i];
104893db446aSBoris Brezillon }
104993db446aSBoris Brezillon
105093db446aSBoris Brezillon /* Write the bad block table to the device? */
105193db446aSBoris Brezillon if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
10520813621bSBoris Brezillon res = write_bbt(this, buf, td, md, chipsel);
105393db446aSBoris Brezillon if (res < 0)
105493db446aSBoris Brezillon return res;
105593db446aSBoris Brezillon }
105693db446aSBoris Brezillon
105793db446aSBoris Brezillon /* Write the mirror bad block table to the device? */
105893db446aSBoris Brezillon if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
10590813621bSBoris Brezillon res = write_bbt(this, buf, md, td, chipsel);
106093db446aSBoris Brezillon if (res < 0)
106193db446aSBoris Brezillon return res;
106293db446aSBoris Brezillon }
106393db446aSBoris Brezillon }
106493db446aSBoris Brezillon return 0;
106593db446aSBoris Brezillon }
106693db446aSBoris Brezillon
106793db446aSBoris Brezillon /**
106899f3351aSBoris Brezillon * nand_update_bbt - update bad block table(s)
106999f3351aSBoris Brezillon * @this: the NAND device
107099f3351aSBoris Brezillon * @offs: the offset of the newly marked block
107199f3351aSBoris Brezillon *
107299f3351aSBoris Brezillon * The function updates the bad block table(s).
107399f3351aSBoris Brezillon */
nand_update_bbt(struct nand_chip * this,loff_t offs)107499f3351aSBoris Brezillon static int nand_update_bbt(struct nand_chip *this, loff_t offs)
107599f3351aSBoris Brezillon {
107699f3351aSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
107799f3351aSBoris Brezillon int len, res = 0;
107899f3351aSBoris Brezillon int chip, chipsel;
107999f3351aSBoris Brezillon uint8_t *buf;
108099f3351aSBoris Brezillon struct nand_bbt_descr *td = this->bbt_td;
108199f3351aSBoris Brezillon struct nand_bbt_descr *md = this->bbt_md;
108299f3351aSBoris Brezillon
108399f3351aSBoris Brezillon if (!this->bbt || !td)
108499f3351aSBoris Brezillon return -EINVAL;
108599f3351aSBoris Brezillon
108699f3351aSBoris Brezillon /* Allocate a temporary buffer for one eraseblock incl. oob */
108799f3351aSBoris Brezillon len = (1 << this->bbt_erase_shift);
108899f3351aSBoris Brezillon len += (len >> this->page_shift) * mtd->oobsize;
108999f3351aSBoris Brezillon buf = kmalloc(len, GFP_KERNEL);
109099f3351aSBoris Brezillon if (!buf)
109199f3351aSBoris Brezillon return -ENOMEM;
109299f3351aSBoris Brezillon
109399f3351aSBoris Brezillon /* Do we have a bbt per chip? */
109499f3351aSBoris Brezillon if (td->options & NAND_BBT_PERCHIP) {
109599f3351aSBoris Brezillon chip = (int)(offs >> this->chip_shift);
109699f3351aSBoris Brezillon chipsel = chip;
109799f3351aSBoris Brezillon } else {
109899f3351aSBoris Brezillon chip = 0;
109999f3351aSBoris Brezillon chipsel = -1;
110099f3351aSBoris Brezillon }
110199f3351aSBoris Brezillon
110299f3351aSBoris Brezillon td->version[chip]++;
110399f3351aSBoris Brezillon if (md)
110499f3351aSBoris Brezillon md->version[chip]++;
110599f3351aSBoris Brezillon
110699f3351aSBoris Brezillon /* Write the bad block table to the device? */
110799f3351aSBoris Brezillon if (td->options & NAND_BBT_WRITE) {
110899f3351aSBoris Brezillon res = write_bbt(this, buf, td, md, chipsel);
110999f3351aSBoris Brezillon if (res < 0)
111099f3351aSBoris Brezillon goto out;
111199f3351aSBoris Brezillon }
111299f3351aSBoris Brezillon /* Write the mirror bad block table to the device? */
111399f3351aSBoris Brezillon if (md && (md->options & NAND_BBT_WRITE)) {
111499f3351aSBoris Brezillon res = write_bbt(this, buf, md, td, chipsel);
111599f3351aSBoris Brezillon }
111699f3351aSBoris Brezillon
111799f3351aSBoris Brezillon out:
111899f3351aSBoris Brezillon kfree(buf);
111999f3351aSBoris Brezillon return res;
112099f3351aSBoris Brezillon }
112199f3351aSBoris Brezillon
112299f3351aSBoris Brezillon /**
11237998d898SMauro Carvalho Chehab * mark_bbt_region - [GENERIC] mark the bad block table regions
11240813621bSBoris Brezillon * @this: the NAND device
112593db446aSBoris Brezillon * @td: bad block table descriptor
112693db446aSBoris Brezillon *
112793db446aSBoris Brezillon * The bad block table regions are marked as "bad" to prevent accidental
112893db446aSBoris Brezillon * erasures / writes. The regions are identified by the mark 0x02.
112993db446aSBoris Brezillon */
mark_bbt_region(struct nand_chip * this,struct nand_bbt_descr * td)11300813621bSBoris Brezillon static void mark_bbt_region(struct nand_chip *this, struct nand_bbt_descr *td)
113193db446aSBoris Brezillon {
11326c836d51SBoris Brezillon u64 targetsize = nanddev_target_size(&this->base);
11330813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
113493db446aSBoris Brezillon int i, j, chips, block, nrblocks, update;
113593db446aSBoris Brezillon uint8_t oldval;
113693db446aSBoris Brezillon
113793db446aSBoris Brezillon /* Do we have a bbt per chip? */
113893db446aSBoris Brezillon if (td->options & NAND_BBT_PERCHIP) {
113932813e28SBoris Brezillon chips = nanddev_ntargets(&this->base);
11406c836d51SBoris Brezillon nrblocks = (int)(targetsize >> this->bbt_erase_shift);
114193db446aSBoris Brezillon } else {
114293db446aSBoris Brezillon chips = 1;
114393db446aSBoris Brezillon nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
114493db446aSBoris Brezillon }
114593db446aSBoris Brezillon
114693db446aSBoris Brezillon for (i = 0; i < chips; i++) {
114793db446aSBoris Brezillon if ((td->options & NAND_BBT_ABSPAGE) ||
114893db446aSBoris Brezillon !(td->options & NAND_BBT_WRITE)) {
114993db446aSBoris Brezillon if (td->pages[i] == -1)
115093db446aSBoris Brezillon continue;
115193db446aSBoris Brezillon block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
115293db446aSBoris Brezillon oldval = bbt_get_entry(this, block);
115393db446aSBoris Brezillon bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
115493db446aSBoris Brezillon if ((oldval != BBT_BLOCK_RESERVED) &&
115593db446aSBoris Brezillon td->reserved_block_code)
11560813621bSBoris Brezillon nand_update_bbt(this, (loff_t)block <<
115793db446aSBoris Brezillon this->bbt_erase_shift);
115893db446aSBoris Brezillon continue;
115993db446aSBoris Brezillon }
116093db446aSBoris Brezillon update = 0;
116193db446aSBoris Brezillon if (td->options & NAND_BBT_LASTBLOCK)
116293db446aSBoris Brezillon block = ((i + 1) * nrblocks) - td->maxblocks;
116393db446aSBoris Brezillon else
116493db446aSBoris Brezillon block = i * nrblocks;
116593db446aSBoris Brezillon for (j = 0; j < td->maxblocks; j++) {
116693db446aSBoris Brezillon oldval = bbt_get_entry(this, block);
116793db446aSBoris Brezillon bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
116893db446aSBoris Brezillon if (oldval != BBT_BLOCK_RESERVED)
116993db446aSBoris Brezillon update = 1;
117093db446aSBoris Brezillon block++;
117193db446aSBoris Brezillon }
117293db446aSBoris Brezillon /*
117393db446aSBoris Brezillon * If we want reserved blocks to be recorded to flash, and some
117493db446aSBoris Brezillon * new ones have been marked, then we need to update the stored
117593db446aSBoris Brezillon * bbts. This should only happen once.
117693db446aSBoris Brezillon */
117793db446aSBoris Brezillon if (update && td->reserved_block_code)
11780813621bSBoris Brezillon nand_update_bbt(this, (loff_t)(block - 1) <<
117993db446aSBoris Brezillon this->bbt_erase_shift);
118093db446aSBoris Brezillon }
118193db446aSBoris Brezillon }
118293db446aSBoris Brezillon
118393db446aSBoris Brezillon /**
118493db446aSBoris Brezillon * verify_bbt_descr - verify the bad block description
11850813621bSBoris Brezillon * @this: the NAND device
118693db446aSBoris Brezillon * @bd: the table to verify
118793db446aSBoris Brezillon *
118893db446aSBoris Brezillon * This functions performs a few sanity checks on the bad block description
118993db446aSBoris Brezillon * table.
119093db446aSBoris Brezillon */
verify_bbt_descr(struct nand_chip * this,struct nand_bbt_descr * bd)11910813621bSBoris Brezillon static void verify_bbt_descr(struct nand_chip *this, struct nand_bbt_descr *bd)
119293db446aSBoris Brezillon {
11936c836d51SBoris Brezillon u64 targetsize = nanddev_target_size(&this->base);
11940813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
119593db446aSBoris Brezillon u32 pattern_len;
119693db446aSBoris Brezillon u32 bits;
119793db446aSBoris Brezillon u32 table_size;
119893db446aSBoris Brezillon
119993db446aSBoris Brezillon if (!bd)
120093db446aSBoris Brezillon return;
120193db446aSBoris Brezillon
120293db446aSBoris Brezillon pattern_len = bd->len;
120393db446aSBoris Brezillon bits = bd->options & NAND_BBT_NRBITS_MSK;
120493db446aSBoris Brezillon
120593db446aSBoris Brezillon BUG_ON((this->bbt_options & NAND_BBT_NO_OOB) &&
120693db446aSBoris Brezillon !(this->bbt_options & NAND_BBT_USE_FLASH));
120793db446aSBoris Brezillon BUG_ON(!bits);
120893db446aSBoris Brezillon
120993db446aSBoris Brezillon if (bd->options & NAND_BBT_VERSION)
121093db446aSBoris Brezillon pattern_len++;
121193db446aSBoris Brezillon
121293db446aSBoris Brezillon if (bd->options & NAND_BBT_NO_OOB) {
121393db446aSBoris Brezillon BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH));
121493db446aSBoris Brezillon BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB));
121593db446aSBoris Brezillon BUG_ON(bd->offs);
121693db446aSBoris Brezillon if (bd->options & NAND_BBT_VERSION)
121793db446aSBoris Brezillon BUG_ON(bd->veroffs != bd->len);
121893db446aSBoris Brezillon BUG_ON(bd->options & NAND_BBT_SAVECONTENT);
121993db446aSBoris Brezillon }
122093db446aSBoris Brezillon
122193db446aSBoris Brezillon if (bd->options & NAND_BBT_PERCHIP)
12226c836d51SBoris Brezillon table_size = targetsize >> this->bbt_erase_shift;
122393db446aSBoris Brezillon else
122493db446aSBoris Brezillon table_size = mtd->size >> this->bbt_erase_shift;
122593db446aSBoris Brezillon table_size >>= 3;
122693db446aSBoris Brezillon table_size *= bits;
122793db446aSBoris Brezillon if (bd->options & NAND_BBT_NO_OOB)
122893db446aSBoris Brezillon table_size += pattern_len;
122993db446aSBoris Brezillon BUG_ON(table_size > (1 << this->bbt_erase_shift));
123093db446aSBoris Brezillon }
123193db446aSBoris Brezillon
123293db446aSBoris Brezillon /**
123393db446aSBoris Brezillon * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s)
12340813621bSBoris Brezillon * @this: the NAND device
123593db446aSBoris Brezillon * @bd: descriptor for the good/bad block search pattern
123693db446aSBoris Brezillon *
123793db446aSBoris Brezillon * The function checks, if a bad block table(s) is/are already available. If
123893db446aSBoris Brezillon * not it scans the device for manufacturer marked good / bad blocks and writes
123993db446aSBoris Brezillon * the bad block table(s) to the selected place.
124093db446aSBoris Brezillon *
124193db446aSBoris Brezillon * The bad block table memory is allocated here. It must be freed by calling
124293db446aSBoris Brezillon * the nand_free_bbt function.
124393db446aSBoris Brezillon */
nand_scan_bbt(struct nand_chip * this,struct nand_bbt_descr * bd)12440813621bSBoris Brezillon static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
124593db446aSBoris Brezillon {
12460813621bSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(this);
124793db446aSBoris Brezillon int len, res;
124893db446aSBoris Brezillon uint8_t *buf;
124993db446aSBoris Brezillon struct nand_bbt_descr *td = this->bbt_td;
125093db446aSBoris Brezillon struct nand_bbt_descr *md = this->bbt_md;
125193db446aSBoris Brezillon
125293db446aSBoris Brezillon len = (mtd->size >> (this->bbt_erase_shift + 2)) ? : 1;
125393db446aSBoris Brezillon /*
125493db446aSBoris Brezillon * Allocate memory (2bit per block) and clear the memory bad block
125593db446aSBoris Brezillon * table.
125693db446aSBoris Brezillon */
125793db446aSBoris Brezillon this->bbt = kzalloc(len, GFP_KERNEL);
125893db446aSBoris Brezillon if (!this->bbt)
125993db446aSBoris Brezillon return -ENOMEM;
126093db446aSBoris Brezillon
126193db446aSBoris Brezillon /*
1262735bf220SKieran Bingham * If no primary table descriptor is given, scan the device to build a
126393db446aSBoris Brezillon * memory based bad block table.
126493db446aSBoris Brezillon */
126593db446aSBoris Brezillon if (!td) {
12660813621bSBoris Brezillon if ((res = nand_memory_bbt(this, bd))) {
126793db446aSBoris Brezillon pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
126886aa04f4SWenwen Wang goto err_free_bbt;
126993db446aSBoris Brezillon }
127093db446aSBoris Brezillon return 0;
127193db446aSBoris Brezillon }
12720813621bSBoris Brezillon verify_bbt_descr(this, td);
12730813621bSBoris Brezillon verify_bbt_descr(this, md);
127493db446aSBoris Brezillon
127593db446aSBoris Brezillon /* Allocate a temporary buffer for one eraseblock incl. oob */
127693db446aSBoris Brezillon len = (1 << this->bbt_erase_shift);
127793db446aSBoris Brezillon len += (len >> this->page_shift) * mtd->oobsize;
127893db446aSBoris Brezillon buf = vmalloc(len);
127993db446aSBoris Brezillon if (!buf) {
128093db446aSBoris Brezillon res = -ENOMEM;
128186aa04f4SWenwen Wang goto err_free_bbt;
128293db446aSBoris Brezillon }
128393db446aSBoris Brezillon
128493db446aSBoris Brezillon /* Is the bbt at a given page? */
128593db446aSBoris Brezillon if (td->options & NAND_BBT_ABSPAGE) {
12860813621bSBoris Brezillon read_abs_bbts(this, buf, td, md);
128793db446aSBoris Brezillon } else {
128893db446aSBoris Brezillon /* Search the bad block table using a pattern in oob */
12890813621bSBoris Brezillon search_read_bbts(this, buf, td, md);
129093db446aSBoris Brezillon }
129193db446aSBoris Brezillon
12920813621bSBoris Brezillon res = check_create(this, buf, bd);
129393db446aSBoris Brezillon if (res)
129486aa04f4SWenwen Wang goto err_free_buf;
129593db446aSBoris Brezillon
129693db446aSBoris Brezillon /* Prevent the bbt regions from erasing / writing */
12970813621bSBoris Brezillon mark_bbt_region(this, td);
129893db446aSBoris Brezillon if (md)
12990813621bSBoris Brezillon mark_bbt_region(this, md);
130093db446aSBoris Brezillon
130193db446aSBoris Brezillon vfree(buf);
130293db446aSBoris Brezillon return 0;
130393db446aSBoris Brezillon
130486aa04f4SWenwen Wang err_free_buf:
130586aa04f4SWenwen Wang vfree(buf);
130686aa04f4SWenwen Wang err_free_bbt:
130793db446aSBoris Brezillon kfree(this->bbt);
130893db446aSBoris Brezillon this->bbt = NULL;
130993db446aSBoris Brezillon return res;
131093db446aSBoris Brezillon }
131193db446aSBoris Brezillon
131293db446aSBoris Brezillon /*
131393db446aSBoris Brezillon * Define some generic bad / good block scan pattern which are used
131493db446aSBoris Brezillon * while scanning a device for factory marked good / bad blocks.
131593db446aSBoris Brezillon */
131693db446aSBoris Brezillon static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
131793db446aSBoris Brezillon
131893db446aSBoris Brezillon /* Generic flash bbt descriptors */
131993db446aSBoris Brezillon static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
132093db446aSBoris Brezillon static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
132193db446aSBoris Brezillon
132293db446aSBoris Brezillon static struct nand_bbt_descr bbt_main_descr = {
132393db446aSBoris Brezillon .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
132493db446aSBoris Brezillon | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
132593db446aSBoris Brezillon .offs = 8,
132693db446aSBoris Brezillon .len = 4,
132793db446aSBoris Brezillon .veroffs = 12,
132893db446aSBoris Brezillon .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
132993db446aSBoris Brezillon .pattern = bbt_pattern
133093db446aSBoris Brezillon };
133193db446aSBoris Brezillon
133293db446aSBoris Brezillon static struct nand_bbt_descr bbt_mirror_descr = {
133393db446aSBoris Brezillon .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
133493db446aSBoris Brezillon | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
133593db446aSBoris Brezillon .offs = 8,
133693db446aSBoris Brezillon .len = 4,
133793db446aSBoris Brezillon .veroffs = 12,
133893db446aSBoris Brezillon .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
133993db446aSBoris Brezillon .pattern = mirror_pattern
134093db446aSBoris Brezillon };
134193db446aSBoris Brezillon
134293db446aSBoris Brezillon static struct nand_bbt_descr bbt_main_no_oob_descr = {
134393db446aSBoris Brezillon .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
134493db446aSBoris Brezillon | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
134593db446aSBoris Brezillon | NAND_BBT_NO_OOB,
134693db446aSBoris Brezillon .len = 4,
134793db446aSBoris Brezillon .veroffs = 4,
134893db446aSBoris Brezillon .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
134993db446aSBoris Brezillon .pattern = bbt_pattern
135093db446aSBoris Brezillon };
135193db446aSBoris Brezillon
135293db446aSBoris Brezillon static struct nand_bbt_descr bbt_mirror_no_oob_descr = {
135393db446aSBoris Brezillon .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
135493db446aSBoris Brezillon | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
135593db446aSBoris Brezillon | NAND_BBT_NO_OOB,
135693db446aSBoris Brezillon .len = 4,
135793db446aSBoris Brezillon .veroffs = 4,
135893db446aSBoris Brezillon .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
135993db446aSBoris Brezillon .pattern = mirror_pattern
136093db446aSBoris Brezillon };
136193db446aSBoris Brezillon
136293db446aSBoris Brezillon #define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)
136393db446aSBoris Brezillon /**
136493db446aSBoris Brezillon * nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure
136593db446aSBoris Brezillon * @this: NAND chip to create descriptor for
136693db446aSBoris Brezillon *
136793db446aSBoris Brezillon * This function allocates and initializes a nand_bbt_descr for BBM detection
136893db446aSBoris Brezillon * based on the properties of @this. The new descriptor is stored in
136993db446aSBoris Brezillon * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
137093db446aSBoris Brezillon * passed to this function.
137193db446aSBoris Brezillon */
nand_create_badblock_pattern(struct nand_chip * this)137293db446aSBoris Brezillon static int nand_create_badblock_pattern(struct nand_chip *this)
137393db446aSBoris Brezillon {
137493db446aSBoris Brezillon struct nand_bbt_descr *bd;
137593db446aSBoris Brezillon if (this->badblock_pattern) {
137693db446aSBoris Brezillon pr_warn("Bad block pattern already allocated; not replacing\n");
137793db446aSBoris Brezillon return -EINVAL;
137893db446aSBoris Brezillon }
137993db446aSBoris Brezillon bd = kzalloc(sizeof(*bd), GFP_KERNEL);
138093db446aSBoris Brezillon if (!bd)
138193db446aSBoris Brezillon return -ENOMEM;
138293db446aSBoris Brezillon bd->options = this->bbt_options & BADBLOCK_SCAN_MASK;
138393db446aSBoris Brezillon bd->offs = this->badblockpos;
138493db446aSBoris Brezillon bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
138593db446aSBoris Brezillon bd->pattern = scan_ff_pattern;
138693db446aSBoris Brezillon bd->options |= NAND_BBT_DYNAMICSTRUCT;
138793db446aSBoris Brezillon this->badblock_pattern = bd;
138893db446aSBoris Brezillon return 0;
138993db446aSBoris Brezillon }
139093db446aSBoris Brezillon
139193db446aSBoris Brezillon /**
139244b07b92SBoris Brezillon * nand_create_bbt - [NAND Interface] Select a default bad block table for the device
139344b07b92SBoris Brezillon * @this: NAND chip object
139493db446aSBoris Brezillon *
139593db446aSBoris Brezillon * This function selects the default bad block table support for the device and
139693db446aSBoris Brezillon * calls the nand_scan_bbt function.
139793db446aSBoris Brezillon */
nand_create_bbt(struct nand_chip * this)139844b07b92SBoris Brezillon int nand_create_bbt(struct nand_chip *this)
139993db446aSBoris Brezillon {
140093db446aSBoris Brezillon int ret;
140193db446aSBoris Brezillon
140293db446aSBoris Brezillon /* Is a flash based bad block table requested? */
140393db446aSBoris Brezillon if (this->bbt_options & NAND_BBT_USE_FLASH) {
140493db446aSBoris Brezillon /* Use the default pattern descriptors */
140593db446aSBoris Brezillon if (!this->bbt_td) {
140693db446aSBoris Brezillon if (this->bbt_options & NAND_BBT_NO_OOB) {
140793db446aSBoris Brezillon this->bbt_td = &bbt_main_no_oob_descr;
140893db446aSBoris Brezillon this->bbt_md = &bbt_mirror_no_oob_descr;
140993db446aSBoris Brezillon } else {
141093db446aSBoris Brezillon this->bbt_td = &bbt_main_descr;
141193db446aSBoris Brezillon this->bbt_md = &bbt_mirror_descr;
141293db446aSBoris Brezillon }
141393db446aSBoris Brezillon }
141493db446aSBoris Brezillon } else {
141593db446aSBoris Brezillon this->bbt_td = NULL;
141693db446aSBoris Brezillon this->bbt_md = NULL;
141793db446aSBoris Brezillon }
141893db446aSBoris Brezillon
141993db446aSBoris Brezillon if (!this->badblock_pattern) {
142093db446aSBoris Brezillon ret = nand_create_badblock_pattern(this);
142193db446aSBoris Brezillon if (ret)
142293db446aSBoris Brezillon return ret;
142393db446aSBoris Brezillon }
142493db446aSBoris Brezillon
14250813621bSBoris Brezillon return nand_scan_bbt(this, this->badblock_pattern);
142693db446aSBoris Brezillon }
142744b07b92SBoris Brezillon EXPORT_SYMBOL(nand_create_bbt);
142893db446aSBoris Brezillon
142993db446aSBoris Brezillon /**
143093db446aSBoris Brezillon * nand_isreserved_bbt - [NAND Interface] Check if a block is reserved
14315740d4c4SBoris Brezillon * @this: NAND chip object
143293db446aSBoris Brezillon * @offs: offset in the device
143393db446aSBoris Brezillon */
nand_isreserved_bbt(struct nand_chip * this,loff_t offs)14345740d4c4SBoris Brezillon int nand_isreserved_bbt(struct nand_chip *this, loff_t offs)
143593db446aSBoris Brezillon {
143693db446aSBoris Brezillon int block;
143793db446aSBoris Brezillon
143893db446aSBoris Brezillon block = (int)(offs >> this->bbt_erase_shift);
143993db446aSBoris Brezillon return bbt_get_entry(this, block) == BBT_BLOCK_RESERVED;
144093db446aSBoris Brezillon }
144193db446aSBoris Brezillon
144293db446aSBoris Brezillon /**
144393db446aSBoris Brezillon * nand_isbad_bbt - [NAND Interface] Check if a block is bad
14445740d4c4SBoris Brezillon * @this: NAND chip object
144593db446aSBoris Brezillon * @offs: offset in the device
144693db446aSBoris Brezillon * @allowbbt: allow access to bad block table region
144793db446aSBoris Brezillon */
nand_isbad_bbt(struct nand_chip * this,loff_t offs,int allowbbt)14485740d4c4SBoris Brezillon int nand_isbad_bbt(struct nand_chip *this, loff_t offs, int allowbbt)
144993db446aSBoris Brezillon {
145093db446aSBoris Brezillon int block, res;
145193db446aSBoris Brezillon
145293db446aSBoris Brezillon block = (int)(offs >> this->bbt_erase_shift);
145393db446aSBoris Brezillon res = bbt_get_entry(this, block);
145493db446aSBoris Brezillon
145593db446aSBoris Brezillon pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
145693db446aSBoris Brezillon (unsigned int)offs, block, res);
145793db446aSBoris Brezillon
1458ad5e35f5SMiquel Raynal if (mtd_check_expert_analysis_mode())
145967b967ddSMiquel Raynal return 0;
146067b967ddSMiquel Raynal
146193db446aSBoris Brezillon switch (res) {
146293db446aSBoris Brezillon case BBT_BLOCK_GOOD:
146393db446aSBoris Brezillon return 0;
146493db446aSBoris Brezillon case BBT_BLOCK_WORN:
146593db446aSBoris Brezillon return 1;
146693db446aSBoris Brezillon case BBT_BLOCK_RESERVED:
146793db446aSBoris Brezillon return allowbbt ? 0 : 1;
146893db446aSBoris Brezillon }
146993db446aSBoris Brezillon return 1;
147093db446aSBoris Brezillon }
147193db446aSBoris Brezillon
147293db446aSBoris Brezillon /**
147393db446aSBoris Brezillon * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT
14745740d4c4SBoris Brezillon * @this: NAND chip object
147593db446aSBoris Brezillon * @offs: offset of the bad block
147693db446aSBoris Brezillon */
nand_markbad_bbt(struct nand_chip * this,loff_t offs)14775740d4c4SBoris Brezillon int nand_markbad_bbt(struct nand_chip *this, loff_t offs)
147893db446aSBoris Brezillon {
147993db446aSBoris Brezillon int block, ret = 0;
148093db446aSBoris Brezillon
148193db446aSBoris Brezillon block = (int)(offs >> this->bbt_erase_shift);
148293db446aSBoris Brezillon
148393db446aSBoris Brezillon /* Mark bad block in memory */
148493db446aSBoris Brezillon bbt_mark_entry(this, block, BBT_BLOCK_WORN);
148593db446aSBoris Brezillon
148693db446aSBoris Brezillon /* Update flash-based bad block table */
148793db446aSBoris Brezillon if (this->bbt_options & NAND_BBT_USE_FLASH)
14880813621bSBoris Brezillon ret = nand_update_bbt(this, offs);
148993db446aSBoris Brezillon
149093db446aSBoris Brezillon return ret;
149193db446aSBoris Brezillon }
1492