jtagspi/pld: add support from gatemate driver
[openocd.git] / src / pld / gatemate.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 #include <jtag/adapter.h>
14 #include "pld.h"
15 #include "raw_bit.h"
16
17 #define JTAG_CONFIGURE 0x06
18 #define JTAG_SPI_BYPASS 0x05
19 #define BYPASS 0x3F
20
21 struct gatemate_pld_device {
22 struct jtag_tap *tap;
23 };
24
25 struct gatemate_bit_file {
26 struct raw_bit_file raw_file;
27 size_t capacity;
28 };
29
30 static int gatemate_add_byte_to_bitfile(struct gatemate_bit_file *bit_file, uint8_t byte)
31 {
32 const size_t chunk_size = 8192;
33 if (bit_file->raw_file.length + 1 > bit_file->capacity) {
34 uint8_t *buffer;
35 if (bit_file->raw_file.data)
36 buffer = realloc(bit_file->raw_file.data, bit_file->capacity + chunk_size);
37 else
38 buffer = malloc(chunk_size);
39 if (!buffer) {
40 LOG_ERROR("Out of memory");
41 return ERROR_FAIL;
42 }
43 bit_file->raw_file.data = buffer;
44 bit_file->capacity += chunk_size;
45 }
46
47 bit_file->raw_file.data[bit_file->raw_file.length++] = byte;
48
49 return ERROR_OK;
50 }
51
52 static int gatemate_read_cfg_line(struct gatemate_bit_file *bit_file, const char *line_buffer, size_t nread)
53 {
54 for (size_t idx = 0; idx < nread; ++idx) {
55 if (line_buffer[idx] == ' ') {
56 continue;
57 } else if (line_buffer[idx] == 0) {
58 break;
59 } else if (idx + 1 < nread) {
60 if (isxdigit(line_buffer[idx]) && isxdigit(line_buffer[idx + 1])) {
61 uint8_t byte;
62 unhexify(&byte, line_buffer + idx, 2);
63 int retval = gatemate_add_byte_to_bitfile(bit_file, byte);
64 if (retval != ERROR_OK)
65 return retval;
66 } else if (line_buffer[idx] == '/' && line_buffer[idx + 1] == '/') {
67 break;
68 }
69 ++idx;
70 } else {
71 LOG_ERROR("parsing failed");
72 return ERROR_FAIL;
73 }
74 }
75 return ERROR_OK;
76 }
77
78 static int gatemate_getline(char **buffer, size_t *buf_size, FILE *input_file)
79 {
80 const size_t chunk_size = 32;
81 if (!*buffer)
82 *buf_size = 0;
83
84 size_t read = 0;
85 do {
86 if (read + 1 > *buf_size) {
87 char *new_buffer;
88 if (*buffer)
89 new_buffer = realloc(*buffer, *buf_size + chunk_size);
90 else
91 new_buffer = malloc(chunk_size);
92 if (!new_buffer) {
93 LOG_ERROR("Out of memory");
94 return -1;
95 }
96 *buffer = new_buffer;
97 *buf_size += chunk_size;
98 }
99
100 int c = fgetc(input_file);
101 if ((c == EOF && read) || (char)c == '\n') {
102 (*buffer)[read++] = 0;
103 return read;
104 } else if (c == EOF) {
105 return -1;
106 }
107
108 (*buffer)[read++] = (char)c;
109 } while (1);
110
111 return -1;
112 }
113
114 static int gatemate_read_cfg_file(struct gatemate_bit_file *bit_file, const char *filename)
115 {
116 FILE *input_file = fopen(filename, "r");
117
118 if (!input_file) {
119 LOG_ERROR("Couldn't open %s: %s", filename, strerror(errno));
120 return ERROR_PLD_FILE_LOAD_FAILED;
121 }
122
123 int retval = ERROR_OK;
124 char *line_buffer = NULL;
125 size_t buffer_length = 0;
126 int nread;
127 while (((nread = gatemate_getline(&line_buffer, &buffer_length, input_file)) != -1) && (retval == ERROR_OK))
128 retval = gatemate_read_cfg_line(bit_file, line_buffer, (size_t)nread);
129
130 if (line_buffer)
131 free(line_buffer);
132
133 fclose(input_file);
134 if (retval != ERROR_OK)
135 free(bit_file->raw_file.data);
136 return retval;
137 }
138
139 static int gatemate_read_file(struct gatemate_bit_file *bit_file, const char *filename)
140 {
141 memset(bit_file, 0, sizeof(struct gatemate_bit_file));
142
143 if (!filename || !bit_file)
144 return ERROR_COMMAND_SYNTAX_ERROR;
145
146 /* check if binary .bit or ascii .cfg */
147 const char *file_suffix_pos = strrchr(filename, '.');
148 if (!file_suffix_pos) {
149 LOG_ERROR("Unable to detect filename suffix");
150 return ERROR_PLD_FILE_LOAD_FAILED;
151 }
152
153 if (strcasecmp(file_suffix_pos, ".bit") == 0)
154 return cpld_read_raw_bit_file(&bit_file->raw_file, filename);
155 else if (strcasecmp(file_suffix_pos, ".cfg") == 0)
156 return gatemate_read_cfg_file(bit_file, filename);
157
158 LOG_ERROR("Filetype not supported, expecting .bit or .cfg file");
159 return ERROR_PLD_FILE_LOAD_FAILED;
160 }
161
162 static int gatemate_set_instr(struct jtag_tap *tap, uint8_t new_instr)
163 {
164 struct scan_field field;
165 field.num_bits = tap->ir_length;
166 void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
167 if (!t) {
168 LOG_ERROR("Out of memory");
169 return ERROR_FAIL;
170 }
171 field.out_value = t;
172 buf_set_u32(t, 0, field.num_bits, new_instr);
173 field.in_value = NULL;
174 jtag_add_ir_scan(tap, &field, TAP_IDLE);
175 jtag_add_runtest(3, TAP_IDLE);
176 free(t);
177 return ERROR_OK;
178 }
179
180 static int gatemate_load(struct pld_device *pld_device, const char *filename)
181 {
182 if (!pld_device)
183 return ERROR_FAIL;
184
185 struct gatemate_pld_device *gatemate_info = pld_device->driver_priv;
186
187 if (!gatemate_info || !gatemate_info->tap)
188 return ERROR_FAIL;
189 struct jtag_tap *tap = gatemate_info->tap;
190
191 struct gatemate_bit_file bit_file;
192 int retval = gatemate_read_file(&bit_file, filename);
193 if (retval != ERROR_OK)
194 return retval;
195
196 retval = gatemate_set_instr(tap, JTAG_CONFIGURE);
197 if (retval != ERROR_OK) {
198 free(bit_file.raw_file.data);
199 return retval;
200 }
201
202 struct scan_field field;
203 field.num_bits = bit_file.raw_file.length * 8;
204 field.out_value = bit_file.raw_file.data;
205 field.in_value = NULL;
206 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
207
208 retval = jtag_execute_queue();
209 free(bit_file.raw_file.data);
210
211 return retval;
212 }
213
214 static int gatemate_has_jtagspi_instruction(struct pld_device *device, bool *has_instruction)
215 {
216 *has_instruction = true;
217 return ERROR_OK;
218 }
219
220 static int gatemate_connect_spi_to_jtag(struct pld_device *pld_device)
221 {
222 if (!pld_device)
223 return ERROR_FAIL;
224
225 struct gatemate_pld_device *pld_device_info = pld_device->driver_priv;
226 if (!pld_device_info)
227 return ERROR_FAIL;
228
229 struct jtag_tap *tap = pld_device_info->tap;
230 if (!tap)
231 return ERROR_FAIL;
232
233 if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == JTAG_SPI_BYPASS)
234 return ERROR_OK;
235
236 gatemate_set_instr(tap, JTAG_SPI_BYPASS);
237
238 return jtag_execute_queue();
239 }
240
241 static int gatemate_disconnect_spi_from_jtag(struct pld_device *pld_device)
242 {
243 if (!pld_device)
244 return ERROR_FAIL;
245
246 struct gatemate_pld_device *pld_device_info = pld_device->driver_priv;
247 if (!pld_device_info)
248 return ERROR_FAIL;
249
250 struct jtag_tap *tap = pld_device_info->tap;
251 if (!tap)
252 return ERROR_FAIL;
253
254 if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != JTAG_SPI_BYPASS)
255 return ERROR_OK;
256
257 gatemate_set_instr(tap, BYPASS);
258
259 return jtag_execute_queue();
260 }
261
262 static int gatemate_get_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits,
263 unsigned int *trailing_write_bits)
264 {
265 if (!pld_device)
266 return ERROR_FAIL;
267
268 *facing_read_bits = 1;
269 *trailing_write_bits = 1;
270
271 return ERROR_OK;
272 }
273
274 PLD_CREATE_COMMAND_HANDLER(gatemate_pld_create_command)
275 {
276 if (CMD_ARGC != 4)
277 return ERROR_COMMAND_SYNTAX_ERROR;
278
279 if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
280 return ERROR_COMMAND_SYNTAX_ERROR;
281
282 struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
283 if (!tap) {
284 command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
285 return ERROR_FAIL;
286 }
287
288 struct gatemate_pld_device *gatemate_info = malloc(sizeof(struct gatemate_pld_device));
289 if (!gatemate_info) {
290 LOG_ERROR("Out of memory");
291 return ERROR_FAIL;
292 }
293 gatemate_info->tap = tap;
294
295 pld->driver_priv = gatemate_info;
296
297 return ERROR_OK;
298 }
299
300 struct pld_driver gatemate_pld = {
301 .name = "gatemate",
302 .pld_create_command = &gatemate_pld_create_command,
303 .load = &gatemate_load,
304 .has_jtagspi_instruction = gatemate_has_jtagspi_instruction,
305 .connect_spi_to_jtag = gatemate_connect_spi_to_jtag,
306 .disconnect_spi_from_jtag = gatemate_disconnect_spi_from_jtag,
307 .get_stuff_bits = gatemate_get_stuff_bits,
308 };

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)