ipdbg/pld: ipdbg can get tap and hub/ir from pld driver.
[openocd.git] / src / pld / efinix.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2022 by Daniel Anselmi *
5 * danselmi@gmx.ch *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <jtag/jtag.h>
13
14 #include "pld.h"
15 #include "raw_bit.h"
16
17 #define PROGRAM 0x4
18 #define ENTERUSER 0x7
19 #define USER1 0x8
20 #define USER2 0x9
21 #define USER3 0xa
22 #define USER4 0xb
23
24 enum efinix_family_e {
25 EFINIX_TRION,
26 EFINIX_TITANIUM,
27 EFINIX_UNKNOWN
28 };
29
30 #define TRAILING_ZEROS 4000
31 #define RUNTEST_START_CYCLES 100
32 #define RUNTEST_FINISH_CYCLES 100
33
34 struct efinix_device {
35 uint32_t idcode;
36 int num_user;
37 };
38
39 struct efinix_pld_device {
40 struct jtag_tap *tap;
41 enum efinix_family_e family;
42 };
43
44 static int efinix_read_bit_file(struct raw_bit_file *bit_file, const char *filename)
45 {
46 FILE *input_file = fopen(filename, "r");
47 if (!input_file) {
48 LOG_ERROR("couldn't open %s: %s", filename, strerror(errno));
49 return ERROR_PLD_FILE_LOAD_FAILED;
50 }
51
52 fseek(input_file, 0, SEEK_END);
53 long length = ftell(input_file);
54 fseek(input_file, 0, SEEK_SET);
55
56 if (length < 0 || ((length % 3))) {
57 fclose(input_file);
58 LOG_ERROR("Failed to get length from file %s: %s", filename, strerror(errno));
59 return ERROR_PLD_FILE_LOAD_FAILED;
60 }
61 bit_file->length = DIV_ROUND_UP(length, 3);
62
63 bit_file->data = malloc(bit_file->length);
64 if (!bit_file->data) {
65 fclose(input_file);
66 LOG_ERROR("Out of memory");
67 return ERROR_PLD_FILE_LOAD_FAILED;
68 }
69
70 bool end_detected = false;
71 char buffer[3];
72 for (size_t idx = 0; !end_detected && idx < bit_file->length; ++idx) {
73 size_t read_count = fread(buffer, sizeof(char), 3, input_file);
74 end_detected = feof(input_file);
75 if ((read_count == 3 && buffer[2] != '\n') ||
76 (read_count != 3 && !end_detected) ||
77 (read_count != 2 && end_detected)) {
78 fclose(input_file);
79 free(bit_file->data);
80 bit_file->data = NULL;
81 LOG_ERROR("unexpected line length");
82 return ERROR_PLD_FILE_LOAD_FAILED;
83 }
84
85 if (!isxdigit(buffer[0]) || !isxdigit(buffer[1])) {
86 fclose(input_file);
87 free(bit_file->data);
88 bit_file->data = NULL;
89 LOG_ERROR("unexpected char in hex string");
90 return ERROR_PLD_FILE_LOAD_FAILED;
91 }
92 unhexify(&bit_file->data[idx], buffer, 2);
93 }
94
95 fclose(input_file);
96
97 return ERROR_OK;
98 }
99
100 static int efinix_read_file(struct raw_bit_file *bit_file, const char *filename)
101 {
102 if (!filename || !bit_file)
103 return ERROR_COMMAND_SYNTAX_ERROR;
104
105 /* check if binary .bin or ascii .bit/.hex */
106 const char *file_ending_pos = strrchr(filename, '.');
107 if (!file_ending_pos) {
108 LOG_ERROR("Unable to detect filename suffix");
109 return ERROR_PLD_FILE_LOAD_FAILED;
110 }
111
112 if (strcasecmp(file_ending_pos, ".bin") == 0) {
113 return cpld_read_raw_bit_file(bit_file, filename);
114 } else if ((strcasecmp(file_ending_pos, ".bit") == 0) ||
115 (strcasecmp(file_ending_pos, ".hex") == 0)) {
116 return efinix_read_bit_file(bit_file, filename);
117 }
118
119 LOG_ERROR("Unable to detect filetype");
120 return ERROR_PLD_FILE_LOAD_FAILED;
121 }
122
123 static int efinix_set_instr(struct jtag_tap *tap, uint8_t new_instr)
124 {
125 struct scan_field field;
126 field.num_bits = tap->ir_length;
127 void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
128 if (!t) {
129 LOG_ERROR("Out of memory");
130 return ERROR_FAIL;
131 }
132 field.out_value = t;
133 buf_set_u32(t, 0, field.num_bits, new_instr);
134 field.in_value = NULL;
135 jtag_add_ir_scan(tap, &field, TAP_IDLE);
136 free(t);
137 return ERROR_OK;
138 }
139
140 static int efinix_load(struct pld_device *pld_device, const char *filename)
141 {
142 struct raw_bit_file bit_file;
143 struct scan_field field[2];
144
145 if (!pld_device || !pld_device->driver_priv)
146 return ERROR_FAIL;
147
148 struct efinix_pld_device *efinix_info = pld_device->driver_priv;
149 if (!efinix_info || !efinix_info->tap)
150 return ERROR_FAIL;
151 struct jtag_tap *tap = efinix_info->tap;
152
153 jtag_add_tlr();
154
155 int retval = efinix_set_instr(tap, PROGRAM);
156 if (retval != ERROR_OK)
157 return retval;
158 jtag_add_runtest(RUNTEST_START_CYCLES, TAP_IDLE);
159 retval = efinix_set_instr(tap, PROGRAM); /* fix for T20 */
160 if (retval != ERROR_OK)
161 return retval;
162 retval = jtag_execute_queue();
163 if (retval != ERROR_OK)
164 return retval;
165
166 retval = efinix_read_file(&bit_file, filename);
167 if (retval != ERROR_OK)
168 return retval;
169
170 for (size_t i = 0; i < bit_file.length; i++)
171 bit_file.data[i] = flip_u32(bit_file.data[i], 8);
172
173 /* shift in the bitstream */
174 field[0].num_bits = bit_file.length * 8;
175 field[0].out_value = bit_file.data;
176 field[0].in_value = NULL;
177
178 /* followed by zeros */
179 field[1].num_bits = TRAILING_ZEROS;
180 uint8_t *buf = calloc(TRAILING_ZEROS / 8, 1);
181 if (!buf) {
182 free(bit_file.data);
183 LOG_ERROR("Out of memory");
184 return ERROR_FAIL;
185 }
186 field[1].out_value = buf;
187 field[1].in_value = NULL;
188
189 jtag_add_dr_scan(tap, 2, field, TAP_DRPAUSE);
190 retval = jtag_execute_queue();
191 free(bit_file.data);
192 free(buf);
193 if (retval != ERROR_OK)
194 return retval;
195
196 retval = efinix_set_instr(tap, ENTERUSER);
197 if (retval != ERROR_OK)
198 return retval;
199
200 /* entering RUN/TEST for 100 cycles */
201 jtag_add_runtest(RUNTEST_FINISH_CYCLES, TAP_IDLE);
202 retval = jtag_execute_queue();
203
204 return retval;
205 }
206
207 static int efinix_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
208 {
209 if (!pld_device)
210 return ERROR_FAIL;
211
212 struct efinix_pld_device *pld_device_info = pld_device->driver_priv;
213
214 if (!pld_device_info || !pld_device_info->tap)
215 return ERROR_FAIL;
216
217 hub->tap = pld_device_info->tap;
218
219 if (pld_device_info->family == EFINIX_UNKNOWN) {
220 LOG_ERROR("family unknown, please specify for 'pld create'");
221 return ERROR_FAIL;
222 }
223 int num_user = 2; /* trion */
224 if (pld_device_info->family == EFINIX_TITANIUM)
225 num_user = 4;
226
227 if (user_num > num_user) {
228 LOG_ERROR("Devices has only user register 1 to %d", num_user);
229 return ERROR_FAIL;
230 }
231
232 switch (user_num) {
233 case 1:
234 hub->user_ir_code = USER1;
235 break;
236 case 2:
237 hub->user_ir_code = USER2;
238 break;
239 case 3:
240 hub->user_ir_code = USER3;
241 break;
242 case 4:
243 hub->user_ir_code = USER4;
244 break;
245 default:
246 LOG_ERROR("efinix devices only have user register 1 to %d", num_user);
247 return ERROR_FAIL;
248 }
249 return ERROR_OK;
250 }
251
252 PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
253 {
254 if (CMD_ARGC != 4 && CMD_ARGC != 6)
255 return ERROR_COMMAND_SYNTAX_ERROR;
256
257 if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
258 return ERROR_COMMAND_SYNTAX_ERROR;
259
260 struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
261 if (!tap) {
262 command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
263 return ERROR_FAIL;
264 }
265
266 enum efinix_family_e family = EFINIX_UNKNOWN;
267 if (CMD_ARGC == 6) {
268 if (strcmp(CMD_ARGV[4], "-family") != 0)
269 return ERROR_COMMAND_SYNTAX_ERROR;
270
271 if (strcmp(CMD_ARGV[5], "trion") == 0) {
272 family = EFINIX_TRION;
273 } else if (strcmp(CMD_ARGV[5], "titanium") == 0) {
274 family = EFINIX_TITANIUM;
275 } else {
276 command_print(CMD, "unknown family");
277 return ERROR_FAIL;
278 }
279 }
280
281 struct efinix_pld_device *efinix_info = malloc(sizeof(struct efinix_pld_device));
282 if (!efinix_info) {
283 LOG_ERROR("Out of memory");
284 return ERROR_FAIL;
285 }
286 efinix_info->tap = tap;
287 efinix_info->family = family;
288
289 pld->driver_priv = efinix_info;
290
291 return ERROR_OK;
292 }
293
294 struct pld_driver efinix_pld = {
295 .name = "efinix",
296 .pld_create_command = &efinix_pld_create_command,
297 .load = &efinix_load,
298 .get_ipdbg_hub = efinix_get_ipdbg_hub,
299 };

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)