xref: /linux/drivers/mtd/nand/raw/nand_bbt.c (revision 9367043f)
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 	}
58093db446aSBoris Brezillon 
58193db446aSBoris Brezillon 	for (i = 0; i < chips; i++) {
58293db446aSBoris Brezillon 		/* Reset version information */
58393db446aSBoris Brezillon 		td->version[i] = 0;
58493db446aSBoris Brezillon 		td->pages[i] = -1;
58593db446aSBoris Brezillon 		/* Scan the maximum number of blocks */
58693db446aSBoris Brezillon 		for (block = 0; block < td->maxblocks; block++) {
58793db446aSBoris Brezillon 
58893db446aSBoris Brezillon 			int actblock = startblock + dir * block;
58993db446aSBoris Brezillon 			loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
59093db446aSBoris Brezillon 
5911a57b13eSStefan Riedmueller 			/* Check if block is marked bad */
5921a57b13eSStefan Riedmueller 			if (bbt_block_checkbad(this, td, offs, buf))
5931a57b13eSStefan Riedmueller 				continue;
5941a57b13eSStefan Riedmueller 
59593db446aSBoris Brezillon 			/* Read first page */
5960813621bSBoris Brezillon 			scan_read(this, buf, offs, mtd->writesize, td);
59793db446aSBoris Brezillon 			if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
59893db446aSBoris Brezillon 				td->pages[i] = actblock << blocktopage;
59993db446aSBoris Brezillon 				if (td->options & NAND_BBT_VERSION) {
6000813621bSBoris Brezillon 					offs = bbt_get_ver_offs(this, td);
60193db446aSBoris Brezillon 					td->version[i] = buf[offs];
60293db446aSBoris Brezillon 				}
60393db446aSBoris Brezillon 				break;
60493db446aSBoris Brezillon 			}
60593db446aSBoris Brezillon 		}
6066c836d51SBoris Brezillon 		startblock += targetsize >> this->bbt_erase_shift;
60793db446aSBoris Brezillon 	}
60893db446aSBoris Brezillon 	/* Check, if we found a bbt for each requested chip */
60993db446aSBoris Brezillon 	for (i = 0; i < chips; i++) {
61093db446aSBoris Brezillon 		if (td->pages[i] == -1)
61193db446aSBoris Brezillon 			pr_warn("Bad block table not found for chip %d\n", i);
61293db446aSBoris Brezillon 		else
61393db446aSBoris Brezillon 			pr_info("Bad block table found at page %d, version 0x%02X\n",
61493db446aSBoris Brezillon 				td->pages[i], td->version[i]);
61593db446aSBoris Brezillon 	}
61693db446aSBoris Brezillon 	return 0;
61793db446aSBoris Brezillon }
61893db446aSBoris Brezillon 
61993db446aSBoris Brezillon /**
62093db446aSBoris Brezillon  * search_read_bbts - [GENERIC] scan the device for bad block table(s)
6210813621bSBoris Brezillon  * @this: NAND chip object
62293db446aSBoris Brezillon  * @buf: temporary buffer
62393db446aSBoris Brezillon  * @td: descriptor for the bad block table
62493db446aSBoris Brezillon  * @md: descriptor for the bad block table mirror
62593db446aSBoris Brezillon  *
62693db446aSBoris Brezillon  * Search and read the bad block table(s).
62793db446aSBoris Brezillon  */
search_read_bbts(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * td,struct nand_bbt_descr * md)6280813621bSBoris Brezillon static void search_read_bbts(struct nand_chip *this, uint8_t *buf,
62993db446aSBoris Brezillon 			     struct nand_bbt_descr *td,
63093db446aSBoris Brezillon 			     struct nand_bbt_descr *md)
63193db446aSBoris Brezillon {
63293db446aSBoris Brezillon 	/* Search the primary table */
6330813621bSBoris Brezillon 	search_bbt(this, buf, td);
63493db446aSBoris Brezillon 
63593db446aSBoris Brezillon 	/* Search the mirror table */
63693db446aSBoris Brezillon 	if (md)
6370813621bSBoris Brezillon 		search_bbt(this, buf, md);
63893db446aSBoris Brezillon }
63993db446aSBoris Brezillon 
64093db446aSBoris Brezillon /**
64193db446aSBoris Brezillon  * get_bbt_block - Get the first valid eraseblock suitable to store a BBT
64293db446aSBoris Brezillon  * @this: the NAND device
64393db446aSBoris Brezillon  * @td: the BBT description
64493db446aSBoris Brezillon  * @md: the mirror BBT descriptor
64593db446aSBoris Brezillon  * @chip: the CHIP selector
64693db446aSBoris Brezillon  *
64793db446aSBoris Brezillon  * This functions returns a positive block number pointing a valid eraseblock
64893db446aSBoris Brezillon  * suitable to store a BBT (i.e. in the range reserved for BBT), or -ENOSPC if
64993db446aSBoris Brezillon  * all blocks are already used of marked bad. If td->pages[chip] was already
65093db446aSBoris Brezillon  * pointing to a valid block we re-use it, otherwise we search for the next
65193db446aSBoris Brezillon  * valid one.
65293db446aSBoris Brezillon  */
get_bbt_block(struct nand_chip * this,struct nand_bbt_descr * td,struct nand_bbt_descr * md,int chip)65393db446aSBoris Brezillon static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
65493db446aSBoris Brezillon 			 struct nand_bbt_descr *md, int chip)
65593db446aSBoris Brezillon {
6566c836d51SBoris Brezillon 	u64 targetsize = nanddev_target_size(&this->base);
65793db446aSBoris Brezillon 	int startblock, dir, page, numblocks, i;
65893db446aSBoris Brezillon 
65993db446aSBoris Brezillon 	/*
66093db446aSBoris Brezillon 	 * There was already a version of the table, reuse the page. This
66193db446aSBoris Brezillon 	 * applies for absolute placement too, as we have the page number in
66293db446aSBoris Brezillon 	 * td->pages.
66393db446aSBoris Brezillon 	 */
66493db446aSBoris Brezillon 	if (td->pages[chip] != -1)
66593db446aSBoris Brezillon 		return td->pages[chip] >>
66693db446aSBoris Brezillon 				(this->bbt_erase_shift - this->page_shift);
66793db446aSBoris Brezillon 
6686c836d51SBoris Brezillon 	numblocks = (int)(targetsize >> this->bbt_erase_shift);
66993db446aSBoris Brezillon 	if (!(td->options & NAND_BBT_PERCHIP))
67032813e28SBoris Brezillon 		numblocks *= nanddev_ntargets(&this->base);
67193db446aSBoris Brezillon 
67293db446aSBoris Brezillon 	/*
67393db446aSBoris Brezillon 	 * Automatic placement of the bad block table. Search direction
67493db446aSBoris Brezillon 	 * top -> down?
67593db446aSBoris Brezillon 	 */
67693db446aSBoris Brezillon 	if (td->options & NAND_BBT_LASTBLOCK) {
67793db446aSBoris Brezillon 		startblock = numblocks * (chip + 1) - 1;
67893db446aSBoris Brezillon 		dir = -1;
67993db446aSBoris Brezillon 	} else {
68093db446aSBoris Brezillon 		startblock = chip * numblocks;
68193db446aSBoris Brezillon 		dir = 1;
68293db446aSBoris Brezillon 	}
68393db446aSBoris Brezillon 
68493db446aSBoris Brezillon 	for (i = 0; i < td->maxblocks; i++) {
68593db446aSBoris Brezillon 		int block = startblock + dir * i;
68693db446aSBoris Brezillon 
68793db446aSBoris Brezillon 		/* Check, if the block is bad */
68893db446aSBoris Brezillon 		switch (bbt_get_entry(this, block)) {
68993db446aSBoris Brezillon 		case BBT_BLOCK_WORN:
69093db446aSBoris Brezillon 		case BBT_BLOCK_FACTORY_BAD:
69193db446aSBoris Brezillon 			continue;
69293db446aSBoris Brezillon 		}
69393db446aSBoris Brezillon 
69493db446aSBoris Brezillon 		page = block << (this->bbt_erase_shift - this->page_shift);
69593db446aSBoris Brezillon 
69693db446aSBoris Brezillon 		/* Check, if the block is used by the mirror table */
69793db446aSBoris Brezillon 		if (!md || md->pages[chip] != page)
69893db446aSBoris Brezillon 			return block;
69993db446aSBoris Brezillon 	}
70093db446aSBoris Brezillon 
70193db446aSBoris Brezillon 	return -ENOSPC;
70293db446aSBoris Brezillon }
70393db446aSBoris Brezillon 
70493db446aSBoris Brezillon /**
70593db446aSBoris Brezillon  * mark_bbt_block_bad - Mark one of the block reserved for BBT bad
70693db446aSBoris Brezillon  * @this: the NAND device
70793db446aSBoris Brezillon  * @td: the BBT description
70893db446aSBoris Brezillon  * @chip: the CHIP selector
70993db446aSBoris Brezillon  * @block: the BBT block to mark
71093db446aSBoris Brezillon  *
71193db446aSBoris Brezillon  * Blocks reserved for BBT can become bad. This functions is an helper to mark
71293db446aSBoris Brezillon  * such blocks as bad. It takes care of updating the in-memory BBT, marking the
71393db446aSBoris Brezillon  * block as bad using a bad block marker and invalidating the associated
71493db446aSBoris Brezillon  * td->pages[] entry.
71593db446aSBoris Brezillon  */
mark_bbt_block_bad(struct nand_chip * this,struct nand_bbt_descr * td,int chip,int block)71693db446aSBoris Brezillon static void mark_bbt_block_bad(struct nand_chip *this,
71793db446aSBoris Brezillon 			       struct nand_bbt_descr *td,
71893db446aSBoris Brezillon 			       int chip, int block)
71993db446aSBoris Brezillon {
72093db446aSBoris Brezillon 	loff_t to;
72193db446aSBoris Brezillon 	int res;
72293db446aSBoris Brezillon 
72393db446aSBoris Brezillon 	bbt_mark_entry(this, block, BBT_BLOCK_WORN);
72493db446aSBoris Brezillon 
72593db446aSBoris Brezillon 	to = (loff_t)block << this->bbt_erase_shift;
726cdc784c7SBoris Brezillon 	res = nand_markbad_bbm(this, to);
72793db446aSBoris Brezillon 	if (res)
72893db446aSBoris Brezillon 		pr_warn("nand_bbt: error %d while marking block %d bad\n",
72993db446aSBoris Brezillon 			res, block);
73093db446aSBoris Brezillon 
73193db446aSBoris Brezillon 	td->pages[chip] = -1;
73293db446aSBoris Brezillon }
73393db446aSBoris Brezillon 
73493db446aSBoris Brezillon /**
73593db446aSBoris Brezillon  * write_bbt - [GENERIC] (Re)write the bad block table
7360813621bSBoris Brezillon  * @this: NAND chip object
73793db446aSBoris Brezillon  * @buf: temporary buffer
73893db446aSBoris Brezillon  * @td: descriptor for the bad block table
73993db446aSBoris Brezillon  * @md: descriptor for the bad block table mirror
74093db446aSBoris Brezillon  * @chipsel: selector for a specific chip, -1 for all
74193db446aSBoris Brezillon  *
74293db446aSBoris Brezillon  * (Re)write the bad block table.
74393db446aSBoris Brezillon  */
write_bbt(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * td,struct nand_bbt_descr * md,int chipsel)7440813621bSBoris Brezillon static int write_bbt(struct nand_chip *this, uint8_t *buf,
74593db446aSBoris Brezillon 		     struct nand_bbt_descr *td, struct nand_bbt_descr *md,
74693db446aSBoris Brezillon 		     int chipsel)
74793db446aSBoris Brezillon {
7486c836d51SBoris Brezillon 	u64 targetsize = nanddev_target_size(&this->base);
7490813621bSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(this);
75093db446aSBoris Brezillon 	struct erase_info einfo;
75193db446aSBoris Brezillon 	int i, res, chip = 0;
75293db446aSBoris Brezillon 	int bits, page, offs, numblocks, sft, sftmsk;
75393db446aSBoris Brezillon 	int nrchips, pageoffs, ooboffs;
75493db446aSBoris Brezillon 	uint8_t msk[4];
75593db446aSBoris Brezillon 	uint8_t rcode = td->reserved_block_code;
75693db446aSBoris Brezillon 	size_t retlen, len = 0;
75793db446aSBoris Brezillon 	loff_t to;
758*745df179SMichał Kępień 	struct mtd_oob_ops ops = { };
75993db446aSBoris Brezillon 
76093db446aSBoris Brezillon 	ops.ooblen = mtd->oobsize;
76193db446aSBoris Brezillon 	ops.ooboffs = 0;
76293db446aSBoris Brezillon 	ops.datbuf = NULL;
76393db446aSBoris Brezillon 	ops.mode = MTD_OPS_PLACE_OOB;
76493db446aSBoris Brezillon 
76593db446aSBoris Brezillon 	if (!rcode)
76693db446aSBoris Brezillon 		rcode = 0xff;
76793db446aSBoris Brezillon 	/* Write bad block table per chip rather than per device? */
76893db446aSBoris Brezillon 	if (td->options & NAND_BBT_PERCHIP) {
7696c836d51SBoris Brezillon 		numblocks = (int)(targetsize >> this->bbt_erase_shift);
77093db446aSBoris Brezillon 		/* Full device write or specific chip? */
77193db446aSBoris Brezillon 		if (chipsel == -1) {
77232813e28SBoris Brezillon 			nrchips = nanddev_ntargets(&this->base);
77393db446aSBoris Brezillon 		} else {
77493db446aSBoris Brezillon 			nrchips = chipsel + 1;
77593db446aSBoris Brezillon 			chip = chipsel;
77693db446aSBoris Brezillon 		}
77793db446aSBoris Brezillon 	} else {
77893db446aSBoris Brezillon 		numblocks = (int)(mtd->size >> this->bbt_erase_shift);
77993db446aSBoris Brezillon 		nrchips = 1;
78093db446aSBoris Brezillon 	}
78193db446aSBoris Brezillon 
78293db446aSBoris Brezillon 	/* Loop through the chips */
78393db446aSBoris Brezillon 	while (chip < nrchips) {
78493db446aSBoris Brezillon 		int block;
78593db446aSBoris Brezillon 
78693db446aSBoris Brezillon 		block = get_bbt_block(this, td, md, chip);
78793db446aSBoris Brezillon 		if (block < 0) {
78893db446aSBoris Brezillon 			pr_err("No space left to write bad block table\n");
78993db446aSBoris Brezillon 			res = block;
79093db446aSBoris Brezillon 			goto outerr;
79193db446aSBoris Brezillon 		}
79293db446aSBoris Brezillon 
79393db446aSBoris Brezillon 		/*
79493db446aSBoris Brezillon 		 * get_bbt_block() returns a block number, shift the value to
79593db446aSBoris Brezillon 		 * get a page number.
79693db446aSBoris Brezillon 		 */
79793db446aSBoris Brezillon 		page = block << (this->bbt_erase_shift - this->page_shift);
79893db446aSBoris Brezillon 
79993db446aSBoris Brezillon 		/* Set up shift count and masks for the flash table */
80093db446aSBoris Brezillon 		bits = td->options & NAND_BBT_NRBITS_MSK;
80193db446aSBoris Brezillon 		msk[2] = ~rcode;
80293db446aSBoris Brezillon 		switch (bits) {
80393db446aSBoris Brezillon 		case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
80493db446aSBoris Brezillon 			msk[3] = 0x01;
80593db446aSBoris Brezillon 			break;
80693db446aSBoris Brezillon 		case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
80793db446aSBoris Brezillon 			msk[3] = 0x03;
80893db446aSBoris Brezillon 			break;
80993db446aSBoris Brezillon 		case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
81093db446aSBoris Brezillon 			msk[3] = 0x0f;
81193db446aSBoris Brezillon 			break;
81293db446aSBoris Brezillon 		case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
81393db446aSBoris Brezillon 			msk[3] = 0xff;
81493db446aSBoris Brezillon 			break;
81593db446aSBoris Brezillon 		default: return -EINVAL;
81693db446aSBoris Brezillon 		}
81793db446aSBoris Brezillon 
81893db446aSBoris Brezillon 		to = ((loff_t)page) << this->page_shift;
81993db446aSBoris Brezillon 
82093db446aSBoris Brezillon 		/* Must we save the block contents? */
82193db446aSBoris Brezillon 		if (td->options & NAND_BBT_SAVECONTENT) {
82293db446aSBoris Brezillon 			/* Make it block aligned */
82393db446aSBoris Brezillon 			to &= ~(((loff_t)1 << this->bbt_erase_shift) - 1);
82493db446aSBoris Brezillon 			len = 1 << this->bbt_erase_shift;
82593db446aSBoris Brezillon 			res = mtd_read(mtd, to, len, &retlen, buf);
82693db446aSBoris Brezillon 			if (res < 0) {
82793db446aSBoris Brezillon 				if (retlen != len) {
82893db446aSBoris Brezillon 					pr_info("nand_bbt: error reading block for writing the bad block table\n");
82993db446aSBoris Brezillon 					return res;
83093db446aSBoris Brezillon 				}
83193db446aSBoris Brezillon 				pr_warn("nand_bbt: ECC error while reading block for writing bad block table\n");
83293db446aSBoris Brezillon 			}
83393db446aSBoris Brezillon 			/* Read oob data */
83493db446aSBoris Brezillon 			ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
83593db446aSBoris Brezillon 			ops.oobbuf = &buf[len];
83693db446aSBoris Brezillon 			res = mtd_read_oob(mtd, to + mtd->writesize, &ops);
83793db446aSBoris Brezillon 			if (res < 0 || ops.oobretlen != ops.ooblen)
83893db446aSBoris Brezillon 				goto outerr;
83993db446aSBoris Brezillon 
84093db446aSBoris Brezillon 			/* Calc the byte offset in the buffer */
84193db446aSBoris Brezillon 			pageoffs = page - (int)(to >> this->page_shift);
84293db446aSBoris Brezillon 			offs = pageoffs << this->page_shift;
84393db446aSBoris Brezillon 			/* Preset the bbt area with 0xff */
84493db446aSBoris Brezillon 			memset(&buf[offs], 0xff, (size_t)(numblocks >> sft));
84593db446aSBoris Brezillon 			ooboffs = len + (pageoffs * mtd->oobsize);
84693db446aSBoris Brezillon 
84793db446aSBoris Brezillon 		} else if (td->options & NAND_BBT_NO_OOB) {
84893db446aSBoris Brezillon 			ooboffs = 0;
84993db446aSBoris Brezillon 			offs = td->len;
85093db446aSBoris Brezillon 			/* The version byte */
85193db446aSBoris Brezillon 			if (td->options & NAND_BBT_VERSION)
85293db446aSBoris Brezillon 				offs++;
85393db446aSBoris Brezillon 			/* Calc length */
85493db446aSBoris Brezillon 			len = (size_t)(numblocks >> sft);
85593db446aSBoris Brezillon 			len += offs;
85693db446aSBoris Brezillon 			/* Make it page aligned! */
85793db446aSBoris Brezillon 			len = ALIGN(len, mtd->writesize);
85893db446aSBoris Brezillon 			/* Preset the buffer with 0xff */
85993db446aSBoris Brezillon 			memset(buf, 0xff, len);
86093db446aSBoris Brezillon 			/* Pattern is located at the begin of first page */
86193db446aSBoris Brezillon 			memcpy(buf, td->pattern, td->len);
86293db446aSBoris Brezillon 		} else {
86393db446aSBoris Brezillon 			/* Calc length */
86493db446aSBoris Brezillon 			len = (size_t)(numblocks >> sft);
86593db446aSBoris Brezillon 			/* Make it page aligned! */
86693db446aSBoris Brezillon 			len = ALIGN(len, mtd->writesize);
86793db446aSBoris Brezillon 			/* Preset the buffer with 0xff */
86893db446aSBoris Brezillon 			memset(buf, 0xff, len +
86993db446aSBoris Brezillon 			       (len >> this->page_shift)* mtd->oobsize);
87093db446aSBoris Brezillon 			offs = 0;
87193db446aSBoris Brezillon 			ooboffs = len;
87293db446aSBoris Brezillon 			/* Pattern is located in oob area of first page */
87393db446aSBoris Brezillon 			memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
87493db446aSBoris Brezillon 		}
87593db446aSBoris Brezillon 
87693db446aSBoris Brezillon 		if (td->options & NAND_BBT_VERSION)
87793db446aSBoris Brezillon 			buf[ooboffs + td->veroffs] = td->version[chip];
87893db446aSBoris Brezillon 
87993db446aSBoris Brezillon 		/* Walk through the memory table */
88093db446aSBoris Brezillon 		for (i = 0; i < numblocks; i++) {
88193db446aSBoris Brezillon 			uint8_t dat;
88293db446aSBoris Brezillon 			int sftcnt = (i << (3 - sft)) & sftmsk;
88393db446aSBoris Brezillon 			dat = bbt_get_entry(this, chip * numblocks + i);
88493db446aSBoris Brezillon 			/* Do not store the reserved bbt blocks! */
88593db446aSBoris Brezillon 			buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt);
88693db446aSBoris Brezillon 		}
88793db446aSBoris Brezillon 
88893db446aSBoris Brezillon 		memset(&einfo, 0, sizeof(einfo));
88993db446aSBoris Brezillon 		einfo.addr = to;
89093db446aSBoris Brezillon 		einfo.len = 1 << this->bbt_erase_shift;
891e4cdf9cbSBoris Brezillon 		res = nand_erase_nand(this, &einfo, 1);
89293db446aSBoris Brezillon 		if (res < 0) {
89393db446aSBoris Brezillon 			pr_warn("nand_bbt: error while erasing BBT block %d\n",
89493db446aSBoris Brezillon 				res);
89593db446aSBoris Brezillon 			mark_bbt_block_bad(this, td, chip, block);
89693db446aSBoris Brezillon 			continue;
89793db446aSBoris Brezillon 		}
89893db446aSBoris Brezillon 
8990813621bSBoris Brezillon 		res = scan_write_bbt(this, to, len, buf,
9000813621bSBoris Brezillon 				     td->options & NAND_BBT_NO_OOB ?
9010813621bSBoris Brezillon 				     NULL : &buf[len]);
90293db446aSBoris Brezillon 		if (res < 0) {
90393db446aSBoris Brezillon 			pr_warn("nand_bbt: error while writing BBT block %d\n",
90493db446aSBoris Brezillon 				res);
90593db446aSBoris Brezillon 			mark_bbt_block_bad(this, td, chip, block);
90693db446aSBoris Brezillon 			continue;
90793db446aSBoris Brezillon 		}
90893db446aSBoris Brezillon 
90993db446aSBoris Brezillon 		pr_info("Bad block table written to 0x%012llx, version 0x%02X\n",
91093db446aSBoris Brezillon 			 (unsigned long long)to, td->version[chip]);
91193db446aSBoris Brezillon 
91293db446aSBoris Brezillon 		/* Mark it as used */
91393db446aSBoris Brezillon 		td->pages[chip++] = page;
91493db446aSBoris Brezillon 	}
91593db446aSBoris Brezillon 	return 0;
91693db446aSBoris Brezillon 
91793db446aSBoris Brezillon  outerr:
91893db446aSBoris Brezillon 	pr_warn("nand_bbt: error while writing bad block table %d\n", res);
91993db446aSBoris Brezillon 	return res;
92093db446aSBoris Brezillon }
92193db446aSBoris Brezillon 
92293db446aSBoris Brezillon /**
92393db446aSBoris Brezillon  * nand_memory_bbt - [GENERIC] create a memory based bad block table
9240813621bSBoris Brezillon  * @this: NAND chip object
92593db446aSBoris Brezillon  * @bd: descriptor for the good/bad block search pattern
92693db446aSBoris Brezillon  *
92793db446aSBoris Brezillon  * The function creates a memory based bbt by scanning the device for
92893db446aSBoris Brezillon  * manufacturer / software marked good / bad blocks.
92993db446aSBoris Brezillon  */
nand_memory_bbt(struct nand_chip * this,struct nand_bbt_descr * bd)9300813621bSBoris Brezillon static inline int nand_memory_bbt(struct nand_chip *this,
9310813621bSBoris Brezillon 				  struct nand_bbt_descr *bd)
93293db446aSBoris Brezillon {
933eeab7174SBoris Brezillon 	u8 *pagebuf = nand_get_data_buf(this);
934eeab7174SBoris Brezillon 
935eeab7174SBoris Brezillon 	return create_bbt(this, pagebuf, bd, -1);
93693db446aSBoris Brezillon }
93793db446aSBoris Brezillon 
93893db446aSBoris Brezillon /**
93993db446aSBoris Brezillon  * check_create - [GENERIC] create and write bbt(s) if necessary
9400813621bSBoris Brezillon  * @this: the NAND device
94193db446aSBoris Brezillon  * @buf: temporary buffer
94293db446aSBoris Brezillon  * @bd: descriptor for the good/bad block search pattern
94393db446aSBoris Brezillon  *
94493db446aSBoris Brezillon  * The function checks the results of the previous call to read_bbt and creates
94593db446aSBoris Brezillon  * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found
94693db446aSBoris Brezillon  * for the chip/device. Update is necessary if one of the tables is missing or
94793db446aSBoris Brezillon  * the version nr. of one table is less than the other.
94893db446aSBoris Brezillon  */
check_create(struct nand_chip * this,uint8_t * buf,struct nand_bbt_descr * bd)9490813621bSBoris Brezillon static int check_create(struct nand_chip *this, uint8_t *buf,
9500813621bSBoris Brezillon 			struct nand_bbt_descr *bd)
95193db446aSBoris Brezillon {
95293db446aSBoris Brezillon 	int i, chips, writeops, create, chipsel, res, res2;
95393db446aSBoris Brezillon 	struct nand_bbt_descr *td = this->bbt_td;
95493db446aSBoris Brezillon 	struct nand_bbt_descr *md = this->bbt_md;
95593db446aSBoris Brezillon 	struct nand_bbt_descr *rd, *rd2;
95693db446aSBoris Brezillon 
95793db446aSBoris Brezillon 	/* Do we have a bbt per chip? */
95893db446aSBoris Brezillon 	if (td->options & NAND_BBT_PERCHIP)
95932813e28SBoris Brezillon 		chips = nanddev_ntargets(&this->base);
96093db446aSBoris Brezillon 	else
96193db446aSBoris Brezillon 		chips = 1;
96293db446aSBoris Brezillon 
96393db446aSBoris Brezillon 	for (i = 0; i < chips; i++) {
96493db446aSBoris Brezillon 		writeops = 0;
96593db446aSBoris Brezillon 		create = 0;
96693db446aSBoris Brezillon 		rd = NULL;
96793db446aSBoris Brezillon 		rd2 = NULL;
96893db446aSBoris Brezillon 		res = res2 = 0;
96993db446aSBoris Brezillon 		/* Per chip or per device? */
97093db446aSBoris Brezillon 		chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
97193db446aSBoris Brezillon 		/* Mirrored table available? */
97293db446aSBoris Brezillon 		if (md) {
97393db446aSBoris Brezillon 			if (td->pages[i] == -1 && md->pages[i] == -1) {
97493db446aSBoris Brezillon 				create = 1;
97593db446aSBoris Brezillon 				writeops = 0x03;
97693db446aSBoris Brezillon 			} else if (td->pages[i] == -1) {
97793db446aSBoris Brezillon 				rd = md;
97893db446aSBoris Brezillon 				writeops = 0x01;
97993db446aSBoris Brezillon 			} else if (md->pages[i] == -1) {
98093db446aSBoris Brezillon 				rd = td;
98193db446aSBoris Brezillon 				writeops = 0x02;
98293db446aSBoris Brezillon 			} else if (td->version[i] == md->version[i]) {
98393db446aSBoris Brezillon 				rd = td;
98493db446aSBoris Brezillon 				if (!(td->options & NAND_BBT_VERSION))
98593db446aSBoris Brezillon 					rd2 = md;
98693db446aSBoris Brezillon 			} else if (((int8_t)(td->version[i] - md->version[i])) > 0) {
98793db446aSBoris Brezillon 				rd = td;
98893db446aSBoris Brezillon 				writeops = 0x02;
98993db446aSBoris Brezillon 			} else {
99093db446aSBoris Brezillon 				rd = md;
99193db446aSBoris Brezillon 				writeops = 0x01;
99293db446aSBoris Brezillon 			}
99393db446aSBoris Brezillon 		} else {
99493db446aSBoris Brezillon 			if (td->pages[i] == -1) {
99593db446aSBoris Brezillon 				create = 1;
99693db446aSBoris Brezillon 				writeops = 0x01;
99793db446aSBoris Brezillon 			} else {
99893db446aSBoris Brezillon 				rd = td;
99993db446aSBoris Brezillon 			}
100093db446aSBoris Brezillon 		}
100193db446aSBoris Brezillon 
100293db446aSBoris Brezillon 		if (create) {
100393db446aSBoris Brezillon 			/* Create the bad block table by scanning the device? */
100493db446aSBoris Brezillon 			if (!(td->options & NAND_BBT_CREATE))
100593db446aSBoris Brezillon 				continue;
100693db446aSBoris Brezillon 
100793db446aSBoris Brezillon 			/* Create the table in memory by scanning the chip(s) */
100893db446aSBoris Brezillon 			if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY))
10090813621bSBoris Brezillon 				create_bbt(this, buf, bd, chipsel);
101093db446aSBoris Brezillon 
101193db446aSBoris Brezillon 			td->version[i] = 1;
101293db446aSBoris Brezillon 			if (md)
101393db446aSBoris Brezillon 				md->version[i] = 1;
101493db446aSBoris Brezillon 		}
101593db446aSBoris Brezillon 
101693db446aSBoris Brezillon 		/* Read back first? */
101793db446aSBoris Brezillon 		if (rd) {
10180813621bSBoris Brezillon 			res = read_abs_bbt(this, buf, rd, chipsel);
101993db446aSBoris Brezillon 			if (mtd_is_eccerr(res)) {
102093db446aSBoris Brezillon 				/* Mark table as invalid */
102193db446aSBoris Brezillon 				rd->pages[i] = -1;
102293db446aSBoris Brezillon 				rd->version[i] = 0;
102393db446aSBoris Brezillon 				i--;
102493db446aSBoris Brezillon 				continue;
102593db446aSBoris Brezillon 			}
102693db446aSBoris Brezillon 		}
102793db446aSBoris Brezillon 		/* If they weren't versioned, read both */
102893db446aSBoris Brezillon 		if (rd2) {
10290813621bSBoris Brezillon 			res2 = read_abs_bbt(this, buf, rd2, chipsel);
103093db446aSBoris Brezillon 			if (mtd_is_eccerr(res2)) {
103193db446aSBoris Brezillon 				/* Mark table as invalid */
103293db446aSBoris Brezillon 				rd2->pages[i] = -1;
103393db446aSBoris Brezillon 				rd2->version[i] = 0;
103493db446aSBoris Brezillon 				i--;
103593db446aSBoris Brezillon 				continue;
103693db446aSBoris Brezillon 			}
103793db446aSBoris Brezillon 		}
103893db446aSBoris Brezillon 
103993db446aSBoris Brezillon 		/* Scrub the flash table(s)? */
104093db446aSBoris Brezillon 		if (mtd_is_bitflip(res) || mtd_is_bitflip(res2))
104193db446aSBoris Brezillon 			writeops = 0x03;
104293db446aSBoris Brezillon 
104393db446aSBoris Brezillon 		/* Update version numbers before writing */
104493db446aSBoris Brezillon 		if (md) {
104593db446aSBoris Brezillon 			td->version[i] = max(td->version[i], md->version[i]);
104693db446aSBoris Brezillon 			md->version[i] = td->version[i];
104793db446aSBoris Brezillon 		}
104893db446aSBoris Brezillon 
104993db446aSBoris Brezillon 		/* Write the bad block table to the device? */
105093db446aSBoris Brezillon 		if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
10510813621bSBoris Brezillon 			res = write_bbt(this, buf, td, md, chipsel);
105293db446aSBoris Brezillon 			if (res < 0)
105393db446aSBoris Brezillon 				return res;
105493db446aSBoris Brezillon 		}
105593db446aSBoris Brezillon 
105693db446aSBoris Brezillon 		/* Write the mirror bad block table to the device? */
105793db446aSBoris Brezillon 		if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
10580813621bSBoris Brezillon 			res = write_bbt(this, buf, md, td, chipsel);
105993db446aSBoris Brezillon 			if (res < 0)
106093db446aSBoris Brezillon 				return res;
106193db446aSBoris Brezillon 		}
106293db446aSBoris Brezillon 	}
106393db446aSBoris Brezillon 	return 0;
106493db446aSBoris Brezillon }
106593db446aSBoris Brezillon 
106693db446aSBoris Brezillon /**
106799f3351aSBoris Brezillon  * nand_update_bbt - update bad block table(s)
106899f3351aSBoris Brezillon  * @this: the NAND device
106999f3351aSBoris Brezillon  * @offs: the offset of the newly marked block
107099f3351aSBoris Brezillon  *
107199f3351aSBoris Brezillon  * The function updates the bad block table(s).
107299f3351aSBoris Brezillon  */
nand_update_bbt(struct nand_chip * this,loff_t offs)107399f3351aSBoris Brezillon static int nand_update_bbt(struct nand_chip *this, loff_t offs)
107499f3351aSBoris Brezillon {
107599f3351aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(this);
107699f3351aSBoris Brezillon 	int len, res = 0;
107799f3351aSBoris Brezillon 	int chip, chipsel;
107899f3351aSBoris Brezillon 	uint8_t *buf;
107999f3351aSBoris Brezillon 	struct nand_bbt_descr *td = this->bbt_td;
108099f3351aSBoris Brezillon 	struct nand_bbt_descr *md = this->bbt_md;
108199f3351aSBoris Brezillon 
108299f3351aSBoris Brezillon 	if (!this->bbt || !td)
108399f3351aSBoris Brezillon 		return -EINVAL;
108499f3351aSBoris Brezillon 
108599f3351aSBoris Brezillon 	/* Allocate a temporary buffer for one eraseblock incl. oob */
108699f3351aSBoris Brezillon 	len = (1 << this->bbt_erase_shift);
108799f3351aSBoris Brezillon 	len += (len >> this->page_shift) * mtd->oobsize;
108899f3351aSBoris Brezillon 	buf = kmalloc(len, GFP_KERNEL);
108999f3351aSBoris Brezillon 	if (!buf)
109099f3351aSBoris Brezillon 		return -ENOMEM;
109199f3351aSBoris Brezillon 
109299f3351aSBoris Brezillon 	/* Do we have a bbt per chip? */
109399f3351aSBoris Brezillon 	if (td->options & NAND_BBT_PERCHIP) {
109499f3351aSBoris Brezillon 		chip = (int)(offs >> this->chip_shift);
109599f3351aSBoris Brezillon 		chipsel = chip;
109699f3351aSBoris Brezillon 	} else {
109799f3351aSBoris Brezillon 		chip = 0;
109899f3351aSBoris Brezillon 		chipsel = -1;
109999f3351aSBoris Brezillon 	}
110099f3351aSBoris Brezillon 
110199f3351aSBoris Brezillon 	td->version[chip]++;
110299f3351aSBoris Brezillon 	if (md)
110399f3351aSBoris Brezillon 		md->version[chip]++;
110499f3351aSBoris Brezillon 
110599f3351aSBoris Brezillon 	/* Write the bad block table to the device? */
110699f3351aSBoris Brezillon 	if (td->options & NAND_BBT_WRITE) {
110799f3351aSBoris Brezillon 		res = write_bbt(this, buf, td, md, chipsel);
110899f3351aSBoris Brezillon 		if (res < 0)
110999f3351aSBoris Brezillon 			goto out;
111099f3351aSBoris Brezillon 	}
111199f3351aSBoris Brezillon 	/* Write the mirror bad block table to the device? */
111299f3351aSBoris Brezillon 	if (md && (md->options & NAND_BBT_WRITE)) {
111399f3351aSBoris Brezillon 		res = write_bbt(this, buf, md, td, chipsel);
111499f3351aSBoris Brezillon 	}
111599f3351aSBoris Brezillon 
111699f3351aSBoris Brezillon  out:
111799f3351aSBoris Brezillon 	kfree(buf);
111899f3351aSBoris Brezillon 	return res;
111999f3351aSBoris Brezillon }
112099f3351aSBoris Brezillon 
112199f3351aSBoris Brezillon /**
11227998d898SMauro Carvalho Chehab  * mark_bbt_region - [GENERIC] mark the bad block table regions
11230813621bSBoris Brezillon  * @this: the NAND device
112493db446aSBoris Brezillon  * @td: bad block table descriptor
112593db446aSBoris Brezillon  *
112693db446aSBoris Brezillon  * The bad block table regions are marked as "bad" to prevent accidental
112793db446aSBoris Brezillon  * erasures / writes. The regions are identified by the mark 0x02.
112893db446aSBoris Brezillon  */
mark_bbt_region(struct nand_chip * this,struct nand_bbt_descr * td)11290813621bSBoris Brezillon static void mark_bbt_region(struct nand_chip *this, struct nand_bbt_descr *td)
113093db446aSBoris Brezillon {
11316c836d51SBoris Brezillon 	u64 targetsize = nanddev_target_size(&this->base);
11320813621bSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(this);
113393db446aSBoris Brezillon 	int i, j, chips, block, nrblocks, update;
113493db446aSBoris Brezillon 	uint8_t oldval;
113593db446aSBoris Brezillon 
113693db446aSBoris Brezillon 	/* Do we have a bbt per chip? */
113793db446aSBoris Brezillon 	if (td->options & NAND_BBT_PERCHIP) {
113832813e28SBoris Brezillon 		chips = nanddev_ntargets(&this->base);
11396c836d51SBoris Brezillon 		nrblocks = (int)(targetsize >> this->bbt_erase_shift);
114093db446aSBoris Brezillon 	} else {
114193db446aSBoris Brezillon 		chips = 1;
114293db446aSBoris Brezillon 		nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
114393db446aSBoris Brezillon 	}
114493db446aSBoris Brezillon 
114593db446aSBoris Brezillon 	for (i = 0; i < chips; i++) {
114693db446aSBoris Brezillon 		if ((td->options & NAND_BBT_ABSPAGE) ||
114793db446aSBoris Brezillon 		    !(td->options & NAND_BBT_WRITE)) {
114893db446aSBoris Brezillon 			if (td->pages[i] == -1)
114993db446aSBoris Brezillon 				continue;
115093db446aSBoris Brezillon 			block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
115193db446aSBoris Brezillon 			oldval = bbt_get_entry(this, block);
115293db446aSBoris Brezillon 			bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
115393db446aSBoris Brezillon 			if ((oldval != BBT_BLOCK_RESERVED) &&
115493db446aSBoris Brezillon 					td->reserved_block_code)
11550813621bSBoris Brezillon 				nand_update_bbt(this, (loff_t)block <<
115693db446aSBoris Brezillon 						this->bbt_erase_shift);
115793db446aSBoris Brezillon 			continue;
115893db446aSBoris Brezillon 		}
115993db446aSBoris Brezillon 		update = 0;
116093db446aSBoris Brezillon 		if (td->options & NAND_BBT_LASTBLOCK)
116193db446aSBoris Brezillon 			block = ((i + 1) * nrblocks) - td->maxblocks;
116293db446aSBoris Brezillon 		else
116393db446aSBoris Brezillon 			block = i * nrblocks;
116493db446aSBoris Brezillon 		for (j = 0; j < td->maxblocks; j++) {
116593db446aSBoris Brezillon 			oldval = bbt_get_entry(this, block);
116693db446aSBoris Brezillon 			bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
116793db446aSBoris Brezillon 			if (oldval != BBT_BLOCK_RESERVED)
116893db446aSBoris Brezillon 				update = 1;
116993db446aSBoris Brezillon 			block++;
117093db446aSBoris Brezillon 		}
117193db446aSBoris Brezillon 		/*
117293db446aSBoris Brezillon 		 * If we want reserved blocks to be recorded to flash, and some
117393db446aSBoris Brezillon 		 * new ones have been marked, then we need to update the stored
117493db446aSBoris Brezillon 		 * bbts.  This should only happen once.
117593db446aSBoris Brezillon 		 */
117693db446aSBoris Brezillon 		if (update && td->reserved_block_code)
11770813621bSBoris Brezillon 			nand_update_bbt(this, (loff_t)(block - 1) <<
117893db446aSBoris Brezillon 					this->bbt_erase_shift);
117993db446aSBoris Brezillon 	}
118093db446aSBoris Brezillon }
118193db446aSBoris Brezillon 
118293db446aSBoris Brezillon /**
118393db446aSBoris Brezillon  * verify_bbt_descr - verify the bad block description
11840813621bSBoris Brezillon  * @this: the NAND device
118593db446aSBoris Brezillon  * @bd: the table to verify
118693db446aSBoris Brezillon  *
118793db446aSBoris Brezillon  * This functions performs a few sanity checks on the bad block description
118893db446aSBoris Brezillon  * table.
118993db446aSBoris Brezillon  */
verify_bbt_descr(struct nand_chip * this,struct nand_bbt_descr * bd)11900813621bSBoris Brezillon static void verify_bbt_descr(struct nand_chip *this, struct nand_bbt_descr *bd)
119193db446aSBoris Brezillon {
11926c836d51SBoris Brezillon 	u64 targetsize = nanddev_target_size(&this->base);
11930813621bSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(this);
119493db446aSBoris Brezillon 	u32 pattern_len;
119593db446aSBoris Brezillon 	u32 bits;
119693db446aSBoris Brezillon 	u32 table_size;
119793db446aSBoris Brezillon 
119893db446aSBoris Brezillon 	if (!bd)
119993db446aSBoris Brezillon 		return;
120093db446aSBoris Brezillon 
120193db446aSBoris Brezillon 	pattern_len = bd->len;
120293db446aSBoris Brezillon 	bits = bd->options & NAND_BBT_NRBITS_MSK;
120393db446aSBoris Brezillon 
120493db446aSBoris Brezillon 	BUG_ON((this->bbt_options & NAND_BBT_NO_OOB) &&
120593db446aSBoris Brezillon 			!(this->bbt_options & NAND_BBT_USE_FLASH));
120693db446aSBoris Brezillon 	BUG_ON(!bits);
120793db446aSBoris Brezillon 
120893db446aSBoris Brezillon 	if (bd->options & NAND_BBT_VERSION)
120993db446aSBoris Brezillon 		pattern_len++;
121093db446aSBoris Brezillon 
121193db446aSBoris Brezillon 	if (bd->options & NAND_BBT_NO_OOB) {
121293db446aSBoris Brezillon 		BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH));
121393db446aSBoris Brezillon 		BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB));
121493db446aSBoris Brezillon 		BUG_ON(bd->offs);
121593db446aSBoris Brezillon 		if (bd->options & NAND_BBT_VERSION)
121693db446aSBoris Brezillon 			BUG_ON(bd->veroffs != bd->len);
121793db446aSBoris Brezillon 		BUG_ON(bd->options & NAND_BBT_SAVECONTENT);
121893db446aSBoris Brezillon 	}
121993db446aSBoris Brezillon 
122093db446aSBoris Brezillon 	if (bd->options & NAND_BBT_PERCHIP)
12216c836d51SBoris Brezillon 		table_size = targetsize >> this->bbt_erase_shift;
122293db446aSBoris Brezillon 	else
122393db446aSBoris Brezillon 		table_size = mtd->size >> this->bbt_erase_shift;
122493db446aSBoris Brezillon 	table_size >>= 3;
122593db446aSBoris Brezillon 	table_size *= bits;
122693db446aSBoris Brezillon 	if (bd->options & NAND_BBT_NO_OOB)
122793db446aSBoris Brezillon 		table_size += pattern_len;
122893db446aSBoris Brezillon 	BUG_ON(table_size > (1 << this->bbt_erase_shift));
122993db446aSBoris Brezillon }
123093db446aSBoris Brezillon 
123193db446aSBoris Brezillon /**
123293db446aSBoris Brezillon  * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s)
12330813621bSBoris Brezillon  * @this: the NAND device
123493db446aSBoris Brezillon  * @bd: descriptor for the good/bad block search pattern
123593db446aSBoris Brezillon  *
123693db446aSBoris Brezillon  * The function checks, if a bad block table(s) is/are already available. If
123793db446aSBoris Brezillon  * not it scans the device for manufacturer marked good / bad blocks and writes
123893db446aSBoris Brezillon  * the bad block table(s) to the selected place.
123993db446aSBoris Brezillon  *
124093db446aSBoris Brezillon  * The bad block table memory is allocated here. It must be freed by calling
124193db446aSBoris Brezillon  * the nand_free_bbt function.
124293db446aSBoris Brezillon  */
nand_scan_bbt(struct nand_chip * this,struct nand_bbt_descr * bd)12430813621bSBoris Brezillon static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
124493db446aSBoris Brezillon {
12450813621bSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(this);
124693db446aSBoris Brezillon 	int len, res;
124793db446aSBoris Brezillon 	uint8_t *buf;
124893db446aSBoris Brezillon 	struct nand_bbt_descr *td = this->bbt_td;
124993db446aSBoris Brezillon 	struct nand_bbt_descr *md = this->bbt_md;
125093db446aSBoris Brezillon 
125193db446aSBoris Brezillon 	len = (mtd->size >> (this->bbt_erase_shift + 2)) ? : 1;
125293db446aSBoris Brezillon 	/*
125393db446aSBoris Brezillon 	 * Allocate memory (2bit per block) and clear the memory bad block
125493db446aSBoris Brezillon 	 * table.
125593db446aSBoris Brezillon 	 */
125693db446aSBoris Brezillon 	this->bbt = kzalloc(len, GFP_KERNEL);
125793db446aSBoris Brezillon 	if (!this->bbt)
125893db446aSBoris Brezillon 		return -ENOMEM;
125993db446aSBoris Brezillon 
126093db446aSBoris Brezillon 	/*
1261735bf220SKieran Bingham 	 * If no primary table descriptor is given, scan the device to build a
126293db446aSBoris Brezillon 	 * memory based bad block table.
126393db446aSBoris Brezillon 	 */
126493db446aSBoris Brezillon 	if (!td) {
12650813621bSBoris Brezillon 		if ((res = nand_memory_bbt(this, bd))) {
126693db446aSBoris Brezillon 			pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
126786aa04f4SWenwen Wang 			goto err_free_bbt;
126893db446aSBoris Brezillon 		}
126993db446aSBoris Brezillon 		return 0;
127093db446aSBoris Brezillon 	}
12710813621bSBoris Brezillon 	verify_bbt_descr(this, td);
12720813621bSBoris Brezillon 	verify_bbt_descr(this, md);
127393db446aSBoris Brezillon 
127493db446aSBoris Brezillon 	/* Allocate a temporary buffer for one eraseblock incl. oob */
127593db446aSBoris Brezillon 	len = (1 << this->bbt_erase_shift);
127693db446aSBoris Brezillon 	len += (len >> this->page_shift) * mtd->oobsize;
127793db446aSBoris Brezillon 	buf = vmalloc(len);
127893db446aSBoris Brezillon 	if (!buf) {
127993db446aSBoris Brezillon 		res = -ENOMEM;
128086aa04f4SWenwen Wang 		goto err_free_bbt;
128193db446aSBoris Brezillon 	}
128293db446aSBoris Brezillon 
128393db446aSBoris Brezillon 	/* Is the bbt at a given page? */
128493db446aSBoris Brezillon 	if (td->options & NAND_BBT_ABSPAGE) {
12850813621bSBoris Brezillon 		read_abs_bbts(this, buf, td, md);
128693db446aSBoris Brezillon 	} else {
128793db446aSBoris Brezillon 		/* Search the bad block table using a pattern in oob */
12880813621bSBoris Brezillon 		search_read_bbts(this, buf, td, md);
128993db446aSBoris Brezillon 	}
129093db446aSBoris Brezillon 
12910813621bSBoris Brezillon 	res = check_create(this, buf, bd);
129293db446aSBoris Brezillon 	if (res)
129386aa04f4SWenwen Wang 		goto err_free_buf;
129493db446aSBoris Brezillon 
129593db446aSBoris Brezillon 	/* Prevent the bbt regions from erasing / writing */
12960813621bSBoris Brezillon 	mark_bbt_region(this, td);
129793db446aSBoris Brezillon 	if (md)
12980813621bSBoris Brezillon 		mark_bbt_region(this, md);
129993db446aSBoris Brezillon 
130093db446aSBoris Brezillon 	vfree(buf);
130193db446aSBoris Brezillon 	return 0;
130293db446aSBoris Brezillon 
130386aa04f4SWenwen Wang err_free_buf:
130486aa04f4SWenwen Wang 	vfree(buf);
130586aa04f4SWenwen Wang err_free_bbt:
130693db446aSBoris Brezillon 	kfree(this->bbt);
130793db446aSBoris Brezillon 	this->bbt = NULL;
130893db446aSBoris Brezillon 	return res;
130993db446aSBoris Brezillon }
131093db446aSBoris Brezillon 
131193db446aSBoris Brezillon /*
131293db446aSBoris Brezillon  * Define some generic bad / good block scan pattern which are used
131393db446aSBoris Brezillon  * while scanning a device for factory marked good / bad blocks.
131493db446aSBoris Brezillon  */
131593db446aSBoris Brezillon static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
131693db446aSBoris Brezillon 
131793db446aSBoris Brezillon /* Generic flash bbt descriptors */
131893db446aSBoris Brezillon static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
131993db446aSBoris Brezillon static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
132093db446aSBoris Brezillon 
132193db446aSBoris Brezillon static struct nand_bbt_descr bbt_main_descr = {
132293db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
132393db446aSBoris Brezillon 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
132493db446aSBoris Brezillon 	.offs =	8,
132593db446aSBoris Brezillon 	.len = 4,
132693db446aSBoris Brezillon 	.veroffs = 12,
132793db446aSBoris Brezillon 	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
132893db446aSBoris Brezillon 	.pattern = bbt_pattern
132993db446aSBoris Brezillon };
133093db446aSBoris Brezillon 
133193db446aSBoris Brezillon static struct nand_bbt_descr bbt_mirror_descr = {
133293db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
133393db446aSBoris Brezillon 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
133493db446aSBoris Brezillon 	.offs =	8,
133593db446aSBoris Brezillon 	.len = 4,
133693db446aSBoris Brezillon 	.veroffs = 12,
133793db446aSBoris Brezillon 	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
133893db446aSBoris Brezillon 	.pattern = mirror_pattern
133993db446aSBoris Brezillon };
134093db446aSBoris Brezillon 
134193db446aSBoris Brezillon static struct nand_bbt_descr bbt_main_no_oob_descr = {
134293db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
134393db446aSBoris Brezillon 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
134493db446aSBoris Brezillon 		| NAND_BBT_NO_OOB,
134593db446aSBoris Brezillon 	.len = 4,
134693db446aSBoris Brezillon 	.veroffs = 4,
134793db446aSBoris Brezillon 	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
134893db446aSBoris Brezillon 	.pattern = bbt_pattern
134993db446aSBoris Brezillon };
135093db446aSBoris Brezillon 
135193db446aSBoris Brezillon static struct nand_bbt_descr bbt_mirror_no_oob_descr = {
135293db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
135393db446aSBoris Brezillon 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
135493db446aSBoris Brezillon 		| NAND_BBT_NO_OOB,
135593db446aSBoris Brezillon 	.len = 4,
135693db446aSBoris Brezillon 	.veroffs = 4,
135793db446aSBoris Brezillon 	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
135893db446aSBoris Brezillon 	.pattern = mirror_pattern
135993db446aSBoris Brezillon };
136093db446aSBoris Brezillon 
136193db446aSBoris Brezillon #define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)
136293db446aSBoris Brezillon /**
136393db446aSBoris Brezillon  * nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure
136493db446aSBoris Brezillon  * @this: NAND chip to create descriptor for
136593db446aSBoris Brezillon  *
136693db446aSBoris Brezillon  * This function allocates and initializes a nand_bbt_descr for BBM detection
136793db446aSBoris Brezillon  * based on the properties of @this. The new descriptor is stored in
136893db446aSBoris Brezillon  * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
136993db446aSBoris Brezillon  * passed to this function.
137093db446aSBoris Brezillon  */
nand_create_badblock_pattern(struct nand_chip * this)137193db446aSBoris Brezillon static int nand_create_badblock_pattern(struct nand_chip *this)
137293db446aSBoris Brezillon {
137393db446aSBoris Brezillon 	struct nand_bbt_descr *bd;
137493db446aSBoris Brezillon 	if (this->badblock_pattern) {
137593db446aSBoris Brezillon 		pr_warn("Bad block pattern already allocated; not replacing\n");
137693db446aSBoris Brezillon 		return -EINVAL;
137793db446aSBoris Brezillon 	}
137893db446aSBoris Brezillon 	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
137993db446aSBoris Brezillon 	if (!bd)
138093db446aSBoris Brezillon 		return -ENOMEM;
138193db446aSBoris Brezillon 	bd->options = this->bbt_options & BADBLOCK_SCAN_MASK;
138293db446aSBoris Brezillon 	bd->offs = this->badblockpos;
138393db446aSBoris Brezillon 	bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
138493db446aSBoris Brezillon 	bd->pattern = scan_ff_pattern;
138593db446aSBoris Brezillon 	bd->options |= NAND_BBT_DYNAMICSTRUCT;
138693db446aSBoris Brezillon 	this->badblock_pattern = bd;
138793db446aSBoris Brezillon 	return 0;
138893db446aSBoris Brezillon }
138993db446aSBoris Brezillon 
139093db446aSBoris Brezillon /**
139144b07b92SBoris Brezillon  * nand_create_bbt - [NAND Interface] Select a default bad block table for the device
139244b07b92SBoris Brezillon  * @this: NAND chip object
139393db446aSBoris Brezillon  *
139493db446aSBoris Brezillon  * This function selects the default bad block table support for the device and
139593db446aSBoris Brezillon  * calls the nand_scan_bbt function.
139693db446aSBoris Brezillon  */
nand_create_bbt(struct nand_chip * this)139744b07b92SBoris Brezillon int nand_create_bbt(struct nand_chip *this)
139893db446aSBoris Brezillon {
139993db446aSBoris Brezillon 	int ret;
140093db446aSBoris Brezillon 
140193db446aSBoris Brezillon 	/* Is a flash based bad block table requested? */
140293db446aSBoris Brezillon 	if (this->bbt_options & NAND_BBT_USE_FLASH) {
140393db446aSBoris Brezillon 		/* Use the default pattern descriptors */
140493db446aSBoris Brezillon 		if (!this->bbt_td) {
140593db446aSBoris Brezillon 			if (this->bbt_options & NAND_BBT_NO_OOB) {
140693db446aSBoris Brezillon 				this->bbt_td = &bbt_main_no_oob_descr;
140793db446aSBoris Brezillon 				this->bbt_md = &bbt_mirror_no_oob_descr;
140893db446aSBoris Brezillon 			} else {
140993db446aSBoris Brezillon 				this->bbt_td = &bbt_main_descr;
141093db446aSBoris Brezillon 				this->bbt_md = &bbt_mirror_descr;
141193db446aSBoris Brezillon 			}
141293db446aSBoris Brezillon 		}
141393db446aSBoris Brezillon 	} else {
141493db446aSBoris Brezillon 		this->bbt_td = NULL;
141593db446aSBoris Brezillon 		this->bbt_md = NULL;
141693db446aSBoris Brezillon 	}
141793db446aSBoris Brezillon 
141893db446aSBoris Brezillon 	if (!this->badblock_pattern) {
141993db446aSBoris Brezillon 		ret = nand_create_badblock_pattern(this);
142093db446aSBoris Brezillon 		if (ret)
142193db446aSBoris Brezillon 			return ret;
142293db446aSBoris Brezillon 	}
142393db446aSBoris Brezillon 
14240813621bSBoris Brezillon 	return nand_scan_bbt(this, this->badblock_pattern);
142593db446aSBoris Brezillon }
142644b07b92SBoris Brezillon EXPORT_SYMBOL(nand_create_bbt);
142793db446aSBoris Brezillon 
142893db446aSBoris Brezillon /**
142993db446aSBoris Brezillon  * nand_isreserved_bbt - [NAND Interface] Check if a block is reserved
14305740d4c4SBoris Brezillon  * @this: NAND chip object
143193db446aSBoris Brezillon  * @offs: offset in the device
143293db446aSBoris Brezillon  */
nand_isreserved_bbt(struct nand_chip * this,loff_t offs)14335740d4c4SBoris Brezillon int nand_isreserved_bbt(struct nand_chip *this, loff_t offs)
143493db446aSBoris Brezillon {
143593db446aSBoris Brezillon 	int block;
143693db446aSBoris Brezillon 
143793db446aSBoris Brezillon 	block = (int)(offs >> this->bbt_erase_shift);
143893db446aSBoris Brezillon 	return bbt_get_entry(this, block) == BBT_BLOCK_RESERVED;
143993db446aSBoris Brezillon }
144093db446aSBoris Brezillon 
144193db446aSBoris Brezillon /**
144293db446aSBoris Brezillon  * nand_isbad_bbt - [NAND Interface] Check if a block is bad
14435740d4c4SBoris Brezillon  * @this: NAND chip object
144493db446aSBoris Brezillon  * @offs: offset in the device
144593db446aSBoris Brezillon  * @allowbbt: allow access to bad block table region
144693db446aSBoris Brezillon  */
nand_isbad_bbt(struct nand_chip * this,loff_t offs,int allowbbt)14475740d4c4SBoris Brezillon int nand_isbad_bbt(struct nand_chip *this, loff_t offs, int allowbbt)
144893db446aSBoris Brezillon {
144993db446aSBoris Brezillon 	int block, res;
145093db446aSBoris Brezillon 
145193db446aSBoris Brezillon 	block = (int)(offs >> this->bbt_erase_shift);
145293db446aSBoris Brezillon 	res = bbt_get_entry(this, block);
145393db446aSBoris Brezillon 
145493db446aSBoris Brezillon 	pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
145593db446aSBoris Brezillon 		 (unsigned int)offs, block, res);
145693db446aSBoris Brezillon 
1457ad5e35f5SMiquel Raynal 	if (mtd_check_expert_analysis_mode())
145867b967ddSMiquel Raynal 		return 0;
145967b967ddSMiquel Raynal 
146093db446aSBoris Brezillon 	switch (res) {
146193db446aSBoris Brezillon 	case BBT_BLOCK_GOOD:
146293db446aSBoris Brezillon 		return 0;
146393db446aSBoris Brezillon 	case BBT_BLOCK_WORN:
146493db446aSBoris Brezillon 		return 1;
146593db446aSBoris Brezillon 	case BBT_BLOCK_RESERVED:
146693db446aSBoris Brezillon 		return allowbbt ? 0 : 1;
146793db446aSBoris Brezillon 	}
146893db446aSBoris Brezillon 	return 1;
146993db446aSBoris Brezillon }
147093db446aSBoris Brezillon 
147193db446aSBoris Brezillon /**
147293db446aSBoris Brezillon  * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT
14735740d4c4SBoris Brezillon  * @this: NAND chip object
147493db446aSBoris Brezillon  * @offs: offset of the bad block
147593db446aSBoris Brezillon  */
nand_markbad_bbt(struct nand_chip * this,loff_t offs)14765740d4c4SBoris Brezillon int nand_markbad_bbt(struct nand_chip *this, loff_t offs)
147793db446aSBoris Brezillon {
147893db446aSBoris Brezillon 	int block, ret = 0;
147993db446aSBoris Brezillon 
148093db446aSBoris Brezillon 	block = (int)(offs >> this->bbt_erase_shift);
148193db446aSBoris Brezillon 
148293db446aSBoris Brezillon 	/* Mark bad block in memory */
148393db446aSBoris Brezillon 	bbt_mark_entry(this, block, BBT_BLOCK_WORN);
148493db446aSBoris Brezillon 
148593db446aSBoris Brezillon 	/* Update flash-based bad block table */
148693db446aSBoris Brezillon 	if (this->bbt_options & NAND_BBT_USE_FLASH)
14870813621bSBoris Brezillon 		ret = nand_update_bbt(this, offs);
148893db446aSBoris Brezillon 
148993db446aSBoris Brezillon 	return ret;
149093db446aSBoris Brezillon }
1491