NAND support work in progress
This commit is contained in:
parent
d24db665ac
commit
3f90fc9d3e
|
@ -4,4 +4,5 @@ obj-$(CONFIG_NAND) += nand_bbt.o
|
|||
obj-$(CONFIG_NAND) += nand.o
|
||||
obj-$(CONFIG_NAND) += nand_ecc.o
|
||||
obj-$(CONFIG_NAND) += nand_ids.o
|
||||
obj-$(CONFIG_NAND) += imx_nand.o
|
||||
#obj-$(CONFIG_NAND) += nand_util.o
|
||||
|
|
|
@ -22,59 +22,50 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <nand.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <init.h>
|
||||
#include <xfuncs.h>
|
||||
#include <driver.h>
|
||||
|
||||
char *default_nand_name = "huhu";
|
||||
|
||||
static inline int board_nand_init(struct nand_chip *nand)
|
||||
static ssize_t nand_read(struct device_d *dev, void* buf, size_t count, ulong offset, ulong flags)
|
||||
{
|
||||
return 0;
|
||||
struct nand_chip *nand = dev->priv;
|
||||
size_t retlen;
|
||||
int ret;
|
||||
char oobuf[NAND_MAX_OOBSIZE];
|
||||
|
||||
printf("%s\n", __FUNCTION__);
|
||||
|
||||
ret = nand->read_ecc(nand, offset, count, &retlen, buf, oobuf, &nand->oobinfo);
|
||||
|
||||
if(ret)
|
||||
return ret;
|
||||
return retlen;
|
||||
}
|
||||
|
||||
static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand,
|
||||
ulong base_addr)
|
||||
static ssize_t nand_write(struct device_d* dev, const void* buf, size_t count, ulong offset, ulong flags)
|
||||
{
|
||||
mtd->priv = nand;
|
||||
|
||||
nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;
|
||||
if (board_nand_init(nand) == 0) {
|
||||
if (nand_scan(mtd, 1) == 0) {
|
||||
if (!mtd->name)
|
||||
mtd->name = (char *)default_nand_name;
|
||||
} else
|
||||
mtd->name = NULL;
|
||||
} else {
|
||||
mtd->name = NULL;
|
||||
mtd->size = 0;
|
||||
}
|
||||
struct nand_chip *nand = dev->priv;
|
||||
size_t retlen;
|
||||
int ret;
|
||||
|
||||
ret = nand->write_ecc(nand, offset, count, &retlen, buf, NULL, &nand->oobinfo);
|
||||
if (ret)
|
||||
return ret;
|
||||
return retlen;
|
||||
}
|
||||
|
||||
struct nand_host {
|
||||
struct mtd_info info;
|
||||
struct nand_chip chip;
|
||||
struct device_d *dev;
|
||||
};
|
||||
|
||||
static int nand_probe (struct device_d *dev)
|
||||
{
|
||||
struct nand_host *host;
|
||||
|
||||
host = xzalloc(sizeof(*host));
|
||||
|
||||
nand_init_chip(&host->info, &host->chip, dev->map_base);
|
||||
|
||||
printf("%s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct driver_d nand_driver = {
|
||||
.name = "nand_flash",
|
||||
.probe = nand_probe,
|
||||
// .read = nand_read,
|
||||
// .write = nand_write,
|
||||
.read = nand_read,
|
||||
.write = nand_write,
|
||||
// .erase = nand_erase,
|
||||
// .protect= nand_protect,
|
||||
// .memmap = generic_memmap_ro,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -117,11 +117,10 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des
|
|||
* Read the bad block table starting from page.
|
||||
*
|
||||
*/
|
||||
static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||
static int read_bbt (struct nand_chip *this, uint8_t *buf, int page, int num,
|
||||
int bits, int offs, int reserved_block_code)
|
||||
{
|
||||
int res, i, j, act = 0;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
size_t retlen, len, totlen;
|
||||
loff_t from;
|
||||
uint8_t msk = (uint8_t) ((1 << bits) - 1);
|
||||
|
@ -131,7 +130,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
|||
|
||||
while (totlen) {
|
||||
len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
|
||||
res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
|
||||
res = this->read_ecc (this, from, len, &retlen, buf, NULL, this->autooob);
|
||||
if (res < 0) {
|
||||
if (retlen != len) {
|
||||
printk (KERN_INFO "nand_bbt: Error reading bad block table\n");
|
||||
|
@ -182,9 +181,8 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
|||
* Read the bad block table for all chips starting at a given page
|
||||
* We assume that the bbt bits are in consecutive order.
|
||||
*/
|
||||
static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
|
||||
static int read_abs_bbt (struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *td, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int res = 0, i;
|
||||
int bits;
|
||||
|
||||
|
@ -193,13 +191,13 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
|
|||
int offs = 0;
|
||||
for (i = 0; i < this->numchips; i++) {
|
||||
if (chip == -1 || chip == i)
|
||||
res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code);
|
||||
res = read_bbt (this, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code);
|
||||
if (res)
|
||||
return res;
|
||||
offs += this->chipsize >> (this->bbt_erase_shift + 2);
|
||||
}
|
||||
} else {
|
||||
res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code);
|
||||
res = read_bbt (this, buf, td->pages[0], this->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code);
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
|
@ -217,22 +215,21 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
|
|||
* We assume that the bbt bits are in consecutive order.
|
||||
*
|
||||
*/
|
||||
static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td,
|
||||
static int read_abs_bbts (struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *td,
|
||||
struct nand_bbt_descr *md)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
/* Read the primary version, if available */
|
||||
if (td->options & NAND_BBT_VERSION) {
|
||||
nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
|
||||
td->version[0] = buf[mtd->oobblock + td->veroffs];
|
||||
nand_read_raw (this, buf, td->pages[0] << this->page_shift, this->oobblock, this->oobsize);
|
||||
td->version[0] = buf[this->oobblock + td->veroffs];
|
||||
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 */
|
||||
if (md && (md->options & NAND_BBT_VERSION)) {
|
||||
nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
|
||||
md->version[0] = buf[mtd->oobblock + md->veroffs];
|
||||
nand_read_raw (this, buf, md->pages[0] << this->page_shift, this->oobblock, this->oobsize);
|
||||
md->version[0] = buf[this->oobblock + md->veroffs];
|
||||
printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
|
||||
}
|
||||
|
||||
|
@ -250,9 +247,8 @@ static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_de
|
|||
* Create a bad block table by scanning the device
|
||||
* for the given good/bad block identify pattern
|
||||
*/
|
||||
static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
|
||||
static void create_bbt (struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int i, j, numblocks, len, scanlen;
|
||||
int startblock;
|
||||
loff_t from;
|
||||
|
@ -266,14 +262,14 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
|||
else
|
||||
len = 1;
|
||||
}
|
||||
scanlen = mtd->oobblock + mtd->oobsize;
|
||||
readlen = len * mtd->oobblock;
|
||||
ooblen = len * mtd->oobsize;
|
||||
scanlen = this->oobblock + this->oobsize;
|
||||
readlen = len * this->oobblock;
|
||||
ooblen = len * this->oobsize;
|
||||
|
||||
if (chip == -1) {
|
||||
/* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it
|
||||
* makes shifting and masking less painful */
|
||||
numblocks = mtd->size >> (this->bbt_erase_shift - 1);
|
||||
numblocks = this->size >> (this->bbt_erase_shift - 1);
|
||||
startblock = 0;
|
||||
from = 0;
|
||||
} else {
|
||||
|
@ -289,9 +285,9 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
|||
}
|
||||
|
||||
for (i = startblock; i < numblocks;) {
|
||||
nand_read_raw (mtd, buf, from, readlen, ooblen);
|
||||
nand_read_raw (this, buf, from, readlen, ooblen);
|
||||
for (j = 0; j < len; j++) {
|
||||
if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
|
||||
if (check_pattern (&buf[j * scanlen], scanlen, this->oobblock, bd)) {
|
||||
this->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
||||
break;
|
||||
}
|
||||
|
@ -318,17 +314,16 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
|||
* The bbt ident pattern resides in the oob area of the first page
|
||||
* in a block.
|
||||
*/
|
||||
static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
|
||||
static int search_bbt (struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *td)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int i, chips;
|
||||
int bits, startblock, block, dir;
|
||||
int scanlen = mtd->oobblock + mtd->oobsize;
|
||||
int scanlen = this->oobblock + this->oobsize;
|
||||
int bbtblocks;
|
||||
|
||||
/* Search direction top -> down ? */
|
||||
if (td->options & NAND_BBT_LASTBLOCK) {
|
||||
startblock = (mtd->size >> this->bbt_erase_shift) -1;
|
||||
startblock = (this->size >> this->bbt_erase_shift) -1;
|
||||
dir = -1;
|
||||
} else {
|
||||
startblock = 0;
|
||||
|
@ -342,7 +337,7 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
|||
startblock &= bbtblocks - 1;
|
||||
} else {
|
||||
chips = 1;
|
||||
bbtblocks = mtd->size >> this->bbt_erase_shift;
|
||||
bbtblocks = this->size >> this->bbt_erase_shift;
|
||||
}
|
||||
|
||||
/* Number of bits for each erase block in the bbt */
|
||||
|
@ -356,11 +351,11 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
|||
for (block = 0; block < td->maxblocks; block++) {
|
||||
int actblock = startblock + dir * block;
|
||||
/* Read first page */
|
||||
nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
|
||||
if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
|
||||
nand_read_raw (this, buf, actblock << this->bbt_erase_shift, this->oobblock, this->oobsize);
|
||||
if (!check_pattern(buf, scanlen, this->oobblock, td)) {
|
||||
td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
|
||||
if (td->options & NAND_BBT_VERSION) {
|
||||
td->version[i] = buf[mtd->oobblock + td->veroffs];
|
||||
td->version[i] = buf[this->oobblock + td->veroffs];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -386,15 +381,15 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
|||
*
|
||||
* Search and read the bad block table(s)
|
||||
*/
|
||||
static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
|
||||
static int search_read_bbts (struct nand_chip *this, uint8_t *buf,
|
||||
struct nand_bbt_descr *td, struct nand_bbt_descr *md)
|
||||
{
|
||||
/* Search the primary table */
|
||||
search_bbt (mtd, buf, td);
|
||||
search_bbt (this, buf, td);
|
||||
|
||||
/* Search the mirror table */
|
||||
if (md)
|
||||
search_bbt (mtd, buf, md);
|
||||
search_bbt (this, buf, md);
|
||||
|
||||
/* Force result check */
|
||||
return 1;
|
||||
|
@ -413,10 +408,9 @@ static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
|
|||
* (Re)write the bad block table
|
||||
*
|
||||
*/
|
||||
static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
|
||||
static int write_bbt (struct nand_chip *this, uint8_t *buf,
|
||||
struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_oobinfo oobinfo;
|
||||
struct erase_info einfo;
|
||||
int i, j, res, chip = 0;
|
||||
|
@ -440,7 +434,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
|
|||
chip = chipsel;
|
||||
}
|
||||
} else {
|
||||
numblocks = (int) (mtd->size >> this->bbt_erase_shift);
|
||||
numblocks = (int) (this->size >> this->bbt_erase_shift);
|
||||
nrchips = 1;
|
||||
}
|
||||
|
||||
|
@ -505,7 +499,7 @@ write:
|
|||
/* Make it block aligned */
|
||||
to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
|
||||
len = 1 << this->bbt_erase_shift;
|
||||
res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
|
||||
res = this->read_ecc (this, to, len, &retlen, buf, &buf[len], &oobinfo);
|
||||
if (res < 0) {
|
||||
if (retlen != len) {
|
||||
printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n");
|
||||
|
@ -519,18 +513,18 @@ write:
|
|||
/* Preset the bbt area with 0xff */
|
||||
memset (&buf[offs], 0xff, (size_t)(numblocks >> sft));
|
||||
/* Preset the bbt's oob area with 0xff */
|
||||
memset (&buf[len + pageoffs * mtd->oobsize], 0xff,
|
||||
((len >> this->page_shift) - pageoffs) * mtd->oobsize);
|
||||
memset (&buf[len + pageoffs * this->oobsize], 0xff,
|
||||
((len >> this->page_shift) - pageoffs) * this->oobsize);
|
||||
if (td->options & NAND_BBT_VERSION) {
|
||||
buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
|
||||
buf[len + (pageoffs * this->oobsize) + td->veroffs] = td->version[chip];
|
||||
}
|
||||
} else {
|
||||
/* Calc length */
|
||||
len = (size_t) (numblocks >> sft);
|
||||
/* Make it page aligned ! */
|
||||
len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1);
|
||||
len = (len + (this->oobblock-1)) & ~(this->oobblock-1);
|
||||
/* Preset the buffer with 0xff */
|
||||
memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
|
||||
memset (buf, 0xff, len + (len >> this->page_shift) * this->oobsize);
|
||||
offs = 0;
|
||||
/* Pattern is located in oob area of first page */
|
||||
memcpy (&buf[len + td->offs], td->pattern, td->len);
|
||||
|
@ -552,16 +546,16 @@ write:
|
|||
}
|
||||
|
||||
memset (&einfo, 0, sizeof (einfo));
|
||||
einfo.mtd = mtd;
|
||||
einfo.nand = this;
|
||||
einfo.addr = (unsigned long) to;
|
||||
einfo.len = 1 << this->bbt_erase_shift;
|
||||
res = nand_erase_nand (mtd, &einfo, 1);
|
||||
res = nand_erase_nand (this, &einfo, 1);
|
||||
if (res < 0) {
|
||||
printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
|
||||
res = this->write_ecc (this, to, len, &retlen, buf, &buf[len], &oobinfo);
|
||||
if (res < 0) {
|
||||
printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
|
||||
return res;
|
||||
|
@ -583,13 +577,11 @@ write:
|
|||
* The function creates a memory based bbt by scanning the device
|
||||
* for manufacturer / software marked good / bad blocks
|
||||
*/
|
||||
static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
static int nand_memory_bbt (struct nand_chip *this, struct nand_bbt_descr *bd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
/* Ensure that we only scan for the pattern and nothing else */
|
||||
bd->options = 0;
|
||||
create_bbt (mtd, this->data_buf, bd, -1);
|
||||
create_bbt (this, this->data_buf, bd, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -605,10 +597,9 @@ static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
|||
* Update is neccecary if one of the tables is missing or the
|
||||
* version nr. of one table is less than the other
|
||||
*/
|
||||
static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
|
||||
static int check_create (struct nand_chip *this, uint8_t *buf, struct nand_bbt_descr *bd)
|
||||
{
|
||||
int i, chips, writeops, chipsel, res;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_bbt_descr *td = this->bbt_td;
|
||||
struct nand_bbt_descr *md = this->bbt_md;
|
||||
struct nand_bbt_descr *rd, *rd2;
|
||||
|
@ -679,7 +670,7 @@ create:
|
|||
continue;
|
||||
|
||||
/* Create the table in memory by scanning the chip(s) */
|
||||
create_bbt (mtd, buf, bd, chipsel);
|
||||
create_bbt (this, buf, bd, chipsel);
|
||||
|
||||
td->version[i] = 1;
|
||||
if (md)
|
||||
|
@ -687,21 +678,21 @@ create:
|
|||
writecheck:
|
||||
/* read back first ? */
|
||||
if (rd)
|
||||
read_abs_bbt (mtd, buf, rd, chipsel);
|
||||
read_abs_bbt (this, buf, rd, chipsel);
|
||||
/* If they weren't versioned, read both. */
|
||||
if (rd2)
|
||||
read_abs_bbt (mtd, buf, rd2, chipsel);
|
||||
read_abs_bbt (this, buf, rd2, chipsel);
|
||||
|
||||
/* Write the bad block table to the device ? */
|
||||
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt (mtd, buf, td, md, chipsel);
|
||||
res = write_bbt (this, buf, td, md, chipsel);
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Write the mirror bad block table to the device ? */
|
||||
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt (mtd, buf, md, td, chipsel);
|
||||
res = write_bbt (this, buf, md, td, chipsel);
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
|
@ -718,9 +709,8 @@ writecheck:
|
|||
* accidental erasures / writes. The regions are identified by
|
||||
* the mark 0x02.
|
||||
*/
|
||||
static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
static void mark_bbt_region (struct nand_chip *this, struct nand_bbt_descr *td)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int i, j, chips, block, nrblocks, update;
|
||||
uint8_t oldval, newval;
|
||||
|
||||
|
@ -730,7 +720,7 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
|
|||
nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
|
||||
} else {
|
||||
chips = 1;
|
||||
nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
|
||||
nrblocks = (int)(this->size >> this->bbt_erase_shift);
|
||||
}
|
||||
|
||||
for (i = 0; i < chips; i++) {
|
||||
|
@ -743,7 +733,7 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
|
|||
newval = oldval | (0x2 << (block & 0x06));
|
||||
this->bbt[(block >> 3)] = newval;
|
||||
if ((oldval != newval) && td->reserved_block_code)
|
||||
nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1));
|
||||
nand_update_bbt(this, block << (this->bbt_erase_shift - 1));
|
||||
continue;
|
||||
}
|
||||
update = 0;
|
||||
|
@ -763,7 +753,7 @@ 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
|
||||
bbts. This should only happen once. */
|
||||
if (update && td->reserved_block_code)
|
||||
nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1));
|
||||
nand_update_bbt(this, (block - 2) << (this->bbt_erase_shift - 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -781,15 +771,14 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
|
|||
* by calling the nand_free_bbt function.
|
||||
*
|
||||
*/
|
||||
int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
int nand_scan_bbt (struct nand_chip *this, struct nand_bbt_descr *bd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int len, res = 0;
|
||||
uint8_t *buf;
|
||||
struct nand_bbt_descr *td = this->bbt_td;
|
||||
struct nand_bbt_descr *md = this->bbt_md;
|
||||
|
||||
len = mtd->size >> (this->bbt_erase_shift + 2);
|
||||
len = this->size >> (this->bbt_erase_shift + 2);
|
||||
/* Allocate memory (2bit per block) */
|
||||
this->bbt = kmalloc (len, GFP_KERNEL);
|
||||
if (!this->bbt) {
|
||||
|
@ -803,11 +792,11 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
|||
* to build a memory based bad block table
|
||||
*/
|
||||
if (!td)
|
||||
return nand_memory_bbt(mtd, bd);
|
||||
return nand_memory_bbt(this, bd);
|
||||
|
||||
/* Allocate a temporary buffer for one eraseblock incl. oob */
|
||||
len = (1 << this->bbt_erase_shift);
|
||||
len += (len >> this->page_shift) * mtd->oobsize;
|
||||
len += (len >> this->page_shift) * this->oobsize;
|
||||
buf = kmalloc (len, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
printk (KERN_ERR "nand_bbt: Out of memory\n");
|
||||
|
@ -818,19 +807,19 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
|||
|
||||
/* Is the bbt at a given page ? */
|
||||
if (td->options & NAND_BBT_ABSPAGE) {
|
||||
res = read_abs_bbts (mtd, buf, td, md);
|
||||
res = read_abs_bbts (this, buf, td, md);
|
||||
} else {
|
||||
/* Search the bad block table using a pattern in oob */
|
||||
res = search_read_bbts (mtd, buf, td, md);
|
||||
res = search_read_bbts (this, buf, td, md);
|
||||
}
|
||||
|
||||
if (res)
|
||||
res = check_create (mtd, buf, bd);
|
||||
res = check_create (this, buf, bd);
|
||||
|
||||
/* Prevent the bbt regions from erasing / writing */
|
||||
mark_bbt_region (mtd, td);
|
||||
mark_bbt_region (this, td);
|
||||
if (md)
|
||||
mark_bbt_region (mtd, md);
|
||||
mark_bbt_region (this, md);
|
||||
|
||||
kfree (buf);
|
||||
return res;
|
||||
|
@ -844,9 +833,8 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
|||
*
|
||||
* The function updates the bad block table(s)
|
||||
*/
|
||||
int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
|
||||
int nand_update_bbt (struct nand_chip *this, loff_t offs)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int len, res = 0, writeops = 0;
|
||||
int chip, chipsel;
|
||||
uint8_t *buf;
|
||||
|
@ -856,10 +844,10 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
|
|||
if (!this->bbt || !td)
|
||||
return -EINVAL;
|
||||
|
||||
len = mtd->size >> (this->bbt_erase_shift + 2);
|
||||
len = this->size >> (this->bbt_erase_shift + 2);
|
||||
/* Allocate a temporary buffer for one eraseblock incl. oob */
|
||||
len = (1 << this->bbt_erase_shift);
|
||||
len += (len >> this->page_shift) * mtd->oobsize;
|
||||
len += (len >> this->page_shift) * this->oobsize;
|
||||
buf = kmalloc (len, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
printk (KERN_ERR "nand_update_bbt: Out of memory\n");
|
||||
|
@ -883,13 +871,13 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
|
|||
|
||||
/* Write the bad block table to the device ? */
|
||||
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt (mtd, buf, td, md, chipsel);
|
||||
res = write_bbt (this, buf, td, md, chipsel);
|
||||
if (res < 0)
|
||||
goto out;
|
||||
}
|
||||
/* Write the mirror bad block table to the device ? */
|
||||
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt (mtd, buf, md, td, chipsel);
|
||||
res = write_bbt (this, buf, md, td, chipsel);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -974,10 +962,8 @@ static struct nand_bbt_descr bbt_mirror_descr = {
|
|||
* support for the device and calls the nand_scan_bbt function
|
||||
*
|
||||
*/
|
||||
int nand_default_bbt (struct mtd_info *mtd)
|
||||
int nand_default_bbt (struct nand_chip *this)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
/* Default for AG-AND. We must use a flash based
|
||||
* bad block table as the devices have factory marked
|
||||
* _good_ blocks. Erasing those blocks leads to loss
|
||||
|
@ -992,7 +978,7 @@ int nand_default_bbt (struct mtd_info *mtd)
|
|||
this->bbt_md = &bbt_mirror_descr;
|
||||
}
|
||||
this->options |= NAND_USE_FLASH_BBT;
|
||||
return nand_scan_bbt (mtd, &agand_flashbased);
|
||||
return nand_scan_bbt (this, &agand_flashbased);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1004,18 +990,18 @@ int nand_default_bbt (struct mtd_info *mtd)
|
|||
this->bbt_md = &bbt_mirror_descr;
|
||||
}
|
||||
if (!this->badblock_pattern) {
|
||||
this->badblock_pattern = (mtd->oobblock > 512) ?
|
||||
this->badblock_pattern = (this->oobblock > 512) ?
|
||||
&largepage_flashbased : &smallpage_flashbased;
|
||||
}
|
||||
} else {
|
||||
this->bbt_td = NULL;
|
||||
this->bbt_md = NULL;
|
||||
if (!this->badblock_pattern) {
|
||||
this->badblock_pattern = (mtd->oobblock > 512) ?
|
||||
this->badblock_pattern = (this->oobblock > 512) ?
|
||||
&largepage_memorybased : &smallpage_memorybased;
|
||||
}
|
||||
}
|
||||
return nand_scan_bbt (mtd, this->badblock_pattern);
|
||||
return nand_scan_bbt (this, this->badblock_pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1025,9 +1011,8 @@ int nand_default_bbt (struct mtd_info *mtd)
|
|||
* @allowbbt: allow access to bad block table region
|
||||
*
|
||||
*/
|
||||
int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
|
||||
int nand_isbad_bbt (struct nand_chip *this, loff_t offs, int allowbbt)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int block;
|
||||
uint8_t res;
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ static void nand_trans_result(u_char reg2, u_char reg3,
|
|||
* @dat: raw data
|
||||
* @ecc_code: buffer for ECC
|
||||
*/
|
||||
int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
|
||||
int nand_calculate_ecc(struct nand_chip *nand, const u_char *dat, u_char *ecc_code)
|
||||
{
|
||||
u_char idx, reg1, reg2, reg3;
|
||||
int j;
|
||||
|
@ -154,7 +154,7 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code
|
|||
*
|
||||
* Detect and correct a 1 bit error for 256 byte block
|
||||
*/
|
||||
int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
|
||||
int nand_correct_data(struct nand_chip *nand, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
u_char a, b, c, d1, d2, d3, add, bit, i;
|
||||
|
||||
|
|
|
@ -2,110 +2,129 @@
|
|||
* drivers/mtd/nandids.c
|
||||
*
|
||||
* Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
|
||||
*
|
||||
* $Id: nand_ids.c,v 1.10 2004/05/26 13:40:12 gleixner Exp $
|
||||
*
|
||||
* $Id: nand_ids.c,v 1.16 2005/11/07 11:14:31 gleixner Exp $
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
|
||||
/*
|
||||
* Chip ID list
|
||||
*
|
||||
* Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
|
||||
* options
|
||||
*
|
||||
* Pagesize; 0, 256, 512
|
||||
* 0 get this information from the extended chip ID
|
||||
* Pagesize; 0, 256, 512
|
||||
* 0 get this information from the extended chip ID
|
||||
+ 256 256 Byte page size
|
||||
* 512 512 Byte page size
|
||||
*/
|
||||
struct nand_flash_dev nand_flash_ids[] = {
|
||||
{"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
|
||||
{"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
|
||||
{"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
|
||||
{"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0},
|
||||
{"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
|
||||
{"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0},
|
||||
{"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
|
||||
{"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0},
|
||||
{"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0},
|
||||
{"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0},
|
||||
|
||||
{"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0},
|
||||
{"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
|
||||
{"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
|
||||
{"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
|
||||
#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
|
||||
{"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
|
||||
{"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
|
||||
{"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
|
||||
{"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0},
|
||||
{"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
|
||||
{"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0},
|
||||
{"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
|
||||
{"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0},
|
||||
{"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0},
|
||||
{"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0},
|
||||
|
||||
{"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
|
||||
{"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
|
||||
{"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0},
|
||||
{"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
|
||||
{"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
|
||||
{"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
|
||||
#endif
|
||||
|
||||
{"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0},
|
||||
{"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0},
|
||||
{"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
|
||||
{"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
|
||||
{"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
|
||||
|
||||
{"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0},
|
||||
{"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0},
|
||||
{"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0},
|
||||
{"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0},
|
||||
{"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
|
||||
|
||||
{"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},
|
||||
{"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},
|
||||
{"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0},
|
||||
{"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0},
|
||||
{"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
|
||||
|
||||
{"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},
|
||||
{"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},
|
||||
{"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0},
|
||||
{"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},
|
||||
{"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
||||
{"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
|
||||
|
||||
{"NAND 512MiB 3,3V 8-bit", 0xDC, 512, 512, 0x4000, 0},
|
||||
{"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},
|
||||
|
||||
/*
|
||||
* These are the new chips with large page size. The pagesize and the
|
||||
* erasesize is determined from the extended id bytes
|
||||
*/
|
||||
#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR)
|
||||
#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
|
||||
|
||||
/*512 Megabit */
|
||||
{"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS},
|
||||
{"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS},
|
||||
{"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16},
|
||||
{"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16},
|
||||
|
||||
/* These are the new chips with large page size. The pagesize
|
||||
* and the erasesize is determined from the extended id bytes
|
||||
*/
|
||||
/* 1 Gigabit */
|
||||
{"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS},
|
||||
{"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, LP_OPTIONS},
|
||||
{"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16},
|
||||
{"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16},
|
||||
|
||||
/* 2 Gigabit */
|
||||
{"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS},
|
||||
{"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, LP_OPTIONS},
|
||||
{"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, LP_OPTIONS16},
|
||||
{"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, LP_OPTIONS16},
|
||||
|
||||
/* 4 Gigabit */
|
||||
{"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, LP_OPTIONS},
|
||||
{"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, LP_OPTIONS},
|
||||
{"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, LP_OPTIONS16},
|
||||
{"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, LP_OPTIONS16},
|
||||
|
||||
/* 8 Gigabit */
|
||||
{"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, LP_OPTIONS},
|
||||
{"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, LP_OPTIONS},
|
||||
{"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, LP_OPTIONS16},
|
||||
{"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, LP_OPTIONS16},
|
||||
|
||||
/* 16 Gigabit */
|
||||
{"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
|
||||
{"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
|
||||
{"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, LP_OPTIONS},
|
||||
{"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, LP_OPTIONS},
|
||||
{"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16},
|
||||
{"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16},
|
||||
|
||||
/* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
|
||||
* The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
|
||||
* 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
|
||||
* Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
|
||||
* There are more speed improvements for reads and writes possible, but not implemented now
|
||||
/*
|
||||
* Renesas AND 1 Gigabit. Those chips do not support extended id and
|
||||
* have a strange page/block layout ! The chosen minimum erasesize is
|
||||
* 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page
|
||||
* planes 1 block = 2 pages, but due to plane arrangement the blocks
|
||||
* 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would
|
||||
* increase the eraseblock size so we chose a combined one which can be
|
||||
* erased in one go There are more speed improvements for reads and
|
||||
* writes possible, but not implemented now
|
||||
*/
|
||||
{"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},
|
||||
{"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000,
|
||||
NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY |
|
||||
BBT_AUTO_REFRESH
|
||||
},
|
||||
|
||||
{NULL,}
|
||||
};
|
||||
|
@ -120,6 +139,8 @@ struct nand_manufacturers nand_manuf_ids[] = {
|
|||
{NAND_MFR_NATIONAL, "National"},
|
||||
{NAND_MFR_RENESAS, "Renesas"},
|
||||
{NAND_MFR_STMICRO, "ST Micro"},
|
||||
{NAND_MFR_HYNIX, "Hynix"},
|
||||
{NAND_MFR_MICRON, "Micron"},
|
||||
{0x0, "Unknown"}
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
fail_addr = 0xffffffff, the failure was not at the device level or was not
|
||||
specific to any particular block. */
|
||||
struct erase_info {
|
||||
struct mtd_info *mtd;
|
||||
struct nand_chip *nand;
|
||||
u_int32_t addr;
|
||||
u_int32_t len;
|
||||
u_int32_t fail_addr;
|
||||
|
@ -43,92 +43,6 @@ struct mtd_erase_region_info {
|
|||
u_int32_t numblocks; /* Number of blocks of erasesize in this region */
|
||||
};
|
||||
|
||||
struct mtd_info {
|
||||
u_char type;
|
||||
u_int32_t flags;
|
||||
u_int32_t size; /* Total size of the MTD */
|
||||
|
||||
/* "Major" erase size for the device. Naïve users may take this
|
||||
* to be the only erase size available, or may use the more detailed
|
||||
* information below if they desire
|
||||
*/
|
||||
u_int32_t erasesize;
|
||||
|
||||
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 oobavail; /* Number of bytes in OOB area available for fs */
|
||||
u_int32_t ecctype;
|
||||
u_int32_t eccsize;
|
||||
|
||||
|
||||
/* Kernel-only stuff starts here. */
|
||||
char *name;
|
||||
int index;
|
||||
|
||||
/* oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) */
|
||||
struct nand_oobinfo oobinfo;
|
||||
|
||||
/* Data for variable erase regions. If numeraseregions is zero,
|
||||
* it means that the whole device has erasesize as given above.
|
||||
*/
|
||||
int numeraseregions;
|
||||
struct mtd_erase_region_info *eraseregions;
|
||||
|
||||
/* This really shouldn't be here. It can go away in 2.5 */
|
||||
u_int32_t bank_size;
|
||||
|
||||
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
|
||||
|
||||
/* This stuff for eXecute-In-Place */
|
||||
int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
|
||||
|
||||
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
|
||||
void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
|
||||
|
||||
|
||||
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
|
||||
|
||||
int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
|
||||
int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
|
||||
|
||||
int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
|
||||
|
||||
/*
|
||||
* Methods to access the protection register area, present in some
|
||||
* flash devices. The user data is one time programmable but the
|
||||
* factory data is read only.
|
||||
*/
|
||||
int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
|
||||
int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
|
||||
/* This function is not yet implemented */
|
||||
int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
/* Sync */
|
||||
void (*sync) (struct mtd_info *mtd);
|
||||
/* Bad block management functions */
|
||||
int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
|
||||
int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
|
||||
|
||||
void *priv;
|
||||
|
||||
struct module *owner;
|
||||
int usecount;
|
||||
};
|
||||
|
||||
|
||||
/* Kernel-side ioctl definitions */
|
||||
|
||||
extern int add_mtd_device(struct mtd_info *mtd);
|
||||
extern int del_mtd_device (struct mtd_info *mtd);
|
||||
|
||||
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
|
||||
|
||||
extern void put_mtd_device(struct mtd_info *mtd);
|
||||
|
||||
|
||||
#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
|
||||
#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
|
||||
#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
|
||||
|
|
|
@ -54,15 +54,16 @@
|
|||
|
||||
#include <linux/mtd/compat.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <driver.h>
|
||||
|
||||
struct mtd_info;
|
||||
struct nand_chip;
|
||||
/* Scan and identify a NAND device */
|
||||
extern int nand_scan (struct mtd_info *mtd, int max_chips);
|
||||
extern int nand_scan (struct nand_chip *, int max_chips);
|
||||
/* Free resources held by the NAND device */
|
||||
extern void nand_release (struct mtd_info *mtd);
|
||||
extern void nand_release (struct nand_chip *);
|
||||
|
||||
/* Read raw data from the device without ECC */
|
||||
extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
|
||||
extern int nand_read_raw (struct nand_chip *, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
|
||||
|
||||
|
||||
/* This constant declares the max. oobsize / page, which
|
||||
|
@ -165,6 +166,16 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
|
|||
/* Chip has a array of 4 pages which can be read without
|
||||
* additional ready /busy waits */
|
||||
#define NAND_4PAGE_ARRAY 0x00000040
|
||||
/* Chip requires that BBT is periodically rewritten to prevent
|
||||
* bits from adjacent blocks from 'leaking' in altering data.
|
||||
* This happens with the Renesas AG-AND chips, possibly others. */
|
||||
#define BBT_AUTO_REFRESH 0x00000080
|
||||
/* Chip does not require ready check on read. True
|
||||
* for all large page devices, as they do not support
|
||||
* autoincrement.*/
|
||||
#define NAND_NO_READRDY 0x00000100
|
||||
/* Chip does not allow subpage writes */
|
||||
#define NAND_NO_SUBPAGE_WRITE 0x00000200
|
||||
|
||||
/* Options valid for Samsung large page devices */
|
||||
#define NAND_SAMSUNG_LP_OPTIONS \
|
||||
|
@ -275,26 +286,26 @@ struct nand_chip {
|
|||
void __iomem *IO_ADDR_R;
|
||||
void __iomem *IO_ADDR_W;
|
||||
|
||||
u_char (*read_byte)(struct mtd_info *mtd);
|
||||
void (*write_byte)(struct mtd_info *mtd, u_char byte);
|
||||
u16 (*read_word)(struct mtd_info *mtd);
|
||||
void (*write_word)(struct mtd_info *mtd, u16 word);
|
||||
u_char (*read_byte)(struct nand_chip *);
|
||||
void (*write_byte)(struct nand_chip *, u_char byte);
|
||||
u16 (*read_word)(struct nand_chip *);
|
||||
void (*write_word)(struct nand_chip *, u16 word);
|
||||
|
||||
void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
|
||||
void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
|
||||
int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
|
||||
void (*select_chip)(struct mtd_info *mtd, int chip);
|
||||
int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
|
||||
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
|
||||
void (*hwcontrol)(struct mtd_info *mtd, int cmd);
|
||||
int (*dev_ready)(struct mtd_info *mtd);
|
||||
void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
|
||||
int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
|
||||
int (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
|
||||
int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
|
||||
void (*enable_hwecc)(struct mtd_info *mtd, int mode);
|
||||
void (*erase_cmd)(struct mtd_info *mtd, int page);
|
||||
int (*scan_bbt)(struct mtd_info *mtd);
|
||||
void (*write_buf)(struct nand_chip *, const u_char *buf, int len);
|
||||
void (*read_buf)(struct nand_chip *, u_char *buf, int len);
|
||||
int (*verify_buf)(struct nand_chip *, const u_char *buf, int len);
|
||||
void (*select_chip)(struct nand_chip *, int chip);
|
||||
int (*block_bad)(struct nand_chip *, loff_t ofs, int getchip);
|
||||
int (*block_markbad)(struct nand_chip *, loff_t ofs);
|
||||
void (*hwcontrol)(struct nand_chip *, int cmd);
|
||||
int (*dev_ready)(struct nand_chip *);
|
||||
void (*cmdfunc)(struct nand_chip *, unsigned command, int column, int page_addr);
|
||||
int (*waitfunc)(struct nand_chip *, int state);
|
||||
int (*calculate_ecc)(struct nand_chip *, const u_char *dat, u_char *ecc_code);
|
||||
int (*correct_data)(struct nand_chip *, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
|
||||
void (*enable_hwecc)(struct nand_chip *, int mode);
|
||||
void (*erase_cmd)(struct nand_chip *, int page);
|
||||
int (*scan_bbt)(struct nand_chip *);
|
||||
int eccmode;
|
||||
int eccsize;
|
||||
int eccbytes;
|
||||
|
@ -321,6 +332,55 @@ struct nand_chip {
|
|||
struct nand_bbt_descr *badblock_pattern;
|
||||
struct nand_hw_control *controller;
|
||||
void *priv;
|
||||
|
||||
|
||||
/* Members formerly from mtd_info */
|
||||
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 oobavail; /* Number of bytes in OOB area available for fs */
|
||||
u_int32_t ecctype;
|
||||
|
||||
/* "Major" erase size for the device. Naïve users may take this
|
||||
* to be the only erase size available, or may use the more detailed
|
||||
* information below if they desire
|
||||
*/
|
||||
u_int32_t erasesize;
|
||||
|
||||
/* Kernel-only stuff starts here. */
|
||||
char *name;
|
||||
u_int32_t size; /* Total size of the MTD */
|
||||
|
||||
int (*read_ecc) (struct nand_chip *, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
|
||||
int (*write_ecc) (struct nand_chip *, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
|
||||
|
||||
int (*read_oob) (struct nand_chip *, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
int (*write_oob) (struct nand_chip *, loff_t to, size_t len, size_t *retlen, const u_char *buf);
|
||||
|
||||
/* Sync */
|
||||
void (*sync) (struct nand_chip *);
|
||||
/* Bad block management functions */
|
||||
int (*block_isbad) (struct nand_chip *, loff_t ofs);
|
||||
|
||||
int (*read) (struct nand_chip *, loff_t from, size_t len, size_t *retlen, u_char *buf);
|
||||
int (*write) (struct nand_chip *, loff_t to, size_t len, size_t *retlen, const u_char *buf);
|
||||
|
||||
/* oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) */
|
||||
struct nand_oobinfo oobinfo;
|
||||
|
||||
u_char type;
|
||||
u_int32_t flags;
|
||||
int (*erase) (struct nand_chip *, struct erase_info *instr);
|
||||
|
||||
/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
|
||||
* though individual bits can be cleared), in case of NAND flash it is
|
||||
* one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
|
||||
* it is of ECC block size, etc. It is illegal to have writesize = 0.
|
||||
* Any driver registering a struct mtd_info must ensure a writesize of
|
||||
* 1 or larger.
|
||||
*/
|
||||
u_int32_t writesize;
|
||||
|
||||
struct device_d dev;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -332,6 +392,8 @@ struct nand_chip {
|
|||
#define NAND_MFR_NATIONAL 0x8f
|
||||
#define NAND_MFR_RENESAS 0x07
|
||||
#define NAND_MFR_STMICRO 0x20
|
||||
#define NAND_MFR_HYNIX 0xad
|
||||
#define NAND_MFR_MICRON 0x2c
|
||||
|
||||
/**
|
||||
* struct nand_flash_dev - NAND Flash Device ID Structure
|
||||
|
@ -437,11 +499,11 @@ struct nand_bbt_descr {
|
|||
/* The maximum number of blocks to scan for a bbt */
|
||||
#define NAND_BBT_SCAN_MAXBLOCKS 4
|
||||
|
||||
extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
|
||||
extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
|
||||
extern int nand_default_bbt (struct mtd_info *mtd);
|
||||
extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
|
||||
extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
|
||||
extern int nand_scan_bbt (struct nand_chip *, struct nand_bbt_descr *bd);
|
||||
extern int nand_update_bbt (struct nand_chip *, loff_t offs);
|
||||
extern int nand_default_bbt (struct nand_chip *);
|
||||
extern int nand_isbad_bbt (struct nand_chip *, loff_t offs, int allowbbt);
|
||||
extern int nand_erase_nand (struct nand_chip *, struct erase_info *instr, int allowbbt);
|
||||
|
||||
/*
|
||||
* Constants for oob configuration
|
||||
|
|
|
@ -20,11 +20,11 @@ struct mtd_info;
|
|||
/*
|
||||
* Calculate 3 byte ECC code for 256 byte block
|
||||
*/
|
||||
int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
|
||||
int nand_calculate_ecc(struct nand_chip *, const u_char *dat, u_char *ecc_code);
|
||||
|
||||
/*
|
||||
* Detect and correct a 1 bit error for 256 byte block
|
||||
*/
|
||||
int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
|
||||
int nand_correct_data(struct nand_chip *, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
|
||||
|
||||
#endif /* __MTD_NAND_ECC_H__ */
|
||||
|
|
124
include/nand.h
124
include/nand.h
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2005
|
||||
* 2N Telekomunikace, a.s. <www.2n.cz>
|
||||
* Ladislav Michl <michl@2n.cz>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _NAND_H_
|
||||
#define _NAND_H_
|
||||
|
||||
#include <linux/mtd/compat.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
|
||||
typedef struct mtd_info nand_info_t;
|
||||
|
||||
extern int nand_curr_device;
|
||||
extern nand_info_t nand_info[];
|
||||
|
||||
static inline int nand_read(nand_info_t *info, ulong ofs, ulong *len, u_char *buf)
|
||||
{
|
||||
return info->read(info, ofs, *len, (size_t *)len, buf);
|
||||
}
|
||||
|
||||
static inline int nand_write(nand_info_t *info, ulong ofs, ulong *len, u_char *buf)
|
||||
{
|
||||
return info->write(info, ofs, *len, (size_t *)len, buf);
|
||||
}
|
||||
|
||||
static inline int nand_block_isbad(nand_info_t *info, ulong ofs)
|
||||
{
|
||||
return info->block_isbad(info, ofs);
|
||||
}
|
||||
|
||||
static inline int nand_erase(nand_info_t *info, ulong off, ulong size)
|
||||
{
|
||||
struct erase_info instr;
|
||||
|
||||
instr.mtd = info;
|
||||
instr.addr = off;
|
||||
instr.len = size;
|
||||
instr.callback = 0;
|
||||
|
||||
return info->erase(info, &instr);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* declarations from nand_util.c
|
||||
****************************************************************************/
|
||||
|
||||
struct nand_write_options {
|
||||
u_char *buffer; /* memory block containing image to write */
|
||||
ulong length; /* number of bytes to write */
|
||||
ulong offset; /* start address in NAND */
|
||||
int quiet; /* don't display progress messages */
|
||||
int autoplace; /* if true use auto oob layout */
|
||||
int forcejffs2; /* force jffs2 oob layout */
|
||||
int forceyaffs; /* force yaffs oob layout */
|
||||
int noecc; /* write without ecc */
|
||||
int writeoob; /* image contains oob data */
|
||||
int pad; /* pad to page size */
|
||||
int blockalign; /* 1|2|4 set multiple of eraseblocks
|
||||
* to align to */
|
||||
};
|
||||
|
||||
typedef struct nand_write_options nand_write_options_t;
|
||||
|
||||
struct nand_read_options {
|
||||
u_char *buffer; /* memory block in which read image is written*/
|
||||
ulong length; /* number of bytes to read */
|
||||
ulong offset; /* start address in NAND */
|
||||
int quiet; /* don't display progress messages */
|
||||
int readoob; /* put oob data in image */
|
||||
};
|
||||
|
||||
typedef struct nand_read_options nand_read_options_t;
|
||||
|
||||
struct nand_erase_options {
|
||||
ulong length; /* number of bytes to erase */
|
||||
ulong offset; /* first address in NAND to erase */
|
||||
int quiet; /* don't display progress messages */
|
||||
int jffs2; /* if true: format for jffs2 usage
|
||||
* (write appropriate cleanmarker blocks) */
|
||||
int scrub; /* if true, really clean NAND by erasing
|
||||
* bad blocks (UNSAFE) */
|
||||
};
|
||||
|
||||
typedef struct nand_erase_options nand_erase_options_t;
|
||||
|
||||
int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts);
|
||||
|
||||
int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts);
|
||||
int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
|
||||
|
||||
#define NAND_LOCK_STATUS_TIGHT 0x01
|
||||
#define NAND_LOCK_STATUS_LOCK 0x02
|
||||
#define NAND_LOCK_STATUS_UNLOCK 0x04
|
||||
|
||||
int nand_lock( nand_info_t *meminfo, int tight );
|
||||
int nand_unlock( nand_info_t *meminfo, ulong start, ulong length );
|
||||
int nand_get_lock_status(nand_info_t *meminfo, ulong offset);
|
||||
|
||||
#ifdef CFG_NAND_SELECT_DEVICE
|
||||
void board_nand_select_device(struct nand_chip *nand, int chip);
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue