Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 207766
b: refs/heads/master
c: 58373ff
h: refs/heads/master
v: v3
  • Loading branch information
Brian Norris authored and David Woodhouse committed Aug 2, 2010
1 parent a1f435e commit 44f73da
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 56 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c7b28e25cb9beb943aead770ff14551b55fa8c79
refs/heads/master: 58373ff0afff4cc8ac40608872995f4d87eb72ec
14 changes: 14 additions & 0 deletions trunk/drivers/mtd/nand/nand_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -2963,6 +2963,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
*maf_id == NAND_MFR_MICRON))
chip->options |= NAND_BBT_SCAN2NDPAGE;

/*
* Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6
*/
if (!(busw & NAND_BUSWIDTH_16) &&
*maf_id == NAND_MFR_STMICRO &&
mtd->writesize == 2048) {
chip->options |= NAND_BBT_SCANBYTE1AND6;
chip->badblockpos = 0;
}

/* Check for AND chips with 4 page planes */
if (chip->options & NAND_4PAGE_ARRAY)
Expand Down Expand Up @@ -3322,6 +3331,11 @@ void nand_release(struct mtd_info *mtd)
kfree(chip->bbt);
if (!(chip->options & NAND_OWN_BUFFERS))
kfree(chip->buffers);

/* Free bad block descriptor memory */
if (chip->badblock_pattern && chip->badblock_pattern->options
& NAND_BBT_DYNAMICSTRUCT)
kfree(chip->badblock_pattern);
}

EXPORT_SYMBOL_GPL(nand_lock);
Expand Down
127 changes: 72 additions & 55 deletions trunk/drivers/mtd/nand/nand_bbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,28 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
return -1;
}

/* Check both positions 1 and 6 for pattern? */
if (td->options & NAND_BBT_SCANBYTE1AND6) {
if (td->options & NAND_BBT_SCANEMPTY) {
p += td->len;
end += NAND_SMALL_BADBLOCK_POS - td->offs;
/* Check region between positions 1 and 6 */
for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len;
i++) {
if (*p++ != 0xff)
return -1;
}
}
else {
p += NAND_SMALL_BADBLOCK_POS - td->offs;
}
/* Compare the pattern */
for (i = 0; i < td->len; i++) {
if (p[i] != td->pattern[i])
return -1;
}
}

if (td->options & NAND_BBT_SCANEMPTY) {
p += td->len;
end += td->len;
Expand Down Expand Up @@ -124,6 +146,13 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
if (p[td->offs + i] != td->pattern[i])
return -1;
}
/* Need to check location 1 AND 6? */
if (td->options & NAND_BBT_SCANBYTE1AND6) {
for (i = 0; i < td->len; i++) {
if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i])
return -1;
}
}
return 0;
}

Expand Down Expand Up @@ -397,12 +426,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,

if (bd->options & NAND_BBT_SCANALLPAGES)
len = 1 << (this->bbt_erase_shift - this->page_shift);
else {
if (bd->options & NAND_BBT_SCAN2NDPAGE)
len = 2;
else
len = 1;
}
else if (bd->options & NAND_BBT_SCAN2NDPAGE)
len = 2;
else
len = 1;

if (!(bd->options & NAND_BBT_SCANEMPTY)) {
/* We need only read few bytes from the OOB area */
Expand Down Expand Up @@ -1092,41 +1119,6 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
* while scanning a device for factory marked good / bad blocks. */
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };

static struct nand_bbt_descr smallpage_memorybased = {
.options = 0,
.offs = NAND_SMALL_BADBLOCK_POS,
.len = 1,
.pattern = scan_ff_pattern
};

static struct nand_bbt_descr smallpage_scan2nd_memorybased = {
.options = NAND_BBT_SCAN2NDPAGE,
.offs = NAND_SMALL_BADBLOCK_POS,
.len = 2,
.pattern = scan_ff_pattern
};

static struct nand_bbt_descr largepage_memorybased = {
.options = 0,
.offs = NAND_LARGE_BADBLOCK_POS,
.len = 1,
.pattern = scan_ff_pattern
};

static struct nand_bbt_descr largepage_scan2nd_memorybased = {
.options = NAND_BBT_SCAN2NDPAGE,
.offs = NAND_LARGE_BADBLOCK_POS,
.len = 2,
.pattern = scan_ff_pattern
};

static struct nand_bbt_descr lastpage_memorybased = {
.options = NAND_BBT_SCANLASTPAGE,
.offs = 0,
.len = 1,
.pattern = scan_ff_pattern
};

static struct nand_bbt_descr smallpage_flashbased = {
.options = NAND_BBT_SCAN2NDPAGE,
.offs = NAND_SMALL_BADBLOCK_POS,
Expand Down Expand Up @@ -1175,6 +1167,43 @@ static struct nand_bbt_descr bbt_mirror_descr = {
.pattern = mirror_pattern
};

#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \
NAND_BBT_SCANBYTE1AND6)
/**
* nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure
* @this: NAND chip to create descriptor for
*
* This function allocates and initializes a nand_bbt_descr for BBM detection
* based on the properties of "this". The new descriptor is stored in
* this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
* passed to this function.
*
* TODO: Handle other flags, replace other static structs
* (e.g. handle NAND_BBT_FLASH for flash-based BBT,
* replace smallpage_flashbased)
*
*/
static int nand_create_default_bbt_descr(struct nand_chip *this)
{
struct nand_bbt_descr *bd;
if (this->badblock_pattern) {
printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
return -EINVAL;
}
bd = kzalloc(sizeof(*bd), GFP_KERNEL);
if (!bd) {
printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n");
return -ENOMEM;
}
bd->options = this->options & BBT_SCAN_OPTIONS;
bd->offs = this->badblockpos;
bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
bd->pattern = scan_ff_pattern;
bd->options |= NAND_BBT_DYNAMICSTRUCT;
this->badblock_pattern = bd;
return 0;
}

/**
* nand_default_bbt - [NAND Interface] Select a default bad block table for the device
* @mtd: MTD device structure
Expand Down Expand Up @@ -1217,20 +1246,8 @@ int nand_default_bbt(struct mtd_info *mtd)
} else {
this->bbt_td = NULL;
this->bbt_md = NULL;
if (!this->badblock_pattern) {
if (this->options & NAND_BBT_SCANLASTPAGE)
this->badblock_pattern = &lastpage_memorybased;
else if (this->options & NAND_BBT_SCAN2NDPAGE)
this->badblock_pattern = this->badblockpos ==
NAND_SMALL_BADBLOCK_POS ?
&smallpage_scan2nd_memorybased :
&largepage_scan2nd_memorybased;
else
this->badblock_pattern = this->badblockpos ==
NAND_SMALL_BADBLOCK_POS ?
&smallpage_memorybased :
&largepage_memorybased;
}
if (!this->badblock_pattern)
nand_create_default_bbt_descr(this);
}
return nand_scan_bbt(mtd, this->badblock_pattern);
}
Expand Down
4 changes: 4 additions & 0 deletions trunk/include/linux/mtd/bbm.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ struct nand_bbt_descr {
#define NAND_BBT_SCAN2NDPAGE 0x00004000
/* Search good / bad pattern on the last page of the eraseblock */
#define NAND_BBT_SCANLASTPAGE 0x00008000
/* Chip stores bad block marker on BOTH 1st and 6th bytes of OOB */
#define NAND_BBT_SCANBYTE1AND6 0x00100000
/* The nand_bbt_descr was created dynamicaly and must be freed */
#define NAND_BBT_DYNAMICSTRUCT 0x00200000

/* The maximum number of blocks to scan for a bbt */
#define NAND_BBT_SCAN_MAXBLOCKS 4
Expand Down

0 comments on commit 44f73da

Please sign in to comment.