mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 14:41:31 +00:00
NAND: Update to support 64 bit device size
This patch adds support for NANDs greater than 2 GB. Patch is based on the MTD NAND driver in the kernel. Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com> Signed-off-by: Scott Wood <scottwood@freescale.com>
This commit is contained in:
parent
581d04f14d
commit
aaa8eec532
4 changed files with 42 additions and 31 deletions
|
@ -2211,13 +2211,15 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||||
int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
||||||
int allowbbt)
|
int allowbbt)
|
||||||
{
|
{
|
||||||
int page, len, status, pages_per_block, ret, chipnr;
|
int page, status, pages_per_block, ret, chipnr;
|
||||||
struct nand_chip *chip = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
int rewrite_bbt[CONFIG_SYS_NAND_MAX_CHIPS]={0};
|
loff_t rewrite_bbt[CONFIG_SYS_NAND_MAX_CHIPS] = {0};
|
||||||
unsigned int bbt_masked_page = 0xffffffff;
|
unsigned int bbt_masked_page = 0xffffffff;
|
||||||
|
loff_t len;
|
||||||
|
|
||||||
MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
|
MTDDEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%012llx, "
|
||||||
(unsigned int) instr->addr, (unsigned int) instr->len);
|
"len = %llu\n", (unsigned long long) instr->addr,
|
||||||
|
(unsigned long long) instr->len);
|
||||||
|
|
||||||
/* Start address must align on block boundary */
|
/* Start address must align on block boundary */
|
||||||
if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
|
if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
|
||||||
|
@ -2313,7 +2315,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
||||||
MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase: "
|
MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase: "
|
||||||
"Failed erase, page 0x%08x\n", page);
|
"Failed erase, page 0x%08x\n", page);
|
||||||
instr->state = MTD_ERASE_FAILED;
|
instr->state = MTD_ERASE_FAILED;
|
||||||
instr->fail_addr = (page << chip->page_shift);
|
instr->fail_addr = ((loff_t)page << chip->page_shift);
|
||||||
goto erase_exit;
|
goto erase_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2323,7 +2325,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
||||||
*/
|
*/
|
||||||
if (bbt_masked_page != 0xffffffff &&
|
if (bbt_masked_page != 0xffffffff &&
|
||||||
(page & BBT_PAGE_MASK) == bbt_masked_page)
|
(page & BBT_PAGE_MASK) == bbt_masked_page)
|
||||||
rewrite_bbt[chipnr] = (page << chip->page_shift);
|
rewrite_bbt[chipnr] =
|
||||||
|
((loff_t)page << chip->page_shift);
|
||||||
|
|
||||||
/* Increment page address and decrement length */
|
/* Increment page address and decrement length */
|
||||||
len -= (1 << chip->phys_erase_shift);
|
len -= (1 << chip->phys_erase_shift);
|
||||||
|
@ -2370,8 +2373,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
||||||
continue;
|
continue;
|
||||||
/* update the BBT for chip */
|
/* update the BBT for chip */
|
||||||
MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
|
MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
|
||||||
"(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
|
"(%d:0x%0llx 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
|
||||||
chip->bbt_td->pages[chipnr]);
|
chip->bbt_td->pages[chipnr]);
|
||||||
nand_update_bbt(mtd, rewrite_bbt[chipnr]);
|
nand_update_bbt(mtd, rewrite_bbt[chipnr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2566,7 +2569,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
||||||
if (!mtd->name)
|
if (!mtd->name)
|
||||||
mtd->name = type->name;
|
mtd->name = type->name;
|
||||||
|
|
||||||
chip->chipsize = type->chipsize << 20;
|
chip->chipsize = (uint64_t)type->chipsize << 20;
|
||||||
|
|
||||||
/* Newer devices have all the information in additional id bytes */
|
/* Newer devices have all the information in additional id bytes */
|
||||||
if (!type->pagesize) {
|
if (!type->pagesize) {
|
||||||
|
@ -2624,7 +2627,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
||||||
|
|
||||||
chip->bbt_erase_shift = chip->phys_erase_shift =
|
chip->bbt_erase_shift = chip->phys_erase_shift =
|
||||||
ffs(mtd->erasesize) - 1;
|
ffs(mtd->erasesize) - 1;
|
||||||
chip->chip_shift = ffs(chip->chipsize) - 1;
|
if (chip->chipsize & 0xffffffff)
|
||||||
|
chip->chip_shift = ffs(chip->chipsize) - 1;
|
||||||
|
else
|
||||||
|
chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 31;
|
||||||
|
|
||||||
/* Set the bad block position */
|
/* Set the bad block position */
|
||||||
chip->badblockpos = mtd->writesize > 512 ?
|
chip->badblockpos = mtd->writesize > 512 ?
|
||||||
|
|
|
@ -182,16 +182,19 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||||
if (tmp == msk)
|
if (tmp == msk)
|
||||||
continue;
|
continue;
|
||||||
if (reserved_block_code && (tmp == reserved_block_code)) {
|
if (reserved_block_code && (tmp == reserved_block_code)) {
|
||||||
printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
|
printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n",
|
||||||
((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
|
(loff_t)((offs << 2) +
|
||||||
|
(act >> 1)) <<
|
||||||
|
this->bbt_erase_shift);
|
||||||
this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
|
this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
|
||||||
mtd->ecc_stats.bbtblocks++;
|
mtd->ecc_stats.bbtblocks++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Leave it for now, if its matured we can move this
|
/* Leave it for now, if its matured we can move this
|
||||||
* message to MTD_DEBUG_LEVEL0 */
|
* message to MTD_DEBUG_LEVEL0 */
|
||||||
printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
|
printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n",
|
||||||
((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
|
(loff_t)((offs << 2) + (act >> 1)) <<
|
||||||
|
this->bbt_erase_shift);
|
||||||
/* Factory marked bad or worn out ? */
|
/* Factory marked bad or worn out ? */
|
||||||
if (tmp == 0)
|
if (tmp == 0)
|
||||||
this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
|
this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
|
||||||
|
@ -295,8 +298,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
|
||||||
|
|
||||||
/* Read the primary version, if available */
|
/* Read the primary version, if available */
|
||||||
if (td->options & NAND_BBT_VERSION) {
|
if (td->options & NAND_BBT_VERSION) {
|
||||||
scan_read_raw(mtd, buf, td->pages[0] << this->page_shift,
|
scan_read_raw(mtd, buf, (loff_t)td->pages[0] <<
|
||||||
mtd->writesize);
|
this->page_shift, mtd->writesize);
|
||||||
td->version[0] = buf[mtd->writesize + td->veroffs];
|
td->version[0] = buf[mtd->writesize + td->veroffs];
|
||||||
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
|
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
|
||||||
td->pages[0], td->version[0]);
|
td->pages[0], td->version[0]);
|
||||||
|
@ -304,8 +307,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
|
||||||
|
|
||||||
/* Read the mirror version, if available */
|
/* Read the mirror version, if available */
|
||||||
if (md && (md->options & NAND_BBT_VERSION)) {
|
if (md && (md->options & NAND_BBT_VERSION)) {
|
||||||
scan_read_raw(mtd, buf, md->pages[0] << this->page_shift,
|
scan_read_raw(mtd, buf, (loff_t)md->pages[0] <<
|
||||||
mtd->writesize);
|
this->page_shift, mtd->writesize);
|
||||||
md->version[0] = buf[mtd->writesize + md->veroffs];
|
md->version[0] = buf[mtd->writesize + md->veroffs];
|
||||||
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
|
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
|
||||||
md->pages[0], md->version[0]);
|
md->pages[0], md->version[0]);
|
||||||
|
@ -422,7 +425,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||||
numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
|
numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
|
||||||
startblock = chip * numblocks;
|
startblock = chip * numblocks;
|
||||||
numblocks += startblock;
|
numblocks += startblock;
|
||||||
from = startblock << (this->bbt_erase_shift - 1);
|
from = (loff_t)startblock << (this->bbt_erase_shift - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = startblock; i < numblocks;) {
|
for (i = startblock; i < numblocks;) {
|
||||||
|
@ -440,8 +443,8 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||||
if (ret) {
|
if (ret) {
|
||||||
this->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
this->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
||||||
MTDDEBUG (MTD_DEBUG_LEVEL0,
|
MTDDEBUG (MTD_DEBUG_LEVEL0,
|
||||||
"Bad eraseblock %d at 0x%08x\n",
|
"Bad eraseblock %d at 0x%012llx\n",
|
||||||
i >> 1, (unsigned int)from);
|
i >> 1, (unsigned long long)from);
|
||||||
mtd->ecc_stats.badblocks++;
|
mtd->ecc_stats.badblocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +510,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||||
for (block = 0; block < td->maxblocks; block++) {
|
for (block = 0; block < td->maxblocks; block++) {
|
||||||
|
|
||||||
int actblock = startblock + dir * block;
|
int actblock = startblock + dir * block;
|
||||||
loff_t offs = actblock << this->bbt_erase_shift;
|
loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
|
||||||
|
|
||||||
/* Read first page */
|
/* Read first page */
|
||||||
scan_read_raw(mtd, buf, offs, mtd->writesize);
|
scan_read_raw(mtd, buf, offs, mtd->writesize);
|
||||||
|
@ -731,7 +734,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||||
|
|
||||||
memset(&einfo, 0, sizeof(einfo));
|
memset(&einfo, 0, sizeof(einfo));
|
||||||
einfo.mtd = mtd;
|
einfo.mtd = mtd;
|
||||||
einfo.addr = (unsigned long)to;
|
einfo.addr = to;
|
||||||
einfo.len = 1 << this->bbt_erase_shift;
|
einfo.len = 1 << this->bbt_erase_shift;
|
||||||
res = nand_erase_nand(mtd, &einfo, 1);
|
res = nand_erase_nand(mtd, &einfo, 1);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
|
@ -741,8 +744,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
goto outerr;
|
goto outerr;
|
||||||
|
|
||||||
printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
|
printk(KERN_DEBUG "Bad block table written to 0x%012llx, "
|
||||||
"0x%02X\n", (unsigned int)to, td->version[chip]);
|
"version 0x%02X\n", (unsigned long long)to,
|
||||||
|
td->version[chip]);
|
||||||
|
|
||||||
/* Mark it as used */
|
/* Mark it as used */
|
||||||
td->pages[chip] = page;
|
td->pages[chip] = page;
|
||||||
|
@ -922,7 +926,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||||
newval = oldval | (0x2 << (block & 0x06));
|
newval = oldval | (0x2 << (block & 0x06));
|
||||||
this->bbt[(block >> 3)] = newval;
|
this->bbt[(block >> 3)] = newval;
|
||||||
if ((oldval != newval) && td->reserved_block_code)
|
if ((oldval != newval) && td->reserved_block_code)
|
||||||
nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1));
|
nand_update_bbt(mtd, (loff_t)block <<
|
||||||
|
(this->bbt_erase_shift - 1));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
update = 0;
|
update = 0;
|
||||||
|
@ -943,7 +948,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||||
new ones have been marked, then we need to update the stored
|
new ones have been marked, then we need to update the stored
|
||||||
bbts. This should only happen once. */
|
bbts. This should only happen once. */
|
||||||
if (update && td->reserved_block_code)
|
if (update && td->reserved_block_code)
|
||||||
nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1));
|
nand_update_bbt(mtd, (loff_t)(block - 2) <<
|
||||||
|
(this->bbt_erase_shift - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,7 +1045,6 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
||||||
if (!this->bbt || !td)
|
if (!this->bbt || !td)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
len = mtd->size >> (this->bbt_erase_shift + 2);
|
|
||||||
/* Allocate a temporary buffer for one eraseblock incl. oob */
|
/* Allocate a temporary buffer for one eraseblock incl. oob */
|
||||||
len = (1 << this->bbt_erase_shift);
|
len = (1 << this->bbt_erase_shift);
|
||||||
len += (len >> this->page_shift) * mtd->oobsize;
|
len += (len >> this->page_shift) * mtd->oobsize;
|
||||||
|
|
|
@ -397,7 +397,7 @@ struct nand_chip {
|
||||||
int bbt_erase_shift;
|
int bbt_erase_shift;
|
||||||
int chip_shift;
|
int chip_shift;
|
||||||
int numchips;
|
int numchips;
|
||||||
unsigned long chipsize;
|
uint64_t chipsize;
|
||||||
int pagemask;
|
int pagemask;
|
||||||
int pagebuf;
|
int pagebuf;
|
||||||
int subpagesize;
|
int subpagesize;
|
||||||
|
|
|
@ -38,8 +38,8 @@
|
||||||
|
|
||||||
struct mtd_partition {
|
struct mtd_partition {
|
||||||
char *name; /* identifier string */
|
char *name; /* identifier string */
|
||||||
u_int32_t size; /* partition size */
|
uint64_t size; /* partition size */
|
||||||
u_int32_t offset; /* offset within the master MTD space */
|
uint64_t offset; /* offset within the master MTD space */
|
||||||
u_int32_t mask_flags; /* master MTD flags to mask out for this partition */
|
u_int32_t mask_flags; /* master MTD flags to mask out for this partition */
|
||||||
struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
|
struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
|
||||||
struct mtd_info **mtdp; /* pointer to store the MTD object */
|
struct mtd_info **mtdp; /* pointer to store the MTD object */
|
||||||
|
|
Loading…
Add table
Reference in a new issue