667f2a7c0ba46e07c3f88dee719224fc26c2da73
[fw/openocd] / src / jtag / hla / hla_interface.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2011 by Mathias Kuester                                 *
5  *   Mathias Kuester <kesmtp@freenet.de>                                   *
6  *                                                                         *
7  *   Copyright (C) 2012 by Spencer Oliver                                  *
8  *   spen@spen-soft.co.uk                                                  *
9  ***************************************************************************/
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 /* project specific includes */
16 #include <jtag/interface.h>
17 #include <transport/transport.h>
18 #include <helper/time_support.h>
19
20 #include <jtag/hla/hla_tcl.h>
21 #include <jtag/hla/hla_layout.h>
22 #include <jtag/hla/hla_transport.h>
23 #include <jtag/hla/hla_interface.h>
24
25 #include <target/target.h>
26
27 static struct hl_interface_s hl_if = {
28         .param = {
29                 .device_desc = NULL,
30                 .vid = { 0 },
31                 .pid = { 0 },
32                 .transport = HL_TRANSPORT_UNKNOWN,
33                 .connect_under_reset = false,
34                 .initial_interface_speed = -1,
35                 .use_stlink_tcp = false,
36                 .stlink_tcp_port = 7184,
37         },
38         .layout = NULL,
39         .handle = NULL,
40 };
41
42 int hl_interface_open(enum hl_transports tr)
43 {
44         LOG_DEBUG("hl_interface_open");
45
46         enum reset_types jtag_reset_config = jtag_get_reset_config();
47
48         if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
49                 if (jtag_reset_config & RESET_SRST_NO_GATING)
50                         hl_if.param.connect_under_reset = true;
51                 else
52                         LOG_WARNING("\'srst_nogate\' reset_config option is required");
53         }
54
55         /* set transport mode */
56         hl_if.param.transport = tr;
57
58         int result = hl_if.layout->open(&hl_if);
59         if (result != ERROR_OK)
60                 return result;
61
62         return hl_interface_init_reset();
63 }
64
65 int hl_interface_init_target(struct target *t)
66 {
67         int res;
68
69         LOG_DEBUG("hl_interface_init_target");
70
71         /* this is the interface for the current target and we
72          * can setup the private pointer in the tap structure
73          * if the interface match the tap idcode
74          */
75         res = hl_if.layout->api->idcode(hl_if.handle, &t->tap->idcode);
76
77         if (res != ERROR_OK)
78                 return res;
79
80         unsigned ii, limit = t->tap->expected_ids_cnt;
81         int found = 0;
82
83         for (ii = 0; ii < limit; ii++) {
84                 uint32_t expected = t->tap->expected_ids[ii];
85
86                 /* treat "-expected-id 0" as a "don't-warn" wildcard */
87                 if (!expected || !t->tap->idcode ||
88                     (t->tap->idcode == expected)) {
89                         found = 1;
90                         break;
91                 }
92         }
93
94         if (found == 0) {
95                 LOG_WARNING("UNEXPECTED idcode: 0x%08" PRIx32, t->tap->idcode);
96                 for (ii = 0; ii < limit; ii++)
97                         LOG_ERROR("expected %u of %u: 0x%08" PRIx32, ii + 1, limit,
98                                 t->tap->expected_ids[ii]);
99
100                 return ERROR_FAIL;
101         }
102
103         t->tap->priv = &hl_if;
104         t->tap->hasidcode = 1;
105
106         return ERROR_OK;
107 }
108
109 static int hl_interface_init(void)
110 {
111         LOG_DEBUG("hl_interface_init");
112
113         /* here we can initialize the layout */
114         return hl_layout_init(&hl_if);
115 }
116
117 static int hl_interface_quit(void)
118 {
119         LOG_DEBUG("hl_interface_quit");
120
121         if (hl_if.layout->api->close)
122                 hl_if.layout->api->close(hl_if.handle);
123
124         jtag_command_queue_reset();
125
126         free((void *)hl_if.param.device_desc);
127
128         return ERROR_OK;
129 }
130
131 static int hl_interface_reset(int req_trst, int req_srst)
132 {
133         return hl_if.layout->api->assert_srst(hl_if.handle, req_srst ? 0 : 1);
134 }
135
136 int hl_interface_init_reset(void)
137 {
138         /* in case the adapter has not already handled asserting srst
139          * we will attempt it again */
140         if (hl_if.param.connect_under_reset) {
141                 adapter_assert_reset();
142         } else {
143                 adapter_deassert_reset();
144         }
145
146         return ERROR_OK;
147 }
148
149 static int hl_interface_khz(int khz, int *jtag_speed)
150 {
151         if (!hl_if.layout->api->speed)
152                 return ERROR_OK;
153
154         *jtag_speed = hl_if.layout->api->speed(hl_if.handle, khz, true);
155         return ERROR_OK;
156 }
157
158 static int hl_interface_speed_div(int speed, int *khz)
159 {
160         *khz = speed;
161         return ERROR_OK;
162 }
163
164 static int hl_interface_speed(int speed)
165 {
166         if (!hl_if.layout->api->speed)
167                 return ERROR_OK;
168
169         if (!hl_if.handle) {
170                 /* pass speed as initial param as interface not open yet */
171                 hl_if.param.initial_interface_speed = speed;
172                 return ERROR_OK;
173         }
174
175         hl_if.layout->api->speed(hl_if.handle, speed, false);
176
177         return ERROR_OK;
178 }
179
180 int hl_interface_override_target(const char **targetname)
181 {
182         if (hl_if.layout->api->override_target) {
183                 if (hl_if.layout->api->override_target(*targetname)) {
184                         *targetname = "hla_target";
185                         return ERROR_OK;
186                 } else
187                         return ERROR_FAIL;
188         }
189         return ERROR_FAIL;
190 }
191
192 static int hl_interface_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
193                 uint32_t port_size, unsigned int *trace_freq,
194                 unsigned int traceclkin_freq, uint16_t *prescaler)
195 {
196         if (hl_if.layout->api->config_trace)
197                 return hl_if.layout->api->config_trace(hl_if.handle, enabled,
198                         pin_protocol, port_size, trace_freq, traceclkin_freq, prescaler);
199         else if (enabled) {
200                 LOG_ERROR("The selected interface does not support tracing");
201                 return ERROR_FAIL;
202         }
203
204         return ERROR_OK;
205 }
206
207 static int hl_interface_poll_trace(uint8_t *buf, size_t *size)
208 {
209         if (hl_if.layout->api->poll_trace)
210                 return hl_if.layout->api->poll_trace(hl_if.handle, buf, size);
211
212         return ERROR_FAIL;
213 }
214
215 COMMAND_HANDLER(hl_interface_handle_device_desc_command)
216 {
217         LOG_DEBUG("hl_interface_handle_device_desc_command");
218
219         if (CMD_ARGC == 1) {
220                 hl_if.param.device_desc = strdup(CMD_ARGV[0]);
221         } else {
222                 LOG_ERROR("expected exactly one argument to hl_device_desc <description>");
223         }
224
225         return ERROR_OK;
226 }
227
228 COMMAND_HANDLER(hl_interface_handle_layout_command)
229 {
230         LOG_DEBUG("hl_interface_handle_layout_command");
231
232         if (CMD_ARGC != 1) {
233                 LOG_ERROR("Need exactly one argument to stlink_layout");
234                 return ERROR_COMMAND_SYNTAX_ERROR;
235         }
236
237         if (hl_if.layout) {
238                 LOG_ERROR("already specified hl_layout %s",
239                                 hl_if.layout->name);
240                 return (strcmp(hl_if.layout->name, CMD_ARGV[0]) != 0)
241                     ? ERROR_FAIL : ERROR_OK;
242         }
243
244         for (const struct hl_layout *l = hl_layout_get_list(); l->name;
245              l++) {
246                 if (strcmp(l->name, CMD_ARGV[0]) == 0) {
247                         hl_if.layout = l;
248                         return ERROR_OK;
249                 }
250         }
251
252         LOG_ERROR("No adapter layout '%s' found", CMD_ARGV[0]);
253         return ERROR_FAIL;
254 }
255
256 COMMAND_HANDLER(hl_interface_handle_vid_pid_command)
257 {
258         if (CMD_ARGC > HLA_MAX_USB_IDS * 2) {
259                 LOG_WARNING("ignoring extra IDs in hla_vid_pid "
260                         "(maximum is %d pairs)", HLA_MAX_USB_IDS);
261                 CMD_ARGC = HLA_MAX_USB_IDS * 2;
262         }
263         if (CMD_ARGC < 2 || (CMD_ARGC & 1)) {
264                 LOG_WARNING("incomplete hla_vid_pid configuration directive");
265                 return ERROR_COMMAND_SYNTAX_ERROR;
266         }
267
268         unsigned i;
269         for (i = 0; i < CMD_ARGC; i += 2) {
270                 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], hl_if.param.vid[i / 2]);
271                 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], hl_if.param.pid[i / 2]);
272         }
273
274         /*
275          * Explicitly terminate, in case there are multiple instances of
276          * hla_vid_pid.
277          */
278         hl_if.param.vid[i / 2] = hl_if.param.pid[i / 2] = 0;
279
280         return ERROR_OK;
281 }
282
283 COMMAND_HANDLER(hl_interface_handle_stlink_backend_command)
284 {
285         /* default values */
286         bool use_stlink_tcp = false;
287         uint16_t stlink_tcp_port = 7184;
288
289         if (CMD_ARGC == 0 || CMD_ARGC > 2)
290                 return ERROR_COMMAND_SYNTAX_ERROR;
291         else if (strcmp(CMD_ARGV[0], "usb") == 0) {
292                 if (CMD_ARGC > 1)
293                         return ERROR_COMMAND_SYNTAX_ERROR;
294                 /* else use_stlink_tcp = false (already the case ) */
295         } else if (strcmp(CMD_ARGV[0], "tcp") == 0) {
296                 use_stlink_tcp = true;
297                 if (CMD_ARGC == 2)
298                         COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], stlink_tcp_port);
299         } else
300                 return ERROR_COMMAND_SYNTAX_ERROR;
301
302         hl_if.param.use_stlink_tcp = use_stlink_tcp;
303         hl_if.param.stlink_tcp_port = stlink_tcp_port;
304
305         return ERROR_OK;
306 }
307
308 COMMAND_HANDLER(interface_handle_hla_command)
309 {
310         if (CMD_ARGC != 1)
311                 return ERROR_COMMAND_SYNTAX_ERROR;
312
313         if (!hl_if.layout->api->custom_command) {
314                 LOG_ERROR("The selected adapter doesn't support custom commands");
315                 return ERROR_FAIL;
316         }
317
318         hl_if.layout->api->custom_command(hl_if.handle, CMD_ARGV[0]);
319
320         return ERROR_OK;
321 }
322
323 static const struct command_registration hl_interface_command_handlers[] = {
324         {
325          .name = "hla_device_desc",
326          .handler = &hl_interface_handle_device_desc_command,
327          .mode = COMMAND_CONFIG,
328          .help = "set the device description of the adapter",
329          .usage = "description_string",
330          },
331         {
332          .name = "hla_layout",
333          .handler = &hl_interface_handle_layout_command,
334          .mode = COMMAND_CONFIG,
335          .help = "set the layout of the adapter",
336          .usage = "layout_name",
337          },
338         {
339          .name = "hla_vid_pid",
340          .handler = &hl_interface_handle_vid_pid_command,
341          .mode = COMMAND_CONFIG,
342          .help = "the vendor and product ID of the adapter",
343          .usage = "(vid pid)*",
344          },
345         {
346          .name = "hla_stlink_backend",
347          .handler = &hl_interface_handle_stlink_backend_command,
348          .mode = COMMAND_CONFIG,
349          .help = "select which ST-Link backend to use",
350          .usage = "usb | tcp [port]",
351         },
352          {
353          .name = "hla_command",
354          .handler = &interface_handle_hla_command,
355          .mode = COMMAND_EXEC,
356          .help = "execute a custom adapter-specific command",
357          .usage = "<command>",
358          },
359         COMMAND_REGISTRATION_DONE
360 };
361
362 struct adapter_driver hl_adapter_driver = {
363         .name = "hla",
364         .transports = hl_transports,
365         .commands = hl_interface_command_handlers,
366
367         .init = hl_interface_init,
368         .quit = hl_interface_quit,
369         .reset = hl_interface_reset,
370         .speed = &hl_interface_speed,
371         .khz = &hl_interface_khz,
372         .speed_div = &hl_interface_speed_div,
373         .config_trace = &hl_interface_config_trace,
374         .poll_trace = &hl_interface_poll_trace,
375
376         /* no ops for HLA, targets hla_target and stm8 intercept them all */
377 };