1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2007 by Pavel Chromy *
6 ***************************************************************************/
10 * Holds driver for PRESTO programmer from ASIX.
11 * http://tools.asix.net/prg_presto.htm
21 #include <jtag/adapter.h>
22 #include <jtag/interface.h>
23 #include <helper/time_support.h>
26 /* PRESTO access library includes */
27 #include "libftdi_helper.h"
29 /* -------------------------------------------------------------------------- */
31 #define FT_DEVICE_NAME_LEN 64
32 #define FT_DEVICE_SERNUM_LEN 64
34 #define PRESTO_VID_PID 0x0403f1a0
35 #define PRESTO_VID (0x0403)
36 #define PRESTO_PID (0xf1a0)
38 #define BUFFER_SIZE (64*62)
41 struct ftdi_context ftdic
;
44 char serial
[FT_DEVICE_SERNUM_LEN
];
46 uint8_t buff_out
[BUFFER_SIZE
];
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 */
54 unsigned long total_out
;
55 unsigned long total_in
;
57 int jtag_tms
; /* last tms state */
58 int jtag_tck
; /* last tck state */
59 int jtag_rst
; /* last trst state */
67 static struct presto presto_state
;
68 static struct presto
*presto
= &presto_state
;
70 static uint8_t presto_init_seq
[] = {
71 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
74 static int presto_write(uint8_t *buf
, uint32_t size
)
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
;
82 ftbytes
= presto
->retval
;
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
;
93 static int presto_read(uint8_t *buf
, uint32_t size
)
97 struct timeval timeout
, now
;
98 gettimeofday(&timeout
, NULL
);
99 timeval_add_time(&timeout
, 1, 0); /* one second timeout */
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
;
107 ftbytes
+= presto
->retval
;
109 gettimeofday(&now
, NULL
);
110 if (timeval_compare(&now
, &timeout
) > 0)
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
;
125 static int presto_open_libftdi(const char *req_serial
)
129 LOG_DEBUG("searching for PRESTO using libftdi");
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
;
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
;
143 if (ftdi_usb_reset(&presto
->ftdic
) < 0) {
144 LOG_ERROR("unable to reset PRESTO device");
145 return ERROR_JTAG_DEVICE_ERROR
;
148 if (ftdi_set_latency_timer(&presto
->ftdic
, 1) < 0) {
149 LOG_ERROR("unable to set latency timer");
150 return ERROR_JTAG_DEVICE_ERROR
;
153 if (ftdi_tcioflush(&presto
->ftdic
) < 0) {
154 LOG_ERROR("unable to flush PRESTO buffers");
155 return ERROR_JTAG_DEVICE_ERROR
;
159 if (presto_write(&presto_data
, 1) != ERROR_OK
) {
160 LOG_ERROR("error writing to PRESTO");
161 return ERROR_JTAG_DEVICE_ERROR
;
164 if (presto_read(&presto_data
, 1) != ERROR_OK
) {
165 LOG_DEBUG("no response from PRESTO, retrying");
167 if (ftdi_tcioflush(&presto
->ftdic
) < 0)
168 return ERROR_JTAG_DEVICE_ERROR
;
171 if (presto_write(&presto_data
, 1) != ERROR_OK
)
172 return ERROR_JTAG_DEVICE_ERROR
;
174 if (presto_read(&presto_data
, 1) != ERROR_OK
) {
175 LOG_ERROR("no response from PRESTO, giving up");
176 return ERROR_JTAG_DEVICE_ERROR
;
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
;
188 static int presto_open(const char *req_serial
)
190 presto
->buff_out_pos
= 0;
191 presto
->buff_in_pos
= 0;
192 presto
->buff_in_len
= 0;
193 presto
->buff_in_exp
= 0;
195 presto
->total_out
= 0;
196 presto
->total_in
= 0;
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;
204 presto
->jtag_speed
= 0;
206 return presto_open_libftdi(req_serial
);
209 static int presto_close(void)
212 int result
= ERROR_OK
;
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
;
218 presto
->retval
= ftdi_set_latency_timer(&presto
->ftdic
, 16);
219 if (presto
->retval
< 0)
220 result
= ERROR_JTAG_DEVICE_ERROR
;
222 presto
->retval
= ftdi_usb_close(&presto
->ftdic
);
223 if (presto
->retval
< 0)
224 result
= ERROR_JTAG_DEVICE_ERROR
;
226 ftdi_deinit(&presto
->ftdic
);
231 static int presto_flush(void)
233 if (presto
->buff_out_pos
== 0)
236 if (presto
->retval
< 0) {
237 LOG_DEBUG("error in previous communication, canceling I/O operation");
238 return ERROR_JTAG_DEVICE_ERROR
;
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
;
246 presto
->total_out
+= presto
->buff_out_pos
;
247 presto
->buff_out_pos
= 0;
249 if (presto
->buff_in_exp
== 0)
252 presto
->buff_in_pos
= 0;
253 presto
->buff_in_len
= 0;
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
;
260 presto
->total_in
+= presto
->buff_in_exp
;
261 presto
->buff_in_len
= presto
->buff_in_exp
;
262 presto
->buff_in_exp
= 0;
267 static int presto_sendbyte(int data
)
270 return presto_flush();
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
++;
277 return ERROR_JTAG_DEVICE_ERROR
;
279 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
281 if (presto
->buff_out_pos
>= BUFFER_SIZE
|| presto
->buff_in_exp
== 128)
282 return presto_flush();
288 static int presto_getbyte(void)
290 if (presto
->buff_in_pos
< presto
->buff_in_len
)
291 return presto
->buff_in
[presto
->buff_in_pos
++];
293 if (presto
->buff_in_exp
== 0)
296 if (presto_flush() != ERROR_OK
)
299 if (presto
->buff_in_pos
< presto
->buff_in_len
)
300 return presto
->buff_in
[presto
->buff_in_pos
++];
306 /* -------------------------------------------------------------------------- */
308 static int presto_tdi_flush(void)
310 if (presto
->jtag_tdi_count
== 0)
313 if (presto
->jtag_tck
== 0) {
314 LOG_ERROR("BUG: unexpected TAP condition, TCK low");
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;
326 static int presto_tck_idle(void)
328 if (presto
->jtag_tck
== 1) {
329 presto_sendbyte(0xCA);
330 presto
->jtag_tck
= 0;
336 /* -------------------------------------------------------------------------- */
338 static int presto_bitq_out(int tms
, int tdi
, int tdo_req
)
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
;
348 if (++presto
->jtag_tdi_count
== 4)
356 cmd
= tdi
? 0xCB : 0xCA;
357 presto_sendbyte(cmd
);
359 if (tms
!= presto
->jtag_tms
) {
360 presto_sendbyte((tms
? 0xEC : 0xE8) | (presto
->jtag_rst
? 0x02 : 0));
361 presto
->jtag_tms
= tms
;
364 /* delay with TCK low */
365 for (i
= presto
->jtag_speed
; i
> 1; i
--)
366 presto_sendbyte(cmd
);
369 presto_sendbyte(cmd
| (tdo_req
? 0x10 : 0));
371 /* delay with TCK high */
372 for (i
= presto
->jtag_speed
; i
> 1; i
--)
373 presto_sendbyte(cmd
);
375 presto
->jtag_tck
= 1;
380 static int presto_bitq_flush(void)
385 presto_sendbyte(0xA0); /* LED indicator - JTAG idle */
387 return presto_flush();
390 static int presto_bitq_in_rdy(void)
392 if (presto
->buff_in_pos
>= presto
->buff_in_len
)
394 return presto
->buff_in_len
-presto
->buff_in_pos
;
397 static int presto_bitq_in(void)
399 if (presto
->buff_in_pos
>= presto
->buff_in_len
)
401 if (presto
->buff_in
[presto
->buff_in_pos
++]&0x08)
406 static int presto_bitq_sleep(unsigned long us
)
419 waits
= us
/ 170 + 2;
421 presto_sendbyte(0x80);
426 static int presto_bitq_reset(int trst
, int srst
)
431 /* add a delay after possible TCK transition */
432 presto_sendbyte(0x80);
433 presto_sendbyte(0x80);
435 presto
->jtag_rst
= trst
|| srst
;
436 presto_sendbyte((presto
->jtag_rst
? 0xEA : 0xE8) | (presto
->jtag_tms
? 0x04 : 0));
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
,
450 /* -------------------------------------------------------------------------- */
452 static int presto_adapter_khz(int khz
, int *jtag_speed
)
456 return ERROR_COMMAND_SYNTAX_ERROR
;
462 *jtag_speed
= (1000 + khz
-1)/khz
;
467 static int presto_jtag_speed_div(int speed
, int *khz
)
469 if ((speed
< 0) || (speed
> 1000)) {
471 return ERROR_COMMAND_SYNTAX_ERROR
;
482 static int presto_jtag_speed(int speed
)
486 if (presto_jtag_speed_div(speed
, &khz
))
487 return ERROR_COMMAND_SYNTAX_ERROR
;
489 presto
->jtag_speed
= speed
;
492 LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed
, khz
/1000);
494 LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed
, khz
);
499 static int presto_jtag_init(void)
501 const char *presto_serial
= adapter_get_required_serial();
503 if (presto_open(presto_serial
) != ERROR_OK
) {
506 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial
);
508 LOG_ERROR("Cannot open PRESTO");
509 return ERROR_JTAG_INIT_FAILED
;
511 LOG_INFO("PRESTO open, serial number '%s'", presto
->serial
);
513 bitq_interface
= &presto_bitq
;
517 static int presto_jtag_quit(void)
521 LOG_INFO("PRESTO closed");
525 static struct jtag_interface presto_interface
= {
526 .execute_queue
= bitq_execute_queue
,
529 struct adapter_driver presto_adapter_driver
= {
531 .transports
= jtag_only
,
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
,
539 .jtag_ops
= &presto_interface
,
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)