pld/xilinx: make instruction codes configurable
[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_load_prepare(struct pld_device *pld_device)
147 {
148 struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
149 int retval;
150
151 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jprog_b);
152 if (retval != ERROR_OK)
153 return retval;
154
155 retval = jtag_execute_queue();
156 if (retval != ERROR_OK)
157 return retval;
158 jtag_add_sleep(1000);
159
160 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_in);
161 if (retval != ERROR_OK)
162 return retval;
163
164 return jtag_execute_queue();
165 }
166
167 static int virtex2_load_cleanup(struct pld_device *pld_device)
168 {
169 struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
170 int retval;
171
172 jtag_add_tlr();
173
174 if (!(virtex2_info->no_jstart)) {
175 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
176 if (retval != ERROR_OK)
177 return retval;
178 }
179 jtag_add_runtest(13, TAP_IDLE);
180 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
181 if (retval != ERROR_OK)
182 return retval;
183 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
184 if (retval != ERROR_OK)
185 return retval;
186 if (!(virtex2_info->no_jstart)) {
187 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
188 if (retval != ERROR_OK)
189 return retval;
190 }
191 jtag_add_runtest(13, TAP_IDLE);
192 retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
193 if (retval != ERROR_OK)
194 return retval;
195
196 return jtag_execute_queue();
197 }
198
199 static int virtex2_load(struct pld_device *pld_device, const char *filename)
200 {
201 struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
202 struct xilinx_bit_file bit_file;
203 int retval;
204 unsigned int i;
205 struct scan_field field;
206
207 field.in_value = NULL;
208
209 retval = xilinx_read_bit_file(&bit_file, filename);
210 if (retval != ERROR_OK)
211 return retval;
212
213 retval = virtex2_load_prepare(pld_device);
214 if (retval != ERROR_OK) {
215 xilinx_free_bit_file(&bit_file);
216 return retval;
217 }
218
219 for (i = 0; i < bit_file.length; i++)
220 bit_file.data[i] = flip_u32(bit_file.data[i], 8);
221
222 field.num_bits = bit_file.length * 8;
223 field.out_value = bit_file.data;
224
225 jtag_add_dr_scan(virtex2_info->tap, 1, &field, TAP_DRPAUSE);
226 retval = jtag_execute_queue();
227 if (retval != ERROR_OK) {
228 xilinx_free_bit_file(&bit_file);
229 return retval;
230 }
231
232 retval = virtex2_load_cleanup(pld_device);
233
234 xilinx_free_bit_file(&bit_file);
235
236 return retval;
237 }
238
239 COMMAND_HANDLER(virtex2_handle_read_stat_command)
240 {
241 struct pld_device *device;
242 uint32_t status;
243
244 if (CMD_ARGC < 1)
245 return ERROR_COMMAND_SYNTAX_ERROR;
246
247 device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
248 if (!device) {
249 command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
250 return ERROR_FAIL;
251 }
252
253 int retval = virtex2_read_stat(device, &status);
254 if (retval != ERROR_OK) {
255 command_print(CMD, "cannot read virtex2 status register");
256 return retval;
257 }
258
259 command_print(CMD, "virtex2 status register: 0x%8.8" PRIx32, status);
260
261 return ERROR_OK;
262 }
263
264 COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command)
265 {
266 if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS))
267 return ERROR_COMMAND_SYNTAX_ERROR;
268
269 struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
270 if (!device) {
271 command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
272 return ERROR_FAIL;
273 }
274
275 struct virtex2_pld_device *virtex2_info = device->driver_priv;
276 if (!virtex2_info)
277 return ERROR_FAIL;
278
279 struct virtex2_command_set instr_codes;
280 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], instr_codes.cfg_out);
281 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[2], instr_codes.cfg_in);
282 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], instr_codes.jprog_b);
283 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[4], instr_codes.jstart);
284 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[5], instr_codes.jshutdown);
285 instr_codes.bypass = 0xffffffffffffffff;
286
287 unsigned int num_user = CMD_ARGC - 6;
288 for (unsigned int i = 0; i < num_user; ++i)
289 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[6 + i], instr_codes.user[i]);
290 instr_codes.num_user = num_user;
291
292 virtex2_info->command_set = instr_codes;
293 return ERROR_OK;
294 }
295
296 COMMAND_HANDLER(virtex2_handle_set_user_codes_command)
297 {
298 if (CMD_ARGC < 2 || CMD_ARGC > (1 + VIRTEX2_MAX_USER_INSTRUCTIONS))
299 return ERROR_COMMAND_SYNTAX_ERROR;
300
301 struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
302 if (!device) {
303 command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
304 return ERROR_FAIL;
305 }
306
307 struct virtex2_pld_device *virtex2_info = device->driver_priv;
308 if (!virtex2_info)
309 return ERROR_FAIL;
310
311 uint64_t user[VIRTEX2_MAX_USER_INSTRUCTIONS];
312 unsigned int num_user = CMD_ARGC - 1;
313 for (unsigned int i = 0; i < num_user; ++i)
314 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1 + i], user[i]);
315 virtex2_info->command_set.num_user = num_user;
316 memcpy(virtex2_info->command_set.user, user, num_user * sizeof(uint64_t));
317 return ERROR_OK;
318 }
319
320 PLD_CREATE_COMMAND_HANDLER(virtex2_pld_create_command)
321 {
322 if (CMD_ARGC < 4)
323 return ERROR_COMMAND_SYNTAX_ERROR;
324
325 if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
326 return ERROR_COMMAND_SYNTAX_ERROR;
327
328 struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
329 if (!tap) {
330 command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
331 return ERROR_FAIL;
332 }
333
334 struct virtex2_pld_device *virtex2_info = malloc(sizeof(struct virtex2_pld_device));
335 if (!virtex2_info) {
336 LOG_ERROR("Out of memory");
337 return ERROR_FAIL;
338 }
339 virtex2_info->tap = tap;
340 virtex2_info->command_set = virtex2_default_commands;
341
342 virtex2_info->no_jstart = 0;
343 if (CMD_ARGC >= 5 && strcmp(CMD_ARGV[4], "-no_jstart") == 0)
344 virtex2_info->no_jstart = 1;
345
346 pld->driver_priv = virtex2_info;
347
348 return ERROR_OK;
349 }
350
351 static const struct command_registration virtex2_exec_command_handlers[] = {
352 {
353 .name = "read_stat",
354 .mode = COMMAND_EXEC,
355 .handler = virtex2_handle_read_stat_command,
356 .help = "read status register",
357 .usage = "pld_name",
358 }, {
359 .name = "set_instr_codes",
360 .mode = COMMAND_EXEC,
361 .handler = virtex2_handle_set_instuction_codes_command,
362 .help = "set instructions codes used for loading the bitstream/refreshing/jtag-hub",
363 .usage = "pld_name cfg_out cfg_in jprogb jstart jshutdown"
364 " [user1 [user2 [user3 [user4]]]]",
365 }, {
366 .name = "set_user_codes",
367 .mode = COMMAND_EXEC,
368 .handler = virtex2_handle_set_user_codes_command,
369 .help = "set instructions codes used for jtag-hub",
370 .usage = "pld_name user1 [user2 [user3 [user4]]]",
371 },
372 COMMAND_REGISTRATION_DONE
373 };
374
375 static const struct command_registration virtex2_command_handler[] = {
376 {
377 .name = "virtex2",
378 .mode = COMMAND_ANY,
379 .help = "Virtex-II specific commands",
380 .usage = "",
381 .chain = virtex2_exec_command_handlers,
382 },
383 COMMAND_REGISTRATION_DONE
384 };
385
386 struct pld_driver virtex2_pld = {
387 .name = "virtex2",
388 .commands = virtex2_command_handler,
389 .pld_create_command = &virtex2_pld_create_command,
390 .load = &virtex2_load,
391 };

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)