jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / driver.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 * *
7 * Copyright (C) 2007-2010 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
9 * *
10 * Copyright (C) 2009 SoftPLC Corporation *
11 * http://softplc.com *
12 * dick@softplc.com *
13 * *
14 * Copyright (C) 2009 Zachary T Welch *
15 * zw@superlucidity.net *
16 ***************************************************************************/
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <jtag/jtag.h>
23 #include <jtag/interface.h>
24 #include <jtag/commands.h>
25 #include <jtag/minidriver.h>
26 #include <helper/command.h>
27
28 struct jtag_callback_entry {
29 struct jtag_callback_entry *next;
30
31 jtag_callback_t callback;
32 jtag_callback_data_t data0;
33 jtag_callback_data_t data1;
34 jtag_callback_data_t data2;
35 jtag_callback_data_t data3;
36 };
37
38 static struct jtag_callback_entry *jtag_callback_queue_head;
39 static struct jtag_callback_entry *jtag_callback_queue_tail;
40
41 static void jtag_callback_queue_reset(void)
42 {
43 jtag_callback_queue_head = NULL;
44 jtag_callback_queue_tail = NULL;
45 }
46
47 /**
48 * see jtag_add_ir_scan()
49 *
50 */
51 int interface_jtag_add_ir_scan(struct jtag_tap *active,
52 const struct scan_field *in_fields, tap_state_t state)
53 {
54 size_t num_taps = jtag_tap_count_enabled();
55
56 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
57 struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
58 struct scan_field *out_fields = cmd_queue_alloc(num_taps * sizeof(struct scan_field));
59
60 jtag_queue_command(cmd);
61
62 cmd->type = JTAG_SCAN;
63 cmd->cmd.scan = scan;
64
65 scan->ir_scan = true;
66 scan->num_fields = num_taps; /* one field per device */
67 scan->fields = out_fields;
68 scan->end_state = state;
69
70 struct scan_field *field = out_fields; /* keep track where we insert data */
71
72 /* loop over all enabled TAPs */
73
74 for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
75 /* search the input field list for fields for the current TAP */
76
77 if (tap == active) {
78 /* if TAP is listed in input fields, copy the value */
79 tap->bypass = false;
80
81 jtag_scan_field_clone(field, in_fields);
82 } else {
83 /* if a TAP isn't listed in input fields, set it to BYPASS */
84
85 tap->bypass = true;
86
87 field->num_bits = tap->ir_length;
88 if (tap->ir_bypass_value) {
89 uint8_t *v = cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8));
90 buf_set_u64(v, 0, tap->ir_length, tap->ir_bypass_value);
91 field->out_value = v;
92 } else {
93 field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length);
94 }
95 field->in_value = NULL; /* do not collect input for tap's in bypass */
96 }
97
98 /* update device information */
99 buf_cpy(field->out_value, tap->cur_instr, tap->ir_length);
100
101 field++;
102 }
103 /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
104 assert(field == out_fields + num_taps);
105
106 return ERROR_OK;
107 }
108
109 /**
110 * see jtag_add_dr_scan()
111 *
112 */
113 int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields,
114 const struct scan_field *in_fields, tap_state_t state)
115 {
116 /* count devices in bypass */
117
118 size_t bypass_devices = 0;
119 size_t all_devices = 0;
120
121 for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
122 all_devices++;
123
124 if (tap->bypass)
125 bypass_devices++;
126 }
127
128 if (all_devices == bypass_devices) {
129 LOG_ERROR("At least one TAP shouldn't be in BYPASS mode");
130
131 return ERROR_FAIL;
132 }
133
134 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
135 struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
136 struct scan_field *out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field));
137
138 jtag_queue_command(cmd);
139
140 cmd->type = JTAG_SCAN;
141 cmd->cmd.scan = scan;
142
143 scan->ir_scan = false;
144 scan->num_fields = in_num_fields + bypass_devices;
145 scan->fields = out_fields;
146 scan->end_state = state;
147
148 struct scan_field *field = out_fields; /* keep track where we insert data */
149
150 /* loop over all enabled TAPs */
151
152 for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
153 /* if TAP is not bypassed insert matching input fields */
154
155 if (!tap->bypass) {
156 assert(active == tap);
157 #ifndef NDEBUG
158 /* remember initial position for assert() */
159 struct scan_field *start_field = field;
160 #endif /* NDEBUG */
161
162 for (int j = 0; j < in_num_fields; j++) {
163 jtag_scan_field_clone(field, in_fields + j);
164
165 field++;
166 }
167
168 assert(field > start_field); /* must have at least one input field per not bypassed TAP */
169 }
170
171 /* if a TAP is bypassed, generated a dummy bit*/
172 else {
173 field->num_bits = 1;
174 field->out_value = NULL;
175 field->in_value = NULL;
176
177 field++;
178 }
179 }
180
181 assert(field == out_fields + scan->num_fields); /* no superfluous input fields permitted */
182
183 return ERROR_OK;
184 }
185
186 static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits,
187 uint8_t *in_bits, tap_state_t state, bool ir_scan)
188 {
189 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
190 struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
191 struct scan_field *out_fields = cmd_queue_alloc(sizeof(struct scan_field));
192
193 jtag_queue_command(cmd);
194
195 cmd->type = JTAG_SCAN;
196 cmd->cmd.scan = scan;
197
198 scan->ir_scan = ir_scan;
199 scan->num_fields = 1;
200 scan->fields = out_fields;
201 scan->end_state = state;
202
203 out_fields->num_bits = num_bits;
204 out_fields->out_value = buf_cpy(out_bits, cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
205 out_fields->in_value = in_bits;
206
207 return ERROR_OK;
208 }
209
210 int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
211 {
212 return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, false);
213 }
214
215 int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
216 {
217 return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, true);
218 }
219
220 int interface_jtag_add_tlr(void)
221 {
222 tap_state_t state = TAP_RESET;
223
224 /* allocate memory for a new list member */
225 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
226
227 jtag_queue_command(cmd);
228
229 cmd->type = JTAG_TLR_RESET;
230
231 cmd->cmd.statemove = cmd_queue_alloc(sizeof(struct statemove_command));
232 cmd->cmd.statemove->end_state = state;
233
234 return ERROR_OK;
235 }
236
237 int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
238 {
239 struct jtag_command *cmd;
240
241 cmd = cmd_queue_alloc(sizeof(struct jtag_command));
242 if (!cmd)
243 return ERROR_FAIL;
244
245 cmd->type = JTAG_TMS;
246 cmd->cmd.tms = cmd_queue_alloc(sizeof(*cmd->cmd.tms));
247 if (!cmd->cmd.tms)
248 return ERROR_FAIL;
249
250 /* copy the bits; our caller doesn't guarantee they'll persist */
251 cmd->cmd.tms->num_bits = num_bits;
252 cmd->cmd.tms->bits = buf_cpy(seq,
253 cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
254 if (!cmd->cmd.tms->bits)
255 return ERROR_FAIL;
256
257 jtag_queue_command(cmd);
258
259 return ERROR_OK;
260 }
261
262 int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
263 {
264 /* allocate memory for a new list member */
265 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
266
267 jtag_queue_command(cmd);
268
269 cmd->type = JTAG_PATHMOVE;
270
271 cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command));
272 cmd->cmd.pathmove->num_states = num_states;
273 cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
274
275 for (int i = 0; i < num_states; i++)
276 cmd->cmd.pathmove->path[i] = path[i];
277
278 return ERROR_OK;
279 }
280
281 int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
282 {
283 /* allocate memory for a new list member */
284 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
285
286 jtag_queue_command(cmd);
287
288 cmd->type = JTAG_RUNTEST;
289
290 cmd->cmd.runtest = cmd_queue_alloc(sizeof(struct runtest_command));
291 cmd->cmd.runtest->num_cycles = num_cycles;
292 cmd->cmd.runtest->end_state = state;
293
294 return ERROR_OK;
295 }
296
297 int interface_jtag_add_clocks(int num_cycles)
298 {
299 /* allocate memory for a new list member */
300 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
301
302 jtag_queue_command(cmd);
303
304 cmd->type = JTAG_STABLECLOCKS;
305
306 cmd->cmd.stableclocks = cmd_queue_alloc(sizeof(struct stableclocks_command));
307 cmd->cmd.stableclocks->num_cycles = num_cycles;
308
309 return ERROR_OK;
310 }
311
312 int interface_jtag_add_reset(int req_trst, int req_srst)
313 {
314 /* allocate memory for a new list member */
315 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
316
317 jtag_queue_command(cmd);
318
319 cmd->type = JTAG_RESET;
320
321 cmd->cmd.reset = cmd_queue_alloc(sizeof(struct reset_command));
322 cmd->cmd.reset->trst = req_trst;
323 cmd->cmd.reset->srst = req_srst;
324
325 return ERROR_OK;
326 }
327
328 int interface_jtag_add_sleep(uint32_t us)
329 {
330 /* allocate memory for a new list member */
331 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
332
333 jtag_queue_command(cmd);
334
335 cmd->type = JTAG_SLEEP;
336
337 cmd->cmd.sleep = cmd_queue_alloc(sizeof(struct sleep_command));
338 cmd->cmd.sleep->us = us;
339
340 return ERROR_OK;
341 }
342
343 /* add callback to end of queue */
344 void interface_jtag_add_callback4(jtag_callback_t callback,
345 jtag_callback_data_t data0, jtag_callback_data_t data1,
346 jtag_callback_data_t data2, jtag_callback_data_t data3)
347 {
348 struct jtag_callback_entry *entry = cmd_queue_alloc(sizeof(struct jtag_callback_entry));
349
350 entry->next = NULL;
351 entry->callback = callback;
352 entry->data0 = data0;
353 entry->data1 = data1;
354 entry->data2 = data2;
355 entry->data3 = data3;
356
357 if (!jtag_callback_queue_head) {
358 jtag_callback_queue_head = entry;
359 jtag_callback_queue_tail = entry;
360 } else {
361 jtag_callback_queue_tail->next = entry;
362 jtag_callback_queue_tail = entry;
363 }
364 }
365
366 int interface_jtag_execute_queue(void)
367 {
368 static int reentry;
369
370 assert(reentry == 0);
371 reentry++;
372
373 int retval = default_interface_jtag_execute_queue();
374 if (retval == ERROR_OK) {
375 struct jtag_callback_entry *entry;
376 for (entry = jtag_callback_queue_head; entry; entry = entry->next) {
377 retval = entry->callback(entry->data0, entry->data1, entry->data2, entry->data3);
378 if (retval != ERROR_OK)
379 break;
380 }
381 }
382
383 jtag_command_queue_reset();
384 jtag_callback_queue_reset();
385
386 reentry--;
387
388 return retval;
389 }
390
391 static int jtag_convert_to_callback4(jtag_callback_data_t data0,
392 jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
393 {
394 ((jtag_callback1_t)data1)(data0);
395 return ERROR_OK;
396 }
397
398 void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
399 {
400 jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
401 }
402
403 void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
404 {
405 interface_jtag_add_callback(f, data0);
406 }
407
408 void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
409 jtag_callback_data_t data1, jtag_callback_data_t data2,
410 jtag_callback_data_t data3)
411 {
412 interface_jtag_add_callback4(f, data0, data1, data2, data3);
413 }

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)