blob: 369c645d3c58e388fb46e0a55c2ed4432094501d [file] [log] [blame]
Marc Schink3578ec62016-03-17 16:23:03 +01001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2016 Marc Schink <flashrom-dev@marcschink.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17/*
18 * Driver for the J-Link hardware by SEGGER.
19 * See https://www.segger.com/ for more info.
20 */
21
22#include <stdlib.h>
23#include <stdbool.h>
24#include <stdint.h>
25#include <string.h>
26#include <errno.h>
27#include <libjaylink/libjaylink.h>
28
29#include "flash.h"
30#include "programmer.h"
31#include "spi.h"
32
33/*
34 * Maximum number of bytes that can be transferred at once via the JTAG
35 * interface, see jaylink_jtag_io().
36 */
Marc Schinka8c0b682020-08-22 11:29:22 +020037#define JTAG_MAX_TRANSFER_SIZE (32768 / 8)
Marc Schink3578ec62016-03-17 16:23:03 +010038
39/*
40 * Default base frequency in Hz. Used when the base frequency can not be
41 * retrieved from the device.
42 */
43#define DEFAULT_FREQ 16000000
44
45/*
46 * Default frequency divider. Used when the frequency divider can not be
47 * retrieved from the device.
48 */
49#define DEFAULT_FREQ_DIV 4
50
51/* Minimum target voltage required for operation in mV. */
52#define MIN_TARGET_VOLTAGE 1200
53
54static struct jaylink_context *jaylink_ctx;
55static struct jaylink_device_handle *jaylink_devh;
56static bool reset_cs;
57
58static bool assert_cs(void)
59{
60 int ret;
61
62 if (reset_cs) {
63 ret = jaylink_clear_reset(jaylink_devh);
64
65 if (ret != JAYLINK_OK) {
66 msg_perr("jaylink_clear_reset() failed: %s.\n", jaylink_strerror(ret));
67 return false;
68 }
69 } else {
70 ret = jaylink_jtag_clear_trst(jaylink_devh);
71
72 if (ret != JAYLINK_OK) {
73 msg_perr("jaylink_jtag_clear_trst() failed: %s.\n", jaylink_strerror(ret));
74 return false;
75 }
76 }
77
78 return true;
79}
80
81static bool deassert_cs(void)
82{
83 int ret;
84
85 if (reset_cs) {
86 ret = jaylink_set_reset(jaylink_devh);
87
88 if (ret != JAYLINK_OK) {
89 msg_perr("jaylink_set_reset() failed: %s.\n", jaylink_strerror(ret));
90 return false;
91 }
92 } else {
93 ret = jaylink_jtag_set_trst(jaylink_devh);
94
95 if (ret != JAYLINK_OK) {
96 msg_perr("jaylink_jtag_set_trst() failed: %s.\n", jaylink_strerror(ret));
97 return false;
98 }
99 }
100
101 return true;
102}
103
Edward O'Callaghan5eca4272020-04-12 17:27:53 +1000104static int jlink_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
Marc Schink3578ec62016-03-17 16:23:03 +0100105 const unsigned char *writearr, unsigned char *readarr)
106{
107 uint32_t length;
108 uint8_t *buffer;
109
110 length = writecnt + readcnt;
111
112 if (length > JTAG_MAX_TRANSFER_SIZE)
113 return SPI_INVALID_LENGTH;
114
115 buffer = malloc(length);
116
117 if (!buffer) {
118 msg_perr("Memory allocation failed.\n");
119 return SPI_GENERIC_ERROR;
120 }
121
122 /* Reverse all bytes because the device transfers data LSB first. */
123 reverse_bytes(buffer, writearr, writecnt);
124
125 memset(buffer + writecnt, 0x00, readcnt);
126
127 if (!assert_cs()) {
128 free(buffer);
129 return SPI_PROGRAMMER_ERROR;
130 }
131
132 int ret;
133
134 ret = jaylink_jtag_io(jaylink_devh, buffer, buffer, buffer, length * 8, JAYLINK_JTAG_VERSION_2);
135
136 if (ret != JAYLINK_OK) {
Angel Pons281ed262021-04-16 10:55:03 +0200137 msg_perr("jaylink_jtag_io() failed: %s.\n", jaylink_strerror(ret));
Marc Schink3578ec62016-03-17 16:23:03 +0100138 free(buffer);
139 return SPI_PROGRAMMER_ERROR;
140 }
141
142 if (!deassert_cs()) {
143 free(buffer);
144 return SPI_PROGRAMMER_ERROR;
145 }
146
147 /* Reverse all bytes because the device transfers data LSB first. */
148 reverse_bytes(readarr, buffer + writecnt, readcnt);
149 free(buffer);
150
151 return 0;
152}
153
154static const struct spi_master spi_master_jlink_spi = {
Marc Schink3578ec62016-03-17 16:23:03 +0100155 /* Maximum data read size in one go (excluding opcode+address). */
156 .max_data_read = JTAG_MAX_TRANSFER_SIZE - 5,
157 /* Maximum data write size in one go (excluding opcode+address). */
158 .max_data_write = JTAG_MAX_TRANSFER_SIZE - 5,
159 .command = jlink_spi_send_command,
160 .multicommand = default_spi_send_multicommand,
161 .read = default_spi_read,
162 .write_256 = default_spi_write_256,
163 .write_aai = default_spi_write_aai,
164 .features = SPI_MASTER_4BA,
165};
166
167static int jlink_spi_shutdown(void *data)
168{
169 if (jaylink_devh)
170 jaylink_close(jaylink_devh);
171
172 jaylink_exit(jaylink_ctx);
173
174 return 0;
175}
176
177int jlink_spi_init(void)
178{
179 char *arg;
180 unsigned long speed = 0;
181
182 register_shutdown(jlink_spi_shutdown, NULL);
183
184 arg = extract_programmer_param("spispeed");
185
186 if (arg) {
187 char *endptr;
188
189 errno = 0;
190 speed = strtoul(arg, &endptr, 10);
191
192 if (*endptr != '\0' || errno != 0) {
193 msg_perr("Invalid SPI speed specified: %s.\n", arg);
194 free(arg);
195 return 1;
196 }
197
198 if (speed < 1) {
199 msg_perr("SPI speed must be at least 1 kHz.\n");
200 free(arg);
201 return 1;
202 }
203 }
204
205 free(arg);
206
207 int ret;
208 bool use_serial_number;
209 uint32_t serial_number;
210
211 arg = extract_programmer_param("serial");
212
213 if (arg) {
214 if (!strlen(arg)) {
Angel Pons281ed262021-04-16 10:55:03 +0200215 msg_perr("Empty serial number specified.\n");
Marc Schink3578ec62016-03-17 16:23:03 +0100216 free(arg);
217 return 1;
218 }
219
220 ret = jaylink_parse_serial_number(arg, &serial_number);
221
222 if (ret == JAYLINK_ERR) {
223 msg_perr("Invalid serial number specified: %s.\n", arg);
224 free(arg);
225 return 1;
226 } if (ret != JAYLINK_OK) {
227 msg_perr("jaylink_parse_serial_number() failed: %s.\n", jaylink_strerror(ret));
228 free(arg);
229 return 1;
230 }
231
232 use_serial_number = true;
233 } else {
234 use_serial_number = false;
235 }
236
237 free(arg);
238
239 reset_cs = true;
240 arg = extract_programmer_param("cs");
241
242 if (arg) {
243 if (!strcasecmp(arg, "reset")) {
244 reset_cs = true;
245 } else if (!strcasecmp(arg, "trst")) {
246 reset_cs = false;
247 } else {
248 msg_perr("Invalid chip select pin specified: '%s'.\n", arg);
249 free(arg);
250 return 1;
251 }
252 }
253
254 free(arg);
255
256 if (reset_cs)
257 msg_pdbg("Using RESET as chip select signal.\n");
258 else
259 msg_pdbg("Using TRST as chip select signal.\n");
260
261 ret = jaylink_init(&jaylink_ctx);
262
263 if (ret != JAYLINK_OK) {
264 msg_perr("jaylink_init() failed: %s.\n", jaylink_strerror(ret));
265 return 1;
266 }
267
268 ret = jaylink_discovery_scan(jaylink_ctx, 0);
269
270 if (ret != JAYLINK_OK) {
Angel Pons281ed262021-04-16 10:55:03 +0200271 msg_perr("jaylink_discovery_scan() failed: %s.\n", jaylink_strerror(ret));
Marc Schink3578ec62016-03-17 16:23:03 +0100272 return 1;
273 }
274
275 struct jaylink_device **devs;
276
277 ret = jaylink_get_devices(jaylink_ctx, &devs, NULL);
278
279 if (ret != JAYLINK_OK) {
280 msg_perr("jaylink_get_devices() failed: %s.\n", jaylink_strerror(ret));
281 return 1;
282 }
283
284 if (!use_serial_number)
285 msg_pdbg("No device selected, using first device.\n");
286
287 size_t i;
288 struct jaylink_device *dev;
289 bool device_found = false;
290
291 for (i = 0; devs[i]; i++) {
292 if (use_serial_number) {
293 uint32_t tmp;
294
295 ret = jaylink_device_get_serial_number(devs[i], &tmp);
296
297 if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
298 continue;
299 } else if (ret != JAYLINK_OK) {
300 msg_pwarn("jaylink_device_get_serial_number() failed: %s.\n",
301 jaylink_strerror(ret));
302 continue;
303 }
304
305 if (serial_number != tmp)
306 continue;
307 }
308
309 ret = jaylink_open(devs[i], &jaylink_devh);
310
311 if (ret == JAYLINK_OK) {
312 dev = devs[i];
313 device_found = true;
314 break;
315 }
316
317 jaylink_devh = NULL;
318 }
319
320 jaylink_free_devices(devs, true);
321
322 if (!device_found) {
323 msg_perr("No J-Link device found.\n");
324 return 1;
325 }
326
327 size_t length;
328 char *firmware_version;
329
330 ret = jaylink_get_firmware_version(jaylink_devh, &firmware_version,
331 &length);
332
333 if (ret != JAYLINK_OK) {
334 msg_perr("jaylink_get_firmware_version() failed: %s.\n", jaylink_strerror(ret));
335 return 1;
336 } else if (length > 0) {
337 msg_pdbg("Firmware: %s\n", firmware_version);
338 free(firmware_version);
339 }
340
341 ret = jaylink_device_get_serial_number(dev, &serial_number);
342
343 if (ret == JAYLINK_OK) {
344 msg_pdbg("S/N: %" PRIu32 "\n", serial_number);
345 } else if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
346 msg_pdbg("S/N: N/A\n");
347 } else {
348 msg_perr("jaylink_device_get_serial_number() failed: %s.\n", jaylink_strerror(ret));
349 return 1;
350 }
351
Angel Pons7e134562021-06-07 13:29:13 +0200352 uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE] = { 0 };
Marc Schink3578ec62016-03-17 16:23:03 +0100353
Marc Schink3578ec62016-03-17 16:23:03 +0100354 ret = jaylink_get_caps(jaylink_devh, caps);
355
356 if (ret != JAYLINK_OK) {
357 msg_perr("jaylink_get_caps() failed: %s.\n", jaylink_strerror(ret));
358 return 1;
359 }
360
361 if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_EXT_CAPS)) {
362 ret = jaylink_get_extended_caps(jaylink_devh, caps);
363
364 if (ret != JAYLINK_OK) {
Angel Pons281ed262021-04-16 10:55:03 +0200365 msg_perr("jaylink_get_extended_caps() failed: %s.\n", jaylink_strerror(ret));
Marc Schink3578ec62016-03-17 16:23:03 +0100366 return 1;
367 }
368 }
369
370 uint32_t ifaces;
371
372 ret = jaylink_get_available_interfaces(jaylink_devh, &ifaces);
373
374 if (ret != JAYLINK_OK) {
375 msg_perr("jaylink_get_available_interfaces() failed: %s.\n", jaylink_strerror(ret));
376 return 1;
377 }
378
379 if (!(ifaces & (1 << JAYLINK_TIF_JTAG))) {
380 msg_perr("Device does not support JTAG interface.\n");
381 return 1;
382 }
383
384 ret = jaylink_select_interface(jaylink_devh, JAYLINK_TIF_JTAG, NULL);
385
386 if (ret != JAYLINK_OK) {
387 msg_perr("jaylink_select_interface() failed: %s.\n", jaylink_strerror(ret));
388 return 1;
389 }
390
391 struct jaylink_hardware_status hwstat;
392
393 ret = jaylink_get_hardware_status(jaylink_devh, &hwstat);
394
395 if (ret != JAYLINK_OK) {
396 msg_perr("jaylink_get_hardware_status() failed: %s.\n", jaylink_strerror(ret));
397 return 1;
398 }
399
400 msg_pdbg("VTarget: %u.%03u V\n", hwstat.target_voltage / 1000,
401 hwstat.target_voltage % 1000);
402
403 if (hwstat.target_voltage < MIN_TARGET_VOLTAGE) {
404 msg_perr("Target voltage is below %u.%03u V. You need to attach VTref to the I/O voltage of "
405 "the chip.\n", MIN_TARGET_VOLTAGE / 1000, MIN_TARGET_VOLTAGE % 1000);
406 return 1;
407 }
408
409 struct jaylink_speed device_speeds;
410
411 device_speeds.freq = DEFAULT_FREQ;
412 device_speeds.div = DEFAULT_FREQ_DIV;
413
414 if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) {
415 ret = jaylink_get_speeds(jaylink_devh, &device_speeds);
416
417 if (ret != JAYLINK_OK) {
418 msg_perr("jaylink_get_speeds() failed: %s.\n", jaylink_strerror(ret));
419 return 1;
420 }
421 }
422
423 device_speeds.freq /= 1000;
424
425 msg_pdbg("Maximum SPI speed: %" PRIu32 " kHz\n", device_speeds.freq / device_speeds.div);
426
427 if (!speed) {
428 speed = device_speeds.freq / device_speeds.div;
429 msg_pdbg("SPI speed not specified, using %lu kHz.\n", speed);
430 }
431
432 if (speed > (device_speeds.freq / device_speeds.div)) {
433 msg_perr("Specified SPI speed of %lu kHz is too high. Maximum is %" PRIu32 " kHz.\n", speed,
434 device_speeds.freq / device_speeds.div);
435 return 1;
436 }
437
438 ret = jaylink_set_speed(jaylink_devh, speed);
439
440 if (ret != JAYLINK_OK) {
441 msg_perr("jaylink_set_speed() failed: %s.\n", jaylink_strerror(ret));
442 return 1;
443 }
444
445 msg_pdbg("SPI speed: %lu kHz\n", speed);
446
447 /* Ensure that the CS signal is not active initially. */
448 if (!deassert_cs())
449 return 1;
450
451 register_spi_master(&spi_master_jlink_spi);
452
453 return 0;
454}