pld/virtex2: add program/refresh command
[openocd.git] / src / pld / lattice.c
index f3d9c0da79de61977e30fed4dd3492f9de6ea90c..63d730677adeb6f752fdb001a00f279d712716c3 100644 (file)
@@ -15,6 +15,7 @@
 #include "lattice_bit.h"
 #include "ecp2_3.h"
 #include "ecp5.h"
+#include "certus.h"
 
 #define PRELOAD              0x1C
 
@@ -50,6 +51,9 @@ static const struct lattice_devices_elem lattice_devices[] = {
        {0x01111043,  409, LATTICE_ECP5 /* "LAE5UM-25F" */},
        {0x01112043,  510, LATTICE_ECP5 /* "LAE5UM-45F" */},
        {0x01113043,  750, LATTICE_ECP5 /* "LAE5UM-85F" */},
+       {0x310f0043,  362, LATTICE_CERTUS /* LFD2NX-17 */},
+       {0x310f1043,  362, LATTICE_CERTUS /* LFD2NX-40 */},
+       {0x010f4043,  362, LATTICE_CERTUS /* LFCPNX-100 */},
 };
 
 int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t endstate)
@@ -116,6 +120,27 @@ int lattice_read_u32_register(struct jtag_tap *tap, uint8_t cmd, uint32_t *in_va
        return retval;
 }
 
+int lattice_read_u64_register(struct jtag_tap *tap, uint8_t cmd, uint64_t *in_val,
+                                                       uint64_t out_val)
+{
+       struct scan_field field;
+       uint8_t buffer[8];
+
+       int retval = lattice_set_instr(tap, cmd, TAP_IDLE);
+       if (retval != ERROR_OK)
+               return retval;
+       h_u64_to_le(buffer, out_val);
+       field.num_bits = 64;
+       field.out_value = buffer;
+       field.in_value = buffer;
+       jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
+       retval = jtag_execute_queue();
+       if (retval == ERROR_OK)
+               *in_val = le_to_h_u64(buffer);
+
+       return retval;
+}
+
 int lattice_preload(struct lattice_pld_device *lattice_device)
 {
        struct scan_field field;
@@ -150,6 +175,8 @@ static int lattice_read_usercode(struct lattice_pld_device *lattice_device, uint
                return lattice_ecp2_3_read_usercode(tap, usercode, out);
        else if (lattice_device->family == LATTICE_ECP5)
                return lattice_ecp5_read_usercode(tap, usercode, out);
+       else if (lattice_device->family == LATTICE_CERTUS)
+               return lattice_certus_read_usercode(tap, usercode, out);
 
        return ERROR_FAIL;
 }
@@ -177,6 +204,8 @@ static int lattice_write_usercode(struct lattice_pld_device *lattice_device, uin
                return lattice_ecp2_3_write_usercode(lattice_device, usercode);
        else if (lattice_device->family == LATTICE_ECP5)
                return lattice_ecp5_write_usercode(lattice_device, usercode);
+       else if (lattice_device->family == LATTICE_CERTUS)
+               return lattice_certus_write_usercode(lattice_device, usercode);
 
        return ERROR_FAIL;
 }
@@ -194,12 +223,22 @@ static int lattice_read_status_u32(struct lattice_pld_device *lattice_device, ui
 
        return ERROR_FAIL;
 }
+static int lattice_read_status_u64(struct lattice_pld_device *lattice_device, uint64_t *status,
+                                                               uint64_t out)
+{
+       if (!lattice_device->tap)
+               return ERROR_FAIL;
+
+       if (lattice_device->family == LATTICE_CERTUS)
+               return lattice_certus_read_status(lattice_device->tap, status, out);
+
+       return ERROR_FAIL;
+}
 
 int lattice_verify_status_register_u32(struct lattice_pld_device *lattice_device, uint32_t out,
                                                uint32_t expected, uint32_t mask, bool do_idle)
 {
        uint32_t status;
-
        int retval = lattice_read_status_u32(lattice_device, &status, out, do_idle);
        if (retval != ERROR_OK)
                return retval;
@@ -212,13 +251,28 @@ int lattice_verify_status_register_u32(struct lattice_pld_device *lattice_device
        return ERROR_OK;
 }
 
+int lattice_verify_status_register_u64(struct lattice_pld_device *lattice_device, uint64_t out,
+                                               uint64_t expected, uint64_t mask)
+{
+       uint64_t status;
+       int retval = lattice_read_status_u64(lattice_device, &status, out);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if ((status & mask) != expected) {
+               LOG_ERROR("verifying status register failed got: 0x%08" PRIx64 " expected: 0x%08" PRIx64,
+                       status & mask, expected);
+               return ERROR_FAIL;
+       }
+       return ERROR_OK;
+}
+
 static int lattice_load_command(struct pld_device *pld_device, const char *filename)
 {
        if (!pld_device)
                return ERROR_FAIL;
 
        struct lattice_pld_device *lattice_device = pld_device->driver_priv;
-
        if (!lattice_device || !lattice_device->tap)
                return ERROR_FAIL;
        struct jtag_tap *tap = lattice_device->tap;
@@ -245,10 +299,14 @@ static int lattice_load_command(struct pld_device *pld_device, const char *filen
                retval = lattice_ecp3_load(lattice_device, &bit_file);
                break;
        case LATTICE_ECP5:
+       case LATTICE_CERTUS:
                if (bit_file.has_id && id != bit_file.idcode)
                        LOG_WARNING("Id on device (0x%8.8" PRIx32 ") and id in bit-stream (0x%8.8" PRIx32 ") don't match.",
                                id, bit_file.idcode);
-               retval = lattice_ecp5_load(lattice_device, &bit_file);
+               if (lattice_device->family == LATTICE_ECP5)
+                       retval = lattice_ecp5_load(lattice_device, &bit_file);
+               else
+                       retval = lattice_certus_load(lattice_device, &bit_file);
                break;
        default:
                LOG_ERROR("loading unknown device family");
@@ -258,37 +316,46 @@ static int lattice_load_command(struct pld_device *pld_device, const char *filen
        return retval;
 }
 
-PLD_DEVICE_COMMAND_HANDLER(lattice_pld_device_command)
+PLD_CREATE_COMMAND_HANDLER(lattice_pld_create_command)
 {
-       if (CMD_ARGC < 2 || CMD_ARGC > 3)
+       if (CMD_ARGC != 4 && CMD_ARGC != 6)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
+       struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
        if (!tap) {
-               command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
+               command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
                return ERROR_FAIL;
        }
 
-       struct lattice_pld_device *lattice_device = malloc(sizeof(struct lattice_pld_device));
-       if (!lattice_device) {
-               LOG_ERROR("Out of memory");
-               return ERROR_FAIL;
-       }
        /* id is not known yet -> postpone lattice_check_device_family() */
        enum lattice_family_e family = LATTICE_UNKNOWN;
-       if (CMD_ARGC == 3) {
-               if (strcasecmp(CMD_ARGV[2], "ecp2") == 0) {
+       if (CMD_ARGC == 6) {
+               if (strcmp(CMD_ARGV[4], "-family") != 0)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+
+               if (strcasecmp(CMD_ARGV[5], "ecp2") == 0) {
                        family = LATTICE_ECP2;
-               } else if (strcasecmp(CMD_ARGV[2], "ecp3") == 0) {
+               } else if (strcasecmp(CMD_ARGV[5], "ecp3") == 0) {
                        family = LATTICE_ECP3;
-               } else if (strcasecmp(CMD_ARGV[2], "ecp5") == 0) {
+               } else if (strcasecmp(CMD_ARGV[5], "ecp5") == 0) {
                        family = LATTICE_ECP5;
+               } else if (strcasecmp(CMD_ARGV[5], "certus") == 0) {
+                       family = LATTICE_CERTUS;
                } else {
                        command_print(CMD, "unknown family");
-                       free(lattice_device);
                        return ERROR_FAIL;
                }
        }
+
+       struct lattice_pld_device *lattice_device = malloc(sizeof(struct lattice_pld_device));
+       if (!lattice_device) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+
        lattice_device->tap = tap;
        lattice_device->family = family;
        lattice_device->preload_length = 0;
@@ -300,16 +367,14 @@ PLD_DEVICE_COMMAND_HANDLER(lattice_pld_device_command)
 
 COMMAND_HANDLER(lattice_read_usercode_register_command_handler)
 {
-       int dev_id;
        uint32_t usercode;
 
        if (CMD_ARGC != 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
-       struct pld_device *device = get_pld_device_by_num(dev_id);
+       struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
        if (!device) {
-               command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
+               command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
                return ERROR_FAIL;
        }
 
@@ -330,16 +395,14 @@ COMMAND_HANDLER(lattice_read_usercode_register_command_handler)
 
 COMMAND_HANDLER(lattice_set_preload_command_handler)
 {
-       int dev_id;
        unsigned int preload_length;
 
        if (CMD_ARGC != 2)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
-       struct pld_device *device = get_pld_device_by_num(dev_id);
+       struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
        if (!device) {
-               command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
+               command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
                return ERROR_FAIL;
        }
 
@@ -357,16 +420,14 @@ COMMAND_HANDLER(lattice_set_preload_command_handler)
 
 COMMAND_HANDLER(lattice_write_usercode_register_command_handler)
 {
-       int dev_id;
        uint32_t usercode;
 
        if (CMD_ARGC != 2)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
-       struct pld_device *device = get_pld_device_by_num(dev_id);
+       struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
        if (!device) {
-               command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
+               command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
                return ERROR_FAIL;
        }
 
@@ -385,15 +446,12 @@ COMMAND_HANDLER(lattice_write_usercode_register_command_handler)
 
 COMMAND_HANDLER(lattice_read_status_command_handler)
 {
-       int dev_id;
-
        if (CMD_ARGC != 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
-       struct pld_device *device = get_pld_device_by_num(dev_id);
+       struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
        if (!device) {
-               command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
+               command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
                return ERROR_FAIL;
        }
 
@@ -405,11 +463,18 @@ COMMAND_HANDLER(lattice_read_status_command_handler)
        if (retval != ERROR_OK)
                return retval;
 
-       uint32_t status;
-       const bool do_idle = lattice_device->family == LATTICE_ECP5;
-       retval = lattice_read_status_u32(lattice_device, &status, 0x0, do_idle);
-       if (retval == ERROR_OK)
-               command_print(CMD, "0x%8.8" PRIx32, status);
+       if (lattice_device->family == LATTICE_CERTUS) {
+               uint64_t status;
+               retval = lattice_read_status_u64(lattice_device, &status, 0x0);
+               if (retval == ERROR_OK)
+                       command_print(CMD, "0x%016" PRIx64, status);
+       } else {
+               uint32_t status;
+               const bool do_idle = lattice_device->family == LATTICE_ECP5;
+               retval = lattice_read_status_u32(lattice_device, &status, 0x0, do_idle);
+               if (retval == ERROR_OK)
+                       command_print(CMD, "0x%8.8" PRIx32, status);
+       }
 
        return retval;
 }
@@ -420,25 +485,25 @@ static const struct command_registration lattice_exec_command_handlers[] = {
                .mode = COMMAND_EXEC,
                .handler = lattice_read_status_command_handler,
                .help = "reading status register from FPGA",
-               .usage = "num_pld",
+               .usage = "pld_name",
        }, {
                .name = "read_user",
                .mode = COMMAND_EXEC,
                .handler = lattice_read_usercode_register_command_handler,
                .help = "reading usercode register from FPGA",
-               .usage = "num_pld",
+               .usage = "pld_name",
        }, {
                .name = "write_user",
                .mode = COMMAND_EXEC,
                .handler = lattice_write_usercode_register_command_handler,
                .help = "writing usercode register to FPGA",
-               .usage = "num_pld value",
+               .usage = "pld_name value",
        }, {
                .name = "set_preload",
                .mode = COMMAND_EXEC,
                .handler = lattice_set_preload_command_handler,
                .help = "set length for preload (device specific)",
-               .usage = "num_pld value",
+               .usage = "pld_name value",
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -457,6 +522,6 @@ static const struct command_registration lattice_command_handler[] = {
 struct pld_driver lattice_pld = {
        .name = "lattice",
        .commands = lattice_command_handler,
-       .pld_device_command = &lattice_pld_device_command,
+       .pld_create_command = &lattice_pld_create_command,
        .load = &lattice_load_command,
 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)