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 <bootstage.h>
25 #include <asm/cache.h>
26 #include <linux/mtd/mtd.h>
27 #include <linux/mtd/rawnand.h>
33 #include <asm/byteorder.h>
34 #include <jffs2/jffs2.h>
37 #include "legacy-mtd-utils.h"
39 #if defined(CONFIG_CMD_MTDPARTS)
41 /* partition handling routines */
42 int mtdparts_init(void);
43 int find_dev_and_part(const char *id, struct mtd_device **dev,
44 u8 *part_num, struct part_info **part);
47 static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
51 u_char *datbuf, *oobbuf, *p;
56 off = last + mtd->writesize;
60 datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
62 puts("No memory for page buffer\n");
66 oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
68 puts("No memory for page buffer\n");
72 off &= ~(mtd->writesize - 1);
73 loff_t addr = (loff_t) off;
74 struct mtd_oob_ops ops;
75 memset(&ops, 0, sizeof(ops));
78 ops.len = mtd->writesize;
79 ops.ooblen = mtd->oobsize;
80 ops.mode = MTD_OPS_RAW;
81 i = mtd_read_oob(mtd, addr, &ops);
83 printf("Error (%d) reading page %08lx\n", i, off);
87 printf("Page %08lx dump:\n", off);
90 i = mtd->writesize >> 4;
94 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
95 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
96 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
97 p[8], p[9], p[10], p[11], p[12], p[13], p[14],
104 i = mtd->oobsize >> 3;
107 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
108 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
120 /* ------------------------------------------------------------------------- */
122 static int set_dev(int dev)
124 struct mtd_info *mtd = get_nand_dev_by_index(dev);
129 if (nand_curr_device == dev)
132 printf("Device %d: %s", dev, mtd->name);
133 puts("... is now current device\n");
134 nand_curr_device = dev;
136 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
137 board_nand_select_device(mtd_to_nand(mtd), dev);
143 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
144 static void print_status(ulong start, ulong end, ulong erasesize, int status)
147 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
148 * not the same as others. Instead of bit 1 being lock, it is
149 * #lock_tight. To make the driver support either format, ignore bit 1
150 * and use only bit 0 and bit 2.
152 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
155 (end - start) / erasesize,
156 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
157 (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
158 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
161 static void do_nand_status(struct mtd_info *mtd)
163 ulong block_start = 0;
165 int last_status = -1;
167 struct nand_chip *nand_chip = mtd_to_nand(mtd);
168 /* check the WP bit */
169 nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
170 printf("device is %swrite protected\n",
171 (nand_chip->read_byte(mtd) & 0x80 ?
174 for (off = 0; off < mtd->size; off += mtd->erasesize) {
175 int s = nand_get_lock_status(mtd, off);
177 /* print message only if status has changed */
178 if (s != last_status && off != 0) {
179 print_status(block_start, off, mtd->erasesize,
185 /* Print the last block info */
186 print_status(block_start, off, mtd->erasesize, last_status);
190 #ifdef CONFIG_ENV_OFFSET_OOB
191 unsigned long nand_env_oob_offset;
193 int do_nand_env_oob(struct cmd_tbl *cmdtp, int argc, char *const argv[])
196 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
197 struct mtd_info *mtd = get_nand_dev_by_index(0);
200 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
201 puts("no devices available\n");
207 if (!strcmp(cmd, "get")) {
208 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
212 printf("0x%08lx\n", nand_env_oob_offset);
213 } else if (!strcmp(cmd, "set")) {
216 struct mtd_oob_ops ops;
222 mtd = get_nand_dev_by_index(idx);
223 /* We don't care about size, or maxsize. */
224 if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
225 MTD_DEV_TYPE_NAND, mtd->size)) {
226 puts("Offset or partition name expected\n");
230 puts("Offset or partition name expected\n");
235 puts("Partition not on first NAND device\n");
239 if (mtd->oobavail < ENV_OFFSET_SIZE) {
240 printf("Insufficient available OOB bytes:\n"
241 "%d OOB bytes available but %d required for "
243 mtd->oobavail, ENV_OFFSET_SIZE);
247 if ((addr & (mtd->erasesize - 1)) != 0) {
248 printf("Environment offset must be block-aligned\n");
253 ops.mode = MTD_OOB_AUTO;
255 ops.ooblen = ENV_OFFSET_SIZE;
256 ops.oobbuf = (void *) oob_buf;
258 oob_buf[0] = ENV_OOB_MARKER;
259 oob_buf[1] = addr / mtd->erasesize;
261 ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
263 printf("Error writing OOB block 0\n");
267 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
269 printf("Error reading env offset in OOB\n");
273 if (addr != nand_env_oob_offset) {
274 printf("Verification of env offset in OOB failed: "
275 "0x%08llx expected but got 0x%08lx\n",
276 (unsigned long long)addr, nand_env_oob_offset);
286 return CMD_RET_USAGE;
291 static void nand_print_and_set_info(int idx)
293 struct mtd_info *mtd;
294 struct nand_chip *chip;
296 mtd = get_nand_dev_by_index(idx);
300 chip = mtd_to_nand(mtd);
301 printf("Device %d: ", idx);
302 if (chip->numchips > 1)
303 printf("%dx ", chip->numchips);
304 printf("%s, sector size %u KiB\n",
305 mtd->name, mtd->erasesize >> 10);
306 printf(" Page size %8d b\n", mtd->writesize);
307 printf(" OOB size %8d b\n", mtd->oobsize);
308 printf(" Erase size %8d b\n", mtd->erasesize);
309 printf(" subpagesize %8d b\n", chip->subpagesize);
310 printf(" options 0x%08x\n", chip->options);
311 printf(" bbt options 0x%08x\n", chip->bbt_options);
313 /* Set geometry info */
314 env_set_hex("nand_writesize", mtd->writesize);
315 env_set_hex("nand_oobsize", mtd->oobsize);
316 env_set_hex("nand_erasesize", mtd->erasesize);
319 static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
320 ulong count, int read, int no_verify)
326 mtd_oob_ops_t ops = {
327 .datbuf = (u8 *)addr,
328 .oobbuf = ((u8 *)addr) + mtd->writesize,
329 .len = mtd->writesize,
330 .ooblen = mtd->oobsize,
335 ret = mtd_read_oob(mtd, off, &ops);
337 ret = mtd_write_oob(mtd, off, &ops);
338 if (!ret && !no_verify)
339 ret = nand_verify_page_oob(mtd, &ops, off);
343 printf("%s: error at offset %llx, ret %d\n",
344 __func__, (long long)off, ret);
348 addr += mtd->writesize + mtd->oobsize;
349 off += mtd->writesize;
355 /* Adjust a chip/partition size down for bad blocks so we don't
356 * read/write past the end of a chip/partition by accident.
358 static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
360 /* We grab the nand info object here fresh because this is usually
361 * called after arg_off_size() which can change the value of dev.
363 struct mtd_info *mtd = get_nand_dev_by_index(dev);
364 loff_t maxoffset = offset + *size;
367 /* count badblocks in NAND from offset to offset + size */
368 for (; offset < maxoffset; offset += mtd->erasesize) {
369 if (nand_block_isbad(mtd, offset))
372 /* adjust size if any bad blocks found */
374 *size -= badblocks * mtd->erasesize;
375 printf("size adjusted to 0x%llx (%d bad blocks)\n",
376 (unsigned long long)*size, badblocks);
380 static int do_nand(struct cmd_tbl *cmdtp, int flag, int argc,
385 loff_t off, size, maxsize;
387 struct mtd_info *mtd;
388 #ifdef CONFIG_SYS_NAND_QUIET
389 int quiet = CONFIG_SYS_NAND_QUIET;
393 const char *quiet_str = env_get("quiet");
394 int dev = nand_curr_device;
395 int repeat = flag & CMD_FLAG_REPEAT;
397 /* at least two arguments please */
402 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
406 /* Only "dump" is repeatable. */
407 if (repeat && strcmp(cmd, "dump"))
410 if (strcmp(cmd, "info") == 0) {
413 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
414 nand_print_and_set_info(i);
418 if (strcmp(cmd, "device") == 0) {
421 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
422 puts("no devices available\n");
424 nand_print_and_set_info(dev);
428 dev = (int)dectoul(argv[2], NULL);
434 #ifdef CONFIG_ENV_OFFSET_OOB
435 /* this command operates only on the first nand device */
436 if (strcmp(cmd, "env.oob") == 0)
437 return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
440 /* The following commands operate on the current device, unless
441 * overridden by a partition specifier. Note that if somehow the
442 * current device is invalid, it will have to be changed to a valid
443 * one before these commands can run, even if a partition specifier
444 * for another device is to be used.
446 mtd = get_nand_dev_by_index(dev);
448 puts("\nno devices available\n");
452 if (strcmp(cmd, "bad") == 0) {
453 printf("\nDevice %d bad blocks:\n", dev);
454 for (off = 0; off < mtd->size; off += mtd->erasesize)
455 if (nand_block_isbad(mtd, off))
456 printf(" %08llx\n", (unsigned long long)off);
463 * nand erase [clean] [off size]
465 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
466 nand_erase_options_t opts;
467 /* "clean" at index 2 means request to write cleanmarker */
468 int clean = argc > 2 && !strcmp("clean", argv[2]);
469 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
470 int o = (clean || scrub_yes) ? 3 : 2;
471 int scrub = !strncmp(cmd, "scrub", 5);
474 const char *scrub_warn =
476 "scrub option will erase all factory set bad blocks!\n"
478 "There is no reliable way to recover them.\n"
480 "Use this command only for testing purposes if you\n"
482 "are sure of what you are doing!\n"
483 "\nReally scrub this NAND flash? <y/N>\n";
486 if (!strcmp(&cmd[5], ".spread")) {
488 } else if (!strcmp(&cmd[5], ".part")) {
490 } else if (!strcmp(&cmd[5], ".chip")) {
498 * Don't allow missing arguments to cause full chip/partition
499 * erases -- easy to do accidentally, e.g. with a misspelled
502 if (argc != o + args)
505 printf("\nNAND %s: ", cmd);
506 /* skip first two or three arguments, look for offset and size */
507 if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
508 &maxsize, MTD_DEV_TYPE_NAND,
515 mtd = get_nand_dev_by_index(dev);
517 memset(&opts, 0, sizeof(opts));
522 opts.spread = spread;
529 if (confirm_yesno()) {
532 puts("scrub aborted\n");
537 ret = nand_erase_opts(mtd, &opts);
538 printf("%s\n", ret ? "ERROR" : "OK");
540 return ret == 0 ? 0 : 1;
543 if (strncmp(cmd, "dump", 4) == 0) {
547 off = (int)hextoul(argv[2], NULL);
548 ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
550 return ret == 0 ? 1 : 0;
553 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
563 addr = (ulong)hextoul(argv[2], NULL);
565 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
566 printf("\nNAND %s: ", read ? "read" : "write");
568 s = strchr(cmd, '.');
570 if (s && !strncmp(s, ".raw", 4)) {
573 if (!strcmp(s, ".raw.noverify"))
576 if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
584 mtd = get_nand_dev_by_index(dev);
586 if (argc > 4 && !str2long(argv[4], &pagecount)) {
587 printf("'%s' is not a number\n", argv[4]);
591 if (pagecount * mtd->writesize > size) {
592 puts("Size exceeds partition or device limit\n");
596 rwsize = pagecount * (mtd->writesize + mtd->oobsize);
598 if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
607 /* size is unspecified */
609 adjust_size_for_badblocks(&size, off, dev);
613 mtd = get_nand_dev_by_index(dev);
615 if (!s || !strcmp(s, ".jffs2") ||
616 !strcmp(s, ".e") || !strcmp(s, ".i")) {
618 ret = nand_read_skip_bad(mtd, off, &rwsize,
622 ret = nand_write_skip_bad(mtd, off, &rwsize,
626 #ifdef CONFIG_CMD_NAND_TRIMFFS
627 } else if (!strcmp(s, ".trimffs")) {
629 printf("Unknown nand command suffix '%s'\n", s);
632 ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
633 maxsize, (u_char *)addr,
634 WITH_DROP_FFS | WITH_WR_VERIFY);
636 } else if (!strcmp(s, ".oob")) {
637 /* out-of-band data */
638 mtd_oob_ops_t ops = {
639 .oobbuf = (u8 *)addr,
645 ret = mtd_read_oob(mtd, off, &ops);
647 ret = mtd_write_oob(mtd, off, &ops);
649 ret = raw_access(mtd, addr, off, pagecount, read,
652 printf("Unknown nand command suffix '%s'.\n", s);
656 printf(" %zu bytes %s: %s\n", rwsize,
657 read ? "read" : "written", ret ? "ERROR" : "OK");
659 return ret == 0 ? 0 : 1;
662 #ifdef CONFIG_CMD_NAND_TORTURE
663 if (strcmp(cmd, "torture") == 0) {
665 unsigned int failed = 0, passed = 0;
670 if (!str2off(argv[2], &off)) {
671 puts("Offset is not a valid number\n");
675 size = mtd->erasesize;
677 if (!str2off(argv[3], &size)) {
678 puts("Size is not a valid number\n");
684 if (endoff > mtd->size) {
685 puts("Arguments beyond end of NAND\n");
689 off = round_down(off, mtd->erasesize);
690 endoff = round_up(endoff, mtd->erasesize);
692 printf("\nNAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)\n",
693 dev, off, size, mtd->erasesize);
694 while (off < endoff) {
695 ret = nand_torture(mtd, off);
698 printf(" block at 0x%llx failed\n", off);
702 off += mtd->erasesize;
704 printf(" Passed: %u, failed: %u\n", passed, failed);
709 if (strcmp(cmd, "markbad") == 0) {
717 addr = hextoul(*argv, NULL);
719 if (mtd_block_markbad(mtd, addr)) {
720 printf("block 0x%08lx NOT marked "
721 "as bad! ERROR %d\n",
725 printf("block 0x%08lx successfully "
735 if (strcmp(cmd, "biterr") == 0) {
740 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
741 if (strcmp(cmd, "lock") == 0) {
745 if (!strcmp("tight", argv[2]))
747 if (!strcmp("status", argv[2]))
753 if (!nand_lock(mtd, tight)) {
754 puts("NAND flash successfully locked\n");
756 puts("Error locking NAND flash\n");
763 if (strncmp(cmd, "unlock", 5) == 0) {
766 s = strchr(cmd, '.');
768 if (s && !strcmp(s, ".allexcept"))
771 if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
772 &maxsize, MTD_DEV_TYPE_NAND,
779 mtd = get_nand_dev_by_index(dev);
781 if (!nand_unlock(mtd, off, size, allexcept)) {
782 puts("NAND flash successfully unlocked\n");
784 puts("Error unlocking NAND flash, "
785 "write and erase will probably fail\n");
793 return CMD_RET_USAGE;
796 #ifdef CONFIG_SYS_LONGHELP
797 static char nand_help_text[] =
798 "info - show available NAND devices\n"
799 "nand device [dev] - show or set current device\n"
800 "nand read - addr off|partition size\n"
801 "nand write - addr off|partition size\n"
802 " read/write 'size' bytes starting at offset 'off'\n"
803 " to/from memory address 'addr', skipping bad blocks.\n"
804 "nand read.raw - addr off|partition [count]\n"
805 "nand write.raw[.noverify] - addr off|partition [count]\n"
806 " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
807 #ifdef CONFIG_CMD_NAND_TRIMFFS
808 "nand write.trimffs - addr off|partition size\n"
809 " write 'size' bytes starting at offset 'off' from memory address\n"
810 " 'addr', skipping bad blocks and dropping any pages at the end\n"
811 " of eraseblocks that contain only 0xFF\n"
813 "nand erase[.spread] [clean] off size - erase 'size' bytes "
814 "from offset 'off'\n"
815 " With '.spread', erase enough for given file size, otherwise,\n"
816 " 'size' includes skipped bad blocks.\n"
817 "nand erase.part [clean] partition - erase entire mtd partition'\n"
818 "nand erase.chip [clean] - erase entire chip'\n"
819 "nand bad - show bad blocks\n"
820 "nand dump[.oob] off - dump page\n"
821 #ifdef CONFIG_CMD_NAND_TORTURE
822 "nand torture off - torture one block at offset\n"
823 "nand torture off [size] - torture blocks from off to off+size\n"
825 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
826 " really clean NAND erasing bad blocks (UNSAFE)\n"
827 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
828 "nand biterr off - make a bit error at offset (UNSAFE)"
829 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
831 "nand lock [tight] [status]\n"
832 " bring nand to lock state or display locked pages\n"
833 "nand unlock[.allexcept] [offset] [size] - unlock section"
835 #ifdef CONFIG_ENV_OFFSET_OOB
837 "nand env.oob - environment offset in OOB of block 0 of"
839 "nand env.oob set off|partition - set enviromnent offset\n"
840 "nand env.oob get - get environment offset"
846 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
847 "NAND sub-system", nand_help_text
850 static int nand_load_image(struct cmd_tbl *cmdtp, struct mtd_info *mtd,
851 ulong offset, ulong addr, char *cmd)
856 #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
859 #if defined(CONFIG_FIT)
860 const void *fit_hdr = NULL;
863 s = strchr(cmd, '.');
865 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
866 printf("Unknown nand load suffix '%s'\n", s);
867 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
871 printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
873 cnt = mtd->writesize;
874 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
877 puts("** Read error\n");
878 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
881 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
883 switch (genimg_get_format ((void *)addr)) {
884 #if defined(CONFIG_LEGACY_IMAGE_FORMAT)
885 case IMAGE_FORMAT_LEGACY:
886 hdr = (image_header_t *)addr;
888 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
889 image_print_contents (hdr);
891 cnt = image_get_image_size (hdr);
894 #if defined(CONFIG_FIT)
895 case IMAGE_FORMAT_FIT:
896 fit_hdr = (const void *)addr;
897 puts ("Fit image detected...\n");
899 cnt = fit_get_size (fit_hdr);
903 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
904 puts ("** Unknown image type\n");
907 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
909 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
912 puts("** Read error\n");
913 bootstage_error(BOOTSTAGE_ID_NAND_READ);
916 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
918 #if defined(CONFIG_FIT)
919 /* This cannot be done earlier, we need complete FIT image in RAM first */
920 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
921 if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
922 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
923 puts ("** Bad FIT image format\n");
926 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
927 fit_print_contents (fit_hdr);
931 /* Loading ok, update default load address */
933 image_load_addr = addr;
935 return bootm_maybe_autostart(cmdtp, cmd);
938 static int do_nandboot(struct cmd_tbl *cmdtp, int flag, int argc,
941 char *boot_device = NULL;
943 ulong addr, offset = 0;
944 struct mtd_info *mtd;
945 #if defined(CONFIG_CMD_MTDPARTS)
946 struct mtd_device *dev;
947 struct part_info *part;
951 char *p = (argc == 2) ? argv[1] : argv[2];
952 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
953 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
954 if (dev->id->type != MTD_DEV_TYPE_NAND) {
955 puts("Not a NAND device\n");
961 addr = hextoul(argv[1], NULL);
963 addr = CONFIG_SYS_LOAD_ADDR;
965 mtd = get_nand_dev_by_index(dev->id->num);
966 return nand_load_image(cmdtp, mtd, part->offset,
972 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
975 addr = CONFIG_SYS_LOAD_ADDR;
976 boot_device = env_get("bootdevice");
979 addr = hextoul(argv[1], NULL);
980 boot_device = env_get("bootdevice");
983 addr = hextoul(argv[1], NULL);
984 boot_device = argv[2];
987 addr = hextoul(argv[1], NULL);
988 boot_device = argv[2];
989 offset = hextoul(argv[3], NULL);
992 #if defined(CONFIG_CMD_MTDPARTS)
995 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
996 return CMD_RET_USAGE;
998 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
1001 puts("\n** No boot device **\n");
1002 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1005 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1007 idx = hextoul(boot_device, NULL);
1009 mtd = get_nand_dev_by_index(idx);
1011 printf("\n** Device %d not available\n", idx);
1012 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
1015 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
1017 return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
1020 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
1021 "boot from NAND device",
1022 "[partition] | [[[loadAddr] dev] offset]"