1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2006 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 ***************************************************************************/
14 #include <helper/log.h>
15 #include <helper/replacements.h>
16 #include <helper/time_support.h>
19 static struct pld_driver
*pld_drivers
[] = {
29 static struct pld_device
*pld_devices
;
31 struct pld_device
*get_pld_device_by_num(int num
)
36 for (p
= pld_devices
; p
; p
= p
->next
) {
38 LOG_WARNING("DEPRECATED: use pld name \"%s\" instead of number %d", p
->name
, num
);
46 struct pld_device
*get_pld_device_by_name(const char *name
)
48 for (struct pld_device
*p
= pld_devices
; p
; p
= p
->next
) {
49 if (strcmp(p
->name
, name
) == 0)
56 struct pld_device
*get_pld_device_by_name_or_numstr(const char *str
)
58 struct pld_device
*dev
= get_pld_device_by_name(str
);
63 unsigned long dev_num
= strtoul(str
, &end
, 0);
64 if (*end
|| dev_num
> INT_MAX
) {
65 LOG_ERROR("Invalid argument");
69 return get_pld_device_by_num(dev_num
);
73 int pld_has_jtagspi_instruction(struct pld_device
*pld_device
, bool *has_instruction
)
75 *has_instruction
= false; /* default is using a proxy bitstream */
80 struct pld_driver
*pld_driver
= pld_device
->driver
;
82 LOG_ERROR("pld device has no associated driver");
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) */
92 int pld_get_jtagspi_userircode(struct pld_device
*pld_device
, unsigned int *ir
)
97 struct pld_driver
*pld_driver
= pld_device
->driver
;
99 LOG_ERROR("pld device has no associated driver");
103 if (pld_driver
->get_jtagspi_userircode
)
104 return pld_driver
->get_jtagspi_userircode(pld_device
, ir
);
109 int pld_get_jtagspi_stuff_bits(struct pld_device
*pld_device
, unsigned int *facing_read_bits
,
110 unsigned int *trailing_write_bits
)
115 struct pld_driver
*pld_driver
= pld_device
->driver
;
117 LOG_ERROR("pld device has no associated driver");
121 if (pld_driver
->get_stuff_bits
)
122 return pld_driver
->get_stuff_bits(pld_device
, facing_read_bits
, trailing_write_bits
);
127 int pld_connect_spi_to_jtag(struct pld_device
*pld_device
)
132 struct pld_driver
*pld_driver
= pld_device
->driver
;
134 LOG_ERROR("pld device has no associated driver");
138 if (pld_driver
->connect_spi_to_jtag
)
139 return pld_driver
->connect_spi_to_jtag(pld_device
);
144 int pld_disconnect_spi_from_jtag(struct pld_device
*pld_device
)
149 struct pld_driver
*pld_driver
= pld_device
->driver
;
151 LOG_ERROR("pld device has no associated driver");
155 if (pld_driver
->disconnect_spi_from_jtag
)
156 return pld_driver
->disconnect_spi_from_jtag(pld_device
);
161 COMMAND_HANDLER(handle_pld_create_command
)
164 return ERROR_COMMAND_SYNTAX_ERROR
;
166 struct pld_driver
*pld_driver
= NULL
;
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
];
176 LOG_ERROR("pld driver '%s' not found", CMD_ARGV
[1]);
177 return ERROR_FAIL
; /* exit(-1); */
180 if (get_pld_device_by_name(CMD_ARGV
[0])) {
181 LOG_ERROR("pld device with name '%s' already exists", CMD_ARGV
[0]);
185 struct pld_device
*pld_device
= malloc(sizeof(struct pld_device
));
187 LOG_ERROR("Out of memory");
191 pld_device
->driver
= pld_driver
;
192 pld_device
->next
= NULL
;
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",
201 pld_device
->name
= strdup(CMD_ARGV
[0]);
202 if (!pld_device
->name
) {
203 LOG_ERROR("Out of memory");
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
);
220 /* find last pld device */
221 struct pld_device
*p
= pld_devices
;
222 for (; p
&& p
->next
; p
= p
->next
)
225 p
->next
= pld_device
;
227 pld_devices
= pld_device
;
233 COMMAND_HANDLER(handle_pld_devices_command
)
235 struct pld_device
*p
;
239 command_print(CMD
, "no pld devices configured");
243 for (p
= pld_devices
; p
; p
= p
->next
)
244 command_print(CMD
, "#%i: %s (driver: %s)", i
++, p
->name
, p
->driver
->name
);
249 COMMAND_HANDLER(handle_pld_load_command
)
252 struct timeval start
, end
, duration
;
253 struct pld_device
*p
;
255 gettimeofday(&start
, NULL
);
258 return ERROR_COMMAND_SYNTAX_ERROR
;
260 p
= get_pld_device_by_name_or_numstr(CMD_ARGV
[0]);
262 command_print(CMD
, "pld device '#%s' is out of bounds or unknown", CMD_ARGV
[0]);
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
;
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
;
277 if (input_stat
.st_size
== 0) {
278 LOG_ERROR("Empty file %s", CMD_ARGV
[1]);
279 return ERROR_PLD_FILE_LOAD_FAILED
;
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]);
288 gettimeofday(&end
, NULL
);
289 timeval_subtract(&duration
, &end
, &start
);
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
);
299 static const struct command_registration pld_exec_command_handlers
[] = {
302 .handler
= handle_pld_devices_command
,
303 .mode
= COMMAND_EXEC
,
304 .help
= "list configured pld devices",
309 .handler
= handle_pld_load_command
,
310 .mode
= COMMAND_EXEC
,
311 .help
= "load configuration file into PLD",
312 .usage
= "pld_name filename",
314 COMMAND_REGISTRATION_DONE
317 static int pld_init(struct command_context
*cmd_ctx
)
322 return register_commands(cmd_ctx
, "pld", pld_exec_command_handlers
);
325 COMMAND_HANDLER(handle_pld_init_command
)
328 return ERROR_COMMAND_SYNTAX_ERROR
;
330 static bool pld_initialized
;
331 if (pld_initialized
) {
332 LOG_INFO("'pld init' has already been called");
335 pld_initialized
= true;
337 LOG_DEBUG("Initializing PLDs...");
338 return pld_init(CMD_CTX
);
341 static const struct command_registration pld_config_command_handlers
[] = {
344 .mode
= COMMAND_CONFIG
,
345 .handler
= handle_pld_create_command
,
346 .help
= "create a PLD device",
347 .usage
= "name.pld driver_name [driver_args ... ]",
351 .mode
= COMMAND_CONFIG
,
352 .handler
= handle_pld_init_command
,
353 .help
= "initialize PLD devices",
356 COMMAND_REGISTRATION_DONE
358 static const struct command_registration pld_command_handler
[] = {
362 .help
= "programmable logic device commands",
364 .chain
= pld_config_command_handlers
,
366 COMMAND_REGISTRATION_DONE
368 int pld_register_commands(struct command_context
*cmd_ctx
)
370 return register_commands(cmd_ctx
, NULL
, pld_command_handler
);