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>
29 #include <asm/byteorder.h>
30 #include <jffs2/jffs2.h>
33 #if defined(CONFIG_CMD_MTDPARTS)
35 /* partition handling routines */
36 int mtdparts_init(void);
37 int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
38 int find_dev_and_part(const char *id, struct mtd_device **dev,
39 u8 *part_num, struct part_info **part);
42 static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
46 u_char *datbuf, *oobbuf, *p;
51 off = last + mtd->writesize;
55 datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
57 puts("No memory for page buffer\n");
61 oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
63 puts("No memory for page buffer\n");
67 off &= ~(mtd->writesize - 1);
68 loff_t addr = (loff_t) off;
69 struct mtd_oob_ops ops;
70 memset(&ops, 0, sizeof(ops));
73 ops.len = mtd->writesize;
74 ops.ooblen = mtd->oobsize;
75 ops.mode = MTD_OPS_RAW;
76 i = mtd_read_oob(mtd, addr, &ops);
78 printf("Error (%d) reading page %08lx\n", i, off);
82 printf("Page %08lx dump:\n", off);
85 i = mtd->writesize >> 4;
89 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
90 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
91 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
92 p[8], p[9], p[10], p[11], p[12], p[13], p[14],
99 i = mtd->oobsize >> 3;
102 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
103 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
115 /* ------------------------------------------------------------------------- */
117 static int set_dev(int dev)
119 struct mtd_info *mtd = get_nand_dev_by_index(dev);
124 if (nand_curr_device == dev)
127 printf("Device %d: %s", dev, mtd->name);
128 puts("... is now current device\n");
129 nand_curr_device = dev;
131 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
132 board_nand_select_device(mtd_to_nand(mtd), dev);
138 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
139 static void print_status(ulong start, ulong end, ulong erasesize, int status)
142 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
143 * not the same as others. Instead of bit 1 being lock, it is
144 * #lock_tight. To make the driver support either format, ignore bit 1
145 * and use only bit 0 and bit 2.
147 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
150 (end - start) / erasesize,
151 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
152 (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
153 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
156 static void do_nand_status(struct mtd_info *mtd)
158 ulong block_start = 0;
160 int last_status = -1;
162 struct nand_chip *nand_chip = mtd_to_nand(mtd);
163 /* check the WP bit */
164 nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
165 printf("device is %swrite protected\n",
166 (nand_chip->read_byte(mtd) & 0x80 ?
169 for (off = 0; off < mtd->size; off += mtd->erasesize) {
170 int s = nand_get_lock_status(mtd, off);
172 /* print message only if status has changed */
173 if (s != last_status && off != 0) {
174 print_status(block_start, off, mtd->erasesize,
180 /* Print the last block info */
181 print_status(block_start, off, mtd->erasesize, last_status);
185 #ifdef CONFIG_ENV_OFFSET_OOB
186 unsigned long nand_env_oob_offset;
188 int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
191 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
192 struct mtd_info *mtd = get_nand_dev_by_index(0);
195 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
196 puts("no devices available\n");
202 if (!strcmp(cmd, "get")) {
203 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
207 printf("0x%08lx\n", nand_env_oob_offset);
208 } else if (!strcmp(cmd, "set")) {
211 struct mtd_oob_ops ops;
217 mtd = get_nand_dev_by_index(idx);
218 /* We don't care about size, or maxsize. */
219 if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
220 MTD_DEV_TYPE_NAND, mtd->size)) {
221 puts("Offset or partition name expected\n");
225 puts("Offset or partition name expected\n");
230 puts("Partition not on first NAND device\n");
234 if (mtd->oobavail < ENV_OFFSET_SIZE) {
235 printf("Insufficient available OOB bytes:\n"
236 "%d OOB bytes available but %d required for "
238 mtd->oobavail, ENV_OFFSET_SIZE);
242 if ((addr & (mtd->erasesize - 1)) != 0) {
243 printf("Environment offset must be block-aligned\n");
248 ops.mode = MTD_OOB_AUTO;
250 ops.ooblen = ENV_OFFSET_SIZE;
251 ops.oobbuf = (void *) oob_buf;
253 oob_buf[0] = ENV_OOB_MARKER;
254 oob_buf[1] = addr / mtd->erasesize;
256 ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
258 printf("Error writing OOB block 0\n");
262 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
264 printf("Error reading env offset in OOB\n");
268 if (addr != nand_env_oob_offset) {
269 printf("Verification of env offset in OOB failed: "
270 "0x%08llx expected but got 0x%08lx\n",
271 (unsigned long long)addr, nand_env_oob_offset);
281 return CMD_RET_USAGE;
286 static void nand_print_and_set_info(int idx)
288 struct mtd_info *mtd;
289 struct nand_chip *chip;
291 mtd = get_nand_dev_by_index(idx);
295 chip = mtd_to_nand(mtd);
296 printf("Device %d: ", idx);
297 if (chip->numchips > 1)
298 printf("%dx ", chip->numchips);
299 printf("%s, sector size %u KiB\n",
300 mtd->name, mtd->erasesize >> 10);
301 printf(" Page size %8d b\n", mtd->writesize);
302 printf(" OOB size %8d b\n", mtd->oobsize);
303 printf(" Erase size %8d b\n", mtd->erasesize);
304 printf(" subpagesize %8d b\n", chip->subpagesize);
305 printf(" options 0x%08x\n", chip->options);
306 printf(" bbt options 0x%08x\n", chip->bbt_options);
308 /* Set geometry info */
309 env_set_hex("nand_writesize", mtd->writesize);
310 env_set_hex("nand_oobsize", mtd->oobsize);
311 env_set_hex("nand_erasesize", mtd->erasesize);
314 static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
315 ulong count, int read, int no_verify)
321 mtd_oob_ops_t ops = {
322 .datbuf = (u8 *)addr,
323 .oobbuf = ((u8 *)addr) + mtd->writesize,
324 .len = mtd->writesize,
325 .ooblen = mtd->oobsize,
330 ret = mtd_read_oob(mtd, off, &ops);
332 ret = mtd_write_oob(mtd, off, &ops);
333 if (!ret && !no_verify)
334 ret = nand_verify_page_oob(mtd, &ops, off);
338 printf("%s: error at offset %llx, ret %d\n",
339 __func__, (long long)off, ret);
343 addr += mtd->writesize + mtd->oobsize;
344 off += mtd->writesize;
350 /* Adjust a chip/partition size down for bad blocks so we don't
351 * read/write past the end of a chip/partition by accident.
353 static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
355 /* We grab the nand info object here fresh because this is usually
356 * called after arg_off_size() which can change the value of dev.
358 struct mtd_info *mtd = get_nand_dev_by_index(dev);
359 loff_t maxoffset = offset + *size;
362 /* count badblocks in NAND from offset to offset + size */
363 for (; offset < maxoffset; offset += mtd->erasesize) {
364 if (nand_block_isbad(mtd, offset))
367 /* adjust size if any bad blocks found */
369 *size -= badblocks * mtd->erasesize;
370 printf("size adjusted to 0x%llx (%d bad blocks)\n",
371 (unsigned long long)*size, badblocks);
375 static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
379 loff_t off, size, maxsize;
381 struct mtd_info *mtd;
382 #ifdef CONFIG_SYS_NAND_QUIET
383 int quiet = CONFIG_SYS_NAND_QUIET;
387 const char *quiet_str = env_get("quiet");
388 int dev = nand_curr_device;
389 int repeat = flag & CMD_FLAG_REPEAT;
391 /* at least two arguments please */
396 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
400 /* Only "dump" is repeatable. */
401 if (repeat && strcmp(cmd, "dump"))
404 if (strcmp(cmd, "info") == 0) {
407 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
408 nand_print_and_set_info(i);
412 if (strcmp(cmd, "device") == 0) {
415 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
416 puts("no devices available\n");
418 nand_print_and_set_info(dev);
422 dev = (int)simple_strtoul(argv[2], NULL, 10);
428 #ifdef CONFIG_ENV_OFFSET_OOB
429 /* this command operates only on the first nand device */
430 if (strcmp(cmd, "env.oob") == 0)
431 return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
434 /* The following commands operate on the current device, unless
435 * overridden by a partition specifier. Note that if somehow the
436 * current device is invalid, it will have to be changed to a valid
437 * one before these commands can run, even if a partition specifier
438 * for another device is to be used.
440 mtd = get_nand_dev_by_index(dev);
442 puts("\nno devices available\n");
446 if (strcmp(cmd, "bad") == 0) {
447 printf("\nDevice %d bad blocks:\n", dev);
448 for (off = 0; off < mtd->size; off += mtd->erasesize)
449 if (nand_block_isbad(mtd, off))
450 printf(" %08llx\n", (unsigned long long)off);
457 * nand erase [clean] [off size]
459 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
460 nand_erase_options_t opts;
461 /* "clean" at index 2 means request to write cleanmarker */
462 int clean = argc > 2 && !strcmp("clean", argv[2]);
463 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
464 int o = (clean || scrub_yes) ? 3 : 2;
465 int scrub = !strncmp(cmd, "scrub", 5);
468 const char *scrub_warn =
470 "scrub option will erase all factory set bad blocks!\n"
472 "There is no reliable way to recover them.\n"
474 "Use this command only for testing purposes if you\n"
476 "are sure of what you are doing!\n"
477 "\nReally scrub this NAND flash? <y/N>\n";
480 if (!strcmp(&cmd[5], ".spread")) {
482 } else if (!strcmp(&cmd[5], ".part")) {
484 } else if (!strcmp(&cmd[5], ".chip")) {
492 * Don't allow missing arguments to cause full chip/partition
493 * erases -- easy to do accidentally, e.g. with a misspelled
496 if (argc != o + args)
499 printf("\nNAND %s: ", cmd);
500 /* skip first two or three arguments, look for offset and size */
501 if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
502 &maxsize, MTD_DEV_TYPE_NAND,
509 mtd = get_nand_dev_by_index(dev);
511 memset(&opts, 0, sizeof(opts));
516 opts.spread = spread;
523 if (confirm_yesno()) {
526 puts("scrub aborted\n");
531 ret = nand_erase_opts(mtd, &opts);
532 printf("%s\n", ret ? "ERROR" : "OK");
534 return ret == 0 ? 0 : 1;
537 if (strncmp(cmd, "dump", 4) == 0) {
541 off = (int)simple_strtoul(argv[2], NULL, 16);
542 ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
544 return ret == 0 ? 1 : 0;
547 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
557 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
559 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
560 printf("\nNAND %s: ", read ? "read" : "write");
562 s = strchr(cmd, '.');
564 if (s && !strncmp(s, ".raw", 4)) {
567 if (!strcmp(s, ".raw.noverify"))
570 if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
578 mtd = get_nand_dev_by_index(dev);
580 if (argc > 4 && !str2long(argv[4], &pagecount)) {
581 printf("'%s' is not a number\n", argv[4]);
585 if (pagecount * mtd->writesize > size) {
586 puts("Size exceeds partition or device limit\n");
590 rwsize = pagecount * (mtd->writesize + mtd->oobsize);
592 if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
601 /* size is unspecified */
603 adjust_size_for_badblocks(&size, off, dev);
607 mtd = get_nand_dev_by_index(dev);
609 if (!s || !strcmp(s, ".jffs2") ||
610 !strcmp(s, ".e") || !strcmp(s, ".i")) {
612 ret = nand_read_skip_bad(mtd, off, &rwsize,
616 ret = nand_write_skip_bad(mtd, off, &rwsize,
620 #ifdef CONFIG_CMD_NAND_TRIMFFS
621 } else if (!strcmp(s, ".trimffs")) {
623 printf("Unknown nand command suffix '%s'\n", s);
626 ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
627 maxsize, (u_char *)addr,
628 WITH_DROP_FFS | WITH_WR_VERIFY);
630 } else if (!strcmp(s, ".oob")) {
631 /* out-of-band data */
632 mtd_oob_ops_t ops = {
633 .oobbuf = (u8 *)addr,
639 ret = mtd_read_oob(mtd, off, &ops);
641 ret = mtd_write_oob(mtd, off, &ops);
643 ret = raw_access(mtd, addr, off, pagecount, read,
646 printf("Unknown nand command suffix '%s'.\n", s);
650 printf(" %zu bytes %s: %s\n", rwsize,
651 read ? "read" : "written", ret ? "ERROR" : "OK");
653 return ret == 0 ? 0 : 1;
656 #ifdef CONFIG_CMD_NAND_TORTURE
657 if (strcmp(cmd, "torture") == 0) {
659 unsigned int failed = 0, passed = 0;
664 if (!str2off(argv[2], &off)) {
665 puts("Offset is not a valid number\n");
669 size = mtd->erasesize;
671 if (!str2off(argv[3], &size)) {
672 puts("Size is not a valid number\n");
678 if (endoff > mtd->size) {
679 puts("Arguments beyond end of NAND\n");
683 off = round_down(off, mtd->erasesize);
684 endoff = round_up(endoff, mtd->erasesize);
686 printf("\nNAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)\n",
687 dev, off, size, mtd->erasesize);
688 while (off < endoff) {
689 ret = nand_torture(mtd, off);
692 printf(" block at 0x%llx failed\n", off);
696 off += mtd->erasesize;
698 printf(" Passed: %u, failed: %u\n", passed, failed);
703 if (strcmp(cmd, "markbad") == 0) {
711 addr = simple_strtoul(*argv, NULL, 16);
713 if (mtd_block_markbad(mtd, addr)) {
714 printf("block 0x%08lx NOT marked "
715 "as bad! ERROR %d\n",
719 printf("block 0x%08lx successfully "
729 if (strcmp(cmd, "biterr") == 0) {
734 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
735 if (strcmp(cmd, "lock") == 0) {
739 if (!strcmp("tight", argv[2]))
741 if (!strcmp("status", argv[2]))
747 if (!nand_lock(mtd, tight)) {
748 puts("NAND flash successfully locked\n");
750 puts("Error locking NAND flash\n");
757 if (strncmp(cmd, "unlock", 5) == 0) {
760 s = strchr(cmd, '.');
762 if (s && !strcmp(s, ".allexcept"))
765 if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
766 &maxsize, MTD_DEV_TYPE_NAND,
773 mtd = get_nand_dev_by_index(dev);
775 if (!nand_unlock(mtd, off, size, allexcept)) {
776 puts("NAND flash successfully unlocked\n");
778 puts("Error unlocking NAND flash, "
779 "write and erase will probably fail\n");
787 return CMD_RET_USAGE;
790 #ifdef CONFIG_SYS_LONGHELP
791 static char nand_help_text[] =
792 "info - show available NAND devices\n"
793 "nand device [dev] - show or set current device\n"
794 "nand read - addr off|partition size\n"
795 "nand write - addr off|partition size\n"
796 " read/write 'size' bytes starting at offset 'off'\n"
797 " to/from memory address 'addr', skipping bad blocks.\n"
798 "nand read.raw - addr off|partition [count]\n"
799 "nand write.raw[.noverify] - addr off|partition [count]\n"
800 " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
801 #ifdef CONFIG_CMD_NAND_TRIMFFS
802 "nand write.trimffs - addr off|partition size\n"
803 " write 'size' bytes starting at offset 'off' from memory address\n"
804 " 'addr', skipping bad blocks and dropping any pages at the end\n"
805 " of eraseblocks that contain only 0xFF\n"
807 "nand erase[.spread] [clean] off size - erase 'size' bytes "
808 "from offset 'off'\n"
809 " With '.spread', erase enough for given file size, otherwise,\n"
810 " 'size' includes skipped bad blocks.\n"
811 "nand erase.part [clean] partition - erase entire mtd partition'\n"
812 "nand erase.chip [clean] - erase entire chip'\n"
813 "nand bad - show bad blocks\n"
814 "nand dump[.oob] off - dump page\n"
815 #ifdef CONFIG_CMD_NAND_TORTURE
816 "nand torture off - torture one block at offset\n"
817 "nand torture off [size] - torture blocks from off to off+size\n"
819 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
820 " really clean NAND erasing bad blocks (UNSAFE)\n"
821 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
822 "nand biterr off - make a bit error at offset (UNSAFE)"
823 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
825 "nand lock [tight] [status]\n"
826 " bring nand to lock state or display locked pages\n"
827 "nand unlock[.allexcept] [offset] [size] - unlock section"
829 #ifdef CONFIG_ENV_OFFSET_OOB
831 "nand env.oob - environment offset in OOB of block 0 of"
833 "nand env.oob set off|partition - set enviromnent offset\n"
834 "nand env.oob get - get environment offset"
840 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
841 "NAND sub-system", nand_help_text
844 static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd,
845 ulong offset, ulong addr, char *cmd)
850 #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
853 #if defined(CONFIG_FIT)
854 const void *fit_hdr = NULL;
857 s = strchr(cmd, '.');
859 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
860 printf("Unknown nand load suffix '%s'\n", s);
861 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
865 printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
867 cnt = mtd->writesize;
868 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
871 puts("** Read error\n");
872 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
875 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
877 switch (genimg_get_format ((void *)addr)) {
878 #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
879 case IMAGE_FORMAT_LEGACY:
880 hdr = (image_header_t *)addr;
882 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
883 image_print_contents (hdr);
885 cnt = image_get_image_size (hdr);
888 #if defined(CONFIG_FIT)
889 case IMAGE_FORMAT_FIT:
890 fit_hdr = (const void *)addr;
891 puts ("Fit image detected...\n");
893 cnt = fit_get_size (fit_hdr);
897 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
898 puts ("** Unknown image type\n");
901 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
903 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
906 puts("** Read error\n");
907 bootstage_error(BOOTSTAGE_ID_NAND_READ);
910 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
912 #if defined(CONFIG_FIT)
913 /* This cannot be done earlier, we need complete FIT image in RAM first */
914 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
915 if (!fit_check_format (fit_hdr)) {
916 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
917 puts ("** Bad FIT image format\n");
920 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
921 fit_print_contents (fit_hdr);
925 /* Loading ok, update default load address */
929 return bootm_maybe_autostart(cmdtp, cmd);
932 static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
935 char *boot_device = NULL;
937 ulong addr, offset = 0;
938 struct mtd_info *mtd;
939 #if defined(CONFIG_CMD_MTDPARTS)
940 struct mtd_device *dev;
941 struct part_info *part;
945 char *p = (argc == 2) ? argv[1] : argv[2];
946 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
947 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
948 if (dev->id->type != MTD_DEV_TYPE_NAND) {
949 puts("Not a NAND device\n");
955 addr = simple_strtoul(argv[1], NULL, 16);
957 addr = CONFIG_SYS_LOAD_ADDR;
959 mtd = get_nand_dev_by_index(dev->id->num);
960 return nand_load_image(cmdtp, mtd, part->offset,
966 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
969 addr = CONFIG_SYS_LOAD_ADDR;
970 boot_device = env_get("bootdevice");
973 addr = simple_strtoul(argv[1], NULL, 16);
974 boot_device = env_get("bootdevice");
977 addr = simple_strtoul(argv[1], NULL, 16);
978 boot_device = argv[2];
981 addr = simple_strtoul(argv[1], NULL, 16);
982 boot_device = argv[2];
983 offset = simple_strtoul(argv[3], NULL, 16);
986 #if defined(CONFIG_CMD_MTDPARTS)
989 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
990 return CMD_RET_USAGE;
992 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
995 puts("\n** No boot device **\n");
996 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
999 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1001 idx = simple_strtoul(boot_device, NULL, 16);
1003 mtd = get_nand_dev_by_index(idx);
1005 printf("\n** Device %d not available\n", idx);
1006 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
1009 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
1011 return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
1014 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
1015 "boot from NAND device",
1016 "[partition] | [[[loadAddr] dev] offset]"