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