cmd_nand.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /*
  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>
  6. *
  7. * Added 16-bit nand support
  8. * (C) 2004 Texas Instruments
  9. */
  10. #include <common.h>
  11. #ifndef CFG_NAND_LEGACY
  12. /*
  13. *
  14. * New NAND support
  15. *
  16. */
  17. #include <common.h>
  18. #if (CONFIG_COMMANDS & CFG_CMD_NAND)
  19. #include <command.h>
  20. #include <watchdog.h>
  21. #include <malloc.h>
  22. #include <asm/byteorder.h>
  23. #ifdef CONFIG_SHOW_BOOT_PROGRESS
  24. # include <status_led.h>
  25. # define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
  26. #else
  27. # define SHOW_BOOT_PROGRESS(arg)
  28. #endif
  29. #include <jffs2/jffs2.h>
  30. #include <nand.h>
  31. extern nand_info_t nand_info[]; /* info for NAND chips */
  32. static int nand_dump_oob(nand_info_t *nand, ulong off)
  33. {
  34. return 0;
  35. }
  36. static int nand_dump(nand_info_t *nand, ulong off)
  37. {
  38. int i;
  39. u_char *buf, *p;
  40. buf = malloc(nand->oobblock + nand->oobsize);
  41. if (!buf) {
  42. puts("No memory for page buffer\n");
  43. return 1;
  44. }
  45. off &= ~(nand->oobblock - 1);
  46. i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
  47. if (i < 0) {
  48. printf("Error (%d) reading page %08x\n", i, off);
  49. free(buf);
  50. return 1;
  51. }
  52. printf("Page %08x dump:\n", off);
  53. i = nand->oobblock >> 4; p = buf;
  54. while (i--) {
  55. printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
  56. " %02x %02x %02x %02x %02x %02x %02x %02x\n",
  57. p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
  58. p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
  59. p += 16;
  60. }
  61. puts("OOB:\n");
  62. i = nand->oobsize >> 3;
  63. while (i--) {
  64. printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
  65. p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
  66. p += 8;
  67. }
  68. free(buf);
  69. return 0;
  70. }
  71. /* ------------------------------------------------------------------------- */
  72. static void
  73. arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize)
  74. {
  75. *off = 0;
  76. *size = 0;
  77. #if defined(CONFIG_JFFS2_NAND) && defined(CFG_JFFS_CUSTOM_PART)
  78. if (argc >= 1 && strcmp(argv[0], "partition") == 0) {
  79. int part_num;
  80. struct part_info *part;
  81. const char *partstr;
  82. if (argc >= 2)
  83. partstr = argv[1];
  84. else
  85. partstr = getenv("partition");
  86. if (partstr)
  87. part_num = (int)simple_strtoul(partstr, NULL, 10);
  88. else
  89. part_num = 0;
  90. part = jffs2_part_info(part_num);
  91. if (part == NULL) {
  92. printf("\nInvalid partition %d\n", part_num);
  93. return;
  94. }
  95. *size = part->size;
  96. *off = (ulong)part->offset;
  97. } else
  98. #endif
  99. {
  100. if (argc >= 1)
  101. *off = (ulong)simple_strtoul(argv[0], NULL, 16);
  102. else
  103. *off = 0;
  104. if (argc >= 2)
  105. *size = (ulong)simple_strtoul(argv[1], NULL, 16);
  106. else
  107. *size = totsize - *off;
  108. }
  109. }
  110. int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
  111. {
  112. int i, dev, ret;
  113. ulong addr, off, size;
  114. char *cmd, *s;
  115. nand_info_t *nand;
  116. /* at least two arguments please */
  117. if (argc < 2)
  118. goto usage;
  119. cmd = argv[1];
  120. if (strcmp(cmd, "info") == 0) {
  121. putc('\n');
  122. for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
  123. if (nand_info[i].name)
  124. printf("Device %d: %s, sector size %lu KiB\n",
  125. i, nand_info[i].name,
  126. nand_info[i].erasesize >> 10);
  127. }
  128. return 0;
  129. }
  130. if (strcmp(cmd, "device") == 0) {
  131. if (argc < 3) {
  132. if ((nand_curr_device < 0) ||
  133. (nand_curr_device >= CFG_MAX_NAND_DEVICE))
  134. puts("\nno devices available\n");
  135. else
  136. printf("\nDevice %d: %s\n", nand_curr_device,
  137. nand_info[nand_curr_device].name);
  138. return 0;
  139. }
  140. dev = (int)simple_strtoul(argv[2], NULL, 10);
  141. if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
  142. puts("No such device\n");
  143. return 1;
  144. }
  145. printf("Device %d: %s", dev, nand_info[dev].name);
  146. puts("... is now current device\n");
  147. nand_curr_device = dev;
  148. return 0;
  149. }
  150. if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
  151. strncmp(cmd, "dump", 4) != 0 &&
  152. strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0)
  153. goto usage;
  154. /* the following commands operate on the current device */
  155. if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
  156. !nand_info[nand_curr_device].name) {
  157. puts("\nno devices available\n");
  158. return 1;
  159. }
  160. nand = &nand_info[nand_curr_device];
  161. if (strcmp(cmd, "bad") == 0) {
  162. printf("\nDevice %d bad blocks:\n", nand_curr_device);
  163. for (off = 0; off < nand->size; off += nand->erasesize)
  164. if (nand_block_isbad(nand, off))
  165. printf(" %08x\n", off);
  166. return 0;
  167. }
  168. if (strcmp(cmd, "erase") == 0) {
  169. arg_off_size(argc - 2, argv + 2, &off, &size, nand->size);
  170. if (off == 0 && size == 0)
  171. return 1;
  172. printf("\nNAND erase: device %d offset 0x%x, size 0x%x ",
  173. nand_curr_device, off, size);
  174. ret = nand_erase(nand, off, size);
  175. printf("%s\n", ret ? "ERROR" : "OK");
  176. return ret == 0 ? 0 : 1;
  177. }
  178. if (strncmp(cmd, "dump", 4) == 0) {
  179. if (argc < 3)
  180. goto usage;
  181. s = strchr(cmd, '.');
  182. off = (int)simple_strtoul(argv[2], NULL, 16);
  183. if (s != NULL && strcmp(s, ".oob") == 0)
  184. ret = nand_dump_oob(nand, off);
  185. else
  186. ret = nand_dump(nand, off);
  187. return ret == 0 ? 1 : 0;
  188. }
  189. /* read write */
  190. if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
  191. if (argc < 4)
  192. goto usage;
  193. /*
  194. s = strchr(cmd, '.');
  195. clean = CLEAN_NONE;
  196. if (s != NULL) {
  197. if (strcmp(s, ".jffs2") == 0 || strcmp(s, ".e") == 0
  198. || strcmp(s, ".i"))
  199. clean = CLEAN_JFFS2;
  200. }
  201. */
  202. addr = (ulong)simple_strtoul(argv[2], NULL, 16);
  203. arg_off_size(argc - 3, argv + 3, &off, &size, nand->size);
  204. if (off == 0 && size == 0)
  205. return 1;
  206. i = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
  207. printf("\nNAND %s: device %d offset %u, size %u ... ",
  208. i ? "read" : "write", nand_curr_device, off, size);
  209. if (i)
  210. ret = nand_read(nand, off, &size, (u_char *)addr);
  211. else
  212. ret = nand_write(nand, off, &size, (u_char *)addr);
  213. printf(" %d bytes %s: %s\n", size,
  214. i ? "read" : "written", ret ? "ERROR" : "OK");
  215. return ret == 0 ? 0 : 1;
  216. }
  217. usage:
  218. printf("Usage:\n%s\n", cmdtp->usage);
  219. return 1;
  220. }
  221. U_BOOT_CMD(nand, 5, 1, do_nand,
  222. "nand - NAND sub-system\n",
  223. "info - show available NAND devices\n"
  224. "nand device [dev] - show or set current device\n"
  225. "nand read[.jffs2] - addr off size\n"
  226. "nand write[.jffs2] - addr off size - read/write `size' bytes starting\n"
  227. " at offset `off' to/from memory address `addr'\n"
  228. "nand erase [clean] [off size] - erase `size' bytes from\n"
  229. " offset `off' (entire device if not specified)\n"
  230. "nand bad - show bad blocks\n"
  231. "nand dump[.oob] off - dump page\n"
  232. "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
  233. "nand markbad off - mark bad block at offset (UNSAFE)\n"
  234. "nand biterr off - make a bit error at offset (UNSAFE)\n");
  235. int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
  236. {
  237. char *boot_device = NULL;
  238. char *ep;
  239. int dev;
  240. int r;
  241. ulong addr, cnt, offset = 0;
  242. image_header_t *hdr;
  243. nand_info_t *nand;
  244. switch (argc) {
  245. case 1:
  246. addr = CFG_LOAD_ADDR;
  247. boot_device = getenv("bootdevice");
  248. break;
  249. case 2:
  250. addr = simple_strtoul(argv[1], NULL, 16);
  251. boot_device = getenv("bootdevice");
  252. break;
  253. case 3:
  254. addr = simple_strtoul(argv[1], NULL, 16);
  255. boot_device = argv[2];
  256. break;
  257. case 4:
  258. addr = simple_strtoul(argv[1], NULL, 16);
  259. boot_device = argv[2];
  260. offset = simple_strtoul(argv[3], NULL, 16);
  261. break;
  262. default:
  263. printf("Usage:\n%s\n", cmdtp->usage);
  264. SHOW_BOOT_PROGRESS(-1);
  265. return 1;
  266. }
  267. if (!boot_device) {
  268. puts("\n** No boot device **\n");
  269. SHOW_BOOT_PROGRESS(-1);
  270. return 1;
  271. }
  272. dev = simple_strtoul(boot_device, &ep, 16);
  273. if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
  274. printf("\n** Device %d not available\n", dev);
  275. SHOW_BOOT_PROGRESS(-1);
  276. return 1;
  277. }
  278. nand = &nand_info[dev];
  279. printf("\nLoading from device %d: %s (offset 0x%lx)\n",
  280. dev, nand->name, offset);
  281. cnt = nand->oobblock;
  282. r = nand_read(nand, offset, &cnt, (u_char *) addr);
  283. if (r) {
  284. printf("** Read error on %d\n", dev);
  285. SHOW_BOOT_PROGRESS(-1);
  286. return 1;
  287. }
  288. hdr = (image_header_t *) addr;
  289. if (ntohl(hdr->ih_magic) != IH_MAGIC) {
  290. printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
  291. SHOW_BOOT_PROGRESS(-1);
  292. return 1;
  293. }
  294. print_image_hdr(hdr);
  295. cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
  296. r = nand_read(nand, offset, &cnt, (u_char *) addr);
  297. if (r) {
  298. printf("** Read error on %d\n", dev);
  299. SHOW_BOOT_PROGRESS(-1);
  300. return 1;
  301. }
  302. /* Loading ok, update default load address */
  303. load_addr = addr;
  304. /* Check if we should attempt an auto-start */
  305. if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
  306. char *local_args[2];
  307. extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
  308. local_args[0] = argv[0];
  309. local_args[1] = NULL;
  310. printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
  311. do_bootm(cmdtp, 0, 1, local_args);
  312. return 1;
  313. }
  314. return 0;
  315. }
  316. U_BOOT_CMD(nboot, 4, 1, do_nandboot,
  317. "nboot - boot from NAND device\n", "loadAddr dev\n");
  318. #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
  319. #else /* CFG_NAND_LEGACY */
  320. /*
  321. *
  322. * Legacy NAND support - to be phased out
  323. *
  324. */
  325. #include <command.h>
  326. #include <malloc.h>
  327. #include <asm/io.h>
  328. #include <watchdog.h>
  329. #ifdef CONFIG_SHOW_BOOT_PROGRESS
  330. # include <status_led.h>
  331. # define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
  332. #else
  333. # define SHOW_BOOT_PROGRESS(arg)
  334. #endif
  335. #if (CONFIG_COMMANDS & CFG_CMD_NAND)
  336. #include <linux/mtd/nand_legacy.h>
  337. #if 0
  338. #include <linux/mtd/nand_ids.h>
  339. #include <jffs2/jffs2.h>
  340. #endif
  341. #ifdef CONFIG_OMAP1510
  342. void archflashwp(void *archdata, int wp);
  343. #endif
  344. #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
  345. #undef NAND_DEBUG
  346. #undef PSYCHO_DEBUG
  347. /* ****************** WARNING *********************
  348. * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
  349. * erase (or at least attempt to erase) blocks that are marked
  350. * bad. This can be very handy if you are _sure_ that the block
  351. * is OK, say because you marked a good block bad to test bad
  352. * block handling and you are done testing, or if you have
  353. * accidentally marked blocks bad.
  354. *
  355. * Erasing factory marked bad blocks is a _bad_ idea. If the
  356. * erase succeeds there is no reliable way to find them again,
  357. * and attempting to program or erase bad blocks can affect
  358. * the data in _other_ (good) blocks.
  359. */
  360. #define ALLOW_ERASE_BAD_DEBUG 0
  361. #define CONFIG_MTD_NAND_ECC /* enable ECC */
  362. #define CONFIG_MTD_NAND_ECC_JFFS2
  363. /* bits for nand_legacy_rw() `cmd'; or together as needed */
  364. #define NANDRW_READ 0x01
  365. #define NANDRW_WRITE 0x00
  366. #define NANDRW_JFFS2 0x02
  367. #define NANDRW_JFFS2_SKIP 0x04
  368. /*
  369. * Imports from nand_legacy.c
  370. */
  371. extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
  372. extern int curr_device;
  373. extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs,
  374. size_t len, int clean);
  375. extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start,
  376. size_t len, size_t *retlen, u_char *buf);
  377. extern void nand_print(struct nand_chip *nand);
  378. extern void nand_print_bad(struct nand_chip *nand);
  379. extern int nand_read_oob(struct nand_chip *nand, size_t ofs,
  380. size_t len, size_t *retlen, u_char *buf);
  381. extern int nand_write_oob(struct nand_chip *nand, size_t ofs,
  382. size_t len, size_t *retlen, const u_char *buf);
  383. int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  384. {
  385. int rcode = 0;
  386. switch (argc) {
  387. case 0:
  388. case 1:
  389. printf ("Usage:\n%s\n", cmdtp->usage);
  390. return 1;
  391. case 2:
  392. if (strcmp(argv[1],"info") == 0) {
  393. int i;
  394. putc ('\n');
  395. for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {
  396. if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)
  397. continue; /* list only known devices */
  398. printf ("Device %d: ", i);
  399. nand_print(&nand_dev_desc[i]);
  400. }
  401. return 0;
  402. } else if (strcmp(argv[1],"device") == 0) {
  403. if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
  404. puts ("\nno devices available\n");
  405. return 1;
  406. }
  407. printf ("\nDevice %d: ", curr_device);
  408. nand_print(&nand_dev_desc[curr_device]);
  409. return 0;
  410. } else if (strcmp(argv[1],"bad") == 0) {
  411. if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
  412. puts ("\nno devices available\n");
  413. return 1;
  414. }
  415. printf ("\nDevice %d bad blocks:\n", curr_device);
  416. nand_print_bad(&nand_dev_desc[curr_device]);
  417. return 0;
  418. }
  419. printf ("Usage:\n%s\n", cmdtp->usage);
  420. return 1;
  421. case 3:
  422. if (strcmp(argv[1],"device") == 0) {
  423. int dev = (int)simple_strtoul(argv[2], NULL, 10);
  424. printf ("\nDevice %d: ", dev);
  425. if (dev >= CFG_MAX_NAND_DEVICE) {
  426. puts ("unknown device\n");
  427. return 1;
  428. }
  429. nand_print(&nand_dev_desc[dev]);
  430. /*nand_print (dev);*/
  431. if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
  432. return 1;
  433. }
  434. curr_device = dev;
  435. puts ("... is now current device\n");
  436. return 0;
  437. }
  438. else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
  439. struct nand_chip* nand = &nand_dev_desc[curr_device];
  440. ulong off = 0;
  441. ulong size = nand->totlen;
  442. int ret;
  443. printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
  444. curr_device, off, size);
  445. ret = nand_legacy_erase (nand, off, size, 1);
  446. printf("%s\n", ret ? "ERROR" : "OK");
  447. return ret;
  448. }
  449. printf ("Usage:\n%s\n", cmdtp->usage);
  450. return 1;
  451. default:
  452. /* at least 4 args */
  453. if (strncmp(argv[1], "read", 4) == 0 ||
  454. strncmp(argv[1], "write", 5) == 0) {
  455. ulong addr = simple_strtoul(argv[2], NULL, 16);
  456. ulong off = simple_strtoul(argv[3], NULL, 16);
  457. ulong size = simple_strtoul(argv[4], NULL, 16);
  458. int cmd = (strncmp(argv[1], "read", 4) == 0) ?
  459. NANDRW_READ : NANDRW_WRITE;
  460. int ret, total;
  461. char* cmdtail = strchr(argv[1], '.');
  462. if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
  463. /* read out-of-band data */
  464. if (cmd & NANDRW_READ) {
  465. ret = nand_read_oob(nand_dev_desc + curr_device,
  466. off, size, (size_t *)&total,
  467. (u_char*)addr);
  468. }
  469. else {
  470. ret = nand_write_oob(nand_dev_desc + curr_device,
  471. off, size, (size_t *)&total,
  472. (u_char*)addr);
  473. }
  474. return ret;
  475. }
  476. else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
  477. cmd |= NANDRW_JFFS2; /* skip bad blocks */
  478. else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) {
  479. cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */
  480. if (cmd & NANDRW_READ)
  481. cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */
  482. }
  483. #ifdef SXNI855T
  484. /* need ".e" same as ".j" for compatibility with older units */
  485. else if (cmdtail && !strcmp(cmdtail, ".e"))
  486. cmd |= NANDRW_JFFS2; /* skip bad blocks */
  487. #endif
  488. #ifdef CFG_NAND_SKIP_BAD_DOT_I
  489. /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */
  490. /* ".i" for image -> read skips bad block (no 0xff) */
  491. else if (cmdtail && !strcmp(cmdtail, ".i")) {
  492. cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */
  493. if (cmd & NANDRW_READ)
  494. cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */
  495. }
  496. #endif /* CFG_NAND_SKIP_BAD_DOT_I */
  497. else if (cmdtail) {
  498. printf ("Usage:\n%s\n", cmdtp->usage);
  499. return 1;
  500. }
  501. printf ("\nNAND %s: device %d offset %ld, size %ld ... ",
  502. (cmd & NANDRW_READ) ? "read" : "write",
  503. curr_device, off, size);
  504. ret = nand_legacy_rw(nand_dev_desc + curr_device, cmd, off, size,
  505. (size_t *)&total, (u_char*)addr);
  506. printf (" %d bytes %s: %s\n", total,
  507. (cmd & NANDRW_READ) ? "read" : "written",
  508. ret ? "ERROR" : "OK");
  509. return ret;
  510. } else if (strcmp(argv[1],"erase") == 0 &&
  511. (argc == 4 || strcmp("clean", argv[2]) == 0)) {
  512. int clean = argc == 5;
  513. ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
  514. ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
  515. int ret;
  516. printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
  517. curr_device, off, size);
  518. ret = nand_legacy_erase (nand_dev_desc + curr_device,
  519. off, size, clean);
  520. printf("%s\n", ret ? "ERROR" : "OK");
  521. return ret;
  522. } else {
  523. printf ("Usage:\n%s\n", cmdtp->usage);
  524. rcode = 1;
  525. }
  526. return rcode;
  527. }
  528. }
  529. U_BOOT_CMD(
  530. nand, 5, 1, do_nand,
  531. "nand - NAND sub-system\n",
  532. "info - show available NAND devices\n"
  533. "nand device [dev] - show or set current device\n"
  534. "nand read[.jffs2[s]] addr off size\n"
  535. "nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
  536. " at offset `off' to/from memory address `addr'\n"
  537. "nand erase [clean] [off size] - erase `size' bytes from\n"
  538. " offset `off' (entire device if not specified)\n"
  539. "nand bad - show bad blocks\n"
  540. "nand read.oob addr off size - read out-of-band data\n"
  541. "nand write.oob addr off size - read out-of-band data\n"
  542. );
  543. int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  544. {
  545. char *boot_device = NULL;
  546. char *ep;
  547. int dev;
  548. ulong cnt;
  549. ulong addr;
  550. ulong offset = 0;
  551. image_header_t *hdr;
  552. int rcode = 0;
  553. switch (argc) {
  554. case 1:
  555. addr = CFG_LOAD_ADDR;
  556. boot_device = getenv ("bootdevice");
  557. break;
  558. case 2:
  559. addr = simple_strtoul(argv[1], NULL, 16);
  560. boot_device = getenv ("bootdevice");
  561. break;
  562. case 3:
  563. addr = simple_strtoul(argv[1], NULL, 16);
  564. boot_device = argv[2];
  565. break;
  566. case 4:
  567. addr = simple_strtoul(argv[1], NULL, 16);
  568. boot_device = argv[2];
  569. offset = simple_strtoul(argv[3], NULL, 16);
  570. break;
  571. default:
  572. printf ("Usage:\n%s\n", cmdtp->usage);
  573. SHOW_BOOT_PROGRESS (-1);
  574. return 1;
  575. }
  576. if (!boot_device) {
  577. puts ("\n** No boot device **\n");
  578. SHOW_BOOT_PROGRESS (-1);
  579. return 1;
  580. }
  581. dev = simple_strtoul(boot_device, &ep, 16);
  582. if ((dev >= CFG_MAX_NAND_DEVICE) ||
  583. (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
  584. printf ("\n** Device %d not available\n", dev);
  585. SHOW_BOOT_PROGRESS (-1);
  586. return 1;
  587. }
  588. printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
  589. dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
  590. offset);
  591. if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
  592. SECTORSIZE, NULL, (u_char *)addr)) {
  593. printf ("** Read error on %d\n", dev);
  594. SHOW_BOOT_PROGRESS (-1);
  595. return 1;
  596. }
  597. hdr = (image_header_t *)addr;
  598. if (ntohl(hdr->ih_magic) == IH_MAGIC) {
  599. print_image_hdr (hdr);
  600. cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
  601. cnt -= SECTORSIZE;
  602. } else {
  603. printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic));
  604. SHOW_BOOT_PROGRESS (-1);
  605. return 1;
  606. }
  607. if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
  608. offset + SECTORSIZE, cnt, NULL,
  609. (u_char *)(addr+SECTORSIZE))) {
  610. printf ("** Read error on %d\n", dev);
  611. SHOW_BOOT_PROGRESS (-1);
  612. return 1;
  613. }
  614. /* Loading ok, update default load address */
  615. load_addr = addr;
  616. /* Check if we should attempt an auto-start */
  617. if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
  618. char *local_args[2];
  619. extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
  620. local_args[0] = argv[0];
  621. local_args[1] = NULL;
  622. printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
  623. do_bootm (cmdtp, 0, 1, local_args);
  624. rcode = 1;
  625. }
  626. return rcode;
  627. }
  628. U_BOOT_CMD(
  629. nboot, 4, 1, do_nandboot,
  630. "nboot - boot from NAND device\n",
  631. "loadAddr dev\n"
  632. );
  633. #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
  634. #endif /* CFG_NAND_LEGACY */