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>
28 #include <asm/byteorder.h>
29 #include <jffs2/jffs2.h>
32 #if defined(CONFIG_CMD_MTDPARTS)
34 /* partition handling routines */
35 int mtdparts_init(void);
36 int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
37 int find_dev_and_part(const char *id, struct mtd_device **dev,
38 u8 *part_num, struct part_info **part);
41 static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
45 u_char *datbuf, *oobbuf, *p;
50 off = last + mtd->writesize;
54 datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
56 puts("No memory for page buffer\n");
60 oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
62 puts("No memory for page buffer\n");
66 off &= ~(mtd->writesize - 1);
67 loff_t addr = (loff_t) off;
68 struct mtd_oob_ops ops;
69 memset(&ops, 0, sizeof(ops));
72 ops.len = mtd->writesize;
73 ops.ooblen = mtd->oobsize;
74 ops.mode = MTD_OPS_RAW;
75 i = mtd_read_oob(mtd, addr, &ops);
77 printf("Error (%d) reading page %08lx\n", i, off);
81 printf("Page %08lx dump:\n", off);
84 i = mtd->writesize >> 4;
88 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
89 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
90 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
91 p[8], p[9], p[10], p[11], p[12], p[13], p[14],
98 i = mtd->oobsize >> 3;
101 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
102 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
114 /* ------------------------------------------------------------------------- */
116 static int set_dev(int dev)
118 struct mtd_info *mtd = get_nand_dev_by_index(dev);
123 if (nand_curr_device == dev)
126 printf("Device %d: %s", dev, mtd->name);
127 puts("... is now current device\n");
128 nand_curr_device = dev;
130 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
131 board_nand_select_device(mtd_to_nand(mtd), dev);
137 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
138 static void print_status(ulong start, ulong end, ulong erasesize, int status)
141 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
142 * not the same as others. Instead of bit 1 being lock, it is
143 * #lock_tight. To make the driver support either format, ignore bit 1
144 * and use only bit 0 and bit 2.
146 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
149 (end - start) / erasesize,
150 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
151 (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
152 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
155 static void do_nand_status(struct mtd_info *mtd)
157 ulong block_start = 0;
159 int last_status = -1;
161 struct nand_chip *nand_chip = mtd_to_nand(mtd);
162 /* check the WP bit */
163 nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
164 printf("device is %swrite protected\n",
165 (nand_chip->read_byte(mtd) & 0x80 ?
168 for (off = 0; off < mtd->size; off += mtd->erasesize) {
169 int s = nand_get_lock_status(mtd, off);
171 /* print message only if status has changed */
172 if (s != last_status && off != 0) {
173 print_status(block_start, off, mtd->erasesize,
179 /* Print the last block info */
180 print_status(block_start, off, mtd->erasesize, last_status);
184 #ifdef CONFIG_ENV_OFFSET_OOB
185 unsigned long nand_env_oob_offset;
187 int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
190 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
191 struct mtd_info *mtd = get_nand_dev_by_index(0);
194 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
195 puts("no devices available\n");
201 if (!strcmp(cmd, "get")) {
202 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
206 printf("0x%08lx\n", nand_env_oob_offset);
207 } else if (!strcmp(cmd, "set")) {
210 struct mtd_oob_ops ops;
216 mtd = get_nand_dev_by_index(idx);
217 /* We don't care about size, or maxsize. */
218 if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
219 MTD_DEV_TYPE_NAND, mtd->size)) {
220 puts("Offset or partition name expected\n");
224 puts("Offset or partition name expected\n");
229 puts("Partition not on first NAND device\n");
233 if (mtd->oobavail < ENV_OFFSET_SIZE) {
234 printf("Insufficient available OOB bytes:\n"
235 "%d OOB bytes available but %d required for "
237 mtd->oobavail, ENV_OFFSET_SIZE);
241 if ((addr & (mtd->erasesize - 1)) != 0) {
242 printf("Environment offset must be block-aligned\n");
247 ops.mode = MTD_OOB_AUTO;
249 ops.ooblen = ENV_OFFSET_SIZE;
250 ops.oobbuf = (void *) oob_buf;
252 oob_buf[0] = ENV_OOB_MARKER;
253 oob_buf[1] = addr / mtd->erasesize;
255 ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
257 printf("Error writing OOB block 0\n");
261 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
263 printf("Error reading env offset in OOB\n");
267 if (addr != nand_env_oob_offset) {
268 printf("Verification of env offset in OOB failed: "
269 "0x%08llx expected but got 0x%08lx\n",
270 (unsigned long long)addr, nand_env_oob_offset);
280 return CMD_RET_USAGE;
285 static void nand_print_and_set_info(int idx)
287 struct mtd_info *mtd;
288 struct nand_chip *chip;
290 mtd = get_nand_dev_by_index(idx);
294 chip = mtd_to_nand(mtd);
295 printf("Device %d: ", idx);
296 if (chip->numchips > 1)
297 printf("%dx ", chip->numchips);
298 printf("%s, sector size %u KiB\n",
299 mtd->name, mtd->erasesize >> 10);
300 printf(" Page size %8d b\n", mtd->writesize);
301 printf(" OOB size %8d b\n", mtd->oobsize);
302 printf(" Erase size %8d b\n", mtd->erasesize);
303 printf(" subpagesize %8d b\n", chip->subpagesize);
304 printf(" options 0x%08x\n", chip->options);
305 printf(" bbt options 0x%08x\n", chip->bbt_options);
307 /* Set geometry info */
308 env_set_hex("nand_writesize", mtd->writesize);
309 env_set_hex("nand_oobsize", mtd->oobsize);
310 env_set_hex("nand_erasesize", mtd->erasesize);
313 static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
314 ulong count, int read, int no_verify)
320 mtd_oob_ops_t ops = {
321 .datbuf = (u8 *)addr,
322 .oobbuf = ((u8 *)addr) + mtd->writesize,
323 .len = mtd->writesize,
324 .ooblen = mtd->oobsize,
329 ret = mtd_read_oob(mtd, off, &ops);
331 ret = mtd_write_oob(mtd, off, &ops);
332 if (!ret && !no_verify)
333 ret = nand_verify_page_oob(mtd, &ops, off);
337 printf("%s: error at offset %llx, ret %d\n",
338 __func__, (long long)off, ret);
342 addr += mtd->writesize + mtd->oobsize;
343 off += mtd->writesize;
349 /* Adjust a chip/partition size down for bad blocks so we don't
350 * read/write past the end of a chip/partition by accident.
352 static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
354 /* We grab the nand info object here fresh because this is usually
355 * called after arg_off_size() which can change the value of dev.
357 struct mtd_info *mtd = get_nand_dev_by_index(dev);
358 loff_t maxoffset = offset + *size;
361 /* count badblocks in NAND from offset to offset + size */
362 for (; offset < maxoffset; offset += mtd->erasesize) {
363 if (nand_block_isbad(mtd, offset))
366 /* adjust size if any bad blocks found */
368 *size -= badblocks * mtd->erasesize;
369 printf("size adjusted to 0x%llx (%d bad blocks)\n",
370 (unsigned long long)*size, badblocks);
374 static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
378 loff_t off, size, maxsize;
380 struct mtd_info *mtd;
381 #ifdef CONFIG_SYS_NAND_QUIET
382 int quiet = CONFIG_SYS_NAND_QUIET;
386 const char *quiet_str = env_get("quiet");
387 int dev = nand_curr_device;
388 int repeat = flag & CMD_FLAG_REPEAT;
390 /* at least two arguments please */
395 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
399 /* Only "dump" is repeatable. */
400 if (repeat && strcmp(cmd, "dump"))
403 if (strcmp(cmd, "info") == 0) {
406 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
407 nand_print_and_set_info(i);
411 if (strcmp(cmd, "device") == 0) {
414 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
415 puts("no devices available\n");
417 nand_print_and_set_info(dev);
421 dev = (int)simple_strtoul(argv[2], NULL, 10);
427 #ifdef CONFIG_ENV_OFFSET_OOB
428 /* this command operates only on the first nand device */
429 if (strcmp(cmd, "env.oob") == 0)
430 return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
433 /* The following commands operate on the current device, unless
434 * overridden by a partition specifier. Note that if somehow the
435 * current device is invalid, it will have to be changed to a valid
436 * one before these commands can run, even if a partition specifier
437 * for another device is to be used.
439 mtd = get_nand_dev_by_index(dev);
441 puts("\nno devices available\n");
445 if (strcmp(cmd, "bad") == 0) {
446 printf("\nDevice %d bad blocks:\n", dev);
447 for (off = 0; off < mtd->size; off += mtd->erasesize)
448 if (nand_block_isbad(mtd, off))
449 printf(" %08llx\n", (unsigned long long)off);
456 * nand erase [clean] [off size]
458 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
459 nand_erase_options_t opts;
460 /* "clean" at index 2 means request to write cleanmarker */
461 int clean = argc > 2 && !strcmp("clean", argv[2]);
462 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
463 int o = (clean || scrub_yes) ? 3 : 2;
464 int scrub = !strncmp(cmd, "scrub", 5);
467 const char *scrub_warn =
469 "scrub option will erase all factory set bad blocks!\n"
471 "There is no reliable way to recover them.\n"
473 "Use this command only for testing purposes if you\n"
475 "are sure of what you are doing!\n"
476 "\nReally scrub this NAND flash? <y/N>\n";
479 if (!strcmp(&cmd[5], ".spread")) {
481 } else if (!strcmp(&cmd[5], ".part")) {
483 } else if (!strcmp(&cmd[5], ".chip")) {
491 * Don't allow missing arguments to cause full chip/partition
492 * erases -- easy to do accidentally, e.g. with a misspelled
495 if (argc != o + args)
498 printf("\nNAND %s: ", cmd);
499 /* skip first two or three arguments, look for offset and size */
500 if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
501 &maxsize, MTD_DEV_TYPE_NAND,
508 mtd = get_nand_dev_by_index(dev);
510 memset(&opts, 0, sizeof(opts));
515 opts.spread = spread;
522 if (confirm_yesno()) {
525 puts("scrub aborted\n");
530 ret = nand_erase_opts(mtd, &opts);
531 printf("%s\n", ret ? "ERROR" : "OK");
533 return ret == 0 ? 0 : 1;
536 if (strncmp(cmd, "dump", 4) == 0) {
540 off = (int)simple_strtoul(argv[2], NULL, 16);
541 ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
543 return ret == 0 ? 1 : 0;
546 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
556 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
558 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
559 printf("\nNAND %s: ", read ? "read" : "write");
561 s = strchr(cmd, '.');
563 if (s && !strncmp(s, ".raw", 4)) {
566 if (!strcmp(s, ".raw.noverify"))
569 if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
577 mtd = get_nand_dev_by_index(dev);
579 if (argc > 4 && !str2long(argv[4], &pagecount)) {
580 printf("'%s' is not a number\n", argv[4]);
584 if (pagecount * mtd->writesize > size) {
585 puts("Size exceeds partition or device limit\n");
589 rwsize = pagecount * (mtd->writesize + mtd->oobsize);
591 if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
600 /* size is unspecified */
602 adjust_size_for_badblocks(&size, off, dev);
606 mtd = get_nand_dev_by_index(dev);
608 if (!s || !strcmp(s, ".jffs2") ||
609 !strcmp(s, ".e") || !strcmp(s, ".i")) {
611 ret = nand_read_skip_bad(mtd, off, &rwsize,
615 ret = nand_write_skip_bad(mtd, off, &rwsize,
619 #ifdef CONFIG_CMD_NAND_TRIMFFS
620 } else if (!strcmp(s, ".trimffs")) {
622 printf("Unknown nand command suffix '%s'\n", s);
625 ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
626 maxsize, (u_char *)addr,
627 WITH_DROP_FFS | WITH_WR_VERIFY);
629 } else if (!strcmp(s, ".oob")) {
630 /* out-of-band data */
631 mtd_oob_ops_t ops = {
632 .oobbuf = (u8 *)addr,
638 ret = mtd_read_oob(mtd, off, &ops);
640 ret = mtd_write_oob(mtd, off, &ops);
642 ret = raw_access(mtd, addr, off, pagecount, read,
645 printf("Unknown nand command suffix '%s'.\n", s);
649 printf(" %zu bytes %s: %s\n", rwsize,
650 read ? "read" : "written", ret ? "ERROR" : "OK");
652 return ret == 0 ? 0 : 1;
655 #ifdef CONFIG_CMD_NAND_TORTURE
656 if (strcmp(cmd, "torture") == 0) {
658 unsigned int failed = 0, passed = 0;
663 if (!str2off(argv[2], &off)) {
664 puts("Offset is not a valid number\n");
668 size = mtd->erasesize;
670 if (!str2off(argv[3], &size)) {
671 puts("Size is not a valid number\n");
677 if (endoff > mtd->size) {
678 puts("Arguments beyond end of NAND\n");
682 off = round_down(off, mtd->erasesize);
683 endoff = round_up(endoff, mtd->erasesize);
685 printf("\nNAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)\n",
686 dev, off, size, mtd->erasesize);
687 while (off < endoff) {
688 ret = nand_torture(mtd, off);
691 printf(" block at 0x%llx failed\n", off);
695 off += mtd->erasesize;
697 printf(" Passed: %u, failed: %u\n", passed, failed);
702 if (strcmp(cmd, "markbad") == 0) {
710 addr = simple_strtoul(*argv, NULL, 16);
712 if (mtd_block_markbad(mtd, addr)) {
713 printf("block 0x%08lx NOT marked "
714 "as bad! ERROR %d\n",
718 printf("block 0x%08lx successfully "
728 if (strcmp(cmd, "biterr") == 0) {
733 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
734 if (strcmp(cmd, "lock") == 0) {
738 if (!strcmp("tight", argv[2]))
740 if (!strcmp("status", argv[2]))
746 if (!nand_lock(mtd, tight)) {
747 puts("NAND flash successfully locked\n");
749 puts("Error locking NAND flash\n");
756 if (strncmp(cmd, "unlock", 5) == 0) {
759 s = strchr(cmd, '.');
761 if (s && !strcmp(s, ".allexcept"))
764 if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
765 &maxsize, MTD_DEV_TYPE_NAND,
772 mtd = get_nand_dev_by_index(dev);
774 if (!nand_unlock(mtd, off, size, allexcept)) {
775 puts("NAND flash successfully unlocked\n");
777 puts("Error unlocking NAND flash, "
778 "write and erase will probably fail\n");
786 return CMD_RET_USAGE;
789 #ifdef CONFIG_SYS_LONGHELP
790 static char nand_help_text[] =
791 "info - show available NAND devices\n"
792 "nand device [dev] - show or set current device\n"
793 "nand read - addr off|partition size\n"
794 "nand write - addr off|partition size\n"
795 " read/write 'size' bytes starting at offset 'off'\n"
796 " to/from memory address 'addr', skipping bad blocks.\n"
797 "nand read.raw - addr off|partition [count]\n"
798 "nand write.raw[.noverify] - addr off|partition [count]\n"
799 " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
800 #ifdef CONFIG_CMD_NAND_TRIMFFS
801 "nand write.trimffs - addr off|partition size\n"
802 " write 'size' bytes starting at offset 'off' from memory address\n"
803 " 'addr', skipping bad blocks and dropping any pages at the end\n"
804 " of eraseblocks that contain only 0xFF\n"
806 "nand erase[.spread] [clean] off size - erase 'size' bytes "
807 "from offset 'off'\n"
808 " With '.spread', erase enough for given file size, otherwise,\n"
809 " 'size' includes skipped bad blocks.\n"
810 "nand erase.part [clean] partition - erase entire mtd partition'\n"
811 "nand erase.chip [clean] - erase entire chip'\n"
812 "nand bad - show bad blocks\n"
813 "nand dump[.oob] off - dump page\n"
814 #ifdef CONFIG_CMD_NAND_TORTURE
815 "nand torture off - torture one block at offset\n"
816 "nand torture off [size] - torture blocks from off to off+size\n"
818 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
819 " really clean NAND erasing bad blocks (UNSAFE)\n"
820 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
821 "nand biterr off - make a bit error at offset (UNSAFE)"
822 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
824 "nand lock [tight] [status]\n"
825 " bring nand to lock state or display locked pages\n"
826 "nand unlock[.allexcept] [offset] [size] - unlock section"
828 #ifdef CONFIG_ENV_OFFSET_OOB
830 "nand env.oob - environment offset in OOB of block 0 of"
832 "nand env.oob set off|partition - set enviromnent offset\n"
833 "nand env.oob get - get environment offset"
839 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
840 "NAND sub-system", nand_help_text
843 static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd,
844 ulong offset, ulong addr, char *cmd)
849 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
852 #if defined(CONFIG_FIT)
853 const void *fit_hdr = NULL;
856 s = strchr(cmd, '.');
858 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
859 printf("Unknown nand load suffix '%s'\n", s);
860 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
864 printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
866 cnt = mtd->writesize;
867 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
870 puts("** Read error\n");
871 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
874 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
876 switch (genimg_get_format ((void *)addr)) {
877 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
878 case IMAGE_FORMAT_LEGACY:
879 hdr = (image_header_t *)addr;
881 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
882 image_print_contents (hdr);
884 cnt = image_get_image_size (hdr);
887 #if defined(CONFIG_FIT)
888 case IMAGE_FORMAT_FIT:
889 fit_hdr = (const void *)addr;
890 puts ("Fit image detected...\n");
892 cnt = fit_get_size (fit_hdr);
896 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
897 puts ("** Unknown image type\n");
900 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
902 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
905 puts("** Read error\n");
906 bootstage_error(BOOTSTAGE_ID_NAND_READ);
909 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
911 #if defined(CONFIG_FIT)
912 /* This cannot be done earlier, we need complete FIT image in RAM first */
913 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
914 if (!fit_check_format (fit_hdr)) {
915 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
916 puts ("** Bad FIT image format\n");
919 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
920 fit_print_contents (fit_hdr);
924 /* Loading ok, update default load address */
928 return bootm_maybe_autostart(cmdtp, cmd);
931 static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
934 char *boot_device = NULL;
936 ulong addr, offset = 0;
937 struct mtd_info *mtd;
938 #if defined(CONFIG_CMD_MTDPARTS)
939 struct mtd_device *dev;
940 struct part_info *part;
944 char *p = (argc == 2) ? argv[1] : argv[2];
945 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
946 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
947 if (dev->id->type != MTD_DEV_TYPE_NAND) {
948 puts("Not a NAND device\n");
954 addr = simple_strtoul(argv[1], NULL, 16);
956 addr = CONFIG_SYS_LOAD_ADDR;
958 mtd = get_nand_dev_by_index(dev->id->num);
959 return nand_load_image(cmdtp, mtd, part->offset,
965 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
968 addr = CONFIG_SYS_LOAD_ADDR;
969 boot_device = env_get("bootdevice");
972 addr = simple_strtoul(argv[1], NULL, 16);
973 boot_device = env_get("bootdevice");
976 addr = simple_strtoul(argv[1], NULL, 16);
977 boot_device = argv[2];
980 addr = simple_strtoul(argv[1], NULL, 16);
981 boot_device = argv[2];
982 offset = simple_strtoul(argv[3], NULL, 16);
985 #if defined(CONFIG_CMD_MTDPARTS)
988 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
989 return CMD_RET_USAGE;
991 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
994 puts("\n** No boot device **\n");
995 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
998 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1000 idx = simple_strtoul(boot_device, NULL, 16);
1002 mtd = get_nand_dev_by_index(idx);
1004 printf("\n** Device %d not available\n", idx);
1005 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
1008 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
1010 return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
1013 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
1014 "boot from NAND device",
1015 "[partition] | [[[loadAddr] dev] offset]"