pld/virtex2: add program/refresh command
[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 COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command)
310 {
311 if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS))
312 return ERROR_COMMAND_SYNTAX_ERROR;
313
314 struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
315 if (!device) {
316 command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
317 return ERROR_FAIL;
318 }
319
320 struct virtex2_pld_device *virtex2_info = device->driver_priv;
321 if (!virtex2_info)
322 return ERROR_FAIL;
323
324 struct virtex2_command_set instr_codes;
325 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], instr_codes.cfg_out);
326 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[2], instr_codes.cfg_in);
327 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], instr_codes.jprog_b);
328 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[4], instr_codes.jstart);
329 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[5], instr_codes.jshutdown);
330 instr_codes.bypass = 0xffffffffffffffff;
331
332 unsigned int num_user = CMD_ARGC - 6;
333 for (unsigned int i = 0; i < num_user; ++i)
334 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[6 + i], instr_codes.user[i]);
335 instr_codes.num_user = num_user;
336
337 virtex2_info->command_set = instr_codes;
338 return ERROR_OK;
339 }
340
341 COMMAND_HANDLER(virtex2_handle_set_user_codes_command)
342 {
343 if (CMD_ARGC < 2 || CMD_ARGC > (1 + VIRTEX2_MAX_USER_INSTRUCTIONS))
344 return ERROR_COMMAND_SYNTAX_ERROR;
345
346 struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
347 if (!device) {
348 command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
349 return ERROR_FAIL;
350 }
351
352 struct virtex2_pld_device *virtex2_info = device->driver_priv;
353 if (!virtex2_info)
354 return ERROR_FAIL;
355
356 uint64_t user[VIRTEX2_MAX_USER_INSTRUCTIONS];
357 unsigned int num_user = CMD_ARGC - 1;
358 for (unsigned int i = 0; i < num_user; ++i)
359 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1 + i], user[i]);
360 virtex2_info->command_set.num_user = num_user;
361 memcpy(virtex2_info->command_set.user, user, num_user * sizeof(uint64_t));
362 return ERROR_OK;
363 }
364
365 PLD_CREATE_COMMAND_HANDLER(virtex2_pld_create_command)
366 {
367 if (CMD_ARGC < 4)
368 return ERROR_COMMAND_SYNTAX_ERROR;
369
370 if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
371 return ERROR_COMMAND_SYNTAX_ERROR;
372
373 struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
374 if (!tap) {
375 command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
376 return ERROR_FAIL;
377 }
378
379 struct virtex2_pld_device *virtex2_info = malloc(sizeof(struct virtex2_pld_device));
380 if (!virtex2_info) {
381 LOG_ERROR("Out of memory");
382 return ERROR_FAIL;
383 }
384 virtex2_info->tap = tap;
385 virtex2_info->command_set = virtex2_default_commands;
386
387 virtex2_info->no_jstart = 0;
388 if (CMD_ARGC >= 5 && strcmp(CMD_ARGV[4], "-no_jstart") == 0)
389 virtex2_info->no_jstart = 1;
390
391 pld->driver_priv = virtex2_info;
392
393 return ERROR_OK;
394 }
395
396 static const struct command_registration virtex2_exec_command_handlers[] = {
397 {
398 .name = "read_stat",
399 .mode = COMMAND_EXEC,
400 .handler = virtex2_handle_read_stat_command,
401 .help = "read status register",
402 .usage = "pld_name",
403 }, {
404 .name = "set_instr_codes",
405 .mode = COMMAND_EXEC,
406 .handler = virtex2_handle_set_instuction_codes_command,
407 .help = "set instructions codes used for loading the bitstream/refreshing/jtag-hub",
408 .usage = "pld_name cfg_out cfg_in jprogb jstart jshutdown"
409 " [user1 [user2 [user3 [user4]]]]",
410 }, {
411 .name = "set_user_codes",
412 .mode = COMMAND_EXEC,
413 .handler = virtex2_handle_set_user_codes_command,
414 .help = "set instructions codes used for jtag-hub",
415 .usage = "pld_name user1 [user2 [user3 [user4]]]",
416 }, {
417 .name = "program",
418 .mode = COMMAND_EXEC,
419 .handler = virtex2_handle_program_command,
420 .help = "start loading of configuration (refresh)",
421 .usage = "pld_name",
422 },
423 COMMAND_REGISTRATION_DONE
424 };
425
426 static const struct command_registration virtex2_command_handler[] = {
427 {
428 .name = "virtex2",
429 .mode = COMMAND_ANY,
430 .help = "Virtex-II specific commands",
431 .usage = "",
432 .chain = virtex2_exec_command_handlers,
433 },
434 COMMAND_REGISTRATION_DONE
435 };
436
437 struct pld_driver virtex2_pld = {
438 .name = "virtex2",
439 .commands = virtex2_command_handler,
440 .pld_create_command = &virtex2_pld_create_command,
441 .load = &virtex2_load,
442 };

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)