2 * Driver for NAND support, Rick Bronson
3 * borrowed heavily from:
4 * (c) 1999 Machine Vision Holdings, Inc.
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 #include "legacy-mtd-utils.h"
35 #if defined(CONFIG_CMD_MTDPARTS)
37 /* partition handling routines */
38 int mtdparts_init(void);
39 int find_dev_and_part(const char *id, struct mtd_device **dev,
40 u8 *part_num, struct part_info **part);
43 static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
47 u_char *datbuf, *oobbuf, *p;
52 off = last + mtd->writesize;
56 datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
58 puts("No memory for page buffer\n");
62 oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
64 puts("No memory for page buffer\n");
68 off &= ~(mtd->writesize - 1);
69 loff_t addr = (loff_t) off;
70 struct mtd_oob_ops ops;
71 memset(&ops, 0, sizeof(ops));
74 ops.len = mtd->writesize;
75 ops.ooblen = mtd->oobsize;
76 ops.mode = MTD_OPS_RAW;
77 i = mtd_read_oob(mtd, addr, &ops);
79 printf("Error (%d) reading page %08lx\n", i, off);
83 printf("Page %08lx dump:\n", off);
86 i = mtd->writesize >> 4;
90 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
91 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
92 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
93 p[8], p[9], p[10], p[11], p[12], p[13], p[14],
100 i = mtd->oobsize >> 3;
103 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
104 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
116 /* ------------------------------------------------------------------------- */
118 static int set_dev(int dev)
120 struct mtd_info *mtd = get_nand_dev_by_index(dev);
125 if (nand_curr_device == dev)
128 printf("Device %d: %s", dev, mtd->name);
129 puts("... is now current device\n");
130 nand_curr_device = dev;
132 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
133 board_nand_select_device(mtd_to_nand(mtd), dev);
139 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
140 static void print_status(ulong start, ulong end, ulong erasesize, int status)
143 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
144 * not the same as others. Instead of bit 1 being lock, it is
145 * #lock_tight. To make the driver support either format, ignore bit 1
146 * and use only bit 0 and bit 2.
148 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
151 (end - start) / erasesize,
152 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
153 (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
154 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
157 static void do_nand_status(struct mtd_info *mtd)
159 ulong block_start = 0;
161 int last_status = -1;
163 struct nand_chip *nand_chip = mtd_to_nand(mtd);
164 /* check the WP bit */
165 nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
166 printf("device is %swrite protected\n",
167 (nand_chip->read_byte(mtd) & 0x80 ?
170 for (off = 0; off < mtd->size; off += mtd->erasesize) {
171 int s = nand_get_lock_status(mtd, off);
173 /* print message only if status has changed */
174 if (s != last_status && off != 0) {
175 print_status(block_start, off, mtd->erasesize,
181 /* Print the last block info */
182 print_status(block_start, off, mtd->erasesize, last_status);
186 #ifdef CONFIG_ENV_OFFSET_OOB
187 unsigned long nand_env_oob_offset;
189 int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
192 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
193 struct mtd_info *mtd = get_nand_dev_by_index(0);
196 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
197 puts("no devices available\n");
203 if (!strcmp(cmd, "get")) {
204 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
208 printf("0x%08lx\n", nand_env_oob_offset);
209 } else if (!strcmp(cmd, "set")) {
212 struct mtd_oob_ops ops;
218 mtd = get_nand_dev_by_index(idx);
219 /* We don't care about size, or maxsize. */
220 if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
221 MTD_DEV_TYPE_NAND, mtd->size)) {
222 puts("Offset or partition name expected\n");
226 puts("Offset or partition name expected\n");
231 puts("Partition not on first NAND device\n");
235 if (mtd->oobavail < ENV_OFFSET_SIZE) {
236 printf("Insufficient available OOB bytes:\n"
237 "%d OOB bytes available but %d required for "
239 mtd->oobavail, ENV_OFFSET_SIZE);
243 if ((addr & (mtd->erasesize - 1)) != 0) {
244 printf("Environment offset must be block-aligned\n");
249 ops.mode = MTD_OOB_AUTO;
251 ops.ooblen = ENV_OFFSET_SIZE;
252 ops.oobbuf = (void *) oob_buf;
254 oob_buf[0] = ENV_OOB_MARKER;
255 oob_buf[1] = addr / mtd->erasesize;
257 ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
259 printf("Error writing OOB block 0\n");
263 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
265 printf("Error reading env offset in OOB\n");
269 if (addr != nand_env_oob_offset) {
270 printf("Verification of env offset in OOB failed: "
271 "0x%08llx expected but got 0x%08lx\n",
272 (unsigned long long)addr, nand_env_oob_offset);
282 return CMD_RET_USAGE;
287 static void nand_print_and_set_info(int idx)
289 struct mtd_info *mtd;
290 struct nand_chip *chip;
292 mtd = get_nand_dev_by_index(idx);
296 chip = mtd_to_nand(mtd);
297 printf("Device %d: ", idx);
298 if (chip->numchips > 1)
299 printf("%dx ", chip->numchips);
300 printf("%s, sector size %u KiB\n",
301 mtd->name, mtd->erasesize >> 10);
302 printf(" Page size %8d b\n", mtd->writesize);
303 printf(" OOB size %8d b\n", mtd->oobsize);
304 printf(" Erase size %8d b\n", mtd->erasesize);
305 printf(" subpagesize %8d b\n", chip->subpagesize);
306 printf(" options 0x%08x\n", chip->options);
307 printf(" bbt options 0x%08x\n", chip->bbt_options);
309 /* Set geometry info */
310 env_set_hex("nand_writesize", mtd->writesize);
311 env_set_hex("nand_oobsize", mtd->oobsize);
312 env_set_hex("nand_erasesize", mtd->erasesize);
315 static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
316 ulong count, int read, int no_verify)
322 mtd_oob_ops_t ops = {
323 .datbuf = (u8 *)addr,
324 .oobbuf = ((u8 *)addr) + mtd->writesize,
325 .len = mtd->writesize,
326 .ooblen = mtd->oobsize,
331 ret = mtd_read_oob(mtd, off, &ops);
333 ret = mtd_write_oob(mtd, off, &ops);
334 if (!ret && !no_verify)
335 ret = nand_verify_page_oob(mtd, &ops, off);
339 printf("%s: error at offset %llx, ret %d\n",
340 __func__, (long long)off, ret);
344 addr += mtd->writesize + mtd->oobsize;
345 off += mtd->writesize;
351 /* Adjust a chip/partition size down for bad blocks so we don't
352 * read/write past the end of a chip/partition by accident.
354 static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
356 /* We grab the nand info object here fresh because this is usually
357 * called after arg_off_size() which can change the value of dev.
359 struct mtd_info *mtd = get_nand_dev_by_index(dev);
360 loff_t maxoffset = offset + *size;
363 /* count badblocks in NAND from offset to offset + size */
364 for (; offset < maxoffset; offset += mtd->erasesize) {
365 if (nand_block_isbad(mtd, offset))
368 /* adjust size if any bad blocks found */
370 *size -= badblocks * mtd->erasesize;
371 printf("size adjusted to 0x%llx (%d bad blocks)\n",
372 (unsigned long long)*size, badblocks);
376 static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
380 loff_t off, size, maxsize;
382 struct mtd_info *mtd;
383 #ifdef CONFIG_SYS_NAND_QUIET
384 int quiet = CONFIG_SYS_NAND_QUIET;
388 const char *quiet_str = env_get("quiet");
389 int dev = nand_curr_device;
390 int repeat = flag & CMD_FLAG_REPEAT;
392 /* at least two arguments please */
397 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
401 /* Only "dump" is repeatable. */
402 if (repeat && strcmp(cmd, "dump"))
405 if (strcmp(cmd, "info") == 0) {
408 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
409 nand_print_and_set_info(i);
413 if (strcmp(cmd, "device") == 0) {
416 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
417 puts("no devices available\n");
419 nand_print_and_set_info(dev);
423 dev = (int)simple_strtoul(argv[2], NULL, 10);
429 #ifdef CONFIG_ENV_OFFSET_OOB
430 /* this command operates only on the first nand device */
431 if (strcmp(cmd, "env.oob") == 0)
432 return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
435 /* The following commands operate on the current device, unless
436 * overridden by a partition specifier. Note that if somehow the
437 * current device is invalid, it will have to be changed to a valid
438 * one before these commands can run, even if a partition specifier
439 * for another device is to be used.
441 mtd = get_nand_dev_by_index(dev);
443 puts("\nno devices available\n");
447 if (strcmp(cmd, "bad") == 0) {
448 printf("\nDevice %d bad blocks:\n", dev);
449 for (off = 0; off < mtd->size; off += mtd->erasesize)
450 if (nand_block_isbad(mtd, off))
451 printf(" %08llx\n", (unsigned long long)off);
458 * nand erase [clean] [off size]
460 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
461 nand_erase_options_t opts;
462 /* "clean" at index 2 means request to write cleanmarker */
463 int clean = argc > 2 && !strcmp("clean", argv[2]);
464 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
465 int o = (clean || scrub_yes) ? 3 : 2;
466 int scrub = !strncmp(cmd, "scrub", 5);
469 const char *scrub_warn =
471 "scrub option will erase all factory set bad blocks!\n"
473 "There is no reliable way to recover them.\n"
475 "Use this command only for testing purposes if you\n"
477 "are sure of what you are doing!\n"
478 "\nReally scrub this NAND flash? <y/N>\n";
481 if (!strcmp(&cmd[5], ".spread")) {
483 } else if (!strcmp(&cmd[5], ".part")) {
485 } else if (!strcmp(&cmd[5], ".chip")) {
493 * Don't allow missing arguments to cause full chip/partition
494 * erases -- easy to do accidentally, e.g. with a misspelled
497 if (argc != o + args)
500 printf("\nNAND %s: ", cmd);
501 /* skip first two or three arguments, look for offset and size */
502 if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
503 &maxsize, MTD_DEV_TYPE_NAND,
510 mtd = get_nand_dev_by_index(dev);
512 memset(&opts, 0, sizeof(opts));
517 opts.spread = spread;
524 if (confirm_yesno()) {
527 puts("scrub aborted\n");
532 ret = nand_erase_opts(mtd, &opts);
533 printf("%s\n", ret ? "ERROR" : "OK");
535 return ret == 0 ? 0 : 1;
538 if (strncmp(cmd, "dump", 4) == 0) {
542 off = (int)simple_strtoul(argv[2], NULL, 16);
543 ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
545 return ret == 0 ? 1 : 0;
548 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
558 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
560 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
561 printf("\nNAND %s: ", read ? "read" : "write");
563 s = strchr(cmd, '.');
565 if (s && !strncmp(s, ".raw", 4)) {
568 if (!strcmp(s, ".raw.noverify"))
571 if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
579 mtd = get_nand_dev_by_index(dev);
581 if (argc > 4 && !str2long(argv[4], &pagecount)) {
582 printf("'%s' is not a number\n", argv[4]);
586 if (pagecount * mtd->writesize > size) {
587 puts("Size exceeds partition or device limit\n");
591 rwsize = pagecount * (mtd->writesize + mtd->oobsize);
593 if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
602 /* size is unspecified */
604 adjust_size_for_badblocks(&size, off, dev);
608 mtd = get_nand_dev_by_index(dev);
610 if (!s || !strcmp(s, ".jffs2") ||
611 !strcmp(s, ".e") || !strcmp(s, ".i")) {
613 ret = nand_read_skip_bad(mtd, off, &rwsize,
617 ret = nand_write_skip_bad(mtd, off, &rwsize,
621 #ifdef CONFIG_CMD_NAND_TRIMFFS
622 } else if (!strcmp(s, ".trimffs")) {
624 printf("Unknown nand command suffix '%s'\n", s);
627 ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
628 maxsize, (u_char *)addr,
629 WITH_DROP_FFS | WITH_WR_VERIFY);
631 } else if (!strcmp(s, ".oob")) {
632 /* out-of-band data */
633 mtd_oob_ops_t ops = {
634 .oobbuf = (u8 *)addr,
640 ret = mtd_read_oob(mtd, off, &ops);
642 ret = mtd_write_oob(mtd, off, &ops);
644 ret = raw_access(mtd, addr, off, pagecount, read,
647 printf("Unknown nand command suffix '%s'.\n", s);
651 printf(" %zu bytes %s: %s\n", rwsize,
652 read ? "read" : "written", ret ? "ERROR" : "OK");
654 return ret == 0 ? 0 : 1;
657 #ifdef CONFIG_CMD_NAND_TORTURE
658 if (strcmp(cmd, "torture") == 0) {
660 unsigned int failed = 0, passed = 0;
665 if (!str2off(argv[2], &off)) {
666 puts("Offset is not a valid number\n");
670 size = mtd->erasesize;
672 if (!str2off(argv[3], &size)) {
673 puts("Size is not a valid number\n");
679 if (endoff > mtd->size) {
680 puts("Arguments beyond end of NAND\n");
684 off = round_down(off, mtd->erasesize);
685 endoff = round_up(endoff, mtd->erasesize);
687 printf("\nNAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)\n",
688 dev, off, size, mtd->erasesize);
689 while (off < endoff) {
690 ret = nand_torture(mtd, off);
693 printf(" block at 0x%llx failed\n", off);
697 off += mtd->erasesize;
699 printf(" Passed: %u, failed: %u\n", passed, failed);
704 if (strcmp(cmd, "markbad") == 0) {
712 addr = simple_strtoul(*argv, NULL, 16);
714 if (mtd_block_markbad(mtd, addr)) {
715 printf("block 0x%08lx NOT marked "
716 "as bad! ERROR %d\n",
720 printf("block 0x%08lx successfully "
730 if (strcmp(cmd, "biterr") == 0) {
735 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
736 if (strcmp(cmd, "lock") == 0) {
740 if (!strcmp("tight", argv[2]))
742 if (!strcmp("status", argv[2]))
748 if (!nand_lock(mtd, tight)) {
749 puts("NAND flash successfully locked\n");
751 puts("Error locking NAND flash\n");
758 if (strncmp(cmd, "unlock", 5) == 0) {
761 s = strchr(cmd, '.');
763 if (s && !strcmp(s, ".allexcept"))
766 if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
767 &maxsize, MTD_DEV_TYPE_NAND,
774 mtd = get_nand_dev_by_index(dev);
776 if (!nand_unlock(mtd, off, size, allexcept)) {
777 puts("NAND flash successfully unlocked\n");
779 puts("Error unlocking NAND flash, "
780 "write and erase will probably fail\n");
788 return CMD_RET_USAGE;
791 #ifdef CONFIG_SYS_LONGHELP
792 static char nand_help_text[] =
793 "info - show available NAND devices\n"
794 "nand device [dev] - show or set current device\n"
795 "nand read - addr off|partition size\n"
796 "nand write - addr off|partition size\n"
797 " read/write 'size' bytes starting at offset 'off'\n"
798 " to/from memory address 'addr', skipping bad blocks.\n"
799 "nand read.raw - addr off|partition [count]\n"
800 "nand write.raw[.noverify] - addr off|partition [count]\n"
801 " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
802 #ifdef CONFIG_CMD_NAND_TRIMFFS
803 "nand write.trimffs - addr off|partition size\n"
804 " write 'size' bytes starting at offset 'off' from memory address\n"
805 " 'addr', skipping bad blocks and dropping any pages at the end\n"
806 " of eraseblocks that contain only 0xFF\n"
808 "nand erase[.spread] [clean] off size - erase 'size' bytes "
809 "from offset 'off'\n"
810 " With '.spread', erase enough for given file size, otherwise,\n"
811 " 'size' includes skipped bad blocks.\n"
812 "nand erase.part [clean] partition - erase entire mtd partition'\n"
813 "nand erase.chip [clean] - erase entire chip'\n"
814 "nand bad - show bad blocks\n"
815 "nand dump[.oob] off - dump page\n"
816 #ifdef CONFIG_CMD_NAND_TORTURE
817 "nand torture off - torture one block at offset\n"
818 "nand torture off [size] - torture blocks from off to off+size\n"
820 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
821 " really clean NAND erasing bad blocks (UNSAFE)\n"
822 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
823 "nand biterr off - make a bit error at offset (UNSAFE)"
824 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
826 "nand lock [tight] [status]\n"
827 " bring nand to lock state or display locked pages\n"
828 "nand unlock[.allexcept] [offset] [size] - unlock section"
830 #ifdef CONFIG_ENV_OFFSET_OOB
832 "nand env.oob - environment offset in OOB of block 0 of"
834 "nand env.oob set off|partition - set enviromnent offset\n"
835 "nand env.oob get - get environment offset"
841 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
842 "NAND sub-system", nand_help_text
845 static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd,
846 ulong offset, ulong addr, char *cmd)
851 #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
854 #if defined(CONFIG_FIT)
855 const void *fit_hdr = NULL;
858 s = strchr(cmd, '.');
860 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
861 printf("Unknown nand load suffix '%s'\n", s);
862 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
866 printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
868 cnt = mtd->writesize;
869 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
872 puts("** Read error\n");
873 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
876 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
878 switch (genimg_get_format ((void *)addr)) {
879 #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
880 case IMAGE_FORMAT_LEGACY:
881 hdr = (image_header_t *)addr;
883 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
884 image_print_contents (hdr);
886 cnt = image_get_image_size (hdr);
889 #if defined(CONFIG_FIT)
890 case IMAGE_FORMAT_FIT:
891 fit_hdr = (const void *)addr;
892 puts ("Fit image detected...\n");
894 cnt = fit_get_size (fit_hdr);
898 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
899 puts ("** Unknown image type\n");
902 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
904 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
907 puts("** Read error\n");
908 bootstage_error(BOOTSTAGE_ID_NAND_READ);
911 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
913 #if defined(CONFIG_FIT)
914 /* This cannot be done earlier, we need complete FIT image in RAM first */
915 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
916 if (!fit_check_format (fit_hdr)) {
917 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
918 puts ("** Bad FIT image format\n");
921 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
922 fit_print_contents (fit_hdr);
926 /* Loading ok, update default load address */
930 return bootm_maybe_autostart(cmdtp, cmd);
933 static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
936 char *boot_device = NULL;
938 ulong addr, offset = 0;
939 struct mtd_info *mtd;
940 #if defined(CONFIG_CMD_MTDPARTS)
941 struct mtd_device *dev;
942 struct part_info *part;
946 char *p = (argc == 2) ? argv[1] : argv[2];
947 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
948 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
949 if (dev->id->type != MTD_DEV_TYPE_NAND) {
950 puts("Not a NAND device\n");
956 addr = simple_strtoul(argv[1], NULL, 16);
958 addr = CONFIG_SYS_LOAD_ADDR;
960 mtd = get_nand_dev_by_index(dev->id->num);
961 return nand_load_image(cmdtp, mtd, part->offset,
967 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
970 addr = CONFIG_SYS_LOAD_ADDR;
971 boot_device = env_get("bootdevice");
974 addr = simple_strtoul(argv[1], NULL, 16);
975 boot_device = env_get("bootdevice");
978 addr = simple_strtoul(argv[1], NULL, 16);
979 boot_device = argv[2];
982 addr = simple_strtoul(argv[1], NULL, 16);
983 boot_device = argv[2];
984 offset = simple_strtoul(argv[3], NULL, 16);
987 #if defined(CONFIG_CMD_MTDPARTS)
990 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
991 return CMD_RET_USAGE;
993 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
996 puts("\n** No boot device **\n");
997 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1000 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1002 idx = simple_strtoul(boot_device, NULL, 16);
1004 mtd = get_nand_dev_by_index(idx);
1006 printf("\n** Device %d not available\n", idx);
1007 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
1010 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
1012 return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
1015 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
1016 "boot from NAND device",
1017 "[partition] | [[[loadAddr] dev] offset]"