[MTD] Introduce writesize
At least two flashes exists that have the concept of a minimum write unit, similar to NAND pages, but no other NAND characteristics. Therefore, rename the minimum write unit to "writesize" for all flashes, including NAND. Signed-off-by: Joern Engel <joern@wh.fh-wedel.de>
This commit is contained in:
parent
8ca9ed5db3
commit
28318776a8
17 changed files with 117 additions and 114 deletions
|
@ -545,12 +545,12 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
|
||||||
if (extp->MinorVersion >= '4') {
|
if (extp->MinorVersion >= '4') {
|
||||||
struct cfi_intelext_programming_regioninfo *prinfo;
|
struct cfi_intelext_programming_regioninfo *prinfo;
|
||||||
prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
|
prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
|
||||||
MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift;
|
mtd->writesize = cfi->interleave << prinfo->ProgRegShift;
|
||||||
MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid;
|
MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid;
|
||||||
MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid;
|
MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid;
|
||||||
mtd->flags |= MTD_PROGRAM_REGIONS;
|
mtd->flags |= MTD_PROGRAM_REGIONS;
|
||||||
printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
|
printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
|
||||||
map->name, MTD_PROGREGION_SIZE(mtd),
|
map->name, mtd->writesize,
|
||||||
MTD_PROGREGION_CTRLMODE_VALID(mtd),
|
MTD_PROGREGION_CTRLMODE_VALID(mtd),
|
||||||
MTD_PROGREGION_CTRLMODE_INVALID(mtd));
|
MTD_PROGREGION_CTRLMODE_INVALID(mtd));
|
||||||
}
|
}
|
||||||
|
|
|
@ -579,7 +579,7 @@ void DoC2k_init(struct mtd_info *mtd)
|
||||||
mtd->ecctype = MTD_ECC_RS_DiskOnChip;
|
mtd->ecctype = MTD_ECC_RS_DiskOnChip;
|
||||||
mtd->size = 0;
|
mtd->size = 0;
|
||||||
mtd->erasesize = 0;
|
mtd->erasesize = 0;
|
||||||
mtd->oobblock = 512;
|
mtd->writesize = 512;
|
||||||
mtd->oobsize = 16;
|
mtd->oobsize = 16;
|
||||||
mtd->owner = THIS_MODULE;
|
mtd->owner = THIS_MODULE;
|
||||||
mtd->erase = doc_erase;
|
mtd->erase = doc_erase;
|
||||||
|
|
|
@ -361,7 +361,7 @@ void DoCMil_init(struct mtd_info *mtd)
|
||||||
/* FIXME: erase size is not always 8KiB */
|
/* FIXME: erase size is not always 8KiB */
|
||||||
mtd->erasesize = 0x2000;
|
mtd->erasesize = 0x2000;
|
||||||
|
|
||||||
mtd->oobblock = 512;
|
mtd->writesize = 512;
|
||||||
mtd->oobsize = 16;
|
mtd->oobsize = 16;
|
||||||
mtd->owner = THIS_MODULE;
|
mtd->owner = THIS_MODULE;
|
||||||
mtd->erase = doc_erase;
|
mtd->erase = doc_erase;
|
||||||
|
|
|
@ -483,7 +483,7 @@ void DoCMilPlus_init(struct mtd_info *mtd)
|
||||||
mtd->size = 0;
|
mtd->size = 0;
|
||||||
|
|
||||||
mtd->erasesize = 0;
|
mtd->erasesize = 0;
|
||||||
mtd->oobblock = 512;
|
mtd->writesize = 512;
|
||||||
mtd->oobsize = 16;
|
mtd->oobsize = 16;
|
||||||
mtd->owner = THIS_MODULE;
|
mtd->owner = THIS_MODULE;
|
||||||
mtd->erase = doc_erase;
|
mtd->erase = doc_erase;
|
||||||
|
|
|
@ -278,9 +278,9 @@ concat_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Check alignment */
|
/* Check alignment */
|
||||||
if (mtd->oobblock > 1) {
|
if (mtd->writesize > 1) {
|
||||||
loff_t __to = to;
|
loff_t __to = to;
|
||||||
if (do_div(__to, mtd->oobblock) || (total_len % mtd->oobblock))
|
if (do_div(__to, mtd->writesize) || (total_len % mtd->writesize))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ concat_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
|
||||||
*retlen += retsize;
|
*retlen += retsize;
|
||||||
total_len -= wsize;
|
total_len -= wsize;
|
||||||
if (concat->mtd.type == MTD_NANDFLASH && eccbuf)
|
if (concat->mtd.type == MTD_NANDFLASH && eccbuf)
|
||||||
eccbuf += mtd->oobavail * (wsize / mtd->oobblock);
|
eccbuf += mtd->oobavail * (wsize / mtd->writesize);
|
||||||
|
|
||||||
if (total_len == 0)
|
if (total_len == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -833,7 +833,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
|
||||||
concat->mtd.flags = subdev[0]->flags;
|
concat->mtd.flags = subdev[0]->flags;
|
||||||
concat->mtd.size = subdev[0]->size;
|
concat->mtd.size = subdev[0]->size;
|
||||||
concat->mtd.erasesize = subdev[0]->erasesize;
|
concat->mtd.erasesize = subdev[0]->erasesize;
|
||||||
concat->mtd.oobblock = subdev[0]->oobblock;
|
concat->mtd.writesize = subdev[0]->writesize;
|
||||||
concat->mtd.oobsize = subdev[0]->oobsize;
|
concat->mtd.oobsize = subdev[0]->oobsize;
|
||||||
concat->mtd.ecctype = subdev[0]->ecctype;
|
concat->mtd.ecctype = subdev[0]->ecctype;
|
||||||
concat->mtd.eccsize = subdev[0]->eccsize;
|
concat->mtd.eccsize = subdev[0]->eccsize;
|
||||||
|
@ -881,7 +881,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
|
||||||
subdev[i]->flags & MTD_WRITEABLE;
|
subdev[i]->flags & MTD_WRITEABLE;
|
||||||
}
|
}
|
||||||
concat->mtd.size += subdev[i]->size;
|
concat->mtd.size += subdev[i]->size;
|
||||||
if (concat->mtd.oobblock != subdev[i]->oobblock ||
|
if (concat->mtd.writesize != subdev[i]->writesize ||
|
||||||
concat->mtd.oobsize != subdev[i]->oobsize ||
|
concat->mtd.oobsize != subdev[i]->oobsize ||
|
||||||
concat->mtd.ecctype != subdev[i]->ecctype ||
|
concat->mtd.ecctype != subdev[i]->ecctype ||
|
||||||
concat->mtd.eccsize != subdev[i]->eccsize ||
|
concat->mtd.eccsize != subdev[i]->eccsize ||
|
||||||
|
|
|
@ -398,7 +398,7 @@ int add_mtd_partitions(struct mtd_info *master,
|
||||||
slave->mtd.type = master->type;
|
slave->mtd.type = master->type;
|
||||||
slave->mtd.flags = master->flags & ~parts[i].mask_flags;
|
slave->mtd.flags = master->flags & ~parts[i].mask_flags;
|
||||||
slave->mtd.size = parts[i].size;
|
slave->mtd.size = parts[i].size;
|
||||||
slave->mtd.oobblock = master->oobblock;
|
slave->mtd.writesize = master->writesize;
|
||||||
slave->mtd.oobsize = master->oobsize;
|
slave->mtd.oobsize = master->oobsize;
|
||||||
slave->mtd.oobavail = master->oobavail;
|
slave->mtd.oobavail = master->oobavail;
|
||||||
slave->mtd.ecctype = master->ecctype;
|
slave->mtd.ecctype = master->ecctype;
|
||||||
|
|
|
@ -356,9 +356,9 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
|
||||||
if (command == NAND_CMD_SEQIN) {
|
if (command == NAND_CMD_SEQIN) {
|
||||||
int readcmd;
|
int readcmd;
|
||||||
|
|
||||||
if (column >= mtd->oobblock) {
|
if (column >= mtd->writesize) {
|
||||||
/* OOB area */
|
/* OOB area */
|
||||||
column -= mtd->oobblock;
|
column -= mtd->writesize;
|
||||||
readcmd = NAND_CMD_READOOB;
|
readcmd = NAND_CMD_READOOB;
|
||||||
} else if (column < 256) {
|
} else if (column < 256) {
|
||||||
/* First 256 bytes --> READ0 */
|
/* First 256 bytes --> READ0 */
|
||||||
|
|
|
@ -761,9 +761,9 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu
|
||||||
if (command == NAND_CMD_SEQIN) {
|
if (command == NAND_CMD_SEQIN) {
|
||||||
int readcmd;
|
int readcmd;
|
||||||
|
|
||||||
if (column >= mtd->oobblock) {
|
if (column >= mtd->writesize) {
|
||||||
/* OOB area */
|
/* OOB area */
|
||||||
column -= mtd->oobblock;
|
column -= mtd->writesize;
|
||||||
readcmd = NAND_CMD_READOOB;
|
readcmd = NAND_CMD_READOOB;
|
||||||
} else if (column < 256) {
|
} else if (column < 256) {
|
||||||
/* First 256 bytes --> READ0 */
|
/* First 256 bytes --> READ0 */
|
||||||
|
@ -1093,8 +1093,8 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch
|
||||||
size_t retlen;
|
size_t retlen;
|
||||||
|
|
||||||
for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
|
for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
|
||||||
ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
|
ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
|
||||||
if (retlen != mtd->oobblock)
|
if (retlen != mtd->writesize)
|
||||||
continue;
|
continue;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", offs);
|
printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", offs);
|
||||||
|
@ -1118,8 +1118,8 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch
|
||||||
/* Only one mediaheader was found. We want buf to contain a
|
/* Only one mediaheader was found. We want buf to contain a
|
||||||
mediaheader on return, so we'll have to re-read the one we found. */
|
mediaheader on return, so we'll have to re-read the one we found. */
|
||||||
offs = doc->mh0_page << this->page_shift;
|
offs = doc->mh0_page << this->page_shift;
|
||||||
ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
|
ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
|
||||||
if (retlen != mtd->oobblock) {
|
if (retlen != mtd->writesize) {
|
||||||
/* Insanity. Give up. */
|
/* Insanity. Give up. */
|
||||||
printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n");
|
printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1139,7 +1139,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
|
||||||
unsigned blocks, maxblocks;
|
unsigned blocks, maxblocks;
|
||||||
int offs, numheaders;
|
int offs, numheaders;
|
||||||
|
|
||||||
buf = kmalloc(mtd->oobblock, GFP_KERNEL);
|
buf = kmalloc(mtd->writesize, GFP_KERNEL);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
|
printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1247,7 +1247,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
|
||||||
if (inftl_bbt_write)
|
if (inftl_bbt_write)
|
||||||
end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift);
|
end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift);
|
||||||
|
|
||||||
buf = kmalloc(mtd->oobblock, GFP_KERNEL);
|
buf = kmalloc(mtd->writesize, GFP_KERNEL);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
|
printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -560,9 +560,9 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column, int
|
||||||
if (command == NAND_CMD_SEQIN) {
|
if (command == NAND_CMD_SEQIN) {
|
||||||
int readcmd;
|
int readcmd;
|
||||||
|
|
||||||
if (column >= mtd->oobblock) {
|
if (column >= mtd->writesize) {
|
||||||
/* OOB area */
|
/* OOB area */
|
||||||
column -= mtd->oobblock;
|
column -= mtd->writesize;
|
||||||
readcmd = NAND_CMD_READOOB;
|
readcmd = NAND_CMD_READOOB;
|
||||||
} else if (column < 256) {
|
} else if (column < 256) {
|
||||||
/* First 256 bytes --> READ0 */
|
/* First 256 bytes --> READ0 */
|
||||||
|
@ -658,7 +658,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column,
|
||||||
|
|
||||||
/* Emulate NAND_CMD_READOOB */
|
/* Emulate NAND_CMD_READOOB */
|
||||||
if (command == NAND_CMD_READOOB) {
|
if (command == NAND_CMD_READOOB) {
|
||||||
column += mtd->oobblock;
|
column += mtd->writesize;
|
||||||
command = NAND_CMD_READ0;
|
command = NAND_CMD_READ0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,7 +889,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag
|
||||||
/* No ecc, write all */
|
/* No ecc, write all */
|
||||||
case NAND_ECC_NONE:
|
case NAND_ECC_NONE:
|
||||||
printk(KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
|
printk(KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
|
||||||
this->write_buf(mtd, this->data_poi, mtd->oobblock);
|
this->write_buf(mtd, this->data_poi, mtd->writesize);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Software ecc 3/256, write all */
|
/* Software ecc 3/256, write all */
|
||||||
|
@ -900,7 +900,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag
|
||||||
oob_buf[oob_config[eccidx]] = ecc_code[i];
|
oob_buf[oob_config[eccidx]] = ecc_code[i];
|
||||||
datidx += this->eccsize;
|
datidx += this->eccsize;
|
||||||
}
|
}
|
||||||
this->write_buf(mtd, this->data_poi, mtd->oobblock);
|
this->write_buf(mtd, this->data_poi, mtd->writesize);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
eccbytes = this->eccbytes;
|
eccbytes = this->eccbytes;
|
||||||
|
@ -1161,9 +1161,9 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
page = realpage & this->pagemask;
|
page = realpage & this->pagemask;
|
||||||
|
|
||||||
/* Get raw starting column */
|
/* Get raw starting column */
|
||||||
col = from & (mtd->oobblock - 1);
|
col = from & (mtd->writesize - 1);
|
||||||
|
|
||||||
end = mtd->oobblock;
|
end = mtd->writesize;
|
||||||
ecc = this->eccsize;
|
ecc = this->eccsize;
|
||||||
eccbytes = this->eccbytes;
|
eccbytes = this->eccbytes;
|
||||||
|
|
||||||
|
@ -1321,7 +1321,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
buf[read++] = data_poi[j];
|
buf[read++] = data_poi[j];
|
||||||
this->pagebuf = realpage;
|
this->pagebuf = realpage;
|
||||||
} else
|
} else
|
||||||
read += mtd->oobblock;
|
read += mtd->writesize;
|
||||||
|
|
||||||
/* Apply delay or wait for ready/busy pin
|
/* Apply delay or wait for ready/busy pin
|
||||||
* Do this before the AUTOINCR check, so no problems
|
* Do this before the AUTOINCR check, so no problems
|
||||||
|
@ -1479,7 +1479,7 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, s
|
||||||
int chip = (int)(from >> this->chip_shift);
|
int chip = (int)(from >> this->chip_shift);
|
||||||
int sndcmd = 1;
|
int sndcmd = 1;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
int pagesize = mtd->oobblock + mtd->oobsize;
|
int pagesize = mtd->writesize + mtd->oobsize;
|
||||||
int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
|
int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
|
||||||
|
|
||||||
/* Do not allow reads past end of device */
|
/* Do not allow reads past end of device */
|
||||||
|
@ -1581,7 +1581,7 @@ static u_char *nand_prepare_oobbuf(struct mtd_info *mtd, u_char *fsbuf, struct n
|
||||||
return this->oob_buf;
|
return this->oob_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0
|
#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nand_write - [MTD Interface] compability function for nand_write_ecc
|
* nand_write - [MTD Interface] compability function for nand_write_ecc
|
||||||
|
@ -1694,7 +1694,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
/* Next oob page */
|
/* Next oob page */
|
||||||
oob += mtd->oobsize;
|
oob += mtd->oobsize;
|
||||||
/* Update written bytes count */
|
/* Update written bytes count */
|
||||||
written += mtd->oobblock;
|
written += mtd->writesize;
|
||||||
if (written == len)
|
if (written == len)
|
||||||
goto cmp;
|
goto cmp;
|
||||||
|
|
||||||
|
@ -1805,7 +1805,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *r
|
||||||
|
|
||||||
if (NAND_MUST_PAD(this)) {
|
if (NAND_MUST_PAD(this)) {
|
||||||
/* Write out desired data */
|
/* Write out desired data */
|
||||||
this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask);
|
this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page & this->pagemask);
|
||||||
/* prepad 0xff for partial programming */
|
/* prepad 0xff for partial programming */
|
||||||
this->write_buf(mtd, ffchars, column);
|
this->write_buf(mtd, ffchars, column);
|
||||||
/* write data */
|
/* write data */
|
||||||
|
@ -1814,7 +1814,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *r
|
||||||
this->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
|
this->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
|
||||||
} else {
|
} else {
|
||||||
/* Write out desired data */
|
/* Write out desired data */
|
||||||
this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->oobblock + column, page & this->pagemask);
|
this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column, page & this->pagemask);
|
||||||
/* write data */
|
/* write data */
|
||||||
this->write_buf(mtd, buf, len);
|
this->write_buf(mtd, buf, len);
|
||||||
}
|
}
|
||||||
|
@ -1947,7 +1947,7 @@ static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsign
|
||||||
/* If the given tuple is >= pagesize then
|
/* If the given tuple is >= pagesize then
|
||||||
* write it out from the iov
|
* write it out from the iov
|
||||||
*/
|
*/
|
||||||
if ((vecs->iov_len - len) >= mtd->oobblock) {
|
if ((vecs->iov_len - len) >= mtd->writesize) {
|
||||||
/* Calc number of pages we can write
|
/* Calc number of pages we can write
|
||||||
* out of this iov in one go */
|
* out of this iov in one go */
|
||||||
numpages = (vecs->iov_len - len) >> this->page_shift;
|
numpages = (vecs->iov_len - len) >> this->page_shift;
|
||||||
|
@ -1967,8 +1967,8 @@ static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsign
|
||||||
&oobbuf[oob], oobsel, i != numpages);
|
&oobbuf[oob], oobsel, i != numpages);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
this->data_poi += mtd->oobblock;
|
this->data_poi += mtd->writesize;
|
||||||
len += mtd->oobblock;
|
len += mtd->writesize;
|
||||||
oob += mtd->oobsize;
|
oob += mtd->oobsize;
|
||||||
page++;
|
page++;
|
||||||
}
|
}
|
||||||
|
@ -1983,7 +1983,7 @@ static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsign
|
||||||
* tuple until we have a full page to write
|
* tuple until we have a full page to write
|
||||||
*/
|
*/
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
while (cnt < mtd->oobblock) {
|
while (cnt < mtd->writesize) {
|
||||||
if (vecs->iov_base != NULL && vecs->iov_len)
|
if (vecs->iov_base != NULL && vecs->iov_len)
|
||||||
this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];
|
this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];
|
||||||
/* Check, if we have to switch to the next tuple */
|
/* Check, if we have to switch to the next tuple */
|
||||||
|
@ -2009,7 +2009,7 @@ static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsign
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
written += mtd->oobblock * numpages;
|
written += mtd->writesize * numpages;
|
||||||
/* All done ? */
|
/* All done ? */
|
||||||
if (!count)
|
if (!count)
|
||||||
break;
|
break;
|
||||||
|
@ -2411,10 +2411,10 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
||||||
/* The 4th id byte is the important one */
|
/* The 4th id byte is the important one */
|
||||||
extid = this->read_byte(mtd);
|
extid = this->read_byte(mtd);
|
||||||
/* Calc pagesize */
|
/* Calc pagesize */
|
||||||
mtd->oobblock = 1024 << (extid & 0x3);
|
mtd->writesize = 1024 << (extid & 0x3);
|
||||||
extid >>= 2;
|
extid >>= 2;
|
||||||
/* Calc oobsize */
|
/* Calc oobsize */
|
||||||
mtd->oobsize = (8 << (extid & 0x01)) * (mtd->oobblock >> 9);
|
mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
|
||||||
extid >>= 2;
|
extid >>= 2;
|
||||||
/* Calc blocksize. Blocksize is multiples of 64KiB */
|
/* Calc blocksize. Blocksize is multiples of 64KiB */
|
||||||
mtd->erasesize = (64 * 1024) << (extid & 0x03);
|
mtd->erasesize = (64 * 1024) << (extid & 0x03);
|
||||||
|
@ -2426,8 +2426,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
||||||
/* Old devices have this data hardcoded in the
|
/* Old devices have this data hardcoded in the
|
||||||
* device id table */
|
* device id table */
|
||||||
mtd->erasesize = nand_flash_ids[i].erasesize;
|
mtd->erasesize = nand_flash_ids[i].erasesize;
|
||||||
mtd->oobblock = nand_flash_ids[i].pagesize;
|
mtd->writesize = nand_flash_ids[i].pagesize;
|
||||||
mtd->oobsize = mtd->oobblock / 32;
|
mtd->oobsize = mtd->writesize / 32;
|
||||||
busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
|
busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2451,12 +2451,12 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the address shift from the page size */
|
/* Calculate the address shift from the page size */
|
||||||
this->page_shift = ffs(mtd->oobblock) - 1;
|
this->page_shift = ffs(mtd->writesize) - 1;
|
||||||
this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;
|
this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;
|
||||||
this->chip_shift = ffs(this->chipsize) - 1;
|
this->chip_shift = ffs(this->chipsize) - 1;
|
||||||
|
|
||||||
/* Set the bad block position */
|
/* Set the bad block position */
|
||||||
this->badblockpos = mtd->oobblock > 512 ? NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
|
this->badblockpos = mtd->writesize > 512 ? NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
|
||||||
|
|
||||||
/* Get chip options, preserve non chip based options */
|
/* Get chip options, preserve non chip based options */
|
||||||
this->options &= ~NAND_CHIPOPTIONS_MSK;
|
this->options &= ~NAND_CHIPOPTIONS_MSK;
|
||||||
|
@ -2476,7 +2476,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
||||||
this->erase_cmd = single_erase_cmd;
|
this->erase_cmd = single_erase_cmd;
|
||||||
|
|
||||||
/* Do not replace user supplied command function ! */
|
/* Do not replace user supplied command function ! */
|
||||||
if (mtd->oobblock > 512 && this->cmdfunc == nand_command)
|
if (mtd->writesize > 512 && this->cmdfunc == nand_command)
|
||||||
this->cmdfunc = nand_command_lp;
|
this->cmdfunc = nand_command_lp;
|
||||||
|
|
||||||
printk(KERN_INFO "NAND device: Manufacturer ID:"
|
printk(KERN_INFO "NAND device: Manufacturer ID:"
|
||||||
|
@ -2519,7 +2519,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
||||||
|
|
||||||
if (!this->data_buf) {
|
if (!this->data_buf) {
|
||||||
size_t len;
|
size_t len;
|
||||||
len = mtd->oobblock + mtd->oobsize;
|
len = mtd->writesize + mtd->oobsize;
|
||||||
this->data_buf = kmalloc(len, GFP_KERNEL);
|
this->data_buf = kmalloc(len, GFP_KERNEL);
|
||||||
if (!this->data_buf) {
|
if (!this->data_buf) {
|
||||||
if (this->options & NAND_OOBBUF_ALLOC)
|
if (this->options & NAND_OOBBUF_ALLOC)
|
||||||
|
@ -2575,9 +2575,9 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
||||||
|
|
||||||
switch (this->eccmode) {
|
switch (this->eccmode) {
|
||||||
case NAND_ECC_HW12_2048:
|
case NAND_ECC_HW12_2048:
|
||||||
if (mtd->oobblock < 2048) {
|
if (mtd->writesize < 2048) {
|
||||||
printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n",
|
printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n",
|
||||||
mtd->oobblock);
|
mtd->writesize);
|
||||||
this->eccmode = NAND_ECC_SOFT;
|
this->eccmode = NAND_ECC_SOFT;
|
||||||
this->calculate_ecc = nand_calculate_ecc;
|
this->calculate_ecc = nand_calculate_ecc;
|
||||||
this->correct_data = nand_correct_data;
|
this->correct_data = nand_correct_data;
|
||||||
|
@ -2588,7 +2588,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
||||||
case NAND_ECC_HW3_512:
|
case NAND_ECC_HW3_512:
|
||||||
case NAND_ECC_HW6_512:
|
case NAND_ECC_HW6_512:
|
||||||
case NAND_ECC_HW8_512:
|
case NAND_ECC_HW8_512:
|
||||||
if (mtd->oobblock == 256) {
|
if (mtd->writesize == 256) {
|
||||||
printk(KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
|
printk(KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
|
||||||
this->eccmode = NAND_ECC_SOFT;
|
this->eccmode = NAND_ECC_SOFT;
|
||||||
this->calculate_ecc = nand_calculate_ecc;
|
this->calculate_ecc = nand_calculate_ecc;
|
||||||
|
@ -2638,16 +2638,16 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
||||||
/* Set the number of read / write steps for one page to ensure ECC generation */
|
/* Set the number of read / write steps for one page to ensure ECC generation */
|
||||||
switch (this->eccmode) {
|
switch (this->eccmode) {
|
||||||
case NAND_ECC_HW12_2048:
|
case NAND_ECC_HW12_2048:
|
||||||
this->eccsteps = mtd->oobblock / 2048;
|
this->eccsteps = mtd->writesize / 2048;
|
||||||
break;
|
break;
|
||||||
case NAND_ECC_HW3_512:
|
case NAND_ECC_HW3_512:
|
||||||
case NAND_ECC_HW6_512:
|
case NAND_ECC_HW6_512:
|
||||||
case NAND_ECC_HW8_512:
|
case NAND_ECC_HW8_512:
|
||||||
this->eccsteps = mtd->oobblock / 512;
|
this->eccsteps = mtd->writesize / 512;
|
||||||
break;
|
break;
|
||||||
case NAND_ECC_HW3_256:
|
case NAND_ECC_HW3_256:
|
||||||
case NAND_ECC_SOFT:
|
case NAND_ECC_SOFT:
|
||||||
this->eccsteps = mtd->oobblock / 256;
|
this->eccsteps = mtd->writesize / 256;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAND_ECC_NONE:
|
case NAND_ECC_NONE:
|
||||||
|
|
|
@ -247,15 +247,15 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
|
||||||
|
|
||||||
/* Read the primary version, if available */
|
/* Read the primary version, if available */
|
||||||
if (td->options & NAND_BBT_VERSION) {
|
if (td->options & NAND_BBT_VERSION) {
|
||||||
nand_read_raw(mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
|
nand_read_raw(mtd, buf, td->pages[0] << this->page_shift, mtd->writesize, mtd->oobsize);
|
||||||
td->version[0] = buf[mtd->oobblock + td->veroffs];
|
td->version[0] = buf[mtd->writesize + td->veroffs];
|
||||||
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
|
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)) {
|
||||||
nand_read_raw(mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
|
nand_read_raw(mtd, buf, md->pages[0] << this->page_shift, mtd->writesize, mtd->oobsize);
|
||||||
md->version[0] = buf[mtd->oobblock + md->veroffs];
|
md->version[0] = buf[mtd->writesize + md->veroffs];
|
||||||
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
|
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,8 +298,8 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||||
readlen = bd->len;
|
readlen = bd->len;
|
||||||
} else {
|
} else {
|
||||||
/* Full page content should be read */
|
/* Full page content should be read */
|
||||||
scanlen = mtd->oobblock + mtd->oobsize;
|
scanlen = mtd->writesize + mtd->oobsize;
|
||||||
readlen = len * mtd->oobblock;
|
readlen = len * mtd->writesize;
|
||||||
ooblen = len * mtd->oobsize;
|
ooblen = len * mtd->oobsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||||
|
|
||||||
/* Read the full oob until read_oob is fixed to
|
/* Read the full oob until read_oob is fixed to
|
||||||
* handle single byte reads for 16 bit buswidth */
|
* handle single byte reads for 16 bit buswidth */
|
||||||
ret = mtd->read_oob(mtd, from + j * mtd->oobblock, mtd->oobsize, &retlen, buf);
|
ret = mtd->read_oob(mtd, from + j * mtd->writesize, mtd->oobsize, &retlen, buf);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -345,7 +345,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (check_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
|
if (check_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
|
||||||
this->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
this->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
||||||
printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
|
printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
|
||||||
i >> 1, (unsigned int)from);
|
i >> 1, (unsigned int)from);
|
||||||
|
@ -381,7 +381,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||||
struct nand_chip *this = mtd->priv;
|
struct nand_chip *this = mtd->priv;
|
||||||
int i, chips;
|
int i, chips;
|
||||||
int bits, startblock, block, dir;
|
int bits, startblock, block, dir;
|
||||||
int scanlen = mtd->oobblock + mtd->oobsize;
|
int scanlen = mtd->writesize + mtd->oobsize;
|
||||||
int bbtblocks;
|
int bbtblocks;
|
||||||
|
|
||||||
/* Search direction top -> down ? */
|
/* Search direction top -> down ? */
|
||||||
|
@ -414,11 +414,11 @@ 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;
|
||||||
/* Read first page */
|
/* Read first page */
|
||||||
nand_read_raw(mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
|
nand_read_raw(mtd, buf, actblock << this->bbt_erase_shift, mtd->writesize, mtd->oobsize);
|
||||||
if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
|
if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
|
||||||
td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
|
td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
|
||||||
if (td->options & NAND_BBT_VERSION) {
|
if (td->options & NAND_BBT_VERSION) {
|
||||||
td->version[i] = buf[mtd->oobblock + td->veroffs];
|
td->version[i] = buf[mtd->writesize + td->veroffs];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -586,7 +586,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||||
/* Calc length */
|
/* Calc length */
|
||||||
len = (size_t) (numblocks >> sft);
|
len = (size_t) (numblocks >> sft);
|
||||||
/* Make it page aligned ! */
|
/* Make it page aligned ! */
|
||||||
len = (len + (mtd->oobblock - 1)) & ~(mtd->oobblock - 1);
|
len = (len + (mtd->writesize - 1)) & ~(mtd->writesize - 1);
|
||||||
/* Preset the buffer with 0xff */
|
/* Preset the buffer with 0xff */
|
||||||
memset(buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
|
memset(buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
|
||||||
offs = 0;
|
offs = 0;
|
||||||
|
@ -1063,13 +1063,13 @@ int nand_default_bbt(struct mtd_info *mtd)
|
||||||
this->bbt_md = &bbt_mirror_descr;
|
this->bbt_md = &bbt_mirror_descr;
|
||||||
}
|
}
|
||||||
if (!this->badblock_pattern) {
|
if (!this->badblock_pattern) {
|
||||||
this->badblock_pattern = (mtd->oobblock > 512) ? &largepage_flashbased : &smallpage_flashbased;
|
this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
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->oobblock > 512) ?
|
this->badblock_pattern = (mtd->writesize > 512) ?
|
||||||
&largepage_memorybased : &smallpage_memorybased;
|
&largepage_memorybased : &smallpage_memorybased;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -369,7 +369,7 @@ init_nandsim(struct mtd_info *mtd)
|
||||||
/* Initialize the NAND flash parameters */
|
/* Initialize the NAND flash parameters */
|
||||||
ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8;
|
ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8;
|
||||||
ns->geom.totsz = mtd->size;
|
ns->geom.totsz = mtd->size;
|
||||||
ns->geom.pgsz = mtd->oobblock;
|
ns->geom.pgsz = mtd->writesize;
|
||||||
ns->geom.oobsz = mtd->oobsize;
|
ns->geom.oobsz = mtd->oobsize;
|
||||||
ns->geom.secsz = mtd->erasesize;
|
ns->geom.secsz = mtd->erasesize;
|
||||||
ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
|
ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
|
||||||
|
|
|
@ -487,7 +487,7 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s
|
||||||
if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
|
if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
|
||||||
er_stat |= 1 << 1; /* err_ecc_not_avail */
|
er_stat |= 1 << 1; /* err_ecc_not_avail */
|
||||||
} else {
|
} else {
|
||||||
len = mtd->oobblock;
|
len = mtd->writesize;
|
||||||
buf = kmalloc(len, GFP_KERNEL);
|
buf = kmalloc(len, GFP_KERNEL);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
|
printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
|
||||||
|
|
|
@ -354,7 +354,7 @@ static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
|
||||||
|
|
||||||
if (ONENAND_CURRENT_BUFFERRAM(this)) {
|
if (ONENAND_CURRENT_BUFFERRAM(this)) {
|
||||||
if (area == ONENAND_DATARAM)
|
if (area == ONENAND_DATARAM)
|
||||||
return mtd->oobblock;
|
return mtd->writesize;
|
||||||
if (area == ONENAND_SPARERAM)
|
if (area == ONENAND_SPARERAM)
|
||||||
return mtd->oobsize;
|
return mtd->oobsize;
|
||||||
}
|
}
|
||||||
|
@ -632,14 +632,14 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
/* TODO handling oob */
|
/* TODO handling oob */
|
||||||
|
|
||||||
while (read < len) {
|
while (read < len) {
|
||||||
thislen = min_t(int, mtd->oobblock, len - read);
|
thislen = min_t(int, mtd->writesize, len - read);
|
||||||
|
|
||||||
column = from & (mtd->oobblock - 1);
|
column = from & (mtd->writesize - 1);
|
||||||
if (column + thislen > mtd->oobblock)
|
if (column + thislen > mtd->writesize)
|
||||||
thislen = mtd->oobblock - column;
|
thislen = mtd->writesize - column;
|
||||||
|
|
||||||
if (!onenand_check_bufferram(mtd, from)) {
|
if (!onenand_check_bufferram(mtd, from)) {
|
||||||
this->command(mtd, ONENAND_CMD_READ, from, mtd->oobblock);
|
this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
|
||||||
|
|
||||||
ret = this->wait(mtd, FL_READING);
|
ret = this->wait(mtd, FL_READING);
|
||||||
/* First copy data and check return value for ECC handling */
|
/* First copy data and check return value for ECC handling */
|
||||||
|
@ -752,7 +752,7 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
/* Read more? */
|
/* Read more? */
|
||||||
if (read < len) {
|
if (read < len) {
|
||||||
/* Page size */
|
/* Page size */
|
||||||
from += mtd->oobblock;
|
from += mtd->writesize;
|
||||||
column = 0;
|
column = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,7 +809,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
|
||||||
void __iomem *dataram0, *dataram1;
|
void __iomem *dataram0, *dataram1;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock);
|
this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
|
||||||
|
|
||||||
ret = this->wait(mtd, FL_READING);
|
ret = this->wait(mtd, FL_READING);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -819,9 +819,9 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
|
||||||
|
|
||||||
/* Check, if the two dataram areas are same */
|
/* Check, if the two dataram areas are same */
|
||||||
dataram0 = this->base + ONENAND_DATARAM;
|
dataram0 = this->base + ONENAND_DATARAM;
|
||||||
dataram1 = dataram0 + mtd->oobblock;
|
dataram1 = dataram0 + mtd->writesize;
|
||||||
|
|
||||||
if (memcmp(dataram0, dataram1, mtd->oobblock))
|
if (memcmp(dataram0, dataram1, mtd->writesize))
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -831,7 +831,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
|
||||||
#define onenand_verify_oob(...) (0)
|
#define onenand_verify_oob(...) (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0)
|
#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* onenand_write_ecc - [MTD Interface] OneNAND write with ECC
|
* onenand_write_ecc - [MTD Interface] OneNAND write with ECC
|
||||||
|
@ -875,14 +875,14 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
|
|
||||||
/* Loop until all data write */
|
/* Loop until all data write */
|
||||||
while (written < len) {
|
while (written < len) {
|
||||||
int thislen = min_t(int, mtd->oobblock, len - written);
|
int thislen = min_t(int, mtd->writesize, len - written);
|
||||||
|
|
||||||
this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
|
this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
|
||||||
|
|
||||||
this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
|
this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
|
||||||
this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
|
this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
|
||||||
|
|
||||||
this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
|
this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
|
||||||
|
|
||||||
onenand_update_bufferram(mtd, to, 1);
|
onenand_update_bufferram(mtd, to, 1);
|
||||||
|
|
||||||
|
@ -1070,10 +1070,10 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
|
||||||
* If the given tuple is >= pagesize then
|
* If the given tuple is >= pagesize then
|
||||||
* write it out from the iov
|
* write it out from the iov
|
||||||
*/
|
*/
|
||||||
if ((vecs->iov_len - len) >= mtd->oobblock) {
|
if ((vecs->iov_len - len) >= mtd->writesize) {
|
||||||
pbuf = vecs->iov_base + len;
|
pbuf = vecs->iov_base + len;
|
||||||
|
|
||||||
len += mtd->oobblock;
|
len += mtd->writesize;
|
||||||
|
|
||||||
/* Check, if we have to switch to the next tuple */
|
/* Check, if we have to switch to the next tuple */
|
||||||
if (len >= (int) vecs->iov_len) {
|
if (len >= (int) vecs->iov_len) {
|
||||||
|
@ -1083,8 +1083,8 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int cnt = 0, thislen;
|
int cnt = 0, thislen;
|
||||||
while (cnt < mtd->oobblock) {
|
while (cnt < mtd->writesize) {
|
||||||
thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len);
|
thislen = min_t(int, mtd->writesize - cnt, vecs->iov_len - len);
|
||||||
memcpy(this->page_buf + cnt, vecs->iov_base + len, thislen);
|
memcpy(this->page_buf + cnt, vecs->iov_base + len, thislen);
|
||||||
cnt += thislen;
|
cnt += thislen;
|
||||||
len += thislen;
|
len += thislen;
|
||||||
|
@ -1098,12 +1098,12 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
|
this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
|
||||||
|
|
||||||
this->write_bufferram(mtd, ONENAND_DATARAM, pbuf, 0, mtd->oobblock);
|
this->write_bufferram(mtd, ONENAND_DATARAM, pbuf, 0, mtd->writesize);
|
||||||
this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
|
this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
|
||||||
|
|
||||||
this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
|
this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
|
||||||
|
|
||||||
onenand_update_bufferram(mtd, to, 1);
|
onenand_update_bufferram(mtd, to, 1);
|
||||||
|
|
||||||
|
@ -1121,9 +1121,9 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
written += mtd->oobblock;
|
written += mtd->writesize;
|
||||||
|
|
||||||
to += mtd->oobblock;
|
to += mtd->writesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -1467,11 +1467,11 @@ static int do_otp_write(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Force buffer page aligned */
|
/* Force buffer page aligned */
|
||||||
if (len < mtd->oobblock) {
|
if (len < mtd->writesize) {
|
||||||
memcpy(this->page_buf, buf, len);
|
memcpy(this->page_buf, buf, len);
|
||||||
memset(this->page_buf + len, 0xff, mtd->oobblock - len);
|
memset(this->page_buf + len, 0xff, mtd->writesize - len);
|
||||||
pbuf = this->page_buf;
|
pbuf = this->page_buf;
|
||||||
len = mtd->oobblock;
|
len = mtd->writesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enter OTP access mode */
|
/* Enter OTP access mode */
|
||||||
|
@ -1546,12 +1546,12 @@ static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
otp_pages = 10;
|
otp_pages = 10;
|
||||||
|
|
||||||
if (mode == MTD_OTP_FACTORY) {
|
if (mode == MTD_OTP_FACTORY) {
|
||||||
from += mtd->oobblock * otp_pages;
|
from += mtd->writesize * otp_pages;
|
||||||
otp_pages = 64 - otp_pages;
|
otp_pages = 64 - otp_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check User/Factory boundary */
|
/* Check User/Factory boundary */
|
||||||
if (((mtd->oobblock * otp_pages) - (from + len)) < 0)
|
if (((mtd->writesize * otp_pages) - (from + len)) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (len > 0 && otp_pages > 0) {
|
while (len > 0 && otp_pages > 0) {
|
||||||
|
@ -1564,10 +1564,10 @@ static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
|
|
||||||
otpinfo = (struct otp_info *) buf;
|
otpinfo = (struct otp_info *) buf;
|
||||||
otpinfo->start = from;
|
otpinfo->start = from;
|
||||||
otpinfo->length = mtd->oobblock;
|
otpinfo->length = mtd->writesize;
|
||||||
otpinfo->locked = 0;
|
otpinfo->locked = 0;
|
||||||
|
|
||||||
from += mtd->oobblock;
|
from += mtd->writesize;
|
||||||
buf += sizeof(struct otp_info);
|
buf += sizeof(struct otp_info);
|
||||||
*retlen += sizeof(struct otp_info);
|
*retlen += sizeof(struct otp_info);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1811,15 +1811,15 @@ static int onenand_probe(struct mtd_info *mtd)
|
||||||
|
|
||||||
/* OneNAND page size & block size */
|
/* OneNAND page size & block size */
|
||||||
/* The data buffer size is equal to page size */
|
/* The data buffer size is equal to page size */
|
||||||
mtd->oobblock = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
|
mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
|
||||||
mtd->oobsize = mtd->oobblock >> 5;
|
mtd->oobsize = mtd->writesize >> 5;
|
||||||
/* Pagers per block is always 64 in OneNAND */
|
/* Pagers per block is always 64 in OneNAND */
|
||||||
mtd->erasesize = mtd->oobblock << 6;
|
mtd->erasesize = mtd->writesize << 6;
|
||||||
|
|
||||||
this->erase_shift = ffs(mtd->erasesize) - 1;
|
this->erase_shift = ffs(mtd->erasesize) - 1;
|
||||||
this->page_shift = ffs(mtd->oobblock) - 1;
|
this->page_shift = ffs(mtd->writesize) - 1;
|
||||||
this->ppb_shift = (this->erase_shift - this->page_shift);
|
this->ppb_shift = (this->erase_shift - this->page_shift);
|
||||||
this->page_mask = (mtd->erasesize / mtd->oobblock) - 1;
|
this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
|
||||||
|
|
||||||
/* REVIST: Multichip handling */
|
/* REVIST: Multichip handling */
|
||||||
|
|
||||||
|
@ -1909,7 +1909,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
|
||||||
/* Allocate buffers, if necessary */
|
/* Allocate buffers, if necessary */
|
||||||
if (!this->page_buf) {
|
if (!this->page_buf) {
|
||||||
size_t len;
|
size_t len;
|
||||||
len = mtd->oobblock + mtd->oobsize;
|
len = mtd->writesize + mtd->oobsize;
|
||||||
this->page_buf = kmalloc(len, GFP_KERNEL);
|
this->page_buf = kmalloc(len, GFP_KERNEL);
|
||||||
if (!this->page_buf) {
|
if (!this->page_buf) {
|
||||||
printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
|
printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
|
||||||
|
|
|
@ -87,13 +87,13 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||||
|
|
||||||
/* No need to read pages fully,
|
/* No need to read pages fully,
|
||||||
* just read required OOB bytes */
|
* just read required OOB bytes */
|
||||||
ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs,
|
ret = mtd->read_oob(mtd, from + j * mtd->writesize + bd->offs,
|
||||||
readlen, &retlen, &buf[0]);
|
readlen, &retlen, &buf[0]);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
|
if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
|
||||||
bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
||||||
printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
|
printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
|
||||||
i >> 1, (unsigned int) from);
|
i >> 1, (unsigned int) from);
|
||||||
|
|
|
@ -1173,7 +1173,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
|
||||||
|
|
||||||
/* Initialise write buffer */
|
/* Initialise write buffer */
|
||||||
init_rwsem(&c->wbuf_sem);
|
init_rwsem(&c->wbuf_sem);
|
||||||
c->wbuf_pagesize = c->mtd->oobblock;
|
c->wbuf_pagesize = c->mtd->writesize;
|
||||||
c->wbuf_ofs = 0xFFFFFFFF;
|
c->wbuf_ofs = 0xFFFFFFFF;
|
||||||
|
|
||||||
c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
|
c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
|
||||||
|
@ -1266,11 +1266,11 @@ void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) {
|
||||||
|
|
||||||
int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
|
int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
|
||||||
/* Cleanmarker currently occupies a whole programming region */
|
/* Cleanmarker currently occupies a whole programming region */
|
||||||
c->cleanmarker_size = MTD_PROGREGION_SIZE(c->mtd);
|
c->cleanmarker_size = c->mtd->writesize;
|
||||||
|
|
||||||
/* Initialize write buffer */
|
/* Initialize write buffer */
|
||||||
init_rwsem(&c->wbuf_sem);
|
init_rwsem(&c->wbuf_sem);
|
||||||
c->wbuf_pagesize = MTD_PROGREGION_SIZE(c->mtd);
|
c->wbuf_pagesize = c->mtd->writesize;
|
||||||
c->wbuf_ofs = 0xFFFFFFFF;
|
c->wbuf_ofs = 0xFFFFFFFF;
|
||||||
|
|
||||||
c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
|
c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
|
||||||
|
|
|
@ -66,8 +66,12 @@ struct mtd_info {
|
||||||
* information below if they desire
|
* information below if they desire
|
||||||
*/
|
*/
|
||||||
u_int32_t erasesize;
|
u_int32_t erasesize;
|
||||||
|
/* Smallest availlable size for writing to the device. For NAND,
|
||||||
|
* this is the page size, for some NOR chips, the size of ECC
|
||||||
|
* covered blocks.
|
||||||
|
*/
|
||||||
|
u_int32_t writesize;
|
||||||
|
|
||||||
u_int32_t oobblock; // Size of OOB blocks (e.g. 512)
|
|
||||||
u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
|
u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
|
||||||
u_int32_t ecctype;
|
u_int32_t ecctype;
|
||||||
u_int32_t eccsize;
|
u_int32_t eccsize;
|
||||||
|
@ -79,7 +83,6 @@ struct mtd_info {
|
||||||
* MTD_PROGRAM_REGIONS flag is set.
|
* MTD_PROGRAM_REGIONS flag is set.
|
||||||
* (Maybe we should have an union for those?)
|
* (Maybe we should have an union for those?)
|
||||||
*/
|
*/
|
||||||
#define MTD_PROGREGION_SIZE(mtd) (mtd)->oobblock
|
|
||||||
#define MTD_PROGREGION_CTRLMODE_VALID(mtd) (mtd)->oobsize
|
#define MTD_PROGREGION_CTRLMODE_VALID(mtd) (mtd)->oobsize
|
||||||
#define MTD_PROGREGION_CTRLMODE_INVALID(mtd) (mtd)->ecctype
|
#define MTD_PROGREGION_CTRLMODE_INVALID(mtd) (mtd)->ecctype
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct mtd_info_user {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t size; // Total size of the MTD
|
uint32_t size; // Total size of the MTD
|
||||||
uint32_t erasesize;
|
uint32_t erasesize;
|
||||||
uint32_t oobblock; // Size of OOB blocks (e.g. 512)
|
uint32_t writesize;
|
||||||
uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
|
uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
|
||||||
uint32_t ecctype;
|
uint32_t ecctype;
|
||||||
uint32_t eccsize;
|
uint32_t eccsize;
|
||||||
|
|
Loading…
Reference in a new issue