This is an automated email from Gerrit.

"Daniel Anselmi <danse...@gmx.ch>" just uploaded a new patch set to Gerrit, 
which you can find at https://review.openocd.org/c/openocd/+/7353

-- gerrit

commit 628421a3d343d1db2da4bdfc8913172d6fb4980b
Author: Daniel Anselmi <danse...@gmx.ch>
Date:   Fri Oct 14 00:57:12 2022 +0200

    pld: add support lattice certus and certuspro devices
    
    Change-Id: If401b1f66bc4db0a49ea1603fa36af7f0bdbce32
    Signed-off-by: Daniel Anselmi <danse...@gmx.ch>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 8cca4ab98b..d41e7f4163 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -8552,6 +8552,26 @@ openocd -f trion_t20_bga256.cfg \
 @end example
 @end deffn
 
+@deffn {FPGA Driver} {certus}
+Certus and CertusPro are FPGA families sold by Lattice.
+This driver can be used to load the bitstream into the FPGA.
+
+@example
+openocd -f board/certuspro_evaluation.cfg -c "init" \
+       -c "pld load 0 ecertuspro_blinker_impl1.bit"
+@end example
+
+@deffn {Command} {certus read_status} num
+Reads and displays the status register
+for FPGA @var{num}.
+@end deffn
+
+@deffn {Command} {certus read_user} num
+Reads and displays the user register
+for FPGA @var{num}.
+@end deffn
+@end deffn
+
 
 @node General Commands
 @chapter General Commands
diff --git a/src/pld/Makefile.am b/src/pld/Makefile.am
index 78124fb3d4..b587824945 100644
--- a/src/pld/Makefile.am
+++ b/src/pld/Makefile.am
@@ -6,14 +6,15 @@ noinst_LTLIBRARIES += %D%/libpld.la
        %D%/xilinx_bit.c \
        %D%/virtex2.c \
        %D%/raw_bit.c \
-       %D%/ecp_bit.c \
-       %D%/ecp.c \
+       %D%/lattice_bit.c \
+       %D%/lattice.c \
        %D%/ecp2_3.c \
        %D%/ecp5.c \
+       %D%/certus.c \
        %D%/efinix.c \
        %D%/pld.h \
        %D%/xilinx_bit.h \
        %D%/virtex2.h \
        %D%/raw_bit.h \
-       %D%/ecp_bit.h \
-       %D%/ecp.h
+       %D%/lattice_bit.h \
+       %D%/lattice.h
diff --git a/src/pld/certus.c b/src/pld/certus.c
new file mode 100644
index 0000000000..805b42de19
--- /dev/null
+++ b/src/pld/certus.c
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ *   Copyright (C) 2022 by Daniel Anselmi                                  *
+ *   danse...@gmx.ch                                                       *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "lattice.h"
+#include "pld.h"
+#include "lattice_bit.h"
+
+#define ISC_ERASE            0x0E
+#define PRELOAD              0x1C
+#define ISC_DISABLE          0x26
+#define LSC_READ_STATUS      0x3C
+#define LSC_INIT_ADDRESS     0x46
+#define LSC_ENABLE_X         0x74
+#define LSC_REFRESH          0x79
+#define LSC_BITSTREAM_BURST  0x7A
+#define LSC_DEVICE_CTRL      0x7D
+#define READ_USERCODE        0xC0
+#define ISC_ENABLE           0xC6
+#define BYPASS               0xFF
+
+#define PRELOAD_LENGTH 362
+
+static int certus_read_status(struct jtag_tap *tap, uint64_t *status, uint64_t 
out)
+{
+       return lattice_read_u64_register(tap, LSC_READ_STATUS, status, out);
+}
+
+static int certus_read_user(struct jtag_tap *tap, uint32_t *status, uint32_t 
out)
+{
+       return lattice_read_u32_register(tap, READ_USERCODE, status, out, 
false);
+}
+
+static int certus_enable_transparent_mode(struct jtag_tap *tap)
+{
+       struct scan_field field;
+
+       lattice_set_instr(tap, LSC_ENABLE_X, TAP_IDLE);
+
+       uint8_t buffer = 0x0;
+       field.num_bits = 8;
+       field.out_value = &buffer;
+       field.in_value = NULL;
+       jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
+       jtag_add_runtest(2, TAP_IDLE);
+
+       return jtag_execute_queue();
+}
+
+static int certus_verify_status_register(struct jtag_tap *tap, uint64_t 
out_val,
+                                                                       
uint64_t expected, uint64_t mask)
+{
+       uint64_t status;
+
+       int retval = certus_read_status(tap, &status, out_val);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if ((status & mask) != expected) {
+               LOG_ERROR("verifying status register failed got: 0x%016" PRIx64 
" expected: 0x%016" PRIx64,
+                               status & mask, expected);
+               return ERROR_FAIL;
+       }
+       return ERROR_OK;
+}
+
+static int certus_erase_device(struct jtag_tap *tap)
+{
+       struct scan_field field;
+
+       lattice_set_instr(tap, LSC_DEVICE_CTRL, TAP_IRPAUSE);
+
+       uint8_t buffer = 8;
+       field.num_bits = 8;
+       field.out_value = &buffer;
+       field.in_value = NULL;
+       jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
+       jtag_add_runtest(2, TAP_IDLE);
+       int retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       lattice_set_instr(tap, LSC_DEVICE_CTRL, TAP_IDLE);
+       buffer = 0;
+       field.num_bits = 8;
+       field.out_value = &buffer;
+       jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
+       jtag_add_runtest(2, TAP_IDLE);
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       lattice_set_instr(tap, ISC_ERASE, TAP_IDLE);
+       buffer = 0;
+       field.num_bits = 8;
+       field.out_value = &buffer;
+       jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
+       jtag_add_runtest(100, TAP_IDLE);
+       jtag_add_sleep(5000);
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* check done is cleared and fail is cleared */
+       const uint64_t status_done_flag =  0x100;
+       const uint64_t status_fail_flag = 0x2000;
+       return certus_verify_status_register(tap, 0x0, 0x0, status_done_flag | 
status_fail_flag);
+}
+
+static int certus_enable_programming(struct jtag_tap *tap)
+{
+       struct scan_field field;
+
+       lattice_set_instr(tap, LSC_REFRESH, TAP_IDLE);
+       jtag_add_runtest(2, TAP_IDLE);
+       int retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
+       uint8_t buffer = 0;
+       field.num_bits = 8;
+       field.out_value = &buffer;
+       jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
+       jtag_add_runtest(2, TAP_IDLE);
+       return jtag_execute_queue();
+}
+
+static int certus_init_address(struct jtag_tap *tap)
+{
+       lattice_set_instr(tap, LSC_INIT_ADDRESS, TAP_IDLE);
+       jtag_add_runtest(2, TAP_IDLE);
+       return jtag_execute_queue();
+}
+
+static int certus_exit_programming_mode(struct jtag_tap *tap)
+{
+       lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
+       jtag_add_runtest(2, TAP_IDLE);
+       lattice_set_instr(tap, BYPASS, TAP_IDLE);
+       jtag_add_runtest(100, TAP_IDLE);
+       return jtag_execute_queue();
+}
+
+static int certus_program_fuse_map(struct jtag_tap *tap, struct 
lattice_bit_file *bit_file)
+{
+       struct scan_field field;
+
+       lattice_set_instr(tap, LSC_BITSTREAM_BURST, TAP_IDLE);
+
+       field.num_bits = (bit_file->raw_bit.length - bit_file->offset) * 8;
+       field.out_value = bit_file->raw_bit.data + bit_file->offset;
+       field.in_value = NULL;
+       jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
+
+       return jtag_execute_queue();
+}
+
+static int certus_load(struct jtag_tap *tap, struct lattice_bit_file *bit_file)
+{
+       int retval = lattice_preload(tap, PRELOAD, PRELOAD_LENGTH);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /*  check password protection is disabled */
+       const uint64_t status_pwd_protection = 0x20000;
+       retval = certus_verify_status_register(tap, 0x0, 0x0, 
status_pwd_protection);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Password protection is set");
+               return retval;
+       }
+
+       retval = certus_enable_transparent_mode(tap);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* Check the SRAM Erase Lock */
+       const uint64_t status_otp = 0x40;
+       retval = certus_verify_status_register(tap, 0x0, status_otp, 
status_otp);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("NV User Feature Sector OTP is Set");
+               return retval;
+       }
+
+       /* Check the SRAM Lock */
+       const uint64_t status_write_protected = 0x400;
+       retval = certus_verify_status_register(tap, 0x0, 0x0, 
status_write_protected);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("NV User Feature Sector OTP is Set");
+               return retval;
+       }
+
+       retval = certus_enable_programming(tap);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("failed to enable programming mode");
+               return retval;
+       }
+
+       retval = certus_erase_device(tap);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("erasing device failed");
+               return retval;
+       }
+
+       retval = certus_init_address(tap);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = certus_program_fuse_map(tap, bit_file);
+       if (retval != ERROR_OK)
+               return retval;
+       const uint32_t expected = 0x100; // done
+       const uint32_t mask = expected |
+                       0x3000 | // Busy Flag and Fail Flag
+                       0xf000000; // BSE Error
+       retval = certus_verify_status_register(tap, 0x0, 0x100, mask);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return certus_exit_programming_mode(tap);
+}
+
+static int certus_load_command(struct pld_device *pld_device, const char 
*filename)
+{
+       struct lattice_bit_file bit_file;
+
+       if (!pld_device || !pld_device->driver_priv)
+               return ERROR_FAIL;
+
+       struct lattice_pld_device *certus_info = pld_device->driver_priv;
+       if (!certus_info || !certus_info->tap)
+               return ERROR_FAIL;
+       struct jtag_tap *tap = certus_info->tap;
+
+       if (!tap->hasidcode)
+               return ERROR_FAIL;
+       uint32_t id = tap->idcode;
+
+       int retval = lattice_read_file(&bit_file, filename, true);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (bit_file.has_id && id != bit_file.idcode)
+               LOG_WARNING("id on device and bit-stream don't match!");
+
+       retval = certus_load(tap, &bit_file);
+       free(bit_file.raw_bit.data);
+       return retval;
+}
+
+static int certus_read_status_register(struct pld_device *pld_device, uint64_t 
*status)
+{
+       if (!pld_device)
+               return ERROR_FAIL;
+
+       struct lattice_pld_device *certus_info = pld_device->driver_priv;
+
+       if (!certus_info || !certus_info->tap)
+               return ERROR_FAIL;
+
+       return certus_read_status(certus_info->tap, status, 0x0);
+}
+
+static int certus_read_user_register(struct pld_device *pld_device, uint32_t 
*user)
+{
+       if (!pld_device)
+               return ERROR_FAIL;
+
+       struct lattice_pld_device *certus_info = pld_device->driver_priv;
+
+       if (!certus_info || !certus_info->tap)
+               return ERROR_FAIL;
+
+       return certus_read_user(certus_info->tap, user, 0x0);
+}
+
+COMMAND_HANDLER(certus_read_status_command_handler)
+{
+       int dev_id;
+       uint64_t status;
+
+       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);
+       if (!device) {
+               command_print(CMD, "pld device '#%s' is out of bounds", 
CMD_ARGV[0]);
+               return ERROR_FAIL;
+       }
+
+       int retval = certus_read_status_register(device, &status);
+       if (retval == ERROR_OK)
+               command_print(CMD, "0x%016" PRIx64 "", status);
+
+       return retval;
+}
+
+COMMAND_HANDLER(certus_read_user_register_command_handler)
+{
+       int dev_id;
+       uint32_t user;
+
+       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);
+       if (!device) {
+               command_print(CMD, "pld device '#%s' is out of bounds", 
CMD_ARGV[0]);
+               return ERROR_FAIL;
+       }
+
+       int retval = certus_read_user_register(device, &user);
+       if (retval == ERROR_OK)
+               command_print(CMD, "0x%8.8" PRIx32 "", user);
+
+       return retval;
+}
+
+PLD_DEVICE_COMMAND_HANDLER(certus_pld_device_command)
+{
+       if (CMD_ARGC != 2)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
+       if (!tap) {
+               command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
+               return ERROR_FAIL;
+       }
+
+       struct lattice_pld_device *certus_info = malloc(sizeof(struct 
lattice_pld_device));
+       if (!certus_info) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+       certus_info->tap = tap;
+
+       pld->driver_priv = certus_info;
+
+       return ERROR_OK;
+}
+
+static const struct command_registration certus_exec_command_handlers[] = {
+       {
+               .name = "read_status",
+               .mode = COMMAND_EXEC,
+               .handler = certus_read_status_command_handler,
+               .help = "reading status register from FPGA",
+               .usage = "num_pld",
+       }, {
+               .name = "read_user",
+               .mode = COMMAND_EXEC,
+               .handler = certus_read_user_register_command_handler,
+               .help = "reading user register from FPGA",
+               .usage = "num_pld",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration certus_command_handler[] = {
+       {
+               .name = "certus",
+               .mode = COMMAND_ANY,
+               .help = "certus specific commands",
+               .usage = "",
+               .chain = certus_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct pld_driver certus_pld = {
+       .name = "certus",
+       .commands = certus_command_handler,
+       .pld_device_command = &certus_pld_device_command,
+       .load = &certus_load_command,
+};
diff --git a/src/pld/ecp.h b/src/pld/ecp.h
deleted file mode 100644
index 9a627ca035..0000000000
--- a/src/pld/ecp.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/***************************************************************************
- *   Copyright (C) 2022 by Daniel Anselmi                                  *
- *   danse...@gmx.ch                                                       *
- ***************************************************************************/
-
-#ifndef OPENOCD_PLD_ECP_H
-#define OPENOCD_PLD_ECP_H
-
-#include <jtag/jtag.h>
-
-struct ecp_pld_device {
-       struct jtag_tap *tap;
-};
-
-struct ecp_devices_preload_length_elem {
-       uint32_t id;
-       size_t preload_length;
-};
-
-void ecp_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t 
endstate);
-int ecp_read_register(struct jtag_tap *tap, uint8_t cmd, uint32_t *in_val,
-                                                       uint32_t out_val, bool 
do_idle);
-int ecp_get_preload_length(uint32_t id, const struct 
ecp_devices_preload_length_elem *elems,
-                                               size_t num_elems, size_t 
*length);
-int ecp_preload(struct jtag_tap *tap, size_t length);
-
-#endif /* OPENOCD_PLD_ECP_H */
diff --git a/src/pld/ecp2_3.c b/src/pld/ecp2_3.c
index 99519fb9fe..987094c6dc 100644
--- a/src/pld/ecp2_3.c
+++ b/src/pld/ecp2_3.c
@@ -9,9 +9,9 @@
 #include "config.h"
 #endif
 
-#include "ecp.h"
+#include "lattice.h"
 #include "pld.h"
-#include "ecp_bit.h"
+#include "lattice_bit.h"
 
 #define LSCC_REFRESH         0x23
 #define ISC_ENABLE           0x15
@@ -23,6 +23,7 @@
 #define BYPASS               0xFF
 #define LSCC_READ_STATUS     0x53
 #define LSCC_BITSTREAM_BURST 0x02
+#define PRELOAD              0x1C
 
 #define STATUS_DONE_BIT        0x00020000
 #define STATUS_ERROR_BITS_ECP2 0x00040003
@@ -30,7 +31,7 @@
 #define REGISTER_ALL_BITS_1    0xffffffff
 #define REGISTER_ALL_BITS_0    0x00000000
 
-static const struct ecp_devices_preload_length_elem 
ecp2_devices_preload_length[] = {
+static const struct lattice_devices_preload_length_elem 
ecp2_devices_preload_length[] = {
        {0x01270043,  654 /* ecp2-6e */},
        {0x01271043,  643 /* ecp2-12e */},
        {0x01272043,  827 /* ecp2-20e */},
@@ -44,7 +45,7 @@ static const struct ecp_devices_preload_length_elem 
ecp2_devices_preload_length[
        {0x0127D043, 1311 /* ecp2m100e */},
 };
 
-static const struct ecp_devices_preload_length_elem 
ecp3_devices_preload_length[] = {
+static const struct lattice_devices_preload_length_elem 
ecp3_devices_preload_length[] = {
        {0x01010043,  467 /* ecp3 lae3-17ea & lfe3-17ea*/},
        {0x01012043,  675 /* ecp3 lae3-35ea & lfe3-35ea*/},
        {0x01014043, 1077 /* ecp3 lfe3-70ea & lfe3-70e & lfe3-95ea && 
lfe3-95e*/},
@@ -53,13 +54,13 @@ static const struct ecp_devices_preload_length_elem 
ecp3_devices_preload_length[
 
 static int ecp2_get_preload_length(uint32_t id, size_t *length)
 {
-       return ecp_get_preload_length(id, ecp2_devices_preload_length,
+       return lattice_get_preload_length(id, ecp2_devices_preload_length,
                                                                
ARRAY_SIZE(ecp2_devices_preload_length), length);
 }
 
 static int ecp3_get_preload_length(uint32_t id, size_t *length)
 {
-       return ecp_get_preload_length(id, ecp3_devices_preload_length,
+       return lattice_get_preload_length(id, ecp3_devices_preload_length,
                                                                
ARRAY_SIZE(ecp3_devices_preload_length), length);
 }
 
@@ -75,17 +76,17 @@ static int ecp2_3_preload(struct jtag_tap *tap, bool 
is_ecp3)
        if (retval != ERROR_OK)
                return retval;
 
-       return ecp_preload(tap, length);
+       return lattice_preload(tap, PRELOAD, length);
 }
 
 static int ecp2_3_read_status(struct jtag_tap *tap, uint32_t *status, uint32_t 
out)
 {
-       return ecp_read_register(tap, LSCC_READ_STATUS, status, out, false);
+       return lattice_read_u32_register(tap, LSCC_READ_STATUS, status, out, 
false);
 }
 
 static int ecp2_3_read_user(struct jtag_tap *tap, uint32_t *user, uint32_t out)
 {
-       return ecp_read_register(tap, READ_USERCODE, user, out, false);
+       return lattice_read_u32_register(tap, READ_USERCODE, user, out, false);
 }
 
 static int ecp2_3_verify_usercode(struct jtag_tap *tap, uint32_t out,
@@ -125,10 +126,10 @@ static int ecp2_erase_device(struct jtag_tap *tap)
        struct scan_field field;
        uint8_t buffer[4] = {0, 0, 0, 0};
 
-       ecp_set_instr(tap, LSCC_RESET_ADDRESS, TAP_IDLE);
+       lattice_set_instr(tap, LSCC_RESET_ADDRESS, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(2000);
-       ecp_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IRPAUSE);
+       lattice_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IRPAUSE);
        field.num_bits = 32;
        field.out_value = buffer;
        field.in_value = NULL;
@@ -136,7 +137,7 @@ static int ecp2_erase_device(struct jtag_tap *tap)
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(2000);
 
-       ecp_set_instr(tap, ISC_ERASE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_ERASE, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(100000);
        /* after erasing check all bits in user register are cleared */
@@ -152,7 +153,7 @@ static int ecp3_erase_device(struct jtag_tap *tap)
        uint8_t buffer[4] = {0xff, 0xff, 0xff, 0xff};
 
        /* program user code with all bits set */
-       ecp_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IRPAUSE);
+       lattice_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IRPAUSE);
        field.num_bits = 32;
        field.out_value = buffer;
        field.in_value = NULL;
@@ -168,11 +169,11 @@ static int ecp3_erase_device(struct jtag_tap *tap)
        if (retval != ERROR_OK)
                return retval;
 
-       ecp_set_instr(tap, ISC_ERASE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_ERASE, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(2000000);
 
-       ecp_set_instr(tap, LSCC_RESET_ADDRESS, TAP_IDLE);
+       lattice_set_instr(tap, LSCC_RESET_ADDRESS, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(2000);
 
@@ -183,10 +184,10 @@ static int ecp3_erase_device(struct jtag_tap *tap)
 
 static int ecp2_3_exit_programming_mode(struct jtag_tap *tap)
 {
-       ecp_set_instr(tap, ISC_DISABLE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(200000);
-       ecp_set_instr(tap, BYPASS, TAP_IDLE);
+       lattice_set_instr(tap, BYPASS, TAP_IDLE);
        jtag_add_runtest(100, TAP_IDLE);
        jtag_add_sleep(1000);
        return jtag_execute_queue();
@@ -197,11 +198,11 @@ static int ecp2_3_write_user(struct jtag_tap *tap, 
uint32_t user)
        struct scan_field field;
        uint8_t buffer[4];
 
-       ecp_set_instr(tap, ISC_ENABLE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(20000);
 
-       ecp_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IDLE);
 
        h_u32_to_le(buffer, user);
        field.num_bits = 32;
@@ -211,20 +212,20 @@ static int ecp2_3_write_user(struct jtag_tap *tap, 
uint32_t user)
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(2000);
 
-       ecp_set_instr(tap, ISC_DISABLE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(200000);
 
        return jtag_execute_queue();
 }
 
-static int ecp2_3_program_fuse_map(struct jtag_tap *tap, struct ecp_bit_file 
*bit_file)
+static int ecp2_3_program_fuse_map(struct jtag_tap *tap, struct 
lattice_bit_file *bit_file)
 {
        struct scan_field field;
-       ecp_set_instr(tap, LSCC_RESET_ADDRESS, TAP_IDLE);
+       lattice_set_instr(tap, LSCC_RESET_ADDRESS, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(2000);
-       ecp_set_instr(tap, LSCC_BITSTREAM_BURST, TAP_IDLE);
+       lattice_set_instr(tap, LSCC_BITSTREAM_BURST, TAP_IDLE);
        field.num_bits = (bit_file->raw_bit.length - bit_file->offset) * 8;
        field.out_value = bit_file->raw_bit.data + bit_file->offset;
        field.in_value = NULL;
@@ -234,7 +235,7 @@ static int ecp2_3_program_fuse_map(struct jtag_tap *tap, 
struct ecp_bit_file *bi
        return jtag_execute_queue();
 }
 
-static int ecp3_load(struct jtag_tap *tap, struct ecp_bit_file *bit_file)
+static int ecp3_load(struct jtag_tap *tap, struct lattice_bit_file *bit_file)
 {
        /* Program Bscan register */
        int retval = ecp2_3_preload(tap, true);
@@ -242,10 +243,10 @@ static int ecp3_load(struct jtag_tap *tap, struct 
ecp_bit_file *bit_file)
                return retval;
 
        /* Enable the programming mode */
-       ecp_set_instr(tap, LSCC_REFRESH, TAP_IDLE);
+       lattice_set_instr(tap, LSCC_REFRESH, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(50000);
-       ecp_set_instr(tap, ISC_ENABLE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(20000);
 
@@ -268,15 +269,15 @@ static int ecp3_load(struct jtag_tap *tap, struct 
ecp_bit_file *bit_file)
        return ecp2_3_verify_status_register(tap, out, expected, mask);
 }
 
-static int ecp2_load(struct jtag_tap *tap, struct ecp_bit_file *bit_file)
+static int ecp2_load(struct jtag_tap *tap, struct lattice_bit_file *bit_file)
 {
        int retval = ecp2_3_preload(tap, false);
        if (retval != ERROR_OK)
                return retval;
 
        /* Enable the programming mode */
-       ecp_set_instr(tap, LSCC_REFRESH, TAP_IDLE);
-       ecp_set_instr(tap, ISC_ENABLE, TAP_IDLE);
+       lattice_set_instr(tap, LSCC_REFRESH, TAP_IDLE);
+       lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(20000);
 
@@ -302,7 +303,7 @@ static int ecp2_load(struct jtag_tap *tap, struct 
ecp_bit_file *bit_file)
 
 static int ecp2_3_read_status_register(struct pld_device *pld_device, uint32_t 
*status)
 {
-       struct ecp_pld_device *ecp2_3_info;
+       struct lattice_pld_device *ecp2_3_info;
 
        if (!pld_device)
                return ERROR_FAIL;
@@ -317,7 +318,7 @@ static int ecp2_3_read_status_register(struct pld_device 
*pld_device, uint32_t *
 
 static int ecp2_3_read_user_register(struct pld_device *pld_device, uint32_t 
*user)
 {
-       struct ecp_pld_device *ecp2_3_info;
+       struct lattice_pld_device *ecp2_3_info;
 
        if (!pld_device)
                return ERROR_FAIL;
@@ -332,7 +333,7 @@ static int ecp2_3_read_user_register(struct pld_device 
*pld_device, uint32_t *us
 
 static int ecp2_3_write_user_register(struct pld_device *pld_device, uint32_t 
user)
 {
-       struct ecp_pld_device *ecp2_3_info;
+       struct lattice_pld_device *ecp2_3_info;
 
        if (!pld_device)
                return ERROR_FAIL;
@@ -414,8 +415,8 @@ COMMAND_HANDLER(ecp2_3_write_user_register_command_handler)
 
 static int ecp2_3_load(struct pld_device *pld_device, const char *filename)
 {
-       struct ecp_pld_device *ecp2_3_info;
-       struct ecp_bit_file bit_file;
+       struct lattice_pld_device *ecp2_3_info;
+       struct lattice_bit_file bit_file;
 
        if (!pld_device || !pld_device->driver_priv)
                return ERROR_FAIL;
@@ -429,7 +430,7 @@ static int ecp2_3_load(struct pld_device *pld_device, const 
char *filename)
                return ERROR_FAIL;
        uint32_t id = tap->idcode;
 
-       int retval = ecp_read_file(&bit_file, filename, false);
+       int retval = lattice_read_file(&bit_file, filename, false);
        if (retval != ERROR_OK)
                return retval;
 
@@ -453,7 +454,7 @@ static int ecp2_3_load(struct pld_device *pld_device, const 
char *filename)
 
 PLD_DEVICE_COMMAND_HANDLER(ecp2_3_pld_device_command)
 {
-       struct ecp_pld_device *ecp2_3_info;
+       struct lattice_pld_device *ecp2_3_info;
 
        if (CMD_ARGC != 2)
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -464,7 +465,7 @@ PLD_DEVICE_COMMAND_HANDLER(ecp2_3_pld_device_command)
                return ERROR_FAIL;
        }
 
-       ecp2_3_info = malloc(sizeof(struct ecp_pld_device));
+       ecp2_3_info = malloc(sizeof(struct lattice_pld_device));
        if (!ecp2_3_info) {
                LOG_ERROR("Out of memory");
                return ERROR_FAIL;
diff --git a/src/pld/ecp5.c b/src/pld/ecp5.c
index d6c2970793..11e0996ee9 100644
--- a/src/pld/ecp5.c
+++ b/src/pld/ecp5.c
@@ -9,9 +9,9 @@
 #include "config.h"
 #endif
 
-#include "ecp.h"
+#include "lattice.h"
 #include "pld.h"
-#include "ecp_bit.h"
+#include "lattice_bit.h"
 
 #define BYPASS               0xFF
 #define ISC_ENABLE           0xC6
@@ -22,6 +22,7 @@
 #define READ_USERCODE        0xC0
 #define ISC_DISABLE          0x26
 #define ISC_PROGRAM_USERCODE 0xC2
+#define PRELOAD              0x1C
 
 #define STATUS_DONE_BIT        0x00000100
 #define STATUS_ERROR_BITS      0x00020040
@@ -29,7 +30,7 @@
 #define STATUS_FAIL_FLAG       0x00002000
 #define STATUS_BUSY_FLAG       0x00001000
 
-static const struct ecp_devices_preload_length_elem 
ecp5_devices_preload_length[] = {
+static const struct lattice_devices_preload_length_elem 
ecp5_devices_preload_length[] = {
        {0x21111043,  409}, /* "LAE5U-12F & LFE5U-12F" */
        {0x41111043,  409}, /* "LFE5U-25F" */
        {0x41112043,  510}, /* "LFE5U-45F" */
@@ -44,7 +45,7 @@ static const struct ecp_devices_preload_length_elem 
ecp5_devices_preload_length[
 
 static int ecp5_get_preload_length(uint32_t id, size_t *length)
 {
-       return ecp_get_preload_length(id, ecp5_devices_preload_length, 
ARRAY_SIZE(ecp5_devices_preload_length), length);
+       return lattice_get_preload_length(id, ecp5_devices_preload_length, 
ARRAY_SIZE(ecp5_devices_preload_length), length);
 }
 
 static int ecp5_preload(struct jtag_tap *tap)
@@ -55,24 +56,24 @@ static int ecp5_preload(struct jtag_tap *tap)
        if (retval != ERROR_OK)
                return retval;
 
-       return ecp_preload(tap, length);
+       return lattice_preload(tap, PRELOAD, length);
 }
 
 static int ecp5_read_status(struct jtag_tap *tap, uint32_t *status, uint32_t 
out, bool do_idle)
 {
-       return ecp_read_register(tap, LSCC_READ_STATUS, status, out, do_idle);
+       return lattice_read_u32_register(tap, LSCC_READ_STATUS, status, out, 
do_idle);
 }
 
 static int ecp5_read_user(struct jtag_tap *tap, uint32_t *user, uint32_t out)
 {
-       return ecp_read_register(tap, READ_USERCODE, user, out, true);
+       return lattice_read_u32_register(tap, READ_USERCODE, user, out, true);
 }
 
 static int ecp5_enable_sram_programming(struct jtag_tap *tap)
 {
        struct scan_field field;
 
-       ecp_set_instr(tap, ISC_ENABLE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
 
        uint8_t buffer = 0x0;
        field.num_bits = 8;
@@ -89,7 +90,7 @@ static int ecp5_erase_sram(struct jtag_tap *tap)
 {
        struct scan_field field;
 
-       ecp_set_instr(tap, ISC_ERASE, TAP_IRPAUSE);
+       lattice_set_instr(tap, ISC_ERASE, TAP_IRPAUSE);
 
        uint8_t buffer = 1;
        field.num_bits = 8;
@@ -105,7 +106,7 @@ static int ecp5_init_address(struct jtag_tap *tap)
 {
        struct scan_field field;
 
-       ecp_set_instr(tap, LSC_INIT_ADDRESS, TAP_IDLE);
+       lattice_set_instr(tap, LSC_INIT_ADDRESS, TAP_IDLE);
        uint8_t buffer = 1;
        field.num_bits = 8;
        field.out_value = &buffer;
@@ -137,11 +138,11 @@ static int ecp5_write_user(struct jtag_tap *tap, uint32_t 
user)
        struct scan_field field;
        uint8_t buffer[4];
 
-       ecp_set_instr(tap, ISC_ENABLE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(20000);
 
-       ecp_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_PROGRAM_USERCODE, TAP_IDLE);
 
        h_u32_to_le(buffer, user);
        field.num_bits = 32;
@@ -151,7 +152,7 @@ static int ecp5_write_user(struct jtag_tap *tap, uint32_t 
user)
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(2000);
 
-       ecp_set_instr(tap, ISC_DISABLE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
        jtag_add_runtest(5, TAP_IDLE);
        jtag_add_sleep(200000);
 
@@ -160,20 +161,20 @@ static int ecp5_write_user(struct jtag_tap *tap, uint32_t 
user)
 
 static int ecp5_exit_programming_mode(struct jtag_tap *tap)
 {
-       ecp_set_instr(tap, ISC_DISABLE, TAP_IDLE);
+       lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
        jtag_add_runtest(2, TAP_IDLE);
        jtag_add_sleep(200000);
-       ecp_set_instr(tap, BYPASS, TAP_IDLE);
+       lattice_set_instr(tap, BYPASS, TAP_IDLE);
        jtag_add_runtest(2, TAP_IDLE);
        jtag_add_sleep(1000);
        return jtag_execute_queue();
 }
 
-static int ecp5_program_fuse_map(struct jtag_tap *tap, struct ecp_bit_file 
*bit_file)
+static int ecp5_program_fuse_map(struct jtag_tap *tap, struct lattice_bit_file 
*bit_file)
 {
        struct scan_field field;
 
-       ecp_set_instr(tap, LSC_BITSTREAM_BURST, TAP_IDLE);
+       lattice_set_instr(tap, LSC_BITSTREAM_BURST, TAP_IDLE);
        jtag_add_runtest(2, TAP_IDLE);
        jtag_add_sleep(10000);
 
@@ -182,14 +183,14 @@ static int ecp5_program_fuse_map(struct jtag_tap *tap, 
struct ecp_bit_file *bit_
        field.in_value = NULL;
        jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
 
-       ecp_set_instr(tap, BYPASS, TAP_IDLE);
+       lattice_set_instr(tap, BYPASS, TAP_IDLE);
        jtag_add_runtest(100, TAP_IDLE);
        jtag_add_sleep(10000);
 
        return jtag_execute_queue();
 }
 
-static int ecp5_load(struct jtag_tap *tap, struct ecp_bit_file *bit_file)
+static int ecp5_load(struct jtag_tap *tap, struct lattice_bit_file *bit_file)
 {
        int retval = ecp5_preload(tap);
        if (retval != ERROR_OK)
@@ -234,12 +235,12 @@ static int ecp5_load(struct jtag_tap *tap, struct 
ecp_bit_file *bit_file)
 
 static int ecp5_load_command(struct pld_device *pld_device, const char 
*filename)
 {
-       struct ecp_bit_file bit_file;
+       struct lattice_bit_file bit_file;
 
        if (!pld_device || !pld_device->driver_priv)
                return ERROR_FAIL;
 
-       struct ecp_pld_device *ecp5_info = pld_device->driver_priv;
+       struct lattice_pld_device *ecp5_info = pld_device->driver_priv;
        if (!ecp5_info || !ecp5_info->tap)
                return ERROR_FAIL;
        struct jtag_tap *tap = ecp5_info->tap;
@@ -248,11 +249,11 @@ static int ecp5_load_command(struct pld_device 
*pld_device, const char *filename
                return ERROR_FAIL;
        uint32_t id = tap->idcode;
 
-       int retval = ecp_read_file(&bit_file, filename, true);
+       int retval = lattice_read_file(&bit_file, filename, true);
        if (retval != ERROR_OK)
                return retval;
 
-       if (!bit_file.encrypted && id != bit_file.idcode)
+       if (bit_file.has_id && id != bit_file.idcode)
                LOG_WARNING("id on device and bit-stream don't match!");
 
        retval = ecp5_load(tap, &bit_file);
@@ -265,7 +266,7 @@ static int ecp5_read_status_register(struct pld_device 
*pld_device, uint32_t *st
        if (!pld_device)
                return ERROR_FAIL;
 
-       struct ecp_pld_device *ecp5_info = pld_device->driver_priv;
+       struct lattice_pld_device *ecp5_info = pld_device->driver_priv;
 
        if (!ecp5_info || !ecp5_info->tap)
                return ERROR_FAIL;
@@ -278,7 +279,7 @@ static int ecp5_read_user_register(struct pld_device 
*pld_device, uint32_t *user
        if (!pld_device)
                return ERROR_FAIL;
 
-       struct ecp_pld_device *ecp5_info = pld_device->driver_priv;
+       struct lattice_pld_device *ecp5_info = pld_device->driver_priv;
 
        if (!ecp5_info || !ecp5_info->tap)
                return ERROR_FAIL;
@@ -291,7 +292,7 @@ static int ecp5_write_user_register(struct pld_device 
*pld_device, uint32_t user
        if (!pld_device)
                return ERROR_FAIL;
 
-       struct ecp_pld_device *ecp5_info = pld_device->driver_priv;
+       struct lattice_pld_device *ecp5_info = pld_device->driver_priv;
 
        if (!ecp5_info || !ecp5_info->tap)
                return ERROR_FAIL;
@@ -374,7 +375,7 @@ PLD_DEVICE_COMMAND_HANDLER(ecp5_pld_device_command)
                return ERROR_FAIL;
        }
 
-       struct ecp_pld_device *ecp5_info = malloc(sizeof(struct 
ecp_pld_device));
+       struct lattice_pld_device *ecp5_info = malloc(sizeof(struct 
lattice_pld_device));
        if (!ecp5_info) {
                LOG_ERROR("Out of memory");
                return ERROR_FAIL;
diff --git a/src/pld/ecp.c b/src/pld/lattice.c
similarity index 65%
rename from src/pld/ecp.c
rename to src/pld/lattice.c
index 4a805cdb6f..db0ec2c52d 100644
--- a/src/pld/ecp.c
+++ b/src/pld/lattice.c
@@ -9,11 +9,10 @@
 #include "config.h"
 #endif
 
-#include "ecp.h"
+#include "lattice.h"
 
-#define PRELOAD 0x1C
 
-void ecp_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t 
endstate)
+void lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t 
endstate)
 {
        struct scan_field field;
 
@@ -26,13 +25,13 @@ void ecp_set_instr(struct jtag_tap *tap, uint8_t new_instr, 
tap_state_t endstate
        free(t);
 }
 
-int ecp_read_register(struct jtag_tap *tap, uint8_t cmd, uint32_t *in_val,
+int lattice_read_u32_register(struct jtag_tap *tap, uint8_t cmd, uint32_t 
*in_val,
                                                        uint32_t out_val, bool 
do_idle)
 {
        struct scan_field field;
        uint8_t buffer[4];
 
-       ecp_set_instr(tap, cmd, TAP_IDLE);
+       lattice_set_instr(tap, cmd, TAP_IDLE);
        if (do_idle) {
                jtag_add_runtest(2, TAP_IDLE);
                jtag_add_sleep(1000);
@@ -50,7 +49,26 @@ int ecp_read_register(struct jtag_tap *tap, uint8_t cmd, 
uint32_t *in_val,
        return retval;
 }
 
-int ecp_get_preload_length(uint32_t id, const struct 
ecp_devices_preload_length_elem *elems,
+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];
+
+       lattice_set_instr(tap, cmd, TAP_IDLE);
+       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);
+       int retval = jtag_execute_queue();
+       if (retval == ERROR_OK)
+               *in_val = le_to_h_u64(buffer);
+
+       return retval;
+}
+
+int lattice_get_preload_length(uint32_t id, const struct 
lattice_devices_preload_length_elem *elems,
                                                size_t num_elems, size_t 
*length)
 {
        for (size_t i = 0; i < num_elems; ++i) {
@@ -63,12 +81,12 @@ int ecp_get_preload_length(uint32_t id, const struct 
ecp_devices_preload_length_
 }
 
 
-int ecp_preload(struct jtag_tap *tap, size_t length)
+int lattice_preload(struct jtag_tap *tap, uint8_t preload_cmd, size_t length)
 {
        struct scan_field field;
        size_t sz_bytes = DIV_ROUND_UP(length, 8);
 
-       ecp_set_instr(tap, PRELOAD, TAP_IDLE);
+       lattice_set_instr(tap, preload_cmd, TAP_IDLE);
        uint8_t *buffer = malloc(sz_bytes);
        if (!buffer) {
                LOG_ERROR("Out of memory");
diff --git a/src/pld/lattice.h b/src/pld/lattice.h
new file mode 100644
index 0000000000..8f6f1ca882
--- /dev/null
+++ b/src/pld/lattice.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ *   Copyright (C) 2022 by Daniel Anselmi                                  *
+ *   danse...@gmx.ch                                                       *
+ ***************************************************************************/
+
+#ifndef OPENOCD_PLD_LATTICE_H
+#define OPENOCD_PLD_LATTICE_H
+
+#include <jtag/jtag.h>
+
+struct lattice_pld_device {
+       struct jtag_tap *tap;
+};
+
+struct lattice_devices_preload_length_elem {
+       uint32_t id;
+       size_t preload_length;
+};
+
+void lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t 
endstate);
+int lattice_read_u32_register(struct jtag_tap *tap, uint8_t cmd, uint32_t 
*in_val,
+                                                       uint32_t out_val, bool 
do_idle);
+int lattice_read_u64_register(struct jtag_tap *tap, uint8_t cmd, uint64_t 
*in_val,
+                                                       uint64_t out_val);
+int lattice_get_preload_length(uint32_t id, const struct 
lattice_devices_preload_length_elem *elems,
+                                               size_t num_elems, size_t 
*length);
+int lattice_preload(struct jtag_tap *tap, uint8_t preload_cmd, size_t length);
+
+#endif /* OPENOCD_PLD_LATTICE_H */
diff --git a/src/pld/ecp_bit.c b/src/pld/lattice_bit.c
similarity index 84%
rename from src/pld/ecp_bit.c
rename to src/pld/lattice_bit.c
index db0ba2b6ac..0d4795c65e 100644
--- a/src/pld/ecp_bit.c
+++ b/src/pld/lattice_bit.c
@@ -8,7 +8,7 @@
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
-#include "ecp_bit.h"
+#include "lattice_bit.h"
 #include "raw_bit.h"
 #include "pld.h"
 #include <sys/stat.h>
@@ -22,16 +22,14 @@
 #define SEEK_ID           4
 #define DONE              5
 
-static int ecp_read_bit_file(struct ecp_bit_file *bit_file, const char 
*filename, bool v5)
+static int lattice_read_bit_file(struct lattice_bit_file *bit_file, const char 
*filename, enum bit_file_version version)
 {
        int retval = cpld_read_raw_bit_file(&bit_file->raw_bit, filename);
        if (retval != ERROR_OK)
                return retval;
 
-       bit_file->idcode = 0;
        bit_file->part = 0;
-
-       bit_file->encrypted = false;
+       bit_file->has_id = false;
        int state = SEEK_HEADER_START;
        for (size_t pos = 1; pos < bit_file->raw_bit.length && state != DONE; 
++pos) {
                switch (state) {
@@ -46,7 +44,7 @@ static int ecp_read_bit_file(struct ecp_bit_file *bit_file, 
const char *filename
                                LOG_INFO("part found: %s\n", bit_file->part);
                        } else if (bit_file->raw_bit.data[pos] == 0xff && 
bit_file->raw_bit.data[pos - 1] == 0) {
                                bit_file->offset = pos;
-                               state = (v5) ? SEEK_PREAMBLE : DONE;
+                               state = (version != ecp2_3) ? SEEK_PREAMBLE : 
DONE;
                        }
                        break;
                case SEEK_PREAMBLE:
@@ -59,7 +57,11 @@ static int ecp_read_bit_file(struct ecp_bit_file *bit_file, 
const char *filename
                                if (bit_file->raw_bit.data[pos - 1] == 0xbf &&
                                        bit_file->raw_bit.data[pos - 2] == 0xff 
&&
                                        bit_file->raw_bit.data[pos - 3] == 
0xff) {
-                                       bit_file->encrypted = 1;
+                                       state = DONE;
+                               }
+                               if (bit_file->raw_bit.data[pos - 1] == 0xbe &&
+                                       bit_file->raw_bit.data[pos - 2] == 0xff 
&&
+                                       bit_file->raw_bit.data[pos - 3] == 
0xff) {
                                        state = DONE;
                                }
                        }
@@ -67,6 +69,7 @@ static int ecp_read_bit_file(struct ecp_bit_file *bit_file, 
const char *filename
                case SEEK_ID:
                        if (pos + 7 < bit_file->raw_bit.length && 
bit_file->raw_bit.data[pos] == 0xe2) {
                                bit_file->idcode = 
be_to_h_u32(&bit_file->raw_bit.data[pos + 4]);
+                               bit_file->has_id = true;
                                state = DONE;
                        }
                        break;
@@ -86,7 +89,7 @@ static int ecp_read_bit_file(struct ecp_bit_file *bit_file, 
const char *filename
        return ERROR_OK;
 }
 
-int ecp_read_file(struct ecp_bit_file *bit_file, const char *filename, bool v5)
+int lattice_read_file(struct lattice_bit_file *bit_file, const char *filename, 
enum bit_file_version version)
 {
        struct stat input_stat;
 
@@ -116,7 +119,7 @@ int ecp_read_file(struct ecp_bit_file *bit_file, const char 
*filename, bool v5)
        }
 
        if (strcasecmp(file_suffix_pos, ".bit") == 0)
-               return ecp_read_bit_file(bit_file, filename, v5);
+               return lattice_read_bit_file(bit_file, filename, version);
 
        LOG_ERROR("Filetype not supported");
        return ERROR_PLD_FILE_LOAD_FAILED;
diff --git a/src/pld/ecp_bit.h b/src/pld/lattice_bit.h
similarity index 63%
rename from src/pld/ecp_bit.h
rename to src/pld/lattice_bit.h
index 6570acd77c..d1a8633ee3 100644
--- a/src/pld/ecp_bit.h
+++ b/src/pld/lattice_bit.h
@@ -5,22 +5,24 @@
  *   danse...@gmx.ch                                                       *
  ***************************************************************************/
 
-#ifndef OPENOCD_PLD_ECP_BIT_H
-#define OPENOCD_PLD_ECP_BIT_H
+#ifndef OPENOCD_PLD_LATTICE_BIT_H
+#define OPENOCD_PLD_LATTICE_BIT_H
 
 #include "helper/types.h"
 #include "raw_bit.h"
 
 
-struct ecp_bit_file {
+struct lattice_bit_file {
        struct raw_bit_file raw_bit;
        size_t offset;
        uint32_t idcode;
        const char *part; /* reuses memory in raw_bit_file */
-       bool encrypted;
+       bool has_id;
 };
 
-int ecp_read_file(struct ecp_bit_file *bit_file, const char *filename, bool 
v5);
+enum bit_file_version {ecp2_3, ecp5, certus};
 
+int lattice_read_file(struct lattice_bit_file *bit_file, const char *filename, 
enum bit_file_version version);
 
-#endif /* OPENOCD_PLD_ECP_BIT_H */
+
+#endif /* OPENOCD_PLD_LATTICE_BIT_H */
diff --git a/src/pld/pld.c b/src/pld/pld.c
index 34a0283781..97c894e585 100644
--- a/src/pld/pld.c
+++ b/src/pld/pld.c
@@ -21,8 +21,11 @@ extern struct pld_driver virtex2_pld;
 extern struct pld_driver ecp2_3_pld;
 extern struct pld_driver ecp5_pld;
 extern struct pld_driver trion_pld;
+extern struct pld_driver certus_pld;
+
 
 static struct pld_driver *pld_drivers[] = {
+       &certus_pld,
        &ecp2_3_pld,
        &ecp5_pld,
        &trion_pld,
diff --git a/tcl/board/certuspro_evaluation.cfg 
b/tcl/board/certuspro_evaluation.cfg
new file mode 100644
index 0000000000..5ff2a1e329
--- /dev/null
+++ b/tcl/board/certuspro_evaluation.cfg
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# 
https://www.latticesemi.com/products/developmentboardsandkits/certuspro-nx-versa-board
+
+adapter driver ftdi
+ftdi vid_pid 0x0403 0x6010
+
+ftdi channel 0
+ftdi layout_init 0x0008 0x008b
+reset_config none
+transport select jtag
+adapter speed 10000
+
+source [find fpga/lattice_certuspro.cfg]
diff --git a/tcl/fpga/lattice_certus.cfg b/tcl/fpga/lattice_certus.cfg
new file mode 100644
index 0000000000..bfd1c16b3c
--- /dev/null
+++ b/tcl/fpga/lattice_certus.cfg
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+if { [info exists CHIPNAME] } {
+       set _CHIPNAME $_CHIPNAME
+} else {
+       set _CHIPNAME certus
+}
+
+# Lattice Certus
+#
+# Certus NX LFD2NX-17     0x310f0043
+# Certus NX LFD2NX-40     0x310f1043
+
+
+jtag newtap $_CHIPNAME tap -irlen 8 -irmask 0x83 -ircapture 0x1 \
+       -expected-id 0x310F1043 -expected-id 0x310F0043
+
+pld device certus $_CHIPNAME.tap
diff --git a/tcl/fpga/lattice_certuspro.cfg b/tcl/fpga/lattice_certuspro.cfg
new file mode 100644
index 0000000000..d328c1d995
--- /dev/null
+++ b/tcl/fpga/lattice_certuspro.cfg
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+if { [info exists CHIPNAME] } {
+       set _CHIPNAME $_CHIPNAME
+} else {
+       set _CHIPNAME certuspro
+}
+
+# Lattice CertusPro
+#
+# 0x010f4043 - LFCPNX-100
+# 0x     043 - LFCPNX-50
+
+jtag newtap $_CHIPNAME tap -irlen 8 -irmask 0x83 -ircapture 0x1 \
+       -expected-id 0x010f4043
+#    -expected-id 0x01112043
+
+pld device certus $_CHIPNAME.tap

-- 


Reply via email to