flash: print bank usage on failure
[fw/openocd] / src / flash / nand / tcl.c
index e69882bb5851397b466d2d8a77db70fa752da29c..6389377903baa64c4b17204d533f4091e772b39d 100644 (file)
@@ -27,6 +27,7 @@
 #include "core.h"
 #include "imp.h"
 #include "fileio.h"
+#include <target/target.h>
 
 // to be removed
 extern struct nand_device *nand_devices;
@@ -147,18 +148,11 @@ COMMAND_HANDLER(handle_nand_probe_command)
 
        if ((retval = nand_probe(p)) == ERROR_OK)
        {
-               command_print(CMD_CTX, "NAND flash device '%s' found", p->device->name);
-       }
-       else if (retval == ERROR_NAND_OPERATION_FAILED)
-       {
-               command_print(CMD_CTX, "probing failed for NAND flash device");
-       }
-       else
-       {
-               command_print(CMD_CTX, "unknown error when probing NAND flash device");
+               command_print(CMD_CTX, "NAND flash device '%s (%s)' found",
+                               p->device->name, p->manufacturer->name);
        }
 
-       return ERROR_OK;
+       return retval;
 }
 
 COMMAND_HANDLER(handle_nand_erase_command)
@@ -183,12 +177,12 @@ COMMAND_HANDLER(handle_nand_erase_command)
 
                COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
                if ((offset % p->erase_size) != 0 || offset >= size)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
 
                COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
                if ((length == 0) || (length % p->erase_size) != 0
                                || (length + offset) > size)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
 
                offset /= p->erase_size;
                length /= p->erase_size;
@@ -205,16 +199,8 @@ COMMAND_HANDLER(handle_nand_erase_command)
                                offset, offset + length,
                                CMD_ARGV[0], p->device->name);
        }
-       else if (retval == ERROR_NAND_OPERATION_FAILED)
-       {
-               command_print(CMD_CTX, "erase failed");
-       }
-       else
-       {
-               command_print(CMD_CTX, "unknown error when erasing NAND flash device");
-       }
 
-       return ERROR_OK;
+       return retval;
 }
 
 COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
@@ -240,12 +226,12 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
 
                COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
                if (offset % p->erase_size)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                offset /= p->erase_size;
 
                COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
                if (length % p->erase_size)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
 
                length -= 1;
                length /= p->erase_size;
@@ -260,18 +246,8 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
                command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
                                "use \"nand info\" command to list blocks");
        }
-       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, "unknown error when checking for bad "
-                               "blocks on NAND flash device");
-       }
 
-       return ERROR_OK;
+       return retval;
 }
 
 COMMAND_HANDLER(handle_nand_write_command)
@@ -309,7 +285,7 @@ COMMAND_HANDLER(handle_nand_write_command)
        if (nand_fileio_finish(&s))
        {
                command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
-                               "offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
+                               "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
                                CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
                                duration_kbps(&s.bench, total_bytes));
        }
@@ -336,13 +312,14 @@ COMMAND_HANDLER(handle_nand_verify_command)
 
        while (file.size > 0)
        {
-               int retval = nand_read_page(nand, dev.address / dev.page_size,
+               retval = nand_read_page(nand, dev.address / dev.page_size,
                                dev.page, dev.page_size, dev.oob, dev.oob_size);
                if (ERROR_OK != retval)
                {
                        command_print(CMD_CTX, "reading NAND flash page failed");
                        nand_fileio_cleanup(&dev);
-                       return nand_fileio_cleanup(&file);
+                       nand_fileio_cleanup(&file);
+                       return retval;
                }
 
                int bytes_read = nand_fileio_read(nand, &file);
@@ -350,7 +327,8 @@ COMMAND_HANDLER(handle_nand_verify_command)
                {
                        command_print(CMD_CTX, "error while reading file");
                        nand_fileio_cleanup(&dev);
-                       return nand_fileio_cleanup(&file);
+                       nand_fileio_cleanup(&file);
+                       return ERROR_FAIL;
                }
 
                if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
@@ -359,7 +337,8 @@ COMMAND_HANDLER(handle_nand_verify_command)
                        command_print(CMD_CTX, "NAND flash contents differ "
                                                "at 0x%8.8" PRIx32, dev.address);
                        nand_fileio_cleanup(&dev);
-                       return nand_fileio_cleanup(&file);
+                       nand_fileio_cleanup(&file);
+                       return ERROR_FAIL;
                }
 
                file.size -= bytes_read;
@@ -369,7 +348,7 @@ COMMAND_HANDLER(handle_nand_verify_command)
        if (nand_fileio_finish(&file) == ERROR_OK)
        {
                command_print(CMD_CTX, "verified file %s in NAND flash %s "
-                               "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
+                               "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
                                CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
                                duration_kbps(&file.bench, dev.size));
        }
@@ -379,6 +358,7 @@ COMMAND_HANDLER(handle_nand_verify_command)
 
 COMMAND_HANDLER(handle_nand_dump_command)
 {
+       int filesize;
        struct nand_device *nand = NULL;
        struct nand_fileio_state s;
        int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
@@ -389,12 +369,13 @@ COMMAND_HANDLER(handle_nand_dump_command)
        while (s.size > 0)
        {
                size_t size_written;
-               int retval = nand_read_page(nand, s.address / nand->page_size,
+               retval = nand_read_page(nand, s.address / nand->page_size,
                                s.page, s.page_size, s.oob, s.oob_size);
                if (ERROR_OK != retval)
                {
                        command_print(CMD_CTX, "reading NAND flash page failed");
-                       return nand_fileio_cleanup(&s);
+                       nand_fileio_cleanup(&s);
+                       return retval;
                }
 
                if (NULL != s.page)
@@ -407,11 +388,15 @@ COMMAND_HANDLER(handle_nand_dump_command)
                s.address += nand->page_size;
        }
 
+       retval = fileio_size(&s.fileio, &filesize);
+       if (retval != ERROR_OK)
+               return retval;
+
        if (nand_fileio_finish(&s) == ERROR_OK)
        {
-               command_print(CMD_CTX, "dumped %zu bytes in %fs (%0.3f kb/s)", 
-                               s.fileio.size, duration_elapsed(&s.bench),
-                               duration_kbps(&s.bench, s.fileio.size));
+               command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)",
+                               (long)filesize, duration_elapsed(&s.bench),
+                               duration_kbps(&s.bench, filesize));
        }
        return ERROR_OK;
 }
@@ -446,74 +431,73 @@ COMMAND_HANDLER(handle_nand_raw_access_command)
 static const struct command_registration nand_exec_command_handlers[] = {
        {
                .name = "list",
-               .handler = &handle_nand_list_command,
+               .handler = handle_nand_list_command,
                .mode = COMMAND_EXEC,
                .help = "list configured NAND flash devices",
        },
        {
                .name = "info",
-               .handler = &handle_nand_info_command,
+               .handler = handle_nand_info_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank>",
-               .help = "print info about a NAND flash device",
+               .usage = "[banknum | first_bank_num last_bank_num]",
+               .help = "print info about one or more NAND flash devices",
        },
        {
                .name = "probe",
-               .handler = &handle_nand_probe_command,
+               .handler = handle_nand_probe_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank>",
-               .help = "identify NAND flash device <num>",
-
+               .usage = "bank_id",
+               .help = "identify NAND flash device",
        },
        {
                .name = "check_bad_blocks",
-               .handler = &handle_nand_check_bad_blocks_command,
+               .handler = handle_nand_check_bad_blocks_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> [<offset> <length>]",
-               .help = "check NAND flash device <num> for bad blocks",
+               .usage = "bank_id [offset length]",
+               .help = "check all or part of NAND flash device for bad blocks",
        },
        {
                .name = "erase",
-               .handler = &handle_nand_erase_command,
+               .handler = handle_nand_erase_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> [<offset> <length>]",
-               .help = "erase blocks on NAND flash device",
+               .usage = "bank_id [offset length]",
+               .help = "erase all or subset of blocks on NAND flash device",
        },
        {
                .name = "dump",
-               .handler = &handle_nand_dump_command,
+               .handler = handle_nand_dump_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> <filename> <offset> <length> "
-                       "[oob_raw | oob_only]",
+               .usage = "bank_id filename offset length "
+                       "['oob_raw'|'oob_only']",
                .help = "dump from NAND flash device",
        },
        {
                .name = "verify",
-               .handler = &handle_nand_verify_command,
+               .handler = handle_nand_verify_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> <filename> <offset> "
-                       "[oob_raw | oob_only | oob_softecc | oob_softecc_kw]",
+               .usage = "bank_id filename offset "
+                       "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
                .help = "verify NAND flash device",
        },
        {
                .name = "write",
-               .handler = &handle_nand_write_command,
+               .handler = handle_nand_write_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> <filename> <offset> "
-                       "[oob_raw | oob_only | oob_softecc | oob_softecc_kw]",
+               .usage = "bank_id filename offset "
+                       "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
                .help = "write to NAND flash device",
        },
        {
                .name = "raw_access",
-               .handler = &handle_nand_raw_access_command,
+               .handler = handle_nand_raw_access_command,
                .mode = COMMAND_EXEC,
-               .usage = "<num> ['enable'|'disable']",
+               .usage = "bank_id ['enable'|'disable']",
                .help = "raw access to NAND flash device",
        },
        COMMAND_REGISTRATION_DONE
 };
 
-int nand_init(struct command_context *cmd_ctx)
+static int nand_init(struct command_context *cmd_ctx)
 {
        if (!nand_devices)
                return ERROR_OK;
@@ -537,12 +521,14 @@ COMMAND_HANDLER(handle_nand_init_command)
        LOG_DEBUG("Initializing NAND devices...");
        return nand_init(CMD_CTX);
 }
-int nand_list_walker(struct nand_flash_controller *c, void *x)
+
+static int nand_list_walker(struct nand_flash_controller *c, void *x)
 {
        struct command_context *cmd_ctx = (struct command_context *)x;
        command_print(cmd_ctx, "  %s", c->name);
        return ERROR_OK;
 }
+
 COMMAND_HANDLER(handle_nand_list_drivers)
 {
        command_print(CMD_CTX, "Available NAND flash controller drivers:");
@@ -552,16 +538,36 @@ COMMAND_HANDLER(handle_nand_list_drivers)
 static COMMAND_HELPER(create_nand_device, const char *bank_name,
                struct nand_flash_controller *controller)
 {
+       struct nand_device *c;
+       struct target *target;
+       int retval;
+
+       if (CMD_ARGC < 2)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       target = get_target(CMD_ARGV[1]);
+       if (!target) {
+               LOG_ERROR("invalid target %s", CMD_ARGV[1]);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
+       }
+
        if (NULL != controller->commands)
        {
-               int retval = register_commands(CMD_CTX, NULL,
+               retval = register_commands(CMD_CTX, NULL,
                                controller->commands);
                if (ERROR_OK != retval)
                        return retval;
        }
-       struct nand_device *c = malloc(sizeof(struct nand_device));
+       c = malloc(sizeof(struct nand_device));
+       if (c == NULL)
+       {
+               LOG_ERROR("End of memory");
+               return ERROR_FAIL;
+       }
 
        c->name = strdup(bank_name);
+       c->target = target;
        c->controller = controller;
        c->controller_priv = NULL;
        c->manufacturer = NULL;
@@ -572,23 +578,29 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name,
        c->use_raw = 0;
        c->next = NULL;
 
-       int retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
+       retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
        if (ERROR_OK != retval)
        {
-               LOG_ERROR("'%s' driver rejected nand flash", controller->name);
+               LOG_ERROR("'%s' driver rejected nand flash. Usage: %s",
+                       controller->name,
+                       controller->usage);
                free(c);
-               return ERROR_OK;
+               return retval;
        }
 
+       if (controller->usage == NULL)
+               LOG_DEBUG("'%s' driver usage field missing", controller->name);
+
+       nand_device_add(c);
+
        return ERROR_OK;
 }
 
 COMMAND_HANDLER(handle_nand_device_command)
 {
-       if (CMD_ARGC < 1)
+       if (CMD_ARGC < 2)
        {
-               LOG_ERROR("incomplete nand device configuration");
-               return ERROR_FLASH_BANK_INVALID;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        // save name and increment (for compatibility) with drivers
@@ -612,18 +624,21 @@ static const struct command_registration nand_config_command_handlers[] = {
                .handler = &handle_nand_device_command,
                .mode = COMMAND_CONFIG,
                .help = "defines a new NAND bank",
+               .usage = "bank_id driver target [driver_options ...]",
        },
        {
                .name = "drivers",
                .handler = &handle_nand_list_drivers,
                .mode = COMMAND_ANY,
                .help = "lists available NAND drivers",
+               .usage = ""
        },
        {
                .name = "init",
                .mode = COMMAND_CONFIG,
                .handler = &handle_nand_init_command,
                .help = "initialize NAND devices",
+               .usage = ""
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -632,6 +647,7 @@ static const struct command_registration nand_command_handlers[] = {
                .name = "nand",
                .mode = COMMAND_ANY,
                .help = "NAND flash command group",
+               .usage = "",
                .chain = nand_config_command_handlers,
        },
        COMMAND_REGISTRATION_DONE