summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/jedec_flash.c18
-rw-r--r--drivers/mtd/nand/atmel_nand.c2
-rw-r--r--drivers/mtd/nand/nand.c2
-rw-r--r--drivers/mtd/nand/nand_base.c29
-rw-r--r--drivers/mtd/nand/nand_util.c63
5 files changed, 90 insertions, 24 deletions
diff --git a/drivers/mtd/jedec_flash.c b/drivers/mtd/jedec_flash.c
index 223fb71..da8c9b1 100644
--- a/drivers/mtd/jedec_flash.c
+++ b/drivers/mtd/jedec_flash.c
@@ -41,6 +41,7 @@
#define AM29DL800BB 0x22CB
#define AM29DL800BT 0x224A
+#define AM29F400BB 0x22AB
#define AM29F800BB 0x2258
#define AM29F800BT 0x22D6
#define AM29LV400BB 0x22BA
@@ -296,6 +297,23 @@ static const struct amd_flash_info jedec_table[] = {
#ifdef CONFIG_SYS_FLASH_LEGACY_512Kx16
{
.mfr_id = (u16)AMD_MANUFACT,
+ .dev_id = AM29F400BB,
+ .name = "AMD AM29F400BB",
+ .uaddr = {
+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
+ },
+ .DevSize = SIZE_512KiB,
+ .CmdSet = CFI_CMDSET_AMD_LEGACY,
+ .NumEraseRegions= 4,
+ .regions = {
+ ERASEINFO(0x04000, 1),
+ ERASEINFO(0x02000, 2),
+ ERASEINFO(0x08000, 1),
+ ERASEINFO(0x10000, 7),
+ }
+ },
+ {
+ .mfr_id = (u16)AMD_MANUFACT,
.dev_id = AM29LV400BB,
.name = "AMD AM29LV400BB",
.uaddr = {
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index d5eb54a..ab8bbb3 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -296,7 +296,7 @@ int board_nand_init(struct nand_chip *nand)
mtd->priv = nand;
/* Detect NAND chips */
- if (nand_scan_ident(mtd, 1)) {
+ if (nand_scan_ident(mtd, 1, NULL)) {
printk(KERN_WARNING "NAND Flash not found !\n");
return -ENXIO;
}
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c
index c0e068a..d987f4c 100644
--- a/drivers/mtd/nand/nand.c
+++ b/drivers/mtd/nand/nand.c
@@ -43,7 +43,7 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand,
ulong base_addr)
{
int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;
- int __attribute__((unused)) i = 0;
+ static int __attribute__((unused)) i = 0;
if (maxchips < 1)
maxchips = 1;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 5239c1f..3b96b0e 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2414,10 +2414,10 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
*/
static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
struct nand_chip *chip,
- int busw, int *maf_id)
+ int busw, int *maf_id,
+ const struct nand_flash_dev *type)
{
- const struct nand_flash_dev *type = NULL;
- int i, dev_id, maf_idx;
+ int dev_id, maf_idx;
int tmp_id, tmp_manf;
/* Select the device */
@@ -2456,15 +2456,14 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
return ERR_PTR(-ENODEV);
}
- /* Lookup the flash id */
- for (i = 0; nand_flash_ids[i].name != NULL; i++) {
- if (dev_id == nand_flash_ids[i].id) {
- type = &nand_flash_ids[i];
- break;
- }
- }
+ if (!type)
+ type = nand_flash_ids;
+
+ for (; type->name != NULL; type++)
+ if (dev_id == type->id)
+ break;
- if (!type) {
+ if (!type->name) {
/* supress warning if there is no nand */
if (*maf_id != 0x00 && *maf_id != 0xff &&
dev_id != 0x00 && dev_id != 0xff)
@@ -2580,13 +2579,15 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
* nand_scan_ident - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure
* @maxchips: Number of chips to scan for
+ * @table: Alternative NAND ID table
*
* This is the first phase of the normal nand_scan() function. It
* reads the flash ID and sets up MTD fields accordingly.
*
* The mtd->owner field must be set to the module of the caller.
*/
-int nand_scan_ident(struct mtd_info *mtd, int maxchips)
+int nand_scan_ident(struct mtd_info *mtd, int maxchips,
+ const struct nand_flash_dev *table)
{
int i, busw, nand_maf_id;
struct nand_chip *chip = mtd->priv;
@@ -2598,7 +2599,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
nand_set_defaults(chip, busw);
/* Read the flash type */
- type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
+ type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id, table);
if (IS_ERR(type)) {
#ifndef CONFIG_SYS_NAND_QUIET_TEST
@@ -2869,7 +2870,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
{
int ret;
- ret = nand_scan_ident(mtd, maxchips);
+ ret = nand_scan_ident(mtd, maxchips, NULL);
if (!ret)
ret = nand_scan_tail(mtd);
return ret;
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 22c7411..8b4f738 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -447,17 +447,34 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
* @param nand NAND device
* @param offset offset in flash
* @param length buffer length
- * @param buf buffer to read from
+ * @param buffer buffer to read from
+ * @param withoob whether write with yaffs format
* @return 0 in case of success
*/
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
- u_char *buffer)
+ u_char *buffer, int withoob)
{
- int rval;
+ int rval = 0, blocksize;
size_t left_to_write = *length;
u_char *p_buffer = buffer;
int need_skip;
+#ifdef CONFIG_CMD_NAND_YAFFS
+ if (withoob) {
+ int pages;
+ pages = nand->erasesize / nand->writesize;
+ blocksize = (pages * nand->oobsize) + nand->erasesize;
+ if (*length % (nand->writesize + nand->oobsize)) {
+ printf ("Attempt to write incomplete page"
+ " in yaffs mode\n");
+ return -EINVAL;
+ }
+ } else
+#endif
+ {
+ blocksize = nand->erasesize;
+ }
+
/*
* nand_write() handles unaligned, partial page writes.
*
@@ -506,12 +523,44 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
continue;
}
- if (left_to_write < (nand->erasesize - block_offset))
+ if (left_to_write < (blocksize - block_offset))
write_size = left_to_write;
else
- write_size = nand->erasesize - block_offset;
+ write_size = blocksize - block_offset;
+
+#ifdef CONFIG_CMD_NAND_YAFFS
+ if (withoob) {
+ int page, pages;
+ size_t pagesize = nand->writesize;
+ size_t pagesize_oob = pagesize + nand->oobsize;
+ struct mtd_oob_ops ops;
+
+ ops.len = pagesize;
+ ops.ooblen = nand->oobsize;
+ ops.mode = MTD_OOB_AUTO;
+ ops.ooboffs = 0;
+
+ pages = write_size / pagesize_oob;
+ for (page = 0; page < pages; page++) {
+ ops.datbuf = p_buffer;
+ ops.oobbuf = ops.datbuf + pagesize;
+
+ rval = nand->write_oob(nand, offset, &ops);
+ if (!rval)
+ break;
+
+ offset += pagesize;
+ p_buffer += pagesize_oob;
+ }
+ }
+ else
+#endif
+ {
+ rval = nand_write (nand, offset, &write_size, p_buffer);
+ offset += write_size;
+ p_buffer += write_size;
+ }
- rval = nand_write (nand, offset, &write_size, p_buffer);
if (rval != 0) {
printf ("NAND write to offset %llx failed %d\n",
offset, rval);
@@ -520,8 +569,6 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
}
left_to_write -= write_size;
- offset += write_size;
- p_buffer += write_size;
}
return 0;