mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-17 02:15:02 +00:00
drivers: mtd: nand: base: Add support for Hardware ECC for check bad block
Leverage linux code to support hardware ECC interface to verify nand bad block. Signed-off-by: Dinesh Maniyam <dinesh.maniyam@intel.com>
This commit is contained in:
parent
7ed5c15a83
commit
597fe4098d
2 changed files with 56 additions and 24 deletions
|
@ -306,6 +306,35 @@ void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* nand_bbm_get_next_page - Get the next page for bad block markers
|
||||
* @chip: The NAND chip
|
||||
* @page: First page to start checking for bad block marker usage
|
||||
*
|
||||
* Returns an integer that corresponds to the page offset within a block, for
|
||||
* a page that is used to store bad block markers. If no more pages are
|
||||
* available, -EINVAL is returned.
|
||||
*/
|
||||
int nand_bbm_get_next_page(struct nand_chip *chip, int page)
|
||||
{
|
||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||
int last_page = ((mtd->erasesize - mtd->writesize) >>
|
||||
chip->page_shift) & chip->pagemask;
|
||||
unsigned int bbm_flags = NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE
|
||||
| NAND_BBM_LASTPAGE;
|
||||
|
||||
if (page == 0 && !(chip->options & bbm_flags))
|
||||
return 0;
|
||||
if (page == 0 && chip->options & NAND_BBM_FIRSTPAGE)
|
||||
return 0;
|
||||
if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
|
||||
return 1;
|
||||
if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
|
||||
return last_page;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* nand_block_bad - [DEFAULT] Read bad block marker from the chip
|
||||
* @mtd: MTD device structure
|
||||
|
@ -315,40 +344,32 @@ void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
*/
|
||||
static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
int page, res = 0, i = 0;
|
||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||
u16 bad;
|
||||
int first_page, page_offset;
|
||||
int res;
|
||||
u8 bad;
|
||||
|
||||
if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
|
||||
ofs += mtd->erasesize - mtd->writesize;
|
||||
first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
|
||||
page_offset = nand_bbm_get_next_page(chip, 0);
|
||||
|
||||
page = (int)(ofs >> chip->page_shift) & chip->pagemask;
|
||||
while (page_offset >= 0) {
|
||||
res = chip->ecc.read_oob(mtd, chip, first_page + page_offset);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
do {
|
||||
if (chip->options & NAND_BUSWIDTH_16) {
|
||||
chip->cmdfunc(mtd, NAND_CMD_READOOB,
|
||||
chip->badblockpos & 0xFE, page);
|
||||
bad = cpu_to_le16(chip->read_word(mtd));
|
||||
if (chip->badblockpos & 0x1)
|
||||
bad >>= 8;
|
||||
else
|
||||
bad &= 0xFF;
|
||||
} else {
|
||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
|
||||
page);
|
||||
bad = chip->read_byte(mtd);
|
||||
}
|
||||
bad = chip->oob_poi[chip->badblockpos];
|
||||
|
||||
if (likely(chip->badblockbits == 8))
|
||||
res = bad != 0xFF;
|
||||
else
|
||||
res = hweight8(bad) < chip->badblockbits;
|
||||
ofs += mtd->writesize;
|
||||
page = (int)(ofs >> chip->page_shift) & chip->pagemask;
|
||||
i++;
|
||||
} while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
return res;
|
||||
page_offset = nand_bbm_get_next_page(chip, page_offset + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -131,6 +131,17 @@ void nand_wait_ready(struct mtd_info *mtd);
|
|||
|
||||
#define NAND_DATA_IFACE_CHECK_ONLY -1
|
||||
|
||||
/*
|
||||
* There are different places where the manufacturer stores the factory bad
|
||||
* block markers.
|
||||
*
|
||||
* Position within the block: Each of these pages needs to be checked for a
|
||||
* bad block marking pattern.
|
||||
*/
|
||||
#define NAND_BBM_FIRSTPAGE BIT(24)
|
||||
#define NAND_BBM_SECONDPAGE BIT(25)
|
||||
#define NAND_BBM_LASTPAGE BIT(26)
|
||||
|
||||
/*
|
||||
* Constants for ECC_MODES
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue