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.
24 #include <linux/mtd/mtd.h>
30 #include <asm/byteorder.h>
31 #include <jffs2/jffs2.h>
34 #include "legacy-mtd-utils.h"
36 #if defined(CONFIG_CMD_MTDPARTS)
38 /* partition handling routines */
39 int mtdparts_init(void);
40 int find_dev_and_part(const char *id, struct mtd_device **dev,
41 u8 *part_num, struct part_info **part);
44 static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
48 u_char *datbuf, *oobbuf, *p;
53 off = last + mtd->writesize;
57 datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
59 puts("No memory for page buffer\n");
63 oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
65 puts("No memory for page buffer\n");
69 off &= ~(mtd->writesize - 1);
70 loff_t addr = (loff_t) off;
71 struct mtd_oob_ops ops;
72 memset(&ops, 0, sizeof(ops));
75 ops.len = mtd->writesize;
76 ops.ooblen = mtd->oobsize;
77 ops.mode = MTD_OPS_RAW;
78 i = mtd_read_oob(mtd, addr, &ops);
80 printf("Error (%d) reading page %08lx\n", i, off);
84 printf("Page %08lx dump:\n", off);
87 i = mtd->writesize >> 4;
91 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
92 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
93 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
94 p[8], p[9], p[10], p[11], p[12], p[13], p[14],
101 i = mtd->oobsize >> 3;
104 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
105 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
117 /* ------------------------------------------------------------------------- */
119 static int set_dev(int dev)
121 struct mtd_info *mtd = get_nand_dev_by_index(dev);
126 if (nand_curr_device == dev)
129 printf("Device %d: %s", dev, mtd->name);
130 puts("... is now current device\n");
131 nand_curr_device = dev;
133 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
134 board_nand_select_device(mtd_to_nand(mtd), dev);
140 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
141 static void print_status(ulong start, ulong end, ulong erasesize, int status)
144 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
145 * not the same as others. Instead of bit 1 being lock, it is
146 * #lock_tight. To make the driver support either format, ignore bit 1
147 * and use only bit 0 and bit 2.
149 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
152 (end - start) / erasesize,
153 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
154 (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
155 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
158 static void do_nand_status(struct mtd_info *mtd)
160 ulong block_start = 0;
162 int last_status = -1;
164 struct nand_chip *nand_chip = mtd_to_nand(mtd);
165 /* check the WP bit */
166 nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
167 printf("device is %swrite protected\n",
168 (nand_chip->read_byte(mtd) & 0x80 ?
171 for (off = 0; off < mtd->size; off += mtd->erasesize) {
172 int s = nand_get_lock_status(mtd, off);
174 /* print message only if status has changed */
175 if (s != last_status && off != 0) {
176 print_status(block_start, off, mtd->erasesize,
182 /* Print the last block info */
183 print_status(block_start, off, mtd->erasesize, last_status);
187 #ifdef CONFIG_ENV_OFFSET_OOB
188 unsigned long nand_env_oob_offset;
190 int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
193 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
194 struct mtd_info *mtd = get_nand_dev_by_index(0);
197 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
198 puts("no devices available\n");
204 if (!strcmp(cmd, "get")) {
205 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
209 printf("0x%08lx\n", nand_env_oob_offset);
210 } else if (!strcmp(cmd, "set")) {
213 struct mtd_oob_ops ops;
219 mtd = get_nand_dev_by_index(idx);
220 /* We don't care about size, or maxsize. */
221 if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
222 MTD_DEV_TYPE_NAND, mtd->size)) {
223 puts("Offset or partition name expected\n");
227 puts("Offset or partition name expected\n");
232 puts("Partition not on first NAND device\n");
236 if (mtd->oobavail < ENV_OFFSET_SIZE) {
237 printf("Insufficient available OOB bytes:\n"
238 "%d OOB bytes available but %d required for "
240 mtd->oobavail, ENV_OFFSET_SIZE);
244 if ((addr & (mtd->erasesize - 1)) != 0) {
245 printf("Environment offset must be block-aligned\n");
250 ops.mode = MTD_OOB_AUTO;
252 ops.ooblen = ENV_OFFSET_SIZE;
253 ops.oobbuf = (void *) oob_buf;
255 oob_buf[0] = ENV_OOB_MARKER;
256 oob_buf[1] = addr / mtd->erasesize;
258 ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
260 printf("Error writing OOB block 0\n");
264 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
266 printf("Error reading env offset in OOB\n");
270 if (addr != nand_env_oob_offset) {
271 printf("Verification of env offset in OOB failed: "
272 "0x%08llx expected but got 0x%08lx\n",
273 (unsigned long long)addr, nand_env_oob_offset);
283 return CMD_RET_USAGE;
288 static void nand_print_and_set_info(int idx)
290 struct mtd_info *mtd;
291 struct nand_chip *chip;
293 mtd = get_nand_dev_by_index(idx);
297 chip = mtd_to_nand(mtd);
298 printf("Device %d: ", idx);
299 if (chip->numchips > 1)
300 printf("%dx ", chip->numchips);
301 printf("%s, sector size %u KiB\n",
302 mtd->name, mtd->erasesize >> 10);
303 printf(" Page size %8d b\n", mtd->writesize);
304 printf(" OOB size %8d b\n", mtd->oobsize);
305 printf(" Erase size %8d b\n", mtd->erasesize);
306 printf(" subpagesize %8d b\n", chip->subpagesize);
307 printf(" options 0x%08x\n", chip->options);
308 printf(" bbt options 0x%08x\n", chip->bbt_options);
310 /* Set geometry info */
311 env_set_hex("nand_writesize", mtd->writesize);
312 env_set_hex("nand_oobsize", mtd->oobsize);
313 env_set_hex("nand_erasesize", mtd->erasesize);
316 static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
317 ulong count, int read, int no_verify)
323 mtd_oob_ops_t ops = {
324 .datbuf = (u8 *)addr,
325 .oobbuf = ((u8 *)addr) + mtd->writesize,
326 .len = mtd->writesize,
327 .ooblen = mtd->oobsize,
332 ret = mtd_read_oob(mtd, off, &ops);
334 ret = mtd_write_oob(mtd, off, &ops);
335 if (!ret && !no_verify)
336 ret = nand_verify_page_oob(mtd, &ops, off);
340 printf("%s: error at offset %llx, ret %d\n",
341 __func__, (long long)off, ret);
345 addr += mtd->writesize + mtd->oobsize;
346 off += mtd->writesize;
352 /* Adjust a chip/partition size down for bad blocks so we don't
353 * read/write past the end of a chip/partition by accident.
355 static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
357 /* We grab the nand info object here fresh because this is usually
358 * called after arg_off_size() which can change the value of dev.
360 struct mtd_info *mtd = get_nand_dev_by_index(dev);
361 loff_t maxoffset = offset + *size;
364 /* count badblocks in NAND from offset to offset + size */
365 for (; offset < maxoffset; offset += mtd->erasesize) {
366 if (nand_block_isbad(mtd, offset))
369 /* adjust size if any bad blocks found */
371 *size -= badblocks * mtd->erasesize;
372 printf("size adjusted to 0x%llx (%d bad blocks)\n",
373 (unsigned long long)*size, badblocks);
377 static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
381 loff_t off, size, maxsize;
383 struct mtd_info *mtd;
384 #ifdef CONFIG_SYS_NAND_QUIET
385 int quiet = CONFIG_SYS_NAND_QUIET;
389 const char *quiet_str = env_get("quiet");
390 int dev = nand_curr_device;
391 int repeat = flag & CMD_FLAG_REPEAT;
393 /* at least two arguments please */
398 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
402 /* Only "dump" is repeatable. */
403 if (repeat && strcmp(cmd, "dump"))
406 if (strcmp(cmd, "info") == 0) {
409 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
410 nand_print_and_set_info(i);
414 if (strcmp(cmd, "device") == 0) {
417 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
418 puts("no devices available\n");
420 nand_print_and_set_info(dev);
424 dev = (int)simple_strtoul(argv[2], NULL, 10);
430 #ifdef CONFIG_ENV_OFFSET_OOB
431 /* this command operates only on the first nand device */
432 if (strcmp(cmd, "env.oob") == 0)
433 return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
436 /* The following commands operate on the current device, unless
437 * overridden by a partition specifier. Note that if somehow the
438 * current device is invalid, it will have to be changed to a valid
439 * one before these commands can run, even if a partition specifier
440 * for another device is to be used.
442 mtd = get_nand_dev_by_index(dev);
444 puts("\nno devices available\n");
448 if (strcmp(cmd, "bad") == 0) {
449 printf("\nDevice %d bad blocks:\n", dev);
450 for (off = 0; off < mtd->size; off += mtd->erasesize)
451 if (nand_block_isbad(mtd, off))
452 printf(" %08llx\n", (unsigned long long)off);
459 * nand erase [clean] [off size]
461 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
462 nand_erase_options_t opts;
463 /* "clean" at index 2 means request to write cleanmarker */
464 int clean = argc > 2 && !strcmp("clean", argv[2]);
465 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
466 int o = (clean || scrub_yes) ? 3 : 2;
467 int scrub = !strncmp(cmd, "scrub", 5);
470 const char *scrub_warn =
472 "scrub option will erase all factory set bad blocks!\n"
474 "There is no reliable way to recover them.\n"
476 "Use this command only for testing purposes if you\n"
478 "are sure of what you are doing!\n"
479 "\nReally scrub this NAND flash? <y/N>\n";
482 if (!strcmp(&cmd[5], ".spread")) {
484 } else if (!strcmp(&cmd[5], ".part")) {
486 } else if (!strcmp(&cmd[5], ".chip")) {
494 * Don't allow missing arguments to cause full chip/partition
495 * erases -- easy to do accidentally, e.g. with a misspelled
498 if (argc != o + args)
501 printf("\nNAND %s: ", cmd);
502 /* skip first two or three arguments, look for offset and size */
503 if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
504 &maxsize, MTD_DEV_TYPE_NAND,
511 mtd = get_nand_dev_by_index(dev);
513 memset(&opts, 0, sizeof(opts));
518 opts.spread = spread;
525 if (confirm_yesno()) {
528 puts("scrub aborted\n");
533 ret = nand_erase_opts(mtd, &opts);
534 printf("%s\n", ret ? "ERROR" : "OK");
536 return ret == 0 ? 0 : 1;
539 if (strncmp(cmd, "dump", 4) == 0) {
543 off = (int)simple_strtoul(argv[2], NULL, 16);
544 ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
546 return ret == 0 ? 1 : 0;
549 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
559 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
561 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
562 printf("\nNAND %s: ", read ? "read" : "write");
564 s = strchr(cmd, '.');
566 if (s && !strncmp(s, ".raw", 4)) {
569 if (!strcmp(s, ".raw.noverify"))
572 if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
580 mtd = get_nand_dev_by_index(dev);
582 if (argc > 4 && !str2long(argv[4], &pagecount)) {
583 printf("'%s' is not a number\n", argv[4]);
587 if (pagecount * mtd->writesize > size) {
588 puts("Size exceeds partition or device limit\n");
592 rwsize = pagecount * (mtd->writesize + mtd->oobsize);
594 if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
603 /* size is unspecified */
605 adjust_size_for_badblocks(&size, off, dev);
609 mtd = get_nand_dev_by_index(dev);
611 if (!s || !strcmp(s, ".jffs2") ||
612 !strcmp(s, ".e") || !strcmp(s, ".i")) {
614 ret = nand_read_skip_bad(mtd, off, &rwsize,
618 ret = nand_write_skip_bad(mtd, off, &rwsize,
622 #ifdef CONFIG_CMD_NAND_TRIMFFS
623 } else if (!strcmp(s, ".trimffs")) {
625 printf("Unknown nand command suffix '%s'\n", s);
628 ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
629 maxsize, (u_char *)addr,
630 WITH_DROP_FFS | WITH_WR_VERIFY);
632 } else if (!strcmp(s, ".oob")) {
633 /* out-of-band data */
634 mtd_oob_ops_t ops = {
635 .oobbuf = (u8 *)addr,
641 ret = mtd_read_oob(mtd, off, &ops);
643 ret = mtd_write_oob(mtd, off, &ops);
645 ret = raw_access(mtd, addr, off, pagecount, read,
648 printf("Unknown nand command suffix '%s'.\n", s);
652 printf(" %zu bytes %s: %s\n", rwsize,
653 read ? "read" : "written", ret ? "ERROR" : "OK");
655 return ret == 0 ? 0 : 1;
658 #ifdef CONFIG_CMD_NAND_TORTURE
659 if (strcmp(cmd, "torture") == 0) {
661 unsigned int failed = 0, passed = 0;
666 if (!str2off(argv[2], &off)) {
667 puts("Offset is not a valid number\n");
671 size = mtd->erasesize;
673 if (!str2off(argv[3], &size)) {
674 puts("Size is not a valid number\n");
680 if (endoff > mtd->size) {
681 puts("Arguments beyond end of NAND\n");
685 off = round_down(off, mtd->erasesize);
686 endoff = round_up(endoff, mtd->erasesize);
688 printf("\nNAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)\n",
689 dev, off, size, mtd->erasesize);
690 while (off < endoff) {
691 ret = nand_torture(mtd, off);
694 printf(" block at 0x%llx failed\n", off);
698 off += mtd->erasesize;
700 printf(" Passed: %u, failed: %u\n", passed, failed);
705 if (strcmp(cmd, "markbad") == 0) {
713 addr = simple_strtoul(*argv, NULL, 16);
715 if (mtd_block_markbad(mtd, addr)) {
716 printf("block 0x%08lx NOT marked "
717 "as bad! ERROR %d\n",
721 printf("block 0x%08lx successfully "
731 if (strcmp(cmd, "biterr") == 0) {
736 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
737 if (strcmp(cmd, "lock") == 0) {
741 if (!strcmp("tight", argv[2]))
743 if (!strcmp("status", argv[2]))
749 if (!nand_lock(mtd, tight)) {
750 puts("NAND flash successfully locked\n");
752 puts("Error locking NAND flash\n");
759 if (strncmp(cmd, "unlock", 5) == 0) {
762 s = strchr(cmd, '.');
764 if (s && !strcmp(s, ".allexcept"))
767 if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
768 &maxsize, MTD_DEV_TYPE_NAND,
775 mtd = get_nand_dev_by_index(dev);
777 if (!nand_unlock(mtd, off, size, allexcept)) {
778 puts("NAND flash successfully unlocked\n");
780 puts("Error unlocking NAND flash, "
781 "write and erase will probably fail\n");
789 return CMD_RET_USAGE;
792 #ifdef CONFIG_SYS_LONGHELP
793 static char nand_help_text[] =
794 "info - show available NAND devices\n"
795 "nand device [dev] - show or set current device\n"
796 "nand read - addr off|partition size\n"
797 "nand write - addr off|partition size\n"
798 " read/write 'size' bytes starting at offset 'off'\n"
799 " to/from memory address 'addr', skipping bad blocks.\n"
800 "nand read.raw - addr off|partition [count]\n"
801 "nand write.raw[.noverify] - addr off|partition [count]\n"
802 " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
803 #ifdef CONFIG_CMD_NAND_TRIMFFS
804 "nand write.trimffs - addr off|partition size\n"
805 " write 'size' bytes starting at offset 'off' from memory address\n"
806 " 'addr', skipping bad blocks and dropping any pages at the end\n"
807 " of eraseblocks that contain only 0xFF\n"
809 "nand erase[.spread] [clean] off size - erase 'size' bytes "
810 "from offset 'off'\n"
811 " With '.spread', erase enough for given file size, otherwise,\n"
812 " 'size' includes skipped bad blocks.\n"
813 "nand erase.part [clean] partition - erase entire mtd partition'\n"
814 "nand erase.chip [clean] - erase entire chip'\n"
815 "nand bad - show bad blocks\n"
816 "nand dump[.oob] off - dump page\n"
817 #ifdef CONFIG_CMD_NAND_TORTURE
818 "nand torture off - torture one block at offset\n"
819 "nand torture off [size] - torture blocks from off to off+size\n"
821 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
822 " really clean NAND erasing bad blocks (UNSAFE)\n"
823 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
824 "nand biterr off - make a bit error at offset (UNSAFE)"
825 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
827 "nand lock [tight] [status]\n"
828 " bring nand to lock state or display locked pages\n"
829 "nand unlock[.allexcept] [offset] [size] - unlock section"
831 #ifdef CONFIG_ENV_OFFSET_OOB
833 "nand env.oob - environment offset in OOB of block 0 of"
835 "nand env.oob set off|partition - set enviromnent offset\n"
836 "nand env.oob get - get environment offset"
842 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
843 "NAND sub-system", nand_help_text
846 static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd,
847 ulong offset, ulong addr, char *cmd)
852 #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
855 #if defined(CONFIG_FIT)
856 const void *fit_hdr = NULL;
859 s = strchr(cmd, '.');
861 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
862 printf("Unknown nand load suffix '%s'\n", s);
863 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
867 printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
869 cnt = mtd->writesize;
870 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
873 puts("** Read error\n");
874 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
877 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
879 switch (genimg_get_format ((void *)addr)) {
880 #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
881 case IMAGE_FORMAT_LEGACY:
882 hdr = (image_header_t *)addr;
884 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
885 image_print_contents (hdr);
887 cnt = image_get_image_size (hdr);
890 #if defined(CONFIG_FIT)
891 case IMAGE_FORMAT_FIT:
892 fit_hdr = (const void *)addr;
893 puts ("Fit image detected...\n");
895 cnt = fit_get_size (fit_hdr);
899 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
900 puts ("** Unknown image type\n");
903 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
905 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
908 puts("** Read error\n");
909 bootstage_error(BOOTSTAGE_ID_NAND_READ);
912 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
914 #if defined(CONFIG_FIT)
915 /* This cannot be done earlier, we need complete FIT image in RAM first */
916 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
917 if (!fit_check_format (fit_hdr)) {
918 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
919 puts ("** Bad FIT image format\n");
922 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
923 fit_print_contents (fit_hdr);
927 /* Loading ok, update default load address */
929 image_load_addr = addr;
931 return bootm_maybe_autostart(cmdtp, cmd);
934 static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
937 char *boot_device = NULL;
939 ulong addr, offset = 0;
940 struct mtd_info *mtd;
941 #if defined(CONFIG_CMD_MTDPARTS)
942 struct mtd_device *dev;
943 struct part_info *part;
947 char *p = (argc == 2) ? argv[1] : argv[2];
948 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
949 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
950 if (dev->id->type != MTD_DEV_TYPE_NAND) {
951 puts("Not a NAND device\n");
957 addr = simple_strtoul(argv[1], NULL, 16);
959 addr = CONFIG_SYS_LOAD_ADDR;
961 mtd = get_nand_dev_by_index(dev->id->num);
962 return nand_load_image(cmdtp, mtd, part->offset,
968 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
971 addr = CONFIG_SYS_LOAD_ADDR;
972 boot_device = env_get("bootdevice");
975 addr = simple_strtoul(argv[1], NULL, 16);
976 boot_device = env_get("bootdevice");
979 addr = simple_strtoul(argv[1], NULL, 16);
980 boot_device = argv[2];
983 addr = simple_strtoul(argv[1], NULL, 16);
984 boot_device = argv[2];
985 offset = simple_strtoul(argv[3], NULL, 16);
988 #if defined(CONFIG_CMD_MTDPARTS)
991 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
992 return CMD_RET_USAGE;
994 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
997 puts("\n** No boot device **\n");
998 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1001 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1003 idx = simple_strtoul(boot_device, NULL, 16);
1005 mtd = get_nand_dev_by_index(idx);
1007 printf("\n** Device %d not available\n", idx);
1008 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
1011 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
1013 return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
1016 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
1017 "boot from NAND device",
1018 "[partition] | [[[loadAddr] dev] offset]"