1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2022 by Daniel Anselmi *
6 ***************************************************************************/
12 #include <jtag/jtag.h>
20 #define TRAILING_ZEROS 4000
21 #define RUNTEST_START_CYCLES 100
22 #define RUNTEST_FINISH_CYCLES 100
24 struct efinix_pld_device
{
28 static int efinix_read_bit_file(struct raw_bit_file
*bit_file
, const char *filename
)
30 FILE *input_file
= fopen(filename
, "r");
32 LOG_ERROR("couldn't open %s: %s", filename
, strerror(errno
));
33 return ERROR_PLD_FILE_LOAD_FAILED
;
36 fseek(input_file
, 0, SEEK_END
);
37 long length
= ftell(input_file
);
38 fseek(input_file
, 0, SEEK_SET
);
40 if (length
< 0 || ((length
% 3))) {
42 LOG_ERROR("Failed to get length from file %s: %s", filename
, strerror(errno
));
43 return ERROR_PLD_FILE_LOAD_FAILED
;
45 bit_file
->length
= DIV_ROUND_UP(length
, 3);
47 bit_file
->data
= malloc(bit_file
->length
);
48 if (!bit_file
->data
) {
50 LOG_ERROR("Out of memory");
51 return ERROR_PLD_FILE_LOAD_FAILED
;
54 bool end_detected
= false;
56 for (size_t idx
= 0; !end_detected
&& idx
< bit_file
->length
; ++idx
) {
57 size_t read_count
= fread(buffer
, sizeof(char), 3, input_file
);
58 end_detected
= feof(input_file
);
59 if ((read_count
== 3 && buffer
[2] != '\n') ||
60 (read_count
!= 3 && !end_detected
) ||
61 (read_count
!= 2 && end_detected
)) {
64 bit_file
->data
= NULL
;
65 LOG_ERROR("unexpected line length");
66 return ERROR_PLD_FILE_LOAD_FAILED
;
69 if (!isxdigit(buffer
[0]) || !isxdigit(buffer
[1])) {
72 bit_file
->data
= NULL
;
73 LOG_ERROR("unexpected char in hex string");
74 return ERROR_PLD_FILE_LOAD_FAILED
;
76 unhexify(&bit_file
->data
[idx
], buffer
, 2);
84 static int efinix_read_file(struct raw_bit_file
*bit_file
, const char *filename
)
86 if (!filename
|| !bit_file
)
87 return ERROR_COMMAND_SYNTAX_ERROR
;
89 /* check if binary .bin or ascii .bit/.hex */
90 const char *file_ending_pos
= strrchr(filename
, '.');
91 if (!file_ending_pos
) {
92 LOG_ERROR("Unable to detect filename suffix");
93 return ERROR_PLD_FILE_LOAD_FAILED
;
96 if (strcasecmp(file_ending_pos
, ".bin") == 0) {
97 return cpld_read_raw_bit_file(bit_file
, filename
);
98 } else if ((strcasecmp(file_ending_pos
, ".bit") == 0) ||
99 (strcasecmp(file_ending_pos
, ".hex") == 0)) {
100 return efinix_read_bit_file(bit_file
, filename
);
103 LOG_ERROR("Unable to detect filetype");
104 return ERROR_PLD_FILE_LOAD_FAILED
;
107 static int efinix_set_instr(struct jtag_tap
*tap
, uint8_t new_instr
)
109 struct scan_field field
;
110 field
.num_bits
= tap
->ir_length
;
111 void *t
= calloc(DIV_ROUND_UP(field
.num_bits
, 8), 1);
113 LOG_ERROR("Out of memory");
117 buf_set_u32(t
, 0, field
.num_bits
, new_instr
);
118 field
.in_value
= NULL
;
119 jtag_add_ir_scan(tap
, &field
, TAP_IDLE
);
124 static int efinix_load(struct pld_device
*pld_device
, const char *filename
)
126 struct raw_bit_file bit_file
;
127 struct scan_field field
[2];
129 if (!pld_device
|| !pld_device
->driver_priv
)
132 struct efinix_pld_device
*efinix_info
= pld_device
->driver_priv
;
133 if (!efinix_info
|| !efinix_info
->tap
)
135 struct jtag_tap
*tap
= efinix_info
->tap
;
139 int retval
= efinix_set_instr(tap
, PROGRAM
);
140 if (retval
!= ERROR_OK
)
142 jtag_add_runtest(RUNTEST_START_CYCLES
, TAP_IDLE
);
143 retval
= efinix_set_instr(tap
, PROGRAM
); /* fix for T20 */
144 if (retval
!= ERROR_OK
)
146 retval
= jtag_execute_queue();
147 if (retval
!= ERROR_OK
)
150 retval
= efinix_read_file(&bit_file
, filename
);
151 if (retval
!= ERROR_OK
)
154 for (size_t i
= 0; i
< bit_file
.length
; i
++)
155 bit_file
.data
[i
] = flip_u32(bit_file
.data
[i
], 8);
157 /* shift in the bitstream */
158 field
[0].num_bits
= bit_file
.length
* 8;
159 field
[0].out_value
= bit_file
.data
;
160 field
[0].in_value
= NULL
;
162 /* followed by zeros */
163 field
[1].num_bits
= TRAILING_ZEROS
;
164 uint8_t *buf
= calloc(TRAILING_ZEROS
/ 8, 1);
167 LOG_ERROR("Out of memory");
170 field
[1].out_value
= buf
;
171 field
[1].in_value
= NULL
;
173 jtag_add_dr_scan(tap
, 2, field
, TAP_DRPAUSE
);
174 retval
= jtag_execute_queue();
177 if (retval
!= ERROR_OK
)
180 retval
= efinix_set_instr(tap
, ENTERUSER
);
181 if (retval
!= ERROR_OK
)
184 /* entering RUN/TEST for 100 cycles */
185 jtag_add_runtest(RUNTEST_FINISH_CYCLES
, TAP_IDLE
);
186 retval
= jtag_execute_queue();
191 PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command
)
194 return ERROR_COMMAND_SYNTAX_ERROR
;
196 if (strcmp(CMD_ARGV
[2], "-chain-position") != 0)
197 return ERROR_COMMAND_SYNTAX_ERROR
;
199 struct jtag_tap
*tap
= jtag_tap_by_string(CMD_ARGV
[3]);
201 command_print(CMD
, "Tap: %s does not exist", CMD_ARGV
[3]);
205 struct efinix_pld_device
*efinix_info
= malloc(sizeof(struct efinix_pld_device
));
207 LOG_ERROR("Out of memory");
210 efinix_info
->tap
= tap
;
212 pld
->driver_priv
= efinix_info
;
217 struct pld_driver efinix_pld
= {
219 .pld_create_command
= &efinix_pld_create_command
,
220 .load
= &efinix_load
,
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)