pld: fix sparser warnings
[openocd.git] / src / pld / virtex2.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2006 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "virtex2.h"
13 #include "xilinx_bit.h"
14 #include "pld.h"
15
16 static const struct virtex2_command_set virtex2_default_commands = {
17 .cfg_out = 0x04,
18 .cfg_in = 0x05,
19 .jprog_b = 0x0b,
20 .jstart = 0x0c,
21 .jshutdown = 0x0d,
22 .bypass = 0x3f,
23 .user = {0x02, 0x03},
24 .num_user = 2, /* virtex II has only 2 user instructions */
25 };
26
27 static int virtex2_set_instr(struct jtag_tap *tap, uint64_t new_instr)
28 {
29 if (!tap)
30 return ERROR_FAIL;
31
32 if (buf_get_u64(tap->cur_instr, 0, tap->ir_length) != new_instr) {
33 struct scan_field field;
34
35 field.num_bits = tap->ir_length;
36 void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
37 if (!t) {
38 LOG_ERROR("Out of memory");
39 return ERROR_FAIL;
40 }
41 field.out_value = t;
42 buf_set_u64(t, 0, field.num_bits, new_instr);
43 field.in_value = NULL;
44
45 jtag_add_ir_scan(tap, &field, TAP_IDLE);
46
47 free(t);
48 }
49
50 return ERROR_OK;
51 }
52
53 static int virtex2_send_32(struct pld_device *pld_device,
54 int num_words, uint32_t *words)
55 {
56 struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
57 struct scan_field scan_field;
58 uint8_t *values;
59 int i;
60
61 values = malloc(num_words * 4);
62 if (!values) {
63 LOG_ERROR("Out of memory");
64 return ERROR_FAIL;
65 }
66
67 scan_field.num_bits = num_words * 32;
68 scan_field.out_value = values;
69 scan_field.in_value = NULL;
70
71 for (i = 0; i < num_words; i++)
72 buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
73
74 int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_in);
75 if (retval != ERROR_OK) {
76 free(values);
77 return retval;
78 }
79
80 jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, TAP_DRPAUSE);
81
82 free(values);
83
84 return ERROR_OK;
85 }
86
87 static inline void virtexflip32(jtag_callback_data_t arg)
88 {
89 uint8_t *in = (uint8_t *)arg;
90 *((uint32_t *)arg) = flip_u32(le_to_h_u32(in), 32);
91 }
92
93 static int virtex2_receive_32(struct pld_device *pld_device,
94 int num_words, uint32_t *words)
95 {
96 struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
97 struct scan_field scan_field;
98
99 scan_field.num_bits = 32;
100 scan_field.out_value = NULL;
101 scan_field.in_value = NULL;
102
103 int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_out);
104 if (retval != ERROR_OK)
105 return retval;
106
107 while (num_words--) {
108 scan_field.in_value = (uint8_t *)words;
109
110 jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, TAP_DRPAUSE);
111
112 jtag_add_callback(virtexflip32, (jtag_callback_data_t)words);
113
114 words++;
115 }
116
117 return ERROR_OK;
118 }
119
120 static int virtex2_read_stat(struct pld_device *pld_device, uint32_t *status)
121 {
122 uint32_t data[5];
123
124 jtag_add_tlr();
125
126 data[0] = 0xaa995566; /* synch word */
127 data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */
128 data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */
129 data[3] = 0x20000000; /* NOOP */
130 data[4] = 0x20000000; /* NOOP */
131 int retval = virtex2_send_32(pld_device, 5, data);
132 if (retval != ERROR_OK)
133 return retval;
134
135 retval = virtex2_receive_32(pld_device, 1, status);
136 if (retval != ERROR_OK)
137 return retval;
138
139 retval = jtag_execute_queue();
140 if (retval == ERROR_OK)
141 LOG_DEBUG("status: 0x%8.8" PRIx32, *status);
142
143 return retval;
144 }
145
146 static int virtex2_program(struct pld_device *pld_device)
147 {
148 struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
149 if (!virtex2_info)
150 return ERROR_FAIL;
151
152 int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jshutdown);
153 if (retval != ERROR_OK)
154 return retval;
155
156 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jprog_b);
157 if (retval != ERROR_OK)
158 return retval;
159
160 jtag_add_runtest(62000, TAP_IDLE);
161 if (!(virtex2_info->no_jstart)) {
162 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
163 if (retval != ERROR_OK)
164 return retval;
165 }
166
167 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
168 if (retval != ERROR_OK)
169 return retval;
170 jtag_add_runtest(2000, TAP_IDLE);
171
172 return jtag_execute_queue();
173 }
174
175 static int virtex2_load_prepare(struct pld_device *pld_device)
176 {
177 struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
178 int retval;
179
180 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jprog_b);
181 if (retval != ERROR_OK)
182 return retval;
183
184 retval = jtag_execute_queue();
185 if (retval != ERROR_OK)
186 return retval;
187 jtag_add_sleep(1000);
188
189 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_in);
190 if (retval != ERROR_OK)
191 return retval;
192
193 return jtag_execute_queue();
194 }
195
196 static int virtex2_load_cleanup(struct pld_device *pld_device)
197 {
198 struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
199 int retval;
200
201 jtag_add_tlr();
202
203 if (!(virtex2_info->no_jstart)) {
204 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
205 if (retval != ERROR_OK)
206 return retval;
207 }
208 jtag_add_runtest(13, TAP_IDLE);
209 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
210 if (retval != ERROR_OK)
211 return retval;
212 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
213 if (retval != ERROR_OK)
214 return retval;
215 if (!(virtex2_info->no_jstart)) {
216 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
217 if (retval != ERROR_OK)
218 return retval;
219 }
220 jtag_add_runtest(13, TAP_IDLE);
221 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
222 if (retval != ERROR_OK)
223 return retval;
224
225 return jtag_execute_queue();
226 }
227
228 static int virtex2_load(struct pld_device *pld_device, const char *filename)
229 {
230 struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
231 struct xilinx_bit_file bit_file;
232 int retval;
233 unsigned int i;
234 struct scan_field field;
235
236 field.in_value = NULL;
237
238 retval = xilinx_read_bit_file(&bit_file, filename);
239 if (retval != ERROR_OK)
240 return retval;
241
242 retval = virtex2_load_prepare(pld_device);
243 if (retval != ERROR_OK) {
244 xilinx_free_bit_file(&bit_file);
245 return retval;
246 }
247
248 for (i = 0; i < bit_file.length; i++)
249 bit_file.data[i] = flip_u32(bit_file.data[i], 8);
250
251 field.num_bits = bit_file.length * 8;
252 field.out_value = bit_file.data;
253
254 jtag_add_dr_scan(virtex2_info->tap, 1, &field, TAP_DRPAUSE);
255 retval = jtag_execute_queue();
256 if (retval != ERROR_OK) {
257 xilinx_free_bit_file(&bit_file);
258 return retval;
259 }
260
261 retval = virtex2_load_cleanup(pld_device);
262
263 xilinx_free_bit_file(&bit_file);
264
265 return retval;
266 }
267
268 COMMAND_HANDLER(virtex2_handle_program_command)
269 {
270 struct pld_device *device;
271
272 if (CMD_ARGC != 1)
273 return ERROR_COMMAND_SYNTAX_ERROR;
274
275 device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
276 if (!device) {
277 command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
278 return ERROR_FAIL;
279 }
280
281 return virtex2_program(device);
282 }
283
284 COMMAND_HANDLER(virtex2_handle_read_stat_command)
285 {
286 struct pld_device *device;
287 uint32_t status;
288
289 if (CMD_ARGC < 1)
290 return ERROR_COMMAND_SYNTAX_ERROR;
291
292 device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
293 if (!device) {
294 command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
295 return ERROR_FAIL;
296 }
297
298 int retval = virtex2_read_stat(device, &status);
299 if (retval != ERROR_OK) {
300 command_print(CMD, "cannot read virtex2 status register");
301 return retval;
302 }
303
304 command_print(CMD, "virtex2 status register: 0x%8.8" PRIx32, status);
305
306 return ERROR_OK;
307 }
308
309 static int xilinx_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
310 {
311 if (!pld_device)
312 return ERROR_FAIL;
313
314 struct virtex2_pld_device *pld_device_info = pld_device->driver_priv;
315
316 if (!pld_device_info || !pld_device_info->tap)
317 return ERROR_FAIL;
318
319 hub->tap = pld_device_info->tap;
320 if (user_num < 1 || (unsigned int)user_num > pld_device_info->command_set.num_user) {
321 LOG_ERROR("device has only user register 1 to %d", pld_device_info->command_set.num_user);
322 return ERROR_FAIL;
323 }
324
325 hub->user_ir_code = pld_device_info->command_set.user[user_num - 1];
326 return ERROR_OK;
327 }
328
329 COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command)
330 {
331 if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS))
332 return ERROR_COMMAND_SYNTAX_ERROR;
333
334 struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
335 if (!device) {
336 command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
337 return ERROR_FAIL;
338 }
339
340 struct virtex2_pld_device *virtex2_info = device->driver_priv;
341 if (!virtex2_info)
342 return ERROR_FAIL;
343
344 struct virtex2_command_set instr_codes;
345 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], instr_codes.cfg_out);
346 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[2], instr_codes.cfg_in);
347 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], instr_codes.jprog_b);
348 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[4], instr_codes.jstart);
349 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[5], instr_codes.jshutdown);
350 instr_codes.bypass = 0xffffffffffffffffULL;
351
352 unsigned int num_user = CMD_ARGC - 6;
353 for (unsigned int i = 0; i < num_user; ++i)
354 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[6 + i], instr_codes.user[i]);
355 instr_codes.num_user = num_user;
356
357 virtex2_info->command_set = instr_codes;
358 return ERROR_OK;
359 }
360
361 COMMAND_HANDLER(virtex2_handle_set_user_codes_command)
362 {
363 if (CMD_ARGC < 2 || CMD_ARGC > (1 + VIRTEX2_MAX_USER_INSTRUCTIONS))
364 return ERROR_COMMAND_SYNTAX_ERROR;
365
366 struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
367 if (!device) {
368 command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
369 return ERROR_FAIL;
370 }
371
372 struct virtex2_pld_device *virtex2_info = device->driver_priv;
373 if (!virtex2_info)
374 return ERROR_FAIL;
375
376 uint64_t user[VIRTEX2_MAX_USER_INSTRUCTIONS];
377 unsigned int num_user = CMD_ARGC - 1;
378 for (unsigned int i = 0; i < num_user; ++i)
379 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1 + i], user[i]);
380 virtex2_info->command_set.num_user = num_user;
381 memcpy(virtex2_info->command_set.user, user, num_user * sizeof(uint64_t));
382 return ERROR_OK;
383 }
384
385 PLD_CREATE_COMMAND_HANDLER(virtex2_pld_create_command)
386 {
387 if (CMD_ARGC < 4)
388 return ERROR_COMMAND_SYNTAX_ERROR;
389
390 if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
391 return ERROR_COMMAND_SYNTAX_ERROR;
392
393 struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
394 if (!tap) {
395 command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
396 return ERROR_FAIL;
397 }
398
399 struct virtex2_pld_device *virtex2_info = malloc(sizeof(struct virtex2_pld_device));
400 if (!virtex2_info) {
401 LOG_ERROR("Out of memory");
402 return ERROR_FAIL;
403 }
404 virtex2_info->tap = tap;
405 virtex2_info->command_set = virtex2_default_commands;
406
407 virtex2_info->no_jstart = 0;
408 if (CMD_ARGC >= 5 && strcmp(CMD_ARGV[4], "-no_jstart") == 0)
409 virtex2_info->no_jstart = 1;
410
411 pld->driver_priv = virtex2_info;
412
413 return ERROR_OK;
414 }
415
416 static const struct command_registration virtex2_exec_command_handlers[] = {
417 {
418 .name = "read_stat",
419 .mode = COMMAND_EXEC,
420 .handler = virtex2_handle_read_stat_command,
421 .help = "read status register",
422 .usage = "pld_name",
423 }, {
424 .name = "set_instr_codes",
425 .mode = COMMAND_ANY,
426 .handler = virtex2_handle_set_instuction_codes_command,
427 .help = "set instructions codes used for loading the bitstream/refreshing/jtag-hub",
428 .usage = "pld_name cfg_out cfg_in jprogb jstart jshutdown"
429 " [user1 [user2 [user3 [user4]]]]",
430 }, {
431 .name = "set_user_codes",
432 .mode = COMMAND_ANY,
433 .handler = virtex2_handle_set_user_codes_command,
434 .help = "set instructions codes used for jtag-hub",
435 .usage = "pld_name user1 [user2 [user3 [user4]]]",
436 }, {
437 .name = "program",
438 .mode = COMMAND_EXEC,
439 .handler = virtex2_handle_program_command,
440 .help = "start loading of configuration (refresh)",
441 .usage = "pld_name",
442 },
443 COMMAND_REGISTRATION_DONE
444 };
445
446 static const struct command_registration virtex2_command_handler[] = {
447 {
448 .name = "virtex2",
449 .mode = COMMAND_ANY,
450 .help = "Virtex-II specific commands",
451 .usage = "",
452 .chain = virtex2_exec_command_handlers,
453 },
454 COMMAND_REGISTRATION_DONE
455 };
456
457 struct pld_driver virtex2_pld = {
458 .name = "virtex2",
459 .commands = virtex2_command_handler,
460 .pld_create_command = &virtex2_pld_create_command,
461 .load = &virtex2_load,
462 .get_ipdbg_hub = xilinx_get_ipdbg_hub,
463 };

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)