+#else /* CFG_NAND_LEGACY */
+/*
+ *
+ * Legacy NAND support - to be phased out
+ *
+ */
+#include <command.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <watchdog.h>
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+#include <linux/mtd/nand_legacy.h>
+#if 0
+#include <linux/mtd/nand_ids.h>
+#include <jffs2/jffs2.h>
+#endif
+
+#ifdef CONFIG_OMAP1510
+void archflashwp(void *archdata, int wp);
+#endif
+
+#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
+
+#undef NAND_DEBUG
+#undef PSYCHO_DEBUG
+
+/* ****************** WARNING *********************
+ * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
+ * erase (or at least attempt to erase) blocks that are marked
+ * bad. This can be very handy if you are _sure_ that the block
+ * is OK, say because you marked a good block bad to test bad
+ * block handling and you are done testing, or if you have
+ * accidentally marked blocks bad.
+ *
+ * Erasing factory marked bad blocks is a _bad_ idea. If the
+ * erase succeeds there is no reliable way to find them again,
+ * and attempting to program or erase bad blocks can affect
+ * the data in _other_ (good) blocks.
+ */
+#define ALLOW_ERASE_BAD_DEBUG 0
+
+#define CONFIG_MTD_NAND_ECC /* enable ECC */
+#define CONFIG_MTD_NAND_ECC_JFFS2
+
+/* bits for nand_legacy_rw() `cmd'; or together as needed */
+#define NANDRW_READ 0x01
+#define NANDRW_WRITE 0x00
+#define NANDRW_JFFS2 0x02
+#define NANDRW_JFFS2_SKIP 0x04
+
+/*
+ * Imports from nand_legacy.c
+ */
+extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
+extern int curr_device;
+extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs,
+ size_t len, int clean);
+extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start,
+ size_t len, size_t *retlen, u_char *buf);
+extern void nand_print(struct nand_chip *nand);
+extern void nand_print_bad(struct nand_chip *nand);
+extern int nand_read_oob(struct nand_chip *nand, size_t ofs,
+ size_t len, size_t *retlen, u_char *buf);
+extern int nand_write_oob(struct nand_chip *nand, size_t ofs,
+ size_t len, size_t *retlen, const u_char *buf);
+
+
+int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int rcode = 0;
+
+ switch (argc) {
+ case 0:
+ case 1:
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ case 2:
+ if (strcmp(argv[1],"info") == 0) {
+ int i;
+
+ putc ('\n');
+
+ for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {
+ if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)
+ continue; /* list only known devices */
+ printf ("Device %d: ", i);
+ nand_print(&nand_dev_desc[i]);
+ }
+ return 0;
+
+ } else if (strcmp(argv[1],"device") == 0) {
+ if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
+ puts ("\nno devices available\n");
+ return 1;
+ }
+ printf ("\nDevice %d: ", curr_device);
+ nand_print(&nand_dev_desc[curr_device]);
+ return 0;
+
+ } else if (strcmp(argv[1],"bad") == 0) {
+ if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
+ puts ("\nno devices available\n");
+ return 1;
+ }
+ printf ("\nDevice %d bad blocks:\n", curr_device);
+ nand_print_bad(&nand_dev_desc[curr_device]);
+ return 0;
+
+ }
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ case 3:
+ if (strcmp(argv[1],"device") == 0) {
+ int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+ printf ("\nDevice %d: ", dev);
+ if (dev >= CFG_MAX_NAND_DEVICE) {
+ puts ("unknown device\n");
+ return 1;
+ }
+ nand_print(&nand_dev_desc[dev]);
+ /*nand_print (dev);*/
+
+ if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
+ return 1;
+ }
+
+ curr_device = dev;
+
+ puts ("... is now current device\n");
+
+ return 0;
+ }
+ else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
+ struct nand_chip* nand = &nand_dev_desc[curr_device];
+ ulong off = 0;
+ ulong size = nand->totlen;
+ int ret;
+
+ printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
+ curr_device, off, size);
+
+ ret = nand_legacy_erase (nand, off, size, 1);
+
+ printf("%s\n", ret ? "ERROR" : "OK");
+
+ return ret;
+ }
+
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ default:
+ /* at least 4 args */
+
+ if (strncmp(argv[1], "read", 4) == 0 ||
+ strncmp(argv[1], "write", 5) == 0) {
+ ulong addr = simple_strtoul(argv[2], NULL, 16);
+ ulong off = simple_strtoul(argv[3], NULL, 16);
+ ulong size = simple_strtoul(argv[4], NULL, 16);
+ int cmd = (strncmp(argv[1], "read", 4) == 0) ?
+ NANDRW_READ : NANDRW_WRITE;
+ int ret, total;
+ char* cmdtail = strchr(argv[1], '.');
+
+ if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
+ /* read out-of-band data */
+ if (cmd & NANDRW_READ) {
+ ret = nand_read_oob(nand_dev_desc + curr_device,
+ off, size, (size_t *)&total,
+ (u_char*)addr);
+ }
+ else {
+ ret = nand_write_oob(nand_dev_desc + curr_device,
+ off, size, (size_t *)&total,
+ (u_char*)addr);
+ }
+ return ret;
+ }
+ else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
+ cmd |= NANDRW_JFFS2; /* skip bad blocks */
+ else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) {
+ cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */
+ if (cmd & NANDRW_READ)
+ cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */
+ }
+#ifdef SXNI855T
+ /* need ".e" same as ".j" for compatibility with older units */
+ else if (cmdtail && !strcmp(cmdtail, ".e"))
+ cmd |= NANDRW_JFFS2; /* skip bad blocks */
+#endif
+#ifdef CFG_NAND_SKIP_BAD_DOT_I
+ /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */
+ /* ".i" for image -> read skips bad block (no 0xff) */
+ else if (cmdtail && !strcmp(cmdtail, ".i")) {
+ cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */
+ if (cmd & NANDRW_READ)
+ cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */
+ }
+#endif /* CFG_NAND_SKIP_BAD_DOT_I */
+ else if (cmdtail) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ printf ("\nNAND %s: device %d offset %ld, size %ld ...\n",
+ (cmd & NANDRW_READ) ? "read" : "write",
+ curr_device, off, size);
+
+ ret = nand_legacy_rw(nand_dev_desc + curr_device, cmd, off, size,
+ (size_t *)&total, (u_char*)addr);
+
+ printf (" %d bytes %s: %s\n", total,
+ (cmd & NANDRW_READ) ? "read" : "written",
+ ret ? "ERROR" : "OK");
+
+ return ret;
+ } else if (strcmp(argv[1],"erase") == 0 &&
+ (argc == 4 || strcmp("clean", argv[2]) == 0)) {
+ int clean = argc == 5;
+ ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
+ ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
+ int ret;
+
+ printf ("\nNAND erase: device %d offset %ld, size %ld ...\n",
+ curr_device, off, size);
+
+ ret = nand_legacy_erase (nand_dev_desc + curr_device,
+ off, size, clean);
+
+ printf("%s\n", ret ? "ERROR" : "OK");
+
+ return ret;
+ } else {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ rcode = 1;
+ }
+
+ return rcode;
+ }
+}
+
+U_BOOT_CMD(
+ nand, 5, 1, do_nand,
+ "nand - legacy NAND sub-system\n",
+ "info - show available NAND devices\n"
+ "nand device [dev] - show or set current device\n"
+ "nand read[.jffs2[s]] addr off size\n"
+ "nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
+ " at offset `off' to/from memory address `addr'\n"
+ "nand erase [clean] [off size] - erase `size' bytes from\n"
+ " offset `off' (entire device if not specified)\n"
+ "nand bad - show bad blocks\n"
+ "nand read.oob addr off size - read out-of-band data\n"
+ "nand write.oob addr off size - read out-of-band data\n"
+);
+
+int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *boot_device = NULL;
+ char *ep;
+ int dev;
+ ulong cnt;
+ ulong addr;
+ ulong offset = 0;
+ image_header_t *hdr;
+ int rcode = 0;
+ switch (argc) {
+ case 1:
+ addr = CFG_LOAD_ADDR;
+ boot_device = getenv ("bootdevice");
+ break;
+ case 2:
+ addr = simple_strtoul(argv[1], NULL, 16);
+ boot_device = getenv ("bootdevice");
+ break;
+ case 3:
+ addr = simple_strtoul(argv[1], NULL, 16);
+ boot_device = argv[2];
+ break;
+ case 4:
+ addr = simple_strtoul(argv[1], NULL, 16);
+ boot_device = argv[2];
+ offset = simple_strtoul(argv[3], NULL, 16);
+ break;
+ default:
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ SHOW_BOOT_PROGRESS (-1);
+ return 1;
+ }
+
+ if (!boot_device) {
+ puts ("\n** No boot device **\n");
+ SHOW_BOOT_PROGRESS (-1);
+ return 1;
+ }
+
+ dev = simple_strtoul(boot_device, &ep, 16);
+
+ if ((dev >= CFG_MAX_NAND_DEVICE) ||
+ (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
+ printf ("\n** Device %d not available\n", dev);
+ SHOW_BOOT_PROGRESS (-1);
+ return 1;
+ }
+
+ printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
+ dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
+ offset);
+
+ if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
+ SECTORSIZE, NULL, (u_char *)addr)) {
+ printf ("** Read error on %d\n", dev);
+ SHOW_BOOT_PROGRESS (-1);
+ return 1;
+ }
+
+ hdr = (image_header_t *)addr;
+
+ if (ntohl(hdr->ih_magic) == IH_MAGIC) {
+
+ print_image_hdr (hdr);
+
+ cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
+ cnt -= SECTORSIZE;
+ } else {
+ printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic));
+ SHOW_BOOT_PROGRESS (-1);
+ return 1;
+ }
+
+ if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
+ offset + SECTORSIZE, cnt, NULL,
+ (u_char *)(addr+SECTORSIZE))) {
+ printf ("** Read error on %d\n", dev);
+ SHOW_BOOT_PROGRESS (-1);
+ return 1;
+ }
+
+ /* Loading ok, update default load address */
+
+ load_addr = addr;
+
+ /* Check if we should attempt an auto-start */
+ if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
+ char *local_args[2];
+ extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
+
+ local_args[0] = argv[0];
+ local_args[1] = NULL;
+
+ printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
+
+ do_bootm (cmdtp, 0, 1, local_args);
+ rcode = 1;
+ }
+ return rcode;
+}
+
+U_BOOT_CMD(
+ nboot, 4, 1, do_nandboot,
+ "nboot - boot from NAND device\n",
+ "loadAddr dev\n"
+);
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
+
+#endif /* CFG_NAND_LEGACY */