#include "lattice_bit.h"
#include "ecp2_3.h"
#include "ecp5.h"
+#include "certus.h"
#define PRELOAD 0x1C
{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)
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;
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;
}
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;
}
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;
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;
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");
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;
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;
}
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;
}
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;
}
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;
}
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;
}
.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
};
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,
};