jtag: drivers: xlnx-pcie-xvc: fix build on Linux pre v4.10
[fw/openocd] / src / jtag / drivers / xlnx-pcie-xvc.c
1 /* SPDX-License-Identifier: GPL-2.0
2  *
3  * Copyright (c) 2019 Google, LLC.
4  * Author: Moritz Fischer <moritzf@google.com>
5  */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include <stdint.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <unistd.h>
15 #include <linux/pci.h>
16
17 #include <jtag/interface.h>
18 #include <jtag/swd.h>
19 #include <jtag/commands.h>
20 #include <helper/replacements.h>
21 #include <helper/bits.h>
22
23 /* Available only from kernel v4.10 */
24 #ifndef PCI_CFG_SPACE_EXP_SIZE
25 #define PCI_CFG_SPACE_EXP_SIZE  4096
26 #endif
27
28 #define PCIE_EXT_CAP_LST        0x100
29
30 #define XLNX_XVC_EXT_CAP        0x00
31 #define XLNX_XVC_VSEC_HDR       0x04
32 #define XLNX_XVC_LEN_REG        0x0C
33 #define XLNX_XVC_TMS_REG        0x10
34 #define XLNX_XVC_TDx_REG        0x14
35
36 #define XLNX_XVC_CAP_SIZE       0x20
37 #define XLNX_XVC_VSEC_ID        0x8
38 #define XLNX_XVC_MAX_BITS       0x20
39
40 struct xlnx_pcie_xvc {
41         int fd;
42         unsigned offset;
43         char *device;
44 };
45
46 static struct xlnx_pcie_xvc xlnx_pcie_xvc_state;
47 static struct xlnx_pcie_xvc *xlnx_pcie_xvc = &xlnx_pcie_xvc_state;
48
49 static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val)
50 {
51         uint32_t res;
52         int err;
53
54         /* Note: This should be ok endianess-wise because by going
55          * through sysfs the kernel does the conversion in the config
56          * space accessor functions
57          */
58         err = pread(xlnx_pcie_xvc->fd, &res, sizeof(res),
59                     xlnx_pcie_xvc->offset + offset);
60         if (err != sizeof(res)) {
61                 LOG_ERROR("Failed to read offset %x", offset);
62                 return ERROR_JTAG_DEVICE_ERROR;
63         }
64
65         if (val)
66                 *val = res;
67
68         return ERROR_OK;
69 }
70
71 static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val)
72 {
73         int err;
74
75         /* Note: This should be ok endianess-wise because by going
76          * through sysfs the kernel does the conversion in the config
77          * space accessor functions
78          */
79         err = pwrite(xlnx_pcie_xvc->fd, &val, sizeof(val),
80                      xlnx_pcie_xvc->offset + offset);
81         if (err != sizeof(val)) {
82                 LOG_ERROR("Failed to write offset: %x with value: %x",
83                           offset, val);
84                 return ERROR_JTAG_DEVICE_ERROR;
85         }
86
87         return ERROR_OK;
88 }
89
90 static int xlnx_pcie_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi,
91                                   uint32_t *tdo)
92 {
93         int err;
94
95         err = xlnx_pcie_xvc_write_reg(XLNX_XVC_LEN_REG, num_bits);
96         if (err != ERROR_OK)
97                 return err;
98
99         err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TMS_REG, tms);
100         if (err != ERROR_OK)
101                 return err;
102
103         err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TDx_REG, tdi);
104         if (err != ERROR_OK)
105                 return err;
106
107         err = xlnx_pcie_xvc_read_reg(XLNX_XVC_TDx_REG, tdo);
108         if (err != ERROR_OK)
109                 return err;
110
111         if (tdo)
112                 LOG_DEBUG_IO("Transact num_bits: %zu, tms: %x, tdi: %x, tdo: %x",
113                              num_bits, tms, tdi, *tdo);
114         else
115                 LOG_DEBUG_IO("Transact num_bits: %zu, tms: %x, tdi: %x, tdo: <null>",
116                              num_bits, tms, tdi);
117         return ERROR_OK;
118 }
119
120 int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
121 {
122         int tms = tap_get_state() == TAP_RESET ? 1 : 0;
123         size_t left = cmd->cmd.stableclocks->num_cycles;
124         size_t write;
125         int err;
126
127         LOG_DEBUG("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
128
129         while (left) {
130                 write = MIN(XLNX_XVC_MAX_BITS, left);
131                 err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
132                 if (err != ERROR_OK)
133                         return err;
134                 left -= write;
135         };
136
137         return ERROR_OK;
138 }
139
140 static int xlnx_pcie_xvc_execute_statemove(size_t skip)
141 {
142         uint8_t tms_scan = tap_get_tms_path(tap_get_state(),
143                                             tap_get_end_state());
144         int tms_count = tap_get_tms_path_len(tap_get_state(),
145                                              tap_get_end_state());
146         int err;
147
148         LOG_DEBUG("statemove starting at (skip: %zu) %s end in %s", skip,
149                   tap_state_name(tap_get_state()),
150                   tap_state_name(tap_get_end_state()));
151
152
153         err = xlnx_pcie_xvc_transact(tms_count - skip, tms_scan >> skip, 0, NULL);
154         if (err != ERROR_OK)
155                 return err;
156
157         tap_set_state(tap_get_end_state());
158
159         return ERROR_OK;
160 }
161
162 static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
163 {
164         int err = ERROR_OK;
165
166         LOG_DEBUG("runtest %i cycles, end in %i",
167                   cmd->cmd.runtest->num_cycles,
168                   cmd->cmd.runtest->end_state);
169
170         tap_state_t tmp_state = tap_get_end_state();
171
172         if (tap_get_state() != TAP_IDLE) {
173                 tap_set_end_state(TAP_IDLE);
174                 err = xlnx_pcie_xvc_execute_statemove(0);
175                 if (err != ERROR_OK)
176                         return err;
177         };
178
179         size_t left = cmd->cmd.runtest->num_cycles;
180         size_t write;
181
182         while (left) {
183                 write = MIN(XLNX_XVC_MAX_BITS, left);
184                 err = xlnx_pcie_xvc_transact(write, 0, 0, NULL);
185                 if (err != ERROR_OK)
186                         return err;
187                 left -= write;
188         };
189
190         tap_set_end_state(tmp_state);
191         if (tap_get_state() != tap_get_end_state())
192                 err = xlnx_pcie_xvc_execute_statemove(0);
193
194         return err;
195 }
196
197 static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
198 {
199         size_t num_states = cmd->cmd.pathmove->num_states;
200         tap_state_t *path = cmd->cmd.pathmove->path;
201         int err = ERROR_OK;
202         size_t i;
203
204         LOG_DEBUG("pathmove: %i states, end in %i",
205                   cmd->cmd.pathmove->num_states,
206                   cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
207
208         for (i = 0; i < num_states; i++) {
209                 if (path[i] == tap_state_transition(tap_get_state(), false)) {
210                         err = xlnx_pcie_xvc_transact(1, 1, 0, NULL);
211                 } else if (path[i] == tap_state_transition(tap_get_state(), true)) {
212                         err = xlnx_pcie_xvc_transact(1, 0, 0, NULL);
213                 } else {
214                         LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.",
215                                   tap_state_name(tap_get_state()),
216                                   tap_state_name(path[i]));
217                         err = ERROR_JTAG_QUEUE_FAILED;
218                 }
219                 if (err != ERROR_OK)
220                         return err;
221                 tap_set_state(path[i]);
222         }
223
224         tap_set_end_state(tap_get_state());
225
226         return ERROR_OK;
227 }
228
229 static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
230 {
231         enum scan_type type = jtag_scan_type(cmd->cmd.scan);
232         tap_state_t saved_end_state = cmd->cmd.scan->end_state;
233         bool ir_scan = cmd->cmd.scan->ir_scan;
234         uint32_t tdi, tms, tdo;
235         uint8_t *buf, *rd_ptr;
236         int err, scan_size;
237         size_t write;
238         size_t left;
239
240         scan_size = jtag_build_buffer(cmd->cmd.scan, &buf);
241         rd_ptr = buf;
242         LOG_DEBUG("%s scan type %d %d bits; starts in %s end in %s",
243                   (cmd->cmd.scan->ir_scan) ? "IR" : "DR", type, scan_size,
244                   tap_state_name(tap_get_state()),
245                   tap_state_name(cmd->cmd.scan->end_state));
246
247         /* If we're in TAP_DR_SHIFT state but need to do a IR_SCAN or
248          * vice-versa, do a statemove to corresponding other state, then restore
249          * end state
250          */
251         if (ir_scan && tap_get_state() != TAP_IRSHIFT) {
252                 tap_set_end_state(TAP_IRSHIFT);
253                 err = xlnx_pcie_xvc_execute_statemove(0);
254                 if (err != ERROR_OK)
255                         goto out_err;
256                 tap_set_end_state(saved_end_state);
257         } else if (!ir_scan && (tap_get_state() != TAP_DRSHIFT)) {
258                 tap_set_end_state(TAP_DRSHIFT);
259                 err = xlnx_pcie_xvc_execute_statemove(0);
260                 if (err != ERROR_OK)
261                         goto out_err;
262                 tap_set_end_state(saved_end_state);
263         }
264
265         left = scan_size;
266         while (left) {
267                 write = MIN(XLNX_XVC_MAX_BITS, left);
268                 /* the last TMS should be a 1, to leave the state */
269                 tms = left <= XLNX_XVC_MAX_BITS ? BIT(write - 1) : 0;
270                 tdi = (type != SCAN_IN) ? buf_get_u32(rd_ptr, 0, write) : 0;
271                 err = xlnx_pcie_xvc_transact(write, tms, tdi, type != SCAN_OUT ?
272                                              &tdo : NULL);
273                 if (err != ERROR_OK)
274                         goto out_err;
275                 left -= write;
276                 if (type != SCAN_OUT)
277                         buf_set_u32(rd_ptr, 0, write, tdo);
278                 rd_ptr += sizeof(uint32_t);
279         };
280
281         err = jtag_read_buffer(buf, cmd->cmd.scan);
282         if (buf)
283                 free(buf);
284
285         if (tap_get_state() != tap_get_end_state())
286                 err = xlnx_pcie_xvc_execute_statemove(1);
287
288         return err;
289
290 out_err:
291         if (buf)
292                 free(buf);
293         return err;
294 }
295
296 static void xlnx_pcie_xvc_execute_reset(struct jtag_command *cmd)
297 {
298         LOG_DEBUG("reset trst: %i srst: %i", cmd->cmd.reset->trst,
299                   cmd->cmd.reset->srst);
300 }
301
302 static void xlnx_pcie_xvc_execute_sleep(struct jtag_command *cmd)
303 {
304         LOG_DEBUG("sleep %" PRIi32 "", cmd->cmd.sleep->us);
305         usleep(cmd->cmd.sleep->us);
306 }
307
308 static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd)
309 {
310         const size_t num_bits = cmd->cmd.tms->num_bits;
311         const uint8_t *bits = cmd->cmd.tms->bits;
312         size_t left, write;
313         uint32_t tms;
314         int err;
315
316         LOG_DEBUG("execute tms %zu", num_bits);
317
318         left = num_bits;
319         while (left) {
320                 write = MIN(XLNX_XVC_MAX_BITS, left);
321                 tms = buf_get_u32(bits, 0, write);
322                 err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
323                 if (err != ERROR_OK)
324                         return err;
325                 left -= write;
326                 bits += 4;
327         };
328
329         return ERROR_OK;
330 }
331
332 static int xlnx_pcie_xvc_execute_command(struct jtag_command *cmd)
333 {
334         LOG_DEBUG("%s: cmd->type: %u", __func__, cmd->type);
335         switch (cmd->type) {
336         case JTAG_STABLECLOCKS:
337                 return xlnx_pcie_xvc_execute_stableclocks(cmd);
338         case JTAG_RUNTEST:
339                 return xlnx_pcie_xvc_execute_runtest(cmd);
340         case JTAG_TLR_RESET:
341                 tap_set_end_state(cmd->cmd.statemove->end_state);
342                 return xlnx_pcie_xvc_execute_statemove(0);
343         case JTAG_PATHMOVE:
344                 return xlnx_pcie_xvc_execute_pathmove(cmd);
345         case JTAG_SCAN:
346                 return xlnx_pcie_xvc_execute_scan(cmd);
347         case JTAG_RESET:
348                 xlnx_pcie_xvc_execute_reset(cmd);
349                 break;
350         case JTAG_SLEEP:
351                 xlnx_pcie_xvc_execute_sleep(cmd);
352                 break;
353         case JTAG_TMS:
354                 return xlnx_pcie_xvc_execute_tms(cmd);
355         default:
356                 LOG_ERROR("BUG: Unknown JTAG command type encountered.");
357                 return ERROR_JTAG_QUEUE_FAILED;
358         }
359
360         return ERROR_OK;
361 }
362
363 static int xlnx_pcie_xvc_execute_queue(void)
364 {
365         struct jtag_command *cmd = jtag_command_queue;
366         int ret;
367
368         while (cmd) {
369                 ret = xlnx_pcie_xvc_execute_command(cmd);
370
371                 if (ret != ERROR_OK)
372                         return ret;
373
374                 cmd = cmd->next;
375         }
376
377         return ERROR_OK;
378 }
379
380
381 static int xlnx_pcie_xvc_init(void)
382 {
383         char filename[PATH_MAX];
384         uint32_t cap, vh;
385         int err;
386
387         snprintf(filename, PATH_MAX, "/sys/bus/pci/devices/%s/config",
388                  xlnx_pcie_xvc->device);
389         xlnx_pcie_xvc->fd = open(filename, O_RDWR | O_SYNC);
390         if (xlnx_pcie_xvc->fd < 0) {
391                 LOG_ERROR("Failed to open device: %s", filename);
392                 return ERROR_JTAG_INIT_FAILED;
393         }
394
395         LOG_INFO("Scanning PCIe device %s's for Xilinx XVC/PCIe ...",
396                  xlnx_pcie_xvc->device);
397         /* Parse the PCIe extended capability list and try to find
398          * vendor specific header */
399         xlnx_pcie_xvc->offset = PCIE_EXT_CAP_LST;
400         while (xlnx_pcie_xvc->offset <= PCI_CFG_SPACE_EXP_SIZE - sizeof(cap) &&
401                xlnx_pcie_xvc->offset >= PCIE_EXT_CAP_LST) {
402                 err = xlnx_pcie_xvc_read_reg(XLNX_XVC_EXT_CAP, &cap);
403                 if (err != ERROR_OK)
404                         return err;
405                 LOG_DEBUG("Checking capability at 0x%x; id=0x%04x version=0x%x next=0x%x",
406                          xlnx_pcie_xvc->offset,
407                          PCI_EXT_CAP_ID(cap),
408                          PCI_EXT_CAP_VER(cap),
409                          PCI_EXT_CAP_NEXT(cap));
410                 if (PCI_EXT_CAP_ID(cap) == PCI_EXT_CAP_ID_VNDR) {
411                         err = xlnx_pcie_xvc_read_reg(XLNX_XVC_VSEC_HDR, &vh);
412                         if (err != ERROR_OK)
413                                 return err;
414                         LOG_DEBUG("Checking possible match at 0x%x; id: 0x%x; rev: 0x%x; length: 0x%x",
415                                  xlnx_pcie_xvc->offset,
416                                  PCI_VNDR_HEADER_ID(vh),
417                                  PCI_VNDR_HEADER_REV(vh),
418                                  PCI_VNDR_HEADER_LEN(vh));
419                         if ((PCI_VNDR_HEADER_ID(vh) == XLNX_XVC_VSEC_ID) &&
420                             (PCI_VNDR_HEADER_LEN(vh) == XLNX_XVC_CAP_SIZE))
421                                 break;
422                 }
423                 xlnx_pcie_xvc->offset = PCI_EXT_CAP_NEXT(cap);
424         }
425         if ((xlnx_pcie_xvc->offset > PCI_CFG_SPACE_EXP_SIZE - XLNX_XVC_CAP_SIZE) ||
426              xlnx_pcie_xvc->offset < PCIE_EXT_CAP_LST) {
427                 close(xlnx_pcie_xvc->fd);
428                 return ERROR_JTAG_INIT_FAILED;
429         }
430
431         LOG_INFO("Found Xilinx XVC/PCIe capability at offset: 0x%x", xlnx_pcie_xvc->offset);
432
433         return ERROR_OK;
434 }
435
436 static int xlnx_pcie_xvc_quit(void)
437 {
438         int err;
439
440         err = close(xlnx_pcie_xvc->fd);
441         if (err)
442                 return err;
443
444         return ERROR_OK;
445 }
446
447 COMMAND_HANDLER(xlnx_pcie_xvc_handle_config_command)
448 {
449         if (CMD_ARGC < 1)
450                 return ERROR_COMMAND_SYNTAX_ERROR;
451
452         /* we can't really free this in a safe manner, so at least
453          * limit the memory we're leaking by freeing the old one first
454          * before allocating a new one ...
455          */
456         if (xlnx_pcie_xvc->device)
457                 free(xlnx_pcie_xvc->device);
458
459         xlnx_pcie_xvc->device = strdup(CMD_ARGV[0]);
460         return ERROR_OK;
461 }
462
463 static const struct command_registration xlnx_pcie_xvc_command_handlers[] = {
464         {
465                 .name = "xlnx_pcie_xvc_config",
466                 .handler = xlnx_pcie_xvc_handle_config_command,
467                 .mode = COMMAND_CONFIG,
468                 .help = "Configure XVC/PCIe JTAG adapter",
469                 .usage = "device",
470         },
471         COMMAND_REGISTRATION_DONE
472 };
473
474 static struct jtag_interface xlnx_pcie_xvc_interface = {
475         .execute_queue = &xlnx_pcie_xvc_execute_queue,
476 };
477
478 struct adapter_driver xlnx_pcie_xvc_adapter_driver = {
479         .name = "xlnx_pcie_xvc",
480         .transports = jtag_only,
481         .commands = xlnx_pcie_xvc_command_handlers,
482
483         .init = &xlnx_pcie_xvc_init,
484         .quit = &xlnx_pcie_xvc_quit,
485
486         .jtag_ops = &xlnx_pcie_xvc_interface,
487 };