drivers/jtag: rewrite usb_blaster driver
[openocd.git] / src / jtag / drivers / usb_blaster / ublast_access_ftdi.c
1 /*
2 * Driver for USB-JTAG, Altera USB-Blaster and compatibles
3 *
4 * Inspired from original code from Kolja Waschk's USB-JTAG project
5 * (http://www.ixo.de/info/usb_jtag/), and from openocd project.
6 *
7 * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr
8 * Copyright (C) 2011 Ali Lown ali@lown.me.uk
9 * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca
10 * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 #include <jtag/interface.h>
28 #include <jtag/commands.h>
29
30 #include "ublast_access.h"
31 #include <ftdi.h>
32
33 static struct ftdi_context *ublast_getftdic(struct ublast_lowlevel *low)
34 {
35 return low->priv;
36 }
37
38 static int ublast_ftdi_read(struct ublast_lowlevel *low, uint8_t *buf,
39 unsigned size, uint32_t *bytes_read)
40 {
41 int retval;
42 int timeout = 100;
43 struct ftdi_context *ftdic = ublast_getftdic(low);
44
45 *bytes_read = 0;
46 while ((*bytes_read < size) && timeout--) {
47 retval = ftdi_read_data(ftdic, buf + *bytes_read,
48 size - *bytes_read);
49 if (retval < 0) {
50 *bytes_read = 0;
51 LOG_ERROR("ftdi_read_data: %s",
52 ftdi_get_error_string(ftdic));
53 return ERROR_JTAG_DEVICE_ERROR;
54 }
55 *bytes_read += retval;
56 }
57 return ERROR_OK;
58 }
59
60 static int ublast_ftdi_write(struct ublast_lowlevel *low, uint8_t *buf, int size,
61 uint32_t *bytes_written)
62 {
63 int retval;
64 struct ftdi_context *ftdic = ublast_getftdic(low);
65
66 retval = ftdi_write_data(ftdic, buf, size);
67 if (retval < 0) {
68 *bytes_written = 0;
69 LOG_ERROR("ftdi_write_data: %s",
70 ftdi_get_error_string(ftdic));
71 return ERROR_JTAG_DEVICE_ERROR;
72 }
73 *bytes_written = retval;
74 return ERROR_OK;
75 }
76
77 static int ublast_ftdi_init(struct ublast_lowlevel *low)
78 {
79 uint8_t latency_timer;
80 struct ftdi_context *ftdic = ublast_getftdic(low);
81
82 LOG_INFO("usb blaster interface using libftdi");
83 if (ftdi_init(ftdic) < 0)
84 return ERROR_JTAG_INIT_FAILED;
85
86 /* context, vendor id, product id */
87 if (ftdi_usb_open(ftdic, low->ublast_vid, low->ublast_pid) < 0) {
88 LOG_ERROR("unable to open ftdi device: %s", ftdic->error_str);
89 return ERROR_JTAG_INIT_FAILED;
90 }
91
92 if (ftdi_usb_reset(ftdic) < 0) {
93 LOG_ERROR("unable to reset ftdi device");
94 return ERROR_JTAG_INIT_FAILED;
95 }
96
97 if (ftdi_set_latency_timer(ftdic, 2) < 0) {
98 LOG_ERROR("unable to set latency timer");
99 return ERROR_JTAG_INIT_FAILED;
100 }
101
102 if (ftdi_get_latency_timer(ftdic, &latency_timer) < 0) {
103 LOG_ERROR("unable to get latency timer");
104 return ERROR_JTAG_INIT_FAILED;
105 }
106 LOG_DEBUG("current latency timer: %u", latency_timer);
107
108 ftdi_disable_bitbang(ftdic);
109 return ERROR_OK;
110 }
111
112 static int ublast_ftdi_quit(struct ublast_lowlevel *low)
113 {
114 struct ftdi_context *ftdic = ublast_getftdic(low);
115
116 ftdi_usb_close(ftdic);
117 ftdi_deinit(ftdic);
118 return ERROR_OK;
119 };
120
121 static struct ublast_lowlevel_priv {
122 struct ftdi_context ftdic;
123 } info;
124
125 static struct ublast_lowlevel low = {
126 .open = ublast_ftdi_init,
127 .close = ublast_ftdi_quit,
128 .read = ublast_ftdi_read,
129 .write = ublast_ftdi_write,
130 .priv = &info,
131 };
132
133 struct ublast_lowlevel *ublast_register_ftdi(void)
134 {
135 return &low;
136 }