2 * Driver for NAND support, Rick Bronson
3 * borrowed heavily from:
4 * (c) 1999 Machine Vision Holdings, Inc.
5 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
7 * Ported 'dynenv' to 'nand env.oob' command
8 * (C) 2010 Nanometrics, Inc.
9 * 'dynenv' -- Dynamic environment offset in NAND OOB
10 * (C) Copyright 2006-2007 OpenMoko, Inc.
11 * Added 16-bit nand support
12 * (C) 2004 Texas Instruments
14 * Copyright 2010, 2012 Freescale Semiconductor
15 * The portions of this file whose copyright is held by Freescale and which
16 * are not considered a derived work of GPL v2-only code may be distributed
17 * and/or modified under the terms of the GNU General Public License as
18 * published by the Free Software Foundation; either version 2 of the
19 * License, or (at your option) any later version.
23 #include <linux/mtd/mtd.h>
27 #include <asm/byteorder.h>
28 #include <jffs2/jffs2.h>
31 #if defined(CONFIG_CMD_MTDPARTS)
33 /* partition handling routines */
34 int mtdparts_init(void);
35 int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
36 int find_dev_and_part(const char *id, struct mtd_device **dev,
37 u8 *part_num, struct part_info **part);
40 static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
43 u_char *datbuf, *oobbuf, *p;
48 off = last + nand->writesize;
52 datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize);
54 puts("No memory for page buffer\n");
58 oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize);
60 puts("No memory for page buffer\n");
64 off &= ~(nand->writesize - 1);
65 loff_t addr = (loff_t) off;
66 struct mtd_oob_ops ops;
67 memset(&ops, 0, sizeof(ops));
70 ops.len = nand->writesize;
71 ops.ooblen = nand->oobsize;
72 ops.mode = MTD_OPS_RAW;
73 i = mtd_read_oob(nand, addr, &ops);
75 printf("Error (%d) reading page %08lx\n", i, off);
79 printf("Page %08lx dump:\n", off);
80 i = nand->writesize >> 4;
85 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
86 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
87 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
88 p[8], p[9], p[10], p[11], p[12], p[13], p[14],
93 i = nand->oobsize >> 3;
96 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
97 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
109 /* ------------------------------------------------------------------------- */
111 static int set_dev(int dev)
113 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
114 !nand_info[dev].name) {
115 puts("No such device\n");
119 if (nand_curr_device == dev)
122 printf("Device %d: %s", dev, nand_info[dev].name);
123 puts("... is now current device\n");
124 nand_curr_device = dev;
126 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
127 board_nand_select_device(nand_info[dev].priv, dev);
133 static inline int str2off(const char *p, loff_t *num)
137 *num = simple_strtoull(p, &endptr, 16);
138 return *p != '\0' && *endptr == '\0';
141 static inline int str2long(const char *p, ulong *num)
145 *num = simple_strtoul(p, &endptr, 16);
146 return *p != '\0' && *endptr == '\0';
149 static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size,
152 #ifdef CONFIG_CMD_MTDPARTS
153 struct mtd_device *dev;
154 struct part_info *part;
158 ret = mtdparts_init();
162 ret = find_dev_and_part(partname, &dev, &pnum, &part);
166 if (dev->id->type != MTD_DEV_TYPE_NAND) {
167 puts("not a NAND device\n");
173 *maxsize = part->size;
182 puts("offset is not a number\n");
187 static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
190 if (!str2off(arg, off))
191 return get_part(arg, idx, off, size, maxsize);
193 if (*off >= nand_info[*idx].size) {
194 puts("Offset exceeds device limit\n");
198 *maxsize = nand_info[*idx].size - *off;
203 static int arg_off_size(int argc, char *const argv[], int *idx,
204 loff_t *off, loff_t *size, loff_t *maxsize)
210 *size = nand_info[*idx].size;
215 ret = arg_off(argv[0], idx, off, size, maxsize);
222 if (!str2off(argv[1], size)) {
223 printf("'%s' is not a number\n", argv[1]);
227 if (*size > *maxsize) {
228 puts("Size exceeds partition or device limit\n");
233 printf("device %d ", *idx);
234 if (*size == nand_info[*idx].size)
235 puts("whole chip\n");
237 printf("offset 0x%llx, size 0x%llx\n",
238 (unsigned long long)*off, (unsigned long long)*size);
242 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
243 static void print_status(ulong start, ulong end, ulong erasesize, int status)
246 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
247 * not the same as others. Instead of bit 1 being lock, it is
248 * #lock_tight. To make the driver support either format, ignore bit 1
249 * and use only bit 0 and bit 2.
251 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
254 (end - start) / erasesize,
255 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
256 (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
257 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
260 static void do_nand_status(nand_info_t *nand)
262 ulong block_start = 0;
264 int last_status = -1;
266 struct nand_chip *nand_chip = nand->priv;
267 /* check the WP bit */
268 nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1);
269 printf("device is %swrite protected\n",
270 (nand_chip->read_byte(nand) & 0x80 ?
273 for (off = 0; off < nand->size; off += nand->erasesize) {
274 int s = nand_get_lock_status(nand, off);
276 /* print message only if status has changed */
277 if (s != last_status && off != 0) {
278 print_status(block_start, off, nand->erasesize,
284 /* Print the last block info */
285 print_status(block_start, off, nand->erasesize, last_status);
289 #ifdef CONFIG_ENV_OFFSET_OOB
290 unsigned long nand_env_oob_offset;
292 int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
295 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
296 nand_info_t *nand = &nand_info[0];
299 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
300 puts("no devices available\n");
306 if (!strcmp(cmd, "get")) {
307 ret = get_nand_env_oob(nand, &nand_env_oob_offset);
311 printf("0x%08lx\n", nand_env_oob_offset);
312 } else if (!strcmp(cmd, "set")) {
315 struct mtd_oob_ops ops;
321 /* We don't care about size, or maxsize. */
322 if (arg_off(argv[2], &idx, &addr, &maxsize, &maxsize)) {
323 puts("Offset or partition name expected\n");
328 puts("Partition not on first NAND device\n");
332 if (nand->oobavail < ENV_OFFSET_SIZE) {
333 printf("Insufficient available OOB bytes:\n"
334 "%d OOB bytes available but %d required for "
336 nand->oobavail, ENV_OFFSET_SIZE);
340 if ((addr & (nand->erasesize - 1)) != 0) {
341 printf("Environment offset must be block-aligned\n");
346 ops.mode = MTD_OOB_AUTO;
348 ops.ooblen = ENV_OFFSET_SIZE;
349 ops.oobbuf = (void *) oob_buf;
351 oob_buf[0] = ENV_OOB_MARKER;
352 oob_buf[1] = addr / nand->erasesize;
354 ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops);
356 printf("Error writing OOB block 0\n");
360 ret = get_nand_env_oob(nand, &nand_env_oob_offset);
362 printf("Error reading env offset in OOB\n");
366 if (addr != nand_env_oob_offset) {
367 printf("Verification of env offset in OOB failed: "
368 "0x%08llx expected but got 0x%08lx\n",
369 (unsigned long long)addr, nand_env_oob_offset);
379 return CMD_RET_USAGE;
384 static void nand_print_and_set_info(int idx)
386 nand_info_t *nand = &nand_info[idx];
387 struct nand_chip *chip = nand->priv;
389 printf("Device %d: ", idx);
390 if (chip->numchips > 1)
391 printf("%dx ", chip->numchips);
392 printf("%s, sector size %u KiB\n",
393 nand->name, nand->erasesize >> 10);
394 printf(" Page size %8d b\n", nand->writesize);
395 printf(" OOB size %8d b\n", nand->oobsize);
396 printf(" Erase size %8d b\n", nand->erasesize);
398 /* Set geometry info */
399 setenv_hex("nand_writesize", nand->writesize);
400 setenv_hex("nand_oobsize", nand->oobsize);
401 setenv_hex("nand_erasesize", nand->erasesize);
404 static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
411 mtd_oob_ops_t ops = {
412 .datbuf = (u8 *)addr,
413 .oobbuf = ((u8 *)addr) + nand->writesize,
414 .len = nand->writesize,
415 .ooblen = nand->oobsize,
420 ret = mtd_read_oob(nand, off, &ops);
422 ret = mtd_write_oob(nand, off, &ops);
425 printf("%s: error at offset %llx, ret %d\n",
426 __func__, (long long)off, ret);
430 addr += nand->writesize + nand->oobsize;
431 off += nand->writesize;
437 /* Adjust a chip/partition size down for bad blocks so we don't
438 * read/write past the end of a chip/partition by accident.
440 static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
442 /* We grab the nand info object here fresh because this is usually
443 * called after arg_off_size() which can change the value of dev.
445 nand_info_t *nand = &nand_info[dev];
446 loff_t maxoffset = offset + *size;
449 /* count badblocks in NAND from offset to offset + size */
450 for (; offset < maxoffset; offset += nand->erasesize) {
451 if (nand_block_isbad(nand, offset))
454 /* adjust size if any bad blocks found */
456 *size -= badblocks * nand->erasesize;
457 printf("size adjusted to 0x%llx (%d bad blocks)\n",
458 (unsigned long long)*size, badblocks);
462 static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
466 loff_t off, size, maxsize;
469 #ifdef CONFIG_SYS_NAND_QUIET
470 int quiet = CONFIG_SYS_NAND_QUIET;
474 const char *quiet_str = getenv("quiet");
475 int dev = nand_curr_device;
476 int repeat = flag & CMD_FLAG_REPEAT;
478 /* at least two arguments please */
483 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
487 /* Only "dump" is repeatable. */
488 if (repeat && strcmp(cmd, "dump"))
491 if (strcmp(cmd, "info") == 0) {
494 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
495 if (nand_info[i].name)
496 nand_print_and_set_info(i);
501 if (strcmp(cmd, "device") == 0) {
504 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
505 puts("no devices available\n");
507 nand_print_and_set_info(dev);
511 dev = (int)simple_strtoul(argv[2], NULL, 10);
517 #ifdef CONFIG_ENV_OFFSET_OOB
518 /* this command operates only on the first nand device */
519 if (strcmp(cmd, "env.oob") == 0)
520 return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
523 /* The following commands operate on the current device, unless
524 * overridden by a partition specifier. Note that if somehow the
525 * current device is invalid, it will have to be changed to a valid
526 * one before these commands can run, even if a partition specifier
527 * for another device is to be used.
529 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
530 !nand_info[dev].name) {
531 puts("\nno devices available\n");
534 nand = &nand_info[dev];
536 if (strcmp(cmd, "bad") == 0) {
537 printf("\nDevice %d bad blocks:\n", dev);
538 for (off = 0; off < nand->size; off += nand->erasesize)
539 if (nand_block_isbad(nand, off))
540 printf(" %08llx\n", (unsigned long long)off);
547 * nand erase [clean] [off size]
549 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
550 nand_erase_options_t opts;
551 /* "clean" at index 2 means request to write cleanmarker */
552 int clean = argc > 2 && !strcmp("clean", argv[2]);
553 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
554 int o = (clean || scrub_yes) ? 3 : 2;
555 int scrub = !strncmp(cmd, "scrub", 5);
558 const char *scrub_warn =
560 "scrub option will erase all factory set bad blocks!\n"
562 "There is no reliable way to recover them.\n"
564 "Use this command only for testing purposes if you\n"
566 "are sure of what you are doing!\n"
567 "\nReally scrub this NAND flash? <y/N>\n";
570 if (!strcmp(&cmd[5], ".spread")) {
572 } else if (!strcmp(&cmd[5], ".part")) {
574 } else if (!strcmp(&cmd[5], ".chip")) {
582 * Don't allow missing arguments to cause full chip/partition
583 * erases -- easy to do accidentally, e.g. with a misspelled
586 if (argc != o + args)
589 printf("\nNAND %s: ", cmd);
590 /* skip first two or three arguments, look for offset and size */
591 if (arg_off_size(argc - o, argv + o, &dev, &off, &size,
595 nand = &nand_info[dev];
597 memset(&opts, 0, sizeof(opts));
602 opts.spread = spread;
610 else if (getc() == 'y') {
615 puts("scrub aborted\n");
619 puts("scrub aborted\n");
623 ret = nand_erase_opts(nand, &opts);
624 printf("%s\n", ret ? "ERROR" : "OK");
626 return ret == 0 ? 0 : 1;
629 if (strncmp(cmd, "dump", 4) == 0) {
633 off = (int)simple_strtoul(argv[2], NULL, 16);
634 ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
636 return ret == 0 ? 1 : 0;
639 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
648 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
650 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
651 printf("\nNAND %s: ", read ? "read" : "write");
653 nand = &nand_info[dev];
655 s = strchr(cmd, '.');
657 if (s && !strcmp(s, ".raw")) {
660 if (arg_off(argv[3], &dev, &off, &size, &maxsize))
663 if (argc > 4 && !str2long(argv[4], &pagecount)) {
664 printf("'%s' is not a number\n", argv[4]);
668 if (pagecount * nand->writesize > size) {
669 puts("Size exceeds partition or device limit\n");
673 rwsize = pagecount * (nand->writesize + nand->oobsize);
675 if (arg_off_size(argc - 3, argv + 3, &dev,
676 &off, &size, &maxsize) != 0)
679 /* size is unspecified */
681 adjust_size_for_badblocks(&size, off, dev);
685 if (!s || !strcmp(s, ".jffs2") ||
686 !strcmp(s, ".e") || !strcmp(s, ".i")) {
688 ret = nand_read_skip_bad(nand, off, &rwsize,
692 ret = nand_write_skip_bad(nand, off, &rwsize,
695 #ifdef CONFIG_CMD_NAND_TRIMFFS
696 } else if (!strcmp(s, ".trimffs")) {
698 printf("Unknown nand command suffix '%s'\n", s);
701 ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
702 maxsize, (u_char *)addr,
705 #ifdef CONFIG_CMD_NAND_YAFFS
706 } else if (!strcmp(s, ".yaffs")) {
708 printf("Unknown nand command suffix '%s'.\n", s);
711 ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
712 maxsize, (u_char *)addr,
715 } else if (!strcmp(s, ".oob")) {
716 /* out-of-band data */
717 mtd_oob_ops_t ops = {
718 .oobbuf = (u8 *)addr,
724 ret = mtd_read_oob(nand, off, &ops);
726 ret = mtd_write_oob(nand, off, &ops);
728 ret = raw_access(nand, addr, off, pagecount, read);
730 printf("Unknown nand command suffix '%s'.\n", s);
734 printf(" %zu bytes %s: %s\n", rwsize,
735 read ? "read" : "written", ret ? "ERROR" : "OK");
737 return ret == 0 ? 0 : 1;
740 #ifdef CONFIG_CMD_NAND_TORTURE
741 if (strcmp(cmd, "torture") == 0) {
745 if (!str2off(argv[2], &off)) {
746 puts("Offset is not a valid number\n");
750 printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n",
751 dev, off, nand->erasesize);
752 ret = nand_torture(nand, off);
753 printf(" %s\n", ret ? "Failed" : "Passed");
755 return ret == 0 ? 0 : 1;
759 if (strcmp(cmd, "markbad") == 0) {
767 addr = simple_strtoul(*argv, NULL, 16);
769 if (mtd_block_markbad(nand, addr)) {
770 printf("block 0x%08lx NOT marked "
771 "as bad! ERROR %d\n",
775 printf("block 0x%08lx successfully "
785 if (strcmp(cmd, "biterr") == 0) {
790 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
791 if (strcmp(cmd, "lock") == 0) {
795 if (!strcmp("tight", argv[2]))
797 if (!strcmp("status", argv[2]))
801 do_nand_status(nand);
803 if (!nand_lock(nand, tight)) {
804 puts("NAND flash successfully locked\n");
806 puts("Error locking NAND flash\n");
813 if (strncmp(cmd, "unlock", 5) == 0) {
816 s = strchr(cmd, '.');
818 if (s && !strcmp(s, ".allexcept"))
821 if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
825 if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
826 puts("NAND flash successfully unlocked\n");
828 puts("Error unlocking NAND flash, "
829 "write and erase will probably fail\n");
837 return CMD_RET_USAGE;
840 #ifdef CONFIG_SYS_LONGHELP
841 static char nand_help_text[] =
842 "info - show available NAND devices\n"
843 "nand device [dev] - show or set current device\n"
844 "nand read - addr off|partition size\n"
845 "nand write - addr off|partition size\n"
846 " read/write 'size' bytes starting at offset 'off'\n"
847 " to/from memory address 'addr', skipping bad blocks.\n"
848 "nand read.raw - addr off|partition [count]\n"
849 "nand write.raw - addr off|partition [count]\n"
850 " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
851 #ifdef CONFIG_CMD_NAND_TRIMFFS
852 "nand write.trimffs - addr off|partition size\n"
853 " write 'size' bytes starting at offset 'off' from memory address\n"
854 " 'addr', skipping bad blocks and dropping any pages at the end\n"
855 " of eraseblocks that contain only 0xFF\n"
857 #ifdef CONFIG_CMD_NAND_YAFFS
858 "nand write.yaffs - addr off|partition size\n"
859 " write 'size' bytes starting at offset 'off' with yaffs format\n"
860 " from memory address 'addr', skipping bad blocks.\n"
862 "nand erase[.spread] [clean] off size - erase 'size' bytes "
863 "from offset 'off'\n"
864 " With '.spread', erase enough for given file size, otherwise,\n"
865 " 'size' includes skipped bad blocks.\n"
866 "nand erase.part [clean] partition - erase entire mtd partition'\n"
867 "nand erase.chip [clean] - erase entire chip'\n"
868 "nand bad - show bad blocks\n"
869 "nand dump[.oob] off - dump page\n"
870 #ifdef CONFIG_CMD_NAND_TORTURE
871 "nand torture off - torture block at offset\n"
873 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
874 " really clean NAND erasing bad blocks (UNSAFE)\n"
875 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
876 "nand biterr off - make a bit error at offset (UNSAFE)"
877 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
879 "nand lock [tight] [status]\n"
880 " bring nand to lock state or display locked pages\n"
881 "nand unlock[.allexcept] [offset] [size] - unlock section"
883 #ifdef CONFIG_ENV_OFFSET_OOB
885 "nand env.oob - environment offset in OOB of block 0 of"
887 "nand env.oob set off|partition - set enviromnent offset\n"
888 "nand env.oob get - get environment offset"
894 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
895 "NAND sub-system", nand_help_text
898 static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
899 ulong offset, ulong addr, char *cmd)
905 #if defined(CONFIG_FIT)
906 const void *fit_hdr = NULL;
909 s = strchr(cmd, '.');
911 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
912 printf("Unknown nand load suffix '%s'\n", s);
913 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
917 printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
919 cnt = nand->writesize;
920 r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
923 puts("** Read error\n");
924 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
927 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
929 switch (genimg_get_format ((void *)addr)) {
930 case IMAGE_FORMAT_LEGACY:
931 hdr = (image_header_t *)addr;
933 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
934 image_print_contents (hdr);
936 cnt = image_get_image_size (hdr);
938 #if defined(CONFIG_FIT)
939 case IMAGE_FORMAT_FIT:
940 fit_hdr = (const void *)addr;
941 puts ("Fit image detected...\n");
943 cnt = fit_get_size (fit_hdr);
947 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
948 puts ("** Unknown image type\n");
951 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
953 r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
956 puts("** Read error\n");
957 bootstage_error(BOOTSTAGE_ID_NAND_READ);
960 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
962 #if defined(CONFIG_FIT)
963 /* This cannot be done earlier, we need complete FIT image in RAM first */
964 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
965 if (!fit_check_format (fit_hdr)) {
966 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
967 puts ("** Bad FIT image format\n");
970 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
971 fit_print_contents (fit_hdr);
975 /* Loading ok, update default load address */
979 return bootm_maybe_autostart(cmdtp, cmd);
982 static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
985 char *boot_device = NULL;
987 ulong addr, offset = 0;
988 #if defined(CONFIG_CMD_MTDPARTS)
989 struct mtd_device *dev;
990 struct part_info *part;
994 char *p = (argc == 2) ? argv[1] : argv[2];
995 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
996 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
997 if (dev->id->type != MTD_DEV_TYPE_NAND) {
998 puts("Not a NAND device\n");
1004 addr = simple_strtoul(argv[1], NULL, 16);
1006 addr = CONFIG_SYS_LOAD_ADDR;
1007 return nand_load_image(cmdtp, &nand_info[dev->id->num],
1008 part->offset, addr, argv[0]);
1013 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
1016 addr = CONFIG_SYS_LOAD_ADDR;
1017 boot_device = getenv("bootdevice");
1020 addr = simple_strtoul(argv[1], NULL, 16);
1021 boot_device = getenv("bootdevice");
1024 addr = simple_strtoul(argv[1], NULL, 16);
1025 boot_device = argv[2];
1028 addr = simple_strtoul(argv[1], NULL, 16);
1029 boot_device = argv[2];
1030 offset = simple_strtoul(argv[3], NULL, 16);
1033 #if defined(CONFIG_CMD_MTDPARTS)
1036 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
1037 return CMD_RET_USAGE;
1039 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
1042 puts("\n** No boot device **\n");
1043 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1046 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1048 idx = simple_strtoul(boot_device, NULL, 16);
1050 if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) {
1051 printf("\n** Device %d not available\n", idx);
1052 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
1055 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
1057 return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
1060 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
1061 "boot from NAND device",
1062 "[partition] | [[[loadAddr] dev] offset]"