jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / pld / pld.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 "pld.h"
13 #include <sys/stat.h>
14 #include <helper/log.h>
15 #include <helper/replacements.h>
16 #include <helper/time_support.h>
17
18
19 static struct pld_driver *pld_drivers[] = {
20 &efinix_pld,
21 &gatemate_pld,
22 &gowin_pld,
23 &intel_pld,
24 &lattice_pld,
25 &virtex2_pld,
26 NULL,
27 };
28
29 static struct pld_device *pld_devices;
30
31 struct pld_device *get_pld_device_by_num(int num)
32 {
33 struct pld_device *p;
34 int i = 0;
35
36 for (p = pld_devices; p; p = p->next) {
37 if (i++ == num) {
38 LOG_WARNING("DEPRECATED: use pld name \"%s\" instead of number %d", p->name, num);
39 return p;
40 }
41 }
42
43 return NULL;
44 }
45
46 struct pld_device *get_pld_device_by_name(const char *name)
47 {
48 for (struct pld_device *p = pld_devices; p; p = p->next) {
49 if (strcmp(p->name, name) == 0)
50 return p;
51 }
52
53 return NULL;
54 }
55
56 struct pld_device *get_pld_device_by_name_or_numstr(const char *str)
57 {
58 struct pld_device *dev = get_pld_device_by_name(str);
59 if (dev)
60 return dev;
61
62 char *end;
63 unsigned long dev_num = strtoul(str, &end, 0);
64 if (*end || dev_num > INT_MAX) {
65 LOG_ERROR("Invalid argument");
66 return NULL;
67 }
68
69 return get_pld_device_by_num(dev_num);
70 }
71
72
73 int pld_has_jtagspi_instruction(struct pld_device *pld_device, bool *has_instruction)
74 {
75 *has_instruction = false; /* default is using a proxy bitstream */
76
77 if (!pld_device)
78 return ERROR_FAIL;
79
80 struct pld_driver *pld_driver = pld_device->driver;
81 if (!pld_driver) {
82 LOG_ERROR("pld device has no associated driver");
83 return ERROR_FAIL;
84 }
85
86 if (pld_driver->has_jtagspi_instruction)
87 return pld_driver->has_jtagspi_instruction(pld_device, has_instruction);
88 /* else, take the default (proxy bitstream) */
89 return ERROR_OK;
90 }
91
92 int pld_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir)
93 {
94 if (!pld_device)
95 return ERROR_FAIL;
96
97 struct pld_driver *pld_driver = pld_device->driver;
98 if (!pld_driver) {
99 LOG_ERROR("pld device has no associated driver");
100 return ERROR_FAIL;
101 }
102
103 if (pld_driver->get_jtagspi_userircode)
104 return pld_driver->get_jtagspi_userircode(pld_device, ir);
105
106 return ERROR_FAIL;
107 }
108
109 int pld_get_jtagspi_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits,
110 unsigned int *trailing_write_bits)
111 {
112 if (!pld_device)
113 return ERROR_FAIL;
114
115 struct pld_driver *pld_driver = pld_device->driver;
116 if (!pld_driver) {
117 LOG_ERROR("pld device has no associated driver");
118 return ERROR_FAIL;
119 }
120
121 if (pld_driver->get_stuff_bits)
122 return pld_driver->get_stuff_bits(pld_device, facing_read_bits, trailing_write_bits);
123
124 return ERROR_OK;
125 }
126
127 int pld_connect_spi_to_jtag(struct pld_device *pld_device)
128 {
129 if (!pld_device)
130 return ERROR_FAIL;
131
132 struct pld_driver *pld_driver = pld_device->driver;
133 if (!pld_driver) {
134 LOG_ERROR("pld device has no associated driver");
135 return ERROR_FAIL;
136 }
137
138 if (pld_driver->connect_spi_to_jtag)
139 return pld_driver->connect_spi_to_jtag(pld_device);
140
141 return ERROR_FAIL;
142 }
143
144 int pld_disconnect_spi_from_jtag(struct pld_device *pld_device)
145 {
146 if (!pld_device)
147 return ERROR_FAIL;
148
149 struct pld_driver *pld_driver = pld_device->driver;
150 if (!pld_driver) {
151 LOG_ERROR("pld device has no associated driver");
152 return ERROR_FAIL;
153 }
154
155 if (pld_driver->disconnect_spi_from_jtag)
156 return pld_driver->disconnect_spi_from_jtag(pld_device);
157
158 return ERROR_FAIL;
159 }
160
161 COMMAND_HANDLER(handle_pld_create_command)
162 {
163 if (CMD_ARGC < 2)
164 return ERROR_COMMAND_SYNTAX_ERROR;
165
166 struct pld_driver *pld_driver = NULL;
167
168 for (int i = 0; pld_drivers[i]; i++) {
169 if (strcmp(CMD_ARGV[1], pld_drivers[i]->name) == 0) {
170 pld_driver = pld_drivers[i];
171 break;
172 }
173 }
174
175 if (!pld_driver) {
176 LOG_ERROR("pld driver '%s' not found", CMD_ARGV[1]);
177 return ERROR_FAIL; /* exit(-1); */
178 }
179
180 if (get_pld_device_by_name(CMD_ARGV[0])) {
181 LOG_ERROR("pld device with name '%s' already exists", CMD_ARGV[0]);
182 return ERROR_FAIL;
183 }
184
185 struct pld_device *pld_device = malloc(sizeof(struct pld_device));
186 if (!pld_device) {
187 LOG_ERROR("Out of memory");
188 return ERROR_FAIL;
189 }
190
191 pld_device->driver = pld_driver;
192 pld_device->next = NULL;
193
194 int retval = CALL_COMMAND_HANDLER(pld_driver->pld_create_command, pld_device);
195 if (retval != ERROR_OK) {
196 LOG_ERROR("'%s' driver rejected pld device",
197 CMD_ARGV[1]);
198 free(pld_device);
199 return ERROR_OK;
200 }
201 pld_device->name = strdup(CMD_ARGV[0]);
202 if (!pld_device->name) {
203 LOG_ERROR("Out of memory");
204 free(pld_device);
205 return ERROR_FAIL;
206 }
207
208 /* register pld specific commands */
209 if (pld_driver->commands) {
210 retval = register_commands(CMD_CTX, NULL, pld_driver->commands);
211 if (retval != ERROR_OK) {
212 LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[1]);
213 free(pld_device->name);
214 free(pld_device);
215 return ERROR_FAIL;
216 }
217 }
218
219 if (pld_devices) {
220 /* find last pld device */
221 struct pld_device *p = pld_devices;
222 for (; p && p->next; p = p->next)
223 ;
224 if (p)
225 p->next = pld_device;
226 } else {
227 pld_devices = pld_device;
228 }
229
230 return ERROR_OK;
231 }
232
233 COMMAND_HANDLER(handle_pld_devices_command)
234 {
235 struct pld_device *p;
236 int i = 0;
237
238 if (!pld_devices) {
239 command_print(CMD, "no pld devices configured");
240 return ERROR_OK;
241 }
242
243 for (p = pld_devices; p; p = p->next)
244 command_print(CMD, "#%i: %s (driver: %s)", i++, p->name, p->driver->name);
245
246 return ERROR_OK;
247 }
248
249 COMMAND_HANDLER(handle_pld_load_command)
250 {
251 int retval;
252 struct timeval start, end, duration;
253 struct pld_device *p;
254
255 gettimeofday(&start, NULL);
256
257 if (CMD_ARGC < 2)
258 return ERROR_COMMAND_SYNTAX_ERROR;
259
260 p = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
261 if (!p) {
262 command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
263 return ERROR_OK;
264 }
265
266 struct stat input_stat;
267 if (stat(CMD_ARGV[1], &input_stat) == -1) {
268 LOG_ERROR("couldn't stat() %s: %s", CMD_ARGV[1], strerror(errno));
269 return ERROR_PLD_FILE_LOAD_FAILED;
270 }
271
272 if (S_ISDIR(input_stat.st_mode)) {
273 LOG_ERROR("%s is a directory", CMD_ARGV[1]);
274 return ERROR_PLD_FILE_LOAD_FAILED;
275 }
276
277 if (input_stat.st_size == 0) {
278 LOG_ERROR("Empty file %s", CMD_ARGV[1]);
279 return ERROR_PLD_FILE_LOAD_FAILED;
280 }
281
282 retval = p->driver->load(p, CMD_ARGV[1]);
283 if (retval != ERROR_OK) {
284 command_print(CMD, "failed loading file %s to pld device %s",
285 CMD_ARGV[1], CMD_ARGV[0]);
286 return retval;
287 } else {
288 gettimeofday(&end, NULL);
289 timeval_subtract(&duration, &end, &start);
290
291 command_print(CMD, "loaded file %s to pld device %s in %jis %jius",
292 CMD_ARGV[1], CMD_ARGV[0],
293 (intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec);
294 }
295
296 return ERROR_OK;
297 }
298
299 static const struct command_registration pld_exec_command_handlers[] = {
300 {
301 .name = "devices",
302 .handler = handle_pld_devices_command,
303 .mode = COMMAND_EXEC,
304 .help = "list configured pld devices",
305 .usage = "",
306 },
307 {
308 .name = "load",
309 .handler = handle_pld_load_command,
310 .mode = COMMAND_EXEC,
311 .help = "load configuration file into PLD",
312 .usage = "pld_name filename",
313 },
314 COMMAND_REGISTRATION_DONE
315 };
316
317 static int pld_init(struct command_context *cmd_ctx)
318 {
319 if (!pld_devices)
320 return ERROR_OK;
321
322 return register_commands(cmd_ctx, "pld", pld_exec_command_handlers);
323 }
324
325 COMMAND_HANDLER(handle_pld_init_command)
326 {
327 if (CMD_ARGC != 0)
328 return ERROR_COMMAND_SYNTAX_ERROR;
329
330 static bool pld_initialized;
331 if (pld_initialized) {
332 LOG_INFO("'pld init' has already been called");
333 return ERROR_OK;
334 }
335 pld_initialized = true;
336
337 LOG_DEBUG("Initializing PLDs...");
338 return pld_init(CMD_CTX);
339 }
340
341 static const struct command_registration pld_config_command_handlers[] = {
342 {
343 .name = "create",
344 .mode = COMMAND_CONFIG,
345 .handler = handle_pld_create_command,
346 .help = "create a PLD device",
347 .usage = "name.pld driver_name [driver_args ... ]",
348 },
349 {
350 .name = "init",
351 .mode = COMMAND_CONFIG,
352 .handler = handle_pld_init_command,
353 .help = "initialize PLD devices",
354 .usage = ""
355 },
356 COMMAND_REGISTRATION_DONE
357 };
358 static const struct command_registration pld_command_handler[] = {
359 {
360 .name = "pld",
361 .mode = COMMAND_ANY,
362 .help = "programmable logic device commands",
363 .usage = "",
364 .chain = pld_config_command_handlers,
365 },
366 COMMAND_REGISTRATION_DONE
367 };
368 int pld_register_commands(struct command_context *cmd_ctx)
369 {
370 return register_commands(cmd_ctx, NULL, pld_command_handler);
371 }

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)