45663647b356c35cac3511ea28899e297a693f54
[fw/openocd] / 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 };