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;
47 off = last + nand->writesize;
51 datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize);
52 oobbuf = memalign(ARCH_DMA_MINALIGN, 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)
235 * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
236 * not the same as others. Instead of bit 1 being lock, it is
237 * #lock_tight. To make the driver support either format, ignore bit 1
238 * and use only bit 0 and bit 2.
240 printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
243 (end - start) / erasesize,
244 ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
245 (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
246 ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
249 static void do_nand_status(nand_info_t *nand)
251 ulong block_start = 0;
253 int last_status = -1;
255 struct nand_chip *nand_chip = nand->priv;
256 /* check the WP bit */
257 nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1);
258 printf("device is %swrite protected\n",
259 (nand_chip->read_byte(nand) & 0x80 ?
262 for (off = 0; off < nand->size; off += nand->erasesize) {
263 int s = nand_get_lock_status(nand, off);
265 /* print message only if status has changed */
266 if (s != last_status && off != 0) {
267 print_status(block_start, off, nand->erasesize,
273 /* Print the last block info */
274 print_status(block_start, off, nand->erasesize, last_status);
278 #ifdef CONFIG_ENV_OFFSET_OOB
279 unsigned long nand_env_oob_offset;
281 int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
284 uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
285 nand_info_t *nand = &nand_info[0];
288 if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
289 puts("no devices available\n");
295 if (!strcmp(cmd, "get")) {
296 ret = get_nand_env_oob(nand, &nand_env_oob_offset);
300 printf("0x%08lx\n", nand_env_oob_offset);
301 } else if (!strcmp(cmd, "set")) {
304 struct mtd_oob_ops ops;
310 if (arg_off(argv[2], &idx, &addr, &maxsize)) {
311 puts("Offset or partition name expected\n");
316 puts("Partition not on first NAND device\n");
320 if (nand->oobavail < ENV_OFFSET_SIZE) {
321 printf("Insufficient available OOB bytes:\n"
322 "%d OOB bytes available but %d required for "
324 nand->oobavail, ENV_OFFSET_SIZE);
328 if ((addr & (nand->erasesize - 1)) != 0) {
329 printf("Environment offset must be block-aligned\n");
334 ops.mode = MTD_OOB_AUTO;
336 ops.ooblen = ENV_OFFSET_SIZE;
337 ops.oobbuf = (void *) oob_buf;
339 oob_buf[0] = ENV_OOB_MARKER;
340 oob_buf[1] = addr / nand->erasesize;
342 ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops);
344 printf("Error writing OOB block 0\n");
348 ret = get_nand_env_oob(nand, &nand_env_oob_offset);
350 printf("Error reading env offset in OOB\n");
354 if (addr != nand_env_oob_offset) {
355 printf("Verification of env offset in OOB failed: "
356 "0x%08llx expected but got 0x%08lx\n",
357 (unsigned long long)addr, nand_env_oob_offset);
367 return CMD_RET_USAGE;
372 static void nand_print_and_set_info(int idx)
374 nand_info_t *nand = &nand_info[idx];
375 struct nand_chip *chip = nand->priv;
378 printf("Device %d: ", idx);
379 if (chip->numchips > 1)
380 printf("%dx ", chip->numchips);
381 printf("%s, sector size %u KiB\n",
382 nand->name, nand->erasesize >> 10);
383 printf(" Page size %8d b\n", nand->writesize);
384 printf(" OOB size %8d b\n", nand->oobsize);
385 printf(" Erase size %8d b\n", nand->erasesize);
387 /* Set geometry info */
388 sprintf(buf, "%x", nand->writesize);
389 setenv("nand_writesize", buf);
391 sprintf(buf, "%x", nand->oobsize);
392 setenv("nand_oobsize", buf);
394 sprintf(buf, "%x", nand->erasesize);
395 setenv("nand_erasesize", buf);
398 static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
405 mtd_oob_ops_t ops = {
406 .datbuf = (u8 *)addr,
407 .oobbuf = ((u8 *)addr) + nand->writesize,
408 .len = nand->writesize,
409 .ooblen = nand->oobsize,
414 ret = nand->read_oob(nand, off, &ops);
416 ret = nand->write_oob(nand, off, &ops);
419 printf("%s: error at offset %llx, ret %d\n",
420 __func__, (long long)off, ret);
424 addr += nand->writesize + nand->oobsize;
425 off += nand->writesize;
431 static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
438 #ifdef CONFIG_SYS_NAND_QUIET
439 int quiet = CONFIG_SYS_NAND_QUIET;
443 const char *quiet_str = getenv("quiet");
444 int dev = nand_curr_device;
445 int repeat = flag & CMD_FLAG_REPEAT;
447 /* at least two arguments please */
452 quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
456 /* Only "dump" is repeatable. */
457 if (repeat && strcmp(cmd, "dump"))
458 return CMD_RET_FAILURE;
460 if (strcmp(cmd, "info") == 0) {
463 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
464 if (nand_info[i].name)
465 nand_print_and_set_info(i);
467 return CMD_RET_SUCCESS;
470 if (strcmp(cmd, "device") == 0) {
473 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
474 puts("no devices available\n");
476 nand_print_and_set_info(dev);
477 return CMD_RET_SUCCESS;
480 dev = (int)simple_strtoul(argv[2], NULL, 10);
483 return CMD_RET_SUCCESS;
486 #ifdef CONFIG_ENV_OFFSET_OOB
487 /* this command operates only on the first nand device */
488 if (strcmp(cmd, "env.oob") == 0)
489 return do_nand_env_oob(cmdtp, argc - 1, argv + 1) ?
490 CMD_RET_FAILURE : CMD_RET_SUCCESS;;
493 /* The following commands operate on the current device, unless
494 * overridden by a partition specifier. Note that if somehow the
495 * current device is invalid, it will have to be changed to a valid
496 * one before these commands can run, even if a partition specifier
497 * for another device is to be used.
499 if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
500 !nand_info[dev].name) {
501 puts("\nno devices available\n");
502 return CMD_RET_FAILURE;
504 nand = &nand_info[dev];
506 if (strcmp(cmd, "bad") == 0) {
507 printf("\nDevice %d bad blocks:\n", dev);
508 for (off = 0; off < nand->size; off += nand->erasesize)
509 if (nand_block_isbad(nand, off))
510 printf(" %08llx\n", (unsigned long long)off);
511 return CMD_RET_SUCCESS;
517 * nand erase [clean] [off size]
519 if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
520 nand_erase_options_t opts;
521 /* "clean" at index 2 means request to write cleanmarker */
522 int clean = argc > 2 && !strcmp("clean", argv[2]);
523 int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
524 int o = (clean || scrub_yes) ? 3 : 2;
525 int scrub = !strncmp(cmd, "scrub", 5);
528 const char *scrub_warn =
530 "scrub option will erase all factory set bad blocks!\n"
532 "There is no reliable way to recover them.\n"
534 "Use this command only for testing purposes if you\n"
536 "are sure of what you are doing!\n"
537 "\nReally scrub this NAND flash? <y/N>\n";
540 if (!strcmp(&cmd[5], ".spread")) {
542 } else if (!strcmp(&cmd[5], ".part")) {
544 } else if (!strcmp(&cmd[5], ".chip")) {
552 * Don't allow missing arguments to cause full chip/partition
553 * erases -- easy to do accidentally, e.g. with a misspelled
556 if (argc != o + args)
559 printf("\nNAND %s: ", cmd);
560 /* skip first two or three arguments, look for offset and size */
561 if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0)
562 return CMD_RET_FAILURE;
564 nand = &nand_info[dev];
566 memset(&opts, 0, sizeof(opts));
571 opts.spread = spread;
579 else if (getc() == 'y') {
584 puts("scrub aborted\n");
585 return CMD_RET_FAILURE;
588 puts("scrub aborted\n");
589 return CMD_RET_FAILURE;
592 ret = nand_erase_opts(nand, &opts);
593 printf("%s\n", ret ? "ERROR" : "OK");
595 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
598 if (strncmp(cmd, "dump", 4) == 0) {
602 off = (int)simple_strtoul(argv[2], NULL, 16);
603 ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
605 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
608 if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
617 addr = (ulong)simple_strtoul(argv[2], NULL, 16);
619 read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
620 printf("\nNAND %s: ", read ? "read" : "write");
621 if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0)
622 return CMD_RET_FAILURE;
624 nand = &nand_info[dev];
626 s = strchr(cmd, '.');
628 if (s && !strcmp(s, ".raw")) {
631 if (arg_off(argv[3], &dev, &off, &size))
634 if (argc > 4 && !str2long(argv[4], &pagecount)) {
635 printf("'%s' is not a number\n", argv[4]);
639 if (pagecount * nand->writesize > size) {
640 puts("Size exceeds partition or device limit\n");
644 rwsize = pagecount * (nand->writesize + nand->oobsize);
646 if (arg_off_size(argc - 3, argv + 3, &dev,
653 if (!s || !strcmp(s, ".jffs2") ||
654 !strcmp(s, ".e") || !strcmp(s, ".i")) {
656 ret = nand_read_skip_bad(nand, off, &rwsize,
659 ret = nand_write_skip_bad(nand, off, &rwsize,
661 #ifdef CONFIG_CMD_NAND_TRIMFFS
662 } else if (!strcmp(s, ".trimffs")) {
664 printf("Unknown nand command suffix '%s'\n", s);
665 return CMD_RET_FAILURE;
667 ret = nand_write_skip_bad(nand, off, &rwsize,
671 #ifdef CONFIG_CMD_NAND_YAFFS
672 } else if (!strcmp(s, ".yaffs")) {
674 printf("Unknown nand command suffix '%s'.\n", s);
675 return CMD_RET_FAILURE;
677 ret = nand_write_skip_bad(nand, off, &rwsize,
681 } else if (!strcmp(s, ".oob")) {
682 /* out-of-band data */
683 mtd_oob_ops_t ops = {
684 .oobbuf = (u8 *)addr,
690 ret = nand->read_oob(nand, off, &ops);
692 ret = nand->write_oob(nand, off, &ops);
694 ret = raw_access(nand, addr, off, pagecount, read);
696 printf("Unknown nand command suffix '%s'.\n", s);
697 return CMD_RET_FAILURE;
700 printf(" %zu bytes %s: %s\n", rwsize,
701 read ? "read" : "written", ret ? "ERROR" : "OK");
703 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
706 #ifdef CONFIG_CMD_NAND_TORTURE
707 if (strcmp(cmd, "torture") == 0) {
711 if (!str2off(argv[2], &off)) {
712 puts("Offset is not a valid number\n");
716 printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n",
717 dev, off, nand->erasesize);
718 ret = nand_torture(nand, off);
719 printf(" %s\n", ret ? "Failed" : "Passed");
721 return ret == 0 ? 0 : 1;
725 if (strcmp(cmd, "markbad") == 0) {
733 addr = simple_strtoul(*argv, NULL, 16);
735 if (nand->block_markbad(nand, addr)) {
736 printf("block 0x%08lx NOT marked "
737 "as bad! ERROR %d\n",
741 printf("block 0x%08lx successfully "
748 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
751 if (strcmp(cmd, "biterr") == 0) {
753 return CMD_RET_FAILURE;
756 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
757 if (strcmp(cmd, "lock") == 0) {
761 if (!strcmp("tight", argv[2]))
763 if (!strcmp("status", argv[2]))
767 do_nand_status(nand);
769 if (!nand_lock(nand, tight)) {
770 puts("NAND flash successfully locked\n");
772 puts("Error locking NAND flash\n");
773 return CMD_RET_FAILURE;
776 return CMD_RET_SUCCESS;
779 if (strncmp(cmd, "unlock", 5) == 0) {
782 s = strchr(cmd, '.');
784 if (s && !strcmp(s, ".allexcept"))
787 if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0)
788 return CMD_RET_FAILURE;
790 if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
791 puts("NAND flash successfully unlocked\n");
793 puts("Error unlocking NAND flash, "
794 "write and erase will probably fail\n");
795 return CMD_RET_FAILURE;
797 return CMD_RET_SUCCESS;
802 return CMD_RET_USAGE;
805 #ifdef CONFIG_SYS_LONGHELP
806 static char nand_help_text[] =
807 "info - show available NAND devices\n"
808 "nand device [dev] - show or set current device\n"
809 "nand read - addr off|partition size\n"
810 "nand write - addr off|partition size\n"
811 " read/write 'size' bytes starting at offset 'off'\n"
812 " to/from memory address 'addr', skipping bad blocks.\n"
813 "nand read.raw - addr off|partition [count]\n"
814 "nand write.raw - addr off|partition [count]\n"
815 " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
816 #ifdef CONFIG_CMD_NAND_TRIMFFS
817 "nand write.trimffs - addr off|partition size\n"
818 " write 'size' bytes starting at offset 'off' from memory address\n"
819 " 'addr', skipping bad blocks and dropping any pages at the end\n"
820 " of eraseblocks that contain only 0xFF\n"
822 #ifdef CONFIG_CMD_NAND_YAFFS
823 "nand write.yaffs - addr off|partition size\n"
824 " write 'size' bytes starting at offset 'off' with yaffs format\n"
825 " from memory address 'addr', skipping bad blocks.\n"
827 "nand erase[.spread] [clean] off size - erase 'size' bytes "
828 "from offset 'off'\n"
829 " With '.spread', erase enough for given file size, otherwise,\n"
830 " 'size' includes skipped bad blocks.\n"
831 "nand erase.part [clean] partition - erase entire mtd partition'\n"
832 "nand erase.chip [clean] - erase entire chip'\n"
833 "nand bad - show bad blocks\n"
834 "nand dump[.oob] off - dump page\n"
835 #ifdef CONFIG_CMD_NAND_TORTURE
836 "nand torture off - torture block at offset\n"
838 "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
839 " really clean NAND erasing bad blocks (UNSAFE)\n"
840 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
841 "nand biterr off - make a bit error at offset (UNSAFE)"
842 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
844 "nand lock [tight] [status]\n"
845 " bring nand to lock state or display locked pages\n"
846 "nand unlock[.allexcept] [offset] [size] - unlock section"
848 #ifdef CONFIG_ENV_OFFSET_OOB
850 "nand env.oob - environment offset in OOB of block 0 of"
852 "nand env.oob set off|partition - set enviromnent offset\n"
853 "nand env.oob get - get environment offset"
859 nand, CONFIG_SYS_MAXARGS, 1, do_nand,
860 "NAND sub-system", nand_help_text
863 static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
864 ulong offset, ulong addr, char *cmd)
870 #if defined(CONFIG_FIT)
871 const void *fit_hdr = NULL;
874 s = strchr(cmd, '.');
876 (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
877 printf("Unknown nand load suffix '%s'\n", s);
878 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
882 printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
884 cnt = nand->writesize;
885 r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr);
887 puts("** Read error\n");
888 bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
891 bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
893 switch (genimg_get_format ((void *)addr)) {
894 case IMAGE_FORMAT_LEGACY:
895 hdr = (image_header_t *)addr;
897 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
898 image_print_contents (hdr);
900 cnt = image_get_image_size (hdr);
902 #if defined(CONFIG_FIT)
903 case IMAGE_FORMAT_FIT:
904 fit_hdr = (const void *)addr;
905 puts ("Fit image detected...\n");
907 cnt = fit_get_size (fit_hdr);
911 bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
912 puts ("** Unknown image type\n");
915 bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
917 r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr);
919 puts("** Read error\n");
920 bootstage_error(BOOTSTAGE_ID_NAND_READ);
923 bootstage_mark(BOOTSTAGE_ID_NAND_READ);
925 #if defined(CONFIG_FIT)
926 /* This cannot be done earlier, we need complete FIT image in RAM first */
927 if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
928 if (!fit_check_format (fit_hdr)) {
929 bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
930 puts ("** Bad FIT image format\n");
933 bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
934 fit_print_contents (fit_hdr);
938 /* Loading ok, update default load address */
942 return bootm_maybe_autostart(cmdtp, cmd);
945 static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
948 char *boot_device = NULL;
950 ulong addr, offset = 0;
951 #if defined(CONFIG_CMD_MTDPARTS)
952 struct mtd_device *dev;
953 struct part_info *part;
957 char *p = (argc == 2) ? argv[1] : argv[2];
958 if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
959 (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
960 if (dev->id->type != MTD_DEV_TYPE_NAND) {
961 puts("Not a NAND device\n");
967 addr = simple_strtoul(argv[1], NULL, 16);
969 addr = CONFIG_SYS_LOAD_ADDR;
970 return nand_load_image(cmdtp, &nand_info[dev->id->num],
971 part->offset, addr, argv[0]);
976 bootstage_mark(BOOTSTAGE_ID_NAND_PART);
979 addr = CONFIG_SYS_LOAD_ADDR;
980 boot_device = getenv("bootdevice");
983 addr = simple_strtoul(argv[1], NULL, 16);
984 boot_device = getenv("bootdevice");
987 addr = simple_strtoul(argv[1], NULL, 16);
988 boot_device = argv[2];
991 addr = simple_strtoul(argv[1], NULL, 16);
992 boot_device = argv[2];
993 offset = simple_strtoul(argv[3], NULL, 16);
996 #if defined(CONFIG_CMD_MTDPARTS)
999 bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
1000 return CMD_RET_USAGE;
1002 bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
1005 puts("\n** No boot device **\n");
1006 bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1009 bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
1011 idx = simple_strtoul(boot_device, NULL, 16);
1013 if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) {
1014 printf("\n** Device %d not available\n", idx);
1015 bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
1018 bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
1020 return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
1023 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
1024 "boot from NAND device",
1025 "[partition] | [[[loadAddr] dev] offset]"