static int set_dev(int dev)
{
- if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
- !nand_info[dev].name) {
- puts("No such device\n");
- return -1;
- }
+ struct mtd_info *mtd = get_nand_dev_by_index(dev);
+
+ if (!mtd)
+ return -ENODEV;
if (nand_curr_device == dev)
return 0;
- printf("Device %d: %s", dev, nand_info[dev].name);
+ printf("Device %d: %s", dev, mtd->name);
puts("... is now current device\n");
nand_curr_device = dev;
#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
- board_nand_select_device(nand_info[dev].priv, dev);
+ board_nand_select_device(mtd_to_nand(mtd), dev);
#endif
return 0;
ulong off;
int last_status = -1;
- struct nand_chip *nand_chip = mtd->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
/* check the WP bit */
nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
printf("device is %swrite protected\n",
{
int ret;
uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
- struct mtd_info *mtd = &nand_info[0];
+ struct mtd_info *mtd = get_nand_dev_by_index(0);
char *cmd = argv[1];
- if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd->name) {
+ if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
puts("no devices available\n");
return 1;
}
if (argc < 3)
goto usage;
+ mtd = get_nand_dev_by_index(idx);
/* We don't care about size, or maxsize. */
if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
- MTD_DEV_TYPE_NAND, nand_info[idx].size)) {
+ MTD_DEV_TYPE_NAND, mtd->size)) {
puts("Offset or partition name expected\n");
return 1;
}
static void nand_print_and_set_info(int idx)
{
- struct mtd_info *mtd = &nand_info[idx];
- struct nand_chip *chip = mtd->priv;
+ struct mtd_info *mtd;
+ struct nand_chip *chip;
+ mtd = get_nand_dev_by_index(idx);
+ if (!mtd)
+ return;
+
+ chip = mtd_to_nand(mtd);
printf("Device %d: ", idx);
if (chip->numchips > 1)
printf("%dx ", chip->numchips);
printf(" OOB size %8d b\n", mtd->oobsize);
printf(" Erase size %8d b\n", mtd->erasesize);
printf(" subpagesize %8d b\n", chip->subpagesize);
- printf(" options 0x%8x\n", chip->options);
- printf(" bbt options 0x%8x\n", chip->bbt_options);
+ printf(" options 0x%08x\n", chip->options);
+ printf(" bbt options 0x%08x\n", chip->bbt_options);
/* Set geometry info */
setenv_hex("nand_writesize", mtd->writesize);
}
static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
- ulong count, int read)
+ ulong count, int read, int no_verify)
{
int ret = 0;
ret = mtd_read_oob(mtd, off, &ops);
} else {
ret = mtd_write_oob(mtd, off, &ops);
- if (!ret)
+ if (!ret && !no_verify)
ret = nand_verify_page_oob(mtd, &ops, off);
}
/* We grab the nand info object here fresh because this is usually
* called after arg_off_size() which can change the value of dev.
*/
- struct mtd_info *mtd = &nand_info[dev];
+ struct mtd_info *mtd = get_nand_dev_by_index(dev);
loff_t maxoffset = offset + *size;
int badblocks = 0;
if (strcmp(cmd, "info") == 0) {
putc('\n');
- for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
- if (nand_info[i].name)
- nand_print_and_set_info(i);
- }
+ for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
+ nand_print_and_set_info(i);
return 0;
}
* one before these commands can run, even if a partition specifier
* for another device is to be used.
*/
- if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
- !nand_info[dev].name) {
+ mtd = get_nand_dev_by_index(dev);
+ if (!mtd) {
puts("\nno devices available\n");
return 1;
}
- mtd = &nand_info[dev];
if (strcmp(cmd, "bad") == 0) {
printf("\nDevice %d bad blocks:\n", dev);
/* skip first two or three arguments, look for offset and size */
if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
&maxsize, MTD_DEV_TYPE_NAND,
- nand_info[dev].size) != 0)
+ mtd->size) != 0)
return 1;
if (set_dev(dev))
return 1;
- mtd = &nand_info[dev];
+ mtd = get_nand_dev_by_index(dev);
memset(&opts, 0, sizeof(opts));
opts.offset = off;
ulong pagecount = 1;
int read;
int raw = 0;
+ int no_verify = 0;
if (argc < 4)
goto usage;
s = strchr(cmd, '.');
- if (s && !strcmp(s, ".raw")) {
+ if (s && !strncmp(s, ".raw", 4)) {
raw = 1;
+ if (!strcmp(s, ".raw.noverify"))
+ no_verify = 1;
+
if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
MTD_DEV_TYPE_NAND,
- nand_info[dev].size))
+ mtd->size))
return 1;
if (set_dev(dev))
return 1;
- mtd = &nand_info[dev];
+ mtd = get_nand_dev_by_index(dev);
if (argc > 4 && !str2long(argv[4], &pagecount)) {
printf("'%s' is not a number\n", argv[4]);
if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
&size, &maxsize,
MTD_DEV_TYPE_NAND,
- nand_info[dev].size) != 0)
+ mtd->size) != 0)
return 1;
if (set_dev(dev))
rwsize = size;
}
- mtd = &nand_info[dev];
+ mtd = get_nand_dev_by_index(dev);
if (!s || !strcmp(s, ".jffs2") ||
!strcmp(s, ".e") || !strcmp(s, ".i")) {
else
ret = mtd_write_oob(mtd, off, &ops);
} else if (raw) {
- ret = raw_access(mtd, addr, off, pagecount, read);
+ ret = raw_access(mtd, addr, off, pagecount, read,
+ no_verify);
} else {
printf("Unknown nand command suffix '%s'.\n", s);
return 1;
#ifdef CONFIG_CMD_NAND_TORTURE
if (strcmp(cmd, "torture") == 0) {
+ loff_t endoff;
+ unsigned int failed = 0, passed = 0;
+
if (argc < 3)
goto usage;
return 1;
}
- printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n",
- dev, off, mtd->erasesize);
- ret = nand_torture(mtd, off);
- printf(" %s\n", ret ? "Failed" : "Passed");
+ size = mtd->erasesize;
+ if (argc > 3) {
+ if (!str2off(argv[3], &size)) {
+ puts("Size is not a valid number\n");
+ return 1;
+ }
+ }
+
+ endoff = off + size;
+ if (endoff > mtd->size) {
+ puts("Arguments beyond end of NAND\n");
+ return 1;
+ }
- return ret == 0 ? 0 : 1;
+ off = round_down(off, mtd->erasesize);
+ endoff = round_up(endoff, mtd->erasesize);
+ size = endoff - off;
+ printf("\nNAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)\n",
+ dev, off, size, mtd->erasesize);
+ while (off < endoff) {
+ ret = nand_torture(mtd, off);
+ if (ret) {
+ failed++;
+ printf(" block at 0x%llx failed\n", off);
+ } else {
+ passed++;
+ }
+ off += mtd->erasesize;
+ }
+ printf(" Passed: %u, failed: %u\n", passed, failed);
+ return failed != 0;
}
#endif
if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
&maxsize, MTD_DEV_TYPE_NAND,
- nand_info[dev].size) < 0)
+ mtd->size) < 0)
return 1;
if (set_dev(dev))
return 1;
- if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
+ mtd = get_nand_dev_by_index(dev);
+
+ if (!nand_unlock(mtd, off, size, allexcept)) {
puts("NAND flash successfully unlocked\n");
} else {
puts("Error unlocking NAND flash, "
" read/write 'size' bytes starting at offset 'off'\n"
" to/from memory address 'addr', skipping bad blocks.\n"
"nand read.raw - addr off|partition [count]\n"
- "nand write.raw - addr off|partition [count]\n"
+ "nand write.raw[.noverify] - addr off|partition [count]\n"
" Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
#ifdef CONFIG_CMD_NAND_TRIMFFS
"nand write.trimffs - addr off|partition size\n"
"nand bad - show bad blocks\n"
"nand dump[.oob] off - dump page\n"
#ifdef CONFIG_CMD_NAND_TORTURE
- "nand torture off - torture block at offset\n"
+ "nand torture off - torture one block at offset\n"
+ "nand torture off [size] - torture blocks from off to off+size\n"
#endif
"nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
" really clean NAND erasing bad blocks (UNSAFE)\n"
char *boot_device = NULL;
int idx;
ulong addr, offset = 0;
+ struct mtd_info *mtd;
#if defined(CONFIG_CMD_MTDPARTS)
struct mtd_device *dev;
struct part_info *part;
addr = simple_strtoul(argv[1], NULL, 16);
else
addr = CONFIG_SYS_LOAD_ADDR;
- return nand_load_image(cmdtp, &nand_info[dev->id->num],
- part->offset, addr, argv[0]);
+
+ mtd = get_nand_dev_by_index(dev->id->num);
+ return nand_load_image(cmdtp, mtd, part->offset,
+ addr, argv[0]);
}
}
#endif
idx = simple_strtoul(boot_device, NULL, 16);
- if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) {
+ mtd = get_nand_dev_by_index(idx);
+ if (!mtd) {
printf("\n** Device %d not available\n", idx);
bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
return 1;
}
bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
- return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
+ return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
}
U_BOOT_CMD(nboot, 4, 1, do_nandboot,