9
0
Fork 0

NAND support work in progress

This commit is contained in:
sascha 2007-10-20 01:13:46 +02:00
parent d24db665ac
commit 3f90fc9d3e
10 changed files with 585 additions and 1121 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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"}
};

View File

@ -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)

View File

@ -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

View File

@ -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__ */

View File

@ -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