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);
82 i = nand->writesize >> 4;
86 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
87 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
88 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
89 p[8], p[9], p[10], p[11], p[12], p[13], p[14],
96 i = nand->oobsize >> 3;
99 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
100 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
112 /* ------------------------------------------------------------------------- */
114 static int set_dev(int dev)
116 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
117 !nand_info[dev].name) {
118 puts("No such device\n");
122 if (nand_curr_device == dev)
125 printf("Device %d: %s", dev, nand_info[dev].name);
126 puts("... is now current device\n");
127 nand_curr_device = dev;
129 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
130 board_nand_select_device(nand_info[dev].priv, dev);
136 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
137 static void print_status(ulong start, ulong end, ulong erasesize, int status)
140 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
141 * not the same as others. Instead of bit 1 being lock, it is
142 * #lock_tight. To make the driver support either format, ignore bit 1
143 * and use only bit 0 and bit 2.
145 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
148 (end - start) / erasesize,
149 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
150 (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
151 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
154 static void do_nand_status(nand_info_t *nand)
156 ulong block_start = 0;
158 int last_status = -1;
160 struct nand_chip *nand_chip = nand->priv;
161 /* check the WP bit */
162 nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1);
163 printf("device is %swrite protected\n",
164 (nand_chip->read_byte(nand) & 0x80 ?
167 for (off = 0; off < nand->size; off += nand->erasesize) {
168 int s = nand_get_lock_status(nand, off);
170 /* print message only if status has changed */
171 if (s != last_status && off != 0) {
172 print_status(block_start, off, nand->erasesize,
178 /* Print the last block info */
179 print_status(block_start, off, nand->erasesize, last_status);
183 #ifdef CONFIG_ENV_OFFSET_OOB
184 unsigned long nand_env_oob_offset;
186 int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
189 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
190 nand_info_t *nand = &nand_info[0];
193 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
194 puts("no devices available\n");
200 if (!strcmp(cmd, "get")) {
201 ret = get_nand_env_oob(nand, &nand_env_oob_offset);
205 printf("0x%08lx\n", nand_env_oob_offset);
206 } else if (!strcmp(cmd, "set")) {
209 struct mtd_oob_ops ops;
215 /* We don't care about size, or maxsize. */
216 if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
217 MTD_DEV_TYPE_NAND, nand_info[idx].size)) {
218 puts("Offset or partition name expected\n");
222 puts("Offset or partition name expected\n");
227 puts("Partition not on first NAND device\n");
231 if (nand->oobavail < ENV_OFFSET_SIZE) {
232 printf("Insufficient available OOB bytes:\n"
233 "%d OOB bytes available but %d required for "
235 nand->oobavail, ENV_OFFSET_SIZE);
239 if ((addr & (nand->erasesize - 1)) != 0) {
240 printf("Environment offset must be block-aligned\n");
245 ops.mode = MTD_OOB_AUTO;
247 ops.ooblen = ENV_OFFSET_SIZE;
248 ops.oobbuf = (void *) oob_buf;
250 oob_buf[0] = ENV_OOB_MARKER;
251 oob_buf[1] = addr / nand->erasesize;
253 ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops);
255 printf("Error writing OOB block 0\n");
259 ret = get_nand_env_oob(nand, &nand_env_oob_offset);
261 printf("Error reading env offset in OOB\n");
265 if (addr != nand_env_oob_offset) {
266 printf("Verification of env offset in OOB failed: "
267 "0x%08llx expected but got 0x%08lx\n",
268 (unsigned long long)addr, nand_env_oob_offset);
278 return CMD_RET_USAGE;
283 static void nand_print_and_set_info(int idx)
285 nand_info_t *nand = &nand_info[idx];
286 struct nand_chip *chip = nand->priv;
288 printf("Device %d: ", idx);
289 if (chip->numchips > 1)
290 printf("%dx ", chip->numchips);
291 printf("%s, sector size %u KiB\n",
292 nand->name, nand->erasesize >> 10);
293 printf(" Page size %8d b\n", nand->writesize);
294 printf(" OOB size %8d b\n", nand->oobsize);
295 printf(" Erase size %8d b\n", nand->erasesize);
296 printf(" subpagesize %8d b\n", chip->subpagesize);
297 printf(" options 0x%8x\n", chip->options);
298 printf(" bbt options 0x%8x\n", chip->bbt_options);
300 /* Set geometry info */
301 setenv_hex("nand_writesize", nand->writesize);
302 setenv_hex("nand_oobsize", nand->oobsize);
303 setenv_hex("nand_erasesize", nand->erasesize);
306 static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
313 mtd_oob_ops_t ops = {
314 .datbuf = (u8 *)addr,
315 .oobbuf = ((u8 *)addr) + nand->writesize,
316 .len = nand->writesize,
317 .ooblen = nand->oobsize,
322 ret = mtd_read_oob(nand, off, &ops);
324 ret = mtd_write_oob(nand, off, &ops);
326 ret = nand_verify_page_oob(nand, &ops, off);
330 printf("%s: error at offset %llx, ret %d\n",
331 __func__, (long long)off, ret);
335 addr += nand->writesize + nand->oobsize;
336 off += nand->writesize;
342 /* Adjust a chip/partition size down for bad blocks so we don't
343 * read/write past the end of a chip/partition by accident.
345 static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
347 /* We grab the nand info object here fresh because this is usually
348 * called after arg_off_size() which can change the value of dev.
350 nand_info_t *nand = &nand_info[dev];
351 loff_t maxoffset = offset + *size;
354 /* count badblocks in NAND from offset to offset + size */
355 for (; offset < maxoffset; offset += nand->erasesize) {
356 if (nand_block_isbad(nand, offset))
359 /* adjust size if any bad blocks found */
361 *size -= badblocks * nand->erasesize;
362 printf("size adjusted to 0x%llx (%d bad blocks)\n",
363 (unsigned long long)*size, badblocks);
367 static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
371 loff_t off, size, maxsize;
374 #ifdef CONFIG_SYS_NAND_QUIET
375 int quiet = CONFIG_SYS_NAND_QUIET;
379 const char *quiet_str = getenv("quiet");
380 int dev = nand_curr_device;
381 int repeat = flag & CMD_FLAG_REPEAT;
383 /* at least two arguments please */
388 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
392 /* Only "dump" is repeatable. */
393 if (repeat && strcmp(cmd, "dump"))
396 if (strcmp(cmd, "info") == 0) {
399 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
400 if (nand_info[i].name)
401 nand_print_and_set_info(i);
406 if (strcmp(cmd, "device") == 0) {
409 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
410 puts("no devices available\n");
412 nand_print_and_set_info(dev);
416 dev = (int)simple_strtoul(argv[2], NULL, 10);
422 #ifdef CONFIG_ENV_OFFSET_OOB
423 /* this command operates only on the first nand device */
424 if (strcmp(cmd, "env.oob") == 0)
425 return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
428 /* The following commands operate on the current device, unless
429 * overridden by a partition specifier. Note that if somehow the
430 * current device is invalid, it will have to be changed to a valid
431 * one before these commands can run, even if a partition specifier
432 * for another device is to be used.
434 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
435 !nand_info[dev].name) {
436 puts("\nno devices available\n");
439 nand = &nand_info[dev];
441 if (strcmp(cmd, "bad") == 0) {
442 printf("\nDevice %d bad blocks:\n", dev);
443 for (off = 0; off < nand->size; off += nand->erasesize)
444 if (nand_block_isbad(nand, off))
445 printf(" %08llx\n", (unsigned long long)off);
452 * nand erase [clean] [off size]
454 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
455 nand_erase_options_t opts;
456 /* "clean" at index 2 means request to write cleanmarker */
457 int clean = argc > 2 && !strcmp("clean", argv[2]);
458 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
459 int o = (clean || scrub_yes) ? 3 : 2;
460 int scrub = !strncmp(cmd, "scrub", 5);
463 const char *scrub_warn =
465 "scrub option will erase all factory set bad blocks!\n"
467 "There is no reliable way to recover them.\n"
469 "Use this command only for testing purposes if you\n"
471 "are sure of what you are doing!\n"
472 "\nReally scrub this NAND flash? <y/N>\n";
475 if (!strcmp(&cmd[5], ".spread")) {
477 } else if (!strcmp(&cmd[5], ".part")) {
479 } else if (!strcmp(&cmd[5], ".chip")) {
487 * Don't allow missing arguments to cause full chip/partition
488 * erases -- easy to do accidentally, e.g. with a misspelled
491 if (argc != o + args)
494 printf("\nNAND %s: ", cmd);
495 /* skip first two or three arguments, look for offset and size */
496 if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
497 &maxsize, MTD_DEV_TYPE_NAND,
498 nand_info[dev].size) != 0)
504 nand = &nand_info[dev];
506 memset(&opts, 0, sizeof(opts));
511 opts.spread = spread;
518 if (confirm_yesno()) {
521 puts("scrub aborted\n");
526 ret = nand_erase_opts(nand, &opts);
527 printf("%s\n", ret ? "ERROR" : "OK");
529 return ret == 0 ? 0 : 1;
532 if (strncmp(cmd, "dump", 4) == 0) {
536 off = (int)simple_strtoul(argv[2], NULL, 16);
537 ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
539 return ret == 0 ? 1 : 0;
542 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
551 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
553 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
554 printf("\nNAND %s: ", read ? "read" : "write");
556 s = strchr(cmd, '.');
558 if (s && !strcmp(s, ".raw")) {
561 if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
563 nand_info[dev].size))
569 nand = &nand_info[dev];
571 if (argc > 4 && !str2long(argv[4], &pagecount)) {
572 printf("'%s' is not a number\n", argv[4]);
576 if (pagecount * nand->writesize > size) {
577 puts("Size exceeds partition or device limit\n");
581 rwsize = pagecount * (nand->writesize + nand->oobsize);
583 if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
586 nand_info[dev].size) != 0)
592 /* size is unspecified */
594 adjust_size_for_badblocks(&size, off, dev);
598 nand = &nand_info[dev];
600 if (!s || !strcmp(s, ".jffs2") ||
601 !strcmp(s, ".e") || !strcmp(s, ".i")) {
603 ret = nand_read_skip_bad(nand, off, &rwsize,
607 ret = nand_write_skip_bad(nand, off, &rwsize,
611 #ifdef CONFIG_CMD_NAND_TRIMFFS
612 } else if (!strcmp(s, ".trimffs")) {
614 printf("Unknown nand command suffix '%s'\n", s);
617 ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
618 maxsize, (u_char *)addr,
619 WITH_DROP_FFS | WITH_WR_VERIFY);
621 } else if (!strcmp(s, ".oob")) {
622 /* out-of-band data */
623 mtd_oob_ops_t ops = {
624 .oobbuf = (u8 *)addr,
630 ret = mtd_read_oob(nand, off, &ops);
632 ret = mtd_write_oob(nand, off, &ops);
634 ret = raw_access(nand, addr, off, pagecount, read);
636 printf("Unknown nand command suffix '%s'.\n", s);
640 printf(" %zu bytes %s: %s\n", rwsize,
641 read ? "read" : "written", ret ? "ERROR" : "OK");
643 return ret == 0 ? 0 : 1;
646 #ifdef CONFIG_CMD_NAND_TORTURE
647 if (strcmp(cmd, "torture") == 0) {
651 if (!str2off(argv[2], &off)) {
652 puts("Offset is not a valid number\n");
656 printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n",
657 dev, off, nand->erasesize);
658 ret = nand_torture(nand, off);
659 printf(" %s\n", ret ? "Failed" : "Passed");
661 return ret == 0 ? 0 : 1;
665 if (strcmp(cmd, "markbad") == 0) {
673 addr = simple_strtoul(*argv, NULL, 16);
675 if (mtd_block_markbad(nand, addr)) {
676 printf("block 0x%08lx NOT marked "
677 "as bad! ERROR %d\n",
681 printf("block 0x%08lx successfully "
691 if (strcmp(cmd, "biterr") == 0) {
696 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
697 if (strcmp(cmd, "lock") == 0) {
701 if (!strcmp("tight", argv[2]))
703 if (!strcmp("status", argv[2]))
707 do_nand_status(nand);
709 if (!nand_lock(nand, tight)) {
710 puts("NAND flash successfully locked\n");
712 puts("Error locking NAND flash\n");
719 if (strncmp(cmd, "unlock", 5) == 0) {
722 s = strchr(cmd, '.');
724 if (s && !strcmp(s, ".allexcept"))
727 if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
728 &maxsize, MTD_DEV_TYPE_NAND,
729 nand_info[dev].size) < 0)
735 if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
736 puts("NAND flash successfully unlocked\n");
738 puts("Error unlocking NAND flash, "
739 "write and erase will probably fail\n");
747 return CMD_RET_USAGE;
750 #ifdef CONFIG_SYS_LONGHELP
751 static char nand_help_text[] =
752 "info - show available NAND devices\n"
753 "nand device [dev] - show or set current device\n"
754 "nand read - addr off|partition size\n"
755 "nand write - addr off|partition size\n"
756 " read/write 'size' bytes starting at offset 'off'\n"
757 " to/from memory address 'addr', skipping bad blocks.\n"
758 "nand read.raw - addr off|partition [count]\n"
759 "nand write.raw - addr off|partition [count]\n"
760 " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
761 #ifdef CONFIG_CMD_NAND_TRIMFFS
762 "nand write.trimffs - addr off|partition size\n"
763 " write 'size' bytes starting at offset 'off' from memory address\n"
764 " 'addr', skipping bad blocks and dropping any pages at the end\n"
765 " of eraseblocks that contain only 0xFF\n"
767 "nand erase[.spread] [clean] off size - erase 'size' bytes "
768 "from offset 'off'\n"
769 " With '.spread', erase enough for given file size, otherwise,\n"
770 " 'size' includes skipped bad blocks.\n"
771 "nand erase.part [clean] partition - erase entire mtd partition'\n"
772 "nand erase.chip [clean] - erase entire chip'\n"
773 "nand bad - show bad blocks\n"
774 "nand dump[.oob] off - dump page\n"
775 #ifdef CONFIG_CMD_NAND_TORTURE
776 "nand torture off - torture block at offset\n"
778 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
779 " really clean NAND erasing bad blocks (UNSAFE)\n"
780 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
781 "nand biterr off - make a bit error at offset (UNSAFE)"
782 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
784 "nand lock [tight] [status]\n"
785 " bring nand to lock state or display locked pages\n"
786 "nand unlock[.allexcept] [offset] [size] - unlock section"
788 #ifdef CONFIG_ENV_OFFSET_OOB
790 "nand env.oob - environment offset in OOB of block 0 of"
792 "nand env.oob set off|partition - set enviromnent offset\n"
793 "nand env.oob get - get environment offset"
799 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
800 "NAND sub-system", nand_help_text
803 static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
804 ulong offset, ulong addr, char *cmd)
809 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
812 #if defined(CONFIG_FIT)
813 const void *fit_hdr = NULL;
816 s = strchr(cmd, '.');
818 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
819 printf("Unknown nand load suffix '%s'\n", s);
820 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
824 printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
826 cnt = nand->writesize;
827 r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
830 puts("** Read error\n");
831 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
834 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
836 switch (genimg_get_format ((void *)addr)) {
837 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
838 case IMAGE_FORMAT_LEGACY:
839 hdr = (image_header_t *)addr;
841 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
842 image_print_contents (hdr);
844 cnt = image_get_image_size (hdr);
847 #if defined(CONFIG_FIT)
848 case IMAGE_FORMAT_FIT:
849 fit_hdr = (const void *)addr;
850 puts ("Fit image detected...\n");
852 cnt = fit_get_size (fit_hdr);
856 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
857 puts ("** Unknown image type\n");
860 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
862 r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
865 puts("** Read error\n");
866 bootstage_error(BOOTSTAGE_ID_NAND_READ);
869 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
871 #if defined(CONFIG_FIT)
872 /* This cannot be done earlier, we need complete FIT image in RAM first */
873 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
874 if (!fit_check_format (fit_hdr)) {
875 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
876 puts ("** Bad FIT image format\n");
879 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
880 fit_print_contents (fit_hdr);
884 /* Loading ok, update default load address */
888 return bootm_maybe_autostart(cmdtp, cmd);
891 static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
894 char *boot_device = NULL;
896 ulong addr, offset = 0;
897 #if defined(CONFIG_CMD_MTDPARTS)
898 struct mtd_device *dev;
899 struct part_info *part;
903 char *p = (argc == 2) ? argv[1] : argv[2];
904 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
905 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
906 if (dev->id->type != MTD_DEV_TYPE_NAND) {
907 puts("Not a NAND device\n");
913 addr = simple_strtoul(argv[1], NULL, 16);
915 addr = CONFIG_SYS_LOAD_ADDR;
916 return nand_load_image(cmdtp, &nand_info[dev->id->num],
917 part->offset, addr, argv[0]);
922 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
925 addr = CONFIG_SYS_LOAD_ADDR;
926 boot_device = getenv("bootdevice");
929 addr = simple_strtoul(argv[1], NULL, 16);
930 boot_device = getenv("bootdevice");
933 addr = simple_strtoul(argv[1], NULL, 16);
934 boot_device = argv[2];
937 addr = simple_strtoul(argv[1], NULL, 16);
938 boot_device = argv[2];
939 offset = simple_strtoul(argv[3], NULL, 16);
942 #if defined(CONFIG_CMD_MTDPARTS)
945 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
946 return CMD_RET_USAGE;
948 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
951 puts("\n** No boot device **\n");
952 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
955 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
957 idx = simple_strtoul(boot_device, NULL, 16);
959 if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) {
960 printf("\n** Device %d not available\n", idx);
961 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
964 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
966 return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
969 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
970 "boot from NAND device",
971 "[partition] | [[[loadAddr] dev] offset]"