Remove FSF address from GPL notices
[fw/openocd] / 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  *   You should have received a copy of the GNU General Public License
23  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 #include <jtag/interface.h>
31 #include <jtag/commands.h>
32
33 #include "ublast_access.h"
34 #include <ftdi.h>
35
36 static struct ftdi_context *ublast_getftdic(struct ublast_lowlevel *low)
37 {
38         return low->priv;
39 }
40
41 static int ublast_ftdi_read(struct ublast_lowlevel *low, uint8_t *buf,
42                             unsigned size, uint32_t *bytes_read)
43 {
44         int retval;
45         int timeout = 100;
46         struct ftdi_context *ftdic = ublast_getftdic(low);
47
48         *bytes_read = 0;
49         while ((*bytes_read < size) && timeout--) {
50                 retval = ftdi_read_data(ftdic, buf + *bytes_read,
51                                 size - *bytes_read);
52                 if (retval < 0) {
53                         *bytes_read = 0;
54                         LOG_ERROR("ftdi_read_data: %s",
55                                         ftdi_get_error_string(ftdic));
56                         return ERROR_JTAG_DEVICE_ERROR;
57                 }
58                 *bytes_read += retval;
59         }
60         return ERROR_OK;
61 }
62
63 static int ublast_ftdi_write(struct ublast_lowlevel *low, uint8_t *buf, int size,
64                              uint32_t *bytes_written)
65 {
66         int retval;
67         struct ftdi_context *ftdic = ublast_getftdic(low);
68
69         retval = ftdi_write_data(ftdic, buf, size);
70         if (retval < 0) {
71                 *bytes_written = 0;
72                 LOG_ERROR("ftdi_write_data: %s",
73                           ftdi_get_error_string(ftdic));
74                 return ERROR_JTAG_DEVICE_ERROR;
75         }
76         *bytes_written = retval;
77         return ERROR_OK;
78 }
79
80 static int ublast_ftdi_init(struct ublast_lowlevel *low)
81 {
82         uint8_t latency_timer;
83         struct ftdi_context *ftdic = ublast_getftdic(low);
84
85         LOG_INFO("usb blaster interface using libftdi");
86         if (ftdi_init(ftdic) < 0)
87                 return ERROR_JTAG_INIT_FAILED;
88
89         /* context, vendor id, product id */
90         if (ftdi_usb_open(ftdic, low->ublast_vid, low->ublast_pid) < 0) {
91                 LOG_ERROR("unable to open ftdi device: %s", ftdic->error_str);
92                 return ERROR_JTAG_INIT_FAILED;
93         }
94
95         if (ftdi_usb_reset(ftdic) < 0) {
96                 LOG_ERROR("unable to reset ftdi device");
97                 return ERROR_JTAG_INIT_FAILED;
98         }
99
100         if (ftdi_set_latency_timer(ftdic, 2) < 0) {
101                 LOG_ERROR("unable to set latency timer");
102                 return ERROR_JTAG_INIT_FAILED;
103         }
104
105         if (ftdi_get_latency_timer(ftdic, &latency_timer) < 0)
106                 LOG_ERROR("unable to get latency timer");
107         else
108                 LOG_DEBUG("current latency timer: %u", latency_timer);
109
110         ftdi_disable_bitbang(ftdic);
111         return ERROR_OK;
112 }
113
114 static int ublast_ftdi_quit(struct ublast_lowlevel *low)
115 {
116         struct ftdi_context *ftdic = ublast_getftdic(low);
117
118         ftdi_usb_close(ftdic);
119         ftdi_deinit(ftdic);
120         return ERROR_OK;
121 };
122
123 static struct ublast_lowlevel_priv {
124         struct ftdi_context ftdic;
125 } info;
126
127 static struct ublast_lowlevel low = {
128         .open = ublast_ftdi_init,
129         .close = ublast_ftdi_quit,
130         .read = ublast_ftdi_read,
131         .write = ublast_ftdi_write,
132         .priv = &info,
133 };
134
135 struct ublast_lowlevel *ublast_register_ftdi(void)
136 {
137         return &low;
138 }