aede83a99d11f86d3486f17f8c4d327d8d3bcde3
[fw/openocd] / src / jtag / aice / aice_interface.c
1 /***************************************************************************
2  *   Copyright (C) 2013 by Andes Technology                                *
3  *   Hsiangkai Wang <hkwang@andestech.com>                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
19  ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <jtag/interface.h>
26 #include <jtag/commands.h>
27 #include <transport/transport.h>
28 #include <target/target.h>
29 #include <jtag/aice/aice_transport.h>
30 #include <jtag/drivers/libusb_common.h>
31 #include "aice_usb.h"
32
33 #define AICE_KHZ_TO_SPEED_MAP_SIZE      16
34 static int aice_khz_to_speed_map[AICE_KHZ_TO_SPEED_MAP_SIZE] = {
35         30000,
36         15000,
37         7500,
38         3750,
39         1875,
40         937,
41         468,
42         234,
43         48000,
44         24000,
45         12000,
46         6000,
47         3000,
48         1500,
49         750,
50         375,
51 };
52
53 static const struct aice_port *aice_port;
54 static struct aice_port_param_s param;
55 static uint32_t retry_times;
56 static uint32_t count_to_check_dbger;
57
58 /***************************************************************************/
59 /* External interface implementation */
60 static uint32_t aice_target_id_codes[AICE_MAX_NUM_CORE];
61 static uint8_t aice_num_of_target_id_codes;
62
63 /***************************************************************************/
64 /* AICE operations */
65 int aice_init_targets(void)
66 {
67         int res;
68         struct target *target;
69         struct aice_port_s *aice;
70
71         LOG_DEBUG("aice_init_targets");
72
73         if (aice_num_of_target_id_codes == 0) {
74                 res = aice_port->api->idcode(aice_target_id_codes, &aice_num_of_target_id_codes);
75                 if (res != ERROR_OK) {
76                         LOG_ERROR("<-- TARGET ERROR! Failed to identify AndesCore "
77                                         "JTAG Manufacture ID in the JTAG scan chain. "
78                                         "Failed to access EDM registers. -->");
79                         return res;
80                 }
81         }
82
83         for (target = all_targets; target; target = target->next) {
84                 target->tap->idcode = aice_target_id_codes[target->tap->abs_chain_position];
85
86                 unsigned ii, limit = target->tap->expected_ids_cnt;
87                 int found = 0;
88
89                 for (ii = 0; ii < limit; ii++) {
90                         uint32_t expected = target->tap->expected_ids[ii];
91
92                         /* treat "-expected-id 0" as a "don't-warn" wildcard */
93                         if (!expected || (target->tap->idcode == expected)) {
94                                 found = 1;
95                                 break;
96                         }
97                 }
98
99                 if (found == 0) {
100                         LOG_ERROR
101                                 ("aice_init_targets: target not found: idcode: %x ",
102                                  target->tap->idcode);
103                         return ERROR_FAIL;
104                 }
105
106                 aice = calloc(1, sizeof(struct aice_port_s));
107                 aice->port = aice_port;
108                 aice->coreid = target->tap->abs_chain_position;
109
110                 target->tap->priv = aice;
111                 target->tap->hasidcode = 1;
112         }
113
114         return ERROR_OK;
115 }
116
117 /***************************************************************************/
118 /* End of External interface implementation */
119
120 /* initial aice
121  * 1. open usb
122  * 2. get/show version number
123  * 3. reset
124  */
125 static int aice_init(void)
126 {
127         if (ERROR_OK != aice_port->api->open(&param)) {
128                 LOG_ERROR("Cannot find AICE Interface! Please check "
129                                 "connection and permissions.");
130                 return ERROR_JTAG_INIT_FAILED;
131         }
132
133         aice_port->api->set_retry_times(retry_times);
134         aice_port->api->set_count_to_check_dbger(count_to_check_dbger);
135
136         LOG_INFO("AICE JTAG Interface ready");
137
138         return ERROR_OK;
139 }
140
141 /* cleanup aice resource
142  * close usb
143  */
144 static int aice_quit(void)
145 {
146         aice_port->api->close();
147         return ERROR_OK;
148 }
149
150 static int aice_execute_reset(struct jtag_command *cmd)
151 {
152         static int last_trst;
153         int retval = ERROR_OK;
154
155         DEBUG_JTAG_IO("reset trst: %i", cmd->cmd.reset->trst);
156
157         if (cmd->cmd.reset->trst != last_trst) {
158                 if (cmd->cmd.reset->trst)
159                         retval = aice_port->api->reset();
160
161                 last_trst = cmd->cmd.reset->trst;
162         }
163
164         return retval;
165 }
166
167 static int aice_execute_command(struct jtag_command *cmd)
168 {
169         int retval;
170
171         switch (cmd->type) {
172                 case JTAG_RESET:
173                         retval = aice_execute_reset(cmd);
174                         break;
175                 default:
176                         retval = ERROR_OK;
177                         break;
178         }
179         return retval;
180 }
181
182 /* aice has no need to implement jtag execution model
183 */
184 static int aice_execute_queue(void)
185 {
186         struct jtag_command *cmd = jtag_command_queue;  /* currently processed command */
187         int retval;
188
189         retval = ERROR_OK;
190
191         while (cmd) {
192                 if (aice_execute_command(cmd) != ERROR_OK)
193                         retval = ERROR_JTAG_QUEUE_FAILED;
194
195                 cmd = cmd->next;
196         }
197
198         return retval;
199 }
200
201 /* set jtag frequency(base frequency/frequency divider) to your jtag adapter */
202 static int aice_speed(int speed)
203 {
204         return aice_port->api->set_jtag_clock(speed);
205 }
206
207 /* convert jtag adapter frequency(base frequency/frequency divider) to
208  * human readable KHz value */
209 static int aice_speed_div(int speed, int *khz)
210 {
211         *khz = aice_khz_to_speed_map[speed];
212
213         return ERROR_OK;
214 }
215
216 /* convert human readable KHz value to jtag adapter frequency
217  * (base frequency/frequency divider) */
218 static int aice_khz(int khz, int *jtag_speed)
219 {
220         int i;
221         for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++) {
222                 if (khz == aice_khz_to_speed_map[i]) {
223                         if (8 <= i)
224                                 *jtag_speed = i | AICE_TCK_CONTROL_TCK3048;
225                         else
226                                 *jtag_speed = i;
227                         break;
228                 }
229         }
230
231         if (i == AICE_KHZ_TO_SPEED_MAP_SIZE) {
232                 LOG_INFO("No support the jtag clock: %d", khz);
233                 LOG_INFO("Supported jtag clocks are:");
234
235                 for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++)
236                         LOG_INFO("* %d", aice_khz_to_speed_map[i]);
237
238                 return ERROR_FAIL;
239         }
240
241         return ERROR_OK;
242 }
243
244 /***************************************************************************/
245 /* Command handlers */
246 COMMAND_HANDLER(aice_handle_aice_info_command)
247 {
248         LOG_DEBUG("aice_handle_aice_info_command");
249
250         command_print(CMD_CTX, "Description: %s", param.device_desc);
251         command_print(CMD_CTX, "Serial number: %s", param.serial);
252         if (strncmp(aice_port->name, "aice_pipe", 9) == 0)
253                 command_print(CMD_CTX, "Adapter: %s", param.adapter_name);
254
255         return ERROR_OK;
256 }
257
258 COMMAND_HANDLER(aice_handle_aice_port_command)
259 {
260         LOG_DEBUG("aice_handle_aice_port_command");
261
262         if (CMD_ARGC != 1) {
263                 LOG_ERROR("Need exactly one argument to 'aice port'");
264                 return ERROR_COMMAND_SYNTAX_ERROR;
265         }
266
267         for (const struct aice_port *l = aice_port_get_list(); l->name; l++) {
268                 if (strcmp(l->name, CMD_ARGV[0]) == 0) {
269                         aice_port = l;
270                         return ERROR_OK;
271                 }
272         }
273
274         LOG_ERROR("No AICE port '%s' found", CMD_ARGV[0]);
275         return ERROR_FAIL;
276 }
277
278 COMMAND_HANDLER(aice_handle_aice_desc_command)
279 {
280         LOG_DEBUG("aice_handle_aice_desc_command");
281
282         if (CMD_ARGC == 1)
283                 param.device_desc = strdup(CMD_ARGV[0]);
284         else
285                 LOG_ERROR("expected exactly one argument to aice desc <description>");
286
287         return ERROR_OK;
288 }
289
290 COMMAND_HANDLER(aice_handle_aice_serial_command)
291 {
292         LOG_DEBUG("aice_handle_aice_serial_command");
293
294         if (CMD_ARGC == 1)
295                 param.serial = strdup(CMD_ARGV[0]);
296         else
297                 LOG_ERROR("expected exactly one argument to aice serial <serial-number>");
298
299         return ERROR_OK;
300 }
301
302 COMMAND_HANDLER(aice_handle_aice_vid_pid_command)
303 {
304         LOG_DEBUG("aice_handle_aice_vid_pid_command");
305
306         if (CMD_ARGC != 2) {
307                 LOG_WARNING("ignoring extra IDs in aice vid_pid (maximum is 1 pair)");
308                 return ERROR_COMMAND_SYNTAX_ERROR;
309         }
310
311         COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], param.vid);
312         COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], param.pid);
313
314         return ERROR_OK;
315 }
316
317 COMMAND_HANDLER(aice_handle_aice_adapter_command)
318 {
319         LOG_DEBUG("aice_handle_aice_adapter_command");
320
321         if (CMD_ARGC == 1)
322                 param.adapter_name = strdup(CMD_ARGV[0]);
323         else
324                 LOG_ERROR("expected exactly one argument to aice adapter <adapter-name>");
325
326         return ERROR_OK;
327 }
328
329 COMMAND_HANDLER(aice_handle_aice_retry_times_command)
330 {
331         LOG_DEBUG("aice_handle_aice_retry_times_command");
332
333         if (CMD_ARGC == 1)
334                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], retry_times);
335         else
336                 LOG_ERROR("expected exactly one argument to aice retry_times <num_of_retry>");
337
338         return ERROR_OK;
339 }
340
341 COMMAND_HANDLER(aice_handle_aice_count_to_check_dbger_command)
342 {
343         LOG_DEBUG("aice_handle_aice_count_to_check_dbger_command");
344
345         if (CMD_ARGC == 1)
346                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], count_to_check_dbger);
347         else
348                 LOG_ERROR("expected exactly one argument to aice count_to_check_dbger "
349                                 "<count_of_checking>");
350
351         return ERROR_OK;
352 }
353
354 COMMAND_HANDLER(aice_handle_aice_custom_srst_script_command)
355 {
356         LOG_DEBUG("aice_handle_aice_custom_srst_script_command");
357
358         if (CMD_ARGC > 0) {
359                 aice_port->api->set_custom_srst_script(CMD_ARGV[0]);
360                 return ERROR_OK;
361         }
362
363         return ERROR_FAIL;
364 }
365
366 COMMAND_HANDLER(aice_handle_aice_custom_trst_script_command)
367 {
368         LOG_DEBUG("aice_handle_aice_custom_trst_script_command");
369
370         if (CMD_ARGC > 0) {
371                 aice_port->api->set_custom_trst_script(CMD_ARGV[0]);
372                 return ERROR_OK;
373         }
374
375         return ERROR_FAIL;
376 }
377
378 COMMAND_HANDLER(aice_handle_aice_custom_restart_script_command)
379 {
380         LOG_DEBUG("aice_handle_aice_custom_restart_script_command");
381
382         if (CMD_ARGC > 0) {
383                 aice_port->api->set_custom_restart_script(CMD_ARGV[0]);
384                 return ERROR_OK;
385         }
386
387         return ERROR_FAIL;
388 }
389
390 COMMAND_HANDLER(aice_handle_aice_reset_command)
391 {
392         LOG_DEBUG("aice_handle_aice_reset_command");
393
394         return aice_port->api->reset();
395 }
396
397
398 static const struct command_registration aice_subcommand_handlers[] = {
399         {
400                 .name = "info",
401                 .handler = &aice_handle_aice_info_command,
402                 .mode = COMMAND_EXEC,
403                 .help = "show aice info",
404                 .usage = "aice info",
405         },
406         {
407                 .name = "port",
408                 .handler = &aice_handle_aice_port_command,
409                 .mode = COMMAND_CONFIG,
410                 .help = "set the port of the AICE",
411                 .usage = "aice port ['aice_pipe'|'aice_usb']",
412         },
413         {
414                 .name = "desc",
415                 .handler = &aice_handle_aice_desc_command,
416                 .mode = COMMAND_CONFIG,
417                 .help = "set the aice device description",
418                 .usage = "aice desc [desciption string]",
419         },
420         {
421                 .name = "serial",
422                 .handler = &aice_handle_aice_serial_command,
423                 .mode = COMMAND_CONFIG,
424                 .help = "set the serial number of the AICE device",
425                 .usage = "aice serial [serial string]",
426         },
427         {
428                 .name = "vid_pid",
429                 .handler = &aice_handle_aice_vid_pid_command,
430                 .mode = COMMAND_CONFIG,
431                 .help = "the vendor and product ID of the AICE device",
432                 .usage = "aice vid_pid (vid pid)*",
433         },
434         {
435                 .name = "adapter",
436                 .handler = &aice_handle_aice_adapter_command,
437                 .mode = COMMAND_CONFIG,
438                 .help = "set the file name of adapter",
439                 .usage = "aice adapter [adapter name]",
440         },
441         {
442                 .name = "retry_times",
443                 .handler = &aice_handle_aice_retry_times_command,
444                 .mode = COMMAND_CONFIG,
445                 .help = "set retry times as AICE timeout",
446                 .usage = "aice retry_times num_of_retry",
447         },
448         {
449                 .name = "count_to_check_dbger",
450                 .handler = &aice_handle_aice_count_to_check_dbger_command,
451                 .mode = COMMAND_CONFIG,
452                 .help = "set retry times as checking $DBGER status",
453                 .usage = "aice count_to_check_dbger count_of_checking",
454         },
455         {
456                 .name = "custom_srst_script",
457                 .handler = &aice_handle_aice_custom_srst_script_command,
458                 .mode = COMMAND_CONFIG,
459                 .usage = "custom_srst_script script_file_name",
460                 .help = "set custom srst script",
461         },
462         {
463                 .name = "custom_trst_script",
464                 .handler = &aice_handle_aice_custom_trst_script_command,
465                 .mode = COMMAND_CONFIG,
466                 .usage = "custom_trst_script script_file_name",
467                 .help = "set custom trst script",
468         },
469         {
470                 .name = "custom_restart_script",
471                 .handler = &aice_handle_aice_custom_restart_script_command,
472                 .mode = COMMAND_CONFIG,
473                 .usage = "custom_restart_script script_file_name",
474                 .help = "set custom restart script",
475         },
476         {
477                 .name = "reset",
478                 .handler = &aice_handle_aice_reset_command,
479                 .mode = COMMAND_EXEC,
480                 .usage = "aice reset",
481                 .help = "reset AICE",
482         },
483         COMMAND_REGISTRATION_DONE
484 };
485
486 static const struct command_registration aice_command_handlers[] = {
487         {
488                 .name = "aice",
489                 .mode = COMMAND_ANY,
490                 .help = "perform aice management",
491                 .usage = "aice [subcommand]",
492                 .chain = aice_subcommand_handlers,
493         },
494         COMMAND_REGISTRATION_DONE
495 };
496 /***************************************************************************/
497 /* End of Command handlers */
498
499 struct jtag_interface aice_interface = {
500         .name = "aice",
501         .commands = aice_command_handlers,
502         .transports = aice_transports,
503         .init = aice_init,
504         .quit = aice_quit,
505         .execute_queue = aice_execute_queue,
506         .speed = aice_speed,            /* set interface speed */
507         .speed_div = aice_speed_div,    /* return readable value */
508         .khz = aice_khz,                /* convert khz to interface speed value */
509 };