openocd: src/jtag: replace the GPL-2.0-or-later license tag
[openocd.git] / src / jtag / drivers / usb_blaster / ublast2_access_libusb.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /*
4 * Driver for USB-JTAG, Altera USB-Blaster II and compatibles
5 *
6 * Copyright (C) 2013 Franck Jullien franck.jullien@gmail.com
7 *
8 */
9
10 #ifdef HAVE_CONFIG_H
11 #include <config.h>
12 #endif
13 #include <jtag/interface.h>
14 #include <jtag/commands.h>
15 #include "helper/system.h"
16 #include <libusb_helper.h>
17 #include <target/image.h>
18
19 #include "ublast_access.h"
20
21 #define USBBLASTER_CTRL_READ_REV 0x94
22 #define USBBLASTER_CTRL_LOAD_FIRM 0xA0
23 #define USBBLASTER_EPOUT 4
24 #define USBBLASTER_EPIN 8
25
26 #define EZUSB_CPUCS 0xe600
27 #define CPU_RESET 1
28
29 /** Maximum size of a single firmware section. Entire EZ-USB code space = 16kB */
30 #define SECTION_BUFFERSIZE 16384
31
32 static int ublast2_libusb_read(struct ublast_lowlevel *low, uint8_t *buf,
33 unsigned size, uint32_t *bytes_read)
34 {
35 int ret, tmp = 0;
36
37 ret = jtag_libusb_bulk_read(low->libusb_dev,
38 USBBLASTER_EPIN |
39 LIBUSB_ENDPOINT_IN,
40 (char *)buf,
41 size,
42 100, &tmp);
43 *bytes_read = tmp;
44
45 return ret;
46 }
47
48 static int ublast2_libusb_write(struct ublast_lowlevel *low, uint8_t *buf,
49 int size, uint32_t *bytes_written)
50 {
51 int ret, tmp = 0;
52
53 ret = jtag_libusb_bulk_write(low->libusb_dev,
54 USBBLASTER_EPOUT |
55 LIBUSB_ENDPOINT_OUT,
56 (char *)buf,
57 size,
58 100, &tmp);
59 *bytes_written = tmp;
60
61 return ret;
62
63 }
64
65 static int ublast2_write_firmware_section(struct libusb_device_handle *libusb_dev,
66 struct image *firmware_image, int section_index)
67 {
68 uint16_t chunk_size;
69 uint8_t data[SECTION_BUFFERSIZE];
70 uint8_t *data_ptr = data;
71 size_t size_read;
72
73 uint16_t size = (uint16_t)firmware_image->sections[section_index].size;
74 uint16_t addr = (uint16_t)firmware_image->sections[section_index].base_address;
75
76 LOG_DEBUG("section %02i at addr 0x%04x (size 0x%04x)", section_index, addr,
77 size);
78
79 /* Copy section contents to local buffer */
80 int ret = image_read_section(firmware_image, section_index, 0, size, data,
81 &size_read);
82
83 if ((ret != ERROR_OK) || (size_read != size)) {
84 /* Propagating the return code would return '0' (misleadingly indicating
85 * successful execution of the function) if only the size check fails. */
86 return ERROR_FAIL;
87 }
88
89 uint16_t bytes_remaining = size;
90
91 /* Send section data in chunks of up to 64 bytes to ULINK */
92 while (bytes_remaining > 0) {
93 if (bytes_remaining > 64)
94 chunk_size = 64;
95 else
96 chunk_size = bytes_remaining;
97
98 jtag_libusb_control_transfer(libusb_dev,
99 LIBUSB_REQUEST_TYPE_VENDOR |
100 LIBUSB_ENDPOINT_OUT,
101 USBBLASTER_CTRL_LOAD_FIRM,
102 addr,
103 0,
104 (char *)data_ptr,
105 chunk_size,
106 100);
107
108 bytes_remaining -= chunk_size;
109 addr += chunk_size;
110 data_ptr += chunk_size;
111 }
112
113 return ERROR_OK;
114 }
115
116 static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
117 struct ublast_lowlevel *low)
118 {
119 struct image ublast2_firmware_image;
120
121 if (!low->firmware_path) {
122 LOG_ERROR("No firmware path specified");
123 return ERROR_FAIL;
124 }
125
126 if (libusb_claim_interface(libusb_dev, 0)) {
127 LOG_ERROR("unable to claim interface");
128 return ERROR_JTAG_INIT_FAILED;
129 }
130
131 ublast2_firmware_image.base_address = 0;
132 ublast2_firmware_image.base_address_set = false;
133
134 int ret = image_open(&ublast2_firmware_image, low->firmware_path, "ihex");
135 if (ret != ERROR_OK) {
136 LOG_ERROR("Could not load firmware image");
137 goto error_release_usb;
138 }
139
140 /** A host loader program must write 0x01 to the CPUCS register
141 * to put the CPU into RESET, load all or part of the EZUSB
142 * RAM with firmware, then reload the CPUCS register
143 * with ‘0’ to take the CPU out of RESET. The CPUCS register
144 * (at 0xE600) is the only EZ-USB register that can be written
145 * using the Firmware Download command.
146 */
147
148 char value = CPU_RESET;
149 jtag_libusb_control_transfer(libusb_dev,
150 LIBUSB_REQUEST_TYPE_VENDOR |
151 LIBUSB_ENDPOINT_OUT,
152 USBBLASTER_CTRL_LOAD_FIRM,
153 EZUSB_CPUCS,
154 0,
155 &value,
156 1,
157 100);
158
159 /* Download all sections in the image to ULINK */
160 for (unsigned int i = 0; i < ublast2_firmware_image.num_sections; i++) {
161 ret = ublast2_write_firmware_section(libusb_dev,
162 &ublast2_firmware_image, i);
163 if (ret != ERROR_OK) {
164 LOG_ERROR("Error while downloading the firmware");
165 goto error_close_firmware;
166 }
167 }
168
169 value = !CPU_RESET;
170 jtag_libusb_control_transfer(libusb_dev,
171 LIBUSB_REQUEST_TYPE_VENDOR |
172 LIBUSB_ENDPOINT_OUT,
173 USBBLASTER_CTRL_LOAD_FIRM,
174 EZUSB_CPUCS,
175 0,
176 &value,
177 1,
178 100);
179
180 error_close_firmware:
181 image_close(&ublast2_firmware_image);
182
183 error_release_usb:
184 /*
185 * Release claimed interface. Most probably it is already disconnected
186 * and re-enumerated as new devices after firmware upload, so we do
187 * not need to care about errors.
188 */
189 libusb_release_interface(libusb_dev, 0);
190
191 return ret;
192 }
193
194 static int ublast2_libusb_init(struct ublast_lowlevel *low)
195 {
196 const uint16_t vids[] = { low->ublast_vid_uninit, 0 };
197 const uint16_t pids[] = { low->ublast_pid_uninit, 0 };
198 struct libusb_device_handle *temp;
199 bool renumeration = false;
200 int ret;
201
202 if (jtag_libusb_open(vids, pids, &temp, NULL) == ERROR_OK) {
203 LOG_INFO("Altera USB-Blaster II (uninitialized) found");
204 LOG_INFO("Loading firmware...");
205 ret = load_usb_blaster_firmware(temp, low);
206 jtag_libusb_close(temp);
207 if (ret != ERROR_OK)
208 return ret;
209 renumeration = true;
210 }
211
212 const uint16_t vids_renum[] = { low->ublast_vid, 0 };
213 const uint16_t pids_renum[] = { low->ublast_pid, 0 };
214
215 if (renumeration == false) {
216 if (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev, NULL) != ERROR_OK) {
217 LOG_ERROR("Altera USB-Blaster II not found");
218 return ERROR_FAIL;
219 }
220 } else {
221 int retry = 10;
222 while (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev, NULL) != ERROR_OK && retry--) {
223 usleep(1000000);
224 LOG_INFO("Waiting for reenumerate...");
225 }
226
227 if (!retry) {
228 LOG_ERROR("Altera USB-Blaster II not found");
229 return ERROR_FAIL;
230 }
231 }
232
233 if (libusb_claim_interface(low->libusb_dev, 0)) {
234 LOG_ERROR("unable to claim interface");
235 jtag_libusb_close(low->libusb_dev);
236 return ERROR_JTAG_INIT_FAILED;
237 }
238
239 char buffer[5];
240 jtag_libusb_control_transfer(low->libusb_dev,
241 LIBUSB_REQUEST_TYPE_VENDOR |
242 LIBUSB_ENDPOINT_IN,
243 USBBLASTER_CTRL_READ_REV,
244 0,
245 0,
246 buffer,
247 5,
248 100);
249
250 LOG_INFO("Altera USB-Blaster II found (Firm. rev. = %s)", buffer);
251
252 return ERROR_OK;
253 }
254
255 static int ublast2_libusb_quit(struct ublast_lowlevel *low)
256 {
257 if (libusb_release_interface(low->libusb_dev, 0))
258 LOG_ERROR("usb release interface failed");
259
260 jtag_libusb_close(low->libusb_dev);
261 return ERROR_OK;
262 };
263
264 static struct ublast_lowlevel low = {
265 .open = ublast2_libusb_init,
266 .close = ublast2_libusb_quit,
267 .read = ublast2_libusb_read,
268 .write = ublast2_libusb_write,
269 .flags = COPY_TDO_BUFFER,
270 };
271
272 struct ublast_lowlevel *ublast2_register_libusb(void)
273 {
274 return &low;
275 }

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)