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>
28 #include <asm/byteorder.h>
29 #include <jffs2/jffs2.h>
32 #if defined(CONFIG_CMD_MTDPARTS)
34 /* partition handling routines */
35 int mtdparts_init(void);
36 int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
37 int find_dev_and_part(const char *id, struct mtd_device **dev,
38 u8 *part_num, struct part_info **part);
41 static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
45 u_char *datbuf, *oobbuf, *p;
50 off = last + mtd->writesize;
54 datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
56 puts("No memory for page buffer\n");
60 oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
62 puts("No memory for page buffer\n");
66 off &= ~(mtd->writesize - 1);
67 loff_t addr = (loff_t) off;
68 struct mtd_oob_ops ops;
69 memset(&ops, 0, sizeof(ops));
72 ops.len = mtd->writesize;
73 ops.ooblen = mtd->oobsize;
74 ops.mode = MTD_OPS_RAW;
75 i = mtd_read_oob(mtd, addr, &ops);
77 printf("Error (%d) reading page %08lx\n", i, off);
81 printf("Page %08lx dump:\n", off);
84 i = mtd->writesize >> 4;
88 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
89 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
90 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
91 p[8], p[9], p[10], p[11], p[12], p[13], p[14],
98 i = mtd->oobsize >> 3;
101 printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
102 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
114 /* ------------------------------------------------------------------------- */
116 static int set_dev(int dev)
118 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
119 !nand_info[dev]->name) {
120 puts("No such device\n");
124 if (nand_curr_device == dev)
127 printf("Device %d: %s", dev, nand_info[dev]->name);
128 puts("... is now current device\n");
129 nand_curr_device = dev;
131 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
132 board_nand_select_device(nand_info[dev]->priv, dev);
138 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
139 static void print_status(ulong start, ulong end, ulong erasesize, int status)
142 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
143 * not the same as others. Instead of bit 1 being lock, it is
144 * #lock_tight. To make the driver support either format, ignore bit 1
145 * and use only bit 0 and bit 2.
147 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
150 (end - start) / erasesize,
151 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
152 (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
153 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
156 static void do_nand_status(struct mtd_info *mtd)
158 ulong block_start = 0;
160 int last_status = -1;
162 struct nand_chip *nand_chip = mtd_to_nand(mtd);
163 /* check the WP bit */
164 nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
165 printf("device is %swrite protected\n",
166 (nand_chip->read_byte(mtd) & 0x80 ?
169 for (off = 0; off < mtd->size; off += mtd->erasesize) {
170 int s = nand_get_lock_status(mtd, off);
172 /* print message only if status has changed */
173 if (s != last_status && off != 0) {
174 print_status(block_start, off, mtd->erasesize,
180 /* Print the last block info */
181 print_status(block_start, off, mtd->erasesize, last_status);
185 #ifdef CONFIG_ENV_OFFSET_OOB
186 unsigned long nand_env_oob_offset;
188 int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
191 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
192 struct mtd_info *mtd = nand_info[0];
195 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd->name) {
196 puts("no devices available\n");
202 if (!strcmp(cmd, "get")) {
203 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
207 printf("0x%08lx\n", nand_env_oob_offset);
208 } else if (!strcmp(cmd, "set")) {
211 struct mtd_oob_ops ops;
217 /* We don't care about size, or maxsize. */
218 if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
219 MTD_DEV_TYPE_NAND, nand_info[idx]->size)) {
220 puts("Offset or partition name expected\n");
224 puts("Offset or partition name expected\n");
229 puts("Partition not on first NAND device\n");
233 if (mtd->oobavail < ENV_OFFSET_SIZE) {
234 printf("Insufficient available OOB bytes:\n"
235 "%d OOB bytes available but %d required for "
237 mtd->oobavail, ENV_OFFSET_SIZE);
241 if ((addr & (mtd->erasesize - 1)) != 0) {
242 printf("Environment offset must be block-aligned\n");
247 ops.mode = MTD_OOB_AUTO;
249 ops.ooblen = ENV_OFFSET_SIZE;
250 ops.oobbuf = (void *) oob_buf;
252 oob_buf[0] = ENV_OOB_MARKER;
253 oob_buf[1] = addr / mtd->erasesize;
255 ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
257 printf("Error writing OOB block 0\n");
261 ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
263 printf("Error reading env offset in OOB\n");
267 if (addr != nand_env_oob_offset) {
268 printf("Verification of env offset in OOB failed: "
269 "0x%08llx expected but got 0x%08lx\n",
270 (unsigned long long)addr, nand_env_oob_offset);
280 return CMD_RET_USAGE;
285 static void nand_print_and_set_info(int idx)
287 struct mtd_info *mtd = nand_info[idx];
288 struct nand_chip *chip = mtd_to_nand(mtd);
290 printf("Device %d: ", idx);
291 if (chip->numchips > 1)
292 printf("%dx ", chip->numchips);
293 printf("%s, sector size %u KiB\n",
294 mtd->name, mtd->erasesize >> 10);
295 printf(" Page size %8d b\n", mtd->writesize);
296 printf(" OOB size %8d b\n", mtd->oobsize);
297 printf(" Erase size %8d b\n", mtd->erasesize);
298 printf(" subpagesize %8d b\n", chip->subpagesize);
299 printf(" options 0x%8x\n", chip->options);
300 printf(" bbt options 0x%8x\n", chip->bbt_options);
302 /* Set geometry info */
303 setenv_hex("nand_writesize", mtd->writesize);
304 setenv_hex("nand_oobsize", mtd->oobsize);
305 setenv_hex("nand_erasesize", mtd->erasesize);
308 static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
309 ulong count, int read, int no_verify)
315 mtd_oob_ops_t ops = {
316 .datbuf = (u8 *)addr,
317 .oobbuf = ((u8 *)addr) + mtd->writesize,
318 .len = mtd->writesize,
319 .ooblen = mtd->oobsize,
324 ret = mtd_read_oob(mtd, off, &ops);
326 ret = mtd_write_oob(mtd, off, &ops);
327 if (!ret && !no_verify)
328 ret = nand_verify_page_oob(mtd, &ops, off);
332 printf("%s: error at offset %llx, ret %d\n",
333 __func__, (long long)off, ret);
337 addr += mtd->writesize + mtd->oobsize;
338 off += mtd->writesize;
344 /* Adjust a chip/partition size down for bad blocks so we don't
345 * read/write past the end of a chip/partition by accident.
347 static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
349 /* We grab the nand info object here fresh because this is usually
350 * called after arg_off_size() which can change the value of dev.
352 struct mtd_info *mtd = nand_info[dev];
353 loff_t maxoffset = offset + *size;
356 /* count badblocks in NAND from offset to offset + size */
357 for (; offset < maxoffset; offset += mtd->erasesize) {
358 if (nand_block_isbad(mtd, offset))
361 /* adjust size if any bad blocks found */
363 *size -= badblocks * mtd->erasesize;
364 printf("size adjusted to 0x%llx (%d bad blocks)\n",
365 (unsigned long long)*size, badblocks);
369 static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
373 loff_t off, size, maxsize;
375 struct mtd_info *mtd;
376 #ifdef CONFIG_SYS_NAND_QUIET
377 int quiet = CONFIG_SYS_NAND_QUIET;
381 const char *quiet_str = getenv("quiet");
382 int dev = nand_curr_device;
383 int repeat = flag & CMD_FLAG_REPEAT;
385 /* at least two arguments please */
390 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
394 /* Only "dump" is repeatable. */
395 if (repeat && strcmp(cmd, "dump"))
398 if (strcmp(cmd, "info") == 0) {
401 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
402 if (nand_info[i]->name)
403 nand_print_and_set_info(i);
408 if (strcmp(cmd, "device") == 0) {
411 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
412 puts("no devices available\n");
414 nand_print_and_set_info(dev);
418 dev = (int)simple_strtoul(argv[2], NULL, 10);
424 #ifdef CONFIG_ENV_OFFSET_OOB
425 /* this command operates only on the first nand device */
426 if (strcmp(cmd, "env.oob") == 0)
427 return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
430 /* The following commands operate on the current device, unless
431 * overridden by a partition specifier. Note that if somehow the
432 * current device is invalid, it will have to be changed to a valid
433 * one before these commands can run, even if a partition specifier
434 * for another device is to be used.
436 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
437 !nand_info[dev]->name) {
438 puts("\nno devices available\n");
441 mtd = nand_info[dev];
443 if (strcmp(cmd, "bad") == 0) {
444 printf("\nDevice %d bad blocks:\n", dev);
445 for (off = 0; off < mtd->size; off += mtd->erasesize)
446 if (nand_block_isbad(mtd, off))
447 printf(" %08llx\n", (unsigned long long)off);
454 * nand erase [clean] [off size]
456 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
457 nand_erase_options_t opts;
458 /* "clean" at index 2 means request to write cleanmarker */
459 int clean = argc > 2 && !strcmp("clean", argv[2]);
460 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
461 int o = (clean || scrub_yes) ? 3 : 2;
462 int scrub = !strncmp(cmd, "scrub", 5);
465 const char *scrub_warn =
467 "scrub option will erase all factory set bad blocks!\n"
469 "There is no reliable way to recover them.\n"
471 "Use this command only for testing purposes if you\n"
473 "are sure of what you are doing!\n"
474 "\nReally scrub this NAND flash? <y/N>\n";
477 if (!strcmp(&cmd[5], ".spread")) {
479 } else if (!strcmp(&cmd[5], ".part")) {
481 } else if (!strcmp(&cmd[5], ".chip")) {
489 * Don't allow missing arguments to cause full chip/partition
490 * erases -- easy to do accidentally, e.g. with a misspelled
493 if (argc != o + args)
496 printf("\nNAND %s: ", cmd);
497 /* skip first two or three arguments, look for offset and size */
498 if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
499 &maxsize, MTD_DEV_TYPE_NAND,
500 nand_info[dev]->size) != 0)
506 mtd = nand_info[dev];
508 memset(&opts, 0, sizeof(opts));
513 opts.spread = spread;
520 if (confirm_yesno()) {
523 puts("scrub aborted\n");
528 ret = nand_erase_opts(mtd, &opts);
529 printf("%s\n", ret ? "ERROR" : "OK");
531 return ret == 0 ? 0 : 1;
534 if (strncmp(cmd, "dump", 4) == 0) {
538 off = (int)simple_strtoul(argv[2], NULL, 16);
539 ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
541 return ret == 0 ? 1 : 0;
544 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
554 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
556 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
557 printf("\nNAND %s: ", read ? "read" : "write");
559 s = strchr(cmd, '.');
561 if (s && !strncmp(s, ".raw", 4)) {
564 if (!strcmp(s, ".raw.noverify"))
567 if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
569 nand_info[dev]->size))
575 mtd = nand_info[dev];
577 if (argc > 4 && !str2long(argv[4], &pagecount)) {
578 printf("'%s' is not a number\n", argv[4]);
582 if (pagecount * mtd->writesize > size) {
583 puts("Size exceeds partition or device limit\n");
587 rwsize = pagecount * (mtd->writesize + mtd->oobsize);
589 if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
592 nand_info[dev]->size) != 0)
598 /* size is unspecified */
600 adjust_size_for_badblocks(&size, off, dev);
604 mtd = nand_info[dev];
606 if (!s || !strcmp(s, ".jffs2") ||
607 !strcmp(s, ".e") || !strcmp(s, ".i")) {
609 ret = nand_read_skip_bad(mtd, off, &rwsize,
613 ret = nand_write_skip_bad(mtd, off, &rwsize,
617 #ifdef CONFIG_CMD_NAND_TRIMFFS
618 } else if (!strcmp(s, ".trimffs")) {
620 printf("Unknown nand command suffix '%s'\n", s);
623 ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
624 maxsize, (u_char *)addr,
625 WITH_DROP_FFS | WITH_WR_VERIFY);
627 } else if (!strcmp(s, ".oob")) {
628 /* out-of-band data */
629 mtd_oob_ops_t ops = {
630 .oobbuf = (u8 *)addr,
636 ret = mtd_read_oob(mtd, off, &ops);
638 ret = mtd_write_oob(mtd, off, &ops);
640 ret = raw_access(mtd, addr, off, pagecount, read,
643 printf("Unknown nand command suffix '%s'.\n", s);
647 printf(" %zu bytes %s: %s\n", rwsize,
648 read ? "read" : "written", ret ? "ERROR" : "OK");
650 return ret == 0 ? 0 : 1;
653 #ifdef CONFIG_CMD_NAND_TORTURE
654 if (strcmp(cmd, "torture") == 0) {
656 unsigned int failed = 0, passed = 0;
661 if (!str2off(argv[2], &off)) {
662 puts("Offset is not a valid number\n");
666 size = mtd->erasesize;
668 if (!str2off(argv[3], &size)) {
669 puts("Size is not a valid number\n");
675 if (endoff > mtd->size) {
676 puts("Arguments beyond end of NAND\n");
680 off = round_down(off, mtd->erasesize);
681 endoff = round_up(endoff, mtd->erasesize);
683 printf("\nNAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)\n",
684 dev, off, size, mtd->erasesize);
685 while (off < endoff) {
686 ret = nand_torture(mtd, off);
689 printf(" block at 0x%llx failed\n", off);
693 off += mtd->erasesize;
695 printf(" Passed: %u, failed: %u\n", passed, failed);
700 if (strcmp(cmd, "markbad") == 0) {
708 addr = simple_strtoul(*argv, NULL, 16);
710 if (mtd_block_markbad(mtd, addr)) {
711 printf("block 0x%08lx NOT marked "
712 "as bad! ERROR %d\n",
716 printf("block 0x%08lx successfully "
726 if (strcmp(cmd, "biterr") == 0) {
731 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
732 if (strcmp(cmd, "lock") == 0) {
736 if (!strcmp("tight", argv[2]))
738 if (!strcmp("status", argv[2]))
744 if (!nand_lock(mtd, tight)) {
745 puts("NAND flash successfully locked\n");
747 puts("Error locking NAND flash\n");
754 if (strncmp(cmd, "unlock", 5) == 0) {
757 s = strchr(cmd, '.');
759 if (s && !strcmp(s, ".allexcept"))
762 if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
763 &maxsize, MTD_DEV_TYPE_NAND,
764 nand_info[dev]->size) < 0)
770 if (!nand_unlock(nand_info[dev], off, size, allexcept)) {
771 puts("NAND flash successfully unlocked\n");
773 puts("Error unlocking NAND flash, "
774 "write and erase will probably fail\n");
782 return CMD_RET_USAGE;
785 #ifdef CONFIG_SYS_LONGHELP
786 static char nand_help_text[] =
787 "info - show available NAND devices\n"
788 "nand device [dev] - show or set current device\n"
789 "nand read - addr off|partition size\n"
790 "nand write - addr off|partition size\n"
791 " read/write 'size' bytes starting at offset 'off'\n"
792 " to/from memory address 'addr', skipping bad blocks.\n"
793 "nand read.raw - addr off|partition [count]\n"
794 "nand write.raw[.noverify] - addr off|partition [count]\n"
795 " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
796 #ifdef CONFIG_CMD_NAND_TRIMFFS
797 "nand write.trimffs - addr off|partition size\n"
798 " write 'size' bytes starting at offset 'off' from memory address\n"
799 " 'addr', skipping bad blocks and dropping any pages at the end\n"
800 " of eraseblocks that contain only 0xFF\n"
802 "nand erase[.spread] [clean] off size - erase 'size' bytes "
803 "from offset 'off'\n"
804 " With '.spread', erase enough for given file size, otherwise,\n"
805 " 'size' includes skipped bad blocks.\n"
806 "nand erase.part [clean] partition - erase entire mtd partition'\n"
807 "nand erase.chip [clean] - erase entire chip'\n"
808 "nand bad - show bad blocks\n"
809 "nand dump[.oob] off - dump page\n"
810 #ifdef CONFIG_CMD_NAND_TORTURE
811 "nand torture off - torture one block at offset\n"
812 "nand torture off [size] - torture blocks from off to off+size\n"
814 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
815 " really clean NAND erasing bad blocks (UNSAFE)\n"
816 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
817 "nand biterr off - make a bit error at offset (UNSAFE)"
818 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
820 "nand lock [tight] [status]\n"
821 " bring nand to lock state or display locked pages\n"
822 "nand unlock[.allexcept] [offset] [size] - unlock section"
824 #ifdef CONFIG_ENV_OFFSET_OOB
826 "nand env.oob - environment offset in OOB of block 0 of"
828 "nand env.oob set off|partition - set enviromnent offset\n"
829 "nand env.oob get - get environment offset"
835 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
836 "NAND sub-system", nand_help_text
839 static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd,
840 ulong offset, ulong addr, char *cmd)
845 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
848 #if defined(CONFIG_FIT)
849 const void *fit_hdr = NULL;
852 s = strchr(cmd, '.');
854 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
855 printf("Unknown nand load suffix '%s'\n", s);
856 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
860 printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
862 cnt = mtd->writesize;
863 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
866 puts("** Read error\n");
867 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
870 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
872 switch (genimg_get_format ((void *)addr)) {
873 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
874 case IMAGE_FORMAT_LEGACY:
875 hdr = (image_header_t *)addr;
877 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
878 image_print_contents (hdr);
880 cnt = image_get_image_size (hdr);
883 #if defined(CONFIG_FIT)
884 case IMAGE_FORMAT_FIT:
885 fit_hdr = (const void *)addr;
886 puts ("Fit image detected...\n");
888 cnt = fit_get_size (fit_hdr);
892 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
893 puts ("** Unknown image type\n");
896 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
898 r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
901 puts("** Read error\n");
902 bootstage_error(BOOTSTAGE_ID_NAND_READ);
905 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
907 #if defined(CONFIG_FIT)
908 /* This cannot be done earlier, we need complete FIT image in RAM first */
909 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
910 if (!fit_check_format (fit_hdr)) {
911 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
912 puts ("** Bad FIT image format\n");
915 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
916 fit_print_contents (fit_hdr);
920 /* Loading ok, update default load address */
924 return bootm_maybe_autostart(cmdtp, cmd);
927 static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
930 char *boot_device = NULL;
932 ulong addr, offset = 0;
933 #if defined(CONFIG_CMD_MTDPARTS)
934 struct mtd_device *dev;
935 struct part_info *part;
939 char *p = (argc == 2) ? argv[1] : argv[2];
940 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
941 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
942 if (dev->id->type != MTD_DEV_TYPE_NAND) {
943 puts("Not a NAND device\n");
949 addr = simple_strtoul(argv[1], NULL, 16);
951 addr = CONFIG_SYS_LOAD_ADDR;
952 return nand_load_image(cmdtp, nand_info[dev->id->num],
953 part->offset, addr, argv[0]);
958 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
961 addr = CONFIG_SYS_LOAD_ADDR;
962 boot_device = getenv("bootdevice");
965 addr = simple_strtoul(argv[1], NULL, 16);
966 boot_device = getenv("bootdevice");
969 addr = simple_strtoul(argv[1], NULL, 16);
970 boot_device = argv[2];
973 addr = simple_strtoul(argv[1], NULL, 16);
974 boot_device = argv[2];
975 offset = simple_strtoul(argv[3], NULL, 16);
978 #if defined(CONFIG_CMD_MTDPARTS)
981 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
982 return CMD_RET_USAGE;
984 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
987 puts("\n** No boot device **\n");
988 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
991 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
993 idx = simple_strtoul(boot_device, NULL, 16);
995 if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx]->name) {
996 printf("\n** Device %d not available\n", idx);
997 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
1000 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
1002 return nand_load_image(cmdtp, nand_info[idx], offset, addr, argv[0]);
1005 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
1006 "boot from NAND device",
1007 "[partition] | [[[loadAddr] dev] offset]"