cmd_nand.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  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) || defined(CONFIG_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. #if ((CONFIG_COMMANDS & CFG_CMD_JFFS2) || defined(CONFIG_CMD_JFFS2)) \
  32. && defined(CONFIG_JFFS2_CMDLINE)
  33. /* parition 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);
  38. #endif
  39. extern nand_info_t nand_info[]; /* info for NAND chips */
  40. static int nand_dump_oob(nand_info_t *nand, ulong off)
  41. {
  42. return 0;
  43. }
  44. static int nand_dump(nand_info_t *nand, ulong off)
  45. {
  46. int i;
  47. u_char *buf, *p;
  48. buf = malloc(nand->oobblock + nand->oobsize);
  49. if (!buf) {
  50. puts("No memory for page buffer\n");
  51. return 1;
  52. }
  53. off &= ~(nand->oobblock - 1);
  54. i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
  55. if (i < 0) {
  56. printf("Error (%d) reading page %08x\n", i, off);
  57. free(buf);
  58. return 1;
  59. }
  60. printf("Page %08x dump:\n", off);
  61. i = nand->oobblock >> 4; p = buf;
  62. while (i--) {
  63. printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
  64. " %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], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
  67. p += 16;
  68. }
  69. puts("OOB:\n");
  70. i = nand->oobsize >> 3;
  71. while (i--) {
  72. printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
  73. p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
  74. p += 8;
  75. }
  76. free(buf);
  77. return 0;
  78. }
  79. /* ------------------------------------------------------------------------- */
  80. static inline int str2long(char *p, ulong *num)
  81. {
  82. char *endptr;
  83. *num = simple_strtoul(p, &endptr, 16);
  84. return (*p != '\0' && *endptr == '\0') ? 1 : 0;
  85. }
  86. static int
  87. arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, ulong *size)
  88. {
  89. int idx = nand_curr_device;
  90. #if ((CONFIG_COMMANDS & CFG_CMD_JFFS2) || defined(CONFIG_CMD_JFFS2)) \
  91. && defined(CONFIG_JFFS2_CMDLINE)
  92. struct mtd_device *dev;
  93. struct part_info *part;
  94. u8 pnum;
  95. if (argc >= 1 && !(str2long(argv[0], off))) {
  96. if ((mtdparts_init() == 0) &&
  97. (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) {
  98. if (dev->id->type != MTD_DEV_TYPE_NAND) {
  99. puts("not a NAND device\n");
  100. return -1;
  101. }
  102. *off = part->offset;
  103. if (argc >= 2) {
  104. if (!(str2long(argv[1], size))) {
  105. printf("'%s' is not a number\n", argv[1]);
  106. return -1;
  107. }
  108. if (*size > part->size)
  109. *size = part->size;
  110. } else {
  111. *size = part->size;
  112. }
  113. idx = dev->id->num;
  114. *nand = nand_info[idx];
  115. goto out;
  116. }
  117. }
  118. #endif
  119. if (argc >= 1) {
  120. if (!(str2long(argv[0], off))) {
  121. printf("'%s' is not a number\n", argv[0]);
  122. return -1;
  123. }
  124. } else {
  125. *off = 0;
  126. }
  127. if (argc >= 2) {
  128. if (!(str2long(argv[1], size))) {
  129. printf("'%s' is not a number\n", argv[1]);
  130. return -1;
  131. }
  132. } else {
  133. *size = nand->size - *off;
  134. }
  135. #if ((CONFIG_COMMANDS & CFG_CMD_JFFS2) || defined(CONFIG_CMD_JFFS2)) \
  136. && defined(CONFIG_JFFS2_CMDLINE)
  137. out:
  138. #endif
  139. printf("device %d ", idx);
  140. if (*size == nand->size)
  141. puts("whole chip\n");
  142. else
  143. printf("offset 0x%x, size 0x%x\n", *off, *size);
  144. return 0;
  145. }
  146. int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
  147. {
  148. int i, dev, ret;
  149. ulong addr, off, size;
  150. char *cmd, *s;
  151. nand_info_t *nand;
  152. int quiet = 0;
  153. const char *quiet_str = getenv("quiet");
  154. /* at least two arguments please */
  155. if (argc < 2)
  156. goto usage;
  157. if (quiet_str)
  158. quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
  159. cmd = argv[1];
  160. if (strcmp(cmd, "info") == 0) {
  161. putc('\n');
  162. for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
  163. if (nand_info[i].name)
  164. printf("Device %d: %s, sector size %lu KiB\n",
  165. i, nand_info[i].name,
  166. nand_info[i].erasesize >> 10);
  167. }
  168. return 0;
  169. }
  170. if (strcmp(cmd, "device") == 0) {
  171. if (argc < 3) {
  172. if ((nand_curr_device < 0) ||
  173. (nand_curr_device >= CFG_MAX_NAND_DEVICE))
  174. puts("\nno devices available\n");
  175. else
  176. printf("\nDevice %d: %s\n", nand_curr_device,
  177. nand_info[nand_curr_device].name);
  178. return 0;
  179. }
  180. dev = (int)simple_strtoul(argv[2], NULL, 10);
  181. if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
  182. puts("No such device\n");
  183. return 1;
  184. }
  185. printf("Device %d: %s", dev, nand_info[dev].name);
  186. puts("... is now current device\n");
  187. nand_curr_device = dev;
  188. #ifdef CFG_NAND_SELECT_DEVICE
  189. /*
  190. * Select the chip in the board/cpu specific driver
  191. */
  192. board_nand_select_device(nand_info[dev].priv, dev);
  193. #endif
  194. return 0;
  195. }
  196. if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
  197. strncmp(cmd, "dump", 4) != 0 &&
  198. strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
  199. strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
  200. strcmp(cmd, "biterr") != 0 &&
  201. strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
  202. goto usage;
  203. /* the following commands operate on the current device */
  204. if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
  205. !nand_info[nand_curr_device].name) {
  206. puts("\nno devices available\n");
  207. return 1;
  208. }
  209. nand = &nand_info[nand_curr_device];
  210. if (strcmp(cmd, "bad") == 0) {
  211. printf("\nDevice %d bad blocks:\n", nand_curr_device);
  212. for (off = 0; off < nand->size; off += nand->erasesize)
  213. if (nand_block_isbad(nand, off))
  214. printf(" %08x\n", off);
  215. return 0;
  216. }
  217. /*
  218. * Syntax is:
  219. * 0 1 2 3 4
  220. * nand erase [clean] [off size]
  221. */
  222. if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
  223. nand_erase_options_t opts;
  224. /* "clean" at index 2 means request to write cleanmarker */
  225. int clean = argc > 2 && !strcmp("clean", argv[2]);
  226. int o = clean ? 3 : 2;
  227. int scrub = !strcmp(cmd, "scrub");
  228. printf("\nNAND %s: ", scrub ? "scrub" : "erase");
  229. /* skip first two or three arguments, look for offset and size */
  230. if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)
  231. return 1;
  232. memset(&opts, 0, sizeof(opts));
  233. opts.offset = off;
  234. opts.length = size;
  235. opts.jffs2 = clean;
  236. opts.quiet = quiet;
  237. if (scrub) {
  238. puts("Warning: "
  239. "scrub option will erase all factory set "
  240. "bad blocks!\n"
  241. " "
  242. "There is no reliable way to recover them.\n"
  243. " "
  244. "Use this command only for testing purposes "
  245. "if you\n"
  246. " "
  247. "are sure of what you are doing!\n"
  248. "\nReally scrub this NAND flash? <y/N>\n");
  249. if (getc() == 'y' && getc() == '\r') {
  250. opts.scrub = 1;
  251. } else {
  252. puts("scrub aborted\n");
  253. return -1;
  254. }
  255. }
  256. ret = nand_erase_opts(nand, &opts);
  257. printf("%s\n", ret ? "ERROR" : "OK");
  258. return ret == 0 ? 0 : 1;
  259. }
  260. if (strncmp(cmd, "dump", 4) == 0) {
  261. if (argc < 3)
  262. goto usage;
  263. s = strchr(cmd, '.');
  264. off = (int)simple_strtoul(argv[2], NULL, 16);
  265. if (s != NULL && strcmp(s, ".oob") == 0)
  266. ret = nand_dump_oob(nand, off);
  267. else
  268. ret = nand_dump(nand, off);
  269. return ret == 0 ? 1 : 0;
  270. }
  271. /* read write */
  272. if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
  273. int read;
  274. if (argc < 4)
  275. goto usage;
  276. addr = (ulong)simple_strtoul(argv[2], NULL, 16);
  277. read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
  278. printf("\nNAND %s: ", read ? "read" : "write");
  279. if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
  280. return 1;
  281. s = strchr(cmd, '.');
  282. if (s != NULL &&
  283. (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
  284. if (read) {
  285. /* read */
  286. nand_read_options_t opts;
  287. memset(&opts, 0, sizeof(opts));
  288. opts.buffer = (u_char*) addr;
  289. opts.length = size;
  290. opts.offset = off;
  291. opts.quiet = quiet;
  292. ret = nand_read_opts(nand, &opts);
  293. } else {
  294. /* write */
  295. nand_write_options_t opts;
  296. memset(&opts, 0, sizeof(opts));
  297. opts.buffer = (u_char*) addr;
  298. opts.length = size;
  299. opts.offset = off;
  300. /* opts.forcejffs2 = 1; */
  301. opts.pad = 1;
  302. opts.blockalign = 1;
  303. opts.quiet = quiet;
  304. ret = nand_write_opts(nand, &opts);
  305. }
  306. } else {
  307. if (read)
  308. ret = nand_read(nand, off, &size, (u_char *)addr);
  309. else
  310. ret = nand_write(nand, off, &size, (u_char *)addr);
  311. }
  312. printf(" %d bytes %s: %s\n", size,
  313. read ? "read" : "written", ret ? "ERROR" : "OK");
  314. return ret == 0 ? 0 : 1;
  315. }
  316. if (strcmp(cmd, "markbad") == 0) {
  317. addr = (ulong)simple_strtoul(argv[2], NULL, 16);
  318. int ret = nand->block_markbad(nand, addr);
  319. if (ret == 0) {
  320. printf("block 0x%08lx successfully marked as bad\n",
  321. (ulong) addr);
  322. return 0;
  323. } else {
  324. printf("block 0x%08lx NOT marked as bad! ERROR %d\n",
  325. (ulong) addr, ret);
  326. }
  327. return 1;
  328. }
  329. if (strcmp(cmd, "biterr") == 0) {
  330. /* todo */
  331. return 1;
  332. }
  333. if (strcmp(cmd, "lock") == 0) {
  334. int tight = 0;
  335. int status = 0;
  336. if (argc == 3) {
  337. if (!strcmp("tight", argv[2]))
  338. tight = 1;
  339. if (!strcmp("status", argv[2]))
  340. status = 1;
  341. }
  342. if (status) {
  343. ulong block_start = 0;
  344. ulong off;
  345. int last_status = -1;
  346. struct nand_chip *nand_chip = nand->priv;
  347. /* check the WP bit */
  348. nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1);
  349. printf("device is %swrite protected\n",
  350. (nand_chip->read_byte(nand) & 0x80 ?
  351. "NOT " : "" ) );
  352. for (off = 0; off < nand->size; off += nand->oobblock) {
  353. int s = nand_get_lock_status(nand, off);
  354. /* print message only if status has changed
  355. * or at end of chip
  356. */
  357. if (off == nand->size - nand->oobblock
  358. || (s != last_status && off != 0)) {
  359. printf("%08x - %08x: %8d pages %s%s%s\n",
  360. block_start,
  361. off-1,
  362. (off-block_start)/nand->oobblock,
  363. ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
  364. ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""),
  365. ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
  366. }
  367. last_status = s;
  368. }
  369. } else {
  370. if (!nand_lock(nand, tight)) {
  371. puts("NAND flash successfully locked\n");
  372. } else {
  373. puts("Error locking NAND flash\n");
  374. return 1;
  375. }
  376. }
  377. return 0;
  378. }
  379. if (strcmp(cmd, "unlock") == 0) {
  380. if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0)
  381. return 1;
  382. if (!nand_unlock(nand, off, size)) {
  383. puts("NAND flash successfully unlocked\n");
  384. } else {
  385. puts("Error unlocking NAND flash, "
  386. "write and erase will probably fail\n");
  387. return 1;
  388. }
  389. return 0;
  390. }
  391. usage:
  392. printf("Usage:\n%s\n", cmdtp->usage);
  393. return 1;
  394. }
  395. U_BOOT_CMD(nand, 5, 1, do_nand,
  396. "nand - NAND sub-system\n",
  397. "info - show available NAND devices\n"
  398. "nand device [dev] - show or set current device\n"
  399. "nand read[.jffs2] - addr off|partition size\n"
  400. "nand write[.jffs2] - addr off|partiton size - read/write `size' bytes starting\n"
  401. " at offset `off' to/from memory address `addr'\n"
  402. "nand erase [clean] [off size] - erase `size' bytes from\n"
  403. " offset `off' (entire device if not specified)\n"
  404. "nand bad - show bad blocks\n"
  405. "nand dump[.oob] off - dump page\n"
  406. "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
  407. "nand markbad off - mark bad block at offset (UNSAFE)\n"
  408. "nand biterr off - make a bit error at offset (UNSAFE)\n"
  409. "nand lock [tight] [status] - bring nand to lock state or display locked pages\n"
  410. "nand unlock [offset] [size] - unlock section\n");
  411. static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
  412. ulong offset, ulong addr, char *cmd)
  413. {
  414. int r;
  415. char *ep;
  416. ulong cnt;
  417. image_header_t *hdr;
  418. printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
  419. cnt = nand->oobblock;
  420. r = nand_read(nand, offset, &cnt, (u_char *) addr);
  421. if (r) {
  422. puts("** Read error\n");
  423. SHOW_BOOT_PROGRESS(-1);
  424. return 1;
  425. }
  426. hdr = (image_header_t *) addr;
  427. if (ntohl(hdr->ih_magic) != IH_MAGIC) {
  428. printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
  429. SHOW_BOOT_PROGRESS(-1);
  430. return 1;
  431. }
  432. print_image_hdr(hdr);
  433. cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
  434. r = nand_read(nand, offset, &cnt, (u_char *) addr);
  435. if (r) {
  436. puts("** Read error\n");
  437. SHOW_BOOT_PROGRESS(-1);
  438. return 1;
  439. }
  440. /* Loading ok, update default load address */
  441. load_addr = addr;
  442. /* Check if we should attempt an auto-start */
  443. if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
  444. char *local_args[2];
  445. extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
  446. local_args[0] = cmd;
  447. local_args[1] = NULL;
  448. printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
  449. do_bootm(cmdtp, 0, 1, local_args);
  450. return 1;
  451. }
  452. return 0;
  453. }
  454. int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
  455. {
  456. char *boot_device = NULL;
  457. int idx;
  458. ulong addr, offset = 0;
  459. #if ((CONFIG_COMMANDS & CFG_CMD_JFFS2) || defined(CONFIG_CMD_JFFS2)) \
  460. && defined(CONFIG_JFFS2_CMDLINE)
  461. struct mtd_device *dev;
  462. struct part_info *part;
  463. u8 pnum;
  464. if (argc >= 2) {
  465. char *p = (argc == 2) ? argv[1] : argv[2];
  466. if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
  467. (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
  468. if (dev->id->type != MTD_DEV_TYPE_NAND) {
  469. puts("Not a NAND device\n");
  470. return 1;
  471. }
  472. if (argc > 3)
  473. goto usage;
  474. if (argc == 3)
  475. addr = simple_strtoul(argv[2], NULL, 16);
  476. else
  477. addr = CFG_LOAD_ADDR;
  478. return nand_load_image(cmdtp, &nand_info[dev->id->num],
  479. part->offset, addr, argv[0]);
  480. }
  481. }
  482. #endif
  483. switch (argc) {
  484. case 1:
  485. addr = CFG_LOAD_ADDR;
  486. boot_device = getenv("bootdevice");
  487. break;
  488. case 2:
  489. addr = simple_strtoul(argv[1], NULL, 16);
  490. boot_device = getenv("bootdevice");
  491. break;
  492. case 3:
  493. addr = simple_strtoul(argv[1], NULL, 16);
  494. boot_device = argv[2];
  495. break;
  496. case 4:
  497. addr = simple_strtoul(argv[1], NULL, 16);
  498. boot_device = argv[2];
  499. offset = simple_strtoul(argv[3], NULL, 16);
  500. break;
  501. default:
  502. #if ((CONFIG_COMMANDS & CFG_CMD_JFFS2) || defined(CONFIG_CMD_JFFS2)) \
  503. && defined(CONFIG_JFFS2_CMDLINE)
  504. usage:
  505. #endif
  506. printf("Usage:\n%s\n", cmdtp->usage);
  507. SHOW_BOOT_PROGRESS(-1);
  508. return 1;
  509. }
  510. if (!boot_device) {
  511. puts("\n** No boot device **\n");
  512. SHOW_BOOT_PROGRESS(-1);
  513. return 1;
  514. }
  515. idx = simple_strtoul(boot_device, NULL, 16);
  516. if (idx < 0 || idx >= CFG_MAX_NAND_DEVICE || !nand_info[idx].name) {
  517. printf("\n** Device %d not available\n", idx);
  518. SHOW_BOOT_PROGRESS(-1);
  519. return 1;
  520. }
  521. return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
  522. }
  523. U_BOOT_CMD(nboot, 4, 1, do_nandboot,
  524. "nboot - boot from NAND device\n",
  525. "[partition] | [[[loadAddr] dev] offset]\n");
  526. #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
  527. #else /* CFG_NAND_LEGACY */
  528. /*
  529. *
  530. * Legacy NAND support - to be phased out
  531. *
  532. */
  533. #include <command.h>
  534. #include <malloc.h>
  535. #include <asm/io.h>
  536. #include <watchdog.h>
  537. #ifdef CONFIG_SHOW_BOOT_PROGRESS
  538. # include <status_led.h>
  539. # define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
  540. #else
  541. # define SHOW_BOOT_PROGRESS(arg)
  542. #endif
  543. #if (CONFIG_COMMANDS & CFG_CMD_NAND) || defined(CONFIG_CMD_NAND)
  544. #include <linux/mtd/nand_legacy.h>
  545. #if 0
  546. #include <linux/mtd/nand_ids.h>
  547. #include <jffs2/jffs2.h>
  548. #endif
  549. #ifdef CONFIG_OMAP1510
  550. void archflashwp(void *archdata, int wp);
  551. #endif
  552. #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
  553. #undef NAND_DEBUG
  554. #undef PSYCHO_DEBUG
  555. /* ****************** WARNING *********************
  556. * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
  557. * erase (or at least attempt to erase) blocks that are marked
  558. * bad. This can be very handy if you are _sure_ that the block
  559. * is OK, say because you marked a good block bad to test bad
  560. * block handling and you are done testing, or if you have
  561. * accidentally marked blocks bad.
  562. *
  563. * Erasing factory marked bad blocks is a _bad_ idea. If the
  564. * erase succeeds there is no reliable way to find them again,
  565. * and attempting to program or erase bad blocks can affect
  566. * the data in _other_ (good) blocks.
  567. */
  568. #define ALLOW_ERASE_BAD_DEBUG 0
  569. #define CONFIG_MTD_NAND_ECC /* enable ECC */
  570. #define CONFIG_MTD_NAND_ECC_JFFS2
  571. /* bits for nand_legacy_rw() `cmd'; or together as needed */
  572. #define NANDRW_READ 0x01
  573. #define NANDRW_WRITE 0x00
  574. #define NANDRW_JFFS2 0x02
  575. #define NANDRW_JFFS2_SKIP 0x04
  576. /*
  577. * Imports from nand_legacy.c
  578. */
  579. extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
  580. extern int curr_device;
  581. extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs,
  582. size_t len, int clean);
  583. extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start,
  584. size_t len, size_t *retlen, u_char *buf);
  585. extern void nand_print(struct nand_chip *nand);
  586. extern void nand_print_bad(struct nand_chip *nand);
  587. extern int nand_read_oob(struct nand_chip *nand, size_t ofs,
  588. size_t len, size_t *retlen, u_char *buf);
  589. extern int nand_write_oob(struct nand_chip *nand, size_t ofs,
  590. size_t len, size_t *retlen, const u_char *buf);
  591. int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
  592. {
  593. int rcode = 0;
  594. switch (argc) {
  595. case 0:
  596. case 1:
  597. printf ("Usage:\n%s\n", cmdtp->usage);
  598. return 1;
  599. case 2:
  600. if (strcmp (argv[1], "info") == 0) {
  601. int i;
  602. putc ('\n');
  603. for (i = 0; i < CFG_MAX_NAND_DEVICE; ++i) {
  604. if (nand_dev_desc[i].ChipID ==
  605. NAND_ChipID_UNKNOWN)
  606. continue; /* list only known devices */
  607. printf ("Device %d: ", i);
  608. nand_print (&nand_dev_desc[i]);
  609. }
  610. return 0;
  611. } else if (strcmp (argv[1], "device") == 0) {
  612. if ((curr_device < 0)
  613. || (curr_device >= CFG_MAX_NAND_DEVICE)) {
  614. puts ("\nno devices available\n");
  615. return 1;
  616. }
  617. printf ("\nDevice %d: ", curr_device);
  618. nand_print (&nand_dev_desc[curr_device]);
  619. return 0;
  620. } else if (strcmp (argv[1], "bad") == 0) {
  621. if ((curr_device < 0)
  622. || (curr_device >= CFG_MAX_NAND_DEVICE)) {
  623. puts ("\nno devices available\n");
  624. return 1;
  625. }
  626. printf ("\nDevice %d bad blocks:\n", curr_device);
  627. nand_print_bad (&nand_dev_desc[curr_device]);
  628. return 0;
  629. }
  630. printf ("Usage:\n%s\n", cmdtp->usage);
  631. return 1;
  632. case 3:
  633. if (strcmp (argv[1], "device") == 0) {
  634. int dev = (int) simple_strtoul (argv[2], NULL, 10);
  635. printf ("\nDevice %d: ", dev);
  636. if (dev >= CFG_MAX_NAND_DEVICE) {
  637. puts ("unknown device\n");
  638. return 1;
  639. }
  640. nand_print (&nand_dev_desc[dev]);
  641. /*nand_print (dev); */
  642. if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
  643. return 1;
  644. }
  645. curr_device = dev;
  646. puts ("... is now current device\n");
  647. return 0;
  648. } else if (strcmp (argv[1], "erase") == 0
  649. && strcmp (argv[2], "clean") == 0) {
  650. struct nand_chip *nand = &nand_dev_desc[curr_device];
  651. ulong off = 0;
  652. ulong size = nand->totlen;
  653. int ret;
  654. printf ("\nNAND erase: device %d offset %ld, size %ld ... ", curr_device, off, size);
  655. ret = nand_legacy_erase (nand, off, size, 1);
  656. printf ("%s\n", ret ? "ERROR" : "OK");
  657. return ret;
  658. }
  659. printf ("Usage:\n%s\n", cmdtp->usage);
  660. return 1;
  661. default:
  662. /* at least 4 args */
  663. if (strncmp (argv[1], "read", 4) == 0 ||
  664. strncmp (argv[1], "write", 5) == 0) {
  665. ulong addr = simple_strtoul (argv[2], NULL, 16);
  666. ulong off = simple_strtoul (argv[3], NULL, 16);
  667. ulong size = simple_strtoul (argv[4], NULL, 16);
  668. int cmd = (strncmp (argv[1], "read", 4) == 0) ?
  669. NANDRW_READ : NANDRW_WRITE;
  670. int ret, total;
  671. char *cmdtail = strchr (argv[1], '.');
  672. if (cmdtail && !strncmp (cmdtail, ".oob", 2)) {
  673. /* read out-of-band data */
  674. if (cmd & NANDRW_READ) {
  675. ret = nand_read_oob (nand_dev_desc + curr_device,
  676. off, size, (size_t *) & total,
  677. (u_char *) addr);
  678. } else {
  679. ret = nand_write_oob (nand_dev_desc + curr_device,
  680. off, size, (size_t *) & total,
  681. (u_char *) addr);
  682. }
  683. return ret;
  684. } else if (cmdtail && !strncmp (cmdtail, ".jffs2", 2))
  685. cmd |= NANDRW_JFFS2; /* skip bad blocks */
  686. else if (cmdtail && !strncmp (cmdtail, ".jffs2s", 2)) {
  687. cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */
  688. if (cmd & NANDRW_READ)
  689. cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */
  690. }
  691. #ifdef SXNI855T
  692. /* need ".e" same as ".j" for compatibility with older units */
  693. else if (cmdtail && !strcmp (cmdtail, ".e"))
  694. cmd |= NANDRW_JFFS2; /* skip bad blocks */
  695. #endif
  696. #ifdef CFG_NAND_SKIP_BAD_DOT_I
  697. /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */
  698. /* ".i" for image -> read skips bad block (no 0xff) */
  699. else if (cmdtail && !strcmp (cmdtail, ".i")) {
  700. cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */
  701. if (cmd & NANDRW_READ)
  702. cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */
  703. }
  704. #endif /* CFG_NAND_SKIP_BAD_DOT_I */
  705. else if (cmdtail) {
  706. printf ("Usage:\n%s\n", cmdtp->usage);
  707. return 1;
  708. }
  709. printf ("\nNAND %s: device %d offset %ld, size %ld ...\n",
  710. (cmd & NANDRW_READ) ? "read" : "write",
  711. curr_device, off, size);
  712. ret = nand_legacy_rw (nand_dev_desc + curr_device,
  713. cmd, off, size,
  714. (size_t *) & total,
  715. (u_char *) addr);
  716. printf (" %d bytes %s: %s\n", total,
  717. (cmd & NANDRW_READ) ? "read" : "written",
  718. ret ? "ERROR" : "OK");
  719. return ret;
  720. } else if (strcmp (argv[1], "erase") == 0 &&
  721. (argc == 4 || strcmp ("clean", argv[2]) == 0)) {
  722. int clean = argc == 5;
  723. ulong off =
  724. simple_strtoul (argv[2 + clean], NULL, 16);
  725. ulong size =
  726. simple_strtoul (argv[3 + clean], NULL, 16);
  727. int ret;
  728. printf ("\nNAND erase: device %d offset %ld, size %ld ...\n",
  729. curr_device, off, size);
  730. ret = nand_legacy_erase (nand_dev_desc + curr_device,
  731. off, size, clean);
  732. printf ("%s\n", ret ? "ERROR" : "OK");
  733. return ret;
  734. } else {
  735. printf ("Usage:\n%s\n", cmdtp->usage);
  736. rcode = 1;
  737. }
  738. return rcode;
  739. }
  740. }
  741. U_BOOT_CMD(
  742. nand, 5, 1, do_nand,
  743. "nand - legacy NAND sub-system\n",
  744. "info - show available NAND devices\n"
  745. "nand device [dev] - show or set current device\n"
  746. "nand read[.jffs2[s]] addr off size\n"
  747. "nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
  748. " at offset `off' to/from memory address `addr'\n"
  749. "nand erase [clean] [off size] - erase `size' bytes from\n"
  750. " offset `off' (entire device if not specified)\n"
  751. "nand bad - show bad blocks\n"
  752. "nand read.oob addr off size - read out-of-band data\n"
  753. "nand write.oob addr off size - read out-of-band data\n"
  754. );
  755. int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  756. {
  757. char *boot_device = NULL;
  758. char *ep;
  759. int dev;
  760. ulong cnt;
  761. ulong addr;
  762. ulong offset = 0;
  763. image_header_t *hdr;
  764. int rcode = 0;
  765. switch (argc) {
  766. case 1:
  767. addr = CFG_LOAD_ADDR;
  768. boot_device = getenv ("bootdevice");
  769. break;
  770. case 2:
  771. addr = simple_strtoul(argv[1], NULL, 16);
  772. boot_device = getenv ("bootdevice");
  773. break;
  774. case 3:
  775. addr = simple_strtoul(argv[1], NULL, 16);
  776. boot_device = argv[2];
  777. break;
  778. case 4:
  779. addr = simple_strtoul(argv[1], NULL, 16);
  780. boot_device = argv[2];
  781. offset = simple_strtoul(argv[3], NULL, 16);
  782. break;
  783. default:
  784. printf ("Usage:\n%s\n", cmdtp->usage);
  785. SHOW_BOOT_PROGRESS (-1);
  786. return 1;
  787. }
  788. if (!boot_device) {
  789. puts ("\n** No boot device **\n");
  790. SHOW_BOOT_PROGRESS (-1);
  791. return 1;
  792. }
  793. dev = simple_strtoul(boot_device, &ep, 16);
  794. if ((dev >= CFG_MAX_NAND_DEVICE) ||
  795. (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
  796. printf ("\n** Device %d not available\n", dev);
  797. SHOW_BOOT_PROGRESS (-1);
  798. return 1;
  799. }
  800. printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
  801. dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
  802. offset);
  803. if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
  804. SECTORSIZE, NULL, (u_char *)addr)) {
  805. printf ("** Read error on %d\n", dev);
  806. SHOW_BOOT_PROGRESS (-1);
  807. return 1;
  808. }
  809. hdr = (image_header_t *)addr;
  810. if (ntohl(hdr->ih_magic) == IH_MAGIC) {
  811. print_image_hdr (hdr);
  812. cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
  813. cnt -= SECTORSIZE;
  814. } else {
  815. printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic));
  816. SHOW_BOOT_PROGRESS (-1);
  817. return 1;
  818. }
  819. if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
  820. offset + SECTORSIZE, cnt, NULL,
  821. (u_char *)(addr+SECTORSIZE))) {
  822. printf ("** Read error on %d\n", dev);
  823. SHOW_BOOT_PROGRESS (-1);
  824. return 1;
  825. }
  826. /* Loading ok, update default load address */
  827. load_addr = addr;
  828. /* Check if we should attempt an auto-start */
  829. if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
  830. char *local_args[2];
  831. extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
  832. local_args[0] = argv[0];
  833. local_args[1] = NULL;
  834. printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
  835. do_bootm (cmdtp, 0, 1, local_args);
  836. rcode = 1;
  837. }
  838. return rcode;
  839. }
  840. U_BOOT_CMD(
  841. nboot, 4, 1, do_nandboot,
  842. "nboot - boot from NAND device\n",
  843. "loadAddr dev\n"
  844. );
  845. #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
  846. #endif /* CFG_NAND_LEGACY */