mx5 clocks: Fix MXC_FEC_CLK
[oweals/u-boot.git] / common / cmd_nand.c
index 0fd3a6c414aa9c35f13a8ec1a9bd60d4614634df..e24ed7f9c4a9afa50d29f914e689ab1518d95dc8 100644 (file)
@@ -11,7 +11,7 @@
  * Added 16-bit nand support
  * (C) 2004 Texas Instruments
  *
- * Copyright 2010 Freescale Semiconductor
+ * Copyright 2010, 2012 Freescale Semiconductor
  * The portions of this file whose copyright is held by Freescale and which
  * are not considered a derived work of GPL v2-only code may be distributed
  * and/or modified under the terms of the GNU General Public License as
@@ -48,8 +48,8 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
 
        last = off;
 
-       datbuf = malloc(nand->writesize);
-       oobbuf = malloc(nand->oobsize);
+       datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize);
+       oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize);
        if (!datbuf || !oobbuf) {
                puts("No memory for page buffer\n");
                return 1;
@@ -231,12 +231,18 @@ print:
 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 static void print_status(ulong start, ulong end, ulong erasesize, int status)
 {
+       /*
+        * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
+        * not the same as others.  Instead of bit 1 being lock, it is
+        * #lock_tight. To make the driver support either format, ignore bit 1
+        * and use only bit 0 and bit 2.
+        */
        printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
                start,
                end - 1,
                (end - start) / erasesize,
                ((status & NAND_LOCK_STATUS_TIGHT) ?  "TIGHT " : ""),
-               ((status & NAND_LOCK_STATUS_LOCK) ?  "LOCK " : ""),
+               (!(status & NAND_LOCK_STATUS_UNLOCK) ?  "LOCK " : ""),
                ((status & NAND_LOCK_STATUS_UNLOCK) ?  "UNLOCK " : ""));
 }
 
@@ -390,6 +396,39 @@ static void nand_print_and_set_info(int idx)
        setenv("nand_erasesize", buf);
 }
 
+static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
+                       int read)
+{
+       int ret = 0;
+
+       while (count--) {
+               /* Raw access */
+               mtd_oob_ops_t ops = {
+                       .datbuf = (u8 *)addr,
+                       .oobbuf = ((u8 *)addr) + nand->writesize,
+                       .len = nand->writesize,
+                       .ooblen = nand->oobsize,
+                       .mode = MTD_OOB_RAW
+               };
+
+               if (read)
+                       ret = nand->read_oob(nand, off, &ops);
+               else
+                       ret = nand->write_oob(nand, off, &ops);
+
+               if (ret) {
+                       printf("%s: error at offset %llx, ret %d\n",
+                               __func__, (long long)off, ret);
+                       break;
+               }
+
+               addr += nand->writesize + nand->oobsize;
+               off += nand->writesize;
+       }
+
+       return ret;
+}
+
 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
        int i, ret = 0;
@@ -568,7 +607,9 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 
        if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
                size_t rwsize;
+               ulong pagecount = 1;
                int read;
+               int raw;
 
                if (argc < 4)
                        goto usage;
@@ -577,13 +618,36 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 
                read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
                printf("\nNAND %s: ", read ? "read" : "write");
-               if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0)
-                       return 1;
 
                nand = &nand_info[dev];
-               rwsize = size;
 
                s = strchr(cmd, '.');
+
+               if (s && !strcmp(s, ".raw")) {
+                       raw = 1;
+
+                       if (arg_off(argv[3], &dev, &off, &size))
+                               return 1;
+
+                       if (argc > 4 && !str2long(argv[4], &pagecount)) {
+                               printf("'%s' is not a number\n", argv[4]);
+                               return 1;
+                       }
+
+                       if (pagecount * nand->writesize > size) {
+                               puts("Size exceeds partition or device limit\n");
+                               return -1;
+                       }
+
+                       rwsize = pagecount * (nand->writesize + nand->oobsize);
+               } else {
+                       if (arg_off_size(argc - 3, argv + 3, &dev,
+                                               &off, &size) != 0)
+                               return 1;
+
+                       rwsize = size;
+               }
+
                if (!s || !strcmp(s, ".jffs2") ||
                    !strcmp(s, ".e") || !strcmp(s, ".i")) {
                        if (read)
@@ -609,7 +673,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                                return 1;
                        }
                        ret = nand_write_skip_bad(nand, off, &rwsize,
-                                               (u_char *)addr, WITH_YAFFS_OOB);
+                                               (u_char *)addr,
+                                               WITH_INLINE_OOB);
 #endif
                } else if (!strcmp(s, ".oob")) {
                        /* out-of-band data */
@@ -623,22 +688,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                                ret = nand->read_oob(nand, off, &ops);
                        else
                                ret = nand->write_oob(nand, off, &ops);
-               } else if (!strcmp(s, ".raw")) {
-                       /* Raw access */
-                       mtd_oob_ops_t ops = {
-                               .datbuf = (u8 *)addr,
-                               .oobbuf = ((u8 *)addr) + nand->writesize,
-                               .len = nand->writesize,
-                               .ooblen = nand->oobsize,
-                               .mode = MTD_OOB_RAW
-                       };
-
-                       rwsize = nand->writesize + nand->oobsize;
-
-                       if (read)
-                               ret = nand->read_oob(nand, off, &ops);
-                       else
-                               ret = nand->write_oob(nand, off, &ops);
+               } else if (raw) {
+                       ret = raw_access(nand, addr, off, pagecount, read);
                } else {
                        printf("Unknown nand command suffix '%s'.\n", s);
                        return 1;
@@ -704,11 +755,18 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
                return 0;
        }
 
-       if (strcmp(cmd, "unlock") == 0) {
+       if (strncmp(cmd, "unlock", 5) == 0) {
+               int allexcept = 0;
+
+               s = strchr(cmd, '.');
+
+               if (s && !strcmp(s, ".allexcept"))
+                       allexcept = 1;
+
                if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0)
                        return 1;
 
-               if (!nand_unlock(&nand_info[dev], off, size)) {
+               if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
                        puts("NAND flash successfully unlocked\n");
                } else {
                        puts("Error unlocking NAND flash, "
@@ -732,9 +790,9 @@ U_BOOT_CMD(
        "nand write - addr off|partition size\n"
        "    read/write 'size' bytes starting at offset 'off'\n"
        "    to/from memory address 'addr', skipping bad blocks.\n"
-       "nand read.raw - addr off|partition\n"
-       "nand write.raw - addr off|partition\n"
-       "    Use read.raw/write.raw to avoid ECC and access the page as-is.\n"
+       "nand read.raw - addr off|partition [count]\n"
+       "nand write.raw - addr off|partition [count]\n"
+       "    Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
 #ifdef CONFIG_CMD_NAND_TRIMFFS
        "nand write.trimffs - addr off|partition size\n"
        "    write 'size' bytes starting at offset 'off' from memory address\n"
@@ -762,7 +820,7 @@ U_BOOT_CMD(
        "\n"
        "nand lock [tight] [status]\n"
        "    bring nand to lock state or display locked pages\n"
-       "nand unlock [offset] [size] - unlock section"
+       "nand unlock[.allexcept] [offset] [size] - unlock section"
 #endif
 #ifdef CONFIG_ENV_OFFSET_OOB
        "\n"