]> git.sur5r.net Git - openocd/blob - src/jtag/aice/aice_interface.c
Remove FSF address from GPL notices
[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/interface.h>
24 #include <jtag/commands.h>
25 #include <transport/transport.h>
26 #include <target/target.h>
27 #include <jtag/aice/aice_transport.h>
28 #include <jtag/drivers/libusb_common.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 (ERROR_OK != aice_port->api->open(&param)) {
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         DEBUG_JTAG_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 (8 <= i)
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 /***************************************************************************/
243 /* Command handlers */
244 COMMAND_HANDLER(aice_handle_aice_info_command)
245 {
246         LOG_DEBUG("aice_handle_aice_info_command");
247
248         command_print(CMD_CTX, "Description: %s", param.device_desc);
249         command_print(CMD_CTX, "Serial number: %s", param.serial);
250         if (strncmp(aice_port->name, "aice_pipe", 9) == 0)
251                 command_print(CMD_CTX, "Adapter: %s", param.adapter_name);
252
253         return ERROR_OK;
254 }
255
256 COMMAND_HANDLER(aice_handle_aice_port_command)
257 {
258         LOG_DEBUG("aice_handle_aice_port_command");
259
260         if (CMD_ARGC != 1) {
261                 LOG_ERROR("Need exactly one argument to 'aice port'");
262                 return ERROR_COMMAND_SYNTAX_ERROR;
263         }
264
265         for (const struct aice_port *l = aice_port_get_list(); l->name; l++) {
266                 if (strcmp(l->name, CMD_ARGV[0]) == 0) {
267                         aice_port = l;
268                         return ERROR_OK;
269                 }
270         }
271
272         LOG_ERROR("No AICE port '%s' found", CMD_ARGV[0]);
273         return ERROR_FAIL;
274 }
275
276 COMMAND_HANDLER(aice_handle_aice_desc_command)
277 {
278         LOG_DEBUG("aice_handle_aice_desc_command");
279
280         if (CMD_ARGC == 1)
281                 param.device_desc = strdup(CMD_ARGV[0]);
282         else
283                 LOG_ERROR("expected exactly one argument to aice desc <description>");
284
285         return ERROR_OK;
286 }
287
288 COMMAND_HANDLER(aice_handle_aice_serial_command)
289 {
290         LOG_DEBUG("aice_handle_aice_serial_command");
291
292         if (CMD_ARGC == 1)
293                 param.serial = strdup(CMD_ARGV[0]);
294         else
295                 LOG_ERROR("expected exactly one argument to aice serial <serial-number>");
296
297         return ERROR_OK;
298 }
299
300 COMMAND_HANDLER(aice_handle_aice_vid_pid_command)
301 {
302         LOG_DEBUG("aice_handle_aice_vid_pid_command");
303
304         if (CMD_ARGC != 2) {
305                 LOG_WARNING("ignoring extra IDs in aice vid_pid (maximum is 1 pair)");
306                 return ERROR_COMMAND_SYNTAX_ERROR;
307         }
308
309         COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], param.vid);
310         COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], param.pid);
311
312         return ERROR_OK;
313 }
314
315 COMMAND_HANDLER(aice_handle_aice_adapter_command)
316 {
317         LOG_DEBUG("aice_handle_aice_adapter_command");
318
319         if (CMD_ARGC == 1)
320                 param.adapter_name = strdup(CMD_ARGV[0]);
321         else
322                 LOG_ERROR("expected exactly one argument to aice adapter <adapter-name>");
323
324         return ERROR_OK;
325 }
326
327 COMMAND_HANDLER(aice_handle_aice_retry_times_command)
328 {
329         LOG_DEBUG("aice_handle_aice_retry_times_command");
330
331         if (CMD_ARGC == 1)
332                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], retry_times);
333         else
334                 LOG_ERROR("expected exactly one argument to aice retry_times <num_of_retry>");
335
336         return ERROR_OK;
337 }
338
339 COMMAND_HANDLER(aice_handle_aice_count_to_check_dbger_command)
340 {
341         LOG_DEBUG("aice_handle_aice_count_to_check_dbger_command");
342
343         if (CMD_ARGC == 1)
344                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], count_to_check_dbger);
345         else
346                 LOG_ERROR("expected exactly one argument to aice count_to_check_dbger "
347                                 "<count_of_checking>");
348
349         return ERROR_OK;
350 }
351
352 COMMAND_HANDLER(aice_handle_aice_custom_srst_script_command)
353 {
354         LOG_DEBUG("aice_handle_aice_custom_srst_script_command");
355
356         if (CMD_ARGC > 0) {
357                 aice_port->api->set_custom_srst_script(CMD_ARGV[0]);
358                 return ERROR_OK;
359         }
360
361         return ERROR_FAIL;
362 }
363
364 COMMAND_HANDLER(aice_handle_aice_custom_trst_script_command)
365 {
366         LOG_DEBUG("aice_handle_aice_custom_trst_script_command");
367
368         if (CMD_ARGC > 0) {
369                 aice_port->api->set_custom_trst_script(CMD_ARGV[0]);
370                 return ERROR_OK;
371         }
372
373         return ERROR_FAIL;
374 }
375
376 COMMAND_HANDLER(aice_handle_aice_custom_restart_script_command)
377 {
378         LOG_DEBUG("aice_handle_aice_custom_restart_script_command");
379
380         if (CMD_ARGC > 0) {
381                 aice_port->api->set_custom_restart_script(CMD_ARGV[0]);
382                 return ERROR_OK;
383         }
384
385         return ERROR_FAIL;
386 }
387
388 COMMAND_HANDLER(aice_handle_aice_reset_command)
389 {
390         LOG_DEBUG("aice_handle_aice_reset_command");
391
392         return aice_port->api->reset();
393 }
394
395
396 static const struct command_registration aice_subcommand_handlers[] = {
397         {
398                 .name = "info",
399                 .handler = &aice_handle_aice_info_command,
400                 .mode = COMMAND_EXEC,
401                 .help = "show aice info",
402                 .usage = "aice info",
403         },
404         {
405                 .name = "port",
406                 .handler = &aice_handle_aice_port_command,
407                 .mode = COMMAND_CONFIG,
408                 .help = "set the port of the AICE",
409                 .usage = "aice port ['aice_pipe'|'aice_usb']",
410         },
411         {
412                 .name = "desc",
413                 .handler = &aice_handle_aice_desc_command,
414                 .mode = COMMAND_CONFIG,
415                 .help = "set the aice device description",
416                 .usage = "aice desc [desciption string]",
417         },
418         {
419                 .name = "serial",
420                 .handler = &aice_handle_aice_serial_command,
421                 .mode = COMMAND_CONFIG,
422                 .help = "set the serial number of the AICE device",
423                 .usage = "aice serial [serial string]",
424         },
425         {
426                 .name = "vid_pid",
427                 .handler = &aice_handle_aice_vid_pid_command,
428                 .mode = COMMAND_CONFIG,
429                 .help = "the vendor and product ID of the AICE device",
430                 .usage = "aice vid_pid (vid pid)*",
431         },
432         {
433                 .name = "adapter",
434                 .handler = &aice_handle_aice_adapter_command,
435                 .mode = COMMAND_CONFIG,
436                 .help = "set the file name of adapter",
437                 .usage = "aice adapter [adapter name]",
438         },
439         {
440                 .name = "retry_times",
441                 .handler = &aice_handle_aice_retry_times_command,
442                 .mode = COMMAND_CONFIG,
443                 .help = "set retry times as AICE timeout",
444                 .usage = "aice retry_times num_of_retry",
445         },
446         {
447                 .name = "count_to_check_dbger",
448                 .handler = &aice_handle_aice_count_to_check_dbger_command,
449                 .mode = COMMAND_CONFIG,
450                 .help = "set retry times as checking $DBGER status",
451                 .usage = "aice count_to_check_dbger count_of_checking",
452         },
453         {
454                 .name = "custom_srst_script",
455                 .handler = &aice_handle_aice_custom_srst_script_command,
456                 .mode = COMMAND_CONFIG,
457                 .usage = "custom_srst_script script_file_name",
458                 .help = "set custom srst script",
459         },
460         {
461                 .name = "custom_trst_script",
462                 .handler = &aice_handle_aice_custom_trst_script_command,
463                 .mode = COMMAND_CONFIG,
464                 .usage = "custom_trst_script script_file_name",
465                 .help = "set custom trst script",
466         },
467         {
468                 .name = "custom_restart_script",
469                 .handler = &aice_handle_aice_custom_restart_script_command,
470                 .mode = COMMAND_CONFIG,
471                 .usage = "custom_restart_script script_file_name",
472                 .help = "set custom restart script",
473         },
474         {
475                 .name = "reset",
476                 .handler = &aice_handle_aice_reset_command,
477                 .mode = COMMAND_EXEC,
478                 .usage = "aice reset",
479                 .help = "reset AICE",
480         },
481         COMMAND_REGISTRATION_DONE
482 };
483
484 static const struct command_registration aice_command_handlers[] = {
485         {
486                 .name = "aice",
487                 .mode = COMMAND_ANY,
488                 .help = "perform aice management",
489                 .usage = "aice [subcommand]",
490                 .chain = aice_subcommand_handlers,
491         },
492         COMMAND_REGISTRATION_DONE
493 };
494 /***************************************************************************/
495 /* End of Command handlers */
496
497 struct jtag_interface aice_interface = {
498         .name = "aice",
499         .commands = aice_command_handlers,
500         .transports = aice_transports,
501         .init = aice_init,
502         .quit = aice_quit,
503         .execute_queue = aice_execute_queue,
504         .speed = aice_speed,            /* set interface speed */
505         .speed_div = aice_speed_div,    /* return readable value */
506         .khz = aice_khz,                /* convert khz to interface speed value */
507 };