jtag: linuxgpiod: drop extra parenthesis
[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 NULL);
108
109 bytes_remaining -= chunk_size;
110 addr += chunk_size;
111 data_ptr += chunk_size;
112 }
113
114 return ERROR_OK;
115 }
116
117 static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
118 struct ublast_lowlevel *low)
119 {
120 struct image ublast2_firmware_image;
121
122 if (!low->firmware_path) {
123 LOG_ERROR("No firmware path specified");
124 return ERROR_FAIL;
125 }
126
127 if (libusb_claim_interface(libusb_dev, 0)) {
128 LOG_ERROR("unable to claim interface");
129 return ERROR_JTAG_INIT_FAILED;
130 }
131
132 ublast2_firmware_image.base_address = 0;
133 ublast2_firmware_image.base_address_set = false;
134
135 int ret = image_open(&ublast2_firmware_image, low->firmware_path, "ihex");
136 if (ret != ERROR_OK) {
137 LOG_ERROR("Could not load firmware image");
138 goto error_release_usb;
139 }
140
141 /** A host loader program must write 0x01 to the CPUCS register
142 * to put the CPU into RESET, load all or part of the EZUSB
143 * RAM with firmware, then reload the CPUCS register
144 * with ‘0’ to take the CPU out of RESET. The CPUCS register
145 * (at 0xE600) is the only EZ-USB register that can be written
146 * using the Firmware Download command.
147 */
148
149 char value = CPU_RESET;
150 jtag_libusb_control_transfer(libusb_dev,
151 LIBUSB_REQUEST_TYPE_VENDOR |
152 LIBUSB_ENDPOINT_OUT,
153 USBBLASTER_CTRL_LOAD_FIRM,
154 EZUSB_CPUCS,
155 0,
156 &value,
157 1,
158 100,
159 NULL);
160
161 /* Download all sections in the image to ULINK */
162 for (unsigned int i = 0; i < ublast2_firmware_image.num_sections; i++) {
163 ret = ublast2_write_firmware_section(libusb_dev,
164 &ublast2_firmware_image, i);
165 if (ret != ERROR_OK) {
166 LOG_ERROR("Error while downloading the firmware");
167 goto error_close_firmware;
168 }
169 }
170
171 value = !CPU_RESET;
172 jtag_libusb_control_transfer(libusb_dev,
173 LIBUSB_REQUEST_TYPE_VENDOR |
174 LIBUSB_ENDPOINT_OUT,
175 USBBLASTER_CTRL_LOAD_FIRM,
176 EZUSB_CPUCS,
177 0,
178 &value,
179 1,
180 100,
181 NULL);
182
183 error_close_firmware:
184 image_close(&ublast2_firmware_image);
185
186 error_release_usb:
187 /*
188 * Release claimed interface. Most probably it is already disconnected
189 * and re-enumerated as new devices after firmware upload, so we do
190 * not need to care about errors.
191 */
192 libusb_release_interface(libusb_dev, 0);
193
194 return ret;
195 }
196
197 static int ublast2_libusb_init(struct ublast_lowlevel *low)
198 {
199 const uint16_t vids[] = { low->ublast_vid_uninit, 0 };
200 const uint16_t pids[] = { low->ublast_pid_uninit, 0 };
201 struct libusb_device_handle *temp;
202 bool renumeration = false;
203 int ret;
204
205 if (jtag_libusb_open(vids, pids, NULL, &temp, NULL) == ERROR_OK) {
206 LOG_INFO("Altera USB-Blaster II (uninitialized) found");
207 LOG_INFO("Loading firmware...");
208 ret = load_usb_blaster_firmware(temp, low);
209 jtag_libusb_close(temp);
210 if (ret != ERROR_OK)
211 return ret;
212 renumeration = true;
213 }
214
215 const uint16_t vids_renum[] = { low->ublast_vid, 0 };
216 const uint16_t pids_renum[] = { low->ublast_pid, 0 };
217
218 if (renumeration == false) {
219 if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev, NULL) != ERROR_OK) {
220 LOG_ERROR("Altera USB-Blaster II not found");
221 return ERROR_FAIL;
222 }
223 } else {
224 int retry = 10;
225 while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev, NULL) != ERROR_OK && retry--) {
226 usleep(1000000);
227 LOG_INFO("Waiting for reenumerate...");
228 }
229
230 if (!retry) {
231 LOG_ERROR("Altera USB-Blaster II not found");
232 return ERROR_FAIL;
233 }
234 }
235
236 if (libusb_claim_interface(low->libusb_dev, 0)) {
237 LOG_ERROR("unable to claim interface");
238 jtag_libusb_close(low->libusb_dev);
239 return ERROR_JTAG_INIT_FAILED;
240 }
241
242 char buffer[5];
243 jtag_libusb_control_transfer(low->libusb_dev,
244 LIBUSB_REQUEST_TYPE_VENDOR |
245 LIBUSB_ENDPOINT_IN,
246 USBBLASTER_CTRL_READ_REV,
247 0,
248 0,
249 buffer,
250 5,
251 100,
252 NULL);
253
254 LOG_INFO("Altera USB-Blaster II found (Firm. rev. = %s)", buffer);
255
256 return ERROR_OK;
257 }
258
259 static int ublast2_libusb_quit(struct ublast_lowlevel *low)
260 {
261 if (libusb_release_interface(low->libusb_dev, 0))
262 LOG_ERROR("usb release interface failed");
263
264 jtag_libusb_close(low->libusb_dev);
265 return ERROR_OK;
266 };
267
268 static struct ublast_lowlevel low = {
269 .open = ublast2_libusb_init,
270 .close = ublast2_libusb_quit,
271 .read = ublast2_libusb_read,
272 .write = ublast2_libusb_write,
273 .flags = COPY_TDO_BUFFER,
274 };
275
276 struct ublast_lowlevel *ublast2_register_libusb(void)
277 {
278 return &low;
279 }

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)