mtd: nand: refactor BB marker detection
Some level of support for various scanning locations was already built in, but this required clean-up. First, BB marker location cannot be determined _only_ by the page size. Instead, I implemented some heuristic detection based on data sheets from various manufacturers (all found in nand_base.c:nand_get_flash_type()). Second, once these options were identified, they were not handled properly by nand_bbt.c:nand_default_bbt(). I updated the static nand_bbt_desc structs to reflect the need for more combinations of detection. The memory allocation here probably needs to be done dynamically in the very near future (see next patches). Signed-off-by: Brian Norris <norris@broadcom.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
78d1022439
commit
c7b28e25cb
2 changed files with 58 additions and 11 deletions
|
@ -2920,9 +2920,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
||||||
chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
|
chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
|
||||||
|
|
||||||
/* Set the bad block position */
|
/* Set the bad block position */
|
||||||
chip->badblockpos = mtd->writesize > 512 ?
|
if (!(busw & NAND_BUSWIDTH_16) && (*maf_id == NAND_MFR_STMICRO ||
|
||||||
NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
|
(*maf_id == NAND_MFR_SAMSUNG &&
|
||||||
chip->badblockbits = 8;
|
mtd->writesize == 512) ||
|
||||||
|
*maf_id == NAND_MFR_AMD))
|
||||||
|
chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
|
||||||
|
else
|
||||||
|
chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
|
||||||
|
|
||||||
|
|
||||||
/* Get chip options, preserve non chip based options */
|
/* Get chip options, preserve non chip based options */
|
||||||
chip->options &= ~NAND_CHIPOPTIONS_MSK;
|
chip->options &= ~NAND_CHIPOPTIONS_MSK;
|
||||||
|
@ -2941,12 +2946,23 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bad block marker is stored in the last page of each block
|
* Bad block marker is stored in the last page of each block
|
||||||
* on Samsung and Hynix MLC devices
|
* on Samsung and Hynix MLC devices; stored in first two pages
|
||||||
|
* of each block on Micron devices with 2KiB pages and on
|
||||||
|
* SLC Samsung, Hynix, and AMD/Spansion. All others scan only
|
||||||
|
* the first page.
|
||||||
*/
|
*/
|
||||||
if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
|
if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
|
||||||
(*maf_id == NAND_MFR_SAMSUNG ||
|
(*maf_id == NAND_MFR_SAMSUNG ||
|
||||||
*maf_id == NAND_MFR_HYNIX))
|
*maf_id == NAND_MFR_HYNIX))
|
||||||
chip->options |= NAND_BBT_SCANLASTPAGE;
|
chip->options |= NAND_BBT_SCANLASTPAGE;
|
||||||
|
else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
|
||||||
|
(*maf_id == NAND_MFR_SAMSUNG ||
|
||||||
|
*maf_id == NAND_MFR_HYNIX ||
|
||||||
|
*maf_id == NAND_MFR_AMD)) ||
|
||||||
|
(mtd->writesize == 2048 &&
|
||||||
|
*maf_id == NAND_MFR_MICRON))
|
||||||
|
chip->options |= NAND_BBT_SCAN2NDPAGE;
|
||||||
|
|
||||||
|
|
||||||
/* Check for AND chips with 4 page planes */
|
/* Check for AND chips with 4 page planes */
|
||||||
if (chip->options & NAND_4PAGE_ARRAY)
|
if (chip->options & NAND_4PAGE_ARRAY)
|
||||||
|
|
|
@ -1093,29 +1093,50 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
||||||
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
|
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
|
||||||
|
|
||||||
static struct nand_bbt_descr smallpage_memorybased = {
|
static struct nand_bbt_descr smallpage_memorybased = {
|
||||||
.options = NAND_BBT_SCAN2NDPAGE,
|
.options = 0,
|
||||||
.offs = 5,
|
.offs = NAND_SMALL_BADBLOCK_POS,
|
||||||
.len = 1,
|
.len = 1,
|
||||||
.pattern = scan_ff_pattern
|
.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 = {
|
static struct nand_bbt_descr largepage_memorybased = {
|
||||||
.options = 0,
|
.options = 0,
|
||||||
.offs = 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,
|
.len = 2,
|
||||||
.pattern = scan_ff_pattern
|
.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 = {
|
static struct nand_bbt_descr smallpage_flashbased = {
|
||||||
.options = NAND_BBT_SCAN2NDPAGE,
|
.options = NAND_BBT_SCAN2NDPAGE,
|
||||||
.offs = 5,
|
.offs = NAND_SMALL_BADBLOCK_POS,
|
||||||
.len = 1,
|
.len = 1,
|
||||||
.pattern = scan_ff_pattern
|
.pattern = scan_ff_pattern
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nand_bbt_descr largepage_flashbased = {
|
static struct nand_bbt_descr largepage_flashbased = {
|
||||||
.options = NAND_BBT_SCAN2NDPAGE,
|
.options = NAND_BBT_SCAN2NDPAGE,
|
||||||
.offs = 0,
|
.offs = NAND_LARGE_BADBLOCK_POS,
|
||||||
.len = 2,
|
.len = 2,
|
||||||
.pattern = scan_ff_pattern
|
.pattern = scan_ff_pattern
|
||||||
};
|
};
|
||||||
|
@ -1197,8 +1218,18 @@ int nand_default_bbt(struct mtd_info *mtd)
|
||||||
this->bbt_td = NULL;
|
this->bbt_td = NULL;
|
||||||
this->bbt_md = NULL;
|
this->bbt_md = NULL;
|
||||||
if (!this->badblock_pattern) {
|
if (!this->badblock_pattern) {
|
||||||
this->badblock_pattern = (mtd->writesize > 512) ?
|
if (this->options & NAND_BBT_SCANLASTPAGE)
|
||||||
&largepage_memorybased : &smallpage_memorybased;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nand_scan_bbt(mtd, this->badblock_pattern);
|
return nand_scan_bbt(mtd, this->badblock_pattern);
|
||||||
|
|
Loading…
Reference in a new issue