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