jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / presto.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2007 by Pavel Chromy *
5 * chromy@asix.cz *
6 ***************************************************************************/
7
8 /**
9 * @file
10 * Holds driver for PRESTO programmer from ASIX.
11 * http://tools.asix.net/prg_presto.htm
12 */
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16
17 #if IS_CYGWIN == 1
18 #include "windows.h"
19 #endif
20
21 #include <jtag/adapter.h>
22 #include <jtag/interface.h>
23 #include <helper/time_support.h>
24 #include "bitq.h"
25
26 /* PRESTO access library includes */
27 #include "libftdi_helper.h"
28
29 /* -------------------------------------------------------------------------- */
30
31 #define FT_DEVICE_NAME_LEN 64
32 #define FT_DEVICE_SERNUM_LEN 64
33
34 #define PRESTO_VID_PID 0x0403f1a0
35 #define PRESTO_VID (0x0403)
36 #define PRESTO_PID (0xf1a0)
37
38 #define BUFFER_SIZE (64*62)
39
40 struct presto {
41 struct ftdi_context ftdic;
42 int retval;
43
44 char serial[FT_DEVICE_SERNUM_LEN];
45
46 uint8_t buff_out[BUFFER_SIZE];
47 int buff_out_pos;
48
49 uint8_t buff_in[BUFFER_SIZE];
50 int buff_in_exp;/* expected in buffer length */
51 int buff_in_len;/* length of data received */
52 int buff_in_pos;
53
54 unsigned long total_out;
55 unsigned long total_in;
56
57 int jtag_tms; /* last tms state */
58 int jtag_tck; /* last tck state */
59 int jtag_rst; /* last trst state */
60
61 int jtag_tdi_data;
62 int jtag_tdi_count;
63
64 int jtag_speed;
65 };
66
67 static struct presto presto_state;
68 static struct presto *presto = &presto_state;
69
70 static uint8_t presto_init_seq[] = {
71 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
72 };
73
74 static int presto_write(uint8_t *buf, uint32_t size)
75 {
76 uint32_t ftbytes;
77 presto->retval = ftdi_write_data(&presto->ftdic, buf, size);
78 if (presto->retval < 0) {
79 LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto->ftdic));
80 return ERROR_JTAG_DEVICE_ERROR;
81 }
82 ftbytes = presto->retval;
83
84 if (ftbytes != size) {
85 LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)",
86 (unsigned)ftbytes, (unsigned)size);
87 return ERROR_JTAG_DEVICE_ERROR;
88 }
89
90 return ERROR_OK;
91 }
92
93 static int presto_read(uint8_t *buf, uint32_t size)
94 {
95 uint32_t ftbytes = 0;
96
97 struct timeval timeout, now;
98 gettimeofday(&timeout, NULL);
99 timeval_add_time(&timeout, 1, 0); /* one second timeout */
100
101 while (ftbytes < size) {
102 presto->retval = ftdi_read_data(&presto->ftdic, buf + ftbytes, size - ftbytes);
103 if (presto->retval < 0) {
104 LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto->ftdic));
105 return ERROR_JTAG_DEVICE_ERROR;
106 }
107 ftbytes += presto->retval;
108
109 gettimeofday(&now, NULL);
110 if (timeval_compare(&now, &timeout) > 0)
111 break;
112 }
113
114 if (ftbytes != size) {
115 /* this is just a warning, there might have been timeout when detecting PRESTO,
116 *which is not fatal */
117 LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)",
118 (unsigned)ftbytes, (unsigned)size);
119 return ERROR_JTAG_DEVICE_ERROR;
120 }
121
122 return ERROR_OK;
123 }
124
125 static int presto_open_libftdi(const char *req_serial)
126 {
127 uint8_t presto_data;
128
129 LOG_DEBUG("searching for PRESTO using libftdi");
130
131 /* initialize FTDI context structure */
132 if (ftdi_init(&presto->ftdic) < 0) {
133 LOG_ERROR("unable to init libftdi: %s", presto->ftdic.error_str);
134 return ERROR_JTAG_DEVICE_ERROR;
135 }
136
137 /* context, vendor id, product id */
138 if (ftdi_usb_open_desc(&presto->ftdic, PRESTO_VID, PRESTO_PID, NULL, req_serial) < 0) {
139 LOG_ERROR("unable to open PRESTO: %s", presto->ftdic.error_str);
140 return ERROR_JTAG_DEVICE_ERROR;
141 }
142
143 if (ftdi_usb_reset(&presto->ftdic) < 0) {
144 LOG_ERROR("unable to reset PRESTO device");
145 return ERROR_JTAG_DEVICE_ERROR;
146 }
147
148 if (ftdi_set_latency_timer(&presto->ftdic, 1) < 0) {
149 LOG_ERROR("unable to set latency timer");
150 return ERROR_JTAG_DEVICE_ERROR;
151 }
152
153 if (ftdi_tcioflush(&presto->ftdic) < 0) {
154 LOG_ERROR("unable to flush PRESTO buffers");
155 return ERROR_JTAG_DEVICE_ERROR;
156 }
157
158 presto_data = 0xD0;
159 if (presto_write(&presto_data, 1) != ERROR_OK) {
160 LOG_ERROR("error writing to PRESTO");
161 return ERROR_JTAG_DEVICE_ERROR;
162 }
163
164 if (presto_read(&presto_data, 1) != ERROR_OK) {
165 LOG_DEBUG("no response from PRESTO, retrying");
166
167 if (ftdi_tcioflush(&presto->ftdic) < 0)
168 return ERROR_JTAG_DEVICE_ERROR;
169
170 presto_data = 0xD0;
171 if (presto_write(&presto_data, 1) != ERROR_OK)
172 return ERROR_JTAG_DEVICE_ERROR;
173
174 if (presto_read(&presto_data, 1) != ERROR_OK) {
175 LOG_ERROR("no response from PRESTO, giving up");
176 return ERROR_JTAG_DEVICE_ERROR;
177 }
178 }
179
180 if (presto_write(presto_init_seq, sizeof(presto_init_seq)) != ERROR_OK) {
181 LOG_ERROR("error writing PRESTO init sequence");
182 return ERROR_JTAG_DEVICE_ERROR;
183 }
184
185 return ERROR_OK;
186 }
187
188 static int presto_open(const char *req_serial)
189 {
190 presto->buff_out_pos = 0;
191 presto->buff_in_pos = 0;
192 presto->buff_in_len = 0;
193 presto->buff_in_exp = 0;
194
195 presto->total_out = 0;
196 presto->total_in = 0;
197
198 presto->jtag_tms = 0;
199 presto->jtag_tck = 0;
200 presto->jtag_rst = 0;
201 presto->jtag_tdi_data = 0;
202 presto->jtag_tdi_count = 0;
203
204 presto->jtag_speed = 0;
205
206 return presto_open_libftdi(req_serial);
207 }
208
209 static int presto_close(void)
210 {
211
212 int result = ERROR_OK;
213
214 presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq));
215 if (presto->retval != sizeof(presto_init_seq))
216 result = ERROR_JTAG_DEVICE_ERROR;
217
218 presto->retval = ftdi_set_latency_timer(&presto->ftdic, 16);
219 if (presto->retval < 0)
220 result = ERROR_JTAG_DEVICE_ERROR;
221
222 presto->retval = ftdi_usb_close(&presto->ftdic);
223 if (presto->retval < 0)
224 result = ERROR_JTAG_DEVICE_ERROR;
225 else
226 ftdi_deinit(&presto->ftdic);
227
228 return result;
229 }
230
231 static int presto_flush(void)
232 {
233 if (presto->buff_out_pos == 0)
234 return ERROR_OK;
235
236 if (presto->retval < 0) {
237 LOG_DEBUG("error in previous communication, canceling I/O operation");
238 return ERROR_JTAG_DEVICE_ERROR;
239 }
240
241 if (presto_write(presto->buff_out, presto->buff_out_pos) != ERROR_OK) {
242 presto->buff_out_pos = 0;
243 return ERROR_JTAG_DEVICE_ERROR;
244 }
245
246 presto->total_out += presto->buff_out_pos;
247 presto->buff_out_pos = 0;
248
249 if (presto->buff_in_exp == 0)
250 return ERROR_OK;
251
252 presto->buff_in_pos = 0;
253 presto->buff_in_len = 0;
254
255 if (presto_read(presto->buff_in, presto->buff_in_exp) != ERROR_OK) {
256 presto->buff_in_exp = 0;
257 return ERROR_JTAG_DEVICE_ERROR;
258 }
259
260 presto->total_in += presto->buff_in_exp;
261 presto->buff_in_len = presto->buff_in_exp;
262 presto->buff_in_exp = 0;
263
264 return ERROR_OK;
265 }
266
267 static int presto_sendbyte(int data)
268 {
269 if (data == EOF)
270 return presto_flush();
271
272 if (presto->buff_out_pos < BUFFER_SIZE) {
273 presto->buff_out[presto->buff_out_pos++] = (uint8_t)data;
274 if (((data & 0xC0) == 0x40) || ((data & 0xD0) == 0xD0))
275 presto->buff_in_exp++;
276 } else
277 return ERROR_JTAG_DEVICE_ERROR;
278
279 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
280 *bytes only!) */
281 if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128)
282 return presto_flush();
283
284 return ERROR_OK;
285 }
286
287 #if 0
288 static int presto_getbyte(void)
289 {
290 if (presto->buff_in_pos < presto->buff_in_len)
291 return presto->buff_in[presto->buff_in_pos++];
292
293 if (presto->buff_in_exp == 0)
294 return -1;
295
296 if (presto_flush() != ERROR_OK)
297 return -1;
298
299 if (presto->buff_in_pos < presto->buff_in_len)
300 return presto->buff_in[presto->buff_in_pos++];
301
302 return -1;
303 }
304 #endif
305
306 /* -------------------------------------------------------------------------- */
307
308 static int presto_tdi_flush(void)
309 {
310 if (presto->jtag_tdi_count == 0)
311 return 0;
312
313 if (presto->jtag_tck == 0) {
314 LOG_ERROR("BUG: unexpected TAP condition, TCK low");
315 return -1;
316 }
317
318 presto->jtag_tdi_data |= (presto->jtag_tdi_count - 1) << 4;
319 presto_sendbyte(presto->jtag_tdi_data);
320 presto->jtag_tdi_count = 0;
321 presto->jtag_tdi_data = 0;
322
323 return 0;
324 }
325
326 static int presto_tck_idle(void)
327 {
328 if (presto->jtag_tck == 1) {
329 presto_sendbyte(0xCA);
330 presto->jtag_tck = 0;
331 }
332
333 return 0;
334 }
335
336 /* -------------------------------------------------------------------------- */
337
338 static int presto_bitq_out(int tms, int tdi, int tdo_req)
339 {
340 int i;
341 unsigned char cmd;
342
343 if (presto->jtag_tck == 0)
344 presto_sendbyte(0xA4); /* LED indicator - JTAG active */
345 else if (presto->jtag_speed == 0 && !tdo_req && tms == presto->jtag_tms) {
346 presto->jtag_tdi_data |= (tdi != 0) << presto->jtag_tdi_count;
347
348 if (++presto->jtag_tdi_count == 4)
349 presto_tdi_flush();
350
351 return 0;
352 }
353
354 presto_tdi_flush();
355
356 cmd = tdi ? 0xCB : 0xCA;
357 presto_sendbyte(cmd);
358
359 if (tms != presto->jtag_tms) {
360 presto_sendbyte((tms ? 0xEC : 0xE8) | (presto->jtag_rst ? 0x02 : 0));
361 presto->jtag_tms = tms;
362 }
363
364 /* delay with TCK low */
365 for (i = presto->jtag_speed; i > 1; i--)
366 presto_sendbyte(cmd);
367
368 cmd |= 0x04;
369 presto_sendbyte(cmd | (tdo_req ? 0x10 : 0));
370
371 /* delay with TCK high */
372 for (i = presto->jtag_speed; i > 1; i--)
373 presto_sendbyte(cmd);
374
375 presto->jtag_tck = 1;
376
377 return 0;
378 }
379
380 static int presto_bitq_flush(void)
381 {
382 presto_tdi_flush();
383 presto_tck_idle();
384
385 presto_sendbyte(0xA0); /* LED indicator - JTAG idle */
386
387 return presto_flush();
388 }
389
390 static int presto_bitq_in_rdy(void)
391 {
392 if (presto->buff_in_pos >= presto->buff_in_len)
393 return 0;
394 return presto->buff_in_len-presto->buff_in_pos;
395 }
396
397 static int presto_bitq_in(void)
398 {
399 if (presto->buff_in_pos >= presto->buff_in_len)
400 return -1;
401 if (presto->buff_in[presto->buff_in_pos++]&0x08)
402 return 1;
403 return 0;
404 }
405
406 static int presto_bitq_sleep(unsigned long us)
407 {
408 long waits;
409
410 presto_tdi_flush();
411 presto_tck_idle();
412
413 if (us > 100000) {
414 presto_bitq_flush();
415 jtag_sleep(us);
416 return 0;
417 }
418
419 waits = us / 170 + 2;
420 while (waits--)
421 presto_sendbyte(0x80);
422
423 return 0;
424 }
425
426 static int presto_bitq_reset(int trst, int srst)
427 {
428 presto_tdi_flush();
429 presto_tck_idle();
430
431 /* add a delay after possible TCK transition */
432 presto_sendbyte(0x80);
433 presto_sendbyte(0x80);
434
435 presto->jtag_rst = trst || srst;
436 presto_sendbyte((presto->jtag_rst ? 0xEA : 0xE8) | (presto->jtag_tms ? 0x04 : 0));
437
438 return 0;
439 }
440
441 static struct bitq_interface presto_bitq = {
442 .out = &presto_bitq_out,
443 .flush = &presto_bitq_flush,
444 .sleep = &presto_bitq_sleep,
445 .reset = &presto_bitq_reset,
446 .in_rdy = &presto_bitq_in_rdy,
447 .in = &presto_bitq_in,
448 };
449
450 /* -------------------------------------------------------------------------- */
451
452 static int presto_adapter_khz(int khz, int *jtag_speed)
453 {
454 if (khz < 0) {
455 *jtag_speed = 0;
456 return ERROR_COMMAND_SYNTAX_ERROR;
457 }
458
459 if (khz >= 3000)
460 *jtag_speed = 0;
461 else
462 *jtag_speed = (1000 + khz-1)/khz;
463
464 return 0;
465 }
466
467 static int presto_jtag_speed_div(int speed, int *khz)
468 {
469 if ((speed < 0) || (speed > 1000)) {
470 *khz = 0;
471 return ERROR_COMMAND_SYNTAX_ERROR;
472 }
473
474 if (speed == 0)
475 *khz = 3000;
476 else
477 *khz = 1000/speed;
478
479 return 0;
480 }
481
482 static int presto_jtag_speed(int speed)
483 {
484 int khz;
485
486 if (presto_jtag_speed_div(speed, &khz))
487 return ERROR_COMMAND_SYNTAX_ERROR;
488
489 presto->jtag_speed = speed;
490
491 if (khz%1000 == 0)
492 LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed, khz/1000);
493 else
494 LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed, khz);
495
496 return 0;
497 }
498
499 static int presto_jtag_init(void)
500 {
501 const char *presto_serial = adapter_get_required_serial();
502
503 if (presto_open(presto_serial) != ERROR_OK) {
504 presto_close();
505 if (presto_serial)
506 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial);
507 else
508 LOG_ERROR("Cannot open PRESTO");
509 return ERROR_JTAG_INIT_FAILED;
510 }
511 LOG_INFO("PRESTO open, serial number '%s'", presto->serial);
512
513 bitq_interface = &presto_bitq;
514 return ERROR_OK;
515 }
516
517 static int presto_jtag_quit(void)
518 {
519 bitq_cleanup();
520 presto_close();
521 LOG_INFO("PRESTO closed");
522 return ERROR_OK;
523 }
524
525 static struct jtag_interface presto_interface = {
526 .execute_queue = bitq_execute_queue,
527 };
528
529 struct adapter_driver presto_adapter_driver = {
530 .name = "presto",
531 .transports = jtag_only,
532
533 .init = presto_jtag_init,
534 .quit = presto_jtag_quit,
535 .speed = presto_jtag_speed,
536 .khz = presto_adapter_khz,
537 .speed_div = presto_jtag_speed_div,
538
539 .jtag_ops = &presto_interface,
540 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)