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