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 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;
47 off = last + nand->writesize;
51 datbuf = malloc(nand->writesize);
52 oobbuf = malloc(nand->oobsize);
53 if (!datbuf || !oobbuf) {
54 puts("No memory for page buffer\n");
57 off &= ~(nand->writesize - 1);
58 loff_t addr = (loff_t) off;
59 struct mtd_oob_ops ops;
60 memset(&ops, 0, sizeof(ops));
63 ops.len = nand->writesize;
64 ops.ooblen = nand->oobsize;
65 ops.mode = MTD_OOB_RAW;
66 i = nand->read_oob(nand, addr, &ops);
68 printf("Error (%d) reading page %08lx\n", i, off);
73 printf("Page %08lx dump:\n", off);
74 i = nand->writesize >> 4;
79 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
80 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
81 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
82 p[8], p[9], p[10], p[11], p[12], p[13], p[14],
87 i = nand->oobsize >> 3;
90 printf("\t%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]);
100 /* ------------------------------------------------------------------------- */
102 static int set_dev(int dev)
104 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
105 !nand_info[dev].name) {
106 puts("No such device\n");
110 if (nand_curr_device == dev)
113 printf("Device %d: %s", dev, nand_info[dev].name);
114 puts("... is now current device\n");
115 nand_curr_device = dev;
117 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
118 board_nand_select_device(nand_info[dev].priv, dev);
124 static inline int str2off(const char *p, loff_t *num)
128 *num = simple_strtoull(p, &endptr, 16);
129 return *p != '\0' && *endptr == '\0';
132 static inline int str2long(const char *p, ulong *num)
136 *num = simple_strtoul(p, &endptr, 16);
137 return *p != '\0' && *endptr == '\0';
140 static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)
142 #ifdef CONFIG_CMD_MTDPARTS
143 struct mtd_device *dev;
144 struct part_info *part;
148 ret = mtdparts_init();
152 ret = find_dev_and_part(partname, &dev, &pnum, &part);
156 if (dev->id->type != MTD_DEV_TYPE_NAND) {
157 puts("not a NAND device\n");
171 puts("offset is not a number\n");
176 static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize)
178 if (!str2off(arg, off))
179 return get_part(arg, idx, off, maxsize);
181 if (*off >= nand_info[*idx].size) {
182 puts("Offset exceeds device limit\n");
186 *maxsize = nand_info[*idx].size - *off;
190 static int arg_off_size(int argc, char *const argv[], int *idx,
191 loff_t *off, loff_t *size)
198 *size = nand_info[*idx].size;
202 ret = arg_off(argv[0], idx, off, &maxsize);
211 if (!str2off(argv[1], size)) {
212 printf("'%s' is not a number\n", argv[1]);
216 if (*size > maxsize) {
217 puts("Size exceeds partition or device limit\n");
222 printf("device %d ", *idx);
223 if (*size == nand_info[*idx].size)
224 puts("whole chip\n");
226 printf("offset 0x%llx, size 0x%llx\n",
227 (unsigned long long)*off, (unsigned long long)*size);
231 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
232 static void print_status(ulong start, ulong end, ulong erasesize, int status)
234 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
237 (end - start) / erasesize,
238 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
239 ((status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""),
240 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
243 static void do_nand_status(nand_info_t *nand)
245 ulong block_start = 0;
247 int last_status = -1;
249 struct nand_chip *nand_chip = nand->priv;
250 /* check the WP bit */
251 nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1);
252 printf("device is %swrite protected\n",
253 (nand_chip->read_byte(nand) & 0x80 ?
256 for (off = 0; off < nand->size; off += nand->erasesize) {
257 int s = nand_get_lock_status(nand, off);
259 /* print message only if status has changed */
260 if (s != last_status && off != 0) {
261 print_status(block_start, off, nand->erasesize,
267 /* Print the last block info */
268 print_status(block_start, off, nand->erasesize, last_status);
272 #ifdef CONFIG_ENV_OFFSET_OOB
273 unsigned long nand_env_oob_offset;
275 int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
278 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
279 nand_info_t *nand = &nand_info[0];
282 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
283 puts("no devices available\n");
289 if (!strcmp(cmd, "get")) {
290 ret = get_nand_env_oob(nand, &nand_env_oob_offset);
294 printf("0x%08lx\n", nand_env_oob_offset);
295 } else if (!strcmp(cmd, "set")) {
298 struct mtd_oob_ops ops;
304 if (arg_off(argv[2], &idx, &addr, &maxsize)) {
305 puts("Offset or partition name expected\n");
310 puts("Partition not on first NAND device\n");
314 if (nand->oobavail < ENV_OFFSET_SIZE) {
315 printf("Insufficient available OOB bytes:\n"
316 "%d OOB bytes available but %d required for "
318 nand->oobavail, ENV_OFFSET_SIZE);
322 if ((addr & (nand->erasesize - 1)) != 0) {
323 printf("Environment offset must be block-aligned\n");
328 ops.mode = MTD_OOB_AUTO;
330 ops.ooblen = ENV_OFFSET_SIZE;
331 ops.oobbuf = (void *) oob_buf;
333 oob_buf[0] = ENV_OOB_MARKER;
334 oob_buf[1] = addr / nand->erasesize;
336 ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops);
338 printf("Error writing OOB block 0\n");
342 ret = get_nand_env_oob(nand, &nand_env_oob_offset);
344 printf("Error reading env offset in OOB\n");
348 if (addr != nand_env_oob_offset) {
349 printf("Verification of env offset in OOB failed: "
350 "0x%08llx expected but got 0x%08lx\n",
351 (unsigned long long)addr, nand_env_oob_offset);
361 return CMD_RET_USAGE;
366 static void nand_print_and_set_info(int idx)
368 nand_info_t *nand = &nand_info[idx];
369 struct nand_chip *chip = nand->priv;
370 const int bufsz = 32;
373 printf("Device %d: ", idx);
374 if (chip->numchips > 1)
375 printf("%dx ", chip->numchips);
376 printf("%s, sector size %u KiB\n",
377 nand->name, nand->erasesize >> 10);
378 printf(" Page size %8d b\n", nand->writesize);
379 printf(" OOB size %8d b\n", nand->oobsize);
380 printf(" Erase size %8d b\n", nand->erasesize);
382 /* Set geometry info */
383 sprintf(buf, "%x", nand->writesize);
384 setenv("nand_writesize", buf);
386 sprintf(buf, "%x", nand->oobsize);
387 setenv("nand_oobsize", buf);
389 sprintf(buf, "%x", nand->erasesize);
390 setenv("nand_erasesize", buf);
393 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
400 #ifdef CONFIG_SYS_NAND_QUIET
401 int quiet = CONFIG_SYS_NAND_QUIET;
405 const char *quiet_str = getenv("quiet");
406 int dev = nand_curr_device;
407 int repeat = flag & CMD_FLAG_REPEAT;
409 /* at least two arguments please */
414 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
418 /* Only "dump" is repeatable. */
419 if (repeat && strcmp(cmd, "dump"))
420 return CMD_RET_FAILURE;
422 if (strcmp(cmd, "info") == 0) {
425 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
426 if (nand_info[i].name)
427 nand_print_and_set_info(i);
429 return CMD_RET_SUCCESS;
432 if (strcmp(cmd, "device") == 0) {
435 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
436 puts("no devices available\n");
438 nand_print_and_set_info(dev);
439 return CMD_RET_SUCCESS;
442 dev = (int)simple_strtoul(argv[2], NULL, 10);
445 return CMD_RET_SUCCESS;
448 #ifdef CONFIG_ENV_OFFSET_OOB
449 /* this command operates only on the first nand device */
450 if (strcmp(cmd, "env.oob") == 0)
451 return do_nand_env_oob(cmdtp, argc - 1, argv + 1) ?
452 CMD_RET_FAILURE : CMD_RET_SUCCESS;;
455 /* The following commands operate on the current device, unless
456 * overridden by a partition specifier. Note that if somehow the
457 * current device is invalid, it will have to be changed to a valid
458 * one before these commands can run, even if a partition specifier
459 * for another device is to be used.
461 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
462 !nand_info[dev].name) {
463 puts("\nno devices available\n");
464 return CMD_RET_FAILURE;
466 nand = &nand_info[dev];
468 if (strcmp(cmd, "bad") == 0) {
469 printf("\nDevice %d bad blocks:\n", dev);
470 for (off = 0; off < nand->size; off += nand->erasesize)
471 if (nand_block_isbad(nand, off))
472 printf(" %08llx\n", (unsigned long long)off);
473 return CMD_RET_SUCCESS;
479 * nand erase [clean] [off size]
481 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
482 nand_erase_options_t opts;
483 /* "clean" at index 2 means request to write cleanmarker */
484 int clean = argc > 2 && !strcmp("clean", argv[2]);
485 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
486 int o = (clean || scrub_yes) ? 3 : 2;
487 int scrub = !strncmp(cmd, "scrub", 5);
490 const char *scrub_warn =
492 "scrub option will erase all factory set bad blocks!\n"
494 "There is no reliable way to recover them.\n"
496 "Use this command only for testing purposes if you\n"
498 "are sure of what you are doing!\n"
499 "\nReally scrub this NAND flash? <y/N>\n";
502 if (!strcmp(&cmd[5], ".spread")) {
504 } else if (!strcmp(&cmd[5], ".part")) {
506 } else if (!strcmp(&cmd[5], ".chip")) {
514 * Don't allow missing arguments to cause full chip/partition
515 * erases -- easy to do accidentally, e.g. with a misspelled
518 if (argc != o + args)
521 printf("\nNAND %s: ", cmd);
522 /* skip first two or three arguments, look for offset and size */
523 if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0)
524 return CMD_RET_FAILURE;
526 nand = &nand_info[dev];
528 memset(&opts, 0, sizeof(opts));
533 opts.spread = spread;
541 else if (getc() == 'y') {
546 puts("scrub aborted\n");
547 return CMD_RET_FAILURE;
550 puts("scrub aborted\n");
551 return CMD_RET_FAILURE;
554 ret = nand_erase_opts(nand, &opts);
555 printf("%s\n", ret ? "ERROR" : "OK");
557 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
560 if (strncmp(cmd, "dump", 4) == 0) {
564 off = (int)simple_strtoul(argv[2], NULL, 16);
565 ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
567 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
570 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
577 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
579 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
580 printf("\nNAND %s: ", read ? "read" : "write");
581 if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0)
582 return CMD_RET_FAILURE;
584 nand = &nand_info[dev];
587 s = strchr(cmd, '.');
588 if (!s || !strcmp(s, ".jffs2") ||
589 !strcmp(s, ".e") || !strcmp(s, ".i")) {
591 ret = nand_read_skip_bad(nand, off, &rwsize,
594 ret = nand_write_skip_bad(nand, off, &rwsize,
596 #ifdef CONFIG_CMD_NAND_TRIMFFS
597 } else if (!strcmp(s, ".trimffs")) {
599 printf("Unknown nand command suffix '%s'\n", s);
600 return CMD_RET_FAILURE;
602 ret = nand_write_skip_bad(nand, off, &rwsize,
606 #ifdef CONFIG_CMD_NAND_YAFFS
607 } else if (!strcmp(s, ".yaffs")) {
609 printf("Unknown nand command suffix '%s'.\n", s);
610 return CMD_RET_FAILURE;
612 ret = nand_write_skip_bad(nand, off, &rwsize,
613 (u_char *)addr, WITH_YAFFS_OOB);
615 } else if (!strcmp(s, ".oob")) {
616 /* out-of-band data */
617 mtd_oob_ops_t ops = {
618 .oobbuf = (u8 *)addr,
624 ret = nand->read_oob(nand, off, &ops);
626 ret = nand->write_oob(nand, off, &ops);
627 } else if (!strcmp(s, ".raw")) {
629 mtd_oob_ops_t ops = {
630 .datbuf = (u8 *)addr,
631 .oobbuf = ((u8 *)addr) + nand->writesize,
632 .len = nand->writesize,
633 .ooblen = nand->oobsize,
637 rwsize = nand->writesize + nand->oobsize;
640 ret = nand->read_oob(nand, off, &ops);
642 ret = nand->write_oob(nand, off, &ops);
644 printf("Unknown nand command suffix '%s'.\n", s);
645 return CMD_RET_FAILURE;
648 printf(" %zu bytes %s: %s\n", rwsize,
649 read ? "read" : "written", ret ? "ERROR" : "OK");
651 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
654 if (strcmp(cmd, "markbad") == 0) {
662 addr = simple_strtoul(*argv, NULL, 16);
664 if (nand->block_markbad(nand, addr)) {
665 printf("block 0x%08lx NOT marked "
666 "as bad! ERROR %d\n",
670 printf("block 0x%08lx successfully "
677 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
680 if (strcmp(cmd, "biterr") == 0) {
682 return CMD_RET_FAILURE;
685 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
686 if (strcmp(cmd, "lock") == 0) {
690 if (!strcmp("tight", argv[2]))
692 if (!strcmp("status", argv[2]))
696 do_nand_status(nand);
698 if (!nand_lock(nand, tight)) {
699 puts("NAND flash successfully locked\n");
701 puts("Error locking NAND flash\n");
702 return CMD_RET_FAILURE;
705 return CMD_RET_SUCCESS;
708 if (strcmp(cmd, "unlock") == 0) {
709 if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0)
710 return CMD_RET_FAILURE;
712 if (!nand_unlock(&nand_info[dev], off, size)) {
713 puts("NAND flash successfully unlocked\n");
715 puts("Error unlocking NAND flash, "
716 "write and erase will probably fail\n");
717 return CMD_RET_FAILURE;
719 return CMD_RET_SUCCESS;
724 return CMD_RET_USAGE;
728 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
730 "info - show available NAND devices\n"
731 "nand device [dev] - show or set current device\n"
732 "nand read - addr off|partition size\n"
733 "nand write - addr off|partition size\n"
734 " read/write 'size' bytes starting at offset 'off'\n"
735 " to/from memory address 'addr', skipping bad blocks.\n"
736 "nand read.raw - addr off|partition\n"
737 "nand write.raw - addr off|partition\n"
738 " Use read.raw/write.raw to avoid ECC and access the page as-is.\n"
739 #ifdef CONFIG_CMD_NAND_TRIMFFS
740 "nand write.trimffs - addr off|partition size\n"
741 " write 'size' bytes starting at offset 'off' from memory address\n"
742 " 'addr', skipping bad blocks and dropping any pages at the end\n"
743 " of eraseblocks that contain only 0xFF\n"
745 #ifdef CONFIG_CMD_NAND_YAFFS
746 "nand write.yaffs - addr off|partition size\n"
747 " write 'size' bytes starting at offset 'off' with yaffs format\n"
748 " from memory address 'addr', skipping bad blocks.\n"
750 "nand erase[.spread] [clean] off size - erase 'size' bytes "
751 "from offset 'off'\n"
752 " With '.spread', erase enough for given file size, otherwise,\n"
753 " 'size' includes skipped bad blocks.\n"
754 "nand erase.part [clean] partition - erase entire mtd partition'\n"
755 "nand erase.chip [clean] - erase entire chip'\n"
756 "nand bad - show bad blocks\n"
757 "nand dump[.oob] off - dump page\n"
758 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
759 " really clean NAND erasing bad blocks (UNSAFE)\n"
760 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
761 "nand biterr off - make a bit error at offset (UNSAFE)"
762 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
764 "nand lock [tight] [status]\n"
765 " bring nand to lock state or display locked pages\n"
766 "nand unlock [offset] [size] - unlock section"
768 #ifdef CONFIG_ENV_OFFSET_OOB
770 "nand env.oob - environment offset in OOB of block 0 of"
772 "nand env.oob set off|partition - set enviromnent offset\n"
773 "nand env.oob get - get environment offset"
777 static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
778 ulong offset, ulong addr, char *cmd)
784 #if defined(CONFIG_FIT)
785 const void *fit_hdr = NULL;
788 s = strchr(cmd, '.');
790 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
791 printf("Unknown nand load suffix '%s'\n", s);
792 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
796 printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
798 cnt = nand->writesize;
799 r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr);
801 puts("** Read error\n");
802 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
805 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
807 switch (genimg_get_format ((void *)addr)) {
808 case IMAGE_FORMAT_LEGACY:
809 hdr = (image_header_t *)addr;
811 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
812 image_print_contents (hdr);
814 cnt = image_get_image_size (hdr);
816 #if defined(CONFIG_FIT)
817 case IMAGE_FORMAT_FIT:
818 fit_hdr = (const void *)addr;
819 puts ("Fit image detected...\n");
821 cnt = fit_get_size (fit_hdr);
825 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
826 puts ("** Unknown image type\n");
829 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
831 r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr);
833 puts("** Read error\n");
834 bootstage_error(BOOTSTAGE_ID_NAND_READ);
837 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
839 #if defined(CONFIG_FIT)
840 /* This cannot be done earlier, we need complete FIT image in RAM first */
841 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
842 if (!fit_check_format (fit_hdr)) {
843 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
844 puts ("** Bad FIT image format\n");
847 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
848 fit_print_contents (fit_hdr);
852 /* Loading ok, update default load address */
856 return bootm_maybe_autostart(cmdtp, cmd);
859 int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
861 char *boot_device = NULL;
863 ulong addr, offset = 0;
864 #if defined(CONFIG_CMD_MTDPARTS)
865 struct mtd_device *dev;
866 struct part_info *part;
870 char *p = (argc == 2) ? argv[1] : argv[2];
871 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
872 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
873 if (dev->id->type != MTD_DEV_TYPE_NAND) {
874 puts("Not a NAND device\n");
880 addr = simple_strtoul(argv[1], NULL, 16);
882 addr = CONFIG_SYS_LOAD_ADDR;
883 return nand_load_image(cmdtp, &nand_info[dev->id->num],
884 part->offset, addr, argv[0]);
889 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
892 addr = CONFIG_SYS_LOAD_ADDR;
893 boot_device = getenv("bootdevice");
896 addr = simple_strtoul(argv[1], NULL, 16);
897 boot_device = getenv("bootdevice");
900 addr = simple_strtoul(argv[1], NULL, 16);
901 boot_device = argv[2];
904 addr = simple_strtoul(argv[1], NULL, 16);
905 boot_device = argv[2];
906 offset = simple_strtoul(argv[3], NULL, 16);
909 #if defined(CONFIG_CMD_MTDPARTS)
912 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
913 return CMD_RET_USAGE;
915 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
918 puts("\n** No boot device **\n");
919 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
922 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
924 idx = simple_strtoul(boot_device, NULL, 16);
926 if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) {
927 printf("\n** Device %d not available\n", idx);
928 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
931 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
933 return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
936 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
937 "boot from NAND device",
938 "[partition] | [[[loadAddr] dev] offset]"