openocd: fix SPDX tag format for files .c
[fw/openocd] / 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 = 0;
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 = 1;
86
87                         field->num_bits = tap->ir_length;
88                         field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length);
89                         field->in_value = NULL; /* do not collect input for tap's in bypass */
90                 }
91
92                 /* update device information */
93                 buf_cpy(field->out_value, tap->cur_instr, tap->ir_length);
94
95                 field++;
96         }
97         /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
98         assert(field == out_fields + num_taps);
99
100         return ERROR_OK;
101 }
102
103 /**
104  * see jtag_add_dr_scan()
105  *
106  */
107 int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields,
108                 const struct scan_field *in_fields, tap_state_t state)
109 {
110         /* count devices in bypass */
111
112         size_t bypass_devices = 0;
113
114         for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
115                 if (tap->bypass)
116                         bypass_devices++;
117         }
118
119         struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
120         struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
121         struct scan_field *out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field));
122
123         jtag_queue_command(cmd);
124
125         cmd->type = JTAG_SCAN;
126         cmd->cmd.scan = scan;
127
128         scan->ir_scan = false;
129         scan->num_fields = in_num_fields + bypass_devices;
130         scan->fields = out_fields;
131         scan->end_state = state;
132
133         struct scan_field *field = out_fields;  /* keep track where we insert data */
134
135         /* loop over all enabled TAPs */
136
137         for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
138                 /* if TAP is not bypassed insert matching input fields */
139
140                 if (!tap->bypass) {
141                         assert(active == tap);
142 #ifndef NDEBUG
143                         /* remember initial position for assert() */
144                         struct scan_field *start_field = field;
145 #endif /* NDEBUG */
146
147                         for (int j = 0; j < in_num_fields; j++) {
148                                 jtag_scan_field_clone(field, in_fields + j);
149
150                                 field++;
151                         }
152
153                         assert(field > start_field);    /* must have at least one input field per not bypassed TAP */
154                 }
155
156                 /* if a TAP is bypassed, generated a dummy bit*/
157                 else {
158                         field->num_bits = 1;
159                         field->out_value = NULL;
160                         field->in_value = NULL;
161
162                         field++;
163                 }
164         }
165
166         assert(field == out_fields + scan->num_fields); /* no superfluous input fields permitted */
167
168         return ERROR_OK;
169 }
170
171 static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits,
172                 uint8_t *in_bits, tap_state_t state, bool ir_scan)
173 {
174         struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
175         struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
176         struct scan_field *out_fields = cmd_queue_alloc(sizeof(struct scan_field));
177
178         jtag_queue_command(cmd);
179
180         cmd->type = JTAG_SCAN;
181         cmd->cmd.scan = scan;
182
183         scan->ir_scan = ir_scan;
184         scan->num_fields = 1;
185         scan->fields = out_fields;
186         scan->end_state = state;
187
188         out_fields->num_bits = num_bits;
189         out_fields->out_value = buf_cpy(out_bits, cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
190         out_fields->in_value = in_bits;
191
192         return ERROR_OK;
193 }
194
195 int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
196 {
197         return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, false);
198 }
199
200 int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
201 {
202         return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, true);
203 }
204
205 int interface_jtag_add_tlr(void)
206 {
207         tap_state_t state = TAP_RESET;
208
209         /* allocate memory for a new list member */
210         struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
211
212         jtag_queue_command(cmd);
213
214         cmd->type = JTAG_TLR_RESET;
215
216         cmd->cmd.statemove = cmd_queue_alloc(sizeof(struct statemove_command));
217         cmd->cmd.statemove->end_state = state;
218
219         return ERROR_OK;
220 }
221
222 int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
223 {
224         struct jtag_command *cmd;
225
226         cmd = cmd_queue_alloc(sizeof(struct jtag_command));
227         if (!cmd)
228                 return ERROR_FAIL;
229
230         cmd->type = JTAG_TMS;
231         cmd->cmd.tms = cmd_queue_alloc(sizeof(*cmd->cmd.tms));
232         if (!cmd->cmd.tms)
233                 return ERROR_FAIL;
234
235         /* copy the bits; our caller doesn't guarantee they'll persist */
236         cmd->cmd.tms->num_bits = num_bits;
237         cmd->cmd.tms->bits = buf_cpy(seq,
238                         cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
239         if (!cmd->cmd.tms->bits)
240                 return ERROR_FAIL;
241
242         jtag_queue_command(cmd);
243
244         return ERROR_OK;
245 }
246
247 int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
248 {
249         /* allocate memory for a new list member */
250         struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
251
252         jtag_queue_command(cmd);
253
254         cmd->type = JTAG_PATHMOVE;
255
256         cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command));
257         cmd->cmd.pathmove->num_states = num_states;
258         cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
259
260         for (int i = 0; i < num_states; i++)
261                 cmd->cmd.pathmove->path[i] = path[i];
262
263         return ERROR_OK;
264 }
265
266 int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
267 {
268         /* allocate memory for a new list member */
269         struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
270
271         jtag_queue_command(cmd);
272
273         cmd->type = JTAG_RUNTEST;
274
275         cmd->cmd.runtest = cmd_queue_alloc(sizeof(struct runtest_command));
276         cmd->cmd.runtest->num_cycles = num_cycles;
277         cmd->cmd.runtest->end_state = state;
278
279         return ERROR_OK;
280 }
281
282 int interface_jtag_add_clocks(int num_cycles)
283 {
284         /* allocate memory for a new list member */
285         struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
286
287         jtag_queue_command(cmd);
288
289         cmd->type = JTAG_STABLECLOCKS;
290
291         cmd->cmd.stableclocks = cmd_queue_alloc(sizeof(struct stableclocks_command));
292         cmd->cmd.stableclocks->num_cycles = num_cycles;
293
294         return ERROR_OK;
295 }
296
297 int interface_jtag_add_reset(int req_trst, int req_srst)
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_RESET;
305
306         cmd->cmd.reset = cmd_queue_alloc(sizeof(struct reset_command));
307         cmd->cmd.reset->trst = req_trst;
308         cmd->cmd.reset->srst = req_srst;
309
310         return ERROR_OK;
311 }
312
313 int interface_jtag_add_sleep(uint32_t us)
314 {
315         /* allocate memory for a new list member */
316         struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
317
318         jtag_queue_command(cmd);
319
320         cmd->type = JTAG_SLEEP;
321
322         cmd->cmd.sleep = cmd_queue_alloc(sizeof(struct sleep_command));
323         cmd->cmd.sleep->us = us;
324
325         return ERROR_OK;
326 }
327
328 /* add callback to end of queue */
329 void interface_jtag_add_callback4(jtag_callback_t callback,
330                 jtag_callback_data_t data0, jtag_callback_data_t data1,
331                 jtag_callback_data_t data2, jtag_callback_data_t data3)
332 {
333         struct jtag_callback_entry *entry = cmd_queue_alloc(sizeof(struct jtag_callback_entry));
334
335         entry->next = NULL;
336         entry->callback = callback;
337         entry->data0 = data0;
338         entry->data1 = data1;
339         entry->data2 = data2;
340         entry->data3 = data3;
341
342         if (!jtag_callback_queue_head) {
343                 jtag_callback_queue_head = entry;
344                 jtag_callback_queue_tail = entry;
345         } else {
346                 jtag_callback_queue_tail->next = entry;
347                 jtag_callback_queue_tail = entry;
348         }
349 }
350
351 int interface_jtag_execute_queue(void)
352 {
353         static int reentry;
354
355         assert(reentry == 0);
356         reentry++;
357
358         int retval = default_interface_jtag_execute_queue();
359         if (retval == ERROR_OK) {
360                 struct jtag_callback_entry *entry;
361                 for (entry = jtag_callback_queue_head; entry; entry = entry->next) {
362                         retval = entry->callback(entry->data0, entry->data1, entry->data2, entry->data3);
363                         if (retval != ERROR_OK)
364                                 break;
365                 }
366         }
367
368         jtag_command_queue_reset();
369         jtag_callback_queue_reset();
370
371         reentry--;
372
373         return retval;
374 }
375
376 static int jtag_convert_to_callback4(jtag_callback_data_t data0,
377                 jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
378 {
379         ((jtag_callback1_t)data1)(data0);
380         return ERROR_OK;
381 }
382
383 void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
384 {
385         jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
386 }
387
388 void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
389 {
390         interface_jtag_add_callback(f, data0);
391 }
392
393 void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
394                 jtag_callback_data_t data1, jtag_callback_data_t data2,
395                 jtag_callback_data_t data3)
396 {
397         interface_jtag_add_callback4(f, data0, data1, data2, data3);
398 }