pld: add support for efinix devices 88/7288/28
authorDaniel Anselmi <danselmi@gmx.ch>
Mon, 12 Dec 2022 08:49:51 +0000 (09:49 +0100)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sun, 30 Apr 2023 14:54:18 +0000 (14:54 +0000)
Change-Id: Ie520e761c255ba1335d5aab9c6825f160a6151d9
Signed-off-by: Daniel Anselmi <danselmi@gmx.ch>
Reviewed-on: https://review.openocd.org/c/openocd/+/7288
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
doc/openocd.texi
src/pld/Makefile.am
src/pld/efinix.c [new file with mode: 0644]
src/pld/pld.c
tcl/board/trion_t20_bga256.cfg [new file with mode: 0644]
tcl/fpga/efinix_titanium.cfg [new file with mode: 0644]
tcl/fpga/efinix_trion.cfg [new file with mode: 0644]

index 24de2ce94da27d341e8f58c96e77919570274c32..6037b8bb23cda409031a73a9385c68f50e6c60a6 100644 (file)
@@ -8524,6 +8524,12 @@ The load command for the FPGA @var{num} will use a length for the preload of @va
 @end deffn
 
 
+@deffn {FPGA Driver} {efinix}
+Both families (Trion and Titanium) sold by Efinix are supported as both use the same protocol for In-System Configuration.
+This driver can be used to load the bitstream into the FPGA.
+@end deffn
+
+
 
 @node General Commands
 @chapter General Commands
index 8ad4296f3aeda525417a5dcc7e74412d8e6aa9d5..be33bcd0982d3656c1ebfc59d6104122a1cae186 100644 (file)
@@ -5,6 +5,7 @@ noinst_LTLIBRARIES += %D%/libpld.la
        %D%/certus.c \
        %D%/ecp2_3.c \
        %D%/ecp5.c \
+       %D%/efinix.c \
        %D%/lattice.c \
        %D%/lattice_bit.c \
        %D%/pld.c \
diff --git a/src/pld/efinix.c b/src/pld/efinix.c
new file mode 100644 (file)
index 0000000..f084394
--- /dev/null
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ *   Copyright (C) 2022 by Daniel Anselmi                                  *
+ *   danselmi@gmx.ch                                                       *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jtag/jtag.h>
+
+#include "pld.h"
+#include "raw_bit.h"
+
+#define PROGRAM   0x4
+#define ENTERUSER 0x7
+
+#define TRAILING_ZEROS 4000
+#define RUNTEST_START_CYCLES 100
+#define RUNTEST_FINISH_CYCLES 100
+
+struct efinix_pld_device {
+       struct jtag_tap *tap;
+};
+
+static int efinix_read_bit_file(struct raw_bit_file *bit_file, const char *filename)
+{
+       FILE *input_file = fopen(filename, "r");
+       if (!input_file) {
+               LOG_ERROR("couldn't open %s: %s", filename, strerror(errno));
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       fseek(input_file, 0, SEEK_END);
+       long length = ftell(input_file);
+       fseek(input_file, 0, SEEK_SET);
+
+       if (length < 0 || ((length % 3))) {
+               fclose(input_file);
+               LOG_ERROR("Failed to get length from file %s: %s", filename, strerror(errno));
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+       bit_file->length = DIV_ROUND_UP(length, 3);
+
+       bit_file->data = malloc(bit_file->length);
+       if (!bit_file->data) {
+               fclose(input_file);
+               LOG_ERROR("Out of memory");
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       bool end_detected = false;
+       char buffer[3];
+       for (size_t idx = 0; !end_detected && idx < bit_file->length; ++idx) {
+               size_t read_count = fread(buffer, sizeof(char), 3, input_file);
+               end_detected = feof(input_file);
+               if ((read_count == 3 && buffer[2] != '\n') ||
+                       (read_count != 3 && !end_detected) ||
+                       (read_count != 2 && end_detected)) {
+                       fclose(input_file);
+                       free(bit_file->data);
+                       bit_file->data = NULL;
+                       LOG_ERROR("unexpected line length");
+                       return ERROR_PLD_FILE_LOAD_FAILED;
+               }
+
+               if (!isxdigit(buffer[0]) || !isxdigit(buffer[1])) {
+                       fclose(input_file);
+                       free(bit_file->data);
+                       bit_file->data = NULL;
+                       LOG_ERROR("unexpected char in hex string");
+                       return ERROR_PLD_FILE_LOAD_FAILED;
+               }
+               unhexify(&bit_file->data[idx], buffer, 2);
+       }
+
+       fclose(input_file);
+
+       return ERROR_OK;
+}
+
+static int efinix_read_file(struct raw_bit_file *bit_file, const char *filename)
+{
+       if (!filename || !bit_file)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       /* check if binary .bin or ascii .bit/.hex */
+       const char *file_ending_pos = strrchr(filename, '.');
+       if (!file_ending_pos) {
+               LOG_ERROR("Unable to detect filename suffix");
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       if (strcasecmp(file_ending_pos, ".bin") == 0) {
+               return cpld_read_raw_bit_file(bit_file, filename);
+       } else if ((strcasecmp(file_ending_pos, ".bit") == 0) ||
+                       (strcasecmp(file_ending_pos, ".hex") == 0)) {
+               return efinix_read_bit_file(bit_file, filename);
+       }
+
+       LOG_ERROR("Unable to detect filetype");
+       return ERROR_PLD_FILE_LOAD_FAILED;
+}
+
+static int efinix_set_instr(struct jtag_tap *tap, uint8_t new_instr)
+{
+       struct scan_field field;
+       field.num_bits = tap->ir_length;
+       void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
+       if (!t) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+       field.out_value = t;
+       buf_set_u32(t, 0, field.num_bits, new_instr);
+       field.in_value = NULL;
+       jtag_add_ir_scan(tap, &field, TAP_IDLE);
+       free(t);
+       return ERROR_OK;
+}
+
+static int efinix_load(struct pld_device *pld_device, const char *filename)
+{
+       struct raw_bit_file bit_file;
+       struct scan_field field[2];
+
+       if (!pld_device || !pld_device->driver_priv)
+               return ERROR_FAIL;
+
+       struct efinix_pld_device *efinix_info = pld_device->driver_priv;
+       if (!efinix_info || !efinix_info->tap)
+               return ERROR_FAIL;
+       struct jtag_tap *tap = efinix_info->tap;
+
+       jtag_add_tlr();
+
+       int retval = efinix_set_instr(tap, PROGRAM);
+       if (retval != ERROR_OK)
+               return retval;
+       jtag_add_runtest(RUNTEST_START_CYCLES, TAP_IDLE);
+       retval = efinix_set_instr(tap, PROGRAM); /* fix for T20 */
+       if (retval != ERROR_OK)
+               return retval;
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = efinix_read_file(&bit_file, filename);
+       if (retval != ERROR_OK)
+               return retval;
+
+       for (size_t i = 0; i < bit_file.length; i++)
+               bit_file.data[i] = flip_u32(bit_file.data[i], 8);
+
+       /* shift in the bitstream */
+       field[0].num_bits = bit_file.length * 8;
+       field[0].out_value = bit_file.data;
+       field[0].in_value = NULL;
+
+       /* followed by zeros */
+       field[1].num_bits = TRAILING_ZEROS;
+       uint8_t *buf = calloc(TRAILING_ZEROS / 8, 1);
+       if (!buf) {
+               free(bit_file.data);
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+       field[1].out_value = buf;
+       field[1].in_value = NULL;
+
+       jtag_add_dr_scan(tap, 2, field, TAP_DRPAUSE);
+       retval = jtag_execute_queue();
+       free(bit_file.data);
+       free(buf);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = efinix_set_instr(tap, ENTERUSER);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* entering RUN/TEST for 100 cycles */
+       jtag_add_runtest(RUNTEST_FINISH_CYCLES, TAP_IDLE);
+       retval = jtag_execute_queue();
+
+       return retval;
+}
+
+PLD_DEVICE_COMMAND_HANDLER(efinix_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 efinix_pld_device *efinix_info = malloc(sizeof(struct efinix_pld_device));
+       if (!efinix_info) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+       efinix_info->tap = tap;
+
+       pld->driver_priv = efinix_info;
+
+       return ERROR_OK;
+}
+
+struct pld_driver efinix_pld = {
+       .name = "efinix",
+       .pld_device_command = &efinix_pld_device_command,
+       .load = &efinix_load,
+};
index e838888cefed236edb45ba5033dfad276ea62ff1..a92486ab1cb8aabe62707fa2def3df8e36bcb589 100644 (file)
 
 /* pld drivers
  */
+extern struct pld_driver efinix_pld;
 extern struct pld_driver lattice_pld;
 extern struct pld_driver virtex2_pld;
 
 static struct pld_driver *pld_drivers[] = {
+       &efinix_pld,
        &lattice_pld,
        &virtex2_pld,
        NULL,
diff --git a/tcl/board/trion_t20_bga256.cfg b/tcl/board/trion_t20_bga256.cfg
new file mode 100644 (file)
index 0000000..045d63d
--- /dev/null
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# TrionĀ® T20 BGA256 Development Kit
+# https://www.efinixinc.com/docs/trion20-devkit-ug-v1.5.pdf
+#
+# works after power cycle or pushing sw1.
+# it is because we cannot control CDONE which is connected to ftdi channel 0
+# note from an006: For JTAG programming, T4, T8, T13, and T20 FPGAs use the
+# CRESET_N and SS_N pins in addition to the standard JTAG pins.
+
+adapter driver ftdi
+ftdi vid_pid 0x0403 0x6010
+
+ftdi channel 1
+ftdi layout_init 0x0008 0x008b
+reset_config none
+transport select jtag
+adapter speed 6000
+
+source [find fpga/efinix_trion.cfg]
+
+#openocd -f board/trion_t20_bga256.cfg -c "init" -c "pld load 0 outflow/trion_blinker.bit"
+#ipdbg -start -tap trion.tap -hub 0x8 -port 5555 -tool 0
+
diff --git a/tcl/fpga/efinix_titanium.cfg b/tcl/fpga/efinix_titanium.cfg
new file mode 100644 (file)
index 0000000..681b58f
--- /dev/null
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# efinix titanium
+# https://www.efinixinc.com/docs/an048-jtag-bst-titanium-v1.0.pdf
+
+if { [info exists CHIPNAME] } {
+       set _CHIPNAME $CHIPNAME
+} else {
+       set _CHIPNAME titanium
+}
+
+jtag newtap $_CHIPNAME tap -irlen 5 -ignore-version \
+       -expected-id 0x10661A79 \
+       -expected-id 0x00360A79 \
+       -expected-id 0x10660A79 \
+       -expected-id 0x00681A79 \
+       -expected-id 0x00688A79 \
+       -expected-id 0x00682A79 \
+       -expected-id 0x0068CA79 \
+       -expected-id 0x00680A79 \
+       -expected-id 0x00684A79
+
+pld device efinix $_CHIPNAME.tap
diff --git a/tcl/fpga/efinix_trion.cfg b/tcl/fpga/efinix_trion.cfg
new file mode 100644 (file)
index 0000000..ecd2eda
--- /dev/null
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# efinix trion
+# https://www.efinixinc.com/docs/an021-jtag-bst-trion-v1.0.pdf
+
+if { [info exists CHIPNAME] } {
+       set _CHIPNAME $CHIPNAME
+} else {
+       set _CHIPNAME trion
+}
+
+jtag newtap $_CHIPNAME tap -irlen 4 -ignore-version \
+       -expected-id 0x00210A79 \
+       -expected-id 0x00240A79 \
+       -expected-id 0x00220A79
+
+pld device efinix $_CHIPNAME.tap

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)