summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand/raw/nand_bbt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/raw/nand_bbt.c')
-rw-r--r--drivers/mtd/nand/raw/nand_bbt.c73
1 files changed, 39 insertions, 34 deletions
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 19a2b563acdf..fd3c10216eda 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -264,18 +264,19 @@ static int read_abs_bbt(struct nand_chip *this, uint8_t *buf,
struct nand_bbt_descr *td, int chip)
{
struct mtd_info *mtd = nand_to_mtd(this);
+ u64 targetsize = nanddev_target_size(&this->base);
int res = 0, i;
if (td->options & NAND_BBT_PERCHIP) {
int offs = 0;
- for (i = 0; i < this->numchips; i++) {
+ for (i = 0; i < nanddev_ntargets(&this->base); i++) {
if (chip == -1 || chip == i)
res = read_bbt(this, buf, td->pages[i],
- this->chipsize >> this->bbt_erase_shift,
+ targetsize >> this->bbt_erase_shift,
td, offs);
if (res)
return res;
- offs += this->chipsize >> this->bbt_erase_shift;
+ offs += targetsize >> this->bbt_erase_shift;
}
} else {
res = read_bbt(this, buf, td->pages[0],
@@ -415,11 +416,12 @@ static void read_abs_bbts(struct nand_chip *this, uint8_t *buf,
/* Scan a given block partially */
static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
- loff_t offs, uint8_t *buf, int numpages)
+ loff_t offs, uint8_t *buf)
{
struct mtd_info *mtd = nand_to_mtd(this);
+
struct mtd_oob_ops ops;
- int j, ret;
+ int ret, page_offset;
ops.ooblen = mtd->oobsize;
ops.oobbuf = buf;
@@ -427,12 +429,15 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
ops.datbuf = NULL;
ops.mode = MTD_OPS_PLACE_OOB;
- for (j = 0; j < numpages; j++) {
+ page_offset = nand_bbm_get_next_page(this, 0);
+
+ while (page_offset >= 0) {
/*
* Read the full oob until read_oob is fixed to handle single
* byte reads for 16 bit buswidth.
*/
- ret = mtd_read_oob(mtd, offs, &ops);
+ ret = mtd_read_oob(mtd, offs + (page_offset * mtd->writesize),
+ &ops);
/* Ignore ECC errors when checking for BBM */
if (ret && !mtd_is_bitflip_or_eccerr(ret))
return ret;
@@ -440,8 +445,9 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
if (check_short_pattern(buf, bd))
return 1;
- offs += mtd->writesize;
+ page_offset = nand_bbm_get_next_page(this, page_offset + 1);
}
+
return 0;
}
@@ -459,43 +465,35 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd,
static int create_bbt(struct nand_chip *this, uint8_t *buf,
struct nand_bbt_descr *bd, int chip)
{
+ u64 targetsize = nanddev_target_size(&this->base);
struct mtd_info *mtd = nand_to_mtd(this);
- int i, numblocks, numpages;
- int startblock;
+ int i, numblocks, startblock;
loff_t from;
pr_info("Scanning device for bad blocks\n");
- if (bd->options & NAND_BBT_SCAN2NDPAGE)
- numpages = 2;
- else
- numpages = 1;
-
if (chip == -1) {
numblocks = mtd->size >> this->bbt_erase_shift;
startblock = 0;
from = 0;
} else {
- if (chip >= this->numchips) {
+ if (chip >= nanddev_ntargets(&this->base)) {
pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
- chip + 1, this->numchips);
+ chip + 1, nanddev_ntargets(&this->base));
return -EINVAL;
}
- numblocks = this->chipsize >> this->bbt_erase_shift;
+ numblocks = targetsize >> this->bbt_erase_shift;
startblock = chip * numblocks;
numblocks += startblock;
from = (loff_t)startblock << this->bbt_erase_shift;
}
- if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
- from += mtd->erasesize - (mtd->writesize * numpages);
-
for (i = startblock; i < numblocks; i++) {
int ret;
BUG_ON(bd->options & NAND_BBT_NO_OOB);
- ret = scan_block_fast(this, bd, from, buf, numpages);
+ ret = scan_block_fast(this, bd, from, buf);
if (ret < 0)
return ret;
@@ -529,6 +527,7 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf,
static int search_bbt(struct nand_chip *this, uint8_t *buf,
struct nand_bbt_descr *td)
{
+ u64 targetsize = nanddev_target_size(&this->base);
struct mtd_info *mtd = nand_to_mtd(this);
int i, chips;
int startblock, block, dir;
@@ -547,8 +546,8 @@ static int search_bbt(struct nand_chip *this, uint8_t *buf,
/* Do we have a bbt per chip? */
if (td->options & NAND_BBT_PERCHIP) {
- chips = this->numchips;
- bbtblocks = this->chipsize >> this->bbt_erase_shift;
+ chips = nanddev_ntargets(&this->base);
+ bbtblocks = targetsize >> this->bbt_erase_shift;
startblock &= bbtblocks - 1;
} else {
chips = 1;
@@ -576,7 +575,7 @@ static int search_bbt(struct nand_chip *this, uint8_t *buf,
break;
}
}
- startblock += this->chipsize >> this->bbt_erase_shift;
+ startblock += targetsize >> this->bbt_erase_shift;
}
/* Check, if we found a bbt for each requested chip */
for (i = 0; i < chips; i++) {
@@ -626,6 +625,7 @@ static void search_read_bbts(struct nand_chip *this, uint8_t *buf,
static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
struct nand_bbt_descr *md, int chip)
{
+ u64 targetsize = nanddev_target_size(&this->base);
int startblock, dir, page, numblocks, i;
/*
@@ -637,9 +637,9 @@ static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
return td->pages[chip] >>
(this->bbt_erase_shift - this->page_shift);
- numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
+ numblocks = (int)(targetsize >> this->bbt_erase_shift);
if (!(td->options & NAND_BBT_PERCHIP))
- numblocks *= this->numchips;
+ numblocks *= nanddev_ntargets(&this->base);
/*
* Automatic placement of the bad block table. Search direction
@@ -717,6 +717,7 @@ static int write_bbt(struct nand_chip *this, uint8_t *buf,
struct nand_bbt_descr *td, struct nand_bbt_descr *md,
int chipsel)
{
+ u64 targetsize = nanddev_target_size(&this->base);
struct mtd_info *mtd = nand_to_mtd(this);
struct erase_info einfo;
int i, res, chip = 0;
@@ -737,10 +738,10 @@ static int write_bbt(struct nand_chip *this, uint8_t *buf,
rcode = 0xff;
/* Write bad block table per chip rather than per device? */
if (td->options & NAND_BBT_PERCHIP) {
- numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
+ numblocks = (int)(targetsize >> this->bbt_erase_shift);
/* Full device write or specific chip? */
if (chipsel == -1) {
- nrchips = this->numchips;
+ nrchips = nanddev_ntargets(&this->base);
} else {
nrchips = chipsel + 1;
chip = chipsel;
@@ -901,7 +902,9 @@ static int write_bbt(struct nand_chip *this, uint8_t *buf,
static inline int nand_memory_bbt(struct nand_chip *this,
struct nand_bbt_descr *bd)
{
- return create_bbt(this, this->data_buf, bd, -1);
+ u8 *pagebuf = nand_get_data_buf(this);
+
+ return create_bbt(this, pagebuf, bd, -1);
}
/**
@@ -925,7 +928,7 @@ static int check_create(struct nand_chip *this, uint8_t *buf,
/* Do we have a bbt per chip? */
if (td->options & NAND_BBT_PERCHIP)
- chips = this->numchips;
+ chips = nanddev_ntargets(&this->base);
else
chips = 1;
@@ -1097,14 +1100,15 @@ static int nand_update_bbt(struct nand_chip *this, loff_t offs)
*/
static void mark_bbt_region(struct nand_chip *this, struct nand_bbt_descr *td)
{
+ u64 targetsize = nanddev_target_size(&this->base);
struct mtd_info *mtd = nand_to_mtd(this);
int i, j, chips, block, nrblocks, update;
uint8_t oldval;
/* Do we have a bbt per chip? */
if (td->options & NAND_BBT_PERCHIP) {
- chips = this->numchips;
- nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
+ chips = nanddev_ntargets(&this->base);
+ nrblocks = (int)(targetsize >> this->bbt_erase_shift);
} else {
chips = 1;
nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
@@ -1157,6 +1161,7 @@ static void mark_bbt_region(struct nand_chip *this, struct nand_bbt_descr *td)
*/
static void verify_bbt_descr(struct nand_chip *this, struct nand_bbt_descr *bd)
{
+ u64 targetsize = nanddev_target_size(&this->base);
struct mtd_info *mtd = nand_to_mtd(this);
u32 pattern_len;
u32 bits;
@@ -1185,7 +1190,7 @@ static void verify_bbt_descr(struct nand_chip *this, struct nand_bbt_descr *bd)
}
if (bd->options & NAND_BBT_PERCHIP)
- table_size = this->chipsize >> this->bbt_erase_shift;
+ table_size = targetsize >> this->bbt_erase_shift;
else
table_size = mtd->size >> this->bbt_erase_shift;
table_size >>= 3;