Transform 'u8' to 'uint8_t' in src/target
[fw/openocd] / src / flash / nand.c
index 87eb976a79b760e88a0e33c9e479ba0a777e8b30..69b676620d0810dce9bc44a8e58a4bdf282dd834 100644 (file)
 #include "time_support.h"
 #include "fileio.h"
 
-#include <inttypes.h>
-
-
 static int handle_nand_list_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_nand_probe_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_nand_check_bad_blocks_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_nand_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-static int handle_nand_copy_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_nand_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@@ -49,6 +45,7 @@ static int nand_write_page(struct nand_device_s *device, u32 page, u8 *data, u32
 
 /* NAND flash controller
  */
+extern nand_flash_controller_t davinci_nand_controller;
 extern nand_flash_controller_t lpc3180_nand_controller;
 extern nand_flash_controller_t orion_nand_controller;
 extern nand_flash_controller_t s3c2410_nand_controller;
@@ -60,6 +57,7 @@ extern nand_flash_controller_t s3c2443_nand_controller;
 
 static nand_flash_controller_t *nand_flash_controllers[] =
 {
+       &davinci_nand_controller,
        &lpc3180_nand_controller,
        &orion_nand_controller,
        &s3c2410_nand_controller,
@@ -86,6 +84,7 @@ static command_t *nand_cmd;
  */
 static nand_info_t nand_flash_ids[] =
 {
+       /* start "museum" IDs */
        {"NAND 1MiB 5V 8-bit",          0x6e, 256, 1, 0x1000, 0},
        {"NAND 2MiB 5V 8-bit",          0x64, 256, 2, 0x1000, 0},
        {"NAND 4MiB 5V 8-bit",          0x6b, 512, 4, 0x2000, 0},
@@ -101,6 +100,7 @@ static nand_info_t nand_flash_ids[] =
        {"NAND 8MiB 3,3V 8-bit",        0xe6, 512, 8, 0x2000, 0},
        {"NAND 8MiB 1,8V 16-bit",       0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
        {"NAND 8MiB 3,3V 16-bit",       0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
+       /* end "museum" IDs */
 
        {"NAND 16MiB 1,8V 8-bit",       0x33, 512, 16, 0x4000, 0},
        {"NAND 16MiB 3,3V 8-bit",       0x73, 512, 16, 0x4000, 0},
@@ -172,6 +172,7 @@ static nand_manufacturer_t nand_manuf_ids[] =
        {NAND_MFR_RENESAS, "Renesas"},
        {NAND_MFR_STMICRO, "ST Micro"},
        {NAND_MFR_HYNIX, "Hynix"},
+       {NAND_MFR_MICRON, "Micron"},
        {0x0, NULL},
 };
 
@@ -305,15 +306,14 @@ int nand_init(struct command_context_s *cmd_ctx)
                register_command(cmd_ctx, nand_cmd, "probe", handle_nand_probe_command, COMMAND_EXEC,
                                                 "identify NAND flash device <num>");
                register_command(cmd_ctx, nand_cmd, "check_bad_blocks", handle_nand_check_bad_blocks_command, COMMAND_EXEC,
-                                                "check NAND flash device <num> for bad blocks [<first> <last>]");
+                                                "check NAND flash device <num> for bad blocks [<offset> <length>]");
                register_command(cmd_ctx, nand_cmd, "erase", handle_nand_erase_command, COMMAND_EXEC,
-                                                "erase blocks on NAND flash device <num> <first> <last>");
-               register_command(cmd_ctx, nand_cmd, "copy", handle_nand_copy_command, COMMAND_EXEC,
-                                                "copy from NAND flash device <num> <offset> <length> <ram-address>");
+                                                "erase blocks on NAND flash device <num> <offset> <length>");
                register_command(cmd_ctx, nand_cmd, "dump", handle_nand_dump_command, COMMAND_EXEC,
-                                                "dump from NAND flash device <num> <filename> <offset> <size> [options]");
+                                                "dump from NAND flash device <num> <filename> "
+                                                "<offset> <length> [oob_raw|oob_only]");
                register_command(cmd_ctx, nand_cmd, "write", handle_nand_write_command, COMMAND_EXEC,
-                                                "write to NAND flash device <num> <filename> <offset> [oob_raw|oob_only|oob_softecc]");
+                                                "write to NAND flash device <num> <filename> <offset> [oob_raw|oob_only|oob_softecc|oob_softecc_kw]");
                register_command(cmd_ctx, nand_cmd, "raw_access", handle_nand_raw_access_command, COMMAND_EXEC,
                                                 "raw access to NAND flash device <num> ['enable'|'disable']");
        }
@@ -357,7 +357,7 @@ static int nand_build_bbt(struct nand_device_s *device, int first, int last)
                        || (((device->page_size == 512) && (oob[5] != 0xff)) ||
                                ((device->page_size == 2048) && (oob[0] != 0xff))))
                {
-                       LOG_WARNING("invalid block: %i", i);
+                       LOG_WARNING("bad block: %i", i);
                        device->blocks[i].is_bad = 1;
                }
                else
@@ -1062,7 +1062,7 @@ int nand_write_page_raw(struct nand_device_s *device, u32 page, u8 *data, u32 da
 int handle_nand_list_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        nand_device_t *p;
-       int i = 0;
+       int i;
 
        if (!nand_devices)
        {
@@ -1070,13 +1070,13 @@ int handle_nand_list_command(struct command_context_s *cmd_ctx, char *cmd, char
                return ERROR_OK;
        }
 
-       for (p = nand_devices; p; p = p->next)
+       for (p = nand_devices, i = 0; p; p = p->next, i++)
        {
                if (p->device)
                        command_print(cmd_ctx, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
-                               i++, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size);
+                               i, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size);
                else
-                       command_print(cmd_ctx, "#%i: not probed");
+                       command_print(cmd_ctx, "#%i: not probed", i);
        }
 
        return ERROR_OK;
@@ -1090,20 +1090,20 @@ static int handle_nand_info_command(struct command_context_s *cmd_ctx, char *cmd
        int first = -1;
        int last = -1;
 
-       if ((argc < 1) || (argc > 3))
-       {
+       switch (argc) {
+       default:
                return ERROR_COMMAND_SYNTAX_ERROR;
-
-       }
-
-       if (argc == 2)
-       {
+       case 1:
+               first = 0;
+               last = INT32_MAX;
+               break;
+       case 2:
                first = last = strtoul(args[1], NULL, 0);
-       }
-       else if (argc == 3)
-       {
+               break;
+       case 3:
                first = strtoul(args[1], NULL, 0);
                last = strtoul(args[2], NULL, 0);
+               break;
        }
 
        p = get_nand_device_by_num(strtoul(args[0], NULL, 0));
@@ -1138,14 +1138,14 @@ static int handle_nand_info_command(struct command_context_s *cmd_ctx, char *cmd
                                else
                                        bad_state = " (block condition unknown)";
 
-                               command_print(cmd_ctx, "\t#%i: 0x%8.8x (0x%xkB) %s%s",
+                               command_print(cmd_ctx, "\t#%i: 0x%8.8x (%dkB) %s%s",
                                                        j, p->blocks[j].offset, p->blocks[j].size / 1024,
                                                        erase_state, bad_state);
                        }
                }
                else
                {
-                       command_print(cmd_ctx, "#%i: not probed");
+                       command_print(cmd_ctx, "#%s: not probed", args[0]);
                }
        }
 
@@ -1200,12 +1200,31 @@ static int handle_nand_erase_command(struct command_context_s *cmd_ctx, char *cm
        p = get_nand_device_by_num(strtoul(args[0], NULL, 0));
        if (p)
        {
-               int first = strtoul(args[1], NULL, 0);
-               int last = strtoul(args[2], NULL, 0);
+               char *cp;
+               unsigned long offset;
+               unsigned long length;
 
-               if ((retval = nand_erase(p, first, last)) == ERROR_OK)
+               offset = strtoul(args[1], &cp, 0);
+               if (*cp || offset == ULONG_MAX || offset % p->erase_size)
                {
-                       command_print(cmd_ctx, "successfully erased blocks %i to %i on NAND flash device '%s'", first, last, p->device->name);
+                       return ERROR_INVALID_ARGUMENTS;
+               }
+               offset /= p->erase_size;
+
+               length = strtoul(args[2], &cp, 0);
+               if (*cp || length == ULONG_MAX || length % p->erase_size)
+               {
+                       return ERROR_INVALID_ARGUMENTS;
+               }
+               length -= 1;
+               length /= p->erase_size;
+
+               retval = nand_erase(p, offset, offset + length);
+               if (retval == ERROR_OK)
+               {
+                       command_print(cmd_ctx, "successfully erased blocks "
+                                       "%lu to %lu on NAND flash device '%s'",
+                                       offset, offset + length, p->device->name);
                }
                else if (retval == ERROR_NAND_OPERATION_FAILED)
                {
@@ -1237,54 +1256,53 @@ int handle_nand_check_bad_blocks_command(struct command_context_s *cmd_ctx, char
 
        }
 
-       if (argc == 3)
-       {
-               first = strtoul(args[1], NULL, 0);
-               last = strtoul(args[2], NULL, 0);
+       p = get_nand_device_by_num(strtoul(args[0], NULL, 0));
+       if (!p) {
+               command_print(cmd_ctx, "NAND flash device '#%s' is out of bounds",
+                               args[0]);
+               return ERROR_INVALID_ARGUMENTS;
        }
 
-       p = get_nand_device_by_num(strtoul(args[0], NULL, 0));
-       if (p)
+       if (argc == 3)
        {
-               if ((retval = nand_build_bbt(p, first, last)) == ERROR_OK)
-               {
-                       command_print(cmd_ctx, "checked NAND flash device for bad blocks, use \"nand info\" command to list blocks", p->device->name);
-               }
-               else if (retval == ERROR_NAND_OPERATION_FAILED)
+               char *cp;
+               unsigned long offset;
+               unsigned long length;
+
+               offset = strtoul(args[1], &cp, 0);
+               if (*cp || offset == ULONG_MAX || offset % p->erase_size)
                {
-                       command_print(cmd_ctx, "error when checking for bad blocks on NAND flash device");
+                       return ERROR_INVALID_ARGUMENTS;
                }
-               else
+               offset /= p->erase_size;
+
+               length = strtoul(args[2], &cp, 0);
+               if (*cp || length == ULONG_MAX || length % p->erase_size)
                {
-                       command_print(cmd_ctx, "unknown error when checking for bad blocks on NAND flash device");
+                       return ERROR_INVALID_ARGUMENTS;
                }
-       }
-       else
-       {
-               command_print(cmd_ctx, "NAND flash device '#%s' is out of bounds", args[0]);
-       }
+               length -= 1;
+               length /= p->erase_size;
 
-       return ERROR_OK;
-}
-
-static int handle_nand_copy_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       nand_device_t *p;
+               first = offset;
+               last = offset + length;
+       }
 
-       if (argc != 4)
+       retval = nand_build_bbt(p, first, last);
+       if (retval == ERROR_OK)
        {
-               return ERROR_COMMAND_SYNTAX_ERROR;
-
+               command_print(cmd_ctx, "checked NAND flash device for bad blocks, "
+                               "use \"nand info\" command to list blocks");
        }
-
-       p = get_nand_device_by_num(strtoul(args[0], NULL, 0));
-       if (p)
+       else if (retval == ERROR_NAND_OPERATION_FAILED)
        {
-
+               command_print(cmd_ctx, "error when checking for bad blocks on "
+                               "NAND flash device");
        }
        else
        {
-               command_print(cmd_ctx, "NAND flash device '#%s' is out of bounds", args[0]);
+               command_print(cmd_ctx, "unknown error when checking for bad "
+                               "blocks on NAND flash device");
        }
 
        return ERROR_OK;
@@ -1567,13 +1585,13 @@ static int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd
                        fileio_close(&fileio);
 
                        duration_stop_measure(&duration, &duration_text);
-                       command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text);
+                       command_print(cmd_ctx, "dumped %lld byte in %s", fileio.size, duration_text);
                        free(duration_text);
                        duration_text = NULL;
                }
                else
                {
-                       command_print(cmd_ctx, "#%i: not probed");
+                       command_print(cmd_ctx, "#%s: not probed", args[0]);
                }
        }
        else
@@ -1618,7 +1636,7 @@ static int handle_nand_raw_access_command(struct command_context_s *cmd_ctx, cha
                }
                else
                {
-                       command_print(cmd_ctx, "#%i: not probed");
+                       command_print(cmd_ctx, "#%s: not probed", args[0]);
                }
        }
        else